]> granicus.if.org Git - strace/commitdiff
netlink: add a basic socket diag parser of AF_NETLINK messages
authorJingPiao Chen <chenjingpiao@gmail.com>
Tue, 13 Jun 2017 02:32:55 +0000 (10:32 +0800)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 15 Jun 2017 22:20:41 +0000 (22:20 +0000)
* linux/netlink_diag.h (NDIAG_SHOW_GROUPS, NDIAG_SHOW_RING_CFG):
New macros.
* netlink_sock_diag.c: Include <linux/netlink_diag.h>,
"xlat/netlink_diag_show.h" and "xlat/netlink_states.h".
(decode_netlink_diag_req, decode_netlink_diag_msg): New functions.
(diag_decoders): Add AF_NETLINK.
* xlat/netlink_diag_show.in: New file.
* xlat/netlink_states.in: Likewise.

Co-authored-by: Fabien Siron <fabien.siron@epita.fr>
linux/netlink_diag.h
netlink_sock_diag.c
xlat/netlink_diag_show.in [new file with mode: 0644]
xlat/netlink_states.in [new file with mode: 0644]

index a52507c75cfd2aca867e3cbb3e3a38bf8fe24bb8..49b7550bc0022cbf792429e4c29b98ae04cbcdaf 100644 (file)
@@ -23,7 +23,9 @@ struct netlink_diag_msg {
        uint32_t ndiag_cookie[2];
 };
 
-#define NDIAG_SHOW_MEMINFO           0x00000001
-#define NDIAG_PROTO_ALL              ((uint8_t) ~0)
+#define NDIAG_SHOW_MEMINFO             0x00000001
+#define NDIAG_SHOW_GROUPS              0x00000002
+#define NDIAG_SHOW_RING_CFG            0x00000004 /* deprecated since 4.6 */
+#define NDIAG_PROTO_ALL                        ((uint8_t) ~0)
 
 #endif /* !STRACE_LINUX_NETLINK_DIAG_H */
index 4687b119a84553d61503a625bdc8b70127274129..f4829572d3b9d97a1406c2028fcad433b35a4e3f 100644 (file)
 
 #include <sys/socket.h>
 #include <linux/netlink.h>
+#include <linux/netlink_diag.h>
 #include <linux/unix_diag.h>
 
 #include "xlat/tcp_states.h"
 #include "xlat/tcp_state_flags.h"
 
+#include "xlat/netlink_diag_show.h"
+#include "xlat/netlink_states.h"
+
 #include "xlat/unix_diag_show.h"
 
 static void
@@ -118,6 +122,86 @@ decode_unix_diag_msg(struct tcb *const tcp,
        tprints("}");
 }
 
+static void
+decode_netlink_diag_req(struct tcb *const tcp,
+                       const struct nlmsghdr *const nlmsghdr,
+                       const uint8_t family,
+                       const kernel_ulong_t addr,
+                       const kernel_ulong_t len)
+{
+       struct netlink_diag_req req = { .sdiag_family = family };
+       const size_t offset = sizeof(req.sdiag_family);
+
+       tprints("{sdiag_family=");
+       printxval(addrfams, req.sdiag_family, "AF_???");
+
+       tprints(", ");
+       if (len >= sizeof(req)) {
+               if (!umoven_or_printaddr(tcp, addr + offset,
+                                        sizeof(req) - offset,
+                                        (void *) &req + offset)) {
+                       tprints("sdiag_protocol=");
+                       if (NDIAG_PROTO_ALL == req.sdiag_protocol)
+                               tprints("NDIAG_PROTO_ALL");
+                       else
+                               printxval(netlink_protocols,
+                                         req.sdiag_protocol, "NETLINK_???");
+                       tprintf(", ndiag_ino=%" PRIu32 ", ndiag_show=",
+                               req.ndiag_ino);
+                       printflags(netlink_diag_show, req.ndiag_show,
+                                  "NDIAG_SHOW_???");
+                       tprintf(", ndiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
+                               req.ndiag_cookie[0], req.ndiag_cookie[1]);
+               }
+       } else
+               tprints("...");
+       tprints("}");
+}
+
+static void
+decode_netlink_diag_msg(struct tcb *const tcp,
+                       const struct nlmsghdr *const nlmsghdr,
+                       const uint8_t family,
+                       const kernel_ulong_t addr,
+                       const kernel_ulong_t len)
+{
+       struct netlink_diag_msg msg = { .ndiag_family = family };
+       const size_t offset = sizeof(msg.ndiag_family);
+
+       tprints("{ndiag_family=");
+       printxval(addrfams, msg.ndiag_family, "AF_???");
+
+       tprints(", ");
+       if (len >= sizeof(msg)) {
+               if (!umoven_or_printaddr(tcp, addr + offset,
+                                        sizeof(msg) - offset,
+                                        (void *) &msg + offset)) {
+                       tprints("ndiag_type=");
+                       printxval(socktypes, msg.ndiag_type, "SOCK_???");
+                       tprints(", ndiag_protocol=");
+                       printxval(netlink_protocols, msg.ndiag_protocol,
+                                 "NETLINK_???");
+                       tprints(", ndiag_state=");
+                       printxval(netlink_states, msg.ndiag_state,
+                                 "NETLINK_???");
+                       tprintf(", ndiag_portid=%" PRIu32
+                               ", ndiag_dst_portid=%" PRIu32
+                               ", ndiag_dst_group=%" PRIu32
+                               ", ndiag_ino=%" PRIu32
+                               ", ndiag_cookie=[%" PRIu32
+                               ", %" PRIu32 "]",
+                               msg.ndiag_portid,
+                               msg.ndiag_dst_portid,
+                               msg.ndiag_dst_group,
+                               msg.ndiag_ino,
+                               msg.ndiag_cookie[0],
+                               msg.ndiag_cookie[1]);
+               }
+       } else
+               tprints("...");
+       tprints("}");
+}
+
 typedef void (*netlink_diag_decoder_t)(struct tcb *,
                                       const struct nlmsghdr *,
                                       uint8_t family,
@@ -127,6 +211,7 @@ typedef void (*netlink_diag_decoder_t)(struct tcb *,
 static const struct {
        const netlink_diag_decoder_t request, response;
 } diag_decoders[] = {
+       [AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
        [AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
 };
 
diff --git a/xlat/netlink_diag_show.in b/xlat/netlink_diag_show.in
new file mode 100644 (file)
index 0000000..9639c5a
--- /dev/null
@@ -0,0 +1,3 @@
+NDIAG_SHOW_MEMINFO
+NDIAG_SHOW_GROUPS
+NDIAG_SHOW_RING_CFG
diff --git a/xlat/netlink_states.in b/xlat/netlink_states.in
new file mode 100644 (file)
index 0000000..4d4aee7
--- /dev/null
@@ -0,0 +1,2 @@
+NETLINK_UNCONNECTED    0
+NETLINK_CONNECTED      1