aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-netlink-generic.c58
-rw-r--r--epan/dissectors/packet-netlink.c4
-rw-r--r--epan/dissectors/packet-netlink.h6
3 files changed, 47 insertions, 21 deletions
diff --git a/epan/dissectors/packet-netlink-generic.c b/epan/dissectors/packet-netlink-generic.c
index 8caa8b18a7..64ae0f1127 100644
--- a/epan/dissectors/packet-netlink-generic.c
+++ b/epan/dissectors/packet-netlink-generic.c
@@ -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;
@@ -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
@@ -403,6 +408,22 @@ 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)
{
@@ -410,8 +431,8 @@ dissect_netlink_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
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);
@@ -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);
}
@@ -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,
diff --git a/epan/dissectors/packet-netlink.c b/epan/dissectors/packet-netlink.c
index 3d73982eea..22cedaa68d 100644
--- a/epan/dissectors/packet-netlink.c
+++ b/epan/dissectors/packet-netlink.c
@@ -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;
@@ -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 */
diff --git a/epan/dissectors/packet-netlink.h b/epan/dissectors/packet-netlink.h
index 12b872e2e7..07e52e9523 100644
--- a/epan/dissectors/packet-netlink.h
+++ b/epan/dissectors/packet-netlink.h
@@ -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__ */