From: Dmitry V. Levin Date: Sat, 3 Jun 2017 23:19:49 +0000 (+0000) Subject: netlink: implement generic nlmsg_type decoding X-Git-Tag: v4.18~122 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8700030e4887373f0afbcb280a765dcb132923b1;p=strace netlink: implement generic nlmsg_type decoding Implement a pluggable mechanism of nlmsg_type decoding. Add decoding of NETLINK_SOCK_DIAG types. * linux/sock_diag.h (SOCK_DESTROY): New macro. * xlat/nl_sock_diag_types.in: New file. * netlink.c: Include xlat/nl_sock_diag_types.h. (get_fd_nl_family, decode_nlmsg_type): New functions. (print_nlmsghdr): Use them for nlmsg_type decoding. Co-authored-by: Fabien Siron --- diff --git a/linux/sock_diag.h b/linux/sock_diag.h index ba0c114f..83daf359 100644 --- a/linux/sock_diag.h +++ b/linux/sock_diag.h @@ -2,6 +2,7 @@ #define STRACE_LINUX_SOCK_DIAG_H #define SOCK_DIAG_BY_FAMILY 20 +#define SOCK_DESTROY 21 struct sock_diag_req { uint8_t sdiag_family; diff --git a/netlink.c b/netlink.c index e7ee9fd8..c2da66b9 100644 --- a/netlink.c +++ b/netlink.c @@ -33,6 +33,7 @@ #include "xlat/netlink_flags.h" #include "xlat/netlink_protocols.h" #include "xlat/netlink_types.h" +#include "xlat/nl_sock_diag_types.h" #undef NLMSG_HDRLEN #define NLMSG_HDRLEN NLMSG_ALIGN(sizeof(struct nlmsghdr)) @@ -60,6 +61,56 @@ enum { 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; + + const char *const details = get_sockaddr_by_inode(tcp, fd, inode); + if (!details) + return NL_FAMILY_ERROR; + + const char *const nl_details = STR_STRIP_PREFIX(details, "NETLINK:["); + if (nl_details == details) + return NL_FAMILY_ERROR; + + const struct xlat *xlats = netlink_protocols; + for (; xlats->str; ++xlats) { + const char *name = STR_STRIP_PREFIX(xlats->str, "NETLINK_"); + if (!strncmp(nl_details, name, strlen(name))) + return xlats->val; + } + + if (*nl_details >= '0' && *nl_details <= '9') + return atoi(nl_details); + + return NL_FAMILY_ERROR; +} + +static const struct { + const struct xlat *const xlat; + const char *const dflt; +} nlmsg_types[] = { + [NETLINK_SOCK_DIAG] = { nl_sock_diag_types, "SOCK_DIAG_???" } +}; + +/* + * As all valid netlink families are positive integers, use unsigned int + * for family here to filter out NL_FAMILY_ERROR and NL_FAMILY_DEFAULT. + */ +static void +decode_nlmsg_type(const uint16_t type, const unsigned int family) +{ + if (family < ARRAY_SIZE(nlmsg_types) + && nlmsg_types[family].xlat) { + printxval(nlmsg_types[family].xlat, type, nlmsg_types[family].dflt); + } else { + printxval(netlink_types, type, "NLMSG_???"); + } +} + static int print_nlmsghdr(struct tcb *tcp, const int fd, @@ -70,7 +121,12 @@ print_nlmsghdr(struct tcb *tcp, tprintf("{len=%u, type=", nlmsghdr->nlmsg_len); - printxval(netlink_types, nlmsghdr->nlmsg_type, "NLMSG_???"); + const int hdr_family = (nlmsghdr->nlmsg_type < NLMSG_MIN_TYPE) + ? NL_FAMILY_DEFAULT + : (family != NL_FAMILY_DEFAULT + ? family : get_fd_nl_family(tcp, fd)); + + decode_nlmsg_type(nlmsghdr->nlmsg_type, hdr_family); tprints(", flags="); printflags(netlink_flags, nlmsghdr->nlmsg_flags, "NLM_F_???"); @@ -78,7 +134,7 @@ print_nlmsghdr(struct tcb *tcp, tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq, nlmsghdr->nlmsg_pid); - return family; + return family != NL_FAMILY_DEFAULT ? family : hdr_family; } static void diff --git a/xlat/nl_sock_diag_types.in b/xlat/nl_sock_diag_types.in new file mode 100644 index 00000000..5c176c80 --- /dev/null +++ b/xlat/nl_sock_diag_types.in @@ -0,0 +1,4 @@ +TCPDIAG_GETSOCK 18 +DCCPDIAG_GETSOCK 19 +SOCK_DIAG_BY_FAMILY 20 +SOCK_DESTROY 21