From c9d8c1c8c518f5c5b9eebb6a922c0eb410356dad Mon Sep 17 00:00:00 2001 From: Martin Kacer Date: Thu, 19 Jan 2017 15:37:54 +0100 Subject: [PATCH] PDML: protocol filter incorrectly filters desired subfields Bug: 12847 Change-Id: I8a560dc44dceb06123d8bcecd512d132ee4ebb0d Reviewed-on: https://code.wireshark.org/review/19671 Petri-Dish: Alexis La Goutte Tested-by: Petri Dish Buildbot Reviewed-by: Alexis La Goutte --- epan/print.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- epan/print.h | 11 ++++++++--- file.c | 4 ++-- tfshark.c | 2 +- tshark.c | 20 ++++++++++++++------ 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/epan/print.c b/epan/print.c index 355cd8279b..d6589368e9 100644 --- a/epan/print.c +++ b/epan/print.c @@ -60,6 +60,7 @@ typedef struct { FILE *fh; GSList *src_list; gchar **filter; + pf_flags filter_flags; } write_pdml_data; typedef struct { @@ -67,6 +68,7 @@ typedef struct { FILE *fh; GSList *src_list; gchar **filter; + pf_flags filter_flags; gboolean print_hex; } write_json_data; @@ -302,7 +304,7 @@ static gboolean check_protocolfilter(gchar **protocolfilter, const char *str) } void -write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh) +write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh) { write_pdml_data data; @@ -321,6 +323,7 @@ write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_diss data.fh = fh; data.src_list = edt->pi.data_src; data.filter = protocolfilter; + data.filter_flags = protocolfilter_flags; proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml, &data); @@ -333,7 +336,7 @@ write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_diss } void -write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh) +write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh) { write_json_data data; char ts[30]; @@ -368,6 +371,7 @@ write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar * data.fh = fh; data.src_list = edt->pi.data_src; data.filter = protocolfilter; + data.filter_flags = protocolfilter_flags; data.print_hex = print_args->print_hex; proto_tree_children_foreach(edt->tree, proto_tree_write_node_json, @@ -384,7 +388,7 @@ write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar * } void -write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh) +write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh) { write_json_data data; char ts[30]; @@ -411,6 +415,7 @@ write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **p data.fh = fh; data.src_list = edt->pi.data_src; data.filter = protocolfilter; + data.filter_flags = protocolfilter_flags; data.print_hex = print_args->print_hex; proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek, @@ -644,10 +649,22 @@ proto_tree_write_node_pdml(proto_node *node, gpointer data) /* We print some levels for PDML. Recurse here. */ if (node->first_child != NULL) { if (pdata->filter == NULL || check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) { + gchar **_filter = NULL; + /* Remove protocol filter for children, if children should be included */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + _filter = pdata->filter; + pdata->filter = NULL; + } + pdata->level++; proto_tree_children_foreach(node, proto_tree_write_node_pdml, pdata); pdata->level--; + + /* Put protocol filter back */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + pdata->filter = _filter; + } } else { /* Indent to the correct level */ for (i = -2; i < pdata->level; i++) { @@ -861,9 +878,21 @@ proto_tree_write_node_json(proto_node *node, gpointer data) /* We print some levels for JSON. Recurse here. */ if (node->first_child != NULL) { if (pdata->filter == NULL || check_protocolfilter(pdata->filter, fi->hfinfo->abbrev)) { + gchar **_filter = NULL; + /* Remove protocol filter for children, if children should be included */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + _filter = pdata->filter; + pdata->filter = NULL; + } + pdata->level++; proto_tree_children_foreach(node, proto_tree_write_node_json, pdata); pdata->level--; + + /* Put protocol filter back */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + pdata->filter = _filter; + } } else { /* Indent to the correct level */ for (i = -4; i < pdata->level; i++) { @@ -1078,9 +1107,21 @@ proto_tree_write_node_ek(proto_node *node, gpointer data) } if(check_protocolfilter(pdata->filter, fi->hfinfo->abbrev) || check_protocolfilter(pdata->filter, abbrev_escaped)) { + gchar **_filter = NULL; + /* Remove protocol filter for children, if children should be included */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + _filter = pdata->filter; + pdata->filter = NULL; + } + pdata->level++; proto_tree_children_foreach(node, proto_tree_write_node_ek, pdata); pdata->level--; + + /* Put protocol filter back */ + if ((pdata->filter_flags&PF_INCLUDE_CHILDREN) == PF_INCLUDE_CHILDREN) { + pdata->filter = _filter; + } } else { /* print dummy field */ fputs("\"filtered\": \"", pdata->fh); diff --git a/epan/print.h b/epan/print.h index 63d3be6932..a5db79a7cb 100644 --- a/epan/print.h +++ b/epan/print.h @@ -86,6 +86,11 @@ typedef enum { FORMAT_XML, /* PDML output */ } fields_format; +typedef enum { + PF_NONE = 0x00, + PF_INCLUDE_CHILDREN = 0x01 +} pf_flags; + /* * Print user selected list of fields */ @@ -112,14 +117,14 @@ WS_DLL_PUBLIC gboolean proto_tree_print(print_args_t *print_args, WS_DLL_PUBLIC gboolean print_hex_data(print_stream_t *stream, epan_dissect_t *edt); WS_DLL_PUBLIC void write_pdml_preamble(FILE *fh, const gchar* filename); -WS_DLL_PUBLIC void write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh); +WS_DLL_PUBLIC void write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh); WS_DLL_PUBLIC void write_pdml_finale(FILE *fh); WS_DLL_PUBLIC void write_json_preamble(FILE *fh); -WS_DLL_PUBLIC void write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh); +WS_DLL_PUBLIC void write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh); WS_DLL_PUBLIC void write_json_finale(FILE *fh); -WS_DLL_PUBLIC void write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh); +WS_DLL_PUBLIC void write_ek_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar **protocolfilter, pf_flags protocolfilter_flags, epan_dissect_t *edt, FILE *fh); WS_DLL_PUBLIC void write_psml_preamble(column_info *cinfo, FILE *fh); WS_DLL_PUBLIC void write_psml_columns(epan_dissect_t *edt, FILE *fh); diff --git a/file.c b/file.c index 547f2bf48c..c8c9c13449 100644 --- a/file.c +++ b/file.c @@ -2518,7 +2518,7 @@ write_pdml_packet(capture_file *cf, frame_data *fdata, epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); /* Write out the information in that tree. */ - write_pdml_proto_tree(NULL, NULL, &args->edt, args->fh); + write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh); epan_dissect_reset(&args->edt); @@ -2812,7 +2812,7 @@ write_json_packet(capture_file *cf, frame_data *fdata, epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL); /* Write out the information in that tree. */ - write_json_proto_tree(NULL, args->print_args, NULL, &args->edt, args->fh); + write_json_proto_tree(NULL, args->print_args, NULL, PF_NONE, &args->edt, args->fh); epan_dissect_reset(&args->edt); diff --git a/tfshark.c b/tfshark.c index a255f78ff6..3e736700f7 100644 --- a/tfshark.c +++ b/tfshark.c @@ -2045,7 +2045,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt) break; case WRITE_XML: - write_pdml_proto_tree(NULL, NULL, edt, stdout); + write_pdml_proto_tree(NULL, NULL, PF_NONE, edt, stdout); printf("\n"); return !ferror(stdout); case WRITE_FIELDS: diff --git a/tshark.c b/tshark.c index 84c8d5f929..f209acc429 100644 --- a/tshark.c +++ b/tshark.c @@ -188,6 +188,7 @@ static print_stream_t *print_stream; static output_fields_t* output_fields = NULL; static gchar **protocolfilter = NULL; +static pf_flags protocolfilter_flags = PF_NONE; /* The line separator used between packets, changeable via the -S option */ static const char *separator = ""; @@ -387,8 +388,11 @@ print_usage(FILE *output) fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); fprintf(output, " -T pdml|ps|psml|json|ek|text|fields\n"); fprintf(output, " format of text output (def: text)\n"); - fprintf(output, " -j protocols layers filter if -T ek|pdml|json selected,\n"); - fprintf(output, " (e.g. \"http tcp ip\",\n"); + fprintf(output, " -j protocols layers filter if -T ek|pdml|json selected\n"); + fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n"); + fprintf(output, " nodes, unless child is specified also in the filter)\n"); + fprintf(output, " -J top level protocol filter if -T ek|pdml|json selected\n"); + fprintf(output, " (e.g. \"http tcp\", filter which expands all child nodes)\n"); fprintf(output, " -e field to print if -Tfields selected (e.g. tcp.port,\n"); fprintf(output, " _ws.col.Info)\n"); fprintf(output, " this option can be repeated to print multiple fields\n"); @@ -717,7 +721,7 @@ main(int argc, char *argv[]) * We do *not* use a leading - because the behavior of a leading - is * platform-dependent. */ -#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "C:e:E:F:gG:hH:j:lo:O:PqQr:R:S:T:U:vVw:W:xX:Y:z:" +#define OPTSTRING "+2" OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON "C:e:E:F:gG:hH:j:J:lo:O:PqQr:R:S:T:U:vVw:W:xX:Y:z:" static const char optstring[] = OPTSTRING; @@ -1192,6 +1196,10 @@ main(int argc, char *argv[]) case 'j': protocolfilter = wmem_strsplit(wmem_epan_scope(), optarg, " ", -1); break; + case 'J': + protocolfilter_flags = PF_INCLUDE_CHILDREN; + protocolfilter = wmem_strsplit(wmem_epan_scope(), optarg, " ", -1); + break; case 'W': /* Select extra information to save in our capture file */ /* This is patterned after the -N flag which may not be the best idea. */ if (strchr(optarg, 'n')) { @@ -3997,7 +4005,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt) break; case WRITE_XML: - write_pdml_proto_tree(output_fields, protocolfilter, edt, stdout); + write_pdml_proto_tree(output_fields, protocolfilter, protocolfilter_flags, edt, stdout); printf("\n"); return !ferror(stdout); case WRITE_FIELDS: @@ -4006,12 +4014,12 @@ print_packet(capture_file *cf, epan_dissect_t *edt) return !ferror(stdout); case WRITE_JSON: print_args.print_hex = print_hex; - write_json_proto_tree(output_fields, &print_args, protocolfilter, edt, stdout); + write_json_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout); printf("\n"); return !ferror(stdout); case WRITE_EK: print_args.print_hex = print_hex; - write_ek_proto_tree(output_fields, &print_args, protocolfilter, edt, stdout); + write_ek_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout); printf("\n"); return !ferror(stdout); }