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