diff options
author | Michael Mann <mmann78@netscape.net> | 2012-12-08 02:42:40 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2012-12-08 02:42:40 +0000 |
commit | 40eca5f0de867c1f7089152a028fe6006aa8bd5c (patch) | |
tree | 4f0a31b68d64815adec117b5e40626935c430a1b | |
parent | 2ff0d7870aeb66abc5cf2905cb1125bad93b9144 (diff) | |
download | wireshark-40eca5f0de867c1f7089152a028fe6006aa8bd5c.tar.gz |
Allow TShark to specify columns as fields with -e option (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=2892)
svn path=/trunk/; revision=46465
-rw-r--r-- | docbook/wsug_src/WSUG_app_tools.xml | 2 | ||||
-rw-r--r-- | print.c | 72 | ||||
-rw-r--r-- | print.h | 3 | ||||
-rw-r--r-- | tshark.c | 26 |
4 files changed, 70 insertions, 33 deletions
diff --git a/docbook/wsug_src/WSUG_app_tools.xml b/docbook/wsug_src/WSUG_app_tools.xml index 6a1a793077..ad6a213456 100644 --- a/docbook/wsug_src/WSUG_app_tools.xml +++ b/docbook/wsug_src/WSUG_app_tools.xml @@ -81,7 +81,7 @@ Output: -x add output of hex and ASCII dump (Packet Bytes) -T pdml|ps|psml|text|fields format of text output (def: text) - -e <field> field to print if -Tfields selected (e.g. tcp.port); + -e <field> field to print if -Tfields selected (e.g. tcp.port, col.Info); this option can be repeated to print multiple fields -E<fieldsoption>=<value> set options for output when -Tfields selected: header=y|n switch headers on and off @@ -84,6 +84,7 @@ struct _output_fields { GHashTable* field_indicies; emem_strbuf_t** field_values; gchar quote; + gboolean includes_col_fields; }; GHashTable *output_only_tables = NULL; @@ -1328,6 +1329,7 @@ output_fields_t* output_fields_new(void) fields->field_indicies = NULL; fields->field_values = NULL; fields->quote='\0'; + fields->includes_col_fields = FALSE; return fields; } @@ -1364,6 +1366,8 @@ void output_fields_free(output_fields_t* fields) g_free(fields); } +#define COLUMN_FIELD_FILTER "col." + void output_fields_add(output_fields_t* fields, const gchar* field) { gchar* field_copy; @@ -1379,6 +1383,11 @@ void output_fields_add(output_fields_t* fields, const gchar* field) field_copy = g_strdup(field); g_ptr_array_add(fields->fields, field_copy); + + /* See if we have a column as a field entry */ + if (!strncmp(field, COLUMN_FIELD_FILTER, strlen(COLUMN_FIELD_FILTER))) + fields->includes_col_fields = TRUE; + } gboolean output_fields_set_option(output_fields_t* info, gchar* option) @@ -1499,6 +1508,11 @@ void output_fields_list_options(FILE *fh) 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); } +gboolean output_fields_has_cols(output_fields_t* fields) +{ + g_assert(fields); + return fields->includes_col_fields; +} void write_fields_preamble(output_fields_t* fields, FILE *fh) { @@ -1521,6 +1535,25 @@ void write_fields_preamble(output_fields_t* fields, FILE *fh) fputc('\n', fh); } +static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value) +{ + if(NULL != value && '\0' != *value) { + guint actual_index; + actual_index = GPOINTER_TO_UINT(field_index); + /* Unwrap change made to disambiguiate zero / null */ + if (fields->field_values[actual_index - 1] == NULL ) { + fields->field_values[actual_index - 1] = ep_strbuf_new(value); + } else if (fields->occurrence == 'l' ) { + /* print only the value of the last occurrence of the field */ + ep_strbuf_printf(fields->field_values[actual_index - 1],"%s",value); + } else if (fields->occurrence == 'a' ) { + /* print the value of all accurrences of the field */ + ep_strbuf_append_printf(fields->field_values[actual_index - 1], + "%c%s",fields->aggregator,value); + } + } +} + static void proto_tree_get_node_field_values(proto_node *node, gpointer data) { write_field_data_t *call_data; @@ -1535,25 +1568,9 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data) field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev); if(NULL != field_index) { - const gchar* value; - - value = get_node_field_value(fi, call_data->edt); /* ep_alloced string */ - - if(NULL != value && '\0' != *value) { - guint actual_index; - actual_index = GPOINTER_TO_UINT(field_index); - /* Unwrap change made to disambiguiate zero / null */ - if ( call_data->fields->field_values[actual_index - 1] == NULL ) { - call_data->fields->field_values[actual_index - 1] = ep_strbuf_new(value); - } else if ( call_data->fields->occurrence == 'l' ) { - /* print only the value of the last occurrence of the field */ - ep_strbuf_printf(call_data->fields->field_values[actual_index - 1],"%s",value); - } else if ( call_data->fields->occurrence == 'a' ) { - /* print the value of all accurrences of the field */ - ep_strbuf_append_printf(call_data->fields->field_values[actual_index - 1], - "%c%s",call_data->fields->aggregator,value); - } - } + format_field_values(call_data->fields, field_index, + get_node_field_value(fi, call_data->edt) /* ep_alloced string */ + ); } /* Recurse here. */ @@ -1563,9 +1580,12 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data) } } -void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE *fh) +void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh) { gsize i; + gint col; + gchar* col_name; + gpointer field_index; write_field_data_t data; @@ -1597,6 +1617,18 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values, &data); + if (fields->includes_col_fields) { + for (col = 0; col < cinfo->num_cols; col++) { + /* Prepend COLUMN_FIELD_FILTER as the field name */ + col_name = ep_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->col_title[col]); + field_index = g_hash_table_lookup(fields->field_indicies, col_name); + + if(NULL != field_index) { + format_field_values(fields, field_index, cinfo->col_data[col]); + } + } + } + for(i = 0; i < fields->fields->len; ++i) { if(0 != i) { fputc(fields->separator, fh); @@ -123,6 +123,7 @@ extern void output_fields_add(output_fields_t* info, const gchar* field); extern gsize output_fields_num_fields(output_fields_t* info); extern gboolean output_fields_set_option(output_fields_t* info, gchar* option); extern void output_fields_list_options(FILE *fh); +extern gboolean output_fields_has_cols(output_fields_t* info); /* * Output only these protocols @@ -154,7 +155,7 @@ extern void proto_tree_write_carrays(guint32 num, FILE *fh, epan_dissect_t *edt) extern void write_carrays_finale(FILE *fh); extern void write_fields_preamble(output_fields_t* fields, FILE *fh); -extern void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, FILE *fh); +extern void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, column_info *cinfo, FILE *fh); extern void write_fields_finale(output_fields_t* fields, FILE *fh); extern const gchar* get_node_field_value(field_info* fi, epan_dissect_t* edt); @@ -142,7 +142,7 @@ static char *separator = ""; /* * TRUE if we're to print packet counts to keep track of captured packets. */ -static gboolean print_packet_counts; +static gboolean print_packet_counts = TRUE; static capture_options global_capture_opts; @@ -307,7 +307,7 @@ print_usage(gboolean print_ver) fprintf(output, " -x add output of hex and ASCII dump (Packet Bytes)\n"); fprintf(output, " -T pdml|ps|psml|text|fields\n"); fprintf(output, " format of text output (def: text)\n"); - fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port);\n"); + fprintf(output, " -e <field> field to print if -Tfields selected (e.g. tcp.port, col.Info);\n"); fprintf(output, " this option can be repeated to print multiple fields\n"); fprintf(output, " -E<fieldsoption>=<value> set options for output when -Tfields selected:\n"); fprintf(output, " header=y|n switch headers on and off\n"); @@ -3148,8 +3148,10 @@ process_packet(capture_file *cf, gint64 offset, struct wtap_pkthdr *whdr, 1) some tap needs the columns or 2) we're printing packet info but we're *not* verbose; in verbose - mode, we print the protocol tree, not the protocol summary. */ - if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary)) + mode, we print the protocol tree, not the protocol summary. + or + 3) there is a column mapped as an individual field */ + if ((tap_flags & TL_REQUIRES_COLUMNS) || (print_packet_info && print_summary) || output_fields_has_cols(output_fields)) cinfo = &cf->cinfo; else cinfo = NULL; @@ -3503,24 +3505,26 @@ print_packet(capture_file *cf, epan_dissect_t *edt) { print_args_t print_args; - if (print_summary) { + if (print_summary || output_fields_has_cols(output_fields)) { /* Just fill in the columns. */ epan_dissect_fill_in_columns(edt, FALSE, TRUE); - /* Now print them. */ - switch (output_action) { + if (print_summary) { + /* Now print them. */ + switch (output_action) { - case WRITE_TEXT: + case WRITE_TEXT: if (!print_columns(cf)) return FALSE; break; - case WRITE_XML: + case WRITE_XML: proto_tree_write_psml(edt, stdout); return !ferror(stdout); - case WRITE_FIELDS: /*No non-verbose "fields" format */ + case WRITE_FIELDS: /*No non-verbose "fields" format */ g_assert_not_reached(); break; + } } } if (print_details) { @@ -3553,7 +3557,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt) printf("\n"); return !ferror(stdout); case WRITE_FIELDS: - proto_tree_write_fields(output_fields, edt, stdout); + proto_tree_write_fields(output_fields, edt, &cf->cinfo, stdout); printf("\n"); return !ferror(stdout); } |