Squelch some compiler warnings.
[obnox/wireshark/wip.git] / tap-iousers.c
1 /* tap-iousers.c
2  * iostat   2003 Ronnie Sahlberg
3  *
4  * $Id: tap-iousers.c,v 1.7 2003/05/19 11:16:29 sahlberg 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-tcp.h"
43 #include "packet-udp.h"
44 #include "packet-eth.h"
45 #include "packet-tr.h"
46 #include <string.h>
47
48 typedef struct _io_users_t {
49         char *type;
50         char *filter;
51         struct _io_users_item_t *items;
52 } io_users_t;
53
54 typedef struct _io_users_item_t {
55         struct _io_users_item_t *next;
56         char *name1;
57         char *name2;
58         void *addr1;
59         void *addr2; 
60         guint32 frames1;
61         guint32 frames2;
62         guint32 bytes1;
63         guint32 bytes2;
64 } io_users_item_t;
65
66
67 /* XXX for now we only handle ipv4 as transport for udp.
68    should extend in the future to also handle ipv6
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         e_ip *ipv4_header;
77         int direction=0;
78
79         ipv4_header=udph->ip_header;
80         switch(ipv4_header->ip_v_hl>>4){
81         case 4:
82                 if(ipv4_header->ip_src>ipv4_header->ip_dst){
83                         snprintf(name1,256,"%s:%s",get_hostname(ipv4_header->ip_src),get_udp_port(udph->uh_sport));
84                         snprintf(name2,256,"%s:%s",get_hostname(ipv4_header->ip_dst),get_udp_port(udph->uh_dport));
85                 } else {
86                         direction=1;
87                         snprintf(name2,256,"%s:%s",get_hostname(ipv4_header->ip_src),get_udp_port(udph->uh_sport));
88                         snprintf(name1,256,"%s:%s",get_hostname(ipv4_header->ip_dst),get_udp_port(udph->uh_dport));
89                 }
90                 break;
91         default:
92                 return 0;
93         }
94
95         for(iui=iu->items;iui;iui=iui->next){
96                 if((!strcmp(iui->name1, name1))
97                 && (!strcmp(iui->name2, name2)) ){
98                         break;
99                 }
100         }
101
102         if(!iui){
103                 iui=g_malloc(sizeof(io_users_item_t));
104                 iui->next=iu->items;
105                 iu->items=iui;
106                 iui->addr1=NULL;
107                 iui->name1=strdup(name1);
108                 iui->addr2=NULL;
109                 iui->name2=strdup(name2);
110                 iui->frames1=0;
111                 iui->frames2=0;
112                 iui->bytes1=0;
113                 iui->bytes2=0;
114         }
115
116         if(direction){
117                 iui->frames1++;
118                 iui->bytes1+=pinfo->fd->pkt_len;
119         } else {
120                 iui->frames2++;
121                 iui->bytes2+=pinfo->fd->pkt_len;
122         }
123
124         return 1;
125 }
126
127 /* XXX for now we only handle ipv4 as transport for tcp.
128    should extend in the future to also handle ipv6
129 */
130 static int
131 iousers_tcpip_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtcph)
132 {
133         struct tcpheader *tcph=vtcph;
134         char name1[256],name2[256];
135         io_users_item_t *iui;
136         e_ip *ipv4_header;
137         int direction=0;
138
139         ipv4_header=tcph->ip_header;
140         switch(ipv4_header->ip_v_hl>>4){
141         case 4:
142                 if(ipv4_header->ip_src>ipv4_header->ip_dst){
143                         snprintf(name1,256,"%s:%s",get_hostname(ipv4_header->ip_src),get_tcp_port(tcph->th_sport));
144                         snprintf(name2,256,"%s:%s",get_hostname(ipv4_header->ip_dst),get_tcp_port(tcph->th_dport));
145                 } else {
146                         direction=1;
147                         snprintf(name2,256,"%s:%s",get_hostname(ipv4_header->ip_src),get_tcp_port(tcph->th_sport));
148                         snprintf(name1,256,"%s:%s",get_hostname(ipv4_header->ip_dst),get_tcp_port(tcph->th_dport));
149                 }
150                 break;
151         default:
152                 return 0;
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         guint32 addr1, addr2;
193         io_users_item_t *iui;
194
195         if(iph->ip_src>iph->ip_dst){
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((!memcmp(iui->addr1, &addr1, 4))
205                 &&(!memcmp(iui->addr2, &addr2, 4)) ){
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                 iui->addr1=g_malloc(4);
215                 memcpy(iui->addr1, &addr1, 4);
216                 iui->name1=strdup(get_hostname(addr1));
217                 iui->addr2=g_malloc(4);
218                 memcpy(iui->addr2, &addr2, 4);
219                 iui->name2=strdup(get_hostname(addr2));
220                 iui->frames1=0;
221                 iui->frames2=0;
222                 iui->bytes1=0;
223                 iui->bytes2=0;
224         }
225
226         if(!memcmp(&iph->ip_dst,iui->addr1,4)){
227                 iui->frames1++;
228                 iui->bytes1+=pinfo->fd->pkt_len;
229         } else {
230                 iui->frames2++;
231                 iui->bytes2+=pinfo->fd->pkt_len;
232         }
233
234         return 1;
235 }
236
237 static int
238 iousers_eth_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *veth)
239 {
240         eth_hdr *ehdr=veth;
241         gchar *addr1, *addr2;
242         io_users_item_t *iui;
243
244         if(memcmp(ehdr->src, ehdr->dst, 6)<0){
245                 addr1=ehdr->src;
246                 addr2=ehdr->dst;
247         } else {
248                 addr2=ehdr->src;
249                 addr1=ehdr->dst;
250         }
251
252         for(iui=iu->items;iui;iui=iui->next){
253                 if((!memcmp(iui->addr1, addr1, 6))
254                 &&(!memcmp(iui->addr2, addr2, 6)) ){
255                         break;
256                 }
257         }
258
259         if(!iui){
260                 iui=g_malloc(sizeof(io_users_item_t));
261                 iui->next=iu->items;
262                 iu->items=iui;
263                 iui->addr1=g_malloc(6);
264                 memcpy(iui->addr1, addr1, 6);
265                 iui->name1=strdup(ether_to_str(addr1));
266                 iui->addr2=g_malloc(6);
267                 memcpy(iui->addr2, addr2, 6);
268                 iui->name2=strdup(ether_to_str(addr2));
269                 iui->frames1=0;
270                 iui->frames2=0;
271                 iui->bytes1=0;
272                 iui->bytes2=0;
273         }
274
275         if(!memcmp(ehdr->dst,iui->addr1,6)){
276                 iui->frames1++;
277                 iui->bytes1+=pinfo->fd->pkt_len;
278         } else {
279                 iui->frames2++;
280                 iui->bytes2+=pinfo->fd->pkt_len;
281         }
282
283         return 1;
284 }
285
286
287 static int
288 iousers_tr_packet(io_users_t *iu, packet_info *pinfo, epan_dissect_t *edt _U_, void *vtr)
289 {
290         tr_hdr *trhdr=vtr;
291         gchar *addr1, *addr2;
292         io_users_item_t *iui;
293
294         if(memcmp(trhdr->src, trhdr->dst, 6)<0){
295                 addr1=trhdr->src;
296                 addr2=trhdr->dst;
297         } else {
298                 addr2=trhdr->src;
299                 addr1=trhdr->dst;
300         }
301
302         for(iui=iu->items;iui;iui=iui->next){
303                 if((!memcmp(iui->addr1, addr1, 6))
304                 &&(!memcmp(iui->addr2, addr2, 6)) ){
305                         break;
306                 }
307         }
308
309         if(!iui){
310                 iui=g_malloc(sizeof(io_users_item_t));
311                 iui->next=iu->items;
312                 iu->items=iui;
313                 iui->addr1=g_malloc(6);
314                 memcpy(iui->addr1, addr1, 6);
315                 iui->name1=strdup(ether_to_str(addr1));
316                 iui->addr2=g_malloc(6);
317                 memcpy(iui->addr2, addr2, 6);
318                 iui->name2=strdup(ether_to_str(addr2));
319                 iui->frames1=0;
320                 iui->frames2=0;
321                 iui->bytes1=0;
322                 iui->bytes2=0;
323         }
324
325         if(!memcmp(trhdr->dst,iui->addr1,6)){
326                 iui->frames1++;
327                 iui->bytes1+=pinfo->fd->pkt_len;
328         } else {
329                 iui->frames2++;
330                 iui->bytes2+=pinfo->fd->pkt_len;
331         }
332
333         return 1;
334 }
335
336 static void
337 iousers_draw(io_users_t *iu)
338 {
339         io_users_item_t *iui;
340         guint32 last_frames, max_frames;
341
342         printf("================================================================================\n");
343         printf("IO-USERS Statistics\n");
344         printf("Type:%s\n",iu->type);
345         printf("Filter:%s\n",iu->filter?iu->filter:"<No Filter>");
346         printf("                                               |       <-      | |       ->      | |     Total     |\n");
347         printf("                                               | Frames  Bytes | | Frames  Bytes | | Frames  Bytes |\n");
348         max_frames=0xffffffff;
349         do {
350                 last_frames=0;
351                 for(iui=iu->items;iui;iui=iui->next){
352                         guint32 tot_frames;
353                         tot_frames=iui->frames1+iui->frames2;
354
355                         if((tot_frames>last_frames)
356                         &&(tot_frames<max_frames)){
357                                 last_frames=tot_frames;
358                         }
359                 }
360                 for(iui=iu->items;iui;iui=iui->next){
361                         guint32 tot_frames;
362                         tot_frames=iui->frames1+iui->frames2;
363
364                         if(tot_frames==last_frames){
365                                 printf("%-20s <-> %-20s  %6d %9d  %6d %9d  %6d %9d\n",
366                                         iui->name1, iui->name2,
367                                         iui->frames1, iui->bytes1,
368                                         iui->frames2, iui->bytes2,
369                                         iui->frames1+iui->frames2,
370                                         iui->bytes1+iui->bytes2
371                                 );
372                         }
373                 }
374                 max_frames=last_frames;
375         } while(last_frames);
376         printf("================================================================================\n");
377 }
378
379 void
380 iousers_init(char *optarg)
381 {
382         char *filter=NULL;
383         char *tap_type;
384         static int (*packet_func)(io_users_t *, packet_info *, epan_dissect_t *, void *);
385         io_users_t *iu=NULL;
386         GString *error_string;
387
388         if(!strncmp(optarg,"io,users,eth",12)){
389                 if(optarg[12]==','){
390                         filter=optarg+13;
391                 } else {
392                         filter=NULL;
393                 }
394                 tap_type="eth";
395                 packet_func=iousers_eth_packet;
396         } else if(!strncmp(optarg,"io,users,tcpip",14)){
397                 if(optarg[14]==','){
398                         filter=optarg+15;
399                 } else {
400                         filter=NULL;
401                 }
402                 tap_type="tcp";
403                 packet_func=iousers_tcpip_packet;
404         } else if(!strncmp(optarg,"io,users,udpip",14)){
405                 if(optarg[14]==','){
406                         filter=optarg+15;
407                 } else {
408                         filter=NULL;
409                 }
410                 tap_type="udp";
411                 packet_func=iousers_udpip_packet;
412         } else if(!strncmp(optarg,"io,users,tr",11)){
413                 if(optarg[11]==','){
414                         filter=optarg+12;
415                 } else {
416                         filter=NULL;
417                 }
418                 tap_type="tr";
419                 packet_func=iousers_tr_packet;
420         } else if(!strncmp(optarg,"io,users,ip",11)){
421                 if(optarg[11]==','){
422                         filter=optarg+12;
423                 } else {
424                         filter=NULL;
425                 }
426                 tap_type="ip";
427                 packet_func=iousers_ip_packet;
428         } else {
429                 fprintf(stderr, "tethereal: invalid \"-z io,users,<type>[,<filter>]\" argument\n");
430                 fprintf(stderr,"   <type> must be one of\n");
431                 fprintf(stderr,"      \"eth\"\n");
432                 fprintf(stderr,"      \"ip\"\n");
433                 fprintf(stderr,"      \"tcpip\"\n");
434                 fprintf(stderr,"      \"tr\"\n");
435                 fprintf(stderr,"      \"udpip\"\n");
436                 exit(1);
437         }
438
439
440         iu=g_malloc(sizeof(io_users_t));
441         iu->items=NULL;
442         iu->type=tap_type;
443         if(filter){
444                 iu->filter=strdup(filter);
445         } else {
446                 iu->filter=NULL;
447         }
448
449         error_string=register_tap_listener(tap_type, iu, filter, NULL, (void*)packet_func, (void*)iousers_draw);
450         if(error_string){
451                 if(iu->items){
452                         g_free(iu->items);
453                 }
454                 g_free(iu);
455                 fprintf(stderr, "tethereal: Couldn't register io,users tap: %s\n",
456                     error_string->str);
457                 g_string_free(error_string, TRUE);
458                 exit(1);
459         }
460
461 }
462
463 void
464 register_tap_listener_iousers(void)
465 {
466         register_ethereal_tap("io,users,", iousers_init);
467 }
468