fe0448969f8b4ef965beb2f6d762a2f294938fab
[obnox/wireshark/wip.git] / tap-expert.c
1 /* tap-expert.c
2  * Copyright 2011 Martin Mathieson
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
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdio.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35
36 #include <string.h>
37 #include <epan/packet.h>
38 #include <epan/packet_info.h>
39 #include <epan/tap.h>
40 #include <epan/stat_cmd_args.h>
41 #include <epan/expert.h>
42
43 /* Tap data */
44 typedef enum severity_level_t {
45     chat_level=0,
46     note_level,
47     warn_level,
48     error_level,
49     max_level
50 } severity_level_t;
51
52 typedef struct expert_tapdata_t {
53     GArray         *ei_array[max_level];   /* expert info items */
54     GStringChunk*  text; /* summary text */
55 } expert_tapdata_t;
56
57 /* Reset expert stats */
58 static void
59 expert_stat_reset(void *tapdata)
60 {
61     gint n;
62     expert_tapdata_t *etd = tapdata;
63
64     /* Free & reallocate chunk of strings */
65     g_string_chunk_free(etd->text);
66     etd->text = g_string_chunk_new(100);
67
68     /* Empty each of the arrays */
69     for (n=0; n < max_level; n++) {
70         g_array_set_size(etd->ei_array[n], 0);
71     }
72 }
73
74 /* Process stat struct for an expert frame */
75 static int
76 expert_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_,
77                    const void *pointer)
78 {
79     expert_info_t    *ei = (expert_info_t *)pointer;
80     expert_tapdata_t *etd = tapdata;
81     severity_level_t severity_level;
82
83     switch (ei->severity) {
84         case PI_CHAT:
85             severity_level = chat_level;
86             break;
87         case PI_NOTE:
88             severity_level = note_level;
89             break;
90         case PI_WARN:
91             severity_level = warn_level;
92             break;
93         case PI_ERROR:
94             severity_level = error_level;
95             break;
96         default:
97             g_assert_not_reached();
98             return 0;
99     }
100
101     /* Add new item to end of list for severity level */
102     g_array_append_val(etd->ei_array[severity_level], *(expert_info_t *)pointer);
103
104     /* Get pointer to newly-allocated item */
105     ei = &g_array_index(etd->ei_array[severity_level], expert_info_t,
106                         etd->ei_array[severity_level]->len - 1); /* ugly */
107     /* Copy/Store protocol and summary strings efficiently using GStringChunk */
108     ei->protocol = g_string_chunk_insert_const(etd->text, ei->protocol);
109     ei->summary = g_string_chunk_insert_const(etd->text, ei->summary);
110
111     return 1;
112 }
113
114 /* Output for all of the items of one severity */
115 static void draw_items_for_severity(GArray *items, const gchar *label)
116 {
117     guint n;
118     expert_info_t *ei;
119
120     /* Don't print title if no items */
121     if (items->len == 0) {
122         return;
123     }
124
125     /* Title */
126     printf("\n%s (%u)\n", label, items->len);
127     printf("=============\n");
128
129     /* Column headings */
130     printf("   Frame      Group           Protocol\n");
131
132     /* Items */
133     for (n=0; n < items->len; n++) {
134         ei = &g_array_index(items, expert_info_t, n);
135         printf("%8u %10s %18s  %s\n", ei->packet_num,
136               val_to_str(ei->group, expert_group_vals, "Unknown"),
137               ei->protocol, ei->summary);
138     }
139 }
140
141 /* (Re)draw expert stats */
142 static void
143 expert_stat_draw(void *phs _U_)
144 {
145     /* Look up the statistics struct */
146     expert_tapdata_t *hs = (expert_tapdata_t *)phs;
147
148     draw_items_for_severity(hs->ei_array[error_level], "Errors");
149     draw_items_for_severity(hs->ei_array[warn_level],  "Warns");
150     draw_items_for_severity(hs->ei_array[note_level],  "Notes");
151     draw_items_for_severity(hs->ei_array[chat_level],  "Chats");
152 }
153
154 /* Create a new expert stats struct */
155 static void expert_stat_init(const char *optarg, void *userdata _U_)
156 {
157     const char        *filter = NULL;
158     GString           *error_string;
159     expert_tapdata_t  *hs;
160     int n;
161
162     /* Check for a filter string */
163     if (strncmp(optarg, "expert,stat,", 13) == 0) {
164         /* Skip those characters from filter to display */
165         filter = optarg + 11;
166     }
167     else {
168         /* No filter */
169         filter = NULL;
170     }
171
172     /* Create top-level struct */
173     hs = g_malloc(sizeof(expert_tapdata_t));
174     memset(hs, 0,  sizeof(expert_tapdata_t));
175
176     /* Allocate chunk of strings */
177     hs->text = g_string_chunk_new(100);
178
179     /* Allocate GArray for each severity level */
180     for (n=0; n < max_level; n++) {
181         hs->ei_array[n] = g_array_sized_new(FALSE, FALSE, sizeof(expert_info_t), 1000);
182     }
183
184     /**********************************************/
185     /* Register the tap listener                  */
186     /**********************************************/
187
188     error_string = register_tap_listener("expert", hs,
189                                          filter, 0,
190                                          expert_stat_reset,
191                                          expert_stat_packet,
192                                          expert_stat_draw);
193     if (error_string) {
194         g_string_free(error_string, TRUE);
195         g_free(hs);
196         exit(1);
197     }
198 }
199
200
201 /* Register this tap listener (need void on own so line register function found) */
202 void
203 register_tap_listener_expert_info(void)
204 {
205     register_stat_cmd_arg("expert,stat", expert_stat_init, NULL);
206 }
207