forked from osmocom/wireshark
netlink: add helper for dissecting an array of attributes
From https://wiki.linuxfoundation.org/networking/generic_netlink_howto "Arrays can be represented by using a single nested attribute as a container with several of the same attribute type inside each representing a spot in the array." This patch adds a helper function to dissect such a type (it will be used by Generic Netlink for CTRL_ATTR_OPS and CTRL_ATTR_MCAST_GROUPS). Change-Id: I60537712f7fb0f9d4fb8850c6c8eef590635f49f Reviewed-on: https://code.wireshark.org/review/20903 Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
802479d237
commit
0add542dbf
|
@ -178,6 +178,10 @@ 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_index NETLINK_HFI_INIT =
|
||||
{ "Index", "netlink.attr_index", FT_UINT16, BASE_DEC,
|
||||
NULL, 0x0000, "Netlink Attribute type (array index)", HFILL };
|
||||
|
||||
static header_field_info hfi_netlink_attr_len NETLINK_HFI_INIT =
|
||||
{ "Len", "netlink.attr_len", FT_UINT16, BASE_DEC,
|
||||
NULL, 0x00, NULL, HFILL };
|
||||
|
@ -236,8 +240,8 @@ static const int *netlink_header_standard_flags[] = {
|
|||
};
|
||||
|
||||
|
||||
int
|
||||
dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
||||
static int
|
||||
dissect_netlink_attributes_common(tvbuff_t *tvb, header_field_info *hfi_type, int ett_tree, int ett_attrib, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
||||
{
|
||||
int encoding;
|
||||
int padding = (4 - offset) & 3;
|
||||
|
@ -269,35 +273,49 @@ dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett,
|
|||
/* XXX expert info when rta_len < length? */
|
||||
rta_len = MIN(rta_len, length);
|
||||
|
||||
attr_tree = proto_tree_add_subtree(tree, tvb, offset, rta_len, ett, &ti, "Attribute");
|
||||
attr_tree = proto_tree_add_subtree(tree, tvb, offset, rta_len, ett_tree, &ti, "Attribute");
|
||||
|
||||
proto_tree_add_item(attr_tree, &hfi_netlink_attr_len, tvb, offset, 2, encoding);
|
||||
offset += 2;
|
||||
|
||||
rta_type = tvb_get_guint16(tvb, offset, encoding);
|
||||
type = rta_type & NLA_TYPE_MASK;
|
||||
type_item = proto_tree_add_item(attr_tree, &hfi_netlink_attr_type, tvb, offset, 2, encoding);
|
||||
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, encoding);
|
||||
proto_tree_add_item(type_tree, &hfi_netlink_attr_type_net_byteorder, tvb, offset, 2, encoding);
|
||||
proto_tree_add_item(type_tree, hfi_type, tvb, offset, 2, encoding);
|
||||
offset += 2;
|
||||
if (ett_attrib == -1) {
|
||||
/* List of attributes */
|
||||
type = rta_type & NLA_TYPE_MASK;
|
||||
type_item = proto_tree_add_item(attr_tree, &hfi_netlink_attr_type, tvb, offset, 2, encoding);
|
||||
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, encoding);
|
||||
proto_tree_add_item(type_tree, &hfi_netlink_attr_type_net_byteorder, tvb, offset, 2, encoding);
|
||||
proto_tree_add_item(type_tree, hfi_type, tvb, offset, 2, encoding);
|
||||
offset += 2;
|
||||
|
||||
if (rta_type & NLA_F_NESTED)
|
||||
proto_item_append_text(type_item, ", Nested");
|
||||
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(type, (const value_string *) hfi_type->strings);
|
||||
if (hfi_type->strings) {
|
||||
/* XXX, export hf_try_val_to_str */
|
||||
const char *rta_str = try_val_to_str(type, (const value_string *) hfi_type->strings);
|
||||
|
||||
if (rta_str) {
|
||||
proto_item_append_text(type_item, ", %s (%d)", rta_str, type);
|
||||
proto_item_append_text(ti, ": %s", 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 (!cb(tvb, data, attr_tree, rta_type, offset, rta_len - 4)) {
|
||||
/* not handled */
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Nested attributes, constructing an array (list of
|
||||
* attributes where its type is the array index and its
|
||||
* value is the actual list of interesting attributes).
|
||||
*/
|
||||
proto_tree_add_item(attr_tree, &hfi_netlink_attr_index, tvb, offset, 2, encoding);
|
||||
offset += 2;
|
||||
proto_item_append_text(ti, " %u", rta_type);
|
||||
|
||||
dissect_netlink_attributes(tvb, hfi_type, ett_attrib, data, nl_data, attr_tree, offset, rta_len - 4, cb);
|
||||
}
|
||||
|
||||
/* Assume offset already aligned, next offset is rta_len plus alignment. */
|
||||
|
@ -309,6 +327,19 @@ dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett,
|
|||
return offset;
|
||||
}
|
||||
|
||||
int
|
||||
dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
||||
{
|
||||
return dissect_netlink_attributes_common(tvb, hfi_type, ett, -1, data, nl_data, tree, offset, length, cb);
|
||||
}
|
||||
|
||||
int
|
||||
dissect_netlink_attributes_array(tvbuff_t *tvb, header_field_info *hfi_type, int ett_array, int ett_attrib, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
||||
{
|
||||
DISSECTOR_ASSERT(ett_attrib != -1);
|
||||
return dissect_netlink_attributes_common(tvb, hfi_type, ett_array, ett_attrib, data, nl_data, tree, offset, length, cb);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_netlink_hdr(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding, guint16 *type, guint32 *port_id)
|
||||
{
|
||||
|
@ -525,6 +556,7 @@ proto_register_netlink(void)
|
|||
&hfi_netlink_attr_type,
|
||||
&hfi_netlink_attr_type_nested,
|
||||
&hfi_netlink_attr_type_net_byteorder,
|
||||
&hfi_netlink_attr_index,
|
||||
|
||||
/* Netlink message payloads */
|
||||
&hfi_netlink_error,
|
||||
|
|
|
@ -109,6 +109,14 @@ typedef int netlink_attributes_cb_t(tvbuff_t *, void *data, proto_tree *, int nl
|
|||
|
||||
int dissect_netlink_attributes(tvbuff_t *tvb, header_field_info *hfi_type, int ett, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb);
|
||||
|
||||
/*
|
||||
* Similar to dissect_netlink_attributes, but used to parse nested attributes
|
||||
* that model an array of attributes. The first level (tree ett_array) contains
|
||||
* array elements and its type field is the array index. The next level (tree
|
||||
* ett_attrib) contains attributes (where hfi_type applies).
|
||||
*/
|
||||
int dissect_netlink_attributes_array(tvbuff_t *tvb, header_field_info *hfi_type, int ett_array, int ett_attrib, void *data, struct packet_netlink_data *nl_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
|
||||
|
|
Loading…
Reference in New Issue