diff options
author | Peter Wu <peter@lekensteyn.nl> | 2016-08-11 23:30:06 +0200 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2016-08-13 21:43:23 +0000 |
commit | 620f5721b176ab4cd0cd87ec618925c91664f2ee (patch) | |
tree | e0e41ad25778956aad0e5a3b0fec38c81f0e8462 | |
parent | 5ae7076b3ead0d3c7ae3ad4d9d05d9a89930d848 (diff) | |
download | wireshark-620f5721b176ab4cd0cd87ec618925c91664f2ee.tar.gz |
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>
-rw-r--r-- | epan/dissectors/packet-netlink-netfilter.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink-route.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink-sock_diag.c | 16 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.c | 70 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.h | 6 |
5 files changed, 69 insertions, 33 deletions
diff --git a/epan/dissectors/packet-netlink-netfilter.c b/epan/dissectors/packet-netlink-netfilter.c index c0af8412d3..de80f9bf9c 100644 --- a/epan/dissectors/packet-netlink-netfilter.c +++ b/epan/dissectors/packet-netlink-netfilter.c @@ -310,7 +310,7 @@ dissect_nfq_config_attrs(tvbuff_t *tvb, void *data _U_, proto_tree *tree, int nl static header_field_info hfi_nfq_config_attr NETLINK_NETFILTER_HFI_INIT = { "Type", "netlink-netfilter.queue.config_attr", FT_UINT16, BASE_DEC, - VALS(nfq_config_attr_vals), 0x00, NULL, HFILL }; + VALS(nfq_config_attr_vals), NLA_TYPE_MASK, NULL, HFILL }; /* QUEUE - Packet and verdict */ @@ -592,7 +592,7 @@ dissect_nfq_attrs(tvbuff_t *tvb, void *data _U_, proto_tree *tree, int nla_type, static header_field_info hfi_nfq_attr NETLINK_NETFILTER_HFI_INIT = { "Type", "netlink-netfilter.queue.attr", FT_UINT16, BASE_DEC, - VALS(nfq_attr_vals), 0x00, NULL, HFILL }; + VALS(nfq_attr_vals), NLA_TYPE_MASK, NULL, HFILL }; /* QUEUE - main */ @@ -605,11 +605,11 @@ dissect_netfilter_queue(tvbuff_t *tvb, netlink_netfilter_info_t *info, proto_tre switch (type) { case WS_NFQNL_MSG_CONFIG: - return dissect_netlink_attributes(tvb, &hfi_nfq_config_attr, ett_nfq_config_attr, info, tree, offset, dissect_nfq_config_attrs); + return dissect_netlink_attributes(tvb, &hfi_nfq_config_attr, ett_nfq_config_attr, info, tree, offset, -1, dissect_nfq_config_attrs); case WS_NFQNL_MSG_PACKET: case WS_NFQNL_MSG_VERDICT: - return dissect_netlink_attributes(tvb, &hfi_nfq_attr, ett_nfq_attr, info, tree, offset, dissect_nfq_attrs); + return dissect_netlink_attributes(tvb, &hfi_nfq_attr, ett_nfq_attr, info, tree, offset, -1, dissect_nfq_attrs); case WS_NFQNL_MSG_VERDICT_BATCH: /* TODO */ diff --git a/epan/dissectors/packet-netlink-route.c b/epan/dissectors/packet-netlink-route.c index 968898e1fa..3fb84bff1f 100644 --- a/epan/dissectors/packet-netlink-route.c +++ b/epan/dissectors/packet-netlink-route.c @@ -334,7 +334,7 @@ dissect_netlink_route_attributes(tvbuff_t *tvb, header_field_info *hfi_type, str */ /* XXX, nice */ - return dissect_netlink_attributes(tvb, hfi_type, ett_netlink_route_attr, info, tree, offset, (netlink_attributes_cb_t *) cb); + return dissect_netlink_attributes(tvb, hfi_type, ett_netlink_route_attr, info, tree, offset, -1, (netlink_attributes_cb_t *) cb); } /* Interface */ diff --git a/epan/dissectors/packet-netlink-sock_diag.c b/epan/dissectors/packet-netlink-sock_diag.c index 00c3646501..18d796a11b 100644 --- a/epan/dissectors/packet-netlink-sock_diag.c +++ b/epan/dissectors/packet-netlink-sock_diag.c @@ -350,7 +350,7 @@ static const value_string netlink_sock_diag_unix_attr_vals[] = { static header_field_info hfi_netlink_sock_diag_unix_attr NETLINK_SOCK_DIAG_HFI_INIT = { "Type", "netlink-sock_diag.unix_attr", FT_UINT16, BASE_DEC, - VALS(netlink_sock_diag_unix_attr_vals), 0x00, NULL, HFILL }; + VALS(netlink_sock_diag_unix_attr_vals), NLA_TYPE_MASK, NULL, HFILL }; static header_field_info hfi_netlink_sock_diag_unix_name NETLINK_SOCK_DIAG_HFI_INIT = { "Name", "netlink-sock_diag.unix_name", FT_STRINGZ, STR_ASCII, @@ -442,7 +442,7 @@ dissect_sock_diag_unix_reply(tvbuff_t *tvb, netlink_sock_diag_info_t *info, prot sock_diag_proto_tree_add_cookie(tree, info, tvb, offset); offset += 8; - return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_unix_attr, ett_netlink_sock_diag_attr, info, tree, offset, dissect_netlink_unix_sock_diag_reply_attrs); + return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_unix_attr, ett_netlink_sock_diag_attr, info, tree, offset, -1, dissect_netlink_unix_sock_diag_reply_attrs); } /* AF_UNIX request */ @@ -539,7 +539,7 @@ static const value_string netlink_sock_diag_inet_attr_vals[] = { static header_field_info hfi_netlink_sock_diag_inet_attr NETLINK_SOCK_DIAG_HFI_INIT = { "Type", "netlink-sock_diag.inet_attr", FT_UINT16, BASE_DEC, - VALS(netlink_sock_diag_inet_attr_vals), 0x00, NULL, HFILL }; + VALS(netlink_sock_diag_inet_attr_vals), NLA_TYPE_MASK, NULL, HFILL }; static int dissect_sock_diag_inet_attributes(tvbuff_t *tvb, void *data, proto_tree *tree, int nla_type, int offset, int len) @@ -699,7 +699,7 @@ dissect_sock_diag_inet_reply(tvbuff_t *tvb, netlink_sock_diag_info_t *info, prot proto_tree_add_item(tree, &hfi_netlink_sock_diag_inode, tvb, offset, 4, info->encoding); offset += 4; - return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_inet_attr, ett_netlink_sock_diag_attr, info, tree, offset, dissect_sock_diag_inet_attributes); + return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_inet_attr, ett_netlink_sock_diag_attr, info, tree, offset, -1, dissect_sock_diag_inet_attributes); } /* AF_INET request */ @@ -742,7 +742,7 @@ static const value_string netlink_sock_diag_netlink_vals[] = { static header_field_info hfi_netlink_sock_diag_netlink_attr NETLINK_SOCK_DIAG_HFI_INIT = { "Type", "netlink-sock_diag.netlink_attr", FT_UINT16, BASE_DEC, - VALS(netlink_sock_diag_netlink_vals), 0x00, NULL, HFILL }; + VALS(netlink_sock_diag_netlink_vals), NLA_TYPE_MASK, NULL, HFILL }; static int dissect_sock_diag_netlink_attributes(tvbuff_t *tvb, void *data, proto_tree *tree, int nla_type, int offset, int len) @@ -815,7 +815,7 @@ dissect_sock_diag_netlink_reply(tvbuff_t *tvb, netlink_sock_diag_info_t *info, p sock_diag_proto_tree_add_cookie(tree, info, tvb, offset); offset += 8; - return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_netlink_attr, ett_netlink_sock_diag_attr, info, tree, offset, dissect_sock_diag_netlink_attributes); + return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_netlink_attr, ett_netlink_sock_diag_attr, info, tree, offset, -1, dissect_sock_diag_netlink_attributes); } /* AF_NETLINK request */ @@ -917,7 +917,7 @@ static const value_string netlink_sock_diag_packet_vals[] = { static header_field_info hfi_netlink_sock_diag_packet_attr NETLINK_SOCK_DIAG_HFI_INIT = { "Type", "netlink-sock_diag.netlink_attr", FT_UINT16, BASE_DEC, - VALS(netlink_sock_diag_packet_vals), 0x00, NULL, HFILL }; + VALS(netlink_sock_diag_packet_vals), NLA_TYPE_MASK, NULL, HFILL }; /* AF_PACKET */ @@ -943,7 +943,7 @@ dissect_sock_diag_packet_reply(tvbuff_t *tvb, netlink_sock_diag_info_t *info, pr sock_diag_proto_tree_add_cookie(tree, info, tvb, offset); offset += 8; - return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_packet_attr, ett_netlink_sock_diag_attr, info, tree, offset, dissect_netlink_packet_sock_diag_reply_attrs); + return dissect_netlink_attributes(tvb, &hfi_netlink_sock_diag_packet_attr, ett_netlink_sock_diag_attr, info, tree, offset, -1, dissect_netlink_packet_sock_diag_reply_attrs); } /* AF_PACKET request */ 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; diff --git a/epan/dissectors/packet-netlink.h b/epan/dissectors/packet-netlink.h index 168310cd53..673fd019ad 100644 --- a/epan/dissectors/packet-netlink.h +++ b/epan/dissectors/packet-netlink.h @@ -93,6 +93,10 @@ struct packet_netlink_data { typedef int netlink_attributes_cb_t(tvbuff_t *, void *data, proto_tree *, int nla_type, int offset, int len); -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); +int 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); + +#define NLA_F_NESTED 0x8000 +#define NLA_F_NET_BYTEORDER 0x4000 +#define NLA_TYPE_MASK 0x3fff #endif /* __PACKET_NETLINK_H__ */ |