2 * Routines for printing packet analysis trees.
4 * Gilbert Ramirez <gram@alumni.rice.edu>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/epan.h>
32 #include <epan/epan_dissect.h>
33 #include <epan/to_str.h>
34 #include <epan/expert.h>
35 #include <epan/column-info.h>
36 #include <epan/color_filters.h>
37 #include <epan/prefs.h>
38 #include <epan/print.h>
39 #include <epan/charsets.h>
40 #include <wsutil/filesystem.h>
41 #include <ws_version_info.h>
42 #include <wsutil/utf8_entities.h>
43 #include <ftypes/ftypes-int.h>
45 #define PDML_VERSION "0"
46 #define PSML_VERSION "0"
50 print_stream_t *stream;
53 print_dissections_e print_dissections;
54 gboolean print_hex_for_data;
55 packet_char_enc encoding;
56 GHashTable *output_only_tables; /* output only these protocols */
64 pf_flags filter_flags;
72 pf_flags filter_flags;
78 output_fields_t *fields;
82 struct _output_fields {
84 gboolean print_header;
89 GHashTable *field_indicies;
90 GPtrArray **field_values;
92 gboolean includes_col_fields;
95 static gchar *get_field_hex_value(GSList *src_list, field_info *fi);
96 static void proto_tree_print_node(proto_node *node, gpointer data);
97 static void proto_tree_write_node_pdml(proto_node *node, gpointer data);
98 static void proto_tree_write_node_ek(proto_node *node, gpointer data);
99 static const guint8 *get_field_data(GSList *src_list, field_info *fi);
100 static void pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi);
101 static void json_write_field_hex_value(write_json_data *pdata, field_info *fi);
102 static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
103 guint length, packet_char_enc encoding);
104 static void write_specified_fields(fields_format format,
105 output_fields_t *fields,
106 epan_dissect_t *edt, column_info *cinfo,
108 static void print_escaped_xml(FILE *fh, const char *unescaped_string);
109 static void print_escaped_json(FILE *fh, const char *unescaped_string);
110 static void print_escaped_ek(FILE *fh, const char *unescaped_string);
112 typedef void (*proto_node_value_writer)(proto_node *, write_json_data *);
113 static void write_json_proto_node_list(GSList *proto_node_list_head, write_json_data *data);
114 static void write_json_proto_node(GSList *node_values_head,
116 proto_node_value_writer value_writer,
117 write_json_data *data);
118 static void write_json_proto_node_value_list(GSList *node_values_head,
119 proto_node_value_writer value_writer,
120 write_json_data *data);
121 static void write_json_proto_node_filtered(proto_node *node, write_json_data *data);
122 static void write_json_proto_node_hex_dump(proto_node *node, write_json_data *data);
123 static void write_json_proto_node_children(proto_node *node, write_json_data *data);
124 static void write_json_proto_node_value(proto_node *node, write_json_data *data);
126 typedef GSList* (*proto_node_children_grouper_func)(proto_node *node);
127 static void write_json_proto_node_no_value(proto_node *node, write_json_data *data);
128 static GSList *proto_node_group_children_by_unique(proto_node *node);
130 static const char *proto_node_to_json_key(proto_node *node);
132 static void print_pdml_geninfo(epan_dissect_t *edt, FILE *fh);
134 static void proto_tree_get_node_field_values(proto_node *node, gpointer data);
136 static gboolean json_is_first;
138 // Function used to group a node's children. Children in the same group are represented in the json output by a single
139 // json key. If multiple nodes are in a group they are wrapped in a json array in the json output.
140 static proto_node_children_grouper_func json_proto_node_children_grouper = proto_node_group_children_by_unique;
142 /* Cache the protocols and field handles that the print functionality needs
143 This helps break explicit dependency on the dissectors. */
144 static int proto_data = -1;
145 static int proto_frame = -1;
147 void print_cache_field_handles(void)
149 proto_data = proto_get_id_by_short_name("Data");
150 proto_frame = proto_get_id_by_short_name("Frame");
154 proto_tree_print(print_dissections_e print_dissections, gboolean print_hex,
155 epan_dissect_t *edt, GHashTable *output_only_tables,
156 print_stream_t *stream)
160 /* Create the output */
162 data.stream = stream;
164 data.src_list = edt->pi.data_src;
165 data.encoding = (packet_char_enc)edt->pi.fd->flags.encoding;
166 data.print_dissections = print_dissections;
167 /* If we're printing the entire packet in hex, don't
168 print uninterpreted data fields in hex as well. */
169 data.print_hex_for_data = !print_hex;
170 data.output_only_tables = output_only_tables;
172 proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
176 /* Print a tree's data, and any child nodes. */
178 proto_tree_print_node(proto_node *node, gpointer data)
180 field_info *fi = PNODE_FINFO(node);
181 print_data *pdata = (print_data*) data;
183 gchar label_str[ITEM_LABEL_LENGTH];
186 /* dissection with an invisible proto tree? */
189 /* Don't print invisible entries. */
190 if (PROTO_ITEM_IS_HIDDEN(node) && (prefs.display_hidden_proto_items == FALSE))
193 /* Give up if we've already gotten an error. */
197 /* was a free format label produced? */
199 label_ptr = fi->rep->representation;
201 else { /* no, make a generic label */
202 label_ptr = label_str;
203 proto_item_fill_label(fi, label_str);
206 if (PROTO_ITEM_IS_GENERATED(node))
207 label_ptr = g_strconcat("[", label_ptr, "]", NULL);
209 pdata->success = print_line(pdata->stream, pdata->level, label_ptr);
211 if (PROTO_ITEM_IS_GENERATED(node))
218 * If -O is specified, only display the protocols which are in the
219 * lookup table. Only check on the first level: once we start printing
220 * a tree, print the rest of the subtree. Otherwise we won't print
221 * subitems whose abbreviation doesn't match the protocol--for example
222 * text items (whose abbreviation is simply "text").
224 if ((pdata->output_only_tables != NULL) && (pdata->level == 0)
225 && (g_hash_table_lookup(pdata->output_only_tables, fi->hfinfo->abbrev) == NULL)) {
229 /* If it's uninterpreted data, dump it (unless our caller will
230 be printing the entire packet in hex). */
231 if ((fi->hfinfo->id == proto_data) && (pdata->print_hex_for_data)) {
233 * Find the data for this field.
235 pd = get_field_data(pdata->src_list, fi);
237 if (!print_line(pdata->stream, 0, "")) {
238 pdata->success = FALSE;
241 if (!print_hex_data_buffer(pdata->stream, pd,
242 fi->length, pdata->encoding)) {
243 pdata->success = FALSE;
249 /* If we're printing all levels, or if this node is one with a
250 subtree and its subtree is expanded, recurse into the subtree,
252 g_assert((fi->tree_type >= -1) && (fi->tree_type < num_tree_types));
253 if ((pdata->print_dissections == print_dissections_expanded) ||
254 ((pdata->print_dissections == print_dissections_as_displayed) &&
255 (fi->tree_type >= 0) && tree_expanded(fi->tree_type))) {
256 if (node->first_child != NULL) {
258 proto_tree_children_foreach(node,
259 proto_tree_print_node, pdata);
267 #define PDML2HTML_XSL "pdml2html.xsl"
269 write_pdml_preamble(FILE *fh, const gchar *filename)
271 time_t t = time(NULL);
272 struct tm * timeinfo;
276 /* Create the output */
277 timeinfo = localtime(&t);
278 if (timeinfo != NULL) {
279 fmt_ts = asctime(timeinfo);
280 fmt_ts[strlen(fmt_ts)-1] = 0; /* overwrite \n */
283 ts = "Not representable";
285 fprintf(fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
286 fprintf(fh, "<?xml-stylesheet type=\"text/xsl\" href=\"" PDML2HTML_XSL "\"?>\n");
287 fprintf(fh, "<!-- You can find " PDML2HTML_XSL " in %s or at https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=" PDML2HTML_XSL ". -->\n", get_datafile_dir());
288 fprintf(fh, "<pdml version=\"" PDML_VERSION "\" creator=\"%s/%s\" time=\"%s\" capture_file=\"", PACKAGE, VERSION, ts);
290 /* \todo filename should be converted to UTF-8. */
291 print_escaped_xml(fh, filename);
293 fprintf(fh, "\">\n");
296 /* Check if the str match the protocolfilter. json_filter is space
297 delimited string and str need to exact-match to one of the value. */
298 static gboolean check_protocolfilter(gchar **protocolfilter, const char *str)
300 gboolean res = FALSE;
303 if (str == NULL || protocolfilter == NULL) {
307 for (ptr = protocolfilter; *ptr; ptr++) {
308 if (strcmp(*ptr, str) == 0) {
318 write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh, gboolean use_color)
320 write_pdml_data data;
321 const color_filter_t *cfp = edt->pi.fd->color_filter;
326 /* Create the output */
327 if (use_color && (cfp != NULL)) {
328 fprintf(fh, "<packet foreground='#%02x%02x%02x' background='#%02x%02x%02x'>\n",
329 cfp->fg_color.red, cfp->fg_color.green, cfp->fg_color.blue,
330 cfp->bg_color.red, cfp->bg_color.green, cfp->bg_color.blue);
333 fprintf(fh, "<packet>\n");
336 /* Print a "geninfo" protocol as required by PDML */
337 print_pdml_geninfo(edt, fh);
339 if (fields == NULL || fields->fields == NULL) {
340 /* Write out all fields */
343 data.src_list = edt->pi.data_src;
344 data.filter = protocolfilter;
345 data.filter_flags = protocolfilter_flags;
347 proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
350 /* Write out specified fields */
351 write_specified_fields(FORMAT_XML, fields, edt, NULL, fh);
354 fprintf(fh, "</packet>\n\n");
358 write_ek_proto_tree(output_fields_t* fields,
359 gboolean print_hex, gchar **protocolfilter,
360 pf_flags protocolfilter_flags, epan_dissect_t *edt,
363 write_json_data data;
365 time_t t = time(NULL);
371 /* Create the output */
372 timeinfo = localtime(&t);
373 if (timeinfo != NULL)
374 strftime(ts, sizeof ts, "%Y-%m-%d", timeinfo);
376 g_strlcpy(ts, "XXXX-XX-XX", sizeof ts); /* XXX - better way of saying "Not representable"? */
378 fprintf(fh, "{\"index\" : {\"_index\": \"packets-%s\", \"_type\": \"pcap_file\", \"_score\": null}}\n", ts);
379 /* Timestamp added for time indexing in Elasticsearch */
380 fprintf(fh, "{\"timestamp\" : \"%" G_GUINT64_FORMAT "%03d\", \"layers\" : {", (guint64)edt->pi.abs_ts.secs, edt->pi.abs_ts.nsecs/1000000);
382 if (fields == NULL || fields->fields == NULL) {
383 /* Write out all fields */
386 data.src_list = edt->pi.data_src;
387 data.filter = protocolfilter;
388 data.filter_flags = protocolfilter_flags;
389 data.print_hex = print_hex;
391 proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek,
394 /* Write out specified fields */
395 write_specified_fields(FORMAT_EK, fields, edt, NULL, fh);
402 write_fields_proto_tree(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
407 /* Create the output */
408 write_specified_fields(FORMAT_CSV, fields, edt, cinfo, fh);
411 /* Indent to the correct level */
412 static void print_indent(int level, FILE *fh)
418 for (i = 0; i < level; i++) {
423 /* Write out a tree's data, and any child nodes, as PDML */
425 proto_tree_write_node_pdml(proto_node *node, gpointer data)
427 field_info *fi = PNODE_FINFO(node);
428 write_pdml_data *pdata = (write_pdml_data*) data;
429 const gchar *label_ptr;
430 gchar label_str[ITEM_LABEL_LENGTH];
431 char *dfilter_string;
432 gboolean wrap_in_fake_protocol;
434 /* dissection with an invisible proto tree? */
437 /* Will wrap up top-level field items inside a fake protocol wrapper to
438 preserve the PDML schema */
439 wrap_in_fake_protocol =
440 (((fi->hfinfo->type != FT_PROTOCOL) ||
441 (fi->hfinfo->id == proto_data)) &&
442 (pdata->level == 0));
444 print_indent(pdata->level + 1, pdata->fh);
446 if (wrap_in_fake_protocol) {
447 /* Open fake protocol wrapper */
448 fputs("<proto name=\"fake-field-wrapper\">\n", pdata->fh);
450 print_indent(pdata->level + 1, pdata->fh);
453 /* Text label. It's printed as a field with no name. */
454 if (fi->hfinfo->id == hf_text_only) {
457 label_ptr = fi->rep->representation;
463 /* Show empty name since it is a required field */
464 fputs("<field name=\"", pdata->fh);
465 fputs("\" show=\"", pdata->fh);
466 print_escaped_xml(pdata->fh, label_ptr);
468 fprintf(pdata->fh, "\" size=\"%d", fi->length);
469 if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
470 fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
472 fprintf(pdata->fh, "\" pos=\"%d", fi->start);
475 if (fi->length > 0) {
476 fputs("\" value=\"", pdata->fh);
477 pdml_write_field_hex_value(pdata, fi);
480 if (node->first_child != NULL) {
481 fputs("\">\n", pdata->fh);
484 fputs("\"/>\n", pdata->fh);
488 /* Uninterpreted data, i.e., the "Data" protocol, is
489 * printed as a field instead of a protocol. */
490 else if (fi->hfinfo->id == proto_data) {
491 /* Write out field with data */
492 fputs("<field name=\"data\" value=\"", pdata->fh);
493 pdml_write_field_hex_value(pdata, fi);
494 fputs("\">\n", pdata->fh);
496 /* Normal protocols and fields */
498 if ((fi->hfinfo->type == FT_PROTOCOL) && (fi->hfinfo->id != proto_expert)) {
499 fputs("<proto name=\"", pdata->fh);
502 fputs("<field name=\"", pdata->fh);
504 print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
508 * http://www.nbee.org/doku.php?id=netpdl:pdml_specification
510 * the show fields contains things in 'human readable' format
511 * showname: contains only the name of the field
512 * show: contains only the data of the field
513 * showdtl: contains additional details of the field data
514 * showmap: contains mappings of the field data (e.g. the hostname to an IP address)
516 * XXX - the showname shouldn't contain the field data itself
517 * (like it's contained in the fi->rep->representation).
518 * Unfortunately, we don't have the field data representation for
519 * all fields, so this isn't currently possible */
520 fputs("\" showname=\"", pdata->fh);
521 print_escaped_xml(pdata->fh, fi->hfinfo->name);
525 fputs("\" showname=\"", pdata->fh);
526 print_escaped_xml(pdata->fh, fi->rep->representation);
529 label_ptr = label_str;
530 proto_item_fill_label(fi, label_str);
531 fputs("\" showname=\"", pdata->fh);
532 print_escaped_xml(pdata->fh, label_ptr);
535 if (PROTO_ITEM_IS_HIDDEN(node) && (prefs.display_hidden_proto_items == FALSE))
536 fprintf(pdata->fh, "\" hide=\"yes");
538 fprintf(pdata->fh, "\" size=\"%d", fi->length);
539 if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
540 fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
542 fprintf(pdata->fh, "\" pos=\"%d", fi->start);
544 /* fprintf(pdata->fh, "\" id=\"%d", fi->hfinfo->id);*/
546 /* show, value, and unmaskedvalue attributes */
547 switch (fi->hfinfo->type)
552 fputs("\" show=\"\" value=\"", pdata->fh);
555 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
556 if (dfilter_string != NULL) {
558 fputs("\" show=\"", pdata->fh);
559 print_escaped_xml(pdata->fh, dfilter_string);
561 wmem_free(NULL, dfilter_string);
564 * XXX - should we omit "value" for any fields?
565 * What should we do for fields whose length is 0?
566 * They might come from a pseudo-header or from
567 * the capture header (e.g., time stamps), or
568 * they might be generated fields.
570 if (fi->length > 0) {
571 fputs("\" value=\"", pdata->fh);
573 if (fi->hfinfo->bitmask!=0) {
574 switch (fi->value.ftype->ftype) {
579 fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
585 fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
591 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
598 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
601 g_assert_not_reached();
603 fputs("\" unmaskedvalue=\"", pdata->fh);
604 pdml_write_field_hex_value(pdata, fi);
607 pdml_write_field_hex_value(pdata, fi);
612 if (node->first_child != NULL) {
613 fputs("\">\n", pdata->fh);
615 else if (fi->hfinfo->id == proto_data) {
616 fputs("\">\n", pdata->fh);
619 fputs("\"/>\n", pdata->fh);
623 /* We print some levels for PDML. Recurse here. */
624 if (node->first_child != NULL) {
625 if (pdata->filter == NULL || check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) {
626 gchar **_filter = NULL;
627 /* Remove protocol filter for children, if children should be included */
628 if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
629 _filter = pdata->filter;
630 pdata->filter = NULL;
634 proto_tree_children_foreach(node,
635 proto_tree_write_node_pdml, pdata);
638 /* Put protocol filter back */
639 if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
640 pdata->filter = _filter;
643 print_indent(pdata->level + 2, pdata->fh);
645 /* print dummy field */
646 fputs("<field name=\"filtered\" value=\"", pdata->fh);
647 print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
648 fputs("\" />\n", pdata->fh);
652 /* Take back the extra level we added for fake wrapper protocol */
653 if (wrap_in_fake_protocol) {
657 if (node->first_child != NULL) {
658 print_indent(pdata->level + 1, pdata->fh);
660 /* Close off current element */
661 /* Data and expert "protocols" use simple tags */
662 if ((fi->hfinfo->id != proto_data) && (fi->hfinfo->id != proto_expert)) {
663 if (fi->hfinfo->type == FT_PROTOCOL) {
664 fputs("</proto>\n", pdata->fh);
667 fputs("</field>\n", pdata->fh);
670 fputs("</field>\n", pdata->fh);
674 /* Close off fake wrapper protocol */
675 if (wrap_in_fake_protocol) {
676 fputs("</proto>\n", pdata->fh);
681 write_json_preamble(FILE *fh)
684 json_is_first = TRUE;
688 write_json_finale(FILE *fh)
690 fputs("\n\n]\n", fh);
694 write_json_proto_tree(output_fields_t* fields,
695 print_dissections_e print_dissections,
696 gboolean print_hex, gchar **protocolfilter,
697 pf_flags protocolfilter_flags, epan_dissect_t *edt,
701 time_t t = time(NULL);
702 struct tm * timeinfo;
703 write_json_data data;
705 if (!json_is_first) {
706 fputs("\n\n ,\n", fh);
708 json_is_first = FALSE;
711 timeinfo = localtime(&t);
712 if (timeinfo != NULL) {
713 strftime(ts, sizeof ts, "%Y-%m-%d", timeinfo);
715 g_strlcpy(ts, "XXXX-XX-XX", sizeof ts); /* XXX - better way of saying "Not representable"? */
719 fprintf(fh, " \"_index\": \"packets-%s\",\n", ts);
720 fputs(" \"_type\": \"pcap_file\",\n", fh);
721 fputs(" \"_score\": null,\n", fh);
722 fputs(" \"_source\": {\n", fh);
723 fputs(" \"layers\": ", fh);
725 if (fields == NULL || fields->fields == NULL) {
726 /* Write out all fields */
729 data.src_list = edt->pi.data_src;
730 data.filter = protocolfilter;
731 data.filter_flags = protocolfilter_flags;
732 data.print_hex = print_hex;
733 data.print_text = TRUE;
734 if (print_dissections == print_dissections_none) {
735 data.print_text = FALSE;
739 * Group nodes together by the key they will have in the json output. This is necessary to know which json keys
740 * have multiple values which need to be put in a json array in the output. A map is not required since we can
741 * easily retrieve the json key from the first value in the linked list.
743 GSList *same_key_nodes_list = json_proto_node_children_grouper(edt->tree);
744 write_json_proto_node_list(same_key_nodes_list, &data);
745 g_slist_free(same_key_nodes_list);
748 write_specified_fields(FORMAT_JSON, fields, edt, NULL, fh);
757 * Write a json object containing a list of key:value pairs where each key:value pair corresponds to a different json
758 * key and its associated nodes in the proto_tree.
759 * @param proto_node_list_head A 2-dimensional list containing a list of values for each different node json key. The
760 * elements themselves are a linked list of values associated with the same json key.
761 * @param data json writing metadata
764 write_json_proto_node_list(GSList *proto_node_list_head, write_json_data *data)
766 GSList *current_node = proto_node_list_head;
768 fputs("{\n", data->fh);
772 * In most of the following if statements we cannot be sure if its the first or last if statement to be
773 * executed. Thus we need a way of knowing whether a key:value pair has already been printed in order to know
774 * if a comma should be printed before the next key:value pair. We use the delimiter_needed variable to store
775 * whether a comma needs to be written before a new key:value pair is written. Note that instead of checking
776 * before writing a new key:value pair if a comma is needed we could also check after writing a key:value pair
777 * whether a comma is needed but this would be considerably more complex since after each if statement a
778 * different condition would have to be checked. After the first value is written a delimiter is always needed so
779 * this value is never set back to FALSE after it has been set to TRUE.
781 gboolean delimiter_needed = FALSE;
783 // Loop over each list of nodes (differentiated by json key) and write the associated json key:value pair in the
785 while (current_node != NULL) {
786 // Get the list of values for the current json key.
787 GSList *node_values_list = (GSList *) current_node->data;
789 // Retrieve the json key from the first value.
790 proto_node *first_value = (proto_node *) node_values_list->data;
791 const char *json_key = proto_node_to_json_key(first_value);
792 // Check if the current json key is filtered from the output with the "-j" cli option.
793 gboolean is_filtered = data->filter != NULL && !check_protocolfilter(data->filter, json_key);
795 field_info *fi = first_value->finfo;
796 char *value_string_repr = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
798 // We assume all values of a json key have roughly the same layout. Thus we can use the first value to derive
799 // attributes of all the values.
800 gboolean has_value = value_string_repr != NULL;
801 gboolean has_children = first_value->first_child != NULL;
802 gboolean is_pseudo_text_field = fi->hfinfo->id == 0;
804 wmem_free(NULL, value_string_repr); // fvalue_to_string_repr returns allocated buffer
806 // "-x" command line option. A "_raw" suffix is added to the json key so the textual value can be printed
807 // with the original json key. If both hex and text writing are enabled the raw information of fields whose
808 // length is equal to 0 is not written to the output. If the field is a special text pseudo field no raw
809 // information is written either.
810 if (data->print_hex && (!data->print_text || fi->length > 0) && !is_pseudo_text_field) {
811 if (delimiter_needed) fputs(",\n", data->fh);
812 write_json_proto_node(node_values_list, "_raw", write_json_proto_node_hex_dump, data);
813 delimiter_needed = TRUE;
816 if (data->print_text && has_value) {
817 if (delimiter_needed) fputs(",\n", data->fh);
818 write_json_proto_node(node_values_list, "", write_json_proto_node_value, data);
819 delimiter_needed = TRUE;
823 if (delimiter_needed) fputs(",\n", data->fh);
826 write_json_proto_node(node_values_list, "", write_json_proto_node_filtered, data);
829 // Remove protocol filter for children, if children should be included. This functionality is enabled
830 // with the "-J" command line option. We save the filter so it can be reenabled when we are done with
831 // the current key:value pair.
832 gchar **_filter = NULL;
833 if ((data->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
834 _filter = data->filter;
838 // If a node has both a value and a set of children we print the value and the children in separate
839 // key:value pairs. These can't have the same key so whenever a value is already printed with the node
840 // json key we print the children with the same key with a "_tree" suffix added.
842 write_json_proto_node(node_values_list, "_tree", write_json_proto_node_children, data);
844 write_json_proto_node(node_values_list, "", write_json_proto_node_children, data);
847 // Put protocol filter back
848 if ((data->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
849 data->filter = _filter;
853 delimiter_needed = TRUE;
856 if (!has_value && !has_children && (data->print_text || (data->print_hex && is_pseudo_text_field))) {
857 if (delimiter_needed) fputs(",\n", data->fh);
858 write_json_proto_node(node_values_list, "", write_json_proto_node_no_value, data);
859 delimiter_needed = TRUE;
862 current_node = current_node->next;
866 fputs("\n", data->fh);
867 print_indent(data->level, data->fh);
868 fputs("}", data->fh);
872 * Writes a single node as a key:value pair. The value_writer param can be used to specify how the node's value should
874 * @param node_values_head Linked list containing all nodes associated with the same json key in this object.
875 * @param suffix Suffix that should be added to the json key.
876 * @param value_writer A function which writes the actual values of the node json key.
877 * @param data json writing metadata
880 write_json_proto_node(GSList *node_values_head,
882 proto_node_value_writer value_writer,
883 write_json_data *data)
885 // Retrieve json key from first value.
886 proto_node *first_value = (proto_node *) node_values_head->data;
887 const char *json_key = proto_node_to_json_key(first_value);
889 print_indent(data->level, data->fh);
890 fputs("\"", data->fh);
891 print_escaped_json(data->fh, json_key);
892 print_escaped_json(data->fh, suffix);
893 fputs("\": ", data->fh);
895 write_json_proto_node_value_list(node_values_head, value_writer, data);
899 * Writes a list of values of a single json key. If multiple values are passed they are wrapped in a json array.
900 * @param node_values_head Linked list containing all values that should be written.
901 * @param value_writer Function which writes the separate values.
902 * @param data json writing metadata
905 write_json_proto_node_value_list(GSList *node_values_head, proto_node_value_writer value_writer, write_json_data *data)
907 GSList *current_value = node_values_head;
909 // Write directly if only a single value is passed. Wrap in json array otherwise.
910 if (current_value->next == NULL) {
911 value_writer((proto_node *) current_value->data, data);
913 fputs("[\n", data->fh);
916 // Print first value outside the while loop so we write the delimiter at the start of each loop without having
917 // to check if we are at the last element.
918 print_indent(data->level, data->fh);
919 value_writer((proto_node *) current_value->data, data);
920 current_value = current_value->next;
922 while (current_value != NULL) {
923 fputs(",\n", data->fh);
925 print_indent(data->level, data->fh);
926 value_writer((proto_node *) current_value->data, data);
927 current_value = current_value->next;
931 fputs("\n", data->fh);
932 print_indent(data->level, data->fh);
933 fputs("]", data->fh);
938 * Writes the value for a node that's filtered from the output.
941 write_json_proto_node_filtered(proto_node *node, write_json_data *data)
943 const char *json_key = proto_node_to_json_key(node);
945 fputs("{\n", data->fh);
948 print_indent(data->level, data->fh);
949 fputs("\"filtered\": ", data->fh);
950 fputs("\"", data->fh);
951 print_escaped_json(data->fh, json_key);
952 fputs("\"\n", data->fh);
955 print_indent(data->level, data->fh);
956 fputs("}", data->fh);
960 * Writes the hex dump of a node. A json array is written containing the hex dump, position, length, bitmask and type of
964 write_json_proto_node_hex_dump(proto_node *node, write_json_data *data)
966 field_info *fi = node->finfo;
968 fputs("[\"", data->fh);
970 if (fi->hfinfo->bitmask!=0) {
971 switch (fi->value.ftype->ftype) {
976 fprintf(data->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
982 fprintf(data->fh, "%X", fvalue_get_uinteger(&fi->value));
988 fprintf(data->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
995 fprintf(data->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
998 g_assert_not_reached();
1001 json_write_field_hex_value(data, fi);
1004 /* Dump raw hex-encoded dissected information including position, length, bitmask, type */
1005 fprintf(data->fh, "\", %" G_GINT32_MODIFIER "d", fi->start);
1006 fprintf(data->fh, ", %" G_GINT32_MODIFIER "d", fi->length);
1007 fprintf(data->fh, ", %" G_GUINT64_FORMAT, fi->hfinfo->bitmask);
1008 fprintf(data->fh, ", %" G_GINT32_MODIFIER "d", (gint32)fi->value.ftype->ftype);
1010 fputs("]", data->fh);
1014 * Writes the children of a node. Calls write_json_proto_node_list internally which recursively writes children of nodes
1018 write_json_proto_node_children(proto_node *node, write_json_data *data)
1020 GSList *same_key_nodes_list = json_proto_node_children_grouper(node);
1021 write_json_proto_node_list(same_key_nodes_list, data);
1022 g_slist_free(same_key_nodes_list);
1026 * Writes the value of a node to the output.
1029 write_json_proto_node_value(proto_node *node, write_json_data *data)
1031 field_info *fi = node->finfo;
1032 // Get the actual value of the node as a string.
1033 char *value_string_repr = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
1035 fputs("\"", data->fh);
1036 print_escaped_json(data->fh, value_string_repr);
1037 fputs("\"", data->fh);
1039 wmem_free(NULL, value_string_repr);
1043 * Write the value for a node that has no value and no children. This is the empty string for all nodes except those of
1044 * type FT_PROTOCOL for which the full name is written instead.
1047 write_json_proto_node_no_value(proto_node *node, write_json_data *data)
1049 field_info *fi = node->finfo;
1051 fputs("\"", data->fh);
1053 if (fi->hfinfo->type == FT_PROTOCOL) {
1055 print_escaped_json(data->fh, fi->rep->representation);
1057 gchar label_str[ITEM_LABEL_LENGTH];
1058 proto_item_fill_label(fi, label_str);
1059 print_escaped_json(data->fh, label_str);
1063 fputs("\"", data->fh);
1067 * Groups each node separately as if it had a unique json key even if it doesn't. Using this function leads to duplicate
1068 * keys in the json output.
1071 proto_node_group_children_by_unique(proto_node *node) {
1072 GSList *unique_nodes_list = NULL;
1073 proto_node *current_child = node->first_child;
1075 while (current_child != NULL) {
1076 GSList *unique_node = g_slist_prepend(NULL, current_child);
1077 unique_nodes_list = g_slist_prepend(unique_nodes_list, unique_node);
1078 current_child = current_child->next;
1081 return g_slist_reverse(unique_nodes_list);
1085 * Returns the json key of a node. Tries to use the node's abbreviated name. If the abbreviated name is not available
1086 * the representation is used instead.
1089 proto_node_to_json_key(proto_node *node)
1091 const char *json_key;
1092 // Check if node has abbreviated name.
1093 if (node->finfo->hfinfo->id != hf_text_only) {
1094 json_key = node->finfo->hfinfo->abbrev;
1095 } else if (node->finfo->rep != NULL) {
1096 json_key = node->finfo->rep->representation;
1104 /* Write out a tree's data, and any child nodes, as JSON for EK */
1106 proto_tree_write_node_ek(proto_node *node, gpointer data)
1108 field_info *fi = PNODE_FINFO(node);
1109 field_info *fi_parent = PNODE_FINFO(node->parent);
1110 write_json_data *pdata = (write_json_data*) data;
1111 const gchar *label_ptr;
1112 gchar label_str[ITEM_LABEL_LENGTH];
1113 char *dfilter_string;
1115 gchar *abbrev_escaped = NULL;
1117 /* dissection with an invisible proto tree? */
1120 /* Text label. It's printed as a field with no name. */
1121 if (fi->hfinfo->id == hf_text_only) {
1124 label_ptr = fi->rep->representation;
1130 /* Show empty name since it is a required field */
1131 fputs("\"", pdata->fh);
1132 if (fi_parent != NULL) {
1133 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
1134 fputs("_", pdata->fh);
1136 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1138 if (node->first_child != NULL) {
1139 fputs("\": \"", pdata->fh);
1140 print_escaped_json(pdata->fh, label_ptr);
1141 fputs("\",", pdata->fh);
1145 if (node->next == NULL) {
1146 fputs("\": \"", pdata->fh);
1147 print_escaped_json(pdata->fh, label_ptr);
1148 fputs("\"", pdata->fh);
1150 fputs("\": \"", pdata->fh);
1151 print_escaped_json(pdata->fh, label_ptr);
1152 fputs("\",", pdata->fh);
1157 /* Normal protocols and fields */
1162 if (pdata->print_hex && fi->length > 0) {
1163 fputs("\"", pdata->fh);
1164 if (fi_parent != NULL) {
1165 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
1166 fputs("_", pdata->fh);
1168 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1169 fputs("_raw", pdata->fh);
1170 fputs("\": \"", pdata->fh);
1172 if (fi->hfinfo->bitmask!=0) {
1173 switch (fi->value.ftype->ftype) {
1178 fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
1184 fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
1190 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
1197 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
1200 g_assert_not_reached();
1202 fputs("\",", pdata->fh);
1205 json_write_field_hex_value(pdata, fi);
1206 fputs("\",", pdata->fh);
1212 fputs("\"", pdata->fh);
1214 if (fi_parent != NULL) {
1215 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
1216 fputs("_", pdata->fh);
1218 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1220 /* show, value, and unmaskedvalue attributes */
1221 switch (fi->hfinfo->type)
1224 if (node->first_child != NULL) {
1225 fputs("\": {", pdata->fh);
1227 fputs("\": \"", pdata->fh);
1229 print_escaped_json(pdata->fh, fi->rep->representation);
1232 label_ptr = label_str;
1233 proto_item_fill_label(fi, label_str);
1234 print_escaped_json(pdata->fh, label_ptr);
1236 if (node->next == NULL) {
1237 fputs("\"", pdata->fh);
1239 fputs("\",", pdata->fh);
1244 if (node->first_child != NULL) {
1245 fputs("\": \"\",", pdata->fh);
1247 if (node->next == NULL) {
1248 fputs("\": \"\"", pdata->fh);
1250 fputs("\": \"\",", pdata->fh);
1255 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
1256 if (dfilter_string != NULL) {
1257 fputs("\": \"", pdata->fh);
1258 print_escaped_json(pdata->fh, dfilter_string);
1260 wmem_free(NULL, dfilter_string);
1262 if (node->next == NULL && node->first_child == NULL) {
1263 fputs("\"", pdata->fh);
1265 fputs("\",", pdata->fh);
1271 /* We print some levels for JSON. Recurse here. */
1272 if (node->first_child != NULL) {
1274 if (pdata->filter != NULL) {
1276 /* to to thread the '.' and '_' equally. The '.' is replace by print_escaped_ek for '_' */
1277 if (fi->hfinfo->abbrev != NULL) {
1278 if (strlen(fi->hfinfo->abbrev) > 0) {
1279 abbrev_escaped = g_strdup(fi->hfinfo->abbrev);
1282 while(abbrev_escaped[i]!='\0') {
1283 if(abbrev_escaped[i]=='.') {
1284 abbrev_escaped[i]='_';
1291 if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev) || check_protocolfilter(pdata->filter, abbrev_escaped)) {
1292 gchar **_filter = NULL;
1293 /* Remove protocol filter for children, if children should be included */
1294 if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
1295 _filter = pdata->filter;
1296 pdata->filter = NULL;
1300 proto_tree_children_foreach(node, proto_tree_write_node_ek, pdata);
1303 /* Put protocol filter back */
1304 if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) {
1305 pdata->filter = _filter;
1308 /* print dummy field */
1309 fputs("\"filtered\": \"", pdata->fh);
1310 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1311 fputs("\"", pdata->fh);
1314 /* release abbrev_escaped string */
1315 if (abbrev_escaped != NULL) {
1316 g_free(abbrev_escaped);
1321 proto_tree_children_foreach(node,
1322 proto_tree_write_node_ek, pdata);
1327 if (node->first_child != NULL) {
1328 if (fi->hfinfo->type == FT_PROTOCOL) {
1329 /* Close off current element */
1330 if (node->next == NULL) {
1331 fputs("}", pdata->fh);
1333 fputs("},", pdata->fh);
1336 if (node->next != NULL) {
1337 fputs(",", pdata->fh);
1343 /* Print info for a 'geninfo' pseudo-protocol. This is required by
1344 * the PDML spec. The information is contained in Wireshark's 'frame' protocol,
1345 * but we produce a 'geninfo' protocol in the PDML to conform to spec.
1346 * The 'frame' protocol follows the 'geninfo' protocol in the PDML. */
1348 print_pdml_geninfo(epan_dissect_t *edt, FILE *fh)
1350 guint32 num, len, caplen;
1351 GPtrArray *finfo_array;
1352 field_info *frame_finfo;
1355 /* Get frame protocol's finfo. */
1356 finfo_array = proto_find_first_finfo(edt->tree, proto_frame);
1357 if (g_ptr_array_len(finfo_array) < 1) {
1360 frame_finfo = (field_info *)finfo_array->pdata[0];
1361 g_ptr_array_free(finfo_array, TRUE);
1363 /* frame.number, packet_info.num */
1366 /* frame.frame_len, packet_info.frame_data->pkt_len */
1367 len = edt->pi.fd->pkt_len;
1369 /* frame.cap_len --> packet_info.frame_data->cap_len */
1370 caplen = edt->pi.fd->cap_len;
1372 /* Print geninfo start */
1374 " <proto name=\"geninfo\" pos=\"0\" showname=\"General information\" size=\"%d\">\n",
1375 frame_finfo->length);
1377 /* Print geninfo.num */
1379 " <field name=\"num\" pos=\"0\" show=\"%u\" showname=\"Number\" value=\"%x\" size=\"%d\"/>\n",
1380 num, num, frame_finfo->length);
1382 /* Print geninfo.len */
1384 " <field name=\"len\" pos=\"0\" show=\"%u\" showname=\"Frame Length\" value=\"%x\" size=\"%d\"/>\n",
1385 len, len, frame_finfo->length);
1387 /* Print geninfo.caplen */
1389 " <field name=\"caplen\" pos=\"0\" show=\"%u\" showname=\"Captured Length\" value=\"%x\" size=\"%d\"/>\n",
1390 caplen, caplen, frame_finfo->length);
1392 tmp = abs_time_to_str(NULL, &edt->pi.abs_ts, ABSOLUTE_TIME_LOCAL, TRUE);
1394 /* Print geninfo.timestamp */
1396 " <field name=\"timestamp\" pos=\"0\" show=\"%s\" showname=\"Captured Time\" value=\"%d.%09d\" size=\"%d\"/>\n",
1397 tmp, (int)edt->pi.abs_ts.secs, edt->pi.abs_ts.nsecs, frame_finfo->length);
1399 wmem_free(NULL, tmp);
1401 /* Print geninfo end */
1407 write_pdml_finale(FILE *fh)
1409 fputs("</pdml>\n", fh);
1415 write_psml_preamble(column_info *cinfo, FILE *fh)
1419 fprintf(fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1420 fprintf(fh, "<psml version=\"" PSML_VERSION "\" creator=\"%s/%s\">\n", PACKAGE, VERSION);
1421 fprintf(fh, "<structure>\n");
1423 for (i = 0; i < cinfo->num_cols; i++) {
1424 fprintf(fh, "<section>");
1425 print_escaped_xml(fh, cinfo->columns[i].col_title);
1426 fprintf(fh, "</section>\n");
1429 fprintf(fh, "</structure>\n\n");
1433 write_psml_columns(epan_dissect_t *edt, FILE *fh, gboolean use_color)
1436 const color_filter_t *cfp = edt->pi.fd->color_filter;
1438 if (use_color && (cfp != NULL)) {
1439 fprintf(fh, "<packet foreground='#%02x%02x%02x' background='#%02x%02x%02x'>\n",
1440 cfp->fg_color.red, cfp->fg_color.green, cfp->fg_color.blue,
1441 cfp->bg_color.red, cfp->bg_color.green, cfp->bg_color.blue);
1444 fprintf(fh, "<packet>\n");
1447 for (i = 0; i < edt->pi.cinfo->num_cols; i++) {
1448 fprintf(fh, "<section>");
1449 print_escaped_xml(fh, edt->pi.cinfo->columns[i].col_data);
1450 fprintf(fh, "</section>\n");
1453 fprintf(fh, "</packet>\n\n");
1457 write_psml_finale(FILE *fh)
1459 fputs("</psml>\n", fh);
1462 static gchar *csv_massage_str(const gchar *source, const gchar *exceptions)
1467 /* In general, our output for any field can contain Unicode characters,
1468 so g_strescape (which escapes any non-ASCII) is the wrong thing to do.
1469 Unfortunately glib doesn't appear to provide g_unicode_strescape()... */
1470 csv_str = g_strescape(source, exceptions);
1472 /* Locate the UTF-8 right arrow character and replace it by an ASCII equivalent */
1473 while ( (tmp_str = strstr(tmp_str, UTF8_RIGHTWARDS_ARROW)) != NULL ) {
1479 while ( (tmp_str = strstr(tmp_str, "\\\"")) != NULL )
1484 static void csv_write_str(const char *str, char sep, FILE *fh)
1488 /* Do not escape the UTF-8 right arrow character */
1489 csv_str = csv_massage_str(str, UTF8_RIGHTWARDS_ARROW);
1490 fprintf(fh, "\"%s\"%c", csv_str, sep);
1495 write_csv_column_titles(column_info *cinfo, FILE *fh)
1499 for (i = 0; i < cinfo->num_cols - 1; i++)
1500 csv_write_str(cinfo->columns[i].col_title, ',', fh);
1501 csv_write_str(cinfo->columns[i].col_title, '\n', fh);
1505 write_csv_columns(epan_dissect_t *edt, FILE *fh)
1509 for (i = 0; i < edt->pi.cinfo->num_cols - 1; i++)
1510 csv_write_str(edt->pi.cinfo->columns[i].col_data, ',', fh);
1511 csv_write_str(edt->pi.cinfo->columns[i].col_data, '\n', fh);
1515 write_carrays_hex_data(guint32 num, FILE *fh, epan_dissect_t *edt)
1517 guint32 i = 0, src_num = 0;
1524 struct data_source *src;
1526 for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
1527 memset(ascii, 0, sizeof(ascii));
1528 src = (struct data_source *)src_le->data;
1529 tvb = get_data_source_tvb(src);
1530 length = tvb_captured_length(tvb);
1534 cp = tvb_get_ptr(tvb, 0, length);
1536 name = get_data_source_name(src);
1538 fprintf(fh, "/* %s */\n", name);
1539 wmem_free(NULL, name);
1542 fprintf(fh, "static const unsigned char pkt%u_%u[%u] = {\n",
1543 num, src_num, length);
1545 fprintf(fh, "static const unsigned char pkt%u[%u] = {\n",
1550 for (i = 0; i < length; i++) {
1551 fprintf(fh, "0x%02x", *(cp + i));
1552 ascii[i % 8] = g_ascii_isprint(*(cp + i)) ? *(cp + i) : '.';
1554 if (i == (length - 1)) {
1559 for ( j = 0; j < 8 - rem; j++ )
1562 fprintf(fh, " /* %s */\n};\n\n", ascii);
1566 if (!((i + 1) % 8)) {
1567 fprintf(fh, ", /* %s */\n", ascii);
1568 memset(ascii, 0, sizeof(ascii));
1578 * Find the data source for a specified field, and return a pointer
1579 * to the data in it. Returns NULL if the data is out of bounds.
1581 /* XXX: What am I missing ?
1582 * Why bother searching for fi->ds_tvb for the matching tvb
1583 * in the data_source list ?
1584 * IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
1587 static const guint8 *
1588 get_field_data(GSList *src_list, field_info *fi)
1592 gint length, tvbuff_length;
1593 struct data_source *src;
1595 for (src_le = src_list; src_le != NULL; src_le = src_le->next) {
1596 src = (struct data_source *)src_le->data;
1597 src_tvb = get_data_source_tvb(src);
1598 if (fi->ds_tvb == src_tvb) {
1602 * XXX - a field can have a length that runs past
1603 * the end of the tvbuff. Ideally, that should
1604 * be fixed when adding an item to the protocol
1605 * tree, but checking the length when doing
1606 * that could be expensive. Until we fix that,
1607 * we'll do the check here.
1609 tvbuff_length = tvb_captured_length_remaining(src_tvb,
1611 if (tvbuff_length < 0) {
1614 length = fi->length;
1615 if (length > tvbuff_length)
1616 length = tvbuff_length;
1617 return tvb_get_ptr(src_tvb, fi->start, length);
1620 g_assert_not_reached();
1621 return NULL; /* not found */
1624 /* Print a string, escaping out certain characters that need to
1625 * escaped out for XML. */
1627 print_escaped_xml(FILE *fh, const char *unescaped_string)
1632 if (fh == NULL || unescaped_string == NULL) {
1636 for (p = unescaped_string; *p != '\0'; p++) {
1648 fputs(""", fh);
1651 fputs("'", fh);
1654 if (g_ascii_isprint(*p))
1657 g_snprintf(temp_str, sizeof(temp_str), "\\x%x", (guint8)*p);
1658 fputs(temp_str, fh);
1665 print_escaped_bare(FILE *fh, const char *unescaped_string, gboolean change_dot)
1670 if (fh == NULL || unescaped_string == NULL) {
1674 for (p = unescaped_string; *p != '\0'; p++) {
1707 if (g_ascii_isprint(*p))
1710 g_snprintf(temp_str, sizeof(temp_str), "\\u00%02x", (guint8)*p);
1711 fputs(temp_str, fh);
1717 /* Print a string, escaping out certain characters that need to
1718 * escaped out for JSON. */
1720 print_escaped_json(FILE *fh, const char *unescaped_string)
1722 print_escaped_bare(fh, unescaped_string, FALSE);
1725 /* Print a string, escaping out certain characters that need to
1726 * escaped out for Elasticsearch title. */
1728 print_escaped_ek(FILE *fh, const char *unescaped_string)
1730 print_escaped_bare(fh, unescaped_string, TRUE);
1734 pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi)
1742 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1743 fprintf(pdata->fh, "field length invalid!");
1747 /* Find the data for this field. */
1748 pd = get_field_data(pdata->src_list, fi);
1751 /* Print a simple hex dump */
1752 for (i = 0 ; i < fi->length; i++) {
1753 fprintf(pdata->fh, "%02x", pd[i]);
1759 json_write_field_hex_value(write_json_data *pdata, field_info *fi)
1767 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1768 fprintf(pdata->fh, "field length invalid!");
1772 /* Find the data for this field. */
1773 pd = get_field_data(pdata->src_list, fi);
1776 /* Print a simple hex dump */
1777 for (i = 0 ; i < fi->length; i++) {
1778 fprintf(pdata->fh, "%02x", pd[i]);
1784 print_hex_data(print_stream_t *stream, epan_dissect_t *edt)
1786 gboolean multiple_sources;
1792 struct data_source *src;
1795 * Set "multiple_sources" iff this frame has more than one
1796 * data source; if it does, we need to print the name of
1797 * the data source before printing the data from the
1800 multiple_sources = (edt->pi.data_src->next != NULL);
1802 for (src_le = edt->pi.data_src; src_le != NULL;
1803 src_le = src_le->next) {
1804 src = (struct data_source *)src_le->data;
1805 tvb = get_data_source_tvb(src);
1806 if (multiple_sources) {
1807 name = get_data_source_name(src);
1808 line = g_strdup_printf("%s:", name);
1809 wmem_free(NULL, name);
1810 print_line(stream, 0, line);
1813 length = tvb_captured_length(tvb);
1816 cp = tvb_get_ptr(tvb, 0, length);
1817 if (!print_hex_data_buffer(stream, cp, length,
1818 (packet_char_enc)edt->pi.fd->flags.encoding))
1825 * This routine is based on a routine created by Dan Lasley
1826 * <DLASLEY@PROMUS.com>.
1828 * It was modified for Wireshark by Gilbert Ramirez and others.
1831 #define MAX_OFFSET_LEN 8 /* max length of hex offset of bytes */
1832 #define BYTES_PER_LINE 16 /* max byte values printed on a line */
1833 #define HEX_DUMP_LEN (BYTES_PER_LINE*3)
1834 /* max number of characters hex dump takes -
1835 2 digits plus trailing blank */
1836 #define DATA_DUMP_LEN (HEX_DUMP_LEN + 2 + BYTES_PER_LINE)
1837 /* number of characters those bytes take;
1838 3 characters per byte of hex dump,
1839 2 blanks separating hex from ASCII,
1840 1 character per byte of ASCII dump */
1841 #define MAX_LINE_LEN (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN)
1842 /* number of characters per line;
1843 offset, 2 blanks separating offset
1844 from data dump, data dump */
1847 print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
1848 guint length, packet_char_enc encoding)
1850 register unsigned int ad, i, j, k, l;
1852 gchar line[MAX_LINE_LEN + 1];
1853 unsigned int use_digits;
1855 static gchar binhex[16] = {
1856 '0', '1', '2', '3', '4', '5', '6', '7',
1857 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1860 * How many of the leading digits of the offset will we supply?
1861 * We always supply at least 4 digits, but if the maximum offset
1862 * won't fit in 4 digits, we use as many digits as will be needed.
1864 if (((length - 1) & 0xF0000000) != 0)
1865 use_digits = 8; /* need all 8 digits */
1866 else if (((length - 1) & 0x0F000000) != 0)
1867 use_digits = 7; /* need 7 digits */
1868 else if (((length - 1) & 0x00F00000) != 0)
1869 use_digits = 6; /* need 6 digits */
1870 else if (((length - 1) & 0x000F0000) != 0)
1871 use_digits = 5; /* need 5 digits */
1873 use_digits = 4; /* we'll supply 4 digits */
1879 while (i < length) {
1880 if ((i & 15) == 0) {
1882 * Start of a new line.
1888 c = (ad >> (l*4)) & 0xF;
1889 line[j++] = binhex[c];
1893 memset(line+j, ' ', DATA_DUMP_LEN);
1896 * Offset in line of ASCII dump.
1898 k = j + HEX_DUMP_LEN + 2;
1901 line[j++] = binhex[c>>4];
1902 line[j++] = binhex[c&0xf];
1904 if (encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) {
1905 c = EBCDIC_to_ASCII1(c);
1907 line[k++] = ((c >= ' ') && (c < 0x7f)) ? c : '.';
1909 if (((i & 15) == 0) || (i == length)) {
1911 * We'll be starting a new line, or
1912 * we're finished printing this buffer;
1913 * dump out the line we've constructed,
1914 * and advance the offset.
1917 if (!print_line(stream, 0, line))
1925 gsize output_fields_num_fields(output_fields_t* fields)
1929 if (NULL == fields->fields) {
1932 return fields->fields->len;
1936 void output_fields_free(output_fields_t* fields)
1940 if (NULL != fields->fields) {
1943 if (NULL != fields->field_indicies) {
1944 /* Keys are stored in fields->fields, values are
1947 g_hash_table_destroy(fields->field_indicies);
1950 if (NULL != fields->field_values) {
1951 g_free(fields->field_values);
1954 for(i = 0; i < fields->fields->len; ++i) {
1955 gchar* field = (gchar *)g_ptr_array_index(fields->fields,i);
1958 g_ptr_array_free(fields->fields, TRUE);
1964 #define COLUMN_FIELD_FILTER "_ws.col."
1966 void output_fields_add(output_fields_t *fields, const gchar *field)
1974 if (NULL == fields->fields) {
1975 fields->fields = g_ptr_array_new();
1978 field_copy = g_strdup(field);
1980 g_ptr_array_add(fields->fields, field_copy);
1982 /* See if we have a column as a field entry */
1983 if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1984 fields->includes_col_fields = TRUE;
1989 output_field_check(void *data, void *user_data)
1991 gchar *field = (gchar *)data;
1992 GSList **invalid_fields = (GSList **)user_data;
1994 if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1997 if (!proto_registrar_get_byname(field)) {
1998 *invalid_fields = g_slist_prepend(*invalid_fields, field);
2004 output_fields_valid(output_fields_t *fields)
2006 GSList *invalid_fields = NULL;
2007 if (fields->fields == NULL) {
2011 g_ptr_array_foreach(fields->fields, output_field_check, &invalid_fields);
2013 return invalid_fields;
2016 gboolean output_fields_set_option(output_fields_t *info, gchar *option)
2018 const gchar *option_name;
2019 const gchar *option_value;
2024 if ('\0' == *option) {
2025 return FALSE; /* this happens if we're called from tshark -E '' */
2027 option_name = strtok(option, "=");
2031 option_value = option + strlen(option_name) + 1;
2032 if (*option_value == '\0') {
2036 if (0 == strcmp(option_name, "header")) {
2037 switch (*option_value) {
2039 info->print_header = FALSE;
2042 info->print_header = TRUE;
2049 else if (0 == strcmp(option_name, "separator")) {
2050 switch (*option_value) {
2052 switch (*++option_value) {
2054 info->separator = '\t';
2057 info->separator = ' ';
2060 info->separator = '\\';
2064 info->separator = *option_value;
2069 else if (0 == strcmp(option_name, "occurrence")) {
2070 switch (*option_value) {
2074 info->occurrence = *option_value;
2081 else if (0 == strcmp(option_name, "aggregator")) {
2082 switch (*option_value) {
2084 switch (*++option_value) {
2086 info->aggregator = ' ';
2089 info->aggregator = '\\';
2093 info->aggregator = *option_value;
2098 else if (0 == strcmp(option_name, "quote")) {
2099 switch (*option_value) {
2115 else if (0 == strcmp(option_name, "bom")) {
2116 switch (*option_value) {
2118 info->print_bom = FALSE;
2121 info->print_bom = TRUE;
2132 void output_fields_list_options(FILE *fh)
2134 fprintf(fh, "TShark: The available options for field output \"E\" are:\n");
2135 fputs("bom=y|n Prepend output with the UTF-8 BOM (def: N: no)\n", fh);
2136 fputs("header=y|n Print field abbreviations as first line of output (def: N: no)\n", fh);
2137 fputs("separator=/t|/s|<character> Set the separator to use;\n \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh);
2138 fputs("occurrence=f|l|a Select the occurrence of a field to use;\n \"f\" = first, \"l\" = last, \"a\" = all (def: a: all)\n", fh);
2139 fputs("aggregator=,|/s|<character> Set the aggregator to use;\n \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh);
2140 fputs("quote=d|s|n Print either d: double-quotes, s: single quotes or \n n: no quotes around field values (def: n: none)\n", fh);
2143 gboolean output_fields_has_cols(output_fields_t* fields)
2146 return fields->includes_col_fields;
2149 void write_fields_preamble(output_fields_t* fields, FILE *fh)
2155 g_assert(fields->fields);
2157 if (fields->print_bom) {
2158 fputs(UTF8_BOM, fh);
2162 if (!fields->print_header) {
2166 for(i = 0; i < fields->fields->len; ++i) {
2167 const gchar* field = (const gchar *)g_ptr_array_index(fields->fields,i);
2169 fputc(fields->separator, fh);
2176 static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
2184 /* Unwrap change made to disambiguiate zero / null */
2185 indx = GPOINTER_TO_UINT(field_index) - 1;
2187 if (fields->field_values[indx] == NULL) {
2188 fields->field_values[indx] = g_ptr_array_new();
2191 /* Essentially: fieldvalues[indx] is a 'GPtrArray *' with each array entry */
2192 /* pointing to a string which is (part of) the final output string. */
2194 fv_p = fields->field_values[indx];
2196 switch (fields->occurrence) {
2198 /* print the value of only the first occurrence of the field */
2199 if (g_ptr_array_len(fv_p) != 0)
2203 /* print the value of only the last occurrence of the field */
2204 g_ptr_array_set_size(fv_p, 0);
2207 /* print the value of all accurrences of the field */
2208 /* If not the first, add the 'aggregator' */
2209 if (g_ptr_array_len(fv_p) > 0) {
2210 g_ptr_array_add(fv_p, (gpointer)g_strdup_printf("%c", fields->aggregator));
2214 g_assert_not_reached();
2218 g_ptr_array_add(fv_p, (gpointer)value);
2221 static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
2223 write_field_data_t *call_data;
2225 gpointer field_index;
2227 call_data = (write_field_data_t *)data;
2228 fi = PNODE_FINFO(node);
2230 /* dissection with an invisible proto tree? */
2233 field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
2234 if (NULL != field_index) {
2235 format_field_values(call_data->fields, field_index,
2236 get_node_field_value(fi, call_data->edt) /* g_ alloc'd string */
2241 if (node->first_child != NULL) {
2242 proto_tree_children_foreach(node, proto_tree_get_node_field_values,
2247 static void write_specified_fields(fields_format format, output_fields_t *fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
2250 gboolean first = TRUE;
2253 gpointer field_index;
2255 write_field_data_t data;
2258 g_assert(fields->fields);
2262 data.fields = fields;
2265 if (NULL == fields->field_indicies) {
2266 /* Prepare a lookup table from string abbreviation for field to its index. */
2267 fields->field_indicies = g_hash_table_new(g_str_hash, g_str_equal);
2270 while (i < fields->fields->len) {
2271 gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2272 /* Store field indicies +1 so that zero is not a valid value,
2273 * and can be distinguished from NULL as a pointer.
2276 g_hash_table_insert(fields->field_indicies, field, GUINT_TO_POINTER(i));
2280 /* Array buffer to store values for this packet */
2281 /* Allocate an array for the 'GPtrarray *' the first time */
2282 /* ths function is invoked for a file; */
2283 /* Any and all 'GPtrArray *' are freed (after use) each */
2284 /* time (each packet) this function is invoked for a flle. */
2285 /* XXX: ToDo: use packet-scope'd memory & (if/when implemented) wmem ptr_array */
2286 if (NULL == fields->field_values)
2287 fields->field_values = g_new0(GPtrArray*, fields->fields->len); /* free'd in output_fields_free() */
2289 proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
2294 if (fields->includes_col_fields) {
2295 for (col = 0; col < cinfo->num_cols; col++) {
2296 /* Prepend COLUMN_FIELD_FILTER as the field name */
2297 col_name = g_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->columns[col].col_title);
2298 field_index = g_hash_table_lookup(fields->field_indicies, col_name);
2301 if (NULL != field_index) {
2302 format_field_values(fields, field_index, g_strdup(cinfo->columns[col].col_data));
2307 for(i = 0; i < fields->fields->len; ++i) {
2309 fputc(fields->separator, fh);
2311 if (NULL != fields->field_values[i]) {
2315 fv_p = fields->field_values[i];
2316 if (fields->quote != '\0') {
2317 fputc(fields->quote, fh);
2320 /* Output the array of (partial) field values */
2321 for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
2322 str = (gchar *)g_ptr_array_index(fv_p, j);
2326 if (fields->quote != '\0') {
2327 fputc(fields->quote, fh);
2329 g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
2330 fields->field_values[i] = NULL;
2335 for(i = 0; i < fields->fields->len; ++i) {
2336 gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2338 if (NULL != fields->field_values[i]) {
2342 fv_p = fields->field_values[i];
2344 /* Output the array of (partial) field values */
2345 for (j = 0; j < (g_ptr_array_len(fv_p)); j+=2 ) {
2346 str = (gchar *)g_ptr_array_index(fv_p, j);
2348 fprintf(fh, " <field name=\"%s\" value=", field);
2350 print_escaped_xml(fh, str);
2351 fputs("\"/>\n", fh);
2354 g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
2355 fields->field_values[i] = NULL;
2361 for(i = 0; i < fields->fields->len; ++i) {
2362 gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2364 if (NULL != fields->field_values[i]) {
2368 fv_p = fields->field_values[i];
2370 /* Output the array of (partial) field values */
2371 for (j = 0; j < (g_ptr_array_len(fv_p)); j += 2) {
2372 str = (gchar *) g_ptr_array_index(fv_p, j);
2378 fprintf(fh, " \"%s\": [", field);
2381 print_escaped_json(fh, str);
2385 if (j + 2 < (g_ptr_array_len(fv_p))) {
2393 g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
2394 fields->field_values[i] = NULL;
2402 for(i = 0; i < fields->fields->len; ++i) {
2403 gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2405 if (NULL != fields->field_values[i]) {
2409 fv_p = fields->field_values[i];
2411 /* Output the array of (partial) field values */
2412 for (j = 0; j < (g_ptr_array_len(fv_p)); j += 2) {
2413 str = (gchar *)g_ptr_array_index(fv_p, j);
2420 print_escaped_ek(fh, field);
2424 print_escaped_json(fh, str);
2428 if (j + 2 < (g_ptr_array_len(fv_p))) {
2438 g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
2439 fields->field_values[i] = NULL;
2445 fprintf(stderr, "Unknown fields format %d\n", format);
2446 g_assert_not_reached();
2451 void write_fields_finale(output_fields_t* fields _U_ , FILE *fh _U_)
2456 /* Returns an g_malloced string */
2457 gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt)
2459 if (fi->hfinfo->id == hf_text_only) {
2463 return g_strdup(fi->rep->representation);
2466 return get_field_hex_value(edt->pi.data_src, fi);
2469 else if (fi->hfinfo->id == proto_data) {
2470 /* Uninterpreted data, i.e., the "Data" protocol, is
2471 * printed as a field instead of a protocol. */
2472 return get_field_hex_value(edt->pi.data_src, fi);
2475 /* Normal protocols and fields */
2476 gchar *dfilter_string;
2478 switch (fi->hfinfo->type)
2481 /* Print out the full details for the protocol. */
2483 return g_strdup(fi->rep->representation);
2485 /* Just print out the protocol abbreviation */
2486 return g_strdup(fi->hfinfo->abbrev);
2489 /* Return "1" so that the presence of a field of type
2490 * FT_NONE can be checked when using -T fields */
2491 return g_strdup("1");
2493 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
2494 if (dfilter_string != NULL) {
2495 gchar* ret = g_strdup(dfilter_string);
2496 wmem_free(NULL, dfilter_string);
2499 return get_field_hex_value(edt->pi.data_src, fi);
2506 get_field_hex_value(GSList *src_list, field_info *fi)
2513 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
2514 return g_strdup("field length invalid!");
2517 /* Find the data for this field. */
2518 pd = get_field_data(src_list, fi);
2525 const int chars_per_byte = 2;
2527 len = chars_per_byte * fi->length;
2528 buffer = (gchar *)g_malloc(sizeof(gchar)*(len + 1));
2529 buffer[len] = '\0'; /* Ensure NULL termination in bad cases */
2531 /* Print a simple hex dump */
2532 for (i = 0 ; i < fi->length; i++) {
2533 g_snprintf(p, chars_per_byte+1, "%02x", pd[i]);
2534 p += chars_per_byte;
2542 output_fields_t* output_fields_new(void)
2544 output_fields_t* fields = g_new(output_fields_t, 1);
2545 fields->print_bom = FALSE;
2546 fields->print_header = FALSE;
2547 fields->separator = '\t';
2548 fields->occurrence = 'a';
2549 fields->aggregator = ',';
2550 fields->fields = NULL; /*Do lazy initialisation */
2551 fields->field_indicies = NULL;
2552 fields->field_values = NULL;
2553 fields->quote ='\0';
2554 fields->includes_col_fields = FALSE;
2559 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2564 * indent-tabs-mode: nil
2567 * vi: set shiftwidth=4 tabstop=8 expandtab:
2568 * :indentSize=4:tabSize=8:noTabs=true: