forked from osmocom/wireshark
packet-netlink-net_dm: try to guess the payload type
The kernel unfortunately doesn't indicate which payload type it is. In particular, it might be an Ethernet packet or an IP one, depending on how the SKB has been generated. We work around this issue by guessing if the packet contains the EtherType at the right offset to be an Ethernet packet, and decode accordingly the payload.
This commit is contained in:
parent
45cf6d9d6e
commit
de2a2c5ddb
|
@ -97,6 +97,7 @@ struct netlink_net_dm_info {
|
|||
|
||||
static dissector_handle_t netlink_net_dm_handle;
|
||||
static dissector_table_t sll_ltype_table;
|
||||
static dissector_table_t ethertype_table;
|
||||
|
||||
static int proto_netlink_net_dm = -1;
|
||||
|
||||
|
@ -244,6 +245,8 @@ dissect_net_dm_attrs(tvbuff_t *tvb, void *data, struct packet_netlink_data *nl_d
|
|||
guint64 pc, timestamp;
|
||||
nstime_t ts_nstime;
|
||||
guint32 value;
|
||||
guint16 protocol;
|
||||
static dissector_table_t dissector_table;
|
||||
tvbuff_t *next_tvb;
|
||||
const guint8 *str;
|
||||
|
||||
|
@ -271,17 +274,37 @@ dissect_net_dm_attrs(tvbuff_t *tvb, void *data, struct packet_netlink_data *nl_d
|
|||
return 1;
|
||||
case WS_NET_DM_ATTR_PROTO:
|
||||
info->protocol = tvb_get_guint16(tvb, offset, nl_data->encoding);
|
||||
|
||||
proto_tree_add_item(tree, hf_net_dm_proto, tvb, offset, len, nl_data->encoding);
|
||||
return 1;
|
||||
case WS_NET_DM_ATTR_PAYLOAD:
|
||||
/* This whole payload protocol thing is messed up:
|
||||
* We can't know from the kernel netlink message what we get exacly
|
||||
*/
|
||||
protocol = info->protocol;
|
||||
dissector_table = sll_ltype_table;
|
||||
/* This attribute encodes 'skb->protocol' and if it is greater
|
||||
* than or equal to 1536 (0x0600), then it is an Ethertype and
|
||||
* we need to treat the packet as Ethernet.
|
||||
*/
|
||||
if (info->protocol >= 1536 || info->protocol == LINUX_SLL_P_802_2)
|
||||
info->protocol = LINUX_SLL_P_ETHERNET;
|
||||
proto_tree_add_item(tree, hf_net_dm_proto, tvb, offset, len, nl_data->encoding);
|
||||
return 1;
|
||||
case WS_NET_DM_ATTR_PAYLOAD:
|
||||
if (info->protocol >= 1536 || info->protocol == LINUX_SLL_P_802_2) {
|
||||
/* It might be ethernet, but we're not really sure what the packet actually is.
|
||||
* We try a guess: if two bytes 12-14 match the Ethertype, then it's ethernet,
|
||||
* otherwise we just assume that we have is a payload of the Ethertype itself.
|
||||
* (this is not a perfect match, but in practice gives good enough results)
|
||||
*
|
||||
* If it's too short to be Ethernet, then for sure we don't have an Ethernet payload.
|
||||
*/
|
||||
if (len >= 14 && tvb_get_guint16(tvb, offset + 12, ENC_BIG_ENDIAN) == info->protocol) {
|
||||
protocol = LINUX_SLL_P_ETHERNET;
|
||||
} else {
|
||||
dissector_table = ethertype_table;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
next_tvb = tvb_new_subset_length(tvb, offset, len);
|
||||
if (!dissector_try_uint(sll_ltype_table, info->protocol, next_tvb, info->pinfo, tree))
|
||||
if (!dissector_try_uint(dissector_table, protocol, next_tvb, info->pinfo, tree))
|
||||
call_data_dissector(next_tvb, info->pinfo, tree);
|
||||
return 1;
|
||||
case WS_NET_DM_ATTR_TRUNC_LEN:
|
||||
|
@ -517,6 +540,7 @@ proto_reg_handoff_netlink_net_dm(void)
|
|||
{
|
||||
dissector_add_string("genl.family", "NET_DM", netlink_net_dm_handle);
|
||||
sll_ltype_table = find_dissector_table("sll.ltype");
|
||||
ethertype_table = find_dissector_table("ethertype");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue