[PATCH v4 09/11] netlink: decode AF_INET inet_diag_req attributes

Dmitry V. Levin ldv at altlinux.org
Mon Jul 10 11:06:35 UTC 2017


On Thu, Jul 06, 2017 at 09:57:35AM +0800, JingPiao Chen wrote:
> * netlink_sock_diag.c: Include "xlat/inet_diag_bytecodes.h".
> (decode_inet_addr, decode_inet_diag_hostcond,
> print_inet_diag_bc_op, decode_inet_diag_markcond,
> decode_bytecode_data, decode_inet_diag_bc_op): New functions.
> (inet_diag_req_nla_decoders): New array.
> (decode_inet_diag_req_compat, decode_inet_diag_req_v2): Use it.
> * linux/inet_diag.h (inet_diag_bc_op, inet_diag_hostcond,
> inet_diag_markcond): New structures.
> (INET_DIAG_BC_*): New enum.
> * xlat/inet_diag_bytecodes.in: New file.
> ---
>  linux/inet_diag.h           |  32 ++++++++
>  netlink_sock_diag.c         | 188 +++++++++++++++++++++++++++++++++++++++++++-
>  xlat/inet_diag_bytecodes.in |  12 +++
>  3 files changed, 230 insertions(+), 2 deletions(-)
>  create mode 100644 xlat/inet_diag_bytecodes.in
> 
> diff --git a/linux/inet_diag.h b/linux/inet_diag.h
> index 24302db..ec6356c 100644
> --- a/linux/inet_diag.h
> +++ b/linux/inet_diag.h
> @@ -39,6 +39,38 @@ enum {
>  	INET_DIAG_REQ_BYTECODE,
>  };
>  
> +struct inet_diag_bc_op {
> +	unsigned char code;
> +	unsigned char yes;
> +	unsigned short no;
> +};
> +
> +enum {
> +	INET_DIAG_BC_NOP,
> +	INET_DIAG_BC_JMP,
> +	INET_DIAG_BC_S_GE,
> +	INET_DIAG_BC_S_LE,
> +	INET_DIAG_BC_D_GE,
> +	INET_DIAG_BC_D_LE,
> +	INET_DIAG_BC_AUTO,
> +	INET_DIAG_BC_S_COND,
> +	INET_DIAG_BC_D_COND,
> +	INET_DIAG_BC_DEV_COND,   /* u32 ifindex */
> +	INET_DIAG_BC_MARK_COND,
> +};
> +
> +struct inet_diag_hostcond {
> +	uint8_t family;
> +	uint8_t prefix_len;
> +	int port;
> +	uint32_t addr[0];
> +};
> +
> +struct inet_diag_markcond {
> +	uint32_t mark;
> +	uint32_t mask;
> +};
> +
>  /* Info structure */
>  struct inet_diag_msg {
>  	uint8_t idiag_family;
> diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c
> index 42860aa..29d61cb 100644
> --- a/netlink_sock_diag.c
> +++ b/netlink_sock_diag.c
> @@ -43,6 +43,7 @@
>  #include <linux/unix_diag.h>
>  
>  #include "xlat/inet_diag_attrs.h"
> +#include "xlat/inet_diag_bytecodes.h"
>  #include "xlat/inet_diag_extended_flags.h"
>  #include "xlat/inet_diag_req_attrs.h"
>  
> @@ -620,6 +621,187 @@ print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
>  }
>  
>  static void
> +decode_inet_addr(struct tcb *const tcp,
> +		 const kernel_ulong_t addr,
> +		 const kernel_ulong_t len,
> +		 const int family)
> +{
> +	switch (family) {
> +	case AF_INET: {
> +		struct in_addr in_addr;
> +
> +		if (len < sizeof(in_addr)) {
> +			printstrn(tcp, addr, len);

The "addr=" prefix is lost.
Don't you think QUOTE_FORCE_HEX would be better?

> +			break;
> +		}
> +
> +		if (umove_or_printaddr(tcp, addr, &in_addr))
> +			break;

The "addr=" prefix is lost.

> +
> +		print_inet_addr(family, &in_addr.s_addr,
> +				sizeof(in_addr.s_addr), "addr.s_addr");

Why .s_addr?

> +		break;
> +	}
> +	case AF_INET6: {
> +		struct in6_addr in6_addr;
> +
> +		if (len < sizeof(in6_addr)) {
> +			printstrn(tcp, addr, len);

The "addr=" prefix is lost.
Don't you think QUOTE_FORCE_HEX would be better?

> +			break;
> +		}
> +		if (umove_or_printaddr(tcp, addr, &in6_addr))
> +			break;

The "addr=" prefix is lost.

> +
> +		print_inet_addr(family, in6_addr.s6_addr,
> +				sizeof(in6_addr.s6_addr),"addr.s6_addr");

Why .s6_addr?

> +		break;
> +	}
> +	default:
> +		tprints("addr=");
> +		printstrn(tcp, addr, len);
> +		break;
> +	}
> +}

	union {
		struct in_addr  a4;
		struct in6_addr a6;
	} addr;
	size_t size = 0;

	switch (family) {
	case AF_INET:
		size = sizeof(addr.a4);
		break;
	case AF_INET6:
		size = sizeof(addr.a6);
		break;
	}

	if (!size || len < size) {
		tprints("addr=");
		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
		return;
	}

	if (umoven(tcp, addr, size, &addr) < 0) {
		tprints("addr=");
		printaddr(addr);
		return;
	}

	print_inet_addr(family, &addr, size, "addr");,

> +static void
> +decode_inet_diag_hostcond(struct tcb *const tcp,
> +			  const kernel_ulong_t addr,
> +			  const kernel_ulong_t len)
> +{
> +	struct inet_diag_hostcond cond;
> +
> +	if (len < sizeof(cond)) {
> +		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
> +		return;
> +	}
> +	if (umove_or_printaddr(tcp, addr, &cond))
> +		return;
> +
> +	PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???");
> +	PRINT_FIELD_U(", ", cond, prefix_len);
> +	PRINT_FIELD_U(", ", cond, port);
> +
> +	if (len > sizeof(cond)) {
> +		tprints(", ");
> +		decode_inet_addr(tcp, addr + sizeof(cond),
> +				 len - sizeof(cond), cond.family);
> +	}
> +	tprints("}");
> +}
> +
> +static void
> +print_inet_diag_bc_op(const struct inet_diag_bc_op *const op)
> +{
> +	PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes,
> +			 "INET_DIAG_BC_???");
> +	PRINT_FIELD_U(", ", *op, yes);
> +	PRINT_FIELD_U(", ", *op, no);
> +	tprints("}");
> +}
> +
> +static void
> +decode_inet_diag_markcond(struct tcb *const tcp,
> +			  const kernel_ulong_t addr,
> +			  const kernel_ulong_t len)
> +{
> +	struct inet_diag_markcond markcond;
> +
> +	if (len < sizeof(markcond)) {
> +		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
> +		return;
> +	}
> +	if (umove_or_printaddr(tcp, addr, &markcond))
> +		return;
> +
> +	PRINT_FIELD_U("{", markcond, mark);
> +	PRINT_FIELD_U(", ", markcond, mask);
> +	tprints("}");
> +}
> +
> +static void
> +decode_bytecode_data(struct tcb *const tcp,
> +		     const kernel_ulong_t addr,
> +		     const kernel_ulong_t len,
> +		     const unsigned char code)
> +{
> +	switch (code) {
> +	case INET_DIAG_BC_S_COND:
> +	case INET_DIAG_BC_D_COND:
> +		decode_inet_diag_hostcond(tcp, addr, len);
> +		break;
> +	case INET_DIAG_BC_DEV_COND: {
> +		uint32_t ifindex;
> +
> +		if (len < sizeof(ifindex)) {
> +			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
> +			break;
> +		}
> +		if (umove_or_printaddr(tcp, addr, &ifindex))
> +			break;
> +
> +		tprintf("%" PRIu32, ifindex);

Use print_ifindex.

> +		break;
> +	}
> +	case INET_DIAG_BC_S_GE:
> +	case INET_DIAG_BC_S_LE:
> +	case INET_DIAG_BC_D_GE:
> +	case INET_DIAG_BC_D_LE: {
> +		struct inet_diag_bc_op op;
> +
> +		if (len < sizeof(op)) {
> +			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
> +			break;
> +		}
> +		if (umove_or_printaddr(tcp, addr, &op))
> +			break;
> +
> +		print_inet_diag_bc_op(&op);

		if (len < sizeof(op))
			printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
		else if (!umove_or_printaddr(tcp, addr, &op))
			print_inet_diag_bc_op(&op);

This is shorter, isn't it?

> +		break;
> +	}
> +	case INET_DIAG_BC_MARK_COND:
> +		decode_inet_diag_markcond(tcp, addr, len);
> +		break;
> +	case INET_DIAG_BC_AUTO:
> +	case INET_DIAG_BC_JMP:
> +	case INET_DIAG_BC_NOP:
> +	default:
> +		printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
> +		break;
> +	}
> +}
> +
> +static bool
> +decode_inet_diag_bc_op(struct tcb *const tcp,
> +		       const kernel_ulong_t addr,
> +		       const kernel_ulong_t len,
> +		       const void *const opaque_data)
> +{
> +	struct inet_diag_bc_op op;
> +
> +	if (len < sizeof(op))
> +		return false;
> +	if (umove_or_printaddr(tcp, addr, &op))
> +		return true;
> +
> +	if (len > sizeof(op))
> +		tprints("{");
> +
> +	print_inet_diag_bc_op(&op);
> +	if (len > sizeof(op)) {
> +		tprints(", ");
> +		decode_bytecode_data(tcp, addr + sizeof(op),
> +				     len - sizeof(op), op.code);
> +		tprints("}");
> +	}
> +
> +	return true;
> +}
> +
> +static const nla_decoder_t inet_diag_req_nla_decoders[] = {
> +	[INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op
> +};
> +
> +static void
>  decode_inet_diag_req_compat(struct tcb *const tcp,
>  			    const struct nlmsghdr *const nlmsghdr,
>  			    const uint8_t family,
> @@ -657,7 +839,8 @@ decode_inet_diag_req_compat(struct tcb *const tcp,
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
>  			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
> -			      NULL, 0, NULL);
> +			      inet_diag_req_nla_decoders,
> +			      ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
>  	}
>  }
>  
> @@ -698,7 +881,8 @@ decode_inet_diag_req_v2(struct tcb *const tcp,
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
>  			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
> -			      NULL, 0, NULL);
> +			      inet_diag_req_nla_decoders,
> +			      ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
>  	}
>  }
>  
> diff --git a/xlat/inet_diag_bytecodes.in b/xlat/inet_diag_bytecodes.in
> new file mode 100644
> index 0000000..ccaf0da
> --- /dev/null
> +++ b/xlat/inet_diag_bytecodes.in
> @@ -0,0 +1,12 @@
> +#unconditional
> +INET_DIAG_BC_NOP
> +INET_DIAG_BC_JMP
> +INET_DIAG_BC_S_GE
> +INET_DIAG_BC_S_LE
> +INET_DIAG_BC_D_GE
> +INET_DIAG_BC_D_LE
> +INET_DIAG_BC_AUTO
> +INET_DIAG_BC_S_COND
> +INET_DIAG_BC_D_COND
> +INET_DIAG_BC_DEV_COND
> +INET_DIAG_BC_MARK_COND

In summary, not bad but needs corrections.


-- 
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/20170710/8156e0fe/attachment.bin>


More information about the Strace-devel mailing list