AMQP: Add field table values as fields
Add the name, type, and values of field tables and arrays as fields under the FT_NONE header. This makes them filterable and show up in JSON export. Fix #18385
This commit is contained in:
parent
cabe0e0239
commit
1293f15897
|
@ -1451,6 +1451,20 @@ static int hf_amqp_method_dtx_start_dtx_identifier = -1;
|
|||
static int hf_amqp_method_tunnel_request_meta_data = -1;
|
||||
static int hf_amqp_method_confirm_select_nowait = -1;
|
||||
static int hf_amqp_field = -1;
|
||||
static int hf_amqp_field_name = -1;
|
||||
static int hf_amqp_field_type = -1;
|
||||
static int hf_amqp_field_integer = -1;
|
||||
static int hf_amqp_field_unsigned_integer = -1;
|
||||
static int hf_amqp_field_string = -1;
|
||||
static int hf_amqp_field_boolean = -1;
|
||||
static int hf_amqp_field_byte = -1;
|
||||
static int hf_amqp_field_unsigned_byte = -1;
|
||||
static int hf_amqp_field_short_int = -1;
|
||||
static int hf_amqp_field_short_uint = -1;
|
||||
static int hf_amqp_field_long_int = -1;
|
||||
static int hf_amqp_field_float = -1;
|
||||
static int hf_amqp_field_double = -1;
|
||||
static int hf_amqp_field_decimal = -1;
|
||||
static int hf_amqp_field_timestamp = -1;
|
||||
static int hf_amqp_field_byte_array = -1;
|
||||
static int hf_amqp_header_class_id = -1;
|
||||
|
@ -1525,6 +1539,7 @@ static gint ett_args = -1;
|
|||
static gint ett_props = -1;
|
||||
static gint ett_field_table = -1;
|
||||
static gint ett_amqp_init = -1;
|
||||
static gint ett_amqp_0_9_field = -1;
|
||||
static gint ett_amqp_0_10_map = -1;
|
||||
static gint ett_amqp_0_10_array = -1;
|
||||
static gint ett_amqp_0_10_struct = -1;
|
||||
|
@ -2381,25 +2396,30 @@ get_amqp_0_9_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
|
|||
static void
|
||||
dissect_amqp_0_9_field_table(tvbuff_t *tvb, packet_info *pinfo, int offset, guint length, proto_item *item)
|
||||
{
|
||||
proto_tree *field_table_tree;
|
||||
proto_tree *field_table_tree, *field_item_tree;
|
||||
proto_item *field_item;
|
||||
guint namelen, vallen;
|
||||
const char *name;
|
||||
const guint8 *name;
|
||||
int field_start;
|
||||
|
||||
field_table_tree = proto_item_add_subtree(item, ett_amqp);
|
||||
|
||||
while (length != 0) {
|
||||
field_start = offset;
|
||||
field_item = proto_tree_add_item(field_table_tree, hf_amqp_field, tvb,
|
||||
offset, 1, ENC_NA);
|
||||
namelen = tvb_get_guint8(tvb, offset);
|
||||
offset += 1;
|
||||
length -= 1;
|
||||
if (length < namelen)
|
||||
goto too_short;
|
||||
name = (char*) tvb_get_string_enc(wmem_packet_scope(), tvb, offset, namelen, ENC_UTF_8|ENC_NA);
|
||||
field_item_tree = proto_item_add_subtree(field_item, ett_amqp_0_9_field);
|
||||
proto_tree_add_item_ret_string(field_item_tree, hf_amqp_field_name, tvb, offset, namelen, ENC_UTF_8, pinfo->pool, &name);
|
||||
proto_item_set_text(field_item, "%s", name);
|
||||
offset += namelen;
|
||||
length -= namelen;
|
||||
|
||||
vallen = dissect_amqp_0_9_field_value(tvb, pinfo, offset, length, name, field_table_tree);
|
||||
vallen = dissect_amqp_0_9_field_value(tvb, pinfo, offset, length, name, field_item_tree);
|
||||
if(vallen == 0)
|
||||
goto too_short;
|
||||
offset += vallen;
|
||||
|
@ -2417,7 +2437,8 @@ too_short:
|
|||
static void
|
||||
dissect_amqp_0_9_field_array(tvbuff_t *tvb, packet_info *pinfo, int offset, guint length, proto_item *item)
|
||||
{
|
||||
proto_tree *field_table_tree;
|
||||
proto_tree *field_table_tree, *field_item_tree;
|
||||
proto_item *field_item;
|
||||
int field_start, idx;
|
||||
guint vallen;
|
||||
const char *name;
|
||||
|
@ -2427,9 +2448,12 @@ dissect_amqp_0_9_field_array(tvbuff_t *tvb, packet_info *pinfo, int offset, guin
|
|||
|
||||
while (length != 0) {
|
||||
field_start = offset;
|
||||
name = wmem_strdup_printf(wmem_packet_scope(), "[%i]", idx);
|
||||
field_item = proto_tree_add_none_format(field_table_tree, hf_amqp_field, tvb,
|
||||
offset, 0, "[%i]", idx);
|
||||
field_item_tree = proto_item_add_subtree(field_item, ett_amqp_0_9_field);
|
||||
name = wmem_strdup_printf(pinfo->pool, "[%i]", idx);
|
||||
|
||||
vallen = dissect_amqp_0_9_field_value(tvb, pinfo, offset, length, name, field_table_tree);
|
||||
vallen = dissect_amqp_0_9_field_value(tvb, pinfo, offset, length, name, field_item_tree);
|
||||
if(vallen == 0)
|
||||
goto too_short;
|
||||
offset += vallen;
|
||||
|
@ -2477,67 +2501,77 @@ too_short:
|
|||
* who follows the 0-9-1 spec for this bit.
|
||||
*/
|
||||
|
||||
static const value_string amqp_0_9_field_type_vals[] = {
|
||||
{ 'A', "array" },
|
||||
{ 'B', "unsigned byte" },
|
||||
{ 'D', "decimal" },
|
||||
{ 'F', "field table" },
|
||||
{ 'I', "integer" },
|
||||
{ 'S', "string" },
|
||||
{ 'T', "timestamp" },
|
||||
{ 'V', "void" },
|
||||
{ 'b', "byte" },
|
||||
{ 'd', "double" },
|
||||
{ 'f', "float" },
|
||||
{ 'i', "unsigned integer" },
|
||||
{ 'l', "long int" },
|
||||
{ 's', "short int" },
|
||||
{ 't', "boolean" },
|
||||
{ 'u', "short uint" },
|
||||
{ 'x', "byte array" },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
static guint
|
||||
dissect_amqp_0_9_field_value(tvbuff_t *tvb, packet_info *pinfo, int offset, guint length,
|
||||
const char *name, proto_tree *field_table_tree)
|
||||
const char *name _U_, proto_tree *field_tree)
|
||||
{
|
||||
proto_item *ti;
|
||||
proto_item *field_item, *type_item, *ti = NULL;
|
||||
guint vallen;
|
||||
guint8 type;
|
||||
char type_buf[7] = { 0 };
|
||||
const char *amqp_typename;
|
||||
const char *value;
|
||||
nstime_t tv;
|
||||
int value_start;
|
||||
|
||||
value_start = offset;
|
||||
if (length < 1)
|
||||
return 0; /* too short */
|
||||
type = tvb_get_guint8(tvb, offset);
|
||||
amqp_typename = char_val_to_str(type, amqp_0_9_field_type_vals, "unknown type");
|
||||
field_item = proto_tree_get_parent(field_tree);
|
||||
proto_item_append_text(field_item, " (%s)", amqp_typename);
|
||||
type_item = proto_tree_add_item(field_tree, hf_amqp_field_type, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
length -= 1;
|
||||
switch (type) {
|
||||
case 'I': /* signed 32-bit */
|
||||
amqp_typename = "integer";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%" PRIi32,
|
||||
tvb_get_ntohil(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_integer, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
break;
|
||||
case 'D':
|
||||
amqp_typename = "decimal";
|
||||
case 'D': /* 40-bit decimal floating point, biased towards small numbers */
|
||||
{
|
||||
if (length < 5)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%f",
|
||||
tvb_get_ntohl(tvb, offset+1) / pow(10, tvb_get_guint8(tvb, offset)));
|
||||
double decimal = tvb_get_ntohl(tvb, offset + 1) / pow(10, tvb_get_guint8(tvb, offset));
|
||||
ti = proto_tree_add_double(field_tree, hf_amqp_field_decimal, tvb, offset, 5, decimal);
|
||||
offset += 5;
|
||||
break;
|
||||
}
|
||||
case 'S': /* long string, UTF-8 encoded */
|
||||
amqp_typename = "string";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
vallen = tvb_get_ntohl(tvb, offset);
|
||||
offset += 4;
|
||||
length -= 4;
|
||||
if (length < vallen)
|
||||
return 0; /* too short */
|
||||
value = (char*) tvb_get_string_enc(wmem_packet_scope(), tvb, offset, vallen, ENC_UTF_8|ENC_NA);
|
||||
ti = proto_tree_add_item_ret_length(field_tree, hf_amqp_field_string, tvb, offset, 4, ENC_BIG_ENDIAN|ENC_UTF_8, &vallen);
|
||||
offset += vallen;
|
||||
break;
|
||||
case 'T': /* timestamp (u64) */
|
||||
if (length < 8)
|
||||
return 0; /* too short */
|
||||
tv.secs = (time_t)tvb_get_ntoh64(tvb, offset);
|
||||
tv.nsecs = 0;
|
||||
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_timestamp, tvb,
|
||||
offset, 8, ENC_TIME_SECS|ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
ti = proto_tree_add_time(field_table_tree, hf_amqp_field_timestamp, tvb,
|
||||
value_start, offset - value_start, &tv);
|
||||
proto_item_prepend_text(ti, "%s ", name);
|
||||
return offset - value_start;
|
||||
break;
|
||||
case 'F': /* nested table */
|
||||
amqp_typename = "field table";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
vallen = tvb_get_ntohl(tvb, offset);
|
||||
|
@ -2545,90 +2579,67 @@ dissect_amqp_0_9_field_value(tvbuff_t *tvb, packet_info *pinfo, int offset, guin
|
|||
length -= 4;
|
||||
if (length < vallen)
|
||||
return 0; /* too short */
|
||||
ti = proto_tree_add_item(field_table_tree, hf_amqp_field, tvb,
|
||||
value_start, offset+vallen - value_start, ENC_NA);
|
||||
proto_item_set_text(ti, "%s (%s)", name, amqp_typename);
|
||||
dissect_amqp_0_9_field_table(tvb, pinfo, offset, vallen, ti);
|
||||
dissect_amqp_0_9_field_table(tvb, pinfo, offset, vallen, field_tree);
|
||||
offset += vallen;
|
||||
return offset - value_start;
|
||||
break;
|
||||
case 'V':
|
||||
amqp_typename = "void";
|
||||
value = "";
|
||||
break;
|
||||
/* AMQP 0-9-1 types */
|
||||
case 't': /* boolean */
|
||||
amqp_typename = "boolean";
|
||||
if (length < 1)
|
||||
return 0; /* too short */
|
||||
value = tvb_get_guint8(tvb, offset) ? "true" : "false";
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_boolean, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
break;
|
||||
case 'b': /* signed 8-bit */
|
||||
amqp_typename = "byte";
|
||||
if (length < 1)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%d",
|
||||
tvb_get_gint8(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_byte, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
break;
|
||||
case 'B': /* unsigned 8-bit */
|
||||
amqp_typename = "unsigned byte";
|
||||
if (length < 1)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%u",
|
||||
tvb_get_guint8(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_unsigned_byte, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
break;
|
||||
case 's': /* signed 16-bit */
|
||||
amqp_typename = "short int";
|
||||
if (length < 2)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%" PRIi16,
|
||||
tvb_get_ntohis(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_short_int, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
case 'u': /* unsigned 16-bit */
|
||||
amqp_typename = "short uint";
|
||||
if (length < 2)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%" PRIu16,
|
||||
tvb_get_ntohs(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_short_uint, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
break;
|
||||
case 'i': /* unsigned 32-bit */
|
||||
amqp_typename = "unsigned integer";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%" PRIu32,
|
||||
tvb_get_ntohl(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_unsigned_integer, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
break;
|
||||
case 'l': /* signed 64-bit */
|
||||
amqp_typename = "long int";
|
||||
if (length < 8)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%" PRIi64,
|
||||
tvb_get_ntohi64(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_long_int, tvb, offset, 8, ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
break;
|
||||
case 'f': /* 32-bit float */
|
||||
amqp_typename = "float";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%f",
|
||||
tvb_get_ntohieee_float(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_float, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
break;
|
||||
case 'd': /* 64-bit float */
|
||||
amqp_typename = "double";
|
||||
if (length < 8)
|
||||
return 0; /* too short */
|
||||
value = wmem_strdup_printf(wmem_packet_scope(), "%f",
|
||||
tvb_get_ntohieee_double(tvb, offset));
|
||||
ti = proto_tree_add_item(field_tree, hf_amqp_field_double, tvb, offset, 8, ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
break;
|
||||
case 'A': /* array */
|
||||
amqp_typename = "array";
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
vallen = tvb_get_ntohl(tvb, offset);
|
||||
|
@ -2636,41 +2647,27 @@ dissect_amqp_0_9_field_value(tvbuff_t *tvb, packet_info *pinfo, int offset, guin
|
|||
length -= 4;
|
||||
if (length < vallen)
|
||||
return 0; /* too short */
|
||||
ti = proto_tree_add_item(field_table_tree, hf_amqp_field, tvb,
|
||||
value_start, offset+vallen - value_start, ENC_NA);
|
||||
proto_item_set_text(ti, "%s (%s)", name, amqp_typename);
|
||||
dissect_amqp_0_9_field_array(tvb, pinfo, offset, vallen, ti);
|
||||
offset += vallen;
|
||||
return offset - value_start;
|
||||
break;
|
||||
case 'x': /* byte array */
|
||||
if (length < 4)
|
||||
return 0; /* too short */
|
||||
vallen = tvb_get_ntohl(tvb, offset);
|
||||
offset += 4;
|
||||
length -= 4;
|
||||
if (length < vallen)
|
||||
return 0; /* too short */
|
||||
ti = proto_tree_add_item(field_table_tree, hf_amqp_field_byte_array, tvb,
|
||||
offset, vallen, ENC_NA);
|
||||
proto_item_prepend_text(ti, "%s ", name);
|
||||
ti = proto_tree_add_item_ret_length(field_tree, hf_amqp_field_byte_array, tvb,
|
||||
offset, 4, ENC_NA, &vallen);
|
||||
offset += vallen;
|
||||
return offset - value_start;
|
||||
default:
|
||||
amqp_typename = "";
|
||||
value = NULL;
|
||||
break;
|
||||
default:
|
||||
expert_add_info(pinfo, type_item, &ei_amqp_array_type_unknown);
|
||||
/* Without knowing the type, we don't know how much to increment
|
||||
* the offset, so break out. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (value != NULL)
|
||||
proto_tree_add_none_format(field_table_tree, hf_amqp_field, tvb,
|
||||
value_start, offset - value_start,
|
||||
"%s (%s): %s", name, amqp_typename, value);
|
||||
else
|
||||
proto_tree_add_none_format(field_table_tree, hf_amqp_field, tvb,
|
||||
value_start, offset - value_start,
|
||||
"%s: unknown type %s",
|
||||
name,
|
||||
hfinfo_char_value_format_display(BASE_HEX, type_buf, type));
|
||||
proto_item_set_end(field_item, tvb, offset);
|
||||
if (ti != NULL) {
|
||||
proto_item_append_text(field_item, ": %s", proto_item_get_display_repr(pinfo->pool, ti));
|
||||
}
|
||||
return offset - value_start;
|
||||
}
|
||||
|
||||
|
@ -13270,16 +13267,72 @@ proto_register_amqp(void)
|
|||
FT_BOOLEAN, 8, NULL, 0x01,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field, {
|
||||
"AMQP", "amqp.field",
|
||||
"Field", "amqp.field",
|
||||
FT_NONE, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_name, {
|
||||
"Name", "amqp.field.name",
|
||||
FT_STRING, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_type, {
|
||||
"Type", "amqp.field.type",
|
||||
FT_CHAR, BASE_HEX, VALS(amqp_0_9_field_type_vals), 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_integer, {
|
||||
"Value", "amqp.field.integer",
|
||||
FT_INT32, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_unsigned_integer, {
|
||||
"Value", "amqp.field.unsigned_integer",
|
||||
FT_UINT32, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_string, {
|
||||
"Value", "amqp.field.string",
|
||||
FT_UINT_STRING, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_boolean, {
|
||||
"Value", "amqp.field.boolean",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_byte, {
|
||||
"Value", "amqp.field.byte",
|
||||
FT_INT8, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_unsigned_byte, {
|
||||
"Value", "amqp.field.unsigned_byte",
|
||||
FT_UINT8, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_short_int, {
|
||||
"Value", "amqp.field.short_int",
|
||||
FT_INT16, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_short_uint, {
|
||||
"Value", "amqp.field.short_uint",
|
||||
FT_UINT16, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_long_int, {
|
||||
"Value", "amqp.field.long_int",
|
||||
FT_INT64, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_float, {
|
||||
"Value", "amqp.field.float",
|
||||
FT_FLOAT, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_double, {
|
||||
"Value", "amqp.field.double",
|
||||
FT_DOUBLE, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_decimal, {
|
||||
"Value", "amqp.field.decimal",
|
||||
FT_DOUBLE, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_timestamp, {
|
||||
"(timestamp)", "amqp.field.timestamp",
|
||||
"Value", "amqp.field.timestamp",
|
||||
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_field_byte_array, {
|
||||
"(byte array)", "amqp.field.byte_array",
|
||||
FT_BYTES, BASE_NONE, NULL, 0,
|
||||
"Value", "amqp.field.byte_array",
|
||||
FT_UINT_BYTES, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL}},
|
||||
{&hf_amqp_header_class_id, {
|
||||
"Class ID", "amqp.header.class",
|
||||
|
@ -13552,6 +13605,7 @@ proto_register_amqp(void)
|
|||
&ett_props,
|
||||
&ett_field_table,
|
||||
&ett_amqp_init,
|
||||
&ett_amqp_0_9_field,
|
||||
&ett_amqp_0_10_map,
|
||||
&ett_amqp_0_10_array,
|
||||
&ett_amqp_0_10_struct,
|
||||
|
|
Loading…
Reference in New Issue