Get rid of -Wshadow warning - I guess we're including something that
[metze/wireshark/wip.git] / ui / cli / 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28
29 #include <string.h>
30 #include <epan/packet_info.h>
31 #include <epan/packet.h>
32 #include <epan/addr_resolv.h>
33 #include <epan/tap.h>
34 #include <epan/timestamp.h>
35 #include <epan/conv_id.h>
36 #include <epan/conversation.h>
37 #include <epan/stat_cmd_args.h>
38 #include <epan/dissectors/packet-ip.h>
39 #include <epan/dissectors/packet-ipv6.h>
40 #include <epan/dissectors/packet-ipx.h>
41 #include <epan/dissectors/packet-tcp.h>
42 #include <epan/dissectors/packet-udp.h>
43 #include <epan/dissectors/packet-eth.h>
44 #include <epan/dissectors/packet-sctp.h>
45 #include <epan/dissectors/packet-tr.h>
46 #include <epan/dissectors/packet-scsi.h>
47 #include <epan/dissectors/packet-fc.h>
48 #include <epan/dissectors/packet-fddi.h>
49
50 typedef struct _io_users_t {
51         const char *type;
52         char *filter;
53         struct _io_users_item_t *items;
54 } io_users_t;
55
56 typedef struct _io_users_item_t {
57         struct _io_users_item_t *next;
58         char                    *name1;
59         char                    *name2;
60         conv_id_t               conv_id;
61         address                 addr1;
62         address                 addr2;
63         guint32                 frames1;
64         guint32                 frames2;
65         guint64                 bytes1;
66         guint64                 bytes2;
67         nstime_t                start_rel_time;
68         nstime_t                stop_rel_time;
69         nstime_t                start_abs_time;
70 } io_users_item_t;
71
72 #define iousers_process_name_packet(iu, name1, name2, direction, pkt_len, rel_ts, abs_ts) \
73     iousers_process_name_packet_with_conv_id(iu, name1, name2, CONV_ID_UNSET, direction, pkt_len, rel_ts, abs_ts)
74
75 static void
76 iousers_process_name_packet_with_conv_id(
77         io_users_t *iu,
78         char *name1,
79         char *name2,
80         conv_id_t conv_id,
81         int direction,
82         guint64 pkt_len,
83         nstime_t *rel_ts,
84         nstime_t *abs_ts)
85 {
86         io_users_item_t *iui;
87
88         for(iui=iu->items;iui;iui=iui->next){
89                 if((iui->conv_id==conv_id)
90                         && (!strcmp(iui->name1, name1))
91                         && (!strcmp(iui->name2, name2)) ){
92                         break;
93                 }
94         }
95
96         if(!iui){
97                 iui=g_new(io_users_item_t,1);
98                 iui->next=iu->items;
99                 iu->items=iui;
100                 iui->name1=g_strdup(name1);
101                 iui->name2=g_strdup(name2);
102                 iui->conv_id=conv_id;
103                 iui->frames1=0;
104                 iui->frames2=0;
105                 iui->bytes1=0;
106                 iui->bytes2=0;
107                 memcpy(&iui->start_rel_time, rel_ts, sizeof(iui->start_rel_time));
108                 memcpy(&iui->stop_rel_time, rel_ts, sizeof(iui->stop_rel_time));
109                 memcpy(&iui->start_abs_time, abs_ts, sizeof(iui->start_abs_time));
110         }
111         else {
112                 if (nstime_cmp(rel_ts, &iui->stop_rel_time) > 0) {
113                         memcpy(&iui->stop_rel_time, rel_ts, sizeof(iui->stop_rel_time));
114                 } else if (nstime_cmp(rel_ts, &iui->start_rel_time) < 0) {
115                         memcpy(&iui->start_rel_time, rel_ts, sizeof(iui->start_rel_time));
116                         memcpy(&iui->start_abs_time, abs_ts, sizeof(iui->start_abs_time));
117                 }
118         }
119
120         if(direction){
121                 iui->frames1++;
122                 iui->bytes1+=pkt_len;
123         } else {
124                 iui->frames2++;
125                 iui->bytes2+=pkt_len;
126         }
127 }
128
129 static void
130 iousers_process_address_packet(io_users_t *iu, const address *src, const address *dst, guint64 pkt_len, 
131                                                                 nstime_t *ts)
132 {
133         const address *addr1, *addr2;
134         io_users_item_t *iui;
135
136         if(CMP_ADDRESS(src, dst)>0){
137                 addr1=src;
138                 addr2=dst;
139         } else {
140                 addr2=src;
141                 addr1=dst;
142         }
143
144         for(iui=iu->items;iui;iui=iui->next){
145                 if((!CMP_ADDRESS(&iui->addr1, addr1))
146                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
147                         break;
148                 }
149         }
150
151         if(!iui){
152                 iui=g_new(io_users_item_t,1);
153                 iui->next=iu->items;
154                 iu->items=iui;
155                 COPY_ADDRESS(&iui->addr1, addr1);
156                 iui->name1=g_strdup(ep_address_to_str(addr1));
157                 COPY_ADDRESS(&iui->addr2, addr2);
158                 iui->name2=g_strdup(ep_address_to_str(addr2));
159                 iui->frames1=0;
160                 iui->frames2=0;
161                 iui->bytes1=0;
162                 iui->bytes2=0;
163                 memcpy(&iui->start_rel_time, ts, sizeof(iui->start_rel_time));
164                 memcpy(&iui->stop_rel_time, ts, sizeof(iui->stop_rel_time));
165         }
166         else {
167                 if (nstime_cmp(ts, &iui->stop_rel_time) > 0) {
168                         memcpy(&iui->stop_rel_time, ts, sizeof(iui->stop_rel_time));
169                 } else if (nstime_cmp(ts, &iui->start_rel_time) < 0) {
170                         memcpy(&iui->start_rel_time, ts, sizeof(iui->start_rel_time));
171                 }
172         }
173
174         if(!CMP_ADDRESS(dst, &iui->addr1)){
175                 iui->frames1++;
176                 iui->bytes1+=pkt_len;
177         } else {
178                 iui->frames2++;
179                 iui->bytes2+=pkt_len;
180         }
181 }
182
183 static int
184 iousers_udpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vudph)
185 {
186         io_users_t *iu=(io_users_t *)arg;
187         const e_udphdr *udph=(const e_udphdr *)vudph;
188         char name1[256],name2[256];
189         int direction=0;
190
191         if(udph->uh_sport>udph->uh_dport){
192                 direction=0;
193                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
194                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
195         } else if(udph->uh_sport<udph->uh_dport){
196                 direction=1;
197                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
198                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
199         } else if(CMP_ADDRESS(&udph->ip_src, &udph->ip_dst)>0){
200                 direction=0;
201                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
202                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
203         } else {
204                 direction=1;
205                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
206                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
207         }
208
209         iousers_process_name_packet(iu, name1, name2, direction, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->fd->abs_ts);
210         
211         return 1;
212 }
213
214
215 static int
216 iousers_sctp_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vsctp)
217 {
218         io_users_t *iu=(io_users_t *)arg;
219         const struct _sctp_info* sctph = (const struct _sctp_info*)vsctp;
220         char name1[256],name2[256], s_sport[10], s_dport[10];
221         int direction=0;
222
223         g_snprintf(s_sport, sizeof s_sport, "%d",sctph->sport);
224         g_snprintf(s_dport, sizeof s_dport, "%d",sctph->dport);
225
226         if(sctph->sport > sctph->dport) {
227                 direction=0;
228                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&sctph->ip_src),s_sport);
229                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&sctph->ip_dst),s_dport);
230         } else if(sctph->sport < sctph->dport) {
231                 direction=1;
232                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&sctph->ip_src),s_sport);
233                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&sctph->ip_dst),s_dport);
234         } else {
235                 direction=0;
236                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&sctph->ip_src),s_sport);
237                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&sctph->ip_dst),s_dport);
238         }
239
240         iousers_process_name_packet(iu, name1, name2, direction, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->fd->abs_ts);
241
242         return 1;
243 }
244
245
246 static int
247 iousers_tcpip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtcph)
248 {
249         io_users_t *iu=(io_users_t *)arg;
250         const struct tcpheader *tcph=(const struct tcpheader *)vtcph;
251         char name1[256],name2[256];
252         int direction=0;
253
254         if(tcph->th_sport>tcph->th_dport){
255                 direction=0;
256                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
257                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
258         } else if(tcph->th_sport<tcph->th_dport){
259                 direction=1;
260                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
261                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
262         } else if(CMP_ADDRESS(&tcph->ip_src, &tcph->ip_dst)>0){
263                 direction=0;
264                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
265                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
266         } else {
267                 direction=1;
268                 g_snprintf(name2,256,"%s:%s",ep_address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
269                 g_snprintf(name1,256,"%s:%s",ep_address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
270         }
271
272         iousers_process_name_packet_with_conv_id(iu, name1, name2, tcph->th_stream, direction, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->fd->abs_ts);
273
274         return 1;
275 }
276
277
278 static int
279 iousers_ip_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
280 {
281         io_users_t *iu=(io_users_t *)arg;
282         const ws_ip *iph=(const ws_ip *)vip;
283
284         iousers_process_address_packet(iu, &iph->ip_src, &iph->ip_dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
285
286         return 1;
287 }
288
289 static int
290 iousers_ipv6_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
291 {
292         io_users_t *iu=(io_users_t *)arg;
293         const struct ip6_hdr *ip6h=(const struct ip6_hdr *)vip;
294         address src, dst;
295
296         /* Addresses aren't implemented as 'address' type in struct ip6_hdr */
297         src.type = dst.type = AT_IPv6;
298         src.len  = dst.len = sizeof(struct e_in6_addr);
299         src.data = &ip6h->ip6_src;
300         dst.data = &ip6h->ip6_dst;
301
302         iousers_process_address_packet(iu, &src, &dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
303
304         return 1;
305 }
306
307 static int
308 iousers_ipx_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vipx)
309 {
310         io_users_t *iu=(io_users_t *)arg;
311         const ipxhdr_t *ipxh=(const ipxhdr_t *)vipx;
312
313         iousers_process_address_packet(iu, &ipxh->ipx_src, &ipxh->ipx_dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
314
315         return 1;
316 }
317
318 static int
319 iousers_fc_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vfc)
320 {
321         io_users_t *iu=(io_users_t *)arg;
322         const fc_hdr *fchdr=(const fc_hdr *)vfc;
323
324         iousers_process_address_packet(iu, &fchdr->s_id, &fchdr->d_id, pinfo->fd->pkt_len, &pinfo->rel_ts);
325
326         return 1;
327 }
328
329 static int
330 iousers_eth_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
331 {
332         io_users_t *iu=(io_users_t *)arg;
333         const eth_hdr *ehdr=(const eth_hdr *)veth;
334
335         iousers_process_address_packet(iu, &ehdr->src, &ehdr->dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
336
337         return 1;
338 }
339
340 static int
341 iousers_fddi_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *veth)
342 {
343         io_users_t *iu=(io_users_t *)arg;
344         const fddi_hdr *ehdr=(const fddi_hdr *)veth;
345
346         iousers_process_address_packet(iu, &ehdr->src, &ehdr->dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
347
348         return 1;
349 }
350
351 static int
352 iousers_tr_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vtr)
353 {
354         io_users_t *iu=(io_users_t *)arg;
355         const tr_hdr *trhdr=(const tr_hdr *)vtr;
356
357         iousers_process_address_packet(iu, &trhdr->src, &trhdr->dst, pinfo->fd->pkt_len, &pinfo->rel_ts);
358
359         return 1;
360 }
361
362 static void
363 iousers_draw(void *arg)
364 {
365         io_users_t *iu = (io_users_t *)arg;
366         io_users_item_t *iui;
367         guint32 last_frames, max_frames;
368         struct tm * tm_time;
369
370         printf("================================================================================\n");
371         printf("%s Conversations\n",iu->type);
372         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
373
374         switch (timestamp_get_type()) {
375         case TS_ABSOLUTE:
376                 printf("                                               |       <-      | |       ->      | |     Total     | Absolute Time  |   Duration   |\n");
377                 printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |      Start     |              |\n");
378                 break;
379         case TS_ABSOLUTE_WITH_DATE:
380                 printf("                                               |       <-      | |       ->      | |     Total     | Absolute Date  |   Duration   |\n");
381                 printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |     Start      |              |\n");
382                 break;
383         case TS_RELATIVE:
384         case TS_NOT_SET:
385         default:
386                 printf("                                               |       <-      | |       ->      | |     Total     |    Relative    |   Duration   |\n");
387                 printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |      Start     |              |\n");
388                 break;
389         }
390
391         max_frames=0xffffffff;
392         do {
393                 last_frames=0;
394                 for(iui=iu->items;iui;iui=iui->next){
395                         guint32 tot_frames;
396                         tot_frames=iui->frames1+iui->frames2;
397
398                         if((tot_frames>last_frames)
399                         &&(tot_frames<max_frames)){
400                                 last_frames=tot_frames;
401                         }
402                 }
403                 for(iui=iu->items;iui;iui=iui->next){
404                         guint32 tot_frames;
405                         tot_frames=iui->frames1+iui->frames2;
406
407                         if(tot_frames==last_frames){
408                                 printf("%-20s <-> %-20s  %6d %9" G_GINT64_MODIFIER "d  %6d %9" G_GINT64_MODIFIER "d  %6d %9" G_GINT64_MODIFIER "d  ",
409                                         iui->name1, iui->name2,
410                                         iui->frames1, iui->bytes1,
411                                         iui->frames2, iui->bytes2,
412                                         iui->frames1+iui->frames2,
413                                         iui->bytes1+iui->bytes2
414                                 );
415
416                                 tm_time = localtime(&iui->start_abs_time.secs);
417                                 switch (timestamp_get_type()) {
418                                 case TS_ABSOLUTE:
419                                         printf("%02d:%02d:%02d   %12.4f\n",
420                                                  tm_time->tm_hour,
421                                                  tm_time->tm_min,
422                                                  tm_time->tm_sec,
423                                                  nstime_to_sec(&iui->stop_rel_time) - nstime_to_sec(&iui->start_rel_time));
424                                         break;
425                                 case TS_ABSOLUTE_WITH_DATE:
426                                         printf("%04d-%02d-%02d %02d:%02d:%02d   %12.4f\n",
427                                                  tm_time->tm_year + 1900,
428                                                  tm_time->tm_mon + 1,
429                                                  tm_time->tm_mday,
430                                                  tm_time->tm_hour,
431                                                  tm_time->tm_min,
432                                                  tm_time->tm_sec,
433                                                  nstime_to_sec(&iui->stop_rel_time) - nstime_to_sec(&iui->start_rel_time));
434                                         break;
435                                 case TS_RELATIVE:
436                                 case TS_NOT_SET:
437                                 default:
438                                         printf("%14.9f   %12.4f\n",
439                                                 nstime_to_sec(&iui->start_rel_time),
440                                                 nstime_to_sec(&iui->stop_rel_time) - nstime_to_sec(&iui->start_rel_time)
441                                         );
442                                         break;
443                                 }
444                         }
445                 }
446                 max_frames=last_frames;
447         } while(last_frames);
448         printf("================================================================================\n");
449 }
450
451 static void
452 iousers_init(const char *opt_arg, void* userdata _U_)
453 {
454         const char *filter=NULL;
455         const char *tap_type, *tap_type_name;
456         tap_packet_cb packet_func;
457         io_users_t *iu=NULL;
458         GString *error_string;
459
460         if(!strncmp(opt_arg,"conv,eth",8)){
461                 if(opt_arg[8]==','){
462                         filter=opt_arg+9;
463                 } else {
464                         filter=NULL;
465                 }
466                 tap_type="eth";
467                 tap_type_name="Ethernet";
468                 packet_func=iousers_eth_packet;
469         } else if(!strncmp(opt_arg,"conv,fc",7)){
470                 if(opt_arg[7]==','){
471                         filter=opt_arg+8;
472                 } else {
473                         filter=NULL;
474                 }
475                 tap_type="fc";
476                 tap_type_name="Fibre Channel";
477                 packet_func=iousers_fc_packet;
478         } else if(!strncmp(opt_arg,"conv,fddi",9)){
479                 if(opt_arg[9]==','){
480                         filter=opt_arg+10;
481                 } else {
482                         filter=NULL;
483                 }
484                 tap_type="fddi";
485                 tap_type_name="FDDI";
486                 packet_func=iousers_fddi_packet;
487         } else if(!strncmp(opt_arg,"conv,tcp",8)){
488                 if(opt_arg[8]==','){
489                         filter=opt_arg+9;
490                 } else {
491                         filter=NULL;
492                 }
493                 tap_type="tcp";
494                 tap_type_name="TCP";
495                 packet_func=iousers_tcpip_packet;
496         } else if(!strncmp(opt_arg,"conv,udp",8)){
497                 if(opt_arg[8]==','){
498                         filter=opt_arg+9;
499                 } else {
500                         filter=NULL;
501                 }
502                 tap_type="udp";
503                 tap_type_name="UDP";
504                 packet_func=iousers_udpip_packet;
505         } else if(!strncmp(opt_arg,"conv,tr",7)){
506                 if(opt_arg[7]==','){
507                         filter=opt_arg+8;
508                 } else {
509                         filter=NULL;
510                 }
511                 tap_type="tr";
512                 tap_type_name="Token Ring";
513                 packet_func=iousers_tr_packet;
514         } else if(!strncmp(opt_arg,"conv,ipx",8)){
515                 if(opt_arg[8]==','){
516                         filter=opt_arg+9;
517                 } else {
518                         filter=NULL;
519                 }
520                 tap_type="ipx";
521                 tap_type_name="IPX";
522                 packet_func=iousers_ipx_packet;
523         } else if(!strncmp(opt_arg,"conv,ipv6",9)){
524                 if(opt_arg[9]==','){
525                         filter=opt_arg+10;
526                 } else {
527                         filter=NULL;
528                 }
529                 tap_type="ipv6";
530                 tap_type_name="IPv6";
531                 packet_func=iousers_ipv6_packet;
532         } else if(!strncmp(opt_arg,"conv,ip",7)){
533                 if(opt_arg[7]==','){
534                         filter=opt_arg+8;
535                 } else {
536                         filter=NULL;
537                 }
538                 tap_type="ip";
539                 tap_type_name="IPv4";
540                 packet_func=iousers_ip_packet;
541         } else if(!strncmp(opt_arg,"conv,sctp",9)) {
542                 if(opt_arg[9]==','){
543                                 filter=opt_arg+10;
544                 } else {
545                         filter=NULL;
546                 }
547                 tap_type="sctp";
548                 tap_type_name="SCTP";
549                 packet_func=iousers_sctp_packet;
550         } else {
551                 fprintf(stderr, "tshark: invalid \"-z conv,<type>[,<filter>]\" argument\n");
552                 fprintf(stderr,"   <type> must be one of\n");
553                 fprintf(stderr,"      \"eth\"\n");
554                 fprintf(stderr,"      \"fc\"\n");
555                 fprintf(stderr,"      \"fddi\"\n");
556                 fprintf(stderr,"      \"ip\"\n");
557                 fprintf(stderr,"      \"ipx\"\n");
558                 fprintf(stderr,"      \"sctp\"\n");
559                 fprintf(stderr,"      \"tcp\"\n");
560                 fprintf(stderr,"      \"tr\"\n");
561                 fprintf(stderr,"      \"udp\"\n");
562                 exit(1);
563         }
564
565
566         iu=g_new(io_users_t,1);
567         iu->items=NULL;
568         iu->type=tap_type_name;
569         if(filter){
570                 iu->filter=g_strdup(filter);
571         } else {
572                 iu->filter=NULL;
573         }
574
575         error_string=register_tap_listener(tap_type, iu, filter, 0, NULL, packet_func, iousers_draw);
576         if(error_string){
577                 if(iu->items){
578                         g_free(iu->items);
579                 }
580                 g_free(iu);
581                 fprintf(stderr, "tshark: Couldn't register conversations tap: %s\n",
582                     error_string->str);
583                 g_string_free(error_string, TRUE);
584                 exit(1);
585         }
586
587 }
588
589 void
590 register_tap_listener_iousers(void)
591 {
592         register_stat_cmd_arg("conv,", iousers_init, NULL);
593 }