Skip to content

Commit

Permalink
netlink: let subdissectors handle the netlink header
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Lekensteyn authored and mmann78 committed Apr 9, 2017
1 parent 0add542 commit 92ebd63
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 88 deletions.
49 changes: 27 additions & 22 deletions epan/dissectors/packet-netlink-netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;

if (_data) {
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
data = (struct packet_netlink_data *) _data;
}
proto_tree *nlmsg_tree;
proto_item *pi;
int offset = 0;

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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down
44 changes: 18 additions & 26 deletions epan/dissectors/packet-netlink-route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

if (_data) {
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
data = (struct packet_netlink_data *) _data;
}
struct packet_netlink_data *data = (struct packet_netlink_data *)_data;
proto_tree *nlmsg_tree;
proto_item *pi;
int offset = 0;

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;

Expand All @@ -1005,37 +999,37 @@ 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:
case WS_RTM_DELADDR:
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:
case WS_RTM_DELROUTE:
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:
case WS_RTM_DELNEIGH:
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;
}

Expand Down Expand Up @@ -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);

Expand Down
28 changes: 12 additions & 16 deletions epan/dissectors/packet-netlink-sock_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

if (_data) {
if (((struct packet_netlink_data *) _data)->magic == PACKET_NETLINK_MAGIC)
data = (struct packet_netlink_data *) _data;
}
proto_tree *nlmsg_tree;
proto_item *pi;
int offset = 0;

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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down
Loading

0 comments on commit 92ebd63

Please sign in to comment.