Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/stat_tap_ui.c
Line
Count
Source
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
#include <wsutil/ws_assert.h>
21
22
/* structure to keep track of what stats have registered command-line
23
   arguments.
24
 */
25
typedef struct _stat_cmd_arg {
26
    stat_tap_ui *ui;
27
    const char *cmd;
28
    bool (*init)(const char *arg, void* userdata);
29
    void* userdata;
30
} stat_cmd_arg;
31
32
static wmem_list_t *stat_cmd_arg_list;
33
static wmem_tree_t* registered_stat_tables;
34
35
36
/* structure to keep track of what stats have been specified on the
37
   command line.
38
 */
39
typedef struct {
40
    stat_cmd_arg *sca;
41
    char *arg;
42
} stat_requested;
43
static GSList *stats_requested;
44
45
/* **********************************************************************
46
 * Function called from stat to register the stat's command-line argument
47
 * and initialization routine
48
 * ********************************************************************** */
49
static int
50
search_duplicate(const void *a, const void *b)
51
0
{
52
0
    return strcmp(((const stat_cmd_arg *)a)->cmd, (const char *)b);
53
0
}
54
55
static int
56
sort_by_name(const void *a, const void *b)
57
0
{
58
0
    return strcmp(((const stat_cmd_arg *)a)->cmd, ((const stat_cmd_arg *)b)->cmd);
59
0
}
60
61
void stat_tap_init(void)
62
16
{
63
16
    stat_cmd_arg_list = wmem_list_new(wmem_epan_scope());
64
16
    registered_stat_tables = wmem_tree_new(wmem_epan_scope());
65
16
}
66
67
void
68
register_stat_tap_ui(stat_tap_ui *ui, void *userdata)
69
0
{
70
0
    stat_cmd_arg *newsca;
71
72
    /* Key is already present */
73
0
    if (wmem_list_find_custom(stat_cmd_arg_list, ui->cli_string, search_duplicate))
74
0
        return;
75
76
0
    newsca = wmem_new(wmem_epan_scope(), stat_cmd_arg);
77
0
    newsca->cmd= wmem_strdup(wmem_epan_scope(), ui->cli_string);
78
0
    newsca->init=ui->tap_init_cb;
79
0
    newsca->userdata=userdata;
80
81
0
    wmem_list_insert_sorted(stat_cmd_arg_list, newsca, sort_by_name);
82
0
}
83
84
/* **********************************************************************
85
 * Function called for a stat command-line argument
86
 * ********************************************************************** */
87
bool
88
process_stat_cmd_arg(const char *optstr)
89
0
{
90
0
    wmem_list_frame_t *entry;
91
0
    stat_cmd_arg *sca;
92
0
    stat_requested *tr;
93
0
    char *stat_command = g_strdup(optstr);
94
95
    /* Renamed in Wireshark 3.0, backwards compatibility. */
96
0
    if (!strncmp(stat_command, "follow,ssl", strlen("follow,ssl"))) {
97
0
        memcpy(stat_command + 7, "tls", 3);
98
0
    }
99
100
    /* The strings "ipx" or "ipv6" must be tested before "ip" to select the
101
      right tap so the sorting does matter.  And it's also why the list is
102
      walked backwards */
103
0
    for (entry = wmem_list_tail(stat_cmd_arg_list); entry; entry = wmem_list_frame_prev(entry)) {
104
0
        sca = (stat_cmd_arg*)wmem_list_frame_data(entry);
105
0
        if (!strncmp(sca->cmd, stat_command, strlen(sca->cmd))) {
106
0
            tr=g_new(stat_requested, 1);
107
0
            tr->sca = sca;
108
0
            tr->arg = stat_command;
109
0
            stats_requested = g_slist_append(stats_requested, tr);
110
0
            return true;
111
0
        }
112
0
    }
113
0
    g_free(stat_command);
114
0
    return false;
115
0
}
116
117
/* **********************************************************************
118
 * Function to list all possible tap command-line arguments
119
 * ********************************************************************** */
120
static void
121
list_stat_cmd_args_func(void *data, void *userdata _U_)
122
0
{
123
0
    fprintf(stderr,"     %s\n", ((stat_cmd_arg*)data)->cmd);
124
0
}
125
126
void
127
list_stat_cmd_args(void)
128
0
{
129
0
    wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
130
0
}
131
132
/* **********************************************************************
133
 * Function to process stats requested with command-line arguments
134
 * ********************************************************************** */
135
bool
136
start_requested_stats(void)
137
0
{
138
0
    stat_requested *sr;
139
0
    bool success = true;
140
141
0
    while(stats_requested){
142
0
        sr=(stat_requested *)stats_requested->data;
143
0
        success &= (*sr->sca->init)(sr->arg,sr->sca->userdata);
144
0
        stats_requested=g_slist_remove(stats_requested, sr);
145
0
        g_free(sr->arg);
146
0
        g_free(sr);
147
0
    }
148
149
0
    return success;
150
0
}
151
152
void register_stat_tap_table_ui(stat_tap_table_ui *ui)
153
464
{
154
464
    wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
155
464
}
156
157
stat_tap_table_ui *stat_tap_by_name(const char *name)
158
0
{
159
0
    return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
160
0
}
161
162
void stat_tap_iterate_tables(wmem_foreach_func func, void *user_data)
163
0
{
164
0
    wmem_tree_foreach(registered_stat_tables, func, user_data);
165
0
}
166
167
void stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
168
0
{
169
0
    unsigned len = (unsigned) strlen(new_stat->cli_string);
170
0
    *filter=NULL;
171
0
    *err=NULL;
172
173
0
    if (!strncmp(opt_arg, new_stat->cli_string, len))
174
0
    {
175
0
        if (opt_arg[len] == ',')
176
0
        {
177
0
           *filter = opt_arg + len+1;
178
0
        }
179
0
    }
180
181
0
    if (new_stat->stat_filter_check_cb)
182
0
        new_stat->stat_filter_check_cb(opt_arg, filter, err);
183
0
}
184
185
stat_tap_table* stat_tap_init_table(const char *name, int num_fields, int num_elements,
186
                const char *filter_string)
187
0
{
188
0
    stat_tap_table* new_table = g_new0(stat_tap_table, 1);
189
190
0
    new_table->title = name;
191
0
    new_table->num_elements = num_elements;
192
0
    new_table->num_fields = num_fields;
193
0
    new_table->filter_string = filter_string;
194
0
    new_table->elements = g_new0(stat_tap_table_item_type*, num_elements);
195
196
0
    return new_table;
197
0
}
198
199
stat_tap_table *stat_tap_find_table(stat_tap_table_ui *ui, const char *name)
200
0
{
201
0
    unsigned i = 0;
202
0
    stat_tap_table *stat_table;
203
204
0
    if (ui->tables == NULL)
205
0
        return NULL;
206
207
0
    for (i = 0; i < ui->tables->len; i++) {
208
0
        stat_table = g_array_index(ui->tables, stat_tap_table *, i);
209
0
        if (!g_strcmp0(stat_table->title, name)) {
210
0
            return stat_table;
211
0
        }
212
0
    }
213
214
0
    return NULL;
215
0
}
216
217
void stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
218
0
{
219
0
    if (new_stat->tables == NULL)
220
0
        new_stat->tables = g_array_new(false, true, sizeof(stat_tap_table*));
221
222
0
    g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
223
0
}
224
225
void stat_tap_init_table_row(stat_tap_table *stat_table, unsigned table_index, unsigned num_fields, const stat_tap_table_item_type* fields)
226
0
{
227
    /* we have discovered a new procedure. Extend the table accordingly */
228
0
    if(table_index>=stat_table->num_elements){
229
0
        unsigned old_num_elements=stat_table->num_elements;
230
0
        unsigned i;
231
232
0
        stat_table->num_elements=table_index+1;
233
0
        stat_table->elements = (stat_tap_table_item_type**)g_realloc(stat_table->elements, sizeof(stat_tap_table_item_type*)*(stat_table->num_elements));
234
0
        for(i=old_num_elements;i<stat_table->num_elements;i++){
235
0
            stat_table->elements[i] = g_new0(stat_tap_table_item_type, stat_table->num_fields);
236
0
        }
237
0
    }
238
0
    memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
239
240
0
}
241
242
stat_tap_table_item_type* stat_tap_get_field_data(const stat_tap_table *stat_table, unsigned table_index, unsigned field_index)
243
0
{
244
0
    stat_tap_table_item_type* field_value;
245
0
    ws_assert(table_index < stat_table->num_elements);
246
247
0
    field_value = stat_table->elements[table_index];
248
249
0
    ws_assert(field_index < stat_table->num_fields);
250
251
0
    return &field_value[field_index];
252
0
}
253
254
void stat_tap_set_field_data(stat_tap_table *stat_table, unsigned table_index, unsigned field_index, stat_tap_table_item_type* field_data)
255
0
{
256
0
    stat_tap_table_item_type* field_value;
257
0
    ws_assert(table_index < stat_table->num_elements);
258
259
0
    field_value = stat_table->elements[table_index];
260
261
0
    ws_assert(field_index < stat_table->num_fields);
262
263
0
    field_value[field_index] = *field_data;
264
0
}
265
266
void reset_stat_table(stat_tap_table_ui* new_stat)
267
0
{
268
0
    unsigned i = 0;
269
0
    stat_tap_table *stat_table;
270
271
0
    for (i = 0; i < new_stat->tables->len; i++)
272
0
    {
273
0
        stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
274
275
0
        if (new_stat->stat_tap_reset_table_cb)
276
0
            new_stat->stat_tap_reset_table_cb(stat_table);
277
0
    }
278
0
}
279
280
void free_stat_tables(stat_tap_table_ui* new_stat)
281
0
{
282
0
    unsigned i = 0, element, field_index;
283
0
    stat_tap_table *stat_table;
284
0
    stat_tap_table_item_type* field_data;
285
286
0
    for (i = 0; i < new_stat->tables->len; i++)
287
0
    {
288
0
        stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
289
290
0
        for (element = 0; element < stat_table->num_elements; element++)
291
0
        {
292
0
            for (field_index = 0; field_index < stat_table->num_fields; field_index++)
293
0
            {
294
0
                field_data = stat_tap_get_field_data(stat_table, element, field_index);
295
                /* Give dissector a crack at it */
296
                /* XXX Should this be per-row instead? */
297
0
                if (new_stat->stat_tap_free_table_item_cb)
298
0
                    new_stat->stat_tap_free_table_item_cb(stat_table, element, field_index, field_data);
299
0
            }
300
0
            g_free(stat_table->elements[element]);
301
0
        }
302
0
        g_free(stat_table->elements);
303
0
        g_free(stat_table);
304
0
    }
305
0
    g_array_set_size(new_stat->tables, 0);
306
0
}
307
308
309
/*
310
 * Editor modelines
311
 *
312
 * Local Variables:
313
 * c-basic-offset: 4
314
 * tab-width: 8
315
 * indent-tabs-mode: nil
316
 * End:
317
 *
318
 * ex: set shiftwidth=4 tabstop=8 expandtab:
319
 * :indentSize=4:tabSize=8:noTabs=true:
320
 */