tshark fields filter added for other outputs

-e fields filter addded to ek|json|pdml output.

Bug: 12529
Change-Id: I1f0f8772eefceb5b71927925ce0c34af483571b9
Reviewed-on: https://code.wireshark.org/review/16193
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Martin Kacer 2016-06-28 13:01:25 +02:00 committed by Guy Harris
parent 348e364551
commit ceae9e4d1f
6 changed files with 203 additions and 63 deletions

View File

@ -291,8 +291,8 @@ from such an account, it will not list any interfaces.
=item -e E<lt>fieldE<gt>
Add a field to the list of fields to display if B<-T fields> is
selected. This option can be used multiple times on the command line.
Add a field to the list of fields to display if B<-T ek|fields|json|pdml>
is selected. This option can be used multiple times on the command line.
At least one field must be provided if the B<-T fields> option is
selected. Column names may be used prefixed with "_ws.col."

View File

@ -78,16 +78,17 @@ typedef struct {
} write_field_data_t;
struct _output_fields {
gboolean print_bom;
gboolean print_header;
gchar separator;
gchar occurrence;
gchar aggregator;
GPtrArray *fields;
GHashTable *field_indicies;
GPtrArray **field_values;
gchar quote;
gboolean includes_col_fields;
gboolean print_bom;
gboolean print_header;
gchar separator;
gchar occurrence;
gchar aggregator;
GPtrArray *fields;
GHashTable *field_indicies;
GPtrArray **field_values;
gchar quote;
gboolean includes_col_fields;
fields_format format;
};
static gchar *get_field_hex_value(GSList *src_list, field_info *fi);
@ -285,10 +286,13 @@ static gboolean check_protocolfilter(gchar **protocolfilter, const char *str)
}
void
write_pdml_proto_tree(gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
write_pdml_proto_tree(output_fields_t* fields, gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
{
write_pdml_data data;
g_assert(edt);
g_assert(fh);
/* Create the output */
data.level = 0;
data.fh = fh;
@ -301,14 +305,19 @@ write_pdml_proto_tree(gchar **protocolfilter, epan_dissect_t *edt, FILE *fh)
/* Print a "geninfo" protocol as required by PDML */
print_pdml_geninfo(edt->tree, fh);
proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
&data);
if (fields == NULL || fields->fields == NULL) {
proto_tree_children_foreach(edt->tree, proto_tree_write_node_pdml,
&data);
} else {
fields->format = FORMAT_XML;
write_fields_proto_tree(fields, edt, NULL, fh);
}
fprintf(fh, "</packet>\n\n");
}
void
write_json_proto_tree(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, epan_dissect_t *edt, FILE *fh)
{
write_json_data data;
char ts[30];
@ -316,6 +325,9 @@ write_json_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_dis
struct tm * timeinfo;
static gboolean is_first = TRUE;
g_assert(edt);
g_assert(fh);
/* Create the output */
data.level = 1;
data.fh = fh;
@ -339,8 +351,13 @@ write_json_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_dis
fputs(" \"_source\": {\n", fh);
fputs(" \"layers\": {\n", fh);
proto_tree_children_foreach(edt->tree, proto_tree_write_node_json,
&data);
if (fields == NULL || fields->fields == NULL) {
proto_tree_children_foreach(edt->tree, proto_tree_write_node_json,
&data);
} else {
fields->format = FORMAT_JSON;
write_fields_proto_tree(fields, edt, NULL, fh);
}
fputs(" }\n", fh);
fputs(" }\n", fh);
@ -349,7 +366,7 @@ write_json_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_dis
}
void
write_ek_proto_tree(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, epan_dissect_t *edt, FILE *fh)
{
write_json_data data;
char ts[30];
@ -358,6 +375,9 @@ write_ek_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_disse
nstime_t *timestamp;
GPtrArray *finfo_array;
g_assert(edt);
g_assert(fh);
/* Create the output */
data.level = 0;
data.fh = fh;
@ -366,7 +386,6 @@ write_ek_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_disse
data.filter = protocolfilter;
data.print_hex = print_args->print_hex;
timeinfo = localtime(&t);
strftime(ts, 30, "%Y-%m-%d", timeinfo);
@ -390,8 +409,14 @@ write_ek_proto_tree(print_args_t *print_args, gchar **protocolfilter, epan_disse
fprintf(fh, "{\"timestamp\" : \"%" G_GUINT64_FORMAT "%03d\", \"layers\" : {", (guint64)timestamp->secs, timestamp->nsecs/1000000);
proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek,
&data);
if (fields == NULL || fields->fields == NULL) {
proto_tree_children_foreach(edt->tree, proto_tree_write_node_ek,
&data);
} else {
fields->format = FORMAT_EK;
write_fields_proto_tree(fields, edt, NULL, fh);
}
fputs("}}\n", fh);
}
@ -2048,44 +2073,152 @@ void write_fields_proto_tree(output_fields_t *fields, epan_dissect_t *edt, colum
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 = g_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->columns[col].col_title);
field_index = g_hash_table_lookup(fields->field_indicies, col_name);
g_free(col_name);
switch (fields->format) {
case FORMAT_CSV:
if (fields->includes_col_fields) {
for (col = 0; col < cinfo->num_cols; col++) {
/* Prepend COLUMN_FIELD_FILTER as the field name */
col_name = g_strdup_printf("%s%s", COLUMN_FIELD_FILTER, cinfo->columns[col].col_title);
field_index = g_hash_table_lookup(fields->field_indicies, col_name);
g_free(col_name);
if (NULL != field_index) {
format_field_values(fields, field_index, g_strdup(cinfo->columns[col].col_data));
if (NULL != field_index) {
format_field_values(fields, field_index, g_strdup(cinfo->columns[col].col_data));
}
}
}
}
for(i = 0; i < fields->fields->len; ++i) {
if (0 != i) {
fputc(fields->separator, fh);
}
if (NULL != fields->field_values[i]) {
GPtrArray *fv_p;
gchar * str;
gsize j;
fv_p = fields->field_values[i];
if (fields->quote != '\0') {
fputc(fields->quote, fh);
for(i = 0; i < fields->fields->len; ++i) {
if (0 != i) {
fputc(fields->separator, fh);
}
if (NULL != fields->field_values[i]) {
GPtrArray *fv_p;
gchar * str;
gsize j;
fv_p = fields->field_values[i];
if (fields->quote != '\0') {
fputc(fields->quote, fh);
}
/* Output the array of (partial) field values */
for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
str = (gchar *)g_ptr_array_index(fv_p, j);
fputs(str, fh);
g_free(str);
/* Output the array of (partial) field values */
for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
str = (gchar *)g_ptr_array_index(fv_p, j);
fputs(str, fh);
g_free(str);
}
if (fields->quote != '\0') {
fputc(fields->quote, fh);
}
g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
fields->field_values[i] = NULL;
}
if (fields->quote != '\0') {
fputc(fields->quote, fh);
}
g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
fields->field_values[i] = NULL;
}
break;
case FORMAT_XML:
for(i = 0; i < fields->fields->len; ++i) {
gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
if (NULL != fields->field_values[i]) {
GPtrArray *fv_p;
gchar * str;
gsize j;
fv_p = fields->field_values[i];
/* Output the array of (partial) field values */
for (j = 0; j < (g_ptr_array_len(fv_p)) - 1; j+=2 ) {
str = (gchar *)g_ptr_array_index(fv_p, j);
fprintf(fh, " <field name=\"%s\" value=", field);
fputs("\"", fh);
print_escaped_xml(fh, str);
fputs("\"/>\n", fh);
g_free(str);
}
g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
fields->field_values[i] = NULL;
}
}
break;
case FORMAT_JSON:
for(i = 0; i < fields->fields->len; ++i) {
gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
if (NULL != fields->field_values[i]) {
GPtrArray *fv_p;
gchar * str;
gsize j;
fv_p = fields->field_values[i];
/* Output the array of (partial) field values */
for (j = 0; j < (g_ptr_array_len(fv_p)) - 1; j+=2 ) {
str = (gchar *)g_ptr_array_index(fv_p, j);
if (j == 0) {
fprintf(fh, " \"%s\": [", field);
}
fputs("\"", fh);
print_escaped_json(fh, str);
fputs("\"", fh);
g_free(str);
if (j + 2 < (g_ptr_array_len(fv_p)) - 1) {
fputs(",", fh);
} else {
fputs("]", fh);
if ( (i + 1 < fields->fields->len) && (g_ptr_array_len(fields->field_values[i + 1]) > 1) ) {
fputs(",\n", fh);
} else {
fputs("\n", fh);
}
}
}
g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
fields->field_values[i] = NULL;
}
}
break;
case FORMAT_EK:
for(i = 0; i < fields->fields->len; ++i) {
gchar *field = (gchar *)g_ptr_array_index(fields->fields, i);
if (NULL != fields->field_values[i]) {
GPtrArray *fv_p;
gchar * str;
gsize j;
fv_p = fields->field_values[i];
/* Output the array of (partial) field values */
for (j = 0; j < (g_ptr_array_len(fv_p)) - 1; j+=2 ) {
str = (gchar *)g_ptr_array_index(fv_p, j);
if (j == 0) {
fputs("\"", fh);
print_escaped_ek(fh, field);
fputs("\": [", fh);
}
fputs("\"", fh);
print_escaped_json(fh, str);
fputs("\"", fh);
g_free(str);
if (j + 2 < (g_ptr_array_len(fv_p)) - 1) {
fputs(",", fh);
} else {
fputs("]", fh);
if ( (i + 1 < fields->fields->len) && (g_ptr_array_len(fields->field_values[i + 1]) > 1) ) {
fputs(",", fh);
} else {
}
}
}
g_ptr_array_free(fv_p, TRUE); /* get ready for the next packet */
fields->field_values[i] = NULL;
}
}
break;
}
}

View File

@ -79,6 +79,13 @@ typedef struct {
* each new packet */
} print_args_t;
typedef enum {
FORMAT_CSV, /* CSV */
FORMAT_JSON, /* JSON */
FORMAT_EK, /* JSON bulk insert to Elasticsearch */
FORMAT_XML, /* PDML output */
} fields_format;
/*
* Print user selected list of fields
*/
@ -105,14 +112,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(gchar **protocolfilter, epan_dissect_t *edt, FILE *fh);
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_finale(FILE *fh);
WS_DLL_PUBLIC void write_json_preamble(FILE *fh);
WS_DLL_PUBLIC void write_json_proto_tree(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, epan_dissect_t *edt, FILE *fh);
WS_DLL_PUBLIC void write_json_finale(FILE *fh);
WS_DLL_PUBLIC void write_ek_proto_tree(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, 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);

4
file.c
View File

@ -2544,7 +2544,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, &args->edt, args->fh);
write_pdml_proto_tree(NULL, NULL, &args->edt, args->fh);
epan_dissect_reset(&args->edt);
@ -2838,7 +2838,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(args->print_args, NULL, &args->edt, args->fh);
write_json_proto_tree(NULL, args->print_args, NULL, &args->edt, args->fh);
epan_dissect_reset(&args->edt);

View File

@ -2072,7 +2072,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
break;
case WRITE_XML:
write_pdml_proto_tree(NULL, edt, stdout);
write_pdml_proto_tree(NULL, NULL, edt, stdout);
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:

View File

@ -1365,9 +1365,9 @@ main(int argc, char *argv[])
}
/* If we specified output fields, but not the output field type... */
if (WRITE_FIELDS != output_action && 0 != output_fields_num_fields(output_fields)) {
if ((WRITE_FIELDS != output_action && WRITE_XML != output_action && WRITE_JSON != output_action && WRITE_EK != output_action) && 0 != output_fields_num_fields(output_fields)) {
cmdarg_err("Output fields were specified with \"-e\", "
"but \"-Tfields\" was not specified.");
"but \"-Tek, -Tfields, -Tjson or -Tpdml\" was not specified.");
return 1;
} else if (WRITE_FIELDS == output_action && 0 == output_fields_num_fields(output_fields)) {
cmdarg_err("\"-Tfields\" was specified, but no fields were "
@ -3834,7 +3834,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
break;
case WRITE_XML:
write_pdml_proto_tree(protocolfilter, edt, stdout);
write_pdml_proto_tree(output_fields, protocolfilter, edt, stdout);
printf("\n");
return !ferror(stdout);
case WRITE_FIELDS:
@ -3843,12 +3843,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(&print_args, protocolfilter, edt, stdout);
write_json_proto_tree(output_fields, &print_args, protocolfilter, edt, stdout);
printf("\n");
return !ferror(stdout);
case WRITE_EK:
print_args.print_hex = print_hex;
write_ek_proto_tree(&print_args, protocolfilter, edt, stdout);
write_ek_proto_tree(output_fields, &print_args, protocolfilter, edt, stdout);
printf("\n");
return !ferror(stdout);
}