* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).