Update Peter Harris' entry
[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/addr_resolv.h>
39 #include <epan/tap.h>
40 #include <epan/conversation.h>
41 #include <epan/stat_cmd_args.h>
42 #include "register.h"
43 #include <epan/dissectors/packet-ip.h>
44 #include <epan/dissectors/packet-ipv6.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         guint64 bytes1;
70         guint64 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",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
86                 g_snprintf(name2,256,"%s:%s",ep_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",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
90                 g_snprintf(name1,256,"%s:%s",ep_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",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
94                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
95         } else {
96                 direction=1;
97                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
98                 g_snprintf(name1,256,"%s:%s",ep_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=g_strdup(name1);
114 /*              iui->addr2=NULL;*/
115                 iui->name2=g_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",ep_address_to_str(&sctph->ip_src),s_sport);
149                 g_snprintf(name2,256,"%s:%s",ep_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",ep_address_to_str(&sctph->ip_src),s_sport);
153                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&sctph->ip_dst),s_dport);
154         } else {
155                 direction=0;
156                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&sctph->ip_src),s_sport);
157                 g_snprintf(name2,256,"%s:%s",ep_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=g_strdup(name1);
173 /*              iui->addr2=NULL;*/
174                 iui->name2=g_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",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
205                 g_snprintf(name2,256,"%s:%s",ep_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",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
209                 g_snprintf(name1,256,"%s:%s",ep_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",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
213                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
214         } else {
215                 direction=1;
216                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
217                 g_snprintf(name1,256,"%s:%s",ep_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=g_strdup(name1);
233 /*              iui->addr2=NULL;*/
234                 iui->name2=g_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 ws_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=g_strdup(ep_address_to_str(addr1));
282                 COPY_ADDRESS(&iui->addr2, addr2);
283                 iui->name2=g_strdup(ep_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_ipv6_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
303 {
304         io_users_t *iu=arg;
305         const struct ip6_hdr *ip6h=vip;
306         address src, dst;
307         const address *addr1, *addr2;
308         io_users_item_t *iui;
309
310         /* Addresses aren't implemented as 'address' type in struct ip6_hdr */
311         src.type = dst.type = AT_IPv6;
312         src.len  = dst.len = sizeof(struct e_in6_addr);
313         src.data = &ip6h->ip6_src;
314         dst.data = &ip6h->ip6_dst;
315
316         if(CMP_ADDRESS(&src, &dst)>0){
317                 addr1=&src;
318                 addr2=&dst;
319         } else {
320                 addr2=&src;
321                 addr1=&dst;
322         }
323
324         for(iui=iu->items;iui;iui=iui->next){
325                 if((!CMP_ADDRESS(&iui->addr1, addr1))
326                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
327                         break;
328                 }
329         }
330
331         if(!iui){
332                 iui=g_malloc(sizeof(io_users_item_t));
333                 iui->next=iu->items;
334                 iu->items=iui;
335                 COPY_ADDRESS(&iui->addr1, addr1);
336                 iui->name1=g_strdup(ep_address_to_str(addr1));
337                 COPY_ADDRESS(&iui->addr2, addr2);
338                 iui->name2=g_strdup(ep_address_to_str(addr2));
339                 iui->frames1=0;
340                 iui->frames2=0;
341                 iui->bytes1=0;
342                 iui->bytes2=0;
343         }
344
345         if(!CMP_ADDRESS(&dst, &iui->addr1)){
346                 iui->frames1++;
347                 iui->bytes1+=pinfo->fd->pkt_len;
348         } else {
349                 iui->frames2++;
350                 iui->bytes2+=pinfo->fd->pkt_len;
351         }
352
353         return 1;
354 }
355
356 static int
357 iousers_ipx_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vipx)
358 {
359         io_users_t *iu=arg;
360         const ipxhdr_t *ipxh=vipx;
361         const address *addr1, *addr2;
362         io_users_item_t *iui;
363
364         if(CMP_ADDRESS(&ipxh->ipx_src, &ipxh->ipx_dst)>0){
365                 addr1=&ipxh->ipx_src;
366                 addr2=&ipxh->ipx_dst;
367         } else {
368                 addr2=&ipxh->ipx_src;
369                 addr1=&ipxh->ipx_dst;
370         }
371
372         for(iui=iu->items;iui;iui=iui->next){
373                 if((!CMP_ADDRESS(&iui->addr1, addr1))
374                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
375                         break;
376                 }
377         }
378
379         if(!iui){
380                 iui=g_malloc(sizeof(io_users_item_t));
381                 iui->next=iu->items;
382                 iu->items=iui;
383                 COPY_ADDRESS(&iui->addr1, addr1);
384                 iui->name1=g_strdup(ep_address_to_str(addr1));
385                 COPY_ADDRESS(&iui->addr2, addr2);
386                 iui->name2=g_strdup(ep_address_to_str(addr2));
387                 iui->frames1=0;
388                 iui->frames2=0;
389                 iui->bytes1=0;
390                 iui->bytes2=0;
391         }
392
393         if(!CMP_ADDRESS(&ipxh->ipx_dst, &iui->addr1)){
394                 iui->frames1++;
395                 iui->bytes1+=pinfo->fd->pkt_len;
396         } else {
397                 iui->frames2++;
398                 iui->bytes2+=pinfo->fd->pkt_len;
399         }
400
401         return 1;
402 }
403
404 static int
405 iousers_fc_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vfc)
406 {
407         io_users_t *iu=arg;
408         const fc_hdr *fchdr=vfc;
409         const address *addr1, *addr2;
410         io_users_item_t *iui;
411
412         if(CMP_ADDRESS(&fchdr->s_id, &fchdr->d_id)<0){
413                 addr1=&fchdr->s_id;
414                 addr2=&fchdr->d_id;
415         } else {
416                 addr2=&fchdr->s_id;
417                 addr1=&fchdr->d_id;
418         }
419
420         for(iui=iu->items;iui;iui=iui->next){
421                 if((!CMP_ADDRESS(&iui->addr1, addr1))
422                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
423                         break;
424                 }
425         }
426
427         if(!iui){
428                 iui=g_malloc(sizeof(io_users_item_t));
429                 iui->next=iu->items;
430                 iu->items=iui;
431                 COPY_ADDRESS(&iui->addr1, addr1);
432                 iui->name1=g_strdup(ep_address_to_str(addr1));
433                 COPY_ADDRESS(&iui->addr2, addr2);
434                 iui->name2=g_strdup(ep_address_to_str(addr2));
435                 iui->frames1=0;
436                 iui->frames2=0;
437                 iui->bytes1=0;
438                 iui->bytes2=0;
439         }
440
441         if(!CMP_ADDRESS(&fchdr->d_id,&iui->addr1)){
442                 iui->frames1++;
443                 iui->bytes1+=pinfo->fd->pkt_len;
444         } else {
445                 iui->frames2++;
446                 iui->bytes2+=pinfo->fd->pkt_len;
447         }
448
449         return 1;
450 }
451
452 static int
453 iousers_eth_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
454 {
455         io_users_t *iu=arg;
456         const eth_hdr *ehdr=veth;
457         const address *addr1, *addr2;
458         io_users_item_t *iui;
459
460         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
461                 addr1=&ehdr->src;
462                 addr2=&ehdr->dst;
463         } else {
464                 addr2=&ehdr->src;
465                 addr1=&ehdr->dst;
466         }
467
468         for(iui=iu->items;iui;iui=iui->next){
469                 if((!CMP_ADDRESS(&iui->addr1, addr1))
470                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
471                         break;
472                 }
473         }
474
475         if(!iui){
476                 iui=g_malloc(sizeof(io_users_item_t));
477                 iui->next=iu->items;
478                 iu->items=iui;
479                 COPY_ADDRESS(&iui->addr1, addr1);
480                 iui->name1=g_strdup(ep_address_to_str(addr1));
481                 COPY_ADDRESS(&iui->addr2, addr2);
482                 iui->name2=g_strdup(ep_address_to_str(addr2));
483                 iui->frames1=0;
484                 iui->frames2=0;
485                 iui->bytes1=0;
486                 iui->bytes2=0;
487         }
488
489         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
490                 iui->frames1++;
491                 iui->bytes1+=pinfo->fd->pkt_len;
492         } else {
493                 iui->frames2++;
494                 iui->bytes2+=pinfo->fd->pkt_len;
495         }
496
497         return 1;
498 }
499
500 static int
501 iousers_fddi_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
502 {
503         io_users_t *iu=arg;
504         const fddi_hdr *ehdr=veth;
505         const address *addr1, *addr2;
506         io_users_item_t *iui;
507
508         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
509                 addr1=&ehdr->src;
510                 addr2=&ehdr->dst;
511         } else {
512                 addr2=&ehdr->src;
513                 addr1=&ehdr->dst;
514         }
515
516         for(iui=iu->items;iui;iui=iui->next){
517                 if((!CMP_ADDRESS(&iui->addr1, addr1))
518                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
519                         break;
520                 }
521         }
522
523         if(!iui){
524                 iui=g_malloc(sizeof(io_users_item_t));
525                 iui->next=iu->items;
526                 iu->items=iui;
527                 COPY_ADDRESS(&iui->addr1, addr1);
528                 iui->name1=g_strdup(ep_address_to_str(addr1));
529                 COPY_ADDRESS(&iui->addr2, addr2);
530                 iui->name2=g_strdup(ep_address_to_str(addr2));
531                 iui->frames1=0;
532                 iui->frames2=0;
533                 iui->bytes1=0;
534                 iui->bytes2=0;
535         }
536
537         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
538                 iui->frames1++;
539                 iui->bytes1+=pinfo->fd->pkt_len;
540         } else {
541                 iui->frames2++;
542                 iui->bytes2+=pinfo->fd->pkt_len;
543         }
544
545         return 1;
546 }
547
548 static int
549 iousers_tr_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtr)
550 {
551         io_users_t *iu=arg;
552         const tr_hdr *trhdr=vtr;
553         const address *addr1, *addr2;
554         io_users_item_t *iui;
555
556         if(CMP_ADDRESS(&trhdr->src, &trhdr->dst)<0){
557                 addr1=&trhdr->src;
558                 addr2=&trhdr->dst;
559         } else {
560                 addr2=&trhdr->src;
561                 addr1=&trhdr->dst;
562         }
563
564         for(iui=iu->items;iui;iui=iui->next){
565                 if((!CMP_ADDRESS(&iui->addr1, addr1))
566                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
567                         break;
568                 }
569         }
570
571         if(!iui){
572                 iui=g_malloc(sizeof(io_users_item_t));
573                 iui->next=iu->items;
574                 iu->items=iui;
575                 COPY_ADDRESS(&iui->addr1, addr1);
576                 iui->name1=g_strdup(ep_address_to_str(addr1));
577                 COPY_ADDRESS(&iui->addr2, addr2);
578                 iui->name2=g_strdup(ep_address_to_str(addr2));
579                 iui->frames1=0;
580                 iui->frames2=0;
581                 iui->bytes1=0;
582                 iui->bytes2=0;
583         }
584
585         if(!CMP_ADDRESS(&trhdr->dst,&iui->addr1)){
586                 iui->frames1++;
587                 iui->bytes1+=pinfo->fd->pkt_len;
588         } else {
589                 iui->frames2++;
590                 iui->bytes2+=pinfo->fd->pkt_len;
591         }
592
593         return 1;
594 }
595
596 static void
597 iousers_draw(void *arg)
598 {
599         io_users_t *iu = arg;
600         io_users_item_t *iui;
601         guint32 last_frames, max_frames;
602
603         printf("================================================================================\n");
604         printf("%s Conversations\n",iu->type);
605         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
606         printf("                                               |       <-      | |       ->      | |     Total     |\n");
607         printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |\n");
608         max_frames=0xffffffff;
609         do {
610                 last_frames=0;
611                 for(iui=iu->items;iui;iui=iui->next){
612                         guint32 tot_frames;
613                         tot_frames=iui->frames1+iui->frames2;
614
615                         if((tot_frames>last_frames)
616                         &&(tot_frames<max_frames)){
617                                 last_frames=tot_frames;
618                         }
619                 }
620                 for(iui=iu->items;iui;iui=iui->next){
621                         guint32 tot_frames;
622                         tot_frames=iui->frames1+iui->frames2;
623
624                         if(tot_frames==last_frames){
625                                 printf("%-20s <-> %-20s  %6d %9" G_GINT64_MODIFIER "d  %6d %9" G_GINT64_MODIFIER "d  %6d %9" G_GINT64_MODIFIER "d\n",
626                                         iui->name1, iui->name2,
627                                         iui->frames1, iui->bytes1,
628                                         iui->frames2, iui->bytes2,
629                                         iui->frames1+iui->frames2,
630                                         iui->bytes1+iui->bytes2
631                                 );
632                         }
633                 }
634                 max_frames=last_frames;
635         } while(last_frames);
636         printf("================================================================================\n");
637 }
638
639 static void
640 iousers_init(const char *optarg, void* userdata _U_)
641 {
642         const char *filter=NULL;
643         const char *tap_type, *tap_type_name;
644         tap_packet_cb packet_func;
645         io_users_t *iu=NULL;
646         GString *error_string;
647
648         if(!strncmp(optarg,"conv,eth",8)){
649                 if(optarg[8]==','){
650                         filter=optarg+9;
651                 } else {
652                         filter=NULL;
653                 }
654                 tap_type="eth";
655                 tap_type_name="Ethernet";
656                 packet_func=iousers_eth_packet;
657         } else if(!strncmp(optarg,"conv,fc",7)){
658                 if(optarg[7]==','){
659                         filter=optarg+8;
660                 } else {
661                         filter=NULL;
662                 }
663                 tap_type="fc";
664                 tap_type_name="Fibre Channel";
665                 packet_func=iousers_fc_packet;
666         } else if(!strncmp(optarg,"conv,fddi",9)){
667                 if(optarg[9]==','){
668                         filter=optarg+10;
669                 } else {
670                         filter=NULL;
671                 }
672                 tap_type="fddi";
673                 tap_type_name="FDDI";
674                 packet_func=iousers_fddi_packet;
675         } else if(!strncmp(optarg,"conv,tcp",8)){
676                 if(optarg[8]==','){
677                         filter=optarg+9;
678                 } else {
679                         filter=NULL;
680                 }
681                 tap_type="tcp";
682                 tap_type_name="TCP";
683                 packet_func=iousers_tcpip_packet;
684         } else if(!strncmp(optarg,"conv,udp",8)){
685                 if(optarg[8]==','){
686                         filter=optarg+9;
687                 } else {
688                         filter=NULL;
689                 }
690                 tap_type="udp";
691                 tap_type_name="UDP";
692                 packet_func=iousers_udpip_packet;
693         } else if(!strncmp(optarg,"conv,tr",7)){
694                 if(optarg[7]==','){
695                         filter=optarg+8;
696                 } else {
697                         filter=NULL;
698                 }
699                 tap_type="tr";
700                 tap_type_name="Token Ring";
701                 packet_func=iousers_tr_packet;
702         } else if(!strncmp(optarg,"conv,ipx",8)){
703                 if(optarg[8]==','){
704                         filter=optarg+9;
705                 } else {
706                         filter=NULL;
707                 }
708                 tap_type="ipx";
709                 tap_type_name="IPX";
710                 packet_func=iousers_ipx_packet;
711         } else if(!strncmp(optarg,"conv,ip",7)){
712                 if(optarg[7]==','){
713                         filter=optarg+8;
714                 } else {
715                         filter=NULL;
716                 }
717                 tap_type="ip";
718                 tap_type_name="IPv4";
719                 packet_func=iousers_ip_packet;
720         } else if(!strncmp(optarg,"conv,ipv6",7)){
721                 if(optarg[7]==','){
722                         filter=optarg+10;
723                 } else {
724                         filter=NULL;
725                 }
726                 tap_type="ipv6";
727                 tap_type_name="IPv6";
728                 packet_func=iousers_ipv6_packet;
729         } else if(!strncmp(optarg,"conv,sctp",9)) {
730                 if(optarg[9]==','){
731                                 filter=optarg+10;
732                 } else {
733                         filter=NULL;
734                 }
735                 tap_type="sctp";
736                 tap_type_name="SCTP";
737                 packet_func=iousers_sctp_packet;
738         } else {
739                 fprintf(stderr, "tshark: invalid \"-z conv,<type>[,<filter>]\" argument\n");
740                 fprintf(stderr,"   <type> must be one of\n");
741                 fprintf(stderr,"      \"eth\"\n");
742                 fprintf(stderr,"      \"fc\"\n");
743                 fprintf(stderr,"      \"fddi\"\n");
744                 fprintf(stderr,"      \"ip\"\n");
745                 fprintf(stderr,"      \"ipx\"\n");
746                 fprintf(stderr,"      \"sctp\"\n");
747                 fprintf(stderr,"      \"tcp\"\n");
748                 fprintf(stderr,"      \"tr\"\n");
749                 fprintf(stderr,"      \"udp\"\n");
750                 exit(1);
751         }
752
753
754         iu=g_malloc(sizeof(io_users_t));
755         iu->items=NULL;
756         iu->type=tap_type_name;
757         if(filter){
758                 iu->filter=g_strdup(filter);
759         } else {
760                 iu->filter=NULL;
761         }
762
763         error_string=register_tap_listener(tap_type, iu, filter, 0, NULL, packet_func, iousers_draw);
764         if(error_string){
765                 if(iu->items){
766                         g_free(iu->items);
767                 }
768                 g_free(iu);
769                 fprintf(stderr, "tshark: Couldn't register conversations tap: %s\n",
770                     error_string->str);
771                 g_string_free(error_string, TRUE);
772                 exit(1);
773         }
774
775 }
776
777 void
778 register_tap_listener_iousers(void)
779 {
780         register_stat_cmd_arg("conv,", iousers_init, NULL);
781 }