2 * Routines to register UI information for stats
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
19 #include <epan/stat_tap_ui.h>
21 /* structure to keep track of what stats have registered command-line
24 typedef struct _stat_cmd_arg {
27 void (*func)(const char *arg, void* userdata);
31 static wmem_list_t *stat_cmd_arg_list=NULL;
33 /* structure to keep track of what stats have been specified on the
40 static GSList *stats_requested = NULL;
42 /* **********************************************************************
43 * Function called from stat to register the stat's command-line argument
44 * and initialization routine
45 * ********************************************************************** */
47 search_duplicate(gconstpointer a, gconstpointer b)
49 return strcmp(((const stat_cmd_arg *)a)->cmd, (const char *)b);
53 sort_by_name(gconstpointer a, gconstpointer b)
55 return strcmp(((const stat_cmd_arg *)a)->cmd, ((const stat_cmd_arg *)b)->cmd);
59 register_stat_tap_ui(stat_tap_ui *ui, void *userdata)
63 if (stat_cmd_arg_list == NULL)
64 stat_cmd_arg_list = wmem_list_new(wmem_epan_scope());
66 /* Key is already present */
67 if (wmem_list_find_custom(stat_cmd_arg_list, ui->cli_string, search_duplicate))
70 newsca = wmem_new(wmem_epan_scope(), stat_cmd_arg);
71 newsca->cmd= wmem_strdup(wmem_epan_scope(), ui->cli_string);
72 newsca->func=ui->tap_init_cb;
73 newsca->userdata=userdata;
75 wmem_list_insert_sorted(stat_cmd_arg_list, newsca, sort_by_name);
78 /* **********************************************************************
79 * Function called for a stat command-line argument
80 * ********************************************************************** */
82 process_stat_cmd_arg(char *optstr)
84 wmem_list_frame_t *entry;
88 /* Renamed in Wireshark 3.0, backwards compatibility. */
89 if (!strncmp(optstr, "follow,ssl", strlen("follow,ssl"))) {
90 memcpy(optstr + 7, "tls", 3);
93 /* The strings "ipx" or "ipv6" must be tested before "ip" to select the
94 right tap so the sorting does matter. And it's also why the list is
96 for (entry = wmem_list_tail(stat_cmd_arg_list); entry; entry = wmem_list_frame_prev(entry)) {
97 sca = (stat_cmd_arg*)wmem_list_frame_data(entry);
98 if(!strncmp(sca->cmd, optstr, strlen(sca->cmd))) {
99 tr=(stat_requested *)g_malloc(sizeof (stat_requested));
101 tr->arg=g_strdup(optstr);
102 stats_requested = g_slist_append(stats_requested, tr);
109 /* **********************************************************************
110 * Function to list all possible tap command-line arguments
111 * ********************************************************************** */
113 list_stat_cmd_args_func(gpointer data, gpointer userdata _U_)
115 fprintf(stderr," %s\n", ((stat_cmd_arg*)data)->cmd);
119 list_stat_cmd_args(void)
121 wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
124 /* **********************************************************************
125 * Function to process stats requested with command-line arguments
126 * ********************************************************************** */
128 start_requested_stats(void)
132 while(stats_requested){
133 sr=(stat_requested *)stats_requested->data;
134 (*sr->sca->func)(sr->arg,sr->sca->userdata);
135 stats_requested=g_slist_remove(stats_requested, sr);
141 static wmem_tree_t *registered_stat_tables = NULL;
143 void register_stat_tap_table_ui(stat_tap_table_ui *ui)
145 if (registered_stat_tables == NULL)
146 registered_stat_tables = wmem_tree_new(wmem_epan_scope());
148 wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
151 stat_tap_table_ui *stat_tap_by_name(const char *name)
153 return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
156 void stat_tap_iterate_tables(wmem_foreach_func func, gpointer user_data)
158 wmem_tree_foreach(registered_stat_tables, func, user_data);
161 void stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
163 guint len = (guint) strlen(new_stat->cli_string);
167 if (!strncmp(opt_arg, new_stat->cli_string, len))
169 if (opt_arg[len] == ',')
171 *filter = opt_arg + len+1;
175 if (new_stat->stat_filter_check_cb)
176 new_stat->stat_filter_check_cb(opt_arg, filter, err);
179 stat_tap_table* stat_tap_init_table(const char *name, int num_fields, int num_elements,
180 const char *filter_string)
182 stat_tap_table* new_table = g_new0(stat_tap_table, 1);
184 new_table->title = name;
185 new_table->num_elements = num_elements;
186 new_table->num_fields = num_fields;
187 new_table->filter_string = filter_string;
188 new_table->elements = g_new0(stat_tap_table_item_type*, num_elements);
193 void stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
195 if (new_stat->tables == NULL)
196 new_stat->tables = g_array_new(FALSE, TRUE, sizeof(stat_tap_table*));
198 g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
201 void stat_tap_init_table_row(stat_tap_table *stat_table, guint table_index, guint num_fields, const stat_tap_table_item_type* fields)
203 /* we have discovered a new procedure. Extend the table accordingly */
204 if(table_index>=stat_table->num_elements){
205 guint old_num_elements=stat_table->num_elements;
208 stat_table->num_elements=table_index+1;
209 stat_table->elements = (stat_tap_table_item_type**)g_realloc(stat_table->elements, sizeof(stat_tap_table_item_type*)*(stat_table->num_elements));
210 for(i=old_num_elements;i<stat_table->num_elements;i++){
211 stat_table->elements[i] = g_new0(stat_tap_table_item_type, stat_table->num_fields);
214 memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
218 stat_tap_table_item_type* stat_tap_get_field_data(const stat_tap_table *stat_table, guint table_index, guint field_index)
220 stat_tap_table_item_type* field_value;
221 g_assert(table_index < stat_table->num_elements);
223 field_value = stat_table->elements[table_index];
225 g_assert(field_index < stat_table->num_fields);
227 return &field_value[field_index];
230 void stat_tap_set_field_data(stat_tap_table *stat_table, guint table_index, guint field_index, stat_tap_table_item_type* field_data)
232 stat_tap_table_item_type* field_value;
233 g_assert(table_index < stat_table->num_elements);
235 field_value = stat_table->elements[table_index];
237 g_assert(field_index < stat_table->num_fields);
239 field_value[field_index] = *field_data;
242 void reset_stat_table(stat_tap_table_ui* new_stat)
245 stat_tap_table *stat_table;
247 for (i = 0; i < new_stat->tables->len; i++)
249 stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
251 if (new_stat->stat_tap_reset_table_cb)
252 new_stat->stat_tap_reset_table_cb(stat_table);
256 void free_stat_tables(stat_tap_table_ui* new_stat)
258 guint i = 0, element, field_index;
259 stat_tap_table *stat_table;
260 stat_tap_table_item_type* field_data;
262 for (i = 0; i < new_stat->tables->len; i++)
264 stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
266 for (element = 0; element < stat_table->num_elements; element++)
268 for (field_index = 0; field_index < stat_table->num_fields; field_index++)
270 field_data = stat_tap_get_field_data(stat_table, element, field_index);
271 /* Give dissector a crack at it */
272 /* XXX Should this be per-row instead? */
273 if (new_stat->stat_tap_free_table_item_cb)
274 new_stat->stat_tap_free_table_item_cb(stat_table, element, field_index, field_data);
276 g_free(stat_table->elements[element]);
278 g_free(stat_table->elements);
281 g_array_set_size(new_stat->tables, 0);
291 * indent-tabs-mode: nil
294 * ex: set shiftwidth=4 tabstop=8 expandtab:
295 * :indentSize=4:tabSize=8:noTabs=true: