2013-12-08 12:01:32 +00:00
|
|
|
/* packet-netlink.c
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-12 11:23:27 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2013-12-08 12:01:32 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* http://www.tcpdump.org/linktypes/LINKTYPE_NETLINK.html */
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <epan/packet.h>
|
2014-12-20 21:23:59 +00:00
|
|
|
#include <epan/arptypes.h>
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
#include <epan/exceptions.h>
|
2013-12-08 12:01:32 +00:00
|
|
|
#include <wiretap/wtap.h>
|
2021-06-16 09:01:23 +00:00
|
|
|
#include <wsutil/ws_roundup.h>
|
2013-12-08 12:01:32 +00:00
|
|
|
|
|
|
|
#include "packet-netlink.h"
|
|
|
|
|
2013-12-13 22:34:10 +00:00
|
|
|
void proto_register_netlink(void);
|
|
|
|
void proto_reg_handoff_netlink(void);
|
|
|
|
|
2013-12-08 12:01:32 +00:00
|
|
|
/*
|
|
|
|
* A DLT_LINUX_SLL fake link-layer header.
|
|
|
|
*/
|
|
|
|
#define SLL_HEADER_SIZE 16 /* total header length */
|
|
|
|
|
2013-12-13 00:51:30 +00:00
|
|
|
static const value_string netlink_family_vals[] = {
|
2016-08-06 14:42:19 +00:00
|
|
|
{ WS_NETLINK_ROUTE, "Route" },
|
|
|
|
{ WS_NETLINK_UNUSED, "Unused" },
|
|
|
|
{ WS_NETLINK_USERSOCK, "User-mode socket protocols" },
|
|
|
|
{ WS_NETLINK_FIREWALL, "Unused (formerly: ip_queue)" },
|
|
|
|
{ WS_NETLINK_SOCK_DIAG, "Socket monitoring" },
|
|
|
|
{ WS_NETLINK_NFLOG, "Netfilter ULOG" },
|
|
|
|
{ WS_NETLINK_XFRM, "IPsec" },
|
|
|
|
{ WS_NETLINK_SELINUX, "SELinux events" },
|
|
|
|
{ WS_NETLINK_ISCSI, "Open-iSCSI" },
|
|
|
|
{ WS_NETLINK_AUDIT, "Auditing" },
|
2014-10-04 15:28:35 +00:00
|
|
|
{ WS_NETLINK_FIB_LOOKUP, "FIB lookup" },
|
2016-08-06 14:42:19 +00:00
|
|
|
{ WS_NETLINK_CONNECTOR, "Kernel connector" },
|
|
|
|
{ WS_NETLINK_NETFILTER, "Netfilter" },
|
|
|
|
{ WS_NETLINK_IP6_FW, "Unused (formerly: ip6_queue)" },
|
|
|
|
{ WS_NETLINK_DNRTMSG, "DECnet routing messages" },
|
|
|
|
{ WS_NETLINK_KOBJECT_UEVENT, "Kernel messages to userspace" },
|
|
|
|
{ WS_NETLINK_GENERIC, "Generic" },
|
2014-10-04 15:28:35 +00:00
|
|
|
{ WS_NETLINK_SCSITRANSPORT, "SCSI Transports" },
|
2016-08-06 14:42:19 +00:00
|
|
|
{ WS_NETLINK_ECRYPTFS, "ecryptfs" },
|
|
|
|
{ WS_NETLINK_RDMA, "RDMA" },
|
|
|
|
{ WS_NETLINK_CRYPTO, "Crypto layer" },
|
2019-12-27 22:36:56 +00:00
|
|
|
{ WS_NETLINK_SMC, "SMC monitoring" },
|
2013-12-08 12:01:32 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2013-12-13 00:51:30 +00:00
|
|
|
value_string_ext netlink_family_vals_ext = VALUE_STRING_EXT_INIT(netlink_family_vals);
|
|
|
|
|
2013-12-08 19:30:33 +00:00
|
|
|
static const value_string type_vals[] = {
|
2016-08-06 14:42:19 +00:00
|
|
|
{ WS_NLMSG_NOOP, "Nothing" },
|
|
|
|
{ WS_NLMSG_ERROR, "Error" },
|
|
|
|
{ WS_NLMSG_DONE, "End of a dump" },
|
|
|
|
{ WS_NLMSG_OVERRUN, "Data lost" },
|
2013-12-08 19:30:33 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2015-06-08 20:24:17 +00:00
|
|
|
static const value_string ha_types[] = {
|
|
|
|
{ ARPHRD_NETLINK, "Netlink" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2016-08-08 12:51:38 +00:00
|
|
|
extern value_string_ext linux_negative_errno_vals_ext;
|
|
|
|
|
2013-12-08 12:01:32 +00:00
|
|
|
static dissector_handle_t netlink_handle;
|
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
static int proto_netlink = -1;
|
|
|
|
|
|
|
|
static int hf_netlink_attr_data = -1;
|
|
|
|
static int hf_netlink_attr_index = -1;
|
|
|
|
static int hf_netlink_attr_len = -1;
|
|
|
|
static int hf_netlink_attr_type = -1;
|
|
|
|
static int hf_netlink_attr_type_nested = -1;
|
|
|
|
static int hf_netlink_attr_type_net_byteorder = -1;
|
|
|
|
static int hf_netlink_error = -1;
|
|
|
|
static int hf_netlink_family = -1;
|
|
|
|
static int hf_netlink_hatype = -1;
|
|
|
|
static int hf_netlink_hdr_flag_ack = -1;
|
|
|
|
static int hf_netlink_hdr_flag_append = -1;
|
|
|
|
static int hf_netlink_hdr_flag_atomic = -1;
|
|
|
|
static int hf_netlink_hdr_flag_create = -1;
|
|
|
|
static int hf_netlink_hdr_flag_dumpfiltered = -1;
|
|
|
|
static int hf_netlink_hdr_flag_dumpintr = -1;
|
|
|
|
static int hf_netlink_hdr_flag_echo = -1;
|
|
|
|
static int hf_netlink_hdr_flag_excl = -1;
|
|
|
|
static int hf_netlink_hdr_flag_match = -1;
|
|
|
|
static int hf_netlink_hdr_flag_multi = -1;
|
|
|
|
static int hf_netlink_hdr_flag_replace = -1;
|
|
|
|
static int hf_netlink_hdr_flag_request = -1;
|
|
|
|
static int hf_netlink_hdr_flag_root = -1;
|
|
|
|
static int hf_netlink_hdr_flags = -1;
|
|
|
|
static int hf_netlink_hdr_len = -1;
|
|
|
|
static int hf_netlink_hdr_pid = -1;
|
|
|
|
static int hf_netlink_hdr_seq = -1;
|
|
|
|
static int hf_netlink_hdr_type = -1;
|
2016-08-06 14:42:19 +00:00
|
|
|
|
2013-12-08 12:01:32 +00:00
|
|
|
static gint ett_netlink_cooked = -1;
|
|
|
|
static gint ett_netlink_msghdr = -1;
|
|
|
|
static gint ett_netlink_msg = -1;
|
2015-06-08 20:24:17 +00:00
|
|
|
static gint ett_netlink_hdr_flags = -1;
|
2016-08-11 21:30:06 +00:00
|
|
|
static gint ett_netlink_attr_type = -1;
|
2013-12-08 12:01:32 +00:00
|
|
|
|
|
|
|
static dissector_table_t netlink_dissector_table;
|
|
|
|
|
2015-06-08 20:24:17 +00:00
|
|
|
|
2020-06-19 01:14:46 +00:00
|
|
|
static int * const netlink_header_get_flags[] = {
|
2021-12-11 15:37:59 +00:00
|
|
|
&hf_netlink_hdr_flag_request,
|
|
|
|
&hf_netlink_hdr_flag_multi,
|
|
|
|
&hf_netlink_hdr_flag_ack,
|
|
|
|
&hf_netlink_hdr_flag_echo,
|
|
|
|
&hf_netlink_hdr_flag_dumpintr,
|
|
|
|
&hf_netlink_hdr_flag_dumpfiltered,
|
|
|
|
|
|
|
|
&hf_netlink_hdr_flag_root,
|
|
|
|
&hf_netlink_hdr_flag_match,
|
|
|
|
&hf_netlink_hdr_flag_atomic,
|
2015-06-08 20:24:17 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2020-06-19 01:14:46 +00:00
|
|
|
static int * const netlink_header_new_flags[] = {
|
2021-12-11 15:37:59 +00:00
|
|
|
&hf_netlink_hdr_flag_request,
|
|
|
|
&hf_netlink_hdr_flag_multi,
|
|
|
|
&hf_netlink_hdr_flag_ack,
|
|
|
|
&hf_netlink_hdr_flag_echo,
|
|
|
|
&hf_netlink_hdr_flag_dumpintr,
|
|
|
|
&hf_netlink_hdr_flag_dumpfiltered,
|
|
|
|
|
|
|
|
&hf_netlink_hdr_flag_replace,
|
|
|
|
&hf_netlink_hdr_flag_excl,
|
|
|
|
&hf_netlink_hdr_flag_create,
|
|
|
|
&hf_netlink_hdr_flag_append,
|
2015-06-08 20:24:17 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2020-06-19 01:14:46 +00:00
|
|
|
static int * const netlink_header_standard_flags[] = {
|
2021-12-11 15:37:59 +00:00
|
|
|
&hf_netlink_hdr_flag_request,
|
|
|
|
&hf_netlink_hdr_flag_multi,
|
|
|
|
&hf_netlink_hdr_flag_ack,
|
|
|
|
&hf_netlink_hdr_flag_echo,
|
|
|
|
&hf_netlink_hdr_flag_dumpintr,
|
|
|
|
&hf_netlink_hdr_flag_dumpfiltered,
|
2016-08-17 19:14:57 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2015-06-08 20:24:17 +00:00
|
|
|
|
2017-04-04 11:13:59 +00:00
|
|
|
static int
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_attributes_common(tvbuff_t *tvb, int hf_type, int ett_tree, int ett_attrib, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
2013-12-11 20:48:18 +00:00
|
|
|
{
|
2016-08-31 18:06:49 +00:00
|
|
|
int encoding;
|
2016-08-11 21:30:06 +00:00
|
|
|
int padding = (4 - offset) & 3;
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
guint data_length;
|
2021-12-11 14:05:11 +00:00
|
|
|
header_field_info *hfi_type;
|
2016-08-11 21:30:06 +00:00
|
|
|
|
2016-08-31 18:06:49 +00:00
|
|
|
DISSECTOR_ASSERT(nl_data);
|
|
|
|
|
|
|
|
encoding = nl_data->encoding;
|
|
|
|
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
/*
|
|
|
|
* A "negative" length is really a very large positive
|
|
|
|
* length, which we presume to go past the end of the
|
|
|
|
* packet.
|
|
|
|
*/
|
|
|
|
if (length < 0)
|
|
|
|
THROW(ReportedBoundsError);
|
|
|
|
|
2013-12-11 20:48:18 +00:00
|
|
|
/* align to 4 */
|
2016-08-11 21:30:06 +00:00
|
|
|
offset += padding;
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
if (length < padding)
|
|
|
|
THROW(ReportedBoundsError);
|
|
|
|
length -= padding;
|
2013-12-11 20:48:18 +00:00
|
|
|
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
data_length = length;
|
|
|
|
|
|
|
|
while (data_length >= 4) {
|
|
|
|
guint rta_len, rta_type, type;
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2016-08-11 21:30:06 +00:00
|
|
|
proto_item *ti, *type_item;
|
|
|
|
proto_tree *attr_tree, *type_tree;
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2016-08-31 18:06:49 +00:00
|
|
|
rta_len = tvb_get_guint16(tvb, offset, encoding);
|
2013-12-11 20:48:18 +00:00
|
|
|
if (rta_len < 4) {
|
|
|
|
/* XXX invalid expert */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
/* XXX expert info when rta_len < data_length? */
|
|
|
|
rta_len = MIN(rta_len, data_length);
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2017-04-04 11:13:59 +00:00
|
|
|
attr_tree = proto_tree_add_subtree(tree, tvb, offset, rta_len, ett_tree, &ti, "Attribute");
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(attr_tree, hf_netlink_attr_len, tvb, offset, 2, encoding);
|
2013-12-11 20:48:18 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2016-08-31 18:06:49 +00:00
|
|
|
rta_type = tvb_get_guint16(tvb, offset, encoding);
|
2017-04-04 11:13:59 +00:00
|
|
|
if (ett_attrib == -1) {
|
|
|
|
/* List of attributes */
|
|
|
|
type = rta_type & NLA_TYPE_MASK;
|
2021-12-11 15:37:59 +00:00
|
|
|
type_item = proto_tree_add_item(attr_tree, hf_netlink_attr_type, tvb, offset, 2, encoding);
|
2017-04-04 11:13:59 +00:00
|
|
|
type_tree = proto_item_add_subtree(type_item, ett_netlink_attr_type);
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(type_tree, hf_netlink_attr_type_nested, tvb, offset, 2, encoding);
|
|
|
|
proto_tree_add_item(type_tree, hf_netlink_attr_type_net_byteorder, tvb, offset, 2, encoding);
|
2021-12-11 14:05:11 +00:00
|
|
|
/* The hf_type _must_ have NLA_TYPE_MASK in it's definition, otherwise the nested/net_byteorder
|
2020-01-09 21:31:02 +00:00
|
|
|
* flags influence the retrieved value. Since this is impossible to enforce (apart from using
|
|
|
|
* a nasty DISSECTOR_ASSERT perhaps) we'll just have to make sure to feed in the properly
|
|
|
|
* masked value. Luckily we already have it: 'type' is the value we need.
|
|
|
|
*/
|
2021-12-11 14:05:11 +00:00
|
|
|
proto_tree_add_uint(type_tree, hf_type, tvb, offset, 2, type);
|
2017-04-04 11:13:59 +00:00
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
if (rta_type & NLA_F_NESTED)
|
|
|
|
proto_item_append_text(type_item, ", Nested");
|
|
|
|
|
2021-12-11 14:05:11 +00:00
|
|
|
hfi_type = proto_registrar_get_nth(hf_type);
|
2017-04-04 11:13:59 +00:00
|
|
|
if (hfi_type->strings) {
|
|
|
|
/* XXX, export hf_try_val_to_str */
|
2017-04-04 23:51:19 +00:00
|
|
|
const char *rta_str;
|
|
|
|
|
|
|
|
if (hfi_type->display & BASE_EXT_STRING) {
|
|
|
|
rta_str = try_val_to_str_ext(type, (value_string_ext *)hfi_type->strings);
|
|
|
|
} else {
|
|
|
|
rta_str = try_val_to_str(type, (const value_string *) hfi_type->strings);
|
|
|
|
}
|
2017-04-04 11:13:59 +00:00
|
|
|
|
|
|
|
if (rta_str) {
|
|
|
|
proto_item_append_text(type_item, ", %s (%d)", rta_str, type);
|
|
|
|
proto_item_append_text(ti, ": %s", rta_str);
|
|
|
|
}
|
|
|
|
}
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2020-01-15 21:41:11 +00:00
|
|
|
/* The callback needs to be passed the netlink_attr_type_net_byteorder as dissected,
|
|
|
|
* to properly dissect the attribute value, which byte order may differ from the
|
|
|
|
* capture host native byte order, as heuristically established in 'encoding'.
|
|
|
|
* We pass in the encoding through nl_data, so we temporarily modify it to match
|
|
|
|
* the NLA_F_NET_BYTEORDER flag.
|
|
|
|
*/
|
|
|
|
if (rta_type & NLA_F_NET_BYTEORDER)
|
|
|
|
nl_data->encoding = ENC_BIG_ENDIAN;
|
|
|
|
|
2020-01-07 22:02:06 +00:00
|
|
|
if (!cb(tvb, data, nl_data, attr_tree, rta_type, offset, rta_len - 4)) {
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(attr_tree, hf_netlink_attr_data, tvb, offset, rta_len - 4, ENC_NA);
|
2016-08-11 21:30:06 +00:00
|
|
|
}
|
2020-01-15 21:41:11 +00:00
|
|
|
|
|
|
|
/* Restore the originaly established encoding. */
|
|
|
|
if (rta_type & NLA_F_NET_BYTEORDER)
|
|
|
|
nl_data->encoding = encoding;
|
2017-04-04 11:13:59 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Nested attributes, constructing an array (list of
|
|
|
|
* attributes where its type is the array index and its
|
|
|
|
* value is the actual list of interesting attributes).
|
|
|
|
*/
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(attr_tree, hf_netlink_attr_index, tvb, offset, 2, encoding);
|
2017-04-04 11:13:59 +00:00
|
|
|
offset += 2;
|
|
|
|
proto_item_append_text(ti, " %u", rta_type);
|
2013-12-11 20:48:18 +00:00
|
|
|
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_attributes(tvb, hf_type, ett_attrib, data, nl_data, attr_tree, offset, rta_len - 4, cb);
|
2013-12-11 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
2016-08-11 21:30:06 +00:00
|
|
|
/* Assume offset already aligned, next offset is rta_len plus alignment. */
|
2021-06-16 09:01:23 +00:00
|
|
|
rta_len = MIN(WS_ROUNDUP_4(rta_len), data_length);
|
2016-08-11 21:30:06 +00:00
|
|
|
offset += rta_len - 4; /* Header was already skipped */
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
if (data_length < rta_len)
|
|
|
|
THROW(ReportedBoundsError);
|
|
|
|
data_length -= rta_len;
|
2013-12-11 20:48:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2017-04-04 11:13:59 +00:00
|
|
|
int
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_attributes(tvbuff_t *tvb, int hf_type, int ett, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
2017-04-04 11:13:59 +00:00
|
|
|
{
|
2021-12-11 14:05:11 +00:00
|
|
|
return dissect_netlink_attributes_common(tvb, hf_type, ett, -1, data, nl_data, tree, offset, length, cb);
|
2017-04-04 11:13:59 +00:00
|
|
|
}
|
|
|
|
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
int
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_attributes_to_end(tvbuff_t *tvb, int hf_type, int ett, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, netlink_attributes_cb_t cb)
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
{
|
2021-12-11 14:05:11 +00:00
|
|
|
return dissect_netlink_attributes_common(tvb, hf_type, ett, -1, data, nl_data, tree, offset, tvb_ensure_reported_length_remaining(tvb, offset), cb);
|
netlink: don't use -1 to mean "to end of packet".
Add dissect_netlink_attributes_to_end(), which takes no length argument,
and uses tvb_ensure_reported_length() to get the remaining length in the
packet.
In dissect_netlink_attributes_common(), treat negative lengths as if
they were a positive length >= 2^31, and throw a reported bounds error.
Also, throw a bounds error if there's more padding to a 4-byte boundary
than there is data in the packet.
At that point, we know the length is positive, so assign it to an
unsigned variable and use *that* in the loop. Throw an error if the
attribute goes past the end of the packet (although we presumably would
have done that already).
(We really should eliminate all use of -1 as "to the end", and make
lengths unsigned. We should also get rid of any places where we're
using negative offsets as offsets from the end of the packet - in the
few cases where you're dealing with trailers, you want to do that
carefully, so as not to throw an exception dissecting the trailer before
you get around to dissecting the rest of the packet - and make offsets
unsigned as well.)
2021-06-15 21:32:54 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 11:13:59 +00:00
|
|
|
int
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_attributes_array(tvbuff_t *tvb, int hf_type, int ett_array, int ett_attrib, void *data, struct packet_netlink_data *nl_data, proto_tree *tree, int offset, int length, netlink_attributes_cb_t cb)
|
2017-04-04 11:13:59 +00:00
|
|
|
{
|
|
|
|
DISSECTOR_ASSERT(ett_attrib != -1);
|
2021-12-11 14:05:11 +00:00
|
|
|
return dissect_netlink_attributes_common(tvb, hf_type, ett_array, ett_attrib, data, nl_data, tree, offset, length, cb);
|
2017-04-04 11:13:59 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
int
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_header(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding, int hf_type, proto_item **pi_type)
|
2016-08-06 14:42:19 +00:00
|
|
|
{
|
|
|
|
guint16 hdr_flags;
|
|
|
|
guint16 hdr_type;
|
|
|
|
proto_tree *fh_hdr;
|
2017-04-04 19:30:45 +00:00
|
|
|
proto_item *pi;
|
2021-12-11 14:05:11 +00:00
|
|
|
header_field_info *hfi_type;
|
2016-08-06 14:42:19 +00:00
|
|
|
|
2017-04-16 22:54:32 +00:00
|
|
|
fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 16, ett_netlink_msghdr, NULL, "Netlink message header");
|
2016-08-06 14:42:19 +00:00
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_hdr, hf_netlink_hdr_len, tvb, offset, 4, encoding);
|
2016-08-06 14:42:19 +00:00
|
|
|
offset += 4;
|
|
|
|
|
2016-08-31 17:44:25 +00:00
|
|
|
hdr_type = tvb_get_guint16(tvb, offset, encoding);
|
2017-04-04 19:30:45 +00:00
|
|
|
if (hdr_type < WS_NLMSG_MIN_TYPE) {
|
|
|
|
/* Reserved control messages. */
|
2021-12-11 15:37:59 +00:00
|
|
|
hf_type = hf_netlink_hdr_type;
|
2021-12-11 14:05:11 +00:00
|
|
|
pi = proto_tree_add_item(fh_hdr, hf_type, tvb, offset, 2, encoding);
|
2017-04-04 19:30:45 +00:00
|
|
|
} else {
|
2021-12-11 14:05:11 +00:00
|
|
|
if (hf_type != -1) {
|
|
|
|
pi = proto_tree_add_item(fh_hdr, hf_type, tvb, offset, 2, encoding);
|
2017-04-04 19:30:45 +00:00
|
|
|
} else {
|
2021-12-11 15:37:59 +00:00
|
|
|
hf_type = hf_netlink_hdr_type;
|
2021-12-11 14:05:11 +00:00
|
|
|
pi = proto_tree_add_item(fh_hdr, hf_type, tvb, offset, 2, encoding);
|
2017-04-04 19:30:45 +00:00
|
|
|
proto_item_set_text(pi, "Message type: Protocol-specific (0x%04x)", hdr_type);
|
|
|
|
}
|
2016-08-06 14:42:19 +00:00
|
|
|
}
|
2021-12-11 14:05:11 +00:00
|
|
|
hfi_type = proto_registrar_get_nth(hf_type);
|
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
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);
|
2016-08-06 14:42:19 +00:00
|
|
|
}
|
|
|
|
offset += 2;
|
|
|
|
|
2016-08-17 19:14:57 +00:00
|
|
|
hdr_flags = tvb_get_guint16(tvb, offset, encoding);
|
|
|
|
if ((hdr_flags & WS_NLM_F_REQUEST) && (hdr_flags & 0x0f00)) {
|
2019-12-27 22:36:56 +00:00
|
|
|
/* TODO detect based on the protocol family and message type
|
2016-08-17 19:14:57 +00:00
|
|
|
* whether this is a GET, NEW or regular request. */
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_bitmask(fh_hdr, tvb, offset, hf_netlink_hdr_flags,
|
2016-08-17 19:14:57 +00:00
|
|
|
ett_netlink_hdr_flags, netlink_header_get_flags, encoding);
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_bitmask(fh_hdr, tvb, offset, hf_netlink_hdr_flags,
|
2016-08-17 19:14:57 +00:00
|
|
|
ett_netlink_hdr_flags, netlink_header_new_flags, encoding);
|
|
|
|
} else {
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_bitmask(fh_hdr, tvb, offset, hf_netlink_hdr_flags,
|
2016-08-17 19:14:57 +00:00
|
|
|
ett_netlink_hdr_flags, netlink_header_standard_flags, encoding);
|
2016-08-06 14:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset += 2;
|
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_hdr, hf_netlink_hdr_seq, tvb, offset, 4, encoding);
|
2016-08-06 14:42:19 +00:00
|
|
|
offset += 4;
|
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_hdr, hf_netlink_hdr_pid, tvb, offset, 4, encoding);
|
2016-08-06 14:42:19 +00:00
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dissect_netlink_error(tvbuff_t *tvb, proto_tree *tree, int offset, int encoding)
|
|
|
|
{
|
2016-08-23 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* XXX - this should make sure we don't run past the end of the
|
|
|
|
* message.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assume sizeof(int) == 4; RFC 3549 doesn't say "32 bits", it
|
|
|
|
* says "integer (typically 32 bits)".
|
|
|
|
*/
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(tree, hf_netlink_error, tvb, offset, 4, encoding);
|
2016-08-06 14:42:19 +00:00
|
|
|
offset += 4;
|
|
|
|
|
2021-12-11 14:05:11 +00:00
|
|
|
dissect_netlink_header(tvb, tree, offset, encoding, -1, NULL);
|
2016-08-06 14:42:19 +00:00
|
|
|
}
|
|
|
|
|
2013-12-08 12:01:32 +00:00
|
|
|
static int
|
2020-01-07 22:02:06 +00:00
|
|
|
dissect_netlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
2013-12-08 12:01:32 +00:00
|
|
|
{
|
2014-10-04 15:28:35 +00:00
|
|
|
guint16 protocol, hatype;
|
2013-12-08 12:01:32 +00:00
|
|
|
proto_item *ti;
|
2014-10-04 15:28:35 +00:00
|
|
|
tvbuff_t *next_tvb;
|
2016-01-17 16:22:47 +00:00
|
|
|
proto_tree *fh_tree;
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
int offset = 0;
|
2016-08-31 17:44:25 +00:00
|
|
|
int encoding;
|
|
|
|
guint len_rem, len_le, len_be;
|
2013-12-08 12:01:32 +00:00
|
|
|
|
|
|
|
hatype = tvb_get_ntohs(tvb, 2);
|
|
|
|
if (hatype != ARPHRD_NETLINK)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netlink");
|
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
ti = proto_tree_add_protocol_format(tree, proto_netlink, tvb, offset,
|
2016-01-17 16:22:47 +00:00
|
|
|
SLL_HEADER_SIZE, "Linux netlink (cooked header)");
|
|
|
|
fh_tree = proto_item_add_subtree(ti, ett_netlink_cooked);
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
/* Packet type
|
|
|
|
* Since this packet, coming from the monitor port, is always outgoing we skip this
|
|
|
|
*/
|
|
|
|
offset += 2;
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_tree, hf_netlink_hatype, tvb, offset, 2, ENC_BIG_ENDIAN);
|
2013-12-08 12:01:32 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
/* Hardware address length plus spare space, unused 10B */
|
2013-12-08 12:01:32 +00:00
|
|
|
offset += 10;
|
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
/* Protocol, used as netlink family identifier */
|
2013-12-08 12:01:32 +00:00
|
|
|
protocol = tvb_get_ntohs(tvb, offset);
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_tree, hf_netlink_family, tvb, offset, 2, ENC_BIG_ENDIAN);
|
2013-12-08 12:01:32 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
/* End of cooked header */
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2016-08-31 17:44:25 +00:00
|
|
|
/*
|
2020-01-13 21:54:53 +00:00
|
|
|
* We do not know the endianness of the capture host, we have to guess.
|
|
|
|
* Compare the size of the message with the reported size of the TVB,
|
|
|
|
* take the endianness in which the messsage length is closer to
|
|
|
|
* the size of the TVB. Normally we have messages with less
|
|
|
|
* than 10KiB here so the sizes are very huge in the wrong endianness.
|
2016-08-31 17:44:25 +00:00
|
|
|
*/
|
|
|
|
len_rem = tvb_reported_length_remaining(tvb, offset);
|
|
|
|
len_le = tvb_get_letohl(tvb, offset);
|
|
|
|
len_be = tvb_get_ntohl(tvb, offset);
|
|
|
|
#define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
|
|
|
|
if (abs_diff(len_be, len_rem) < abs_diff(len_le, len_rem)) {
|
|
|
|
encoding = ENC_BIG_ENDIAN;
|
|
|
|
} else {
|
|
|
|
encoding = ENC_LITTLE_ENDIAN;
|
|
|
|
}
|
|
|
|
|
2013-12-08 12:01:32 +00:00
|
|
|
while (tvb_reported_length_remaining(tvb, offset) >= 16) {
|
|
|
|
int pkt_end_offset;
|
2017-04-04 19:30:45 +00:00
|
|
|
guint16 msg_type;
|
2013-12-08 12:01:32 +00:00
|
|
|
guint32 pkt_len;
|
2013-12-13 22:34:10 +00:00
|
|
|
guint32 port_id;
|
2013-12-08 12:01:32 +00:00
|
|
|
proto_tree *fh_msg;
|
2017-04-04 19:30:45 +00:00
|
|
|
gboolean dissected = FALSE;
|
2015-06-08 20:24:17 +00:00
|
|
|
|
2016-08-31 17:44:25 +00:00
|
|
|
pkt_len = tvb_get_guint32(tvb, offset, encoding);
|
2013-12-08 12:01:32 +00:00
|
|
|
|
|
|
|
pkt_end_offset = offset + pkt_len;
|
|
|
|
|
2016-08-23 18:39:56 +00:00
|
|
|
if (pkt_len < 16) {
|
|
|
|
/*
|
|
|
|
* This field includes the length of the 16-byte header,
|
|
|
|
* so its value is invalid. Add it, report an error,
|
|
|
|
* and stop trying to dissect.
|
|
|
|
*/
|
|
|
|
proto_tree *fh_hdr;
|
|
|
|
|
2017-04-16 22:54:32 +00:00
|
|
|
fh_hdr = proto_tree_add_subtree(tree, tvb, offset, 4, ett_netlink_msghdr, NULL, "Netlink message header");
|
2016-08-23 18:39:56 +00:00
|
|
|
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_tree_add_item(fh_hdr, hf_netlink_hdr_len, tvb, offset, 4, encoding);
|
2016-08-23 18:39:56 +00:00
|
|
|
/* XXX invalid expert */
|
|
|
|
break;
|
|
|
|
}
|
2016-08-23 18:41:24 +00:00
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
/* 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);
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2020-01-13 21:54:53 +00:00
|
|
|
/* Since we have no original direction in the packet coming from
|
|
|
|
* the monitor port we have to derive it from the port_id
|
|
|
|
*/
|
2013-12-13 22:34:10 +00:00
|
|
|
if (port_id == 0x00)
|
|
|
|
pinfo->p2p_dir = P2P_DIR_SENT; /* userspace -> kernel */
|
|
|
|
else
|
|
|
|
pinfo->p2p_dir = P2P_DIR_RECV; /* userspace or kernel -> userspace */
|
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
/*
|
|
|
|
* Try to invoke subdissectors for non-control messages.
|
|
|
|
*/
|
|
|
|
if (msg_type >= WS_NLMSG_MIN_TYPE && pkt_len > 16) {
|
2020-01-07 22:02:06 +00:00
|
|
|
struct packet_netlink_data nl_data;
|
2017-04-04 19:30:45 +00:00
|
|
|
|
2020-01-07 22:02:06 +00:00
|
|
|
nl_data.magic = PACKET_NETLINK_MAGIC;
|
|
|
|
nl_data.encoding = encoding;
|
|
|
|
nl_data.type = msg_type;
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
next_tvb = tvb_new_subset_length(tvb, offset, pkt_len);
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2020-01-07 22:02:06 +00:00
|
|
|
if (dissector_try_uint_new(netlink_dissector_table, protocol, next_tvb, pinfo, tree, TRUE, &nl_data)) {
|
2017-04-04 19:30:45 +00:00
|
|
|
dissected = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2013-12-08 12:01:32 +00:00
|
|
|
|
2017-04-04 19:30:45 +00:00
|
|
|
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");
|
2021-12-11 14:05:11 +00:00
|
|
|
offset = dissect_netlink_header(tvb, fh_msg, offset, encoding, -1, NULL);
|
2017-04-04 19:30:45 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2013-12-08 12:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset = pkt_end_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_netlink(void)
|
|
|
|
{
|
2021-12-11 15:37:59 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_netlink_hatype,
|
|
|
|
{ "Link-layer address type", "netlink.hatype",
|
|
|
|
FT_UINT16, BASE_DEC, VALS(ha_types), 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_family,
|
|
|
|
{ "Family", "netlink.family",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &netlink_family_vals_ext, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_len,
|
|
|
|
{ "Length", "netlink.hdr_len",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Length of message including header", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_type,
|
|
|
|
{ "Message type", "netlink.hdr_type",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_HEX, VALS(type_vals), 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Type of message content", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flags,
|
|
|
|
{ "Flags", "netlink.hdr_flags",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Additional flags", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_dumpfiltered,
|
|
|
|
{ "Dump filtered", "netlink.hdr_flags.dump_filtered",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_DUMP_FILTERED,
|
|
|
|
"Dump was filtered as requested", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_dumpintr,
|
|
|
|
{ "Dump inconsistent", "netlink.hdr_flags.dump_intr",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_DUMP_INTR,
|
|
|
|
"Dump was inconsistent due to sequence change", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_echo,
|
|
|
|
{ "Echo", "netlink.hdr_flags.echo",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_ECHO,
|
|
|
|
"Echo this request", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_ack,
|
|
|
|
{ "Ack", "netlink.hdr_flags.ack",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_ACK,
|
|
|
|
"Asking for an ack", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_multi,
|
|
|
|
{ "Multipart message", "netlink.hdr_flags.multi",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_MULTI,
|
|
|
|
"Part of multi-part message terminated by NLMSG_DONE", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_request,
|
|
|
|
{ "Request", "netlink.hdr_flags.request",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_REQUEST,
|
|
|
|
"It is a request message", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_root,
|
|
|
|
{ "Specify tree root", "netlink.hdr_flags.root",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_ROOT,
|
|
|
|
"Return the complete table instead of a single entry", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_match,
|
|
|
|
{ "Return all matching", "netlink.hdr_flags.match",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_MATCH,
|
|
|
|
"Return all entries matching criteria in request", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_atomic,
|
|
|
|
{ "Atomic", "netlink.hdr_flags.atomic",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_ATOMIC,
|
|
|
|
"Return an atomic snapshot of the table", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_replace,
|
|
|
|
{ "Replace", "netlink.hdr_flags.replace",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_REPLACE,
|
|
|
|
"Replace existing objects", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_excl,
|
|
|
|
{ "Excl", "netlink.hdr_flags.excl",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_EXCL,
|
|
|
|
"Do not replace existing objects", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_create,
|
|
|
|
{ "Create", "netlink.hdr_flags.create",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_CREATE,
|
|
|
|
"Create objects if it does not already exist", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_flag_append,
|
|
|
|
{ "Append", "netlink.hdr_flags.append",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, WS_NLM_F_APPEND,
|
|
|
|
"Add to end of object list", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_seq,
|
|
|
|
{ "Sequence", "netlink.hdr_seq",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Sequence number", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_hdr_pid,
|
|
|
|
{ "Port ID", "netlink.hdr_pid",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Sender port ID", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_len,
|
|
|
|
{ "Len", "netlink.attr_len",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_type,
|
|
|
|
{ "Type", "netlink.attr_type",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_HEX, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Netlink Attribute type", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_type_nested,
|
|
|
|
{ "Nested", "netlink.attr_type.nested",
|
|
|
|
FT_BOOLEAN, 16, TFS(&tfs_true_false), NLA_F_NESTED,
|
|
|
|
"Carries nested attributes", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_type_net_byteorder,
|
|
|
|
{ "Network byte order", "netlink.attr_type.net_byteorder",
|
|
|
|
FT_BOOLEAN, 16, TFS(&tfs_true_false), NLA_F_NET_BYTEORDER,
|
|
|
|
"Payload stored in host or network byte order", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_index,
|
|
|
|
{ "Index", "netlink.attr_index",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Netlink Attribute type (array index)", HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_attr_data,
|
|
|
|
{ "Data", "netlink.attr_data",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_netlink_error,
|
|
|
|
{ "Error code", "netlink.error",
|
2022-02-08 08:56:17 +00:00
|
|
|
FT_INT32, BASE_DEC | BASE_EXT_STRING, &linux_negative_errno_vals_ext, 0x0,
|
2021-12-11 15:37:59 +00:00
|
|
|
"Negative errno or 0 for acknowledgements", HFILL }
|
|
|
|
},
|
2013-12-08 12:01:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_netlink_cooked,
|
|
|
|
&ett_netlink_msghdr,
|
2015-06-08 20:24:17 +00:00
|
|
|
&ett_netlink_msg,
|
2016-08-11 21:30:06 +00:00
|
|
|
&ett_netlink_hdr_flags,
|
|
|
|
&ett_netlink_attr_type,
|
2013-12-08 12:01:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
proto_netlink = proto_register_protocol("Linux netlink protocol", "NETLINK", "netlink" );
|
2021-12-11 15:37:59 +00:00
|
|
|
proto_register_field_array(proto_netlink, hf, array_length(hf));
|
2013-12-08 12:01:32 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
|
2015-12-09 03:49:44 +00:00
|
|
|
netlink_handle = create_dissector_handle(dissect_netlink, proto_netlink);
|
2013-12-08 12:01:32 +00:00
|
|
|
|
|
|
|
netlink_dissector_table = register_dissector_table(
|
|
|
|
"netlink.protocol",
|
|
|
|
"Linux netlink protocol type",
|
2016-03-13 11:51:45 +00:00
|
|
|
proto_netlink, FT_UINT16,
|
2016-08-30 22:51:54 +00:00
|
|
|
BASE_HEX
|
2013-12-08 12:01:32 +00:00
|
|
|
);
|
2016-01-16 15:56:49 +00:00
|
|
|
register_dissector("netlink", dissect_netlink, proto_netlink);
|
2013-12-08 12:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_netlink(void)
|
|
|
|
{
|
|
|
|
dissector_add_uint("wtap_encap", WTAP_ENCAP_NETLINK, netlink_handle);
|
|
|
|
}
|
2014-10-04 15:28:35 +00:00
|
|
|
|
|
|
|
/*
|
2019-07-26 18:43:17 +00:00
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
2014-10-04 15:28:35 +00:00
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|