Put the name, as well as the value, of the family and subfamily fields
[obnox/wireshark/wip.git] / tap-iousers.c
1 /* tap-iousers.c
2  * iostat   2003 Ronnie Sahlberg
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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 "register.h"
41 #include <epan/dissectors/packet-ip.h>
42 #include <epan/dissectors/packet-ipx.h>
43 #include <epan/dissectors/packet-tcp.h>
44 #include <epan/dissectors/packet-udp.h>
45 #include <epan/dissectors/packet-eth.h>
46 #include <epan/dissectors/packet-tr.h>
47 #include <epan/dissectors/packet-fc.h>
48 #include <epan/dissectors/packet-fddi.h>
49 #include <string.h>
50
51 typedef struct _io_users_t {
52         char *type;
53         char *filter;
54         struct _io_users_item_t *items;
55 } io_users_t;
56
57 typedef struct _io_users_item_t {
58         struct _io_users_item_t *next;
59         char *name1;
60         char *name2;
61         address addr1;
62         address addr2; 
63         guint32 frames1;
64         guint32 frames2;
65         guint32 bytes1;
66         guint32 bytes2;
67 } io_users_item_t;
68
69
70 static int
71 iousers_udpip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vudph)
72 {
73         e_udphdr *udph=vudph;
74         char name1[256],name2[256];
75         io_users_item_t *iui;
76         int direction=0;
77
78         if(udph->uh_sport>udph->uh_dport){
79                 direction=0;
80                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
81                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
82         } else if(udph->uh_sport<udph->uh_dport){
83                 direction=1;
84                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
85                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
86         } else if(CMP_ADDRESS(&udph->ip_src, &udph->ip_dst)>0){
87                 direction=0;
88                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
89                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
90         } else {
91                 direction=1;
92                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
93                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
94         }
95
96         for(iui=iu->items;iui;iui=iui->next){
97                 if((!strcmp(iui->name1, name1))
98                 && (!strcmp(iui->name2, name2)) ){
99                         break;
100                 }
101         }
102
103         if(!iui){
104                 iui=g_malloc(sizeof(io_users_item_t));
105                 iui->next=iu->items;
106                 iu->items=iui;
107 /*              iui->addr1=NULL;*/
108                 iui->name1=strdup(name1);
109 /*              iui->addr2=NULL;*/
110                 iui->name2=strdup(name2);
111                 iui->frames1=0;
112                 iui->frames2=0;
113                 iui->bytes1=0;
114                 iui->bytes2=0;
115         }
116
117         if(direction){
118                 iui->frames1++;
119                 iui->bytes1+=pinfo->fd->pkt_len;
120         } else {
121                 iui->frames2++;
122                 iui->bytes2+=pinfo->fd->pkt_len;
123         }
124
125         return 1;
126 }
127
128
129 static int
130 iousers_tcpip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtcph)
131 {
132         struct tcpheader *tcph=vtcph;
133         char name1[256],name2[256];
134         io_users_item_t *iui;
135         int direction=0;
136
137         if(tcph->th_sport>tcph->th_dport){
138                 direction=0;
139                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
140                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
141         } else if(tcph->th_sport<tcph->th_dport){
142                 direction=1;
143                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
144                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
145         } else if(CMP_ADDRESS(&tcph->ip_src, &tcph->ip_dst)>0){
146                 direction=0;
147                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
148                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
149         } else {
150                 direction=1;
151                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
152                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
153         }
154
155         for(iui=iu->items;iui;iui=iui->next){
156                 if((!strcmp(iui->name1, name1))
157                 && (!strcmp(iui->name2, name2)) ){
158                         break;
159                 }
160         }
161
162         if(!iui){
163                 iui=g_malloc(sizeof(io_users_item_t));
164                 iui->next=iu->items;
165                 iu->items=iui;
166 /*              iui->addr1=NULL;*/
167                 iui->name1=strdup(name1);
168 /*              iui->addr2=NULL;*/
169                 iui->name2=strdup(name2);
170                 iui->frames1=0;
171                 iui->frames2=0;
172                 iui->bytes1=0;
173                 iui->bytes2=0;
174         }
175
176         if(direction){
177                 iui->frames1++;
178                 iui->bytes1+=pinfo->fd->pkt_len;
179         } else {
180                 iui->frames2++;
181                 iui->bytes2+=pinfo->fd->pkt_len;
182         }
183
184         return 1;
185 }
186
187
188 static int
189 iousers_ip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vip)
190 {
191         e_ip *iph=vip;
192         address *addr1, *addr2;
193         io_users_item_t *iui;
194
195         if(CMP_ADDRESS(&iph->ip_src, &iph->ip_dst)>0){
196                 addr1=&iph->ip_src;
197                 addr2=&iph->ip_dst;
198         } else {
199                 addr2=&iph->ip_src;
200                 addr1=&iph->ip_dst;
201         }
202
203         for(iui=iu->items;iui;iui=iui->next){
204                 if((!CMP_ADDRESS(&iui->addr1, addr1))
205                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
206                         break;
207                 }
208         }
209
210         if(!iui){
211                 iui=g_malloc(sizeof(io_users_item_t));
212                 iui->next=iu->items;
213                 iu->items=iui;
214                 COPY_ADDRESS(&iui->addr1, addr1);
215                 iui->name1=strdup(address_to_str(addr1));
216                 COPY_ADDRESS(&iui->addr2, addr2);
217                 iui->name2=strdup(address_to_str(addr2));
218                 iui->frames1=0;
219                 iui->frames2=0;
220                 iui->bytes1=0;
221                 iui->bytes2=0;
222         }
223
224         if(!CMP_ADDRESS(&iph->ip_dst, &iui->addr1)){
225                 iui->frames1++;
226                 iui->bytes1+=pinfo->fd->pkt_len;
227         } else {
228                 iui->frames2++;
229                 iui->bytes2+=pinfo->fd->pkt_len;
230         }
231
232         return 1;
233 }
234
235 static int
236 iousers_ipx_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vipx)
237 {
238         ipxhdr_t *ipxh=vipx;
239         address *addr1, *addr2;
240         io_users_item_t *iui;
241
242         if(CMP_ADDRESS(&ipxh->ipx_src, &ipxh->ipx_dst)>0){
243                 addr1=&ipxh->ipx_src;
244                 addr2=&ipxh->ipx_dst;
245         } else {
246                 addr2=&ipxh->ipx_src;
247                 addr1=&ipxh->ipx_dst;
248         }
249
250         for(iui=iu->items;iui;iui=iui->next){
251                 if((!CMP_ADDRESS(&iui->addr1, addr1))
252                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
253                         break;
254                 }
255         }
256
257         if(!iui){
258                 iui=g_malloc(sizeof(io_users_item_t));
259                 iui->next=iu->items;
260                 iu->items=iui;
261                 COPY_ADDRESS(&iui->addr1, addr1);
262                 iui->name1=strdup(address_to_str(addr1));
263                 COPY_ADDRESS(&iui->addr2, addr2);
264                 iui->name2=strdup(address_to_str(addr2));
265                 iui->frames1=0;
266                 iui->frames2=0;
267                 iui->bytes1=0;
268                 iui->bytes2=0;
269         }
270
271         if(!CMP_ADDRESS(&ipxh->ipx_dst, &iui->addr1)){
272                 iui->frames1++;
273                 iui->bytes1+=pinfo->fd->pkt_len;
274         } else {
275                 iui->frames2++;
276                 iui->bytes2+=pinfo->fd->pkt_len;
277         }
278
279         return 1;
280 }
281
282 static int
283 iousers_fc_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vfc)
284 {
285         fc_hdr *fchdr=vfc;
286         address *addr1, *addr2;
287         io_users_item_t *iui;
288
289         if(CMP_ADDRESS(&fchdr->s_id, &fchdr->d_id)<0){
290                 addr1=&fchdr->s_id;
291                 addr2=&fchdr->d_id;
292         } else {
293                 addr2=&fchdr->s_id;
294                 addr1=&fchdr->d_id;
295         }
296
297         for(iui=iu->items;iui;iui=iui->next){
298                 if((!CMP_ADDRESS(&iui->addr1, addr1))
299                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
300                         break;
301                 }
302         }
303
304         if(!iui){
305                 iui=g_malloc(sizeof(io_users_item_t));
306                 iui->next=iu->items;
307                 iu->items=iui;
308                 COPY_ADDRESS(&iui->addr1, addr1);
309                 iui->name1=strdup(address_to_str(addr1));
310                 COPY_ADDRESS(&iui->addr2, addr2);
311                 iui->name2=strdup(address_to_str(addr2));
312                 iui->frames1=0;
313                 iui->frames2=0;
314                 iui->bytes1=0;
315                 iui->bytes2=0;
316         }
317
318         if(!CMP_ADDRESS(&fchdr->d_id,&iui->addr1)){
319                 iui->frames1++;
320                 iui->bytes1+=pinfo->fd->pkt_len;
321         } else {
322                 iui->frames2++;
323                 iui->bytes2+=pinfo->fd->pkt_len;
324         }
325
326         return 1;
327 }
328
329 static int
330 iousers_eth_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *veth)
331 {
332         eth_hdr *ehdr=veth;
333         address *addr1, *addr2;
334         io_users_item_t *iui;
335
336         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
337                 addr1=&ehdr->src;
338                 addr2=&ehdr->dst;
339         } else {
340                 addr2=&ehdr->src;
341                 addr1=&ehdr->dst;
342         }
343
344         for(iui=iu->items;iui;iui=iui->next){
345                 if((!CMP_ADDRESS(&iui->addr1, addr1))
346                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
347                         break;
348                 }
349         }
350
351         if(!iui){
352                 iui=g_malloc(sizeof(io_users_item_t));
353                 iui->next=iu->items;
354                 iu->items=iui;
355                 COPY_ADDRESS(&iui->addr1, addr1);
356                 iui->name1=strdup(address_to_str(addr1));
357                 COPY_ADDRESS(&iui->addr2, addr2);
358                 iui->name2=strdup(address_to_str(addr2));
359                 iui->frames1=0;
360                 iui->frames2=0;
361                 iui->bytes1=0;
362                 iui->bytes2=0;
363         }
364
365         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
366                 iui->frames1++;
367                 iui->bytes1+=pinfo->fd->pkt_len;
368         } else {
369                 iui->frames2++;
370                 iui->bytes2+=pinfo->fd->pkt_len;
371         }
372
373         return 1;
374 }
375
376 static int
377 iousers_fddi_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *veth)
378 {
379         fddi_hdr *ehdr=veth;
380         address *addr1, *addr2;
381         io_users_item_t *iui;
382
383         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
384                 addr1=&ehdr->src;
385                 addr2=&ehdr->dst;
386         } else {
387                 addr2=&ehdr->src;
388                 addr1=&ehdr->dst;
389         }
390
391         for(iui=iu->items;iui;iui=iui->next){
392                 if((!CMP_ADDRESS(&iui->addr1, addr1))
393                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
394                         break;
395                 }
396         }
397
398         if(!iui){
399                 iui=g_malloc(sizeof(io_users_item_t));
400                 iui->next=iu->items;
401                 iu->items=iui;
402                 COPY_ADDRESS(&iui->addr1, addr1);
403                 iui->name1=strdup(address_to_str(addr1));
404                 COPY_ADDRESS(&iui->addr2, addr2);
405                 iui->name2=strdup(address_to_str(addr2));
406                 iui->frames1=0;
407                 iui->frames2=0;
408                 iui->bytes1=0;
409                 iui->bytes2=0;
410         }
411
412         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
413                 iui->frames1++;
414                 iui->bytes1+=pinfo->fd->pkt_len;
415         } else {
416                 iui->frames2++;
417                 iui->bytes2+=pinfo->fd->pkt_len;
418         }
419
420         return 1;
421 }
422
423 static int
424 iousers_tr_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtr)
425 {
426         tr_hdr *trhdr=vtr;
427         address *addr1, *addr2;
428         io_users_item_t *iui;
429
430         if(CMP_ADDRESS(&trhdr->src, &trhdr->dst)<0){
431                 addr1=&trhdr->src;
432                 addr2=&trhdr->dst;
433         } else {
434                 addr2=&trhdr->src;
435                 addr1=&trhdr->dst;
436         }
437
438         for(iui=iu->items;iui;iui=iui->next){
439                 if((!CMP_ADDRESS(&iui->addr1, addr1))
440                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
441                         break;
442                 }
443         }
444
445         if(!iui){
446                 iui=g_malloc(sizeof(io_users_item_t));
447                 iui->next=iu->items;
448                 iu->items=iui;
449                 COPY_ADDRESS(&iui->addr1, addr1);
450                 iui->name1=strdup(address_to_str(addr1));
451                 COPY_ADDRESS(&iui->addr2, addr2);
452                 iui->name2=strdup(address_to_str(addr2));
453                 iui->frames1=0;
454                 iui->frames2=0;
455                 iui->bytes1=0;
456                 iui->bytes2=0;
457         }
458
459         if(!CMP_ADDRESS(&trhdr->dst,&iui->addr1)){
460                 iui->frames1++;
461                 iui->bytes1+=pinfo->fd->pkt_len;
462         } else {
463                 iui->frames2++;
464                 iui->bytes2+=pinfo->fd->pkt_len;
465         }
466
467         return 1;
468 }
469
470 static void
471 iousers_draw(io_users_t *iu)
472 {
473         io_users_item_t *iui;
474         guint32 last_frames, max_frames;
475
476         printf("================================================================================\n");
477         printf("%s Conversations\n",iu->type);
478         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
479         printf("                                               |       <-      | |       ->      | |     Total     |\n");
480         printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |\n");
481         max_frames=0xffffffff;
482         do {
483                 last_frames=0;
484                 for(iui=iu->items;iui;iui=iui->next){
485                         guint32 tot_frames;
486                         tot_frames=iui->frames1+iui->frames2;
487
488                         if((tot_frames>last_frames)
489                         &&(tot_frames<max_frames)){
490                                 last_frames=tot_frames;
491                         }
492                 }
493                 for(iui=iu->items;iui;iui=iui->next){
494                         guint32 tot_frames;
495                         tot_frames=iui->frames1+iui->frames2;
496
497                         if(tot_frames==last_frames){
498                                 printf("%-20s <-> %-20s  %6d %9d  %6d %9d  %6d %9d\n",
499                                         iui->name1, iui->name2,
500                                         iui->frames1, iui->bytes1,
501                                         iui->frames2, iui->bytes2,
502                                         iui->frames1+iui->frames2,
503                                         iui->bytes1+iui->bytes2
504                                 );
505                         }
506                 }
507                 max_frames=last_frames;
508         } while(last_frames);
509         printf("================================================================================\n");
510 }
511
512 void
513 iousers_init(char *optarg)
514 {
515         char *filter=NULL;
516         char *tap_type, *tap_type_name;
517         static int (*packet_func)(io_users_t *, packet_info *, epan_dissect_t *, void *);
518         io_users_t *iu=NULL;
519         GString *error_string;
520
521         if(!strncmp(optarg,"conv,eth",8)){
522                 if(optarg[8]==','){
523                         filter=optarg+9;
524                 } else {
525                         filter=NULL;
526                 }
527                 tap_type="eth";
528                 tap_type_name="Ethernet";
529                 packet_func=iousers_eth_packet;
530         } else if(!strncmp(optarg,"conv,fc",7)){
531                 if(optarg[7]==','){
532                         filter=optarg+8;
533                 } else {
534                         filter=NULL;
535                 }
536                 tap_type="fc";
537                 tap_type_name="Fibre Channel";
538                 packet_func=iousers_fc_packet;
539         } else if(!strncmp(optarg,"conv,fddi",9)){
540                 if(optarg[9]==','){
541                         filter=optarg+10;
542                 } else {
543                         filter=NULL;
544                 }
545                 tap_type="fddi";
546                 tap_type_name="FDDI";
547                 packet_func=iousers_fddi_packet;
548         } else if(!strncmp(optarg,"conv,tcp",8)){
549                 if(optarg[8]==','){
550                         filter=optarg+9;
551                 } else {
552                         filter=NULL;
553                 }
554                 tap_type="tcp";
555                 tap_type_name="TCP";
556                 packet_func=iousers_tcpip_packet;
557         } else if(!strncmp(optarg,"conv,udp",8)){
558                 if(optarg[8]==','){
559                         filter=optarg+9;
560                 } else {
561                         filter=NULL;
562                 }
563                 tap_type="udp";
564                 tap_type_name="UDP";
565                 packet_func=iousers_udpip_packet;
566         } else if(!strncmp(optarg,"conv,tr",7)){
567                 if(optarg[7]==','){
568                         filter=optarg+8;
569                 } else {
570                         filter=NULL;
571                 }
572                 tap_type="tr";
573                 tap_type_name="Token Ring";
574                 packet_func=iousers_tr_packet;
575         } else if(!strncmp(optarg,"conv,ipx",8)){
576                 if(optarg[8]==','){
577                         filter=optarg+9;
578                 } else {
579                         filter=NULL;
580                 }
581                 tap_type="ipx";
582                 tap_type_name="IPX";
583                 packet_func=iousers_ipx_packet;
584         } else if(!strncmp(optarg,"conv,ip",7)){
585                 if(optarg[7]==','){
586                         filter=optarg+8;
587                 } else {
588                         filter=NULL;
589                 }
590                 tap_type="ip";
591                 tap_type_name="IPv4";
592                 packet_func=iousers_ip_packet;
593         } else {
594                 fprintf(stderr, "tethereal: invalid \"-z conv,<type>[,<filter>]\" argument\n");
595                 fprintf(stderr,"   <type> must be one of\n");
596                 fprintf(stderr,"      \"eth\"\n");
597                 fprintf(stderr,"      \"fc\"\n");
598                 fprintf(stderr,"      \"fddi\"\n");
599                 fprintf(stderr,"      \"ip\"\n");
600                 fprintf(stderr,"      \"ipx\"\n");
601                 fprintf(stderr,"      \"tcp\"\n");
602                 fprintf(stderr,"      \"tr\"\n");
603                 fprintf(stderr,"      \"udp\"\n");
604                 exit(1);
605         }
606
607
608         iu=g_malloc(sizeof(io_users_t));
609         iu->items=NULL;
610         iu->type=tap_type_name;
611         if(filter){
612                 iu->filter=strdup(filter);
613         } else {
614                 iu->filter=NULL;
615         }
616
617         error_string=register_tap_listener(tap_type, iu, filter, NULL, (void*)packet_func, (void*)iousers_draw);
618         if(error_string){
619                 if(iu->items){
620                         g_free(iu->items);
621                 }
622                 g_free(iu);
623                 fprintf(stderr, "tethereal: Couldn't register conversations tap: %s\n",
624                     error_string->str);
625                 g_string_free(error_string, TRUE);
626                 exit(1);
627         }
628
629 }
630
631 void
632 register_tap_listener_iousers(void)
633 {
634         register_ethereal_tap("conv,", iousers_init);
635 }
636