sharkd: support exporting ssl secrets
[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  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include <config.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include <glib.h>
32
33 #include <wsutil/wsjsmn.h>
34 #include <wsutil/ws_printf.h>
35
36 #include <file.h>
37 #include <epan/exceptions.h>
38 #include <epan/color_filters.h>
39 #include <epan/prefs.h>
40 #include <epan/prefs-int.h>
41 #include <epan/uat-int.h>
42 #include <wiretap/wtap.h>
43
44 #include <epan/column.h>
45
46 #include <ui/ssl_key_export.h>
47
48 #include <epan/stats_tree_priv.h>
49 #include <epan/stat_tap_ui.h>
50 #include <epan/conversation_table.h>
51 #include <epan/expert.h>
52 #include <epan/export_object.h>
53 #include <epan/follow.h>
54 #include <epan/rtd_table.h>
55 #include <epan/srt_table.h>
56
57 #include <epan/dissectors/packet-h225.h>
58 #include <epan/rtp_pt.h>
59 #include <ui/voip_calls.h>
60 #include <ui/rtp_stream.h>
61 #include <ui/tap-rtp-common.h>
62 #include <epan/to_str.h>
63
64 #ifdef HAVE_GEOIP
65 # include <GeoIP.h>
66 # include <epan/geoip_db.h>
67 # include <wsutil/pint.h>
68 #endif
69
70 #include <wsutil/glib-compat.h>
71 #include <wsutil/strtoi.h>
72
73 #include "sharkd.h"
74
75 static void
76 json_unescape_str(char *input)
77 {
78         char *output = input;
79
80         while (*input)
81         {
82                 char ch = *input++;
83
84                 if (ch == '\\')
85                 {
86                         /* TODO, add more escaping rules */
87                         ch = *input++;
88                 }
89
90                 *output = ch;
91                 output++;
92         }
93
94         *output = '\0';
95 }
96
97 static const char *
98 json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
99 {
100         int i;
101
102         for (i = 0; i < count; i += 2)
103         {
104                 const char *tok_attr  = &buf[tokens[i + 0].start];
105                 const char *tok_value = &buf[tokens[i + 1].start];
106
107                 if (!strcmp(tok_attr, attr))
108                         return tok_value;
109         }
110
111         return NULL;
112 }
113
114 static void
115 json_puts_string(const char *str)
116 {
117         int i;
118
119         if (str == NULL)
120                 str = "";
121
122         putchar('"');
123         for (i = 0; str[i]; i++)
124         {
125                 switch (str[i])
126                 {
127                         case '\\':
128                         case '"':
129                                 putchar('\\');
130                                 putchar(str[i]);
131                                 break;
132
133                         case '\n':
134                                 putchar('\\');
135                                 putchar('n');
136                                 break;
137
138                         default:
139                                 putchar(str[i]);
140                                 break;
141                 }
142         }
143
144         putchar('"');
145 }
146
147 static void
148 json_print_base64(const guint8 *data, int len)
149 {
150         int i;
151         int base64_state1 = 0;
152         int base64_state2 = 0;
153         gsize wrote;
154         gchar buf[(1 / 3 + 1) * 4 + 4 + 1];
155
156         putchar('"');
157
158         for (i = 0; i < len; i++)
159         {
160                 wrote = g_base64_encode_step(&data[i], 1, FALSE, buf, &base64_state1, &base64_state2);
161                 if (wrote > 0)
162                 {
163                         buf[wrote] = '\0';
164                         printf("%s", buf);
165                 }
166         }
167
168         wrote = g_base64_encode_close(FALSE, buf, &base64_state1, &base64_state2);
169         if (wrote > 0)
170         {
171                 buf[wrote] = '\0';
172                 printf("%s", buf);
173         }
174
175         putchar('"');
176 }
177
178 struct filter_item
179 {
180         struct filter_item *next;
181
182         char *filter;
183         guint8 *filtered;
184 };
185
186 static struct filter_item *filter_list = NULL;
187
188 static const guint8 *
189 sharkd_session_filter_data(const char *filter)
190 {
191         struct filter_item *l;
192
193         for (l = filter_list; l; l = l->next)
194         {
195                 if (!strcmp(l->filter, filter))
196                         return l->filtered;
197         }
198
199         {
200                 guint8 *filtered = NULL;
201
202                 int ret = sharkd_filter(filter, &filtered);
203
204                 if (ret == -1)
205                         return NULL;
206
207                 l = (struct filter_item *) g_malloc(sizeof(struct filter_item));
208                 l->filter = g_strdup(filter);
209                 l->filtered = filtered;
210
211                 l->next = filter_list;
212                 filter_list = l;
213
214                 return filtered;
215         }
216 }
217
218 static gboolean
219 sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
220 {
221         struct register_ct *table = (struct register_ct *) value;
222         int *pi = (int *) userdata;
223
224         const char *label = (const char*)key;
225
226         if (get_conversation_packet_func(table))
227         {
228                 printf("%s{", (*pi) ? "," : "");
229                         printf("\"name\":\"Conversation List/%s\"", label);
230                         printf(",\"tap\":\"conv:%s\"", label);
231                 printf("}");
232
233                 *pi = *pi + 1;
234         }
235
236         if (get_hostlist_packet_func(table))
237         {
238                 printf("%s{", (*pi) ? "," : "");
239                         printf("\"name\":\"Endpoint/%s\"", label);
240                         printf(",\"tap\":\"endpt:%s\"", label);
241                 printf("}");
242
243                 *pi = *pi + 1;
244         }
245         return FALSE;
246 }
247
248 static gboolean
249 sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
250 {
251         register_eo_t *eo = (register_eo_t*)value;
252         int *pi = (int *) user_data;
253
254         const int proto_id = get_eo_proto_id(eo);
255         const char *filter = proto_get_protocol_filter_name(proto_id);
256         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
257
258         printf("%s{", (*pi) ? "," : "");
259                 printf("\"name\":\"Export Object/%s\"", label);
260                 printf(",\"tap\":\"eo:%s\"", filter);
261         printf("}");
262
263         *pi = *pi + 1;
264         return FALSE;
265 }
266
267 static gboolean
268 sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data)
269 {
270         register_srt_t *srt = (register_srt_t *) value;
271         int *pi = (int *) user_data;
272
273         const int proto_id = get_srt_proto_id(srt);
274         const char *filter = proto_get_protocol_filter_name(proto_id);
275         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
276
277         printf("%s{", (*pi) ? "," : "");
278                 printf("\"name\":\"Service Response Time/%s\"", label);
279                 printf(",\"tap\":\"srt:%s\"", filter);
280         printf("}");
281
282         *pi = *pi + 1;
283         return FALSE;
284 }
285
286 static gboolean
287 sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data)
288 {
289         register_rtd_t *rtd = (register_rtd_t *) value;
290         int *pi = (int *) user_data;
291
292         const int proto_id = get_rtd_proto_id(rtd);
293         const char *filter = proto_get_protocol_filter_name(proto_id);
294         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
295
296         printf("%s{", (*pi) ? "," : "");
297                 printf("\"name\":\"Response Time Delay/%s\"", label);
298                 printf(",\"tap\":\"rtd:%s\"", filter);
299         printf("}");
300
301         *pi = *pi + 1;
302         return FALSE;
303 }
304
305 static gboolean
306 sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
307 {
308         register_follow_t *follower = (register_follow_t*) value;
309         int *pi = (int *) user_data;
310
311         const int proto_id = get_follow_proto_id(follower);
312         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
313         const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
314
315         printf("%s{", (*pi) ? "," : "");
316                 printf("\"name\":\"Follow/%s\"", label);
317                 printf(",\"tap\":\"follow:%s\"", filter);
318         printf("}");
319
320         *pi = *pi + 1;
321         return FALSE;
322 }
323
324 /**
325  * sharkd_session_process_info()
326  *
327  * Process info request
328  *
329  * Output object with attributes:
330  *   (m) columns - available column formats, array of object with attributes:
331  *                  'name'   - column name
332  *                  'format' - column format-name
333  *
334  *   (m) stats   - available statistics, array of object with attributes:
335  *                  'name' - statistic name
336  *                  'tap'  - sharkd tap-name for statistic
337  *
338  *   (m) convs   - available conversation list, array of object with attributes:
339  *                  'name' - conversation name
340  *                  'tap'  - sharkd tap-name for conversation
341  *
342  *   (m) eo      - available export object list, array of object with attributes:
343  *                  'name' - export object name
344  *                  'tap'  - sharkd tap-name for eo
345  *
346  *   (m) srt     - available service response time list, array of object with attributes:
347  *                  'name' - service response time name
348  *                  'tap'  - sharkd tap-name for srt
349  *
350  *   (m) rtd     - available response time delay list, array of object with attributes:
351  *                  'name' - response time delay name
352  *                  'tap'  - sharkd tap-name for rtd
353  *
354  *   (m) taps - available taps, array of object with attributes:
355  *                  'name' - tap name
356  *                  'tap'  - sharkd tap-name
357  *
358  *   (m) follow - available followers, array of object with attributes:
359  *                  'name' - tap name
360  *                  'tap'  - sharkd tap-name
361  *
362  *   (m) ftypes   - conversation table for FT_ number to string
363  */
364 static void
365 sharkd_session_process_info(void)
366 {
367         int i;
368
369         printf("{\"columns\":[");
370         for (i = 0; i < NUM_COL_FMTS; i++)
371         {
372                 const char *col_format = col_format_to_string(i);
373                 const char *col_descr  = col_format_desc(i);
374
375                 printf("%s{", (i) ? "," : "");
376                         printf("\"name\":\"%s\"", col_descr);
377                         printf(",\"format\":\"%s\"", col_format);
378                 printf("}");
379         }
380         printf("]");
381
382         printf(",\"stats\":[");
383         {
384                 GList *cfg_list = stats_tree_get_cfg_list();
385                 GList *l;
386                 const char *sepa = "";
387
388                 for (l = cfg_list; l; l = l->next)
389                 {
390                         stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
391
392                         printf("%s{", sepa);
393                                 printf("\"name\":\"%s\"", cfg->name);
394                                 printf(",\"tap\":\"stat:%s\"", cfg->abbr);
395                         printf("}");
396                         sepa = ",";
397                 }
398
399                 g_list_free(cfg_list);
400         }
401         printf("]");
402
403         printf(",\"ftypes\":[");
404         for (i = 0; i < FT_NUM_TYPES; i++)
405         {
406                 if (i)
407                         printf(",");
408                 json_puts_string(ftype_name((ftenum_t) i));
409         }
410         printf("]");
411
412         printf(",\"version\":");
413         json_puts_string(sharkd_version());
414
415         printf(",\"convs\":[");
416         i = 0;
417         conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
418         printf("]");
419
420         printf(",\"taps\":[");
421         {
422                 printf("{\"name\":\"%s\",\"tap\":\"%s\"}", "RTP streams", "rtp-streams");
423                 printf(",{\"name\":\"%s\",\"tap\":\"%s\"}", "Expert Information", "expert");
424         }
425         printf("]");
426
427         printf(",\"eo\":[");
428         i = 0;
429         eo_iterate_tables(sharkd_export_object_visit_cb, &i);
430         printf("]");
431
432         printf(",\"srt\":[");
433         i = 0;
434         srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
435         printf("]");
436
437         printf(",\"rtd\":[");
438         i = 0;
439         rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
440         printf("]");
441
442         printf(",\"follow\":[");
443         i = 0;
444         follow_iterate_followers(sharkd_follower_visit_cb, &i);
445         printf("]");
446
447         printf("}\n");
448 }
449
450 /**
451  * sharkd_session_process_load()
452  *
453  * Process load request
454  *
455  * Input:
456  *   (m) file - file to be loaded
457  *
458  * Output object with attributes:
459  *   (m) err - error code
460  */
461 static void
462 sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
463 {
464         const char *tok_file = json_find_attr(buf, tokens, count, "file");
465         int err = 0;
466
467         fprintf(stderr, "load: filename=%s\n", tok_file);
468
469         if (!tok_file)
470                 return;
471
472         if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK)
473         {
474                 printf("{\"err\":%d}\n", err);
475                 return;
476         }
477
478         TRY
479         {
480                 err = sharkd_load_cap_file();
481         }
482         CATCH(OutOfMemoryError)
483         {
484                 fprintf(stderr, "load: OutOfMemoryError\n");
485                 err = ENOMEM;
486         }
487         ENDTRY;
488
489         printf("{\"err\":%d}\n", err);
490 }
491
492 /**
493  * sharkd_session_process_status()
494  *
495  * Process status request
496  *
497  * Output object with attributes:
498  *   (m) frames  - count of currently loaded frames
499  */
500 static void
501 sharkd_session_process_status(void)
502 {
503         printf("{\"frames\":%u", cfile.count);
504
505         printf("}\n");
506 }
507
508 struct sharkd_analyse_data
509 {
510         GHashTable *protocols_set;
511         nstime_t *first_time;
512         nstime_t *last_time;
513 };
514
515 static void
516 sharkd_session_process_analyse_cb(packet_info *pi, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
517 {
518         struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
519         frame_data *fdata = pi->fd;
520
521         (void) tree;
522         (void) cinfo;
523         (void) data_src;
524
525         if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
526                 analyser->first_time = &fdata->abs_ts;
527
528         if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
529                 analyser->last_time = &fdata->abs_ts;
530
531         if (pi->layers)
532         {
533                 wmem_list_frame_t *frame;
534
535                 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
536                 {
537                         int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame));
538
539                         if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL))
540                         {
541                                 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id));
542
543                                 if (g_hash_table_size(analyser->protocols_set) != 1)
544                                         printf(",");
545                                 json_puts_string(proto_get_protocol_filter_name(proto_id));
546                         }
547                 }
548         }
549
550 }
551
552 /**
553  * sharkd_session_process_status()
554  *
555  * Process analyse request
556  *
557  * Output object with attributes:
558  *   (m) frames  - count of currently loaded frames
559  *   (m) protocols - protocol list
560  *   (m) first     - earliest frame time
561  *   (m) last      - latest frame time
562  */
563 static void
564 sharkd_session_process_analyse(void)
565 {
566         unsigned int framenum;
567         struct sharkd_analyse_data analyser;
568
569         analyser.first_time = NULL;
570         analyser.last_time  = NULL;
571         analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */);
572
573         printf("{\"frames\":%u", cfile.count);
574
575         printf(",\"protocols\":[");
576         for (framenum = 1; framenum <= cfile.count; framenum++)
577                 sharkd_dissect_request(framenum, &sharkd_session_process_analyse_cb, 0, 0, 0, &analyser);
578         printf("]");
579
580         if (analyser.first_time)
581                 printf(",\"first\":%.9f", nstime_to_sec(analyser.first_time));
582
583         if (analyser.last_time)
584                 printf(",\"last\":%.9f", nstime_to_sec(analyser.last_time));
585
586         printf("}\n");
587
588         g_hash_table_destroy(analyser.protocols_set);
589 }
590
591 /**
592  * sharkd_session_process_frames()
593  *
594  * Process frames request
595  *
596  * Input:
597  *   (o) filter - filter to be used
598  *   (o) range  - packet range to be used [TODO]
599  *
600  * Output array of frames with attributes:
601  *   (m) c   - array of column data
602  *   (m) num - frame number
603  *   (m) i   - if frame is ignored
604  *   (m) m   - if frame is marked
605  *   (m) bg  - color filter - background color in hex
606  *   (m) fg  - color filter - foreground color in hex
607  */
608 static void
609 sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
610 {
611         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
612
613         const guint8 *filter_data = NULL;
614
615         const char *frame_sepa = "";
616         unsigned int framenum;
617         int col;
618
619         column_info *cinfo = &cfile.cinfo;
620
621         if (tok_filter)
622         {
623                 filter_data = sharkd_session_filter_data(tok_filter);
624                 if (!filter_data)
625                         return;
626         }
627
628         printf("[");
629         for (framenum = 1; framenum <= cfile.count; framenum++)
630         {
631                 frame_data *fdata = frame_data_sequence_find(cfile.frames, framenum);
632
633                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
634                         continue;
635
636                 sharkd_dissect_columns(framenum, cinfo, (fdata->color_filter == NULL));
637
638                 printf("%s{\"c\":[", frame_sepa);
639                 for (col = 0; col < cinfo->num_cols; ++col)
640                 {
641                         const col_item_t *col_item = &cinfo->columns[col];
642
643                         if (col)
644                                 printf(",");
645
646                         json_puts_string(col_item->col_data);
647                 }
648                 printf("],\"num\":%u", framenum);
649
650                 if (fdata->flags.ignored)
651                         printf(",\"i\":true");
652
653                 if (fdata->flags.marked)
654                         printf(",\"m\":true");
655
656                 if (fdata->color_filter)
657                 {
658                         printf(",\"bg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->bg_color));
659                         printf(",\"fg\":\"%x\"", color_t_to_rgb(&fdata->color_filter->fg_color));
660                 }
661
662                 printf("}");
663                 frame_sepa = ",";
664         }
665         printf("]\n");
666
667         if (cinfo != &cfile.cinfo)
668                 col_cleanup(cinfo);
669 }
670
671 static void
672 sharkd_session_process_tap_stats_node_cb(const stat_node *n)
673 {
674         stat_node *node;
675         const char *sepa = "";
676
677         printf("[");
678         for (node = n->children; node; node = node->next)
679         {
680                 /* code based on stats_tree_get_values_from_node() */
681                 printf("%s{\"name\":\"%s\"", sepa, node->name);
682                 printf(",\"count\":%d", node->counter);
683                 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng))
684                 {
685                         printf(",\"avg\":%.2f", ((float)node->total) / node->counter);
686                         printf(",\"min\":%d", node->minvalue);
687                         printf(",\"max\":%d", node->maxvalue);
688                 }
689
690                 if (node->st->elapsed)
691                         printf(",\"rate\":%.4f",((float)node->counter) / node->st->elapsed);
692
693                 if (node->parent && node->parent->counter)
694                         printf(",\"perc\":%.2f", (node->counter * 100.0) / node->parent->counter);
695                 else if (node->parent == &(node->st->root))
696                         printf(",\"perc\":100");
697
698                 if (prefs.st_enable_burstinfo && node->max_burst)
699                 {
700                         if (prefs.st_burst_showcount)
701                                 printf(",\"burstcount\":%d", node->max_burst);
702                         else
703                                 printf(",\"burstrate\":%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
704
705                         printf(",\"bursttime\":%.3f", ((double)node->burst_time / 1000.0));
706                 }
707
708                 if (node->children)
709                 {
710                         printf(",\"sub\":");
711                         sharkd_session_process_tap_stats_node_cb(node);
712                 }
713                 printf("}");
714                 sepa = ",";
715         }
716         printf("]");
717 }
718
719 /**
720  * sharkd_session_process_tap_stats_cb()
721  *
722  * Output stats tap:
723  *
724  *   (m) tap        - tap name
725  *   (m) type:stats - tap output type
726  *   (m) name       - stat name
727  *   (m) stats      - array of object with attributes:
728  *                  (m) name       - stat item name
729  *                  (m) count      - stat item counter
730  *                  (o) avg        - stat item averange value
731  *                  (o) min        - stat item min value
732  *                  (o) max        - stat item max value
733  *                  (o) rate       - stat item rate value (ms)
734  *                  (o) perc       - stat item percentage
735  *                  (o) burstrate  - stat item burst rate
736  *                  (o) burstcount - stat item burst count
737  *                  (o) burstttme  - stat item burst start
738  *                  (o) sub        - array of object with attributes like in stats node.
739  */
740 static void
741 sharkd_session_process_tap_stats_cb(void *psp)
742 {
743         stats_tree *st = (stats_tree *) psp;
744
745         printf("{\"tap\":\"stats:%s\",\"type\":\"stats\"", st->cfg->abbr);
746
747         printf(",\"name\":\"%s\",\"stats\":", st->cfg->name);
748         sharkd_session_process_tap_stats_node_cb(&st->root);
749         printf("},");
750 }
751
752 static void
753 sharkd_session_free_tap_stats_cb(void *psp)
754 {
755         stats_tree *st = (stats_tree *) psp;
756
757         stats_tree_free(st);
758 }
759
760 struct sharkd_expert_tap
761 {
762         GSList *details;
763         GStringChunk *text;
764 };
765
766 /**
767  * sharkd_session_process_tap_expert_cb()
768  *
769  * Output expert tap:
770  *
771  *   (m) tap         - tap name
772  *   (m) type:expert - tap output type
773  *   (m) details     - array of object with attributes:
774  *                  (m) f - frame number, which generated expert information
775  *                  (o) s - severity
776  *                  (o) g - group
777  *                  (m) m - expert message
778  *                  (o) p - protocol
779  */
780 static void
781 sharkd_session_process_tap_expert_cb(void *tapdata)
782 {
783         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
784         GSList *list;
785         const char *sepa = "";
786
787         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "expert", "expert");
788
789         printf(",\"details\":[");
790         for (list = etd->details; list; list = list->next)
791         {
792                 expert_info_t *ei = (expert_info_t *) list->data;
793                 const char *tmp;
794
795                 printf("%s{", sepa);
796
797                 printf("\"f\":%u,", ei->packet_num);
798
799                 tmp = try_val_to_str(ei->severity, expert_severity_vals);
800                 if (tmp)
801                         printf("\"s\":\"%s\",", tmp);
802
803                 tmp = try_val_to_str(ei->group, expert_group_vals);
804                 if (tmp)
805                         printf("\"g\":\"%s\",", tmp);
806
807                 printf("\"m\":");
808                 json_puts_string(ei->summary);
809                 printf(",");
810
811                 if (ei->protocol)
812                 {
813                         printf("\"p\":");
814                         json_puts_string(ei->protocol);
815                 }
816
817                 printf("}");
818                 sepa = ",";
819         }
820         printf("]");
821
822         printf("},");
823 }
824
825 static gboolean
826 sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
827 {
828         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
829         expert_info_t *ei             = (expert_info_t *) pointer;
830
831         ei = (expert_info_t *) g_memdup(ei, sizeof(*ei));
832         ei->protocol = g_string_chunk_insert_const(etd->text, ei->protocol);
833         ei->summary  = g_string_chunk_insert_const(etd->text, ei->summary);
834
835         etd->details = g_slist_prepend(etd->details, ei);
836
837         return TRUE;
838 }
839
840 static void
841 sharkd_session_free_tap_expert_cb(void *tapdata)
842 {
843         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
844
845         g_slist_free_full(etd->details, g_free);
846         g_string_chunk_free(etd->text);
847         g_free(etd);
848 }
849
850 struct sharkd_conv_tap_data
851 {
852         const char *type;
853         conv_hash_t hash;
854         gboolean resolve_name;
855         gboolean resolve_port;
856 };
857
858 static int
859 sharkd_session_geoip_addr(address *addr, const char *suffix)
860 {
861         int with_geoip = 0;
862
863         (void) addr;
864         (void) suffix;
865
866 #ifdef HAVE_GEOIP
867         if (addr->type == AT_IPv4)
868         {
869                 guint32 ip = pntoh32(addr->data);
870
871                 guint num_dbs = geoip_db_num_dbs();
872                 guint dbnum;
873
874                 for (dbnum = 0; dbnum < num_dbs; dbnum++)
875                 {
876                         const char *geoip_key = NULL;
877                         char *geoip_val;
878
879                         int db_type = geoip_db_type(dbnum);
880
881                         switch (db_type)
882                         {
883                                 case GEOIP_COUNTRY_EDITION:
884                                         geoip_key = "geoip_country";
885                                         break;
886
887                                 case GEOIP_CITY_EDITION_REV0:
888                                 case GEOIP_CITY_EDITION_REV1:
889                                         geoip_key = "geoip_city";
890                                         break;
891
892                                 case GEOIP_ORG_EDITION:
893                                         geoip_key = "geoip_org";
894                                         break;
895
896                                 case GEOIP_ISP_EDITION:
897                                         geoip_key = "geoip_isp";
898                                         break;
899
900                                 case GEOIP_ASNUM_EDITION:
901                                         geoip_key = "geoip_as";
902                                         break;
903
904                                 case WS_LAT_FAKE_EDITION:
905                                         geoip_key = "geoip_lat";
906                                         break;
907
908                                 case WS_LON_FAKE_EDITION:
909                                         geoip_key = "geoip_lon";
910                                         break;
911                         }
912
913                         if (geoip_key && (geoip_val = geoip_db_lookup_ipv4(dbnum, ip, NULL)))
914                         {
915                                 printf(",\"%s%s\":", geoip_key, suffix);
916                                 json_puts_string(geoip_val);
917                                 with_geoip = 1;
918                         }
919                 }
920         }
921 #ifdef HAVE_GEOIP_V6
922         if (addr->type == AT_IPv6)
923         {
924                 const struct e_in6_addr *ip6 = (const struct e_in6_addr *) addr->data;
925
926                 guint num_dbs = geoip_db_num_dbs();
927                 guint dbnum;
928
929                 for (dbnum = 0; dbnum < num_dbs; dbnum++)
930                 {
931                         const char *geoip_key = NULL;
932                         char *geoip_val;
933
934                         int db_type = geoip_db_type(dbnum);
935
936                         switch (db_type)
937                         {
938                                 case GEOIP_COUNTRY_EDITION_V6:
939                                         geoip_key = "geoip_country";
940                                         break;
941 #if NUM_DB_TYPES > 31
942                                 case GEOIP_CITY_EDITION_REV0_V6:
943                                 case GEOIP_CITY_EDITION_REV1_V6:
944                                         geoip_key = "geoip_city";
945                                         break;
946
947                                 case GEOIP_ORG_EDITION_V6:
948                                         geoip_key = "geoip_org";
949                                         break;
950
951                                 case GEOIP_ISP_EDITION_V6:
952                                         geoip_key = "geoip_isp";
953                                         break;
954
955                                 case GEOIP_ASNUM_EDITION_V6:
956                                         geoip_key = "geoip_as";
957                                         break;
958 #endif /* DB_NUM_TYPES */
959                                 case WS_LAT_FAKE_EDITION:
960                                         geoip_key = "geoip_lat";
961                                         break;
962
963                                 case WS_LON_FAKE_EDITION:
964                                         geoip_key = "geoip_lon";
965                                         break;
966                         }
967
968                         if (geoip_key && (geoip_val = geoip_db_lookup_ipv6(dbnum, *ip6, NULL)))
969                         {
970                                 printf(",\"%s%s\":", geoip_key, suffix);
971                                 json_puts_string(geoip_val);
972                                 with_geoip = 1;
973                         }
974                 }
975         }
976 #endif /* HAVE_GEOIP_V6 */
977 #endif /* HAVE_GEOIP */
978
979         return with_geoip;
980 }
981
982 /**
983  * sharkd_session_process_tap_conv_cb()
984  *
985  * Output conv tap:
986  *   (m) tap        - tap name
987  *   (m) type       - tap output type
988  *   (m) proto      - protocol short name
989  *   (o) filter     - filter string
990  *
991  *   (o) convs      - array of object with attributes:
992  *                  (m) saddr - source address
993  *                  (m) daddr - destination address
994  *                  (o) sport - source port
995  *                  (o) dport - destination port
996  *                  (m) txf   - TX frame count
997  *                  (m) txb   - TX bytes
998  *                  (m) rxf   - RX frame count
999  *                  (m) rxb   - RX bytes
1000  *                  (m) start - (relative) first packet time
1001  *                  (m) stop  - (relative) last packet time
1002  *
1003  *   (o) hosts      - array of object with attributes:
1004  *                  (m) host - host address
1005  *                  (o) port - host port
1006  *                  (m) txf  - TX frame count
1007  *                  (m) txb  - TX bytes
1008  *                  (m) rxf  - RX frame count
1009  *                  (m) rxb  - RX bytes
1010  */
1011 static void
1012 sharkd_session_process_tap_conv_cb(void *arg)
1013 {
1014         conv_hash_t *hash = (conv_hash_t *) arg;
1015         const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1016         const char *proto;
1017         int proto_with_port;
1018         guint i;
1019
1020         int with_geoip = 0;
1021
1022         if (!strncmp(iu->type, "conv:", 5))
1023         {
1024                 printf("{\"tap\":\"%s\",\"type\":\"conv\"", iu->type);
1025                 printf(",\"convs\":[");
1026                 proto = iu->type + 5;
1027         }
1028         else if (!strncmp(iu->type, "endpt:", 6))
1029         {
1030                 printf("{\"tap\":\"%s\",\"type\":\"host\"", iu->type);
1031                 printf(",\"hosts\":[");
1032                 proto = iu->type + 6;
1033         }
1034         else
1035         {
1036                 printf("{\"tap\":\"%s\",\"type\":\"err\"", iu->type);
1037                 proto = "";
1038         }
1039
1040         proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
1041
1042         if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5))
1043         {
1044                 for (i = 0; i < iu->hash.conv_array->len; i++)
1045                 {
1046                         conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i);
1047                         char *src_addr, *dst_addr;
1048                         char *src_port, *dst_port;
1049                         char *filter_str;
1050
1051                         printf("%s{", i ? "," : "");
1052
1053                         printf("\"saddr\":\"%s\"",  (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name)));
1054                         printf(",\"daddr\":\"%s\"", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name)));
1055
1056                         if (proto_with_port)
1057                         {
1058                                 printf(",\"sport\":\"%s\"", (src_port = get_conversation_port(NULL, iui->src_port, iui->ptype, iu->resolve_port)));
1059                                 printf(",\"dport\":\"%s\"", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->ptype, iu->resolve_port)));
1060
1061                                 wmem_free(NULL, src_port);
1062                                 wmem_free(NULL, dst_port);
1063                         }
1064
1065                         printf(",\"rxf\":%" G_GUINT64_FORMAT, iui->rx_frames);
1066                         printf(",\"rxb\":%" G_GUINT64_FORMAT, iui->rx_bytes);
1067
1068                         printf(",\"txf\":%" G_GUINT64_FORMAT, iui->tx_frames);
1069                         printf(",\"txb\":%" G_GUINT64_FORMAT, iui->tx_bytes);
1070
1071                         printf(",\"start\":%.9f", nstime_to_sec(&iui->start_time));
1072                         printf(",\"stop\":%.9f", nstime_to_sec(&iui->stop_time));
1073
1074                         filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
1075                         if (filter_str)
1076                         {
1077                                 printf(",\"filter\":\"%s\"", filter_str);
1078                                 g_free(filter_str);
1079                         }
1080
1081                         wmem_free(NULL, src_addr);
1082                         wmem_free(NULL, dst_addr);
1083
1084                         if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
1085                                 with_geoip = 1;
1086                         if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
1087                                 with_geoip = 1;
1088
1089                         printf("}");
1090                 }
1091         }
1092         else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6))
1093         {
1094                 for (i = 0; i < iu->hash.conv_array->len; i++)
1095                 {
1096                         hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
1097                         char *host_str, *port_str;
1098                         char *filter_str;
1099
1100                         printf("%s{", i ? "," : "");
1101
1102                         printf("\"host\":\"%s\"", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name)));
1103
1104                         if (proto_with_port)
1105                         {
1106                                 printf(",\"port\":\"%s\"", (port_str = get_conversation_port(NULL, host->port, host->ptype, iu->resolve_port)));
1107
1108                                 wmem_free(NULL, port_str);
1109                         }
1110
1111                         printf(",\"rxf\":%" G_GUINT64_FORMAT, host->rx_frames);
1112                         printf(",\"rxb\":%" G_GUINT64_FORMAT, host->rx_bytes);
1113
1114                         printf(",\"txf\":%" G_GUINT64_FORMAT, host->tx_frames);
1115                         printf(",\"txb\":%" G_GUINT64_FORMAT, host->tx_bytes);
1116
1117                         filter_str = get_hostlist_filter(host);
1118                         if (filter_str)
1119                         {
1120                                 printf(",\"filter\":\"%s\"", filter_str);
1121                                 g_free(filter_str);
1122                         }
1123
1124                         wmem_free(NULL, host_str);
1125
1126                         if (sharkd_session_geoip_addr(&(host->myaddress), ""))
1127                                 with_geoip = 1;
1128                         printf("}");
1129                 }
1130         }
1131
1132         printf("],\"proto\":\"%s\",\"geoip\":%s},", proto, with_geoip ? "true" : "false");
1133 }
1134
1135 static void
1136 sharkd_session_free_tap_conv_cb(void *arg)
1137 {
1138         conv_hash_t *hash = (conv_hash_t *) arg;
1139         struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1140
1141         if (!strncmp(iu->type, "conv:", 5))
1142         {
1143                 reset_conversation_table_data(hash);
1144         }
1145         else if (!strncmp(iu->type, "endpt:", 6))
1146         {
1147                 reset_hostlist_table_data(hash);
1148         }
1149
1150         g_free(iu);
1151 }
1152
1153 /**
1154  * sharkd_session_process_tap_rtd_cb()
1155  *
1156  * Output rtd tap:
1157  *   (m) tap        - tap name
1158  *   (m) type       - tap output type
1159  *   (m) stats - statistics rows - array object with attributes:
1160  *                  (m) type - statistic name
1161  *                  (m) num - number of messages
1162  *                  (m) min - minimum SRT time
1163  *                  (m) max - maximum SRT time
1164  *                  (m) tot - total SRT time
1165  *                  (m) min_frame - minimal SRT
1166  *                  (m) max_frame - maximum SRT
1167  *                  (o) open_req - Open Requests
1168  *                  (o) disc_rsp - Discarded Responses
1169  *                  (o) req_dup  - Duplicated Requests
1170  *                  (o) rsp_dup  - Duplicated Responses
1171  *   (o) open_req   - Open Requests
1172  *   (o) disc_rsp   - Discarded Responses
1173  *   (o) req_dup    - Duplicated Requests
1174  *   (o) rsp_dup    - Duplicated Responses
1175  */
1176 static void
1177 sharkd_session_process_tap_rtd_cb(void *arg)
1178 {
1179         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1180         register_rtd_t *rtd  = (register_rtd_t *) rtd_data->user_data;
1181
1182         guint i, j;
1183
1184         const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
1185
1186         /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
1187          *      some multiple table and single timestat (radius, h225)
1188          *      and it seems that value_string is used one for timestamp-ID, other one for table-ID
1189          *      I wonder how it will gonna work with multiple timestats and multiple timestat...
1190          * (for usage grep for: register_rtd_table)
1191          */
1192         const value_string *vs = get_rtd_value_string(rtd);
1193         const char *sepa = "";
1194
1195         printf("{\"tap\":\"rtd:%s\",\"type\":\"rtd\"", filter);
1196
1197         if (rtd_data->stat_table.num_rtds == 1)
1198         {
1199                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
1200
1201                 printf(",\"open_req\":%u", ms->open_req_num);
1202                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1203                 printf(",\"req_dup\":%u", ms->req_dup_num);
1204                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1205         }
1206
1207         printf(",\"stats\":[");
1208         for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
1209         {
1210                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
1211
1212                 for (j = 0; j < ms->num_timestat; j++)
1213                 {
1214                         const char *type_str;
1215
1216                         if (ms->rtd[j].num == 0)
1217                                 continue;
1218
1219                         printf("%s{", sepa);
1220
1221                         if (rtd_data->stat_table.num_rtds == 1)
1222                                 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
1223                         else
1224                                 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
1225                         printf("\"type\":");
1226                         json_puts_string(type_str);
1227
1228                         printf(",\"num\":%u", ms->rtd[j].num);
1229                         printf(",\"min\":%.9f", nstime_to_sec(&(ms->rtd[j].min)));
1230                         printf(",\"max\":%.9f", nstime_to_sec(&(ms->rtd[j].max)));
1231                         printf(",\"tot\":%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
1232                         printf(",\"min_frame\":%u", ms->rtd[j].min_num);
1233                         printf(",\"max_frame\":%u", ms->rtd[j].max_num);
1234
1235                         if (rtd_data->stat_table.num_rtds != 1)
1236                         {
1237                                 /* like in tshark, display it on every row */
1238                                 printf(",\"open_req\":%u", ms->open_req_num);
1239                                 printf(",\"disc_rsp\":%u", ms->disc_rsp_num);
1240                                 printf(",\"req_dup\":%u", ms->req_dup_num);
1241                                 printf(",\"rsp_dup\":%u", ms->rsp_dup_num);
1242                         }
1243
1244                         printf("}");
1245                         sepa = ",";
1246                 }
1247         }
1248         printf("]},");
1249 }
1250
1251 static void
1252 sharkd_session_free_tap_rtd_cb(void *arg)
1253 {
1254         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1255
1256         free_rtd_table(&rtd_data->stat_table, NULL, NULL);
1257         g_free(rtd_data);
1258 }
1259
1260 /**
1261  * sharkd_session_process_tap_srt_cb()
1262  *
1263  * Output srt tap:
1264  *   (m) tap        - tap name
1265  *   (m) type       - tap output type
1266  *
1267  *   (m) tables - array of object with attributes:
1268  *                  (m) n - table name
1269  *                  (m) f - table filter
1270  *                  (o) c - table column name
1271  *                  (m) r - table rows - array object with attributes:
1272  *                            (m) n   - row name
1273  *                            (m) idx - procedure index
1274  *                            (m) num - number of events
1275  *                            (m) min - minimum SRT time
1276  *                            (m) max - maximum SRT time
1277  *                            (m) tot - total SRT time
1278  */
1279 static void
1280 sharkd_session_process_tap_srt_cb(void *arg)
1281 {
1282         srt_data_t *srt_data = (srt_data_t *) arg;
1283         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1284
1285         const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
1286
1287         guint i;
1288
1289         printf("{\"tap\":\"srt:%s\",\"type\":\"srt\"", filter);
1290
1291         printf(",\"tables\":[");
1292         for (i = 0; i < srt_data->srt_array->len; i++)
1293         {
1294                 /* SRT table */
1295                 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i);
1296                 const char *sepa = "";
1297
1298                 int j;
1299
1300                 if (i)
1301                         printf(",");
1302                 printf("{");
1303
1304                 printf("\"n\":");
1305                 if (rst->name)
1306                         json_puts_string(rst->name);
1307                 else if (rst->short_name)
1308                         json_puts_string(rst->short_name);
1309                 else
1310                         printf("\"table%u\"", i);
1311
1312                 if (rst->filter_string)
1313                 {
1314                         printf(",\"f\":");
1315                         json_puts_string(rst->filter_string);
1316                 }
1317
1318                 if (rst->proc_column_name)
1319                 {
1320                         printf(",\"c\":");
1321                         json_puts_string(rst->proc_column_name);
1322                 }
1323
1324                 printf(",\"r\":[");
1325                 for (j = 0; j < rst->num_procs; j++)
1326                 {
1327                         /* SRT row */
1328                         srt_procedure_t *proc = &rst->procedures[j];
1329
1330                         if (proc->stats.num == 0)
1331                                 continue;
1332
1333                         printf("%s{", sepa);
1334
1335                         printf("\"n\":");
1336                         json_puts_string(proc->procedure);
1337
1338                         if (rst->filter_string)
1339                                 printf(",\"idx\":%d", proc->proc_index);
1340
1341                         printf(",\"num\":%u", proc->stats.num);
1342
1343                         printf(",\"min\":%.9f", nstime_to_sec(&proc->stats.min));
1344                         printf(",\"max\":%.9f", nstime_to_sec(&proc->stats.max));
1345                         printf(",\"tot\":%.9f", nstime_to_sec(&proc->stats.tot));
1346
1347                         printf("}");
1348                         sepa = ",";
1349                 }
1350                 printf("]}");
1351         }
1352
1353         printf("]},");
1354 }
1355
1356 static void
1357 sharkd_session_free_tap_srt_cb(void *arg)
1358 {
1359         srt_data_t *srt_data = (srt_data_t *) arg;
1360         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
1361
1362         free_srt_table(srt, srt_data->srt_array, NULL, NULL);
1363         g_array_free(srt_data->srt_array, TRUE);
1364         g_free(srt_data);
1365 }
1366
1367 struct sharkd_export_object_list
1368 {
1369         struct sharkd_export_object_list *next;
1370
1371         char *type;
1372         const char *proto;
1373         GSList *entries;
1374 };
1375
1376 static struct sharkd_export_object_list *sharkd_eo_list;
1377
1378 /**
1379  * sharkd_session_process_tap_eo_cb()
1380  *
1381  * Output eo tap:
1382  *   (m) tap        - tap name
1383  *   (m) type       - tap output type
1384  *   (m) proto      - protocol short name
1385  *   (m) objects    - array of object with attributes:
1386  *                  (m) pkt - packet number
1387  *                  (o) hostname - hostname
1388  *                  (o) type - content type
1389  *                  (o) filename - filename
1390  *                  (m) len - object length
1391  */
1392 static void
1393 sharkd_session_process_tap_eo_cb(void *tapdata)
1394 {
1395         export_object_list_t *tap_object = (export_object_list_t *) tapdata;
1396         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list*) tap_object->gui_data;
1397         GSList *slist;
1398         int i = 0;
1399
1400         printf("{\"tap\":\"%s\",\"type\":\"eo\"", object_list->type);
1401         printf(",\"proto\":\"%s\"", object_list->proto);
1402         printf(",\"objects\":[");
1403
1404         for (slist = object_list->entries; slist; slist = slist->next)
1405         {
1406                 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
1407
1408                 printf("%s{", i ? "," : "");
1409
1410                 printf("\"pkt\":%u", eo_entry->pkt_num);
1411
1412                 if (eo_entry->hostname)
1413                 {
1414                         printf(",\"hostname\":");
1415                         json_puts_string(eo_entry->hostname);
1416                 }
1417
1418                 if (eo_entry->content_type)
1419                 {
1420                         printf(",\"type\":");
1421                         json_puts_string(eo_entry->content_type);
1422                 }
1423
1424                 if (eo_entry->filename)
1425                 {
1426                         printf(",\"filename\":");
1427                         json_puts_string(eo_entry->filename);
1428                 }
1429
1430                 printf(",\"_download\":\"%s_%d\"", object_list->type, i);
1431
1432                 printf(",\"len\":%" G_GINT64_FORMAT, eo_entry->payload_len);
1433
1434                 printf("}");
1435
1436                 i++;
1437         }
1438
1439         printf("]},");
1440 }
1441
1442 static void
1443 sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
1444 {
1445         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
1446
1447         object_list->entries = g_slist_append(object_list->entries, entry);
1448 }
1449
1450 static export_object_entry_t *
1451 sharkd_eo_object_list_get_entry(void *gui_data, int row)
1452 {
1453         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
1454
1455         return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
1456 }
1457
1458 /**
1459  * sharkd_session_process_tap_rtp_cb()
1460  *
1461  * Output RTP streams tap:
1462  *   (m) tap        - tap name
1463  *   (m) type       - tap output type
1464  *   (m) streams    - array of object with attributes:
1465  *                  (m) ssrc        - RTP synchronization source identifier
1466  *                  (m) payload     - stream payload
1467  *                  (m) saddr       - source address
1468  *                  (m) sport       - source port
1469  *                  (m) daddr       - destination address
1470  *                  (m) dport       - destination port
1471  *                  (m) pkts        - packets count
1472  *                  (m) max_delta   - max delta (ms)
1473  *                  (m) max_jitter  - max jitter (ms)
1474  *                  (m) mean_jitter - mean jitter (ms)
1475  *                  (m) expectednr  -
1476  *                  (m) totalnr     -
1477  *                  (m) problem     - if analyser found the problem
1478  *                  (m) ipver       - address IP version (4 or 6)
1479  */
1480 static void
1481 sharkd_session_process_tap_rtp_cb(void *arg)
1482 {
1483         rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
1484
1485         GList *listx;
1486         const char *sepa = "";
1487
1488         printf("{\"tap\":\"%s\",\"type\":\"%s\"", "rtp-streams", "rtp-streams");
1489
1490         printf(",\"streams\":[");
1491         for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
1492         {
1493                 rtp_stream_info_t *streaminfo = (rtp_stream_info_t *) listx->data;
1494
1495                 char *src_addr, *dst_addr;
1496                 char *payload;
1497                 guint32 expected;
1498
1499                 src_addr = address_to_display(NULL, &(streaminfo->src_addr));
1500                 dst_addr = address_to_display(NULL, &(streaminfo->dest_addr));
1501
1502                 if (streaminfo->payload_type_name != NULL)
1503                         payload = wmem_strdup(NULL, streaminfo->payload_type_name);
1504                 else
1505                         payload = val_to_str_ext_wmem(NULL, streaminfo->payload_type, &rtp_payload_type_short_vals_ext, "Unknown (%u)");
1506
1507                 printf("%s{\"ssrc\":%u", sepa, streaminfo->ssrc);
1508                 printf(",\"payload\":\"%s\"", payload);
1509
1510                 printf(",\"saddr\":\"%s\"", src_addr);
1511                 printf(",\"sport\":%u", streaminfo->src_port);
1512
1513                 printf(",\"daddr\":\"%s\"", dst_addr);
1514                 printf(",\"dport\":%u", streaminfo->dest_port);
1515
1516                 printf(",\"pkts\":%u", streaminfo->packet_count);
1517
1518                 printf(",\"max_delta\":%f", streaminfo->rtp_stats.max_delta);
1519                 printf(",\"max_jitter\":%f", streaminfo->rtp_stats.max_jitter);
1520                 printf(",\"mean_jitter\":%f", streaminfo->rtp_stats.mean_jitter);
1521
1522                 expected = (streaminfo->rtp_stats.stop_seq_nr + streaminfo->rtp_stats.cycles * 65536) - streaminfo->rtp_stats.start_seq_nr + 1;
1523                 printf(",\"expectednr\":%u", expected);
1524                 printf(",\"totalnr\":%u", streaminfo->rtp_stats.total_nr);
1525
1526                 printf(",\"problem\":%s", streaminfo->problem ? "true" : "false");
1527
1528                 /* for filter */
1529                 printf(",\"ipver\":%d", (streaminfo->src_addr.type == AT_IPv6) ? 6 : 4);
1530
1531                 wmem_free(NULL, src_addr);
1532                 wmem_free(NULL, dst_addr);
1533                 wmem_free(NULL, payload);
1534
1535                 printf("}");
1536                 sepa = ",";
1537         }
1538         printf("]},");
1539 }
1540
1541 /**
1542  * sharkd_session_process_tap()
1543  *
1544  * Process tap request
1545  *
1546  * Input:
1547  *   (m) tap0         - First tap request
1548  *   (o) tap1...tap15 - Other tap requests
1549  *
1550  * Output object with attributes:
1551  *   (m) taps  - array of object with attributes:
1552  *                  (m) tap  - tap name
1553  *                  (m) type - tap output type
1554  *                  ...
1555  *                  for type:stats see sharkd_session_process_tap_stats_cb()
1556  *                  for type:conv see sharkd_session_process_tap_conv_cb()
1557  *                  for type:host see sharkd_session_process_tap_conv_cb()
1558  *                  for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
1559  *                  for type:eo see sharkd_session_process_tap_eo_cb()
1560  *                  for type:expert see sharkd_session_process_tap_expert_cb()
1561  *                  for type:rtd see sharkd_session_process_tap_rtd_cb()
1562  *                  for type:srt see sharkd_session_process_tap_srt_cb()
1563  *
1564  *   (m) err   - error code
1565  */
1566 static void
1567 sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
1568 {
1569         void *taps_data[16];
1570         GFreeFunc taps_free[16];
1571         int taps_count = 0;
1572         int i;
1573
1574         rtpstream_tapinfo_t rtp_tapinfo =
1575                 {NULL, NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE};
1576
1577         for (i = 0; i < 16; i++)
1578         {
1579                 char tapbuf[32];
1580                 const char *tok_tap;
1581
1582                 void *tap_data = NULL;
1583                 GFreeFunc tap_free = NULL;
1584                 const char *tap_filter = "";
1585                 GString *tap_error = NULL;
1586
1587                 ws_snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
1588                 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
1589                 if (!tok_tap)
1590                         break;
1591
1592                 if (!strncmp(tok_tap, "stat:", 5))
1593                 {
1594                         stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
1595                         stats_tree *st;
1596
1597                         if (!cfg)
1598                         {
1599                                 fprintf(stderr, "sharkd_session_process_tap() stat %s not found\n", tok_tap + 5);
1600                                 continue;
1601                         }
1602
1603                         st = stats_tree_new(cfg, NULL, tap_filter);
1604
1605                         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);
1606
1607                         if (!tap_error && cfg->init)
1608                                 cfg->init(st);
1609
1610                         tap_data = st;
1611                         tap_free = sharkd_session_free_tap_stats_cb;
1612                 }
1613                 else if (!strcmp(tok_tap, "expert"))
1614                 {
1615                         struct sharkd_expert_tap *expert_tap;
1616
1617                         expert_tap = g_new0(struct sharkd_expert_tap, 1);
1618                         expert_tap->text = g_string_chunk_new(100);
1619
1620                         tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb);
1621
1622                         tap_data = expert_tap;
1623                         tap_free = sharkd_session_free_tap_expert_cb;
1624                 }
1625                 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
1626                 {
1627                         struct register_ct *ct = NULL;
1628                         const char *ct_tapname;
1629                         struct sharkd_conv_tap_data *ct_data;
1630                         tap_packet_cb tap_func = NULL;
1631
1632                         if (!strncmp(tok_tap, "conv:", 5))
1633                         {
1634                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
1635
1636                                 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
1637                                 {
1638                                         fprintf(stderr, "sharkd_session_process_tap() conv %s not found\n", tok_tap + 5);
1639                                         continue;
1640                                 }
1641                         }
1642                         else if (!strncmp(tok_tap, "endpt:", 6))
1643                         {
1644                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
1645
1646                                 if (!ct || !(tap_func = get_hostlist_packet_func(ct)))
1647                                 {
1648                                         fprintf(stderr, "sharkd_session_process_tap() endpt %s not found\n", tok_tap + 6);
1649                                         continue;
1650                                 }
1651                         }
1652                         else
1653                         {
1654                                 fprintf(stderr, "sharkd_session_process_tap() conv/endpt(?): %s not found\n", tok_tap);
1655                                 continue;
1656                         }
1657
1658                         ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
1659
1660                         ct_data = (struct sharkd_conv_tap_data *) g_malloc0(sizeof(struct sharkd_conv_tap_data));
1661                         ct_data->type = tok_tap;
1662                         ct_data->hash.user_data = ct_data;
1663
1664                         /* XXX: make configurable */
1665                         ct_data->resolve_name = TRUE;
1666                         ct_data->resolve_port = TRUE;
1667
1668                         tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb);
1669
1670                         tap_data = &ct_data->hash;
1671                         tap_free = sharkd_session_free_tap_conv_cb;
1672                 }
1673                 else if (!strncmp(tok_tap, "rtd:", 4))
1674                 {
1675                         register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
1676                         rtd_data_t *rtd_data;
1677                         char *err;
1678
1679                         if (!rtd)
1680                         {
1681                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s not found\n", tok_tap + 4);
1682                                 continue;
1683                         }
1684
1685                         rtd_table_get_filter(rtd, "", &tap_filter, &err);
1686                         if (err != NULL)
1687                         {
1688                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s err=%s\n", tok_tap + 4, err);
1689                                 g_free(err);
1690                                 continue;
1691                         }
1692
1693                         rtd_data = g_new0(rtd_data_t, 1);
1694                         rtd_data->user_data = rtd;
1695                         rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL);
1696
1697                         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);
1698
1699                         tap_data = rtd_data;
1700                         tap_free = sharkd_session_free_tap_rtd_cb;
1701                 }
1702                 else if (!strncmp(tok_tap, "srt:", 4))
1703                 {
1704                         register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
1705                         srt_data_t *srt_data;
1706                         char *err;
1707
1708                         if (!srt)
1709                         {
1710                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s not found\n", tok_tap + 4);
1711                                 continue;
1712                         }
1713
1714                         srt_table_get_filter(srt, "", &tap_filter, &err);
1715                         if (err != NULL)
1716                         {
1717                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s err=%s\n", tok_tap + 4, err);
1718                                 g_free(err);
1719                                 continue;
1720                         }
1721
1722                         srt_data = g_new0(srt_data_t, 1);
1723                         srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *));
1724                         srt_data->user_data = srt;
1725                         srt_table_dissector_init(srt, srt_data->srt_array, NULL, NULL);
1726
1727                         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);
1728
1729                         tap_data = srt_data;
1730                         tap_free = sharkd_session_free_tap_srt_cb;
1731                 }
1732                 else if (!strncmp(tok_tap, "eo:", 3))
1733                 {
1734                         register_eo_t *eo = get_eo_by_name(tok_tap + 3);
1735                         export_object_list_t *eo_object;
1736                         struct sharkd_export_object_list *object_list;
1737
1738                         if (!eo)
1739                         {
1740                                 fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
1741                                 continue;
1742                         }
1743
1744                         for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
1745                         {
1746                                 if (!strcmp(object_list->type, tok_tap))
1747                                 {
1748                                         g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
1749                                         object_list->entries = NULL;
1750                                         break;
1751                                 }
1752                         }
1753
1754                         if (!object_list)
1755                         {
1756                                 object_list = g_new(struct sharkd_export_object_list, 1);
1757                                 object_list->type = g_strdup(tok_tap);
1758                                 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
1759                                 object_list->entries = NULL;
1760                                 object_list->next = sharkd_eo_list;
1761                                 sharkd_eo_list = object_list;
1762                         }
1763
1764                         eo_object  = g_new0(export_object_list_t, 1);
1765                         eo_object->add_entry = sharkd_eo_object_list_add_entry;
1766                         eo_object->get_entry = sharkd_eo_object_list_get_entry;
1767                         eo_object->gui_data = (void *) object_list;
1768
1769                         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);
1770
1771                         tap_data = eo_object;
1772                         tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
1773                 }
1774                 else if (!strcmp(tok_tap, "rtp-streams"))
1775                 {
1776                         tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet, sharkd_session_process_tap_rtp_cb);
1777
1778                         tap_data = &rtp_tapinfo;
1779                         tap_free = rtpstream_reset_cb;
1780                 }
1781                 else
1782                 {
1783                         fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);
1784                         continue;
1785                 }
1786
1787                 if (tap_error)
1788                 {
1789                         fprintf(stderr, "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str);
1790                         g_string_free(tap_error, TRUE);
1791                         if (tap_free)
1792                                 tap_free(tap_data);
1793                         continue;
1794                 }
1795
1796                 taps_data[taps_count] = tap_data;
1797                 taps_free[taps_count] = tap_free;
1798                 taps_count++;
1799         }
1800
1801         fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count);
1802         if (taps_count == 0)
1803                 return;
1804
1805         printf("{\"taps\":[");
1806         sharkd_retap();
1807         printf("null],\"err\":0}\n");
1808
1809         for (i = 0; i < taps_count; i++)
1810         {
1811                 if (taps_data[i])
1812                         remove_tap_listener(taps_data[i]);
1813
1814                 if (taps_free[i])
1815                         taps_free[i](taps_data[i]);
1816         }
1817 }
1818
1819 /**
1820  * sharkd_session_process_follow()
1821  *
1822  * Process follow request
1823  *
1824  * Input:
1825  *   (m) follow  - follow protocol request (e.g. HTTP)
1826  *   (m) filter  - filter request (e.g. tcp.stream == 1)
1827  *
1828  * Output object with attributes:
1829  *
1830  *   (m) err    - error code
1831  *   (m) shost  - server host
1832  *   (m) sport  - server port
1833  *   (m) sbytes - server send bytes count
1834  *   (m) chost  - client host
1835  *   (m) cport  - client port
1836  *   (m) cbytes - client send bytes count
1837  *   (o) payloads - array of object with attributes:
1838  *                  (o) s - set if server sent, else client
1839  *                  (m) n - packet number
1840  *                  (m) d - data base64 encoded
1841  */
1842 static void
1843 sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
1844 {
1845         const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
1846         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
1847
1848         register_follow_t *follower;
1849         GString *tap_error;
1850
1851         follow_info_t *follow_info;
1852         const char *host;
1853         char *port;
1854
1855         if (!tok_follow || !tok_filter)
1856                 return;
1857
1858         follower = get_follow_by_name(tok_follow);
1859         if (!follower)
1860         {
1861                 fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
1862                 return;
1863         }
1864
1865         /* follow_reset_stream ? */
1866         follow_info = g_new0(follow_info_t, 1);
1867         /* gui_data, filter_out_filter not set, but not used by dissector */
1868
1869         tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL);
1870         if (tap_error)
1871         {
1872                 fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
1873                 g_string_free(tap_error, TRUE);
1874                 g_free(follow_info);
1875                 return;
1876         }
1877
1878         sharkd_retap();
1879
1880         printf("{");
1881
1882         printf("\"err\":0");
1883
1884         /* Server information: hostname, port, bytes sent */
1885         host = address_to_name(&follow_info->server_ip);
1886         printf(",\"shost\":");
1887         json_puts_string(host);
1888
1889         port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
1890         printf(",\"sport\":");
1891         json_puts_string(port);
1892         wmem_free(NULL, port);
1893
1894         printf(",\"sbytes\":%u", follow_info->bytes_written[0]);
1895
1896         /* Client information: hostname, port, bytes sent */
1897         host = address_to_name(&follow_info->client_ip);
1898         printf(",\"chost\":");
1899         json_puts_string(host);
1900
1901         port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
1902         printf(",\"cport\":");
1903         json_puts_string(port);
1904         wmem_free(NULL, port);
1905
1906         printf(",\"cbytes\":%u", follow_info->bytes_written[1]);
1907
1908         if (follow_info->payload)
1909         {
1910                 follow_record_t *follow_record;
1911                 GList *cur;
1912                 const char *sepa = "";
1913
1914                 printf(",\"payloads\":[");
1915
1916                 for (cur = follow_info->payload; cur; cur = g_list_next(cur))
1917                 {
1918                         follow_record = (follow_record_t *) cur->data;
1919
1920                         printf("%s{", sepa);
1921
1922                         printf("\"n\":%u", follow_record->packet_num);
1923
1924                         printf(",\"d\":");
1925                         json_print_base64(follow_record->data->data, follow_record->data->len);
1926
1927                         if (follow_record->is_server)
1928                                 printf(",\"s\":%d", 1);
1929
1930                         printf("}");
1931                         sepa = ",";
1932                 }
1933
1934                 printf("]");
1935         }
1936
1937         printf("}\n");
1938
1939         remove_tap_listener(follow_info);
1940         follow_info_free(follow_info);
1941 }
1942
1943 static void
1944 sharkd_session_process_frame_cb_tree(proto_tree *tree, tvbuff_t **tvbs)
1945 {
1946         proto_node *node;
1947         const char *sepa = "";
1948
1949         printf("[");
1950         for (node = tree->first_child; node; node = node->next)
1951         {
1952                 field_info *finfo = PNODE_FINFO(node);
1953
1954                 if (!finfo)
1955                         continue;
1956
1957                 /* XXX, for now always skip hidden */
1958                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
1959                         continue;
1960
1961                 printf("%s{", sepa);
1962
1963                 printf("\"l\":");
1964                 if (!finfo->rep)
1965                 {
1966                         char label_str[ITEM_LABEL_LENGTH];
1967
1968                         label_str[0] = '\0';
1969                         proto_item_fill_label(finfo, label_str);
1970                         json_puts_string(label_str);
1971                 }
1972                 else
1973                 {
1974                         json_puts_string(finfo->rep->representation);
1975                 }
1976
1977                 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
1978                 {
1979                         int idx;
1980
1981                         for (idx = 1; tvbs[idx]; idx++)
1982                         {
1983                                 if (tvbs[idx] == finfo->ds_tvb)
1984                                 {
1985                                         printf(",\"ds\":%d", idx);
1986                                         break;
1987                                 }
1988                         }
1989                 }
1990
1991                 if (finfo->start >= 0 && finfo->length > 0)
1992                         printf(",\"h\":[%d,%d]", finfo->start, finfo->length);
1993
1994                 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
1995                         printf(",\"i\":[%d,%d]", finfo->appendix_start, finfo->appendix_length);
1996
1997
1998                 if (finfo->hfinfo)
1999                 {
2000                         if (finfo->hfinfo->type == FT_PROTOCOL)
2001                         {
2002                                 printf(",\"t\":\"proto\"");
2003                         }
2004                         else if (finfo->hfinfo->type == FT_FRAMENUM)
2005                         {
2006                                 printf(",\"t\":\"framenum\",\"fnum\":%u", finfo->value.value.uinteger);
2007                         }
2008                         else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type))
2009                         {
2010                                 char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
2011
2012                                 printf(",\"t\":\"url\",\"url\":");
2013                                 json_puts_string(url);
2014                                 wmem_free(NULL, url);
2015                         }
2016                 }
2017
2018                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2019                 {
2020                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2021
2022                         g_assert(severity != NULL);
2023
2024                         printf(",\"s\":\"%s\"", severity);
2025                 }
2026
2027                 if (((proto_tree *) node)->first_child) {
2028                         if (finfo->tree_type != -1)
2029                                 printf(",\"e\":%d", finfo->tree_type);
2030                         printf(",\"n\":");
2031                         sharkd_session_process_frame_cb_tree((proto_tree *) node, tvbs);
2032                 }
2033
2034                 printf("}");
2035                 sepa = ",";
2036         }
2037         printf("]");
2038 }
2039
2040 static gboolean
2041 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2042 {
2043         register_follow_t *follower = (register_follow_t *) value;
2044         packet_info *pi = (packet_info *) user_data;
2045
2046         const int proto_id = get_follow_proto_id(follower);
2047
2048         guint32 ignore_stream;
2049
2050         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2051         {
2052                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2053                 char *follow_filter;
2054
2055                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2056
2057                 printf(",[\"%s\",", layer_proto);
2058                 json_puts_string(follow_filter);
2059                 printf("]");
2060
2061                 g_free(follow_filter);
2062         }
2063
2064         return FALSE;
2065 }
2066
2067 static void
2068 sharkd_session_process_frame_cb(packet_info *pi, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2069 {
2070         (void) pi;
2071         (void) data;
2072
2073         printf("{");
2074
2075         printf("\"err\":0");
2076
2077         if (tree)
2078         {
2079                 tvbuff_t **tvbs = NULL;
2080
2081                 printf(",\"tree\":");
2082
2083                 /* arrayize data src, to speedup searching for ds_tvb index */
2084                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2085                 {
2086                         guint count = g_slist_length((GSList *) data_src);
2087                         guint i;
2088
2089                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2090
2091                         for (i = 0; i < count; i++)
2092                         {
2093                                 struct data_source *src = (struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2094
2095                                 tvbs[i] = get_data_source_tvb(src);
2096                         }
2097
2098                         tvbs[count] = NULL;
2099                 }
2100
2101                 sharkd_session_process_frame_cb_tree(tree, tvbs);
2102
2103                 g_free(tvbs);
2104         }
2105
2106         if (cinfo)
2107         {
2108                 int col;
2109
2110                 printf(",\"col\":[");
2111                 for (col = 0; col < cinfo->num_cols; ++col)
2112                 {
2113                         const col_item_t *col_item = &cinfo->columns[col];
2114
2115                         printf("%s\"%s\"", (col) ? "," : "", col_item->col_data);
2116                 }
2117                 printf("]");
2118         }
2119
2120         if (data_src)
2121         {
2122                 struct data_source *src = (struct data_source *)data_src->data;
2123                 const char *ds_sepa = NULL;
2124
2125                 tvbuff_t *tvb;
2126                 guint length;
2127
2128                 tvb = get_data_source_tvb(src);
2129                 length = tvb_captured_length(tvb);
2130
2131                 printf(",\"bytes\":");
2132                 if (length != 0)
2133                 {
2134                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2135
2136                         /* XXX pi.fd->flags.encoding */
2137                         json_print_base64(cp, length);
2138                 }
2139                 else
2140                 {
2141                         json_print_base64("", 0);
2142                 }
2143
2144                 data_src = data_src->next;
2145                 if (data_src)
2146                 {
2147                         printf(",\"ds\":[");
2148                         ds_sepa = "";
2149                 }
2150
2151                 while (data_src)
2152                 {
2153                         src = (struct data_source *)data_src->data;
2154
2155                         {
2156                                 char *src_name = get_data_source_name(src);
2157
2158                                 printf("%s{\"name\":", ds_sepa);
2159                                 json_puts_string(src_name);
2160                                 wmem_free(NULL, src_name);
2161                         }
2162
2163                         tvb = get_data_source_tvb(src);
2164                         length = tvb_captured_length(tvb);
2165
2166                         printf(",\"bytes\":");
2167                         if (length != 0)
2168                         {
2169                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
2170
2171                                 /* XXX pi.fd->flags.encoding */
2172                                 json_print_base64(cp, length);
2173                         }
2174                         else
2175                         {
2176                                 json_print_base64("", 0);
2177                         }
2178
2179                         printf("}");
2180                         ds_sepa = ",";
2181
2182                         data_src = data_src->next;
2183                 }
2184
2185                 /* close ds, only if was opened */
2186                 if (ds_sepa != NULL)
2187                         printf("]");
2188         }
2189
2190         printf(",\"fol\":[0");
2191         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
2192         printf("]");
2193
2194         printf("}\n");
2195 }
2196
2197 /**
2198  * sharkd_session_process_intervals()
2199  *
2200  * Process intervals request - generate basic capture file statistics per requested interval.
2201  *
2202  * Input:
2203  *   (o) interval - interval time in ms, if not specified: 1000ms
2204  *   (o) filter   - filter for generating interval request
2205  *
2206  * Output object with attributes:
2207  *   (m) intervals - array of intervals, with indexes:
2208  *             [0] - index of interval,
2209  *             [1] - number of frames during interval,
2210  *             [2] - number of bytes during interval.
2211  *
2212  *   (m) last   - last interval number.
2213  *   (m) frames - total number of frames
2214  *   (m) bytes  - total number of bytes
2215  *
2216  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
2217  */
2218 static void
2219 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
2220 {
2221         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
2222         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2223
2224         const guint8 *filter_data = NULL;
2225
2226         struct
2227         {
2228                 unsigned int frames;
2229                 guint64 bytes;
2230         } st, st_total;
2231
2232         nstime_t *start_ts = NULL;
2233
2234         guint32 interval_ms = 1000; /* default: one per second */
2235
2236         const char *sepa = "";
2237         unsigned int framenum;
2238         gint64 idx;
2239         gint64 max_idx = 0;
2240
2241         if (tok_interval) {
2242                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0) {
2243                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
2244                         return;
2245                 }
2246         }
2247
2248         if (tok_filter)
2249         {
2250                 filter_data = sharkd_session_filter_data(tok_filter);
2251                 if (!filter_data)
2252                         return;
2253         }
2254
2255         st_total.frames = 0;
2256         st_total.bytes  = 0;
2257
2258         st.frames = 0;
2259         st.bytes  = 0;
2260
2261         idx = 0;
2262
2263         printf("{\"intervals\":[");
2264
2265         for (framenum = 1; framenum <= cfile.count; framenum++)
2266         {
2267                 frame_data *fdata = frame_data_sequence_find(cfile.frames, framenum);
2268                 gint64 msec_rel;
2269                 gint64 new_idx;
2270
2271                 if (start_ts == NULL)
2272                         start_ts = &fdata->abs_ts;
2273
2274                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
2275                         continue;
2276
2277                 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
2278                 new_idx  = msec_rel / interval_ms;
2279
2280                 if (idx != new_idx)
2281                 {
2282                         if (st.frames != 0)
2283                         {
2284                                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
2285                                 sepa = ",";
2286                         }
2287
2288                         idx = new_idx;
2289                         if (idx > max_idx)
2290                                 max_idx = idx;
2291
2292                         st.frames = 0;
2293                         st.bytes  = 0;
2294                 }
2295
2296                 st.frames += 1;
2297                 st.bytes  += fdata->pkt_len;
2298
2299                 st_total.frames += 1;
2300                 st_total.bytes  += fdata->pkt_len;
2301         }
2302
2303         if (st.frames != 0)
2304         {
2305                 printf("%s[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", sepa, idx, st.frames, st.bytes);
2306                 /* sepa = ","; */
2307         }
2308
2309         printf("],\"last\":%" G_GINT64_FORMAT ",\"frames\":%u,\"bytes\":%" G_GUINT64_FORMAT "}\n", max_idx, st_total.frames, st_total.bytes);
2310 }
2311
2312 /**
2313  * sharkd_session_process_frame()
2314  *
2315  * Process frame request
2316  *
2317  * Input:
2318  *   (m) frame - requested frame number
2319  *   (o) proto - set if output frame tree
2320  *   (o) columns - set if output frame columns
2321  *   (o) bytes - set if output frame bytes
2322  *
2323  * Output object with attributes:
2324  *   (m) err   - 0 if succeed
2325  *   (o) tree  - array of frame nodes with attributes:
2326  *                  l - label
2327  *                  t: 'proto', 'framenum', 'url' - type of node
2328  *                  s - severity
2329  *                  e - subtree ett index
2330  *                  n - array of subtree nodes
2331  *                  h - two item array: (item start, item length)
2332  *                  i - two item array: (appendix start, appendix length)
2333  *                  p - [RESERVED] two item array: (protocol start, protocol length)
2334  *                  ds- data src index
2335  *                  url  - only for t:'url', url
2336  *                  fnum - only for t:'framenum', frame number
2337  *
2338  *   (o) col   - array of column data
2339  *   (o) bytes - base64 of frame bytes
2340  *   (o) ds    - array of other data srcs
2341  *   (o) fol   - array of follow filters:
2342  *                  [0] - protocol
2343  *                  [1] - filter string
2344  */
2345 static void
2346 sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
2347 {
2348         const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
2349         int tok_proto   = (json_find_attr(buf, tokens, count, "proto") != NULL);
2350         int tok_bytes   = (json_find_attr(buf, tokens, count, "bytes") != NULL);
2351         int tok_columns = (json_find_attr(buf, tokens, count, "columns") != NULL);
2352
2353         guint32 framenum;
2354
2355         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
2356                 return;
2357
2358         sharkd_dissect_request(framenum, &sharkd_session_process_frame_cb, tok_bytes, tok_columns, tok_proto, NULL);
2359 }
2360
2361 /**
2362  * sharkd_session_process_check()
2363  *
2364  * Process check request.
2365  *
2366  * Input:
2367  *   (o) filter - filter to be checked
2368  *
2369  * Output object with attributes:
2370  *   (m) err - always 0
2371  *   (o) filter - 'ok', 'warn' or error message
2372  */
2373 static int
2374 sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
2375 {
2376         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2377
2378         printf("{\"err\":0");
2379         if (tok_filter != NULL)
2380         {
2381                 char *err_msg = NULL;
2382                 dfilter_t *dfp;
2383
2384                 if (dfilter_compile(tok_filter, &dfp, &err_msg))
2385                 {
2386                         const char *s = "ok";
2387
2388                         if (dfilter_deprecated_tokens(dfp))
2389                                 s = "warn";
2390
2391                         printf(",\"filter\":\"%s\"", s);
2392                         dfilter_free(dfp);
2393                 }
2394                 else
2395                 {
2396                         printf(",\"filter\":");
2397                         json_puts_string(err_msg);
2398                         g_free(err_msg);
2399                 }
2400         }
2401
2402         printf("}\n");
2403         return 0;
2404 }
2405
2406 struct sharkd_session_process_complete_pref_data
2407 {
2408         const char *module;
2409         const char *pref;
2410         const char *sepa;
2411 };
2412
2413 static guint
2414 sharkd_session_process_complete_pref_cb(module_t *module, gpointer d)
2415 {
2416         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
2417
2418         if (strncmp(data->pref, module->name, strlen(data->pref)) != 0)
2419                 return 0;
2420
2421         printf("%s{\"f\":\"%s\",\"d\":\"%s\"}", data->sepa, module->name, module->title);
2422         data->sepa = ",";
2423
2424         return 0;
2425 }
2426
2427 static guint
2428 sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d)
2429 {
2430         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
2431         const char *pref_name = prefs_get_name(pref);
2432         const char *pref_title = prefs_get_title(pref);
2433
2434         if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0)
2435                 return 0;
2436
2437         printf("%s{\"f\":\"%s.%s\",\"d\":\"%s\"}", data->sepa, data->module, pref_name, pref_title);
2438         data->sepa = ",";
2439
2440         return 0; /* continue */
2441 }
2442
2443 /**
2444  * sharkd_session_process_complete()
2445  *
2446  * Process complete request
2447  *
2448  * Input:
2449  *   (o) field - field to be completed
2450  *   (o) pref  - preference to be completed
2451  *
2452  * Output object with attributes:
2453  *   (m) err - always 0
2454  *   (o) field - array of object with attributes:
2455  *                  (m) f - field text
2456  *                  (o) t - field type (FT_ number)
2457  *                  (o) n - field name
2458  *   (o) pref  - array of object with attributes:
2459  *                  (m) f - pref name
2460  *                  (o) d - pref description
2461  */
2462 static int
2463 sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count)
2464 {
2465         const char *tok_field = json_find_attr(buf, tokens, count, "field");
2466         const char *tok_pref  = json_find_attr(buf, tokens, count, "pref");
2467
2468         printf("{\"err\":0");
2469         if (tok_field != NULL && tok_field[0])
2470         {
2471                 const size_t filter_length = strlen(tok_field);
2472                 const int filter_with_dot = !!strchr(tok_field, '.');
2473
2474                 void *proto_cookie;
2475                 void *field_cookie;
2476                 int proto_id;
2477                 const char *sepa = "";
2478
2479                 printf(",\"field\":[");
2480
2481                 for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie))
2482                 {
2483                         protocol_t *protocol = find_protocol_by_id(proto_id);
2484                         const char *protocol_filter;
2485                         const char *protocol_name;
2486                         header_field_info *hfinfo;
2487
2488                         if (!proto_is_protocol_enabled(protocol))
2489                                 continue;
2490
2491                         protocol_name   = proto_get_protocol_long_name(protocol);
2492                         protocol_filter = proto_get_protocol_filter_name(proto_id);
2493
2494                         if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length))
2495                         {
2496                                 printf("%s{", sepa);
2497                                 {
2498                                         printf("\"f\":");
2499                                         json_puts_string(protocol_filter);
2500                                         printf(",\"t\":%d", FT_PROTOCOL);
2501                                         printf(",\"n\":");
2502                                         json_puts_string(protocol_name);
2503                                 }
2504                                 printf("}");
2505                                 sepa = ",";
2506                         }
2507
2508                         if (!filter_with_dot)
2509                                 continue;
2510
2511                         for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie))
2512                         {
2513                                 if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
2514                                         continue;
2515
2516                                 if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length))
2517                                 {
2518                                         printf("%s{", sepa);
2519                                         {
2520                                                 printf("\"f\":");
2521                                                 json_puts_string(hfinfo->abbrev);
2522
2523                                                 /* XXX, skip displaying name, if there are multiple (to not confuse user) */
2524                                                 if (hfinfo->same_name_next == NULL)
2525                                                 {
2526                                                         printf(",\"t\":%d", hfinfo->type);
2527                                                         printf(",\"n\":");
2528                                                         json_puts_string(hfinfo->name);
2529                                                 }
2530                                         }
2531                                         printf("}");
2532                                         sepa = ",";
2533                                 }
2534                         }
2535                 }
2536
2537                 printf("]");
2538         }
2539
2540         if (tok_pref != NULL && tok_pref[0])
2541         {
2542                 struct sharkd_session_process_complete_pref_data data;
2543                 char *dot_sepa;
2544
2545                 data.module = tok_pref;
2546                 data.pref = tok_pref;
2547                 data.sepa = "";
2548
2549                 printf(",\"pref\":[");
2550
2551                 if ((dot_sepa = strchr(tok_pref, '.')))
2552                 {
2553                         module_t *pref_mod;
2554
2555                         *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
2556                         data.pref = dot_sepa + 1;
2557
2558                         pref_mod = prefs_find_module(data.module);
2559                         if (pref_mod)
2560                                 prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data);
2561
2562                         *dot_sepa = '.';
2563                 }
2564                 else
2565                 {
2566                         prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data);
2567                 }
2568
2569                 printf("]");
2570         }
2571
2572
2573         printf("}\n");
2574         return 0;
2575 }
2576
2577 /**
2578  * sharkd_session_process_setconf()
2579  *
2580  * Process setconf request
2581  *
2582  * Input:
2583  *   (m) name  - preference name
2584  *   (m) value - preference value
2585  *
2586  * Output object with attributes:
2587  *   (m) err   - error code: 0 succeed
2588  */
2589 static void
2590 sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count)
2591 {
2592         const char *tok_name = json_find_attr(buf, tokens, count, "name");
2593         const char *tok_value = json_find_attr(buf, tokens, count, "value");
2594         char pref[4096];
2595
2596         prefs_set_pref_e ret;
2597
2598         if (!tok_name || tok_name[0] == '\0' || !tok_value)
2599                 return;
2600
2601         ws_snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value);
2602
2603         ret = prefs_set_pref(pref);
2604         printf("{\"err\":%d}\n", ret);
2605 }
2606
2607 struct sharkd_session_process_dumpconf_data
2608 {
2609         module_t *module;
2610         const char *sepa;
2611 };
2612
2613 static guint
2614 sharkd_session_process_dumpconf_cb(pref_t *pref, gpointer d)
2615 {
2616         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
2617         const char *pref_name = prefs_get_name(pref);
2618
2619         printf("%s\"%s.%s\":{", data->sepa, data->module->name, pref_name);
2620
2621         switch (prefs_get_type(pref))
2622         {
2623                 case PREF_UINT:
2624                 case PREF_DECODE_AS_UINT:
2625                         printf("\"u\":%u", prefs_get_uint_value_real(pref, pref_current));
2626                         if (prefs_get_uint_base(pref) != 10)
2627                                 printf(",\"ub\":%u", prefs_get_uint_base(pref));
2628                         break;
2629
2630                 case PREF_BOOL:
2631                         printf("\"b\":%s", prefs_get_bool_value(pref, pref_current) ? "1" : "0");
2632                         break;
2633
2634                 case PREF_STRING:
2635                         printf("\"s\":");
2636                         json_puts_string(prefs_get_string_value(pref, pref_current));
2637                         break;
2638
2639                 case PREF_ENUM:
2640                 {
2641                         const enum_val_t *enums;
2642                         const char *enum_sepa = "";
2643
2644                         printf("\"e\":[");
2645                         for (enums = prefs_get_enumvals(pref); enums->name; enums++)
2646                         {
2647                                 printf("%s{\"v\":%d", enum_sepa, enums->value);
2648
2649                                 if (enums->value == prefs_get_enum_value(pref, pref_current))
2650                                         printf(",\"s\":1");
2651
2652                                 printf(",\"d\":");
2653                                 json_puts_string(enums->description);
2654
2655                                 printf("}");
2656                                 enum_sepa = ",";
2657                         }
2658                         printf("]");
2659                         break;
2660                 }
2661
2662                 case PREF_RANGE:
2663                 case PREF_DECODE_AS_RANGE:
2664                 {
2665                         char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
2666                         printf("\"r\":\"%s\"", range_str);
2667                         wmem_free(NULL, range_str);
2668                         break;
2669                 }
2670
2671                 case PREF_UAT:
2672                 case PREF_COLOR:
2673                 case PREF_CUSTOM:
2674                 case PREF_STATIC_TEXT:
2675                 case PREF_OBSOLETE:
2676                         /* TODO */
2677                         break;
2678         }
2679
2680 #if 0
2681         printf(",\"t\":");
2682         json_puts_string(prefs_get_title(pref));
2683 #endif
2684
2685         printf("}");
2686         data->sepa = ",";
2687
2688         return 0; /* continue */
2689 }
2690
2691 static guint
2692 sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d)
2693 {
2694         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
2695
2696         data->module = module;
2697         prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data);
2698
2699         return 0;
2700 }
2701
2702 /**
2703  * sharkd_session_process_dumpconf()
2704  *
2705  * Process dumpconf request
2706  *
2707  * Input:
2708  *   (o) pref - module, or preference, NULL for all
2709  *
2710  * Output object with attributes:
2711  *   (o) prefs   - object with module preferences
2712  *                  (m) [KEY] - preference name
2713  *                  (o) u - preference value (only for PREF_UINT)
2714  *                  (o) ub - preference value suggested base for display (only for PREF_UINT) and if different than 10
2715  *                  (o) b - preference value (only for PREF_BOOL) (1 true, 0 false)
2716  *                  (o) s - preference value (only for PREF_STRING)
2717  *                  (o) e - preference possible values (only for PREF_ENUM)
2718  *                  (o) r - preference value (only for PREF_RANGE)
2719  *                  (o) t - preference value (only for PREF_UAT)
2720  */
2721 static void
2722 sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
2723 {
2724         const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
2725         module_t *pref_mod;
2726         char *dot_sepa;
2727
2728         if (!tok_pref)
2729         {
2730                 struct sharkd_session_process_dumpconf_data data;
2731
2732                 data.module = NULL;
2733                 data.sepa = "";
2734
2735                 printf("{\"prefs\":{");
2736                 prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data);
2737                 printf("}}\n");
2738                 return;
2739         }
2740
2741         if ((dot_sepa = strchr(tok_pref, '.')))
2742         {
2743                 pref_t *pref = NULL;
2744
2745                 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
2746                 pref_mod = prefs_find_module(tok_pref);
2747                 if (pref_mod)
2748                         pref = prefs_find_preference(pref_mod, dot_sepa + 1);
2749                 *dot_sepa = '.';
2750
2751                 if (pref)
2752                 {
2753                         struct sharkd_session_process_dumpconf_data data;
2754
2755                         data.module = pref_mod;
2756                         data.sepa = "";
2757
2758                         printf("{\"prefs\":{");
2759                         sharkd_session_process_dumpconf_cb(pref, &data);
2760                         printf("}}\n");
2761                 }
2762
2763                 return;
2764         }
2765
2766         pref_mod = prefs_find_module(tok_pref);
2767         if (pref_mod)
2768         {
2769                 struct sharkd_session_process_dumpconf_data data;
2770
2771                 data.module = pref_mod;
2772                 data.sepa = "";
2773
2774                 printf("{\"prefs\":{");
2775                 prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data);
2776                 printf("}}\n");
2777     }
2778 }
2779
2780 /**
2781  * sharkd_session_process_download()
2782  *
2783  * Process download request
2784  *
2785  * Input:
2786  *   (m) token  - token to download
2787  *
2788  * Output object with attributes:
2789  *   (o) file - suggested name of file
2790  *   (o) mime - suggested content type
2791  *   (o) data - payload base64 encoded
2792  */
2793 static void
2794 sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
2795 {
2796         const char *tok_token      = json_find_attr(buf, tokens, count, "token");
2797
2798         if (!tok_token)
2799                 return;
2800
2801         if (!strncmp(tok_token, "eo:", 3))
2802         {
2803                 struct sharkd_export_object_list *object_list;
2804                 const export_object_entry_t *eo_entry = NULL;
2805
2806                 for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
2807                 {
2808                         size_t eo_type_len = strlen(object_list->type);
2809
2810                         if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
2811                         {
2812                                 int row;
2813
2814                                 if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1)
2815                                         break;
2816
2817                                 eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
2818                                 break;
2819                         }
2820                 }
2821
2822                 if (eo_entry)
2823                 {
2824                         const char *mime     = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
2825                         const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
2826
2827                         printf("{\"file\":");
2828                         json_puts_string(filename);
2829                         printf(",\"mime\":");
2830                         json_puts_string(mime);
2831                         printf(",\"data\":");
2832                         json_print_base64(eo_entry->payload_data, (int) eo_entry->payload_len); /* XXX, export object will be truncated if >= 2^31 */
2833                         printf("}\n");
2834                 }
2835         }
2836         else if (!strcmp(tok_token, "ssl-secrets"))
2837         {
2838                 char *str = ssl_export_sessions();
2839
2840                 if (str)
2841                 {
2842                         const char *mime     = "text/plain";
2843                         const char *filename = "keylog.txt";
2844
2845                         printf("{\"file\":");
2846                         json_puts_string(filename);
2847                         printf(",\"mime\":");
2848                         json_puts_string(mime);
2849                         printf(",\"data\":");
2850                         json_print_base64(str, strlen(str));
2851                         printf("}\n");
2852                 }
2853                 g_free(str);
2854         }
2855 }
2856
2857 static void
2858 sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
2859 {
2860         int i;
2861
2862         /* sanity check, and split strings */
2863         if (count < 1 || tokens[0].type != JSMN_OBJECT)
2864         {
2865                 fprintf(stderr, "sanity check(1): [0] not object\n");
2866                 return;
2867         }
2868
2869         /* don't need [0] token */
2870         tokens++;
2871         count--;
2872
2873         if (count & 1)
2874         {
2875                 fprintf(stderr, "sanity check(2): %d not even\n", count);
2876                 return;
2877         }
2878
2879         for (i = 0; i < count; i += 2)
2880         {
2881                 if (tokens[i].type != JSMN_STRING)
2882                 {
2883                         fprintf(stderr, "sanity check(3): [%d] not string\n", i);
2884                         return;
2885                 }
2886
2887                 buf[tokens[i + 0].end] = '\0';
2888                 buf[tokens[i + 1].end] = '\0';
2889
2890                 json_unescape_str(&buf[tokens[i + 0].start]);
2891                 json_unescape_str(&buf[tokens[i + 1].start]);
2892         }
2893
2894         {
2895                 const char *tok_req = json_find_attr(buf, tokens, count, "req");
2896
2897                 if (!tok_req)
2898                 {
2899                         fprintf(stderr, "sanity check(4): no \"req\".\n");
2900                         return;
2901                 }
2902
2903                 if (!strcmp(tok_req, "load"))
2904                         sharkd_session_process_load(buf, tokens, count);
2905                 else if (!strcmp(tok_req, "status"))
2906                         sharkd_session_process_status();
2907                 else if (!strcmp(tok_req, "analyse"))
2908                         sharkd_session_process_analyse();
2909                 else if (!strcmp(tok_req, "info"))
2910                         sharkd_session_process_info();
2911                 else if (!strcmp(tok_req, "check"))
2912                         sharkd_session_process_check(buf, tokens, count);
2913                 else if (!strcmp(tok_req, "complete"))
2914                         sharkd_session_process_complete(buf, tokens, count);
2915                 else if (!strcmp(tok_req, "frames"))
2916                         sharkd_session_process_frames(buf, tokens, count);
2917                 else if (!strcmp(tok_req, "tap"))
2918                         sharkd_session_process_tap(buf, tokens, count);
2919                 else if (!strcmp(tok_req, "follow"))
2920                         sharkd_session_process_follow(buf, tokens, count);
2921                 else if (!strcmp(tok_req, "intervals"))
2922                         sharkd_session_process_intervals(buf, tokens, count);
2923                 else if (!strcmp(tok_req, "frame"))
2924                         sharkd_session_process_frame(buf, tokens, count);
2925                 else if (!strcmp(tok_req, "setconf"))
2926                         sharkd_session_process_setconf(buf, tokens, count);
2927                 else if (!strcmp(tok_req, "dumpconf"))
2928                         sharkd_session_process_dumpconf(buf, tokens, count);
2929                 else if (!strcmp(tok_req, "download"))
2930                         sharkd_session_process_download(buf, tokens, count);
2931                 else if (!strcmp(tok_req, "bye"))
2932                         exit(0);
2933                 else
2934                         fprintf(stderr, "::: req = %s\n", tok_req);
2935
2936                 /* reply for every command are 0+ lines of JSON reply (outputed above), finished by empty new line */
2937                 printf("\n");
2938
2939                 /*
2940                  * We do an explicit fflush after every line, because
2941                  * we want output to be written to the socket as soon
2942                  * as the line is complete.
2943                  *
2944                  * The stream is fully-buffered by default, so it's
2945                  * only flushed when the buffer fills or the FILE *
2946                  * is closed.  On UN*X, we could set it to be line
2947                  * buffered, but the MSVC standard I/O routines don't
2948                  * support line buffering - they only support *byte*
2949                  * buffering, doing a write for every byte written,
2950                  * which is too inefficient, and full buffering,
2951                  * which is what you get if you request line buffering.
2952                  */
2953                 fflush(stdout);
2954         }
2955 }
2956
2957 int
2958 sharkd_session_main(void)
2959 {
2960         char buf[16 * 1024];
2961         jsmntok_t *tokens = NULL;
2962         int tokens_max = -1;
2963
2964         fprintf(stderr, "Hello in child.\n");
2965
2966         while (fgets(buf, sizeof(buf), stdin))
2967         {
2968                 /* every command is line seperated JSON */
2969                 int ret;
2970
2971                 ret = wsjsmn_parse(buf, NULL, 0);
2972                 if (ret < 0)
2973                 {
2974                         fprintf(stderr, "invalid JSON -> closing\n");
2975                         return 1;
2976                 }
2977
2978                 /* fprintf(stderr, "JSON: %d tokens\n", ret); */
2979                 ret += 1;
2980
2981                 if (tokens == NULL || tokens_max < ret)
2982                 {
2983                         tokens_max = ret;
2984                         tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max);
2985                 }
2986
2987                 memset(tokens, 0, ret * sizeof(jsmntok_t));
2988
2989                 ret = wsjsmn_parse(buf, tokens, ret);
2990                 if (ret < 0)
2991                 {
2992                         fprintf(stderr, "invalid JSON(2) -> closing\n");
2993                         return 2;
2994                 }
2995
2996                 sharkd_session_process(buf, tokens, ret);
2997         }
2998
2999         g_free(tokens);
3000
3001         return 0;
3002 }
3003
3004 /*
3005  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3006  *
3007  * Local variables:
3008  * c-basic-offset: 8
3009  * tab-width: 8
3010  * indent-tabs-mode: t
3011  * End:
3012  *
3013  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
3014  * :indentSize=8:tabSize=8:noTabs=false:
3015  */