diff options
-rw-r--r-- | epan/dissectors/packet-netlink-generic.c | 58 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-netlink.h | 6 |
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__ */ |