STEP06 ? add dissect_kerberos_AD_AP_OPTIONS
[metze/wireshark/wip.git] / epan / stat_tap_ui.c
1 /* stat_tap_ui.c
2  * Routines to register UI information for stats
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "config.h"
12
13 #include <stdio.h>
14
15 #include <string.h>
16
17 #include <glib.h>
18
19 #include <epan/stat_tap_ui.h>
20
21 /* structure to keep track of what stats have registered command-line
22    arguments.
23  */
24 typedef struct _stat_cmd_arg {
25     stat_tap_ui *ui;
26     const char *cmd;
27     void (*func)(const char *arg, void* userdata);
28     void* userdata;
29 } stat_cmd_arg;
30
31 static wmem_list_t *stat_cmd_arg_list=NULL;
32
33 /* structure to keep track of what stats have been specified on the
34    command line.
35  */
36 typedef struct {
37     stat_cmd_arg *sca;
38     char *arg;
39 } stat_requested;
40 static GSList *stats_requested = NULL;
41
42 /* **********************************************************************
43  * Function called from stat to register the stat's command-line argument
44  * and initialization routine
45  * ********************************************************************** */
46 static gint
47 search_duplicate(gconstpointer a, gconstpointer b)
48 {
49     return strcmp(((const stat_cmd_arg *)a)->cmd, (const char *)b);
50 }
51
52 static gint
53 sort_by_name(gconstpointer a, gconstpointer b)
54 {
55     return strcmp(((const stat_cmd_arg *)a)->cmd, ((const stat_cmd_arg *)b)->cmd);
56 }
57
58 void
59 register_stat_tap_ui(stat_tap_ui *ui, void *userdata)
60 {
61     stat_cmd_arg *newsca;
62
63     if (stat_cmd_arg_list == NULL)
64         stat_cmd_arg_list = wmem_list_new(wmem_epan_scope());
65
66     /* Key is already present */
67     if (wmem_list_find_custom(stat_cmd_arg_list, ui->cli_string, search_duplicate))
68         return;
69
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;
74
75     wmem_list_insert_sorted(stat_cmd_arg_list, newsca, sort_by_name);
76 }
77
78 /* **********************************************************************
79  * Function called for a stat command-line argument
80  * ********************************************************************** */
81 gboolean
82 process_stat_cmd_arg(const char *optstr)
83 {
84     wmem_list_frame_t *entry;
85     stat_cmd_arg *sca;
86     stat_requested *tr;
87     char *stat_command = g_strdup(optstr);
88
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);
92     }
93
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
96       walked backwards */
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));
101             tr->sca = sca;
102             tr->arg = stat_command;
103             stats_requested = g_slist_append(stats_requested, tr);
104             return TRUE;
105         }
106     }
107     g_free(stat_command);
108     return FALSE;
109 }
110
111 /* **********************************************************************
112  * Function to list all possible tap command-line arguments
113  * ********************************************************************** */
114 static void
115 list_stat_cmd_args_func(gpointer data, gpointer userdata _U_)
116 {
117     fprintf(stderr,"     %s\n", ((stat_cmd_arg*)data)->cmd);
118 }
119
120 void
121 list_stat_cmd_args(void)
122 {
123     wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
124 }
125
126 /* **********************************************************************
127  * Function to process stats requested with command-line arguments
128  * ********************************************************************** */
129 void
130 start_requested_stats(void)
131 {
132     stat_requested *sr;
133
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);
138         g_free(sr->arg);
139         g_free(sr);
140     }
141 }
142
143 static wmem_tree_t *registered_stat_tables = NULL;
144
145 void register_stat_tap_table_ui(stat_tap_table_ui *ui)
146 {
147     if (registered_stat_tables == NULL)
148         registered_stat_tables = wmem_tree_new(wmem_epan_scope());
149
150     wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
151 }
152
153 stat_tap_table_ui *stat_tap_by_name(const char *name)
154 {
155     return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
156 }
157
158 void stat_tap_iterate_tables(wmem_foreach_func func, gpointer user_data)
159 {
160     wmem_tree_foreach(registered_stat_tables, func, user_data);
161 }
162
163 void stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
164 {
165     guint len = (guint) strlen(new_stat->cli_string);
166     *filter=NULL;
167     *err=NULL;
168
169     if (!strncmp(opt_arg, new_stat->cli_string, len))
170     {
171         if (opt_arg[len] == ',')
172         {
173            *filter = opt_arg + len+1;
174         }
175     }
176
177     if (new_stat->stat_filter_check_cb)
178         new_stat->stat_filter_check_cb(opt_arg, filter, err);
179 }
180
181 stat_tap_table* stat_tap_init_table(const char *name, int num_fields, int num_elements,
182                 const char *filter_string)
183 {
184     stat_tap_table* new_table = g_new0(stat_tap_table, 1);
185
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);
191
192     return new_table;
193 }
194
195 void stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
196 {
197     if (new_stat->tables == NULL)
198         new_stat->tables = g_array_new(FALSE, TRUE, sizeof(stat_tap_table*));
199
200     g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
201 }
202
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)
204 {
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;
208         guint i;
209
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);
214         }
215     }
216     memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
217
218 }
219
220 stat_tap_table_item_type* stat_tap_get_field_data(const stat_tap_table *stat_table, guint table_index, guint field_index)
221 {
222     stat_tap_table_item_type* field_value;
223     g_assert(table_index < stat_table->num_elements);
224
225     field_value = stat_table->elements[table_index];
226
227     g_assert(field_index < stat_table->num_fields);
228
229     return &field_value[field_index];
230 }
231
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)
233 {
234     stat_tap_table_item_type* field_value;
235     g_assert(table_index < stat_table->num_elements);
236
237     field_value = stat_table->elements[table_index];
238
239     g_assert(field_index < stat_table->num_fields);
240
241     field_value[field_index] = *field_data;
242 }
243
244 void reset_stat_table(stat_tap_table_ui* new_stat)
245 {
246     guint i = 0;
247     stat_tap_table *stat_table;
248
249     for (i = 0; i < new_stat->tables->len; i++)
250     {
251         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
252
253         if (new_stat->stat_tap_reset_table_cb)
254             new_stat->stat_tap_reset_table_cb(stat_table);
255     }
256 }
257
258 void free_stat_tables(stat_tap_table_ui* new_stat)
259 {
260     guint i = 0, element, field_index;
261     stat_tap_table *stat_table;
262     stat_tap_table_item_type* field_data;
263
264     for (i = 0; i < new_stat->tables->len; i++)
265     {
266         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
267
268         for (element = 0; element < stat_table->num_elements; element++)
269         {
270             for (field_index = 0; field_index < stat_table->num_fields; field_index++)
271             {
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);
277             }
278             g_free(stat_table->elements[element]);
279         }
280         g_free(stat_table->elements);
281         g_free(stat_table);
282     }
283     g_array_set_size(new_stat->tables, 0);
284 }
285
286
287 /*
288  * Editor modelines
289  *
290  * Local Variables:
291  * c-basic-offset: 4
292  * tab-width: 8
293  * indent-tabs-mode: nil
294  * End:
295  *
296  * ex: set shiftwidth=4 tabstop=8 expandtab:
297  * :indentSize=4:tabSize=8:noTabs=true:
298  */