More Ethereal -> Wireshark renaming
[obnox/wireshark/wip.git] / tap-iousers.c
1 /* tap-iousers.c
2  * iostat   2003 Ronnie Sahlberg
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <string.h>
36 #include <epan/packet_info.h>
37 #include <epan/packet.h>
38 #include <epan/emem.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/tap.h>
41 #include <epan/conversation.h>
42 #include <epan/stat_cmd_args.h>
43 #include "register.h"
44 #include <epan/dissectors/packet-ip.h>
45 #include <epan/dissectors/packet-ipx.h>
46 #include <epan/dissectors/packet-tcp.h>
47 #include <epan/dissectors/packet-udp.h>
48 #include <epan/dissectors/packet-eth.h>
49 #include <epan/dissectors/packet-sctp.h>
50 #include <epan/dissectors/packet-tr.h>
51 #include <epan/dissectors/packet-scsi.h>
52 #include <epan/dissectors/packet-fc.h>
53 #include <epan/dissectors/packet-fddi.h>
54
55 typedef struct _io_users_t {
56         const char *type;
57         char *filter;
58         struct _io_users_item_t *items;
59 } io_users_t;
60
61 typedef struct _io_users_item_t {
62         struct _io_users_item_t *next;
63         char *name1;
64         char *name2;
65         address addr1;
66         address addr2; 
67         guint32 frames1;
68         guint32 frames2;
69         guint32 bytes1;
70         guint32 bytes2;
71 } io_users_item_t;
72
73
74 static int
75 iousers_udpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vudph)
76 {
77         io_users_t *iu=arg;
78         const e_udphdr *udph=vudph;
79         char name1[256],name2[256];
80         io_users_item_t *iui;
81         int direction=0;
82
83         if(udph->uh_sport>udph->uh_dport){
84                 direction=0;
85                 g_snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
86                 g_snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
87         } else if(udph->uh_sport<udph->uh_dport){
88                 direction=1;
89                 g_snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
90                 g_snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
91         } else if(CMP_ADDRESS(&udph->ip_src, &udph->ip_dst)>0){
92                 direction=0;
93                 g_snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
94                 g_snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
95         } else {
96                 direction=1;
97                 g_snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
98                 g_snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
99         }
100
101         for(iui=iu->items;iui;iui=iui->next){
102                 if((!strcmp(iui->name1, name1))
103                 && (!strcmp(iui->name2, name2)) ){
104                         break;
105                 }
106         }
107
108         if(!iui){
109                 iui=g_malloc(sizeof(io_users_item_t));
110                 iui->next=iu->items;
111                 iu->items=iui;
112 /*              iui->addr1=NULL;*/
113                 iui->name1=strdup(name1);
114 /*              iui->addr2=NULL;*/
115                 iui->name2=strdup(name2);
116                 iui->frames1=0;
117                 iui->frames2=0;
118                 iui->bytes1=0;
119                 iui->bytes2=0;
120         }
121
122         if(direction){
123                 iui->frames1++;
124                 iui->bytes1+=pinfo->fd->pkt_len;
125         } else {
126                 iui->frames2++;
127                 iui->bytes2+=pinfo->fd->pkt_len;
128         }
129
130         return 1;
131 }
132
133
134 static int
135 iousers_sctp_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vsctp)
136 {
137         io_users_t *iu=arg;
138         const struct _sctp_info* sctph = vsctp;
139         char name1[256],name2[256], s_sport[10], s_dport[10];
140         io_users_item_t *iui;
141         int direction=0;
142
143         g_snprintf(s_sport, sizeof s_sport, "%d",sctph->sport);
144         g_snprintf(s_dport, sizeof s_dport, "%d",sctph->dport);
145         
146         if(sctph->sport > sctph->dport) {
147                 direction=0;
148                 g_snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);   
149                 g_snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);   
150         } else if(sctph->sport < sctph->dport) {
151                 direction=1;
152                 g_snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);   
153                 g_snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);   
154         } else {
155                 direction=0;
156                 g_snprintf(name1,256,"%s:%s",address_to_str(&sctph->ip_src),s_sport);   
157                 g_snprintf(name2,256,"%s:%s",address_to_str(&sctph->ip_dst),s_dport);   
158         }
159
160         for(iui=iu->items;iui;iui=iui->next){
161                 if((!strcmp(iui->name1, name1))
162                  && (!strcmp(iui->name2, name2)) ){
163                         break;
164                 }
165         }
166
167         if(!iui){
168                 iui=g_malloc(sizeof(io_users_item_t));
169                 iui->next=iu->items;
170                 iu->items=iui;
171 /*              iui->addr1=NULL;*/
172                 iui->name1=strdup(name1);
173 /*              iui->addr2=NULL;*/
174                 iui->name2=strdup(name2);
175                 iui->frames1=0;
176                 iui->frames2=0;
177                 iui->bytes1=0;
178                 iui->bytes2=0;
179         }
180
181         if(direction){
182                 iui->frames1++;
183                 iui->bytes1+=pinfo->fd->pkt_len;
184         } else {
185                 iui->frames2++;
186                 iui->bytes2+=pinfo->fd->pkt_len;
187         }
188
189         return 1;
190 }
191
192
193 static int
194 iousers_tcpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtcph)
195 {
196         io_users_t *iu=arg;
197         const struct tcpheader *tcph=vtcph;
198         char name1[256],name2[256];
199         io_users_item_t *iui;
200         int direction=0;
201
202         if(tcph->th_sport>tcph->th_dport){
203                 direction=0;
204                 g_snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
205                 g_snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
206         } else if(tcph->th_sport<tcph->th_dport){
207                 direction=1;
208                 g_snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
209                 g_snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
210         } else if(CMP_ADDRESS(&tcph->ip_src, &tcph->ip_dst)>0){
211                 direction=0;
212                 g_snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
213                 g_snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
214         } else {
215                 direction=1;
216                 g_snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
217                 g_snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
218         }
219
220         for(iui=iu->items;iui;iui=iui->next){
221                 if((!strcmp(iui->name1, name1))
222                 && (!strcmp(iui->name2, name2)) ){
223                         break;
224                 }
225         }
226
227         if(!iui){
228                 iui=g_malloc(sizeof(io_users_item_t));
229                 iui->next=iu->items;
230                 iu->items=iui;
231 /*              iui->addr1=NULL;*/
232                 iui->name1=strdup(name1);
233 /*              iui->addr2=NULL;*/
234                 iui->name2=strdup(name2);
235                 iui->frames1=0;
236                 iui->frames2=0;
237                 iui->bytes1=0;
238                 iui->bytes2=0;
239         }
240
241         if(direction){
242                 iui->frames1++;
243                 iui->bytes1+=pinfo->fd->pkt_len;
244         } else {
245                 iui->frames2++;
246                 iui->bytes2+=pinfo->fd->pkt_len;
247         }
248
249         return 1;
250 }
251
252
253 static int
254 iousers_ip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
255 {
256         io_users_t *iu=arg;
257         const e_ip *iph=vip;
258         const address *addr1, *addr2;
259         io_users_item_t *iui;
260
261         if(CMP_ADDRESS(&iph->ip_src, &iph->ip_dst)>0){
262                 addr1=&iph->ip_src;
263                 addr2=&iph->ip_dst;
264         } else {
265                 addr2=&iph->ip_src;
266                 addr1=&iph->ip_dst;
267         }
268
269         for(iui=iu->items;iui;iui=iui->next){
270                 if((!CMP_ADDRESS(&iui->addr1, addr1))
271                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
272                         break;
273                 }
274         }
275
276         if(!iui){
277                 iui=g_malloc(sizeof(io_users_item_t));
278                 iui->next=iu->items;
279                 iu->items=iui;
280                 COPY_ADDRESS(&iui->addr1, addr1);
281                 iui->name1=strdup(address_to_str(addr1));
282                 COPY_ADDRESS(&iui->addr2, addr2);
283                 iui->name2=strdup(address_to_str(addr2));
284                 iui->frames1=0;
285                 iui->frames2=0;
286                 iui->bytes1=0;
287                 iui->bytes2=0;
288         }
289
290         if(!CMP_ADDRESS(&iph->ip_dst, &iui->addr1)){
291                 iui->frames1++;
292                 iui->bytes1+=pinfo->fd->pkt_len;
293         } else {
294                 iui->frames2++;
295                 iui->bytes2+=pinfo->fd->pkt_len;
296         }
297
298         return 1;
299 }
300
301 static int
302 iousers_ipx_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vipx)
303 {
304         io_users_t *iu=arg;
305         const ipxhdr_t *ipxh=vipx;
306         const address *addr1, *addr2;
307         io_users_item_t *iui;
308
309         if(CMP_ADDRESS(&ipxh->ipx_src, &ipxh->ipx_dst)>0){
310                 addr1=&ipxh->ipx_src;
311                 addr2=&ipxh->ipx_dst;
312         } else {
313                 addr2=&ipxh->ipx_src;
314                 addr1=&ipxh->ipx_dst;
315         }
316
317         for(iui=iu->items;iui;iui=iui->next){
318                 if((!CMP_ADDRESS(&iui->addr1, addr1))
319                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
320                         break;
321                 }
322         }
323
324         if(!iui){
325                 iui=g_malloc(sizeof(io_users_item_t));
326                 iui->next=iu->items;
327                 iu->items=iui;
328                 COPY_ADDRESS(&iui->addr1, addr1);
329                 iui->name1=strdup(address_to_str(addr1));
330                 COPY_ADDRESS(&iui->addr2, addr2);
331                 iui->name2=strdup(address_to_str(addr2));
332                 iui->frames1=0;
333                 iui->frames2=0;
334                 iui->bytes1=0;
335                 iui->bytes2=0;
336         }
337
338         if(!CMP_ADDRESS(&ipxh->ipx_dst, &iui->addr1)){
339                 iui->frames1++;
340                 iui->bytes1+=pinfo->fd->pkt_len;
341         } else {
342                 iui->frames2++;
343                 iui->bytes2+=pinfo->fd->pkt_len;
344         }
345
346         return 1;
347 }
348
349 static int
350 iousers_fc_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vfc)
351 {
352         io_users_t *iu=arg;
353         const fc_hdr *fchdr=vfc;
354         const address *addr1, *addr2;
355         io_users_item_t *iui;
356
357         if(CMP_ADDRESS(&fchdr->s_id, &fchdr->d_id)<0){
358                 addr1=&fchdr->s_id;
359                 addr2=&fchdr->d_id;
360         } else {
361                 addr2=&fchdr->s_id;
362                 addr1=&fchdr->d_id;
363         }
364
365         for(iui=iu->items;iui;iui=iui->next){
366                 if((!CMP_ADDRESS(&iui->addr1, addr1))
367                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
368                         break;
369                 }
370         }
371
372         if(!iui){
373                 iui=g_malloc(sizeof(io_users_item_t));
374                 iui->next=iu->items;
375                 iu->items=iui;
376                 COPY_ADDRESS(&iui->addr1, addr1);
377                 iui->name1=strdup(address_to_str(addr1));
378                 COPY_ADDRESS(&iui->addr2, addr2);
379                 iui->name2=strdup(address_to_str(addr2));
380                 iui->frames1=0;
381                 iui->frames2=0;
382                 iui->bytes1=0;
383                 iui->bytes2=0;
384         }
385
386         if(!CMP_ADDRESS(&fchdr->d_id,&iui->addr1)){
387                 iui->frames1++;
388                 iui->bytes1+=pinfo->fd->pkt_len;
389         } else {
390                 iui->frames2++;
391                 iui->bytes2+=pinfo->fd->pkt_len;
392         }
393
394         return 1;
395 }
396
397 static int
398 iousers_eth_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
399 {
400         io_users_t *iu=arg;
401         const eth_hdr *ehdr=veth;
402         const address *addr1, *addr2;
403         io_users_item_t *iui;
404
405         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
406                 addr1=&ehdr->src;
407                 addr2=&ehdr->dst;
408         } else {
409                 addr2=&ehdr->src;
410                 addr1=&ehdr->dst;
411         }
412
413         for(iui=iu->items;iui;iui=iui->next){
414                 if((!CMP_ADDRESS(&iui->addr1, addr1))
415                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
416                         break;
417                 }
418         }
419
420         if(!iui){
421                 iui=g_malloc(sizeof(io_users_item_t));
422                 iui->next=iu->items;
423                 iu->items=iui;
424                 COPY_ADDRESS(&iui->addr1, addr1);
425                 iui->name1=strdup(address_to_str(addr1));
426                 COPY_ADDRESS(&iui->addr2, addr2);
427                 iui->name2=strdup(address_to_str(addr2));
428                 iui->frames1=0;
429                 iui->frames2=0;
430                 iui->bytes1=0;
431                 iui->bytes2=0;
432         }
433
434         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
435                 iui->frames1++;
436                 iui->bytes1+=pinfo->fd->pkt_len;
437         } else {
438                 iui->frames2++;
439                 iui->bytes2+=pinfo->fd->pkt_len;
440         }
441
442         return 1;
443 }
444
445 static int
446 iousers_fddi_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
447 {
448         io_users_t *iu=arg;
449         const fddi_hdr *ehdr=veth;
450         const address *addr1, *addr2;
451         io_users_item_t *iui;
452
453         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
454                 addr1=&ehdr->src;
455                 addr2=&ehdr->dst;
456         } else {
457                 addr2=&ehdr->src;
458                 addr1=&ehdr->dst;
459         }
460
461         for(iui=iu->items;iui;iui=iui->next){
462                 if((!CMP_ADDRESS(&iui->addr1, addr1))
463                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
464                         break;
465                 }
466         }
467
468         if(!iui){
469                 iui=g_malloc(sizeof(io_users_item_t));
470                 iui->next=iu->items;
471                 iu->items=iui;
472                 COPY_ADDRESS(&iui->addr1, addr1);
473                 iui->name1=strdup(address_to_str(addr1));
474                 COPY_ADDRESS(&iui->addr2, addr2);
475                 iui->name2=strdup(address_to_str(addr2));
476                 iui->frames1=0;
477                 iui->frames2=0;
478                 iui->bytes1=0;
479                 iui->bytes2=0;
480         }
481
482         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
483                 iui->frames1++;
484                 iui->bytes1+=pinfo->fd->pkt_len;
485         } else {
486                 iui->frames2++;
487                 iui->bytes2+=pinfo->fd->pkt_len;
488         }
489
490         return 1;
491 }
492
493 static int
494 iousers_tr_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtr)
495 {
496         io_users_t *iu=arg;
497         const tr_hdr *trhdr=vtr;
498         const address *addr1, *addr2;
499         io_users_item_t *iui;
500
501         if(CMP_ADDRESS(&trhdr->src, &trhdr->dst)<0){
502                 addr1=&trhdr->src;
503                 addr2=&trhdr->dst;
504         } else {
505                 addr2=&trhdr->src;
506                 addr1=&trhdr->dst;
507         }
508
509         for(iui=iu->items;iui;iui=iui->next){
510                 if((!CMP_ADDRESS(&iui->addr1, addr1))
511                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
512                         break;
513                 }
514         }
515
516         if(!iui){
517                 iui=g_malloc(sizeof(io_users_item_t));
518                 iui->next=iu->items;
519                 iu->items=iui;
520                 COPY_ADDRESS(&iui->addr1, addr1);
521                 iui->name1=strdup(address_to_str(addr1));
522                 COPY_ADDRESS(&iui->addr2, addr2);
523                 iui->name2=strdup(address_to_str(addr2));
524                 iui->frames1=0;
525                 iui->frames2=0;
526                 iui->bytes1=0;
527                 iui->bytes2=0;
528         }
529
530         if(!CMP_ADDRESS(&trhdr->dst,&iui->addr1)){
531                 iui->frames1++;
532                 iui->bytes1+=pinfo->fd->pkt_len;
533         } else {
534                 iui->frames2++;
535                 iui->bytes2+=pinfo->fd->pkt_len;
536         }
537
538         return 1;
539 }
540
541 static void
542 iousers_draw(void *arg)
543 {
544         io_users_t *iu = arg;
545         io_users_item_t *iui;
546         guint32 last_frames, max_frames;
547
548         printf("================================================================================\n");
549         printf("%s Conversations\n",iu->type);
550         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
551         printf("                                               |       <-      | |       ->      | |     Total     |\n");
552         printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |\n");
553         max_frames=0xffffffff;
554         do {
555                 last_frames=0;
556                 for(iui=iu->items;iui;iui=iui->next){
557                         guint32 tot_frames;
558                         tot_frames=iui->frames1+iui->frames2;
559
560                         if((tot_frames>last_frames)
561                         &&(tot_frames<max_frames)){
562                                 last_frames=tot_frames;
563                         }
564                 }
565                 for(iui=iu->items;iui;iui=iui->next){
566                         guint32 tot_frames;
567                         tot_frames=iui->frames1+iui->frames2;
568
569                         if(tot_frames==last_frames){
570                                 printf("%-20s <-> %-20s  %6d %9d  %6d %9d  %6d %9d\n",
571                                         iui->name1, iui->name2,
572                                         iui->frames1, iui->bytes1,
573                                         iui->frames2, iui->bytes2,
574                                         iui->frames1+iui->frames2,
575                                         iui->bytes1+iui->bytes2
576                                 );
577                         }
578                 }
579                 max_frames=last_frames;
580         } while(last_frames);
581         printf("================================================================================\n");
582 }
583
584 void
585 iousers_init(const char *optarg, void* userdata _U_)
586 {
587         const char *filter=NULL;
588         const char *tap_type, *tap_type_name;
589         tap_packet_cb packet_func;
590         io_users_t *iu=NULL;
591         GString *error_string;
592
593         if(!strncmp(optarg,"conv,eth",8)){
594                 if(optarg[8]==','){
595                         filter=optarg+9;
596                 } else {
597                         filter=NULL;
598                 }
599                 tap_type="eth";
600                 tap_type_name="Ethernet";
601                 packet_func=iousers_eth_packet;
602         } else if(!strncmp(optarg,"conv,fc",7)){
603                 if(optarg[7]==','){
604                         filter=optarg+8;
605                 } else {
606                         filter=NULL;
607                 }
608                 tap_type="fc";
609                 tap_type_name="Fibre Channel";
610                 packet_func=iousers_fc_packet;
611         } else if(!strncmp(optarg,"conv,fddi",9)){
612                 if(optarg[9]==','){
613                         filter=optarg+10;
614                 } else {
615                         filter=NULL;
616                 }
617                 tap_type="fddi";
618                 tap_type_name="FDDI";
619                 packet_func=iousers_fddi_packet;
620         } else if(!strncmp(optarg,"conv,tcp",8)){
621                 if(optarg[8]==','){
622                         filter=optarg+9;
623                 } else {
624                         filter=NULL;
625                 }
626                 tap_type="tcp";
627                 tap_type_name="TCP";
628                 packet_func=iousers_tcpip_packet;
629         } else if(!strncmp(optarg,"conv,udp",8)){
630                 if(optarg[8]==','){
631                         filter=optarg+9;
632                 } else {
633                         filter=NULL;
634                 }
635                 tap_type="udp";
636                 tap_type_name="UDP";
637                 packet_func=iousers_udpip_packet;
638         } else if(!strncmp(optarg,"conv,tr",7)){
639                 if(optarg[7]==','){
640                         filter=optarg+8;
641                 } else {
642                         filter=NULL;
643                 }
644                 tap_type="tr";
645                 tap_type_name="Token Ring";
646                 packet_func=iousers_tr_packet;
647         } else if(!strncmp(optarg,"conv,ipx",8)){
648                 if(optarg[8]==','){
649                         filter=optarg+9;
650                 } else {
651                         filter=NULL;
652                 }
653                 tap_type="ipx";
654                 tap_type_name="IPX";
655                 packet_func=iousers_ipx_packet;
656         } else if(!strncmp(optarg,"conv,ip",7)){
657                 if(optarg[7]==','){
658                         filter=optarg+8;
659                 } else {
660                         filter=NULL;
661                 }
662                 tap_type="ip";
663                 tap_type_name="IPv4";
664                 packet_func=iousers_ip_packet;
665         } else if(!strncmp(optarg,"conv,sctp",9)) {
666                 if(optarg[9]==','){
667                                 filter=optarg+10;
668                 } else {
669                         filter=NULL;
670                 }
671                 tap_type="sctp";
672                 tap_type_name="SCTP";
673                 packet_func=iousers_sctp_packet;
674         } else {
675                 fprintf(stderr, "tshark: invalid \"-z conv,<type>[,<filter>]\" argument\n");
676                 fprintf(stderr,"   <type> must be one of\n");
677                 fprintf(stderr,"      \"eth\"\n");
678                 fprintf(stderr,"      \"fc\"\n");
679                 fprintf(stderr,"      \"fddi\"\n");
680                 fprintf(stderr,"      \"ip\"\n");
681                 fprintf(stderr,"      \"ipx\"\n");
682                 fprintf(stderr,"      \"sctp\"\n");
683                 fprintf(stderr,"      \"tcp\"\n");
684                 fprintf(stderr,"      \"tr\"\n");
685                 fprintf(stderr,"      \"udp\"\n");
686                 exit(1);
687         }
688
689
690         iu=g_malloc(sizeof(io_users_t));
691         iu->items=NULL;
692         iu->type=tap_type_name;
693         if(filter){
694                 iu->filter=strdup(filter);
695         } else {
696                 iu->filter=NULL;
697         }
698
699         error_string=register_tap_listener(tap_type, iu, filter, NULL, packet_func, iousers_draw);
700         if(error_string){
701                 if(iu->items){
702                         g_free(iu->items);
703                 }
704                 g_free(iu);
705                 fprintf(stderr, "tshark: Couldn't register conversations tap: %s\n",
706                     error_string->str);
707                 g_string_free(error_string, TRUE);
708                 exit(1);
709         }
710
711 }
712
713 void
714 register_tap_listener_iousers(void)
715 {
716         register_stat_cmd_arg("conv,", iousers_init, NULL);
717 }