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