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:
parent
348e364551
commit
ceae9e4d1f
|
@ -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."
|
||||
|
||||
|
|
233
epan/print.c
233
epan/print.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
epan/print.h
13
epan/print.h
|
@ -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
4
file.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
10
tshark.c
10
tshark.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue