All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft 1/2] expressions: concat: add typeof support
@ 2020-02-26 12:26 Florian Westphal
  2020-02-26 12:26 ` [PATCH nft 2/2] tests: update nat_addr_port with typeof+concat maps Florian Westphal
  2020-02-26 12:31 ` [PATCH nft 1/2] expressions: concat: add typeof support Pablo Neira Ayuso
  0 siblings, 2 replies; 3+ messages in thread
From: Florian Westphal @ 2020-02-26 12:26 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Previous patches allow to pass concatenations as the mapped-to
data type.

This doesn't work with typeof() because the concat expression has
no support to store the typeof data in the kernel, leading to:

map t2 {
    typeof numgen inc mod 2 : ip daddr . tcp dport

being shown as
     type 0 : ipv4_addr . inet_service

... which can't be parsed back by nft.

This allows the concat expression to store the sub-expressions
in set of nested attributes.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 src/expression.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/src/expression.c b/src/expression.c
index a2694f4ab0e4..863cf86ec1d0 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -829,6 +829,140 @@ static void concat_expr_print(const struct expr *expr, struct output_ctx *octx)
 	compound_expr_print(expr, " . ", octx);
 }
 
+#define NFTNL_UDATA_SET_KEY_CONCAT_NEST 0
+#define NFTNL_UDATA_SET_KEY_CONCAT_NEST_MAX  NFT_REG32_SIZE
+
+#define NFTNL_UDATA_SET_KEY_CONCAT_SUB_TYPE 0
+#define NFTNL_UDATA_SET_KEY_CONCAT_SUB_DATA 1
+#define NFTNL_UDATA_SET_KEY_CONCAT_SUB_MAX  2
+
+static int concat_expr_build_udata(struct nftnl_udata_buf *udbuf,
+				    const struct expr *concat_expr)
+{
+	struct nftnl_udata *nest;
+	unsigned int i = 0;
+	struct expr *expr;
+
+	list_for_each_entry(expr, &concat_expr->expressions, list) {
+		struct nftnl_udata *nest_expr;
+		int err;
+
+		if (!expr_ops(expr)->build_udata || i >= NFT_REG32_SIZE)
+			return -1;
+
+		nest = nftnl_udata_nest_start(udbuf, NFTNL_UDATA_SET_KEY_CONCAT_NEST + i);
+		nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_CONCAT_SUB_TYPE, expr->etype);
+		nest_expr = nftnl_udata_nest_start(udbuf, NFTNL_UDATA_SET_KEY_CONCAT_SUB_DATA);
+		err = expr_ops(expr)->build_udata(udbuf, expr);
+		if (err < 0)
+			return err;
+		nftnl_udata_nest_end(udbuf, nest_expr);
+		nftnl_udata_nest_end(udbuf, nest);
+		i++;
+	}
+
+	return 0;
+}
+
+static int concat_parse_udata_nest(const struct nftnl_udata *attr, void *data)
+{
+	const struct nftnl_udata **ud = data;
+	uint8_t type = nftnl_udata_type(attr);
+	uint8_t len = nftnl_udata_len(attr);
+
+	if (type >= NFTNL_UDATA_SET_KEY_CONCAT_NEST_MAX)
+		return -1;
+
+	if (len <= sizeof(uint32_t))
+		return -1;
+
+	ud[type] = attr;
+	return 0;
+}
+
+static int concat_parse_udata_nested(const struct nftnl_udata *attr, void *data)
+{
+	const struct nftnl_udata **ud = data;
+	uint8_t type = nftnl_udata_type(attr);
+	uint8_t len = nftnl_udata_len(attr);
+
+	switch (type) {
+	case NFTNL_UDATA_SET_KEY_CONCAT_SUB_TYPE:
+		if (len != sizeof(uint32_t))
+			return -1;
+		break;
+	case NFTNL_UDATA_SET_KEY_CONCAT_SUB_DATA:
+		if (len <= sizeof(uint32_t))
+			return -1;
+		break;
+	default:
+		return 0;
+	}
+
+	ud[type] = attr;
+	return 0;
+}
+
+static struct expr *concat_expr_parse_udata(const struct nftnl_udata *attr)
+{
+	const struct nftnl_udata *ud[NFTNL_UDATA_SET_KEY_CONCAT_NEST_MAX] = {};
+	struct expr *concat_expr;
+	struct datatype *dtype;
+	unsigned int i;
+	int err;
+
+	err = nftnl_udata_parse(nftnl_udata_get(attr), nftnl_udata_len(attr),
+				concat_parse_udata_nest, ud);
+	if (err < 0)
+		return NULL;
+
+	concat_expr = concat_expr_alloc(&internal_location);
+	if (!concat_expr)
+		return NULL;
+
+	dtype = xzalloc(sizeof(*dtype));
+
+	for (i = 0; i < array_size(ud); i++) {
+		const struct nftnl_udata *nest_ud[NFTNL_UDATA_SET_KEY_CONCAT_SUB_MAX];
+		const struct nftnl_udata *nested, *subdata;
+		const struct expr_ops *ops;
+		struct expr *expr;
+		uint32_t etype;
+
+		if (ud[NFTNL_UDATA_SET_KEY_CONCAT_NEST + i] == NULL)
+			break;
+
+		nested = ud[NFTNL_UDATA_SET_KEY_CONCAT_NEST + i];
+		err = nftnl_udata_parse(nftnl_udata_get(nested), nftnl_udata_len(nested),
+					concat_parse_udata_nested, nest_ud);
+		if (err < 0)
+			goto err_free;
+
+		etype = nftnl_udata_get_u32(nest_ud[NFTNL_UDATA_SET_KEY_CONCAT_SUB_TYPE]);
+		ops = expr_ops_by_type(etype);
+		if (!ops || !ops->parse_udata)
+			goto err_free;
+
+		subdata = nest_ud[NFTNL_UDATA_SET_KEY_CONCAT_SUB_DATA];
+		expr = ops->parse_udata(subdata);
+		if (!expr)
+			goto err_free;
+
+		dtype->subtypes++;
+		compound_expr_add(concat_expr, expr);
+		dtype->size += round_up(expr->len, BITS_PER_BYTE * sizeof(uint32_t));
+	}
+
+	concat_expr->dtype = dtype;
+	concat_expr->len = dtype->size;
+
+	return concat_expr;
+
+err_free:
+	expr_free(concat_expr);
+	return NULL;
+}
+
 static const struct expr_ops concat_expr_ops = {
 	.type		= EXPR_CONCAT,
 	.name		= "concat",
@@ -836,6 +970,8 @@ static const struct expr_ops concat_expr_ops = {
 	.json		= concat_expr_json,
 	.clone		= compound_expr_clone,
 	.destroy	= concat_expr_destroy,
+	.build_udata	= concat_expr_build_udata,
+	.parse_udata	= concat_expr_parse_udata,
 };
 
 struct expr *concat_expr_alloc(const struct location *loc)
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH nft 2/2] tests: update nat_addr_port with typeof+concat maps
  2020-02-26 12:26 [PATCH nft 1/2] expressions: concat: add typeof support Florian Westphal
@ 2020-02-26 12:26 ` Florian Westphal
  2020-02-26 12:31 ` [PATCH nft 1/2] expressions: concat: add typeof support Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Florian Westphal @ 2020-02-26 12:26 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 .../testcases/maps/dumps/nat_addr_port.nft    | 40 +++++++++++++++++++
 tests/shell/testcases/maps/nat_addr_port      | 40 +++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/tests/shell/testcases/maps/dumps/nat_addr_port.nft b/tests/shell/testcases/maps/dumps/nat_addr_port.nft
index 210cab7f6b00..89c3bd145b4d 100644
--- a/tests/shell/testcases/maps/dumps/nat_addr_port.nft
+++ b/tests/shell/testcases/maps/dumps/nat_addr_port.nft
@@ -1,4 +1,12 @@
 table ip ipfoo {
+	map t1 {
+		typeof numgen inc mod 2 : ip daddr
+	}
+
+	map t2 {
+		typeof numgen inc mod 2 : ip daddr . tcp dport
+	}
+
 	map x {
 		type ipv4_addr : ipv4_addr
 	}
@@ -21,9 +29,19 @@ table ip ipfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat to 10.2.3.4:4242
 		meta l4proto tcp dnat ip addr . port to ip saddr map @y
 		dnat ip addr . port to ip saddr . tcp dport map @z
+		dnat to numgen inc mod 2 map @t1
+		meta l4proto tcp dnat ip addr . port to numgen inc mod 2 map @t2
 	}
 }
 table ip6 ip6foo {
+	map t1 {
+		typeof numgen inc mod 2 : ip6 daddr
+	}
+
+	map t2 {
+		typeof numgen inc mod 2 : ip6 daddr . tcp dport
+	}
+
 	map x {
 		type ipv6_addr : ipv6_addr
 	}
@@ -44,9 +62,27 @@ table ip6 ip6foo {
 		ip6 saddr dead::2 tcp dport 42 dnat to [c0::1a]:4242
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr map @y
 		dnat ip6 addr . port to ip6 saddr . tcp dport map @z
+		dnat to numgen inc mod 2 map @t1
+		meta l4proto tcp dnat ip6 addr . port to numgen inc mod 2 map @t2
 	}
 }
 table inet inetfoo {
+	map t1v4 {
+		typeof numgen inc mod 2 : ip daddr
+	}
+
+	map t2v4 {
+		typeof numgen inc mod 2 : ip daddr . tcp dport
+	}
+
+	map t1v6 {
+		typeof numgen inc mod 2 : ip6 daddr
+	}
+
+	map t2v6 {
+		typeof numgen inc mod 2 : ip6 daddr . tcp dport
+	}
+
 	map x4 {
 		type ipv4_addr : ipv4_addr
 	}
@@ -80,10 +116,14 @@ table inet inetfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat ip to 10.2.3.4:4242
 		meta l4proto tcp meta nfproto ipv4 dnat ip addr . port to ip saddr map @y4
 		meta nfproto ipv4 dnat ip addr . port to ip saddr . tcp dport map @z4
+		dnat ip to numgen inc mod 2 map @t1v4
+		meta l4proto tcp dnat ip addr . port to numgen inc mod 2 map @t2v4
 		dnat ip6 to ip6 daddr map @x6
 		ip6 saddr dead::1 dnat ip6 to feed::1
 		ip6 saddr dead::2 tcp dport 42 dnat ip6 to [c0::1a]:4242
 		meta l4proto tcp meta nfproto ipv6 dnat ip6 addr . port to ip6 saddr map @y6
 		meta nfproto ipv6 dnat ip6 addr . port to ip6 saddr . tcp dport map @z6
+		dnat ip6 to numgen inc mod 2 map @t1v6
+		meta l4proto tcp dnat ip6 addr . port to numgen inc mod 2 map @t2v6
 	}
 }
diff --git a/tests/shell/testcases/maps/nat_addr_port b/tests/shell/testcases/maps/nat_addr_port
index a8d970e5e5ef..2804d48ca406 100755
--- a/tests/shell/testcases/maps/nat_addr_port
+++ b/tests/shell/testcases/maps/nat_addr_port
@@ -3,6 +3,14 @@
 # skeleton
 $NFT -f /dev/stdin <<EOF || exit 1
 table ip ipfoo {
+	map t1 {
+		typeof numgen inc mod 2 : ip daddr;
+	}
+
+	map t2 {
+		typeof numgen inc mod 2 : ip daddr . tcp dport
+	}
+
 	map x {
 		type ipv4_addr : ipv4_addr
 	}
@@ -23,6 +31,8 @@ table ip ipfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat to 10.2.3.4:4242
 		meta l4proto tcp dnat ip addr . port to ip saddr map @y
 		meta l4proto tcp dnat ip addr . port to ip saddr . tcp dport map @z
+		dnat ip to numgen inc mod 2 map @t1
+		meta l4proto tcp dnat ip addr . port to numgen inc mod 2 map @t2
 	}
 }
 EOF
@@ -36,6 +46,14 @@ $NFT add rule 'ip ipfoo c dnat to ip daddr map @y' && exit 1
 # skeleton 6
 $NFT -f /dev/stdin <<EOF || exit 1
 table ip6 ip6foo {
+	map t1 {
+		typeof numgen inc mod 2 : ip6 daddr;
+	}
+
+	map t2 {
+		typeof numgen inc mod 2 : ip6 daddr . tcp dport
+	}
+
 	map x {
 		type ipv6_addr : ipv6_addr
 	}
@@ -54,6 +72,8 @@ table ip6 ip6foo {
 		ip6 saddr dead::2 tcp dport 42 dnat to [c0::1a]:4242
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr map @y
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr . tcp dport map @z
+		dnat ip6 to numgen inc mod 2 map @t1
+		meta l4proto tcp dnat ip6 addr . port to numgen inc mod 2 map @t2
 	}
 }
 EOF
@@ -67,6 +87,22 @@ $NFT add rule 'ip6 ip6foo c dnat to ip daddr map @y' && exit 1
 # skeleton inet
 $NFT -f /dev/stdin <<EOF || exit 1
 table inet inetfoo {
+	map t1v4 {
+		typeof numgen inc mod 2 : ip daddr
+	}
+
+	map t2v4 {
+		typeof numgen inc mod 2 : ip daddr . tcp dport;
+	}
+
+	map t1v6 {
+		typeof numgen inc mod 2 : ip6 daddr;
+	}
+
+	map t2v6 {
+		typeof numgen inc mod 2 : ip6 daddr . tcp dport
+	}
+
 	map x4 {
 		type ipv4_addr : ipv4_addr
 	}
@@ -95,11 +131,15 @@ table inet inetfoo {
 		ip saddr 10.1.1.2 tcp dport 42 dnat to 10.2.3.4:4242
 		meta l4proto tcp dnat ip addr . port to ip saddr map @y4
 		meta l4proto tcp dnat ip addr . port to ip saddr . tcp dport map @z4
+		dnat ip to numgen inc mod 2 map @t1v4
+		meta l4proto tcp dnat ip addr . port to numgen inc mod 2 map @t2v4
 		dnat ip6 to ip6 daddr map @x6
 		ip6 saddr dead::1 dnat to feed::1
 		ip6 saddr dead::2 tcp dport 42 dnat to [c0::1a]:4242
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr map @y6
 		meta l4proto tcp dnat ip6 addr . port to ip6 saddr . tcp dport map @z6
+		dnat ip6 to numgen inc mod 2 map @t1v6
+		meta l4proto tcp dnat ip6 addr . port to numgen inc mod 2 map @t2v6
 	}
 }
 EOF
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH nft 1/2] expressions: concat: add typeof support
  2020-02-26 12:26 [PATCH nft 1/2] expressions: concat: add typeof support Florian Westphal
  2020-02-26 12:26 ` [PATCH nft 2/2] tests: update nat_addr_port with typeof+concat maps Florian Westphal
@ 2020-02-26 12:31 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2020-02-26 12:31 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Wed, Feb 26, 2020 at 01:26:26PM +0100, Florian Westphal wrote:
> Previous patches allow to pass concatenations as the mapped-to
> data type.
> 
> This doesn't work with typeof() because the concat expression has
> no support to store the typeof data in the kernel, leading to:
> 
> map t2 {
>     typeof numgen inc mod 2 : ip daddr . tcp dport
> 
> being shown as
>      type 0 : ipv4_addr . inet_service
> 
> ... which can't be parsed back by nft.
> 
> This allows the concat expression to store the sub-expressions
> in set of nested attributes.

LGTM, thanks Florian.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-02-26 12:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-26 12:26 [PATCH nft 1/2] expressions: concat: add typeof support Florian Westphal
2020-02-26 12:26 ` [PATCH nft 2/2] tests: update nat_addr_port with typeof+concat maps Florian Westphal
2020-02-26 12:31 ` [PATCH nft 1/2] expressions: concat: add typeof support Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.