quakeworld: fix issue found by PVS Studio (V529)
[metze/wireshark/wip.git] / sharkd_session.c
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 <config.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18
19 #include <glib.h>
20
21 #include <wsutil/wsjson.h>
22 #include <wsutil/ws_printf.h>
23
24 #include <file.h>
25 #include <epan/epan_dissect.h>
26 #include <epan/exceptions.h>
27 #include <epan/color_filters.h>
28 #include <epan/prefs.h>
29 #include <epan/prefs-int.h>
30 #include <epan/uat-int.h>
31 #include <wiretap/wtap.h>
32
33 #include <epan/column.h>
34
35 #include <ui/ssl_key_export.h>
36
37 #include <epan/stats_tree_priv.h>
38 #include <epan/stat_tap_ui.h>
39 #include <epan/conversation_table.h>
40 #include <epan/sequence_analysis.h>
41 #include <epan/expert.h>
42 #include <epan/export_object.h>
43 #include <epan/follow.h>
44 #include <epan/rtd_table.h>
45 #include <epan/srt_table.h>
46
47 #include <epan/dissectors/packet-h225.h>
48 #include <epan/rtp_pt.h>
49 #include <ui/voip_calls.h>
50 #include <ui/rtp_stream.h>
51 #include <ui/tap-rtp-common.h>
52 #include <epan/to_str.h>
53
54 #include <epan/addr_resolv.h>
55 #include <epan/dissectors/packet-rtp.h>
56 #include <ui/rtp_media.h>
57 #ifdef HAVE_SPEEXDSP
58 # include <speex/speex_resampler.h>
59 #else
60 # include <codecs/speex/speex_resampler.h>
61 #endif /* HAVE_SPEEXDSP */
62
63 #include <epan/maxmind_db.h>
64
65 #include <wsutil/pint.h>
66 #include <wsutil/strtoi.h>
67
68 #include "globals.h"
69
70 #include "sharkd.h"
71
72 struct sharkd_filter_item
73 {
74         guint8 *filtered;
75 };
76
77 static GHashTable *filter_table = NULL;
78
79 static gboolean
80 json_unescape_str(char *input)
81 {
82         return wsjson_unescape_json_string(input, input);
83 }
84
85 static const char *
86 json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
87 {
88         int i;
89
90         for (i = 0; i < count; i += 2)
91         {
92                 const char *tok_attr  = &buf[tokens[i + 0].start];
93                 const char *tok_value = &buf[tokens[i + 1].start];
94
95                 if (!strcmp(tok_attr, attr))
96                         return tok_value;
97         }
98
99         return NULL;
100 }
101
102 static void
103 json_puts_string(const char *str)
104 {
105         int i;
106
107         if (str == NULL)
108                 str = "";
109
110         putchar('"');
111         for (i = 0; str[i]; i++)
112         {
113                 switch (str[i])
114                 {
115                         case '\\':
116                         case '"':
117                                 putchar('\\');
118                                 putchar(str[i]);
119                                 break;
120
121                         case '\n':
122                                 putchar('\\');
123                                 putchar('n');
124                                 break;
125
126                         default:
127                                 putchar(str[i]);
128                                 break;
129                 }
130         }
131
132         putchar('"');
133 }
134
135 static void
136 json_print_base64_step(const guint8 *data, int *state1, int *state2)
137 {
138         gchar buf[(1 / 3 + 1) * 4 + 4 + 1];
139         gsize wrote;
140
141         if (data)
142                 wrote = g_base64_encode_step(data, 1, FALSE, buf, state1, state2);
143         else
144                 wrote = g_base64_encode_close(FALSE, buf, state1, state2);
145
146         if (wrote > 0)
147         {
148                 buf[wrote] = '\0';
149                 printf("%s", buf);
150         }
151 }
152
153 static void
154 json_print_base64(const guint8 *data, size_t len)
155 {
156         size_t i;
157         int base64_state1 = 0;
158         int base64_state2 = 0;
159
160         putchar('"');
161
162         for (i = 0; i < len; i++)
163                 json_print_base64_step(&data[i], &base64_state1, &base64_state2);
164
165         json_print_base64_step(NULL, &base64_state1, &base64_state2);
166
167         putchar('"');
168 }
169
170 static void
171 sharkd_session_filter_free(gpointer data)
172 {
173         struct sharkd_filter_item *l = (struct sharkd_filter_item *) data;
174
175         g_free(l->filtered);
176         g_free(l);
177 }
178
179 static const guint8 *
180 sharkd_session_filter_data(const char *filter)
181 {
182         struct sharkd_filter_item *l;
183
184         l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter);
185         if (!l)
186         {
187                 guint8 *filtered = NULL;
188
189                 int ret = sharkd_filter(filter, &filtered);
190
191                 if (ret == -1)
192                         return NULL;
193
194                 l = (struct sharkd_filter_item *) g_malloc(sizeof(struct sharkd_filter_item));
195                 l->filtered = filtered;
196
197                 g_hash_table_insert(filter_table, g_strdup(filter), l);
198         }
199
200         return l->filtered;
201 }
202
203 struct sharkd_rtp_match
204 {
205         guint32 addr_src, addr_dst;
206         address src_addr;
207         address dst_addr;
208         guint16 src_port;
209         guint16 dst_port;
210         guint32 ssrc;
211 };
212
213 static gboolean
214 sharkd_rtp_match_init(struct sharkd_rtp_match *req, const char *init_str)
215 {
216         gboolean ret = FALSE;
217         char **arr;
218
219         arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
220         if (g_strv_length(arr) != 5)
221                 goto fail;
222
223         /* TODO, for now only IPv4 */
224         if (!get_host_ipaddr(arr[0], &req->addr_src))
225                 goto fail;
226
227         if (!ws_strtou16(arr[1], NULL, &req->src_port))
228                 goto fail;
229
230         if (!get_host_ipaddr(arr[2], &req->addr_dst))
231                 goto fail;
232
233         if (!ws_strtou16(arr[3], NULL, &req->dst_port))
234                 goto fail;
235
236         if (!ws_hexstrtou32(arr[4], NULL, &req->ssrc))
237                 goto fail;
238
239         set_address(&req->src_addr, AT_IPv4, 4, &req->addr_src);
240         set_address(&req->dst_addr, AT_IPv4, 4, &req->addr_dst);
241         ret = TRUE;
242
243 fail:
244         g_strfreev(arr);
245         return ret;
246 }
247
248 static gboolean
249 sharkd_rtp_match_check(const struct sharkd_rtp_match *req, const packet_info *pinfo, const struct _rtp_info *rtp_info)
250 {
251         if (rtp_info->info_sync_src == req->ssrc &&
252                 pinfo->srcport == req->src_port &&
253                 pinfo->destport == req->dst_port &&
254                 addresses_equal(&pinfo->src, &req->src_addr) &&
255                 addresses_equal(&pinfo->dst, &req->dst_addr))
256         {
257                 return TRUE;
258         }
259
260         return FALSE;
261 }
262
263 static gboolean
264 sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata)
265 {
266         stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value;
267         int *pi = (int *) userdata;
268
269         printf("%s{", (*pi) ? "," : "");
270                 printf("\"name\":\"%s\"", stat_tap->title);
271                 printf(",\"tap\":\"nstat:%s\"", (const char *) key);
272         printf("}");
273
274         *pi = *pi + 1;
275         return FALSE;
276 }
277
278 static gboolean
279 sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
280 {
281         struct register_ct *table = (struct register_ct *) value;
282         int *pi = (int *) userdata;
283
284         const char *label = (const char *) key;
285
286         if (get_conversation_packet_func(table))
287         {
288                 printf("%s{", (*pi) ? "," : "");
289                         printf("\"name\":\"Conversation List/%s\"", label);
290                         printf(",\"tap\":\"conv:%s\"", label);
291                 printf("}");
292
293                 *pi = *pi + 1;
294         }
295
296         if (get_hostlist_packet_func(table))
297         {
298                 printf("%s{", (*pi) ? "," : "");
299                         printf("\"name\":\"Endpoint/%s\"", label);
300                         printf(",\"tap\":\"endpt:%s\"", label);
301                 printf("}");
302
303                 *pi = *pi + 1;
304         }
305         return FALSE;
306 }
307
308 static gboolean
309 sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata)
310 {
311         register_analysis_t *analysis = (register_analysis_t *) value;
312         int *pi = (int *) userdata;
313
314         printf("%s{", (*pi) ? "," : "");
315                 printf("\"name\":\"%s\"", sequence_analysis_get_ui_name(analysis));
316                 printf(",\"tap\":\"seqa:%s\"", (const char *) key);
317         printf("}");
318
319         *pi = *pi + 1;
320         return FALSE;
321 }
322
323 static gboolean
324 sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
325 {
326         register_eo_t *eo = (register_eo_t *) value;
327         int *pi = (int *) user_data;
328
329         const int proto_id = get_eo_proto_id(eo);
330         const char *filter = proto_get_protocol_filter_name(proto_id);
331         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
332
333         printf("%s{", (*pi) ? "," : "");
334                 printf("\"name\":\"Export Object/%s\"", label);
335                 printf(",\"tap\":\"eo:%s\"", filter);
336         printf("}");
337
338         *pi = *pi + 1;
339         return FALSE;
340 }
341
342 static gboolean
343 sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data)
344 {
345         register_srt_t *srt = (register_srt_t *) value;
346         int *pi = (int *) user_data;
347
348         const int proto_id = get_srt_proto_id(srt);
349         const char *filter = proto_get_protocol_filter_name(proto_id);
350         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
351
352         printf("%s{", (*pi) ? "," : "");
353                 printf("\"name\":\"Service Response Time/%s\"", label);
354                 printf(",\"tap\":\"srt:%s\"", filter);
355         printf("}");
356
357         *pi = *pi + 1;
358         return FALSE;
359 }
360
361 static gboolean
362 sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data)
363 {
364         register_rtd_t *rtd = (register_rtd_t *) value;
365         int *pi = (int *) user_data;
366
367         const int proto_id = get_rtd_proto_id(rtd);
368         const char *filter = proto_get_protocol_filter_name(proto_id);
369         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
370
371         printf("%s{", (*pi) ? "," : "");
372                 printf("\"name\":\"Response Time Delay/%s\"", label);
373                 printf(",\"tap\":\"rtd:%s\"", filter);
374         printf("}");
375
376         *pi = *pi + 1;
377         return FALSE;
378 }
379
380 static gboolean
381 sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
382 {
383         register_follow_t *follower = (register_follow_t *) value;
384         int *pi = (int *) user_data;
385
386         const int proto_id = get_follow_proto_id(follower);
387         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
388         const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
389
390         printf("%s{", (*pi) ? "," : "");
391                 printf("\"name\":\"Follow/%s\"", label);
392                 printf(",\"tap\":\"follow:%s\"", filter);
393         printf("}");
394
395         *pi = *pi + 1;
396         return FALSE;
397 }
398
399 /**
400  * sharkd_session_process_info()
401  *
402  * Process info request
403  *
404  * Output object with attributes:
405  *   (m) columns - available column formats, array of object with attributes:
406  *                  'name'   - column name
407  *                  'format' - column format-name
408  *
409  *   (m) stats   - available statistics, array of object with attributes:
410  *                  'name' - statistic name
411  *                  'tap'  - sharkd tap-name for statistic
412  *
413  *   (m) convs   - available conversation list, array of object with attributes:
414  *                  'name' - conversation name
415  *                  'tap'  - sharkd tap-name for conversation
416  *
417  *   (m) eo      - available export object list, array of object with attributes:
418  *                  'name' - export object name
419  *                  'tap'  - sharkd tap-name for eo
420  *
421  *   (m) srt     - available service response time list, array of object with attributes:
422  *                  'name' - service response time name
423  *                  'tap'  - sharkd tap-name for srt
424  *
425  *   (m) rtd     - available response time delay list, array of object with attributes:
426  *                  'name' - response time delay name
427  *                  'tap'  - sharkd tap-name for rtd
428  *
429  *   (m) seqa    - available sequence analysis (flow) list, array of object with attributes:
430  *                  'name' - sequence analysis name
431  *                  'tap'  - sharkd tap-name
432  *
433  *   (m) taps - available taps, array of object with attributes:
434  *                  'name' - tap name
435  *                  'tap'  - sharkd tap-name
436  *
437  *   (m) follow - available followers, array of object with attributes:
438  *                  'name' - tap name
439  *                  'tap'  - sharkd tap-name
440  *
441  *   (m) ftypes   - conversation table for FT_ number to string
442  */
443 static void
444 sharkd_session_process_info(void)
445 {
446         int i;
447
448         printf("{\"columns\":[");
449         for (i = 0; i < NUM_COL_FMTS; i++)
450         {
451                 const char *col_format = col_format_to_string(i);
452                 const char *col_descr  = col_format_desc(i);
453
454                 printf("%s{", (i) ? "," : "");
455                         printf("\"name\":\"%s\"", col_descr);
456                         printf(",\"format\":\"%s\"", col_format);
457                 printf("}");
458         }
459         printf("]");
460
461         printf(",\"stats\":[");
462         {
463                 GList *cfg_list = stats_tree_get_cfg_list();
464                 GList *l;
465                 const char *sepa = "";
466
467                 for (l = cfg_list; l; l = l->next)
468                 {
469                         stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
470
471                         printf("%s{", sepa);
472                                 printf("\"name\":\"%s\"", cfg->name);
473                                 printf(",\"tap\":\"stat:%s\"", cfg->abbr);
474                         printf("}");
475                         sepa = ",";
476                 }
477
478                 g_list_free(cfg_list);
479         }
480         printf("]");
481
482         printf(",\"ftypes\":[");
483         for (i = 0; i < FT_NUM_TYPES; i++)
484         {
485                 if (i)
486                         printf(",");
487                 json_puts_string(ftype_name((ftenum_t) i));
488         }
489         printf("]");
490
491         printf(",\"version\":");
492         json_puts_string(sharkd_version());
493
494         printf(",\"nstat\":[");
495         i = 0;
496         stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i);
497         printf("]");
498
499         printf(",\"convs\":[");
500         i = 0;
501         conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
502         printf("]");
503
504         printf(",\"seqa\":[");
505         i = 0;
506         sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i);
507         printf("]");
508
509         printf(",\"taps\":[");
510         {
511                 printf("{\"name\":\"%s\",\"tap\":\"%s\"}", "RTP streams", "rtp-streams");
512                 printf(",{\"name\":\"%s\",\"tap\":\"%s\"}", "Expert Information", "expert");
513         }
514         printf("]");
515
516         printf(",\"eo\":[");
517         i = 0;
518         eo_iterate_tables(sharkd_export_object_visit_cb, &i);
519         printf("]");
520
521         printf(",\"srt\":[");
522         i = 0;
523         srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
524         printf("]");
525
526         printf(",\"rtd\":[");
527         i = 0;
528         rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
529         printf("]");
530
531         printf(",\"follow\":[");
532         i = 0;
533         follow_iterate_followers(sharkd_follower_visit_cb, &i);
534         printf("]");
535
536         printf("}\n");
537 }
538
539 /**
540  * sharkd_session_process_load()
541  *
542  * Process load request
543  *
544  * Input:
545  *   (m) file - file to be loaded
546  *
547  * Output object with attributes:
548  *   (m) err - error code
549  */
550 static void
551 sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
552 {
553         const char *tok_file = json_find_attr(buf, tokens, count, "file");
554         int err = 0;
555
556         fprintf(stderr, "load: filename=%s\n", tok_file);
557
558         if (!tok_file)
559                 return;
560
561         if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK)
562         {
563                 printf("{\"err\":%d}\n", err);
564                 return;
565         }
566
567         TRY
568         {
569                 err = sharkd_load_cap_file();
570         }
571         CATCH(OutOfMemoryError)
572         {
573                 fprintf(stderr, "load: OutOfMemoryError\n");
574                 err = ENOMEM;
575         }
576         ENDTRY;
577
578         printf("{\"err\":%d}\n", err);
579 }
580
581 /**
582  * sharkd_session_process_status()
583  *
584  * Process status request
585  *
586  * Output object with attributes:
587  *   (m) frames   - count of currently loaded frames
588  *   (m) duration - time difference between time of first frame, and last loaded frame
589  *   (o) filename - capture filename
590  *   (o) filesize - capture filesize
591  */
592 static void
593 sharkd_session_process_status(void)
594 {
595         printf("{\"frames\":%u", cfile.count);
596
597         printf(",\"duration\":%.9f", nstime_to_sec(&cfile.elapsed_time));
598
599         if (cfile.filename)
600         {
601                 char *name = g_path_get_basename(cfile.filename);
602
603                 printf(",\"filename\":");
604                 json_puts_string(name);
605                 g_free(name);
606         }
607
608         if (cfile.provider.wth)
609         {
610                 gint64 file_size = wtap_file_size(cfile.provider.wth, NULL);
611
612                 if (file_size > 0)
613                         printf(",\"filesize\":%" G_GINT64_FORMAT, file_size);
614         }
615
616         printf("}\n");
617 }
618
619 struct sharkd_analyse_data
620 {
621         GHashTable *protocols_set;
622         nstime_t *first_time;
623         nstime_t *last_time;
624 };
625
626 static void
627 sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
628 {
629         struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
630         packet_info *pi = &edt->pi;
631         frame_data *fdata = pi->fd;
632
633         (void) tree;
634         (void) cinfo;
635         (void) data_src;
636
637         if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
638                 analyser->first_time = &fdata->abs_ts;
639
640         if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
641                 analyser->last_time = &fdata->abs_ts;
642
643         if (pi->layers)
644         {
645                 wmem_list_frame_t *frame;
646
647                 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
648                 {
649                         int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame));
650
651                         if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL))
652                         {
653                                 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id));
654
655                                 if (g_hash_table_size(analyser->protocols_set) != 1)
656                                         printf(",");
657                                 json_puts_string(proto_get_protocol_filter_name(proto_id));
658                         }
659                 }
660         }
661
662 }
663
664 /**
665  * sharkd_session_process_status()
666  *
667  * Process analyse request
668  *
669  * Output object with attributes:
670  *   (m) frames  - count of currently loaded frames
671  *   (m) protocols - protocol list
672  *   (m) first     - earliest frame time
673  *   (m) last      - latest frame time
674  */
675 static void
676 sharkd_session_process_analyse(void)
677 {
678         unsigned int framenum;
679         struct sharkd_analyse_data analyser;
680
681         analyser.first_time = NULL;
682         analyser.last_time  = NULL;
683         analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */);
684
685         printf("{\"frames\":%u", cfile.count);
686
687         printf(",\"protocols\":[");
688         for (framenum = 1; framenum <= cfile.count; framenum++)
689                 sharkd_dissect_request(framenum, (framenum != 1) ? 1 : 0, framenum - 1, &sharkd_session_process_analyse_cb, 0, 0, 0, &analyser);
690         printf("]");
691
692         if (analyser.first_time)
693                 printf(",\"first\":%.9f", nstime_to_sec(analyser.first_time));
694
695         if (analyser.last_time)
696                 printf(",\"last\":%.9f", nstime_to_sec(analyser.last_time));
697
698         printf("}\n");
699
700         g_hash_table_destroy(analyser.protocols_set);
701 }
702
703 static column_info *
704 sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count)
705 {
706         const char *columns_custom[32];
707         guint16 columns_fmt[32];
708         gint16 columns_occur[32];
709
710         int i, cols;
711
712         for (i = 0; i < 32; i++)
713         {
714                 const char *tok_column;
715                 char tok_column_name[64];
716                 char *custom_sepa;
717
718                 ws_snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i);
719                 tok_column = json_find_attr(buf, tokens, count, tok_column_name);
720                 if (tok_column == NULL)
721                         break;
722
723                 columns_custom[i] = NULL;
724                 columns_occur[i] = 0;
725
726                 if ((custom_sepa = strchr(tok_column, ':')))
727                 {
728                         *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */
729
730                         columns_fmt[i] = COL_CUSTOM;
731                         columns_custom[i] = tok_column;
732
733                         if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i]))
734                                 return NULL;
735                 }
736                 else
737                 {
738                         if (!ws_strtou16(tok_column, NULL, &columns_fmt[i]))
739                                 return NULL;
740
741                         if (columns_fmt[i] >= NUM_COL_FMTS)
742                                 return NULL;
743
744                         /* if custom, that it shouldn't be just custom number -> error */
745                         if (columns_fmt[i] == COL_CUSTOM)
746                                 return NULL;
747                 }
748         }
749
750         cols = i;
751
752         col_setup(cinfo, cols);
753
754         for (i = 0; i < cols; i++)
755         {
756                 col_item_t *col_item = &cinfo->columns[i];
757
758                 col_item->col_fmt = columns_fmt[i];
759                 col_item->col_title = NULL; /* no need for title */
760
761                 if (col_item->col_fmt == COL_CUSTOM)
762                 {
763                         col_item->col_custom_fields = g_strdup(columns_custom[i]);
764                         col_item->col_custom_occurrence = columns_occur[i];
765                 }
766
767                 col_item->col_fence = 0;
768         }
769
770         col_finalize(cinfo);
771
772         return cinfo;
773 }
774
775 /**
776  * sharkd_session_process_frames()
777  *
778  * Process frames request
779  *
780  * Input:
781  *   (o) column0...columnXX - requested columns either number in range [0..NUM_COL_FMTS), or custom (syntax <dfilter>:<occurence>).
782  *                            If column0 is not specified default column set will be used.
783  *   (o) filter - filter to be used
784  *   (o) skip=N   - skip N frames
785  *   (o) limit=N  - show only N frames
786  *   (o) refs  - list (comma separated) with sorted time reference frame numbers.
787  *
788  * Output array of frames with attributes:
789  *   (m) c   - array of column data
790  *   (m) num - frame number
791  *   (o) i   - if frame is ignored
792  *   (o) m   - if frame is marked
793  *   (o) ct  - if frame is commented
794  *   (o) bg  - color filter - background color in hex
795  *   (o) fg  - color filter - foreground color in hex
796  */
797 static void
798 sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
799 {
800         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
801         const char *tok_column = json_find_attr(buf, tokens, count, "column0");
802         const char *tok_skip   = json_find_attr(buf, tokens, count, "skip");
803         const char *tok_limit  = json_find_attr(buf, tokens, count, "limit");
804         const char *tok_refs   = json_find_attr(buf, tokens, count, "refs");
805
806         const guint8 *filter_data = NULL;
807
808         const char *frame_sepa = "";
809         int col;
810
811         guint32 framenum, prev_dis_num = 0;
812         guint32 current_ref_frame = 0, next_ref_frame = G_MAXUINT32;
813         guint32 skip;
814         guint32 limit;
815
816         column_info *cinfo = &cfile.cinfo;
817         column_info user_cinfo;
818
819         if (tok_column)
820         {
821                 memset(&user_cinfo, 0, sizeof(user_cinfo));
822                 cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count);
823                 if (!cinfo)
824                         return;
825         }
826
827         if (tok_filter)
828         {
829                 filter_data = sharkd_session_filter_data(tok_filter);
830                 if (!filter_data)
831                         return;
832         }
833
834         skip = 0;
835         if (tok_skip)
836         {
837                 if (!ws_strtou32(tok_skip, NULL, &skip))
838                         return;
839         }
840
841         limit = 0;
842         if (tok_limit)
843         {
844                 if (!ws_strtou32(tok_limit, NULL, &limit))
845                         return;
846         }
847
848         if (tok_refs)
849         {
850                 if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame))
851                         return;
852         }
853
854         printf("[");
855         for (framenum = 1; framenum <= cfile.count; framenum++)
856         {
857                 frame_data *fdata;
858                 guint32 ref_frame = (framenum != 1) ? 1 : 0;
859
860                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
861                         continue;
862
863                 if (skip)
864                 {
865                         skip--;
866                         prev_dis_num = framenum;
867                         continue;
868                 }
869
870                 if (tok_refs)
871                 {
872                         if (framenum >= next_ref_frame)
873                         {
874                                 current_ref_frame = next_ref_frame;
875
876                                 if (*tok_refs != ',')
877                                         next_ref_frame = G_MAXUINT32;
878
879                                 while (*tok_refs == ',' && framenum >= next_ref_frame)
880                                 {
881                                         current_ref_frame = next_ref_frame;
882
883                                         if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame))
884                                         {
885                                                 fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs);
886                                                 break;
887                                         }
888                                 }
889                         }
890
891                         if (current_ref_frame)
892                                 ref_frame = current_ref_frame;
893                 }
894
895                 fdata = sharkd_get_frame(framenum);
896                 sharkd_dissect_columns(fdata, ref_frame, prev_dis_num, cinfo, (fdata->color_filter == NULL));
897
898                 printf("%s{\"c\":[", frame_sepa);
899                 for (col = 0; col < cinfo->num_cols; ++col)
900                 {
901                         const col_item_t *col_item = &cinfo->columns[col];
902
903                         if (col)
904                                 printf(",");
905
906                         json_puts_string(col_item->col_data);
907                 }
908                 printf("],\"num\":%u", framenum);
909
910                 if (fdata->flags.has_user_comment || fdata->flags.has_phdr_comment)
911                 {
912                         if (!fdata->flags.has_user_comment || sharkd_get_user_comment(fdata) != NULL)
913                                 printf(",\"ct\":true");
914                 }
915
916                 if (fdata->flags.ignored)
917                         printf(",\"i\":true");
918
919                 if (fdata->flags.marked)
920                         printf(",\"m\":true");
921
922                 if (fdata->color_filter)
923                 {
924                         printf(",\"bg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->bg_color));
925                         printf(",\"fg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->fg_color));
926                 }
927
928                 printf("}");
929                 frame_sepa = ",";
930                 prev_dis_num = framenum;
931
932                 if (limit && --limit == 0)
933                         break;
934         }
935         printf("]\n");
936
937         if (cinfo != &cfile.cinfo)
938                 col_cleanup(cinfo);
939 }
940
941 static void
942 sharkd_session_process_tap_stats_node_cb(const stat_node *n)
943 {
944         stat_node *node;
945         const char *sepa = "";
946
947         printf("[");
948         for (node = n->children; node; node = node->next)
949         {
950                 /* code based on stats_tree_get_values_from_node() */
951                 printf("%s{\"name\":\"%s\"", sepa, node->name);
952                 printf(",\"count\":%d", node->counter);
953                 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng))
954                 {
955                         printf(",\"avg\":%.2f", ((float)node->total) / node->counter);
956                         printf(",\"min\":%d", node->minvalue);
957                         printf(",\"max\":%d", node->maxvalue);
958                 }
959
960                 if (node->st->elapsed)
961                         printf(",\"rate\":%.4f",((float)node->counter) / node->st->elapsed);
962
963                 if (node->parent && node->parent->counter)
964                         printf(",\"perc\":%.2f", (node->counter * 100.0) / node->parent->counter);
965                 else if (node->parent == &(node->st->root))
966                         printf(",\"perc\":100");
967
968                 if (prefs.st_enable_burstinfo && node->max_burst)
969                 {
970                         if (prefs.st_burst_showcount)
971                                 printf(",\"burstcount\":%d", node->max_burst);
972                         else
973                                 printf(",\"burstrate\":%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
974
975                         printf(",\"bursttime\":%.3f", ((double)node->burst_time / 1000.0));
976                 }
977
978                 if (node->children)
979                 {
980                         printf(",\"sub\":");
981                         sharkd_session_process_tap_stats_node_cb(node);
982                 }
983                 printf("}");
984                 sepa = ",";
985         }
986         printf("]");
987 }
988
989 /**
990  * sharkd_session_process_tap_stats_cb()
991  *
992  * Output stats tap:
993  *
994  *   (m) tap        - tap name
995  *   (m) type:stats - tap output type
996  *   (m) name       - stat name
997  *   (m) stats      - array of object with attributes:
998  *                  (m) name       - stat item name
999  *                  (m) count      - stat item counter
1000  *                  (o) avg        - stat item averange value
1001  *                  (o) min        - stat item min value
1002  *                  (o) max        - stat item max value
1003  *                  (o) rate       - stat item rate value (ms)
1004  *                  (o) perc       - stat item percentage
1005  *                  (o) burstrate  - stat item burst rate
1006  *                  (o) burstcount - stat item burst count
1007  *                  (o) burstttme  - stat item burst start
1008  *                  (o) sub        - array of object with attributes like in stats node.
1009  */
1010 static void
1011 sharkd_session_process_tap_stats_cb(void *psp)
1012 {
1013         stats_tree *st = (stats_tree *) psp;
1014
1015         printf("{\"tap\":\"stats:%s\",\"type\":\"stats\"", st->cfg->abbr);
1016
1017         printf(",\"name\":\"%s\",\"stats\":", st->cfg->name);
1018         sharkd_session_process_tap_stats_node_cb(&st->root);
1019         printf("},");
1020 }
1021
1022 static void
1023 sharkd_session_free_tap_stats_cb(void *psp)
1024 {
1025         stats_tree *st = (stats_tree *) psp;
1026
1027         stats_tree_free(st);
1028 }
1029
1030 struct sharkd_expert_tap
1031 {
1032         GSList *details;
1033         GStringChunk *text;
1034 };
1035
1036 /**
1037  * sharkd_session_process_tap_expert_cb()
1038  *
1039  * Output expert tap:
1040  *
1041  *   (m) tap         - tap name
1042  *   (m) type:expert - tap output type
1043  *   (m) details     - array of object with attributes:
1044  *                  (m) f - frame number, which generated expert information
1045  *                  (o) s - severity
1046  *                  (o) g - group
1047  *                  (m) m - expert message
1048  *                  (o) p - protocol
1049  */
1050 static void
1051 sharkd_session_process_tap_expert_cb(void *tapdata)
1052 {
1053         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1054         GSList *list;
1055         const char *sepa = "";
1056
1057         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "expert", "expert");
1058
1059         printf(",\"details\":[");
1060         for (list = etd->details; list; list = list->next)
1061         {
1062                 expert_info_t *ei = (expert_info_t *) list->data;
1063                 const char *tmp;
1064
1065                 printf("%s{", sepa);
1066
1067                 printf("\"f\":%u,", ei->packet_num);
1068
1069                 tmp = try_val_to_str(ei->severity, expert_severity_vals);
1070                 if (tmp)
1071                         printf("\"s\":\"%s\",", tmp);
1072
1073                 tmp = try_val_to_str(ei->group, expert_group_vals);
1074                 if (tmp)
1075                         printf("\"g\":\"%s\",", tmp);
1076
1077                 printf("\"m\":");
1078                 json_puts_string(ei->summary);
1079                 printf(",");
1080
1081                 if (ei->protocol)
1082                 {
1083                         printf("\"p\":");
1084                         json_puts_string(ei->protocol);
1085                 }
1086
1087                 printf("}");
1088                 sepa = ",";
1089         }
1090         printf("]");
1091
1092         printf("},");
1093 }
1094
1095 static gboolean
1096 sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
1097 {
1098         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1099         const expert_info_t *ei       = (const expert_info_t *) pointer;
1100         expert_info_t *ei_copy;
1101
1102         if (ei == NULL)
1103                 return FALSE;
1104
1105         ei_copy = g_new(expert_info_t, 1);
1106         /* Note: this is a shallow copy */
1107         *ei_copy = *ei;
1108
1109         /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */
1110         ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol);
1111         ei_copy->summary  = g_string_chunk_insert_const(etd->text, ei_copy->summary);
1112
1113         etd->details = g_slist_prepend(etd->details, ei_copy);
1114
1115         return TRUE;
1116 }
1117
1118 static void
1119 sharkd_session_free_tap_expert_cb(void *tapdata)
1120 {
1121         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1122
1123         g_slist_free_full(etd->details, g_free);
1124         g_string_chunk_free(etd->text);
1125         g_free(etd);
1126 }
1127
1128 /**
1129  * sharkd_session_process_tap_flow_cb()
1130  *
1131  * Output flow tap:
1132  *   (m) tap         - tap name
1133  *   (m) type:flow   - tap output type
1134  *   (m) nodes       - array of strings with node address
1135  *   (m) flows       - array of object with attributes:
1136  *                  (m) t  - frame time string
1137  *                  (m) n  - array of two numbers with source node index and destination node index
1138  *                  (m) pn - array of two numbers with source and destination port
1139  *                  (o) c  - comment
1140  */
1141 static void
1142 sharkd_session_process_tap_flow_cb(void *tapdata)
1143 {
1144         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1145         GList *flow_list;
1146         guint i;
1147
1148         const char *sepa = "";
1149
1150         sequence_analysis_get_nodes(graph_analysis);
1151
1152         printf("{\"tap\":\"seqa:%s\",\"type\":\"%s\"", graph_analysis->name, "flow");
1153
1154         printf(",\"nodes\":[");
1155         for (i = 0; i < graph_analysis->num_nodes; i++)
1156         {
1157                 char *addr_str;
1158
1159                 if (i)
1160                         printf(",");
1161
1162                 addr_str = address_to_display(NULL, &(graph_analysis->nodes[i]));
1163                 json_puts_string(addr_str);
1164                 wmem_free(NULL, addr_str);
1165         }
1166         printf("]");
1167
1168         printf(",\"flows\":[");
1169
1170         flow_list = g_queue_peek_nth_link(graph_analysis->items, 0);
1171         while (flow_list)
1172         {
1173                 seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data;
1174
1175                 flow_list = g_list_next(flow_list);
1176
1177                 if (!sai->display)
1178                         continue;
1179
1180                 printf("%s{", sepa);
1181
1182                 printf("\"t\":\"%s\"", sai->time_str);
1183                 printf(",\"n\":[%u,%u]", sai->src_node, sai->dst_node);
1184                 printf(",\"pn\":[%u,%u]", sai->port_src, sai->port_dst);
1185
1186                 if (sai->comment)
1187                 {
1188                         printf(",\"c\":");
1189                         json_puts_string(sai->comment);
1190                 }
1191
1192                 printf("}");
1193                 sepa = ",";
1194         }
1195
1196         printf("]");
1197
1198         printf("},");
1199 }
1200
1201 static void
1202 sharkd_session_free_tap_flow_cb(void *tapdata)
1203 {
1204         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1205
1206         sequence_analysis_info_free(graph_analysis);
1207 }
1208
1209 struct sharkd_conv_tap_data
1210 {
1211         const char *type;
1212         conv_hash_t hash;
1213         gboolean resolve_name;
1214         gboolean resolve_port;
1215 };
1216
1217 static gboolean
1218 sharkd_session_geoip_addr(address *addr, const char *suffix)
1219 {
1220         const mmdb_lookup_t *lookup = NULL;
1221         gboolean with_geoip = FALSE;
1222
1223         if (addr->type == AT_IPv4)
1224         {
1225                 guint32 ip;
1226
1227                 memcpy(&ip, addr->data, 4);
1228                 lookup = maxmind_db_lookup_ipv4(ip);
1229         }
1230         else if (addr->type == AT_IPv6)
1231         {
1232                 const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data;
1233
1234                 lookup = maxmind_db_lookup_ipv6(ip6);
1235         }
1236
1237         if (!lookup || !lookup->found)
1238                 return FALSE;
1239
1240         if (lookup->country)
1241         {
1242                 printf(",\"geoip_country%s\":", suffix);
1243                 json_puts_string(lookup->country);
1244                 with_geoip = TRUE;
1245         }
1246
1247         if (lookup->country_iso)
1248         {
1249                 printf(",\"geoip_country_iso%s\":", suffix);
1250                 json_puts_string(lookup->country_iso);
1251                 with_geoip = TRUE;
1252         }
1253
1254         if (lookup->city)
1255         {
1256                 printf(",\"geoip_city%s\":", suffix);
1257                 json_puts_string(lookup->city);
1258                 with_geoip = TRUE;
1259         }
1260
1261         if (lookup->as_org)
1262         {
1263                 printf(",\"geoip_as_org%s\":", suffix);
1264                 json_puts_string(lookup->as_org);
1265                 with_geoip = TRUE;
1266         }
1267
1268         if (lookup->as_number > 0)
1269         {
1270                 printf(",\"geoip_as%s\":%u", suffix, lookup->as_number);
1271                 with_geoip = TRUE;
1272         }
1273
1274         if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0)
1275         {
1276                 printf(",\"geoip_lat%s\":%f", suffix, lookup->latitude);
1277                 with_geoip = TRUE;
1278         }
1279
1280         if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0)
1281         {
1282                 printf(",\"geoip_lon%s\":%f", suffix, lookup->longitude);
1283                 with_geoip = TRUE;
1284         }
1285
1286         return with_geoip;
1287 }
1288
1289 struct sharkd_analyse_rtp_items
1290 {
1291         guint32 frame_num;
1292         guint32 sequence_num;
1293
1294         double delta;
1295         double jitter;
1296         double skew;
1297         double bandwidth;
1298         gboolean marker;
1299
1300         double arrive_offset;
1301
1302         /* from tap_rtp_stat_t */
1303         guint32 flags;
1304         guint16 pt;
1305 };
1306
1307 struct sharkd_analyse_rtp
1308 {
1309         const char *tap_name;
1310         struct sharkd_rtp_match rtp;
1311
1312         GSList *packets;
1313         double start_time;
1314         tap_rtp_stat_t statinfo;
1315 };
1316
1317 static void
1318 sharkd_session_process_tap_rtp_free_cb(void *tapdata)
1319 {
1320         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1321
1322         g_slist_free_full(rtp_req->packets, g_free);
1323         g_free(rtp_req);
1324 }
1325
1326 static gboolean
1327 sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer)
1328 {
1329         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1330         const struct _rtp_info *rtpinfo = (const struct _rtp_info *) pointer;
1331
1332         if (sharkd_rtp_match_check(&rtp_req->rtp, pinfo, rtpinfo))
1333         {
1334                 tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
1335                 struct sharkd_analyse_rtp_items *item;
1336
1337                 rtp_packet_analyse(statinfo, pinfo, rtpinfo);
1338
1339                 item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
1340
1341                 if (!rtp_req->packets)
1342                         rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
1343
1344                 item->frame_num    = pinfo->num;
1345                 item->sequence_num = rtpinfo->info_seq_num;
1346                 item->delta        = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta;
1347                 item->jitter       = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter;
1348                 item->skew         = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew;
1349                 item->bandwidth    = statinfo->bandwidth;
1350                 item->marker       = rtpinfo->info_marker_set ? TRUE : FALSE;
1351                 item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
1352
1353                 item->flags = statinfo->flags;
1354                 item->pt    = statinfo->pt;
1355
1356                 /* XXX, O(n) optimize */
1357                 rtp_req->packets = g_slist_append(rtp_req->packets, item);
1358         }
1359
1360         return TRUE;
1361 }
1362
1363 /**
1364  * sharkd_session_process_tap_rtp_analyse_cb()
1365  *
1366  * Output rtp analyse tap:
1367  *   (m) tap   - tap name
1368  *   (m) type  - tap output type
1369  *   (m) ssrc         - RTP SSRC
1370  *   (m) max_delta    - Max delta (ms)
1371  *   (m) max_delta_nr - Max delta packet #
1372  *   (m) max_jitter   - Max jitter (ms)
1373  *   (m) mean_jitter  - Mean jitter (ms)
1374  *   (m) max_skew     - Max skew (ms)
1375  *   (m) total_nr     - Total number of RTP packets
1376  *   (m) seq_err      - Number of sequence errors
1377  *   (m) duration     - Duration (ms)
1378  *   (m) items      - array of object with attributes:
1379  *                  (m) f    - frame number
1380  *                  (m) o    - arrive offset
1381  *                  (m) sn   - sequence number
1382  *                  (m) d    - delta
1383  *                  (m) j    - jitter
1384  *                  (m) sk   - skew
1385  *                  (m) bw   - bandwidth
1386  *                  (o) s    - status string
1387  *                  (o) t    - status type
1388  *                  (o) mark - rtp mark
1389  */
1390 static void
1391 sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
1392 {
1393         const int RTP_TYPE_CN       = 1;
1394         const int RTP_TYPE_ERROR    = 2;
1395         const int RTP_TYPE_WARN     = 3;
1396         const int RTP_TYPE_PT_EVENT = 4;
1397
1398         const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1399         const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
1400
1401         const char *sepa = "";
1402         GSList *l;
1403
1404         printf("{\"tap\":\"%s\",\"type\":\"rtp-analyse\"", rtp_req->tap_name);
1405
1406         printf(",\"ssrc\":%u", rtp_req->rtp.ssrc);
1407
1408         printf(",\"max_delta\":%f", statinfo->max_delta);
1409         printf(",\"max_delta_nr\":%u", statinfo->max_nr);
1410         printf(",\"max_jitter\":%f", statinfo->max_jitter);
1411         printf(",\"mean_jitter\":%f", statinfo->mean_jitter);
1412         printf(",\"max_skew\":%f", statinfo->max_skew);
1413         printf(",\"total_nr\":%u", statinfo->total_nr);
1414         printf(",\"seq_err\":%u", statinfo->sequence);
1415         printf(",\"duration\":%f", statinfo->time - statinfo->start_time);
1416
1417         printf(",\"items\":[");
1418         for (l = rtp_req->packets; l; l = l->next)
1419         {
1420                 struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
1421
1422                 printf("%s{", sepa);
1423
1424                 printf("\"f\":%u", item->frame_num);
1425                 printf(",\"o\":%.9f", item->arrive_offset);
1426                 printf(",\"sn\":%u", item->sequence_num);
1427                 printf(",\"d\":%.2f", item->delta);
1428                 printf(",\"j\":%.2f", item->jitter);
1429                 printf(",\"sk\":%.2f", item->skew);
1430                 printf(",\"bw\":%.2f", item->bandwidth);
1431
1432                 if (item->pt == PT_CN)
1433                         printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=13, RFC 3389)", RTP_TYPE_CN);
1434                 else if (item->pt == PT_CN_OLD)
1435                         printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=19, reserved)", RTP_TYPE_CN);
1436                 else if (item->flags & STAT_FLAG_WRONG_SEQ)
1437                         printf(",\"s\":\"%s\",\"t\":%d", "Wrong sequence number", RTP_TYPE_ERROR);
1438                 else if (item->flags & STAT_FLAG_DUP_PKT)
1439                         printf(",\"s\":\"%s\",\"t\":%d", "Suspected duplicate (MAC address) only delta time calculated", RTP_TYPE_WARN);
1440                 else if (item->flags & STAT_FLAG_REG_PT_CHANGE)
1441                         printf(",\"s\":\"Payload changed to PT=%u%s\",\"t\":%d",
1442                                 item->pt,
1443                                 (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : "",
1444                                 RTP_TYPE_WARN);
1445                 else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP)
1446                         printf(",\"s\":\"%s\",\"t\":%d", "Incorrect timestamp", RTP_TYPE_WARN);
1447                 else if ((item->flags & STAT_FLAG_PT_CHANGE)
1448                         &&  !(item->flags & STAT_FLAG_FIRST)
1449                         &&  !(item->flags & STAT_FLAG_PT_CN)
1450                         &&  (item->flags & STAT_FLAG_FOLLOW_PT_CN)
1451                         &&  !(item->flags & STAT_FLAG_MARKER))
1452                 {
1453                         printf(",\"s\":\"%s\",\"t\":%d", "Marker missing?", RTP_TYPE_WARN);
1454                 }
1455                 else if (item->flags & STAT_FLAG_PT_T_EVENT)
1456                         printf(",\"s\":\"PT=%u telephone/event\",\"t\":%d", item->pt, RTP_TYPE_PT_EVENT);
1457                 else if (item->flags & STAT_FLAG_MARKER)
1458                         printf(",\"t\":%d", RTP_TYPE_WARN);
1459
1460                 if (item->marker)
1461                         printf(",\"mark\":1");
1462
1463                 printf("}");
1464                 sepa = ",";
1465         }
1466         printf("]");
1467
1468         printf("},");
1469 }
1470
1471 /**
1472  * sharkd_session_process_tap_conv_cb()
1473  *
1474  * Output conv tap:
1475  *   (m) tap        - tap name
1476  *   (m) type       - tap output type
1477  *   (m) proto      - protocol short name
1478  *   (o) filter     - filter string
1479  *
1480  *   (o) convs      - array of object with attributes:
1481  *                  (m) saddr - source address
1482  *                  (m) daddr - destination address
1483  *                  (o) sport - source port
1484  *                  (o) dport - destination port
1485  *                  (m) txf   - TX frame count
1486  *                  (m) txb   - TX bytes
1487  *                  (m) rxf   - RX frame count
1488  *                  (m) rxb   - RX bytes
1489  *                  (m) start - (relative) first packet time
1490  *                  (m) stop  - (relative) last packet time
1491  *
1492  *   (o) hosts      - array of object with attributes:
1493  *                  (m) host - host address
1494  *                  (o) port - host port
1495  *                  (m) txf  - TX frame count
1496  *                  (m) txb  - TX bytes
1497  *                  (m) rxf  - RX frame count
1498  *                  (m) rxb  - RX bytes
1499  */
1500 static void
1501 sharkd_session_process_tap_conv_cb(void *arg)
1502 {
1503         conv_hash_t *hash = (conv_hash_t *) arg;
1504         const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1505         const char *proto;
1506         int proto_with_port;
1507         guint i;
1508
1509         int with_geoip = 0;
1510
1511         if (!strncmp(iu->type, "conv:", 5))
1512         {
1513                 printf("{\"tap\":\"%s\",\"type\":\"conv\"", iu->type);
1514                 printf(",\"convs\":[");
1515                 proto = iu->type + 5;
1516         }
1517         else if (!strncmp(iu->type, "endpt:", 6))
1518         {
1519                 printf("{\"tap\":\"%s\",\"type\":\"host\"", iu->type);
1520                 printf(",\"hosts\":[");
1521                 proto = iu->type + 6;
1522         }
1523         else
1524         {
1525                 printf("{\"tap\":\"%s\",\"type\":\"err\"", iu->type);
1526                 proto = "";
1527         }
1528
1529         proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
1530
1531         if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5))
1532         {
1533                 for (i = 0; i < iu->hash.conv_array->len; i++)
1534                 {
1535                         conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i);
1536                         char *src_addr, *dst_addr;
1537                         char *src_port, *dst_port;
1538                         char *filter_str;
1539
1540                         printf("%s{", i ? "," : "");
1541
1542                         printf("\"saddr\":\"%s\"",  (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name)));
1543                         printf(",\"daddr\":\"%s\"", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name)));
1544
1545                         if (proto_with_port)
1546                         {
1547                                 printf(",\"sport\":\"%s\"", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port)));
1548                                 printf(",\"dport\":\"%s\"", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port)));
1549
1550                                 wmem_free(NULL, src_port);
1551                                 wmem_free(NULL, dst_port);
1552                         }
1553
1554                         printf(",\"rxf\":%" G_GUINT64_FORMAT, iui->rx_frames);
1555                         printf(",\"rxb\":%" G_GUINT64_FORMAT, iui->rx_bytes);
1556
1557                         printf(",\"txf\":%" G_GUINT64_FORMAT, iui->tx_frames);
1558                         printf(",\"txb\":%" G_GUINT64_FORMAT, iui->tx_bytes);
1559
1560                         printf(",\"start\":%.9f", nstime_to_sec(&iui->start_time));
1561                         printf(",\"stop\":%.9f", nstime_to_sec(&iui->stop_time));
1562
1563                         filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
1564                         if (filter_str)
1565                         {
1566                                 printf(",\"filter\":\"%s\"", filter_str);
1567                                 g_free(filter_str);
1568                         }
1569
1570                         wmem_free(NULL, src_addr);
1571                         wmem_free(NULL, dst_addr);
1572
1573                         if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
1574                                 with_geoip = 1;
1575                         if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
1576                                 with_geoip = 1;
1577
1578                         printf("}");
1579                 }
1580         }
1581         else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6))
1582         {
1583                 for (i = 0; i < iu->hash.conv_array->len; i++)
1584                 {
1585                         hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
1586                         char *host_str, *port_str;
1587                         char *filter_str;
1588
1589                         printf("%s{", i ? "," : "");
1590
1591                         printf("\"host\":\"%s\"", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name)));
1592
1593                         if (proto_with_port)
1594                         {
1595                                 printf(",\"port\":\"%s\"", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port)));
1596
1597                                 wmem_free(NULL, port_str);
1598                         }
1599
1600                         printf(",\"rxf\":%" G_GUINT64_FORMAT, host->rx_frames);
1601                         printf(",\"rxb\":%" G_GUINT64_FORMAT, host->rx_bytes);
1602
1603                         printf(",\"txf\":%" G_GUINT64_FORMAT, host->tx_frames);
1604                         printf(",\"txb\":%" G_GUINT64_FORMAT, host->tx_bytes);
1605
1606                         filter_str = get_hostlist_filter(host);
1607                         if (filter_str)
1608                         {
1609                                 printf(",\"filter\":\"%s\"", filter_str);
1610                                 g_free(filter_str);
1611                         }
1612
1613                         wmem_free(NULL, host_str);
1614
1615                         if (sharkd_session_geoip_addr(&(host->myaddress), ""))
1616                                 with_geoip = 1;
1617                         printf("}");
1618                 }
1619         }
1620
1621         printf("],\"proto\":\"%s\",\"geoip\":%s},", proto, with_geoip ? "true" : "false");
1622 }
1623
1624 static void
1625 sharkd_session_free_tap_conv_cb(void *arg)
1626 {
1627         conv_hash_t *hash = (conv_hash_t *) arg;
1628         struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1629
1630         if (!strncmp(iu->type, "conv:", 5))
1631         {
1632                 reset_conversation_table_data(hash);
1633         }
1634         else if (!strncmp(iu->type, "endpt:", 6))
1635         {
1636                 reset_hostlist_table_data(hash);
1637         }
1638
1639         g_free(iu);
1640 }
1641
1642 /**
1643  * sharkd_session_process_tap_nstat_cb()
1644  *
1645  * Output nstat tap:
1646  *   (m) tap        - tap name
1647  *   (m) type       - tap output type
1648  *   (m) fields: array of objects with attributes:
1649  *                  (m) c - name
1650  *
1651  *   (m) tables: array of object with attributes:
1652  *                  (m) t - table title
1653  *                  (m) i - array of items
1654  */
1655 static void
1656 sharkd_session_process_tap_nstat_cb(void *arg)
1657 {
1658         stat_data_t *stat_data = (stat_data_t *) arg;
1659         guint i, j, k;
1660
1661         printf("{\"tap\":\"nstat:%s\",\"type\":\"nstat\"", stat_data->stat_tap_data->cli_string);
1662
1663         printf(",\"fields\":[");
1664         for (i = 0; i < stat_data->stat_tap_data->nfields; i++)
1665         {
1666                 stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]);
1667
1668                 if (i)
1669                         printf(",");
1670
1671                 printf("{");
1672
1673                 printf("\"c\":");
1674                 json_puts_string(field->column_name);
1675
1676                 printf("}");
1677         }
1678         printf("]");
1679
1680         printf(",\"tables\":[");
1681         for (i = 0; i < stat_data->stat_tap_data->tables->len; i++)
1682         {
1683                 stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i);
1684                 const char *sepa = "";
1685
1686                 if (i)
1687                         printf(",");
1688
1689                 printf("{");
1690
1691                 printf("\"t\":");
1692                 printf("\"%s\"", table->title);
1693
1694                 printf(",\"i\":[");
1695                 for (j = 0; j < table->num_elements; j++)
1696                 {
1697                         stat_tap_table_item_type *field_data;
1698
1699                         field_data = stat_tap_get_field_data(table, j, 0);
1700                         if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */
1701                                 continue;
1702
1703                         printf("%s[", sepa);
1704                         for (k = 0; k < table->num_fields; k++)
1705                         {
1706                                 field_data = stat_tap_get_field_data(table, j, k);
1707
1708                                 if (k)
1709                                         printf(",");
1710
1711                                 switch (field_data->type)
1712                                 {
1713                                         case TABLE_ITEM_UINT:
1714                                                 printf("%u", field_data->value.uint_value);
1715                                                 break;
1716
1717                                         case TABLE_ITEM_INT:
1718                                                 printf("%d", field_data->value.int_value);
1719                                                 break;
1720
1721                                         case TABLE_ITEM_STRING:
1722                                                 json_puts_string(field_data->value.string_value);
1723                                                 break;
1724
1725                                         case TABLE_ITEM_FLOAT:
1726                                                 printf("%f", field_data->value.float_value);
1727                                                 break;
1728
1729                                         case TABLE_ITEM_ENUM:
1730                                                 printf("%d", field_data->value.enum_value);
1731                                                 break;
1732
1733                                         case TABLE_ITEM_NONE:
1734                                                 printf("null");
1735                                                 break;
1736                                 }
1737                         }
1738
1739                         printf("]");
1740                         sepa = ",";
1741                 }
1742                 printf("]");
1743                 printf("}");
1744         }
1745
1746         printf("]},");
1747 }
1748
1749 static void
1750 sharkd_session_free_tap_nstat_cb(void *arg)
1751 {
1752         stat_data_t *stat_data = (stat_data_t *) arg;
1753
1754         free_stat_tables(stat_data->stat_tap_data);
1755 }
1756
1757 /**
1758  * sharkd_session_process_tap_rtd_cb()
1759  *
1760  * Output rtd tap:
1761  *   (m) tap        - tap name
1762  *   (m) type       - tap output type
1763  *   (m) stats - statistics rows - array object with attributes:
1764  *                  (m) type - statistic name
1765  *                  (m) num - number of messages
1766  *                  (m) min - minimum SRT time
1767  *                  (m) max - maximum SRT time
1768  *                  (m) tot - total SRT time
1769  *                  (m) min_frame - minimal SRT
1770  *                  (m) max_frame - maximum SRT
1771  *                  (o) open_req - Open Requests
1772  *                  (o) disc_rsp - Discarded Responses
1773  *                  (o) req_dup  - Duplicated Requests
1774  *                  (o) rsp_dup  - Duplicated Responses
1775  *   (o) open_req   - Open Requests
1776  *   (o) disc_rsp   - Discarded Responses
1777  *   (o) req_dup    - Duplicated Requests
1778  *   (o) rsp_dup    - Duplicated Responses
1779  */
1780 static void
1781 sharkd_session_process_tap_rtd_cb(void *arg)
1782 {
1783         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1784         register_rtd_t *rtd  = (register_rtd_t *) rtd_data->user_data;
1785
1786         guint i, j;
1787
1788         const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
1789
1790         /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
1791          *      some multiple table and single timestat (radius, h225)
1792          *      and it seems that value_string is used one for timestamp-ID, other one for table-ID
1793          *      I wonder how it will gonna work with multiple timestats and multiple tables...
1794          * (for usage grep for: register_rtd_table)
1795          */
1796         const value_string *vs = get_rtd_value_string(rtd);
1797         const char *sepa = "";
1798
1799         printf("{\"tap\":\"rtd:%s\",\"type\":\"rtd\"", filter);
1800
1801         if (rtd_data->stat_table.num_rtds == 1)
1802         {
1803                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
1804
1805                 printf(",\"open_req\":%u", ms->open_req_num);
1806                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1807                 printf(",\"req_dup\":%u", ms->req_dup_num);
1808                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1809         }
1810
1811         printf(",\"stats\":[");
1812         for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
1813         {
1814                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
1815
1816                 for (j = 0; j < ms->num_timestat; j++)
1817                 {
1818                         const char *type_str;
1819
1820                         if (ms->rtd[j].num == 0)
1821                                 continue;
1822
1823                         printf("%s{", sepa);
1824
1825                         if (rtd_data->stat_table.num_rtds == 1)
1826                                 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
1827                         else
1828                                 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
1829                         printf("\"type\":");
1830                         json_puts_string(type_str);
1831
1832                         printf(",\"num\":%u", ms->rtd[j].num);
1833                         printf(",\"min\":%.9f", nstime_to_sec(&(ms->rtd[j].min)));
1834                         printf(",\"max\":%.9f", nstime_to_sec(&(ms->rtd[j].max)));
1835                         printf(",\"tot\":%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
1836                         printf(",\"min_frame\":%u", ms->rtd[j].min_num);
1837                         printf(",\"max_frame\":%u", ms->rtd[j].max_num);
1838
1839                         if (rtd_data->stat_table.num_rtds != 1)
1840                         {
1841                                 /* like in tshark, display it on every row */
1842                                 printf(",\"open_req\":%u", ms->open_req_num);
1843                                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1844                                 printf(",\"req_dup\":%u", ms->req_dup_num);
1845                                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1846                         }
1847
1848                         printf("}");
1849                         sepa = ",";
1850                 }
1851         }
1852         printf("]},");
1853 }
1854
1855 static void
1856 sharkd_session_free_tap_rtd_cb(void *arg)
1857 {
1858         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1859
1860         free_rtd_table(&rtd_data->stat_table);
1861         g_free(rtd_data);
1862 }
1863
1864 /**
1865  * sharkd_session_process_tap_srt_cb()
1866  *
1867  * Output srt tap:
1868  *   (m) tap        - tap name
1869  *   (m) type       - tap output type
1870  *
1871  *   (m) tables - array of object with attributes:
1872  *                  (m) n - table name
1873  *                  (m) f - table filter
1874  *                  (o) c - table column name
1875  *                  (m) r - table rows - array object with attributes:
1876  *                            (m) n   - row name
1877  *                            (m) idx - procedure index
1878  *                            (m) num - number of events
1879  *                            (m) min - minimum SRT time
1880  *                            (m) max - maximum SRT time
1881  *                            (m) tot - total SRT time
1882  */
1883 static void
1884 sharkd_session_process_tap_srt_cb(void *arg)
1885 {
1886         srt_data_t *srt_data = (srt_data_t *) arg;
1887         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1888
1889         const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
1890
1891         guint i;
1892
1893         printf("{\"tap\":\"srt:%s\",\"type\":\"srt\"", filter);
1894
1895         printf(",\"tables\":[");
1896         for (i = 0; i < srt_data->srt_array->len; i++)
1897         {
1898                 /* SRT table */
1899                 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i);
1900                 const char *sepa = "";
1901
1902                 int j;
1903
1904                 if (i)
1905                         printf(",");
1906                 printf("{");
1907
1908                 printf("\"n\":");
1909                 if (rst->name)
1910                         json_puts_string(rst->name);
1911                 else if (rst->short_name)
1912                         json_puts_string(rst->short_name);
1913                 else
1914                         printf("\"table%u\"", i);
1915
1916                 if (rst->filter_string)
1917                 {
1918                         printf(",\"f\":");
1919                         json_puts_string(rst->filter_string);
1920                 }
1921
1922                 if (rst->proc_column_name)
1923                 {
1924                         printf(",\"c\":");
1925                         json_puts_string(rst->proc_column_name);
1926                 }
1927
1928                 printf(",\"r\":[");
1929                 for (j = 0; j < rst->num_procs; j++)
1930                 {
1931                         /* SRT row */
1932                         srt_procedure_t *proc = &rst->procedures[j];
1933
1934                         if (proc->stats.num == 0)
1935                                 continue;
1936
1937                         printf("%s{", sepa);
1938
1939                         printf("\"n\":");
1940                         json_puts_string(proc->procedure);
1941
1942                         if (rst->filter_string)
1943                                 printf(",\"idx\":%d", proc->proc_index);
1944
1945                         printf(",\"num\":%u", proc->stats.num);
1946
1947                         printf(",\"min\":%.9f", nstime_to_sec(&proc->stats.min));
1948                         printf(",\"max\":%.9f", nstime_to_sec(&proc->stats.max));
1949                         printf(",\"tot\":%.9f", nstime_to_sec(&proc->stats.tot));
1950
1951                         printf("}");
1952                         sepa = ",";
1953                 }
1954                 printf("]}");
1955         }
1956
1957         printf("]},");
1958 }
1959
1960 static void
1961 sharkd_session_free_tap_srt_cb(void *arg)
1962 {
1963         srt_data_t *srt_data = (srt_data_t *) arg;
1964         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1965
1966         free_srt_table(srt, srt_data->srt_array);
1967         g_array_free(srt_data->srt_array, TRUE);
1968         g_free(srt_data);
1969 }
1970
1971 struct sharkd_export_object_list
1972 {
1973         struct sharkd_export_object_list *next;
1974
1975         char *type;
1976         const char *proto;
1977         GSList *entries;
1978 };
1979
1980 static struct sharkd_export_object_list *sharkd_eo_list;
1981
1982 /**
1983  * sharkd_session_process_tap_eo_cb()
1984  *
1985  * Output eo tap:
1986  *   (m) tap        - tap name
1987  *   (m) type       - tap output type
1988  *   (m) proto      - protocol short name
1989  *   (m) objects    - array of object with attributes:
1990  *                  (m) pkt - packet number
1991  *                  (o) hostname - hostname
1992  *                  (o) type - content type
1993  *                  (o) filename - filename
1994  *                  (m) len - object length
1995  */
1996 static void
1997 sharkd_session_process_tap_eo_cb(void *tapdata)
1998 {
1999         export_object_list_t *tap_object = (export_object_list_t *) tapdata;
2000         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data;
2001         GSList *slist;
2002         int i = 0;
2003
2004         printf("{\"tap\":\"%s\",\"type\":\"eo\"", object_list->type);
2005         printf(",\"proto\":\"%s\"", object_list->proto);
2006         printf(",\"objects\":[");
2007
2008         for (slist = object_list->entries; slist; slist = slist->next)
2009         {
2010                 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
2011
2012                 printf("%s{", i ? "," : "");
2013
2014                 printf("\"pkt\":%u", eo_entry->pkt_num);
2015
2016                 if (eo_entry->hostname)
2017                 {
2018                         printf(",\"hostname\":");
2019                         json_puts_string(eo_entry->hostname);
2020                 }
2021
2022                 if (eo_entry->content_type)
2023                 {
2024                         printf(",\"type\":");
2025                         json_puts_string(eo_entry->content_type);
2026                 }
2027
2028                 if (eo_entry->filename)
2029                 {
2030                         printf(",\"filename\":");
2031                         json_puts_string(eo_entry->filename);
2032                 }
2033
2034                 printf(",\"_download\":\"%s_%d\"", object_list->type, i);
2035
2036                 printf(",\"len\":%" G_GINT64_FORMAT, eo_entry->payload_len);
2037
2038                 printf("}");
2039
2040                 i++;
2041         }
2042
2043         printf("]},");
2044 }
2045
2046 static void
2047 sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
2048 {
2049         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2050
2051         object_list->entries = g_slist_append(object_list->entries, entry);
2052 }
2053
2054 static export_object_entry_t *
2055 sharkd_eo_object_list_get_entry(void *gui_data, int row)
2056 {
2057         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2058
2059         return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
2060 }
2061
2062 /**
2063  * sharkd_session_process_tap_rtp_cb()
2064  *
2065  * Output RTP streams tap:
2066  *   (m) tap        - tap name
2067  *   (m) type       - tap output type
2068  *   (m) streams    - array of object with attributes:
2069  *                  (m) ssrc        - RTP synchronization source identifier
2070  *                  (m) payload     - stream payload
2071  *                  (m) saddr       - source address
2072  *                  (m) sport       - source port
2073  *                  (m) daddr       - destination address
2074  *                  (m) dport       - destination port
2075  *                  (m) pkts        - packets count
2076  *                  (m) max_delta   - max delta (ms)
2077  *                  (m) max_jitter  - max jitter (ms)
2078  *                  (m) mean_jitter - mean jitter (ms)
2079  *                  (m) expectednr  -
2080  *                  (m) totalnr     -
2081  *                  (m) problem     - if analyser found the problem
2082  *                  (m) ipver       - address IP version (4 or 6)
2083  */
2084 static void
2085 sharkd_session_process_tap_rtp_cb(void *arg)
2086 {
2087         rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
2088
2089         GList *listx;
2090         const char *sepa = "";
2091
2092         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "rtp-streams", "rtp-streams");
2093
2094         printf(",\"streams\":[");
2095         for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
2096         {
2097                 rtp_stream_info_t *streaminfo = (rtp_stream_info_t *) listx->data;
2098
2099                 char *src_addr, *dst_addr;
2100                 char *payload;
2101                 guint32 expected;
2102
2103                 src_addr = address_to_display(NULL, &(streaminfo->src_addr));
2104                 dst_addr = address_to_display(NULL, &(streaminfo->dest_addr));
2105
2106                 if (streaminfo->payload_type_name != NULL)
2107                         payload = wmem_strdup(NULL, streaminfo->payload_type_name);
2108                 else
2109                         payload = val_to_str_ext_wmem(NULL, streaminfo->payload_type, &rtp_payload_type_short_vals_ext, "Unknown (%u)");
2110
2111                 printf("%s{\"ssrc\":%u", sepa, streaminfo->ssrc);
2112                 printf(",\"payload\":\"%s\"", payload);
2113
2114                 printf(",\"saddr\":\"%s\"", src_addr);
2115                 printf(",\"sport\":%u", streaminfo->src_port);
2116
2117                 printf(",\"daddr\":\"%s\"", dst_addr);
2118                 printf(",\"dport\":%u", streaminfo->dest_port);
2119
2120                 printf(",\"pkts\":%u", streaminfo->packet_count);
2121
2122                 printf(",\"max_delta\":%f", streaminfo->rtp_stats.max_delta);
2123                 printf(",\"max_jitter\":%f", streaminfo->rtp_stats.max_jitter);
2124                 printf(",\"mean_jitter\":%f", streaminfo->rtp_stats.mean_jitter);
2125
2126                 expected = (streaminfo->rtp_stats.stop_seq_nr + streaminfo->rtp_stats.cycles * 65536) - streaminfo->rtp_stats.start_seq_nr + 1;
2127                 printf(",\"expectednr\":%u", expected);
2128                 printf(",\"totalnr\":%u", streaminfo->rtp_stats.total_nr);
2129
2130                 printf(",\"problem\":%s", streaminfo->problem ? "true" : "false");
2131
2132                 /* for filter */
2133                 printf(",\"ipver\":%d", (streaminfo->src_addr.type == AT_IPv6) ? 6 : 4);
2134
2135                 wmem_free(NULL, src_addr);
2136                 wmem_free(NULL, dst_addr);
2137                 wmem_free(NULL, payload);
2138
2139                 printf("}");
2140                 sepa = ",";
2141         }
2142         printf("]},");
2143 }
2144
2145 /**
2146  * sharkd_session_process_tap()
2147  *
2148  * Process tap request
2149  *
2150  * Input:
2151  *   (m) tap0         - First tap request
2152  *   (o) tap1...tap15 - Other tap requests
2153  *
2154  * Output object with attributes:
2155  *   (m) taps  - array of object with attributes:
2156  *                  (m) tap  - tap name
2157  *                  (m) type - tap output type
2158  *                  ...
2159  *                  for type:stats see sharkd_session_process_tap_stats_cb()
2160  *                  for type:nstat see sharkd_session_process_tap_nstat_cb()
2161  *                  for type:conv see sharkd_session_process_tap_conv_cb()
2162  *                  for type:host see sharkd_session_process_tap_conv_cb()
2163  *                  for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
2164  *                  for type:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
2165  *                  for type:eo see sharkd_session_process_tap_eo_cb()
2166  *                  for type:expert see sharkd_session_process_tap_expert_cb()
2167  *                  for type:rtd see sharkd_session_process_tap_rtd_cb()
2168  *                  for type:srt see sharkd_session_process_tap_srt_cb()
2169  *                  for type:flow see sharkd_session_process_tap_flow_cb()
2170  *
2171  *   (m) err   - error code
2172  */
2173 static void
2174 sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
2175 {
2176         void *taps_data[16];
2177         GFreeFunc taps_free[16];
2178         int taps_count = 0;
2179         int i;
2180
2181         rtpstream_tapinfo_t rtp_tapinfo =
2182                 { NULL, NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE };
2183
2184         for (i = 0; i < 16; i++)
2185         {
2186                 char tapbuf[32];
2187                 const char *tok_tap;
2188
2189                 void *tap_data = NULL;
2190                 GFreeFunc tap_free = NULL;
2191                 const char *tap_filter = "";
2192                 GString *tap_error = NULL;
2193
2194                 ws_snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
2195                 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
2196                 if (!tok_tap)
2197                         break;
2198
2199                 if (!strncmp(tok_tap, "stat:", 5))
2200                 {
2201                         stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
2202                         stats_tree *st;
2203
2204                         if (!cfg)
2205                         {
2206                                 fprintf(stderr, "sharkd_session_process_tap() stat %s not found\n", tok_tap + 5);
2207                                 continue;
2208                         }
2209
2210                         st = stats_tree_new(cfg, NULL, tap_filter);
2211
2212                         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);
2213
2214                         if (!tap_error && cfg->init)
2215                                 cfg->init(st);
2216
2217                         tap_data = st;
2218                         tap_free = sharkd_session_free_tap_stats_cb;
2219                 }
2220                 else if (!strcmp(tok_tap, "expert"))
2221                 {
2222                         struct sharkd_expert_tap *expert_tap;
2223
2224                         expert_tap = g_new0(struct sharkd_expert_tap, 1);
2225                         expert_tap->text = g_string_chunk_new(100);
2226
2227                         tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb);
2228
2229                         tap_data = expert_tap;
2230                         tap_free = sharkd_session_free_tap_expert_cb;
2231                 }
2232                 else if (!strncmp(tok_tap, "seqa:", 5))
2233                 {
2234                         seq_analysis_info_t *graph_analysis;
2235                         register_analysis_t *analysis;
2236                         const char *tap_name;
2237                         tap_packet_cb tap_func;
2238                         guint tap_flags;
2239
2240                         analysis = sequence_analysis_find_by_name(tok_tap + 5);
2241                         if (!analysis)
2242                         {
2243                                 fprintf(stderr, "sharkd_session_process_tap() seq analysis %s not found\n", tok_tap + 5);
2244                                 continue;
2245                         }
2246
2247                         graph_analysis = sequence_analysis_info_new();
2248                         graph_analysis->name = tok_tap + 5;
2249                         /* TODO, make configurable */
2250                         graph_analysis->any_addr = FALSE;
2251
2252                         tap_name  = sequence_analysis_get_tap_listener_name(analysis);
2253                         tap_flags = sequence_analysis_get_tap_flags(analysis);
2254                         tap_func  = sequence_analysis_get_packet_func(analysis);
2255
2256                         tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb);
2257
2258                         tap_data = graph_analysis;
2259                         tap_free = sharkd_session_free_tap_flow_cb;
2260                 }
2261                 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
2262                 {
2263                         struct register_ct *ct = NULL;
2264                         const char *ct_tapname;
2265                         struct sharkd_conv_tap_data *ct_data;
2266                         tap_packet_cb tap_func = NULL;
2267
2268                         if (!strncmp(tok_tap, "conv:", 5))
2269                         {
2270                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
2271
2272                                 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
2273                                 {
2274                                         fprintf(stderr, "sharkd_session_process_tap() conv %s not found\n", tok_tap + 5);
2275                                         continue;
2276                                 }
2277                         }
2278                         else if (!strncmp(tok_tap, "endpt:", 6))
2279                         {
2280                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
2281
2282                                 if (!ct || !(tap_func = get_hostlist_packet_func(ct)))
2283                                 {
2284                                         fprintf(stderr, "sharkd_session_process_tap() endpt %s not found\n", tok_tap + 6);
2285                                         continue;
2286                                 }
2287                         }
2288                         else
2289                         {
2290                                 fprintf(stderr, "sharkd_session_process_tap() conv/endpt(?): %s not found\n", tok_tap);
2291                                 continue;
2292                         }
2293
2294                         ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
2295
2296                         ct_data = (struct sharkd_conv_tap_data *) g_malloc0(sizeof(struct sharkd_conv_tap_data));
2297                         ct_data->type = tok_tap;
2298                         ct_data->hash.user_data = ct_data;
2299
2300                         /* XXX: make configurable */
2301                         ct_data->resolve_name = TRUE;
2302                         ct_data->resolve_port = TRUE;
2303
2304                         tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb);
2305
2306                         tap_data = &ct_data->hash;
2307                         tap_free = sharkd_session_free_tap_conv_cb;
2308                 }
2309                 else if (!strncmp(tok_tap, "nstat:", 6))
2310                 {
2311                         stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6);
2312                         stat_data_t *stat_data;
2313
2314                         if (!stat_tap)
2315                         {
2316                                 fprintf(stderr, "sharkd_session_process_tap() nstat=%s not found\n", tok_tap + 6);
2317                                 continue;
2318                         }
2319
2320                         stat_tap->stat_tap_init_cb(stat_tap);
2321
2322                         stat_data = g_new0(stat_data_t, 1);
2323                         stat_data->stat_tap_data = stat_tap;
2324                         stat_data->user_data = NULL;
2325
2326                         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);
2327
2328                         tap_data = stat_data;
2329                         tap_free = sharkd_session_free_tap_nstat_cb;
2330                 }
2331                 else if (!strncmp(tok_tap, "rtd:", 4))
2332                 {
2333                         register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
2334                         rtd_data_t *rtd_data;
2335                         char *err;
2336
2337                         if (!rtd)
2338                         {
2339                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s not found\n", tok_tap + 4);
2340                                 continue;
2341                         }
2342
2343                         rtd_table_get_filter(rtd, "", &tap_filter, &err);
2344                         if (err != NULL)
2345                         {
2346                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s err=%s\n", tok_tap + 4, err);
2347                                 g_free(err);
2348                                 continue;
2349                         }
2350
2351                         rtd_data = g_new0(rtd_data_t, 1);
2352                         rtd_data->user_data = rtd;
2353                         rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL);
2354
2355                         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);
2356
2357                         tap_data = rtd_data;
2358                         tap_free = sharkd_session_free_tap_rtd_cb;
2359                 }
2360                 else if (!strncmp(tok_tap, "srt:", 4))
2361                 {
2362                         register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
2363                         srt_data_t *srt_data;
2364                         char *err;
2365
2366                         if (!srt)
2367                         {
2368                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s not found\n", tok_tap + 4);
2369                                 continue;
2370                         }
2371
2372                         srt_table_get_filter(srt, "", &tap_filter, &err);
2373                         if (err != NULL)
2374                         {
2375                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s err=%s\n", tok_tap + 4, err);
2376                                 g_free(err);
2377                                 continue;
2378                         }
2379
2380                         srt_data = g_new0(srt_data_t, 1);
2381                         srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *));
2382                         srt_data->user_data = srt;
2383                         srt_table_dissector_init(srt, srt_data->srt_array);
2384
2385                         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);
2386
2387                         tap_data = srt_data;
2388                         tap_free = sharkd_session_free_tap_srt_cb;
2389                 }
2390                 else if (!strncmp(tok_tap, "eo:", 3))
2391                 {
2392                         register_eo_t *eo = get_eo_by_name(tok_tap + 3);
2393                         export_object_list_t *eo_object;
2394                         struct sharkd_export_object_list *object_list;
2395
2396                         if (!eo)
2397                         {
2398                                 fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
2399                                 continue;
2400                         }
2401
2402                         for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
2403                         {
2404                                 if (!strcmp(object_list->type, tok_tap))
2405                                 {
2406                                         g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
2407                                         object_list->entries = NULL;
2408                                         break;
2409                                 }
2410                         }
2411
2412                         if (!object_list)
2413                         {
2414                                 object_list = g_new(struct sharkd_export_object_list, 1);
2415                                 object_list->type = g_strdup(tok_tap);
2416                                 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
2417                                 object_list->entries = NULL;
2418                                 object_list->next = sharkd_eo_list;
2419                                 sharkd_eo_list = object_list;
2420                         }
2421
2422                         eo_object  = g_new0(export_object_list_t, 1);
2423                         eo_object->add_entry = sharkd_eo_object_list_add_entry;
2424                         eo_object->get_entry = sharkd_eo_object_list_get_entry;
2425                         eo_object->gui_data = (void *) object_list;
2426
2427                         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);
2428
2429                         tap_data = eo_object;
2430                         tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
2431                 }
2432                 else if (!strcmp(tok_tap, "rtp-streams"))
2433                 {
2434                         tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet, sharkd_session_process_tap_rtp_cb);
2435
2436                         tap_data = &rtp_tapinfo;
2437                         tap_free = rtpstream_reset_cb;
2438                 }
2439                 else if (!strncmp(tok_tap, "rtp-analyse:", 12))
2440                 {
2441                         struct sharkd_analyse_rtp *rtp_req;
2442
2443                         rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
2444                         if (!sharkd_rtp_match_init(&rtp_req->rtp, tok_tap + 12))
2445                         {
2446                                 g_free(rtp_req);
2447                                 continue;
2448                         }
2449
2450                         rtp_req->tap_name = tok_tap;
2451                         rtp_req->statinfo.first_packet = TRUE;
2452                         rtp_req->statinfo.reg_pt = PT_UNDEFINED;
2453
2454                         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);
2455
2456                         tap_data = rtp_req;
2457                         tap_free = sharkd_session_process_tap_rtp_free_cb;
2458                 }
2459                 else
2460                 {
2461                         fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);
2462                         continue;
2463                 }
2464
2465                 if (tap_error)
2466                 {
2467                         fprintf(stderr, "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str);
2468                         g_string_free(tap_error, TRUE);
2469                         if (tap_free)
2470                                 tap_free(tap_data);
2471                         continue;
2472                 }
2473
2474                 taps_data[taps_count] = tap_data;
2475                 taps_free[taps_count] = tap_free;
2476                 taps_count++;
2477         }
2478
2479         fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count);
2480         if (taps_count == 0)
2481                 return;
2482
2483         printf("{\"taps\":[");
2484         sharkd_retap();
2485         printf("null],\"err\":0}\n");
2486
2487         for (i = 0; i < taps_count; i++)
2488         {
2489                 if (taps_data[i])
2490                         remove_tap_listener(taps_data[i]);
2491
2492                 if (taps_free[i])
2493                         taps_free[i](taps_data[i]);
2494         }
2495 }
2496
2497 /**
2498  * sharkd_session_process_follow()
2499  *
2500  * Process follow request
2501  *
2502  * Input:
2503  *   (m) follow  - follow protocol request (e.g. HTTP)
2504  *   (m) filter  - filter request (e.g. tcp.stream == 1)
2505  *
2506  * Output object with attributes:
2507  *
2508  *   (m) err    - error code
2509  *   (m) shost  - server host
2510  *   (m) sport  - server port
2511  *   (m) sbytes - server send bytes count
2512  *   (m) chost  - client host
2513  *   (m) cport  - client port
2514  *   (m) cbytes - client send bytes count
2515  *   (o) payloads - array of object with attributes:
2516  *                  (o) s - set if server sent, else client
2517  *                  (m) n - packet number
2518  *                  (m) d - data base64 encoded
2519  */
2520 static void
2521 sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
2522 {
2523         const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
2524         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2525
2526         register_follow_t *follower;
2527         GString *tap_error;
2528
2529         follow_info_t *follow_info;
2530         const char *host;
2531         char *port;
2532
2533         if (!tok_follow || !tok_filter)
2534                 return;
2535
2536         follower = get_follow_by_name(tok_follow);
2537         if (!follower)
2538         {
2539                 fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
2540                 return;
2541         }
2542
2543         /* follow_reset_stream ? */
2544         follow_info = g_new0(follow_info_t, 1);
2545         /* gui_data, filter_out_filter not set, but not used by dissector */
2546
2547         tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL);
2548         if (tap_error)
2549         {
2550                 fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
2551                 g_string_free(tap_error, TRUE);
2552                 g_free(follow_info);
2553                 return;
2554         }
2555
2556         sharkd_retap();
2557
2558         printf("{");
2559
2560         printf("\"err\":0");
2561
2562         /* Server information: hostname, port, bytes sent */
2563         host = address_to_name(&follow_info->server_ip);
2564         printf(",\"shost\":");
2565         json_puts_string(host);
2566
2567         port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
2568         printf(",\"sport\":");
2569         json_puts_string(port);
2570         wmem_free(NULL, port);
2571
2572         printf(",\"sbytes\":%u", follow_info->bytes_written[0]);
2573
2574         /* Client information: hostname, port, bytes sent */
2575         host = address_to_name(&follow_info->client_ip);
2576         printf(",\"chost\":");
2577         json_puts_string(host);
2578
2579         port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
2580         printf(",\"cport\":");
2581         json_puts_string(port);
2582         wmem_free(NULL, port);
2583
2584         printf(",\"cbytes\":%u", follow_info->bytes_written[1]);
2585
2586         if (follow_info->payload)
2587         {
2588                 follow_record_t *follow_record;
2589                 GList *cur;
2590                 const char *sepa = "";
2591
2592                 printf(",\"payloads\":[");
2593
2594                 for (cur = follow_info->payload; cur; cur = g_list_next(cur))
2595                 {
2596                         follow_record = (follow_record_t *) cur->data;
2597
2598                         printf("%s{", sepa);
2599
2600                         printf("\"n\":%u", follow_record->packet_num);
2601
2602                         printf(",\"d\":");
2603                         json_print_base64(follow_record->data->data, follow_record->data->len);
2604
2605                         if (follow_record->is_server)
2606                                 printf(",\"s\":%d", 1);
2607
2608                         printf("}");
2609                         sepa = ",";
2610                 }
2611
2612                 printf("]");
2613         }
2614
2615         printf("}\n");
2616
2617         remove_tap_listener(follow_info);
2618         follow_info_free(follow_info);
2619 }
2620
2621 static void
2622 sharkd_session_process_frame_cb_tree(epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs)
2623 {
2624         proto_node *node;
2625         const char *sepa = "";
2626
2627         printf("[");
2628         for (node = tree->first_child; node; node = node->next)
2629         {
2630                 field_info *finfo = PNODE_FINFO(node);
2631
2632                 if (!finfo)
2633                         continue;
2634
2635                 /* XXX, for now always skip hidden */
2636                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
2637                         continue;
2638
2639                 printf("%s{", sepa);
2640
2641                 printf("\"l\":");
2642                 if (!finfo->rep)
2643                 {
2644                         char label_str[ITEM_LABEL_LENGTH];
2645
2646                         label_str[0] = '\0';
2647                         proto_item_fill_label(finfo, label_str);
2648                         json_puts_string(label_str);
2649                 }
2650                 else
2651                 {
2652                         json_puts_string(finfo->rep->representation);
2653                 }
2654
2655                 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
2656                 {
2657                         int idx;
2658
2659                         for (idx = 1; tvbs[idx]; idx++)
2660                         {
2661                                 if (tvbs[idx] == finfo->ds_tvb)
2662                                 {
2663                                         printf(",\"ds\":%d", idx);
2664                                         break;
2665                                 }
2666                         }
2667                 }
2668
2669                 if (finfo->start >= 0 && finfo->length > 0)
2670                         printf(",\"h\":[%d,%d]", finfo->start, finfo->length);
2671
2672                 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
2673                         printf(",\"i\":[%d,%d]", finfo->appendix_start, finfo->appendix_length);
2674
2675
2676                 if (finfo->hfinfo)
2677                 {
2678                         char *filter;
2679
2680                         if (finfo->hfinfo->type == FT_PROTOCOL)
2681                         {
2682                                 printf(",\"t\":\"proto\"");
2683                         }
2684                         else if (finfo->hfinfo->type == FT_FRAMENUM)
2685                         {
2686                                 printf(",\"t\":\"framenum\",\"fnum\":%u", finfo->value.value.uinteger);
2687                         }
2688                         else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type))
2689                         {
2690                                 char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
2691
2692                                 printf(",\"t\":\"url\",\"url\":");
2693                                 json_puts_string(url);
2694                                 wmem_free(NULL, url);
2695                         }
2696
2697                         filter = proto_construct_match_selected_string(finfo, edt);
2698                         if (filter)
2699                         {
2700                                 printf(",\"f\":");
2701                                 json_puts_string(filter);
2702                                 wmem_free(NULL, filter);
2703                         }
2704                 }
2705
2706                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2707                 {
2708                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2709
2710                         g_assert(severity != NULL);
2711
2712                         printf(",\"s\":\"%s\"", severity);
2713                 }
2714
2715                 if (((proto_tree *) node)->first_child)
2716                 {
2717                         if (finfo->tree_type != -1)
2718                                 printf(",\"e\":%d", finfo->tree_type);
2719                         printf(",\"n\":");
2720                         sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs);
2721                 }
2722
2723                 printf("}");
2724                 sepa = ",";
2725         }
2726         printf("]");
2727 }
2728
2729 static gboolean
2730 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2731 {
2732         register_follow_t *follower = (register_follow_t *) value;
2733         packet_info *pi = (packet_info *) user_data;
2734
2735         const int proto_id = get_follow_proto_id(follower);
2736
2737         guint32 ignore_stream;
2738
2739         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2740         {
2741                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2742                 char *follow_filter;
2743
2744                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2745
2746                 printf(",[\"%s\",", layer_proto);
2747                 json_puts_string(follow_filter);
2748                 printf("]");
2749
2750                 g_free(follow_filter);
2751         }
2752
2753         return FALSE;
2754 }
2755
2756 static void
2757 sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2758 {
2759         packet_info *pi = &edt->pi;
2760         frame_data *fdata = pi->fd;
2761         const char *pkt_comment = NULL;
2762
2763         (void) data;
2764
2765         printf("{");
2766
2767         printf("\"err\":0");
2768
2769         if (fdata->flags.has_user_comment)
2770                 pkt_comment = sharkd_get_user_comment(fdata);
2771         else if (fdata->flags.has_phdr_comment)
2772                 pkt_comment = pi->rec->opt_comment;
2773
2774         if (pkt_comment)
2775         {
2776                 printf(",\"comment\":");
2777                 json_puts_string(pkt_comment);
2778         }
2779
2780         if (tree)
2781         {
2782                 tvbuff_t **tvbs = NULL;
2783
2784                 printf(",\"tree\":");
2785
2786                 /* arrayize data src, to speedup searching for ds_tvb index */
2787                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2788                 {
2789                         guint count = g_slist_length((GSList *) data_src);
2790                         guint i;
2791
2792                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2793
2794                         for (i = 0; i < count; i++)
2795                         {
2796                                 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2797
2798                                 tvbs[i] = get_data_source_tvb(src);
2799                         }
2800
2801                         tvbs[count] = NULL;
2802                 }
2803
2804                 sharkd_session_process_frame_cb_tree(edt, tree, tvbs);
2805
2806                 g_free(tvbs);
2807         }
2808
2809         if (cinfo)
2810         {
2811                 int col;
2812
2813                 printf(",\"col\":[");
2814                 for (col = 0; col < cinfo->num_cols; ++col)
2815                 {
2816                         const col_item_t *col_item = &cinfo->columns[col];
2817
2818                         printf("%s\"%s\"", (col) ? "," : "", col_item->col_data);
2819                 }
2820                 printf("]");
2821         }
2822
2823         if (data_src)
2824         {
2825                 struct data_source *src = (struct data_source *) data_src->data;
2826                 const char *ds_sepa = NULL;
2827
2828                 tvbuff_t *tvb;
2829                 guint length;
2830
2831                 tvb = get_data_source_tvb(src);
2832                 length = tvb_captured_length(tvb);
2833
2834                 printf(",\"bytes\":");
2835                 if (length != 0)
2836                 {
2837                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2838
2839                         /* XXX pi.fd->flags.encoding */
2840                         json_print_base64(cp, length);
2841                 }
2842                 else
2843                 {
2844                         json_print_base64("", 0);
2845                 }
2846
2847                 data_src = data_src->next;
2848                 if (data_src)
2849                 {
2850                         printf(",\"ds\":[");
2851                         ds_sepa = "";
2852                 }
2853
2854                 while (data_src)
2855                 {
2856                         src = (struct data_source *) data_src->data;
2857
2858                         {
2859                                 char *src_name = get_data_source_name(src);
2860
2861                                 printf("%s{\"name\":", ds_sepa);
2862                                 json_puts_string(src_name);
2863                                 wmem_free(NULL, src_name);
2864                         }
2865
2866                         tvb = get_data_source_tvb(src);
2867                         length = tvb_captured_length(tvb);
2868
2869                         printf(",\"bytes\":");
2870                         if (length != 0)
2871                         {
2872                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
2873
2874                                 /* XXX pi.fd->flags.encoding */
2875                                 json_print_base64(cp, length);
2876                         }
2877                         else
2878                         {
2879                                 json_print_base64("", 0);
2880                         }
2881
2882                         printf("}");
2883                         ds_sepa = ",";
2884
2885                         data_src = data_src->next;
2886                 }
2887
2888                 /* close ds, only if was opened */
2889                 if (ds_sepa != NULL)
2890                         printf("]");
2891         }
2892
2893         printf(",\"fol\":[0");
2894         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
2895         printf("]");
2896
2897         printf("}\n");
2898 }
2899
2900 /**
2901  * sharkd_session_process_intervals()
2902  *
2903  * Process intervals request - generate basic capture file statistics per requested interval.
2904  *
2905  * Input:
2906  *   (o) interval - interval time in ms, if not specified: 1000ms
2907  *   (o) filter   - filter for generating interval request
2908  *
2909  * Output object with attributes:
2910  *   (m) intervals - array of intervals, with indexes:
2911  *             [0] - index of interval,
2912  *             [1] - number of frames during interval,
2913  *             [2] - number of bytes during interval.
2914  *
2915  *   (m) last   - last interval number.
2916  *   (m) frames - total number of frames
2917  *   (m) bytes  - total number of bytes
2918  *
2919  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
2920  */
2921 static void
2922 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
2923 {
2924         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
2925         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2926
2927         const guint8 *filter_data = NULL;
2928
2929         struct
2930         {
2931                 unsigned int frames;
2932                 guint64 bytes;
2933         } st, st_total;
2934
2935         nstime_t *start_ts;
2936
2937         guint32 interval_ms = 1000; /* default: one per second */
2938
2939         const char *sepa = "";
2940         unsigned int framenum;
2941         gint64 idx;
2942         gint64 max_idx = 0;
2943
2944         if (tok_interval)
2945         {
2946                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
2947                 {
2948                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
2949                         return;
2950                 }
2951         }
2952
2953         if (tok_filter)
2954         {
2955                 filter_data = sharkd_session_filter_data(tok_filter);
2956                 if (!filter_data)
2957                         return;
2958         }
2959
2960         st_total.frames = 0;
2961         st_total.bytes  = 0;
2962
2963         st.frames = 0;
2964         st.bytes  = 0;
2965
2966         idx = 0;
2967
2968         printf("{\"intervals\":[");
2969
2970         start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL;
2971
2972         for (framenum = 1; framenum <= cfile.count; framenum++)
2973         {
2974                 frame_data *fdata;
2975                 gint64 msec_rel;
2976                 gint64 new_idx;
2977
2978                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
2979                         continue;
2980
2981                 fdata = sharkd_get_frame(framenum);
2982
2983                 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
2984                 new_idx  = msec_rel / interval_ms;
2985
2986                 if (idx != new_idx)
2987                 {
2988                         if (st.frames != 0)
2989                         {
2990                                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
2991                                 sepa = ",";
2992                         }
2993
2994                         idx = new_idx;
2995                         if (idx > max_idx)
2996                                 max_idx = idx;
2997
2998                         st.frames = 0;
2999                         st.bytes  = 0;
3000                 }
3001
3002                 st.frames += 1;
3003                 st.bytes  += fdata->pkt_len;
3004
3005                 st_total.frames += 1;
3006                 st_total.bytes  += fdata->pkt_len;
3007         }
3008
3009         if (st.frames != 0)
3010         {
3011                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
3012                 /* sepa = ","; */
3013         }
3014
3015         printf("],\"last\":%" G_GINT64_FORMAT ",\"frames\":%u,\"bytes\":%" G_GUINT64_FORMAT "}\n", max_idx, st_total.frames, st_total.bytes);
3016 }
3017
3018 /**
3019  * sharkd_session_process_frame()
3020  *
3021  * Process frame request
3022  *
3023  * Input:
3024  *   (m) frame - requested frame number
3025  *   (o) ref_frame - time reference frame number
3026  *   (o) prev_frame - previously displayed frame number
3027  *   (o) proto - set if output frame tree
3028  *   (o) columns - set if output frame columns
3029  *   (o) bytes - set if output frame bytes
3030  *
3031  * Output object with attributes:
3032  *   (m) err   - 0 if succeed
3033  *   (o) tree  - array of frame nodes with attributes:
3034  *                  l - label
3035  *                  t: 'proto', 'framenum', 'url' - type of node
3036  *                  f - filter string
3037  *                  s - severity
3038  *                  e - subtree ett index
3039  *                  n - array of subtree nodes
3040  *                  h - two item array: (item start, item length)
3041  *                  i - two item array: (appendix start, appendix length)
3042  *                  p - [RESERVED] two item array: (protocol start, protocol length)
3043  *                  ds- data src index
3044  *                  url  - only for t:'url', url
3045  *                  fnum - only for t:'framenum', frame number
3046  *
3047  *   (o) col   - array of column data
3048  *   (o) bytes - base64 of frame bytes
3049  *   (o) ds    - array of other data srcs
3050  *   (o) comment - frame comment
3051  *   (o) fol   - array of follow filters:
3052  *                  [0] - protocol
3053  *                  [1] - filter string
3054  */
3055 static void
3056 sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
3057 {
3058         const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
3059         const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame");
3060         const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame");
3061         int tok_proto   = (json_find_attr(buf, tokens, count, "proto") != NULL);
3062         int tok_bytes   = (json_find_attr(buf, tokens, count, "bytes") != NULL);
3063         int tok_columns = (json_find_attr(buf, tokens, count, "columns") != NULL);
3064
3065         guint32 framenum, ref_frame_num, prev_dis_num;
3066
3067         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3068                 return;
3069
3070         ref_frame_num = (framenum != 1) ? 1 : 0;
3071         if (tok_ref_frame && (!ws_strtou32(tok_ref_frame, NULL, &ref_frame_num) || ref_frame_num > framenum))
3072                 return;
3073
3074         prev_dis_num = framenum - 1;
3075         if (tok_prev_frame && (!ws_strtou32(tok_prev_frame, NULL, &prev_dis_num) || prev_dis_num >= framenum))
3076                 return;
3077
3078         sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, &sharkd_session_process_frame_cb, tok_bytes, tok_columns, tok_proto, NULL);
3079 }
3080
3081 /**
3082  * sharkd_session_process_check()
3083  *
3084  * Process check request.
3085  *
3086  * Input:
3087  *   (o) filter - filter to be checked
3088  *
3089  * Output object with attributes:
3090  *   (m) err - always 0
3091  *   (o) filter - 'ok', 'warn' or error message
3092  */
3093 static int
3094 sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
3095 {
3096         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3097
3098         printf("{\"err\":0");
3099         if (tok_filter != NULL)
3100         {
3101                 char *err_msg = NULL;
3102                 dfilter_t *dfp;
3103
3104                 if (dfilter_compile(tok_filter, &dfp, &err_msg))
3105                 {
3106                         const char *s = "ok";
3107
3108                         if (dfilter_deprecated_tokens(dfp))
3109                                 s = "warn";
3110
3111                         printf(",\"filter\":\"%s\"", s);
3112                         dfilter_free(dfp);
3113                 }
3114                 else
3115                 {
3116                         printf(",\"filter\":");
3117                         json_puts_string(err_msg);
3118                         g_free(err_msg);
3119                 }
3120         }
3121
3122         printf("}\n");
3123         return 0;
3124 }
3125
3126 struct sharkd_session_process_complete_pref_data
3127 {
3128         const char *module;
3129         const char *pref;
3130         const char *sepa;
3131 };
3132
3133 static guint
3134 sharkd_session_process_complete_pref_cb(module_t *module, gpointer d)
3135 {
3136         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3137
3138         if (strncmp(data->pref, module->name, strlen(data->pref)) != 0)
3139                 return 0;
3140
3141         printf("%s{\"f\":\"%s\",\"d\":\"%s\"}", data->sepa, module->name, module->title);
3142         data->sepa = ",";
3143
3144         return 0;
3145 }
3146
3147 static guint
3148 sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d)
3149 {
3150         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3151         const char *pref_name = prefs_get_name(pref);
3152         const char *pref_title = prefs_get_title(pref);
3153
3154         if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0)
3155                 return 0;
3156
3157         printf("%s{\"f\":\"%s.%s\",\"d\":\"%s\"}", data->sepa, data->module, pref_name, pref_title);
3158         data->sepa = ",";
3159
3160         return 0; /* continue */
3161 }
3162
3163 /**
3164  * sharkd_session_process_complete()
3165  *
3166  * Process complete request
3167  *
3168  * Input:
3169  *   (o) field - field to be completed
3170  *   (o) pref  - preference to be completed
3171  *
3172  * Output object with attributes:
3173  *   (m) err - always 0
3174  *   (o) field - array of object with attributes:
3175  *                  (m) f - field text
3176  *                  (o) t - field type (FT_ number)
3177  *                  (o) n - field name
3178  *   (o) pref  - array of object with attributes:
3179  *                  (m) f - pref name
3180  *                  (o) d - pref description
3181  */
3182 static int
3183 sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count)
3184 {
3185         const char *tok_field = json_find_attr(buf, tokens, count, "field");
3186         const char *tok_pref  = json_find_attr(buf, tokens, count, "pref");
3187
3188         printf("{\"err\":0");
3189         if (tok_field != NULL && tok_field[0])
3190         {
3191                 const size_t filter_length = strlen(tok_field);
3192                 const int filter_with_dot = !!strchr(tok_field, '.');
3193
3194                 void *proto_cookie;
3195                 void *field_cookie;
3196                 int proto_id;
3197                 const char *sepa = "";
3198
3199                 printf(",\"field\":[");
3200
3201                 for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie))
3202                 {
3203                         protocol_t *protocol = find_protocol_by_id(proto_id);
3204                         const char *protocol_filter;
3205                         const char *protocol_name;
3206                         header_field_info *hfinfo;
3207
3208                         if (!proto_is_protocol_enabled(protocol))
3209                                 continue;
3210
3211                         protocol_name   = proto_get_protocol_long_name(protocol);
3212                         protocol_filter = proto_get_protocol_filter_name(proto_id);
3213
3214                         if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length))
3215                         {
3216                                 printf("%s{", sepa);
3217                                 {
3218                                         printf("\"f\":");
3219                                         json_puts_string(protocol_filter);
3220                                         printf(",\"t\":%d", FT_PROTOCOL);
3221                                         printf(",\"n\":");
3222                                         json_puts_string(protocol_name);
3223                                 }
3224                                 printf("}");
3225                                 sepa = ",";
3226                         }
3227
3228                         if (!filter_with_dot)
3229                                 continue;
3230
3231                         for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie))
3232                         {
3233                                 if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
3234                                         continue;
3235
3236                                 if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length))
3237                                 {
3238                                         printf("%s{", sepa);
3239                                         {
3240                                                 printf("\"f\":");
3241                                                 json_puts_string(hfinfo->abbrev);
3242
3243                                                 /* XXX, skip displaying name, if there are multiple (to not confuse user) */
3244                                                 if (hfinfo->same_name_next == NULL)
3245                                                 {
3246                                                         printf(",\"t\":%d", hfinfo->type);
3247                                                         printf(",\"n\":");
3248                                                         json_puts_string(hfinfo->name);
3249                                                 }
3250                                         }
3251                                         printf("}");
3252                                         sepa = ",";
3253                                 }
3254                         }
3255                 }
3256
3257                 printf("]");
3258         }
3259
3260         if (tok_pref != NULL && tok_pref[0])
3261         {
3262                 struct sharkd_session_process_complete_pref_data data;
3263                 char *dot_sepa;
3264
3265                 data.module = tok_pref;
3266                 data.pref = tok_pref;
3267                 data.sepa = "";
3268
3269                 printf(",\"pref\":[");
3270
3271                 if ((dot_sepa = strchr(tok_pref, '.')))
3272                 {
3273                         module_t *pref_mod;
3274
3275                         *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3276                         data.pref = dot_sepa + 1;
3277
3278                         pref_mod = prefs_find_module(data.module);
3279                         if (pref_mod)
3280                                 prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data);
3281
3282                         *dot_sepa = '.';
3283                 }
3284                 else
3285                 {
3286                         prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data);
3287                 }
3288
3289                 printf("]");
3290         }
3291
3292
3293         printf("}\n");
3294         return 0;
3295 }
3296
3297 /**
3298  * sharkd_session_process_setcomment()
3299  *
3300  * Process setcomment request
3301  *
3302  * Input:
3303  *   (m) frame - frame number
3304  *   (o) comment - user comment
3305  *
3306  * Output object with attributes:
3307  *   (m) err   - error code: 0 succeed
3308  */
3309 static void
3310 sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count)
3311 {
3312         const char *tok_frame   = json_find_attr(buf, tokens, count, "frame");
3313         const char *tok_comment = json_find_attr(buf, tokens, count, "comment");
3314
3315         guint32 framenum;
3316         frame_data *fdata;
3317         int ret;
3318
3319         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3320                 return;
3321
3322         fdata = sharkd_get_frame(framenum);
3323         if (!fdata)
3324                 return;
3325
3326         ret = sharkd_set_user_comment(fdata, tok_comment);
3327         printf("{\"err\":%d}\n", ret);
3328 }
3329
3330 /**
3331  * sharkd_session_process_setconf()
3332  *
3333  * Process setconf request
3334  *
3335  * Input:
3336  *   (m) name  - preference name
3337  *   (m) value - preference value
3338  *
3339  * Output object with attributes:
3340  *   (m) err   - error code: 0 succeed
3341  */
3342 static void
3343 sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count)
3344 {
3345         const char *tok_name = json_find_attr(buf, tokens, count, "name");
3346         const char *tok_value = json_find_attr(buf, tokens, count, "value");
3347         char pref[4096];
3348         char *errmsg = NULL;
3349
3350         prefs_set_pref_e ret;
3351
3352         if (!tok_name || tok_name[0] == '\0' || !tok_value)
3353                 return;
3354
3355         ws_snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value);
3356
3357         ret = prefs_set_pref(pref, &errmsg);
3358         printf("{\"err\":%d", ret);
3359         if (errmsg)
3360         {
3361                 /* Add error message for some syntax errors. */
3362                 printf(",\"errmsg\":");
3363                 json_puts_string(errmsg);
3364         }
3365         printf("}\n");
3366         g_free(errmsg);
3367 }
3368
3369 struct sharkd_session_process_dumpconf_data
3370 {
3371         module_t *module;
3372         const char *sepa;
3373 };
3374
3375 static guint
3376 sharkd_session_process_dumpconf_cb(pref_t *pref, gpointer d)
3377 {
3378         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3379         const char *pref_name = prefs_get_name(pref);
3380
3381         printf("%s\"%s.%s\":{", data->sepa, data->module->name, pref_name);
3382
3383         switch (prefs_get_type(pref))
3384         {
3385                 case PREF_UINT:
3386                 case PREF_DECODE_AS_UINT:
3387                         printf("\"u\":%u", prefs_get_uint_value_real(pref, pref_current));
3388                         if (prefs_get_uint_base(pref) != 10)
3389                                 printf(",\"ub\":%u", prefs_get_uint_base(pref));
3390                         break;
3391
3392                 case PREF_BOOL:
3393                         printf("\"b\":%s", prefs_get_bool_value(pref, pref_current) ? "1" : "0");
3394                         break;
3395
3396                 case PREF_STRING:
3397                 case PREF_SAVE_FILENAME:
3398                 case PREF_OPEN_FILENAME:
3399                 case PREF_DIRNAME:
3400                         printf("\"s\":");
3401                         json_puts_string(prefs_get_string_value(pref, pref_current));
3402                         break;
3403
3404                 case PREF_ENUM:
3405                 {
3406                         const enum_val_t *enums;
3407                         const char *enum_sepa = "";
3408
3409                         printf("\"e\":[");
3410                         for (enums = prefs_get_enumvals(pref); enums->name; enums++)
3411                         {
3412                                 printf("%s{\"v\":%d", enum_sepa, enums->value);
3413
3414                                 if (enums->value == prefs_get_enum_value(pref, pref_current))
3415                                         printf(",\"s\":1");
3416
3417                                 printf(",\"d\":");
3418                                 json_puts_string(enums->description);
3419
3420                                 printf("}");
3421                                 enum_sepa = ",";
3422                         }
3423                         printf("]");
3424                         break;
3425                 }
3426
3427                 case PREF_RANGE:
3428                 case PREF_DECODE_AS_RANGE:
3429                 {
3430                         char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
3431                         printf("\"r\":\"%s\"", range_str);
3432                         wmem_free(NULL, range_str);
3433                         break;
3434                 }
3435
3436                 case PREF_UAT:
3437                 {
3438                         uat_t *uat = prefs_get_uat_value(pref);
3439                         guint idx;
3440
3441                         printf("\"t\":[");
3442                         for (idx = 0; idx < uat->raw_data->len; idx++)
3443                         {
3444                                 void *rec = UAT_INDEX_PTR(uat, idx);
3445                                 guint colnum;
3446
3447                                 if (idx)
3448                                         printf(",");
3449
3450                                 printf("[");
3451                                 for (colnum = 0; colnum < uat->ncols; colnum++)
3452                                 {
3453                                         char *str = uat_fld_tostr(rec, &(uat->fields[colnum]));
3454
3455                                         if (colnum)
3456                                                 printf(",");
3457
3458                                         json_puts_string(str);
3459                                         g_free(str);
3460                                 }
3461
3462                                 printf("]");
3463                         }
3464
3465                         printf("]");
3466                         break;
3467                 }
3468
3469                 case PREF_COLOR:
3470                 case PREF_CUSTOM:
3471                 case PREF_STATIC_TEXT:
3472                 case PREF_OBSOLETE:
3473                         /* TODO */
3474                         break;
3475         }
3476
3477 #if 0
3478         printf(",\"t\":");
3479         json_puts_string(prefs_get_title(pref));
3480 #endif
3481
3482         printf("}");
3483         data->sepa = ",";
3484
3485         return 0; /* continue */
3486 }
3487
3488 static guint
3489 sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d)
3490 {
3491         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3492
3493         data->module = module;
3494         prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data);
3495
3496         return 0;
3497 }
3498
3499 /**
3500  * sharkd_session_process_dumpconf()
3501  *
3502  * Process dumpconf request
3503  *
3504  * Input:
3505  *   (o) pref - module, or preference, NULL for all
3506  *
3507  * Output object with attributes:
3508  *   (o) prefs   - object with module preferences
3509  *                  (m) [KEY] - preference name
3510  *                  (o) u - preference value (for PREF_UINT, PREF_DECODE_AS_UINT)
3511  *                  (o) ub - preference value suggested base for display (for PREF_UINT, PREF_DECODE_AS_UINT) and if different than 10
3512  *                  (o) b - preference value (only for PREF_BOOL) (1 true, 0 false)
3513  *                  (o) s - preference value (for PREF_STRING, PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME)
3514  *                  (o) e - preference possible values (only for PREF_ENUM)
3515  *                  (o) r - preference value (for PREF_RANGE, PREF_DECODE_AS_RANGE)
3516  *                  (o) t - preference value (only for PREF_UAT)
3517  */
3518 static void
3519 sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
3520 {
3521         const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
3522         module_t *pref_mod;
3523         char *dot_sepa;
3524
3525         if (!tok_pref)
3526         {
3527                 struct sharkd_session_process_dumpconf_data data;
3528
3529                 data.module = NULL;
3530                 data.sepa = "";
3531
3532                 printf("{\"prefs\":{");
3533                 prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data);
3534                 printf("}}\n");
3535                 return;
3536         }
3537
3538         if ((dot_sepa = strchr(tok_pref, '.')))
3539         {
3540                 pref_t *pref = NULL;
3541
3542                 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3543                 pref_mod = prefs_find_module(tok_pref);
3544                 if (pref_mod)
3545                         pref = prefs_find_preference(pref_mod, dot_sepa + 1);
3546                 *dot_sepa = '.';
3547
3548                 if (pref)
3549                 {
3550                         struct sharkd_session_process_dumpconf_data data;
3551
3552                         data.module = pref_mod;
3553                         data.sepa = "";
3554
3555                         printf("{\"prefs\":{");
3556                         sharkd_session_process_dumpconf_cb(pref, &data);
3557                         printf("}}\n");
3558                 }
3559
3560                 return;
3561         }
3562
3563         pref_mod = prefs_find_module(tok_pref);
3564         if (pref_mod)
3565         {
3566                 struct sharkd_session_process_dumpconf_data data;
3567
3568                 data.module = pref_mod;
3569                 data.sepa = "";
3570
3571                 printf("{\"prefs\":{");
3572                 prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data);
3573                 printf("}}\n");
3574         }
3575 }
3576
3577 struct sharkd_download_rtp
3578 {
3579         struct sharkd_rtp_match rtp;
3580         GSList *packets;
3581         double start_time;
3582 };
3583
3584 static void
3585 sharkd_rtp_download_free_items(void *ptr)
3586 {
3587         rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr;
3588
3589         g_free(rtp_packet->info);
3590         g_free(rtp_packet->payload_data);
3591         g_free(rtp_packet);
3592 }
3593
3594 static void
3595 sharkd_rtp_download_decode(struct sharkd_download_rtp *req)
3596 {
3597         /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */
3598         /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */
3599
3600         static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char);
3601
3602         guint32 audio_out_rate_ = 0;
3603         struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new();
3604         struct SpeexResamplerState_ *audio_resampler_ = NULL;
3605
3606         gsize resample_buff_len = 0x1000;
3607         SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len);
3608         spx_uint32_t cur_in_rate = 0;
3609         char *write_buff = NULL;
3610         gint64 write_bytes = 0;
3611         unsigned channels = 0;
3612         unsigned sample_rate = 0;
3613
3614         int i;
3615         int base64_state1 = 0;
3616         int base64_state2 = 0;
3617
3618         GSList *l;
3619
3620         for (l = req->packets; l; l = l->next)
3621         {
3622                 rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data;
3623
3624                 SAMPLE *decode_buff = NULL;
3625                 size_t decoded_bytes;
3626
3627                 decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate);
3628                 if (decoded_bytes == 0 || sample_rate == 0)
3629                 {
3630                         /* We didn't decode anything. Clean up and prep for the next packet. */
3631                         g_free(decode_buff);
3632                         continue;
3633                 }
3634
3635                 if (audio_out_rate_ == 0)
3636                 {
3637                         guint32 tmp32;
3638                         guint16 tmp16;
3639                         char wav_hdr[44];
3640
3641                         /* First non-zero wins */
3642                         audio_out_rate_ = sample_rate;
3643
3644                         RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_);
3645
3646                         /* write WAVE header */
3647                         memset(&wav_hdr, 0, sizeof(wav_hdr));
3648                         memcpy(&wav_hdr[0], "RIFF", 4);
3649                         memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
3650                         memcpy(&wav_hdr[8], "WAVE", 4);
3651
3652                         memcpy(&wav_hdr[12], "fmt ", 4);
3653                         memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */
3654                         memcpy(&wav_hdr[20], "\x01\x00", 2);         /* PCM */
3655                         /* # channels */
3656                         tmp16 = channels;
3657                         memcpy(&wav_hdr[22], &tmp16, 2);
3658                         /* sample rate */
3659                         tmp32 = sample_rate;
3660                         memcpy(&wav_hdr[24], &tmp32, 4);
3661                         /* byte rate */
3662                         tmp32 = sample_rate * channels * sample_bytes_;
3663                         memcpy(&wav_hdr[28], &tmp32, 4);
3664                         /* block align */
3665                         tmp16 = channels * sample_bytes_;
3666                         memcpy(&wav_hdr[32], &tmp16, 2);
3667                         /* bits per sample */
3668                         tmp16 = 8 * sample_bytes_;
3669                         memcpy(&wav_hdr[34], &tmp16, 2);
3670
3671                         memcpy(&wav_hdr[36], "data", 4);
3672                         memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
3673
3674                         for (i = 0; i < (int) sizeof(wav_hdr); i++)
3675                                 json_print_base64_step(&wav_hdr[i], &base64_state1, &base64_state2);
3676                 }
3677
3678                 // Write samples to our file.
3679                 write_buff = (char *) decode_buff;
3680                 write_bytes = decoded_bytes;
3681
3682                 if (audio_out_rate_ != sample_rate)
3683                 {
3684                         spx_uint32_t in_len, out_len;
3685
3686                         /* Resample the audio to match our previous output rate. */
3687                         if (!audio_resampler_)
3688                         {
3689                                 audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL);
3690                                 speex_resampler_skip_zeros(audio_resampler_);
3691                                 RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
3692                         }
3693                         else
3694                         {
3695                                 spx_uint32_t audio_out_rate;
3696                                 speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate);
3697
3698                                 if (sample_rate != cur_in_rate)
3699                                 {
3700                                         speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate);
3701                                         RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
3702                                 }
3703                         }
3704                         in_len = (spx_uint32_t)rtp_packet->info->info_payload_len;
3705                         out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0);
3706                         if (out_len * sample_bytes_ > resample_buff_len)
3707                         {
3708                                 while ((out_len * sample_bytes_ > resample_buff_len))
3709                                         resample_buff_len *= 2;
3710                                 resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len);
3711                         }
3712
3713                         speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len);
3714                         write_buff = (char *) resample_buff;
3715                         write_bytes = out_len * sample_bytes_;
3716                 }
3717
3718                 /* Write the decoded, possibly-resampled audio */
3719                 for (i = 0; i < write_bytes; i++)
3720                         json_print_base64_step(&write_buff[i], &base64_state1, &base64_state2);
3721
3722                 g_free(decode_buff);
3723         }
3724
3725         json_print_base64_step(NULL, &base64_state1, &base64_state2);
3726
3727         g_free(resample_buff);
3728         g_hash_table_destroy(decoders_hash_);
3729 }
3730
3731 static gboolean
3732 sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
3733 {
3734         const struct _rtp_info *rtp_info = (const struct _rtp_info *) data;
3735         struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata;
3736
3737         /* do not consider RTP packets without a setup frame */
3738         if (rtp_info->info_setup_frame_num == 0)
3739                 return FALSE;
3740
3741         if (sharkd_rtp_match_check(&req_rtp->rtp, pinfo, rtp_info))
3742         {
3743                 rtp_packet_t *rtp_packet;
3744
3745                 rtp_packet = g_new0(rtp_packet_t, 1);
3746                 rtp_packet->info = (struct _rtp_info *) g_memdup(rtp_info, sizeof(struct _rtp_info));
3747
3748                 if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0)
3749                         rtp_packet->payload_data = (guint8 *) g_memdup(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len);
3750
3751                 if (!req_rtp->packets)
3752                         req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts);
3753
3754                 rtp_packet->frame_num = pinfo->num;
3755                 rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time;
3756
3757                 /* XXX, O(n) optimize */
3758                 req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet);
3759         }
3760
3761         return FALSE;
3762 }
3763
3764 /**
3765  * sharkd_session_process_download()
3766  *
3767  * Process download request
3768  *
3769  * Input:
3770  *   (m) token  - token to download
3771  *
3772  * Output object with attributes:
3773  *   (o) file - suggested name of file
3774  *   (o) mime - suggested content type
3775  *   (o) data - payload base64 encoded
3776  */
3777 static void
3778 sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
3779 {
3780         const char *tok_token      = json_find_attr(buf, tokens, count, "token");
3781
3782         if (!tok_token)
3783                 return;
3784
3785         if (!strncmp(tok_token, "eo:", 3))
3786         {
3787                 struct sharkd_export_object_list *object_list;
3788                 const export_object_entry_t *eo_entry = NULL;
3789
3790                 for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
3791                 {
3792                         size_t eo_type_len = strlen(object_list->type);
3793
3794                         if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
3795                         {
3796                                 int row;
3797
3798                                 if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1)
3799                                         break;
3800
3801                                 eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
3802                                 break;
3803                         }
3804                 }
3805
3806                 if (eo_entry)
3807                 {
3808                         const char *mime     = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
3809                         const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
3810
3811                         printf("{\"file\":");
3812                         json_puts_string(filename);
3813                         printf(",\"mime\":");
3814                         json_puts_string(mime);
3815                         printf(",\"data\":");
3816                         json_print_base64(eo_entry->payload_data, (size_t)(eo_entry->payload_len));
3817                         printf("}\n");
3818                 }
3819         }
3820         else if (!strcmp(tok_token, "ssl-secrets"))
3821         {
3822                 char *str = ssl_export_sessions();
3823
3824                 if (str)
3825                 {
3826                         const char *mime     = "text/plain";
3827                         const char *filename = "keylog.txt";
3828
3829                         printf("{\"file\":");
3830                         json_puts_string(filename);
3831                         printf(",\"mime\":");
3832                         json_puts_string(mime);
3833                         printf(",\"data\":");
3834                         json_print_base64(str, strlen(str));
3835                         printf("}\n");
3836                 }
3837                 g_free(str);
3838         }
3839         else if (!strncmp(tok_token, "rtp:", 4))
3840         {
3841                 struct sharkd_download_rtp rtp_req;
3842                 GString *tap_error;
3843
3844                 memset(&rtp_req, 0, sizeof(rtp_req));
3845                 if (!sharkd_rtp_match_init(&rtp_req.rtp, tok_token + 4))
3846                 {
3847                         fprintf(stderr, "sharkd_session_process_download() rtp tokenizing error %s\n", tok_token);
3848                         return;
3849                 }
3850
3851                 tap_error = register_tap_listener("rtp", &rtp_req, NULL, 0, NULL, sharkd_session_packet_download_tap_rtp_cb, NULL);
3852                 if (tap_error)
3853                 {
3854                         fprintf(stderr, "sharkd_session_process_download() rtp error=%s", tap_error->str);
3855                         g_string_free(tap_error, TRUE);
3856                         return;
3857                 }
3858
3859                 sharkd_retap();
3860                 remove_tap_listener(&rtp_req);
3861
3862                 if (rtp_req.packets)
3863                 {
3864                         const char *mime     = "audio/x-wav";
3865                         const char *filename = tok_token;
3866
3867                         printf("{\"file\":");
3868                         json_puts_string(filename);
3869                         printf(",\"mime\":");
3870                         json_puts_string(mime);
3871
3872                         printf(",\"data\":");
3873                         putchar('"');
3874                         sharkd_rtp_download_decode(&rtp_req);
3875                         putchar('"');
3876
3877                         printf("}\n");
3878
3879                         g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items);
3880                 }
3881         }
3882 }
3883
3884 static void
3885 sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
3886 {
3887         int i;
3888
3889         /* sanity check, and split strings */
3890         if (count < 1 || tokens[0].type != JSMN_OBJECT)
3891         {
3892                 fprintf(stderr, "sanity check(1): [0] not object\n");
3893                 return;
3894         }
3895
3896         /* don't need [0] token */
3897         tokens++;
3898         count--;
3899
3900         if (count & 1)
3901         {
3902                 fprintf(stderr, "sanity check(2): %d not even\n", count);
3903                 return;
3904         }
3905
3906         for (i = 0; i < count; i += 2)
3907         {
3908                 if (tokens[i].type != JSMN_STRING)
3909                 {
3910                         fprintf(stderr, "sanity check(3): [%d] not string\n", i);
3911                         return;
3912                 }
3913
3914                 if (tokens[i + 1].type != JSMN_STRING && tokens[i + 1].type != JSMN_PRIMITIVE)
3915                 {
3916                         fprintf(stderr, "sanity check(3a): [%d] wrong type\n", i + 1);
3917                         return;
3918                 }
3919
3920                 buf[tokens[i + 0].end] = '\0';
3921                 buf[tokens[i + 1].end] = '\0';
3922
3923                 /* unescape only value, as keys are simple strings */
3924                 if (tokens[i + 1].type == JSMN_STRING && !json_unescape_str(&buf[tokens[i + 1].start]))
3925                 {
3926                         fprintf(stderr, "sanity check(3b): [%d] cannot unescape string\n", i + 1);
3927                         return;
3928                 }
3929         }
3930
3931         {
3932                 const char *tok_req = json_find_attr(buf, tokens, count, "req");
3933
3934                 if (!tok_req)
3935                 {
3936                         fprintf(stderr, "sanity check(4): no \"req\".\n");
3937                         return;
3938                 }
3939
3940                 if (!strcmp(tok_req, "load"))
3941                         sharkd_session_process_load(buf, tokens, count);
3942                 else if (!strcmp(tok_req, "status"))
3943                         sharkd_session_process_status();
3944                 else if (!strcmp(tok_req, "analyse"))
3945                         sharkd_session_process_analyse();
3946                 else if (!strcmp(tok_req, "info"))
3947                         sharkd_session_process_info();
3948                 else if (!strcmp(tok_req, "check"))
3949                         sharkd_session_process_check(buf, tokens, count);
3950                 else if (!strcmp(tok_req, "complete"))
3951                         sharkd_session_process_complete(buf, tokens, count);
3952                 else if (!strcmp(tok_req, "frames"))
3953                         sharkd_session_process_frames(buf, tokens, count);
3954                 else if (!strcmp(tok_req, "tap"))
3955                         sharkd_session_process_tap(buf, tokens, count);
3956                 else if (!strcmp(tok_req, "follow"))
3957                         sharkd_session_process_follow(buf, tokens, count);
3958                 else if (!strcmp(tok_req, "intervals"))
3959                         sharkd_session_process_intervals(buf, tokens, count);
3960                 else if (!strcmp(tok_req, "frame"))
3961                         sharkd_session_process_frame(buf, tokens, count);
3962                 else if (!strcmp(tok_req, "setcomment"))
3963                         sharkd_session_process_setcomment(buf, tokens, count);
3964                 else if (!strcmp(tok_req, "setconf"))
3965                         sharkd_session_process_setconf(buf, tokens, count);
3966                 else if (!strcmp(tok_req, "dumpconf"))
3967                         sharkd_session_process_dumpconf(buf, tokens, count);
3968                 else if (!strcmp(tok_req, "download"))
3969                         sharkd_session_process_download(buf, tokens, count);
3970                 else if (!strcmp(tok_req, "bye"))
3971                         exit(0);
3972                 else
3973                         fprintf(stderr, "::: req = %s\n", tok_req);
3974
3975                 /* reply for every command are 0+ lines of JSON reply (outputed above), finished by empty new line */
3976                 printf("\n");
3977
3978                 /*
3979                  * We do an explicit fflush after every line, because
3980                  * we want output to be written to the socket as soon
3981                  * as the line is complete.
3982                  *
3983                  * The stream is fully-buffered by default, so it's
3984                  * only flushed when the buffer fills or the FILE *
3985                  * is closed.  On UN*X, we could set it to be line
3986                  * buffered, but the MSVC standard I/O routines don't
3987                  * support line buffering - they only support *byte*
3988                  * buffering, doing a write for every byte written,
3989                  * which is too inefficient, and full buffering,
3990                  * which is what you get if you request line buffering.
3991                  */
3992                 fflush(stdout);
3993         }
3994 }
3995
3996 int
3997 sharkd_session_main(void)
3998 {
3999         char buf[2 * 1024];
4000         jsmntok_t *tokens = NULL;
4001         int tokens_max = -1;
4002
4003         fprintf(stderr, "Hello in child.\n");
4004
4005         filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free);
4006
4007 #ifdef HAVE_MAXMINDDB
4008         /* mmdbresolve was stopped before fork(), force starting it */
4009         uat_get_table_by_name("MaxMind Database Paths")->post_update_cb();
4010 #endif
4011
4012         while (fgets(buf, sizeof(buf), stdin))
4013         {
4014                 /* every command is line seperated JSON */
4015                 int ret;
4016
4017                 ret = wsjson_parse(buf, NULL, 0);
4018                 if (ret < 0)
4019                 {
4020                         fprintf(stderr, "invalid JSON -> closing\n");
4021                         return 1;
4022                 }
4023
4024                 /* fprintf(stderr, "JSON: %d tokens\n", ret); */
4025                 ret += 1;
4026
4027                 if (tokens == NULL || tokens_max < ret)
4028                 {
4029                         tokens_max = ret;
4030                         tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max);
4031                 }
4032
4033                 memset(tokens, 0, ret * sizeof(jsmntok_t));
4034
4035                 ret = wsjson_parse(buf, tokens, ret);
4036                 if (ret < 0)
4037                 {
4038                         fprintf(stderr, "invalid JSON(2) -> closing\n");
4039                         return 2;
4040                 }
4041
4042 #if defined(HAVE_C_ARES) || defined(HAVE_MAXMINDDB)
4043                 host_name_lookup_process();
4044 #endif
4045
4046                 sharkd_session_process(buf, tokens, ret);
4047         }
4048
4049         g_hash_table_destroy(filter_table);
4050         g_free(tokens);
4051
4052         return 0;
4053 }
4054
4055 /*
4056  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
4057  *
4058  * Local variables:
4059  * c-basic-offset: 8
4060  * tab-width: 8
4061  * indent-tabs-mode: t
4062  * End:
4063  *
4064  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4065  * :indentSize=8:tabSize=8:noTabs=false:
4066  */