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