From Clemens Auer:
[obnox/wireshark/wip.git] / tap-bootpstat.c
1 /* tap-bootpstat.c
2  * boop_stat   2003 Jean-Michel FAYARD
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 #include <string.h>
31
32 #include "epan/packet_info.h"
33 #include <epan/tap.h>
34 #include <epan/stat_cmd_args.h>
35
36
37 typedef const char* bootp_info_value_t;
38
39 /* used to keep track of the statictics for an entire program interface */
40 typedef struct _dhcp_stats_t {
41         char            *filter;
42         GHashTable      *hash;
43         guint            index; /* Number of  to display */
44 } dhcpstat_t;
45 /* used to keep track of a single DHCP message type */
46 typedef struct _dhcp_message_type_t {
47         const char      *name;
48         guint32          packets;
49         dhcpstat_t      *sp;    /* entire program interface */
50 } dhcp_message_type_t;
51
52
53 /* Not used anywhere at this moment */
54 /*
55 static void
56 dhcp_free_hash( gpointer key _U_ , gpointer value, gpointer user_data _U_ )
57 {
58         g_free(value);
59 }
60 */
61
62 static void
63 dhcp_reset_hash(gchar *key _U_ , dhcp_message_type_t *data, gpointer ptr _U_ )
64 {
65         data->packets = 0;
66 }
67
68 /* Update the entry corresponding to the number of packets of a special DHCP Message Type
69  * or create it if it don't exist.
70  */
71 static void
72 dhcp_draw_message_type(gchar *key _U_, dhcp_message_type_t *data, gchar * format )
73 {
74         if ((data==NULL) || (data->packets==0))
75                 return;
76         printf( format, data->name, data->packets);
77 }
78 static void
79 dhcpstat_reset(void *psp)
80 {
81         dhcpstat_t *sp=psp;
82         g_hash_table_foreach( sp->hash, (GHFunc)dhcp_reset_hash, NULL);
83 }
84 static int
85 dhcpstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pri)
86 {
87         dhcpstat_t *sp=psp;
88         const bootp_info_value_t value=pri;
89         dhcp_message_type_t *sc;
90
91         if (sp==NULL)
92                 return 0;
93         sc = g_hash_table_lookup(
94                         sp->hash,
95                         value);
96         if (!sc) {
97                 sc = g_malloc( sizeof(dhcp_message_type_t) );
98                 sc -> packets = 1;
99                 sc -> name = value;
100                 sc -> sp = sp;
101                 g_hash_table_insert(
102                                 sp->hash,
103                                 (gpointer) value,
104                                 sc);
105         } else {
106                 /*g_warning("sc(%s)->packets++", sc->name);*/
107                 sc->packets++;
108         }
109         return 1;
110 }
111
112
113 static void
114 dhcpstat_draw(void *psp)
115 {
116         dhcpstat_t *sp=psp;
117
118         printf("\n");
119         printf("===================================================================\n");
120
121         if (sp->filter==NULL)
122                 printf("BOOTP Statistics\n");
123         else
124                 printf("BOOTP Statistics with filter %s\n",  sp->filter);
125         printf("BOOTP Option 53: DHCP Messages Types:\n");
126         printf("DHCP Message Type      Packets nb\n" );
127         g_hash_table_foreach( sp->hash, (GHFunc) dhcp_draw_message_type,
128                         "%23s %-9d\n" );
129         printf("===================================================================\n");
130
131 }
132
133
134
135
136 /* When called, this function will create a new instance of tap-boopstat.
137  */
138 static void
139 dhcpstat_init(const char *optarg, void* userdata _U_)
140 {
141         dhcpstat_t *sp;
142         const char      *filter=NULL;
143         GString         *error_string;
144
145         if (!strncmp (optarg, "bootp,stat,", 11)){
146                 filter=optarg+11;
147         } else {
148                 filter=NULL;
149         }
150
151         sp = g_malloc( sizeof(dhcpstat_t) );
152         sp->hash = g_hash_table_new( g_str_hash, g_str_equal);
153         if(filter){
154                 sp->filter=g_strdup(filter);
155         } else {
156                 sp->filter=NULL;
157         }
158         sp->index = 0;          /* Nothing to display yet */
159
160         error_string = register_tap_listener(
161                         "bootp",
162                         sp,
163                         filter,
164                         0,
165                         dhcpstat_reset,
166                         dhcpstat_packet,
167                         dhcpstat_draw);
168         if (error_string){
169                 /* error, we failed to attach to the tap. clean up */
170                 g_free(sp->filter);
171                 g_free(sp);
172                 fprintf(stderr, "tshark: Couldn't register dhcp,stat tap: %s\n",
173                                 error_string->str);
174                 g_string_free(error_string, TRUE);
175                 exit(1);
176         }
177 }
178
179
180
181 void
182 register_tap_listener_gtkdhcpstat(void)
183 {
184         register_stat_cmd_arg("bootp,stat,", dhcpstat_init,NULL);
185 }
186