update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / ui / cli / tap-expert.c
blob8fa812cc15b604b02c8c45e586ba2765ce1beadf
1 /* tap-expert.c
2 * Copyright 2011 Martin Mathieson
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
12 #include "config.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include <epan/packet.h>
19 #include <epan/tap.h>
20 #include <epan/stat_tap_ui.h>
21 #include <epan/expert.h>
22 #include <wsutil/ws_assert.h>
24 void register_tap_listener_expert_info(void);
26 /* Tap data */
27 typedef enum severity_level_t {
28 comment_level = 0,
29 chat_level,
30 note_level,
31 warn_level,
32 error_level,
33 max_level
34 } severity_level_t;
36 /* This variable stores the lowest level that will be displayed.
37 May be changed from the command line */
38 static severity_level_t lowest_report_level = comment_level;
40 typedef struct expert_entry
42 uint32_t group;
43 int frequency;
44 const char *protocol;
45 char *summary;
46 } expert_entry;
49 /* Overall struct for storing all data seen */
50 typedef struct expert_tapdata_t {
51 GArray *ei_array[max_level]; /* expert info items */
52 GStringChunk *text; /* for efficient storage of summary strings */
53 } expert_tapdata_t;
56 /* Reset expert stats */
57 static void
58 expert_stat_reset(void *tapdata)
60 int n;
61 expert_tapdata_t *etd = (expert_tapdata_t *)tapdata;
63 /* Free & reallocate chunk of strings */
64 g_string_chunk_free(etd->text);
65 etd->text = g_string_chunk_new(100);
67 /* Empty each of the arrays */
68 for (n=0; n < max_level; n++) {
69 g_array_set_size(etd->ei_array[n], 0);
73 /* Process stat struct for an expert frame */
74 static tap_packet_status
75 expert_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_,
76 const void *pointer, tap_flags_t flags _U_)
78 const expert_info_t *ei = (const expert_info_t *)pointer;
79 expert_tapdata_t *data = (expert_tapdata_t *)tapdata;
80 severity_level_t severity_level;
81 expert_entry tmp_entry;
82 expert_entry *entry;
83 unsigned n;
85 switch (ei->severity) {
86 case PI_COMMENT:
87 severity_level = comment_level;
88 break;
89 case PI_CHAT:
90 severity_level = chat_level;
91 break;
92 case PI_NOTE:
93 severity_level = note_level;
94 break;
95 case PI_WARN:
96 severity_level = warn_level;
97 break;
98 case PI_ERROR:
99 severity_level = error_level;
100 break;
101 default:
102 ws_assert_not_reached();
103 return TAP_PACKET_DONT_REDRAW;
106 /* Don't store details at a lesser severity than we are interested in */
107 if (severity_level < lowest_report_level) {
108 return TAP_PACKET_REDRAW; /* XXX - TAP_PACKET_DONT_REDRAW? */
111 /* If a duplicate just bump up frequency.
112 TODO: could make more efficient by avoiding linear search...*/
113 for (n=0; n < data->ei_array[severity_level]->len; n++) {
114 entry = &g_array_index(data->ei_array[severity_level], expert_entry, n);
115 if ((strcmp(ei->protocol, entry->protocol) == 0) &&
116 (strcmp(ei->summary, entry->summary) == 0)) {
117 entry->frequency++;
118 return TAP_PACKET_REDRAW;
122 /* Else Add new item to end of list for severity level */
123 entry = &tmp_entry;
124 /* Copy/Store protocol and summary strings efficiently using GStringChunk */
125 entry->protocol = g_string_chunk_insert_const(data->text, ei->protocol);
126 entry->summary = g_string_chunk_insert_const(data->text, ei->summary);
127 entry->group = ei->group;
128 entry->frequency = 1;
129 /* Store a copy of the expert entry */
130 g_array_append_val(data->ei_array[severity_level], tmp_entry);
132 return TAP_PACKET_REDRAW;
135 /* Output for all of the items of one severity */
136 static void draw_items_for_severity(GArray *items, const char *label)
138 unsigned n;
139 expert_entry *ei;
140 int total = 0;
141 char *tmp_str;
143 /* Don't print title if no items */
144 if (items->len == 0) {
145 return;
148 /* Add frequencies together to get total */
149 for (n=0; n < items->len; n++) {
150 ei = &g_array_index(items, expert_entry, n);
151 total += ei->frequency;
154 /* Title */
155 printf("\n%s (%d)\n", label, total);
156 printf("=============\n");
158 /* Column headings */
159 printf(" Frequency Group Protocol Summary\n");
161 /* Items */
162 for (n=0; n < items->len; n++) {
163 ei = &g_array_index(items, expert_entry, n);
164 tmp_str = val_to_str_wmem(NULL, ei->group, expert_group_vals, "Unknown (%d)");
165 printf("%12d %10s %18s %s\n",
166 ei->frequency,
167 tmp_str,
168 ei->protocol, ei->summary);
169 wmem_free(NULL, tmp_str);
173 /* (Re)draw expert stats */
174 static void
175 expert_stat_draw(void *phs _U_)
177 /* Look up the statistics struct */
178 expert_tapdata_t *hs = (expert_tapdata_t *)phs;
180 draw_items_for_severity(hs->ei_array[error_level], "Errors");
181 draw_items_for_severity(hs->ei_array[warn_level], "Warns");
182 draw_items_for_severity(hs->ei_array[note_level], "Notes");
183 draw_items_for_severity(hs->ei_array[chat_level], "Chats");
184 draw_items_for_severity(hs->ei_array[comment_level], "Comments");
187 static void
188 expert_tapdata_free(expert_tapdata_t* hs)
190 for (int n = 0; n < max_level; n++) {
191 g_array_free(hs->ei_array[n], true);
193 g_string_chunk_free(hs->text);
194 g_free(hs);
197 /* Create a new expert stats struct */
198 static void expert_stat_init(const char *opt_arg, void *userdata _U_)
200 const char *args = NULL;
201 const char *filter = NULL;
202 GString *error_string;
203 expert_tapdata_t *hs;
204 int n;
206 /* Check for args. */
207 if (strncmp(opt_arg, "expert", 6) == 0) {
208 /* Skip those characters */
209 args = opt_arg + 6;
211 else {
212 /* No args. Will show all reports, with no filter */
213 lowest_report_level = max_level;
216 /* First (optional) arg is Error|Warn|Note|Chat */
217 if (args != NULL) {
218 if (g_ascii_strncasecmp(args, ",error", 6) == 0) {
219 lowest_report_level = error_level;
220 args += 6;
222 else if (g_ascii_strncasecmp(args, ",warn", 5) == 0) {
223 lowest_report_level = warn_level;
224 args += 5;
225 } else if (g_ascii_strncasecmp(args, ",note", 5) == 0) {
226 lowest_report_level = note_level;
227 args += 5;
228 } else if (g_ascii_strncasecmp(args, ",chat", 5) == 0) {
229 lowest_report_level = chat_level;
230 args += 5;
231 } else if (g_ascii_strncasecmp(args, ",comment", 8) == 0) {
232 lowest_report_level = comment_level;
233 args += 8;
237 /* Second (optional) arg is a filter string */
238 if (args != NULL) {
239 if (args[0] == ',') {
240 filter = args+1;
244 /* Create top-level struct */
245 hs = g_new0(expert_tapdata_t, 1);
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_entry), 1000);
255 /**********************************************/
256 /* Register the tap listener */
257 /**********************************************/
259 error_string = register_tap_listener("expert", hs,
260 filter, 0,
261 expert_stat_reset,
262 expert_stat_packet,
263 expert_stat_draw,
264 (tap_finish_cb)expert_tapdata_free);
265 if (error_string) {
266 printf("Expert tap error (%s)!\n", error_string->str);
267 g_string_free(error_string, TRUE);
268 expert_tapdata_free(hs);
269 exit(1);
273 static stat_tap_ui expert_stat_ui = {
274 REGISTER_STAT_GROUP_GENERIC,
275 NULL,
276 "expert",
277 expert_stat_init,
279 NULL
282 /* Register this tap listener (need void on own so line register function found) */
283 void
284 register_tap_listener_expert_info(void)
286 register_stat_tap_ui(&expert_stat_ui, NULL);