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(const char *optstr)
84 wmem_list_frame_t *entry;
87 char *stat_command = g_strdup(optstr);
89 /* Renamed in Wireshark 3.0, backwards compatibility. */
90 if (!strncmp(stat_command, "follow,ssl", strlen("follow,ssl"))) {
91 memcpy(stat_command + 7, "tls", 3);
94 /* The strings "ipx" or "ipv6" must be tested before "ip" to select the
95 right tap so the sorting does matter. And it's also why the list is
97 for (entry = wmem_list_tail(stat_cmd_arg_list); entry; entry = wmem_list_frame_prev(entry)) {
98 sca = (stat_cmd_arg*)wmem_list_frame_data(entry);
99 if (!strncmp(sca->cmd, stat_command, strlen(sca->cmd))) {
100 tr=(stat_requested *)g_malloc(sizeof (stat_requested));
102 tr->arg = stat_command;
103 stats_requested = g_slist_append(stats_requested, tr);
107 g_free(stat_command);
111 /* **********************************************************************
112 * Function to list all possible tap command-line arguments
113 * ********************************************************************** */
115 list_stat_cmd_args_func(gpointer data, gpointer userdata _U_)
117 fprintf(stderr," %s\n", ((stat_cmd_arg*)data)->cmd);
121 list_stat_cmd_args(void)
123 wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
126 /* **********************************************************************
127 * Function to process stats requested with command-line arguments
128 * ********************************************************************** */
130 start_requested_stats(void)
134 while(stats_requested){
135 sr=(stat_requested *)stats_requested->data;
136 (*sr->sca->func)(sr->arg,sr->sca->userdata);
137 stats_requested=g_slist_remove(stats_requested, sr);
143 static wmem_tree_t *registered_stat_tables = NULL;
145 void register_stat_tap_table_ui(stat_tap_table_ui *ui)
147 if (registered_stat_tables == NULL)
148 registered_stat_tables = wmem_tree_new(wmem_epan_scope());
150 wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
153 stat_tap_table_ui *stat_tap_by_name(const char *name)
155 return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
158 void stat_tap_iterate_tables(wmem_foreach_func func, gpointer user_data)
160 wmem_tree_foreach(registered_stat_tables, func, user_data);
163 void stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
165 guint len = (guint) strlen(new_stat->cli_string);
169 if (!strncmp(opt_arg, new_stat->cli_string, len))
171 if (opt_arg[len] == ',')
173 *filter = opt_arg + len+1;
177 if (new_stat->stat_filter_check_cb)
178 new_stat->stat_filter_check_cb(opt_arg, filter, err);
181 stat_tap_table* stat_tap_init_table(const char *name, int num_fields, int num_elements,
182 const char *filter_string)
184 stat_tap_table* new_table = g_new0(stat_tap_table, 1);
186 new_table->title = name;
187 new_table->num_elements = num_elements;
188 new_table->num_fields = num_fields;
189 new_table->filter_string = filter_string;
190 new_table->elements = g_new0(stat_tap_table_item_type*, num_elements);
195 void stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
197 if (new_stat->tables == NULL)
198 new_stat->tables = g_array_new(FALSE, TRUE, sizeof(stat_tap_table*));
200 g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
203 void stat_tap_init_table_row(stat_tap_table *stat_table, guint table_index, guint num_fields, const stat_tap_table_item_type* fields)
205 /* we have discovered a new procedure. Extend the table accordingly */
206 if(table_index>=stat_table->num_elements){
207 guint old_num_elements=stat_table->num_elements;
210 stat_table->num_elements=table_index+1;
211 stat_table->elements = (stat_tap_table_item_type**)g_realloc(stat_table->elements, sizeof(stat_tap_table_item_type*)*(stat_table->num_elements));
212 for(i=old_num_elements;i<stat_table->num_elements;i++){
213 stat_table->elements[i] = g_new0(stat_tap_table_item_type, stat_table->num_fields);
216 memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
220 stat_tap_table_item_type* stat_tap_get_field_data(const stat_tap_table *stat_table, guint table_index, guint field_index)
222 stat_tap_table_item_type* field_value;
223 g_assert(table_index < stat_table->num_elements);
225 field_value = stat_table->elements[table_index];
227 g_assert(field_index < stat_table->num_fields);
229 return &field_value[field_index];
232 void stat_tap_set_field_data(stat_tap_table *stat_table, guint table_index, guint field_index, stat_tap_table_item_type* field_data)
234 stat_tap_table_item_type* field_value;
235 g_assert(table_index < stat_table->num_elements);
237 field_value = stat_table->elements[table_index];
239 g_assert(field_index < stat_table->num_fields);
241 field_value[field_index] = *field_data;
244 void reset_stat_table(stat_tap_table_ui* new_stat)
247 stat_tap_table *stat_table;
249 for (i = 0; i < new_stat->tables->len; i++)
251 stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
253 if (new_stat->stat_tap_reset_table_cb)
254 new_stat->stat_tap_reset_table_cb(stat_table);
258 void free_stat_tables(stat_tap_table_ui* new_stat)
260 guint i = 0, element, field_index;
261 stat_tap_table *stat_table;
262 stat_tap_table_item_type* field_data;
264 for (i = 0; i < new_stat->tables->len; i++)
266 stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
268 for (element = 0; element < stat_table->num_elements; element++)
270 for (field_index = 0; field_index < stat_table->num_fields; field_index++)
272 field_data = stat_tap_get_field_data(stat_table, element, field_index);
273 /* Give dissector a crack at it */
274 /* XXX Should this be per-row instead? */
275 if (new_stat->stat_tap_free_table_item_cb)
276 new_stat->stat_tap_free_table_item_cb(stat_table, element, field_index, field_data);
278 g_free(stat_table->elements[element]);
280 g_free(stat_table->elements);
283 g_array_set_size(new_stat->tables, 0);
293 * indent-tabs-mode: nil
296 * ex: set shiftwidth=4 tabstop=8 expandtab:
297 * :indentSize=4:tabSize=8:noTabs=true: