Bug Summary

File:ui/io_graph_item.h
Warning:line 214, column 35
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name sharkd_session.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-10-21-100328-3623-1 -x c /builds/wireshark/wireshark/sharkd_session.c

/builds/wireshark/wireshark/sharkd_session.c

1/* sharkd_session.c
2 *
3 * Copyright (C) 2016 Jakub Zawadzki
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <[email protected]>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12#include <config.h>
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <stdarg.h>
17#include <string.h>
18#include <errno(*__errno_location ()).h>
19#include <inttypes.h>
20
21#include <glib.h>
22
23#include <wsutil/wsjson.h>
24#include <wsutil/json_dumper.h>
25#include <wsutil/ws_assert.h>
26#include <wsutil/wsgcrypt.h>
27
28#include <file.h>
29#include <epan/epan_dissect.h>
30#include <epan/exceptions.h>
31#include <epan/color_filters.h>
32#include <epan/prefs.h>
33#include <epan/prefs-int.h>
34#include <epan/uat-int.h>
35#include <wiretap/wtap.h>
36
37#include <epan/column.h>
38#include <epan/column-info.h>
39
40#include <ui/io_graph_item.h>
41#include <epan/stats_tree_priv.h>
42#include <epan/stat_tap_ui.h>
43#include <epan/conversation_table.h>
44#include <epan/sequence_analysis.h>
45#include <epan/expert.h>
46#include <epan/export_object.h>
47#include <epan/follow.h>
48#include <epan/rtd_table.h>
49#include <epan/srt_table.h>
50#include <epan/to_str.h>
51#include <epan/secrets.h>
52
53#include <epan/dissectors/packet-h225.h>
54#include <ui/voip_calls.h>
55#include <ui/rtp_stream.h>
56#include <ui/tap-rtp-common.h>
57#include <ui/tap-rtp-analysis.h>
58#include <ui/cli/tap-protohierstat.h>
59#include <ui/cli/tap-voip.h>
60#include <wsutil/version_info.h>
61#include <epan/to_str.h>
62
63#include <epan/addr_resolv.h>
64#include <epan/dissectors/packet-rtp.h>
65#include <epan/dissectors/packet-rtp_pt.h>
66#include <ui/rtp_media.h>
67#include <ui/mcast_stream.h>
68#include <speex/speex_resampler.h>
69
70#include <epan/maxmind_db.h>
71
72#include <wsutil/pint.h>
73#include <wsutil/strnatcmp.h>
74#include <wsutil/strtoi.h>
75
76#include "globals.h"
77
78#include "sharkd.h"
79
80struct sharkd_filter_item
81{
82 uint8_t *filtered; /* can be NULL if all frames are matching for given filter. */
83};
84
85static GHashTable *filter_table;
86
87static int mode;
88static uint32_t rpcid;
89
90static json_dumper dumper;
91
92
93static const char *
94json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
95{
96 int i;
97
98 for (i = 0; i < count; i += 2)
99 {
100 const char *tok_attr = &buf[tokens[i + 0].start];
101 const char *tok_value = &buf[tokens[i + 1].start];
102
103 if (!strcmp(tok_attr, attr))
104 return tok_value;
105 }
106
107 return NULL((void*)0);
108}
109
110static void
111json_print_base64(const uint8_t *data, size_t len)
112{
113 json_dumper_begin_base64(&dumper);
114 json_dumper_write_base64(&dumper, data, len);
115 json_dumper_end_base64(&dumper);
116}
117
118static void G_GNUC_PRINTF(2, 3)__attribute__((__format__ (__printf__, 2, 3)))
119sharkd_json_value_anyf(const char *key, const char *format, ...)
120{
121 if (key)
122 json_dumper_set_member_name(&dumper, key);
123
124 va_list ap;
125 va_start(ap, format)__builtin_va_start(ap, format);
126 json_dumper_value_va_list(&dumper, format, ap);
127 va_end(ap)__builtin_va_end(ap);
128}
129
130static void
131sharkd_json_value_string(const char *key, const char *str)
132{
133 if (key)
134 json_dumper_set_member_name(&dumper, key);
135 json_dumper_value_string(&dumper, str);
136}
137
138static void
139sharkd_json_value_base64(const char *key, const uint8_t *data, size_t len)
140{
141 if (key)
142 json_dumper_set_member_name(&dumper, key);
143 json_print_base64(data, len);
144}
145
146static void G_GNUC_PRINTF(2, 3)__attribute__((__format__ (__printf__, 2, 3)))
147sharkd_json_value_stringf(const char *key, const char *format, ...)
148{
149 if (key)
150 json_dumper_set_member_name(&dumper, key);
151
152 va_list ap;
153 va_start(ap, format)__builtin_va_start(ap, format);
154 char* sformat = ws_strdup_printf("\"%s\"", format)wmem_strdup_printf(((void*)0), "\"%s\"", format);
155 json_dumper_value_va_list(&dumper, sformat, ap);
156 g_free(sformat);
157 va_end(ap)__builtin_va_end(ap);
158}
159
160static void
161sharkd_json_array_open(const char *key)
162{
163 if (key)
164 json_dumper_set_member_name(&dumper, key);
165 json_dumper_begin_array(&dumper);
166}
167
168static void
169sharkd_json_array_close(void)
170{
171 json_dumper_end_array(&dumper);
172}
173
174static void
175sharkd_json_object_open(const char *key)
176{
177 if (key)
178 json_dumper_set_member_name(&dumper, key);
179 json_dumper_begin_object(&dumper);
180}
181
182static void
183sharkd_json_object_close(void)
184{
185 json_dumper_end_object(&dumper);
186}
187
188static void
189sharkd_json_response_open(uint32_t id)
190{
191 json_dumper_begin_object(&dumper); // start the message
192 sharkd_json_value_string("jsonrpc", "2.0");
193 sharkd_json_value_anyf("id", "%d", id);
194}
195
196static void
197sharkd_json_response_close(void)
198{
199 json_dumper_end_object(&dumper); // end the message
200
201 json_dumper_finish(&dumper);
202
203 /*
204 * We do an explicit fflush after every line, because
205 * we want output to be written to the socket as soon
206 * as the line is complete.
207 *
208 * The stream is fully-buffered by default, so it's
209 * only flushed when the buffer fills or the FILE *
210 * is closed. On UN*X, we could set it to be line
211 * buffered, but the MSVC standard I/O routines don't
212 * support line buffering - they only support *byte*
213 * buffering, doing a write for every byte written,
214 * which is too inefficient, and full buffering,
215 * which is what you get if you request line buffering.
216 */
217 fflush(stdoutstdout);
218}
219
220static void
221sharkd_json_result_prologue(uint32_t id)
222{
223 sharkd_json_response_open(id);
224 sharkd_json_object_open("result"); // start the result object
225}
226
227static void
228sharkd_json_result_epilogue(void)
229{
230 json_dumper_end_object(&dumper); // end the result object
231 sharkd_json_response_close();
232}
233
234static void
235sharkd_json_result_array_prologue(uint32_t id)
236{
237 sharkd_json_response_open(id);
238 sharkd_json_array_open("result"); // start the result array
239}
240
241static void
242sharkd_json_result_array_epilogue(void)
243{
244 sharkd_json_array_close(); // end of result array
245 sharkd_json_response_close();
246}
247
248static void
249sharkd_json_simple_ok(uint32_t id)
250{
251 sharkd_json_result_prologue(id);
252 sharkd_json_value_string("status", "OK");
253 sharkd_json_result_epilogue();
254}
255
256static void
257sharkd_json_warning(uint32_t id, char *warning)
258{
259 sharkd_json_result_prologue(id);
260 sharkd_json_value_string("status", "Warning");
261 sharkd_json_value_string("warning", warning);
262 sharkd_json_result_epilogue();
263}
264
265static void G_GNUC_PRINTF(4, 5)__attribute__((__format__ (__printf__, 4, 5)))
266sharkd_json_error(uint32_t id, int code, char* data, char* format, ...)
267{
268 sharkd_json_response_open(id);
269 sharkd_json_object_open("error");
270 sharkd_json_value_anyf("code", "%d", code);
271
272 if (format)
273 {
274 // format the text message
275 va_list args;
276
277 va_start(args, format)__builtin_va_start(args, format);
278 char *error_msg = ws_strdup_vprintf(format, args)wmem_strdup_vprintf(((void*)0), format, args);
279 va_end(args)__builtin_va_end(args);
280
281 sharkd_json_value_string("message", error_msg);
282
283 g_free(error_msg);
284 }
285
286 sharkd_json_object_close();
287
288 if (data)
289 sharkd_json_value_string("data", data);
290
291 sharkd_json_response_close();
292}
293
294static bool_Bool
295is_param_match(const char *param_in, const char *valid_param)
296{
297 char* ptr;
298
299 if ((ptr = g_strrstr(valid_param, "*")))
300 {
301 size_t prefix_len = ptr - valid_param;
302 return !strncmp(param_in, valid_param, prefix_len);
303 }
304 else
305 return !strcmp(param_in, valid_param);
306}
307
308/*
309 * json_prep does four things:
310 *
311 * 1. check the syntax of the root and parameter members
312 * 2. tokenize the names and values by zero terminating them
313 * 3. unescape the names and values
314 * 4. extracts and saves the rpcid
315 * - we have to do it here as it's needed for the error messages
316 *
317 * The objective is to minimise the validation work in the functions
318 * that process each called method.
319 *
320 * This gets a little messy as the JSON parser creates a flat list
321 * of all members rather than create a tree.
322 */
323static bool_Bool
324json_prep(char* buf, const jsmntok_t* tokens, int count)
325{
326 int i;
327 const char* method = NULL((void*)0);
328 char* attr_name = NULL((void*)0);
329 char* attr_value = NULL((void*)0);
330
331#define SHARKD_JSON_ANY0 0
332#define SHARKD_JSON_STRING1 1
333#define SHARKD_JSON_INTEGER2 2
334#define SHARKD_JSON_UINTEGER3 3
335#define SHARKD_JSON_FLOAT4 4
336#define SHARKD_JSON_OBJECT5 5
337#define SHARKD_JSON_ARRAY6 6
338#define SHARKD_JSON_BOOLEAN7 7
339#define SHARKD_ARRAY_END99 99
340
341 struct member_attribute {
342 const char* parent_ctx;
343 const char* name;
344 int level;
345 jsmntype_t type;
346 int value_type;
347 bool_Bool is_mandatory;
348 };
349
350#define SHARKD_MANDATORY1 true1
351#define SHARKD_OPTIONAL0 false0
352
353 /*
354 * The member attribute structure is key to the syntax checking. The
355 * array contains all of the root level (1) member names, the data
356 * types permissible for the value and a boolean that indicates whether
357 * or not the member is mandatory.
358 *
359 * Once we get into the next layer (2) of the json tree, we need to check
360 * params member names and data types dependent in the context of the method
361 * (parent_ctx).
362 */
363
364 struct member_attribute name_array[] = {
365 // Root members
366 {NULL((void*)0), "jsonrpc", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
367 {NULL((void*)0), "userid", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
368 {NULL((void*)0), "id", 1, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_MANDATORY1},
369 {NULL((void*)0), "method", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
370 {NULL((void*)0), "params", 1, JSMN_OBJECT, SHARKD_JSON_OBJECT5, SHARKD_OPTIONAL0},
371
372 // Valid methods
373 {"method", "analyse", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
374 {"method", "bye", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
375 {"method", "check", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
376 {"method", "complete", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
377 {"method", "download", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
378 {"method", "dumpconf", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
379 {"method", "follow", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
380 {"method", "field", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
381 {"method", "fields", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
382 {"method", "frame", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
383 {"method", "frames", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
384 {"method", "info", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
385 {"method", "intervals", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
386 {"method", "iograph", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
387 {"method", "load", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
388 {"method", "setcomment", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
389 {"method", "setconf", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
390 {"method", "status", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
391 {"method", "tap", 1, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
392
393 // Parameters and their method context
394 {"check", "field", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
395 {"check", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
396 {"complete", "field", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
397 {"complete", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
398 {"download", "token", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
399 {"dumpconf", "pref", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
400 {"follow", "follow", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
401 {"follow", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
402 {"follow", "sub_stream", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
403 {"field", "name", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
404 {"frame", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_MANDATORY1},
405 {"frame", "proto", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
406 {"frame", "ref_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
407 {"frame", "prev_frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
408 {"frame", "columns", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
409 {"frame", "color", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
410 {"frame", "bytes", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
411 {"frame", "hidden", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
412 {"frames", "column*", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY0, SHARKD_OPTIONAL0},
413 {"frames", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
414 {"frames", "skip", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
415 {"frames", "limit", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
416 {"frames", "refs", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
417 {"intervals", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
418 {"intervals", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
419 {"iograph", "interval", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
420 {"iograph", "interval_units", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
421 {"iograph", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
422 {"iograph", "graph0", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
423 {"iograph", "graph1", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
424 {"iograph", "graph2", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
425 {"iograph", "graph3", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
426 {"iograph", "graph4", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
427 {"iograph", "graph5", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
428 {"iograph", "graph6", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
429 {"iograph", "graph7", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
430 {"iograph", "graph8", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
431 {"iograph", "graph9", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
432 {"iograph", "filter0", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
433 {"iograph", "filter1", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
434 {"iograph", "filter2", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
435 {"iograph", "filter3", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
436 {"iograph", "filter4", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
437 {"iograph", "filter5", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
438 {"iograph", "filter6", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
439 {"iograph", "filter7", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
440 {"iograph", "filter8", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
441 {"iograph", "filter9", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
442 {"iograph", "aot0", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
443 {"iograph", "aot1", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
444 {"iograph", "aot2", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
445 {"iograph", "aot3", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
446 {"iograph", "aot4", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
447 {"iograph", "aot5", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
448 {"iograph", "aot6", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
449 {"iograph", "aot7", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
450 {"iograph", "aot8", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
451 {"iograph", "aot9", 2, JSMN_PRIMITIVE, SHARKD_JSON_BOOLEAN7, SHARKD_OPTIONAL0},
452 {"load", "file", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
453 {"load", "max_packets", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
454 {"load", "max_bytes", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_OPTIONAL0},
455 {"setcomment", "frame", 2, JSMN_PRIMITIVE, SHARKD_JSON_UINTEGER3, SHARKD_MANDATORY1},
456 {"setcomment", "comment", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
457 {"setconf", "name", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
458 {"setconf", "value", 2, JSMN_UNDEFINED, SHARKD_JSON_ANY0, SHARKD_MANDATORY1},
459 {"tap", "tap0", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_MANDATORY1},
460 {"tap", "tap1", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
461 {"tap", "tap2", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
462 {"tap", "tap3", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
463 {"tap", "tap4", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
464 {"tap", "tap5", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
465 {"tap", "tap6", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
466 {"tap", "tap7", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
467 {"tap", "tap8", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
468 {"tap", "tap9", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
469 {"tap", "tap10", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
470 {"tap", "tap11", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
471 {"tap", "tap12", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
472 {"tap", "tap13", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
473 {"tap", "tap14", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
474 {"tap", "tap15", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
475 {"tap", "filter", 2, JSMN_STRING, SHARKD_JSON_STRING1, SHARKD_OPTIONAL0},
476
477 // End of the name_array
478 {NULL((void*)0), NULL((void*)0), 0, JSMN_STRING, SHARKD_ARRAY_END99, SHARKD_OPTIONAL0},
479 };
480
481 rpcid = 0;
482
483 /* sanity check, and split strings */
484 if (count < 1 || tokens[0].type != JSMN_OBJECT)
485 {
486 sharkd_json_error(
487 rpcid, -32600, NULL((void*)0),
488 "The request must an object"
489 );
490 return false0;
491 }
492
493 /* don't need [0] token */
494 tokens++;
495 count--;
496
497 if (count & 1)
498 {
499 sharkd_json_error(
500 rpcid, -32600, NULL((void*)0),
501 "The request must contain name/value pairs"
502 );
503 return false0;
504 }
505
506 for (i = 0; i < count; i += 2)
507 {
508 buf[tokens[i + 0].end] = '\0';
509 buf[tokens[i + 1].end] = '\0';
510 }
511
512 // we must get the id as soon as possible so that it's available in all future error messages
513 attr_value = (char*)json_find_attr(buf, tokens, count, "id");
514 if (attr_value)
515 {
516 if (!ws_strtou32(attr_value, NULL((void*)0), &rpcid))
517 {
518 sharkd_json_error(
519 rpcid, -32600, NULL((void*)0),
520 "The id value must be a positive integer"
521 );
522 return false0;
523 }
524 }
525
526 method = json_find_attr(buf, tokens, count, "method");
527
528 if (method)
529 {
530 bool_Bool is_supported = false0;
531 i = 0; // name array index
532
533 // check that the request method is good
534 while (name_array[i].value_type != SHARKD_ARRAY_END99)
535 {
536 if (name_array[i].parent_ctx)
537 {
538 if (!strcmp(method, name_array[i].name) && !strcmp(name_array[i].parent_ctx, "method"))
539 is_supported = true1; // the method is valid
540 }
541
542 i++;
543 }
544
545 if (!is_supported)
546 {
547 sharkd_json_error(
548 rpcid, -32601, NULL((void*)0),
549 "The method %s is not supported", method
550 );
551 return false0;
552 }
553 }
554
555 for (i = 0; i < count; i += 2)
556 {
557 if (tokens[i].type != JSMN_STRING)
558 {
559 sharkd_json_error(
560 rpcid, -32600, NULL((void*)0),
561 "Member names must be a string - member %d is not string", (i / 2) + 1
562 );
563 return false0;
564 }
565
566 attr_name = &buf[tokens[i + 0].start];
567 attr_value = &buf[tokens[i + 1].start];
568
569 if (!strcmp(attr_name, "jsonrpc"))
570 {
571 if (strcmp(&buf[tokens[i + 1].start], "2.0"))
572 {
573 sharkd_json_error(
574 rpcid, -32600, NULL((void*)0),
575 "Only JSON %s is supported", "2.0"
576 );
577 return false0;
578 }
579 }
580
581 /* unescape only value, as keys are simple strings */
582 if (tokens[i + 1].type == JSMN_STRING && !json_decode_string_inplace(attr_value))
583 {
584 sharkd_json_error(
585 rpcid, -32600, NULL((void*)0),
586 "Cannot unescape the value string of member %d", (i / 2) + 1
587 );
588 return false0;
589 }
590
591 /* Confirm that the member is valid */
592 bool_Bool match = false0;
593
594 // We need to check root members (level 1) and parameters (level 2), hence the for loop.
595
596 for (int level = 1; level < 3; level++)
597 {
598 size_t j = 0;
599
600 while (name_array[j].value_type != SHARKD_ARRAY_END99) // iterate through the array until we hit the end
601 {
602 if (is_param_match(attr_name, name_array[j].name) && name_array[j].level == level)
603 {
604 // We need to be sure the match is in the correct context
605 // i.e. is this a match for a root member (level 1) or for a parameter (level 2).
606
607 if (level == 1)
608 {
609 // need to guard against a parameter name matching a method name
610 if (method)
611 {
612 if (name_array[j].parent_ctx)
613 {
614 j++;
615 continue;
616 }
617
618 if (!strcmp(method, &buf[tokens[i + 0].start]))
619 {
620 j++;
621 continue;
622 }
623 }
624
625 match = true1;
626 }
627 else if (method)
628 {
629 if (level == 2 && !strcmp(name_array[j].parent_ctx, method))
630 match = true1;
631 else
632 {
633 j++;
634 continue;
635 }
636 }
637 else
638 {
639 j++;
640 continue;
641 }
642
643 // The match looks good, let's now check the data types
644
645 if (tokens[i + 1].type != name_array[j].type && name_array[j].type != SHARKD_JSON_ANY0)
646 {
647 sharkd_json_error(
648 rpcid, -32600, NULL((void*)0),
649 "The data type for member %s is not valid", attr_name
650 );
651 return false0;
652 }
653 else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_UINTEGER3)
654 {
655 uint32_t temp;
656 if (!ws_strtou32(attr_value, NULL((void*)0), &temp) || temp <= 0)
657 {
658 sharkd_json_error(
659 rpcid, -32600, NULL((void*)0),
660 "The value for %s must be a positive integer", name_array[j].name
661 );
662 return false0;
663 }
664 }
665 else if (name_array[j].type == JSMN_PRIMITIVE && name_array[j].value_type == SHARKD_JSON_BOOLEAN7)
666 {
667 if (strcmp(attr_value, "true") && strcmp(attr_value, "false"))
668 {
669 sharkd_json_error(
670 rpcid, -32600, NULL((void*)0),
671 "The value for %s must be a boolean (true or false)", name_array[j].name
672 );
673 return false0;
674 }
675
676 }
677 break; // looks like a valid match
678 }
679 j++;
680 }
681 }
682
683 if (!match)
684 {
685 sharkd_json_error(
686 rpcid, -32600, NULL((void*)0),
687 "%s is not a valid member name", attr_name
688 );
689 return false0;
690 }
691 }
692
693 /* check for mandatory members */
694 size_t j = 0;
695
696 while (name_array[j].value_type != SHARKD_ARRAY_END99)
697 {
698 if (name_array[j].is_mandatory && name_array[j].level == 1)
699 {
700 if (!json_find_attr(buf, tokens, count, name_array[j].name))
701 {
702 sharkd_json_error(
703 rpcid, -32600, NULL((void*)0),
704 "Mandatory member %s is missing", name_array[j].name
705 );
706 return false0;
707 }
708 }
709 j++;
710 }
711
712 // check that the current request contains the mandatory parameters
713 j = 0;
714
715 while (name_array[j].value_type != SHARKD_ARRAY_END99)
716 {
717 if (name_array[j].is_mandatory && name_array[j].level == 2 && !strcmp(method, name_array[j].parent_ctx))
718 {
719 if (!json_find_attr(buf, tokens, count, name_array[j].name))
720 {
721 sharkd_json_error(
722 rpcid, -32600, NULL((void*)0),
723 "Mandatory parameter %s is missing", name_array[j].name
724 );
725 return false0;
726 }
727 }
728 j++;
729 }
730
731
732 // check that the parameters for the current request are valid for the method and that the data type for the value is valid
733
734 return true1;
735}
736
737static void
738sharkd_session_filter_free(void *data)
739{
740 struct sharkd_filter_item *l = (struct sharkd_filter_item *) data;
741
742 g_free(l->filtered);
743 g_free(l);
744}
745
746static const struct sharkd_filter_item *
747sharkd_session_filter_data(const char *filter)
748{
749 struct sharkd_filter_item *l;
750
751 l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter);
752 if (!l)
753 {
754 uint8_t *filtered = NULL((void*)0);
755
756 int ret = sharkd_filter(filter, &filtered);
757
758 if (ret == -1)
759 return NULL((void*)0);
760
761 l = g_new(struct sharkd_filter_item, 1)((struct sharkd_filter_item *) g_malloc_n ((1), sizeof (struct
sharkd_filter_item)))
;
762 l->filtered = filtered;
763
764 g_hash_table_insert(filter_table, g_strdup(filter)g_strdup_inline (filter), l);
765 }
766
767 return l;
768}
769
770static bool_Bool
771sharkd_rtp_match_init(rtpstream_id_t *id, const char *init_str)
772{
773 bool_Bool ret = false0;
774 char **arr;
775 uint32_t tmp_addr_src, tmp_addr_dst;
776 address tmp_src_addr, tmp_dst_addr;
777
778 memset(id, 0, sizeof(*id));
779
780 arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
781 if (g_strv_length(arr) != 5)
782 goto fail;
783
784 /* TODO, for now only IPv4 */
785 if (!get_host_ipaddr(arr[0], &tmp_addr_src))
786 goto fail;
787
788 if (!ws_strtou16(arr[1], NULL((void*)0), &id->src_port))
789 goto fail;
790
791 if (!get_host_ipaddr(arr[2], &tmp_addr_dst))
792 goto fail;
793
794 if (!ws_strtou16(arr[3], NULL((void*)0), &id->dst_port))
795 goto fail;
796
797 if (!ws_hexstrtou32(arr[4], NULL((void*)0), &id->ssrc))
798 goto fail;
799
800 set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src);
801 copy_address(&id->src_addr, &tmp_src_addr);
802 set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst);
803 copy_address(&id->dst_addr, &tmp_dst_addr);
804
805 ret = true1;
806
807fail:
808 g_strfreev(arr);
809 return ret;
810}
811
812static bool_Bool
813sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata _U___attribute__((unused)))
814{
815 stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value;
816
817 json_dumper_begin_object(&dumper);
818 sharkd_json_value_string("name", stat_tap->title);
819 sharkd_json_value_stringf("tap", "nstat:%s", (const char *) key);
820 json_dumper_end_object(&dumper);
821
822 return false0;
823}
824
825static bool_Bool
826sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata _U___attribute__((unused)))
827{
828 struct register_ct *table = (struct register_ct *) value;
829
830 const char *label = (const char *) key;
831
832 if (get_conversation_packet_func(table))
833 {
834 json_dumper_begin_object(&dumper);
835 sharkd_json_value_stringf("name", "Conversation List/%s", label);
836 sharkd_json_value_stringf("tap", "conv:%s", label);
837 json_dumper_end_object(&dumper);
838 }
839
840 if (get_endpoint_packet_func(table))
841 {
842 json_dumper_begin_object(&dumper);
843 sharkd_json_value_stringf("name", "Endpoint/%s", label);
844 sharkd_json_value_stringf("tap", "endpt:%s", label);
845 json_dumper_end_object(&dumper);
846 }
847 return false0;
848}
849
850static bool_Bool
851sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata _U___attribute__((unused)))
852{
853 register_analysis_t *analysis = (register_analysis_t *) value;
854
855 json_dumper_begin_object(&dumper);
856 sharkd_json_value_string("name", sequence_analysis_get_ui_name(analysis));
857 sharkd_json_value_stringf("tap", "seqa:%s", (const char *) key);
858 json_dumper_end_object(&dumper);
859
860 return false0;
861}
862
863static bool_Bool
864sharkd_export_object_visit_cb(const void *key _U___attribute__((unused)), void *value, void *user_data _U___attribute__((unused)))
865{
866 register_eo_t *eo = (register_eo_t *) value;
867
868 const int proto_id = get_eo_proto_id(eo);
869 const char *filter = proto_get_protocol_filter_name(proto_id);
870 const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
871
872 json_dumper_begin_object(&dumper);
873 sharkd_json_value_stringf("name", "Export Object/%s", label);
874 sharkd_json_value_stringf("tap", "eo:%s", filter);
875 json_dumper_end_object(&dumper);
876
877 return false0;
878}
879
880static bool_Bool
881sharkd_srt_visit_cb(const void *key _U___attribute__((unused)), void *value, void *user_data _U___attribute__((unused)))
882{
883 register_srt_t *srt = (register_srt_t *) value;
884
885 const int proto_id = get_srt_proto_id(srt);
886 const char *filter = proto_get_protocol_filter_name(proto_id);
887 const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
888
889 json_dumper_begin_object(&dumper);
890 sharkd_json_value_stringf("name", "Service Response Time/%s", label);
891 sharkd_json_value_stringf("tap", "srt:%s", filter);
892 json_dumper_end_object(&dumper);
893
894 return false0;
895}
896
897static bool_Bool
898sharkd_rtd_visit_cb(const void *key _U___attribute__((unused)), void *value, void *user_data _U___attribute__((unused)))
899{
900 register_rtd_t *rtd = (register_rtd_t *) value;
901
902 const int proto_id = get_rtd_proto_id(rtd);
903 const char *filter = proto_get_protocol_filter_name(proto_id);
904 const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
905
906 json_dumper_begin_object(&dumper);
907 sharkd_json_value_stringf("name", "Response Time Delay/%s", label);
908 sharkd_json_value_stringf("tap", "rtd:%s", filter);
909 json_dumper_end_object(&dumper);
910
911 return false0;
912}
913
914static bool_Bool
915sharkd_follower_visit_cb(const void *key _U___attribute__((unused)), void *value, void *user_data _U___attribute__((unused)))
916{
917 register_follow_t *follower = (register_follow_t *) value;
918
919 const int proto_id = get_follow_proto_id(follower);
920 const char *label = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
921 const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
922
923 json_dumper_begin_object(&dumper);
924 sharkd_json_value_stringf("name", "Follow/%s", label);
925 sharkd_json_value_stringf("tap", "follow:%s", filter);
926 json_dumper_end_object(&dumper);
927
928 return false0;
929}
930
931static void
932sharkd_session_print_capture_types(void)
933{
934 unsigned i;
935 GArray *writable_type_subtypes;
936 writable_type_subtypes = wtap_get_writable_file_types_subtypes(FT_SORT_BY_NAME);
937 for (i = 0; i < writable_type_subtypes->len; i++) {
938 int ft = g_array_index(writable_type_subtypes, int, i)(((int*) (void *) (writable_type_subtypes)->data) [(i)]);
939 sharkd_json_object_open(NULL((void*)0));
940 sharkd_json_value_string("name", wtap_file_type_subtype_name(ft));
941 sharkd_json_value_string("description", wtap_file_type_subtype_description(ft));
942 sharkd_json_object_close();
943 }
944 g_array_free(writable_type_subtypes, TRUE(!(0)));
945}
946
947struct encap_type_info
948{
949 const char *name;
950 const char *description;
951};
952
953static int
954encap_type_info_nat_compare(const void *a, const void *b)
955{
956 return ws_ascii_strnatcmp(((const struct encap_type_info *)a)->name,
957 ((const struct encap_type_info *)b)->name);
958}
959
960static void
961encap_type_info_visit(void *data, void *user_data _U___attribute__((unused)))
962{
963 sharkd_json_object_open(NULL((void*)0));
964 sharkd_json_value_string("name", ((struct encap_type_info *)data)->name);
965 sharkd_json_value_string("description", ((struct encap_type_info *)data)->description);
966 sharkd_json_object_close();
967}
968
969static void
970sharkd_session_print_encap_types(void)
971{
972 int i;
973 struct encap_type_info *encaps;
974 GSList *list = NULL((void*)0);
975 encaps = g_new(struct encap_type_info, WTAP_NUM_ENCAP_TYPES)((struct encap_type_info *) g_malloc_n ((wtap_get_num_encap_types
()), sizeof (struct encap_type_info)))
;
976 for (i = 0; i < WTAP_NUM_ENCAP_TYPESwtap_get_num_encap_types(); i++) {
977 encaps[i].name = wtap_encap_name(i);
978 if (encaps[i].name != NULL((void*)0)) {
979 encaps[i].description = wtap_encap_description(i);
980 list = g_slist_insert_sorted(list, &encaps[i], encap_type_info_nat_compare);
981 }
982 }
983 g_slist_foreach(list, encap_type_info_visit, NULL((void*)0));
984 g_slist_free(list);
985 g_free(encaps);
986}
987
988/**
989 * sharkd_session_process_info()
990 *
991 * Process info request
992 *
993 * Output object with attributes:
994 * (m) version - version number
995 *
996 * (m) columns - available column formats, array of object with attributes:
997 * 'name' - column name
998 * 'format' - column format-name
999 *
1000 * (m) stats - available statistics, array of object with attributes:
1001 * 'name' - statistic name
1002 * 'tap' - sharkd tap-name for statistic
1003 *
1004 * (m) convs - available conversation list, array of object with attributes:
1005 * 'name' - conversation name
1006 * 'tap' - sharkd tap-name for conversation
1007 *
1008 * (m) eo - available export object list, array of object with attributes:
1009 * 'name' - export object name
1010 * 'tap' - sharkd tap-name for eo
1011 *
1012 * (m) srt - available service response time list, array of object with attributes:
1013 * 'name' - service response time name
1014 * 'tap' - sharkd tap-name for srt
1015 *
1016 * (m) rtd - available response time delay list, array of object with attributes:
1017 * 'name' - response time delay name
1018 * 'tap' - sharkd tap-name for rtd
1019 *
1020 * (m) seqa - available sequence analysis (flow) list, array of object with attributes:
1021 * 'name' - sequence analysis name
1022 * 'tap' - sharkd tap-name
1023 *
1024 * (m) taps - available taps, array of object with attributes:
1025 * 'name' - tap name
1026 * 'tap' - sharkd tap-name
1027 *
1028 * (m) follow - available followers, array of object with attributes:
1029 * 'name' - tap name
1030 * 'tap' - sharkd tap-name
1031 *
1032 * (m) ftypes - conversation table for FT_ number to string, array of FT_xxx strings.
1033 *
1034 * (m) nstat - available table-based taps, array of object with attributes:
1035 * 'name' - tap name
1036 * 'tap' - sharkd tap-name
1037 *
1038 * (m) capture_types - available capture types, array of object with attributes:
1039 * 'name' - capture type name
1040 * 'description' - capture type description
1041 *
1042 * (m) encap_types - available encapsulation types, array of object with attributes:
1043 * 'name' - encapsulation type name
1044 * 'description' - encapsulation type description
1045 */
1046static void
1047sharkd_session_process_info(void)
1048{
1049 int i;
1050
1051 sharkd_json_result_prologue(rpcid);
1052
1053 sharkd_json_array_open("columns");
1054 for (i = 0; i < NUM_COL_FMTS; i++)
1055 {
1056 const char *col_format = col_format_to_string(i);
1057 const char *col_descr = col_format_desc(i);
1058
1059 json_dumper_begin_object(&dumper);
1060 sharkd_json_value_string("name", col_descr);
1061 sharkd_json_value_string("format", col_format);
1062 json_dumper_end_object(&dumper);
1063 }
1064 sharkd_json_array_close();
1065
1066 sharkd_json_array_open("stats");
1067 {
1068 GList *cfg_list = stats_tree_get_cfg_list();
1069 GList *l;
1070
1071 for (l = cfg_list; l; l = l->next)
1072 {
1073 stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
1074
1075 json_dumper_begin_object(&dumper);
1076 sharkd_json_value_string("name", cfg->title);
1077 sharkd_json_value_stringf("tap", "stat:%s", cfg->abbr);
1078 json_dumper_end_object(&dumper);
1079 }
1080
1081 g_list_free(cfg_list);
1082 }
1083 sharkd_json_array_close();
1084
1085 sharkd_json_array_open("ftypes");
1086 for (i = 0; i < FT_NUM_TYPES; i++)
1087 sharkd_json_value_string(NULL((void*)0), ftype_name((ftenum_t) i));
1088 sharkd_json_array_close();
1089
1090 sharkd_json_array_open("capture_types");
1091 sharkd_session_print_capture_types();
1092 sharkd_json_array_close();
1093
1094 sharkd_json_array_open("encap_types");
1095 sharkd_session_print_encap_types();
1096 sharkd_json_array_close();
1097
1098 sharkd_json_value_string("version", get_ws_vcs_version_info_short());
1099
1100 sharkd_json_array_open("nstat");
1101 i = 0;
1102 stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i);
1103 sharkd_json_array_close();
1104
1105 sharkd_json_array_open("convs");
1106 i = 0;
1107 conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
1108 sharkd_json_array_close();
1109
1110 sharkd_json_array_open("seqa");
1111 i = 0;
1112 sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i);
1113 sharkd_json_array_close();
1114
1115 sharkd_json_array_open("taps");
1116 {
1117 json_dumper_begin_object(&dumper);
1118 sharkd_json_value_string("name", "UDP Multicast Streams");
1119 sharkd_json_value_string("tap", "multicast");
1120 json_dumper_end_object(&dumper);
1121
1122 json_dumper_begin_object(&dumper);
1123 sharkd_json_value_string("name", "RTP streams");
1124 sharkd_json_value_string("tap", "rtp-streams");
1125 json_dumper_end_object(&dumper);
1126
1127 json_dumper_begin_object(&dumper);
1128 sharkd_json_value_string("name", "Protocol Hierarchy Statistics");
1129 sharkd_json_value_string("tap", "phs");
1130 json_dumper_end_object(&dumper);
1131
1132 json_dumper_begin_object(&dumper);
1133 sharkd_json_value_string("name", "VoIP Calls");
1134 sharkd_json_value_string("tap", "voip-calls");
1135 json_dumper_end_object(&dumper);
1136
1137 json_dumper_begin_object(&dumper);
1138 sharkd_json_value_string("name", "VoIP Conversations");
1139 sharkd_json_value_string("tap", "voip-convs");
1140 json_dumper_end_object(&dumper);
1141
1142 json_dumper_begin_object(&dumper);
1143 sharkd_json_value_string("name", "Expert Information");
1144 sharkd_json_value_string("tap", "expert");
1145 json_dumper_end_object(&dumper);
1146 }
1147 sharkd_json_array_close();
1148
1149 sharkd_json_array_open("eo");
1150 i = 0;
1151 eo_iterate_tables(sharkd_export_object_visit_cb, &i);
1152 sharkd_json_array_close();
1153
1154 sharkd_json_array_open("srt");
1155 i = 0;
1156 srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
1157 sharkd_json_array_close();
1158
1159 sharkd_json_array_open("rtd");
1160 i = 0;
1161 rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
1162 sharkd_json_array_close();
1163
1164 sharkd_json_array_open("follow");
1165 i = 0;
1166 follow_iterate_followers(sharkd_follower_visit_cb, &i);
1167 sharkd_json_array_close();
1168
1169 sharkd_json_result_epilogue();
1170}
1171
1172static void sharkd_session_print_field(header_field_info* current_header_field_info, gboolean as_object)
1173{
1174 if (as_object)
1175 {
1176 sharkd_json_object_open(NULL((void*)0));
1177 }
1178
1179 sharkd_json_value_stringf("id", "%i", current_header_field_info->id);
1180 sharkd_json_value_stringf("parent_id", "%i", current_header_field_info->parent);
1181 sharkd_json_value_string("name", current_header_field_info->abbrev);
1182 sharkd_json_value_string("display_name", current_header_field_info->name);
1183 sharkd_json_value_string("type", ftype_name(current_header_field_info->type));
1184
1185 if (as_object)
1186 {
1187 sharkd_json_object_close();
1188 }
1189}
1190
1191static void
1192sharkd_session_print_fields(void)
1193{
1194 void* proto_cookie = NULL((void*)0);
1195 void* field_cookie = NULL((void*)0);
1196 int protocol_id = -1;
1197
1198 for (protocol_id = proto_get_first_protocol(&proto_cookie); protocol_id != -1; protocol_id = proto_get_next_protocol(&proto_cookie))
1199 {
1200 protocol_t* protocol = find_protocol_by_id(protocol_id);
1201 if (!proto_is_protocol_enabled(protocol))
1202 {
1203 continue;
1204 }
1205
1206 header_field_info* current_header_field_info = proto_registrar_get_nth(proto_get_id(protocol));
1207
1208 sharkd_session_print_field(current_header_field_info, TRUE(!(0)));
1209
1210 for (current_header_field_info = proto_get_first_protocol_field(protocol_id, &field_cookie); current_header_field_info != NULL((void*)0); current_header_field_info = proto_get_next_protocol_field(protocol_id, &field_cookie))
1211 {
1212 if (current_header_field_info->same_name_prev_id != -1)
1213 {
1214 continue;
1215 }
1216
1217 sharkd_session_print_field(current_header_field_info, TRUE(!(0)));
1218 }
1219 }
1220}
1221
1222/**
1223 * sharkd_session_process_fields()
1224 *
1225 * Process fields request
1226 *
1227 * Output object with attributes:
1228 * (m) fields - all fields with their id, name, display_name, type and id of their parent
1229 */
1230static void
1231sharkd_session_process_fields(void)
1232{
1233 sharkd_json_result_prologue(rpcid);
1234
1235 sharkd_json_array_open("fields");
1236 sharkd_session_print_fields();
1237 sharkd_json_array_close();
1238
1239 sharkd_json_result_epilogue();
1240}
1241
1242/**
1243 * sharkd_session_process_field()
1244 *
1245 * Process field request
1246 *
1247 * Input:
1248 * (m) name - (filter) name of the field
1249 *
1250 * Output object with attributes:
1251 * (m) id - id of the field
1252 * (m) parent_id - id of the field's parent
1253 * (m) name - name of the field
1254 * (m) display_name - display_name of the field
1255 * (m) type - type of the field
1256 */
1257static void
1258sharkd_session_process_field(const char* buf, const jsmntok_t* tokens, int count)
1259{
1260 const char* tok_name = json_find_attr(buf, tokens, count, "name");
1261
1262 sharkd_json_result_prologue(rpcid);
1263
1264 if (tok_name)
1265 {
1266 header_field_info* current_header_field_info = proto_registrar_get_byname(tok_name);
1267 if (current_header_field_info == NULL((void*)0))
1268 {
1269 sharkd_json_error(
1270 rpcid, -32602, NULL((void*)0),
1271 "Unknown field name"
1272 );
1273 return;
1274 }
1275
1276 sharkd_session_print_field(current_header_field_info, FALSE(0));
1277 }
1278
1279 sharkd_json_result_epilogue();
1280}
1281
1282/**
1283 * sharkd_session_process_load()
1284 *
1285 * Process load request
1286 *
1287 * Input:
1288 * (m) file - file to be loaded
1289 *
1290 * Output object with attributes:
1291 * (m) err - error code
1292 */
1293static void
1294sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
1295{
1296 const char *tok_file = json_find_attr(buf, tokens, count, "file");
1297 const char *tok_max_packets = json_find_attr(buf, tokens, count, "max_packets");
1298 const char *tok_max_bytes = json_find_attr(buf, tokens, count, "max_bytes");
1299 int err = 0;
1300
1301 uint32_t max_packets = 0; /* 0 means unlimited */
1302 uint64_t max_bytes = 0; /* 0 means unlimited */
1303
1304 if (!tok_file)
1305 return;
1306
1307 /* Parse optional max_packets parameter */
1308 if (tok_max_packets)
1309 {
1310 if (!ws_strtou32(tok_max_packets, NULL((void*)0), &max_packets))
1311 {
1312 sharkd_json_error(
1313 rpcid, -32602, NULL((void*)0),
1314 "Invalid max_packets parameter"
1315 );
1316 return;
1317 }
1318 }
1319
1320 /* Parse optional max_bytes parameter */
1321 if (tok_max_bytes)
1322 {
1323 if (!ws_strtou64(tok_max_bytes, NULL((void*)0), &max_bytes))
1324 {
1325 sharkd_json_error(
1326 rpcid, -32602, NULL((void*)0),
1327 "Invalid max_bytes parameter"
1328 );
1329 return;
1330 }
1331 }
1332
1333 fprintf(stderrstderr, "load: filename=%s, max_packets=%u, max_bytes=%" PRIu64"l" "u" "\n",
1334 tok_file, max_packets, max_bytes);
1335
1336 if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO0, false0, &err) != CF_OK)
1337 {
1338 sharkd_json_error(
1339 rpcid, -2001, NULL((void*)0),
1340 "Unable to open the file"
1341 );
1342 return;
1343 }
1344
1345 TRY{ except_t *volatile exc; volatile int except_state = 0; static
const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode
except_sn; struct except_catch except_ch; except_setup_try(&
except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch
.except_jmp)) *(&exc) = &except_ch.except_obj; else *
(&exc) = 0; if(except_state & 1) except_state |= 2; except_state
&= ~1; if (except_state == 0 && exc == 0)
1346 {
1347 if (max_packets > 0 || max_bytes > 0)
1348 {
1349 err = sharkd_load_cap_file_with_limits((int)max_packets, (int64_t)max_bytes);
1350 }
1351 else
1352 {
1353 err = sharkd_load_cap_file();
1354 }
1355 }
1356 CATCH(OutOfMemoryError)if (except_state == 0 && exc != 0 && exc->
except_id.except_code == (8) && (except_state |= 1))
1357 {
1358 sharkd_json_error(
1359 rpcid, -32603, NULL((void*)0),
1360 "Load failed, out of memory"
1361 );
1362 fprintf(stderrstderr, "load: OutOfMemoryError\n");
1363 err = ENOMEM12;
1364 }
1365 ENDTRYif(!(except_state&1) && exc != 0) except_rethrow(
exc); except_free(except_ch.except_obj.except_dyndata); except_pop
(); };}
;
1366
1367 if (err == 0)
1368 {
1369 sharkd_json_simple_ok(rpcid);
1370 }
1371 else
1372 {
1373 sharkd_json_result_prologue(rpcid);
1374 sharkd_json_value_string("status", wtap_strerror(err));
1375 sharkd_json_value_anyf("err", "%d", err);
1376 sharkd_json_result_epilogue();
1377 }
1378
1379}
1380
1381/**
1382 * sharkd_session_process_status()
1383 *
1384 * Process status request
1385 *
1386 * Output object with attributes:
1387 * (m) frames - count of currently loaded frames
1388 * (m) duration - time difference between time of first frame, and last loaded frame
1389 * (o) filename - capture filename
1390 * (o) filesize - capture filesize
1391 * (o) columns - array of column titles
1392 * (o) column_info - array of column infos, array of object with attributes:
1393 * 'title' - column title
1394 * 'format' - column format (%x or %Cus:<expr>:<occurrence> if COL_CUSTOM)
1395 * 'visible' - true if column is visible
1396 * 'display' - column display format; 'U', 'R' or 'D'
1397 */
1398static void
1399sharkd_session_process_status(void)
1400{
1401 sharkd_json_result_prologue(rpcid);
1402
1403 sharkd_json_value_anyf("frames", "%u", cfile.count);
1404 sharkd_json_value_anyf("duration", "%.9f", nstime_to_sec(&cfile.elapsed_time));
1405
1406 if (cfile.filename)
1407 {
1408 char *name = g_path_get_basename(cfile.filename);
1409
1410 sharkd_json_value_string("filename", name);
1411 g_free(name);
1412 }
1413
1414 if (cfile.provider.wth)
1415 {
1416 int64_t file_size = wtap_file_size(cfile.provider.wth, NULL((void*)0));
1417
1418 if (file_size > 0)
1419 sharkd_json_value_anyf("filesize", "%" PRId64"l" "d", file_size);
1420 }
1421
1422 if (cfile.cinfo.num_cols > 0)
1423 {
1424 sharkd_json_array_open("columns");
1425 for (int i = 0; i < cfile.cinfo.num_cols; ++i)
1426 {
1427 sharkd_json_value_string(NULL((void*)0), get_column_title(i));
1428 }
1429 sharkd_json_array_close();
1430
1431 sharkd_json_array_open("column_info");
1432 for (int i = 0; i < cfile.cinfo.num_cols; ++i)
1433 {
1434 int fmt = get_column_format(i);
1435 sharkd_json_object_open(NULL((void*)0));
1436 sharkd_json_value_string("title", get_column_title(i));
1437 if (fmt != COL_CUSTOM)
1438 {
1439 sharkd_json_value_string("format", col_format_to_string(fmt));
1440 } else {
1441 sharkd_json_value_stringf("format", "%s:%s:%d", col_format_to_string(fmt), get_column_custom_fields(i), get_column_custom_occurrence(i));
1442 }
1443 sharkd_json_value_anyf("visible", get_column_visible(i) ? "true" : "false");
1444 sharkd_json_value_stringf("display", "%c", get_column_display_format(i));
1445 sharkd_json_object_close();
1446 }
1447 sharkd_json_array_close();
1448 }
1449
1450 sharkd_json_result_epilogue();
1451}
1452
1453struct sharkd_analyse_data
1454{
1455 GHashTable *protocols_set;
1456 nstime_t *first_time;
1457 nstime_t *last_time;
1458};
1459
1460static void
1461sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree _U___attribute__((unused)),
1462 struct epan_column_info *cinfo _U___attribute__((unused)), const GSList *data_src _U___attribute__((unused)), void *data)
1463{
1464 struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
1465 packet_info *pi = &edt->pi;
1466 frame_data *fdata = pi->fd;
1467
1468 if (analyser->first_time == NULL((void*)0) || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
1469 analyser->first_time = &fdata->abs_ts;
1470
1471 if (analyser->last_time == NULL((void*)0) || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
1472 analyser->last_time = &fdata->abs_ts;
1473
1474 if (pi->layers)
1475 {
1476 wmem_list_frame_t *frame;
1477
1478 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
1479 {
1480 int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame))((guint) (gulong) (wmem_list_frame_data(frame)));
1481
1482 if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id)((gpointer) (gulong) (proto_id)), NULL((void*)0), NULL((void*)0)))
1483 {
1484 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id)((gpointer) (gulong) (proto_id)), GUINT_TO_POINTER(proto_id)((gpointer) (gulong) (proto_id)));
1485 sharkd_json_value_string(NULL((void*)0), proto_get_protocol_filter_name(proto_id));
1486 }
1487 }
1488 }
1489
1490}
1491
1492/**
1493 * sharkd_session_process_status()
1494 *
1495 * Process analyse request
1496 *
1497 * Output object with attributes:
1498 * (m) frames - count of currently loaded frames
1499 * (m) protocols - protocol list
1500 * (m) first - earliest frame time
1501 * (m) last - latest frame time
1502 */
1503static void
1504sharkd_session_process_analyse(void)
1505{
1506 struct sharkd_analyse_data analyser;
1507 wtap_rec rec; /* Record information */
1508
1509 analyser.first_time = NULL((void*)0);
1510 analyser.last_time = NULL((void*)0);
1511 analyser.protocols_set = g_hash_table_new(NULL((void*)0) /* g_direct_hash() */, NULL((void*)0) /* g_direct_equal */);
1512
1513 sharkd_json_result_prologue(rpcid);
1514
1515 sharkd_json_value_anyf("frames", "%u", cfile.count);
1516
1517 sharkd_json_array_open("protocols");
1518
1519 wtap_rec_init(&rec, 1514);
1520
1521 for (uint32_t framenum = 1; framenum <= cfile.count; framenum++)
1522 {
1523 enum dissect_request_status status;
1524 int err;
1525 char *err_info;
1526
1527 status = sharkd_dissect_request(framenum,
1528 (framenum != 1) ? 1 : 0, framenum - 1,
1529 &rec, NULL((void*)0), SHARKD_DISSECT_FLAG_NULL0x00u,
1530 &sharkd_session_process_analyse_cb, &analyser,
1531 &err, &err_info);
1532 switch (status) {
1533
1534 case DISSECT_REQUEST_SUCCESS:
1535 break;
1536
1537 case DISSECT_REQUEST_NO_SUCH_FRAME:
1538 /* XXX - report the error. */
1539 break;
1540
1541 case DISSECT_REQUEST_READ_ERROR:
1542 /*
1543 * Free up the error string.
1544 * XXX - report the error.
1545 */
1546 g_free(err_info);
1547 break;
1548 }
1549 }
1550
1551 sharkd_json_array_close();
1552
1553 if (analyser.first_time)
1554 sharkd_json_value_anyf("first", "%.9f", nstime_to_sec(analyser.first_time));
1555
1556 if (analyser.last_time)
1557 sharkd_json_value_anyf("last", "%.9f", nstime_to_sec(analyser.last_time));
1558
1559 sharkd_json_result_epilogue();
1560
1561 wtap_rec_cleanup(&rec);
1562
1563 g_hash_table_destroy(analyser.protocols_set);
1564}
1565
1566static column_info *
1567sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count)
1568{
1569 const char *columns_custom[32];
1570 uint16_t columns_fmt[32];
1571 int16_t columns_occur[32];
1572
1573 int i, cols;
1574
1575 for (i = 0; i < 32; i++)
1576 {
1577 const char *tok_column;
1578 char tok_column_name[64];
1579 char *custom_sepa;
1580
1581 snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i);
1582 tok_column = json_find_attr(buf, tokens, count, tok_column_name);
1583 if (tok_column == NULL((void*)0))
1584 break;
1585
1586 columns_custom[i] = NULL((void*)0);
1587 columns_occur[i] = 0;
1588
1589 if ((custom_sepa = strchr(tok_column, ':')))
1590 {
1591 *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */
1592
1593 columns_fmt[i] = COL_CUSTOM;
1594 columns_custom[i] = tok_column;
1595
1596 if (!ws_strtoi16(custom_sepa + 1, NULL((void*)0), &columns_occur[i]))
1597 return NULL((void*)0);
1598 }
1599 else
1600 {
1601 if (!ws_strtou16(tok_column, NULL((void*)0), &columns_fmt[i]))
1602 return NULL((void*)0);
1603
1604 if (columns_fmt[i] >= NUM_COL_FMTS)
1605 return NULL((void*)0);
1606
1607 /* if custom, that it shouldn't be just custom number -> error */
1608 if (columns_fmt[i] == COL_CUSTOM)
1609 return NULL((void*)0);
1610 }
1611 }
1612
1613 cols = i;
1614
1615 col_setup(cinfo, cols);
1616
1617 for (i = 0; i < cols; i++)
1618 {
1619 col_item_t *col_item = &cinfo->columns[i];
1620
1621 col_item->col_fmt = columns_fmt[i];
1622 col_item->col_title = NULL((void*)0); /* no need for title */
1623
1624 if (col_item->col_fmt == COL_CUSTOM)
1625 {
1626 col_item->col_custom_fields = g_strdup(columns_custom[i])g_strdup_inline (columns_custom[i]);
1627 col_item->col_custom_occurrence = columns_occur[i];
1628 }
1629
1630 col_item->col_fence = 0;
1631 }
1632
1633 col_finalize(cinfo);
1634
1635 return cinfo;
1636}
1637
1638static void
1639sharkd_session_process_frames_cb(epan_dissect_t *edt, proto_tree *tree _U___attribute__((unused)),
1640 struct epan_column_info *cinfo, const GSList *data_src _U___attribute__((unused)), void *data _U___attribute__((unused)))
1641{
1642 packet_info *pi = &edt->pi;
1643 frame_data *fdata = pi->fd;
1644 wtap_block_t pkt_block = NULL((void*)0);
1645 unsigned int i;
1646 char *comment = NULL((void*)0);
1647
1648 json_dumper_begin_object(&dumper);
1649
1650 sharkd_json_array_open("c");
1651 for (int col = 0; col < cinfo->num_cols; ++col)
1652 {
1653 sharkd_json_value_string(NULL((void*)0), get_column_text(cinfo, col));
1654 }
1655 sharkd_json_array_close();
1656
1657 sharkd_json_value_anyf("num", "%u", pi->num);
1658
1659 /*
1660 * Get the block for this record, if it has one.
1661 */
1662 pkt_block = sharkd_get_packet_block(fdata);
1663
1664 /*
1665 * Does this record have any comments?
1666 */
1667 if (pkt_block != NULL((void*)0) &&
1668 WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT1, 0, &comment))
1669 {
1670 sharkd_json_value_anyf("ct", "true");
1671
1672 sharkd_json_array_open("comments");
1673 for (i = 0; wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT1, i, &comment) == WTAP_OPTTYPE_SUCCESS; i++) {
1674 sharkd_json_value_string(NULL((void*)0), comment);
1675 }
1676 sharkd_json_array_close();
1677 }
1678
1679 if (fdata->ignored)
1680 sharkd_json_value_anyf("i", "true");
1681
1682 if (fdata->marked)
1683 sharkd_json_value_anyf("m", "true");
1684
1685 if (fdata->color_filter)
1686 {
1687 sharkd_json_value_stringf("bg", "%06x", color_t_to_rgb(&fdata->color_filter->bg_color));
1688 sharkd_json_value_stringf("fg", "%06x", color_t_to_rgb(&fdata->color_filter->fg_color));
1689 }
1690
1691 wtap_block_unref(pkt_block);
1692 json_dumper_end_object(&dumper);
1693}
1694
1695/**
1696 * sharkd_session_process_frames()
1697 *
1698 * Process frames request
1699 *
1700 * Input:
1701 * (o) column0...columnXX - requested columns either number in range [0..NUM_COL_FMTS), or custom (syntax <dfilter>:<occurrence>).
1702 * If column0 is not specified default column set will be used.
1703 * (o) filter - filter to be used
1704 * (o) skip=N - skip N frames
1705 * (o) limit=N - show only N frames
1706 * (o) refs - list (comma separated) with sorted time reference frame numbers.
1707 *
1708 * Output array of frames with attributes:
1709 * (m) c - array of column data
1710 * (m) num - frame number
1711 * (o) i - if frame is ignored
1712 * (o) m - if frame is marked
1713 * (o) ct - if frame is commented
1714 * (o) comments - array of comment strings
1715 * (o) bg - color filter - background color in hex
1716 * (o) fg - color filter - foreground color in hex
1717 */
1718static void
1719sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
1720{
1721 const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
1722 const char *tok_column = json_find_attr(buf, tokens, count, "column0");
1723 const char *tok_skip = json_find_attr(buf, tokens, count, "skip");
1724 const char *tok_limit = json_find_attr(buf, tokens, count, "limit");
1725 const char *tok_refs = json_find_attr(buf, tokens, count, "refs");
1726
1727 const uint8_t *filter_data = NULL((void*)0);
1728
1729 uint32_t prev_dis_num = 0;
1730 uint32_t current_ref_frame = 0, next_ref_frame = UINT32_MAX(4294967295U);
1731 uint32_t skip;
1732 uint32_t limit;
1733
1734 wtap_rec rec; /* Record information */
1735 column_info *cinfo = &cfile.cinfo;
1736 column_info user_cinfo;
1737
1738 if (tok_column)
1739 {
1740 memset(&user_cinfo, 0, sizeof(user_cinfo));
1741 cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count);
1742 if (!cinfo)
1743 {
1744 sharkd_json_error(
1745 rpcid, -13001, NULL((void*)0),
1746 "Column definition invalid - note column 6 requires a custom definition"
1747 );
1748 return;
1749 }
1750 }
1751
1752 if (tok_filter)
1753 {
1754 const struct sharkd_filter_item *filter_item;
1755
1756 filter_item = sharkd_session_filter_data(tok_filter);
1757 if (!filter_item)
1758 {
1759 sharkd_json_error(
1760 rpcid, -13002, NULL((void*)0),
1761 "Filter expression invalid"
1762 );
1763 return;
1764 }
1765
1766 filter_data = filter_item->filtered;
1767 }
1768
1769 skip = 0;
1770 if (tok_skip)
1771 {
1772 if (!ws_strtou32(tok_skip, NULL((void*)0), &skip))
1773 return;
1774 }
1775
1776 limit = 0;
1777 if (tok_limit)
1778 {
1779 if (!ws_strtou32(tok_limit, NULL((void*)0), &limit))
1780 return;
1781 }
1782
1783 if (tok_refs)
1784 {
1785 if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame))
1786 return;
1787 }
1788
1789 sharkd_json_result_array_prologue(rpcid);
1790
1791 wtap_rec_init(&rec, 1514);
1792
1793 for (uint32_t framenum = 1; framenum <= cfile.count; framenum++)
1794 {
1795 frame_data *fdata;
1796 uint32_t ref_frame = (framenum != 1) ? 1 : 0;
1797 enum dissect_request_status status;
1798 int err;
1799 char *err_info;
1800
1801 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
1802 continue;
1803
1804 if (skip)
1805 {
1806 skip--;
1807 prev_dis_num = framenum;
1808 continue;
1809 }
1810
1811 if (tok_refs)
1812 {
1813 if (framenum >= next_ref_frame)
1814 {
1815 current_ref_frame = next_ref_frame;
1816
1817 if (*tok_refs != ',')
1818 next_ref_frame = UINT32_MAX(4294967295U);
1819
1820 while (*tok_refs == ',' && framenum >= next_ref_frame)
1821 {
1822 current_ref_frame = next_ref_frame;
1823
1824 if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame))
1825 {
1826 fprintf(stderrstderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs);
1827 break;
1828 }
1829 }
1830
1831 if (*tok_refs == '\0' && framenum >= next_ref_frame)
1832 {
1833 current_ref_frame = next_ref_frame;
1834 next_ref_frame = UINT32_MAX(4294967295U);
1835 }
1836 }
1837
1838 if (current_ref_frame)
1839 ref_frame = current_ref_frame;
1840 }
1841
1842 fdata = sharkd_get_frame(framenum);
1843 status = sharkd_dissect_request(framenum,
1844 ref_frame, prev_dis_num,
1845 &rec, cinfo,
1846 (fdata->color_filter == NULL((void*)0)) ? SHARKD_DISSECT_FLAG_COLOR0x08u : SHARKD_DISSECT_FLAG_NULL0x00u,
1847 &sharkd_session_process_frames_cb, NULL((void*)0),
1848 &err, &err_info);
1849 switch (status) {
1850
1851 case DISSECT_REQUEST_SUCCESS:
1852 break;
1853
1854 case DISSECT_REQUEST_NO_SUCH_FRAME:
1855 /* XXX - report the error. */
1856 break;
1857
1858 case DISSECT_REQUEST_READ_ERROR:
1859 /*
1860 * Free up the error string.
1861 * XXX - report the error.
1862 */
1863 g_free(err_info);
1864 break;
1865 }
1866
1867 prev_dis_num = framenum;
1868
1869 if (limit && --limit == 0)
1870 break;
1871 }
1872 sharkd_json_result_array_epilogue();
1873
1874 if (cinfo != &cfile.cinfo)
1875 col_cleanup(cinfo);
1876
1877 wtap_rec_cleanup(&rec);
1878}
1879
1880static void
1881// NOLINTNEXTLINE(misc-no-recursion)
1882sharkd_session_process_tap_stats_node_cb(const char *key, const stat_node *n)
1883{
1884 stat_node *node;
1885
1886 sharkd_json_array_open(key);
1887 for (node = n->children; node; node = node->next)
1888 {
1889 json_dumper_begin_object(&dumper);
1890
1891 /* code based on stats_tree_get_values_from_node() */
1892 sharkd_json_value_string("name", node->name);
1893 sharkd_json_value_anyf("count", "%d", node->counter);
1894 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE0x10000000) || node->rng))
1895 {
1896 switch(node->datatype)
1897 {
1898 case STAT_DT_INT:
1899 sharkd_json_value_anyf("avg", "%.2f", ((float)node->total.int_total) / node->counter);
1900 sharkd_json_value_anyf("min", "%d", node->minvalue.int_min);
1901 sharkd_json_value_anyf("max", "%d", node->maxvalue.int_max);
1902 break;
1903 case STAT_DT_FLOAT:
1904 sharkd_json_value_anyf("avg", "%.2f", node->total.float_total / node->counter);
1905 sharkd_json_value_anyf("min", "%f", node->minvalue.float_min);
1906 sharkd_json_value_anyf("max", "%f", node->maxvalue.float_max);
1907 break;
1908 }
1909 }
1910
1911 if (node->st->elapsed)
1912 sharkd_json_value_anyf("rate", "%.4f", ((float)node->counter) / node->st->elapsed);
1913
1914 if (node->parent && node->parent->counter)
1915 sharkd_json_value_anyf("perc", "%.2f", (node->counter * 100.0) / node->parent->counter);
1916 else if (node->parent == &(node->st->root))
1917 sharkd_json_value_anyf("perc", "100");
1918
1919 if (prefs.st_enable_burstinfo && node->max_burst)
1920 {
1921 if (prefs.st_burst_showcount)
1922 sharkd_json_value_anyf("burstcount", "%d", node->max_burst);
1923 else
1924 sharkd_json_value_anyf("burstrate", "%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
1925
1926 sharkd_json_value_anyf("bursttime", "%.3f", (node->burst_time / 1000.0));
1927 }
1928
1929 if (node->children)
1930 {
1931 // We recurse here but our depth is limited
1932 sharkd_session_process_tap_stats_node_cb("sub", node);
1933 }
1934 json_dumper_end_object(&dumper);
1935 }
1936 sharkd_json_array_close();
1937}
1938
1939/**
1940 * sharkd_session_process_tap_stats_cb()
1941 *
1942 * Output stats tap:
1943 *
1944 * (m) tap - tap name
1945 * (m) type:stats - tap output type
1946 * (m) name - stat name
1947 * (m) stats - array of object with attributes:
1948 * (m) name - stat item name
1949 * (m) count - stat item counter
1950 * (o) avg - stat item averange value
1951 * (o) min - stat item min value
1952 * (o) max - stat item max value
1953 * (o) rate - stat item rate value (ms)
1954 * (o) perc - stat item percentage
1955 * (o) burstrate - stat item burst rate
1956 * (o) burstcount - stat item burst count
1957 * (o) burstttme - stat item burst start
1958 * (o) sub - array of object with attributes like in stats node.
1959 */
1960static void
1961sharkd_session_process_tap_stats_cb(void *psp)
1962{
1963 stats_tree *st = (stats_tree *) psp;
1964
1965 json_dumper_begin_object(&dumper);
1966
1967 sharkd_json_value_stringf("tap", "stats:%s", st->cfg->abbr);
1968 sharkd_json_value_string("type", "stats");
1969 sharkd_json_value_string("name", st->cfg->path);
1970
1971 sharkd_session_process_tap_stats_node_cb("stats", &st->root);
1972
1973 json_dumper_end_object(&dumper);
1974}
1975
1976static void
1977sharkd_session_free_tap_stats_cb(void *psp)
1978{
1979 stats_tree *st = (stats_tree *) psp;
1980
1981 stats_tree_free(st);
1982}
1983
1984struct sharkd_expert_tap
1985{
1986 GSList *details;
1987 GStringChunk *text;
1988};
1989
1990/**
1991 * sharkd_session_process_tap_expert_cb()
1992 *
1993 * Output expert tap:
1994 *
1995 * (m) tap - tap name
1996 * (m) type:expert - tap output type
1997 * (m) details - array of object with attributes:
1998 * (m) f - frame number, which generated expert information
1999 * (o) s - severity
2000 * (o) g - group
2001 * (m) m - expert message
2002 * (o) p - protocol
2003 */
2004static void
2005sharkd_session_process_tap_expert_cb(void *tapdata)
2006{
2007 struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
2008 GSList *list;
2009
2010 json_dumper_begin_object(&dumper);
2011
2012 sharkd_json_value_string("tap", "expert");
2013 sharkd_json_value_string("type", "expert");
2014
2015 sharkd_json_array_open("details");
2016 for (list = etd->details; list; list = list->next)
2017 {
2018 expert_info_t *ei = (expert_info_t *) list->data;
2019 const char *tmp;
2020
2021 json_dumper_begin_object(&dumper);
2022
2023 sharkd_json_value_anyf("f", "%u", ei->packet_num);
2024
2025 tmp = try_val_to_str(ei->severity, expert_severity_vals);
2026 if (tmp)
2027 sharkd_json_value_string("s", tmp);
2028
2029 tmp = try_val_to_str(ei->group, expert_group_vals);
2030 if (tmp)
2031 sharkd_json_value_string("g", tmp);
2032
2033 sharkd_json_value_string("m", ei->summary);
2034
2035 if (ei->protocol)
2036 sharkd_json_value_string("p", ei->protocol);
2037
2038 json_dumper_end_object(&dumper);
2039 }
2040 sharkd_json_array_close();
2041
2042 json_dumper_end_object(&dumper);
2043}
2044
2045static tap_packet_status
2046sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U___attribute__((unused)), epan_dissect_t *edt _U___attribute__((unused)), const void *pointer, tap_flags_t flags _U___attribute__((unused)))
2047{
2048 struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
2049 const expert_info_t *ei = (const expert_info_t *) pointer;
2050 expert_info_t *ei_copy;
2051
2052 if (ei == NULL((void*)0))
2053 return TAP_PACKET_DONT_REDRAW;
2054
2055 ei_copy = g_new(expert_info_t, 1)((expert_info_t *) g_malloc_n ((1), sizeof (expert_info_t)));
2056 /* Note: this is a shallow copy */
2057 *ei_copy = *ei;
2058
2059 /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */
2060 ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol);
2061 ei_copy->summary = g_string_chunk_insert_const(etd->text, ei_copy->summary);
2062
2063 etd->details = g_slist_prepend(etd->details, ei_copy);
2064
2065 return TAP_PACKET_REDRAW;
2066}
2067
2068static void
2069sharkd_session_free_tap_expert_cb(void *tapdata)
2070{
2071 struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
2072
2073 g_slist_free_full(etd->details, g_free);
2074 g_string_chunk_free(etd->text);
2075 g_free(etd);
2076}
2077
2078/**
2079 * sharkd_session_process_tap_flow_cb()
2080 *
2081 * Output flow tap:
2082 * (m) tap - tap name
2083 * (m) type:flow - tap output type
2084 * (m) nodes - array of strings with node address
2085 * (m) flows - array of object with attributes:
2086 * (m) t - frame time string
2087 * (m) n - array of two numbers with source node index and destination node index
2088 * (m) pn - array of two numbers with source and destination port
2089 * (o) c - comment
2090 */
2091static void
2092sharkd_session_process_tap_flow_cb(void *tapdata)
2093{
2094 seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
2095 GList *flow_list;
2096 unsigned i;
2097
2098 sequence_analysis_get_nodes(graph_analysis);
2099
2100 json_dumper_begin_object(&dumper);
2101 sharkd_json_value_stringf("tap", "seqa:%s", graph_analysis->name);
2102 sharkd_json_value_string("type", "flow");
2103
2104 sharkd_json_array_open("nodes");
2105 for (i = 0; i < graph_analysis->num_nodes; i++)
2106 {
2107 char *addr_str;
2108
2109 addr_str = address_to_display(NULL((void*)0), &(graph_analysis->nodes[i]));
2110 sharkd_json_value_string(NULL((void*)0), addr_str);
2111 wmem_free(NULL((void*)0), addr_str);
2112 }
2113 sharkd_json_array_close();
2114
2115 sharkd_json_array_open("flows");
2116 flow_list = g_queue_peek_nth_link(graph_analysis->items, 0);
2117 while (flow_list)
2118 {
2119 seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data;
2120
2121 flow_list = g_list_next(flow_list)((flow_list) ? (((GList *)(flow_list))->next) : ((void*)0)
)
;
2122
2123 if (!sai->display)
2124 continue;
2125
2126 json_dumper_begin_object(&dumper);
2127
2128 sharkd_json_value_string("t", sai->time_str);
2129 sharkd_json_value_anyf("n", "[%u,%u]", sai->src_node, sai->dst_node);
2130 sharkd_json_value_anyf("pn", "[%u,%u]", sai->port_src, sai->port_dst);
2131
2132 if (sai->comment)
2133 sharkd_json_value_string("c", sai->comment);
2134
2135 json_dumper_end_object(&dumper);
2136 }
2137 sharkd_json_array_close();
2138
2139 json_dumper_end_object(&dumper);
2140}
2141
2142static void
2143sharkd_session_free_tap_flow_cb(void *tapdata)
2144{
2145 seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
2146
2147 sequence_analysis_info_free(graph_analysis);
2148}
2149
2150struct sharkd_conv_tap_data
2151{
2152 const char *type;
2153 conv_hash_t hash;
2154 bool_Bool resolve_name;
2155 bool_Bool resolve_port;
2156};
2157
2158static bool_Bool
2159sharkd_session_geoip_addr(address *addr, const char *suffix)
2160{
2161 const mmdb_lookup_t *lookup = NULL((void*)0);
2162 bool_Bool with_geoip = false0;
2163 char json_key[64];
2164
2165 if (addr->type == AT_IPv4)
2166 {
2167 const ws_in4_addr *ip4 = (const ws_in4_addr *) addr->data;
2168
2169 lookup = maxmind_db_lookup_ipv4(ip4);
2170 }
2171 else if (addr->type == AT_IPv6)
2172 {
2173 const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data;
2174
2175 lookup = maxmind_db_lookup_ipv6(ip6);
2176 }
2177
2178 if (!lookup || !lookup->found)
2179 return false0;
2180
2181 if (lookup->country)
2182 {
2183 snprintf(json_key, sizeof(json_key), "geoip_country%s", suffix);
2184 sharkd_json_value_string(json_key, lookup->country);
2185 with_geoip = true1;
2186 }
2187
2188 if (lookup->country_iso)
2189 {
2190 snprintf(json_key, sizeof(json_key), "geoip_country_iso%s", suffix);
2191 sharkd_json_value_string(json_key, lookup->country_iso);
2192 with_geoip = true1;
2193 }
2194
2195 if (lookup->city)
2196 {
2197 snprintf(json_key, sizeof(json_key), "geoip_city%s", suffix);
2198 sharkd_json_value_string(json_key, lookup->city);
2199 with_geoip = true1;
2200 }
2201
2202 if (lookup->as_org)
2203 {
2204 snprintf(json_key, sizeof(json_key), "geoip_as_org%s", suffix);
2205 sharkd_json_value_string(json_key, lookup->as_org);
2206 with_geoip = true1;
2207 }
2208
2209 if (lookup->as_number > 0)
2210 {
2211 snprintf(json_key, sizeof(json_key), "geoip_as%s", suffix);
2212 sharkd_json_value_anyf(json_key, "%u", lookup->as_number);
2213 with_geoip = true1;
2214 }
2215
2216 if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0)
2217 {
2218 snprintf(json_key, sizeof(json_key), "geoip_lat%s", suffix);
2219 sharkd_json_value_anyf(json_key, "%f", lookup->latitude);
2220 with_geoip = true1;
2221 }
2222
2223 if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0)
2224 {
2225 snprintf(json_key, sizeof(json_key), "geoip_lon%s", suffix);
2226 sharkd_json_value_anyf(json_key, "%f", lookup->longitude);
2227 with_geoip = true1;
2228 }
2229
2230 return with_geoip;
2231}
2232
2233struct sharkd_analyse_rtp_items
2234{
2235 uint32_t frame_num;
2236 uint32_t sequence_num;
2237
2238 double delta;
2239 double jitter;
2240 double skew;
2241 double bandwidth;
2242 bool_Bool marker;
2243
2244 double arrive_offset;
2245
2246 /* from tap_rtp_stat_t */
2247 uint32_t flags;
2248 uint16_t pt;
2249};
2250
2251struct sharkd_analyse_rtp
2252{
2253 const char *tap_name;
2254 rtpstream_id_t id;
2255
2256 GSList *packets;
2257 double start_time;
2258 tap_rtp_stat_t statinfo;
2259};
2260
2261static void
2262sharkd_session_process_tap_rtp_free_cb(void *tapdata)
2263{
2264 struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
2265
2266 g_slist_free_full(rtp_req->packets, g_free);
2267 g_free(rtp_req);
2268}
2269
2270static tap_packet_status
2271sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *pointer, tap_flags_t flags _U___attribute__((unused)))
2272{
2273 struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
2274 const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer;
2275
2276 if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info))
2277 {
2278 tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
2279 struct sharkd_analyse_rtp_items *item;
2280
2281 rtppacket_analyse(statinfo, pinfo, rtp_info);
2282
2283 item = g_new(struct sharkd_analyse_rtp_items, 1)((struct sharkd_analyse_rtp_items *) g_malloc_n ((1), sizeof (
struct sharkd_analyse_rtp_items)))
;
2284
2285 if (!rtp_req->packets)
2286 rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
2287
2288 item->frame_num = pinfo->num;
2289 item->sequence_num = rtp_info->info_seq_num;
2290 item->delta = (statinfo->flags & STAT_FLAG_FIRST0x001) ? 0.0 : statinfo->delta;
2291 item->jitter = (statinfo->flags & STAT_FLAG_FIRST0x001) ? 0.0 : statinfo->jitter;
2292 item->skew = (statinfo->flags & STAT_FLAG_FIRST0x001) ? 0.0 : statinfo->skew;
2293 item->bandwidth = statinfo->bandwidth;
2294 item->marker = rtp_info->info_marker_set ? true1 : false0;
2295 item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
2296
2297 item->flags = statinfo->flags;
2298 item->pt = statinfo->pt;
2299
2300 /* XXX, O(n) optimize */
2301 rtp_req->packets = g_slist_append(rtp_req->packets, item);
2302 }
2303
2304 return TAP_PACKET_REDRAW;
2305}
2306
2307/**
2308 * sharkd_session_process_tap_rtp_analyse_cb()
2309 *
2310 * Output rtp analyse tap:
2311 * (m) tap - tap name
2312 * (m) type - tap output type
2313 * (m) ssrc - RTP SSRC
2314 * (m) max_delta - Max delta (ms)
2315 * (m) max_delta_nr - Max delta packet #
2316 * (m) max_jitter - Max jitter (ms)
2317 * (m) mean_jitter - Mean jitter (ms)
2318 * (m) max_skew - Max skew (ms)
2319 * (m) total_nr - Total number of RTP packets
2320 * (m) seq_err - Number of sequence errors
2321 * (m) duration - Duration (ms)
2322 * (m) items - array of object with attributes:
2323 * (m) f - frame number
2324 * (m) o - arrive offset
2325 * (m) sn - sequence number
2326 * (m) d - delta
2327 * (m) j - jitter
2328 * (m) sk - skew
2329 * (m) bw - bandwidth
2330 * (o) s - status string
2331 * (o) t - status type
2332 * (o) mark - rtp mark
2333 */
2334static void
2335sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
2336{
2337 const int RTP_TYPE_CN = 1;
2338 const int RTP_TYPE_ERROR = 2;
2339 const int RTP_TYPE_WARN = 3;
2340 const int RTP_TYPE_PT_EVENT = 4;
2341
2342 const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
2343 const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
2344
2345 GSList *l;
2346
2347 json_dumper_begin_object(&dumper);
2348
2349 sharkd_json_value_string("tap", rtp_req->tap_name);
2350 sharkd_json_value_string("type", "rtp-analyse");
2351 sharkd_json_value_stringf("ssrc", "0x%x", rtp_req->id.ssrc);
2352
2353 sharkd_json_value_anyf("max_delta", "%f", statinfo->max_delta);
2354 sharkd_json_value_anyf("max_delta_nr", "%u", statinfo->max_nr);
2355 sharkd_json_value_anyf("max_jitter", "%f", statinfo->max_jitter);
2356 sharkd_json_value_anyf("mean_jitter", "%f", statinfo->mean_jitter);
2357 sharkd_json_value_anyf("max_skew", "%f", statinfo->max_skew);
2358 sharkd_json_value_anyf("total_nr", "%u", statinfo->total_nr);
2359 sharkd_json_value_anyf("seq_err", "%u", statinfo->sequence);
2360 sharkd_json_value_anyf("duration", "%f", statinfo->time - statinfo->start_time);
2361
2362 sharkd_json_array_open("items");
2363 for (l = rtp_req->packets; l; l = l->next)
2364 {
2365 struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
2366
2367 json_dumper_begin_object(&dumper);
2368
2369 sharkd_json_value_anyf("f", "%u", item->frame_num);
2370 sharkd_json_value_anyf("o", "%.9f", item->arrive_offset);
2371 sharkd_json_value_anyf("sn", "%u", item->sequence_num);
2372 sharkd_json_value_anyf("d", "%.2f", item->delta);
2373 sharkd_json_value_anyf("j", "%.2f", item->jitter);
2374 sharkd_json_value_anyf("sk", "%.2f", item->skew);
2375 sharkd_json_value_anyf("bw", "%.2f", item->bandwidth);
2376
2377 if (item->pt == PT_CN13)
2378 {
2379 sharkd_json_value_string("s", "Comfort noise (PT=13, RFC 3389)");
2380 sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN);
2381 }
2382 else if (item->pt == PT_CN_OLD19)
2383 {
2384 sharkd_json_value_string("s", "Comfort noise (PT=19, reserved)");
2385 sharkd_json_value_anyf("t", "%d", RTP_TYPE_CN);
2386 }
2387 else if (item->flags & STAT_FLAG_WRONG_SEQ0x004)
2388 {
2389 sharkd_json_value_string("s", "Wrong sequence number");
2390 sharkd_json_value_anyf("t", "%d", RTP_TYPE_ERROR);
2391 }
2392 else if (item->flags & STAT_FLAG_DUP_PKT0x200)
2393 {
2394 sharkd_json_value_string("s", "Suspected duplicate (MAC address) only delta time calculated");
2395 sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN);
2396 }
2397 else if (item->flags & STAT_FLAG_REG_PT_CHANGE0x040)
2398 {
2399 sharkd_json_value_stringf("s", "Payload changed to PT=%u%s",
2400 item->pt,
2401 (item->flags & STAT_FLAG_PT_T_EVENT0x100) ? " telephone/event" : "");
2402 sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN);
2403 }
2404 else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP0x080)
2405 {
2406 sharkd_json_value_string("s", "Incorrect timestamp");
2407 sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN);
2408 }
2409 else if ((item->flags & STAT_FLAG_PT_CHANGE0x008)
2410 && !(item->flags & STAT_FLAG_FIRST0x001)
2411 && !(item->flags & STAT_FLAG_PT_CN0x010)
2412 && (item->flags & STAT_FLAG_FOLLOW_PT_CN0x020)
2413 && !(item->flags & STAT_FLAG_MARKER0x002))
2414 {
2415 sharkd_json_value_string("s", "Marker missing?");
2416 sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN);
2417 }
2418 else if (item->flags & STAT_FLAG_PT_T_EVENT0x100)
2419 {
2420 sharkd_json_value_stringf("s", "PT=%u telephone/event", item->pt);
2421 sharkd_json_value_anyf("t", "%d", RTP_TYPE_PT_EVENT);
2422 }
2423 else if (item->flags & STAT_FLAG_MARKER0x002)
2424 {
2425 sharkd_json_value_anyf("t", "%d", RTP_TYPE_WARN);
2426 }
2427
2428 if (item->marker)
2429 sharkd_json_value_anyf("mark", "1");
2430
2431 json_dumper_end_object(&dumper);
2432 }
2433 sharkd_json_array_close();
2434
2435 json_dumper_end_object(&dumper);
2436}
2437
2438/**
2439 * sharkd_session_process_tap_conv_cb()
2440 *
2441 * Output conv tap:
2442 * (m) tap - tap name
2443 * (m) type - tap output type
2444 * (m) proto - protocol short name
2445 * (o) filter - filter string
2446 * (o) geoip - whether GeoIP information is available, boolean
2447 *
2448 * (o) convs - array of object with attributes:
2449 * (m) saddr - source address
2450 * (m) daddr - destination address
2451 * (o) sport - source port
2452 * (o) dport - destination port
2453 * (m) txf - TX frame count
2454 * (m) txb - TX bytes
2455 * (m) rxf - RX frame count
2456 * (m) rxb - RX bytes
2457 * (m) start - (relative) first packet time
2458 * (m) stop - (relative) last packet time
2459 * (o) filter - conversation filter
2460 *
2461 * (o) hosts - array of object with attributes:
2462 * (m) host - host address
2463 * (o) port - host port
2464 * (m) txf - TX frame count
2465 * (m) txb - TX bytes
2466 * (m) rxf - RX frame count
2467 * (m) rxb - RX bytes
2468 */
2469static void
2470sharkd_session_process_tap_conv_cb(void *arg)
2471{
2472 conv_hash_t *hash = (conv_hash_t *) arg;
2473 const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
2474 const char *proto;
2475 int proto_with_port;
2476 unsigned i;
2477
2478 int with_geoip = 0;
2479
2480 json_dumper_begin_object(&dumper);
2481 sharkd_json_value_string("tap", iu->type);
2482
2483 if (!strncmp(iu->type, "conv:", 5))
2484 {
2485 sharkd_json_value_string("type", "conv");
2486 sharkd_json_array_open("convs");
2487 proto = iu->type + 5;
2488 }
2489 else if (!strncmp(iu->type, "endpt:", 6))
2490 {
2491 sharkd_json_value_string("type", "host");
2492 sharkd_json_array_open("hosts");
2493 proto = iu->type + 6;
2494 }
2495 else
2496 {
2497 sharkd_json_value_string("type", "err");
2498 proto = "";
2499 }
2500
2501 proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
2502
2503 if (iu->hash.conv_array != NULL((void*)0) && !strncmp(iu->type, "conv:", 5))
2504 {
2505 for (i = 0; i < iu->hash.conv_array->len; i++)
2506 {
2507 conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i)(((conv_item_t*) (void *) (iu->hash.conv_array)->data) [
(i)])
;
2508 char *src_addr, *dst_addr;
2509 char *src_port, *dst_port;
2510 char *filter_str;
2511
2512 json_dumper_begin_object(&dumper);
2513
2514 sharkd_json_value_string("saddr", (src_addr = get_conversation_address(NULL((void*)0), &iui->src_address, iu->resolve_name)));
2515 sharkd_json_value_string("daddr", (dst_addr = get_conversation_address(NULL((void*)0), &iui->dst_address, iu->resolve_name)));
2516
2517 if (proto_with_port)
2518 {
2519 sharkd_json_value_string("sport", (src_port = get_conversation_port(NULL((void*)0), iui->src_port, iui->ctype, iu->resolve_port)));
2520 sharkd_json_value_string("dport", (dst_port = get_conversation_port(NULL((void*)0), iui->dst_port, iui->ctype, iu->resolve_port)));
2521
2522 wmem_free(NULL((void*)0), src_port);
2523 wmem_free(NULL((void*)0), dst_port);
2524 }
2525
2526 sharkd_json_value_anyf("rxf", "%" PRIu64"l" "u", iui->rx_frames);
2527 sharkd_json_value_anyf("rxb", "%" PRIu64"l" "u", iui->rx_bytes);
2528
2529 sharkd_json_value_anyf("txf", "%" PRIu64"l" "u", iui->tx_frames);
2530 sharkd_json_value_anyf("txb", "%" PRIu64"l" "u", iui->tx_bytes);
2531
2532 sharkd_json_value_anyf("start", "%.9f", nstime_to_sec(&iui->start_time));
2533 sharkd_json_value_anyf("stop", "%.9f", nstime_to_sec(&iui->stop_time));
2534
2535 filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
2536 if (filter_str)
2537 {
2538 sharkd_json_value_string("filter", filter_str);
2539 g_free(filter_str);
2540 }
2541
2542 wmem_free(NULL((void*)0), src_addr);
2543 wmem_free(NULL((void*)0), dst_addr);
2544
2545 if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
2546 with_geoip = 1;
2547 if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
2548 with_geoip = 1;
2549
2550 json_dumper_end_object(&dumper);
2551 }
2552 }
2553 else if (iu->hash.conv_array != NULL((void*)0) && !strncmp(iu->type, "endpt:", 6))
2554 {
2555 for (i = 0; i < iu->hash.conv_array->len; i++)
2556 {
2557 endpoint_item_t *endpoint = &g_array_index(iu->hash.conv_array, endpoint_item_t, i)(((endpoint_item_t*) (void *) (iu->hash.conv_array)->data
) [(i)])
;
2558 char *host_str, *port_str;
2559 char *filter_str;
2560
2561 json_dumper_begin_object(&dumper);
2562
2563 sharkd_json_value_string("host", (host_str = get_conversation_address(NULL((void*)0), &endpoint->myaddress, iu->resolve_name)));
2564
2565 if (proto_with_port)
2566 {
2567 sharkd_json_value_string("port", (port_str = get_endpoint_port(NULL((void*)0), endpoint, iu->resolve_port)));
2568
2569 wmem_free(NULL((void*)0), port_str);
2570 }
2571
2572 sharkd_json_value_anyf("rxf", "%" PRIu64"l" "u", endpoint->rx_frames);
2573 sharkd_json_value_anyf("rxb", "%" PRIu64"l" "u", endpoint->rx_bytes);
2574
2575 sharkd_json_value_anyf("txf", "%" PRIu64"l" "u", endpoint->tx_frames);
2576 sharkd_json_value_anyf("txb", "%" PRIu64"l" "u", endpoint->tx_bytes);
2577
2578 filter_str = get_endpoint_filter(endpoint);
2579 if (filter_str)
2580 {
2581 sharkd_json_value_string("filter", filter_str);
2582 g_free(filter_str);
2583 }
2584
2585 wmem_free(NULL((void*)0), host_str);
2586
2587 if (sharkd_session_geoip_addr(&(endpoint->myaddress), ""))
2588 with_geoip = 1;
2589 json_dumper_end_object(&dumper);
2590 }
2591 }
2592 sharkd_json_array_close();
2593
2594 sharkd_json_value_string("proto", proto);
2595 sharkd_json_value_anyf("geoip", with_geoip ? "true" : "false");
2596
2597 json_dumper_end_object(&dumper);
2598}
2599
2600static void
2601sharkd_session_free_tap_conv_cb(void *arg)
2602{
2603 conv_hash_t *hash = (conv_hash_t *) arg;
2604 struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
2605
2606 if (!strncmp(iu->type, "conv:", 5))
2607 {
2608 reset_conversation_table_data(hash);
2609 }
2610 else if (!strncmp(iu->type, "endpt:", 6))
2611 {
2612 reset_endpoint_table_data(hash);
2613 }
2614
2615 g_free(iu);
2616}
2617
2618/**
2619 * sharkd_session_process_tap_nstat_cb()
2620 *
2621 * Output nstat tap:
2622 * (m) tap - tap name
2623 * (m) type - tap output type
2624 * (m) fields: array of objects with attributes:
2625 * (m) c - name
2626 *
2627 * (m) tables: array of object with attributes:
2628 * (m) t - table title
2629 * (m) i - array of items
2630 */
2631static void
2632sharkd_session_process_tap_nstat_cb(void *arg)
2633{
2634 stat_data_t *stat_data = (stat_data_t *) arg;
2635 unsigned i, j, k;
2636
2637 json_dumper_begin_object(&dumper);
2638 sharkd_json_value_stringf("tap", "nstat:%s", stat_data->stat_tap_data->cli_string);
2639 sharkd_json_value_string("type", "nstat");
2640
2641 sharkd_json_array_open("fields");
2642 for (i = 0; i < stat_data->stat_tap_data->nfields; i++)
2643 {
2644 stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]);
2645
2646 json_dumper_begin_object(&dumper);
2647 sharkd_json_value_string("c", field->column_name);
2648 json_dumper_end_object(&dumper);
2649 }
2650 sharkd_json_array_close();
2651
2652 sharkd_json_array_open("tables");
2653 for (i = 0; i < stat_data->stat_tap_data->tables->len; i++)
2654 {
2655 stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i)(((stat_tap_table **) (void *) (stat_data->stat_tap_data->
tables)->data) [(i)])
;
2656
2657 json_dumper_begin_object(&dumper);
2658
2659 sharkd_json_value_string("t", table->title);
2660
2661 sharkd_json_array_open("i");
2662 for (j = 0; j < table->num_elements; j++)
2663 {
2664 stat_tap_table_item_type *field_data;
2665
2666 field_data = stat_tap_get_field_data(table, j, 0);
2667 if (field_data == NULL((void*)0) || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */
2668 continue;
2669
2670 sharkd_json_array_open(NULL((void*)0));
2671 for (k = 0; k < table->num_fields; k++)
2672 {
2673 field_data = stat_tap_get_field_data(table, j, k);
2674
2675 switch (field_data->type)
2676 {
2677 case TABLE_ITEM_UINT:
2678 sharkd_json_value_anyf(NULL((void*)0), "%u", field_data->value.uint_value);
2679 break;
2680
2681 case TABLE_ITEM_INT:
2682 sharkd_json_value_anyf(NULL((void*)0), "%d", field_data->value.int_value);
2683 break;
2684
2685 case TABLE_ITEM_STRING:
2686 sharkd_json_value_string(NULL((void*)0), field_data->value.string_value);
2687 break;
2688
2689 case TABLE_ITEM_FLOAT:
2690 sharkd_json_value_anyf(NULL((void*)0), "%f", field_data->value.float_value);
2691 break;
2692
2693 case TABLE_ITEM_ENUM:
2694 sharkd_json_value_anyf(NULL((void*)0), "%d", field_data->value.enum_value);
2695 break;
2696
2697 case TABLE_ITEM_NONE:
2698 sharkd_json_value_anyf(NULL((void*)0), "null");
2699 break;
2700 }
2701 }
2702
2703 sharkd_json_array_close();
2704 }
2705 sharkd_json_array_close();
2706 json_dumper_end_object(&dumper);
2707 }
2708 sharkd_json_array_close();
2709
2710 json_dumper_end_object(&dumper);
2711}
2712
2713static void
2714sharkd_session_free_tap_nstat_cb(void *arg)
2715{
2716 stat_data_t *stat_data = (stat_data_t *) arg;
2717
2718 free_stat_tables(stat_data->stat_tap_data);
2719}
2720
2721/**
2722 * sharkd_session_process_tap_rtd_cb()
2723 *
2724 * Output rtd tap:
2725 * (m) tap - tap name
2726 * (m) type - tap output type
2727 * (m) stats - statistics rows - array object with attributes:
2728 * (m) type - statistic name
2729 * (m) num - number of messages
2730 * (m) min - minimum SRT time
2731 * (m) max - maximum SRT time
2732 * (m) tot - total SRT time
2733 * (m) min_frame - minimal SRT
2734 * (m) max_frame - maximum SRT
2735 * (o) open_req - Open Requests
2736 * (o) disc_rsp - Discarded Responses
2737 * (o) req_dup - Duplicated Requests
2738 * (o) rsp_dup - Duplicated Responses
2739 * (o) open_req - Open Requests
2740 * (o) disc_rsp - Discarded Responses
2741 * (o) req_dup - Duplicated Requests
2742 * (o) rsp_dup - Duplicated Responses
2743 */
2744static void
2745sharkd_session_process_tap_rtd_cb(void *arg)
2746{
2747 rtd_data_t *rtd_data = (rtd_data_t *) arg;
2748 register_rtd_t *rtd = (register_rtd_t *) rtd_data->user_data;
2749
2750 unsigned i, j;
2751
2752 const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
2753
2754 /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
2755 * some multiple table and single timestat (radius, h225)
2756 * and it seems that value_string is used one for timestamp-ID, other one for table-ID
2757 * I wonder how it will gonna work with multiple timestats and multiple tables...
2758 * (for usage grep for: register_rtd_table)
2759 */
2760 const value_string *vs = get_rtd_value_string(rtd);
2761
2762 json_dumper_begin_object(&dumper);
2763 sharkd_json_value_stringf("tap", "rtd:%s", filter);
2764 sharkd_json_value_string("type", "rtd");
2765
2766 if (rtd_data->stat_table.num_rtds == 1)
2767 {
2768 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
2769
2770 sharkd_json_value_anyf("open_req", "%u", ms->open_req_num);
2771 sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num);
2772 sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num);
2773 sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num);
2774 }
2775
2776 sharkd_json_array_open("stats");
2777 for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
2778 {
2779 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
2780
2781 for (j = 0; j < ms->num_timestat; j++)
2782 {
2783 const char *type_str;
2784
2785 if (ms->rtd[j].num == 0)
2786 continue;
2787
2788 json_dumper_begin_object(&dumper);
2789
2790 if (rtd_data->stat_table.num_rtds == 1)
2791 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
2792 else
2793 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
2794 sharkd_json_value_string("type", type_str);
2795
2796 sharkd_json_value_anyf("num", "%u", ms->rtd[j].num);
2797 sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&(ms->rtd[j].min)));
2798 sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&(ms->rtd[j].max)));
2799 sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
2800 sharkd_json_value_anyf("min_frame", "%u", ms->rtd[j].min_num);
2801 sharkd_json_value_anyf("max_frame", "%u", ms->rtd[j].max_num);
2802
2803 if (rtd_data->stat_table.num_rtds != 1)
2804 {
2805 /* like in tshark, display it on every row */
2806 sharkd_json_value_anyf("open_req", "%u", ms->open_req_num);
2807 sharkd_json_value_anyf("disc_rsp", "%u", ms->disc_rsp_num);
2808 sharkd_json_value_anyf("req_dup", "%u", ms->req_dup_num);
2809 sharkd_json_value_anyf("rsp_dup", "%u", ms->rsp_dup_num);
2810 }
2811
2812 json_dumper_end_object(&dumper);
2813 }
2814 }
2815 sharkd_json_array_close();
2816
2817 json_dumper_end_object(&dumper);
2818}
2819
2820static void
2821sharkd_session_free_tap_rtd_cb(void *arg)
2822{
2823 rtd_data_t *rtd_data = (rtd_data_t *) arg;
2824
2825 free_rtd_table(&rtd_data->stat_table);
2826 g_free(rtd_data);
2827}
2828
2829/**
2830 * sharkd_session_process_tap_srt_cb()
2831 *
2832 * Output srt tap:
2833 * (m) tap - tap name
2834 * (m) type - tap output type
2835 *
2836 * (m) tables - array of object with attributes:
2837 * (m) n - table name
2838 * (m) f - table filter
2839 * (o) c - table column name
2840 * (m) r - table rows - array object with attributes:
2841 * (m) n - row name
2842 * (m) idx - procedure index
2843 * (m) num - number of events
2844 * (m) min - minimum SRT time
2845 * (m) max - maximum SRT time
2846 * (m) tot - total SRT time
2847 */
2848static void
2849sharkd_session_process_tap_srt_cb(void *arg)
2850{
2851 srt_data_t *srt_data = (srt_data_t *) arg;
2852 register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2853
2854 const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
2855
2856 unsigned i;
2857
2858 json_dumper_begin_object(&dumper);
2859 sharkd_json_value_stringf("tap", "srt:%s", filter);
2860 sharkd_json_value_string("type", "srt");
2861
2862 sharkd_json_array_open("tables");
2863 for (i = 0; i < srt_data->srt_array->len; i++)
2864 {
2865 /* SRT table */
2866 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i)(((srt_stat_table **) (void *) (srt_data->srt_array)->data
) [(i)])
;
2867
2868 int j;
2869
2870 json_dumper_begin_object(&dumper);
2871
2872 if (rst->name)
2873 sharkd_json_value_string("n", rst->name);
2874 else if (rst->short_name)
2875 sharkd_json_value_string("n", rst->short_name);
2876 else
2877 sharkd_json_value_stringf("n", "table%u", i);
2878
2879 if (rst->filter_string)
2880 sharkd_json_value_string("f", rst->filter_string);
2881
2882 if (rst->proc_column_name)
2883 sharkd_json_value_string("c", rst->proc_column_name);
2884
2885 sharkd_json_array_open("r");
2886 for (j = 0; j < rst->num_procs; j++)
2887 {
2888 /* SRT row */
2889 srt_procedure_t *proc = &rst->procedures[j];
2890
2891 if (proc->stats.num == 0)
2892 continue;
2893
2894 json_dumper_begin_object(&dumper);
2895
2896 sharkd_json_value_string("n", proc->procedure);
2897
2898 if (rst->filter_string)
2899 sharkd_json_value_anyf("idx", "%d", proc->proc_index);
2900
2901 sharkd_json_value_anyf("num", "%u", proc->stats.num);
2902
2903 sharkd_json_value_anyf("min", "%.9f", nstime_to_sec(&proc->stats.min));
2904 sharkd_json_value_anyf("max", "%.9f", nstime_to_sec(&proc->stats.max));
2905 sharkd_json_value_anyf("tot", "%.9f", nstime_to_sec(&proc->stats.tot));
2906
2907 json_dumper_end_object(&dumper);
2908 }
2909 sharkd_json_array_close();
2910
2911 json_dumper_end_object(&dumper);
2912 }
2913 sharkd_json_array_close();
2914
2915 json_dumper_end_object(&dumper);
2916}
2917
2918static void
2919sharkd_session_free_tap_srt_cb(void *arg)
2920{
2921 srt_data_t *srt_data = (srt_data_t *) arg;
2922 register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2923
2924 free_srt_table(srt, srt_data->srt_array);
2925 g_array_free(srt_data->srt_array, TRUE(!(0)));
2926 g_free(srt_data);
2927}
2928
2929static void
2930// NOLINTNEXTLINE(misc-no-recursion)
2931sharkd_session_process_tap_phs_cb_aux(phs_t *rs)
2932{
2933 for (; rs; rs = rs->sibling) {
2934 if (rs->protocol == -1) {
2935 return;
2936 }
2937 sharkd_json_object_open(NULL((void*)0));
2938 sharkd_json_value_string("proto", rs->proto_name);
2939 sharkd_json_value_anyf("frames", "%"PRIu32"u", rs->frames);
2940 sharkd_json_value_anyf("bytes", "%"PRIu64"l" "u", rs->bytes);
2941 if (rs->child != NULL((void*)0) && rs->child->protocol != -1) {
2942 sharkd_json_array_open("protos");
2943 // We recurse here but our depth is limited
2944 sharkd_session_process_tap_phs_cb_aux(rs->child);
2945 sharkd_json_array_close();
2946 }
2947 sharkd_json_object_close();
2948 }
2949}
2950
2951/**
2952 * sharkd_session_process_tap_phs_cb()
2953 *
2954 * Output phs tap:
2955 * (m) tap - tap name
2956 * (m) type - tap output type
2957 * (m) filter - tap filter argument
2958 * (m) protos - array of proto objects
2959 *
2960 * proto object:
2961 * (m) proto - protocol name
2962 * (m) frames - frame count
2963 * (m) bytes - bytes count
2964 * (o) protos - array of proto objects
2965 */
2966static void
2967sharkd_session_process_tap_phs_cb(void *arg)
2968{
2969 phs_t *rs = (phs_t *)arg;
2970 sharkd_json_object_open(NULL((void*)0));
2971 sharkd_json_value_string("tap", "phs");
2972 sharkd_json_value_string("type", "phs");
2973 sharkd_json_value_string("filter", rs->filter ? rs->filter : "");
2974 sharkd_json_array_open("protos");
2975 sharkd_session_process_tap_phs_cb_aux(rs);
2976 sharkd_json_array_close();
2977 sharkd_json_object_close();
2978}
2979
2980static void
2981sharkd_session_free_tap_phs_cb(void *arg)
2982{
2983 phs_t *rs = (phs_t *)arg;
2984 free_phs(rs);
2985}
2986
2987struct sharkd_export_object_list
2988{
2989 struct sharkd_export_object_list *next;
2990
2991 char *type;
2992 const char *proto;
2993 GSList *entries;
2994};
2995
2996static struct sharkd_export_object_list *sharkd_eo_list;
2997
2998/**
2999 * sharkd_session_process_tap_eo_cb()
3000 *
3001 * Output eo tap:
3002 * (m) tap - tap name
3003 * (m) type - tap output type
3004 * (m) proto - protocol short name
3005 * (m) objects - array of object with attributes:
3006 * (m) pkt - packet number
3007 * (o) hostname - hostname
3008 * (o) type - content type
3009 * (o) filename - filename
3010 * (m) len - object length
3011 * (m) sha1 - object's sha1 sum
3012 */
3013static void
3014sharkd_session_process_tap_eo_cb(void *tapdata)
3015{
3016 export_object_list_t *tap_object = (export_object_list_t *) tapdata;
3017 struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data;
3018 GSList *slist;
3019 int i = 0;
3020 char sha1sum_bytes[HASH_SHA1_LENGTH20], *sha1sum_str;
3021
3022 json_dumper_begin_object(&dumper);
3023 sharkd_json_value_string("tap", object_list->type);
3024 sharkd_json_value_string("type", "eo");
3025
3026 sharkd_json_value_string("proto", object_list->proto);
3027
3028 sharkd_json_array_open("objects");
3029 for (slist = object_list->entries; slist; slist = slist->next)
3030 {
3031 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
3032
3033 json_dumper_begin_object(&dumper);
3034
3035 sharkd_json_value_anyf("pkt", "%u", eo_entry->pkt_num);
3036
3037 if (eo_entry->hostname)
3038 sharkd_json_value_string("hostname", eo_entry->hostname);
3039
3040 if (eo_entry->content_type)
3041 sharkd_json_value_string("type", eo_entry->content_type);
3042
3043 if (eo_entry->filename)
3044 sharkd_json_value_string("filename", eo_entry->filename);
3045
3046 sharkd_json_value_stringf("_download", "%s_%d", object_list->type, i);
3047
3048 sharkd_json_value_anyf("len", "%zu", eo_entry->payload_len);
3049
3050 gcry_md_hash_buffer(GCRY_MD_SHA1, sha1sum_bytes, eo_entry->payload_data, eo_entry->payload_len);
3051 sha1sum_str = bytes_to_str(NULL, sha1sum_bytes, HASH_SHA1_LENGTH)bytes_to_str_maxlen(((void*)0), sha1sum_bytes, 20, 36);
3052 sharkd_json_value_string("sha1", sha1sum_str);
3053 g_free(sha1sum_str);
3054
3055 json_dumper_end_object(&dumper);
3056
3057 i++;
3058 }
3059 sharkd_json_array_close();
3060
3061 json_dumper_end_object(&dumper);
3062}
3063
3064static void
3065sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
3066{
3067 struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
3068
3069 object_list->entries = g_slist_append(object_list->entries, entry);
3070}
3071
3072static export_object_entry_t *
3073sharkd_eo_object_list_get_entry(void *gui_data, int row)
3074{
3075 struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
3076
3077 return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
3078}
3079
3080static struct sharkd_export_object_list *
3081sharkd_eo_object_list_get_entry_by_type(void *gui_data, const char *tap_type)
3082{
3083 struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
3084 for (; object_list; object_list = object_list->next)
3085 {
3086 if (!strcmp(object_list->type, tap_type))
3087 return object_list;
3088 }
3089 return NULL((void*)0);
3090}
3091
3092
3093/**
3094 * sharkd_session_process_tap_rtp_cb()
3095 *
3096 * Output RTP streams tap:
3097 * (m) tap - tap name
3098 * (m) type - tap output type
3099 * (m) streams - array of object with attributes:
3100 * (m) ssrc - RTP synchronization source identifier
3101 * (m) payload - stream payload
3102 * (m) saddr - source address
3103 * (m) sport - source port
3104 * (m) daddr - destination address
3105 * (m) dport - destination port
3106 * (m) pkts - packets count
3107 * (m) max_delta - max delta (ms)
3108 * (m) max_jitter - max jitter (ms)
3109 * (m) mean_jitter - mean jitter (ms)
3110 * (m) expectednr -
3111 * (m) totalnr -
3112 * (m) problem - if analyser found the problem
3113 * (m) ipver - address IP version (4 or 6)
3114 */
3115static void
3116sharkd_session_process_tap_rtp_cb(void *arg)
3117{
3118 rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
3119
3120 GList *listx;
3121
3122 json_dumper_begin_object(&dumper);
3123 sharkd_json_value_string("tap", "rtp-streams");
3124 sharkd_json_value_string("type", "rtp-streams");
3125
3126 sharkd_json_array_open("streams");
3127 for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
3128 {
3129 rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
3130 rtpstream_info_calc_t calc;
3131
3132 rtpstream_info_calculate(streaminfo, &calc);
3133
3134 json_dumper_begin_object(&dumper);
3135
3136 sharkd_json_value_stringf("ssrc", "0x%x", calc.ssrc);
3137 sharkd_json_value_string("payload", calc.all_payload_type_names);
3138
3139 sharkd_json_value_string("saddr", calc.src_addr_str);
3140 sharkd_json_value_anyf("sport", "%u", calc.src_port);
3141 sharkd_json_value_string("daddr", calc.dst_addr_str);
3142 sharkd_json_value_anyf("dport", "%u", calc.dst_port);
3143
3144 sharkd_json_value_anyf("start_time", "%f", calc.start_time_ms);
3145 sharkd_json_value_anyf("duration", "%f", calc.duration_ms);
3146
3147 sharkd_json_value_anyf("pkts", "%u", calc.packet_count);
3148 sharkd_json_value_anyf("lost", "%u", calc.lost_num);
3149 sharkd_json_value_anyf("lost_percent", "%f", calc.lost_perc);
3150
3151 sharkd_json_value_anyf("max_delta", "%f",calc.max_delta);
3152 sharkd_json_value_anyf("min_delta", "%f",calc.min_delta);
3153 sharkd_json_value_anyf("mean_delta", "%f",calc.mean_delta);
3154 sharkd_json_value_anyf("min_jitter", "%f", calc.min_jitter);
3155 sharkd_json_value_anyf("max_jitter", "%f", calc.max_jitter);
3156 sharkd_json_value_anyf("mean_jitter", "%f", calc.mean_jitter);
3157
3158 sharkd_json_value_anyf("expectednr", "%u", calc.packet_expected);
3159 sharkd_json_value_anyf("totalnr", "%u", calc.total_nr);
3160
3161 sharkd_json_value_anyf("problem", calc.problem ? "true" : "false");
3162
3163 /* for filter */
3164 sharkd_json_value_anyf("ipver", "%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4);
3165
3166 rtpstream_info_calc_free(&calc);
3167
3168 json_dumper_end_object(&dumper);
3169 }
3170 sharkd_json_array_close();
3171
3172 json_dumper_end_object(&dumper);
3173}
3174
3175/**
3176* sharkd_session_process_tap_multicast_cb()
3177*
3178* Output UDP Multicast streams tap:
3179* (m) tap - tap name
3180* (m) type - tap output type
3181* (m) bufferThresholdBytes - byte count for a stream where a buffer alarm should be reported
3182* (m) burstIntervalMs - analysis interval in milliseconds
3183* (m) burstThresholdPackets - count of packets in an interval that should trigger an alarm
3184* (m) streams - array of streams with metrics:
3185* (m) saddr - source address
3186* (m) sport - source port
3187* (m) daddr - destination address
3188* (m) dport - destination port
3189* (m) packets - object group for packet metrics with attributes:
3190* (m) number - count of packets in the stream
3191* (m) perSecond - average number of packets per seconds in the stream
3192* (m) bandwidth - object group for bandwidth metrics with attributes:
3193* (m) average - average measured bitrate in the stream
3194* (m) max - max measured bitrate in the stream
3195* (m) buffer - object group for buffer metrics with attributes:
3196* (m) alarms - number of times the stream exceeded the buffer threshold
3197* (m) max - highest stream buffer utilization
3198* (m) burst - object group for burst metrics with attributes:
3199* (m) alarms - number of times the stream exceeded the burst threshold
3200* (m) max - most stream packets measured in a burst interval
3201*/
3202static void
3203sharkd_session_process_tap_multicast_cb(void *arg)
3204{
3205 mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)arg;
3206 GList *list_item;
3207 char *addr_str;
3208
3209 json_dumper_begin_object(&dumper);
3210
3211 sharkd_json_value_string("tap", "multicast");
3212 sharkd_json_value_string("type", "multicast");
3213
3214 sharkd_json_value_anyf("bufferThresholdBytes", "%u", mcast_stream_bufferalarm);
3215 sharkd_json_value_anyf("burstIntervalMs", "%u", mcast_stream_burstint);
3216 sharkd_json_value_anyf("burstThresholdPackets", "%u", mcast_stream_trigger);
3217
3218 sharkd_json_array_open("streams");
3219 for (list_item = g_list_first(tapinfo->strinfo_list); list_item; list_item = list_item->next) {
3220 mcast_stream_info_t *stream_info = (mcast_stream_info_t *) list_item->data;
3221 sharkd_json_object_open(NULL((void*)0));
3222 {
3223 addr_str = address_to_display(NULL((void*)0), &stream_info->src_addr);
3224 sharkd_json_value_string("saddr", addr_str);
3225 wmem_free(NULL((void*)0), addr_str);
3226 sharkd_json_value_anyf("sport", "%u", stream_info->src_port);
3227 addr_str = address_to_display(NULL((void*)0), &stream_info->dest_addr);
3228 sharkd_json_value_string("daddr", addr_str);
3229 wmem_free(NULL((void*)0), addr_str);
3230 sharkd_json_value_anyf("dport", "%u", stream_info->dest_port);
3231 sharkd_json_object_open("packets");
3232 {
3233 sharkd_json_value_anyf("number", "%u", stream_info->npackets);
3234 sharkd_json_value_anyf("perSecond", "%f", stream_info->apackets);
3235 }
3236 sharkd_json_object_close();
3237 sharkd_json_object_open("bandwidth");
3238 {
3239 sharkd_json_value_anyf("average", "%f", stream_info->average_bw);
3240 sharkd_json_value_anyf("max", "%f", stream_info->element.maxbw);
3241 }
3242 sharkd_json_object_close();
3243 sharkd_json_object_open("buffer");
3244 {
3245 sharkd_json_value_anyf("alarms", "%u", stream_info->element.numbuffalarms);
3246 sharkd_json_value_anyf("max", "%u", stream_info->element.topbuffusage);
3247 }
3248 sharkd_json_object_close();
3249 sharkd_json_object_open("burst");
3250 {
3251 sharkd_json_value_anyf("alarms", "%u", stream_info->element.numbursts);
3252 sharkd_json_value_anyf("max", "%u", stream_info->element.topburstsize);
3253 }
3254 sharkd_json_object_close();
3255 }
3256 sharkd_json_object_close();
3257 }
3258 sharkd_json_array_close();
3259
3260 json_dumper_end_object(&dumper);
3261}
3262
3263static void
3264sharkd_session_process_free_tap_multicast_cb(void *tapdata)
3265{
3266 mcaststream_tapinfo_t *tapinfo = (mcaststream_tapinfo_t *)tapdata;
3267
3268 mcaststream_reset(tapinfo);
3269
3270 g_free(tapinfo);
3271}
3272
3273/**
3274 * sharkd_session_process_tap_voip_calls_cb()
3275 *
3276 * Output VoIP Calls tap:
3277 * (m) tap - tap name
3278 * (m) type - tap output type
3279 * (m) calls - array of objects with attributes:
3280 * (m) call - call number
3281 * (m) start_time - start timestamp
3282 * (m) stop_time - stop timestamp
3283 * (m) initial_speaker - address of initial speaker
3284 * (m) from - from address
3285 * (m) to - to address
3286 * (m) protocol - protocol name
3287 * (m) packets - packet count
3288 * (m) state - state string
3289 * (m) comment - comment string
3290 */
3291static void
3292sharkd_session_process_tap_voip_calls_cb(void *arg)
3293{
3294 voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *)arg;
3295 char *addr_str;
3296 GList *cur_call = g_queue_peek_nth_link(tapinfo->callsinfos, 0);
3297 sharkd_json_object_open(NULL((void*)0));
3298 sharkd_json_value_string("tap", "voip-calls");
3299 sharkd_json_value_string("type", "voip-calls");
3300 sharkd_json_array_open("calls");
3301 while (cur_call && cur_call->data) {
3302 voip_calls_info_t *call_info_ = (voip_calls_info_t*) cur_call->data;
3303 sharkd_json_object_open(NULL((void*)0));
3304 sharkd_json_value_anyf("call", "%hu", call_info_->call_num);
3305 sharkd_json_value_anyf("start_time", "%.6f", nstime_to_sec(&(call_info_->start_rel_ts)));
3306 sharkd_json_value_anyf("stop_time", "%.6f", nstime_to_sec(&(call_info_->stop_rel_ts)));
3307 addr_str = address_to_display(NULL((void*)0), &(call_info_->initial_speaker));
3308 sharkd_json_value_string("initial_speaker", addr_str);
3309 wmem_free(NULL((void*)0), addr_str);
3310 sharkd_json_value_string("from", call_info_->from_identity);
3311 sharkd_json_value_string("to", call_info_->to_identity);
3312 sharkd_json_value_string("protocol", ((call_info_->protocol == VOIP_COMMON) && call_info_->protocol_name) ?
3313 call_info_->protocol_name : voip_protocol_name[call_info_->protocol]);
3314 sharkd_json_value_anyf("packets", "%u", call_info_->npackets);
3315 sharkd_json_value_string("state", voip_call_state_name[call_info_->call_state]);
3316 sharkd_json_value_string("comment", call_info_->call_comment);
3317 sharkd_json_object_close();
3318 cur_call = g_list_next(cur_call)((cur_call) ? (((GList *)(cur_call))->next) : ((void*)0));
3319 }
3320 sharkd_json_array_close();
3321 sharkd_json_object_close();
3322}
3323
3324static void
3325sharkd_session_free_tap_voip_calls_cb(void *tapdata)
3326{
3327 voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *)tapdata;
3328 voip_calls_remove_all_tap_listeners(tapinfo);
3329 if (tapinfo->callsinfos != NULL((void*)0)) {
3330 g_queue_free(tapinfo->callsinfos);
3331 }
3332 if (tapinfo->graph_analysis != NULL((void*)0)) {
3333 sequence_analysis_info_free(tapinfo->graph_analysis);
3334 }
3335 memset(tapinfo, 0, sizeof(*tapinfo));
3336}
3337
3338
3339struct sharkd_voip_convs_req {
3340 voip_calls_tapinfo_t *tapinfo;
3341 const char *tap_name;
3342};
3343
3344/**
3345 * sharkd_session_process_tap_voip_convs_cb()
3346 *
3347 * Output VoIP Conversations tap:
3348 * (m) tap - tap name
3349 * (m) type - tap output type
3350 * (m) convs - array of objects with attributes:
3351 * (m) frame - frame number
3352 * (m) call - call number
3353 * (m) time - timestamp
3354 * (m) dst_addr - destination address
3355 * (m) dst_port - destination port
3356 * (m) src_addr - source address
3357 * (m) src_port - source port
3358 * (m) label - label string
3359 * (m) comment - comment string
3360 */
3361static void
3362sharkd_session_process_tap_voip_convs_cb(void *arg)
3363{
3364 struct sharkd_voip_convs_req *voip_convs_req = (struct sharkd_voip_convs_req *)arg;
3365 voip_calls_tapinfo_t *tapinfo = voip_convs_req->tapinfo;
3366 seq_analysis_info_t *sainfo = tapinfo->graph_analysis;
3367 char *addr_str;
3368 sequence_analysis_list_sort(sainfo);
3369 sharkd_json_object_open(NULL((void*)0));
3370 sharkd_json_value_string("tap", voip_convs_req->tap_name);
3371 sharkd_json_value_string("type", "voip-convs");
3372 sharkd_json_array_open("convs");
3373 for (GList *cur = g_queue_peek_nth_link(sainfo->items, 0); cur; cur = g_list_next(cur)((cur) ? (((GList *)(cur))->next) : ((void*)0))) {
3374 seq_analysis_item_t *sai = (seq_analysis_item_t *) cur->data;
3375 if ((voip_conv_sel[sai->conv_num / VOIP_CONV_BITS(sizeof(int) * 8)] & (1 << (sai->conv_num % VOIP_CONV_BITS(sizeof(int) * 8)))) == 0)
3376 continue;
3377 sharkd_json_object_open(NULL((void*)0));
3378 sharkd_json_value_anyf("frame", "%d", sai->frame_number);
3379 sharkd_json_value_anyf("call", "%d", sai->conv_num);
3380 sharkd_json_value_string("time", sai->time_str);
3381 addr_str = address_to_display(NULL((void*)0), &(sai->dst_addr));
3382 sharkd_json_value_string("dst_addr", addr_str);
3383 wmem_free(NULL((void*)0), addr_str);
3384 sharkd_json_value_anyf("dst_port", "%d", sai->port_dst);
3385 addr_str = address_to_display(NULL((void*)0), &(sai->src_addr));
3386 sharkd_json_value_string("src_addr", addr_str);
3387 wmem_free(NULL((void*)0), addr_str);
3388 sharkd_json_value_anyf("src_port", "%d", sai->port_src);
3389 sharkd_json_value_string("label", sai->frame_label);
3390 sharkd_json_value_string("comment", sai->comment);
3391 sharkd_json_object_close();
3392 }
3393 sharkd_json_array_close();
3394 sharkd_json_object_close();
3395}
3396
3397static void
3398sharkd_session_free_tap_voip_convs_cb(void *tapdata)
3399{
3400 struct sharkd_voip_convs_req *voip_convs_req = (struct sharkd_voip_convs_req *)tapdata;
3401 voip_calls_tapinfo_t *tapinfo = voip_convs_req->tapinfo;
3402 voip_calls_remove_all_tap_listeners(tapinfo);
3403 if (tapinfo->callsinfos != NULL((void*)0)) {
3404 g_queue_free(tapinfo->callsinfos);
3405 }
3406 if (tapinfo->graph_analysis != NULL((void*)0)) {
3407 sequence_analysis_info_free(tapinfo->graph_analysis);
3408 }
3409 memset(tapinfo, 0, sizeof(*tapinfo));
3410 g_free(voip_convs_req);
3411}
3412
3413struct sharkd_hosts_req {
3414 const char *tap_name;
3415 bool_Bool dump_v4;
3416 bool_Bool dump_v6;
3417};
3418
3419static int
3420sharkd_session_tap_ipv4_host_compare(const void *a, const void *b)
3421{
3422 return ws_ascii_strnatcmp(((const hashipv4_t *)a)->name,
3423 ((const hashipv4_t *)b)->name);
3424}
3425
3426static int
3427sharkd_session_tap_ipv6_host_compare(const void *a, const void *b)
3428{
3429 return ws_ascii_strnatcmp(((const hashipv6_t *)a)->name,
3430 ((const hashipv6_t *)b)->name);
3431}
3432
3433static void
3434sharkd_session_tap_ipv4_host_print(void *data, void *user_data _U___attribute__((unused)))
3435{
3436 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)data;
3437 sharkd_json_object_open(NULL((void*)0));
3438 sharkd_json_value_string("name", ipv4_hash_table_entry->name);
3439 sharkd_json_value_string("addr", ipv4_hash_table_entry->ip);
3440 sharkd_json_object_close();
3441}
3442
3443static void
3444sharkd_session_tap_ipv6_host_print(void *data, void *user_data _U___attribute__((unused)))
3445{
3446 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)data;
3447 sharkd_json_object_open(NULL((void*)0));
3448 sharkd_json_value_string("name", ipv6_hash_table_entry->name);
3449 sharkd_json_value_string("addr", ipv6_hash_table_entry->ip6);
3450 sharkd_json_object_close();
3451}
3452
3453static void
3454sharkd_session_tap_ipv4_host_insert_sorted(void *key _U___attribute__((unused)), void *value, void *user_data)
3455{
3456 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
3457 GSList **list = (GSList **)user_data;
3458 if ((ipv4_hash_table_entry->flags & NAME_RESOLVED(1U<<1))) {
3459 *list = g_slist_insert_sorted(*list, ipv4_hash_table_entry, sharkd_session_tap_ipv4_host_compare);
3460 }
3461}
3462
3463static void
3464sharkd_session_tap_ipv6_host_insert_sorted(void *key _U___attribute__((unused)), void *value, void *user_data)
3465{
3466 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
3467 GSList **list = (GSList **) user_data;
3468 if ((ipv6_hash_table_entry->flags & NAME_RESOLVED(1U<<1))) {
3469 *list = g_slist_insert_sorted(*list, ipv6_hash_table_entry, sharkd_session_tap_ipv6_host_compare);
3470 }
3471}
3472
3473static void
3474sharkd_session_tap_ipv4_hosts_print(void)
3475{
3476 wmem_map_t *ipv4_hash_table = get_ipv4_hash_table();
3477 if (!ipv4_hash_table)
3478 return;
3479 GSList *list = NULL((void*)0);
3480 wmem_map_foreach(ipv4_hash_table, sharkd_session_tap_ipv4_host_insert_sorted, &list);
3481 g_slist_foreach(list, sharkd_session_tap_ipv4_host_print, NULL((void*)0));
3482 g_slist_free(list);
3483}
3484
3485static void
3486sharkd_session_tap_ipv6_hosts_print(void)
3487{
3488 wmem_map_t *ipv6_hash_table = get_ipv6_hash_table();
3489 if (!ipv6_hash_table)
3490 return;
3491 GSList *list = NULL((void*)0);
3492 wmem_map_foreach(ipv6_hash_table, sharkd_session_tap_ipv6_host_insert_sorted, &list);
3493 g_slist_foreach(list, sharkd_session_tap_ipv6_host_print, NULL((void*)0));
3494 g_slist_free(list);
3495}
3496
3497/**
3498 * sharkd_session_process_tap_hosts_cb()
3499 *
3500 * Output Hosts tap:
3501 * (m) tap - tap name
3502 * (m) type - tap output type
3503 * (o) ipv4_hosts - array of objects with attributes:
3504 * (m) addr - ipv4 address
3505 * (m) name - resolved name of address
3506 * (o) ipv6_hosts - array of objects with attributes:
3507 * (m) addr - ipv6 address
3508 * (m) name - resolved name of address
3509 */
3510static void
3511sharkd_session_process_tap_hosts_cb(void *arg)
3512{
3513 struct sharkd_hosts_req *hosts_req = (struct sharkd_hosts_req *)arg;
3514 sharkd_json_object_open(NULL((void*)0));
3515 sharkd_json_value_string("tap", hosts_req->tap_name);
3516 sharkd_json_value_string("type", "hosts");
3517 if (hosts_req->dump_v4) {
3518 sharkd_json_array_open("ipv4_hosts");
3519 sharkd_session_tap_ipv4_hosts_print();
3520 sharkd_json_array_close();
3521 }
3522 if (hosts_req->dump_v6) {
3523 sharkd_json_array_open("ipv6_hosts");
3524 sharkd_session_tap_ipv6_hosts_print();
3525 sharkd_json_array_close();
3526 }
3527 sharkd_json_object_close();
3528}
3529
3530static void
3531sharkd_session_free_tap_hosts_cb(void *tapdata)
3532{
3533 struct sharkd_hosts_req *hosts_req = (struct sharkd_hosts_req *)tapdata;
3534 g_free(hosts_req);
3535}
3536
3537static GString*
3538sharkd_session_eo_register_tap_listener(register_eo_t *eo, const char *tap_type, const char *tap_filter, tap_draw_cb tap_draw, void **ptap_data, GFreeFunc* ptap_free)
3539{
3540 export_object_list_t *eo_object;
3541 struct sharkd_export_object_list *object_list;
3542
3543 object_list = sharkd_eo_object_list_get_entry_by_type(sharkd_eo_list, tap_type);
3544 if (object_list)
3545 {
3546 g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
3547 object_list->entries = NULL((void*)0);
3548 }
3549 else
3550 {
3551 object_list = g_new(struct sharkd_export_object_list, 1)((struct sharkd_export_object_list *) g_malloc_n ((1), sizeof
(struct sharkd_export_object_list)))
;
3552 object_list->type = g_strdup(tap_type)g_strdup_inline (tap_type);
3553 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
3554 object_list->entries = NULL((void*)0);
3555 object_list->next = sharkd_eo_list;
3556 sharkd_eo_list = object_list;
3557 }
3558
3559 eo_object = g_new0(export_object_list_t, 1)((export_object_list_t *) g_malloc0_n ((1), sizeof (export_object_list_t
)))
;
3560 eo_object->add_entry = sharkd_eo_object_list_add_entry;
3561 eo_object->get_entry = sharkd_eo_object_list_get_entry;
3562 eo_object->gui_data = (void *) object_list;
3563
3564 *ptap_data = eo_object;
3565 *ptap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
3566
3567 return register_tap_listener(get_eo_tap_listener_name(eo), eo_object, tap_filter, 0, NULL((void*)0), get_eo_packet_func(eo), tap_draw, NULL((void*)0));
3568}
3569
3570/**
3571 * sharkd_session_process_tap()
3572 *
3573 * Process tap request
3574 *
3575 * Input:
3576 * (m) tap0 - First tap request
3577 * (o) tap1...tap15 - Other tap requests
3578 *
3579 * Output object with attributes:
3580 * (m) taps - array of object with attributes:
3581 * (m) tap - tap name
3582 * (m) type - tap output type
3583 * ...
3584 * for type:stats see sharkd_session_process_tap_stats_cb()
3585 * for type:nstat see sharkd_session_process_tap_nstat_cb()
3586 * for type:conv see sharkd_session_process_tap_conv_cb()
3587 * for type:host see sharkd_session_process_tap_conv_cb()
3588 * for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
3589 * for type:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
3590 * for type:eo see sharkd_session_process_tap_eo_cb()
3591 * for type:expert see sharkd_session_process_tap_expert_cb()
3592 * for type:rtd see sharkd_session_process_tap_rtd_cb()
3593 * for type:srt see sharkd_session_process_tap_srt_cb()
3594 * for type:flow see sharkd_session_process_tap_flow_cb()
3595 *
3596 * (m) err - error code
3597 */
3598static void
3599sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
3600{
3601 void *taps_data[16];
3602 GFreeFunc taps_free[16];
3603 int taps_count = 0;
3604 int i;
3605 const char *tap_filter = json_find_attr(buf, tokens, count, "filter");
3606
3607 rtpstream_tapinfo_t rtp_tapinfo =
3608 { NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, NULL((void*)0), NULL((void*)0), 0, TAP_ANALYSE, NULL((void*)0), NULL((void*)0), NULL((void*)0), false0, false0};
3609
3610 for (i = 0; i < 16; i++)
3611 {
3612 char tapbuf[32];
3613 const char *tok_tap;
3614
3615 void *tap_data = NULL((void*)0);
3616 GFreeFunc tap_free = NULL((void*)0);
3617 GString *tap_error = NULL((void*)0);
3618
3619 snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
3620 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
3621 if (!tok_tap)
3622 break;
3623
3624 if (!strncmp(tok_tap, "stat:", 5))
3625 {
3626 stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
3627 stats_tree *st;
3628
3629 if (!cfg)
3630 {
3631 sharkd_json_error(
3632 rpcid, -11001, NULL((void*)0),
3633 "sharkd_session_process_tap() stat %s not found", tok_tap + 5
3634 );
3635 return;
3636 }
3637
3638 st = stats_tree_new(cfg, NULL((void*)0), tap_filter);
3639
3640 tap_error = register_tap_listener(st->cfg->tapname, st, st->filter, st->cfg->flags, stats_tree_reset, stats_tree_packet, sharkd_session_process_tap_stats_cb, NULL((void*)0));
3641
3642 if (!tap_error && cfg->init)
3643 cfg->init(st);
3644
3645 tap_data = st;
3646 tap_free = sharkd_session_free_tap_stats_cb;
3647 }
3648 else if (!strcmp(tok_tap, "expert"))
3649 {
3650 struct sharkd_expert_tap *expert_tap;
3651
3652 expert_tap = g_new0(struct sharkd_expert_tap, 1)((struct sharkd_expert_tap *) g_malloc0_n ((1), sizeof (struct
sharkd_expert_tap)))
;
3653 expert_tap->text = g_string_chunk_new(100);
3654
3655 tap_error = register_tap_listener("expert", expert_tap, tap_filter, 0, NULL((void*)0), sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb, NULL((void*)0));
3656
3657 tap_data = expert_tap;
3658 tap_free = sharkd_session_free_tap_expert_cb;
3659 }
3660 else if (!strncmp(tok_tap, "seqa:", 5))
3661 {
3662 seq_analysis_info_t *graph_analysis;
3663 register_analysis_t *analysis;
3664 const char *tap_name;
3665 tap_packet_cb tap_func;
3666 unsigned tap_flags;
3667
3668 analysis = sequence_analysis_find_by_name(tok_tap + 5);
3669 if (!analysis)
3670 {
3671 sharkd_json_error(
3672 rpcid, -11002, NULL((void*)0),
3673 "sharkd_session_process_tap() seq analysis %s not found", tok_tap + 5
3674 );
3675 return;
3676 }
3677
3678 graph_analysis = sequence_analysis_info_new();
3679 graph_analysis->name = tok_tap + 5;
3680 /* TODO, make configurable */
3681 graph_analysis->any_addr = false0;
3682
3683 tap_name = sequence_analysis_get_tap_listener_name(analysis);
3684 tap_flags = sequence_analysis_get_tap_flags(analysis);
3685 tap_func = sequence_analysis_get_packet_func(analysis);
3686
3687 tap_error = register_tap_listener(tap_name, graph_analysis, tap_filter, tap_flags, NULL((void*)0), tap_func, sharkd_session_process_tap_flow_cb, NULL((void*)0));
3688
3689 tap_data = graph_analysis;
3690 tap_free = sharkd_session_free_tap_flow_cb;
3691 }
3692 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
3693 {
3694 struct register_ct *ct = NULL((void*)0);
3695 const char *ct_tapname;
3696 struct sharkd_conv_tap_data *ct_data;
3697 tap_packet_cb tap_func = NULL((void*)0);
3698
3699 if (!strncmp(tok_tap, "conv:", 5))
3700 {
3701 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
3702
3703 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
3704 {
3705 sharkd_json_error(
3706 rpcid, -11003, NULL((void*)0),
3707 "sharkd_session_process_tap() conv %s not found", tok_tap + 5
3708 );
3709 return;
3710 }
3711 }
3712 else if (!strncmp(tok_tap, "endpt:", 6))
3713 {
3714 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
3715
3716 if (!ct || !(tap_func = get_endpoint_packet_func(ct)))
3717 {
3718 sharkd_json_error(
3719 rpcid, -11004, NULL((void*)0),
3720 "sharkd_session_process_tap() endpt %s not found", tok_tap + 6
3721 );
3722 return;
3723 }
3724 }
3725 else
3726 {
3727 sharkd_json_error(
3728 rpcid, -11005, NULL((void*)0),
3729 "sharkd_session_process_tap() conv/endpt(?): %s not found", tok_tap
3730 );
3731 return;
3732 }
3733
3734 ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
3735
3736 ct_data = g_new0(struct sharkd_conv_tap_data, 1)((struct sharkd_conv_tap_data *) g_malloc0_n ((1), sizeof (struct
sharkd_conv_tap_data)))
;
3737 ct_data->type = tok_tap;
3738 ct_data->hash.user_data = ct_data;
3739
3740 /* XXX: make configurable */
3741 ct_data->resolve_name = true1;
3742 ct_data->resolve_port = true1;
3743
3744 tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL((void*)0), tap_func, sharkd_session_process_tap_conv_cb, NULL((void*)0));
3745
3746 tap_data = &ct_data->hash;
3747 tap_free = sharkd_session_free_tap_conv_cb;
3748 }
3749 else if (!strncmp(tok_tap, "nstat:", 6))
3750 {
3751 stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6);
3752 stat_data_t *stat_data;
3753
3754 if (!stat_tap)
3755 {
3756 sharkd_json_error(
3757 rpcid, -11006, NULL((void*)0),
3758 "sharkd_session_process_tap() nstat=%s not found", tok_tap + 6
3759 );
3760 return;
3761 }
3762
3763 stat_tap->stat_tap_init_cb(stat_tap);
3764
3765 stat_data = g_new0(stat_data_t, 1)((stat_data_t *) g_malloc0_n ((1), sizeof (stat_data_t)));
3766 stat_data->stat_tap_data = stat_tap;
3767 stat_data->user_data = NULL((void*)0);
3768
3769 tap_error = register_tap_listener(stat_tap->tap_name, stat_data, tap_filter, 0, NULL((void*)0), stat_tap->packet_func, sharkd_session_process_tap_nstat_cb, NULL((void*)0));
3770
3771 tap_data = stat_data;
3772 tap_free = sharkd_session_free_tap_nstat_cb;
3773 }
3774 else if (!strncmp(tok_tap, "rtd:", 4))
3775 {
3776 register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
3777 rtd_data_t *rtd_data;
3778 char *err;
3779
3780 if (!rtd)
3781 {
3782 sharkd_json_error(
3783 rpcid, -11007, NULL((void*)0),
3784 "sharkd_session_process_tap() rtd=%s not found", tok_tap + 4
3785 );
3786 return;
3787 }
3788
3789 rtd_table_get_filter(rtd, "", &tap_filter, &err);
3790 if (err != NULL((void*)0))
3791 {
3792 sharkd_json_error(
3793 rpcid, -11008, NULL((void*)0),
3794 "sharkd_session_process_tap() rtd=%s err=%s", tok_tap + 4, err
3795 );
3796 g_free(err);
3797 return;
3798 }
3799
3800 rtd_data = g_new0(rtd_data_t, 1)((rtd_data_t *) g_malloc0_n ((1), sizeof (rtd_data_t)));
3801 rtd_data->user_data = rtd;
3802 rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL((void*)0), NULL((void*)0));
3803
3804 tap_error = register_tap_listener(get_rtd_tap_listener_name(rtd), rtd_data, tap_filter, 0, NULL((void*)0), get_rtd_packet_func(rtd), sharkd_session_process_tap_rtd_cb, NULL((void*)0));
3805
3806 tap_data = rtd_data;
3807 tap_free = sharkd_session_free_tap_rtd_cb;
3808 }
3809 else if (!strncmp(tok_tap, "srt:", 4))
3810 {
3811 register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
3812 srt_data_t *srt_data;
3813 char *err;
3814
3815 if (!srt)
3816 {
3817 sharkd_json_error(
3818 rpcid, -11009, NULL((void*)0),
3819 "sharkd_session_process_tap() srt=%s not found", tok_tap + 4
3820 );
3821 return;
3822 }
3823
3824 srt_table_get_filter(srt, "", &tap_filter, &err);
3825 if (err != NULL((void*)0))
3826 {
3827 sharkd_json_error(
3828 rpcid, -11010, NULL((void*)0),
3829 "sharkd_session_process_tap() srt=%s err=%s", tok_tap + 4, err
3830 );
3831 g_free(err);
3832 return;
3833 }
3834
3835 srt_data = g_new0(srt_data_t, 1)((srt_data_t *) g_malloc0_n ((1), sizeof (srt_data_t)));
3836 srt_data->srt_array = g_array_new(FALSE(0), TRUE(!(0)), sizeof(srt_stat_table *));
3837 srt_data->user_data = srt;
3838 srt_table_dissector_init(srt, srt_data->srt_array);
3839
3840 tap_error = register_tap_listener(get_srt_tap_listener_name(srt), srt_data, tap_filter, 0, NULL((void*)0), get_srt_packet_func(srt), sharkd_session_process_tap_srt_cb, NULL((void*)0));
3841
3842 tap_data = srt_data;
3843 tap_free = sharkd_session_free_tap_srt_cb;
3844 }
3845 else if (!strncmp(tok_tap, "eo:", 3))
3846 {
3847 register_eo_t *eo = get_eo_by_name(tok_tap + 3);
3848
3849 if (!eo)
3850 {
3851 sharkd_json_error(
3852 rpcid, -11011, NULL((void*)0),
3853 "sharkd_session_process_tap() eo=%s not found", tok_tap + 3
3854 );
3855 return;
3856 }
3857
3858 tap_error = sharkd_session_eo_register_tap_listener(eo, tok_tap, tap_filter, sharkd_session_process_tap_eo_cb, &tap_data, &tap_free);
3859
3860 /* tap_data & tap_free assigned by sharkd_session_eo_register_tap_listener */
3861 }
3862 else if (!strcmp(tok_tap, "rtp-streams"))
3863 {
3864 tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb, NULL((void*)0));
3865
3866 tap_data = &rtp_tapinfo;
3867 tap_free = rtpstream_reset_cb;
3868 }
3869 else if (!strncmp(tok_tap, "rtp-analyse:", 12))
3870 {
3871 struct sharkd_analyse_rtp *rtp_req;
3872
3873 rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
3874 if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12))
3875 {
3876 rtpstream_id_free(&rtp_req->id);
3877 g_free(rtp_req);
3878 continue;
3879 }
3880
3881 rtp_req->tap_name = tok_tap;
3882 rtp_req->statinfo.first_packet = true1;
3883 rtp_req->statinfo.reg_pt = PT_UNDEFINED-1;
3884
3885 tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL((void*)0), sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb, NULL((void*)0));
3886
3887 tap_data = rtp_req;
3888 tap_free = sharkd_session_process_tap_rtp_free_cb;
3889 }
3890 else if (!strcmp(tok_tap, "multicast"))
3891 {
3892 mcaststream_tapinfo_t *mcaststream_tapinfo;
3893 mcaststream_tapinfo = (mcaststream_tapinfo_t *) g_malloc0(sizeof(*mcaststream_tapinfo));
3894
3895 tap_error = register_tap_listener("udp", mcaststream_tapinfo, tap_filter, 0, NULL((void*)0), mcaststream_packet, sharkd_session_process_tap_multicast_cb, NULL((void*)0));
3896 tap_data = mcaststream_tapinfo;
3897 tap_free = sharkd_session_process_free_tap_multicast_cb;
3898 }
3899 else if (!strcmp(tok_tap, "phs"))
3900 {
3901 phs_t *rs;
3902
3903 pc_proto_id = proto_registrar_get_id_byname("pkt_comment");
3904
3905 rs = new_phs_t(NULL((void*)0), tap_filter);
3906
3907 tap_error = register_tap_listener("frame", rs, tap_filter,
3908 TL_REQUIRES_PROTO_TREE0x00000001|TL_REQUIRES_PROTOCOLS0x00000020,
3909 NULL((void*)0), protohierstat_packet,
3910 sharkd_session_process_tap_phs_cb, NULL((void*)0));
3911
3912 tap_data = rs;
3913 tap_free = sharkd_session_free_tap_phs_cb;
3914 }
3915 else if (!strcmp(tok_tap, "voip-calls"))
3916 {
3917 voip_stat_init_tapinfo();
3918
3919 tap_error = register_tap_listener("frame", &tapinfo_, tap_filter, 0, NULL((void*)0), NULL((void*)0), sharkd_session_process_tap_voip_calls_cb, NULL((void*)0));
3920
3921 tapinfo_.session = cfile.epan;
3922 voip_calls_init_all_taps(&tapinfo_);
3923
3924 tap_data = &tapinfo_;
3925 tap_free = sharkd_session_free_tap_voip_calls_cb;
3926 }
3927 else if (!strncmp(tok_tap, "voip-convs:", 11))
3928 {
3929 int len;
3930 unsigned int min, max;
3931 struct sharkd_voip_convs_req *voip_convs_req;
3932 const char *conv_arg = tok_tap + 11;
3933
3934 // parse tok_tap to get which call we are asking for
3935 if (*conv_arg == 0) {
3936 // set all bits of voip_conv_sel (-1 in binary is all 1's)
3937 memset(voip_conv_sel, -1, sizeof(voip_conv_sel));
3938 } else {
3939 memset(voip_conv_sel, 0, sizeof(voip_conv_sel));
3940
3941 while (*conv_arg != 0) {
3942 if (*conv_arg == ',') {
3943 conv_arg++;
3944 }
3945 if (sscanf(conv_arg, "%u-%u%n", &min, &max, &len) == 2) {
3946 conv_arg += len;
3947 } else if (sscanf(conv_arg, "%u%n", &min, &len) == 1) {
3948 max = min;
3949 conv_arg += len;
3950 } else {
3951 sharkd_json_error(
3952 rpcid, -11014, NULL((void*)0),
3953 "sharkd_session_process_tap() voip-convs=%s invalid 'convs' parameter", tok_tap
3954 );
3955 return;
3956 }
3957 if (min > max || min >= VOIP_CONV_MAX((sizeof(int) * 8) * ((1<<(sizeof(uint16_t) * 8))/(sizeof
(int) * 8)))
|| max >= VOIP_CONV_MAX((sizeof(int) * 8) * ((1<<(sizeof(uint16_t) * 8))/(sizeof
(int) * 8)))
) {
3958 sharkd_json_error(
3959 rpcid, -11012, NULL((void*)0),
3960 "sharkd_session_process_tap() voip-convs=%s invalid 'convs' number range", tok_tap
3961 );
3962 return;
3963 }
3964 for(; min <= max; min++) {
3965 voip_conv_sel[min / VOIP_CONV_BITS(sizeof(int) * 8)] |= 1 << (min % VOIP_CONV_BITS(sizeof(int) * 8));
3966 }
3967 }
3968 }
3969
3970 voip_stat_init_tapinfo();
3971
3972 voip_convs_req = (struct sharkd_voip_convs_req *) g_malloc0(sizeof(*voip_convs_req));
3973 voip_convs_req->tapinfo = &tapinfo_;
3974 voip_convs_req->tap_name = tok_tap;
3975
3976 tap_error = register_tap_listener("frame", voip_convs_req, tap_filter, 0, NULL((void*)0), NULL((void*)0), sharkd_session_process_tap_voip_convs_cb, NULL((void*)0));
3977
3978 tapinfo_.session = cfile.epan;
3979 voip_calls_init_all_taps(&tapinfo_);
3980
3981 tap_data = voip_convs_req;
3982 tap_free = sharkd_session_free_tap_voip_convs_cb;
3983 }
3984 else if (!strncmp(tok_tap, "hosts:", 6))
3985 {
3986 bool_Bool dump_v4;
3987 bool_Bool dump_v6;
3988 struct sharkd_hosts_req *hosts_req;
3989 const char *proto_arg;
3990 char **proto_tokens;
3991 int proto_count;
3992
3993 proto_arg = tok_tap + 6;
3994
3995 if (strlen(proto_arg) == 0) {
3996 dump_v4 = true1;
3997 dump_v6 = true1;
3998 } else {
3999 dump_v4 = false0;
4000 dump_v6 = false0;
4001
4002 proto_tokens = g_strsplit(proto_arg, ",", 0);
4003 proto_count = 0;
4004 while (proto_tokens[proto_count]) {
4005 if (!strcmp("ip", proto_tokens[proto_count]) ||
4006 !strcmp("ipv4", proto_tokens[proto_count])) {
4007 dump_v4 = true1;
4008 } else if (!strcmp("ipv6", proto_tokens[proto_count])) {
4009 dump_v6 = true1;
4010 } else {
4011 g_strfreev(proto_tokens);
4012 sharkd_json_error(
4013 rpcid, -11015, NULL((void*)0),
4014 "sharkd_session_process_tap() hosts=%s invalid 'protos' parameter", tok_tap
4015 );
4016 return;
4017 }
4018 proto_count++;
4019 }
4020 g_strfreev(proto_tokens);
4021 }
4022
4023 hosts_req = (struct sharkd_hosts_req *)g_malloc0(sizeof(*hosts_req));
4024 hosts_req->dump_v4 = dump_v4;
4025 hosts_req->dump_v6 = dump_v6;
4026 hosts_req->tap_name = tok_tap;
4027
4028 tap_error = register_tap_listener("frame", hosts_req, tap_filter, TL_REQUIRES_PROTO_TREE0x00000001, NULL((void*)0), NULL((void*)0), sharkd_session_process_tap_hosts_cb, NULL((void*)0));
4029
4030 tap_data = hosts_req;
4031 tap_free = sharkd_session_free_tap_hosts_cb;
4032 }
4033 else
4034 {
4035 sharkd_json_error(
4036 rpcid, -11012, NULL((void*)0),
4037 "sharkd_session_process_tap() %s not recognized", tok_tap
4038 );
4039 return;
4040 }
4041
4042 if (tap_error)
4043 {
4044 sharkd_json_error(
4045 rpcid, -11013, NULL((void*)0),
4046 "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str
4047 );
4048 g_string_free(tap_error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tap_error), ((!(0)))) : g_string_free_and_steal (tap_error))
: (g_string_free) ((tap_error), ((!(0)))))
;
4049 if (tap_free)
4050 tap_free(tap_data);
4051 return;
4052 }
4053
4054 taps_data[taps_count] = tap_data;
4055 taps_free[taps_count] = tap_free;
4056 taps_count++;
4057 }
4058
4059 fprintf(stderrstderr, "sharkd_session_process_tap() count=%d\n", taps_count);
4060 if (taps_count == 0)
4061 {
4062 sharkd_json_result_prologue(rpcid);
4063 sharkd_json_array_open("taps");
4064 sharkd_json_array_close();
4065 sharkd_json_result_epilogue();
4066 return;
4067 }
4068
4069 sharkd_json_result_prologue(rpcid);
4070 sharkd_json_array_open("taps");
4071 sharkd_retap();
4072 sharkd_json_array_close();
4073 sharkd_json_result_epilogue();
4074
4075 for (i = 0; i < taps_count; i++)
4076 {
4077 if (taps_data[i])
4078 remove_tap_listener(taps_data[i]);
4079
4080 if (taps_free[i])
4081 taps_free[i](taps_data[i]);
4082 }
4083}
4084
4085/**
4086 * sharkd_session_process_follow()
4087 *
4088 * Process follow request
4089 *
4090 * Input:
4091 * (m) follow - follow protocol request (e.g. HTTP)
4092 * (m) filter - filter request (e.g. tcp.stream == 1)
4093 * (m) stream - stream index number
4094 * (o) sub_stream - follow sub-stream index number (e.g. for HTTP/2 and QUIC streams)
4095 *
4096 * Output object with attributes:
4097 *
4098 * (m) err - error code
4099 * (m) shost - server host
4100 * (m) sport - server port
4101 * (m) sbytes - server send bytes count
4102 * (m) chost - client host
4103 * (m) cport - client port
4104 * (m) cbytes - client send bytes count
4105 * (o) payloads - array of object with attributes:
4106 * (o) s - set if server sent, else client
4107 * (m) n - packet number
4108 * (m) d - data base64 encoded
4109 */
4110static void
4111sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
4112{
4113 const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
4114 const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
4115 const char *tok_sub_stream = json_find_attr(buf, tokens, count, "sub_stream");
4116
4117 register_follow_t *follower;
4118 GString *tap_error;
4119
4120 follow_info_t *follow_info;
4121 const char *host;
4122 char *port;
4123
4124 follower = get_follow_by_name(tok_follow);
4125 if (!follower)
4126 {
4127 sharkd_json_error(
4128 rpcid, -12001, NULL((void*)0),
4129 "sharkd_session_process_follow() follower=%s not found", tok_follow
4130 );
4131 return;
4132 }
4133
4134 uint64_t substream_id = SUBSTREAM_UNUSED0xFFFFFFFFFFFFFFFFUL;
4135 if (tok_sub_stream)
4136 {
4137 ws_strtou64(tok_sub_stream, NULL((void*)0), &substream_id);
4138 }
4139
4140 /* follow_reset_stream ? */
4141 follow_info = g_new0(follow_info_t, 1)((follow_info_t *) g_malloc0_n ((1), sizeof (follow_info_t)));
4142 follow_info->substream_id = substream_id;
4143 /* gui_data, filter_out_filter not set, but not used by dissector */
4144
4145 tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL((void*)0), get_follow_tap_handler(follower), NULL((void*)0), NULL((void*)0));
4146 if (tap_error)
4147 {
4148 sharkd_json_error(
4149 rpcid, -12002, NULL((void*)0),
4150 "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str
4151 );
4152 g_string_free(tap_error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tap_error), ((!(0)))) : g_string_free_and_steal (tap_error))
: (g_string_free) ((tap_error), ((!(0)))))
;
4153 g_free(follow_info);
4154 return;
4155 }
4156
4157 sharkd_retap();
4158
4159 sharkd_json_result_prologue(rpcid);
4160
4161 /* Server information: hostname, port, bytes sent */
4162 host = address_to_name(&follow_info->server_ip);
4163 sharkd_json_value_string("shost", host);
4164
4165 port = get_follow_port_to_display(follower)(NULL((void*)0), follow_info->server_port);
4166 sharkd_json_value_string("sport", port);
4167 wmem_free(NULL((void*)0), port);
4168
4169 sharkd_json_value_anyf("sbytes", "%u", follow_info->bytes_written[0]);
4170
4171 /* Client information: hostname, port, bytes sent */
4172 host = address_to_name(&follow_info->client_ip);
4173 sharkd_json_value_string("chost", host);
4174
4175 port = get_follow_port_to_display(follower)(NULL((void*)0), follow_info->client_port);
4176 sharkd_json_value_string("cport", port);
4177 wmem_free(NULL((void*)0), port);
4178
4179 sharkd_json_value_anyf("cbytes", "%u", follow_info->bytes_written[1]);
4180
4181 if (follow_info->payload)
4182 {
4183 follow_record_t *follow_record;
4184 GList *cur;
4185
4186 sharkd_json_array_open("payloads");
4187 for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur)((cur) ? (((GList *)(cur))->prev) : ((void*)0)))
4188 {
4189 follow_record = (follow_record_t *) cur->data;
4190
4191 json_dumper_begin_object(&dumper);
4192
4193 sharkd_json_value_anyf("n", "%u", follow_record->packet_num);
4194 sharkd_json_value_base64("d", follow_record->data->data, follow_record->data->len);
4195
4196 if (follow_record->is_server)
4197 sharkd_json_value_anyf("s", "%d", 1);
4198
4199 json_dumper_end_object(&dumper);
4200 }
4201 sharkd_json_array_close();
4202 }
4203
4204 sharkd_json_result_epilogue();
4205
4206 remove_tap_listener(follow_info);
4207 follow_info_free(follow_info);
4208}
4209
4210static void
4211// NOLINTNEXTLINE(misc-no-recursion)
4212sharkd_session_process_frame_cb_tree(const char *key, epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs, bool_Bool display_hidden)
4213{
4214 proto_node *node;
4215
4216 sharkd_json_array_open(key);
4217 for (node = tree->first_child; node; node = node->next)
4218 {
4219 field_info *finfo = PNODE_FINFO(node)((node)->finfo);
4220
4221 if (!finfo)
4222 continue;
4223
4224 if (!display_hidden && FI_GET_FLAG(finfo, FI_HIDDEN)((finfo) ? ((finfo)->flags & (0x00000001)) : 0))
4225 continue;
4226
4227 json_dumper_begin_object(&dumper);
4228
4229 if (!finfo->rep)
4230 {
4231 char label_str[ITEM_LABEL_LENGTH240];
4232
4233 label_str[0] = '\0';
4234 proto_item_fill_label(finfo, label_str, NULL((void*)0));
4235 sharkd_json_value_string("l", label_str);
4236 }
4237 else
4238 {
4239 sharkd_json_value_string("l", finfo->rep->representation);
4240 }
4241
4242 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
4243 {
4244 int idx;
4245
4246 for (idx = 1; tvbs[idx]; idx++)
4247 {
4248 if (tvbs[idx] == finfo->ds_tvb)
4249 {
4250 sharkd_json_value_anyf("ds", "%d", idx);
4251 break;
4252 }
4253 }
4254 }
4255
4256 if (finfo->start >= 0 && finfo->length > 0)
4257 sharkd_json_value_anyf("h", "[%d,%d]", finfo->start, finfo->length);
4258
4259 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
4260 sharkd_json_value_anyf("i", "[%d,%d]", finfo->appendix_start, finfo->appendix_length);
4261
4262
4263 if (finfo->hfinfo)
4264 {
4265 char *filter;
4266
4267 if (finfo->hfinfo->type == FT_PROTOCOL)
4268 {
4269 sharkd_json_value_string("t", "proto");
4270 }
4271 else if (finfo->hfinfo->type == FT_FRAMENUM)
4272 {
4273 sharkd_json_value_string("t", "framenum");
4274 sharkd_json_value_anyf("fnum", "%u", fvalue_get_uinteger(finfo->value));
4275 }
4276 else if (FI_GET_FLAG(finfo, FI_URL)((finfo) ? ((finfo)->flags & (0x00000004)) : 0) && FT_IS_STRING(finfo->hfinfo->type)((finfo->hfinfo->type) == FT_STRING || (finfo->hfinfo
->type) == FT_STRINGZ || (finfo->hfinfo->type) == FT_STRINGZPAD
|| (finfo->hfinfo->type) == FT_STRINGZTRUNC || (finfo->
hfinfo->type) == FT_UINT_STRING || (finfo->hfinfo->type
) == FT_AX25)
)
4277 {
4278 char *url = fvalue_to_string_repr(NULL((void*)0), finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
4279
4280 sharkd_json_value_string("t", "url");
4281 sharkd_json_value_string("url", url);
4282 wmem_free(NULL((void*)0), url);
4283 }
4284
4285 filter = proto_construct_match_selected_string(finfo, edt);
4286 if (filter)
4287 {
4288 sharkd_json_value_string("f", filter);
4289 wmem_free(NULL((void*)0), filter);
4290 }
4291
4292 if (finfo->hfinfo->abbrev)
4293 sharkd_json_value_string("fn", finfo->hfinfo->abbrev);
4294 }
4295
4296 if (FI_GET_FLAG(finfo, FI_GENERATED)((finfo) ? ((finfo)->flags & (0x00000002)) : 0))
4297 sharkd_json_value_anyf("g", "true");
4298
4299 if (FI_GET_FLAG(finfo, FI_HIDDEN)((finfo) ? ((finfo)->flags & (0x00000001)) : 0))
4300 sharkd_json_value_anyf("v", "true");
4301
4302 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK)((finfo) ? ((finfo)->flags & (0x00F00000)) : 0))
4303 {
4304 const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK)((finfo) ? ((finfo)->flags & (0x00F00000)) : 0), expert_severity_vals);
4305
4306 ws_assert(severity != NULL)do { if ((1) && !(severity != ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "sharkd_session.c", 4306, __func__, "assertion failed: %s"
, "severity != ((void*)0)"); } while (0)
;
4307
4308 sharkd_json_value_string("s", severity);
4309 }
4310
4311 if (((proto_tree *) node)->first_child)
4312 {
4313 if (finfo->tree_type != -1)
4314 sharkd_json_value_anyf("e", "%d", finfo->tree_type);
4315
4316 // We recurse here but our depth is limited
4317 sharkd_session_process_frame_cb_tree("n", edt, (proto_tree *) node, tvbs, display_hidden);
4318 }
4319
4320 json_dumper_end_object(&dumper);
4321 }
4322 sharkd_json_array_close();
4323}
4324
4325static bool_Bool
4326sharkd_follower_visit_layers_cb(const void *key _U___attribute__((unused)), void *value, void *user_data)
4327{
4328 register_follow_t *follower = (register_follow_t *) value;
4329 epan_dissect_t *edt = (epan_dissect_t *) user_data;
4330 packet_info *pi = &edt->pi;
4331
4332 const int proto_id = get_follow_proto_id(follower);
4333
4334 uint32_t ignore_stream;
4335 uint32_t ignore_sub_stream;
4336
4337 if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
4338 {
4339 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
4340 char *follow_filter;
4341
4342 follow_filter = get_follow_conv_func(follower)(edt, pi, &ignore_stream, &ignore_sub_stream);
4343
4344 json_dumper_begin_array(&dumper);
4345 json_dumper_value_string(&dumper, layer_proto);
4346 json_dumper_value_string(&dumper, follow_filter);
4347 json_dumper_end_array(&dumper);
4348
4349 g_free(follow_filter);
4350 }
4351
4352 return false0;
4353}
4354
4355static bool_Bool
4356sharkd_followers_visit_layers_cb(const void *key _U___attribute__((unused)), void *value, void *user_data)
4357{
4358 register_follow_t *follower = (register_follow_t *) value;
4359 epan_dissect_t *edt = (epan_dissect_t *) user_data;
4360 packet_info *pi = &edt->pi;
4361
4362 const int proto_id = get_follow_proto_id(follower);
4363
4364 unsigned stream;
4365 unsigned sub_stream;
4366
4367 if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
4368 {
4369 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
4370 char *follow_filter;
4371
4372 follow_filter = get_follow_conv_func(follower)(edt, pi, &stream, &sub_stream);
4373
4374 sharkd_json_object_open(NULL((void*)0));
4375 sharkd_json_value_string("protocol", layer_proto);
4376 sharkd_json_value_string("filter", follow_filter);
4377 if (get_follow_stream_count_func(follower) != NULL((void*)0))
4378 {
4379 sharkd_json_value_anyf("stream", "%u", stream);
4380 }
4381 if (get_follow_sub_stream_id_func(follower) != NULL((void*)0))
4382 {
4383 sharkd_json_value_anyf("sub_stream", "%u", sub_stream);
4384 }
4385 sharkd_json_object_close();
4386
4387 g_free(follow_filter);
4388 }
4389
4390 return false0;
4391}
4392
4393struct sharkd_frame_request_data
4394{
4395 bool_Bool display_hidden;
4396};
4397
4398static void
4399sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
4400{
4401 packet_info *pi = &edt->pi;
4402 frame_data *fdata = pi->fd;
4403 wtap_block_t pkt_block = NULL((void*)0);
4404
4405 const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data;
4406 const bool_Bool display_hidden = (req_data) ? req_data->display_hidden : false0;
4407
4408 sharkd_json_result_prologue(rpcid);
4409
4410 if (fdata->has_modified_block)
4411 pkt_block = sharkd_get_modified_block(fdata);
4412 else
4413 pkt_block = pi->rec->block;
4414
4415 if (pkt_block)
4416 {
4417 unsigned i;
4418 unsigned n;
4419 char *comment;
4420
4421 n = wtap_block_count_option(pkt_block, OPT_COMMENT1);
4422
4423 sharkd_json_array_open("comment");
4424 for (i = 0; i < n; i++) {
4425 if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT1, i, &comment)) {
4426 sharkd_json_value_string(NULL((void*)0), comment);
4427 }
4428 }
4429 sharkd_json_array_close();
4430 }
4431
4432 if (tree)
4433 {
4434 tvbuff_t **tvbs = NULL((void*)0);
4435
4436 /* arrayize data src, to speedup searching for ds_tvb index */
4437 if (data_src && data_src->next /* only needed if there are more than one data source */)
4438 {
4439 unsigned count = g_slist_length((GSList *) data_src);
4440 unsigned i;
4441
4442 tvbs = (tvbuff_t **) g_malloc0((count + 1) * sizeof(*tvbs));
4443
4444 for (i = 0; i < count; i++)
4445 {
4446 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
4447
4448 tvbs[i] = get_data_source_tvb(src);
4449 }
4450
4451 tvbs[count] = NULL((void*)0);
4452 }
4453
4454 sharkd_session_process_frame_cb_tree("tree", edt, tree, tvbs, display_hidden);
4455
4456 g_free(tvbs);
4457 }
4458
4459 if (cinfo)
4460 {
4461 int col;
4462
4463 sharkd_json_array_open("col");
4464 for (col = 0; col < cinfo->num_cols; ++col)
4465 {
4466 sharkd_json_value_string(NULL((void*)0), get_column_text(cinfo, col));
4467 }
4468 sharkd_json_array_close();
4469 }
4470
4471 if (fdata->ignored)
4472 sharkd_json_value_anyf("i", "true");
4473
4474 if (fdata->marked)
4475 sharkd_json_value_anyf("m", "true");
4476
4477 if (fdata->color_filter)
4478 {
4479 sharkd_json_value_stringf("bg", "%06x", color_t_to_rgb(&fdata->color_filter->bg_color));
4480 sharkd_json_value_stringf("fg", "%06x", color_t_to_rgb(&fdata->color_filter->fg_color));
4481 }
4482
4483 if (data_src)
4484 {
4485 struct data_source *src = (struct data_source *) data_src->data;
4486 bool_Bool ds_open = false0;
4487
4488 tvbuff_t *tvb;
4489 unsigned length;
4490
4491 tvb = get_data_source_tvb(src);
4492 length = tvb_captured_length(tvb);
4493
4494 if (length != 0)
4495 {
4496 const unsigned char *cp = tvb_get_ptr(tvb, 0, length);
4497
4498 /* XXX pi.fd->encoding */
4499 sharkd_json_value_base64("bytes", cp, length);
4500 }
4501 else
4502 {
4503 sharkd_json_value_base64("bytes", "", 0);
4504 }
4505
4506 data_src = data_src->next;
4507 if (data_src)
4508 {
4509 sharkd_json_array_open("ds");
4510 ds_open = true1;
4511 }
4512
4513 while (data_src)
4514 {
4515 src = (struct data_source *) data_src->data;
4516
4517 json_dumper_begin_object(&dumper);
4518
4519 {
4520 char *src_description = get_data_source_description(src);
4521
4522 sharkd_json_value_string("name", src_description);
4523 wmem_free(NULL((void*)0), src_description);
4524 }
4525
4526 tvb = get_data_source_tvb(src);
4527 length = tvb_captured_length(tvb);
4528
4529 if (length != 0)
4530 {
4531 const unsigned char *cp = tvb_get_ptr(tvb, 0, length);
4532
4533 /* XXX pi.fd->encoding */
4534 sharkd_json_value_base64("bytes", cp, length);
4535 }
4536 else
4537 {
4538 sharkd_json_value_base64("bytes", "", 0);
4539 }
4540
4541 json_dumper_end_object(&dumper);
4542
4543 data_src = data_src->next;
4544 }
4545
4546 /* close ds, only if was opened */
4547 if (ds_open)
4548 sharkd_json_array_close();
4549 }
4550
4551 sharkd_json_array_open("fol");
4552 follow_iterate_followers(sharkd_follower_visit_layers_cb, edt);
4553 sharkd_json_array_close();
4554
4555 sharkd_json_array_open("followers");
4556 follow_iterate_followers(sharkd_followers_visit_layers_cb, edt);
4557 sharkd_json_array_close();
4558
4559 sharkd_json_result_epilogue();
4560}
4561
4562#define SHARKD_IOGRAPH_MAX_ITEMS1 << 25 1 << 25 /* 33,554,432 limit of items, same as max_io_items_ in ui/qt/io_graph_dialog.h */
4563
4564struct sharkd_iograph
4565{
4566 /* config */
4567 int hf_index;
4568 io_graph_item_unit_t calc_type;
4569 uint32_t interval;
4570 bool_Bool aot;
4571
4572 /* result */
4573 int space_items;
4574 int num_items;
4575 io_graph_item_t *items;
4576 GString *error;
4577};
4578
4579static tap_packet_status
4580sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U___attribute__((unused)), tap_flags_t flags _U___attribute__((unused)))
4581{
4582 struct sharkd_iograph *graph = (struct sharkd_iograph *) g;
4583 int idx;
4584 bool_Bool update_succeeded;
4585
4586 int64_t tmp_idx = get_io_graph_index(pinfo, graph->interval);
4587 if (tmp_idx < 0 || tmp_idx >= SHARKD_IOGRAPH_MAX_ITEMS1 << 25)
1
Assuming 'tmp_idx' is >= 0
2
Assuming the condition is false
3
Taking false branch
4588 return TAP_PACKET_DONT_REDRAW;
4589
4590 idx = (int)tmp_idx;
4591
4592 if (idx + 1 > graph->num_items)
4
Assuming the condition is true
5
Taking true branch
4593 {
4594 if (idx + 1 > graph->space_items)
6
Assuming the condition is false
7
Taking false branch
4595 {
4596 int new_size = idx + 1024;
4597
4598 graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size);
4599 reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items, graph->hf_index);
4600
4601 graph->space_items = new_size;
4602 }
4603 else if (graph->items == NULL((void*)0))
8
Assuming field 'items' is equal to NULL
9
Taking true branch
4604 {
4605 graph->items = g_new(io_graph_item_t, graph->space_items)((io_graph_item_t *) g_malloc_n ((graph->space_items), sizeof
(io_graph_item_t)))
;
10
Uninitialized value stored to field 'first_frame_in_invl'
4606 reset_io_graph_items(graph->items, graph->space_items, graph->hf_index);
11
Calling 'reset_io_graph_items'
14
Returning from 'reset_io_graph_items'
4607 }
4608
4609 graph->num_items = idx + 1;
4610 }
4611
4612 update_succeeded = update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval);
15
Calling 'update_io_graph_item'
4613 /* XXX - TAP_PACKET_FAILED if the item couldn't be updated, with an error message? */
4614 return update_succeeded ? TAP_PACKET_REDRAW : TAP_PACKET_DONT_REDRAW;
4615}
4616
4617/**
4618 * sharkd_session_process_iograph()
4619 *
4620 * Process iograph request
4621 *
4622 * Input:
4623 * (o) interval - interval time, if not specified: 1000
4624 * (o) interval_units - units for interval time, must be 's', 'ms' or 'us', if not specified: ms
4625 * (m) graph0 - First graph request
4626 * (o) graph1...graph9 - Other graph requests
4627 * (o) filter0 - First graph filter
4628 * (o) filter1...filter9 - Other graph filters
4629 *
4630 * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>",
4631 * if you use variant with <field>, you need to pass field name in filter request.
4632 *
4633 * Output object with attributes:
4634 * (m) iograph - array of graph results with attributes:
4635 * errmsg - graph cannot be constructed
4636 * items - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string
4637 */
4638static void
4639sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count)
4640{
4641 const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
4642 const char *tok_interval_units = json_find_attr(buf, tokens, count, "interval_units");
4643 struct sharkd_iograph graphs[10];
4644 bool_Bool is_any_ok = false0;
4645 int graph_count;
4646
4647 int i;
4648
4649 /* default: 1000ms = one per second */
4650 uint32_t interval = 1000;
4651 const char *interval_units = "ms";
4652
4653 if (tok_interval)
4654 ws_strtou32(tok_interval, NULL((void*)0), &interval);
4655
4656 if (tok_interval_units)
4657 {
4658 if (strcmp(tok_interval_units, "us") != 0 &&
4659 strcmp(tok_interval_units, "ms") != 0 &&
4660 strcmp(tok_interval_units, "s") != 0)
4661 {
4662 sharkd_json_error(
4663 rpcid, -7003, NULL((void*)0),
4664 "Invalid interval_units parameter: '%s', must be 's', 'ms' or 'us'", tok_interval_units
4665 );
4666 return;
4667 }
4668 interval_units = tok_interval_units;
4669 }
4670
4671 uint32_t interval_us = 0;
4672 if (strcmp(interval_units, "us") == 0)
4673 {
4674 interval_us = interval;
4675 }
4676 else if (strcmp(interval_units, "ms") == 0)
4677 {
4678 interval_us = 1000 * interval;
4679 }
4680 else if (strcmp(interval_units, "s") == 0)
4681 {
4682 interval_us = 1000000 * interval;
4683 }
4684
4685 for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs)(sizeof (graphs) / sizeof ((graphs)[0])); i++)
4686 {
4687 struct sharkd_iograph *graph = &graphs[graph_count];
4688
4689 const char *tok_graph;
4690 const char *tok_filter;
4691 char tok_format_buf[32];
4692 const char *field_name;
4693 const char *tok_aot;
4694
4695 snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i);
4696 tok_graph = json_find_attr(buf, tokens, count, tok_format_buf);
4697 if (!tok_graph)
4698 break;
4699
4700 snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i);
4701 tok_filter = json_find_attr(buf, tokens, count, tok_format_buf);
4702
4703 if (!strcmp(tok_graph, "packets"))
4704 graph->calc_type = IOG_ITEM_UNIT_PACKETS;
4705 else if (!strcmp(tok_graph, "bytes"))
4706 graph->calc_type = IOG_ITEM_UNIT_BYTES;
4707 else if (!strcmp(tok_graph, "bits"))
4708 graph->calc_type = IOG_ITEM_UNIT_BITS;
4709 else if (g_str_has_prefix(tok_graph, "sum:")(__builtin_constant_p ("sum:")? __extension__ ({ const char *
const __str = (tok_graph); const char * const __prefix = ("sum:"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (tok_graph, "sum:") )
)
4710 graph->calc_type = IOG_ITEM_UNIT_CALC_SUM;
4711 else if (g_str_has_prefix(tok_graph, "frames:")(__builtin_constant_p ("frames:")? __extension__ ({ const char
* const __str = (tok_graph); const char * const __prefix = (
"frames:"); gboolean __result = (0); if (__str == ((void*)0) ||
__prefix == ((void*)0)) __result = (g_str_has_prefix) (__str
, __prefix); else { const size_t __str_len = strlen (((__str)
+ !(__str))); const size_t __prefix_len = strlen (((__prefix
) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (tok_graph, "frames:"
) )
)
4712 graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES;
4713 else if (g_str_has_prefix(tok_graph, "fields:")(__builtin_constant_p ("fields:")? __extension__ ({ const char
* const __str = (tok_graph); const char * const __prefix = (
"fields:"); gboolean __result = (0); if (__str == ((void*)0) ||
__prefix == ((void*)0)) __result = (g_str_has_prefix) (__str
, __prefix); else { const size_t __str_len = strlen (((__str)
+ !(__str))); const size_t __prefix_len = strlen (((__prefix
) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (tok_graph, "fields:"
) )
)
4714 graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS;
4715 else if (g_str_has_prefix(tok_graph, "max:")(__builtin_constant_p ("max:")? __extension__ ({ const char *
const __str = (tok_graph); const char * const __prefix = ("max:"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (tok_graph, "max:") )
)
4716 graph->calc_type = IOG_ITEM_UNIT_CALC_MAX;
4717 else if (g_str_has_prefix(tok_graph, "min:")(__builtin_constant_p ("min:")? __extension__ ({ const char *
const __str = (tok_graph); const char * const __prefix = ("min:"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (tok_graph, "min:") )
)
4718 graph->calc_type = IOG_ITEM_UNIT_CALC_MIN;
4719 else if (g_str_has_prefix(tok_graph, "avg:")(__builtin_constant_p ("avg:")? __extension__ ({ const char *
const __str = (tok_graph); const char * const __prefix = ("avg:"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (tok_graph, "avg:") )
)
4720 graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE;
4721 else if (g_str_has_prefix(tok_graph, "load:")(__builtin_constant_p ("load:")? __extension__ ({ const char *
const __str = (tok_graph); const char * const __prefix = ("load:"
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (tok_graph, "load:") )
)
4722 graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD;
4723 else if (g_str_has_prefix(tok_graph, "throughput:")(__builtin_constant_p ("throughput:")? __extension__ ({ const
char * const __str = (tok_graph); const char * const __prefix
= ("throughput:"); gboolean __result = (0); if (__str == ((void
*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix)
(__str, __prefix); else { const size_t __str_len = strlen ((
(__str) + !(__str))); const size_t __prefix_len = strlen (((__prefix
) + !(__prefix))); if (__str_len >= __prefix_len) __result
= memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len
) == 0; } __result; }) : (g_str_has_prefix) (tok_graph, "throughput:"
) )
)
4724 graph->calc_type = IOG_ITEM_UNIT_CALC_THROUGHPUT;
4725 else
4726 break;
4727
4728 field_name = strchr(tok_graph, ':');
4729 if (field_name)
4730 field_name = field_name + 1;
4731
4732 /* io_graph_item now supports microseconds (and this parameter
4733 * is expected to be in microseconds.) */
4734 graph->interval = interval_us;
4735
4736 graph->hf_index = -1;
4737 graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type);
4738
4739 graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */
4740 graph->num_items = 0;
4741 graph->items = NULL((void*)0);
4742
4743 snprintf(tok_format_buf, sizeof(tok_format_buf), "aot%d", i);
4744 tok_aot = json_find_attr(buf, tokens, count, tok_format_buf);
4745 if (tok_aot!=NULL((void*)0)) {
4746 graph->aot = (!strcmp(tok_aot, "true")) ? true1 : false0;
4747 }
4748 else {
4749 graph->aot = false0;
4750 }
4751
4752 if (!graph->error)
4753 graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE0x00000001, NULL((void*)0), sharkd_iograph_packet, NULL((void*)0), NULL((void*)0));
4754
4755 graph_count++;
4756
4757 if (graph->error)
4758 {
4759 sharkd_json_error(
4760 rpcid, -6001, NULL((void*)0),
4761 "%s", graph->error->str
4762 );
4763 g_string_free(graph->error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(graph->error), ((!(0)))) : g_string_free_and_steal (graph
->error)) : (g_string_free) ((graph->error), ((!(0)))))
;
4764 return;
4765 }
4766
4767 if (graph->error == NULL((void*)0))
4768 is_any_ok = true1;
4769 }
4770
4771 /* retap only if we have at least one ok */
4772 if (is_any_ok)
4773 sharkd_retap();
4774
4775 sharkd_json_result_prologue(rpcid);
4776
4777 sharkd_json_array_open("iograph");
4778 for (i = 0; i < graph_count; i++)
4779 {
4780 struct sharkd_iograph *graph = &graphs[i];
4781
4782 json_dumper_begin_object(&dumper);
4783
4784 if (graph->error)
4785 {
4786 fprintf(stderrstderr, "SNAP 6002 - we should never get to here.\n");
4787 g_string_free(graph->error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(graph->error), ((!(0)))) : g_string_free_and_steal (graph
->error)) : (g_string_free) ((graph->error), ((!(0)))))
;
4788 exit(-1);
4789 }
4790 else
4791 {
4792 int idx;
4793 int next_idx = 0;
4794
4795 sharkd_json_array_open("items");
4796 for (idx = 0; idx < graph->num_items; idx++)
4797 {
4798 double val;
4799
4800 val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items, graph->aot);
4801
4802 /* if it's zero, don't display */
4803 if (val == 0.0)
4804 continue;
4805
4806 /* cause zeros are not printed, need to output index */
4807 if (next_idx != idx)
4808 sharkd_json_value_stringf(NULL((void*)0), "%x", idx);
4809
4810 sharkd_json_value_anyf(NULL((void*)0), "%f", val);
4811 next_idx = idx + 1;
4812 }
4813 sharkd_json_array_close();
4814 }
4815 json_dumper_end_object(&dumper);
4816
4817 remove_tap_listener(graph);
4818 g_free(graph->items);
4819 }
4820 sharkd_json_array_close();
4821
4822 sharkd_json_result_epilogue();
4823}
4824
4825/**
4826 * sharkd_session_process_intervals()
4827 *
4828 * Process intervals request - generate basic capture file statistics per requested interval.
4829 *
4830 * Input:
4831 * (o) interval - interval time in ms, if not specified: 1000ms
4832 * (o) filter - filter for generating interval request
4833 *
4834 * Output object with attributes:
4835 * (m) intervals - array of intervals, with indexes:
4836 * [0] - index of interval,
4837 * [1] - number of frames during interval,
4838 * [2] - number of bytes during interval.
4839 *
4840 * (m) last - last interval number.
4841 * (m) frames - total number of frames
4842 * (m) bytes - total number of bytes
4843 *
4844 * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
4845 */
4846static void
4847sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
4848{
4849 const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
4850 const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
4851
4852 const uint8_t *filter_data = NULL((void*)0);
4853
4854 struct
4855 {
4856 unsigned int frames;
4857 uint64_t bytes;
4858 } st, st_total;
4859
4860 nstime_t *start_ts;
4861
4862 uint32_t interval_ms = 1000; /* default: one per second */
4863
4864 int64_t idx;
4865 int64_t max_idx = 0;
4866
4867 if (tok_interval)
4868 ws_strtou32(tok_interval, NULL((void*)0), &interval_ms); // already validated
4869
4870 if (tok_filter)
4871 {
4872 const struct sharkd_filter_item *filter_item;
4873
4874 filter_item = sharkd_session_filter_data(tok_filter);
4875 if (!filter_item)
4876 {
4877 sharkd_json_error(
4878 rpcid, -7001, NULL((void*)0),
4879 "Invalid filter parameter: %s", tok_filter
4880 );
4881 return;
4882 }
4883 filter_data = filter_item->filtered;
4884 }
4885
4886 st_total.frames = 0;
4887 st_total.bytes = 0;
4888
4889 st.frames = 0;
4890 st.bytes = 0;
4891
4892 idx = 0;
4893
4894 sharkd_json_result_prologue(rpcid);
4895 sharkd_json_array_open("intervals");
4896
4897 start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL((void*)0);
4898
4899 for (uint32_t framenum = 1; framenum <= cfile.count; framenum++)
4900 {
4901 frame_data *fdata;
4902 int64_t msec_rel;
4903 int64_t new_idx;
4904
4905 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
4906 continue;
4907
4908 fdata = sharkd_get_frame(framenum);
4909
4910 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (int64_t) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
4911 new_idx = msec_rel / interval_ms;
4912
4913 if (idx != new_idx)
4914 {
4915 if (st.frames != 0)
4916 {
4917 sharkd_json_value_anyf(NULL((void*)0), "[%" PRId64"l" "d" ",%u,%" PRIu64"l" "u" "]", idx, st.frames, st.bytes);
4918 }
4919
4920 idx = new_idx;
4921 if (idx > max_idx)
4922 max_idx = idx;
4923
4924 st.frames = 0;
4925 st.bytes = 0;
4926 }
4927
4928 st.frames += 1;
4929 st.bytes += fdata->pkt_len;
4930
4931 st_total.frames += 1;
4932 st_total.bytes += fdata->pkt_len;
4933 }
4934
4935 if (st.frames != 0)
4936 {
4937 sharkd_json_value_anyf(NULL((void*)0), "[%" PRId64"l" "d" ",%u,%" PRIu64"l" "u" "]", idx, st.frames, st.bytes);
4938 }
4939 sharkd_json_array_close();
4940
4941 sharkd_json_value_anyf("last", "%" PRId64"l" "d", max_idx);
4942 sharkd_json_value_anyf("frames", "%u", st_total.frames);
4943 sharkd_json_value_anyf("bytes", "%" PRIu64"l" "u", st_total.bytes);
4944
4945 sharkd_json_result_epilogue();
4946}
4947
4948/**
4949 * sharkd_session_process_frame()
4950 *
4951 * Process frame request
4952 *
4953 * Input:
4954 * (m) frame - requested frame number
4955 * (o) ref_frame - time reference frame number
4956 * (o) prev_frame - previously displayed frame number
4957 * (o) proto - set if output frame tree
4958 * (o) columns - set if output frame columns
4959 * (o) color - set if output color-filter bg/fg
4960 * (o) bytes - set if output frame bytes
4961 * (o) hidden - set if output hidden tree fields
4962 *
4963 * Output object with attributes:
4964 * (m) err - 0 if succeed
4965 * (o) tree - array of frame nodes with attributes:
4966 * l - label
4967 * t: 'proto', 'framenum', 'url' - type of node
4968 * f - filter string
4969 * fn - field name
4970 * s - severity
4971 * e - subtree ett index
4972 * n - array of subtree nodes
4973 * h - two item array: (item start, item length)
4974 * i - two item array: (appendix start, appendix length)
4975 * p - [RESERVED] two item array: (protocol start, protocol length)
4976 * ds- data src index
4977 * url - only for t:'url', url
4978 * fnum - only for t:'framenum', frame number
4979 * g - if field is generated by Wireshark
4980 * v - if field is hidden
4981 *
4982 * (o) col - array of column data
4983 * (o) bytes - base64 of frame bytes
4984 * (o) ds - array of other data srcs
4985 * (o) comment - frame comment
4986 * (o) fol - array of follow filters:
4987 * [0] - protocol
4988 * [1] - filter string
4989 * (o) followers - array of followers with attributes:
4990 * protocol - protocol string
4991 * filter - filter string
4992 * stream - stream index number
4993 * sub_stream - sub-stream index number (optional, e.g. for HTTP/2 and QUIC streams)
4994 * (o) i - if frame is ignored
4995 * (o) m - if frame is marked
4996 * (o) bg - color filter - background color in hex
4997 * (o) fg - color filter - foreground color in hex
4998 */
4999static void
5000sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
5001{
5002 const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
5003 const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame");
5004 const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame");
5005 column_info *cinfo = NULL((void*)0);
5006
5007 uint32_t framenum, ref_frame_num, prev_dis_num;
5008 uint32_t dissect_flags = SHARKD_DISSECT_FLAG_NULL0x00u;
5009 struct sharkd_frame_request_data req_data;
5010 wtap_rec rec; /* Record information */
5011 enum dissect_request_status status;
5012 int err;
5013 char *err_info;
5014
5015 ws_strtou32(tok_frame, NULL((void*)0), &framenum); // we have already validated this
5016
5017 ref_frame_num = (framenum != 1) ? 1 : 0;
5018 if (tok_ref_frame)
5019 {
5020 ws_strtou32(tok_ref_frame, NULL((void*)0), &ref_frame_num);
5021 if (ref_frame_num > framenum)
5022 {
5023 sharkd_json_error(
5024 rpcid, -8001, NULL((void*)0),
5025 "Invalid ref_frame - The ref_frame occurs after the frame specified"
5026 );
5027 return;
5028 }
5029 }
5030
5031 prev_dis_num = framenum - 1;
5032 if (tok_prev_frame)
5033 {
5034 ws_strtou32(tok_prev_frame, NULL((void*)0), &prev_dis_num);
5035 if (prev_dis_num >= framenum)
5036 {
5037 sharkd_json_error(
5038 rpcid, -8002, NULL((void*)0),
5039 "Invalid prev_frame - The prev_frame occurs on or after the frame specified"
5040 );
5041 return;
5042 }
5043 }
5044
5045 if (json_find_attr(buf, tokens, count, "proto") != NULL((void*)0))
5046 dissect_flags |= SHARKD_DISSECT_FLAG_PROTO_TREE0x04u;
5047 if (json_find_attr(buf, tokens, count, "bytes") != NULL((void*)0))
5048 dissect_flags |= SHARKD_DISSECT_FLAG_BYTES0x01u;
5049 if (json_find_attr(buf, tokens, count, "columns") != NULL((void*)0)) {
5050 dissect_flags |= SHARKD_DISSECT_FLAG_COLUMNS0x02u;
5051 cinfo = &cfile.cinfo;
5052 }
5053 if (json_find_attr(buf, tokens, count, "color") != NULL((void*)0))
5054 dissect_flags |= SHARKD_DISSECT_FLAG_COLOR0x08u;
5055
5056 req_data.display_hidden = (json_find_attr(buf, tokens, count, "v") != NULL((void*)0));
5057
5058 wtap_rec_init(&rec, 1514);
5059
5060 status = sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num,
5061 &rec, cinfo, dissect_flags,
5062 &sharkd_session_process_frame_cb, &req_data, &err, &err_info);
5063 switch (status) {
5064
5065 case DISSECT_REQUEST_SUCCESS:
5066 /* success */
5067 break;
5068
5069 case DISSECT_REQUEST_NO_SUCH_FRAME:
5070 sharkd_json_error(
5071 rpcid, -8003, NULL((void*)0),
5072 "Invalid frame - The frame number requested is out of range"
5073 );
5074 break;
5075
5076 case DISSECT_REQUEST_READ_ERROR:
5077 sharkd_json_error(
5078 rpcid, -8003, NULL((void*)0),
5079 /* XXX - show the error details */
5080 "Read error - The frame could not be read from the file"
5081 );
5082 g_free(err_info);
5083 break;
5084 }
5085
5086 wtap_rec_cleanup(&rec);
5087}
5088
5089/**
5090 * sharkd_session_process_check()
5091 *
5092 * Process check request.
5093 *
5094 * Input:
5095 * (o) filter - filter to be checked
5096 * (o) field - field to be checked
5097 *
5098 * Output object with attributes:
5099 * (m) err - always 0
5100 * (o) filter - 'ok', 'warn' or error message
5101 * (o) field - 'ok', or 'notfound'
5102 */
5103static int
5104sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
5105{
5106 const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
5107 const char *tok_field = json_find_attr(buf, tokens, count, "field");
5108
5109 if (tok_filter != NULL((void*)0))
5110 {
5111 dfilter_t *dfp;
5112 df_error_t *df_err = NULL((void*)0);
5113
5114 if (dfilter_compile(tok_filter, &dfp, &df_err)dfilter_compile_full(tok_filter, &dfp, &df_err, (1U <<
1)|(1U << 2), __func__)
)
5115 {
5116 if (dfp && dfilter_deprecated_tokens(dfp))
5117 sharkd_json_warning(rpcid, "Filter contains deprecated tokens");
5118 else
5119 sharkd_json_simple_ok(rpcid);
5120
5121 dfilter_free(dfp);
5122 df_error_free(&df_err);
5123 return 0;
5124 }
5125 else
5126 {
5127 sharkd_json_error(
5128 rpcid, -5001, NULL((void*)0),
5129 "Filter invalid - %s", df_err->msg
5130 );
5131 df_error_free(&df_err);
5132 return -5001;
5133 }
5134 }
5135
5136 if (tok_field != NULL((void*)0))
5137 {
5138 header_field_info *hfi = proto_registrar_get_byname(tok_field);
5139
5140 if (!hfi)
5141 {
5142 sharkd_json_error(
5143 rpcid, -5002, NULL((void*)0),
5144 "Field %s not found", tok_field
5145 );
5146 return -5002;
5147 }
5148 else
5149 {
5150 sharkd_json_simple_ok(rpcid);
5151 return 0;
5152 }
5153 }
5154
5155 sharkd_json_simple_ok(rpcid);
5156 return 0;
5157}
5158
5159struct sharkd_session_process_complete_pref_data
5160{
5161 const char *module;
5162 const char *pref;
5163};
5164
5165static unsigned
5166sharkd_session_process_complete_pref_cb(module_t *module, void *d)
5167{
5168 struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
5169
5170 if (strncmp(data->pref, module->name, strlen(data->pref)) != 0)
5171 return 0;
5172
5173 json_dumper_begin_object(&dumper);
5174 sharkd_json_value_string("f", module->name);
5175 sharkd_json_value_string("d", module->title);
5176 json_dumper_end_object(&dumper);
5177
5178 return 0;
5179}
5180
5181static unsigned
5182sharkd_session_process_complete_pref_option_cb(pref_t *pref, void *d)
5183{
5184 struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
5185 const char *pref_name = prefs_get_name(pref);
5186 const char *pref_title = prefs_get_title(pref);
5187
5188 if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0)
5189 return 0;
5190
5191 json_dumper_begin_object(&dumper);
5192 sharkd_json_value_stringf("f", "%s.%s", data->module, pref_name);
5193 sharkd_json_value_string("d", pref_title);
5194 json_dumper_end_object(&dumper);
5195
5196 return 0; /* continue */
5197}
5198
5199/**
5200 * sharkd_session_process_complete()
5201 *
5202 * Process complete request
5203 *
5204 * Input:
5205 * (o) field - field to be completed
5206 * (o) pref - preference to be completed
5207 *
5208 * Output object with attributes:
5209 * (m) err - always 0
5210 * (o) field - array of object with attributes:
5211 * (m) f - field text
5212 * (o) t - field type (FT_ number)
5213 * (o) n - field name
5214 * (o) pref - array of object with attributes:
5215 * (m) f - pref name
5216 * (o) d - pref description
5217 */
5218static int
5219sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count)
5220{
5221 const char *tok_field = json_find_attr(buf, tokens, count, "field");
5222 const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
5223
5224 sharkd_json_result_prologue(rpcid);
5225
5226 if (tok_field != NULL((void*)0) && tok_field[0])
5227 {
5228 const size_t filter_length = strlen(tok_field);
5229 const int filter_with_dot = !!strchr(tok_field, '.');
5230
5231 void *proto_cookie;
5232 void *field_cookie;
5233 int proto_id;
5234
5235 sharkd_json_array_open("field");
5236
5237 for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie))
5238 {
5239 protocol_t *protocol = find_protocol_by_id(proto_id);
5240 const char *protocol_filter;
5241 const char *protocol_name;
5242 header_field_info *hfinfo;
5243
5244 if (!proto_is_protocol_enabled(protocol))
5245 continue;
5246
5247 protocol_name = proto_get_protocol_long_name(protocol);
5248 protocol_filter = proto_get_protocol_filter_name(proto_id);
5249
5250 if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length))
5251 {
5252 json_dumper_begin_object(&dumper);
5253 {
5254 sharkd_json_value_string("f", protocol_filter);
5255 sharkd_json_value_anyf("t", "%d", FT_PROTOCOL);
5256 sharkd_json_value_string("n", protocol_name);
5257 }
5258 json_dumper_end_object(&dumper);
5259 }
5260
5261 if (!filter_with_dot)
5262 continue;
5263
5264 for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL((void*)0); hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie))
5265 {
5266 if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
5267 continue;
5268
5269 if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length))
5270 {
5271 json_dumper_begin_object(&dumper);
5272 {
5273 sharkd_json_value_string("f", hfinfo->abbrev);
5274
5275 /* XXX, skip displaying name, if there are multiple (to not confuse user) */
5276 if (hfinfo->same_name_next == NULL((void*)0))
5277 {
5278 sharkd_json_value_anyf("t", "%d", hfinfo->type);
5279 sharkd_json_value_string("n", hfinfo->name);
5280 }
5281 }
5282 json_dumper_end_object(&dumper);
5283 }
5284 }
5285 }
5286
5287 sharkd_json_array_close();
5288 }
5289
5290 if (tok_pref != NULL((void*)0) && tok_pref[0])
5291 {
5292 struct sharkd_session_process_complete_pref_data data;
5293 char *dot_sepa;
5294
5295 data.module = tok_pref;
5296 data.pref = tok_pref;
5297
5298 sharkd_json_array_open("pref");
5299 if ((dot_sepa = strchr(tok_pref, '.')))
5300 {
5301 module_t *pref_mod;
5302
5303 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
5304 data.pref = dot_sepa + 1;
5305
5306 pref_mod = prefs_find_module(data.module);
5307 if (pref_mod)
5308 prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data);
5309
5310 *dot_sepa = '.';
5311 }
5312 else
5313 {
5314 prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data);
5315 }
5316 sharkd_json_array_close();
5317 }
5318
5319 sharkd_json_result_epilogue();
5320
5321 return 0;
5322}
5323
5324/**
5325 * sharkd_session_process_setcomment()
5326 *
5327 * Process setcomment request
5328 *
5329 * Input:
5330 * (m) frame - frame number
5331 * (o) comment - user comment
5332 *
5333 * Output object with attributes:
5334 * (m) err - error code: 0 succeed
5335 *
5336 * Note:
5337 * For now, adds comments, doesn't remove or replace them.
5338 */
5339static void
5340sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count)
5341{
5342 const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
5343 const char *tok_comment = json_find_attr(buf, tokens, count, "comment");
5344
5345 uint32_t framenum;
5346 frame_data *fdata;
5347 wtap_opttype_return_val ret;
5348 wtap_block_t pkt_block = NULL((void*)0);
5349
5350 if (!tok_frame || !ws_strtou32(tok_frame, NULL((void*)0), &framenum) || framenum == 0)
5351 {
5352 sharkd_json_error(
5353 rpcid, -3001, NULL((void*)0),
5354 "Frame number must be a positive integer"
5355 );
5356 return;
5357 }
5358
5359 fdata = sharkd_get_frame(framenum); // BUG HERE - If no file loaded you get a crash
5360 if (!fdata)
5361 {
5362 sharkd_json_error(
5363 rpcid, -3002, NULL((void*)0),
5364 "Frame number is out of range"
5365 );
5366 return;
5367 }
5368
5369 pkt_block = sharkd_get_packet_block(fdata);
5370
5371 ret = wtap_block_add_string_option(pkt_block, OPT_COMMENT1, tok_comment, strlen(tok_comment));
5372
5373 if (ret != WTAP_OPTTYPE_SUCCESS)
5374 {
5375 sharkd_json_error(
5376 rpcid, -3003, NULL((void*)0),
5377 "Unable to set the comment"
5378 );
5379 }
5380 else
5381 {
5382 sharkd_set_modified_block(fdata, pkt_block);
5383 sharkd_json_simple_ok(rpcid);
5384 }
5385}
5386
5387/**
5388 * sharkd_session_process_setconf()
5389 *
5390 * Process setconf request
5391 *
5392 * Input:
5393 * (m) name - preference name
5394 * (m) value - preference value
5395 *
5396 * Output object with attributes:
5397 * (m) err - error code: 0 succeed
5398 */
5399static void
5400sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count)
5401{
5402 const char *tok_name = json_find_attr(buf, tokens, count, "name");
5403 const char *tok_value = json_find_attr(buf, tokens, count, "value");
5404 char pref[4096];
5405 char *errmsg = NULL((void*)0);
5406
5407 prefs_set_pref_e ret;
5408
5409 if (!tok_name || tok_name[0] == '\0')
5410 {
5411 sharkd_json_error(
5412 rpcid, -4001, NULL((void*)0),
5413 "Preference name missing"
5414 );
5415 return;
5416 }
5417
5418 if (!tok_value)
5419 {
5420 sharkd_json_error(
5421 rpcid, -4002, NULL((void*)0),
5422 "Preference value missing"
5423 );
5424 return;
5425 }
5426
5427 snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value);
5428
5429 ret = prefs_set_pref(pref, &errmsg);
5430
5431 switch (ret)
5432 {
5433 case PREFS_SET_OK:
5434 sharkd_json_simple_ok(rpcid);
5435 break;
5436
5437 case PREFS_SET_OBSOLETE:
5438 sharkd_json_error(
5439 rpcid, -4003, NULL((void*)0),
5440 "The preference specified is obsolete"
5441 );
5442 break;
5443
5444 case PREFS_SET_NO_SUCH_PREF:
5445 sharkd_json_error(
5446 rpcid, -4004, NULL((void*)0),
5447 "No such preference exists"
5448 );
5449 break;
5450
5451 default:
5452 sharkd_json_error(
5453 rpcid, -4005, NULL((void*)0),
5454 "Unable to set the preference%s%s",
5455 errmsg ? ": " : "", errmsg ? errmsg : ""
5456 );
5457 }
5458
5459 g_free(errmsg);
5460}
5461
5462struct sharkd_session_process_dumpconf_data
5463{
5464 module_t *module;
5465};
5466
5467static unsigned
5468sharkd_session_process_dumpconf_cb(pref_t *pref, void *d)
5469{
5470 struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
5471 const char *pref_name = prefs_get_name(pref);
5472
5473 char json_pref_key[512];
5474
5475 snprintf(json_pref_key, sizeof(json_pref_key), "%s.%s", data->module->name, pref_name);
5476 sharkd_json_object_open(json_pref_key);
5477
5478 if (!prefs_is_preference_obsolete(pref)) {
5479 switch (prefs_get_type(pref))
5480 {
5481 case PREF_UINT:
5482 sharkd_json_value_anyf("u", "%u", prefs_get_uint_value(pref, pref_current));
5483 if (prefs_get_uint_base(pref) != 10)
5484 sharkd_json_value_anyf("ub", "%u", prefs_get_uint_base(pref));
5485 break;
5486
5487 case PREF_BOOL:
5488 sharkd_json_value_anyf("b", prefs_get_bool_value(pref, pref_current) ? "1" : "0");
5489 break;
5490
5491 case PREF_STRING:
5492 case PREF_SAVE_FILENAME:
5493 case PREF_OPEN_FILENAME:
5494 case PREF_DIRNAME:
5495 case PREF_PASSWORD:
5496 case PREF_DISSECTOR:
5497 sharkd_json_value_string("s", prefs_get_string_value(pref, pref_current));
5498 break;
5499
5500 case PREF_ENUM:
5501 {
5502 const enum_val_t *enums;
5503
5504 sharkd_json_array_open("e");
5505 for (enums = prefs_get_enumvals(pref); enums->name; enums++)
5506 {
5507 json_dumper_begin_object(&dumper);
5508
5509 sharkd_json_value_anyf("v", "%d", enums->value);
5510
5511 if (enums->value == prefs_get_enum_value(pref, pref_current))
5512 sharkd_json_value_anyf("s", "1");
5513
5514 sharkd_json_value_string("d", enums->description);
5515
5516 json_dumper_end_object(&dumper);
5517 }
5518 sharkd_json_array_close();
5519 break;
5520 }
5521
5522 case PREF_RANGE:
5523 case PREF_DECODE_AS_RANGE:
5524 {
5525 char *range_str = range_convert_range(NULL((void*)0), prefs_get_range_value_real(pref, pref_current));
5526 sharkd_json_value_string("r", range_str);
5527 wmem_free(NULL((void*)0), range_str);
5528 break;
5529 }
5530
5531 case PREF_UAT:
5532 {
5533 uat_t *uat = prefs_get_uat_value(pref);
5534 unsigned idx;
5535
5536 sharkd_json_array_open("t");
5537 for (idx = 0; idx < uat->raw_data->len; idx++)
5538 {
5539 void *rec = UAT_INDEX_PTR(uat, idx)(uat->raw_data->data + (uat->record_size * (idx)));
5540 unsigned colnum;
5541
5542 sharkd_json_array_open(NULL((void*)0));
5543 for (colnum = 0; colnum < uat->ncols; colnum++)
5544 {
5545 char *str = uat_fld_tostr(rec, &(uat->fields[colnum]));
5546
5547 sharkd_json_value_string(NULL((void*)0), str);
5548 g_free(str);
5549 }
5550
5551 sharkd_json_array_close();
5552 }
5553
5554 sharkd_json_array_close();
5555 break;
5556 }
5557
5558 case PREF_COLOR:
5559 case PREF_CUSTOM:
5560 case PREF_STATIC_TEXT:
5561 /* TODO */
5562 break;
5563 }
5564 }
5565
5566#if 0
5567 sharkd_json_value_string("t", prefs_get_title(pref));
5568#endif
5569
5570 sharkd_json_object_close();
5571
5572 return 0; /* continue */
5573}
5574
5575static unsigned
5576sharkd_session_process_dumpconf_mod_cb(module_t *module, void *d)
5577{
5578 struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
5579
5580 data->module = module;
5581 prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data);
5582
5583 return 0;
5584}
5585
5586/**
5587 * sharkd_session_process_dumpconf()
5588 *
5589 * Process dumpconf request
5590 *
5591 * Input:
5592 * (o) pref - module, or preference, NULL for all
5593 *
5594 * Output object with attributes:
5595 * (o) prefs - object with module preferences
5596 * (m) [KEY] - preference name
5597 * (o) u - preference value (for PREF_UINT)
5598 * (o) ub - preference value suggested base for display (for PREF_UINT) and if different than 10
5599 * (o) b - preference value (only for PREF_BOOL) (1 true, 0 false)
5600 * (o) s - preference value (for PREF_STRING, PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME, PREF_PASSWORD, PREF_DISSECTOR)
5601 * (o) e - preference possible values (only for PREF_ENUM)
5602 * (o) r - preference value (for PREF_RANGE, PREF_DECODE_AS_RANGE)
5603 * (o) t - preference value (only for PREF_UAT)
5604 */
5605static void
5606sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
5607{
5608 const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
5609 module_t *pref_mod;
5610 char *dot_sepa;
5611
5612 if (!tok_pref)
5613 {
5614 struct sharkd_session_process_dumpconf_data data;
5615
5616 data.module = NULL((void*)0);
5617
5618 sharkd_json_result_prologue(rpcid);
5619
5620 sharkd_json_object_open("prefs");
5621 prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data);
5622 sharkd_json_object_close();
5623
5624 sharkd_json_result_epilogue();
5625 return;
5626 }
5627
5628 if ((dot_sepa = strchr(tok_pref, '.')))
5629 {
5630 pref_t *pref = NULL((void*)0);
5631
5632 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
5633 pref_mod = prefs_find_module(tok_pref);
5634 if (pref_mod)
5635 pref = prefs_find_preference(pref_mod, dot_sepa + 1);
5636 *dot_sepa = '.';
5637
5638 if (pref)
5639 {
5640 struct sharkd_session_process_dumpconf_data data;
5641
5642 data.module = pref_mod;
5643
5644 sharkd_json_result_prologue(rpcid);
5645
5646 sharkd_json_object_open("prefs");
5647 sharkd_session_process_dumpconf_cb(pref, &data);
5648 sharkd_json_object_close();
5649
5650 sharkd_json_result_epilogue();
5651 return;
5652 }
5653 else
5654 {
5655 sharkd_json_error(
5656 rpcid, -9001, NULL((void*)0),
5657 "Invalid pref %s.", tok_pref
5658 );
5659 return;
5660 }
5661
5662 }
5663
5664 pref_mod = prefs_find_module(tok_pref);
5665 if (pref_mod)
5666 {
5667 struct sharkd_session_process_dumpconf_data data;
5668
5669 data.module = pref_mod;
5670
5671 sharkd_json_result_prologue(rpcid);
5672
5673 sharkd_json_object_open("prefs");
5674 prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data);
5675 sharkd_json_object_close();
5676
5677 sharkd_json_result_epilogue();
5678 }
5679 else
5680 {
5681 sharkd_json_error(
5682 rpcid, -9002, NULL((void*)0),
5683 "Invalid pref %s.", tok_pref
5684 );
5685 }
5686}
5687
5688struct sharkd_download_rtp
5689{
5690 rtpstream_id_t id;
5691 GSList *packets;
5692 double start_time;
5693};
5694
5695static void
5696sharkd_rtp_download_free_items(void *ptr)
5697{
5698 rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr;
5699
5700 g_free(rtp_packet->info);
5701 g_free(rtp_packet->payload_data);
5702 g_free(rtp_packet);
5703}
5704
5705static void
5706sharkd_rtp_download_decode(struct sharkd_download_rtp *req)
5707{
5708 /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */
5709 /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */
5710
5711 static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char);
5712
5713 uint32_t audio_out_rate_ = 0;
5714 struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new();
5715 struct SpeexResamplerState_ *audio_resampler_ = NULL((void*)0);
5716
5717 size_t resample_buff_len = 0x1000;
5718 SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len);
5719 spx_uint32_t cur_in_rate = 0;
5720 char *write_buff = NULL((void*)0);
5721 size_t write_bytes = 0;
5722 unsigned channels = 0;
5723 unsigned sample_rate = 0;
5724
5725 GSList *l;
5726
5727 for (l = req->packets; l; l = l->next)
5728 {
5729 rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data;
5730
5731 SAMPLE *decode_buff = NULL((void*)0);
5732 size_t decoded_bytes;
5733
5734 decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate);
5735 if (decoded_bytes == 0 || sample_rate == 0)
5736 {
5737 /* We didn't decode anything. Clean up and prep for the next packet. */
5738 g_free(decode_buff);
5739 continue;
5740 }
5741
5742 if (audio_out_rate_ == 0)
5743 {
5744 uint32_t tmp32;
5745 uint16_t tmp16;
5746 char wav_hdr[44];
5747
5748 /* First non-zero wins */
5749 audio_out_rate_ = sample_rate;
5750
5751 RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_);
5752
5753 /* write WAVE header */
5754 memset(&wav_hdr, 0, sizeof(wav_hdr));
5755 memcpy(&wav_hdr[0], "RIFF", 4);
5756 memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
5757 memcpy(&wav_hdr[8], "WAVE", 4);
5758
5759 memcpy(&wav_hdr[12], "fmt ", 4);
5760 memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */
5761 memcpy(&wav_hdr[20], "\x01\x00", 2); /* PCM */
5762 /* # channels */
5763 tmp16 = channels;
5764 memcpy(&wav_hdr[22], &tmp16, 2);
5765 /* sample rate */
5766 tmp32 = sample_rate;
5767 memcpy(&wav_hdr[24], &tmp32, 4);
5768 /* byte rate */
5769 tmp32 = sample_rate * channels * sample_bytes_;
5770 memcpy(&wav_hdr[28], &tmp32, 4);
5771 /* block align */
5772 tmp16 = channels * sample_bytes_;
5773 memcpy(&wav_hdr[32], &tmp16, 2);
5774 /* bits per sample */
5775 tmp16 = 8 * sample_bytes_;
5776 memcpy(&wav_hdr[34], &tmp16, 2);
5777
5778 memcpy(&wav_hdr[36], "data", 4);
5779 memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
5780
5781 json_dumper_write_base64(&dumper, wav_hdr, sizeof(wav_hdr));
5782 }
5783
5784 // Write samples to our file.
5785 write_buff = (char *) decode_buff;
5786 write_bytes = decoded_bytes;
5787
5788 if (audio_out_rate_ != sample_rate)
5789 {
5790 spx_uint32_t in_len, out_len;
5791
5792 /* Resample the audio to match our previous output rate. */
5793 if (!audio_resampler_)
5794 {
5795 audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL((void*)0));
5796 speex_resampler_skip_zeros(audio_resampler_);
5797 RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
5798 }
5799 else
5800 {
5801 spx_uint32_t audio_out_rate;
5802 speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate);
5803
5804 if (sample_rate != cur_in_rate)
5805 {
5806 speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate);
5807 RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
5808 }
5809 }
5810 in_len = (spx_uint32_t)rtp_packet->info->info_payload_len;
5811 out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0);
5812 if (out_len * sample_bytes_ > resample_buff_len)
5813 {
5814 while ((out_len * sample_bytes_ > resample_buff_len))
5815 resample_buff_len *= 2;
5816 resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len);
5817 }
5818
5819 speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len);
5820 write_buff = (char *) resample_buff;
5821 write_bytes = out_len * sample_bytes_;
5822 }
5823
5824 /* Write the decoded, possibly-resampled audio */
5825 json_dumper_write_base64(&dumper, write_buff, write_bytes);
5826
5827 g_free(decode_buff);
5828 }
5829
5830 g_free(resample_buff);
5831 g_hash_table_destroy(decoders_hash_);
5832}
5833
5834static tap_packet_status
5835sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U___attribute__((unused)), const void *data, tap_flags_t flags _U___attribute__((unused)))
5836{
5837 const struct _rtp_info *rtp_info = (const struct _rtp_info *) data;
5838 struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata;
5839
5840 /* do not consider RTP packets without a setup frame */
5841 if (rtp_info->info_setup_frame_num == 0)
5842 return TAP_PACKET_DONT_REDRAW;
5843
5844 if (rtpstream_id_equal_pinfo_rtp_info(&req_rtp->id, pinfo, rtp_info))
5845 {
5846 rtp_packet_t *rtp_packet;
5847
5848 rtp_packet = g_new0(rtp_packet_t, 1)((rtp_packet_t *) g_malloc0_n ((1), sizeof (rtp_packet_t)));
5849 rtp_packet->info = (struct _rtp_info *) g_memdup2(rtp_info, sizeof(struct _rtp_info));
5850
5851 if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0)
5852 rtp_packet->payload_data = (uint8_t *) g_memdup2(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len);
5853
5854 if (!req_rtp->packets)
5855 req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts);
5856
5857 rtp_packet->frame_num = pinfo->num;
5858 rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time;
5859
5860 /* XXX, O(n) optimize */
5861 req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet);
5862 }
5863
5864 return TAP_PACKET_DONT_REDRAW;
5865}
5866
5867static bool_Bool
5868sharkd_session_eo_retap_listener(const char *tap_type) {
5869 bool_Bool ok = true1;
5870 register_eo_t *eo = NULL((void*)0);
5871 GString *tap_error = NULL((void*)0);
5872 void *tap_data = NULL((void*)0);
5873 GFreeFunc tap_free = NULL((void*)0);
5874
5875 // get <name> from eo:<name>, get_eo_by_name only needs the name (http etc.)
5876 eo = get_eo_by_name(tap_type + 3);
5877 if (!eo)
5878 {
5879 ok = false0;
5880 sharkd_json_error(
5881 rpcid, -11011, NULL((void*)0),
5882 "sharkd_session_eo_retap_listener() eo=%s not found", tap_type + 3
5883 );
5884 }
5885
5886 if (ok)
5887 {
5888 tap_error = sharkd_session_eo_register_tap_listener(eo, tap_type, NULL((void*)0), NULL((void*)0), &tap_data, &tap_free);
5889 if (tap_error)
5890 {
5891 ok = false0;
5892 sharkd_json_error(
5893 rpcid, -10002, NULL((void*)0),
5894 "sharkd_session_eo_retap_listener() sharkd_session_eo_register_tap_listener error %s",
5895 tap_error->str);
5896 g_string_free(tap_error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tap_error), ((!(0)))) : g_string_free_and_steal (tap_error))
: (g_string_free) ((tap_error), ((!(0)))))
;
5897 }
5898 }
5899
5900 if (ok)
5901 sharkd_retap();
5902
5903 if (!tap_error)
5904 remove_tap_listener(tap_data);
5905
5906 if (tap_free)
5907 tap_free(tap_data);
5908
5909 return ok;
5910}
5911
5912/**
5913 * sharkd_session_process_download()
5914 *
5915 * Process download request
5916 *
5917 * Input:
5918 * (m) token - token to download
5919 *
5920 * Output object with attributes:
5921 * (o) file - suggested name of file
5922 * (o) mime - suggested content type
5923 * (o) data - payload base64 encoded
5924 */
5925static void
5926sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
5927{
5928 const char *tok_token = json_find_attr(buf, tokens, count, "token");
5929
5930 if (!tok_token)
5931 {
5932 sharkd_json_error(
5933 rpcid, -10005, NULL((void*)0),
5934 "missing token"
5935 );
5936 return;
5937 }
5938
5939 if (!strncmp(tok_token, "eo:", 3))
5940 {
5941 // get eo:<name> from eo:<name>_<row>
5942 char *tap_type = g_strdup(tok_token)g_strdup_inline (tok_token);
5943 char *tmp = strrchr(tap_type, '_');
5944 if (tmp)
5945 *tmp = '\0';
5946
5947 // if eo:<name> not in sharkd_eo_list, retap
5948 if (!sharkd_eo_object_list_get_entry_by_type(sharkd_eo_list, tap_type) &&
5949 !sharkd_session_eo_retap_listener(tap_type))
5950 {
5951 g_free(tap_type);
5952 // sharkd_json_error called in sharkd_session_eo_retap_listener
5953 return;
5954 }
5955
5956 g_free(tap_type);
5957
5958 struct sharkd_export_object_list *object_list;
5959 const export_object_entry_t *eo_entry = NULL((void*)0);
5960
5961 for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
5962 {
5963 size_t eo_type_len = strlen(object_list->type);
5964
5965 if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
5966 {
5967 int row;
5968
5969 if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1)
5970 break;
5971
5972 eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
5973 break;
5974 }
5975 }
5976
5977 if (eo_entry)
5978 {
5979 const char *mime = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
5980 const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
5981
5982 sharkd_json_result_prologue(rpcid);
5983 sharkd_json_value_string("file", filename);
5984 sharkd_json_value_string("mime", mime);
5985 sharkd_json_value_base64("data", eo_entry->payload_data, eo_entry->payload_len);
5986 sharkd_json_result_epilogue();
5987 }
5988 else
5989 {
5990 sharkd_json_result_prologue(rpcid);
5991 sharkd_json_result_epilogue();
5992 }
5993 }
5994 else if (!strcmp(tok_token, "ssl-secrets"))
5995 {
5996 size_t str_len = 0;
5997 unsigned num_keys = 0;
5998 char* str = NULL((void*)0);
5999 secrets_export_values ret = secrets_export("TLS", &str, &str_len, &num_keys);
6000
6001 if ((ret == SECRETS_EXPORT_SUCCESS) && (str_len > 0))
6002 {
6003 const char *mime = "text/plain";
6004 const char *filename = "keylog.txt";
6005
6006 sharkd_json_result_prologue(rpcid);
6007 sharkd_json_value_string("file", filename);
6008 sharkd_json_value_string("mime", mime);
6009 sharkd_json_value_base64("data", str, str_len);
6010 sharkd_json_result_epilogue();
6011 }
6012 g_free(str);
6013 }
6014 else if (!strncmp(tok_token, "rtp:", 4))
6015 {
6016 struct sharkd_download_rtp rtp_req;
6017 GString *tap_error;
6018
6019 memset(&rtp_req, 0, sizeof(rtp_req));
6020 if (!sharkd_rtp_match_init(&rtp_req.id, tok_token + 4))
6021 {
6022 sharkd_json_error(
6023 rpcid, -10001, NULL((void*)0),
6024 "sharkd_session_process_download() rtp tokenizing error %s", tok_token
6025 );
6026 return;
6027 }
6028
6029 tap_error = register_tap_listener("rtp", &rtp_req, NULL((void*)0), 0, NULL((void*)0), sharkd_session_packet_download_tap_rtp_cb, NULL((void*)0), NULL((void*)0));
6030 if (tap_error)
6031 {
6032 sharkd_json_error(
6033 rpcid, -10002, NULL((void*)0),
6034 "sharkd_session_process_download() rtp error %s", tap_error->str
6035 );
6036 g_string_free(tap_error, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(tap_error), ((!(0)))) : g_string_free_and_steal (tap_error))
: (g_string_free) ((tap_error), ((!(0)))))
;
6037 return;
6038 }
6039
6040 sharkd_retap();
6041 remove_tap_listener(&rtp_req);
6042
6043 if (rtp_req.packets)
6044 {
6045 const char *mime = "audio/x-wav";
6046 const char *filename = tok_token;
6047
6048 sharkd_json_result_prologue(rpcid);
6049 sharkd_json_value_string("file", filename);
6050 sharkd_json_value_string("mime", mime);
6051
6052 json_dumper_set_member_name(&dumper, "data");
6053 json_dumper_begin_base64(&dumper);
6054 sharkd_rtp_download_decode(&rtp_req);
6055 json_dumper_end_base64(&dumper);
6056
6057 sharkd_json_result_epilogue();
6058
6059 g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items);
6060 }
6061 else
6062 {
6063 sharkd_json_error(
6064 rpcid, -10003, NULL((void*)0),
6065 "no rtp data available"
6066 );
6067 }
6068 }
6069 else
6070 {
6071 sharkd_json_error(
6072 rpcid, -10004, NULL((void*)0),
6073 "unrecognized token"
6074 );
6075 }
6076}
6077
6078static void
6079sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
6080{
6081 if (json_prep(buf, tokens, count))
6082 {
6083 /* don't need [0] token */
6084 tokens++;
6085 count--;
6086
6087 const char* tok_method = json_find_attr(buf, tokens, count, "method");
6088
6089 if (!tok_method) {
6090 sharkd_json_error(
6091 rpcid, -32601, NULL((void*)0),
6092 "No method found");
6093 return;
6094 }
6095 if (!strcmp(tok_method, "load"))
6096 sharkd_session_process_load(buf, tokens, count);
6097 else if (!strcmp(tok_method, "status"))
6098 sharkd_session_process_status();
6099 else if (!strcmp(tok_method, "analyse"))
6100 sharkd_session_process_analyse();
6101 else if (!strcmp(tok_method, "info"))
6102 sharkd_session_process_info();
6103 else if (!strcmp(tok_method, "fields"))
6104 sharkd_session_process_fields();
6105 else if (!strcmp(tok_method, "field"))
6106 sharkd_session_process_field(buf, tokens, count);
6107 else if (!strcmp(tok_method, "check"))
6108 sharkd_session_process_check(buf, tokens, count);
6109 else if (!strcmp(tok_method, "complete"))
6110 sharkd_session_process_complete(buf, tokens, count);
6111 else if (!strcmp(tok_method, "frames"))
6112 sharkd_session_process_frames(buf, tokens, count);
6113 else if (!strcmp(tok_method, "tap"))
6114 sharkd_session_process_tap(buf, tokens, count);
6115 else if (!strcmp(tok_method, "follow"))
6116 sharkd_session_process_follow(buf, tokens, count);
6117 else if (!strcmp(tok_method, "iograph"))
6118 sharkd_session_process_iograph(buf, tokens, count);
6119 else if (!strcmp(tok_method, "intervals"))
6120 sharkd_session_process_intervals(buf, tokens, count);
6121 else if (!strcmp(tok_method, "frame"))
6122 sharkd_session_process_frame(buf, tokens, count);
6123 else if (!strcmp(tok_method, "setcomment"))
6124 sharkd_session_process_setcomment(buf, tokens, count);
6125 else if (!strcmp(tok_method, "setconf"))
6126 sharkd_session_process_setconf(buf, tokens, count);
6127 else if (!strcmp(tok_method, "dumpconf"))
6128 sharkd_session_process_dumpconf(buf, tokens, count);
6129 else if (!strcmp(tok_method, "download"))
6130 sharkd_session_process_download(buf, tokens, count);
6131 else if (!strcmp(tok_method, "bye"))
6132 {
6133 sharkd_json_simple_ok(rpcid);
6134 exit(0);
6135 }
6136 else
6137 {
6138 sharkd_json_error(
6139 rpcid, -32601, NULL((void*)0),
6140 "The method \"%s\" is unknown", tok_method
6141 );
6142 }
6143 }
6144}
6145
6146int
6147sharkd_session_main(int mode_setting)
6148{
6149 char buf[8 * 1024];
6150 jsmntok_t *tokens = NULL((void*)0);
6151 int tokens_max = -1;
6152
6153 mode = mode_setting;
6154
6155 fprintf(stderrstderr, "Hello in child.\n");
6156
6157 dumper.output_file = stdoutstdout;
6158
6159 filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free);
6160
6161#ifdef HAVE_MAXMINDDB1
6162 /* mmdbresolve was stopped before fork(), force starting it */
6163 uat_get_table_by_name("MaxMind Database Paths")->post_update_cb();
6164#endif
6165
6166 set_resolution_synchrony(true1);
6167
6168 while (fgets(buf, sizeof(buf), stdinstdin))
6169 {
6170 /* every command is line separated JSON */
6171 int ret;
6172
6173 ret = json_parse(buf, NULL((void*)0), 0);
6174 if (ret <= 0)
6175 {
6176 sharkd_json_error(
6177 rpcid, -32600, NULL((void*)0),
6178 "Invalid JSON(1)"
6179 );
6180 continue;
6181 }
6182
6183 /* fprintf(stderr, "JSON: %d tokens\n", ret); */
6184 ret += 1;
6185
6186 if (tokens == NULL((void*)0) || tokens_max < ret)
6187 {
6188 tokens_max = ret;
6189 tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max);
6190 }
6191
6192 memset(tokens, 0, ret * sizeof(jsmntok_t));
6193
6194 ret = json_parse(buf, tokens, ret);
6195 if (ret <= 0)
6196 {
6197 sharkd_json_error(
6198 rpcid, -32600, NULL((void*)0),
6199 "Invalid JSON(2)"
6200 );
6201 continue;
6202 }
6203
6204 host_name_lookup_process();
6205
6206 sharkd_session_process(buf, tokens, ret);
6207 }
6208
6209 g_hash_table_destroy(filter_table);
6210 g_free(tokens);
6211
6212 return 0;
6213}

/builds/wireshark/wireshark/ui/io_graph_item.h

1/** @file
2 *
3 * Definitions and functions for I/O graph items
4 *
5 * Copied from gtk/io_stat.c, (c) 2002 Ronnie Sahlberg
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <[email protected]>
9 * Copyright 1998 Gerald Combs
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
14#ifndef __IO_GRAPH_ITEM_H__
15#define __IO_GRAPH_ITEM_H__
16
17#include "cfile.h"
18#include <wsutil/ws_assert.h>
19
20#include <epan/epan_dissect.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif /* __cplusplus */
25
26typedef enum {
27 IOG_ITEM_UNIT_FIRST,
28 IOG_ITEM_UNIT_PACKETS = IOG_ITEM_UNIT_FIRST,
29 IOG_ITEM_UNIT_BYTES,
30 IOG_ITEM_UNIT_BITS,
31 IOG_ITEM_UNIT_CALC_SUM,
32 IOG_ITEM_UNIT_CALC_FRAMES,
33 IOG_ITEM_UNIT_CALC_FIELDS,
34 IOG_ITEM_UNIT_CALC_MAX,
35 IOG_ITEM_UNIT_CALC_MIN,
36 IOG_ITEM_UNIT_CALC_AVERAGE,
37 IOG_ITEM_UNIT_CALC_THROUGHPUT,
38 IOG_ITEM_UNIT_CALC_LOAD,
39 IOG_ITEM_UNIT_LAST = IOG_ITEM_UNIT_CALC_LOAD,
40 NUM_IOG_ITEM_UNITS
41} io_graph_item_unit_t;
42
43typedef struct _io_graph_item_t {
44 uint32_t frames; /* always calculated, will hold number of frames*/
45 uint64_t bytes; /* always calculated, will hold number of bytes*/
46 uint64_t fields;
47 /* We use a double for totals because of overflow. For min and max,
48 * unsigned 64 bit integers larger than 2^53 cannot all be represented
49 * in a double, and this is useful for determining the frame with the
50 * min or max value, even though for plotting it will be converted to a
51 * double.
52 */
53 union {
54 nstime_t time_max;
55 double double_max;
56 int64_t int_max;
57 uint64_t uint_max;
58 };
59 union {
60 nstime_t time_min;
61 double double_min;
62 int64_t int_min;
63 uint64_t uint_min;
64 };
65 union {
66 nstime_t time_tot;
67 double double_tot;
68 };
69 uint32_t first_frame_in_invl;
70 uint32_t min_frame_in_invl;
71 uint32_t max_frame_in_invl;
72 uint32_t last_frame_in_invl;
73} io_graph_item_t;
74
75/** Reset (zero) an io_graph_item_t.
76 *
77 * @param items [in,out] Array containing the items to reset.
78 * @param count [in] The number of items in the array.
79 */
80static inline void
81reset_io_graph_items(io_graph_item_t *items, size_t count, int hf_index _U___attribute__((unused))) {
82 io_graph_item_t *item;
83 size_t i;
84
85 for (i = 0; i < count; i++) {
12
Assuming 'i' is >= 'count'
13
Loop condition is false. Execution continues on line 4606
86 item = &items[i];
87
88 item->frames = 0;
89 item->bytes = 0;
90 item->fields = 0;
91 item->first_frame_in_invl = 0;
92 item->min_frame_in_invl = 0;
93 item->max_frame_in_invl = 0;
94 item->last_frame_in_invl = 0;
95
96 nstime_set_zero(&item->time_max);
97 nstime_set_zero(&item->time_min);
98 nstime_set_zero(&item->time_tot);
99
100#if 0
101 /* XXX - On C, type punning is explicitly allowed since C99 so
102 * setting the nstime_t values to 0 is always sufficient.
103 * On C++ that appears technically to be undefined behavior (though
104 * I don't know of any compilers for which it doesn't work and I
105 * can't get UBSAN to complain about it) and this would be safer.
106 */
107 if (hf_index > 0) {
108
109 switch (proto_registrar_get_ftype(hf_index)) {
110
111 case FT_INT8:
112 case FT_INT16:
113 case FT_INT24:
114 case FT_INT32:
115 case FT_INT40:
116 case FT_INT48:
117 case FT_INT56:
118 case FT_INT64:
119 item->int_max = 0;
120 item->int_min = 0;
121 item->double_tot = 0;
122 break;
123
124 case FT_UINT8:
125 case FT_UINT16:
126 case FT_UINT24:
127 case FT_UINT32:
128 case FT_UINT40:
129 case FT_UINT48:
130 case FT_UINT56:
131 case FT_UINT64:
132 item->uint_max = 0;
133 item->uint_min = 0;
134 item->double_tot = 0;
135 break;
136
137 case FT_DOUBLE:
138 case FT_FLOAT:
139 item->double_max = 0;
140 item->double_min = 0;
141 item->double_tot = 0;
142 break;
143
144 case FT_RELATIVE_TIME:
145 nstime_set_zero(&item->time_max);
146 nstime_set_zero(&item->time_min);
147 nstime_set_zero(&item->time_tot);
148 break;
149
150 default:
151 break;
152 }
153 }
154#endif
155 }
156}
157
158/** Get the interval (array index) for a packet
159 *
160 * It is up to the caller to determine if the return value is valid.
161 *
162 * @param [in] pinfo Packet of interest.
163 * @param [in] interval Time interval in microseconds
164 * @return Array index on success, -1 on failure.
165 *
166 * @note pinfo->rel_ts, and hence the index, is not affected by ignoring
167 * frames.
168 */
169int64_t get_io_graph_index(packet_info *pinfo, int interval);
170
171/** Check field and item unit compatibility
172 *
173 * @param field_name [in] Header field name to check
174 * @param hf_index [out] Assigned the header field index corresponding to field_name if valid.
175 * Can be NULL.
176 * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
177 * @return NULL if compatible, otherwise an error string. The string must
178 * be freed by the caller.
179 */
180GString *check_field_unit(const char *field_name, int *hf_index, io_graph_item_unit_t item_unit);
181
182/** Get the value at the given interval (idx) for the current value unit.
183 *
184 * @param items [in] Array containing the item to get.
185 * @param val_units [in] The type of unit to calculate. From IOG_ITEM_UNITS.
186 * @param idx [in] Index of the item to get.
187 * @param hf_index [in] Header field index for advanced statistics.
188 * @param cap_file [in] Capture file.
189 * @param interval [in] Timing interval in ms.
190 * @param cur_idx [in] Current index.
191 * @param asAOT [in] Interpret when possible the value as an Average Over Time.
192 */
193double get_io_graph_item(const io_graph_item_t *items, io_graph_item_unit_t val_units, int idx, int hf_index, const capture_file *cap_file, int interval, int cur_idx, bool_Bool asAOT);
194
195/** Update the values of an io_graph_item_t.
196 *
197 * Frame and byte counts are always calculated. If edt is non-NULL advanced
198 * statistics are calculated using hfindex.
199 *
200 * @param items [in,out] Array containing the item to update.
201 * @param idx [in] Index of the item to update.
202 * @param pinfo [in] Packet containing update information.
203 * @param edt [in] Dissection information for advanced statistics. May be NULL.
204 * @param hf_index [in] Header field index for advanced statistics.
205 * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
206 * @param interval [in] Timing interval in μs.
207 * @return true if the update was successful, otherwise false.
208 */
209static inline bool_Bool
210update_io_graph_item(io_graph_item_t *items, int idx, packet_info *pinfo, epan_dissect_t *edt, int hf_index, int item_unit, uint32_t interval) {
211 io_graph_item_t *item = &items[idx];
212
213 /* Set the first and last frame num in current interval matching the target field+filter */
214 if (item->first_frame_in_invl == 0) {
16
The left operand of '==' is a garbage value
215 item->first_frame_in_invl = pinfo->num;
216 }
217 item->last_frame_in_invl = pinfo->num;
218
219 if (edt && hf_index >= 0) {
220 GPtrArray *gp;
221 unsigned i;
222
223 gp = proto_get_finfo_ptr_array(edt->tree, hf_index);
224 if (!gp) {
225 return false0;
226 }
227
228 /* Update the appropriate counters. If fields == 0, this is the first seen
229 * value so set any min/max values accordingly. */
230 for (i=0; i < gp->len; i++) {
231 int64_t new_int64;
232 uint64_t new_uint64;
233 float new_float;
234 double new_double;
235 const nstime_t *new_time;
236
237 switch (proto_registrar_get_ftype(hf_index)) {
238 case FT_UINT8:
239 case FT_UINT16:
240 case FT_UINT24:
241 case FT_UINT32:
242 new_uint64 = fvalue_get_uinteger(((field_info *)gp->pdata[i])->value);
243
244 if ((new_uint64 > item->uint_max) || (item->fields == 0)) {
245 item->uint_max = new_uint64;
246 item->max_frame_in_invl = pinfo->num;
247 }
248 if ((new_uint64 < item->uint_min) || (item->fields == 0)) {
249 item->uint_min = new_uint64;
250 item->min_frame_in_invl = pinfo->num;
251 }
252 item->double_tot += (double)new_uint64;
253 item->fields++;
254 break;
255 case FT_INT8:
256 case FT_INT16:
257 case FT_INT24:
258 case FT_INT32:
259 new_int64 = fvalue_get_sinteger(((field_info *)gp->pdata[i])->value);
260 if ((new_int64 > item->int_max) || (item->fields == 0)) {
261 item->int_max = new_int64;
262 item->max_frame_in_invl = pinfo->num;
263 }
264 if ((new_int64 < item->int_min) || (item->fields == 0)) {
265 item->int_min = new_int64;
266 item->min_frame_in_invl = pinfo->num;
267 }
268 item->double_tot += (double)new_int64;
269 item->fields++;
270 break;
271 case FT_UINT40:
272 case FT_UINT48:
273 case FT_UINT56:
274 case FT_UINT64:
275 new_uint64 = fvalue_get_uinteger64(((field_info *)gp->pdata[i])->value);
276 if ((new_uint64 > item->uint_max) || (item->fields == 0)) {
277 item->uint_max = new_uint64;
278 item->max_frame_in_invl = pinfo->num;
279 }
280 if ((new_uint64 < item->uint_min) || (item->fields == 0)) {
281 item->uint_min = new_uint64;
282 item->min_frame_in_invl = pinfo->num;
283 }
284 item->double_tot += (double)new_uint64;
285 item->fields++;
286 break;
287 case FT_INT40:
288 case FT_INT48:
289 case FT_INT56:
290 case FT_INT64:
291 new_int64 = fvalue_get_sinteger64(((field_info *)gp->pdata[i])->value);
292 if ((new_int64 > item->int_max) || (item->fields == 0)) {
293 item->int_max = new_int64;
294 item->max_frame_in_invl = pinfo->num;
295 }
296 if ((new_int64 < item->int_min) || (item->fields == 0)) {
297 item->int_min = new_int64;
298 item->min_frame_in_invl = pinfo->num;
299 }
300 item->double_tot += (double)new_int64;
301 item->fields++;
302 break;
303 case FT_FLOAT:
304 new_float = (float)fvalue_get_floating(((field_info *)gp->pdata[i])->value);
305 if ((new_float > item->double_max) || (item->fields == 0)) {
306 item->double_max = new_float;
307 item->max_frame_in_invl = pinfo->num;
308 }
309 if ((new_float < item->double_min) || (item->fields == 0)) {
310 item->double_min = new_float;
311 item->min_frame_in_invl = pinfo->num;
312 }
313 item->double_tot += new_float;
314 item->fields++;
315 break;
316 case FT_DOUBLE:
317 new_double = fvalue_get_floating(((field_info *)gp->pdata[i])->value);
318 if ((new_double > item->double_max) || (item->fields == 0)) {
319 item->double_max = new_double;
320 item->max_frame_in_invl = pinfo->num;
321 }
322 if ((new_double < item->double_min) || (item->fields == 0)) {
323 item->double_min = new_double;
324 item->min_frame_in_invl = pinfo->num;
325 }
326 item->double_tot += new_double;
327 item->fields++;
328 break;
329 case FT_RELATIVE_TIME:
330 new_time = fvalue_get_time(((field_info *)gp->pdata[i])->value);
331
332 switch (item_unit) {
333 case IOG_ITEM_UNIT_CALC_LOAD:
334 {
335 uint64_t t, pt; /* time in us */
336 int j;
337 /*
338 * Add the time this call spanned each interval according to
339 * its contribution to that interval.
340 * If the call time is negative (unlikely, requires both an
341 * out of order capture file plus retransmission), ignore.
342 */
343 const nstime_t time_zero = NSTIME_INIT_ZERO{0, 0};
344 if (nstime_cmp(new_time, &time_zero) < 0) {
345 break;
346 }
347 t = new_time->secs;
348 t = t * 1000000 + new_time->nsecs / 1000;
349 j = idx;
350 /*
351 * Handle current interval
352 * This cannot be negative, because get_io_graph_index
353 * returns an invalid interval if so.
354 */
355 pt = pinfo->rel_ts.secs * 1000000 + pinfo->rel_ts.nsecs / 1000;
356 pt = pt % interval;
357 if (pt > t) {
358 pt = t;
359 }
360 while (t) {
361 io_graph_item_t *load_item;
362
363 load_item = &items[j];
364 load_item->time_tot.nsecs += (int) (pt * 1000);
365 if (load_item->time_tot.nsecs > 1000000000) {
366 load_item->time_tot.secs++;
367 load_item->time_tot.nsecs -= 1000000000;
368 }
369 load_item->fields++;
370
371 if (j == 0) {
372 break;
373 }
374 j--;
375 t -= pt;
376 if (t > (uint64_t) interval) {
377 pt = (uint64_t) interval;
378 } else {
379 pt = t;
380 }
381 }
382 break;
383 }
384 default:
385 if ( (nstime_cmp(new_time, &item->time_max) > 0)
386 || (item->fields == 0)) {
387 item->time_max = *new_time;
388 item->max_frame_in_invl = pinfo->num;
389 }
390 if ( (nstime_cmp(new_time, &item->time_min) < 0)
391 || (item->fields == 0)) {
392 item->time_min = *new_time;
393 item->min_frame_in_invl = pinfo->num;
394 }
395 nstime_add(&item->time_tot, new_time)nstime_sum(&item->time_tot, &item->time_tot, new_time
)
;
396 item->fields++;
397 }
398 break;
399 default:
400 if ((item_unit == IOG_ITEM_UNIT_CALC_FRAMES) ||
401 (item_unit == IOG_ITEM_UNIT_CALC_FIELDS)) {
402 /*
403 * It's not an integeresque type, but
404 * all we want to do is count it, so
405 * that's all right.
406 */
407 item->fields++;
408 }
409 else {
410 /*
411 * "Can't happen"; see the "check that the
412 * type is compatible" check in
413 * filter_callback().
414 */
415 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "ui/io_graph_item.h", 415
, __func__, "assertion \"not reached\" failed")
;
416 }
417 break;
418 }
419 }
420 }
421
422 item->frames++;
423 item->bytes += pinfo->fd->pkt_len;
424
425 return true1;
426}
427
428
429#ifdef __cplusplus
430}
431#endif /* __cplusplus */
432
433#endif /* __IO_GRAPH_ITEM_H__ */