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/packet-range.h>
36 #include <epan/print.h>
37 #include <epan/charsets.h>
38 #include <wsutil/filesystem.h>
39 #include <ws_version_info.h>
40 #include <wsutil/utf8_entities.h>
41 #include <ftypes/ftypes-int.h>
43 #define PDML_VERSION "0"
44 #define PSML_VERSION "0"
48 print_stream_t *stream;
51 print_dissections_e print_dissections;
52 gboolean print_hex_for_data;
53 packet_char_enc encoding;
55 GHashTable *output_only_tables; /* output only these protocols */
76 output_fields_t *fields;
80 struct _output_fields {
82 gboolean print_header;
87 GHashTable *field_indicies;
88 GPtrArray **field_values;
90 gboolean includes_col_fields;
93 static gchar *get_field_hex_value(GSList *src_list, field_info *fi);
94 static void proto_tree_print_node(proto_node *node, gpointer data);
95 static void proto_tree_write_node_pdml(proto_node *node, gpointer data);
96 static void proto_tree_write_node_json(proto_node *node, gpointer data);
97 static void proto_tree_write_node_ek(proto_node *node, gpointer data);
98 static const guint8 *get_field_data(GSList *src_list, field_info *fi);
99 static void pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi);
100 static void json_write_field_hex_value(write_json_data *pdata, field_info *fi);
101 static gboolean print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
102 guint length, packet_char_enc encoding);
103 static void print_escaped_xml(FILE *fh, const char *unescaped_string);
104 static void print_escaped_json(FILE *fh, const char *unescaped_string);
105 static void print_escaped_ek(FILE *fh, const char *unescaped_string);
107 static void print_pdml_geninfo(proto_tree *tree, FILE *fh);
109 static void proto_tree_get_node_field_values(proto_node *node, gpointer data);
111 /* Cache the protocols and field handles that the print functionality needs
112 This helps break explicit dependency on the dissectors. */
113 static int proto_data = -1;
114 static int proto_frame = -1;
115 static int hf_frame_arrival_time = -1;
116 static int hf_frame_number = -1;
117 static int hf_frame_len = -1;
118 static int hf_frame_capture_len = -1;
120 void print_cache_field_handles(void)
122 proto_data = proto_get_id_by_short_name("Data");
123 proto_frame = proto_get_id_by_short_name("Frame");
124 hf_frame_arrival_time = proto_registrar_get_id_byname("frame.time");
125 hf_frame_number = proto_registrar_get_id_byname("frame.number");
126 hf_frame_len = proto_registrar_get_id_byname("frame.len");
127 hf_frame_capture_len = proto_registrar_get_id_byname("frame.cap_len");
131 proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
132 GHashTable *output_only_tables, print_stream_t *stream)
136 /* Create the output */
138 data.stream = stream;
140 data.src_list = edt->pi.data_src;
141 data.encoding = (packet_char_enc)edt->pi.fd->flags.encoding;
142 data.print_dissections = print_args->print_dissections;
143 /* If we're printing the entire packet in hex, don't
144 print uninterpreted data fields in hex as well. */
145 data.print_hex_for_data = !print_args->print_hex;
147 data.output_only_tables = output_only_tables;
149 proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
153 /* Print a tree's data, and any child nodes. */
155 proto_tree_print_node(proto_node *node, gpointer data)
157 field_info *fi = PNODE_FINFO(node);
158 print_data *pdata = (print_data*) data;
160 gchar label_str[ITEM_LABEL_LENGTH];
163 /* dissection with an invisible proto tree? */
166 /* Don't print invisible entries. */
167 if (PROTO_ITEM_IS_HIDDEN(node))
170 /* Give up if we've already gotten an error. */
174 /* was a free format label produced? */
176 label_ptr = fi->rep->representation;
178 else { /* no, make a generic label */
179 label_ptr = label_str;
180 proto_item_fill_label(fi, label_str);
183 if (PROTO_ITEM_IS_GENERATED(node))
184 label_ptr = g_strconcat("[", label_ptr, "]", NULL);
186 pdata->success = print_line(pdata->stream, pdata->level, label_ptr);
188 if (PROTO_ITEM_IS_GENERATED(node))
195 * If -O is specified, only display the protocols which are in the
196 * lookup table. Only check on the first level: once we start printing
197 * a tree, print the rest of the subtree. Otherwise we won't print
198 * subitems whose abbreviation doesn't match the protocol--for example
199 * text items (whose abbreviation is simply "text").
201 if ((pdata->output_only_tables != NULL) && (pdata->level == 0)
202 && (g_hash_table_lookup(pdata->output_only_tables, fi->hfinfo->abbrev) == NULL)) {
206 /* If it's uninterpreted data, dump it (unless our caller will
207 be printing the entire packet in hex). */
208 if ((fi->hfinfo->id == proto_data) && (pdata->print_hex_for_data)) {
210 * Find the data for this field.
212 pd = get_field_data(pdata->src_list, fi);
214 if (!print_line(pdata->stream, 0, "")) {
215 pdata->success = FALSE;
218 if (!print_hex_data_buffer(pdata->stream, pd,
219 fi->length, pdata->encoding)) {
220 pdata->success = FALSE;
226 /* If we're printing all levels, or if this node is one with a
227 subtree and its subtree is expanded, recurse into the subtree,
229 g_assert((fi->tree_type >= -1) && (fi->tree_type < num_tree_types));
230 if ((pdata->print_dissections == print_dissections_expanded) ||
231 ((pdata->print_dissections == print_dissections_as_displayed) &&
232 (fi->tree_type >= 0) && tree_expanded(fi->tree_type))) {
233 if (node->first_child != NULL) {
235 proto_tree_children_foreach(node,
236 proto_tree_print_node, pdata);
244 #define PDML2HTML_XSL "pdml2html.xsl"
246 write_pdml_preamble(FILE *fh, const gchar *filename)
248 time_t t = time(NULL);
249 char *ts = asctime(localtime(&t));
251 ts[strlen(ts)-1] = 0; /* overwrite \n */
253 fputs("<?xml version=\"1.0\"?>\n", fh);
254 fputs("<?xml-stylesheet type=\"text/xsl\" href=\"" PDML2HTML_XSL "\"?>\n", fh);
255 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());
256 fputs("<pdml version=\"" PDML_VERSION "\" ", fh);
257 fprintf(fh, "creator=\"%s/%s\" time=\"%s\" capture_file=\"%s\">\n", PACKAGE, VERSION, ts, filename ? filename : "");
261 write_json_preamble(FILE *fh)
266 /* Check if the str match the protocolfilter. json_filter is space
267 delimited string and str need to exact-match to one of the value. */
268 gboolean check_protocolfilter(gchar **protocolfilter, const char *str)
270 gboolean res = FALSE;
273 if (str == NULL || protocolfilter == NULL) {
277 for (ptr = protocolfilter; *ptr; ptr++) {
278 if (strcmp(*ptr, str) == 0) {
288 write_pdml_proto_tree(gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
290 write_pdml_data data;
292 /* Create the output */
295 data.src_list = edt->pi.data_src;
297 data.filter = protocolfilter;
299 fprintf(fh, "<packet>\n");
301 /* Print a "geninfo" protocol as required by PDML */
302 print_pdml_geninfo(edt->tree, fh);
304 proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
307 fprintf(fh, "</packet>\n\n");
311 write_json_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
313 write_json_data data;
315 time_t t = time(NULL);
316 struct tm * timeinfo;
317 static gboolean is_first = TRUE;
319 /* Create the output */
322 data.src_list = edt->pi.data_src;
324 data.filter = protocolfilter;
325 data.print_hex = print_args->print_hex;
327 timeinfo = localtime(&t);
328 strftime(ts, 30, "%Y-%m-%d", timeinfo);
336 fprintf(fh, " \"_index\": \"packets-%s\",\n", ts);
337 fputs(" \"_type\": \"pcap_file\",\n", fh);
338 fputs(" \"_score\": null,\n", fh);
339 fputs(" \"_source\": {\n", fh);
340 fputs(" \"layers\": {\n", fh);
342 proto_tree_children_foreach(edt->tree, proto_tree_write_node_json,
352 write_ek_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
354 write_json_data data;
356 time_t t = time(NULL);
359 GPtrArray *finfo_array;
361 /* Create the output */
364 data.src_list = edt->pi.data_src;
366 data.filter = protocolfilter;
367 data.print_hex = print_args->print_hex;
370 timeinfo = localtime(&t);
371 strftime(ts, 30, "%Y-%m-%d", timeinfo);
374 /* Get frame protocol's finfo. */
375 finfo_array = proto_find_finfo(edt->tree, proto_frame);
376 if (g_ptr_array_len(finfo_array) < 1) {
379 /* frame.time --> geninfo.timestamp */
380 finfo_array = proto_find_finfo(edt->tree, hf_frame_arrival_time);
381 if (g_ptr_array_len(finfo_array) < 1) {
384 timestamp = (nstime_t *)fvalue_get(&((field_info*)finfo_array->pdata[0])->value);
385 g_ptr_array_free(finfo_array, TRUE);
388 fprintf(fh, "{\"index\" : {\"_index\": \"packets-%s\", \"_type\": \"pcap_file\", \"_score\": null}}\n", ts);
389 /* Timestamp added for time indexing in Elasticsearch */
390 fprintf(fh, "{\"timestamp\" : \"%" G_GUINT64_FORMAT "%03d\", \"layers\" : {", (guint64)timestamp->secs, timestamp->nsecs/1000000);
393 proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek,
398 /* Write out a tree's data, and any child nodes, as PDML */
400 proto_tree_write_node_pdml(proto_node *node, gpointer data)
402 field_info *fi = PNODE_FINFO(node);
403 write_pdml_data *pdata = (write_pdml_data*) data;
404 const gchar *label_ptr;
405 gchar label_str[ITEM_LABEL_LENGTH];
406 char *dfilter_string;
408 gboolean wrap_in_fake_protocol;
410 /* dissection with an invisible proto tree? */
413 /* Will wrap up top-level field items inside a fake protocol wrapper to
414 preserve the PDML schema */
415 wrap_in_fake_protocol =
416 (((fi->hfinfo->type != FT_PROTOCOL) ||
417 (fi->hfinfo->id == proto_data)) &&
418 (pdata->level == 0));
420 /* Indent to the correct level */
421 for (i = -1; i < pdata->level; i++) {
422 fputs(" ", pdata->fh);
425 if (wrap_in_fake_protocol) {
426 /* Open fake protocol wrapper */
427 fputs("<proto name=\"fake-field-wrapper\">\n", pdata->fh);
429 /* Indent to increased level before writing out field */
431 for (i = -1; i < pdata->level; i++) {
432 fputs(" ", pdata->fh);
436 /* Text label. It's printed as a field with no name. */
437 if (fi->hfinfo->id == hf_text_only) {
440 label_ptr = fi->rep->representation;
446 /* Show empty name since it is a required field */
447 fputs("<field name=\"", pdata->fh);
448 fputs("\" show=\"", pdata->fh);
449 print_escaped_xml(pdata->fh, label_ptr);
451 fprintf(pdata->fh, "\" size=\"%d", fi->length);
452 if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
453 fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
455 fprintf(pdata->fh, "\" pos=\"%d", fi->start);
458 if (fi->length > 0) {
459 fputs("\" value=\"", pdata->fh);
460 pdml_write_field_hex_value(pdata, fi);
463 if (node->first_child != NULL) {
464 fputs("\">\n", pdata->fh);
467 fputs("\"/>\n", pdata->fh);
471 /* Uninterpreted data, i.e., the "Data" protocol, is
472 * printed as a field instead of a protocol. */
473 else if (fi->hfinfo->id == proto_data) {
474 /* Write out field with data */
475 fputs("<field name=\"data\" value=\"", pdata->fh);
476 pdml_write_field_hex_value(pdata, fi);
477 fputs("\">\n", pdata->fh);
479 /* Normal protocols and fields */
481 if ((fi->hfinfo->type == FT_PROTOCOL) && (fi->hfinfo->id != proto_expert)) {
482 fputs("<proto name=\"", pdata->fh);
485 fputs("<field name=\"", pdata->fh);
487 print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
491 * http://www.nbee.org/doku.php?id=netpdl:pdml_specification
493 * the show fields contains things in 'human readable' format
494 * showname: contains only the name of the field
495 * show: contains only the data of the field
496 * showdtl: contains additional details of the field data
497 * showmap: contains mappings of the field data (e.g. the hostname to an IP address)
499 * XXX - the showname shouldn't contain the field data itself
500 * (like it's contained in the fi->rep->representation).
501 * Unfortunately, we don't have the field data representation for
502 * all fields, so this isn't currently possible */
503 fputs("\" showname=\"", pdata->fh);
504 print_escaped_xml(pdata->fh, fi->hfinfo->name);
508 fputs("\" showname=\"", pdata->fh);
509 print_escaped_xml(pdata->fh, fi->rep->representation);
512 label_ptr = label_str;
513 proto_item_fill_label(fi, label_str);
514 fputs("\" showname=\"", pdata->fh);
515 print_escaped_xml(pdata->fh, label_ptr);
518 if (PROTO_ITEM_IS_HIDDEN(node))
519 fprintf(pdata->fh, "\" hide=\"yes");
521 fprintf(pdata->fh, "\" size=\"%d", fi->length);
522 if (node->parent && node->parent->finfo && (fi->start < node->parent->finfo->start)) {
523 fprintf(pdata->fh, "\" pos=\"%d", node->parent->finfo->start + fi->start);
525 fprintf(pdata->fh, "\" pos=\"%d", fi->start);
527 /* fprintf(pdata->fh, "\" id=\"%d", fi->hfinfo->id);*/
529 /* show, value, and unmaskedvalue attributes */
530 switch (fi->hfinfo->type)
535 fputs("\" show=\"\" value=\"", pdata->fh);
538 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
539 if (dfilter_string != NULL) {
541 fputs("\" show=\"", pdata->fh);
542 print_escaped_xml(pdata->fh, dfilter_string);
544 wmem_free(NULL, dfilter_string);
547 * XXX - should we omit "value" for any fields?
548 * What should we do for fields whose length is 0?
549 * They might come from a pseudo-header or from
550 * the capture header (e.g., time stamps), or
551 * they might be generated fields.
553 if (fi->length > 0) {
554 fputs("\" value=\"", pdata->fh);
556 if (fi->hfinfo->bitmask!=0) {
557 switch (fi->value.ftype->ftype) {
562 fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
568 fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
574 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
581 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
584 g_assert_not_reached();
586 fputs("\" unmaskedvalue=\"", pdata->fh);
587 pdml_write_field_hex_value(pdata, fi);
590 pdml_write_field_hex_value(pdata, fi);
595 if (node->first_child != NULL) {
596 fputs("\">\n", pdata->fh);
598 else if (fi->hfinfo->id == proto_data) {
599 fputs("\">\n", pdata->fh);
602 fputs("\"/>\n", pdata->fh);
606 /* We print some levels for PDML. Recurse here. */
607 if (node->first_child != NULL) {
608 if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) {
610 proto_tree_children_foreach(node,
611 proto_tree_write_node_pdml, pdata);
614 /* Indent to the correct level */
615 for (i = -2; i < pdata->level; i++) {
616 fputs(" ", pdata->fh);
618 /* print dummy field */
619 fputs("<field name=\"filtered\" value=\"", pdata->fh);
620 print_escaped_xml(pdata->fh, fi->hfinfo->abbrev);
621 fputs("\" />\n", pdata->fh);
625 /* Take back the extra level we added for fake wrapper protocol */
626 if (wrap_in_fake_protocol) {
630 if (node->first_child != NULL) {
631 /* Indent to correct level */
632 for (i = -1; i < pdata->level; i++) {
633 fputs(" ", pdata->fh);
635 /* Close off current element */
636 /* Data and expert "protocols" use simple tags */
637 if ((fi->hfinfo->id != proto_data) && (fi->hfinfo->id != proto_expert)) {
638 if (fi->hfinfo->type == FT_PROTOCOL) {
639 fputs("</proto>\n", pdata->fh);
642 fputs("</field>\n", pdata->fh);
645 fputs("</field>\n", pdata->fh);
649 /* Close off fake wrapper protocol */
650 if (wrap_in_fake_protocol) {
651 fputs("</proto>\n", pdata->fh);
656 /* Write out a tree's data, and any child nodes, as JSON */
658 proto_tree_write_node_json(proto_node *node, gpointer data)
660 field_info *fi = PNODE_FINFO(node);
661 write_json_data *pdata = (write_json_data*) data;
662 const gchar *label_ptr;
663 char *dfilter_string;
666 /* dissection with an invisible proto tree? */
669 /* Indent to the correct level */
670 for (i = -3; i < pdata->level; i++) {
671 fputs(" ", pdata->fh);
674 /* Text label. It's printed as a field with no name. */
675 if (fi->hfinfo->id == hf_text_only) {
678 label_ptr = fi->rep->representation;
684 /* Show empty name since it is a required field */
685 fputs("\"", pdata->fh);
686 print_escaped_json(pdata->fh, label_ptr);
688 if (node->first_child != NULL) {
689 fputs("\": {\n", pdata->fh);
692 if (node->next == NULL) {
693 fputs("\": \"\"\n", pdata->fh);
695 fputs("\": \"\",\n", pdata->fh);
700 /* Normal protocols and fields */
705 if (pdata->print_hex && fi->length > 0) {
706 fputs("\"", pdata->fh);
707 print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
708 fputs("_raw", pdata->fh);
709 fputs("\": \"", pdata->fh);
711 if (fi->hfinfo->bitmask!=0) {
712 switch (fi->value.ftype->ftype) {
717 fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
723 fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
729 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
736 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
739 g_assert_not_reached();
741 fputs("\",\n", pdata->fh);
744 json_write_field_hex_value(pdata, fi);
745 fputs("\",\n", pdata->fh);
748 /* Indent to the correct level */
749 for (i = -3; i < pdata->level; i++) {
750 fputs(" ", pdata->fh);
755 fputs("\"", pdata->fh);
757 print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
759 /* show, value, and unmaskedvalue attributes */
760 switch (fi->hfinfo->type)
763 if (node->first_child != NULL) {
764 fputs("\": {\n", pdata->fh);
768 if (node->first_child != NULL) {
769 fputs("\": {\n", pdata->fh);
771 if (node->next == NULL) {
772 fputs("\": \"\"\n", pdata->fh);
774 fputs("\": \"\",\n", pdata->fh);
779 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
780 if (dfilter_string != NULL) {
781 if (node->first_child == NULL) {
782 fputs("\": \"", pdata->fh);
783 print_escaped_json(pdata->fh, dfilter_string);
785 fputs("\": {\n", pdata->fh);
788 wmem_free(NULL, dfilter_string);
790 if (node->first_child == NULL) {
791 if (node->next == NULL) {
792 fputs("\"\n", pdata->fh);
794 fputs("\",\n", pdata->fh);
801 /* We print some levels for JSON. Recurse here. */
802 if (node->first_child != NULL) {
803 if (pdata->filter != NULL) {
804 if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) {
806 proto_tree_children_foreach(node,
807 proto_tree_write_node_json, pdata);
810 /* Indent to the correct level */
811 for (i = -4; i < pdata->level; i++) {
812 fputs(" ", pdata->fh);
814 /* print dummy field */
815 fputs("\"filtered\": \"", pdata->fh);
816 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
817 fputs("\"\n", pdata->fh);
821 proto_tree_children_foreach(node,
822 proto_tree_write_node_json, pdata);
827 if (node->first_child != NULL) {
828 /* Indent to correct level */
829 for (i = -3; i < pdata->level; i++) {
830 fputs(" ", pdata->fh);
832 /* Close off current element */
833 if (node->next == NULL) {
834 fputs("}\n", pdata->fh);
836 fputs("},\n", pdata->fh);
841 /* Write out a tree's data, and any child nodes, as JSON for EK */
843 proto_tree_write_node_ek(proto_node *node, gpointer data)
845 field_info *fi = PNODE_FINFO(node);
846 field_info *fi_parent = PNODE_FINFO(node->parent);
847 write_json_data *pdata = (write_json_data*) data;
848 const gchar *label_ptr;
849 char *dfilter_string;
851 gchar *abbrev_escaped = NULL;
853 /* dissection with an invisible proto tree? */
856 /* Text label. It's printed as a field with no name. */
857 if (fi->hfinfo->id == hf_text_only) {
860 label_ptr = fi->rep->representation;
866 /* Show empty name since it is a required field */
867 fputs("\"", pdata->fh);
868 if (fi_parent != NULL) {
869 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
870 fputs("_", pdata->fh);
872 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
874 if (node->first_child != NULL) {
875 fputs("\": \"", pdata->fh);
876 print_escaped_json(pdata->fh, label_ptr);
877 fputs("\",", pdata->fh);
881 if (node->next == NULL) {
882 fputs("\": \"", pdata->fh);
883 print_escaped_json(pdata->fh, label_ptr);
884 fputs("\"", pdata->fh);
886 fputs("\": \"", pdata->fh);
887 print_escaped_json(pdata->fh, label_ptr);
888 fputs("\",", pdata->fh);
893 /* Normal protocols and fields */
898 if (pdata->print_hex && fi->length > 0) {
899 fputs("\"", pdata->fh);
900 if (fi_parent != NULL) {
901 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
902 fputs("_", pdata->fh);
904 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
905 fputs("_raw", pdata->fh);
906 fputs("\": \"", pdata->fh);
908 if (fi->hfinfo->bitmask!=0) {
909 switch (fi->value.ftype->ftype) {
914 fprintf(pdata->fh, "%X", (guint) fvalue_get_sinteger(&fi->value));
920 fprintf(pdata->fh, "%X", fvalue_get_uinteger(&fi->value));
926 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_sinteger64(&fi->value));
933 fprintf(pdata->fh, "%" G_GINT64_MODIFIER "X", fvalue_get_uinteger64(&fi->value));
936 g_assert_not_reached();
938 fputs("\",", pdata->fh);
941 json_write_field_hex_value(pdata, fi);
942 fputs("\",", pdata->fh);
948 fputs("\"", pdata->fh);
950 if (fi_parent != NULL) {
951 print_escaped_ek(pdata->fh, fi_parent->hfinfo->abbrev);
952 fputs("_", pdata->fh);
954 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
956 /* show, value, and unmaskedvalue attributes */
957 switch (fi->hfinfo->type)
960 if (node->first_child != NULL) {
961 fputs("\": {", pdata->fh);
965 if (node->first_child != NULL) {
966 fputs("\": \"\",", pdata->fh);
968 if (node->next == NULL) {
969 fputs("\": \"\"", pdata->fh);
971 fputs("\": \"\",", pdata->fh);
976 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
977 if (dfilter_string != NULL) {
978 if (node->first_child == NULL) {
979 fputs("\": \"", pdata->fh);
980 print_escaped_json(pdata->fh, dfilter_string);
982 fputs("\": \"\",", pdata->fh);
985 wmem_free(NULL, dfilter_string);
987 if (node->first_child == NULL) {
988 if (node->next == NULL) {
989 fputs("\"", pdata->fh);
991 fputs("\",", pdata->fh);
998 /* We print some levels for JSON. Recurse here. */
999 if (node->first_child != NULL) {
1001 if (pdata->filter != NULL) {
1003 /* to to thread the '.' and '_' equally. The '.' is replace by print_escaped_ek for '_' */
1004 if (fi->hfinfo->abbrev != NULL) {
1005 if (strlen(fi->hfinfo->abbrev) > 0) {
1006 abbrev_escaped = g_strdup(fi->hfinfo->abbrev);
1009 while(abbrev_escaped[i]!='\0') {
1010 if(abbrev_escaped[i]=='.')
1012 abbrev_escaped[i]='_';
1019 if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev) || check_protocolfilter(pdata->filter, abbrev_escaped)) {
1021 proto_tree_children_foreach(node,
1022 proto_tree_write_node_ek, pdata);
1025 /* print dummy field */
1026 fputs("\"filtered\": \"", pdata->fh);
1027 print_escaped_ek(pdata->fh, fi->hfinfo->abbrev);
1028 fputs("\"", pdata->fh);
1031 /* release abbrev_escaped string */
1032 if (abbrev_escaped != NULL) {
1033 g_free(abbrev_escaped);
1038 proto_tree_children_foreach(node,
1039 proto_tree_write_node_ek, pdata);
1044 if (node->first_child != NULL) {
1045 if (fi->hfinfo->type == FT_PROTOCOL) {
1046 /* Close off current element */
1047 if (node->next == NULL) {
1048 fputs("}", pdata->fh);
1050 fputs("},", pdata->fh);
1053 if (node->next != NULL) {
1054 fputs(",", pdata->fh);
1060 /* Print info for a 'geninfo' pseudo-protocol. This is required by
1061 * the PDML spec. The information is contained in Wireshark's 'frame' protocol,
1062 * but we produce a 'geninfo' protocol in the PDML to conform to spec.
1063 * The 'frame' protocol follows the 'geninfo' protocol in the PDML. */
1065 print_pdml_geninfo(proto_tree *tree, FILE *fh)
1067 guint32 num, len, caplen;
1068 nstime_t *timestamp;
1069 GPtrArray *finfo_array;
1070 field_info *frame_finfo;
1073 /* Get frame protocol's finfo. */
1074 finfo_array = proto_find_finfo(tree, proto_frame);
1075 if (g_ptr_array_len(finfo_array) < 1) {
1078 frame_finfo = (field_info *)finfo_array->pdata[0];
1079 g_ptr_array_free(finfo_array, TRUE);
1081 /* frame.number --> geninfo.num */
1082 finfo_array = proto_find_finfo(tree, hf_frame_number);
1083 if (g_ptr_array_len(finfo_array) < 1) {
1086 num = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
1087 g_ptr_array_free(finfo_array, TRUE);
1089 /* frame.frame_len --> geninfo.len */
1090 finfo_array = proto_find_finfo(tree, hf_frame_len);
1091 if (g_ptr_array_len(finfo_array) < 1) {
1094 len = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
1095 g_ptr_array_free(finfo_array, TRUE);
1097 /* frame.cap_len --> geninfo.caplen */
1098 finfo_array = proto_find_finfo(tree, hf_frame_capture_len);
1099 if (g_ptr_array_len(finfo_array) < 1) {
1102 caplen = fvalue_get_uinteger(&((field_info*)finfo_array->pdata[0])->value);
1103 g_ptr_array_free(finfo_array, TRUE);
1105 /* frame.time --> geninfo.timestamp */
1106 finfo_array = proto_find_finfo(tree, hf_frame_arrival_time);
1107 if (g_ptr_array_len(finfo_array) < 1) {
1110 timestamp = (nstime_t *)fvalue_get(&((field_info*)finfo_array->pdata[0])->value);
1111 g_ptr_array_free(finfo_array, TRUE);
1113 /* Print geninfo start */
1115 " <proto name=\"geninfo\" pos=\"0\" showname=\"General information\" size=\"%d\">\n",
1116 frame_finfo->length);
1118 /* Print geninfo.num */
1120 " <field name=\"num\" pos=\"0\" show=\"%u\" showname=\"Number\" value=\"%x\" size=\"%d\"/>\n",
1121 num, num, frame_finfo->length);
1123 /* Print geninfo.len */
1125 " <field name=\"len\" pos=\"0\" show=\"%u\" showname=\"Frame Length\" value=\"%x\" size=\"%d\"/>\n",
1126 len, len, frame_finfo->length);
1128 /* Print geninfo.caplen */
1130 " <field name=\"caplen\" pos=\"0\" show=\"%u\" showname=\"Captured Length\" value=\"%x\" size=\"%d\"/>\n",
1131 caplen, caplen, frame_finfo->length);
1133 tmp = abs_time_to_str(NULL, timestamp, ABSOLUTE_TIME_LOCAL, TRUE);
1135 /* Print geninfo.timestamp */
1137 " <field name=\"timestamp\" pos=\"0\" show=\"%s\" showname=\"Captured Time\" value=\"%d.%09d\" size=\"%d\"/>\n",
1138 tmp, (int) timestamp->secs, timestamp->nsecs, frame_finfo->length);
1140 wmem_free(NULL, tmp);
1142 /* Print geninfo end */
1148 write_pdml_finale(FILE *fh)
1150 fputs("</pdml>\n", fh);
1154 write_json_finale(FILE *fh)
1160 write_psml_preamble(column_info *cinfo, FILE *fh)
1164 fputs("<?xml version=\"1.0\"?>\n", fh);
1165 fputs("<psml version=\"" PSML_VERSION "\" ", fh);
1166 fprintf(fh, "creator=\"%s/%s\">\n", PACKAGE, VERSION);
1167 fprintf(fh, "<structure>\n");
1169 for (i = 0; i < cinfo->num_cols; i++) {
1170 fprintf(fh, "<section>");
1171 print_escaped_xml(fh, cinfo->columns[i].col_title);
1172 fprintf(fh, "</section>\n");
1175 fprintf(fh, "</structure>\n\n");
1179 write_psml_columns(epan_dissect_t *edt, FILE *fh)
1183 fprintf(fh, "<packet>\n");
1185 for (i = 0; i < edt->pi.cinfo->num_cols; i++) {
1186 fprintf(fh, "<section>");
1187 print_escaped_xml(fh, edt->pi.cinfo->columns[i].col_data);
1188 fprintf(fh, "</section>\n");
1191 fprintf(fh, "</packet>\n\n");
1195 write_psml_finale(FILE *fh)
1197 fputs("</psml>\n", fh);
1200 static gchar *csv_massage_str(const gchar *source, const gchar *exceptions)
1205 /* In general, our output for any field can contain Unicode characters,
1206 so g_strescape (which escapes any non-ASCII) is the wrong thing to do.
1207 Unfortunately glib doesn't appear to provide g_unicode_strescape()... */
1208 csv_str = g_strescape(source, exceptions);
1210 /* Locate the UTF-8 right arrow character and replace it by an ASCII equivalent */
1211 while ( (tmp_str = strstr(tmp_str, UTF8_RIGHTWARDS_ARROW)) != NULL ) {
1217 while ( (tmp_str = strstr(tmp_str, "\\\"")) != NULL )
1222 static void csv_write_str(const char *str, char sep, FILE *fh)
1226 /* Do not escape the UTF-8 right arrow character */
1227 csv_str = csv_massage_str(str, UTF8_RIGHTWARDS_ARROW);
1228 fprintf(fh, "\"%s\"%c", csv_str, sep);
1233 write_csv_column_titles(column_info *cinfo, FILE *fh)
1237 for (i = 0; i < cinfo->num_cols - 1; i++)
1238 csv_write_str(cinfo->columns[i].col_title, ',', fh);
1239 csv_write_str(cinfo->columns[i].col_title, '\n', fh);
1243 write_csv_columns(epan_dissect_t *edt, FILE *fh)
1247 for (i = 0; i < edt->pi.cinfo->num_cols - 1; i++)
1248 csv_write_str(edt->pi.cinfo->columns[i].col_data, ',', fh);
1249 csv_write_str(edt->pi.cinfo->columns[i].col_data, '\n', fh);
1253 write_carrays_hex_data(guint32 num, FILE *fh, epan_dissect_t *edt)
1255 guint32 i = 0, src_num = 0;
1262 struct data_source *src;
1264 for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
1265 memset(ascii, 0, sizeof(ascii));
1266 src = (struct data_source *)src_le->data;
1267 tvb = get_data_source_tvb(src);
1268 length = tvb_captured_length(tvb);
1272 cp = tvb_get_ptr(tvb, 0, length);
1274 name = get_data_source_name(src);
1276 fprintf(fh, "/* %s */\n", name);
1277 wmem_free(NULL, name);
1280 fprintf(fh, "static const unsigned char pkt%u_%u[%u] = {\n",
1281 num, src_num, length);
1283 fprintf(fh, "static const unsigned char pkt%u[%u] = {\n",
1288 for (i = 0; i < length; i++) {
1289 fprintf(fh, "0x%02x", *(cp + i));
1290 ascii[i % 8] = g_ascii_isprint(*(cp + i)) ? *(cp + i) : '.';
1292 if (i == (length - 1)) {
1297 for ( j = 0; j < 8 - rem; j++ )
1300 fprintf(fh, " /* %s */\n};\n\n", ascii);
1304 if (!((i + 1) % 8)) {
1305 fprintf(fh, ", /* %s */\n", ascii);
1306 memset(ascii, 0, sizeof(ascii));
1316 * Find the data source for a specified field, and return a pointer
1317 * to the data in it. Returns NULL if the data is out of bounds.
1319 /* XXX: What am I missing ?
1320 * Why bother searching for fi->ds_tvb for the matching tvb
1321 * in the data_source list ?
1322 * IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
1325 static const guint8 *
1326 get_field_data(GSList *src_list, field_info *fi)
1330 gint length, tvbuff_length;
1331 struct data_source *src;
1333 for (src_le = src_list; src_le != NULL; src_le = src_le->next) {
1334 src = (struct data_source *)src_le->data;
1335 src_tvb = get_data_source_tvb(src);
1336 if (fi->ds_tvb == src_tvb) {
1340 * XXX - a field can have a length that runs past
1341 * the end of the tvbuff. Ideally, that should
1342 * be fixed when adding an item to the protocol
1343 * tree, but checking the length when doing
1344 * that could be expensive. Until we fix that,
1345 * we'll do the check here.
1347 tvbuff_length = tvb_captured_length_remaining(src_tvb,
1349 if (tvbuff_length < 0) {
1352 length = fi->length;
1353 if (length > tvbuff_length)
1354 length = tvbuff_length;
1355 return tvb_get_ptr(src_tvb, fi->start, length);
1358 g_assert_not_reached();
1359 return NULL; /* not found */
1362 /* Print a string, escaping out certain characters that need to
1363 * escaped out for XML. */
1365 print_escaped_xml(FILE *fh, const char *unescaped_string)
1370 for (p = unescaped_string; *p != '\0'; p++) {
1382 fputs(""", fh);
1385 fputs("'", fh);
1388 if (g_ascii_isprint(*p))
1391 g_snprintf(temp_str, sizeof(temp_str), "\\x%x", (guint8)*p);
1392 fputs(temp_str, fh);
1398 /* Print a string, escaping out certain characters that need to
1399 * escaped out for JSON. */
1401 print_escaped_json(FILE *fh, const char *unescaped_string)
1406 for (p = unescaped_string; *p != '\0'; p++) {
1433 if (g_ascii_isprint(*p))
1436 g_snprintf(temp_str, sizeof(temp_str), "\\u00%u", (guint8)*p);
1437 fputs(temp_str, fh);
1443 /* Print a string, escaping out certain characters that need to
1444 * escaped out for Elasticsearch title. */
1446 print_escaped_ek(FILE *fh, const char *unescaped_string)
1451 for (p = unescaped_string; *p != '\0'; p++) {
1481 if (g_ascii_isprint(*p))
1484 g_snprintf(temp_str, sizeof(temp_str), "\\u00%u", (guint8)*p);
1485 fputs(temp_str, fh);
1492 pdml_write_field_hex_value(write_pdml_data *pdata, field_info *fi)
1500 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1501 fprintf(pdata->fh, "field length invalid!");
1505 /* Find the data for this field. */
1506 pd = get_field_data(pdata->src_list, fi);
1509 /* Print a simple hex dump */
1510 for (i = 0 ; i < fi->length; i++) {
1511 fprintf(pdata->fh, "%02x", pd[i]);
1517 json_write_field_hex_value(write_json_data *pdata, field_info *fi)
1525 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
1526 fprintf(pdata->fh, "field length invalid!");
1530 /* Find the data for this field. */
1531 pd = get_field_data(pdata->src_list, fi);
1534 /* Print a simple hex dump */
1535 for (i = 0 ; i < fi->length; i++) {
1536 fprintf(pdata->fh, "%02x", pd[i]);
1542 print_hex_data(print_stream_t *stream, epan_dissect_t *edt)
1544 gboolean multiple_sources;
1550 struct data_source *src;
1553 * Set "multiple_sources" iff this frame has more than one
1554 * data source; if it does, we need to print the name of
1555 * the data source before printing the data from the
1558 multiple_sources = (edt->pi.data_src->next != NULL);
1560 for (src_le = edt->pi.data_src; src_le != NULL;
1561 src_le = src_le->next) {
1562 src = (struct data_source *)src_le->data;
1563 tvb = get_data_source_tvb(src);
1564 if (multiple_sources) {
1565 name = get_data_source_name(src);
1566 line = g_strdup_printf("%s:", name);
1567 wmem_free(NULL, name);
1568 print_line(stream, 0, line);
1571 length = tvb_captured_length(tvb);
1574 cp = tvb_get_ptr(tvb, 0, length);
1575 if (!print_hex_data_buffer(stream, cp, length,
1576 (packet_char_enc)edt->pi.fd->flags.encoding))
1583 * This routine is based on a routine created by Dan Lasley
1584 * <DLASLEY@PROMUS.com>.
1586 * It was modified for Wireshark by Gilbert Ramirez and others.
1589 #define MAX_OFFSET_LEN 8 /* max length of hex offset of bytes */
1590 #define BYTES_PER_LINE 16 /* max byte values printed on a line */
1591 #define HEX_DUMP_LEN (BYTES_PER_LINE*3)
1592 /* max number of characters hex dump takes -
1593 2 digits plus trailing blank */
1594 #define DATA_DUMP_LEN (HEX_DUMP_LEN + 2 + BYTES_PER_LINE)
1595 /* number of characters those bytes take;
1596 3 characters per byte of hex dump,
1597 2 blanks separating hex from ASCII,
1598 1 character per byte of ASCII dump */
1599 #define MAX_LINE_LEN (MAX_OFFSET_LEN + 2 + DATA_DUMP_LEN)
1600 /* number of characters per line;
1601 offset, 2 blanks separating offset
1602 from data dump, data dump */
1605 print_hex_data_buffer(print_stream_t *stream, const guchar *cp,
1606 guint length, packet_char_enc encoding)
1608 register unsigned int ad, i, j, k, l;
1610 gchar line[MAX_LINE_LEN + 1];
1611 unsigned int use_digits;
1613 static gchar binhex[16] = {
1614 '0', '1', '2', '3', '4', '5', '6', '7',
1615 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1618 * How many of the leading digits of the offset will we supply?
1619 * We always supply at least 4 digits, but if the maximum offset
1620 * won't fit in 4 digits, we use as many digits as will be needed.
1622 if (((length - 1) & 0xF0000000) != 0)
1623 use_digits = 8; /* need all 8 digits */
1624 else if (((length - 1) & 0x0F000000) != 0)
1625 use_digits = 7; /* need 7 digits */
1626 else if (((length - 1) & 0x00F00000) != 0)
1627 use_digits = 6; /* need 6 digits */
1628 else if (((length - 1) & 0x000F0000) != 0)
1629 use_digits = 5; /* need 5 digits */
1631 use_digits = 4; /* we'll supply 4 digits */
1637 while (i < length) {
1638 if ((i & 15) == 0) {
1640 * Start of a new line.
1646 c = (ad >> (l*4)) & 0xF;
1647 line[j++] = binhex[c];
1651 memset(line+j, ' ', DATA_DUMP_LEN);
1654 * Offset in line of ASCII dump.
1656 k = j + HEX_DUMP_LEN + 2;
1659 line[j++] = binhex[c>>4];
1660 line[j++] = binhex[c&0xf];
1662 if (encoding == PACKET_CHAR_ENC_CHAR_EBCDIC) {
1663 c = EBCDIC_to_ASCII1(c);
1665 line[k++] = ((c >= ' ') && (c < 0x7f)) ? c : '.';
1667 if (((i & 15) == 0) || (i == length)) {
1669 * We'll be starting a new line, or
1670 * we're finished printing this buffer;
1671 * dump out the line we've constructed,
1672 * and advance the offset.
1675 if (!print_line(stream, 0, line))
1683 gsize output_fields_num_fields(output_fields_t* fields)
1687 if (NULL == fields->fields) {
1690 return fields->fields->len;
1694 void output_fields_free(output_fields_t* fields)
1698 if (NULL != fields->fields) {
1701 if (NULL != fields->field_indicies) {
1702 /* Keys are stored in fields->fields, values are
1705 g_hash_table_destroy(fields->field_indicies);
1708 if (NULL != fields->field_values) {
1709 g_free(fields->field_values);
1712 for(i = 0; i < fields->fields->len; ++i) {
1713 gchar* field = (gchar *)g_ptr_array_index(fields->fields,i);
1716 g_ptr_array_free(fields->fields, TRUE);
1722 #define COLUMN_FIELD_FILTER "_ws.col."
1724 void output_fields_add(output_fields_t *fields, const gchar *field)
1732 if (NULL == fields->fields) {
1733 fields->fields = g_ptr_array_new();
1736 field_copy = g_strdup(field);
1738 g_ptr_array_add(fields->fields, field_copy);
1740 /* See if we have a column as a field entry */
1741 if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1742 fields->includes_col_fields = TRUE;
1747 output_field_check(void *data, void *user_data)
1749 gchar *field = (gchar *)data;
1750 GSList **invalid_fields = (GSList **)user_data;
1752 if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER)))
1755 if (!proto_registrar_get_byname(field)) {
1756 *invalid_fields = g_slist_prepend(*invalid_fields, field);
1762 output_fields_valid(output_fields_t *fields)
1764 GSList *invalid_fields = NULL;
1765 if (fields->fields == NULL) {
1769 g_ptr_array_foreach(fields->fields, output_field_check, &invalid_fields);
1771 return invalid_fields;
1774 gboolean output_fields_set_option(output_fields_t *info, gchar *option)
1776 const gchar *option_name;
1777 const gchar *option_value;
1782 if ('\0' == *option) {
1783 return FALSE; /* this happens if we're called from tshark -E '' */
1785 option_name = strtok(option, "=");
1789 option_value = option + strlen(option_name) + 1;
1790 if (*option_value == '\0') {
1794 if (0 == strcmp(option_name, "header")) {
1795 switch (*option_value) {
1797 info->print_header = FALSE;
1800 info->print_header = TRUE;
1807 else if (0 == strcmp(option_name, "separator")) {
1808 switch (*option_value) {
1810 switch (*++option_value) {
1812 info->separator = '\t';
1815 info->separator = ' ';
1818 info->separator = '\\';
1822 info->separator = *option_value;
1827 else if (0 == strcmp(option_name, "occurrence")) {
1828 switch (*option_value) {
1832 info->occurrence = *option_value;
1839 else if (0 == strcmp(option_name, "aggregator")) {
1840 switch (*option_value) {
1842 switch (*++option_value) {
1844 info->aggregator = ' ';
1847 info->aggregator = '\\';
1851 info->aggregator = *option_value;
1856 else if (0 == strcmp(option_name, "quote")) {
1857 switch (*option_value) {
1873 else if (0 == strcmp(option_name, "bom")) {
1874 switch (*option_value) {
1876 info->print_bom = FALSE;
1879 info->print_bom = TRUE;
1890 void output_fields_list_options(FILE *fh)
1892 fprintf(fh, "TShark: The available options for field output \"E\" are:\n");
1893 fputs("bom=y|n Prepend output with the UTF-8 BOM (def: N: no)\n", fh);
1894 fputs("header=y|n Print field abbreviations as first line of output (def: N: no)\n", fh);
1895 fputs("separator=/t|/s|<character> Set the separator to use;\n \"/t\" = tab, \"/s\" = space (def: /t: tab)\n", fh);
1896 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);
1897 fputs("aggregator=,|/s|<character> Set the aggregator to use;\n \",\" = comma, \"/s\" = space (def: ,: comma)\n", fh);
1898 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);
1901 gboolean output_fields_has_cols(output_fields_t* fields)
1904 return fields->includes_col_fields;
1907 void write_fields_preamble(output_fields_t* fields, FILE *fh)
1913 g_assert(fields->fields);
1915 if (fields->print_bom) {
1916 fputs(UTF8_BOM, fh);
1920 if (!fields->print_header) {
1924 for(i = 0; i < fields->fields->len; ++i) {
1925 const gchar* field = (const gchar *)g_ptr_array_index(fields->fields,i);
1927 fputc(fields->separator, fh);
1934 static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
1942 /* Unwrap change made to disambiguiate zero / null */
1943 indx = GPOINTER_TO_UINT(field_index) - 1;
1945 if (fields->field_values[indx] == NULL) {
1946 fields->field_values[indx] = g_ptr_array_new();
1949 /* Essentially: fieldvalues[indx] is a 'GPtrArray *' with each array entry */
1950 /* pointing to a string which is (part of) the final output string. */
1952 fv_p = fields->field_values[indx];
1954 switch (fields->occurrence) {
1956 /* print the value of only the first occurrence of the field */
1957 if (g_ptr_array_len(fv_p) != 0)
1961 /* print the value of only the last occurrence of the field */
1962 g_ptr_array_set_size(fv_p, 0);
1965 /* print the value of all accurrences of the field */
1966 /* If not the first, add the 'aggregator' */
1967 if (g_ptr_array_len(fv_p) > 0) {
1968 g_ptr_array_add(fv_p, (gpointer)g_strdup_printf("%c", fields->aggregator));
1972 g_assert_not_reached();
1976 g_ptr_array_add(fv_p, (gpointer)value);
1979 static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
1981 write_field_data_t *call_data;
1983 gpointer field_index;
1985 call_data = (write_field_data_t *)data;
1986 fi = PNODE_FINFO(node);
1988 /* dissection with an invisible proto tree? */
1991 field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
1992 if (NULL != field_index) {
1993 format_field_values(call_data->fields, field_index,
1994 get_node_field_value(fi, call_data->edt) /* g_ alloc'd string */
1999 if (node->first_child != NULL) {
2000 proto_tree_children_foreach(node, proto_tree_get_node_field_values,
2005 void write_fields_proto_tree(output_fields_t *fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh)
2010 gpointer field_index;
2012 write_field_data_t data;
2015 g_assert(fields->fields);
2019 data.fields = fields;
2022 if (NULL == fields->field_indicies) {
2023 /* Prepare a lookup table from string abbreviation for field to its index. */
2024 fields->field_indicies = g_hash_table_new(g_str_hash, g_str_equal);
2027 while (i < fields->fields->len) {
2028 gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
2029 /* Store field indicies +1 so that zero is not a valid value,
2030 * and can be distinguished from NULL as a pointer.
2033 g_hash_table_insert(fields->field_indicies, field, GUINT_TO_POINTER(i));
2037 /* Array buffer to store values for this packet */
2038 /* Allocate an array for the 'GPtrarray *' the first time */
2039 /* ths function is invoked for a file; */
2040 /* Any and all 'GPtrArray *' are freed (after use) each */
2041 /* time (each packet) this function is invoked for a flle. */
2042 /* XXX: ToDo: use packet-scope'd memory & (if/when implemented) wmem ptr_array */
2043 if (NULL == fields->field_values)
2044 fields->field_values = g_new0(GPtrArray*, fields->fields->len); /* free'd in output_fields_free() */
2046 proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
2049 if (fields->includes_col_fields) {
2050 for (col = 0; col < cinfo->num_cols; col++) {
2051 /* Prepend COLUMN_FIELD_FILTER as the field name */
2052 col_name = g_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->columns[col].col_title);
2053 field_index = g_hash_table_lookup(fields->field_indicies, col_name);
2056 if (NULL != field_index) {
2057 format_field_values(fields, field_index, g_strdup(cinfo->columns[col].col_data));
2062 for(i = 0; i < fields->fields->len; ++i) {
2064 fputc(fields->separator, fh);
2066 if (NULL != fields->field_values[i]) {
2070 fv_p = fields->field_values[i];
2071 if (fields->quote != '\0') {
2072 fputc(fields->quote, fh);
2075 /* Output the array of (partial) field values */
2076 for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
2077 str = (gchar *)g_ptr_array_index(fv_p, j);
2081 if (fields->quote != '\0') {
2082 fputc(fields->quote, fh);
2084 g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
2085 fields->field_values[i] = NULL;
2090 void write_fields_finale(output_fields_t* fields _U_ , FILE *fh _U_)
2095 /* Returns an g_malloced string */
2096 gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt)
2098 if (fi->hfinfo->id == hf_text_only) {
2102 return g_strdup(fi->rep->representation);
2105 return get_field_hex_value(edt->pi.data_src, fi);
2108 else if (fi->hfinfo->id == proto_data) {
2109 /* Uninterpreted data, i.e., the "Data" protocol, is
2110 * printed as a field instead of a protocol. */
2111 return get_field_hex_value(edt->pi.data_src, fi);
2114 /* Normal protocols and fields */
2115 gchar *dfilter_string;
2117 switch (fi->hfinfo->type)
2120 /* Print out the full details for the protocol. */
2122 return g_strdup(fi->rep->representation);
2124 /* Just print out the protocol abbreviation */
2125 return g_strdup(fi->hfinfo->abbrev);
2128 /* Return "1" so that the presence of a field of type
2129 * FT_NONE can be checked when using -T fields */
2130 return g_strdup("1");
2132 dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
2133 if (dfilter_string != NULL) {
2134 gchar* ret = g_strdup(dfilter_string);
2135 wmem_free(NULL, dfilter_string);
2138 return get_field_hex_value(edt->pi.data_src, fi);
2145 get_field_hex_value(GSList *src_list, field_info *fi)
2152 if (fi->length > tvb_captured_length_remaining(fi->ds_tvb, fi->start)) {
2153 return g_strdup("field length invalid!");
2156 /* Find the data for this field. */
2157 pd = get_field_data(src_list, fi);
2164 const int chars_per_byte = 2;
2166 len = chars_per_byte * fi->length;
2167 buffer = (gchar *)g_malloc(sizeof(gchar)*(len + 1));
2168 buffer[len] = '\0'; /* Ensure NULL termination in bad cases */
2170 /* Print a simple hex dump */
2171 for (i = 0 ; i < fi->length; i++) {
2172 g_snprintf(p, chars_per_byte+1, "%02x", pd[i]);
2173 p += chars_per_byte;
2181 output_fields_t* output_fields_new(void)
2183 output_fields_t* fields = g_new(output_fields_t, 1);
2184 fields->print_bom = FALSE;
2185 fields->print_header = FALSE;
2186 fields->separator = '\t';
2187 fields->occurrence = 'a';
2188 fields->aggregator = ',';
2189 fields->fields = NULL; /*Do lazy initialisation */
2190 fields->field_indicies = NULL;
2191 fields->field_values = NULL;
2192 fields->quote ='\0';
2193 fields->includes_col_fields = FALSE;
2198 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2203 * indent-tabs-mode: nil
2206 * vi: set shiftwidth=4 tabstop=8 expandtab:
2207 * :indentSize=4:tabSize=8:noTabs=true: