[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