aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-json.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-json.c')
-rw-r--r--epan/dissectors/packet-json.c868
1 files changed, 484 insertions, 384 deletions
diff --git a/epan/dissectors/packet-json.c b/epan/dissectors/packet-json.c
index cc9670889e..4c2ed41fe5 100644
--- a/epan/dissectors/packet-json.c
+++ b/epan/dissectors/packet-json.c
@@ -12,9 +12,6 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-
-#define NEW_PROTO_TREE_API
-
#include "config.h"
#include <epan/packet.h>
@@ -27,135 +24,82 @@
#include <wiretap/wtap.h>
-#include "packet-http.h"
+#include "packet-media-type.h"
#include "packet-acdr.h"
-#include "packet-gtpv2.h"
+#include "packet-json.h"
void proto_register_json(void);
void proto_reg_handoff_json(void);
-static char* json_string_unescape(tvbparse_elem_t *tok, gboolean enclose_in_quotation_marks);
-
+static char* json_string_unescape(wmem_allocator_t *scope, const char *string, size_t *length_ptr);
+static const char* get_json_string(wmem_allocator_t *scope, tvbparse_elem_t *tok, gboolean remove_quotes);
static dissector_handle_t json_handle;
+static dissector_handle_t json_file_handle;
-static int proto_json = -1;
-static int proto_json_3gpp = -1;
+static int proto_json;
//Used to get AC DR proto data
-static int proto_acdr = -1;
-
-static gint ett_json = -1;
-static gint ett_json_array = -1;
-static gint ett_json_object = -1;
-static gint ett_json_member = -1;
+static int proto_acdr;
+
+static int hf_json_array;
+static int hf_json_array_compact;
+static int hf_json_array_item_compact;
+static int hf_json_array_raw;
+static int hf_json_array_item_raw;
+static int hf_json_binary_data;
+static int hf_json_ignored_leading_bytes;
+static int hf_json_key;
+static int hf_json_member;
+static int hf_json_member_compact;
+static int hf_json_member_raw;
+static int hf_json_member_with_value;
+static int hf_json_object;
+static int hf_json_object_compact;
+static int hf_json_object_raw;
+static int hf_json_path;
+static int hf_json_path_with_value;
+static int hf_json_value_false;
+static int hf_json_value_nan;
+static int hf_json_value_null;
+static int hf_json_value_number;
+static int hf_json_value_string;
+static int hf_json_value_true;
+
+static gint ett_json;
+static gint ett_json_array;
+static gint ett_json_object;
+static gint ett_json_member;
/* Define the trees for json compact form */
-static gint ett_json_compact = -1;
-static gint ett_json_array_compact = -1;
-static gint ett_json_object_compact = -1;
-static gint ett_json_member_compact = -1;
-static gint ett_json_base64decoded_eps_ie = -1;
-
-static header_field_info *hfi_json = NULL;
-
-#define JSON_HFI_INIT HFI_INIT(proto_json)
-
-static header_field_info hfi_json_array JSON_HFI_INIT =
- { "Array", "json.array", FT_NONE, BASE_NONE, NULL, 0x00, "JSON array", HFILL };
-
-static header_field_info hfi_json_object JSON_HFI_INIT =
- { "Object", "json.object", FT_NONE, BASE_NONE, NULL, 0x00, "JSON object", HFILL };
-
-static header_field_info hfi_json_member JSON_HFI_INIT =
- { "Member", "json.member", FT_STRING, STR_UNICODE, NULL, 0x00, "JSON object member", HFILL };
-
-static header_field_info hfi_json_key JSON_HFI_INIT =
- { "Key", "json.key", FT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL };
-
-static header_field_info hfi_json_path JSON_HFI_INIT =
- { "Path", "json.path", FT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL };
-
-static header_field_info hfi_json_path_with_value JSON_HFI_INIT =
- { "Path with value", "json.path_with_value", FT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL };
-
-static header_field_info hfi_json_member_with_value JSON_HFI_INIT =
- { "Member with value", "json.member_with_value", FT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL };
+static gint ett_json_compact;
+static gint ett_json_array_compact;
+static gint ett_json_object_compact;
+static gint ett_json_member_compact;
+/* Define the trees for json raw form */
+static gint ett_json_raw;
+static gint ett_json_array_raw;
+static gint ett_json_object_raw;
+static gint ett_json_member_raw;
-static header_field_info hfi_json_value_string JSON_HFI_INIT = /* FT_STRINGZ? */
- { "String value", "json.value.string", FT_STRING, STR_UNICODE, NULL, 0x00, "JSON string value", HFILL };
-
-static header_field_info hfi_json_value_number JSON_HFI_INIT = /* FT_DOUBLE/ FT_INT64? */
- { "Number value", "json.value.number", FT_STRING, BASE_NONE, NULL, 0x00, "JSON number value", HFILL };
-
-static header_field_info hfi_json_value_false JSON_HFI_INIT =
- { "False value", "json.value.false", FT_NONE, BASE_NONE, NULL, 0x00, "JSON false value", HFILL };
-
-static header_field_info hfi_json_value_null JSON_HFI_INIT =
- { "Null value", "json.value.null", FT_NONE, BASE_NONE, NULL, 0x00, "JSON null value", HFILL };
-
-static header_field_info hfi_json_value_true JSON_HFI_INIT =
- { "True value", "json.value.true", FT_NONE, BASE_NONE, NULL, 0x00, "JSON true value", HFILL };
-
-static header_field_info hfi_json_value_nan JSON_HFI_INIT =
- { "NaN value", "json.value.nan", FT_NONE, BASE_NONE, NULL, 0x00, "JSON NaN value", HFILL };
-
-/* HFIs below are used only for compact form display */
-static header_field_info hfi_json_array_compact JSON_HFI_INIT =
- { "Array compact", "json.array_compact", FT_NONE, BASE_NONE, NULL, 0x00, "JSON array compact", HFILL };
-
-static header_field_info hfi_json_object_compact JSON_HFI_INIT =
- { "Object compact", "json.object_compact", FT_NONE, BASE_NONE, NULL, 0x00, "JSON object compact", HFILL };
-
-static header_field_info hfi_json_member_compact JSON_HFI_INIT =
- { "Member compact", "json.member_compact", FT_NONE, BASE_NONE, NULL, 0x00, "JSON member compact", HFILL };
-
-static header_field_info hfi_json_array_item_compact JSON_HFI_INIT =
- { "Array item compact", "json.array_item_compact", FT_NONE, BASE_NONE, NULL, 0x00, "JSON array item compact", HFILL };
-
-static header_field_info hfi_json_binary_data JSON_HFI_INIT =
- { "Binary data", "json.binary_data", FT_BYTES, BASE_NONE, NULL, 0x00, "JSON binary data", HFILL };
-
-static header_field_info hfi_json_ignored_leading_bytes JSON_HFI_INIT =
- { "Ignored leading bytes", "json.ignored_leading_bytes", FT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL };
+/* Preferences */
+static gboolean json_compact = FALSE;
-static int hf_json_3gpp_ueepspdnconnection = -1;
-static int hf_json_3gpp_bearerlevelqos = -1;
-static int hf_json_3gpp_epsbearersetup = -1;
-static int hf_json_3gpp_forwardingbearercontexts = -1;
-static int hf_json_3gpp_forwardingfteid = -1;
-static int hf_json_3gpp_pgwnodename = -1;
-static int hf_json_3gpp_pgws8cfteid = -1;
-static int hf_json_3gpp_pgws8ufteid = -1;
+static gboolean json_raw = FALSE;
-/* json data decoding function XXXX only works for the compact form.
- * Callback function to further dissect json data
- * The first implementation is a 3GPP json element which carry an Base64 encoded GTPv2 IE
- * https://www.etsi.org/deliver/etsi_ts/129500_129599/129502/15.01.00_60/ts_129502v150100p.pdf
- */
-typedef void(*json_data_decoder_func)(tvbuff_t* tvb, proto_tree* tree, packet_info* pinfo, int offset, int len);
-
-/* Array of functions to dissect IEs
-*/
-typedef struct _json_ie {
- void(*json_data_decoder_func)(tvbuff_t* tvb, proto_tree* tree, packet_info* pinfo, int offset, int len);
-} json_ie_t;
-
-/* A struct to hold the hf and callback function stored in a hastable with the json key as key.
- * If the callback is null NULL the filter will be used useful to create filterable items in json.
- * XXX Todo: Implement hte UAT from the http dissector to enable the users to create filters? and/or
- * read config from file, similar to Diameter(filter only)?
+/* Determine whether to hide the tree of original form or root item of compact or raw form
+ * based on the enabled status of compact_form and raw_form preferences.
+ * If the preference auto_hide is TRUE and compact_form or raw_form is TRUE, hide the tree of
+ * original form. If the preference auto_hide is TRUE and only one of preference of
+ * compact_form or raw_form is TRUE, then hide the root item of compact or raw form and put
+ * the content of compact or raw form under the tree item of JSON protocol directly.
*/
-typedef struct {
- int *hf_id;
- json_data_decoder_func json_data_decoder;
-} json_data_decoder_t;
-
-/* Preferences */
-static gboolean json_compact = FALSE;
+static gboolean auto_hide = FALSE;
static gboolean ignore_leading_bytes = FALSE;
static gboolean hide_extended_path_based_filtering = FALSE;
+static gboolean unescape_strings = FALSE;
+
static tvbparse_wanted_t* want;
static tvbparse_wanted_t* want_ignore;
@@ -176,6 +120,16 @@ typedef enum {
} json_token_type_t;
+typedef enum {
+ JSON_MARK_TYPE_NONE = 0,
+ JSON_MARK_TYPE_BEGIN_OBJECT,
+ JSON_MARK_TYPE_END_OBJECT,
+ JSON_MARK_TYPE_BEGIN_ARRAY,
+ JSON_MARK_TYPE_END_ARRAY,
+ JSON_MARK_TYPE_MEMBER_NAME,
+ JSON_MARK_TYPE_VALUE
+} json_mark_type_t;
+
typedef struct {
wmem_stack_t *stack;
wmem_stack_t *stack_compact; /* Used for compact json form only */
@@ -185,6 +139,9 @@ typedef struct {
Array -1: no key, -2: has key */
wmem_stack_t* stack_path;
packet_info* pinfo;
+ wmem_stack_t* stack_raw; /* Used for raw json form only */
+ json_mark_type_t prev_item_type_raw; /* Used for raw json form only */
+ proto_item* prev_item_raw; /* Used for raw json form only */
} json_parser_data_t;
#define JSON_COMPACT_TOP_ITEM -3
@@ -198,6 +155,9 @@ typedef struct {
#define JSON_INSIDE_ARRAY(idx) (idx >= JSON_COMPACT_ARRAY)
#define JSON_OBJECT_SET_HAS_KEY(idx) (idx == JSON_COMPACT_OBJECT_WITH_KEY)
+#define json_hide_original_tree() (auto_hide && (json_compact || json_raw))
+#define json_hide_root_item() (auto_hide && ((json_compact && !json_raw) || (!json_compact && json_raw)))
+
static void
json_array_index_increment(json_parser_data_t *data)
{
@@ -214,31 +174,22 @@ json_object_add_key(json_parser_data_t *data)
}
static char*
-json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
+json_string_unescape(wmem_allocator_t *scope, const char *string, size_t *length_ptr)
{
- int read_index = 0;
+ size_t read_index = 0;
+ size_t string_length = strlen(string);
- wmem_strbuf_t* output_string_buffer = wmem_strbuf_sized_new(wmem_packet_scope(), tok->len, tok->len + 2);
-
- if (enclose_in_quotation_marks == TRUE)
- {
- wmem_strbuf_append_c(output_string_buffer, '\"');
- }
+ wmem_strbuf_t* output_string_buffer = wmem_strbuf_new_sized(scope, string_length);
while (true)
{
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
break;
}
- guint8 current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ guint8 current_character = string[read_index];
// character that IS NOT escaped
if (current_character != '\\')
@@ -254,20 +205,13 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
for (int i = 0; i < utf8_character_length; i++)
{
- // If it is a character of length 1 these checks are redundant.
- // But it avoids a seperate code path since this loop works for lengths from 1 to 6
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len ))
+ if (!(read_index < string_length))
{
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
read_index++;
wmem_strbuf_append_c(output_string_buffer, current_character);
}
@@ -277,18 +221,13 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
{
read_index++;
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
if (current_character == '\"' || current_character == '\\' || current_character == '/')
{
@@ -329,20 +268,14 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
for (int i = 0; i < 4; i++)
{
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- is_valid_unicode_character = FALSE;
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
is_valid_unicode_character = FALSE;
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
read_index++;
int nibble = ws_xton(current_character);
@@ -359,34 +292,24 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
if ((IS_LEAD_SURROGATE(code_point)))
{
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
if (current_character == '\\')
{
read_index++;
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
if (current_character == 'u') {
guint16 lead_surrogate = code_point;
guint16 trail_surrogate = 0;
@@ -395,20 +318,14 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
for (int i = 0; i < 4; i++)
{
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- is_valid_unicode_character = FALSE;
- break;
- }
// Do not overflow input string
- if (!(read_index < tok->len))
+ if (!(read_index < string_length))
{
is_valid_unicode_character = FALSE;
break;
}
- current_character = tvb_get_guint8(tok->tvb, tok->offset + read_index);
+ current_character = string[read_index];
read_index++;
int nibble = ws_xton(current_character);
@@ -458,17 +375,6 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
for (int i = 0; i < utf8_character_length; i++)
{
- // Do not overflow TVB
- if (!tvb_offset_exists(tok->tvb, tok->offset + read_index))
- {
- break;
- }
- // Do not overflow input string
- if (!(read_index < tok->len))
- {
- break;
- }
-
current_character = length_test_buffer[i];
wmem_strbuf_append_c(output_string_buffer, current_character);
@@ -477,7 +383,7 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
}
else
{
- wmem_strbuf_append_unichar(output_string_buffer, 0xFFFD);
+ wmem_strbuf_append_unichar_repl(output_string_buffer);
}
}
else
@@ -488,45 +394,67 @@ json_string_unescape(tvbparse_elem_t* tok, gboolean enclose_in_quotation_marks)
}
}
- if (enclose_in_quotation_marks == TRUE)
- {
- wmem_strbuf_append_c(output_string_buffer, '\"');
+ if (length_ptr)
+ *length_ptr = wmem_strbuf_get_len(output_string_buffer);
+
+ return wmem_strbuf_finalize(output_string_buffer);
+}
+
+/* This functions allocates memory with packet_scope but the returned pointer
+ * cannot be freed. */
+static const char*
+get_json_string(wmem_allocator_t *scope, tvbparse_elem_t *tok, gboolean remove_quotes)
+{
+ char *string;
+ size_t length;
+
+ string = tvb_get_string_enc(scope, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
+
+ if (unescape_strings) {
+ string = json_string_unescape(scope, string, &length);
+ }
+ else {
+ length = strlen(string);
}
- char* output_string = wmem_strbuf_finalize(output_string_buffer);
+ if (remove_quotes) {
+ if (string[length - 1] == '"') {
+ string[length - 1] = '\0';
+ }
+ if (string[0] == '"') {
+ string += 1;
+ }
+ }
- return output_string;
+ return string;
}
-static GHashTable* header_fields_hash = NULL;
+GHashTable* json_header_fields_hash;
static proto_item*
-json_key_lookup(proto_tree* tree, tvbparse_elem_t* tok, char* key_str, packet_info* pinfo, gboolean use_compact)
+json_key_lookup(proto_tree* tree, tvbparse_elem_t* tok, const char* key_str, packet_info* pinfo, gboolean use_compact)
{
proto_item* ti;
int hf_id = -1;
- header_field_info* hfi;
- json_data_decoder_t* json_data_decoder_rec = (json_data_decoder_t*)g_hash_table_lookup(header_fields_hash, key_str);
+ json_data_decoder_t* json_data_decoder_rec = (json_data_decoder_t*)g_hash_table_lookup(json_header_fields_hash, key_str);
if (json_data_decoder_rec == NULL) {
return NULL;
}
hf_id = *json_data_decoder_rec->hf_id;
-
- hfi = proto_registrar_get_nth(hf_id);
- DISSECTOR_ASSERT(hfi != NULL);
+ DISSECTOR_ASSERT(hf_id > 0);
if (use_compact) {
int str_len = (int)strlen(key_str);
- ti = proto_tree_add_item(tree, hfi, tok->tvb, tok->offset + (4 + str_len), tok->len - (5 + str_len), ENC_NA);
+ ti = proto_tree_add_item(tree, hf_id, tok->tvb, tok->offset + (4 + str_len), tok->len - (5 + str_len), ENC_NA);
if (json_data_decoder_rec->json_data_decoder) {
- (*json_data_decoder_rec->json_data_decoder)(tok->tvb, tree, pinfo, tok->offset + (4 + str_len), tok->len - (5 + str_len));
+ (*json_data_decoder_rec->json_data_decoder)(tok->tvb, tree, pinfo, tok->offset + (4 + str_len), tok->len - (5 + str_len), key_str, use_compact);
}
} else {
- ti = proto_tree_add_item(tree, hfi, tok->tvb, tok->offset, tok->len, ENC_NA);
+ ti = proto_tree_add_item(tree, hf_id, tok->tvb, tok->offset, tok->len, ENC_NA);
if (json_data_decoder_rec->json_data_decoder) {
- (*json_data_decoder_rec->json_data_decoder)(tok->tvb, tree, pinfo, tok->offset, tok->len);
+ (*json_data_decoder_rec->json_data_decoder)(tok->tvb, tree, pinfo, tok->offset, tok->len, key_str, use_compact);
}
}
return ti;
@@ -534,7 +462,7 @@ json_key_lookup(proto_tree* tree, tvbparse_elem_t* tok, char* key_str, packet_in
}
static char*
-join_strings(char* string_a, char* string_b, char separator)
+join_strings(wmem_allocator_t *pool, const char* string_a, const char* string_b, char separator)
{
if (string_a == NULL)
{
@@ -545,7 +473,7 @@ join_strings(char* string_a, char* string_b, char separator)
return NULL;
}
- wmem_strbuf_t* output_string_buffer = wmem_strbuf_new(wmem_packet_scope(), string_a);
+ wmem_strbuf_t* output_string_buffer = wmem_strbuf_new(pool, string_a);
if (separator != '\0')
{
@@ -567,7 +495,7 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
json_parser_data_t parser_data;
tvbparse_t *tt;
- http_message_info_t *message_info;
+ media_content_info_t *content_info;
const char *data_name;
int offset;
@@ -582,10 +510,10 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
if (strcmp(name, "frame")) {
col_append_sep_str(pinfo->cinfo, COL_PROTOCOL, "/", "JSON");
- col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "JavaScript Object Notation");
+ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "JSON");
} else {
col_set_str(pinfo->cinfo, COL_PROTOCOL, "JSON");
- col_set_str(pinfo->cinfo, COL_INFO, "JavaScript Object Notation");
+ col_set_str(pinfo->cinfo, COL_INFO, "JSON");
}
}
@@ -594,14 +522,14 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
/*
* No information from "match_string"
*/
- message_info = (http_message_info_t *)data;
- if (message_info == NULL) {
+ content_info = (media_content_info_t *)data;
+ if (content_info == NULL) {
/*
* No information from dissector data
*/
data_name = NULL;
} else {
- data_name = message_info->media_str;
+ data_name = content_info->media_str;
if (! (data_name && data_name[0])) {
/*
* No information from dissector data
@@ -612,7 +540,7 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
}
if (tree) {
- ti = proto_tree_add_item(tree, hfi_json, tvb, 0, -1, ENC_NA);
+ ti = proto_tree_add_item(tree, proto_json, tvb, 0, -1, ENC_NA);
json_tree = proto_item_add_subtree(ti, ett_json);
if (data_name)
@@ -623,11 +551,11 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
/* XXX*/
p_add_proto_data(pinfo->pool, pinfo, proto_json, 0, tvb);
- parser_data.stack = wmem_stack_new(wmem_packet_scope());
+ parser_data.stack = wmem_stack_new(pinfo->pool);
wmem_stack_push(parser_data.stack, json_tree);
// extended path based filtering
- parser_data.stack_path = wmem_stack_new(wmem_packet_scope());
+ parser_data.stack_path = wmem_stack_new(pinfo->pool);
wmem_stack_push(parser_data.stack_path, "");
wmem_stack_push(parser_data.stack_path, "");
@@ -646,21 +574,32 @@ dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
if(offset > 0)
{
- proto_tree_add_item(json_tree ? json_tree : tree, &hfi_json_ignored_leading_bytes, tvb, 0, offset, ENC_NA);
+ proto_tree_add_item(json_tree ? json_tree : tree, hf_json_ignored_leading_bytes, tvb, 0, offset, ENC_ASCII);
}
}
if (json_compact) {
- proto_tree* json_tree_compact = NULL;
- json_tree_compact = proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_compact, NULL, "JSON compact form:");
+ proto_tree* json_tree_compact = json_hide_root_item() ? json_tree :
+ proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_compact, NULL, "JSON compact form:");
- parser_data.stack_compact = wmem_stack_new(wmem_packet_scope());
+ parser_data.stack_compact = wmem_stack_new(pinfo->pool);
wmem_stack_push(parser_data.stack_compact, json_tree_compact);
- parser_data.array_idx = wmem_stack_new(wmem_packet_scope());
+ parser_data.array_idx = wmem_stack_new(pinfo->pool);
wmem_stack_push(parser_data.array_idx, GINT_TO_POINTER(JSON_COMPACT_TOP_ITEM)); /* top element */
}
+ if (json_raw) {
+ proto_tree* json_tree_raw = json_hide_root_item() ? json_tree :
+ proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_raw, NULL, "JSON raw form:");
+
+ parser_data.stack_raw = wmem_stack_new(pinfo->pool);
+ wmem_stack_push(parser_data.stack_raw, json_tree_raw);
+
+ parser_data.prev_item_raw = NULL;
+ parser_data.prev_item_type_raw = JSON_MARK_TYPE_NONE;
+ }
+
tt = tvbparse_init(pinfo->pool, tvb, offset, buffer_length - offset, &parser_data, want_ignore);
/* XXX, only one json in packet? */
@@ -702,7 +641,10 @@ before_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
proto_tree *subtree;
proto_item *ti;
- ti = proto_tree_add_item(tree, &hfi_json_object, tok->tvb, tok->offset, tok->len, ENC_NA);
+ ti = proto_tree_add_item(tree, hf_json_object, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
+ if (json_hide_original_tree() && wmem_stack_count(data->stack) == 1) {
+ proto_item_set_hidden(ti);
+ }
subtree = proto_item_add_subtree(ti, ett_json_object);
wmem_stack_push(data->stack, subtree);
@@ -715,7 +657,7 @@ before_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
gint idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
if (JSON_INSIDE_ARRAY(idx)) {
- ti_compact = proto_tree_add_none_format(tree_compact, &hfi_json_object_compact, tok->tvb, tok->offset, tok->len, "%d:", idx);
+ ti_compact = proto_tree_add_none_format(tree_compact, hf_json_object_compact, tok->tvb, tok->offset, tok->len, "%d:", idx);
subtree_compact = proto_item_add_subtree(ti_compact, ett_json_object_compact);
json_array_index_increment(data);
} else {
@@ -725,10 +667,35 @@ before_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
JSON_OBJECT_BEGIN(data);
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_tree* subtree_raw;
+ proto_item* ti_raw;
+
+ if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_END_OBJECT) {
+ proto_item_append_text(data->prev_item_raw, ",");
+ }
+
+ if (data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
+ /* this is an object value of an member, add the "{" just after the member name */
+ ti_raw = data->prev_item_raw;
+ proto_item_append_text(ti_raw, " {");
+ } else {
+ /* this object is either the top object or an element of an array, add the "{" as a single item */
+ ti_raw = proto_tree_add_none_format(tree_raw, hf_json_object_raw, tok->tvb, tok->offset, tok->len, "{");
+ }
+
+ subtree_raw = proto_item_add_subtree(ti_raw, ett_json_object_raw);
+ wmem_stack_push(data->stack_raw, subtree_raw);
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_BEGIN_OBJECT;
+ }
}
static void
-after_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *elem _U_) {
+after_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t* tok) {
json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
wmem_stack_pop(data->stack);
@@ -748,6 +715,23 @@ after_object(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
JSON_ARRAY_OBJECT_END(data);
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_tree* parent_tree = proto_tree_get_parent_tree(tree_raw);
+ proto_item* ti_raw;
+ if (data->prev_item_type_raw == JSON_MARK_TYPE_BEGIN_OBJECT) { /* an empty object */
+ ti_raw = data->prev_item_raw;
+ proto_item_append_text(ti_raw, "}");
+ } else {
+ tvbparse_elem_t* tok_last = tok->sub->last;
+ ti_raw = proto_tree_add_none_format(parent_tree, hf_json_object_raw, tok_last->tvb, tok_last->offset, tok_last->len, "}");
+ }
+ wmem_stack_pop(data->stack_raw);
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_END_OBJECT;
+ }
}
static void
@@ -758,15 +742,9 @@ before_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
proto_tree *subtree;
proto_item *ti;
- // tvb parse element covers the qutation marks which we don't want
- tvbparse_elem_t key_parse_element = tok->sub[0];
- key_parse_element.offset += 1;
- key_parse_element.len -= 2;
- char* key_string_without_quotation_marks = json_string_unescape(&key_parse_element, FALSE);
+ const char* key_string_without_quotation_marks = get_json_string(data->pinfo->pool, tok->sub, TRUE);
- char* key_string_with_quotation_marks = json_string_unescape(tok->sub, FALSE);
-
- ti = proto_tree_add_string(tree, &hfi_json_member, tok->tvb, tok->offset, tok->len, key_string_without_quotation_marks);
+ ti = proto_tree_add_string(tree, hf_json_member, tok->tvb, tok->offset, tok->len, key_string_without_quotation_marks);
subtree = proto_item_add_subtree(ti, ett_json_member);
wmem_stack_push(data->stack, subtree);
@@ -777,9 +755,10 @@ before_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
wmem_stack_push(data->stack_path, base_path);
wmem_stack_push(data->stack_path, last_key_string);
- char* path = join_strings(base_path, key_string_without_quotation_marks, '/');
+ char* path = join_strings(data->pinfo->pool, base_path, key_string_without_quotation_marks, '/');
wmem_stack_push(data->stack_path, path);
- wmem_stack_push(data->stack_path, key_string_without_quotation_marks);
+ /* stack won't write/free pointer. */
+ wmem_stack_push(data->stack_path, (void *)key_string_without_quotation_marks);
if (json_compact) {
proto_tree *tree_compact = (proto_tree *)wmem_stack_peek(data->stack_compact);
@@ -791,15 +770,41 @@ before_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t
if (key_tok && key_tok->id == JSON_TOKEN_STRING) {
ti_compact = json_key_lookup(tree_compact, tok, key_string_without_quotation_marks, data->pinfo, TRUE);
if (!ti_compact) {
- ti_compact = proto_tree_add_none_format(tree_compact, &hfi_json_member_compact, tok->tvb, tok->offset, tok->len, "%s:", key_string_with_quotation_marks);
+ ti_compact = proto_tree_add_none_format(tree_compact, hf_json_member_compact, tok->tvb, tok->offset, tok->len, "\"%s\":", key_string_without_quotation_marks);
}
} else {
- ti_compact = proto_tree_add_item(tree_compact, &hfi_json_member_compact, tok->tvb, tok->offset, tok->len, ENC_NA);
+ ti_compact = proto_tree_add_item(tree_compact, hf_json_member_compact, tok->tvb, tok->offset, tok->len, ENC_NA);
}
subtree_compact = proto_item_add_subtree(ti_compact, ett_json_member_compact);
wmem_stack_push(data->stack_compact, subtree_compact);
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_tree* subtree_raw;
+ proto_item* ti_raw = NULL;
+ tvbparse_elem_t* key_tok = tok->sub;
+
+ if (data->prev_item_raw && data->prev_item_type_raw != JSON_MARK_TYPE_BEGIN_OBJECT && data->prev_item_type_raw != JSON_MARK_TYPE_BEGIN_ARRAY) {
+ proto_item_append_text(data->prev_item_raw, ",");
+ }
+
+ if (key_tok && key_tok->id == JSON_TOKEN_STRING) {
+ ti_raw = json_key_lookup(tree_raw, tok, key_string_without_quotation_marks, data->pinfo, TRUE);
+ if (!ti_raw) {
+ ti_raw = proto_tree_add_none_format(tree_raw, hf_json_member_raw, tok->tvb, tok->offset, tok->len, "\"%s\":", key_string_without_quotation_marks);
+ }
+ } else {
+ ti_raw = proto_tree_add_item(tree_raw, hf_json_member_raw, tok->tvb, tok->offset, tok->len, ENC_NA);
+ }
+
+ subtree_raw = proto_item_add_subtree(ti_raw, ett_json_member_raw);
+ wmem_stack_push(data->stack_raw, subtree_raw);
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_MEMBER_NAME;
+ }
}
static void
@@ -811,12 +816,9 @@ after_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
tvbparse_elem_t* key_tok = tok->sub;
if (tree && key_tok && key_tok->id == JSON_TOKEN_STRING) {
- tvbparse_elem_t key_parse_element = key_tok[0];
- key_parse_element.offset += 1;
- key_parse_element.len -= 2;
- char* key_string_without_quotation_marks = json_string_unescape(&key_parse_element, FALSE);
+ const char* key_string_without_quotation_marks = get_json_string(data->pinfo->pool, key_tok, TRUE);
- proto_tree_add_string(tree, &hfi_json_key, key_tok->tvb, key_tok->offset, key_tok->len, key_string_without_quotation_marks);
+ proto_tree_add_string(tree, hf_json_key, key_tok->tvb, key_tok->offset, key_tok->len, key_string_without_quotation_marks);
}
// extended path based filtering
@@ -824,7 +826,7 @@ after_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
char* path = (char*)wmem_stack_pop(data->stack_path);
if (tree)
{
- proto_item* path_item = proto_tree_add_string(tree, &hfi_json_path, tok->tvb, tok->offset, tok->len, path);
+ proto_item* path_item = proto_tree_add_string(tree, hf_json_path, tok->tvb, tok->offset, tok->len, path);
proto_item_set_generated(path_item);
if (hide_extended_path_based_filtering)
{
@@ -836,6 +838,10 @@ after_member(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
wmem_stack_pop(data->stack_compact);
json_object_add_key(data);
}
+
+ if (json_raw) {
+ wmem_stack_pop(data->stack_raw);
+ }
}
static void
@@ -846,7 +852,10 @@ before_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
proto_tree *subtree;
proto_item *ti;
- ti = proto_tree_add_item(tree, &hfi_json_array, tok->tvb, tok->offset, tok->len, ENC_NA);
+ ti = proto_tree_add_item(tree, hf_json_array, tok->tvb, tok->offset, tok->len, ENC_NA);
+ if (json_hide_original_tree() && wmem_stack_count(data->stack) == 1) {
+ proto_item_set_hidden(ti);
+ }
subtree = proto_item_add_subtree(ti, ett_json_array);
wmem_stack_push(data->stack, subtree);
@@ -857,7 +866,7 @@ before_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
wmem_stack_push(data->stack_path, base_path);
wmem_stack_push(data->stack_path, last_key_string);
- char* path = join_strings(base_path, "[]", '/');
+ char* path = join_strings(data->pinfo->pool, base_path, "[]", '/');
wmem_stack_push(data->stack_path, path);
wmem_stack_push(data->stack_path, "[]");
@@ -866,12 +875,52 @@ before_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *
json_key_lookup(tree, tok, last_key_string, data->pinfo, FALSE);
if (json_compact) {
+ proto_tree* tree_compact = (proto_tree*)wmem_stack_peek(data->stack_compact);
+ proto_tree* subtree_compact;
+ proto_item* ti_compact;
+
+ gint idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
+
+ if (JSON_INSIDE_ARRAY(idx)) {
+ ti_compact = proto_tree_add_none_format(tree_compact, hf_json_array_compact, tok->tvb, tok->offset, tok->len, "%d:", idx);
+ subtree_compact = proto_item_add_subtree(ti_compact, ett_json_array_compact);
+ json_array_index_increment(data);
+ } else {
+ subtree_compact = tree_compact;
+ }
+ wmem_stack_push(data->stack_compact, subtree_compact);
+
JSON_ARRAY_BEGIN(data);
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_tree* subtree_raw;
+ proto_item* ti_raw;
+
+ if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_END_ARRAY) {
+ proto_item_append_text(data->prev_item_raw, ",");
+ }
+
+ if (data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
+ /* this is an array value of an member, add the "[" just after the member name */
+ ti_raw = data->prev_item_raw;
+ proto_item_append_text(ti_raw, " [");
+ } else {
+ /* this array is either the top element or an element of an array, add the "[" as a single item */
+ ti_raw = proto_tree_add_none_format(tree_raw, hf_json_array_raw, tok->tvb, tok->offset, tok->len, "[");
+ }
+
+ subtree_raw = proto_item_add_subtree(ti_raw, ett_json_array_raw);
+ wmem_stack_push(data->stack_raw, subtree_raw);
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_BEGIN_ARRAY;
+ }
}
static void
-after_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *elem _U_) {
+after_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t* tok) {
json_parser_data_t *data = (json_parser_data_t *) tvbparse_data;
wmem_stack_pop(data->stack);
@@ -890,8 +939,27 @@ after_array(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *e
else
proto_item_append_text(parent_item, " [...]");
+ wmem_stack_pop(data->stack_compact);
+
JSON_ARRAY_OBJECT_END(data);
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_tree* parent_tree = proto_tree_get_parent_tree(tree_raw);
+ proto_item* ti_raw;
+ if (data->prev_item_type_raw == JSON_MARK_TYPE_BEGIN_ARRAY) { /* an empty array */
+ ti_raw = data->prev_item_raw;
+ proto_item_append_text(ti_raw, "]");
+ } else {
+ tvbparse_elem_t* tok_last = tok->sub->last;
+ ti_raw = proto_tree_add_none_format(parent_tree, hf_json_array_raw, tok_last->tvb, tok_last->offset, tok_last->len, "]");
+ }
+ wmem_stack_pop(data->stack_raw);
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_END_ARRAY;
+ }
}
static void
@@ -911,25 +979,20 @@ after_value(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *t
char* key_string = (char*)wmem_stack_pop(data->stack_path);
char* path = (char*)wmem_stack_pop(data->stack_path);
- char* value_str = NULL;
+ const char* value_str = NULL;
if (value_id == JSON_TOKEN_STRING && tok->len >= 2)
{
- // tvb parse element covers the qutation marks which we don't want
- tvbparse_elem_t key_parse_element = tok[0];
- key_parse_element.offset += 1;
- key_parse_element.len -= 2;
-
- value_str = json_string_unescape(&key_parse_element, FALSE);
+ value_str = get_json_string(data->pinfo->pool, tok, TRUE);
}
else
{
- value_str = json_string_unescape(tok, FALSE);
+ value_str = get_json_string(data->pinfo->pool, tok, FALSE);
}
- char* path_with_value = join_strings(path, value_str, ':');
- char* memeber_with_value = join_strings(key_string, value_str, ':');
- proto_item* path_with_value_item = proto_tree_add_string(tree, &hfi_json_path_with_value, tok->tvb, tok->offset, tok->len, path_with_value);
- proto_item* member_with_value_item = proto_tree_add_string(tree, &hfi_json_member_with_value, tok->tvb, tok->offset, tok->len, memeber_with_value);
+ char* path_with_value = join_strings(data->pinfo->pool, path, value_str, ':');
+ char* memeber_with_value = join_strings(data->pinfo->pool, key_string, value_str, ':');
+ proto_item* path_with_value_item = proto_tree_add_string(tree, hf_json_path_with_value, tok->tvb, tok->offset, tok->len, path_with_value);
+ proto_item* member_with_value_item = proto_tree_add_string(tree, hf_json_member_with_value, tok->tvb, tok->offset, tok->len, memeber_with_value);
proto_item_set_generated(path_with_value_item);
proto_item_set_generated(member_with_value_item);
@@ -950,39 +1013,39 @@ after_value(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *t
proto_item *key_lookup = NULL;
key_lookup = json_key_lookup(tree, tok, key_string, data->pinfo, FALSE);
if (!key_lookup) {
- proto_tree_add_string(tree, &hfi_json_value_string, tok->tvb, tok->offset, tok->len, value_str);
+ proto_tree_add_string(tree, hf_json_value_string, tok->tvb, tok->offset, tok->len, value_str);
}
}
else
{
- proto_tree_add_item(tree, &hfi_json_value_string, tok->tvb, tok->offset, tok->len, ENC_ASCII | ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_string, tok->tvb, tok->offset, tok->len, ENC_ASCII | ENC_NA);
}
break;
case JSON_TOKEN_NUMBER:
/* XXX, convert to number */
- proto_tree_add_item(tree, &hfi_json_value_number, tok->tvb, tok->offset, tok->len, ENC_ASCII|ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_number, tok->tvb, tok->offset, tok->len, ENC_ASCII);
break;
case JSON_TOKEN_FALSE:
- proto_tree_add_item(tree, &hfi_json_value_false, tok->tvb, tok->offset, tok->len, ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_false, tok->tvb, tok->offset, tok->len, ENC_NA);
break;
case JSON_TOKEN_NULL:
- proto_tree_add_item(tree, &hfi_json_value_null, tok->tvb, tok->offset, tok->len, ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_null, tok->tvb, tok->offset, tok->len, ENC_NA);
break;
case JSON_TOKEN_TRUE:
- proto_tree_add_item(tree, &hfi_json_value_true, tok->tvb, tok->offset, tok->len, ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_true, tok->tvb, tok->offset, tok->len, ENC_NA);
break;
case JSON_TOKEN_NAN:
- proto_tree_add_item(tree, &hfi_json_value_nan, tok->tvb, tok->offset, tok->len, ENC_NA);
+ proto_tree_add_item(tree, hf_json_value_nan, tok->tvb, tok->offset, tok->len, ENC_NA);
break;
@@ -996,16 +1059,36 @@ after_value(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *t
gint idx = GPOINTER_TO_INT(wmem_stack_peek(data->array_idx));
- char *val_str = tvb_get_string_enc(wmem_packet_scope(), tok->tvb, tok->offset, tok->len, ENC_UTF_8);
+ char *val_str = tvb_get_string_enc(data->pinfo->pool, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
if (JSON_INSIDE_ARRAY(idx)) {
- proto_tree_add_none_format(tree_compact, &hfi_json_array_item_compact, tok->tvb, tok->offset, tok->len, "%d: %s", idx, val_str);
+ proto_tree_add_none_format(tree_compact, hf_json_array_item_compact, tok->tvb, tok->offset, tok->len, "%d: %s", idx, val_str);
json_array_index_increment(data);
} else {
proto_item *parent_item = proto_tree_get_parent(tree_compact);
proto_item_append_text(parent_item, " %s", val_str);
}
}
+
+ if (json_raw) {
+ proto_tree* tree_raw = (proto_tree*)wmem_stack_peek(data->stack_raw);
+ proto_item* ti_raw;
+ char* val_str = tvb_get_string_enc(data->pinfo->pool, tok->tvb, tok->offset, tok->len, ENC_UTF_8);
+
+ if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_VALUE) {
+ proto_item_append_text(data->prev_item_raw, ","); /* this value is an element of an array */
+ }
+
+ if (data->prev_item_raw && data->prev_item_type_raw == JSON_MARK_TYPE_MEMBER_NAME) {
+ ti_raw = proto_tree_get_parent(tree_raw);
+ proto_item_append_text(ti_raw, " %s", val_str);
+ } else {
+ ti_raw = proto_tree_add_none_format(tree_raw, hf_json_array_item_raw, tok->tvb, tok->offset, tok->len, "%s", val_str);
+ }
+
+ data->prev_item_raw = ti_raw;
+ data->prev_item_type_raw = JSON_MARK_TYPE_VALUE;
+ }
}
static void
@@ -1148,7 +1231,7 @@ static gboolean
dissect_json_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
guint len = tvb_captured_length(tvb);
- const guint8* buf = tvb_get_string_enc(wmem_packet_scope(), tvb, 0, len, ENC_ASCII);
+ const guint8* buf = tvb_get_string_enc(pinfo->pool, tvb, 0, len, ENC_ASCII);
if (json_validate(buf, len) == FALSE)
return FALSE;
@@ -1166,111 +1249,135 @@ dissect_json_acdr_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
return FALSE;
}
-/* Functions to sub dissect json content */
-static void
-dissect_base64decoded_eps_ie(tvbuff_t* tvb, proto_tree* tree, packet_info* pinfo, int offset, int len)
-{
- /* base64-encoded characters, encoding the
- * EPS IE specified in 3GPP TS 29.274.
- */
- proto_item* ti;
- proto_tree* sub_tree;
- tvbuff_t* bin_tvb = base64_tvb_to_new_tvb(tvb, offset, len);
- add_new_data_source(pinfo, bin_tvb, "Base64 decoded");
- ti = proto_tree_add_item(tree, &hfi_json_binary_data, bin_tvb, 0, -1, ENC_NA);
- sub_tree = proto_item_add_subtree(ti, ett_json_base64decoded_eps_ie);
- dissect_gtpv2_ie_common(bin_tvb, pinfo, sub_tree, 0, 0/* Message type 0, Reserved */, NULL);
-}
-
static void
register_static_headers(void) {
- gchar* header_name;
+ json_header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+}
- /* Here hf[x].hfinfo.name is a header method which is used as key
- * for matching ids while processing HTTP2 packets */
+void
+proto_register_json(void)
+{
static hf_register_info hf[] = {
- {
- &hf_json_3gpp_ueepspdnconnection,
- {"ueEpsPdnConnection", "json.3gpp.ueepspdnconnection",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_array,
+ { "Array", "json.array",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON array", HFILL }
},
- {
- &hf_json_3gpp_bearerlevelqos,
- {"bearerLevelQoS", "json.3gpp.bearerlevelqos",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_object,
+ { "Object", "json.object",
+ FT_STRING, BASE_NONE|BASE_NO_DISPLAY_VALUE, NULL, 0x00,
+ "JSON object", HFILL }
},
- {
- &hf_json_3gpp_epsbearersetup,
- {"epsBearerSetup", "json.3gpp.epsbearersetup",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_member,
+ { "Member", "json.member",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "JSON object member", HFILL }
},
- {
- &hf_json_3gpp_forwardingbearercontexts,
- {"forwardingBearerContexts", "json.3gpp.forwardingbearercontexts",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_key,
+ { "Key", "json.key",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
},
- {
- &hf_json_3gpp_forwardingfteid,
- {"forwardingFTeid", "json.3gpp.forwardingfteid",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_path,
+ { "Path", "json.path",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
},
- {
- &hf_json_3gpp_pgwnodename,
- {"pgwNodeName", "json.3gpp.pgwnodename",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_path_with_value,
+ { "Path with value", "json.path_with_value",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
},
- {
- &hf_json_3gpp_pgws8cfteid,
- {"pgwS8cFteid", "json.3gpp.pgws8cfteid",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
+ { &hf_json_member_with_value,
+ { "Member with value", "json.member_with_value",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_json_value_string,
+ { /* FT_STRINGZ? */ "String value", "json.value.string",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "JSON string value", HFILL }
+ },
+ { &hf_json_value_number,
+ { /* FT_DOUBLE/ FT_INT64? */ "Number value", "json.value.number",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "JSON number value", HFILL }
+ },
+ { &hf_json_value_false,
+ { "False value", "json.value.false",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON false value", HFILL }
+ },
+ { &hf_json_value_null,
+ { "Null value", "json.value.null",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON null value", HFILL }
+ },
+ { &hf_json_value_true,
+ { "True value", "json.value.true",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON true value", HFILL }
+ },
+ { &hf_json_value_nan,
+ { "NaN value", "json.value.nan",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON NaN value", HFILL }
+ },
+ { &hf_json_array_compact,
+ { "Array compact", "json.array_compact",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON array compact", HFILL }
+ },
+ { &hf_json_object_compact,
+ { "Object compact", "json.object_compact",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON object compact", HFILL }
+ },
+ { &hf_json_member_compact,
+ { "Member compact", "json.member_compact",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON member compact", HFILL }
+ },
+ { &hf_json_array_item_compact,
+ { "Array item compact", "json.array_item_compact",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON array item compact", HFILL }
+ },
+ { &hf_json_binary_data,
+ { "Binary data", "json.binary_data",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "JSON binary data", HFILL }
+ },
+ { &hf_json_ignored_leading_bytes,
+ { "Ignored leading bytes", "json.ignored_leading_bytes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_json_array_raw,
+ { "Array raw", "json.array_raw",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON array raw", HFILL }
+ },
+ { &hf_json_object_raw,
+ { "Object raw", "json.object_raw",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON object raw", HFILL }
+ },
+ { &hf_json_member_raw,
+ { "Member raw", "json.member_raw",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON member raw", HFILL }
+ },
+ { &hf_json_array_item_raw,
+ { "Array item raw", "json.array_item_raw",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JSON array item raw", HFILL }
},
- {
- &hf_json_3gpp_pgws8ufteid,
- {"pgwS8uFteid", "json.3gpp.pgws8ufteid",
- FT_STRING, BASE_NONE, NULL, 0x0,
- NULL, HFILL}
- }
- };
- /* List of decoding functions the index matches the HF */
- static void(*json_decode_fn[])(tvbuff_t * tvb, proto_tree * tree, packet_info * pinfo, int offset, int len) = {
- dissect_base64decoded_eps_ie, /* ueEpsPdnConnection */
- dissect_base64decoded_eps_ie, /* bearerLevelQoS */
- dissect_base64decoded_eps_ie, /* epsBearerSetup */
- dissect_base64decoded_eps_ie, /* forwardingBearerContexts */
- dissect_base64decoded_eps_ie, /* forwardingFTeid */
- dissect_base64decoded_eps_ie, /* pgwNodeName */
- dissect_base64decoded_eps_ie, /* pgwS8cFteid */
- dissect_base64decoded_eps_ie, /* pgwS8uFteid */
-
- NULL, /* NONE */
};
- /* Hfs with functions */
- for (guint i = 0; i < G_N_ELEMENTS(hf); ++i) {
- header_name = g_strdup(hf[i].hfinfo.name);
- json_data_decoder_t* json_data_decoder_rec = g_new(json_data_decoder_t, 1);
- json_data_decoder_rec->hf_id = &hf[i].hfinfo.id;
- json_data_decoder_rec->json_data_decoder = json_decode_fn[i];
- g_hash_table_insert(header_fields_hash, header_name, json_data_decoder_rec);
- }
-
- proto_register_field_array(proto_json_3gpp, hf, G_N_ELEMENTS(hf));
-}
-
-void
-proto_register_json(void)
-{
static gint *ett[] = {
&ett_json,
&ett_json_array,
@@ -1280,42 +1387,20 @@ proto_register_json(void)
&ett_json_array_compact,
&ett_json_object_compact,
&ett_json_member_compact,
- &ett_json_base64decoded_eps_ie,
+ &ett_json_raw,
+ &ett_json_array_raw,
+ &ett_json_object_raw,
+ &ett_json_member_raw,
};
-#ifndef HAVE_HFI_SECTION_INIT
- static header_field_info *hfi[] = {
- &hfi_json_array,
- &hfi_json_object,
- &hfi_json_member,
- &hfi_json_key,
- &hfi_json_path,
- &hfi_json_path_with_value,
- &hfi_json_member_with_value,
- &hfi_json_value_string,
- &hfi_json_value_number,
- &hfi_json_value_false,
- &hfi_json_value_null,
- &hfi_json_value_true,
- &hfi_json_value_nan,
- &hfi_json_array_compact,
- &hfi_json_object_compact,
- &hfi_json_member_compact,
- &hfi_json_array_item_compact,
- &hfi_json_binary_data,
- &hfi_json_ignored_leading_bytes
- };
-#endif
-
module_t *json_module;
proto_json = proto_register_protocol("JavaScript Object Notation", "JSON", "json");
- hfi_json = proto_registrar_get_nth(proto_json);
-
- proto_register_fields(proto_json, hfi, array_length(hfi));
+ proto_register_field_array(proto_json, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
json_handle = register_dissector("json", dissect_json, proto_json);
+ json_file_handle = register_dissector("json_file", dissect_json_file, proto_json);
init_json_parser();
@@ -1325,6 +1410,17 @@ proto_register_json(void)
"Display JSON like in browsers devtool",
&json_compact);
+ prefs_register_bool_preference(json_module, "raw_form",
+ "Display JSON in raw form",
+ "Display JSON like in vscode editor",
+ &json_raw);
+
+ prefs_register_bool_preference(json_module, "auto_hide",
+ "Hide tree or root item automatically",
+ "Determine whether to hide the tree of original form or root item of compact or raw form"
+ " based on the enabled status of compact_form and raw_form preferences.",
+ &auto_hide);
+
prefs_register_bool_preference(json_module, "ignore_leading_bytes",
"Ignore leading non JSON bytes",
"Leading bytes will be ignored until first '[' or '{' is found.",
@@ -1335,7 +1431,10 @@ proto_register_json(void)
"Hide extended path based filtering",
&hide_extended_path_based_filtering);
- proto_json_3gpp = proto_register_protocol("JSON 3GPP", "JSON_3GPP", "json_3gpp");
+ prefs_register_bool_preference(json_module, "unescape_strings",
+ "Replace character escapes with the escaped literal value",
+ "Replace character escapes with the escaped literal value",
+ &unescape_strings);
/* Fill hash table with static headers */
register_static_headers();
@@ -1344,8 +1443,6 @@ proto_register_json(void)
void
proto_reg_handoff_json(void)
{
- dissector_handle_t json_file_handle = create_dissector_handle(dissect_json_file, proto_json);
-
heur_dissector_add("hpfeeds", dissect_json_heur, "JSON over HPFEEDS", "json_hpfeeds", proto_json, HEURISTIC_ENABLE);
heur_dissector_add("db-lsp", dissect_json_heur, "JSON over DB-LSP", "json_db_lsp", proto_json, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_json_acdr_heur, "JSON over AC DR", "json_acdr", proto_json, HEURISTIC_ENABLE);
@@ -1354,6 +1451,8 @@ proto_reg_handoff_json(void)
dissector_add_for_decode_as("udp.port", json_file_handle);
dissector_add_string("media_type", "application/json", json_handle); /* RFC 4627 */
+ dissector_add_string("media_type", "application/senml+json", json_handle); /* RFC 8428 */
+ dissector_add_string("media_type", "application/sensml+json", json_handle); /* RFC 8428 */
dissector_add_string("media_type", "application/json-rpc", json_handle); /* JSON-RPC over HTTP */
dissector_add_string("media_type", "application/jsonrequest", json_handle); /* JSON-RPC over HTTP */
dissector_add_string("media_type", "application/dds-web+json", json_handle); /* DDS Web Integration Service over HTTP */
@@ -1362,6 +1461,7 @@ proto_reg_handoff_json(void)
dissector_add_string("media_type", "application/merge-patch+json", json_handle); /* RFC 7386 HTTP PATCH methods (RFC 5789) */
dissector_add_string("media_type", "application/json-patch+json", json_handle); /* RFC 6902 JavaScript Object Notation (JSON) Patch */
dissector_add_string("media_type", "application/x-ndjson", json_handle);
+ dissector_add_string("media_type", "application/3gppHal+json", json_handle);
dissector_add_string("grpc_message_type", "application/grpc+json", json_handle);
dissector_add_uint_range_with_preference("tcp.port", "", json_file_handle); /* JSON-RPC over TCP */
dissector_add_uint_range_with_preference("udp.port", "", json_file_handle); /* JSON-RPC over UDP */