[PATCH v2 1/3] netlink: call get_fd_nl_family before decode nlmsghdr
JingPiao Chen
chenjingpiao at gmail.com
Tue Aug 8 14:37:37 UTC 2017
Prepare for NETLINK_KOBJECT_UEVENT decode. The messages
of NETLINK_KOBJECT_UEVENT do not contain nlmsghdr.
* netlink.c (NL_FAMILY_*): Remove enum.
(get_fd_nl_family): Replace NL_FAMILY_ERROR with -1.
(decode_nlmsg_type): Correct the comment.
Skip family specific type decoders for type < NLMSG_MIN_TYPE.
(decode_nlmsghdr_with_payload): Skip family specific decoders
for type < NLMSG_MIN_TYPE && type != NLMSG_DONE.
(print_nlmsghdr): Move get_fd_nl_family call ...
(decode_nlmsghdr_with_payload): ... here.
---
netlink.c | 53 +++++++++++++++++++++++++----------------------------
1 file changed, 25 insertions(+), 28 deletions(-)
diff --git a/netlink.c b/netlink.c
index f3a7cf9..2cc7967 100644
--- a/netlink.c
+++ b/netlink.c
@@ -67,25 +67,20 @@ fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr *const nlmsghdr,
return true;
}
-enum {
- NL_FAMILY_ERROR = -1,
- NL_FAMILY_DEFAULT = -2
-};
-
static int
get_fd_nl_family(struct tcb *const tcp, const int fd)
{
const unsigned long inode = getfdinode(tcp, fd);
if (!inode)
- return NL_FAMILY_ERROR;
+ return -1;
const char *const details = get_sockaddr_by_inode(tcp, fd, inode);
if (!details)
- return NL_FAMILY_ERROR;
+ return -1;
const char *const nl_details = STR_STRIP_PREFIX(details, "NETLINK:[");
if (nl_details == details)
- return NL_FAMILY_ERROR;
+ return -1;
const struct xlat *xlats = netlink_protocols;
for (; xlats->str; ++xlats) {
@@ -97,7 +92,7 @@ get_fd_nl_family(struct tcb *const tcp, const int fd)
if (*nl_details >= '0' && *nl_details <= '9')
return atoi(nl_details);
- return NL_FAMILY_ERROR;
+ return -1;
}
static void
@@ -173,7 +168,7 @@ static const struct {
/*
* As all valid netlink families are positive integers, use unsigned int
- * for family here to filter out NL_FAMILY_ERROR and NL_FAMILY_DEFAULT.
+ * for family here to filter out -1.
*/
static void
decode_nlmsg_type(const uint16_t type, const unsigned int family)
@@ -182,7 +177,8 @@ decode_nlmsg_type(const uint16_t type, const unsigned int family)
const struct xlat *xlat = netlink_types;
const char *dflt = "NLMSG_???";
- if (type != NLMSG_DONE && family < ARRAY_SIZE(nlmsg_types)) {
+ /* type < NLMSG_MIN_TYPE are reserved control messages. */
+ if (type >= NLMSG_MIN_TYPE && family < ARRAY_SIZE(nlmsg_types)) {
if (nlmsg_types[family].decoder)
decoder = nlmsg_types[family].decoder;
if (nlmsg_types[family].xlat)
@@ -258,32 +254,24 @@ end:
printflags_ex(flags, "NLM_F_???", netlink_flags, table, NULL);
}
-static int
+static void
print_nlmsghdr(struct tcb *tcp,
const int fd,
- int family,
+ const int family,
const struct nlmsghdr *const nlmsghdr)
{
/* print the whole structure regardless of its nlmsg_len */
tprintf("{len=%u, type=", nlmsghdr->nlmsg_len);
- const int hdr_family = (nlmsghdr->nlmsg_type < NLMSG_MIN_TYPE
- && nlmsghdr->nlmsg_type != NLMSG_DONE)
- ? NL_FAMILY_DEFAULT
- : (family != NL_FAMILY_DEFAULT
- ? family : get_fd_nl_family(tcp, fd));
-
- decode_nlmsg_type(nlmsghdr->nlmsg_type, hdr_family);
+ decode_nlmsg_type(nlmsghdr->nlmsg_type, family);
tprints(", flags=");
decode_nlmsg_flags(nlmsghdr->nlmsg_flags,
- nlmsghdr->nlmsg_type, hdr_family);
+ nlmsghdr->nlmsg_type, family);
tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq,
nlmsghdr->nlmsg_pid);
-
- return family != NL_FAMILY_DEFAULT ? family : hdr_family;
}
static bool
@@ -319,7 +307,7 @@ static const nla_decoder_t nlmsgerr_nla_decoders[] = {
static void
decode_nlmsghdr_with_payload(struct tcb *const tcp,
const int fd,
- int family,
+ const int family,
const struct nlmsghdr *const nlmsghdr,
const kernel_ulong_t addr,
const kernel_ulong_t len);
@@ -399,7 +387,15 @@ decode_payload(struct tcb *const tcp,
return;
}
- if ((unsigned int) family < ARRAY_SIZE(netlink_decoders)
+ /*
+ * While many NLMSG_DONE messages indeed have payload
+ * containing just one integer, there are exceptions.
+ * Passing payloads of NLMSG_DONE messages to family
+ * specific netlink payload decoders.
+ */
+ if ((nlmsghdr->nlmsg_type >= NLMSG_MIN_TYPE
+ || nlmsghdr->nlmsg_type == NLMSG_DONE)
+ && (unsigned int) family < ARRAY_SIZE(netlink_decoders)
&& netlink_decoders[family]
&& netlink_decoders[family](tcp, nlmsghdr, addr, len)) {
return;
@@ -419,7 +415,7 @@ decode_payload(struct tcb *const tcp,
static void
decode_nlmsghdr_with_payload(struct tcb *const tcp,
const int fd,
- int family,
+ const int family,
const struct nlmsghdr *const nlmsghdr,
const kernel_ulong_t addr,
const kernel_ulong_t len)
@@ -430,7 +426,7 @@ decode_nlmsghdr_with_payload(struct tcb *const tcp,
if (nlmsg_len > NLMSG_HDRLEN)
tprints("{");
- family = print_nlmsghdr(tcp, fd, family, nlmsghdr);
+ print_nlmsghdr(tcp, fd, family, nlmsghdr);
if (nlmsg_len > NLMSG_HDRLEN) {
tprints(", ");
@@ -446,6 +442,7 @@ decode_netlink(struct tcb *const tcp,
kernel_ulong_t addr,
kernel_ulong_t len)
{
+ const int family = get_fd_nl_family(tcp, fd);
struct nlmsghdr nlmsghdr;
bool print_array = false;
unsigned int elt;
@@ -472,7 +469,7 @@ decode_netlink(struct tcb *const tcp,
print_array = true;
}
- decode_nlmsghdr_with_payload(tcp, fd, NL_FAMILY_DEFAULT,
+ decode_nlmsghdr_with_payload(tcp, fd, family,
&nlmsghdr, addr, len);
if (!next_addr)
--
2.7.4
More information about the Strace-devel
mailing list