checkAPIs.pl: improve value_string validation in field definitions
[metze/wireshark/wip.git] / sharkd_session.c
1 /* sharkd_session.c
2  *
3  * Copyright (C) 2016 Jakub Zawadzki
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include <config.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18
19 #include <glib.h>
20
21 #include <wsutil/wsjson.h>
22 #include <wsutil/ws_printf.h>
23
24 #include <file.h>
25 #include <epan/epan_dissect.h>
26 #include <epan/exceptions.h>
27 #include <epan/color_filters.h>
28 #include <epan/prefs.h>
29 #include <epan/prefs-int.h>
30 #include <epan/uat-int.h>
31 #include <wiretap/wtap.h>
32
33 #include <epan/column.h>
34
35 #include <ui/ssl_key_export.h>
36
37 #include <ui/io_graph_item.h>
38 #include <epan/stats_tree_priv.h>
39 #include <epan/stat_tap_ui.h>
40 #include <epan/conversation_table.h>
41 #include <epan/sequence_analysis.h>
42 #include <epan/expert.h>
43 #include <epan/export_object.h>
44 #include <epan/follow.h>
45 #include <epan/rtd_table.h>
46 #include <epan/srt_table.h>
47
48 #include <epan/dissectors/packet-h225.h>
49 #include <epan/rtp_pt.h>
50 #include <ui/voip_calls.h>
51 #include <ui/rtp_stream.h>
52 #include <ui/tap-rtp-common.h>
53 #include <ui/tap-rtp-analysis.h>
54 #include <epan/to_str.h>
55
56 #include <epan/addr_resolv.h>
57 #include <epan/dissectors/packet-rtp.h>
58 #include <ui/rtp_media.h>
59 #ifdef HAVE_SPEEXDSP
60 # include <speex/speex_resampler.h>
61 #else
62 # include <codecs/speex/speex_resampler.h>
63 #endif /* HAVE_SPEEXDSP */
64
65 #include <epan/maxmind_db.h>
66
67 #include <wsutil/pint.h>
68 #include <wsutil/strtoi.h>
69
70 #include "globals.h"
71
72 #include "sharkd.h"
73
74 struct sharkd_filter_item
75 {
76         guint8 *filtered; /* 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_calc_t calc;
2085                 rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
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                 {
2683                         printf(",\"g\":true");
2684                 }
2685
2686                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
2687                 {
2688                         printf(",\"v\":true");
2689                 }
2690
2691                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2692                 {
2693                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2694
2695                         g_assert(severity != NULL);
2696
2697                         printf(",\"s\":\"%s\"", severity);
2698                 }
2699
2700                 if (((proto_tree *) node)->first_child)
2701                 {
2702                         if (finfo->tree_type != -1)
2703                                 printf(",\"e\":%d", finfo->tree_type);
2704                         printf(",\"n\":");
2705                         sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs, display_hidden);
2706                 }
2707
2708                 printf("}");
2709                 sepa = ",";
2710         }
2711         printf("]");
2712 }
2713
2714 static gboolean
2715 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2716 {
2717         register_follow_t *follower = (register_follow_t *) value;
2718         packet_info *pi = (packet_info *) user_data;
2719
2720         const int proto_id = get_follow_proto_id(follower);
2721
2722         guint32 ignore_stream;
2723
2724         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2725         {
2726                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2727                 char *follow_filter;
2728
2729                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2730
2731                 printf(",[\"%s\",", layer_proto);
2732                 json_puts_string(follow_filter);
2733                 printf("]");
2734
2735                 g_free(follow_filter);
2736         }
2737
2738         return FALSE;
2739 }
2740
2741 struct sharkd_frame_request_data
2742 {
2743         gboolean display_hidden;
2744 };
2745
2746 static void
2747 sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2748 {
2749         packet_info *pi = &edt->pi;
2750         frame_data *fdata = pi->fd;
2751         const char *pkt_comment = NULL;
2752
2753         const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data;
2754         const gboolean display_hidden = (req_data) ? req_data->display_hidden : FALSE;
2755         printf("{");
2756
2757         printf("\"err\":0");
2758
2759         if (fdata->flags.has_user_comment)
2760                 pkt_comment = sharkd_get_user_comment(fdata);
2761         else if (fdata->flags.has_phdr_comment)
2762                 pkt_comment = pi->rec->opt_comment;
2763
2764         if (pkt_comment)
2765         {
2766                 printf(",\"comment\":");
2767                 json_puts_string(pkt_comment);
2768         }
2769
2770         if (tree)
2771         {
2772                 tvbuff_t **tvbs = NULL;
2773
2774                 printf(",\"tree\":");
2775
2776                 /* arrayize data src, to speedup searching for ds_tvb index */
2777                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2778                 {
2779                         guint count = g_slist_length((GSList *) data_src);
2780                         guint i;
2781
2782                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2783
2784                         for (i = 0; i < count; i++)
2785                         {
2786                                 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2787
2788                                 tvbs[i] = get_data_source_tvb(src);
2789                         }
2790
2791                         tvbs[count] = NULL;
2792                 }
2793
2794                 sharkd_session_process_frame_cb_tree(edt, tree, tvbs, display_hidden);
2795
2796                 g_free(tvbs);
2797         }
2798
2799         if (cinfo)
2800         {
2801                 int col;
2802
2803                 printf(",\"col\":[");
2804                 for (col = 0; col < cinfo->num_cols; ++col)
2805                 {
2806                         const col_item_t *col_item = &cinfo->columns[col];
2807
2808                         printf("%s\"%s\"", (col) ? "," : "", col_item->col_data);
2809                 }
2810                 printf("]");
2811         }
2812
2813         if (fdata->flags.ignored)
2814                 printf(",\"i\":true");
2815
2816         if (fdata->flags.marked)
2817                 printf(",\"m\":true");
2818
2819         if (fdata->color_filter)
2820         {
2821                 printf(",\"bg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->bg_color));
2822                 printf(",\"fg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->fg_color));
2823         }
2824
2825         if (data_src)
2826         {
2827                 struct data_source *src = (struct data_source *) data_src->data;
2828                 const char *ds_sepa = NULL;
2829
2830                 tvbuff_t *tvb;
2831                 guint length;
2832
2833                 tvb = get_data_source_tvb(src);
2834                 length = tvb_captured_length(tvb);
2835
2836                 printf(",\"bytes\":");
2837                 if (length != 0)
2838                 {
2839                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2840
2841                         /* XXX pi.fd->flags.encoding */
2842                         json_print_base64(cp, length);
2843                 }
2844                 else
2845                 {
2846                         json_print_base64("", 0);
2847                 }
2848
2849                 data_src = data_src->next;
2850                 if (data_src)
2851                 {
2852                         printf(",\"ds\":[");
2853                         ds_sepa = "";
2854                 }
2855
2856                 while (data_src)
2857                 {
2858                         src = (struct data_source *) data_src->data;
2859
2860                         {
2861                                 char *src_name = get_data_source_name(src);
2862
2863                                 printf("%s{\"name\":", ds_sepa);
2864                                 json_puts_string(src_name);
2865                                 wmem_free(NULL, src_name);
2866                         }
2867
2868                         tvb = get_data_source_tvb(src);
2869                         length = tvb_captured_length(tvb);
2870
2871                         printf(",\"bytes\":");
2872                         if (length != 0)
2873                         {
2874                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
2875
2876                                 /* XXX pi.fd->flags.encoding */
2877                                 json_print_base64(cp, length);
2878                         }
2879                         else
2880                         {
2881                                 json_print_base64("", 0);
2882                         }
2883
2884                         printf("}");
2885                         ds_sepa = ",";
2886
2887                         data_src = data_src->next;
2888                 }
2889
2890                 /* close ds, only if was opened */
2891                 if (ds_sepa != NULL)
2892                         printf("]");
2893         }
2894
2895         printf(",\"fol\":[0");
2896         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
2897         printf("]");
2898
2899         printf("}\n");
2900 }
2901
2902 #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 */
2903
2904 struct sharkd_iograph
2905 {
2906         /* config */
2907         int hf_index;
2908         io_graph_item_unit_t calc_type;
2909         guint32 interval;
2910
2911         /* result */
2912         int space_items;
2913         int num_items;
2914         io_graph_item_t *items;
2915         GString *error;
2916 };
2917
2918 static gboolean
2919 sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_)
2920 {
2921         struct sharkd_iograph *graph = (struct sharkd_iograph *) g;
2922         int idx;
2923
2924         idx = get_io_graph_index(pinfo, graph->interval);
2925         if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS)
2926                 return FALSE;
2927
2928         if (idx + 1 > graph->num_items)
2929         {
2930                 if (idx + 1 > graph->space_items)
2931                 {
2932                         int new_size = idx + 1024;
2933
2934                         graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size);
2935                         reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items);
2936
2937                         graph->space_items = new_size;
2938                 }
2939                 else if (graph->items == NULL)
2940                 {
2941                         graph->items = (io_graph_item_t *) g_malloc(sizeof(io_graph_item_t) * graph->space_items);
2942                         reset_io_graph_items(graph->items, graph->space_items);
2943                 }
2944
2945                 graph->num_items = idx + 1;
2946         }
2947
2948         return update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval);
2949 }
2950
2951 /**
2952  * sharkd_session_process_iograph()
2953  *
2954  * Process iograph request
2955  *
2956  * Input:
2957  *   (o) interval - interval time in ms, if not specified: 1000ms
2958  *   (m) graph0             - First graph request
2959  *   (o) graph1...graph9    - Other graph requests
2960  *   (o) filter0            - First graph filter
2961  *   (o) filter1...filter9  - Other graph filters
2962  *
2963  * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>",
2964  * if you use variant with <field>, you need to pass field name in filter request.
2965  *
2966  * Output object with attributes:
2967  *   (m) iograph - array of graph results with attributes:
2968  *                  errmsg - graph cannot be constructed
2969  *                  items  - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string
2970  */
2971 static void
2972 sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count)
2973 {
2974         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
2975         struct sharkd_iograph graphs[10];
2976         gboolean is_any_ok = FALSE;
2977         int graph_count;
2978
2979         guint32 interval_ms = 1000; /* default: one per second */
2980         int i;
2981
2982         if (tok_interval)
2983         {
2984                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
2985                 {
2986                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
2987                         return;
2988                 }
2989         }
2990
2991         for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++)
2992         {
2993                 struct sharkd_iograph *graph = &graphs[graph_count];
2994
2995                 const char *tok_graph;
2996                 const char *tok_filter;
2997                 char tok_format_buf[32];
2998                 const char *field_name;
2999
3000                 snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i);
3001                 tok_graph = json_find_attr(buf, tokens, count, tok_format_buf);
3002                 if (!tok_graph)
3003                         break;
3004
3005                 snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i);
3006                 tok_filter = json_find_attr(buf, tokens, count, tok_format_buf);
3007
3008                 if (!strcmp(tok_graph, "packets"))
3009                         graph->calc_type = IOG_ITEM_UNIT_PACKETS;
3010                 else if (!strcmp(tok_graph, "bytes"))
3011                         graph->calc_type = IOG_ITEM_UNIT_BYTES;
3012                 else if (!strcmp(tok_graph, "bits"))
3013                         graph->calc_type = IOG_ITEM_UNIT_BITS;
3014                 else if (g_str_has_prefix(tok_graph, "sum:"))
3015                         graph->calc_type = IOG_ITEM_UNIT_CALC_SUM;
3016                 else if (g_str_has_prefix(tok_graph, "frames:"))
3017                         graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES;
3018                 else if (g_str_has_prefix(tok_graph, "fields:"))
3019                         graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS;
3020                 else if (g_str_has_prefix(tok_graph, "max:"))
3021                         graph->calc_type = IOG_ITEM_UNIT_CALC_MAX;
3022                 else if (g_str_has_prefix(tok_graph, "min:"))
3023                         graph->calc_type = IOG_ITEM_UNIT_CALC_MIN;
3024                 else if (g_str_has_prefix(tok_graph, "avg:"))
3025                         graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE;
3026                 else if (g_str_has_prefix(tok_graph, "load:"))
3027                         graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD;
3028                 else
3029                         break;
3030
3031                 field_name = strchr(tok_graph, ':');
3032                 if (field_name)
3033                         field_name = field_name + 1;
3034
3035                 graph->interval = interval_ms;
3036
3037                 graph->hf_index = -1;
3038                 graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type);
3039
3040                 graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */
3041                 graph->num_items = 0;
3042                 graph->items = NULL;
3043
3044                 if (!graph->error)
3045                         graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL, NULL);
3046
3047                 graph_count++;
3048
3049                 if (graph->error == NULL)
3050                         is_any_ok = TRUE;
3051         }
3052
3053         /* retap only if we have at least one ok */
3054         if (is_any_ok)
3055                 sharkd_retap();
3056
3057         printf("{\"iograph\":[");
3058
3059         for (i = 0; i < graph_count; i++)
3060         {
3061                 struct sharkd_iograph *graph = &graphs[i];
3062
3063                 if (i)
3064                         printf(",");
3065                 printf("{");
3066
3067                 if (graph->error)
3068                 {
3069                         printf("\"errmsg\":");
3070                         json_puts_string(graph->error->str);
3071                         g_string_free(graph->error, TRUE);
3072                 }
3073                 else
3074                 {
3075                         int idx;
3076                         int next_idx = 0;
3077                         const char *sepa = "";
3078
3079                         printf("\"items\":[");
3080                         for (idx = 0; idx < graph->num_items; idx++)
3081                         {
3082                                 double val;
3083
3084                                 val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items);
3085
3086                                 /* if it's zero, don't display */
3087                                 if (val == 0.0)
3088                                         continue;
3089
3090                                 printf("%s", sepa);
3091
3092                                 /* cause zeros are not printed, need to output index */
3093                                 if (next_idx != idx)
3094                                         printf("\"%x\",", idx);
3095
3096                                 printf("%f", val);
3097                                 next_idx = idx + 1;
3098                                 sepa = ",";
3099                         }
3100                         printf("]");
3101                 }
3102                 printf("}");
3103
3104                 remove_tap_listener(graph);
3105                 g_free(graph->items);
3106         }
3107
3108         printf("]}\n");
3109 }
3110
3111 /**
3112  * sharkd_session_process_intervals()
3113  *
3114  * Process intervals request - generate basic capture file statistics per requested interval.
3115  *
3116  * Input:
3117  *   (o) interval - interval time in ms, if not specified: 1000ms
3118  *   (o) filter   - filter for generating interval request
3119  *
3120  * Output object with attributes:
3121  *   (m) intervals - array of intervals, with indexes:
3122  *             [0] - index of interval,
3123  *             [1] - number of frames during interval,
3124  *             [2] - number of bytes during interval.
3125  *
3126  *   (m) last   - last interval number.
3127  *   (m) frames - total number of frames
3128  *   (m) bytes  - total number of bytes
3129  *
3130  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
3131  */
3132 static void
3133 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
3134 {
3135         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3136         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3137
3138         const guint8 *filter_data = NULL;
3139
3140         struct
3141         {
3142                 unsigned int frames;
3143                 guint64 bytes;
3144         } st, st_total;
3145
3146         nstime_t *start_ts;
3147
3148         guint32 interval_ms = 1000; /* default: one per second */
3149
3150         const char *sepa = "";
3151         unsigned int framenum;
3152         gint64 idx;
3153         gint64 max_idx = 0;
3154
3155         if (tok_interval)
3156         {
3157                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3158                 {
3159                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3160                         return;
3161                 }
3162         }
3163
3164         if (tok_filter)
3165         {
3166                 const struct sharkd_filter_item *filter_item;
3167
3168                 filter_item = sharkd_session_filter_data(tok_filter);
3169                 if (!filter_item)
3170                         return;
3171                 filter_data = filter_item->filtered;
3172         }
3173
3174         st_total.frames = 0;
3175         st_total.bytes  = 0;
3176
3177         st.frames = 0;
3178         st.bytes  = 0;
3179
3180         idx = 0;
3181
3182         printf("{\"intervals\":[");
3183
3184         start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL;
3185
3186         for (framenum = 1; framenum <= cfile.count; framenum++)
3187         {
3188                 frame_data *fdata;
3189                 gint64 msec_rel;
3190                 gint64 new_idx;
3191
3192                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
3193                         continue;
3194
3195                 fdata = sharkd_get_frame(framenum);
3196
3197                 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
3198                 new_idx  = msec_rel / interval_ms;
3199
3200                 if (idx != new_idx)
3201                 {
3202                         if (st.frames != 0)
3203                         {
3204                                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
3205                                 sepa = ",";
3206                         }
3207
3208                         idx = new_idx;
3209                         if (idx > max_idx)
3210                                 max_idx = idx;
3211
3212                         st.frames = 0;
3213                         st.bytes  = 0;
3214                 }
3215
3216                 st.frames += 1;
3217                 st.bytes  += fdata->pkt_len;
3218
3219                 st_total.frames += 1;
3220                 st_total.bytes  += fdata->pkt_len;
3221         }
3222
3223         if (st.frames != 0)
3224         {
3225                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
3226                 /* sepa = ","; */
3227         }
3228
3229         printf("],\"last\":%" G_GINT64_FORMAT ",\"frames\":%u,\"bytes\":%" G_GUINT64_FORMAT "}\n", max_idx, st_total.frames, st_total.bytes);
3230 }
3231
3232 /**
3233  * sharkd_session_process_frame()
3234  *
3235  * Process frame request
3236  *
3237  * Input:
3238  *   (m) frame - requested frame number
3239  *   (o) ref_frame - time reference frame number
3240  *   (o) prev_frame - previously displayed frame number
3241  *   (o) proto - set if output frame tree
3242  *   (o) columns - set if output frame columns
3243  *   (o) color - set if output color-filter bg/fg
3244  *   (o) bytes - set if output frame bytes
3245  *   (o) hidden - set if output hidden tree fields
3246  *
3247  * Output object with attributes:
3248  *   (m) err   - 0 if succeed
3249  *   (o) tree  - array of frame nodes with attributes:
3250  *                  l - label
3251  *                  t: 'proto', 'framenum', 'url' - type of node
3252  *                  f - filter string
3253  *                  s - severity
3254  *                  e - subtree ett index
3255  *                  n - array of subtree nodes
3256  *                  h - two item array: (item start, item length)
3257  *                  i - two item array: (appendix start, appendix length)
3258  *                  p - [RESERVED] two item array: (protocol start, protocol length)
3259  *                  ds- data src index
3260  *                  url  - only for t:'url', url
3261  *                  fnum - only for t:'framenum', frame number
3262  *                  g - if field is generated by Wireshark
3263  *                  v - if field is hidden
3264  *
3265  *   (o) col   - array of column data
3266  *   (o) bytes - base64 of frame bytes
3267  *   (o) ds    - array of other data srcs
3268  *   (o) comment - frame comment
3269  *   (o) fol   - array of follow filters:
3270  *                  [0] - protocol
3271  *                  [1] - filter string
3272  *   (o) i   - if frame is ignored
3273  *   (o) m   - if frame is marked
3274  *   (o) bg  - color filter - background color in hex
3275  *   (o) fg  - color filter - foreground color in hex
3276  */
3277 static void
3278 sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
3279 {
3280         const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
3281         const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame");
3282         const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame");
3283         guint32 framenum, ref_frame_num, prev_dis_num;
3284         guint32 dissect_flags = SHARKD_DISSECT_FLAG_NULL;
3285         if (json_find_attr(buf, tokens, count, "proto") != NULL)
3286                 dissect_flags |= SHARKD_DISSECT_FLAG_PROTO_TREE;
3287         if (json_find_attr(buf, tokens, count, "bytes") != NULL)
3288                 dissect_flags |= SHARKD_DISSECT_FLAG_BYTES;
3289         if (json_find_attr(buf, tokens, count, "columns") != NULL)
3290                 dissect_flags |= SHARKD_DISSECT_FLAG_COLUMNS;
3291         if (json_find_attr(buf, tokens, count, "color") != NULL)
3292                 dissect_flags |= SHARKD_DISSECT_FLAG_COLOR;
3293
3294         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3295                 return;
3296
3297         ref_frame_num = (framenum != 1) ? 1 : 0;
3298         if (tok_ref_frame && (!ws_strtou32(tok_ref_frame, NULL, &ref_frame_num) || ref_frame_num > framenum))
3299                 return;
3300
3301         prev_dis_num = framenum - 1;
3302         if (tok_prev_frame && (!ws_strtou32(tok_prev_frame, NULL, &prev_dis_num) || prev_dis_num >= framenum))
3303                 return;
3304
3305         struct sharkd_frame_request_data req_data;
3306         req_data.display_hidden = (json_find_attr(buf, tokens, count, "v") != NULL);
3307
3308         sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, &sharkd_session_process_frame_cb, dissect_flags, &req_data);
3309 }
3310
3311 /**
3312  * sharkd_session_process_check()
3313  *
3314  * Process check request.
3315  *
3316  * Input:
3317  *   (o) filter - filter to be checked
3318  *
3319  * Output object with attributes:
3320  *   (m) err - always 0
3321  *   (o) filter - 'ok', 'warn' or error message
3322  */
3323 static int
3324 sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
3325 {
3326         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3327
3328         printf("{\"err\":0");
3329         if (tok_filter != NULL)
3330         {
3331                 char *err_msg = NULL;
3332                 dfilter_t *dfp;
3333
3334                 if (dfilter_compile(tok_filter, &dfp, &err_msg))
3335                 {
3336                         const char *s = "ok";
3337
3338                         if (dfilter_deprecated_tokens(dfp))
3339                                 s = "warn";
3340
3341                         printf(",\"filter\":\"%s\"", s);
3342                         dfilter_free(dfp);
3343                 }
3344                 else
3345                 {
3346                         printf(",\"filter\":");
3347                         json_puts_string(err_msg);
3348                         g_free(err_msg);
3349                 }
3350         }
3351
3352         printf("}\n");
3353         return 0;
3354 }
3355
3356 struct sharkd_session_process_complete_pref_data
3357 {
3358         const char *module;
3359         const char *pref;
3360         const char *sepa;
3361 };
3362
3363 static guint
3364 sharkd_session_process_complete_pref_cb(module_t *module, gpointer d)
3365 {
3366         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3367
3368         if (strncmp(data->pref, module->name, strlen(data->pref)) != 0)
3369                 return 0;
3370
3371         printf("%s{\"f\":\"%s\",\"d\":\"%s\"}", data->sepa, module->name, module->title);
3372         data->sepa = ",";
3373
3374         return 0;
3375 }
3376
3377 static guint
3378 sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d)
3379 {
3380         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3381         const char *pref_name = prefs_get_name(pref);
3382         const char *pref_title = prefs_get_title(pref);
3383
3384         if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0)
3385                 return 0;
3386
3387         printf("%s{\"f\":\"%s.%s\",\"d\":\"%s\"}", data->sepa, data->module, pref_name, pref_title);
3388         data->sepa = ",";
3389
3390         return 0; /* continue */
3391 }
3392
3393 /**
3394  * sharkd_session_process_complete()
3395  *
3396  * Process complete request
3397  *
3398  * Input:
3399  *   (o) field - field to be completed
3400  *   (o) pref  - preference to be completed
3401  *
3402  * Output object with attributes:
3403  *   (m) err - always 0
3404  *   (o) field - array of object with attributes:
3405  *                  (m) f - field text
3406  *                  (o) t - field type (FT_ number)
3407  *                  (o) n - field name
3408  *   (o) pref  - array of object with attributes:
3409  *                  (m) f - pref name
3410  *                  (o) d - pref description
3411  */
3412 static int
3413 sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count)
3414 {
3415         const char *tok_field = json_find_attr(buf, tokens, count, "field");
3416         const char *tok_pref  = json_find_attr(buf, tokens, count, "pref");
3417
3418         printf("{\"err\":0");
3419         if (tok_field != NULL && tok_field[0])
3420         {
3421                 const size_t filter_length = strlen(tok_field);
3422                 const int filter_with_dot = !!strchr(tok_field, '.');
3423
3424                 void *proto_cookie;
3425                 void *field_cookie;
3426                 int proto_id;
3427                 const char *sepa = "";
3428
3429                 printf(",\"field\":[");
3430
3431                 for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie))
3432                 {
3433                         protocol_t *protocol = find_protocol_by_id(proto_id);
3434                         const char *protocol_filter;
3435                         const char *protocol_name;
3436                         header_field_info *hfinfo;
3437
3438                         if (!proto_is_protocol_enabled(protocol))
3439                                 continue;
3440
3441                         protocol_name   = proto_get_protocol_long_name(protocol);
3442                         protocol_filter = proto_get_protocol_filter_name(proto_id);
3443
3444                         if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length))
3445                         {
3446                                 printf("%s{", sepa);
3447                                 {
3448                                         printf("\"f\":");
3449                                         json_puts_string(protocol_filter);
3450                                         printf(",\"t\":%d", FT_PROTOCOL);
3451                                         printf(",\"n\":");
3452                                         json_puts_string(protocol_name);
3453                                 }
3454                                 printf("}");
3455                                 sepa = ",";
3456                         }
3457
3458                         if (!filter_with_dot)
3459                                 continue;
3460
3461                         for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie))
3462                         {
3463                                 if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
3464                                         continue;
3465
3466                                 if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length))
3467                                 {
3468                                         printf("%s{", sepa);
3469                                         {
3470                                                 printf("\"f\":");
3471                                                 json_puts_string(hfinfo->abbrev);
3472
3473                                                 /* XXX, skip displaying name, if there are multiple (to not confuse user) */
3474                                                 if (hfinfo->same_name_next == NULL)
3475                                                 {
3476                                                         printf(",\"t\":%d", hfinfo->type);
3477                                                         printf(",\"n\":");
3478                                                         json_puts_string(hfinfo->name);
3479                                                 }
3480                                         }
3481                                         printf("}");
3482                                         sepa = ",";
3483                                 }
3484                         }
3485                 }
3486
3487                 printf("]");
3488         }
3489
3490         if (tok_pref != NULL && tok_pref[0])
3491         {
3492                 struct sharkd_session_process_complete_pref_data data;
3493                 char *dot_sepa;
3494
3495                 data.module = tok_pref;
3496                 data.pref = tok_pref;
3497                 data.sepa = "";
3498
3499                 printf(",\"pref\":[");
3500
3501                 if ((dot_sepa = strchr(tok_pref, '.')))
3502                 {
3503                         module_t *pref_mod;
3504
3505                         *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3506                         data.pref = dot_sepa + 1;
3507
3508                         pref_mod = prefs_find_module(data.module);
3509                         if (pref_mod)
3510                                 prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data);
3511
3512                         *dot_sepa = '.';
3513                 }
3514                 else
3515                 {
3516                         prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data);
3517                 }
3518
3519                 printf("]");
3520         }
3521
3522
3523         printf("}\n");
3524         return 0;
3525 }
3526
3527 /**
3528  * sharkd_session_process_setcomment()
3529  *
3530  * Process setcomment request
3531  *
3532  * Input:
3533  *   (m) frame - frame number
3534  *   (o) comment - user comment
3535  *
3536  * Output object with attributes:
3537  *   (m) err   - error code: 0 succeed
3538  */
3539 static void
3540 sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count)
3541 {
3542         const char *tok_frame   = json_find_attr(buf, tokens, count, "frame");
3543         const char *tok_comment = json_find_attr(buf, tokens, count, "comment");
3544
3545         guint32 framenum;
3546         frame_data *fdata;
3547         int ret;
3548
3549         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3550                 return;
3551
3552         fdata = sharkd_get_frame(framenum);
3553         if (!fdata)
3554                 return;
3555
3556         ret = sharkd_set_user_comment(fdata, tok_comment);
3557         printf("{\"err\":%d}\n", ret);
3558 }
3559
3560 /**
3561  * sharkd_session_process_setconf()
3562  *
3563  * Process setconf request
3564  *
3565  * Input:
3566  *   (m) name  - preference name
3567  *   (m) value - preference value
3568  *
3569  * Output object with attributes:
3570  *   (m) err   - error code: 0 succeed
3571  */
3572 static void
3573 sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count)
3574 {
3575         const char *tok_name = json_find_attr(buf, tokens, count, "name");
3576         const char *tok_value = json_find_attr(buf, tokens, count, "value");
3577         char pref[4096];
3578         char *errmsg = NULL;
3579
3580         prefs_set_pref_e ret;
3581
3582         if (!tok_name || tok_name[0] == '\0' || !tok_value)
3583                 return;
3584
3585         ws_snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value);
3586
3587         ret = prefs_set_pref(pref, &errmsg);
3588         printf("{\"err\":%d", ret);
3589         if (errmsg)
3590         {
3591                 /* Add error message for some syntax errors. */
3592                 printf(",\"errmsg\":");
3593                 json_puts_string(errmsg);
3594         }
3595         printf("}\n");
3596         g_free(errmsg);
3597 }
3598
3599 struct sharkd_session_process_dumpconf_data
3600 {
3601         module_t *module;
3602         const char *sepa;
3603 };
3604
3605 static guint
3606 sharkd_session_process_dumpconf_cb(pref_t *pref, gpointer d)
3607 {
3608         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3609         const char *pref_name = prefs_get_name(pref);
3610
3611         printf("%s\"%s.%s\":{", data->sepa, data->module->name, pref_name);
3612
3613         switch (prefs_get_type(pref))
3614         {
3615                 case PREF_UINT:
3616                 case PREF_DECODE_AS_UINT:
3617                         printf("\"u\":%u", prefs_get_uint_value_real(pref, pref_current));
3618                         if (prefs_get_uint_base(pref) != 10)
3619                                 printf(",\"ub\":%u", prefs_get_uint_base(pref));
3620                         break;
3621
3622                 case PREF_BOOL:
3623                         printf("\"b\":%s", prefs_get_bool_value(pref, pref_current) ? "1" : "0");
3624                         break;
3625
3626                 case PREF_STRING:
3627                 case PREF_SAVE_FILENAME:
3628                 case PREF_OPEN_FILENAME:
3629                 case PREF_DIRNAME:
3630                         printf("\"s\":");
3631                         json_puts_string(prefs_get_string_value(pref, pref_current));
3632                         break;
3633
3634                 case PREF_ENUM:
3635                 {
3636                         const enum_val_t *enums;
3637                         const char *enum_sepa = "";
3638
3639                         printf("\"e\":[");
3640                         for (enums = prefs_get_enumvals(pref); enums->name; enums++)
3641                         {
3642                                 printf("%s{\"v\":%d", enum_sepa, enums->value);
3643
3644                                 if (enums->value == prefs_get_enum_value(pref, pref_current))
3645                                         printf(",\"s\":1");
3646
3647                                 printf(",\"d\":");
3648                                 json_puts_string(enums->description);
3649
3650                                 printf("}");
3651                                 enum_sepa = ",";
3652                         }
3653                         printf("]");
3654                         break;
3655                 }
3656
3657                 case PREF_RANGE:
3658                 case PREF_DECODE_AS_RANGE:
3659                 {
3660                         char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
3661                         printf("\"r\":\"%s\"", range_str);
3662                         wmem_free(NULL, range_str);
3663                         break;
3664                 }
3665
3666                 case PREF_UAT:
3667                 {
3668                         uat_t *uat = prefs_get_uat_value(pref);
3669                         guint idx;
3670
3671                         printf("\"t\":[");
3672                         for (idx = 0; idx < uat->raw_data->len; idx++)
3673                         {
3674                                 void *rec = UAT_INDEX_PTR(uat, idx);
3675                                 guint colnum;
3676
3677                                 if (idx)
3678                                         printf(",");
3679
3680                                 printf("[");
3681                                 for (colnum = 0; colnum < uat->ncols; colnum++)
3682                                 {
3683                                         char *str = uat_fld_tostr(rec, &(uat->fields[colnum]));
3684
3685                                         if (colnum)
3686                                                 printf(",");
3687
3688                                         json_puts_string(str);
3689                                         g_free(str);
3690                                 }
3691
3692                                 printf("]");
3693                         }
3694
3695                         printf("]");
3696                         break;
3697                 }
3698
3699                 case PREF_COLOR:
3700                 case PREF_CUSTOM:
3701                 case PREF_STATIC_TEXT:
3702                 case PREF_OBSOLETE:
3703                         /* TODO */
3704                         break;
3705         }
3706
3707 #if 0
3708         printf(",\"t\":");
3709         json_puts_string(prefs_get_title(pref));
3710 #endif
3711
3712         printf("}");
3713         data->sepa = ",";
3714
3715         return 0; /* continue */
3716 }
3717
3718 static guint
3719 sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d)
3720 {
3721         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3722
3723         data->module = module;
3724         prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data);
3725
3726         return 0;
3727 }
3728
3729 /**
3730  * sharkd_session_process_dumpconf()
3731  *
3732  * Process dumpconf request
3733  *
3734  * Input:
3735  *   (o) pref - module, or preference, NULL for all
3736  *
3737  * Output object with attributes:
3738  *   (o) prefs   - object with module preferences
3739  *                  (m) [KEY] - preference name
3740  *                  (o) u - preference value (for PREF_UINT, PREF_DECODE_AS_UINT)
3741  *                  (o) ub - preference value suggested base for display (for PREF_UINT, PREF_DECODE_AS_UINT) and if different than 10
3742  *                  (o) b - preference value (only for PREF_BOOL) (1 true, 0 false)
3743  *                  (o) s - preference value (for PREF_STRING, PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME)
3744  *                  (o) e - preference possible values (only for PREF_ENUM)
3745  *                  (o) r - preference value (for PREF_RANGE, PREF_DECODE_AS_RANGE)
3746  *                  (o) t - preference value (only for PREF_UAT)
3747  */
3748 static void
3749 sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
3750 {
3751         const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
3752         module_t *pref_mod;
3753         char *dot_sepa;
3754
3755         if (!tok_pref)
3756         {
3757                 struct sharkd_session_process_dumpconf_data data;
3758
3759                 data.module = NULL;
3760                 data.sepa = "";
3761
3762                 printf("{\"prefs\":{");
3763                 prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data);
3764                 printf("}}\n");
3765                 return;
3766         }
3767
3768         if ((dot_sepa = strchr(tok_pref, '.')))
3769         {
3770                 pref_t *pref = NULL;
3771
3772                 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3773                 pref_mod = prefs_find_module(tok_pref);
3774                 if (pref_mod)
3775                         pref = prefs_find_preference(pref_mod, dot_sepa + 1);
3776                 *dot_sepa = '.';
3777
3778                 if (pref)
3779                 {
3780                         struct sharkd_session_process_dumpconf_data data;
3781
3782                         data.module = pref_mod;
3783                         data.sepa = "";
3784
3785                         printf("{\"prefs\":{");
3786                         sharkd_session_process_dumpconf_cb(pref, &data);
3787                         printf("}}\n");
3788                 }
3789
3790                 return;
3791         }
3792
3793         pref_mod = prefs_find_module(tok_pref);
3794         if (pref_mod)
3795         {
3796                 struct sharkd_session_process_dumpconf_data data;
3797
3798                 data.module = pref_mod;
3799                 data.sepa = "";
3800
3801                 printf("{\"prefs\":{");
3802                 prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data);
3803                 printf("}}\n");
3804         }
3805 }
3806
3807 struct sharkd_download_rtp
3808 {
3809         rtpstream_id_t id;
3810         GSList *packets;
3811         double start_time;
3812 };
3813
3814 static void
3815 sharkd_rtp_download_free_items(void *ptr)
3816 {
3817         rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr;
3818
3819         g_free(rtp_packet->info);
3820         g_free(rtp_packet->payload_data);
3821         g_free(rtp_packet);
3822 }
3823
3824 static void
3825 sharkd_rtp_download_decode(struct sharkd_download_rtp *req)
3826 {
3827         /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */
3828         /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */
3829
3830         static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char);
3831
3832         guint32 audio_out_rate_ = 0;
3833         struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new();
3834         struct SpeexResamplerState_ *audio_resampler_ = NULL;
3835
3836         gsize resample_buff_len = 0x1000;
3837         SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len);
3838         spx_uint32_t cur_in_rate = 0;
3839         char *write_buff = NULL;
3840         gint64 write_bytes = 0;
3841         unsigned channels = 0;
3842         unsigned sample_rate = 0;
3843
3844         int i;
3845         int base64_state1 = 0;
3846         int base64_state2 = 0;
3847
3848         GSList *l;
3849
3850         for (l = req->packets; l; l = l->next)
3851         {
3852                 rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data;
3853
3854                 SAMPLE *decode_buff = NULL;
3855                 size_t decoded_bytes;
3856
3857                 decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate);
3858                 if (decoded_bytes == 0 || sample_rate == 0)
3859                 {
3860                         /* We didn't decode anything. Clean up and prep for the next packet. */
3861                         g_free(decode_buff);
3862                         continue;
3863                 }
3864
3865                 if (audio_out_rate_ == 0)
3866                 {
3867                         guint32 tmp32;
3868                         guint16 tmp16;
3869                         char wav_hdr[44];
3870
3871                         /* First non-zero wins */
3872                         audio_out_rate_ = sample_rate;
3873
3874                         RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_);
3875
3876                         /* write WAVE header */
3877                         memset(&wav_hdr, 0, sizeof(wav_hdr));
3878                         memcpy(&wav_hdr[0], "RIFF", 4);
3879                         memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
3880                         memcpy(&wav_hdr[8], "WAVE", 4);
3881
3882                         memcpy(&wav_hdr[12], "fmt ", 4);
3883                         memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */
3884                         memcpy(&wav_hdr[20], "\x01\x00", 2);         /* PCM */
3885                         /* # channels */
3886                         tmp16 = channels;
3887                         memcpy(&wav_hdr[22], &tmp16, 2);
3888                         /* sample rate */
3889                         tmp32 = sample_rate;
3890                         memcpy(&wav_hdr[24], &tmp32, 4);
3891                         /* byte rate */
3892                         tmp32 = sample_rate * channels * sample_bytes_;
3893                         memcpy(&wav_hdr[28], &tmp32, 4);
3894                         /* block align */
3895                         tmp16 = channels * sample_bytes_;
3896                         memcpy(&wav_hdr[32], &tmp16, 2);
3897                         /* bits per sample */
3898                         tmp16 = 8 * sample_bytes_;
3899                         memcpy(&wav_hdr[34], &tmp16, 2);
3900
3901                         memcpy(&wav_hdr[36], "data", 4);
3902                         memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
3903
3904                         for (i = 0; i < (int) sizeof(wav_hdr); i++)
3905                                 json_print_base64_step(&wav_hdr[i], &base64_state1, &base64_state2);
3906                 }
3907
3908                 // Write samples to our file.
3909                 write_buff = (char *) decode_buff;
3910                 write_bytes = decoded_bytes;
3911
3912                 if (audio_out_rate_ != sample_rate)
3913                 {
3914                         spx_uint32_t in_len, out_len;
3915
3916                         /* Resample the audio to match our previous output rate. */
3917                         if (!audio_resampler_)
3918                         {
3919                                 audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL);
3920                                 speex_resampler_skip_zeros(audio_resampler_);
3921                                 RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
3922                         }
3923                         else
3924                         {
3925                                 spx_uint32_t audio_out_rate;
3926                                 speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate);
3927
3928                                 if (sample_rate != cur_in_rate)
3929                                 {
3930                                         speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate);
3931                                         RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
3932                                 }
3933                         }
3934                         in_len = (spx_uint32_t)rtp_packet->info->info_payload_len;
3935                         out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0);
3936                         if (out_len * sample_bytes_ > resample_buff_len)
3937                         {
3938                                 while ((out_len * sample_bytes_ > resample_buff_len))
3939                                         resample_buff_len *= 2;
3940                                 resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len);
3941                         }
3942
3943                         speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len);
3944                         write_buff = (char *) resample_buff;
3945                         write_bytes = out_len * sample_bytes_;
3946                 }
3947
3948                 /* Write the decoded, possibly-resampled audio */
3949                 for (i = 0; i < write_bytes; i++)
3950                         json_print_base64_step(&write_buff[i], &base64_state1, &base64_state2);
3951
3952                 g_free(decode_buff);
3953         }
3954
3955         json_print_base64_step(NULL, &base64_state1, &base64_state2);
3956
3957         g_free(resample_buff);
3958         g_hash_table_destroy(decoders_hash_);
3959 }
3960
3961 static gboolean
3962 sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
3963 {
3964         const struct _rtp_info *rtp_info = (const struct _rtp_info *) data;
3965         struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata;
3966
3967         /* do not consider RTP packets without a setup frame */
3968         if (rtp_info->info_setup_frame_num == 0)
3969                 return FALSE;
3970
3971         if (rtpstream_id_equal_pinfo_rtp_info(&req_rtp->id, pinfo, rtp_info))
3972         {
3973                 rtp_packet_t *rtp_packet;
3974
3975                 rtp_packet = g_new0(rtp_packet_t, 1);
3976                 rtp_packet->info = (struct _rtp_info *) g_memdup(rtp_info, sizeof(struct _rtp_info));
3977
3978                 if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0)
3979                         rtp_packet->payload_data = (guint8 *) g_memdup(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len);
3980
3981                 if (!req_rtp->packets)
3982                         req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts);
3983
3984                 rtp_packet->frame_num = pinfo->num;
3985                 rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time;
3986
3987                 /* XXX, O(n) optimize */
3988                 req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet);
3989         }
3990
3991         return FALSE;
3992 }
3993
3994 /**
3995  * sharkd_session_process_download()
3996  *
3997  * Process download request
3998  *
3999  * Input:
4000  *   (m) token  - token to download
4001  *
4002  * Output object with attributes:
4003  *   (o) file - suggested name of file
4004  *   (o) mime - suggested content type
4005  *   (o) data - payload base64 encoded
4006  */
4007 static void
4008 sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
4009 {
4010         const char *tok_token      = json_find_attr(buf, tokens, count, "token");
4011
4012         if (!tok_token)
4013                 return;
4014
4015         if (!strncmp(tok_token, "eo:", 3))
4016         {
4017                 struct sharkd_export_object_list *object_list;
4018                 const export_object_entry_t *eo_entry = NULL;
4019
4020                 for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
4021                 {
4022                         size_t eo_type_len = strlen(object_list->type);
4023
4024                         if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
4025                         {
4026                                 int row;
4027
4028                                 if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1)
4029                                         break;
4030
4031                                 eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
4032                                 break;
4033                         }
4034                 }
4035
4036                 if (eo_entry)
4037                 {
4038                         const char *mime     = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
4039                         const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
4040
4041                         printf("{\"file\":");
4042                         json_puts_string(filename);
4043                         printf(",\"mime\":");
4044                         json_puts_string(mime);
4045                         printf(",\"data\":");
4046                         json_print_base64(eo_entry->payload_data, (size_t)(eo_entry->payload_len));
4047                         printf("}\n");
4048                 }
4049         }
4050         else if (!strcmp(tok_token, "ssl-secrets"))
4051         {
4052                 char *str = ssl_export_sessions();
4053
4054                 if (str)
4055                 {
4056                         const char *mime     = "text/plain";
4057                         const char *filename = "keylog.txt";
4058
4059                         printf("{\"file\":");
4060                         json_puts_string(filename);
4061                         printf(",\"mime\":");
4062                         json_puts_string(mime);
4063                         printf(",\"data\":");
4064                         json_print_base64(str, strlen(str));
4065                         printf("}\n");
4066                 }
4067                 g_free(str);
4068         }
4069         else if (!strncmp(tok_token, "rtp:", 4))
4070         {
4071                 struct sharkd_download_rtp rtp_req;
4072                 GString *tap_error;
4073
4074                 memset(&rtp_req, 0, sizeof(rtp_req));
4075                 if (!sharkd_rtp_match_init(&rtp_req.id, tok_token + 4))
4076                 {
4077                         fprintf(stderr, "sharkd_session_process_download() rtp tokenizing error %s\n", tok_token);
4078                         return;
4079                 }
4080
4081                 tap_error = register_tap_listener("rtp", &rtp_req, NULL, 0, NULL, sharkd_session_packet_download_tap_rtp_cb, NULL, NULL);
4082                 if (tap_error)
4083                 {
4084                         fprintf(stderr, "sharkd_session_process_download() rtp error=%s", tap_error->str);
4085                         g_string_free(tap_error, TRUE);
4086                         return;
4087                 }
4088
4089                 sharkd_retap();
4090                 remove_tap_listener(&rtp_req);
4091
4092                 if (rtp_req.packets)
4093                 {
4094                         const char *mime     = "audio/x-wav";
4095                         const char *filename = tok_token;
4096
4097                         printf("{\"file\":");
4098                         json_puts_string(filename);
4099                         printf(",\"mime\":");
4100                         json_puts_string(mime);
4101
4102                         printf(",\"data\":");
4103                         putchar('"');
4104                         sharkd_rtp_download_decode(&rtp_req);
4105                         putchar('"');
4106
4107                         printf("}\n");
4108
4109                         g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items);
4110                 }
4111         }
4112 }
4113
4114 static void
4115 sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
4116 {
4117         int i;
4118
4119         /* sanity check, and split strings */
4120         if (count < 1 || tokens[0].type != JSMN_OBJECT)
4121         {
4122                 fprintf(stderr, "sanity check(1): [0] not object\n");
4123                 return;
4124         }
4125
4126         /* don't need [0] token */
4127         tokens++;
4128         count--;
4129
4130         if (count & 1)
4131         {
4132                 fprintf(stderr, "sanity check(2): %d not even\n", count);
4133                 return;
4134         }
4135
4136         for (i = 0; i < count; i += 2)
4137         {
4138                 if (tokens[i].type != JSMN_STRING)
4139                 {
4140                         fprintf(stderr, "sanity check(3): [%d] not string\n", i);
4141                         return;
4142                 }
4143
4144                 if (tokens[i + 1].type != JSMN_STRING && tokens[i + 1].type != JSMN_PRIMITIVE)
4145                 {
4146                         fprintf(stderr, "sanity check(3a): [%d] wrong type\n", i + 1);
4147                         return;
4148                 }
4149
4150                 buf[tokens[i + 0].end] = '\0';
4151                 buf[tokens[i + 1].end] = '\0';
4152
4153                 /* unescape only value, as keys are simple strings */
4154                 if (tokens[i + 1].type == JSMN_STRING && !json_unescape_str(&buf[tokens[i + 1].start]))
4155                 {
4156                         fprintf(stderr, "sanity check(3b): [%d] cannot unescape string\n", i + 1);
4157                         return;
4158                 }
4159         }
4160
4161         {
4162                 const char *tok_req = json_find_attr(buf, tokens, count, "req");
4163
4164                 if (!tok_req)
4165                 {
4166                         fprintf(stderr, "sanity check(4): no \"req\".\n");
4167                         return;
4168                 }
4169
4170                 if (!strcmp(tok_req, "load"))
4171                         sharkd_session_process_load(buf, tokens, count);
4172                 else if (!strcmp(tok_req, "status"))
4173                         sharkd_session_process_status();
4174                 else if (!strcmp(tok_req, "analyse"))
4175                         sharkd_session_process_analyse();
4176                 else if (!strcmp(tok_req, "info"))
4177                         sharkd_session_process_info();
4178                 else if (!strcmp(tok_req, "check"))
4179                         sharkd_session_process_check(buf, tokens, count);
4180                 else if (!strcmp(tok_req, "complete"))
4181                         sharkd_session_process_complete(buf, tokens, count);
4182                 else if (!strcmp(tok_req, "frames"))
4183                         sharkd_session_process_frames(buf, tokens, count);
4184                 else if (!strcmp(tok_req, "tap"))
4185                         sharkd_session_process_tap(buf, tokens, count);
4186                 else if (!strcmp(tok_req, "follow"))
4187                         sharkd_session_process_follow(buf, tokens, count);
4188                 else if (!strcmp(tok_req, "iograph"))
4189                         sharkd_session_process_iograph(buf, tokens, count);
4190                 else if (!strcmp(tok_req, "intervals"))
4191                         sharkd_session_process_intervals(buf, tokens, count);
4192                 else if (!strcmp(tok_req, "frame"))
4193                         sharkd_session_process_frame(buf, tokens, count);
4194                 else if (!strcmp(tok_req, "setcomment"))
4195                         sharkd_session_process_setcomment(buf, tokens, count);
4196                 else if (!strcmp(tok_req, "setconf"))
4197                         sharkd_session_process_setconf(buf, tokens, count);
4198                 else if (!strcmp(tok_req, "dumpconf"))
4199                         sharkd_session_process_dumpconf(buf, tokens, count);
4200                 else if (!strcmp(tok_req, "download"))
4201                         sharkd_session_process_download(buf, tokens, count);
4202                 else if (!strcmp(tok_req, "bye"))
4203                         exit(0);
4204                 else
4205                         fprintf(stderr, "::: req = %s\n", tok_req);
4206
4207                 /* reply for every command are 0+ lines of JSON reply (outputed above), finished by empty new line */
4208                 printf("\n");
4209
4210                 /*
4211                  * We do an explicit fflush after every line, because
4212                  * we want output to be written to the socket as soon
4213                  * as the line is complete.
4214                  *
4215                  * The stream is fully-buffered by default, so it's
4216                  * only flushed when the buffer fills or the FILE *
4217                  * is closed.  On UN*X, we could set it to be line
4218                  * buffered, but the MSVC standard I/O routines don't
4219                  * support line buffering - they only support *byte*
4220                  * buffering, doing a write for every byte written,
4221                  * which is too inefficient, and full buffering,
4222                  * which is what you get if you request line buffering.
4223                  */
4224                 fflush(stdout);
4225         }
4226 }
4227
4228 int
4229 sharkd_session_main(void)
4230 {
4231         char buf[2 * 1024];
4232         jsmntok_t *tokens = NULL;
4233         int tokens_max = -1;
4234
4235         fprintf(stderr, "Hello in child.\n");
4236
4237         filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free);
4238
4239 #ifdef HAVE_MAXMINDDB
4240         /* mmdbresolve was stopped before fork(), force starting it */
4241         uat_get_table_by_name("MaxMind Database Paths")->post_update_cb();
4242 #endif
4243
4244         while (fgets(buf, sizeof(buf), stdin))
4245         {
4246                 /* every command is line seperated JSON */
4247                 int ret;
4248
4249                 ret = wsjson_parse(buf, NULL, 0);
4250                 if (ret < 0)
4251                 {
4252                         fprintf(stderr, "invalid JSON -> closing\n");
4253                         return 1;
4254                 }
4255
4256                 /* fprintf(stderr, "JSON: %d tokens\n", ret); */
4257                 ret += 1;
4258
4259                 if (tokens == NULL || tokens_max < ret)
4260                 {
4261                         tokens_max = ret;
4262                         tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max);
4263                 }
4264
4265                 memset(tokens, 0, ret * sizeof(jsmntok_t));
4266
4267                 ret = wsjson_parse(buf, tokens, ret);
4268                 if (ret < 0)
4269                 {
4270                         fprintf(stderr, "invalid JSON(2) -> closing\n");
4271                         return 2;
4272                 }
4273
4274 #if defined(HAVE_C_ARES) || defined(HAVE_MAXMINDDB)
4275                 host_name_lookup_process();
4276 #endif
4277
4278                 sharkd_session_process(buf, tokens, ret);
4279         }
4280
4281         g_hash_table_destroy(filter_table);
4282         g_free(tokens);
4283
4284         return 0;
4285 }
4286
4287 /*
4288  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
4289  *
4290  * Local variables:
4291  * c-basic-offset: 8
4292  * tab-width: 8
4293  * indent-tabs-mode: t
4294  * End:
4295  *
4296  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4297  * :indentSize=8:tabSize=8:noTabs=false:
4298  */