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