forked from osmocom/wireshark
netlink: let subdissectors handle the netlink header
Let subdissectors handle parsing and addition of the Netlink header instead of doing this before calling subdissectors. After this patch: - Protocol filters like "netlink-netfilter" can be used to match packets (previously only a text item was added to the tree). - Subdissectors have more freedom in modifying the type field, so now it shows the correct type directly rather than "Message type: Protocol-specific". - netfilter: the type fields are now actually linked to a tvb, previously it was linked to a NULL tvb. - netfilter: fix unintended rejection of packets (the length should have been added to the offset, otherwise it would fallback to the data dissector). - Now subdissectors will not be called for control messages (so the netlink-conntrack.pcap sample now shows "Netlink" instead of "Netlink route" for the "End of dump" control message). Change-Id: I2ab1bef91fb0080664195b281a6a45c9702914e5 Reviewed-on: https://code.wireshark.org/review/20910 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
0add542dbf
commit
92ebd63892
|
@ -239,6 +239,8 @@ enum ws_ipset_ip_attr {
|
|||
};
|
||||
|
||||
|
||||
static int proto_netlink_netfilter;
|
||||
|
||||
static int ett_netlink_netfilter = -1;
|
||||
static int ett_nfq_config_attr = -1;
|
||||
static int ett_nfq_attr = -1;
|
||||
|
@ -735,11 +737,14 @@ static int
|
|||
dissect_netfilter_ulog(tvbuff_t *tvb, netlink_netfilter_info_t *info, proto_tree *tree, int offset)
|
||||
{
|
||||
enum ws_nfulnl_msg_types type = (enum ws_nfulnl_msg_types) (info->data->type & 0xff);
|
||||
tvbuff_t *next_tvb;
|
||||
|
||||
switch (type) {
|
||||
case WS_NFULNL_MSG_PACKET:
|
||||
/* Note that NFLOG dissects the nfgenmsg header */
|
||||
call_dissector(nflog_handle, tvb, info->pinfo, tree);
|
||||
next_tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
call_dissector(nflog_handle, next_tvb, info->pinfo, tree);
|
||||
offset = tvb_reported_length(tvb);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1117,35 +1122,34 @@ static header_field_info hfi_netlink_netfilter_subsys NETLINK_NETFILTER_HFI_INIT
|
|||
static int
|
||||
dissect_netlink_netfilter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data)
|
||||
{
|
||||
struct packet_netlink_data *data = NULL;
|
||||
struct packet_netlink_data *data = (struct packet_netlink_data *)_data;
|
||||
netlink_netfilter_info_t info;
|
||||
int offset;
|
||||
proto_tree *nlmsg_tree;
|
||||
proto_item *pi;
|
||||
int offset = 0;
|
||||
|
||||
if (_data) {
|
||||
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
|
||||
data = (struct packet_netlink_data *) _data;
|
||||
}
|
||||
|
||||
DISSECTOR_ASSERT(data);
|
||||
DISSECTOR_ASSERT(data && data->magic == PACKET_NETLINK_MAGIC);
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netlink netfilter");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
proto_item_set_text(tree, "Linux netlink netfilter message");
|
||||
pi = proto_tree_add_item(tree, proto_registrar_get_nth(proto_netlink_netfilter), tvb, 0, -1, ENC_NA);
|
||||
nlmsg_tree = proto_item_add_subtree(pi, ett_netlink_netfilter);
|
||||
|
||||
/* XXX, from header tvb */
|
||||
proto_tree_add_uint(tree, &hfi_netlink_netfilter_subsys, NULL, 0, 0, data->type);
|
||||
/* Netlink message header (nlmsghdr) */
|
||||
offset = dissect_netlink_header(tvb, nlmsg_tree, offset, data->encoding, NULL, NULL);
|
||||
proto_tree_add_item(nlmsg_tree, &hfi_netlink_netfilter_subsys, tvb, 4, 2, data->encoding);
|
||||
switch (data->type >> 8) {
|
||||
case WS_NFNL_SUBSYS_QUEUE:
|
||||
proto_tree_add_uint(tree, &hfi_nfq_type, NULL, 0, 0, data->type);
|
||||
proto_tree_add_item(nlmsg_tree, &hfi_nfq_type, tvb, 4, 2, data->encoding);
|
||||
break;
|
||||
|
||||
case WS_NFNL_SUBSYS_ULOG:
|
||||
proto_tree_add_uint(tree, &hfi_netlink_netfilter_ulog_type, NULL, 0, 0, data->type);
|
||||
proto_tree_add_item(nlmsg_tree, &hfi_netlink_netfilter_ulog_type, tvb, 4, 2, data->encoding);
|
||||
break;
|
||||
|
||||
case WS_NFNL_SUBSYS_IPSET:
|
||||
proto_tree_add_uint(tree, &hfi_ipset_command, NULL, 0, 0, data->type);
|
||||
proto_tree_add_item(nlmsg_tree, &hfi_ipset_command, tvb, 4, 2, data->encoding);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1154,19 +1158,22 @@ dissect_netlink_netfilter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v
|
|||
info.data = data;
|
||||
info.hw_protocol = 0;
|
||||
|
||||
offset = 0;
|
||||
|
||||
switch (data->type >> 8) {
|
||||
case WS_NFNL_SUBSYS_QUEUE:
|
||||
offset = dissect_netfilter_queue(tvb, &info, tree, offset);
|
||||
offset = dissect_netfilter_queue(tvb, &info, nlmsg_tree, offset);
|
||||
break;
|
||||
|
||||
case WS_NFNL_SUBSYS_ULOG:
|
||||
offset = dissect_netfilter_ulog(tvb, &info, tree, offset);
|
||||
offset = dissect_netfilter_ulog(tvb, &info, nlmsg_tree, offset);
|
||||
break;
|
||||
|
||||
case WS_NFNL_SUBSYS_IPSET:
|
||||
offset = dissect_netfilter_ipset(tvb, &info, tree, offset);
|
||||
offset = dissect_netfilter_ipset(tvb, &info, nlmsg_tree, offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, nlmsg_tree);
|
||||
offset = tvb_reported_length(tvb);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1242,8 +1249,6 @@ proto_register_netlink_netfilter(void)
|
|||
&ett_ipset_ip_attr,
|
||||
};
|
||||
|
||||
int proto_netlink_netfilter;
|
||||
|
||||
proto_netlink_netfilter = proto_register_protocol("Linux netlink netfilter protocol", "netfilter", "netlink-netfilter" );
|
||||
hfi_netlink_netfilter = proto_registrar_get_nth(proto_netlink_netfilter);
|
||||
|
||||
|
|
|
@ -287,6 +287,8 @@ enum {
|
|||
WS_NUD_PERMANENT = 0x80
|
||||
};
|
||||
|
||||
static int proto_netlink_route;
|
||||
|
||||
static dissector_handle_t netlink_route_handle;
|
||||
|
||||
static header_field_info *hfi_netlink_route = NULL;
|
||||
|
@ -970,32 +972,24 @@ static header_field_info hfi_netlink_route_nltype NETLINK_ROUTE_HFI_INIT =
|
|||
static int
|
||||
dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data)
|
||||
{
|
||||
int offset;
|
||||
|
||||
struct netlink_route_info info;
|
||||
struct packet_netlink_data *data = NULL;
|
||||
struct packet_netlink_data *data = (struct packet_netlink_data *)_data;
|
||||
proto_tree *nlmsg_tree;
|
||||
proto_item *pi;
|
||||
int offset = 0;
|
||||
|
||||
if (_data) {
|
||||
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
|
||||
data = (struct packet_netlink_data *) _data;
|
||||
}
|
||||
|
||||
DISSECTOR_ASSERT(data);
|
||||
DISSECTOR_ASSERT(data && data->magic == PACKET_NETLINK_MAGIC);
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netlink route");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
offset = 0;
|
||||
pi = proto_tree_add_item(tree, proto_registrar_get_nth(proto_netlink_route), tvb, 0, -1, ENC_NA);
|
||||
nlmsg_tree = proto_item_add_subtree(pi, ett_netlink_route);
|
||||
|
||||
if (tree) {
|
||||
proto_item_set_text(tree, "Linux rtnetlink (route netlink) message");
|
||||
|
||||
/* XXX, from header tvb */
|
||||
proto_tree_add_uint(tree, &hfi_netlink_route_nltype, NULL, 0, 0, data->type);
|
||||
}
|
||||
/* Netlink message header (nlmsghdr) */
|
||||
offset = dissect_netlink_header(tvb, nlmsg_tree, offset, data->encoding, &hfi_netlink_route_nltype, NULL);
|
||||
|
||||
info.encoding = data->encoding;
|
||||
|
||||
info.pinfo = pinfo;
|
||||
info.data = data;
|
||||
|
||||
|
@ -1005,9 +999,9 @@ dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
|
|||
case WS_RTM_GETLINK:
|
||||
/* backward compatibility with legacy tools; 16 is sizeof(struct ifinfomsg) */
|
||||
info.legacy = (data->type == WS_RTM_GETLINK) && (tvb_reported_length_remaining(tvb, offset) < 16);
|
||||
offset = dissect_netlink_route_ifinfomsg(tvb, &info, tree, offset);
|
||||
offset = dissect_netlink_route_ifinfomsg(tvb, &info, nlmsg_tree, offset);
|
||||
/* Optional attributes */
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_ifla_attr_type, &info, tree, offset, dissect_netlink_route_ifla_attrs);
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_ifla_attr_type, &info, nlmsg_tree, offset, dissect_netlink_route_ifla_attrs);
|
||||
break;
|
||||
|
||||
case WS_RTM_NEWADDR:
|
||||
|
@ -1015,9 +1009,9 @@ dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
|
|||
case WS_RTM_GETADDR:
|
||||
/* backward compatibility with legacy tools; 8 is sizeof(struct ifaddrmsg) */
|
||||
info.legacy = (data->type == WS_RTM_GETADDR) && (tvb_reported_length_remaining(tvb, offset) < 8);
|
||||
offset = dissect_netlink_route_ifaddrmsg(tvb, &info, tree, offset);
|
||||
offset = dissect_netlink_route_ifaddrmsg(tvb, &info, nlmsg_tree, offset);
|
||||
/* Optional attributes */
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_ifa_attr_type, &info, tree, offset, dissect_netlink_route_ifa_attrs);
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_ifa_attr_type, &info, nlmsg_tree, offset, dissect_netlink_route_ifa_attrs);
|
||||
break;
|
||||
|
||||
case WS_RTM_NEWROUTE:
|
||||
|
@ -1025,9 +1019,9 @@ dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
|
|||
case WS_RTM_GETROUTE:
|
||||
/* backward compatibility with legacy tools; 12 is sizeof(struct rtmsg) */
|
||||
info.legacy = (data->type == WS_RTM_GETROUTE) && (tvb_reported_length_remaining(tvb, offset) < 12);
|
||||
offset = dissect_netlink_route_rtmsg(tvb, &info, tree, offset);
|
||||
offset = dissect_netlink_route_rtmsg(tvb, &info, nlmsg_tree, offset);
|
||||
/* Optional attributes */
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_rta_attr_type, &info, tree, offset, dissect_netlink_route_route_attrs);
|
||||
offset = dissect_netlink_route_attributes(tvb, &hfi_netlink_route_rta_attr_type, &info, nlmsg_tree, offset, dissect_netlink_route_route_attrs);
|
||||
break;
|
||||
|
||||
case WS_RTM_NEWNEIGH:
|
||||
|
@ -1035,7 +1029,7 @@ dissect_netlink_route(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
|
|||
case WS_RTM_GETNEIGH:
|
||||
/* backward compatibility with legacy tools; 12 is sizeof(struct ndmsg) */
|
||||
info.legacy = (data->type == WS_RTM_GETNEIGH) && (tvb_reported_length_remaining(tvb, offset) < 12);
|
||||
offset = dissect_netlink_route_ndmsg(tvb, &info, tree, offset);
|
||||
offset = dissect_netlink_route_ndmsg(tvb, &info, nlmsg_tree, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1103,8 +1097,6 @@ proto_register_netlink_route(void)
|
|||
&ett_netlink_route_if_flags
|
||||
};
|
||||
|
||||
int proto_netlink_route;
|
||||
|
||||
proto_netlink_route = proto_register_protocol("Linux rtnetlink (route netlink) protocol", "rtnetlink", "netlink-route" );
|
||||
hfi_netlink_route = proto_registrar_get_nth(proto_netlink_route);
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ typedef struct {
|
|||
int encoding; /* copy of data->encoding */
|
||||
} netlink_sock_diag_info_t;
|
||||
|
||||
static int proto_netlink_sock_diag;
|
||||
|
||||
static dissector_handle_t netlink_sock_diag_handle;
|
||||
|
||||
static header_field_info *hfi_netlink_sock_diag = NULL;
|
||||
|
@ -1103,26 +1105,22 @@ static header_field_info hfi_netlink_sock_diag_nltype NETLINK_SOCK_DIAG_HFI_INIT
|
|||
static int
|
||||
dissect_netlink_sock_diag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data)
|
||||
{
|
||||
struct packet_netlink_data *data = NULL;
|
||||
struct packet_netlink_data *data = (struct packet_netlink_data *)_data;
|
||||
netlink_sock_diag_info_t info;
|
||||
int offset;
|
||||
proto_tree *nlmsg_tree;
|
||||
proto_item *pi;
|
||||
int offset = 0;
|
||||
|
||||
if (_data) {
|
||||
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
|
||||
data = (struct packet_netlink_data *) _data;
|
||||
}
|
||||
|
||||
DISSECTOR_ASSERT(data);
|
||||
DISSECTOR_ASSERT(data && data->magic == PACKET_NETLINK_MAGIC);
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netlink sock diag");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
if (tree) {
|
||||
proto_item_set_text(tree, "Linux netlink sock diag message");
|
||||
pi = proto_tree_add_item(tree, proto_registrar_get_nth(proto_netlink_sock_diag), tvb, 0, -1, ENC_NA);
|
||||
nlmsg_tree = proto_item_add_subtree(pi, ett_netlink_sock_diag);
|
||||
|
||||
/* XXX, from header tvb */
|
||||
proto_tree_add_uint(tree, &hfi_netlink_sock_diag_nltype, NULL, 0, 0, data->type);
|
||||
}
|
||||
/* Netlink message header (nlmsghdr) */
|
||||
offset = dissect_netlink_header(tvb, nlmsg_tree, offset, data->encoding, &hfi_netlink_sock_diag_nltype, NULL);
|
||||
|
||||
info.encoding = data->encoding;
|
||||
info.pinfo = pinfo;
|
||||
|
@ -1137,7 +1135,7 @@ dissect_netlink_sock_diag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v
|
|||
break;
|
||||
|
||||
case WS_SOCK_DIAG_BY_FAMILY:
|
||||
offset = dissect_sock_diag_by_family(tvb, &info, tree, offset);
|
||||
offset = dissect_sock_diag_by_family(tvb, &info, nlmsg_tree, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1221,8 +1219,6 @@ proto_register_netlink_sock_diag(void)
|
|||
&ett_netlink_sock_diag_attr
|
||||
};
|
||||
|
||||
int proto_netlink_sock_diag;
|
||||
|
||||
proto_netlink_sock_diag = proto_register_protocol("Linux netlink sock diag protocol", "sock_diag", "netlink-sock_diag" );
|
||||
hfi_netlink_sock_diag = proto_registrar_get_nth(proto_netlink_sock_diag);
|
||||
|
||||
|
|
|
@ -340,27 +340,43 @@ dissect_netlink_attributes_array(tvbuff_t *tvb, header_field_info *hfi_type, int
|
|||
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)
|
||||
int
|
||||
dissect_netlink_header(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding, header_field_info *hfi_type, proto_item **pi_type)
|
||||
{
|
||||
guint16 hdr_flags;
|
||||
guint16 hdr_type;
|
||||
|
||||
proto_tree *fh_hdr;
|
||||
proto_item *pi_type;
|
||||
proto_item *pi;
|
||||
|
||||
fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 16, ett_netlink_msghdr, NULL, "Header");
|
||||
|
||||
proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_len, tvb, offset, 4, encoding);
|
||||
offset += 4;
|
||||
|
||||
pi_type = proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_type, tvb, offset, 2, encoding);
|
||||
hdr_type = tvb_get_guint16(tvb, offset, encoding);
|
||||
if (hdr_type >= WS_NLMSG_MIN_TYPE) {
|
||||
proto_item_set_text(pi_type, "Message type: Protocol-specific (0x%04x)", hdr_type);
|
||||
if (hdr_type < WS_NLMSG_MIN_TYPE) {
|
||||
/* Reserved control messages. */
|
||||
hfi_type = &hfi_netlink_hdr_type;
|
||||
pi = proto_tree_add_item(fh_hdr, hfi_type, tvb, offset, 2, encoding);
|
||||
} else {
|
||||
if (hfi_type) {
|
||||
pi = proto_tree_add_item(fh_hdr, hfi_type, tvb, offset, 2, encoding);
|
||||
} else {
|
||||
hfi_type = &hfi_netlink_hdr_type;
|
||||
pi = proto_tree_add_item(fh_hdr, hfi_type, tvb, offset, 2, encoding);
|
||||
proto_item_set_text(pi, "Message type: Protocol-specific (0x%04x)", hdr_type);
|
||||
}
|
||||
}
|
||||
if (type) {
|
||||
*type = hdr_type;
|
||||
if (pi_type) {
|
||||
*pi_type = pi;
|
||||
}
|
||||
/* TODO export hf_try_val_to_str? */
|
||||
if (hfi_type->strings && hfi_type->display & BASE_EXT_STRING) {
|
||||
proto_item_append_text(fh_hdr, " (type: %s)", val_to_str_ext(hdr_type, (value_string_ext *)hfi_type->strings, "0x%04x"));
|
||||
} else if (hfi_type->strings) {
|
||||
proto_item_append_text(fh_hdr, " (type: %s)", val_to_str(hdr_type, (const value_string *)hfi_type->strings, "0x%04x"));
|
||||
} else {
|
||||
proto_item_append_text(fh_hdr, " (type: 0x%04x)", hdr_type);
|
||||
}
|
||||
offset += 2;
|
||||
|
||||
|
@ -382,7 +398,7 @@ dissect_netlink_hdr(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding, g
|
|||
proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_seq, tvb, offset, 4, encoding);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item_ret_uint(fh_hdr, hfi_netlink_hdr_pid.id, tvb, offset, 4, encoding, port_id);
|
||||
proto_tree_add_item(fh_hdr, &hfi_netlink_hdr_pid, tvb, offset, 4, encoding);
|
||||
offset += 4;
|
||||
|
||||
return offset;
|
||||
|
@ -403,7 +419,7 @@ dissect_netlink_error(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding)
|
|||
proto_tree_add_item(tree, &hfi_netlink_error, tvb, offset, 4, encoding);
|
||||
offset += 4;
|
||||
|
||||
dissect_netlink_hdr(tvb, tree, offset, encoding, NULL, NULL);
|
||||
dissect_netlink_header(tvb, tree, offset, encoding, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -462,21 +478,17 @@ dissect_netlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data
|
|||
}
|
||||
|
||||
while (tvb_reported_length_remaining(tvb, offset) >= 16) {
|
||||
struct packet_netlink_data data;
|
||||
|
||||
int pkt_end_offset;
|
||||
guint16 msg_type;
|
||||
guint32 pkt_len;
|
||||
guint32 port_id;
|
||||
|
||||
proto_tree *fh_msg;
|
||||
|
||||
gboolean dissected = FALSE;
|
||||
|
||||
pkt_len = tvb_get_guint32(tvb, offset, encoding);
|
||||
|
||||
pkt_end_offset = offset + pkt_len;
|
||||
|
||||
fh_msg = proto_tree_add_subtree(tree, tvb, offset, pkt_len, ett_netlink_msg, NULL, "Netlink message");
|
||||
|
||||
if (pkt_len < 16) {
|
||||
/*
|
||||
* This field includes the length of the 16-byte header,
|
||||
|
@ -492,7 +504,9 @@ dissect_netlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data
|
|||
break;
|
||||
}
|
||||
|
||||
offset = dissect_netlink_hdr(tvb, fh_msg, offset, encoding, &data.type, &port_id);
|
||||
/* message type field comes after length field. */
|
||||
msg_type = tvb_get_guint16(tvb, offset + 4, encoding);
|
||||
port_id = tvb_get_guint32(tvb, offset + 12, encoding);
|
||||
|
||||
/* XXX */
|
||||
if (port_id == 0x00)
|
||||
|
@ -500,17 +514,37 @@ dissect_netlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *_data
|
|||
else
|
||||
pinfo->p2p_dir = P2P_DIR_RECV; /* userspace or kernel -> userspace */
|
||||
|
||||
if (data.type == WS_NLMSG_ERROR) {
|
||||
dissect_netlink_error(tvb, fh_msg, offset, encoding);
|
||||
} else if (pkt_len > 16) {
|
||||
/*
|
||||
* Try to invoke subdissectors for non-control messages.
|
||||
*/
|
||||
if (msg_type >= WS_NLMSG_MIN_TYPE && pkt_len > 16) {
|
||||
struct packet_netlink_data data;
|
||||
|
||||
data.magic = PACKET_NETLINK_MAGIC;
|
||||
data.encoding = encoding;
|
||||
data.type = msg_type;
|
||||
|
||||
next_tvb = tvb_new_subset_length(tvb, offset, pkt_len-16);
|
||||
next_tvb = tvb_new_subset_length(tvb, offset, pkt_len);
|
||||
|
||||
if (!dissector_try_uint_new(netlink_dissector_table, protocol, next_tvb, pinfo, fh_msg, TRUE, &data))
|
||||
if (dissector_try_uint_new(netlink_dissector_table, protocol, next_tvb, pinfo, tree, TRUE, &data)) {
|
||||
dissected = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dissected) {
|
||||
/*
|
||||
* No subdissector was called, add a new layer with the
|
||||
* header and the payload. Note that pkt_len>=16.
|
||||
*/
|
||||
fh_msg = proto_tree_add_subtree(tree, tvb, offset, pkt_len, ett_netlink_msg, NULL, "Netlink message");
|
||||
offset = dissect_netlink_header(tvb, fh_msg, offset, encoding, NULL, NULL);
|
||||
|
||||
if (msg_type == WS_NLMSG_ERROR) {
|
||||
dissect_netlink_error(tvb, fh_msg, offset, encoding);
|
||||
} else if (pkt_len > 16) {
|
||||
next_tvb = tvb_new_subset_length(tvb, offset, pkt_len - 16);
|
||||
call_data_dissector(next_tvb, pinfo, fh_msg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
offset = pkt_end_offset;
|
||||
|
|
|
@ -105,6 +105,12 @@ struct packet_netlink_data {
|
|||
guint16 type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dissects the Netlink message header (struct nlmsghdr). The "hfi_type" field
|
||||
* is added for the "nlmsg_type" field and returned into pi_type.
|
||||
*/
|
||||
int dissect_netlink_header(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding, header_field_info *hfi_type, proto_item **pi_type);
|
||||
|
||||
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, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb);
|
||||
|
|
Loading…
Reference in New Issue