From 8e9c9e4631aecc82d3672baec53af917dda32e65 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 10 Jun 2017 22:07:54 +0000 Subject: [PATCH] netlink: add a basic socket diag parser of AF_UNIX messages * defs.h (socktypes): New xlat prototype. * linux/unix_diag.h (UDIAG_SHOW_VFS, UDIAG_SHOW_ICONS, UDIAG_SHOW_RQLEN, UDIAG_SHOW_MEMINFO): New macros. * netlink_sock_diag.c: Include , , , "xlat/tcp_states.h", "xlat/tcp_state_flags.h", and "xlat/unix_diag_show.h". (decode_unix_diag_req, decode_unix_diag_msg): New functions. (netlink_diag_decoder_t): New typedef. (diag_decoders): New array. (decode_netlink_sock_diag): Use it. * xlat/tcp_state_flags.in: New file. * xlat/tcp_states.in: Likewise. * xlat/unix_diag_show.in: Likewise. Co-authored-by: Fabien Siron Co-authored-by: JingPiao Chen --- defs.h | 1 + linux/unix_diag.h | 4 ++ netlink_sock_diag.c | 103 +++++++++++++++++++++++++++++++++++++++- xlat/tcp_state_flags.in | 13 +++++ xlat/tcp_states.in | 12 +++++ xlat/unix_diag_show.in | 6 +++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 xlat/tcp_state_flags.in create mode 100644 xlat/tcp_states.in create mode 100644 xlat/unix_diag_show.in diff --git a/defs.h b/defs.h index ddf80229..3b60d3d4 100644 --- a/defs.h +++ b/defs.h @@ -300,6 +300,7 @@ extern const struct xlat resource_flags[]; extern const struct xlat setns_types[]; extern const struct xlat sg_io_info[]; extern const struct xlat socketlayers[]; +extern const struct xlat socktypes[]; extern const struct xlat whence_codes[]; /* Format of syscall return values */ diff --git a/linux/unix_diag.h b/linux/unix_diag.h index 0c3da5bb..a6b62bab 100644 --- a/linux/unix_diag.h +++ b/linux/unix_diag.h @@ -12,7 +12,11 @@ struct unix_diag_req { }; #define UDIAG_SHOW_NAME 0x01 +#define UDIAG_SHOW_VFS 0x02 #define UDIAG_SHOW_PEER 0x04 +#define UDIAG_SHOW_ICONS 0x08 +#define UDIAG_SHOW_RQLEN 0x10 +#define UDIAG_SHOW_MEMINFO 0x20 struct unix_diag_msg { uint8_t udiag_family; diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c index 29c09f3d..4687b119 100644 --- a/netlink_sock_diag.c +++ b/netlink_sock_diag.c @@ -29,6 +29,15 @@ #include "defs.h" +#include +#include +#include + +#include "xlat/tcp_states.h" +#include "xlat/tcp_state_flags.h" + +#include "xlat/unix_diag_show.h" + static void decode_family(struct tcb *const tcp, const uint8_t family, const kernel_ulong_t addr, const kernel_ulong_t len) @@ -43,6 +52,84 @@ decode_family(struct tcb *const tcp, const uint8_t family, tprints("}"); } +static void +decode_unix_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 unix_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)) { + tprintf("sdiag_protocol=%" PRIu8 ", udiag_states=", + req.sdiag_protocol); + printflags(tcp_state_flags, req.udiag_states, + "1<= sizeof(msg)) { + if (!umoven_or_printaddr(tcp, addr + offset, + sizeof(msg) - offset, + (void *) &msg + offset)) { + tprints("udiag_type="); + printxval(socktypes, msg.udiag_type, "SOCK_???"); + tprintf(", udiag_state="); + printxval(tcp_states, msg.udiag_state, "TCP_???"); + tprintf(", udiag_ino=%" PRIu32 + ", udiag_cookie=[%" PRIu32 ", %" PRIu32 "]", + msg.udiag_ino, + msg.udiag_cookie[0], msg.udiag_cookie[1]); + } + } else + tprints("..."); + tprints("}"); +} + +typedef void (*netlink_diag_decoder_t)(struct tcb *, + const struct nlmsghdr *, + uint8_t family, + kernel_ulong_t addr, + kernel_ulong_t len); + +static const struct { + const netlink_diag_decoder_t request, response; +} diag_decoders[] = { + [AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg } +}; + bool decode_netlink_sock_diag(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, @@ -51,8 +138,22 @@ decode_netlink_sock_diag(struct tcb *const tcp, { uint8_t family; - if (!umove_or_printaddr(tcp, addr, &family)) + if (!umove_or_printaddr(tcp, addr, &family)) { + if (family < ARRAY_SIZE(diag_decoders) + && len > sizeof(family)) { + const netlink_diag_decoder_t decoder = + (nlmsghdr->nlmsg_flags & NLM_F_REQUEST) + ? diag_decoders[family].request + : diag_decoders[family].response; + + if (decoder) { + decoder(tcp, nlmsghdr, family, addr, len); + return true; + } + } + decode_family(tcp, family, addr, len); + } return true; } diff --git a/xlat/tcp_state_flags.in b/xlat/tcp_state_flags.in new file mode 100644 index 00000000..8b63c158 --- /dev/null +++ b/xlat/tcp_state_flags.in @@ -0,0 +1,13 @@ +/* this file should be included after xlat/tcp_states.h */ +1<