forked from osmocom/wireshark
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>
This commit is contained in:
parent
5ae7076b3e
commit
620f5721b1
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue