aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-netlink.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-08-11 23:30:06 +0200
committerMichael Mann <mmann78@netscape.net>2016-08-13 21:43:23 +0000
commit620f5721b176ab4cd0cd87ec618925c91664f2ee (patch)
treee0e41ad25778956aad0e5a3b0fec38c81f0e8462 /epan/dissectors/packet-netlink.c
parent5ae7076b3ead0d3c7ae3ad4d9d05d9a89930d848 (diff)
netlink: fully dissect NLA Type, add length restriction
NLA types consist of a type and two flags, add new fields for this. Add a new parameter to restrict the data consumed by the dissect_netlink_attributes function, this is needed when implementing nested attributes using another call to this function. This also avoids adding padding to the payload and matches the comment in include/uapi/linux/netlink.h (Linux 4.7). Change-Id: I34dbfa466081b6c6c4580941aff568bd120b4210 Reviewed-on: https://code.wireshark.org/review/17030 Reviewed-by: Peter Wu <peter@lekensteyn.nl> Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-netlink.c')
-rw-r--r--epan/dissectors/packet-netlink.c70
1 files changed, 51 insertions, 19 deletions
diff --git a/epan/dissectors/packet-netlink.c b/epan/dissectors/packet-netlink.c
index 9548da798a..ca9a3c5fe4 100644
--- a/epan/dissectors/packet-netlink.c
+++ b/epan/dissectors/packet-netlink.c
@@ -166,6 +166,18 @@ static header_field_info hfi_netlink_hdr_pid NETLINK_HFI_INIT =
{ "Port ID", "netlink.hdr_pid", FT_UINT32, BASE_DEC,
NULL, 0x00, "Sender port ID", HFILL };
+static header_field_info hfi_netlink_attr_type NETLINK_HFI_INIT =
+ { "Type", "netlink.attr_type", FT_UINT16, BASE_HEX,
+ NULL, 0x0000, "Netlink Attribute type", HFILL };
+
+static header_field_info hfi_netlink_attr_type_nested NETLINK_HFI_INIT =
+ { "Nested", "netlink.attr_type.nested", FT_UINT16, BASE_DEC,
+ NULL, NLA_F_NESTED, "Carries nested attributes", HFILL };
+
+static header_field_info hfi_netlink_attr_type_net_byteorder NETLINK_HFI_INIT =
+ { "Network byte order", "netlink.attr_type.net_byteorder", FT_UINT16, BASE_DEC,
+ NULL, NLA_F_NET_BYTEORDER, "Payload stored in network byte order", HFILL };
+
static header_field_info hfi_netlink_attr_len NETLINK_HFI_INIT =
{ "Len", "netlink.attr_len", FT_UINT16, BASE_DEC,
NULL, 0x00, NULL, HFILL };
@@ -179,6 +191,7 @@ static gint ett_netlink_cooked = -1;
static gint ett_netlink_msghdr = -1;
static gint ett_netlink_msg = -1;
static gint ett_netlink_hdr_flags = -1;
+static gint ett_netlink_attr_type = -1;
static dissector_table_t netlink_dissector_table;
@@ -214,17 +227,23 @@ static const int *netlink_header_new_flags[] = {
int
-dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, proto_tree *tree, int offset, netlink_attributes_cb_t cb)
+dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
{
+ int padding = (4 - offset) & 3;
+
/* align to 4 */
- offset = (offset + 3) & ~3;
+ offset += padding;
+ if (length == -1) {
+ length = tvb_captured_length_remaining(tvb, offset);
+ } else {
+ length -= padding;
+ }
- while (tvb_captured_length_remaining(tvb, offset) >= 4) {
- guint16 rta_len, rta_type;
- int end_offset;
+ while (length >= 4) {
+ guint16 rta_len, rta_type, type;
- proto_item *ti;
- proto_tree *attr_tree;
+ proto_item *ti, *type_item;
+ proto_tree *attr_tree, *type_tree;
rta_len = tvb_get_letohs(tvb, offset);
if (rta_len < 4) {
@@ -232,35 +251,44 @@ dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett,
break;
}
- end_offset = (offset + rta_len + 3) & ~3;
- /* Padding could be missing from the last attribute. */
- end_offset = MIN(end_offset, (int)tvb_captured_length(tvb));
+ /* XXX expert info when rta_len < length? */
+ rta_len = MIN(rta_len, length);
- attr_tree = proto_tree_add_subtree(tree, tvb, offset, end_offset - offset, ett, &ti, "Attribute");
+ attr_tree = proto_tree_add_subtree(tree, tvb, offset, rta_len, ett, &ti, "Attribute");
proto_tree_add_item(attr_tree, &hfi_netlink_attr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
rta_type = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(attr_tree, hfi_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ type = rta_type & NLA_TYPE_MASK;
+ type_item = proto_tree_add_item(attr_tree, &hfi_netlink_attr_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ type_tree = proto_item_add_subtree(type_item, ett_netlink_attr_type);
+ proto_tree_add_item(type_tree, &hfi_netlink_attr_type_nested, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(type_tree, &hfi_netlink_attr_type_net_byteorder, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(type_tree, hfi_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
+ if (rta_type & NLA_F_NESTED)
+ proto_item_append_text(type_item, ", Nested");
+
if (hfi_type->strings) {
/* XXX, export hf_try_val_to_str */
- const char *rta_str = try_val_to_str(rta_type, (const value_string *) hfi_type->strings);
+ const char *rta_str = try_val_to_str(type, (const value_string *) hfi_type->strings);
- if (rta_str)
+ if (rta_str) {
+ proto_item_append_text(type_item, ", %s (%d)", rta_str, type);
proto_item_append_text(ti, ": %s", rta_str);
+ }
}
if (!cb(tvb, data, attr_tree, rta_type, offset, rta_len - 4)) {
/* not handled */
}
- if (end_offset <= offset)
- break;
-
- offset = end_offset;
+ /* Assume offset already aligned, next offset is rta_len plus alignment. */
+ rta_len = MIN((rta_len + 3) & ~3, length);
+ offset += rta_len - 4; /* Header was already skipped */
+ length -= rta_len;
}
return offset;
@@ -439,6 +467,9 @@ proto_register_netlink(void)
/* Netlink message attribute */
&hfi_netlink_attr_len,
+ &hfi_netlink_attr_type,
+ &hfi_netlink_attr_type_nested,
+ &hfi_netlink_attr_type_net_byteorder,
/* Netlink message payloads */
&hfi_netlink_error,
@@ -449,7 +480,8 @@ proto_register_netlink(void)
&ett_netlink_cooked,
&ett_netlink_msghdr,
&ett_netlink_msg,
- &ett_netlink_hdr_flags
+ &ett_netlink_hdr_flags,
+ &ett_netlink_attr_type,
};
int proto_netlink;