Skip to content

Commit

Permalink
genl: make subdissectors responsible for header
Browse files Browse the repository at this point in the history
Allow subdissectors to specify the command field for the Generic Netlink
message header, similar to how Netlink subdissectors handle the Netlink
message header (for its type field).

Pass the root tree instead of the genl tree to subdissectors (so
subdissectors can add their own layer).

Change-Id: I3e56f538661b7e8a51d2411da14d181ead820c4b
Reviewed-on: https://code.wireshark.org/review/21150
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
  • Loading branch information
Lekensteyn authored and mmann78 committed Apr 17, 2017
1 parent 407a2b0 commit 61c5e8e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 21 deletions.
58 changes: 40 additions & 18 deletions epan/dissectors/packet-netlink-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,15 +351,20 @@ dissect_genl_ctrl_attrs(tvbuff_t *tvb, void *data, proto_tree *tree, int nla_typ
return offset;
}

static header_field_info hfi_genl_ctrl_cmd NETLINK_GENERIC_HFI_INIT =
{ "Command", "genl.ctrl.cmd", FT_UINT8, BASE_DEC,
VALS(genl_ctrl_cmds), 0x00, "Generic Netlink command", HFILL };

static header_field_info hfi_genl_ctrl_attr NETLINK_GENERIC_HFI_INIT =
{ "Type", "genl.ctrl_attr", FT_UINT16, BASE_DEC,
VALS(genl_ctrl_attr_vals), NLA_TYPE_MASK, NULL, HFILL };

static int
dissect_genl_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
dissect_genl_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data)
{
genl_info_t *genl_info = (genl_info_t *) data;
genl_ctrl_info_t info;
int offset;

if (!genl_info) {
return 0;
Expand All @@ -370,9 +375,9 @@ dissect_genl_ctrl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void
info.family_id = 0;
info.family_name = NULL;

proto_item_append_text(genl_info->cmd_pi, " (%s)",
val_to_str_const(genl_info->cmd, genl_ctrl_cmds, "Unknown"));
dissect_netlink_attributes(tvb, &hfi_genl_ctrl_attr, ett_genl_ctrl_attr, &info, info.data, tree, 0, -1, dissect_genl_ctrl_attrs);
offset = dissect_genl_header(tvb, genl_info, &hfi_genl_ctrl_cmd);

dissect_netlink_attributes(tvb, &hfi_genl_ctrl_attr, ett_genl_ctrl_attr, &info, info.data, genl_info->genl_tree, offset, -1, dissect_genl_ctrl_attrs);

/*
* Remember association of dynamic ID with the family name such that
Expand Down Expand Up @@ -403,15 +408,31 @@ static header_field_info hfi_genl_reserved NETLINK_GENERIC_HFI_INIT =
{ "Reserved", "genl.reserved", FT_NONE, BASE_NONE,
NULL, 0x00, NULL, HFILL };

int dissect_genl_header(tvbuff_t *tvb, genl_info_t *genl_info, header_field_info *hfi_cmd)
{
int offset = 0;

if (!hfi_cmd) {
hfi_cmd = &hfi_genl_cmd;
}
proto_tree_add_item(genl_info->genl_tree, hfi_cmd, tvb, offset, 1, ENC_NA);
offset++;
proto_tree_add_item(genl_info->genl_tree, &hfi_genl_version, tvb, offset, 1, ENC_NA);
offset++;
proto_tree_add_item(genl_info->genl_tree, &hfi_genl_reserved, tvb, offset, 2, genl_info->encoding);
offset += 2;
return offset;
}

static int
dissect_netlink_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data)
{
struct packet_netlink_data *data = (struct packet_netlink_data *)_data;
genl_info_t info;
proto_tree *nlmsg_tree;
proto_item *pi, *pi_type;
guint32 cmd;
const char *family_name;
tvbuff_t *next_tvb;
int offset = 0;

DISSECTOR_ASSERT(data && data->magic == PACKET_NETLINK_MAGIC);
Expand All @@ -427,30 +448,30 @@ dissect_netlink_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
family_name = (const char *)wmem_map_lookup(genl_family_map, GUINT_TO_POINTER(data->type));
proto_item_append_text(pi_type, " (%s)", family_name ? family_name : "Unknown");

/* Generic Netlink message header (genlmsghdr) */
/* Populate info from Generic Netlink message header (genlmsghdr) */
info.data = data;
info.encoding = data->encoding;
info.cmd_pi = proto_tree_add_item_ret_uint(nlmsg_tree, hfi_genl_cmd.id, tvb, offset, 1, ENC_NA, &cmd);
info.cmd = cmd;
offset++;
proto_tree_add_item(nlmsg_tree, &hfi_genl_version, tvb, offset, 1, ENC_NA);
offset++;
proto_tree_add_item(nlmsg_tree, &hfi_genl_reserved, tvb, offset, 2, ENC_NA);
offset += 2;
info.genl_tree = nlmsg_tree;
info.cmd = tvb_get_guint8(tvb, offset);

/* Optional user-specific message header and optional message payload. */
if (tvb_reported_length_remaining(tvb, offset)) {
tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
next_tvb = tvb_new_subset_remaining(tvb, offset);
/* Try subdissector if there is a payload. */
if (tvb_reported_length_remaining(tvb, offset + 4)) {
if (family_name) {
int ret;
/* XXX should subdissectors add to the top-level tree? */
ret = dissector_try_string(genl_dissector_table, family_name, next_tvb, pinfo, nlmsg_tree, &info);
/* Invoke subdissector with genlmsghdr present. */
ret = dissector_try_string(genl_dissector_table, family_name, next_tvb, pinfo, tree, &info);
if (ret) {
return ret;
}
}
}

/* fallback if no subdissector was found. */
/* No subdissector added the genl header, do it now. */
offset = dissect_genl_header(next_tvb, &info, NULL);
if (tvb_reported_length_remaining(tvb, offset)) {
next_tvb = tvb_new_subset_remaining(tvb, offset);
call_data_dissector(next_tvb, pinfo, tree);
}

Expand All @@ -475,6 +496,7 @@ proto_register_netlink_generic(void)
&hfi_genl_reserved,
&hfi_genl_ctrl_attr,
/* Controller */
&hfi_genl_ctrl_cmd,
&hfi_genl_ctrl_family_id,
&hfi_genl_ctrl_family_name,
&hfi_genl_ctrl_version,
Expand Down
4 changes: 2 additions & 2 deletions epan/dissectors/packet-netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ dissect_netlink_header(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding
proto_tree *fh_hdr;
proto_item *pi;

fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 16, ett_netlink_msghdr, NULL, "Header");
fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 16, ett_netlink_msghdr, NULL, "Netlink message header");

proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_len, tvb, offset, 4, encoding);
offset += 4;
Expand Down Expand Up @@ -497,7 +497,7 @@ dissect_netlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data
*/
proto_tree *fh_hdr;

fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 4, ett_netlink_msghdr, NULL, "Header");
fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 4, ett_netlink_msghdr, NULL, "Netlink message header");

proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_len, tvb, offset, 4, encoding);
/* XXX invalid expert */
Expand Down
6 changes: 5 additions & 1 deletion epan/dissectors/packet-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,13 @@ typedef struct {
struct packet_netlink_data *data;
int encoding; /* copy of data->encoding */

/* For internal use by genl. */
proto_tree *genl_tree;

/* fields from genlmsghdr */
guint8 cmd; /* Command number */
proto_item *cmd_pi; /* Field for command, for appending protocol-specific name. */
} genl_info_t;

int dissect_genl_header(tvbuff_t *tvb, genl_info_t *genl_info, header_field_info *hfi_cmd);

#endif /* __PACKET_NETLINK_H__ */

0 comments on commit 61c5e8e

Please sign in to comment.