Make various lengths unsigned in "dissect_fhandle_data_unknown()", so
[obnox/wireshark/wip.git] / tap-iousers.c
1 /* tap-iousers.c
2  * iostat   2003 Ronnie Sahlberg
3  *
4  * $Id: tap-iousers.c,v 1.12 2003/08/25 00:44:20 guy Exp $
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/resolv.h>
39 #include "tap.h"
40 #include "register.h"
41 #include "packet-ip.h"
42 #include "packet-ipx.h"
43 #include "packet-tcp.h"
44 #include "packet-udp.h"
45 #include "packet-eth.h"
46 #include "packet-tr.h"
47 #include "packet-fc.h"
48 #include <string.h>
49
50 typedef struct _io_users_t {
51         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         address addr1;
61         address addr2; 
62         guint32 frames1;
63         guint32 frames2;
64         guint32 bytes1;
65         guint32 bytes2;
66 } io_users_item_t;
67
68
69 static int
70 iousers_udpip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vudph)
71 {
72         e_udphdr *udph=vudph;
73         char name1[256],name2[256];
74         io_users_item_t *iui;
75         int direction=0;
76
77         if(CMP_ADDRESS(&udph->ip_src, &udph->ip_dst)>0){
78                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
79                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
80         } else {
81                 direction=1;
82                 snprintf(name2,256,"%s:%s",address_to_str(&udph->ip_src),get_udp_port(udph->uh_sport));
83                 snprintf(name1,256,"%s:%s",address_to_str(&udph->ip_dst),get_udp_port(udph->uh_dport));
84         }
85
86         for(iui=iu->items;iui;iui=iui->next){
87                 if((!strcmp(iui->name1, name1))
88                 && (!strcmp(iui->name2, name2)) ){
89                         break;
90                 }
91         }
92
93         if(!iui){
94                 iui=g_malloc(sizeof(io_users_item_t));
95                 iui->next=iu->items;
96                 iu->items=iui;
97 /*              iui->addr1=NULL;*/
98                 iui->name1=strdup(name1);
99 /*              iui->addr2=NULL;*/
100                 iui->name2=strdup(name2);
101                 iui->frames1=0;
102                 iui->frames2=0;
103                 iui->bytes1=0;
104                 iui->bytes2=0;
105         }
106
107         if(direction){
108                 iui->frames1++;
109                 iui->bytes1+=pinfo->fd->pkt_len;
110         } else {
111                 iui->frames2++;
112                 iui->bytes2+=pinfo->fd->pkt_len;
113         }
114
115         return 1;
116 }
117
118
119 static int
120 iousers_tcpip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtcph)
121 {
122         struct tcpheader *tcph=vtcph;
123         char name1[256],name2[256];
124         io_users_item_t *iui;
125         int direction=0;
126
127         if(CMP_ADDRESS(&tcph->ip_src, &tcph->ip_dst)>0){
128                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
129                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
130         } else {
131                 direction=1;
132                 snprintf(name2,256,"%s:%s",address_to_str(&tcph->ip_src),get_tcp_port(tcph->th_sport));
133                 snprintf(name1,256,"%s:%s",address_to_str(&tcph->ip_dst),get_tcp_port(tcph->th_dport));
134         }
135
136         for(iui=iu->items;iui;iui=iui->next){
137                 if((!strcmp(iui->name1, name1))
138                 && (!strcmp(iui->name2, name2)) ){
139                         break;
140                 }
141         }
142
143         if(!iui){
144                 iui=g_malloc(sizeof(io_users_item_t));
145                 iui->next=iu->items;
146                 iu->items=iui;
147 /*              iui->addr1=NULL;*/
148                 iui->name1=strdup(name1);
149 /*              iui->addr2=NULL;*/
150                 iui->name2=strdup(name2);
151                 iui->frames1=0;
152                 iui->frames2=0;
153                 iui->bytes1=0;
154                 iui->bytes2=0;
155         }
156
157         if(direction){
158                 iui->frames1++;
159                 iui->bytes1+=pinfo->fd->pkt_len;
160         } else {
161                 iui->frames2++;
162                 iui->bytes2+=pinfo->fd->pkt_len;
163         }
164
165         return 1;
166 }
167
168
169 static int
170 iousers_ip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vip)
171 {
172         e_ip *iph=vip;
173         address *addr1, *addr2;
174         io_users_item_t *iui;
175
176         if(CMP_ADDRESS(&iph->ip_src, &iph->ip_dst)>0){
177                 addr1=&iph->ip_src;
178                 addr2=&iph->ip_dst;
179         } else {
180                 addr2=&iph->ip_src;
181                 addr1=&iph->ip_dst;
182         }
183
184         for(iui=iu->items;iui;iui=iui->next){
185                 if((!CMP_ADDRESS(&iui->addr1, addr1))
186                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
187                         break;
188                 }
189         }
190
191         if(!iui){
192                 iui=g_malloc(sizeof(io_users_item_t));
193                 iui->next=iu->items;
194                 iu->items=iui;
195                 COPY_ADDRESS(&iui->addr1, addr1);
196                 iui->name1=strdup(address_to_str(addr1));
197                 COPY_ADDRESS(&iui->addr2, addr2);
198                 iui->name2=strdup(address_to_str(addr2));
199                 iui->frames1=0;
200                 iui->frames2=0;
201                 iui->bytes1=0;
202                 iui->bytes2=0;
203         }
204
205         if(!CMP_ADDRESS(&iph->ip_dst, &iui->addr1)){
206                 iui->frames1++;
207                 iui->bytes1+=pinfo->fd->pkt_len;
208         } else {
209                 iui->frames2++;
210                 iui->bytes2+=pinfo->fd->pkt_len;
211         }
212
213         return 1;
214 }
215
216 static int
217 iousers_ipx_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vipx)
218 {
219         ipxhdr_t *ipxh=vipx;
220         address *addr1, *addr2;
221         io_users_item_t *iui;
222
223         if(CMP_ADDRESS(&ipxh->ipx_src, &ipxh->ipx_dst)>0){
224                 addr1=&ipxh->ipx_src;
225                 addr2=&ipxh->ipx_dst;
226         } else {
227                 addr2=&ipxh->ipx_src;
228                 addr1=&ipxh->ipx_dst;
229         }
230
231         for(iui=iu->items;iui;iui=iui->next){
232                 if((!CMP_ADDRESS(&iui->addr1, addr1))
233                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
234                         break;
235                 }
236         }
237
238         if(!iui){
239                 iui=g_malloc(sizeof(io_users_item_t));
240                 iui->next=iu->items;
241                 iu->items=iui;
242                 COPY_ADDRESS(&iui->addr1, addr1);
243                 iui->name1=strdup(address_to_str(addr1));
244                 COPY_ADDRESS(&iui->addr2, addr2);
245                 iui->name2=strdup(address_to_str(addr2));
246                 iui->frames1=0;
247                 iui->frames2=0;
248                 iui->bytes1=0;
249                 iui->bytes2=0;
250         }
251
252         if(!CMP_ADDRESS(&ipxh->ipx_dst, &iui->addr1)){
253                 iui->frames1++;
254                 iui->bytes1+=pinfo->fd->pkt_len;
255         } else {
256                 iui->frames2++;
257                 iui->bytes2+=pinfo->fd->pkt_len;
258         }
259
260         return 1;
261 }
262
263 static int
264 iousers_fc_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vfc)
265 {
266         fc_hdr *fchdr=vfc;
267         address *addr1, *addr2;
268         io_users_item_t *iui;
269
270         if(CMP_ADDRESS(&fchdr->s_id, &fchdr->d_id)<0){
271                 addr1=&fchdr->s_id;
272                 addr2=&fchdr->d_id;
273         } else {
274                 addr2=&fchdr->s_id;
275                 addr1=&fchdr->d_id;
276         }
277
278         for(iui=iu->items;iui;iui=iui->next){
279                 if((!CMP_ADDRESS(&iui->addr1, addr1))
280                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
281                         break;
282                 }
283         }
284
285         if(!iui){
286                 iui=g_malloc(sizeof(io_users_item_t));
287                 iui->next=iu->items;
288                 iu->items=iui;
289                 COPY_ADDRESS(&iui->addr1, addr1);
290                 iui->name1=strdup(address_to_str(addr1));
291                 COPY_ADDRESS(&iui->addr2, addr2);
292                 iui->name2=strdup(address_to_str(addr2));
293                 iui->frames1=0;
294                 iui->frames2=0;
295                 iui->bytes1=0;
296                 iui->bytes2=0;
297         }
298
299         if(!CMP_ADDRESS(&fchdr->d_id,&iui->addr1)){
300                 iui->frames1++;
301                 iui->bytes1+=pinfo->fd->pkt_len;
302         } else {
303                 iui->frames2++;
304                 iui->bytes2+=pinfo->fd->pkt_len;
305         }
306
307         return 1;
308 }
309
310 static int
311 iousers_eth_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *veth)
312 {
313         eth_hdr *ehdr=veth;
314         address *addr1, *addr2;
315         io_users_item_t *iui;
316
317         if(CMP_ADDRESS(&ehdr->src, &ehdr->dst)<0){
318                 addr1=&ehdr->src;
319                 addr2=&ehdr->dst;
320         } else {
321                 addr2=&ehdr->src;
322                 addr1=&ehdr->dst;
323         }
324
325         for(iui=iu->items;iui;iui=iui->next){
326                 if((!CMP_ADDRESS(&iui->addr1, addr1))
327                 &&(!CMP_ADDRESS(&iui->addr2, addr2)) ){
328                         break;
329                 }
330         }
331
332         if(!iui){
333                 iui=g_malloc(sizeof(io_users_item_t));
334                 iui->next=iu->items;
335                 iu->items=iui;
336                 COPY_ADDRESS(&iui->addr1, addr1);
337                 iui->name1=strdup(address_to_str(addr1));
338                 COPY_ADDRESS(&iui->addr2, addr2);
339                 iui->name2=strdup(address_to_str(addr2));
340                 iui->frames1=0;
341                 iui->frames2=0;
342                 iui->bytes1=0;
343                 iui->bytes2=0;
344         }
345
346         if(!CMP_ADDRESS(&ehdr->dst,&iui->addr1)){
347                 iui->frames1++;
348                 iui->bytes1+=pinfo->fd->pkt_len;
349         } else {
350                 iui->frames2++;
351                 iui->bytes2+=pinfo->fd->pkt_len;
352         }
353
354         return 1;
355 }
356
357 static int
358 iousers_tr_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtr)
359 {
360         tr_hdr *trhdr=vtr;
361         address *addr1, *addr2;
362         io_users_item_t *iui;
363
364         if(CMP_ADDRESS(&trhdr->src, &trhdr->dst)<0){
365                 addr1=&trhdr->src;
366                 addr2=&trhdr->dst;
367         } else {
368                 addr2=&trhdr->src;
369                 addr1=&trhdr->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=strdup(address_to_str(addr1));
385                 COPY_ADDRESS(&iui->addr2, addr2);
386                 iui->name2=strdup(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(&trhdr->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 void
405 iousers_draw(io_users_t *iu)
406 {
407         io_users_item_t *iui;
408         guint32 last_frames, max_frames;
409
410         printf("================================================================================\n");
411         printf("%s Talkers\n",iu->type);
412         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
413         printf("                                               |       <-      | |       ->      | |     Total     |\n");
414         printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |\n");
415         max_frames=0xffffffff;
416         do {
417                 last_frames=0;
418                 for(iui=iu->items;iui;iui=iui->next){
419                         guint32 tot_frames;
420                         tot_frames=iui->frames1+iui->frames2;
421
422                         if((tot_frames>last_frames)
423                         &&(tot_frames<max_frames)){
424                                 last_frames=tot_frames;
425                         }
426                 }
427                 for(iui=iu->items;iui;iui=iui->next){
428                         guint32 tot_frames;
429                         tot_frames=iui->frames1+iui->frames2;
430
431                         if(tot_frames==last_frames){
432                                 printf("%-20s <-> %-20s  %6d %9d  %6d %9d  %6d %9d\n",
433                                         iui->name1, iui->name2,
434                                         iui->frames1, iui->bytes1,
435                                         iui->frames2, iui->bytes2,
436                                         iui->frames1+iui->frames2,
437                                         iui->bytes1+iui->bytes2
438                                 );
439                         }
440                 }
441                 max_frames=last_frames;
442         } while(last_frames);
443         printf("================================================================================\n");
444 }
445
446 void
447 iousers_init(char *optarg)
448 {
449         char *filter=NULL;
450         char *tap_type, *tap_type_name;
451         static int (*packet_func)(io_users_t *, packet_info *, epan_dissect_t *, void *);
452         io_users_t *iu=NULL;
453         GString *error_string;
454
455         if(!strncmp(optarg,"talkers,eth",11)){
456                 if(optarg[11]==','){
457                         filter=optarg+12;
458                 } else {
459                         filter=NULL;
460                 }
461                 tap_type="eth";
462                 tap_type_name="Ethernet";
463                 packet_func=iousers_eth_packet;
464         } else if(!strncmp(optarg,"talkers,fc",10)){
465                 if(optarg[10]==','){
466                         filter=optarg+11;
467                 } else {
468                         filter=NULL;
469                 }
470                 tap_type="fc";
471                 tap_type_name="Fibre Channel";
472                 packet_func=iousers_fc_packet;
473         } else if(!strncmp(optarg,"talkers,tcp",11)){
474                 if(optarg[11]==','){
475                         filter=optarg+12;
476                 } else {
477                         filter=NULL;
478                 }
479                 tap_type="tcp";
480                 tap_type_name="TCP";
481                 packet_func=iousers_tcpip_packet;
482         } else if(!strncmp(optarg,"talkers,udp",11)){
483                 if(optarg[11]==','){
484                         filter=optarg+12;
485                 } else {
486                         filter=NULL;
487                 }
488                 tap_type="udp";
489                 tap_type_name="UDP";
490                 packet_func=iousers_udpip_packet;
491         } else if(!strncmp(optarg,"talkers,tr",10)){
492                 if(optarg[10]==','){
493                         filter=optarg+11;
494                 } else {
495                         filter=NULL;
496                 }
497                 tap_type="tr";
498                 tap_type_name="Token Ring";
499                 packet_func=iousers_tr_packet;
500         } else if(!strncmp(optarg,"talkers,ipx",11)){
501                 if(optarg[11]==','){
502                         filter=optarg+12;
503                 } else {
504                         filter=NULL;
505                 }
506                 tap_type="ipx";
507                 tap_type_name="IPX";
508                 packet_func=iousers_ipx_packet;
509         } else if(!strncmp(optarg,"talkers,ip",10)){
510                 if(optarg[10]==','){
511                         filter=optarg+11;
512                 } else {
513                         filter=NULL;
514                 }
515                 tap_type="ip";
516                 tap_type_name="IPv4";
517                 packet_func=iousers_ip_packet;
518         } else {
519                 fprintf(stderr, "tethereal: invalid \"-z talkers,<type>[,<filter>]\" argument\n");
520                 fprintf(stderr,"   <type> must be one of\n");
521                 fprintf(stderr,"      \"eth\"\n");
522                 fprintf(stderr,"      \"fc\"\n");
523                 fprintf(stderr,"      \"ip\"\n");
524                 fprintf(stderr,"      \"ipx\"\n");
525                 fprintf(stderr,"      \"tcp\"\n");
526                 fprintf(stderr,"      \"tr\"\n");
527                 fprintf(stderr,"      \"udp\"\n");
528                 exit(1);
529         }
530
531
532         iu=g_malloc(sizeof(io_users_t));
533         iu->items=NULL;
534         iu->type=tap_type_name;
535         if(filter){
536                 iu->filter=strdup(filter);
537         } else {
538                 iu->filter=NULL;
539         }
540
541         error_string=register_tap_listener(tap_type, iu, filter, NULL, (void*)packet_func, (void*)iousers_draw);
542         if(error_string){
543                 if(iu->items){
544                         g_free(iu->items);
545                 }
546                 g_free(iu);
547                 fprintf(stderr, "tethereal: Couldn't register talkers tap: %s\n",
548                     error_string->str);
549                 g_string_free(error_string, TRUE);
550                 exit(1);
551         }
552
553 }
554
555 void
556 register_tap_listener_iousers(void)
557 {
558         register_ethereal_tap("talkers,", iousers_init);
559 }
560