tests: add regression tests for Follow TCP Stream
[metze/wireshark/wip.git] / sharkd_session.c
1 /* sharkd_session.c
2  *
3  * Copyright (C) 2016 Jakub Zawadzki
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include <config.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18
19 #include <glib.h>
20
21 #include <wsutil/wsjson.h>
22 #include <wsutil/ws_printf.h>
23
24 #include <file.h>
25 #include <epan/epan_dissect.h>
26 #include <epan/exceptions.h>
27 #include <epan/color_filters.h>
28 #include <epan/prefs.h>
29 #include <epan/prefs-int.h>
30 #include <epan/uat-int.h>
31 #include <wiretap/wtap.h>
32
33 #include <epan/column.h>
34
35 #include <ui/ssl_key_export.h>
36
37 #include <ui/io_graph_item.h>
38 #include <epan/stats_tree_priv.h>
39 #include <epan/stat_tap_ui.h>
40 #include <epan/conversation_table.h>
41 #include <epan/sequence_analysis.h>
42 #include <epan/expert.h>
43 #include <epan/export_object.h>
44 #include <epan/follow.h>
45 #include <epan/rtd_table.h>
46 #include <epan/srt_table.h>
47
48 #include <epan/dissectors/packet-h225.h>
49 #include <epan/rtp_pt.h>
50 #include <ui/voip_calls.h>
51 #include <ui/rtp_stream.h>
52 #include <ui/tap-rtp-common.h>
53 #include <ui/tap-rtp-analysis.h>
54 #include <epan/to_str.h>
55
56 #include <epan/addr_resolv.h>
57 #include <epan/dissectors/packet-rtp.h>
58 #include <ui/rtp_media.h>
59 #ifdef HAVE_SPEEXDSP
60 # include <speex/speex_resampler.h>
61 #else
62 # include <codecs/speex/speex_resampler.h>
63 #endif /* HAVE_SPEEXDSP */
64
65 #include <epan/maxmind_db.h>
66
67 #include <wsutil/pint.h>
68 #include <wsutil/strtoi.h>
69
70 #include "globals.h"
71
72 #include "sharkd.h"
73
74 struct sharkd_filter_item
75 {
76         guint8 *filtered;
77 };
78
79 static GHashTable *filter_table = NULL;
80
81 static gboolean
82 json_unescape_str(char *input)
83 {
84         return wsjson_unescape_json_string(input, input);
85 }
86
87 static const char *
88 json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
89 {
90         int i;
91
92         for (i = 0; i < count; i += 2)
93         {
94                 const char *tok_attr  = &buf[tokens[i + 0].start];
95                 const char *tok_value = &buf[tokens[i + 1].start];
96
97                 if (!strcmp(tok_attr, attr))
98                         return tok_value;
99         }
100
101         return NULL;
102 }
103
104 static void
105 json_puts_string(const char *str)
106 {
107         int i;
108
109         if (str == NULL)
110                 str = "";
111
112         putchar('"');
113         for (i = 0; str[i]; i++)
114         {
115                 switch (str[i])
116                 {
117                         case '\\':
118                         case '"':
119                                 putchar('\\');
120                                 putchar(str[i]);
121                                 break;
122
123                         case '\n':
124                                 putchar('\\');
125                                 putchar('n');
126                                 break;
127
128                         default:
129                                 putchar(str[i]);
130                                 break;
131                 }
132         }
133
134         putchar('"');
135 }
136
137 static void
138 json_print_base64_step(const guint8 *data, int *state1, int *state2)
139 {
140         gchar buf[(1 / 3 + 1) * 4 + 4 + 1];
141         gsize wrote;
142
143         if (data)
144                 wrote = g_base64_encode_step(data, 1, FALSE, buf, state1, state2);
145         else
146                 wrote = g_base64_encode_close(FALSE, buf, state1, state2);
147
148         if (wrote > 0)
149         {
150                 buf[wrote] = '\0';
151                 printf("%s", buf);
152         }
153 }
154
155 static void
156 json_print_base64(const guint8 *data, size_t len)
157 {
158         size_t i;
159         int base64_state1 = 0;
160         int base64_state2 = 0;
161
162         putchar('"');
163
164         for (i = 0; i < len; i++)
165                 json_print_base64_step(&data[i], &base64_state1, &base64_state2);
166
167         json_print_base64_step(NULL, &base64_state1, &base64_state2);
168
169         putchar('"');
170 }
171
172 static void
173 sharkd_session_filter_free(gpointer data)
174 {
175         struct sharkd_filter_item *l = (struct sharkd_filter_item *) data;
176
177         g_free(l->filtered);
178         g_free(l);
179 }
180
181 static const guint8 *
182 sharkd_session_filter_data(const char *filter)
183 {
184         struct sharkd_filter_item *l;
185
186         l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter);
187         if (!l)
188         {
189                 guint8 *filtered = NULL;
190
191                 int ret = sharkd_filter(filter, &filtered);
192
193                 if (ret == -1)
194                         return NULL;
195
196                 l = (struct sharkd_filter_item *) g_malloc(sizeof(struct sharkd_filter_item));
197                 l->filtered = filtered;
198
199                 g_hash_table_insert(filter_table, g_strdup(filter), l);
200         }
201
202         return l->filtered;
203 }
204
205 static gboolean
206 sharkd_rtp_match_init(rtpstream_id_t *id, const char *init_str)
207 {
208         gboolean ret = FALSE;
209         char **arr;
210         guint32 tmp_addr_src, tmp_addr_dst;
211         address tmp_src_addr, tmp_dst_addr;
212
213         memset(id, 0, sizeof(*id));
214
215         arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
216         if (g_strv_length(arr) != 5)
217                 goto fail;
218
219         /* TODO, for now only IPv4 */
220         if (!get_host_ipaddr(arr[0], &tmp_addr_src))
221                 goto fail;
222
223         if (!ws_strtou16(arr[1], NULL, &id->src_port))
224                 goto fail;
225
226         if (!get_host_ipaddr(arr[2], &tmp_addr_dst))
227                 goto fail;
228
229         if (!ws_strtou16(arr[3], NULL, &id->dst_port))
230                 goto fail;
231
232         if (!ws_hexstrtou32(arr[4], NULL, &id->ssrc))
233                 goto fail;
234
235         set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src);
236         copy_address(&id->src_addr, &tmp_src_addr);
237         set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst);
238         copy_address(&id->dst_addr, &tmp_dst_addr);
239
240         ret = TRUE;
241
242 fail:
243         g_strfreev(arr);
244         return ret;
245 }
246
247 static gboolean
248 sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata)
249 {
250         stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value;
251         int *pi = (int *) userdata;
252
253         printf("%s{", (*pi) ? "," : "");
254                 printf("\"name\":\"%s\"", stat_tap->title);
255                 printf(",\"tap\":\"nstat:%s\"", (const char *) key);
256         printf("}");
257
258         *pi = *pi + 1;
259         return FALSE;
260 }
261
262 static gboolean
263 sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
264 {
265         struct register_ct *table = (struct register_ct *) value;
266         int *pi = (int *) userdata;
267
268         const char *label = (const char *) key;
269
270         if (get_conversation_packet_func(table))
271         {
272                 printf("%s{", (*pi) ? "," : "");
273                         printf("\"name\":\"Conversation List/%s\"", label);
274                         printf(",\"tap\":\"conv:%s\"", label);
275                 printf("}");
276
277                 *pi = *pi + 1;
278         }
279
280         if (get_hostlist_packet_func(table))
281         {
282                 printf("%s{", (*pi) ? "," : "");
283                         printf("\"name\":\"Endpoint/%s\"", label);
284                         printf(",\"tap\":\"endpt:%s\"", label);
285                 printf("}");
286
287                 *pi = *pi + 1;
288         }
289         return FALSE;
290 }
291
292 static gboolean
293 sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata)
294 {
295         register_analysis_t *analysis = (register_analysis_t *) value;
296         int *pi = (int *) userdata;
297
298         printf("%s{", (*pi) ? "," : "");
299                 printf("\"name\":\"%s\"", sequence_analysis_get_ui_name(analysis));
300                 printf(",\"tap\":\"seqa:%s\"", (const char *) key);
301         printf("}");
302
303         *pi = *pi + 1;
304         return FALSE;
305 }
306
307 static gboolean
308 sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
309 {
310         register_eo_t *eo = (register_eo_t *) value;
311         int *pi = (int *) user_data;
312
313         const int proto_id = get_eo_proto_id(eo);
314         const char *filter = proto_get_protocol_filter_name(proto_id);
315         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
316
317         printf("%s{", (*pi) ? "," : "");
318                 printf("\"name\":\"Export Object/%s\"", label);
319                 printf(",\"tap\":\"eo:%s\"", filter);
320         printf("}");
321
322         *pi = *pi + 1;
323         return FALSE;
324 }
325
326 static gboolean
327 sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data)
328 {
329         register_srt_t *srt = (register_srt_t *) value;
330         int *pi = (int *) user_data;
331
332         const int proto_id = get_srt_proto_id(srt);
333         const char *filter = proto_get_protocol_filter_name(proto_id);
334         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
335
336         printf("%s{", (*pi) ? "," : "");
337                 printf("\"name\":\"Service Response Time/%s\"", label);
338                 printf(",\"tap\":\"srt:%s\"", filter);
339         printf("}");
340
341         *pi = *pi + 1;
342         return FALSE;
343 }
344
345 static gboolean
346 sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data)
347 {
348         register_rtd_t *rtd = (register_rtd_t *) value;
349         int *pi = (int *) user_data;
350
351         const int proto_id = get_rtd_proto_id(rtd);
352         const char *filter = proto_get_protocol_filter_name(proto_id);
353         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
354
355         printf("%s{", (*pi) ? "," : "");
356                 printf("\"name\":\"Response Time Delay/%s\"", label);
357                 printf(",\"tap\":\"rtd:%s\"", filter);
358         printf("}");
359
360         *pi = *pi + 1;
361         return FALSE;
362 }
363
364 static gboolean
365 sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
366 {
367         register_follow_t *follower = (register_follow_t *) value;
368         int *pi = (int *) user_data;
369
370         const int proto_id = get_follow_proto_id(follower);
371         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
372         const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
373
374         printf("%s{", (*pi) ? "," : "");
375                 printf("\"name\":\"Follow/%s\"", label);
376                 printf(",\"tap\":\"follow:%s\"", filter);
377         printf("}");
378
379         *pi = *pi + 1;
380         return FALSE;
381 }
382
383 /**
384  * sharkd_session_process_info()
385  *
386  * Process info request
387  *
388  * Output object with attributes:
389  *   (m) columns - available column formats, array of object with attributes:
390  *                  'name'   - column name
391  *                  'format' - column format-name
392  *
393  *   (m) stats   - available statistics, array of object with attributes:
394  *                  'name' - statistic name
395  *                  'tap'  - sharkd tap-name for statistic
396  *
397  *   (m) convs   - available conversation list, array of object with attributes:
398  *                  'name' - conversation name
399  *                  'tap'  - sharkd tap-name for conversation
400  *
401  *   (m) eo      - available export object list, array of object with attributes:
402  *                  'name' - export object name
403  *                  'tap'  - sharkd tap-name for eo
404  *
405  *   (m) srt     - available service response time list, array of object with attributes:
406  *                  'name' - service response time name
407  *                  'tap'  - sharkd tap-name for srt
408  *
409  *   (m) rtd     - available response time delay list, array of object with attributes:
410  *                  'name' - response time delay name
411  *                  'tap'  - sharkd tap-name for rtd
412  *
413  *   (m) seqa    - available sequence analysis (flow) list, array of object with attributes:
414  *                  'name' - sequence analysis name
415  *                  'tap'  - sharkd tap-name
416  *
417  *   (m) taps - available taps, array of object with attributes:
418  *                  'name' - tap name
419  *                  'tap'  - sharkd tap-name
420  *
421  *   (m) follow - available followers, array of object with attributes:
422  *                  'name' - tap name
423  *                  'tap'  - sharkd tap-name
424  *
425  *   (m) ftypes   - conversation table for FT_ number to string
426  */
427 static void
428 sharkd_session_process_info(void)
429 {
430         int i;
431
432         printf("{\"columns\":[");
433         for (i = 0; i < NUM_COL_FMTS; i++)
434         {
435                 const char *col_format = col_format_to_string(i);
436                 const char *col_descr  = col_format_desc(i);
437
438                 printf("%s{", (i) ? "," : "");
439                         printf("\"name\":\"%s\"", col_descr);
440                         printf(",\"format\":\"%s\"", col_format);
441                 printf("}");
442         }
443         printf("]");
444
445         printf(",\"stats\":[");
446         {
447                 GList *cfg_list = stats_tree_get_cfg_list();
448                 GList *l;
449                 const char *sepa = "";
450
451                 for (l = cfg_list; l; l = l->next)
452                 {
453                         stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
454
455                         printf("%s{", sepa);
456                                 printf("\"name\":\"%s\"", cfg->name);
457                                 printf(",\"tap\":\"stat:%s\"", cfg->abbr);
458                         printf("}");
459                         sepa = ",";
460                 }
461
462                 g_list_free(cfg_list);
463         }
464         printf("]");
465
466         printf(",\"ftypes\":[");
467         for (i = 0; i < FT_NUM_TYPES; i++)
468         {
469                 if (i)
470                         printf(",");
471                 json_puts_string(ftype_name((ftenum_t) i));
472         }
473         printf("]");
474
475         printf(",\"version\":");
476         json_puts_string(sharkd_version());
477
478         printf(",\"nstat\":[");
479         i = 0;
480         stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i);
481         printf("]");
482
483         printf(",\"convs\":[");
484         i = 0;
485         conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
486         printf("]");
487
488         printf(",\"seqa\":[");
489         i = 0;
490         sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i);
491         printf("]");
492
493         printf(",\"taps\":[");
494         {
495                 printf("{\"name\":\"%s\",\"tap\":\"%s\"}", "RTP streams", "rtp-streams");
496                 printf(",{\"name\":\"%s\",\"tap\":\"%s\"}", "Expert Information", "expert");
497         }
498         printf("]");
499
500         printf(",\"eo\":[");
501         i = 0;
502         eo_iterate_tables(sharkd_export_object_visit_cb, &i);
503         printf("]");
504
505         printf(",\"srt\":[");
506         i = 0;
507         srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
508         printf("]");
509
510         printf(",\"rtd\":[");
511         i = 0;
512         rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
513         printf("]");
514
515         printf(",\"follow\":[");
516         i = 0;
517         follow_iterate_followers(sharkd_follower_visit_cb, &i);
518         printf("]");
519
520         printf("}\n");
521 }
522
523 /**
524  * sharkd_session_process_load()
525  *
526  * Process load request
527  *
528  * Input:
529  *   (m) file - file to be loaded
530  *
531  * Output object with attributes:
532  *   (m) err - error code
533  */
534 static void
535 sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
536 {
537         const char *tok_file = json_find_attr(buf, tokens, count, "file");
538         int err = 0;
539
540         fprintf(stderr, "load: filename=%s\n", tok_file);
541
542         if (!tok_file)
543                 return;
544
545         if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK)
546         {
547                 printf("{\"err\":%d}\n", err);
548                 return;
549         }
550
551         TRY
552         {
553                 err = sharkd_load_cap_file();
554         }
555         CATCH(OutOfMemoryError)
556         {
557                 fprintf(stderr, "load: OutOfMemoryError\n");
558                 err = ENOMEM;
559         }
560         ENDTRY;
561
562         printf("{\"err\":%d}\n", err);
563 }
564
565 /**
566  * sharkd_session_process_status()
567  *
568  * Process status request
569  *
570  * Output object with attributes:
571  *   (m) frames   - count of currently loaded frames
572  *   (m) duration - time difference between time of first frame, and last loaded frame
573  *   (o) filename - capture filename
574  *   (o) filesize - capture filesize
575  */
576 static void
577 sharkd_session_process_status(void)
578 {
579         printf("{\"frames\":%u", cfile.count);
580
581         printf(",\"duration\":%.9f", nstime_to_sec(&cfile.elapsed_time));
582
583         if (cfile.filename)
584         {
585                 char *name = g_path_get_basename(cfile.filename);
586
587                 printf(",\"filename\":");
588                 json_puts_string(name);
589                 g_free(name);
590         }
591
592         if (cfile.provider.wth)
593         {
594                 gint64 file_size = wtap_file_size(cfile.provider.wth, NULL);
595
596                 if (file_size > 0)
597                         printf(",\"filesize\":%" G_GINT64_FORMAT, file_size);
598         }
599
600         printf("}\n");
601 }
602
603 struct sharkd_analyse_data
604 {
605         GHashTable *protocols_set;
606         nstime_t *first_time;
607         nstime_t *last_time;
608 };
609
610 static void
611 sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
612 {
613         struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
614         packet_info *pi = &edt->pi;
615         frame_data *fdata = pi->fd;
616
617         (void) tree;
618         (void) cinfo;
619         (void) data_src;
620
621         if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
622                 analyser->first_time = &fdata->abs_ts;
623
624         if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
625                 analyser->last_time = &fdata->abs_ts;
626
627         if (pi->layers)
628         {
629                 wmem_list_frame_t *frame;
630
631                 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
632                 {
633                         int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame));
634
635                         if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL))
636                         {
637                                 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id));
638
639                                 if (g_hash_table_size(analyser->protocols_set) != 1)
640                                         printf(",");
641                                 json_puts_string(proto_get_protocol_filter_name(proto_id));
642                         }
643                 }
644         }
645
646 }
647
648 /**
649  * sharkd_session_process_status()
650  *
651  * Process analyse request
652  *
653  * Output object with attributes:
654  *   (m) frames  - count of currently loaded frames
655  *   (m) protocols - protocol list
656  *   (m) first     - earliest frame time
657  *   (m) last      - latest frame time
658  */
659 static void
660 sharkd_session_process_analyse(void)
661 {
662         unsigned int framenum;
663         struct sharkd_analyse_data analyser;
664
665         analyser.first_time = NULL;
666         analyser.last_time  = NULL;
667         analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */);
668
669         printf("{\"frames\":%u", cfile.count);
670
671         printf(",\"protocols\":[");
672         for (framenum = 1; framenum <= cfile.count; framenum++)
673                 sharkd_dissect_request(framenum, (framenum != 1) ? 1 : 0, framenum - 1, &sharkd_session_process_analyse_cb, 0, 0, 0, &analyser);
674         printf("]");
675
676         if (analyser.first_time)
677                 printf(",\"first\":%.9f", nstime_to_sec(analyser.first_time));
678
679         if (analyser.last_time)
680                 printf(",\"last\":%.9f", nstime_to_sec(analyser.last_time));
681
682         printf("}\n");
683
684         g_hash_table_destroy(analyser.protocols_set);
685 }
686
687 static column_info *
688 sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count)
689 {
690         const char *columns_custom[32];
691         guint16 columns_fmt[32];
692         gint16 columns_occur[32];
693
694         int i, cols;
695
696         for (i = 0; i < 32; i++)
697         {
698                 const char *tok_column;
699                 char tok_column_name[64];
700                 char *custom_sepa;
701
702                 ws_snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i);
703                 tok_column = json_find_attr(buf, tokens, count, tok_column_name);
704                 if (tok_column == NULL)
705                         break;
706
707                 columns_custom[i] = NULL;
708                 columns_occur[i] = 0;
709
710                 if ((custom_sepa = strchr(tok_column, ':')))
711                 {
712                         *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */
713
714                         columns_fmt[i] = COL_CUSTOM;
715                         columns_custom[i] = tok_column;
716
717                         if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i]))
718                                 return NULL;
719                 }
720                 else
721                 {
722                         if (!ws_strtou16(tok_column, NULL, &columns_fmt[i]))
723                                 return NULL;
724
725                         if (columns_fmt[i] >= NUM_COL_FMTS)
726                                 return NULL;
727
728                         /* if custom, that it shouldn't be just custom number -> error */
729                         if (columns_fmt[i] == COL_CUSTOM)
730                                 return NULL;
731                 }
732         }
733
734         cols = i;
735
736         col_setup(cinfo, cols);
737
738         for (i = 0; i < cols; i++)
739         {
740                 col_item_t *col_item = &cinfo->columns[i];
741
742                 col_item->col_fmt = columns_fmt[i];
743                 col_item->col_title = NULL; /* no need for title */
744
745                 if (col_item->col_fmt == COL_CUSTOM)
746                 {
747                         col_item->col_custom_fields = g_strdup(columns_custom[i]);
748                         col_item->col_custom_occurrence = columns_occur[i];
749                 }
750
751                 col_item->col_fence = 0;
752         }
753
754         col_finalize(cinfo);
755
756         return cinfo;
757 }
758
759 /**
760  * sharkd_session_process_frames()
761  *
762  * Process frames request
763  *
764  * Input:
765  *   (o) column0...columnXX - requested columns either number in range [0..NUM_COL_FMTS), or custom (syntax <dfilter>:<occurence>).
766  *                            If column0 is not specified default column set will be used.
767  *   (o) filter - filter to be used
768  *   (o) skip=N   - skip N frames
769  *   (o) limit=N  - show only N frames
770  *   (o) refs  - list (comma separated) with sorted time reference frame numbers.
771  *
772  * Output array of frames with attributes:
773  *   (m) c   - array of column data
774  *   (m) num - frame number
775  *   (o) i   - if frame is ignored
776  *   (o) m   - if frame is marked
777  *   (o) ct  - if frame is commented
778  *   (o) bg  - color filter - background color in hex
779  *   (o) fg  - color filter - foreground color in hex
780  */
781 static void
782 sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
783 {
784         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
785         const char *tok_column = json_find_attr(buf, tokens, count, "column0");
786         const char *tok_skip   = json_find_attr(buf, tokens, count, "skip");
787         const char *tok_limit  = json_find_attr(buf, tokens, count, "limit");
788         const char *tok_refs   = json_find_attr(buf, tokens, count, "refs");
789
790         const guint8 *filter_data = NULL;
791
792         const char *frame_sepa = "";
793         int col;
794
795         guint32 framenum, prev_dis_num = 0;
796         guint32 current_ref_frame = 0, next_ref_frame = G_MAXUINT32;
797         guint32 skip;
798         guint32 limit;
799
800         column_info *cinfo = &cfile.cinfo;
801         column_info user_cinfo;
802
803         if (tok_column)
804         {
805                 memset(&user_cinfo, 0, sizeof(user_cinfo));
806                 cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count);
807                 if (!cinfo)
808                         return;
809         }
810
811         if (tok_filter)
812         {
813                 filter_data = sharkd_session_filter_data(tok_filter);
814                 if (!filter_data)
815                         return;
816         }
817
818         skip = 0;
819         if (tok_skip)
820         {
821                 if (!ws_strtou32(tok_skip, NULL, &skip))
822                         return;
823         }
824
825         limit = 0;
826         if (tok_limit)
827         {
828                 if (!ws_strtou32(tok_limit, NULL, &limit))
829                         return;
830         }
831
832         if (tok_refs)
833         {
834                 if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame))
835                         return;
836         }
837
838         printf("[");
839         for (framenum = 1; framenum <= cfile.count; framenum++)
840         {
841                 frame_data *fdata;
842                 guint32 ref_frame = (framenum != 1) ? 1 : 0;
843
844                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
845                         continue;
846
847                 if (skip)
848                 {
849                         skip--;
850                         prev_dis_num = framenum;
851                         continue;
852                 }
853
854                 if (tok_refs)
855                 {
856                         if (framenum >= next_ref_frame)
857                         {
858                                 current_ref_frame = next_ref_frame;
859
860                                 if (*tok_refs != ',')
861                                         next_ref_frame = G_MAXUINT32;
862
863                                 while (*tok_refs == ',' && framenum >= next_ref_frame)
864                                 {
865                                         current_ref_frame = next_ref_frame;
866
867                                         if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame))
868                                         {
869                                                 fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs);
870                                                 break;
871                                         }
872                                 }
873                         }
874
875                         if (current_ref_frame)
876                                 ref_frame = current_ref_frame;
877                 }
878
879                 fdata = sharkd_get_frame(framenum);
880                 sharkd_dissect_columns(fdata, ref_frame, prev_dis_num, cinfo, (fdata->color_filter == NULL));
881
882                 printf("%s{\"c\":[", frame_sepa);
883                 for (col = 0; col < cinfo->num_cols; ++col)
884                 {
885                         const col_item_t *col_item = &cinfo->columns[col];
886
887                         if (col)
888                                 printf(",");
889
890                         json_puts_string(col_item->col_data);
891                 }
892                 printf("],\"num\":%u", framenum);
893
894                 if (fdata->flags.has_user_comment || fdata->flags.has_phdr_comment)
895                 {
896                         if (!fdata->flags.has_user_comment || sharkd_get_user_comment(fdata) != NULL)
897                                 printf(",\"ct\":true");
898                 }
899
900                 if (fdata->flags.ignored)
901                         printf(",\"i\":true");
902
903                 if (fdata->flags.marked)
904                         printf(",\"m\":true");
905
906                 if (fdata->color_filter)
907                 {
908                         printf(",\"bg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->bg_color));
909                         printf(",\"fg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->fg_color));
910                 }
911
912                 printf("}");
913                 frame_sepa = ",";
914                 prev_dis_num = framenum;
915
916                 if (limit && --limit == 0)
917                         break;
918         }
919         printf("]\n");
920
921         if (cinfo != &cfile.cinfo)
922                 col_cleanup(cinfo);
923 }
924
925 static void
926 sharkd_session_process_tap_stats_node_cb(const stat_node *n)
927 {
928         stat_node *node;
929         const char *sepa = "";
930
931         printf("[");
932         for (node = n->children; node; node = node->next)
933         {
934                 /* code based on stats_tree_get_values_from_node() */
935                 printf("%s{\"name\":\"%s\"", sepa, node->name);
936                 printf(",\"count\":%d", node->counter);
937                 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng))
938                 {
939                         printf(",\"avg\":%.2f", ((float)node->total) / node->counter);
940                         printf(",\"min\":%d", node->minvalue);
941                         printf(",\"max\":%d", node->maxvalue);
942                 }
943
944                 if (node->st->elapsed)
945                         printf(",\"rate\":%.4f",((float)node->counter) / node->st->elapsed);
946
947                 if (node->parent && node->parent->counter)
948                         printf(",\"perc\":%.2f", (node->counter * 100.0) / node->parent->counter);
949                 else if (node->parent == &(node->st->root))
950                         printf(",\"perc\":100");
951
952                 if (prefs.st_enable_burstinfo && node->max_burst)
953                 {
954                         if (prefs.st_burst_showcount)
955                                 printf(",\"burstcount\":%d", node->max_burst);
956                         else
957                                 printf(",\"burstrate\":%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
958
959                         printf(",\"bursttime\":%.3f", ((double)node->burst_time / 1000.0));
960                 }
961
962                 if (node->children)
963                 {
964                         printf(",\"sub\":");
965                         sharkd_session_process_tap_stats_node_cb(node);
966                 }
967                 printf("}");
968                 sepa = ",";
969         }
970         printf("]");
971 }
972
973 /**
974  * sharkd_session_process_tap_stats_cb()
975  *
976  * Output stats tap:
977  *
978  *   (m) tap        - tap name
979  *   (m) type:stats - tap output type
980  *   (m) name       - stat name
981  *   (m) stats      - array of object with attributes:
982  *                  (m) name       - stat item name
983  *                  (m) count      - stat item counter
984  *                  (o) avg        - stat item averange value
985  *                  (o) min        - stat item min value
986  *                  (o) max        - stat item max value
987  *                  (o) rate       - stat item rate value (ms)
988  *                  (o) perc       - stat item percentage
989  *                  (o) burstrate  - stat item burst rate
990  *                  (o) burstcount - stat item burst count
991  *                  (o) burstttme  - stat item burst start
992  *                  (o) sub        - array of object with attributes like in stats node.
993  */
994 static void
995 sharkd_session_process_tap_stats_cb(void *psp)
996 {
997         stats_tree *st = (stats_tree *) psp;
998
999         printf("{\"tap\":\"stats:%s\",\"type\":\"stats\"", st->cfg->abbr);
1000
1001         printf(",\"name\":\"%s\",\"stats\":", st->cfg->name);
1002         sharkd_session_process_tap_stats_node_cb(&st->root);
1003         printf("},");
1004 }
1005
1006 static void
1007 sharkd_session_free_tap_stats_cb(void *psp)
1008 {
1009         stats_tree *st = (stats_tree *) psp;
1010
1011         stats_tree_free(st);
1012 }
1013
1014 struct sharkd_expert_tap
1015 {
1016         GSList *details;
1017         GStringChunk *text;
1018 };
1019
1020 /**
1021  * sharkd_session_process_tap_expert_cb()
1022  *
1023  * Output expert tap:
1024  *
1025  *   (m) tap         - tap name
1026  *   (m) type:expert - tap output type
1027  *   (m) details     - array of object with attributes:
1028  *                  (m) f - frame number, which generated expert information
1029  *                  (o) s - severity
1030  *                  (o) g - group
1031  *                  (m) m - expert message
1032  *                  (o) p - protocol
1033  */
1034 static void
1035 sharkd_session_process_tap_expert_cb(void *tapdata)
1036 {
1037         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1038         GSList *list;
1039         const char *sepa = "";
1040
1041         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "expert", "expert");
1042
1043         printf(",\"details\":[");
1044         for (list = etd->details; list; list = list->next)
1045         {
1046                 expert_info_t *ei = (expert_info_t *) list->data;
1047                 const char *tmp;
1048
1049                 printf("%s{", sepa);
1050
1051                 printf("\"f\":%u,", ei->packet_num);
1052
1053                 tmp = try_val_to_str(ei->severity, expert_severity_vals);
1054                 if (tmp)
1055                         printf("\"s\":\"%s\",", tmp);
1056
1057                 tmp = try_val_to_str(ei->group, expert_group_vals);
1058                 if (tmp)
1059                         printf("\"g\":\"%s\",", tmp);
1060
1061                 printf("\"m\":");
1062                 json_puts_string(ei->summary);
1063                 printf(",");
1064
1065                 if (ei->protocol)
1066                 {
1067                         printf("\"p\":");
1068                         json_puts_string(ei->protocol);
1069                 }
1070
1071                 printf("}");
1072                 sepa = ",";
1073         }
1074         printf("]");
1075
1076         printf("},");
1077 }
1078
1079 static gboolean
1080 sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
1081 {
1082         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1083         const expert_info_t *ei       = (const expert_info_t *) pointer;
1084         expert_info_t *ei_copy;
1085
1086         if (ei == NULL)
1087                 return FALSE;
1088
1089         ei_copy = g_new(expert_info_t, 1);
1090         /* Note: this is a shallow copy */
1091         *ei_copy = *ei;
1092
1093         /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */
1094         ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol);
1095         ei_copy->summary  = g_string_chunk_insert_const(etd->text, ei_copy->summary);
1096
1097         etd->details = g_slist_prepend(etd->details, ei_copy);
1098
1099         return TRUE;
1100 }
1101
1102 static void
1103 sharkd_session_free_tap_expert_cb(void *tapdata)
1104 {
1105         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1106
1107         g_slist_free_full(etd->details, g_free);
1108         g_string_chunk_free(etd->text);
1109         g_free(etd);
1110 }
1111
1112 /**
1113  * sharkd_session_process_tap_flow_cb()
1114  *
1115  * Output flow tap:
1116  *   (m) tap         - tap name
1117  *   (m) type:flow   - tap output type
1118  *   (m) nodes       - array of strings with node address
1119  *   (m) flows       - array of object with attributes:
1120  *                  (m) t  - frame time string
1121  *                  (m) n  - array of two numbers with source node index and destination node index
1122  *                  (m) pn - array of two numbers with source and destination port
1123  *                  (o) c  - comment
1124  */
1125 static void
1126 sharkd_session_process_tap_flow_cb(void *tapdata)
1127 {
1128         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1129         GList *flow_list;
1130         guint i;
1131
1132         const char *sepa = "";
1133
1134         sequence_analysis_get_nodes(graph_analysis);
1135
1136         printf("{\"tap\":\"seqa:%s\",\"type\":\"%s\"", graph_analysis->name, "flow");
1137
1138         printf(",\"nodes\":[");
1139         for (i = 0; i < graph_analysis->num_nodes; i++)
1140         {
1141                 char *addr_str;
1142
1143                 if (i)
1144                         printf(",");
1145
1146                 addr_str = address_to_display(NULL, &(graph_analysis->nodes[i]));
1147                 json_puts_string(addr_str);
1148                 wmem_free(NULL, addr_str);
1149         }
1150         printf("]");
1151
1152         printf(",\"flows\":[");
1153
1154         flow_list = g_queue_peek_nth_link(graph_analysis->items, 0);
1155         while (flow_list)
1156         {
1157                 seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data;
1158
1159                 flow_list = g_list_next(flow_list);
1160
1161                 if (!sai->display)
1162                         continue;
1163
1164                 printf("%s{", sepa);
1165
1166                 printf("\"t\":\"%s\"", sai->time_str);
1167                 printf(",\"n\":[%u,%u]", sai->src_node, sai->dst_node);
1168                 printf(",\"pn\":[%u,%u]", sai->port_src, sai->port_dst);
1169
1170                 if (sai->comment)
1171                 {
1172                         printf(",\"c\":");
1173                         json_puts_string(sai->comment);
1174                 }
1175
1176                 printf("}");
1177                 sepa = ",";
1178         }
1179
1180         printf("]");
1181
1182         printf("},");
1183 }
1184
1185 static void
1186 sharkd_session_free_tap_flow_cb(void *tapdata)
1187 {
1188         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1189
1190         sequence_analysis_info_free(graph_analysis);
1191 }
1192
1193 struct sharkd_conv_tap_data
1194 {
1195         const char *type;
1196         conv_hash_t hash;
1197         gboolean resolve_name;
1198         gboolean resolve_port;
1199 };
1200
1201 static gboolean
1202 sharkd_session_geoip_addr(address *addr, const char *suffix)
1203 {
1204         const mmdb_lookup_t *lookup = NULL;
1205         gboolean with_geoip = FALSE;
1206
1207         if (addr->type == AT_IPv4)
1208         {
1209                 guint32 ip;
1210
1211                 memcpy(&ip, addr->data, 4);
1212                 lookup = maxmind_db_lookup_ipv4(ip);
1213         }
1214         else if (addr->type == AT_IPv6)
1215         {
1216                 const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data;
1217
1218                 lookup = maxmind_db_lookup_ipv6(ip6);
1219         }
1220
1221         if (!lookup || !lookup->found)
1222                 return FALSE;
1223
1224         if (lookup->country)
1225         {
1226                 printf(",\"geoip_country%s\":", suffix);
1227                 json_puts_string(lookup->country);
1228                 with_geoip = TRUE;
1229         }
1230
1231         if (lookup->country_iso)
1232         {
1233                 printf(",\"geoip_country_iso%s\":", suffix);
1234                 json_puts_string(lookup->country_iso);
1235                 with_geoip = TRUE;
1236         }
1237
1238         if (lookup->city)
1239         {
1240                 printf(",\"geoip_city%s\":", suffix);
1241                 json_puts_string(lookup->city);
1242                 with_geoip = TRUE;
1243         }
1244
1245         if (lookup->as_org)
1246         {
1247                 printf(",\"geoip_as_org%s\":", suffix);
1248                 json_puts_string(lookup->as_org);
1249                 with_geoip = TRUE;
1250         }
1251
1252         if (lookup->as_number > 0)
1253         {
1254                 printf(",\"geoip_as%s\":%u", suffix, lookup->as_number);
1255                 with_geoip = TRUE;
1256         }
1257
1258         if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0)
1259         {
1260                 printf(",\"geoip_lat%s\":%f", suffix, lookup->latitude);
1261                 with_geoip = TRUE;
1262         }
1263
1264         if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0)
1265         {
1266                 printf(",\"geoip_lon%s\":%f", suffix, lookup->longitude);
1267                 with_geoip = TRUE;
1268         }
1269
1270         return with_geoip;
1271 }
1272
1273 struct sharkd_analyse_rtp_items
1274 {
1275         guint32 frame_num;
1276         guint32 sequence_num;
1277
1278         double delta;
1279         double jitter;
1280         double skew;
1281         double bandwidth;
1282         gboolean marker;
1283
1284         double arrive_offset;
1285
1286         /* from tap_rtp_stat_t */
1287         guint32 flags;
1288         guint16 pt;
1289 };
1290
1291 struct sharkd_analyse_rtp
1292 {
1293         const char *tap_name;
1294         rtpstream_id_t id;
1295
1296         GSList *packets;
1297         double start_time;
1298         tap_rtp_stat_t statinfo;
1299 };
1300
1301 static void
1302 sharkd_session_process_tap_rtp_free_cb(void *tapdata)
1303 {
1304         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1305
1306         g_slist_free_full(rtp_req->packets, g_free);
1307         g_free(rtp_req);
1308 }
1309
1310 static gboolean
1311 sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer)
1312 {
1313         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1314         const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer;
1315
1316         if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info))
1317         {
1318                 tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
1319                 struct sharkd_analyse_rtp_items *item;
1320
1321                 rtppacket_analyse(statinfo, pinfo, rtp_info);
1322
1323                 item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
1324
1325                 if (!rtp_req->packets)
1326                         rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
1327
1328                 item->frame_num    = pinfo->num;
1329                 item->sequence_num = rtp_info->info_seq_num;
1330                 item->delta        = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta;
1331                 item->jitter       = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter;
1332                 item->skew         = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew;
1333                 item->bandwidth    = statinfo->bandwidth;
1334                 item->marker       = rtp_info->info_marker_set ? TRUE : FALSE;
1335                 item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
1336
1337                 item->flags = statinfo->flags;
1338                 item->pt    = statinfo->pt;
1339
1340                 /* XXX, O(n) optimize */
1341                 rtp_req->packets = g_slist_append(rtp_req->packets, item);
1342         }
1343
1344         return TRUE;
1345 }
1346
1347 /**
1348  * sharkd_session_process_tap_rtp_analyse_cb()
1349  *
1350  * Output rtp analyse tap:
1351  *   (m) tap   - tap name
1352  *   (m) type  - tap output type
1353  *   (m) ssrc         - RTP SSRC
1354  *   (m) max_delta    - Max delta (ms)
1355  *   (m) max_delta_nr - Max delta packet #
1356  *   (m) max_jitter   - Max jitter (ms)
1357  *   (m) mean_jitter  - Mean jitter (ms)
1358  *   (m) max_skew     - Max skew (ms)
1359  *   (m) total_nr     - Total number of RTP packets
1360  *   (m) seq_err      - Number of sequence errors
1361  *   (m) duration     - Duration (ms)
1362  *   (m) items      - array of object with attributes:
1363  *                  (m) f    - frame number
1364  *                  (m) o    - arrive offset
1365  *                  (m) sn   - sequence number
1366  *                  (m) d    - delta
1367  *                  (m) j    - jitter
1368  *                  (m) sk   - skew
1369  *                  (m) bw   - bandwidth
1370  *                  (o) s    - status string
1371  *                  (o) t    - status type
1372  *                  (o) mark - rtp mark
1373  */
1374 static void
1375 sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
1376 {
1377         const int RTP_TYPE_CN       = 1;
1378         const int RTP_TYPE_ERROR    = 2;
1379         const int RTP_TYPE_WARN     = 3;
1380         const int RTP_TYPE_PT_EVENT = 4;
1381
1382         const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1383         const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
1384
1385         const char *sepa = "";
1386         GSList *l;
1387
1388         printf("{\"tap\":\"%s\",\"type\":\"rtp-analyse\"", rtp_req->tap_name);
1389
1390         printf(",\"ssrc\":%u", rtp_req->id.ssrc);
1391
1392         printf(",\"max_delta\":%f", statinfo->max_delta);
1393         printf(",\"max_delta_nr\":%u", statinfo->max_nr);
1394         printf(",\"max_jitter\":%f", statinfo->max_jitter);
1395         printf(",\"mean_jitter\":%f", statinfo->mean_jitter);
1396         printf(",\"max_skew\":%f", statinfo->max_skew);
1397         printf(",\"total_nr\":%u", statinfo->total_nr);
1398         printf(",\"seq_err\":%u", statinfo->sequence);
1399         printf(",\"duration\":%f", statinfo->time - statinfo->start_time);
1400
1401         printf(",\"items\":[");
1402         for (l = rtp_req->packets; l; l = l->next)
1403         {
1404                 struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
1405
1406                 printf("%s{", sepa);
1407
1408                 printf("\"f\":%u", item->frame_num);
1409                 printf(",\"o\":%.9f", item->arrive_offset);
1410                 printf(",\"sn\":%u", item->sequence_num);
1411                 printf(",\"d\":%.2f", item->delta);
1412                 printf(",\"j\":%.2f", item->jitter);
1413                 printf(",\"sk\":%.2f", item->skew);
1414                 printf(",\"bw\":%.2f", item->bandwidth);
1415
1416                 if (item->pt == PT_CN)
1417                         printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=13, RFC 3389)", RTP_TYPE_CN);
1418                 else if (item->pt == PT_CN_OLD)
1419                         printf(",\"s\":\"%s\",\"t\":%d", "Comfort noise (PT=19, reserved)", RTP_TYPE_CN);
1420                 else if (item->flags & STAT_FLAG_WRONG_SEQ)
1421                         printf(",\"s\":\"%s\",\"t\":%d", "Wrong sequence number", RTP_TYPE_ERROR);
1422                 else if (item->flags & STAT_FLAG_DUP_PKT)
1423                         printf(",\"s\":\"%s\",\"t\":%d", "Suspected duplicate (MAC address) only delta time calculated", RTP_TYPE_WARN);
1424                 else if (item->flags & STAT_FLAG_REG_PT_CHANGE)
1425                         printf(",\"s\":\"Payload changed to PT=%u%s\",\"t\":%d",
1426                                 item->pt,
1427                                 (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : "",
1428                                 RTP_TYPE_WARN);
1429                 else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP)
1430                         printf(",\"s\":\"%s\",\"t\":%d", "Incorrect timestamp", RTP_TYPE_WARN);
1431                 else if ((item->flags & STAT_FLAG_PT_CHANGE)
1432                         &&  !(item->flags & STAT_FLAG_FIRST)
1433                         &&  !(item->flags & STAT_FLAG_PT_CN)
1434                         &&  (item->flags & STAT_FLAG_FOLLOW_PT_CN)
1435                         &&  !(item->flags & STAT_FLAG_MARKER))
1436                 {
1437                         printf(",\"s\":\"%s\",\"t\":%d", "Marker missing?", RTP_TYPE_WARN);
1438                 }
1439                 else if (item->flags & STAT_FLAG_PT_T_EVENT)
1440                         printf(",\"s\":\"PT=%u telephone/event\",\"t\":%d", item->pt, RTP_TYPE_PT_EVENT);
1441                 else if (item->flags & STAT_FLAG_MARKER)
1442                         printf(",\"t\":%d", RTP_TYPE_WARN);
1443
1444                 if (item->marker)
1445                         printf(",\"mark\":1");
1446
1447                 printf("}");
1448                 sepa = ",";
1449         }
1450         printf("]");
1451
1452         printf("},");
1453 }
1454
1455 /**
1456  * sharkd_session_process_tap_conv_cb()
1457  *
1458  * Output conv tap:
1459  *   (m) tap        - tap name
1460  *   (m) type       - tap output type
1461  *   (m) proto      - protocol short name
1462  *   (o) filter     - filter string
1463  *
1464  *   (o) convs      - array of object with attributes:
1465  *                  (m) saddr - source address
1466  *                  (m) daddr - destination address
1467  *                  (o) sport - source port
1468  *                  (o) dport - destination port
1469  *                  (m) txf   - TX frame count
1470  *                  (m) txb   - TX bytes
1471  *                  (m) rxf   - RX frame count
1472  *                  (m) rxb   - RX bytes
1473  *                  (m) start - (relative) first packet time
1474  *                  (m) stop  - (relative) last packet time
1475  *
1476  *   (o) hosts      - array of object with attributes:
1477  *                  (m) host - host address
1478  *                  (o) port - host port
1479  *                  (m) txf  - TX frame count
1480  *                  (m) txb  - TX bytes
1481  *                  (m) rxf  - RX frame count
1482  *                  (m) rxb  - RX bytes
1483  */
1484 static void
1485 sharkd_session_process_tap_conv_cb(void *arg)
1486 {
1487         conv_hash_t *hash = (conv_hash_t *) arg;
1488         const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1489         const char *proto;
1490         int proto_with_port;
1491         guint i;
1492
1493         int with_geoip = 0;
1494
1495         if (!strncmp(iu->type, "conv:", 5))
1496         {
1497                 printf("{\"tap\":\"%s\",\"type\":\"conv\"", iu->type);
1498                 printf(",\"convs\":[");
1499                 proto = iu->type + 5;
1500         }
1501         else if (!strncmp(iu->type, "endpt:", 6))
1502         {
1503                 printf("{\"tap\":\"%s\",\"type\":\"host\"", iu->type);
1504                 printf(",\"hosts\":[");
1505                 proto = iu->type + 6;
1506         }
1507         else
1508         {
1509                 printf("{\"tap\":\"%s\",\"type\":\"err\"", iu->type);
1510                 proto = "";
1511         }
1512
1513         proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
1514
1515         if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5))
1516         {
1517                 for (i = 0; i < iu->hash.conv_array->len; i++)
1518                 {
1519                         conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i);
1520                         char *src_addr, *dst_addr;
1521                         char *src_port, *dst_port;
1522                         char *filter_str;
1523
1524                         printf("%s{", i ? "," : "");
1525
1526                         printf("\"saddr\":\"%s\"",  (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name)));
1527                         printf(",\"daddr\":\"%s\"", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name)));
1528
1529                         if (proto_with_port)
1530                         {
1531                                 printf(",\"sport\":\"%s\"", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port)));
1532                                 printf(",\"dport\":\"%s\"", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port)));
1533
1534                                 wmem_free(NULL, src_port);
1535                                 wmem_free(NULL, dst_port);
1536                         }
1537
1538                         printf(",\"rxf\":%" G_GUINT64_FORMAT, iui->rx_frames);
1539                         printf(",\"rxb\":%" G_GUINT64_FORMAT, iui->rx_bytes);
1540
1541                         printf(",\"txf\":%" G_GUINT64_FORMAT, iui->tx_frames);
1542                         printf(",\"txb\":%" G_GUINT64_FORMAT, iui->tx_bytes);
1543
1544                         printf(",\"start\":%.9f", nstime_to_sec(&iui->start_time));
1545                         printf(",\"stop\":%.9f", nstime_to_sec(&iui->stop_time));
1546
1547                         filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
1548                         if (filter_str)
1549                         {
1550                                 printf(",\"filter\":\"%s\"", filter_str);
1551                                 g_free(filter_str);
1552                         }
1553
1554                         wmem_free(NULL, src_addr);
1555                         wmem_free(NULL, dst_addr);
1556
1557                         if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
1558                                 with_geoip = 1;
1559                         if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
1560                                 with_geoip = 1;
1561
1562                         printf("}");
1563                 }
1564         }
1565         else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6))
1566         {
1567                 for (i = 0; i < iu->hash.conv_array->len; i++)
1568                 {
1569                         hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
1570                         char *host_str, *port_str;
1571                         char *filter_str;
1572
1573                         printf("%s{", i ? "," : "");
1574
1575                         printf("\"host\":\"%s\"", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name)));
1576
1577                         if (proto_with_port)
1578                         {
1579                                 printf(",\"port\":\"%s\"", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port)));
1580
1581                                 wmem_free(NULL, port_str);
1582                         }
1583
1584                         printf(",\"rxf\":%" G_GUINT64_FORMAT, host->rx_frames);
1585                         printf(",\"rxb\":%" G_GUINT64_FORMAT, host->rx_bytes);
1586
1587                         printf(",\"txf\":%" G_GUINT64_FORMAT, host->tx_frames);
1588                         printf(",\"txb\":%" G_GUINT64_FORMAT, host->tx_bytes);
1589
1590                         filter_str = get_hostlist_filter(host);
1591                         if (filter_str)
1592                         {
1593                                 printf(",\"filter\":\"%s\"", filter_str);
1594                                 g_free(filter_str);
1595                         }
1596
1597                         wmem_free(NULL, host_str);
1598
1599                         if (sharkd_session_geoip_addr(&(host->myaddress), ""))
1600                                 with_geoip = 1;
1601                         printf("}");
1602                 }
1603         }
1604
1605         printf("],\"proto\":\"%s\",\"geoip\":%s},", proto, with_geoip ? "true" : "false");
1606 }
1607
1608 static void
1609 sharkd_session_free_tap_conv_cb(void *arg)
1610 {
1611         conv_hash_t *hash = (conv_hash_t *) arg;
1612         struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1613
1614         if (!strncmp(iu->type, "conv:", 5))
1615         {
1616                 reset_conversation_table_data(hash);
1617         }
1618         else if (!strncmp(iu->type, "endpt:", 6))
1619         {
1620                 reset_hostlist_table_data(hash);
1621         }
1622
1623         g_free(iu);
1624 }
1625
1626 /**
1627  * sharkd_session_process_tap_nstat_cb()
1628  *
1629  * Output nstat tap:
1630  *   (m) tap        - tap name
1631  *   (m) type       - tap output type
1632  *   (m) fields: array of objects with attributes:
1633  *                  (m) c - name
1634  *
1635  *   (m) tables: array of object with attributes:
1636  *                  (m) t - table title
1637  *                  (m) i - array of items
1638  */
1639 static void
1640 sharkd_session_process_tap_nstat_cb(void *arg)
1641 {
1642         stat_data_t *stat_data = (stat_data_t *) arg;
1643         guint i, j, k;
1644
1645         printf("{\"tap\":\"nstat:%s\",\"type\":\"nstat\"", stat_data->stat_tap_data->cli_string);
1646
1647         printf(",\"fields\":[");
1648         for (i = 0; i < stat_data->stat_tap_data->nfields; i++)
1649         {
1650                 stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]);
1651
1652                 if (i)
1653                         printf(",");
1654
1655                 printf("{");
1656
1657                 printf("\"c\":");
1658                 json_puts_string(field->column_name);
1659
1660                 printf("}");
1661         }
1662         printf("]");
1663
1664         printf(",\"tables\":[");
1665         for (i = 0; i < stat_data->stat_tap_data->tables->len; i++)
1666         {
1667                 stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i);
1668                 const char *sepa = "";
1669
1670                 if (i)
1671                         printf(",");
1672
1673                 printf("{");
1674
1675                 printf("\"t\":");
1676                 printf("\"%s\"", table->title);
1677
1678                 printf(",\"i\":[");
1679                 for (j = 0; j < table->num_elements; j++)
1680                 {
1681                         stat_tap_table_item_type *field_data;
1682
1683                         field_data = stat_tap_get_field_data(table, j, 0);
1684                         if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */
1685                                 continue;
1686
1687                         printf("%s[", sepa);
1688                         for (k = 0; k < table->num_fields; k++)
1689                         {
1690                                 field_data = stat_tap_get_field_data(table, j, k);
1691
1692                                 if (k)
1693                                         printf(",");
1694
1695                                 switch (field_data->type)
1696                                 {
1697                                         case TABLE_ITEM_UINT:
1698                                                 printf("%u", field_data->value.uint_value);
1699                                                 break;
1700
1701                                         case TABLE_ITEM_INT:
1702                                                 printf("%d", field_data->value.int_value);
1703                                                 break;
1704
1705                                         case TABLE_ITEM_STRING:
1706                                                 json_puts_string(field_data->value.string_value);
1707                                                 break;
1708
1709                                         case TABLE_ITEM_FLOAT:
1710                                                 printf("%f", field_data->value.float_value);
1711                                                 break;
1712
1713                                         case TABLE_ITEM_ENUM:
1714                                                 printf("%d", field_data->value.enum_value);
1715                                                 break;
1716
1717                                         case TABLE_ITEM_NONE:
1718                                                 printf("null");
1719                                                 break;
1720                                 }
1721                         }
1722
1723                         printf("]");
1724                         sepa = ",";
1725                 }
1726                 printf("]");
1727                 printf("}");
1728         }
1729
1730         printf("]},");
1731 }
1732
1733 static void
1734 sharkd_session_free_tap_nstat_cb(void *arg)
1735 {
1736         stat_data_t *stat_data = (stat_data_t *) arg;
1737
1738         free_stat_tables(stat_data->stat_tap_data);
1739 }
1740
1741 /**
1742  * sharkd_session_process_tap_rtd_cb()
1743  *
1744  * Output rtd tap:
1745  *   (m) tap        - tap name
1746  *   (m) type       - tap output type
1747  *   (m) stats - statistics rows - array object with attributes:
1748  *                  (m) type - statistic name
1749  *                  (m) num - number of messages
1750  *                  (m) min - minimum SRT time
1751  *                  (m) max - maximum SRT time
1752  *                  (m) tot - total SRT time
1753  *                  (m) min_frame - minimal SRT
1754  *                  (m) max_frame - maximum SRT
1755  *                  (o) open_req - Open Requests
1756  *                  (o) disc_rsp - Discarded Responses
1757  *                  (o) req_dup  - Duplicated Requests
1758  *                  (o) rsp_dup  - Duplicated Responses
1759  *   (o) open_req   - Open Requests
1760  *   (o) disc_rsp   - Discarded Responses
1761  *   (o) req_dup    - Duplicated Requests
1762  *   (o) rsp_dup    - Duplicated Responses
1763  */
1764 static void
1765 sharkd_session_process_tap_rtd_cb(void *arg)
1766 {
1767         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1768         register_rtd_t *rtd  = (register_rtd_t *) rtd_data->user_data;
1769
1770         guint i, j;
1771
1772         const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
1773
1774         /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
1775          *      some multiple table and single timestat (radius, h225)
1776          *      and it seems that value_string is used one for timestamp-ID, other one for table-ID
1777          *      I wonder how it will gonna work with multiple timestats and multiple tables...
1778          * (for usage grep for: register_rtd_table)
1779          */
1780         const value_string *vs = get_rtd_value_string(rtd);
1781         const char *sepa = "";
1782
1783         printf("{\"tap\":\"rtd:%s\",\"type\":\"rtd\"", filter);
1784
1785         if (rtd_data->stat_table.num_rtds == 1)
1786         {
1787                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
1788
1789                 printf(",\"open_req\":%u", ms->open_req_num);
1790                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1791                 printf(",\"req_dup\":%u", ms->req_dup_num);
1792                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1793         }
1794
1795         printf(",\"stats\":[");
1796         for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
1797         {
1798                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
1799
1800                 for (j = 0; j < ms->num_timestat; j++)
1801                 {
1802                         const char *type_str;
1803
1804                         if (ms->rtd[j].num == 0)
1805                                 continue;
1806
1807                         printf("%s{", sepa);
1808
1809                         if (rtd_data->stat_table.num_rtds == 1)
1810                                 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
1811                         else
1812                                 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
1813                         printf("\"type\":");
1814                         json_puts_string(type_str);
1815
1816                         printf(",\"num\":%u", ms->rtd[j].num);
1817                         printf(",\"min\":%.9f", nstime_to_sec(&(ms->rtd[j].min)));
1818                         printf(",\"max\":%.9f", nstime_to_sec(&(ms->rtd[j].max)));
1819                         printf(",\"tot\":%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
1820                         printf(",\"min_frame\":%u", ms->rtd[j].min_num);
1821                         printf(",\"max_frame\":%u", ms->rtd[j].max_num);
1822
1823                         if (rtd_data->stat_table.num_rtds != 1)
1824                         {
1825                                 /* like in tshark, display it on every row */
1826                                 printf(",\"open_req\":%u", ms->open_req_num);
1827                                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1828                                 printf(",\"req_dup\":%u", ms->req_dup_num);
1829                                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1830                         }
1831
1832                         printf("}");
1833                         sepa = ",";
1834                 }
1835         }
1836         printf("]},");
1837 }
1838
1839 static void
1840 sharkd_session_free_tap_rtd_cb(void *arg)
1841 {
1842         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1843
1844         free_rtd_table(&rtd_data->stat_table);
1845         g_free(rtd_data);
1846 }
1847
1848 /**
1849  * sharkd_session_process_tap_srt_cb()
1850  *
1851  * Output srt tap:
1852  *   (m) tap        - tap name
1853  *   (m) type       - tap output type
1854  *
1855  *   (m) tables - array of object with attributes:
1856  *                  (m) n - table name
1857  *                  (m) f - table filter
1858  *                  (o) c - table column name
1859  *                  (m) r - table rows - array object with attributes:
1860  *                            (m) n   - row name
1861  *                            (m) idx - procedure index
1862  *                            (m) num - number of events
1863  *                            (m) min - minimum SRT time
1864  *                            (m) max - maximum SRT time
1865  *                            (m) tot - total SRT time
1866  */
1867 static void
1868 sharkd_session_process_tap_srt_cb(void *arg)
1869 {
1870         srt_data_t *srt_data = (srt_data_t *) arg;
1871         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1872
1873         const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
1874
1875         guint i;
1876
1877         printf("{\"tap\":\"srt:%s\",\"type\":\"srt\"", filter);
1878
1879         printf(",\"tables\":[");
1880         for (i = 0; i < srt_data->srt_array->len; i++)
1881         {
1882                 /* SRT table */
1883                 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i);
1884                 const char *sepa = "";
1885
1886                 int j;
1887
1888                 if (i)
1889                         printf(",");
1890                 printf("{");
1891
1892                 printf("\"n\":");
1893                 if (rst->name)
1894                         json_puts_string(rst->name);
1895                 else if (rst->short_name)
1896                         json_puts_string(rst->short_name);
1897                 else
1898                         printf("\"table%u\"", i);
1899
1900                 if (rst->filter_string)
1901                 {
1902                         printf(",\"f\":");
1903                         json_puts_string(rst->filter_string);
1904                 }
1905
1906                 if (rst->proc_column_name)
1907                 {
1908                         printf(",\"c\":");
1909                         json_puts_string(rst->proc_column_name);
1910                 }
1911
1912                 printf(",\"r\":[");
1913                 for (j = 0; j < rst->num_procs; j++)
1914                 {
1915                         /* SRT row */
1916                         srt_procedure_t *proc = &rst->procedures[j];
1917
1918                         if (proc->stats.num == 0)
1919                                 continue;
1920
1921                         printf("%s{", sepa);
1922
1923                         printf("\"n\":");
1924                         json_puts_string(proc->procedure);
1925
1926                         if (rst->filter_string)
1927                                 printf(",\"idx\":%d", proc->proc_index);
1928
1929                         printf(",\"num\":%u", proc->stats.num);
1930
1931                         printf(",\"min\":%.9f", nstime_to_sec(&proc->stats.min));
1932                         printf(",\"max\":%.9f", nstime_to_sec(&proc->stats.max));
1933                         printf(",\"tot\":%.9f", nstime_to_sec(&proc->stats.tot));
1934
1935                         printf("}");
1936                         sepa = ",";
1937                 }
1938                 printf("]}");
1939         }
1940
1941         printf("]},");
1942 }
1943
1944 static void
1945 sharkd_session_free_tap_srt_cb(void *arg)
1946 {
1947         srt_data_t *srt_data = (srt_data_t *) arg;
1948         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1949
1950         free_srt_table(srt, srt_data->srt_array);
1951         g_array_free(srt_data->srt_array, TRUE);
1952         g_free(srt_data);
1953 }
1954
1955 struct sharkd_export_object_list
1956 {
1957         struct sharkd_export_object_list *next;
1958
1959         char *type;
1960         const char *proto;
1961         GSList *entries;
1962 };
1963
1964 static struct sharkd_export_object_list *sharkd_eo_list;
1965
1966 /**
1967  * sharkd_session_process_tap_eo_cb()
1968  *
1969  * Output eo tap:
1970  *   (m) tap        - tap name
1971  *   (m) type       - tap output type
1972  *   (m) proto      - protocol short name
1973  *   (m) objects    - array of object with attributes:
1974  *                  (m) pkt - packet number
1975  *                  (o) hostname - hostname
1976  *                  (o) type - content type
1977  *                  (o) filename - filename
1978  *                  (m) len - object length
1979  */
1980 static void
1981 sharkd_session_process_tap_eo_cb(void *tapdata)
1982 {
1983         export_object_list_t *tap_object = (export_object_list_t *) tapdata;
1984         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data;
1985         GSList *slist;
1986         int i = 0;
1987
1988         printf("{\"tap\":\"%s\",\"type\":\"eo\"", object_list->type);
1989         printf(",\"proto\":\"%s\"", object_list->proto);
1990         printf(",\"objects\":[");
1991
1992         for (slist = object_list->entries; slist; slist = slist->next)
1993         {
1994                 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
1995
1996                 printf("%s{", i ? "," : "");
1997
1998                 printf("\"pkt\":%u", eo_entry->pkt_num);
1999
2000                 if (eo_entry->hostname)
2001                 {
2002                         printf(",\"hostname\":");
2003                         json_puts_string(eo_entry->hostname);
2004                 }
2005
2006                 if (eo_entry->content_type)
2007                 {
2008                         printf(",\"type\":");
2009                         json_puts_string(eo_entry->content_type);
2010                 }
2011
2012                 if (eo_entry->filename)
2013                 {
2014                         printf(",\"filename\":");
2015                         json_puts_string(eo_entry->filename);
2016                 }
2017
2018                 printf(",\"_download\":\"%s_%d\"", object_list->type, i);
2019
2020                 printf(",\"len\":%" G_GINT64_FORMAT, eo_entry->payload_len);
2021
2022                 printf("}");
2023
2024                 i++;
2025         }
2026
2027         printf("]},");
2028 }
2029
2030 static void
2031 sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
2032 {
2033         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2034
2035         object_list->entries = g_slist_append(object_list->entries, entry);
2036 }
2037
2038 static export_object_entry_t *
2039 sharkd_eo_object_list_get_entry(void *gui_data, int row)
2040 {
2041         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2042
2043         return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
2044 }
2045
2046 /**
2047  * sharkd_session_process_tap_rtp_cb()
2048  *
2049  * Output RTP streams tap:
2050  *   (m) tap        - tap name
2051  *   (m) type       - tap output type
2052  *   (m) streams    - array of object with attributes:
2053  *                  (m) ssrc        - RTP synchronization source identifier
2054  *                  (m) payload     - stream payload
2055  *                  (m) saddr       - source address
2056  *                  (m) sport       - source port
2057  *                  (m) daddr       - destination address
2058  *                  (m) dport       - destination port
2059  *                  (m) pkts        - packets count
2060  *                  (m) max_delta   - max delta (ms)
2061  *                  (m) max_jitter  - max jitter (ms)
2062  *                  (m) mean_jitter - mean jitter (ms)
2063  *                  (m) expectednr  -
2064  *                  (m) totalnr     -
2065  *                  (m) problem     - if analyser found the problem
2066  *                  (m) ipver       - address IP version (4 or 6)
2067  */
2068 static void
2069 sharkd_session_process_tap_rtp_cb(void *arg)
2070 {
2071         rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
2072
2073         GList *listx;
2074         const char *sepa = "";
2075
2076         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "rtp-streams", "rtp-streams");
2077
2078         printf(",\"streams\":[");
2079         for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
2080         {
2081                 rtpstream_info_calc_t calc;
2082                 rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
2083
2084                 rtpstream_info_calculate(streaminfo, &calc);
2085
2086                 printf("%s{\"ssrc\":%u", sepa, calc.ssrc);
2087                 printf(",\"payload\":\"%s\"", calc.all_payload_type_names);
2088
2089                 printf(",\"saddr\":\"%s\"", calc.src_addr_str);
2090                 printf(",\"sport\":%u", calc.src_port);
2091
2092                 printf(",\"daddr\":\"%s\"", calc.dst_addr_str);
2093                 printf(",\"dport\":%u", calc.dst_port);
2094
2095                 printf(",\"pkts\":%u", calc.packet_count);
2096
2097                 printf(",\"max_delta\":%f",calc.max_delta);
2098                 printf(",\"max_jitter\":%f", calc.max_jitter);
2099                 printf(",\"mean_jitter\":%f", calc.mean_jitter);
2100
2101                 printf(",\"expectednr\":%u", calc.packet_expected);
2102                 printf(",\"totalnr\":%u", calc.total_nr);
2103
2104                 printf(",\"problem\":%s", calc.problem? "true" : "false");
2105
2106                 /* for filter */
2107                 printf(",\"ipver\":%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4);
2108
2109                 rtpstream_info_calc_free(&calc);
2110
2111                 printf("}");
2112                 sepa = ",";
2113         }
2114         printf("]},");
2115 }
2116
2117 /**
2118  * sharkd_session_process_tap()
2119  *
2120  * Process tap request
2121  *
2122  * Input:
2123  *   (m) tap0         - First tap request
2124  *   (o) tap1...tap15 - Other tap requests
2125  *
2126  * Output object with attributes:
2127  *   (m) taps  - array of object with attributes:
2128  *                  (m) tap  - tap name
2129  *                  (m) type - tap output type
2130  *                  ...
2131  *                  for type:stats see sharkd_session_process_tap_stats_cb()
2132  *                  for type:nstat see sharkd_session_process_tap_nstat_cb()
2133  *                  for type:conv see sharkd_session_process_tap_conv_cb()
2134  *                  for type:host see sharkd_session_process_tap_conv_cb()
2135  *                  for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
2136  *                  for type:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
2137  *                  for type:eo see sharkd_session_process_tap_eo_cb()
2138  *                  for type:expert see sharkd_session_process_tap_expert_cb()
2139  *                  for type:rtd see sharkd_session_process_tap_rtd_cb()
2140  *                  for type:srt see sharkd_session_process_tap_srt_cb()
2141  *                  for type:flow see sharkd_session_process_tap_flow_cb()
2142  *
2143  *   (m) err   - error code
2144  */
2145 static void
2146 sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
2147 {
2148         void *taps_data[16];
2149         GFreeFunc taps_free[16];
2150         int taps_count = 0;
2151         int i;
2152
2153         rtpstream_tapinfo_t rtp_tapinfo =
2154                 { NULL, NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE };
2155
2156         for (i = 0; i < 16; i++)
2157         {
2158                 char tapbuf[32];
2159                 const char *tok_tap;
2160
2161                 void *tap_data = NULL;
2162                 GFreeFunc tap_free = NULL;
2163                 const char *tap_filter = "";
2164                 GString *tap_error = NULL;
2165
2166                 ws_snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
2167                 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
2168                 if (!tok_tap)
2169                         break;
2170
2171                 if (!strncmp(tok_tap, "stat:", 5))
2172                 {
2173                         stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
2174                         stats_tree *st;
2175
2176                         if (!cfg)
2177                         {
2178                                 fprintf(stderr, "sharkd_session_process_tap() stat %s not found\n", tok_tap + 5);
2179                                 continue;
2180                         }
2181
2182                         st = stats_tree_new(cfg, NULL, tap_filter);
2183
2184                         tap_error = register_tap_listener(st->cfg->tapname, st, st->filter, st->cfg->flags, stats_tree_reset, stats_tree_packet, sharkd_session_process_tap_stats_cb);
2185
2186                         if (!tap_error && cfg->init)
2187                                 cfg->init(st);
2188
2189                         tap_data = st;
2190                         tap_free = sharkd_session_free_tap_stats_cb;
2191                 }
2192                 else if (!strcmp(tok_tap, "expert"))
2193                 {
2194                         struct sharkd_expert_tap *expert_tap;
2195
2196                         expert_tap = g_new0(struct sharkd_expert_tap, 1);
2197                         expert_tap->text = g_string_chunk_new(100);
2198
2199                         tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb);
2200
2201                         tap_data = expert_tap;
2202                         tap_free = sharkd_session_free_tap_expert_cb;
2203                 }
2204                 else if (!strncmp(tok_tap, "seqa:", 5))
2205                 {
2206                         seq_analysis_info_t *graph_analysis;
2207                         register_analysis_t *analysis;
2208                         const char *tap_name;
2209                         tap_packet_cb tap_func;
2210                         guint tap_flags;
2211
2212                         analysis = sequence_analysis_find_by_name(tok_tap + 5);
2213                         if (!analysis)
2214                         {
2215                                 fprintf(stderr, "sharkd_session_process_tap() seq analysis %s not found\n", tok_tap + 5);
2216                                 continue;
2217                         }
2218
2219                         graph_analysis = sequence_analysis_info_new();
2220                         graph_analysis->name = tok_tap + 5;
2221                         /* TODO, make configurable */
2222                         graph_analysis->any_addr = FALSE;
2223
2224                         tap_name  = sequence_analysis_get_tap_listener_name(analysis);
2225                         tap_flags = sequence_analysis_get_tap_flags(analysis);
2226                         tap_func  = sequence_analysis_get_packet_func(analysis);
2227
2228                         tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb);
2229
2230                         tap_data = graph_analysis;
2231                         tap_free = sharkd_session_free_tap_flow_cb;
2232                 }
2233                 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
2234                 {
2235                         struct register_ct *ct = NULL;
2236                         const char *ct_tapname;
2237                         struct sharkd_conv_tap_data *ct_data;
2238                         tap_packet_cb tap_func = NULL;
2239
2240                         if (!strncmp(tok_tap, "conv:", 5))
2241                         {
2242                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
2243
2244                                 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
2245                                 {
2246                                         fprintf(stderr, "sharkd_session_process_tap() conv %s not found\n", tok_tap + 5);
2247                                         continue;
2248                                 }
2249                         }
2250                         else if (!strncmp(tok_tap, "endpt:", 6))
2251                         {
2252                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
2253
2254                                 if (!ct || !(tap_func = get_hostlist_packet_func(ct)))
2255                                 {
2256                                         fprintf(stderr, "sharkd_session_process_tap() endpt %s not found\n", tok_tap + 6);
2257                                         continue;
2258                                 }
2259                         }
2260                         else
2261                         {
2262                                 fprintf(stderr, "sharkd_session_process_tap() conv/endpt(?): %s not found\n", tok_tap);
2263                                 continue;
2264                         }
2265
2266                         ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
2267
2268                         ct_data = (struct sharkd_conv_tap_data *) g_malloc0(sizeof(struct sharkd_conv_tap_data));
2269                         ct_data->type = tok_tap;
2270                         ct_data->hash.user_data = ct_data;
2271
2272                         /* XXX: make configurable */
2273                         ct_data->resolve_name = TRUE;
2274                         ct_data->resolve_port = TRUE;
2275
2276                         tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb);
2277
2278                         tap_data = &ct_data->hash;
2279                         tap_free = sharkd_session_free_tap_conv_cb;
2280                 }
2281                 else if (!strncmp(tok_tap, "nstat:", 6))
2282                 {
2283                         stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6);
2284                         stat_data_t *stat_data;
2285
2286                         if (!stat_tap)
2287                         {
2288                                 fprintf(stderr, "sharkd_session_process_tap() nstat=%s not found\n", tok_tap + 6);
2289                                 continue;
2290                         }
2291
2292                         stat_tap->stat_tap_init_cb(stat_tap);
2293
2294                         stat_data = g_new0(stat_data_t, 1);
2295                         stat_data->stat_tap_data = stat_tap;
2296                         stat_data->user_data = NULL;
2297
2298                         tap_error = register_tap_listener(stat_tap->tap_name, stat_data, tap_filter, 0, NULL, stat_tap->packet_func, sharkd_session_process_tap_nstat_cb);
2299
2300                         tap_data = stat_data;
2301                         tap_free = sharkd_session_free_tap_nstat_cb;
2302                 }
2303                 else if (!strncmp(tok_tap, "rtd:", 4))
2304                 {
2305                         register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
2306                         rtd_data_t *rtd_data;
2307                         char *err;
2308
2309                         if (!rtd)
2310                         {
2311                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s not found\n", tok_tap + 4);
2312                                 continue;
2313                         }
2314
2315                         rtd_table_get_filter(rtd, "", &tap_filter, &err);
2316                         if (err != NULL)
2317                         {
2318                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s err=%s\n", tok_tap + 4, err);
2319                                 g_free(err);
2320                                 continue;
2321                         }
2322
2323                         rtd_data = g_new0(rtd_data_t, 1);
2324                         rtd_data->user_data = rtd;
2325                         rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL);
2326
2327                         tap_error = register_tap_listener(get_rtd_tap_listener_name(rtd), rtd_data, tap_filter, 0, NULL, get_rtd_packet_func(rtd), sharkd_session_process_tap_rtd_cb);
2328
2329                         tap_data = rtd_data;
2330                         tap_free = sharkd_session_free_tap_rtd_cb;
2331                 }
2332                 else if (!strncmp(tok_tap, "srt:", 4))
2333                 {
2334                         register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
2335                         srt_data_t *srt_data;
2336                         char *err;
2337
2338                         if (!srt)
2339                         {
2340                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s not found\n", tok_tap + 4);
2341                                 continue;
2342                         }
2343
2344                         srt_table_get_filter(srt, "", &tap_filter, &err);
2345                         if (err != NULL)
2346                         {
2347                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s err=%s\n", tok_tap + 4, err);
2348                                 g_free(err);
2349                                 continue;
2350                         }
2351
2352                         srt_data = g_new0(srt_data_t, 1);
2353                         srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *));
2354                         srt_data->user_data = srt;
2355                         srt_table_dissector_init(srt, srt_data->srt_array);
2356
2357                         tap_error = register_tap_listener(get_srt_tap_listener_name(srt), srt_data, tap_filter, 0, NULL, get_srt_packet_func(srt), sharkd_session_process_tap_srt_cb);
2358
2359                         tap_data = srt_data;
2360                         tap_free = sharkd_session_free_tap_srt_cb;
2361                 }
2362                 else if (!strncmp(tok_tap, "eo:", 3))
2363                 {
2364                         register_eo_t *eo = get_eo_by_name(tok_tap + 3);
2365                         export_object_list_t *eo_object;
2366                         struct sharkd_export_object_list *object_list;
2367
2368                         if (!eo)
2369                         {
2370                                 fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
2371                                 continue;
2372                         }
2373
2374                         for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
2375                         {
2376                                 if (!strcmp(object_list->type, tok_tap))
2377                                 {
2378                                         g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
2379                                         object_list->entries = NULL;
2380                                         break;
2381                                 }
2382                         }
2383
2384                         if (!object_list)
2385                         {
2386                                 object_list = g_new(struct sharkd_export_object_list, 1);
2387                                 object_list->type = g_strdup(tok_tap);
2388                                 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
2389                                 object_list->entries = NULL;
2390                                 object_list->next = sharkd_eo_list;
2391                                 sharkd_eo_list = object_list;
2392                         }
2393
2394                         eo_object  = g_new0(export_object_list_t, 1);
2395                         eo_object->add_entry = sharkd_eo_object_list_add_entry;
2396                         eo_object->get_entry = sharkd_eo_object_list_get_entry;
2397                         eo_object->gui_data = (void *) object_list;
2398
2399                         tap_error = register_tap_listener(get_eo_tap_listener_name(eo), eo_object, NULL, 0, NULL, get_eo_packet_func(eo), sharkd_session_process_tap_eo_cb);
2400
2401                         tap_data = eo_object;
2402                         tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
2403                 }
2404                 else if (!strcmp(tok_tap, "rtp-streams"))
2405                 {
2406                         tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb);
2407
2408                         tap_data = &rtp_tapinfo;
2409                         tap_free = rtpstream_reset_cb;
2410                 }
2411                 else if (!strncmp(tok_tap, "rtp-analyse:", 12))
2412                 {
2413                         struct sharkd_analyse_rtp *rtp_req;
2414
2415                         rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
2416                         if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12))
2417                         {
2418                                 rtpstream_id_free(&rtp_req->id);
2419                                 g_free(rtp_req);
2420                                 continue;
2421                         }
2422
2423                         rtp_req->tap_name = tok_tap;
2424                         rtp_req->statinfo.first_packet = TRUE;
2425                         rtp_req->statinfo.reg_pt = PT_UNDEFINED;
2426
2427                         tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL, sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb);
2428
2429                         tap_data = rtp_req;
2430                         tap_free = sharkd_session_process_tap_rtp_free_cb;
2431                 }
2432                 else
2433                 {
2434                         fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);
2435                         continue;
2436                 }
2437
2438                 if (tap_error)
2439                 {
2440                         fprintf(stderr, "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str);
2441                         g_string_free(tap_error, TRUE);
2442                         if (tap_free)
2443                                 tap_free(tap_data);
2444                         continue;
2445                 }
2446
2447                 taps_data[taps_count] = tap_data;
2448                 taps_free[taps_count] = tap_free;
2449                 taps_count++;
2450         }
2451
2452         fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count);
2453         if (taps_count == 0)
2454                 return;
2455
2456         printf("{\"taps\":[");
2457         sharkd_retap();
2458         printf("null],\"err\":0}\n");
2459
2460         for (i = 0; i < taps_count; i++)
2461         {
2462                 if (taps_data[i])
2463                         remove_tap_listener(taps_data[i]);
2464
2465                 if (taps_free[i])
2466                         taps_free[i](taps_data[i]);
2467         }
2468 }
2469
2470 /**
2471  * sharkd_session_process_follow()
2472  *
2473  * Process follow request
2474  *
2475  * Input:
2476  *   (m) follow  - follow protocol request (e.g. HTTP)
2477  *   (m) filter  - filter request (e.g. tcp.stream == 1)
2478  *
2479  * Output object with attributes:
2480  *
2481  *   (m) err    - error code
2482  *   (m) shost  - server host
2483  *   (m) sport  - server port
2484  *   (m) sbytes - server send bytes count
2485  *   (m) chost  - client host
2486  *   (m) cport  - client port
2487  *   (m) cbytes - client send bytes count
2488  *   (o) payloads - array of object with attributes:
2489  *                  (o) s - set if server sent, else client
2490  *                  (m) n - packet number
2491  *                  (m) d - data base64 encoded
2492  */
2493 static void
2494 sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
2495 {
2496         const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
2497         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2498
2499         register_follow_t *follower;
2500         GString *tap_error;
2501
2502         follow_info_t *follow_info;
2503         const char *host;
2504         char *port;
2505
2506         if (!tok_follow || !tok_filter)
2507                 return;
2508
2509         follower = get_follow_by_name(tok_follow);
2510         if (!follower)
2511         {
2512                 fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
2513                 return;
2514         }
2515
2516         /* follow_reset_stream ? */
2517         follow_info = g_new0(follow_info_t, 1);
2518         /* gui_data, filter_out_filter not set, but not used by dissector */
2519
2520         tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL);
2521         if (tap_error)
2522         {
2523                 fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
2524                 g_string_free(tap_error, TRUE);
2525                 g_free(follow_info);
2526                 return;
2527         }
2528
2529         sharkd_retap();
2530
2531         printf("{");
2532
2533         printf("\"err\":0");
2534
2535         /* Server information: hostname, port, bytes sent */
2536         host = address_to_name(&follow_info->server_ip);
2537         printf(",\"shost\":");
2538         json_puts_string(host);
2539
2540         port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
2541         printf(",\"sport\":");
2542         json_puts_string(port);
2543         wmem_free(NULL, port);
2544
2545         printf(",\"sbytes\":%u", follow_info->bytes_written[0]);
2546
2547         /* Client information: hostname, port, bytes sent */
2548         host = address_to_name(&follow_info->client_ip);
2549         printf(",\"chost\":");
2550         json_puts_string(host);
2551
2552         port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
2553         printf(",\"cport\":");
2554         json_puts_string(port);
2555         wmem_free(NULL, port);
2556
2557         printf(",\"cbytes\":%u", follow_info->bytes_written[1]);
2558
2559         if (follow_info->payload)
2560         {
2561                 follow_record_t *follow_record;
2562                 GList *cur;
2563                 const char *sepa = "";
2564
2565                 printf(",\"payloads\":[");
2566
2567                 for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur))
2568                 {
2569                         follow_record = (follow_record_t *) cur->data;
2570
2571                         printf("%s{", sepa);
2572
2573                         printf("\"n\":%u", follow_record->packet_num);
2574
2575                         printf(",\"d\":");
2576                         json_print_base64(follow_record->data->data, follow_record->data->len);
2577
2578                         if (follow_record->is_server)
2579                                 printf(",\"s\":%d", 1);
2580
2581                         printf("}");
2582                         sepa = ",";
2583                 }
2584
2585                 printf("]");
2586         }
2587
2588         printf("}\n");
2589
2590         remove_tap_listener(follow_info);
2591         follow_info_free(follow_info);
2592 }
2593
2594 static void
2595 sharkd_session_process_frame_cb_tree(epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs)
2596 {
2597         proto_node *node;
2598         const char *sepa = "";
2599
2600         printf("[");
2601         for (node = tree->first_child; node; node = node->next)
2602         {
2603                 field_info *finfo = PNODE_FINFO(node);
2604
2605                 if (!finfo)
2606                         continue;
2607
2608                 /* XXX, for now always skip hidden */
2609                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
2610                         continue;
2611
2612                 printf("%s{", sepa);
2613
2614                 printf("\"l\":");
2615                 if (!finfo->rep)
2616                 {
2617                         char label_str[ITEM_LABEL_LENGTH];
2618
2619                         label_str[0] = '\0';
2620                         proto_item_fill_label(finfo, label_str);
2621                         json_puts_string(label_str);
2622                 }
2623                 else
2624                 {
2625                         json_puts_string(finfo->rep->representation);
2626                 }
2627
2628                 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
2629                 {
2630                         int idx;
2631
2632                         for (idx = 1; tvbs[idx]; idx++)
2633                         {
2634                                 if (tvbs[idx] == finfo->ds_tvb)
2635                                 {
2636                                         printf(",\"ds\":%d", idx);
2637                                         break;
2638                                 }
2639                         }
2640                 }
2641
2642                 if (finfo->start >= 0 && finfo->length > 0)
2643                         printf(",\"h\":[%d,%d]", finfo->start, finfo->length);
2644
2645                 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
2646                         printf(",\"i\":[%d,%d]", finfo->appendix_start, finfo->appendix_length);
2647
2648
2649                 if (finfo->hfinfo)
2650                 {
2651                         char *filter;
2652
2653                         if (finfo->hfinfo->type == FT_PROTOCOL)
2654                         {
2655                                 printf(",\"t\":\"proto\"");
2656                         }
2657                         else if (finfo->hfinfo->type == FT_FRAMENUM)
2658                         {
2659                                 printf(",\"t\":\"framenum\",\"fnum\":%u", finfo->value.value.uinteger);
2660                         }
2661                         else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type))
2662                         {
2663                                 char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
2664
2665                                 printf(",\"t\":\"url\",\"url\":");
2666                                 json_puts_string(url);
2667                                 wmem_free(NULL, url);
2668                         }
2669
2670                         filter = proto_construct_match_selected_string(finfo, edt);
2671                         if (filter)
2672                         {
2673                                 printf(",\"f\":");
2674                                 json_puts_string(filter);
2675                                 wmem_free(NULL, filter);
2676                         }
2677                 }
2678
2679                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2680                 {
2681                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2682
2683                         g_assert(severity != NULL);
2684
2685                         printf(",\"s\":\"%s\"", severity);
2686                 }
2687
2688                 if (((proto_tree *) node)->first_child)
2689                 {
2690                         if (finfo->tree_type != -1)
2691                                 printf(",\"e\":%d", finfo->tree_type);
2692                         printf(",\"n\":");
2693                         sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs);
2694                 }
2695
2696                 printf("}");
2697                 sepa = ",";
2698         }
2699         printf("]");
2700 }
2701
2702 static gboolean
2703 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2704 {
2705         register_follow_t *follower = (register_follow_t *) value;
2706         packet_info *pi = (packet_info *) user_data;
2707
2708         const int proto_id = get_follow_proto_id(follower);
2709
2710         guint32 ignore_stream;
2711
2712         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2713         {
2714                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2715                 char *follow_filter;
2716
2717                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2718
2719                 printf(",[\"%s\",", layer_proto);
2720                 json_puts_string(follow_filter);
2721                 printf("]");
2722
2723                 g_free(follow_filter);
2724         }
2725
2726         return FALSE;
2727 }
2728
2729 static void
2730 sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2731 {
2732         packet_info *pi = &edt->pi;
2733         frame_data *fdata = pi->fd;
2734         const char *pkt_comment = NULL;
2735
2736         (void) data;
2737
2738         printf("{");
2739
2740         printf("\"err\":0");
2741
2742         if (fdata->flags.has_user_comment)
2743                 pkt_comment = sharkd_get_user_comment(fdata);
2744         else if (fdata->flags.has_phdr_comment)
2745                 pkt_comment = pi->rec->opt_comment;
2746
2747         if (pkt_comment)
2748         {
2749                 printf(",\"comment\":");
2750                 json_puts_string(pkt_comment);
2751         }
2752
2753         if (tree)
2754         {
2755                 tvbuff_t **tvbs = NULL;
2756
2757                 printf(",\"tree\":");
2758
2759                 /* arrayize data src, to speedup searching for ds_tvb index */
2760                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2761                 {
2762                         guint count = g_slist_length((GSList *) data_src);
2763                         guint i;
2764
2765                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2766
2767                         for (i = 0; i < count; i++)
2768                         {
2769                                 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2770
2771                                 tvbs[i] = get_data_source_tvb(src);
2772                         }
2773
2774                         tvbs[count] = NULL;
2775                 }
2776
2777                 sharkd_session_process_frame_cb_tree(edt, tree, tvbs);
2778
2779                 g_free(tvbs);
2780         }
2781
2782         if (cinfo)
2783         {
2784                 int col;
2785
2786                 printf(",\"col\":[");
2787                 for (col = 0; col < cinfo->num_cols; ++col)
2788                 {
2789                         const col_item_t *col_item = &cinfo->columns[col];
2790
2791                         printf("%s\"%s\"", (col) ? "," : "", col_item->col_data);
2792                 }
2793                 printf("]");
2794         }
2795
2796         if (data_src)
2797         {
2798                 struct data_source *src = (struct data_source *) data_src->data;
2799                 const char *ds_sepa = NULL;
2800
2801                 tvbuff_t *tvb;
2802                 guint length;
2803
2804                 tvb = get_data_source_tvb(src);
2805                 length = tvb_captured_length(tvb);
2806
2807                 printf(",\"bytes\":");
2808                 if (length != 0)
2809                 {
2810                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2811
2812                         /* XXX pi.fd->flags.encoding */
2813                         json_print_base64(cp, length);
2814                 }
2815                 else
2816                 {
2817                         json_print_base64("", 0);
2818                 }
2819
2820                 data_src = data_src->next;
2821                 if (data_src)
2822                 {
2823                         printf(",\"ds\":[");
2824                         ds_sepa = "";
2825                 }
2826
2827                 while (data_src)
2828                 {
2829                         src = (struct data_source *) data_src->data;
2830
2831                         {
2832                                 char *src_name = get_data_source_name(src);
2833
2834                                 printf("%s{\"name\":", ds_sepa);
2835                                 json_puts_string(src_name);
2836                                 wmem_free(NULL, src_name);
2837                         }
2838
2839                         tvb = get_data_source_tvb(src);
2840                         length = tvb_captured_length(tvb);
2841
2842                         printf(",\"bytes\":");
2843                         if (length != 0)
2844                         {
2845                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
2846
2847                                 /* XXX pi.fd->flags.encoding */
2848                                 json_print_base64(cp, length);
2849                         }
2850                         else
2851                         {
2852                                 json_print_base64("", 0);
2853                         }
2854
2855                         printf("}");
2856                         ds_sepa = ",";
2857
2858                         data_src = data_src->next;
2859                 }
2860
2861                 /* close ds, only if was opened */
2862                 if (ds_sepa != NULL)
2863                         printf("]");
2864         }
2865
2866         printf(",\"fol\":[0");
2867         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
2868         printf("]");
2869
2870         printf("}\n");
2871 }
2872
2873 #define SHARKD_IOGRAPH_MAX_ITEMS 250000 /* 250k limit of items is taken from wireshark-qt, on x86_64 sizeof(io_graph_item_t) is 152, so single graph can take max 36 MB */
2874
2875 struct sharkd_iograph
2876 {
2877         /* config */
2878         int hf_index;
2879         io_graph_item_unit_t calc_type;
2880         guint32 interval;
2881
2882         /* result */
2883         int space_items;
2884         int num_items;
2885         io_graph_item_t *items;
2886         GString *error;
2887 };
2888
2889 static gboolean
2890 sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_)
2891 {
2892         struct sharkd_iograph *graph = (struct sharkd_iograph *) g;
2893         int idx;
2894
2895         idx = get_io_graph_index(pinfo, graph->interval);
2896         if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS)
2897                 return FALSE;
2898
2899         if (idx + 1 > graph->num_items)
2900         {
2901                 if (idx + 1 > graph->space_items)
2902                 {
2903                         int new_size = idx + 1024;
2904
2905                         graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size);
2906                         reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items);
2907
2908                         graph->space_items = new_size;
2909                 }
2910                 else if (graph->items == NULL)
2911                 {
2912                         graph->items = (io_graph_item_t *) g_malloc(sizeof(io_graph_item_t) * graph->space_items);
2913                         reset_io_graph_items(graph->items, graph->space_items);
2914                 }
2915
2916                 graph->num_items = idx + 1;
2917         }
2918
2919         return update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval);
2920 }
2921
2922 /**
2923  * sharkd_session_process_iograph()
2924  *
2925  * Process iograph request
2926  *
2927  * Input:
2928  *   (o) interval - interval time in ms, if not specified: 1000ms
2929  *   (m) graph0             - First graph request
2930  *   (o) graph1...graph9    - Other graph requests
2931  *   (o) filter0            - First graph filter
2932  *   (o) filter1...filter9  - Other graph filters
2933  *
2934  * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>",
2935  * if you use variant with <field>, you need to pass field name in filter request.
2936  *
2937  * Output object with attributes:
2938  *   (m) iograph - array of graph results with attributes:
2939  *                  errmsg - graph cannot be constructed
2940  *                  items  - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string
2941  */
2942 static void
2943 sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count)
2944 {
2945         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
2946         struct sharkd_iograph graphs[10];
2947         gboolean is_any_ok = FALSE;
2948         int graph_count;
2949
2950         guint32 interval_ms = 1000; /* default: one per second */
2951         int i;
2952
2953         if (tok_interval)
2954         {
2955                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
2956                 {
2957                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
2958                         return;
2959                 }
2960         }
2961
2962         for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++)
2963         {
2964                 struct sharkd_iograph *graph = &graphs[graph_count];
2965
2966                 const char *tok_graph;
2967                 const char *tok_filter;
2968                 char tok_format_buf[32];
2969                 const char *field_name;
2970
2971                 snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i);
2972                 tok_graph = json_find_attr(buf, tokens, count, tok_format_buf);
2973                 if (!tok_graph)
2974                         break;
2975
2976                 snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i);
2977                 tok_filter = json_find_attr(buf, tokens, count, tok_format_buf);
2978
2979                 if (!strcmp(tok_graph, "packets"))
2980                         graph->calc_type = IOG_ITEM_UNIT_PACKETS;
2981                 else if (!strcmp(tok_graph, "bytes"))
2982                         graph->calc_type = IOG_ITEM_UNIT_BYTES;
2983                 else if (!strcmp(tok_graph, "bits"))
2984                         graph->calc_type = IOG_ITEM_UNIT_BITS;
2985                 else if (g_str_has_prefix(tok_graph, "sum:"))
2986                         graph->calc_type = IOG_ITEM_UNIT_CALC_SUM;
2987                 else if (g_str_has_prefix(tok_graph, "frames:"))
2988                         graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES;
2989                 else if (g_str_has_prefix(tok_graph, "fields:"))
2990                         graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS;
2991                 else if (g_str_has_prefix(tok_graph, "max:"))
2992                         graph->calc_type = IOG_ITEM_UNIT_CALC_MAX;
2993                 else if (g_str_has_prefix(tok_graph, "min:"))
2994                         graph->calc_type = IOG_ITEM_UNIT_CALC_MIN;
2995                 else if (g_str_has_prefix(tok_graph, "avg:"))
2996                         graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE;
2997                 else if (g_str_has_prefix(tok_graph, "load:"))
2998                         graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD;
2999                 else
3000                         break;
3001
3002                 field_name = strchr(tok_graph, ':');
3003                 if (field_name)
3004                         field_name = field_name + 1;
3005
3006                 graph->interval = interval_ms;
3007
3008                 graph->hf_index = -1;
3009                 graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type);
3010
3011                 graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */
3012                 graph->num_items = 0;
3013                 graph->items = NULL;
3014
3015                 if (!graph->error)
3016                         graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL);
3017
3018                 graph_count++;
3019
3020                 if (graph->error == NULL)
3021                         is_any_ok = TRUE;
3022         }
3023
3024         /* retap only if we have at least one ok */
3025         if (is_any_ok)
3026                 sharkd_retap();
3027
3028         printf("{\"iograph\":[");
3029
3030         for (i = 0; i < graph_count; i++)
3031         {
3032                 struct sharkd_iograph *graph = &graphs[i];
3033
3034                 if (i)
3035                         printf(",");
3036                 printf("{");
3037
3038                 if (graph->error)
3039                 {
3040                         printf("\"errmsg\":");
3041                         json_puts_string(graph->error->str);
3042                         g_string_free(graph->error, TRUE);
3043                 }
3044                 else
3045                 {
3046                         int idx;
3047                         int next_idx = 0;
3048                         const char *sepa = "";
3049
3050                         printf("\"items\":[");
3051                         for (idx = 0; idx < graph->num_items; idx++)
3052                         {
3053                                 double val;
3054
3055                                 val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items);
3056
3057                                 /* if it's zero, don't display */
3058                                 if (val == 0.0)
3059                                         continue;
3060
3061                                 printf("%s", sepa);
3062
3063                                 /* cause zeros are not printed, need to output index */
3064                                 if (next_idx != idx)
3065                                         printf("\"%x\",", idx);
3066
3067                                 printf("%f", val);
3068                                 next_idx = idx + 1;
3069                                 sepa = ",";
3070                         }
3071                         printf("]");
3072                 }
3073                 printf("}");
3074
3075                 remove_tap_listener(graph);
3076                 g_free(graph->items);
3077         }
3078
3079         printf("]}\n");
3080 }
3081
3082 /**
3083  * sharkd_session_process_intervals()
3084  *
3085  * Process intervals request - generate basic capture file statistics per requested interval.
3086  *
3087  * Input:
3088  *   (o) interval - interval time in ms, if not specified: 1000ms
3089  *   (o) filter   - filter for generating interval request
3090  *
3091  * Output object with attributes:
3092  *   (m) intervals - array of intervals, with indexes:
3093  *             [0] - index of interval,
3094  *             [1] - number of frames during interval,
3095  *             [2] - number of bytes during interval.
3096  *
3097  *   (m) last   - last interval number.
3098  *   (m) frames - total number of frames
3099  *   (m) bytes  - total number of bytes
3100  *
3101  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
3102  */
3103 static void
3104 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
3105 {
3106         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3107         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3108
3109         const guint8 *filter_data = NULL;
3110
3111         struct
3112         {
3113                 unsigned int frames;
3114                 guint64 bytes;
3115         } st, st_total;
3116
3117         nstime_t *start_ts;
3118
3119         guint32 interval_ms = 1000; /* default: one per second */
3120
3121         const char *sepa = "";
3122         unsigned int framenum;
3123         gint64 idx;
3124         gint64 max_idx = 0;
3125
3126         if (tok_interval)
3127         {
3128                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3129                 {
3130                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3131                         return;
3132                 }
3133         }
3134
3135         if (tok_filter)
3136         {
3137                 filter_data = sharkd_session_filter_data(tok_filter);
3138                 if (!filter_data)
3139                         return;
3140         }
3141
3142         st_total.frames = 0;
3143         st_total.bytes  = 0;
3144
3145         st.frames = 0;
3146         st.bytes  = 0;
3147
3148         idx = 0;
3149
3150         printf("{\"intervals\":[");
3151
3152         start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL;
3153
3154         for (framenum = 1; framenum <= cfile.count; framenum++)
3155         {
3156                 frame_data *fdata;
3157                 gint64 msec_rel;
3158                 gint64 new_idx;
3159
3160                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
3161                         continue;
3162
3163                 fdata = sharkd_get_frame(framenum);
3164
3165                 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
3166                 new_idx  = msec_rel / interval_ms;
3167
3168                 if (idx != new_idx)
3169                 {
3170                         if (st.frames != 0)
3171                         {
3172                                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
3173                                 sepa = ",";
3174                         }
3175
3176                         idx = new_idx;
3177                         if (idx > max_idx)
3178                                 max_idx = idx;
3179
3180                         st.frames = 0;
3181                         st.bytes  = 0;
3182                 }
3183
3184                 st.frames += 1;
3185                 st.bytes  += fdata->pkt_len;
3186
3187                 st_total.frames += 1;
3188                 st_total.bytes  += fdata->pkt_len;
3189         }
3190
3191         if (st.frames != 0)
3192         {
3193                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
3194                 /* sepa = ","; */
3195         }
3196
3197         printf("],\"last\":%" G_GINT64_FORMAT ",\"frames\":%u,\"bytes\":%" G_GUINT64_FORMAT "}\n", max_idx, st_total.frames, st_total.bytes);
3198 }
3199
3200 /**
3201  * sharkd_session_process_frame()
3202  *
3203  * Process frame request
3204  *
3205  * Input:
3206  *   (m) frame - requested frame number
3207  *   (o) ref_frame - time reference frame number
3208  *   (o) prev_frame - previously displayed frame number
3209  *   (o) proto - set if output frame tree
3210  *   (o) columns - set if output frame columns
3211  *   (o) bytes - set if output frame bytes
3212  *
3213  * Output object with attributes:
3214  *   (m) err   - 0 if succeed
3215  *   (o) tree  - array of frame nodes with attributes:
3216  *                  l - label
3217  *                  t: 'proto', 'framenum', 'url' - type of node
3218  *                  f - filter string
3219  *                  s - severity
3220  *                  e - subtree ett index
3221  *                  n - array of subtree nodes
3222  *                  h - two item array: (item start, item length)
3223  *                  i - two item array: (appendix start, appendix length)
3224  *                  p - [RESERVED] two item array: (protocol start, protocol length)
3225  *                  ds- data src index
3226  *                  url  - only for t:'url', url
3227  *                  fnum - only for t:'framenum', frame number
3228  *
3229  *   (o) col   - array of column data
3230  *   (o) bytes - base64 of frame bytes
3231  *   (o) ds    - array of other data srcs
3232  *   (o) comment - frame comment
3233  *   (o) fol   - array of follow filters:
3234  *                  [0] - protocol
3235  *                  [1] - filter string
3236  */
3237 static void
3238 sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
3239 {
3240         const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
3241         const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame");
3242         const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame");
3243         int tok_proto   = (json_find_attr(buf, tokens, count, "proto") != NULL);
3244         int tok_bytes   = (json_find_attr(buf, tokens, count, "bytes") != NULL);
3245         int tok_columns = (json_find_attr(buf, tokens, count, "columns") != NULL);
3246
3247         guint32 framenum, ref_frame_num, prev_dis_num;
3248
3249         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3250                 return;
3251
3252         ref_frame_num = (framenum != 1) ? 1 : 0;
3253         if (tok_ref_frame && (!ws_strtou32(tok_ref_frame, NULL, &ref_frame_num) || ref_frame_num > framenum))
3254                 return;
3255
3256         prev_dis_num = framenum - 1;
3257         if (tok_prev_frame && (!ws_strtou32(tok_prev_frame, NULL, &prev_dis_num) || prev_dis_num >= framenum))
3258                 return;
3259
3260         sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, &sharkd_session_process_frame_cb, tok_bytes, tok_columns, tok_proto, NULL);
3261 }
3262
3263 /**
3264  * sharkd_session_process_check()
3265  *
3266  * Process check request.
3267  *
3268  * Input:
3269  *   (o) filter - filter to be checked
3270  *
3271  * Output object with attributes:
3272  *   (m) err - always 0
3273  *   (o) filter - 'ok', 'warn' or error message
3274  */
3275 static int
3276 sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
3277 {
3278         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3279
3280         printf("{\"err\":0");
3281         if (tok_filter != NULL)
3282         {
3283                 char *err_msg = NULL;
3284                 dfilter_t *dfp;
3285
3286                 if (dfilter_compile(tok_filter, &dfp, &err_msg))
3287                 {
3288                         const char *s = "ok";
3289
3290                         if (dfilter_deprecated_tokens(dfp))
3291                                 s = "warn";
3292
3293                         printf(",\"filter\":\"%s\"", s);
3294                         dfilter_free(dfp);
3295                 }
3296                 else
3297                 {
3298                         printf(",\"filter\":");
3299                         json_puts_string(err_msg);
3300                         g_free(err_msg);
3301                 }