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