]> granicus.if.org Git - strace/commitdiff
netlink: implement generic nlmsg_type decoding
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 3 Jun 2017 23:19:49 +0000 (23:19 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 5 Jun 2017 11:52:11 +0000 (11:52 +0000)
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 <fabien.siron@epita.fr>
linux/sock_diag.h
netlink.c
xlat/nl_sock_diag_types.in [new file with mode: 0644]

index ba0c114f388d6b674229d2d18c613f6835803f53..83daf359b82b9121a17391a3bbbf04e1f73f095d 100644 (file)
@@ -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;
index e7ee9fd87c3b176945b8629812fd5722c93e93bd..c2da66b97a845a0ebe65af463165edc88413c840 100644 (file)
--- 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 (file)
index 0000000..5c176c8
--- /dev/null
@@ -0,0 +1,4 @@
+TCPDIAG_GETSOCK                18
+DCCPDIAG_GETSOCK       19
+SOCK_DIAG_BY_FAMILY    20
+SOCK_DESTROY           21