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
18 #include <epan/packet.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);
27 typedef enum 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
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 */
56 /* Reset expert stats */
58 expert_stat_reset(void *tapdata
)
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
;
85 switch (ei
->severity
) {
87 severity_level
= comment_level
;
90 severity_level
= chat_level
;
93 severity_level
= note_level
;
96 severity_level
= warn_level
;
99 severity_level
= error_level
;
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)) {
118 return TAP_PACKET_REDRAW
;
122 /* Else Add new item to end of list for severity level */
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
)
143 /* Don't print title if no items */
144 if (items
->len
== 0) {
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
;
155 printf("\n%s (%d)\n", label
, total
);
156 printf("=============\n");
158 /* Column headings */
159 printf(" Frequency Group Protocol Summary\n");
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",
168 ei
->protocol
, ei
->summary
);
169 wmem_free(NULL
, tmp_str
);
173 /* (Re)draw expert stats */
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");
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
);
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
;
206 /* Check for args. */
207 if (strncmp(opt_arg
, "expert", 6) == 0) {
208 /* Skip those characters */
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 */
218 if (g_ascii_strncasecmp(args
, ",error", 6) == 0) {
219 lowest_report_level
= error_level
;
222 else if (g_ascii_strncasecmp(args
, ",warn", 5) == 0) {
223 lowest_report_level
= warn_level
;
225 } else if (g_ascii_strncasecmp(args
, ",note", 5) == 0) {
226 lowest_report_level
= note_level
;
228 } else if (g_ascii_strncasecmp(args
, ",chat", 5) == 0) {
229 lowest_report_level
= chat_level
;
231 } else if (g_ascii_strncasecmp(args
, ",comment", 8) == 0) {
232 lowest_report_level
= comment_level
;
237 /* Second (optional) arg is a filter string */
239 if (args
[0] == ',') {
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
,
264 (tap_finish_cb
)expert_tapdata_free
);
266 printf("Expert tap error (%s)!\n", error_string
->str
);
267 g_string_free(error_string
, TRUE
);
268 expert_tapdata_free(hs
);
273 static stat_tap_ui expert_stat_ui
= {
274 REGISTER_STAT_GROUP_GENERIC
,
282 /* Register this tap listener (need void on own so line register function found) */
284 register_tap_listener_expert_info(void)
286 register_stat_tap_ui(&expert_stat_ui
, NULL
);