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