[PATCH] netlink: add a basic netlink socket diag parser
Dmitry V. Levin
ldv at altlinux.org
Mon Jun 12 23:40:56 UTC 2017
On Mon, Jul 11, 2016 at 01:52:27PM +0000, Fabien Siron wrote:
> * Makefile.am (strace_SOURCES): Add netlink_sock_diag.c.
> (EXTRA_DIST): Add linux/packet_diag.h and linux/smc_diag.h.
> * defs.h (ethernet_protocols, inet_protocols)
> (socktypes): New xlat prototype.
> (decode_netlink_sock_diag): New prototype.
> * netlink.c (decode_specific_proto): New function.
> (decode_specific_proto): Use decode_netlink_sock_diag.
> (decode_payload): Use decode_specific_proto.
> * netlink_sock_diag.c: New file.
> * linux/inet_diag.h: Import linux headers.
> * linux/netlink_diag.h: Likewise.
> * linux/unix_diag.h: Likewise.
> * linux/packet_diag.h: New file.
> * linux/smc_diag.h: Likewise.
> * xlat/inet_diag_extended_flags.in: Likewise.
> * xlat/netlink_diag_show.in: Likewise.
> * xlat/netlink_sock_states.in: Likewise.
> * xlat/packet_diag_show.in: Likewise.
> * xlat/smc_diag_extended_flags.in: Likewise.
> * xlat/smc_sock_states.in: Likewise.
> * xlat/tcp_sock_state_flags.in: Likewise.
> * xlat/tcp_sock_states.in: Likewise.
> * xlat/unix_diag_show.in: Likewise.
>
> Co-authored-by: JingPiao Chen <chenjingpiao at gmail.com>
> ---
> Makefile.am | 3 +
> defs.h | 6 +
> linux/inet_diag.h | 36 +++-
> linux/netlink_diag.h | 3 +
> linux/packet_diag.h | 29 +++
> linux/smc_diag.h | 40 ++++
> linux/unix_diag.h | 8 +-
> netlink.c | 20 ++
> netlink_sock_diag.c | 403 +++++++++++++++++++++++++++++++++++++++
> xlat/inet_diag_extended_flags.in | 16 ++
> xlat/netlink_diag_show.in | 3 +
> xlat/netlink_sock_states.in | 2 +
> xlat/packet_diag_show.in | 6 +
> xlat/smc_diag_extended_flags.in | 2 +
> xlat/smc_sock_states.in | 12 ++
> xlat/tcp_sock_state_flags.in | 12 ++
> xlat/tcp_sock_states.in | 12 ++
> xlat/unix_diag_show.in | 6 +
> 18 files changed, 616 insertions(+), 3 deletions(-)
> create mode 100644 linux/packet_diag.h
> create mode 100644 linux/smc_diag.h
> create mode 100644 netlink_sock_diag.c
> create mode 100644 xlat/inet_diag_extended_flags.in
> create mode 100644 xlat/netlink_diag_show.in
> create mode 100644 xlat/netlink_sock_states.in
> create mode 100644 xlat/packet_diag_show.in
> create mode 100644 xlat/smc_diag_extended_flags.in
> create mode 100644 xlat/smc_sock_states.in
> create mode 100644 xlat/tcp_sock_state_flags.in
> create mode 100644 xlat/tcp_sock_states.in
> create mode 100644 xlat/unix_diag_show.in
First of all, the change is too big.
> diff --git a/Makefile.am b/Makefile.am
> index 3d6eba1..52d62f0 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -172,6 +172,7 @@ strace_SOURCES = \
> native_defs.h \
> net.c \
> netlink.c \
> + netlink_sock_diag.c \
> nsfs.c \
> nsfs.h \
> nsig.h \
> @@ -562,6 +563,7 @@ EXTRA_DIST = \
> linux/or1k/set_scno.c \
> linux/or1k/syscallent.h \
> linux/or1k/userent.h \
> + linux/packet_diag.h \
> linux/personality.h \
> linux/powerpc/arch_regs.c \
> linux/powerpc/arch_regs.h \
> @@ -678,6 +680,7 @@ EXTRA_DIST = \
> linux/sh64/syscallent.h \
> linux/sh64/userent.h \
> linux/signalent.h \
> + linux/smc_diag.h \
> linux/sock_diag.h \
> linux/sparc/arch_getrval2.c \
> linux/sparc/arch_regs.c \
> diff --git a/defs.h b/defs.h
> index 6449bce..6b2167a 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -291,7 +291,9 @@ extern const struct xlat addrfams[];
> extern const struct xlat at_flags[];
> extern const struct xlat clocknames[];
> extern const struct xlat dirent_types[];
> +extern const struct xlat ethernet_protocols[];
> extern const struct xlat evdev_abs[];
> +extern const struct xlat inet_protocols[];
> extern const struct xlat msg_flags[];
> extern const struct xlat netlink_protocols[];
> extern const struct xlat open_access_modes[];
> @@ -300,6 +302,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 */
> @@ -627,6 +630,9 @@ tprint_iov_upto(struct tcb *, kernel_ulong_t len, kernel_ulong_t addr,
>
> extern void
> decode_netlink(struct tcb *, int fd, kernel_ulong_t addr, kernel_ulong_t len);
> +extern bool
> +decode_netlink_sock_diag(struct tcb *, kernel_ulong_t addr,
> + kernel_ulong_t len, unsigned int, int);
>
> extern void tprint_open_modes(unsigned int);
> extern const char *sprint_open_modes(unsigned int);
> diff --git a/linux/inet_diag.h b/linux/inet_diag.h
> index 69012af..7302c87 100644
> --- a/linux/inet_diag.h
> +++ b/linux/inet_diag.h
> @@ -14,7 +14,17 @@ struct inet_diag_sockid {
> uint32_t idiag_cookie[2];
> };
>
> -/* Request structure */
> +/* Request structures */
> +struct inet_diag_req {
> + uint8_t idiag_family;
> + uint8_t idiag_src_len;
> + uint8_t idiag_dst_len;
> + uint8_t idiag_ext;
> + struct inet_diag_sockid id;
> + uint32_t idiag_states;
> + uint32_t idiag_dbs;
> +};
> +
> struct inet_diag_req_v2 {
> uint8_t sdiag_family;
> uint8_t sdiag_protocol;
> @@ -40,4 +50,28 @@ struct inet_diag_msg {
> uint32_t idiag_inode;
> };
>
> +/* Extensions */
> +enum {
> + INET_DIAG_NONE,
> + INET_DIAG_MEMINFO,
> + INET_DIAG_INFO,
> + INET_DIAG_VEGASINFO,
> + INET_DIAG_CONG,
> + INET_DIAG_TOS,
> + INET_DIAG_TCLASS,
> + INET_DIAG_SKMEMINFO,
> + INET_DIAG_SHUTDOWN,
> + INET_DIAG_DCTCPINFO,
> + INET_DIAG_PROTOCOL, /* response attribute only */
> + INET_DIAG_SKV6ONLY,
> + INET_DIAG_LOCALS,
> + INET_DIAG_PEERS,
> + INET_DIAG_PAD,
> + INET_DIAG_MARK,
> + INET_DIAG_BBRINFO,
> + __INET_DIAG_MAX,
> +};
> +
> +#define INET_DIAG_MAX (__INET_DIAG_MAX - 1)
> +
> #endif /* !STRACE_LINUX_INET_DIAG_H */
> diff --git a/linux/netlink_diag.h b/linux/netlink_diag.h
> index a52507c..234748c 100644
> --- a/linux/netlink_diag.h
> +++ b/linux/netlink_diag.h
> @@ -24,6 +24,9 @@ struct netlink_diag_msg {
> };
>
> #define NDIAG_SHOW_MEMINFO 0x00000001
> +#define NDIAG_SHOW_GROUPS 0x00000002
> +/* deprecated since 4.6 */
> +#define NDIAG_SHOW_RING_CFG 0x00000004
> #define NDIAG_PROTO_ALL ((uint8_t) ~0)
>
> #endif /* !STRACE_LINUX_NETLINK_DIAG_H */
> diff --git a/linux/packet_diag.h b/linux/packet_diag.h
> new file mode 100644
> index 0000000..24d0694
> --- /dev/null
> +++ b/linux/packet_diag.h
> @@ -0,0 +1,29 @@
> +#ifndef STRACE_LINUX_PACKET_DIAG_H
> +#define STRACE_LINUX_PACKET_DIAG_H
> +
> +struct packet_diag_req {
> + uint8_t sdiag_family;
> + uint8_t sdiag_protocol;
> + uint16_t pad;
> + uint32_t pdiag_ino;
> + uint32_t pdiag_show;
> + uint32_t pdiag_cookie[2];
> +};
> +
> +#define PACKET_SHOW_INFO 0x00000001 /* Basic packet_sk information */
> +#define PACKET_SHOW_MCLIST 0x00000002 /* A set of packet_diag_mclist-s */
> +#define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */
> +#define PACKET_SHOW_FANOUT 0x00000008
> +#define PACKET_SHOW_MEMINFO 0x00000010
> +#define PACKET_SHOW_FILTER 0x00000020
> +
> +struct packet_diag_msg {
> + uint8_t pdiag_family;
> + uint8_t pdiag_type;
> + uint16_t pdiag_num;
> +
> + uint32_t pdiag_ino;
> + uint32_t pdiag_cookie[2];
> +};
> +
> +#endif /* !STRACE_LINUX_PACKET_DIAG_H */
> diff --git a/linux/smc_diag.h b/linux/smc_diag.h
> new file mode 100644
> index 0000000..b7401b8
> --- /dev/null
> +++ b/linux/smc_diag.h
> @@ -0,0 +1,40 @@
> +#ifndef STRACE_LINUX_SMC_DIAG_H
> +#define STRACE_LINUX_SMC_DIAG_H
> +
> +#include <linux/inet_diag.h>
> +
> +/* Request structure */
> +struct smc_diag_req {
> + uint8_t diag_family;
> + uint8_t pad[2];
> + uint8_t diag_ext; /* Query extended information */
> + struct inet_diag_sockid id;
> +};
> +
> +/* Base info structure. It contains socket identity (addrs/ports/cookie) based
> + * on the internal clcsock, and more SMC-related socket data
> + */
> +struct smc_diag_msg {
> + uint8_t diag_family;
> + uint8_t diag_state;
> + uint8_t diag_fallback;
> + uint8_t diag_shutdown;
> + struct inet_diag_sockid id;
> +
> + uint32_t diag_uid;
> + uint64_t diag_inode;
> +};
> +
> +/* Extensions */
> +
> +enum {
> + SMC_DIAG_NONE,
> + SMC_DIAG_CONNINFO,
> + SMC_DIAG_LGRINFO,
> + SMC_DIAG_SHUTDOWN,
> + __SMC_DIAG_MAX,
> +};
> +
> +#define SMC_DIAG_MAX (__SMC_DIAG_MAX - 1)
> +
> +#endif /* !STRACE_LINUX_SMC_DIAG_H */
> diff --git a/linux/unix_diag.h b/linux/unix_diag.h
> index 0c3da5b..f7d3130 100644
> --- a/linux/unix_diag.h
> +++ b/linux/unix_diag.h
> @@ -11,8 +11,12 @@ struct unix_diag_req {
> uint32_t udiag_cookie[2];
> };
>
> -#define UDIAG_SHOW_NAME 0x01
> -#define UDIAG_SHOW_PEER 0x04
> +#define UDIAG_SHOW_NAME 0x00000001 /* show name (not path) */
> +#define UDIAG_SHOW_VFS 0x00000002 /* show VFS inode info */
> +#define UDIAG_SHOW_PEER 0x00000004 /* show peer socket info */
> +#define UDIAG_SHOW_ICONS 0x00000008 /* show pending connections */
> +#define UDIAG_SHOW_RQLEN 0x00000010 /* show skb receive queue len */
> +#define UDIAG_SHOW_MEMINFO 0x00000020 /* show memory info of a socket */
>
> struct unix_diag_msg {
> uint8_t udiag_family;
> diff --git a/netlink.c b/netlink.c
> index 049843d..ad4accb 100644
> --- a/netlink.c
> +++ b/netlink.c
> @@ -274,6 +274,24 @@ decode_nlmsgerr(struct tcb *const tcp,
> tprints("}");
> }
>
> +static bool
> +decode_specific_proto(struct tcb *const tcp,
> + const int family,
> + const struct nlmsghdr *const nlmsghdr,
> + const kernel_ulong_t addr,
> + const kernel_ulong_t len)
> +{
> + switch (family) {
> + case NETLINK_SOCK_DIAG:
> + return decode_netlink_sock_diag(tcp, addr, len,
> + nlmsghdr->nlmsg_type,
> + nlmsghdr->nlmsg_flags &
> + NLM_F_REQUEST);
> + default:
> + return false;
In cases like this an array of functions with the same signature would be
a better choice than a switch statement where every case is a function call.
I've pushed 3 commits to ldv/netlink that demonstrate my idea of netlink
family specific payload decoders, please have a look.
--
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170613/adee799d/attachment.bin>
More information about the Strace-devel
mailing list