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