2 * Copyright 2011 Martin Mathieson
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
37 #include <epan/packet.h>
38 #include <epan/packet_info.h>
40 #include <epan/stat_cmd_args.h>
41 #include <epan/expert.h>
44 typedef enum severity_level_t {
52 /* This variable stores the lowest level that will be displayed.
53 May be changed from the command line */
54 static severity_level_t lowest_report_level = chat_level;
56 typedef struct expert_entry
59 const gchar *protocol;
65 /* Overall struct for storing all data seen */
66 typedef struct expert_tapdata_t {
67 GArray *ei_array[max_level]; /* expert info items */
68 GStringChunk* text; /* for efficient storage of summary strings */
72 /* Reset expert stats */
74 expert_stat_reset(void *tapdata)
77 expert_tapdata_t *etd = tapdata;
79 /* Free & reallocate chunk of strings */
80 g_string_chunk_free(etd->text);
81 etd->text = g_string_chunk_new(100);
83 /* Empty each of the arrays */
84 for (n=0; n < max_level; n++) {
85 g_array_set_size(etd->ei_array[n], 0);
89 /* Process stat struct for an expert frame */
91 expert_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_,
94 expert_info_t *ei = (expert_info_t *)pointer;
95 expert_tapdata_t *data = tapdata;
96 severity_level_t severity_level;
97 expert_entry tmp_entry;
101 switch (ei->severity) {
103 severity_level = chat_level;
106 severity_level = note_level;
109 severity_level = warn_level;
112 severity_level = error_level;
115 g_assert_not_reached();
119 /* Don't store details at a lesser severity than we are interested in */
120 if (severity_level < lowest_report_level) {
124 /* If a duplicate just bump up frequency.
125 TODO: could make more efficient by avoiding linear search...*/
126 for (n=0; n < data->ei_array[severity_level]->len; n++) {
127 entry = &g_array_index(data->ei_array[severity_level], expert_entry, n);
128 if ((strcmp(ei->protocol, entry->protocol) == 0) &&
129 (strcmp(ei->summary, entry->summary) == 0)) {
135 /* Else Add new item to end of list for severity level */
136 g_array_append_val(data->ei_array[severity_level], tmp_entry);
138 /* Get pointer to newly-allocated item */
139 entry = &g_array_index(data->ei_array[severity_level], expert_entry,
140 data->ei_array[severity_level]->len - 1); /* ugly */
141 /* Copy/Store protocol and summary strings efficiently using GStringChunk */
142 entry->protocol = g_string_chunk_insert_const(data->text, ei->protocol);
143 entry->summary = g_string_chunk_insert_const(data->text, ei->summary);
144 entry->group = ei->group;
145 entry->frequency = 1;
150 /* Output for all of the items of one severity */
151 static void draw_items_for_severity(GArray *items, const gchar *label)
157 /* Don't print title if no items */
158 if (items->len == 0) {
162 /* Add frequencies together to get total */
163 for (n=0; n < items->len; n++) {
164 ei = &g_array_index(items, expert_entry, n);
165 total += ei->frequency;
169 printf("\n%s (%u)\n", label, total);
170 printf("=============\n");
172 /* Column headings */
173 printf(" Frequency Group Protocol Summary\n");
176 for (n=0; n < items->len; n++) {
177 ei = &g_array_index(items, expert_entry, n);
178 printf("%12u %10s %18s %s\n",
180 val_to_str(ei->group, expert_group_vals, "Unknown"),
181 ei->protocol, ei->summary);
185 /* (Re)draw expert stats */
187 expert_stat_draw(void *phs _U_)
189 /* Look up the statistics struct */
190 expert_tapdata_t *hs = (expert_tapdata_t *)phs;
192 draw_items_for_severity(hs->ei_array[error_level], "Errors");
193 draw_items_for_severity(hs->ei_array[warn_level], "Warns");
194 draw_items_for_severity(hs->ei_array[note_level], "Notes");
195 draw_items_for_severity(hs->ei_array[chat_level], "Chats");
198 /* Create a new expert stats struct */
199 static void expert_stat_init(const char *optarg, void *userdata _U_)
201 const char *args = NULL;
202 const char *filter = NULL;
203 GString *error_string;
204 expert_tapdata_t *hs;
207 /* Check for args. */
208 if (strncmp(optarg, "expert", 6) == 0) {
209 /* Skip those characters */
213 /* No args. Will show all reports, with no filter */
214 lowest_report_level = max_level;
217 /* First (optional) arg is Error|Warn|Note|Chat */
219 if (g_ascii_strncasecmp(args, ",error", 6) == 0) {
220 lowest_report_level = error_level;
223 else if (g_ascii_strncasecmp(args, ",warn", 5) == 0) {
224 lowest_report_level = warn_level;
226 } else if (g_ascii_strncasecmp(args, ",note", 5) == 0) {
227 lowest_report_level = note_level;
229 } else if (g_ascii_strncasecmp(args, ",chat", 5) == 0) {
230 lowest_report_level = chat_level;
235 /* Second (optional) arg is a filter string */
237 if (args[0] == ',') {
243 /* Create top-level struct */
244 hs = g_malloc(sizeof(expert_tapdata_t));
245 memset(hs, 0, sizeof(expert_tapdata_t));
247 /* Allocate chunk of strings */
248 hs->text = g_string_chunk_new(100);
250 /* Allocate GArray for each severity level */
251 for (n=0; n < max_level; n++) {
252 hs->ei_array[n] = g_array_sized_new(FALSE, FALSE, sizeof(expert_info_t), 1000);
255 /**********************************************/
256 /* Register the tap listener */
257 /**********************************************/
259 error_string = register_tap_listener("expert", hs,
265 printf("Expert tap error (%s)!\n", error_string->str);
266 g_string_free(error_string, TRUE);
273 /* Register this tap listener (need void on own so line register function found) */
275 register_tap_listener_expert_info(void)
277 register_stat_cmd_arg("expert", expert_stat_init, NULL);