aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.src1
-rw-r--r--doc/tshark.pod28
-rw-r--r--epan/print.c110
-rw-r--r--tools/json2pcap/json2pcap.py450
-rw-r--r--tshark.c70
5 files changed, 595 insertions, 64 deletions
diff --git a/AUTHORS.src b/AUTHORS.src
index fee90622e0..076fce214d 100644
--- a/AUTHORS.src
+++ b/AUTHORS.src
@@ -3685,6 +3685,7 @@ Barbu Paul - Gheorghe <barbu.paul.gheorghe[AT]gmail.com> {
Martin Kacer <kacer.martin[AT]gmail.com> {
JSON and Elasticsearch tshark output
+ json2pcap
}
Ben Stewart <bst[AT]google.com> {
SCTE-35 dissector
diff --git a/doc/tshark.pod b/doc/tshark.pod
index 4138d9b1f5..8f1b77d158 100644
--- a/doc/tshark.pod
+++ b/doc/tshark.pod
@@ -545,11 +545,18 @@ this option.
=item -j E<lt>protocol match filterE<gt>
-Protocol match filter used for ek|json|pdml output file types.
+Protocol match filter used for ek|json|jsonraw|pdml output file types.
Parent node containing multiple child nodes is only included,
if the name is found in the filter.
-Example: B<-j "http tcp ip">
+Example: B<-j "ip ip.flags text">
+
+=item -J E<lt>protocol match filterE<gt>
+
+Protocol top level filter used for ek|json|jsonraw|pdml output file types.
+Parent node containing multiple child nodes is included with all children.
+
+Example: B<-J "http tcp">
=item -K E<lt>keytabE<gt>
@@ -741,14 +748,14 @@ was captured
The default format is relative.
-=item -T ek|fields|json|pdml|ps|psml|text
+=item -T ek|fields|json|jsonraw|pdml|ps|psml|text
Set the format of the output when viewing decoded packet data. The
options are one of:
B<ek> Newline delimited JSON format for bulk import into Elasticsearch.
-It can be used with B<-j> including the JSON filter or with B<-x> flag
-to include raw packet data.
+It can be used with B<-j> or B<-J> including the JSON filter or with
+B<-x> flag to include raw hex-encoded packet data.
Example of usage to import data into Elasticsearch:
tshark -T ek -j "http tcp ip" -x -r file.pcap > file.json
@@ -762,13 +769,20 @@ form specified by the B<-E> option. For example,
would generate comma-separated values (CSV) output suitable for importing
into your favorite spreadsheet program.
-B<json> JSON file format. It can be used with B<-j> including
-the JSON filter or with B<-x> flag to influde raw packet data.
+B<json> JSON file format. It can be used with B<-j> or B<-J> including
+the JSON filter or with B<-x> flag to include raw hex-encoded packet data.
Example of usage:
tshark -T json -r file.pcap
tshark -T json -j "http tcp ip" -x -r file.pcap
+B<jsonraw> JSON file format including only raw hex-encoded packet data.
+It can be used with B<-j> including or B<-J >the JSON filter flag.
+Example of usage:
+
+ tshark -T jsonraw -r file.pcap
+ tshark -T jsonraw -j "http tcp ip" -x -r file.pcap
+
B<pdml> Packet Details Markup Language, an XML-based format for the details of
a decoded packet. This information is equivalent to the packet details
printed with the B<-V> flag.
diff --git a/epan/print.c b/epan/print.c
index ed5a8d9be2..5ce5e2b18a 100644
--- a/epan/print.c
+++ b/epan/print.c
@@ -60,7 +60,7 @@ typedef struct {
FILE *fh;
GSList *src_list;
gchar **filter;
- pf_flags filter_flags;
+ pf_flags filter_flags;
} write_pdml_data;
typedef struct {
@@ -68,8 +68,9 @@ typedef struct {
FILE *fh;
GSList *src_list;
gchar **filter;
- pf_flags filter_flags;
+ pf_flags filter_flags;
gboolean print_hex;
+ gboolean print_text;
} write_json_data;
typedef struct {
@@ -373,6 +374,10 @@ write_json_proto_tree(output_fields_t* fields, print_args_t *print_args, gchar *
data.filter = protocolfilter;
data.filter_flags = protocolfilter_flags;
data.print_hex = print_args->print_hex;
+ data.print_text = TRUE;
+ if (print_args->print_dissections == print_dissections_none) {
+ data.print_text = FALSE;
+ }
proto_tree_children_foreach(edt->tree, proto_tree_write_node_json,
&data);
@@ -721,10 +726,10 @@ proto_tree_write_node_json(proto_node *node, gpointer data)
/* dissection with an invisible proto tree? */
g_assert(fi);
- print_indent(pdata->level + 3, pdata->fh);
-
/* Text label. It's printed as a field with no name. */
if (fi->hfinfo->id == hf_text_only) {
+ print_indent(pdata->level + 3, pdata->fh);
+
/* Get the text */
if (fi->rep) {
label_ptr = fi->rep->representation;
@@ -754,11 +759,13 @@ proto_tree_write_node_json(proto_node *node, gpointer data)
/*
* Hex dump -x
*/
- if (pdata->print_hex && fi->length > 0) {
+ if (pdata->print_hex && (!pdata->print_text || fi->length > 0)) {
+ print_indent(pdata->level + 3, pdata->fh);
+
fputs("\"", pdata->fh);
print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
fputs("_raw", pdata->fh);
- fputs("\": \"", pdata->fh);
+ fputs("\": [\"", pdata->fh);
if (fi->hfinfo->bitmask!=0) {
switch (fi->value.ftype->ftype) {
@@ -790,28 +797,47 @@ proto_tree_write_node_json(proto_node *node, gpointer data)
default:
g_assert_not_reached();
}
- fputs("\",\n", pdata->fh);
}
else {
json_write_field_hex_value(pdata, fi);
- fputs("\",\n", pdata->fh);
}
- print_indent(pdata->level + 3, pdata->fh);
- }
+ /* Dump raw hex-encoded dissected information including position, length, bitmask, type */
+ fprintf(pdata->fh, "\", %" G_GINT32_MODIFIER "d", fi->start);
+ fprintf(pdata->fh, ", %" G_GINT32_MODIFIER "d", fi->length);
+ fprintf(pdata->fh, ", %" G_GUINT64_FORMAT, fi->hfinfo->bitmask);
+ fprintf(pdata->fh, ", %" G_GINT32_MODIFIER "d", (gint32)fi->value.ftype->ftype);
+ if (pdata->print_text) {
+ fputs("],\n", pdata->fh);
+ } else {
+ if (node->next == NULL && node->first_child == NULL) {
+ fputs("]\n", pdata->fh);
+ } else {
+ fputs("],\n", pdata->fh);
+ }
+ }
- fputs("\"", pdata->fh);
+ }
- print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
/* show, value, and unmaskedvalue attributes */
switch (fi->hfinfo->type)
{
case FT_PROTOCOL:
if (node->first_child != NULL) {
+ print_indent(pdata->level + 3, pdata->fh);
+
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+
fputs("\": {\n", pdata->fh);
- } else {
+ } else if (pdata->print_text) {
+ print_indent(pdata->level + 3, pdata->fh);
+
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+
fputs("\": \"", pdata->fh);
if (fi->rep) {
print_escaped_json(pdata->fh, fi->rep->representation);
@@ -830,8 +856,18 @@ proto_tree_write_node_json(proto_node *node, gpointer data)
break;
case FT_NONE:
if (node->first_child != NULL) {
+ print_indent(pdata->level + 3, pdata->fh);
+
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+
fputs("\": {\n", pdata->fh);
- } else {
+ } else if (pdata->print_text) {
+ print_indent(pdata->level + 3, pdata->fh);
+
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+
if (node->next == NULL) {
fputs("\": \"\"\n", pdata->fh);
} else {
@@ -840,28 +876,40 @@ proto_tree_write_node_json(proto_node *node, gpointer data)
}
break;
default:
- dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
- if (dfilter_string != NULL) {
- fputs("\": \"", pdata->fh);
- print_escaped_json(pdata->fh, dfilter_string);
- if (node->first_child != NULL) {
- fputs("\",\n", pdata->fh);
- print_indent(pdata->level + 3, pdata->fh);
+ if (pdata->print_text) {
+ print_indent(pdata->level + 3, pdata->fh);
- fputs("\"", pdata->fh);
- print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
- fputs("_tree\": {\n", pdata->fh);
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+
+ dfilter_string = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
+ if (dfilter_string != NULL) {
+ if (pdata->print_text) {
+ fputs("\": \"", pdata->fh);
+ print_escaped_json(pdata->fh, dfilter_string);
+ if (node->first_child != NULL) {
+ fputs("\",\n", pdata->fh);
+ }
+ }
}
- }
- wmem_free(NULL, dfilter_string);
+ wmem_free(NULL, dfilter_string);
- if (node->first_child == NULL) {
- if (node->next == NULL) {
- fputs("\"\n", pdata->fh);
- } else {
- fputs("\",\n", pdata->fh);
+ if (node->first_child == NULL) {
+ if (node->next == NULL) {
+ fputs("\"\n", pdata->fh);
+ } else {
+ fputs("\",\n", pdata->fh);
+ }
}
}
+
+ if (node->first_child != NULL) {
+ print_indent(pdata->level + 3, pdata->fh);
+
+ fputs("\"", pdata->fh);
+ print_escaped_json(pdata->fh, fi->hfinfo->abbrev);
+ fputs("_tree\": {\n", pdata->fh);
+ }
}
}
diff --git a/tools/json2pcap/json2pcap.py b/tools/json2pcap/json2pcap.py
new file mode 100644
index 0000000000..50d0ab5236
--- /dev/null
+++ b/tools/json2pcap/json2pcap.py
@@ -0,0 +1,450 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Copyright 2017, Martin Kacer <kacer.martin[AT]gmail.com>
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 1998 Gerald Combs
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+import json
+import operator
+import copy
+import os
+import binascii
+import array
+import argparse
+import subprocess
+from collections import OrderedDict
+
+#
+# ********* PY TEMPLATES *********
+#
+def read_py_function(name):
+ s = ''
+ record = False
+ indent = 0
+
+ file = open(__file__)
+ for line in file:
+
+ ind = len(line) - len(line.lstrip())
+
+ if (line.find("def " + name) != -1):
+ record = True
+ indent = ind
+ elif (record == True and indent == ind and len(line) > 1):
+ record = False
+
+ if (record == True):
+ s = s + line
+
+ file.close()
+ return s
+
+py_header = """#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# File generated by json2pcap.py
+# json2pcap.py created by Martin Kacer, 2017
+
+import os
+import binascii
+import array
+import sys
+import subprocess
+from collections import OrderedDict
+
+# *****************************************************
+# * PACKET PAYLOAD GENERATED FROM INPUT PCAP *
+# * Modify this function to edit the packet *
+# *****************************************************
+def main():
+ d = OrderedDict()
+"""
+
+py_footer = """ generate_pcap(d)
+
+# *****************************************************
+# * FUNCTIONS from TEMPLATE *
+# * Do not edit these functions if not required *
+# *****************************************************
+
+"""
+py_footer = py_footer + read_py_function("to_pcap_file")
+py_footer = py_footer + read_py_function("hex_to_txt")
+py_footer = py_footer + read_py_function("to_bytes")
+py_footer = py_footer + read_py_function("lsb")
+py_footer = py_footer + read_py_function("rewrite_frame")
+
+py_footer = py_footer + """
+def assemble_frame(d):
+ input = d['frame_raw'][1]
+ isFlat = False
+ linux_cooked_header = False;
+ while(isFlat == False):
+ isFlat = True
+ for key, val in d.items():
+ h = str(val[1]) # hex
+ p = val[2] * 2 # position
+ l = val[3] * 2 # length
+ b = val[4] # bitmask
+ t = val[5] # type
+
+ if (key == "sll_raw"):
+ linux_cooked_header = True;
+
+ # only if the node is not parent
+ isParent = False
+ for k, v in d.items():
+ if (v[0] == key):
+ isParent = True
+ isFlat = False
+ break
+
+ if (isParent == False and val[0] is not None):
+ d[val[0]][1] = rewrite_frame(d[val[0]][1], h, p, l, b, t)
+ del d[key]
+
+ output = d['frame_raw'][1]
+
+ # for Linux cooked header replace dest MAC and remove two bytes to reconstruct normal frame using text2pcap
+ if (linux_cooked_header):
+ output = "000000000000" + output[6*2:] # replce dest MAC
+ output = output[:12*2] + "" + output[14*2:] # remove two bytes before Protocol
+
+ return output
+
+def generate_pcap(d):
+ # 1. Assemble frame
+ input = d['frame_raw'][1]
+ output = assemble_frame(d)
+ print(input)
+ print(output)
+
+ # 2. Testing: compare input and output for not modified json
+ if (input != output):
+ print("Modified frames: ")
+ s1 = input
+ s2 = output
+ print(s1)
+ print(s2)
+ if (len(s1) == len(s2)):
+ d = [i for i in xrange(len(s1)) if s1[i] != s2[i]]
+ print(d)
+
+ # 3. Open TMP file used by text2pcap
+ file = sys.argv[0] + '.tmp'
+ f = open(file,'w')
+ hex_to_txt(output, file)
+ f.close()
+
+ # 4. Generate pcap
+ to_pcap_file(sys.argv[0] + '.tmp', sys.argv[0] + '.pcap')
+ print("Generated " + sys.argv[0] + ".tmp")
+ print("Generated " + sys.argv[0] + ".pcap")
+
+if __name__ == '__main__':
+ main()
+"""
+#
+# ***** End of PY TEMPLATES ******
+#
+
+
+
+#
+# ********** FUNCTIONS ***********
+#
+def to_pcap_file(filename, output_pcap_file):
+ subprocess.call(["text2pcap", filename, output_pcap_file])
+
+def hex_to_txt(hexstring, output_file):
+ h = hexstring.lower()
+
+ file = open(output_file, 'a')
+
+ for i in range(0, len(h), 2):
+ if(i % 32 == 0):
+ file.write(format(i / 2, '06x') + ' ')
+
+ file.write(h[i:i + 2] + ' ')
+
+ if(i % 32 == 30):
+ file.write('\n')
+
+ file.write('\n')
+ file.close()
+
+def raw_flat_collector(dict):
+ if hasattr(dict, 'items'):
+ for k, v in dict.items():
+ if k.endswith("_raw"):
+ yield k, v
+ else:
+ for val in raw_flat_collector(v):
+ yield val
+
+
+# d - input dictionary, parsed from json
+# r - result dictionary
+# frame_name - parent protocol name
+# frame_position - parent protocol position
+def py_generator(d, r, frame_name='frame_raw', frame_position=0):
+ if (d is None or d is None):
+ return
+
+ if hasattr(d, 'items'):
+ for k, v in d.items():
+ # no recursion
+ if k.endswith("_raw"):
+ h = v[0]
+ p = v[1]
+ l = v[2] * 2
+ b = v[3]
+ t = v[4]
+ if (len(h) != l):
+ l = len(h)
+
+ p = p - frame_position
+
+ # Add into result dictionary
+ key = str(k).replace('.', '_')
+ fn = frame_name.replace('.', '_')
+ if (fn == key):
+ fn = None
+ value = [fn , h, p, l, b, t]
+ r[key] = value
+
+ # recursion
+ else:
+ if isinstance(v, dict):
+ fn = frame_name
+ fp = frame_position
+
+ # if there is also preceding raw protocol frame use it
+ # remove tree suffix
+ key = k
+ if key.endswith("_tree"):
+ key = key[:-5]
+ raw_key = key + "_raw"
+ if (raw_key in d):
+ # f = d[raw_key][0]
+ fn = raw_key
+ fp = d[raw_key][1]
+
+ py_generator(v, r, fn, fp)
+
+# To emulate Python 3.2
+def to_bytes(n, length, endianess='big'):
+ h = '%x' % n
+ s = ('0' * (len(h) % 2) + h).zfill(length * 2).decode('hex')
+ return s if endianess == 'big' else s[::-1]
+
+# Returns the index, counting from 0, of the least significant set bit in x
+def lsb(x):
+ return (x & -x).bit_length() - 1
+
+# Rewrite frame
+# h - hex bytes
+# p - position
+# l - length
+# b - bitmask
+# t - type
+def rewrite_frame(frame_raw, h, p, l, b, t):
+ # no bitmask
+ if(b == 0):
+ if (len(h) != l):
+ l = len(h)
+ return frame_raw[:p] + h + frame_raw[p + l:]
+ # bitmask
+ else:
+ # get hex string from frame which will be replaced
+ _h = frame_raw[p:p + l]
+
+ # add 0 padding to have correct length
+ if (len(_h) % 2 == 1):
+ _h = '0' + _h
+ if (len(h) % 2 == 1):
+ h = '0' + h
+
+ # Only replace bits defined by mask
+ # new_hex = (old_hex & !mask) | (new_hex & mask)
+ _H = _h.decode("hex")
+ _H = array.array('B', _H)
+
+ M = to_bytes(b, len(_H))
+ M = array.array('B', M)
+ # shift mask aligned to position
+ for i in range(len(M)):
+ if (i + p / 2) < len(M):
+ M[i] = M[i + p / 2]
+ else:
+ M[i] = 0x00
+
+ H = h.decode("hex")
+ H = array.array('B', H)
+
+ # for i in range(len(_H)):
+ # print "{0:08b}".format(_H[i]),
+ # print
+ # for i in range(len(M)):
+ # print "{0:08b}".format(M[i]),
+ # print
+
+ j = 0;
+ for i in range(len(_H)):
+ if (M[i] != 0):
+ v = H[j] << lsb(M[i])
+ # print "Debug: {0:08b}".format(v),
+ _H[i] = (_H[i] & ~M[i]) | (v & M[i])
+ # print "Debug: " + str(_H[i]),
+ j = j + 1;
+
+ # for i in range(len(_H)):
+ # print "{0:08b}".format(_H[i]),
+ # print
+
+ masked_h = binascii.hexlify(_H)
+
+ return frame_raw[:p] + masked_h + frame_raw[p + l:]
+
+#
+# ************ MAIN **************
+#
+parser = argparse.ArgumentParser(description="""
+Utility to generate pcap from json format.
+
+Packet modification:
+In input json it is possible to modify the raw values of decoded fields.
+The output pcap will include the modified values. The algorithm of
+generating the output pcap is to get all raw hex fields from input json and
+then assembling them by layering from longest (less decoded fields) to
+shortest (more decoded fields). It means if the modified raw field is
+shorter field (more decoded field) it takes precedence against modification
+in longer field (less decoded field). If the json includes duplicated raw
+fields with same position and length, the behavior is not deterministic.
+For manual packet editing it is always possible to remove any not required
+raw fields from json, only frame_raw is field mandatory for reconstruction.
+
+Packet modification with -p switch:
+The python script is generated instead of pcap. This python script when
+executed will generate the pcap of 1st packet from input json. The
+generated code includes the decoded fields and the function to assembly the
+packet. This enables to modify the script and programmatically edit or
+encode the packet variables. The assembling algorithm is different, because
+the decoded packet fields are relative and points to parent node with their
+position (compared to input json which has absolute positions).
+
+""", formatter_class=argparse.RawTextHelpFormatter)
+parser.add_argument('infile', nargs='+', help='json generated by tshark -T jsonraw or by tshark -T json -x')
+parser.add_argument('-p', '--python', help='generate python payload instead of pcap (only 1st packet)', default=False, action='store_true')
+args = parser.parse_args()
+
+# read JSON
+infile = args.infile[0]
+
+with open(infile) as data_file:
+ json = json.load(data_file, object_pairs_hook=OrderedDict)
+
+input_frame_raw = ''
+frame_raw = ''
+
+# Generate pcap
+if args.python == False:
+ # open TMP file used by text2pcap
+ file = infile + '.tmp'
+ f = open(file, 'w')
+
+ # Iterate over packets in JSON
+ for packet in json:
+ list = []
+ linux_cooked_header = False;
+
+ # get flat raw fields into list
+ for raw in raw_flat_collector(packet['_source']['layers']):
+ if (raw[0] == "frame_raw"):
+ frame_raw = raw[1][0]
+ input_frame_raw = copy.copy(frame_raw)
+ else:
+ list.append(raw[1])
+ if (raw[0] == "sll_raw"):
+ linux_cooked_header = True
+
+ # sort list
+ sorted_list = sorted(list, key=operator.itemgetter(1), reverse=False)
+ sorted_list = sorted(sorted_list, key=operator.itemgetter(2), reverse=True)
+ # print("Debug: " + str(sorted_list))
+
+ # rewrite frame
+ for raw in sorted_list:
+ h = str(raw[0]) # hex
+ p = raw[1] * 2 # position
+ l = raw[2] * 2 # length
+ b = raw[3] # bitmask
+ t = raw[4] # type
+
+ # print("Debug: " + str(raw))
+ frame_raw = rewrite_frame(frame_raw, h, p, l, b, t)
+
+ # for Linux cooked header replace dest MAC and remove two bytes to reconstruct normal frame using text2pcap
+ if (linux_cooked_header):
+ frame_raw = "000000000000" + frame_raw[6 * 2:] # replce dest MAC
+ frame_raw = frame_raw[:12 * 2] + "" + frame_raw[14 * 2:] # remove two bytes before Protocol
+
+ # Testing: remove comment to compare input and output for not modified json
+ if (input_frame_raw != frame_raw):
+ print("Modified frames: ")
+ s1 = input_frame_raw
+ s2 = frame_raw
+ print(s1)
+ print(s2)
+ if (len(s1) == len(s2)):
+ d = [i for i in xrange(len(s1)) if s1[i] != s2[i]]
+ print(d)
+
+ hex_to_txt(frame_raw, file)
+
+ f.close()
+ to_pcap_file(infile + '.tmp', sys.argv[1] + '.pcap')
+ os.remove(infile + '.tmp')
+
+# Generate python payload only for first packet
+else:
+ file = infile + '.py'
+ f = open(file, 'w')
+
+ for packet in json:
+ f.write(py_header)
+
+ r = OrderedDict({})
+ py_generator(packet['_source']['layers'], r)
+
+ for key, value in r.iteritems() :
+ f.write(" d['" + key + "'] =",)
+ f.write(" " + str(value) + "\n")
+
+ f.write(py_footer)
+
+ # Currently only first packet is used from pcap
+ f.close
+
+ print("Generated " + infile + '.py')
+
+ break
diff --git a/tshark.c b/tshark.c
index fecc9a97b7..678523f6f8 100644
--- a/tshark.c
+++ b/tshark.c
@@ -169,7 +169,8 @@ typedef enum {
WRITE_TEXT, /* summary or detail text */
WRITE_XML, /* PDML or PSML */
WRITE_FIELDS, /* User defined list of fields */
- WRITE_JSON, /* JSON */
+ WRITE_JSON, /* JSON */
+ WRITE_JSON_RAW, /* JSON only raw hex */
WRITE_EK /* JSON bulk insert to Elasticsearch */
/* Add CSV and the like here */
} output_action_e;
@@ -386,7 +387,7 @@ print_usage(FILE *output)
fprintf(output, " -P print packet summary even when writing to a file\n");
fprintf(output, " -S <separator> the line separator to print between packets\n");
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, " -T pdml|ps|psml|json|jsonraw|ek|text|fields\n");
fprintf(output, " format of text output (def: text)\n");
fprintf(output, " -j <protocolfilter> protocols layers filter if -T ek|pdml|json selected\n");
fprintf(output, " (e.g. \"ip ip.flags text\", filter does not expand child\n");
@@ -1320,31 +1321,38 @@ main(int argc, char *argv[])
output_action = WRITE_EK;
print_details = TRUE; /* Need details */
print_summary = FALSE; /* Don't allow summary */
+ } else if (strcmp(optarg, "jsonraw") == 0) {
+ output_action = WRITE_JSON_RAW;
+ print_details = TRUE; /* Need details */
+ print_summary = FALSE; /* Don't allow summary */
}
else {
cmdarg_err("Invalid -T parameter \"%s\"; it must be one of:", optarg); /* x */
- cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
- "\t specified by the -E option.\n"
- "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
- "\t details of a decoded packet. This information is equivalent to\n"
- "\t the packet details printed with the -V flag.\n"
- "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
- "\t the packets, or a multi-line view of the details of each of\n"
- "\t the packets, depending on whether the -V flag was specified.\n"
- "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
- "\t summary information of a decoded packet. This information is\n"
- "\t equivalent to the information shown in the one-line summary\n"
- "\t printed by default.\n"
- "\t\"json\" Packet Summary, an JSON-based format for the details\n"
- "\t summary information of a decoded packet. This information is \n"
- "\t equivalent to the packet details printed with the -V flag.\n"
- "\t\"ek\" Packet Summary, an EK JSON-based format for the bulk insert \n"
- "\t into elastic search cluster. This information is \n"
- "\t equivalent to the packet details printed with the -V flag.\n"
- "\t\"text\" Text of a human-readable one-line summary of each of the\n"
- "\t packets, or a multi-line view of the details of each of the\n"
- "\t packets, depending on whether the -V flag was specified.\n"
- "\t This is the default.");
+ cmdarg_err_cont("\t\"fields\" The values of fields specified with the -e option, in a form\n"
+ "\t specified by the -E option.\n"
+ "\t\"pdml\" Packet Details Markup Language, an XML-based format for the\n"
+ "\t details of a decoded packet. This information is equivalent to\n"
+ "\t the packet details printed with the -V flag.\n"
+ "\t\"ps\" PostScript for a human-readable one-line summary of each of\n"
+ "\t the packets, or a multi-line view of the details of each of\n"
+ "\t the packets, depending on whether the -V flag was specified.\n"
+ "\t\"psml\" Packet Summary Markup Language, an XML-based format for the\n"
+ "\t summary information of a decoded packet. This information is\n"
+ "\t equivalent to the information shown in the one-line summary\n"
+ "\t printed by default.\n"
+ "\t\"json\" Packet Summary, an JSON-based format for the details\n"
+ "\t summary information of a decoded packet. This information is \n"
+ "\t equivalent to the packet details printed with the -V flag.\n"
+ "\t\"jsonraw\" Packet Details, a JSON-based format for machine parsing\n"
+ "\t including only raw hex decoded fields (same as -T json -x but\n"
+ "\t without text decoding, only raw fields included). \n"
+ "\t\"ek\" Packet Details, an EK JSON-based format for the bulk insert \n"
+ "\t into elastic search cluster. This information is \n"
+ "\t equivalent to the packet details printed with the -V flag.\n"
+ "\t\"text\" Text of a human-readable one-line summary of each of the\n"
+ "\t packets, or a multi-line view of the details of each of the\n"
+ "\t packets, depending on whether the -V flag was specified.\n"
+ "\t This is the default.");
exit_status = INVALID_OPTION;
goto clean_exit;
}
@@ -1553,8 +1561,8 @@ main(int argc, char *argv[])
}
if (print_hex) {
- if (output_action != WRITE_TEXT && output_action != WRITE_JSON && output_action != WRITE_EK) {
- cmdarg_err("Raw packet hex data can only be printed as text, PostScript, JSON or EK JSON");
+ if (output_action != WRITE_TEXT && output_action != WRITE_JSON && output_action != WRITE_JSON_RAW && output_action != WRITE_EK) {
+ cmdarg_err("Raw packet hex data can only be printed as text, PostScript, JSON, JSONRAW or EK JSON");
exit_status = INVALID_OPTION;
goto clean_exit;
}
@@ -3678,6 +3686,7 @@ write_preamble(capture_file *cf)
return !ferror(stdout);
case WRITE_JSON:
+ case WRITE_JSON_RAW:
write_json_preamble(stdout);
return !ferror(stdout);
@@ -3989,6 +3998,7 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
case WRITE_FIELDS: /*No non-verbose "fields" format */
case WRITE_JSON:
case WRITE_EK:
+ case WRITE_JSON_RAW:
g_assert_not_reached();
break;
}
@@ -4028,10 +4038,17 @@ print_packet(capture_file *cf, epan_dissect_t *edt)
printf("\n");
return !ferror(stdout);
case WRITE_JSON:
+ print_args.print_dissections = print_dissections_expanded;
print_args.print_hex = print_hex;
write_json_proto_tree(output_fields, &print_args, protocolfilter, protocolfilter_flags, edt, stdout);
printf("\n");
return !ferror(stdout);
+ case WRITE_JSON_RAW:
+ print_args.print_dissections = print_dissections_none;
+ print_args.print_hex = TRUE;
+ 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, protocolfilter_flags, edt, stdout);
@@ -4071,6 +4088,7 @@ write_finale(void)
return !ferror(stdout);
case WRITE_JSON:
+ case WRITE_JSON_RAW:
write_json_finale(stdout);
return !ferror(stdout);