[PATCH nft,v2 3/4] src: allow to use integer type header fields via typeof set declaration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Header fields such as udp length cannot be used in concatenations because
it is using the generic integer_type:

 test.nft:3:10-19: Error: can not use variable sized data types (integer) in concat expressions
                typeof udp length . @th,32,32
                       ^^^^^^^^^^~~~~~~~~~~~~

This patch slightly extends ("src: allow to use typeof of raw expressions in
set declaration") to set on NFTNL_UDATA_SET_KEY_PAYLOAD_LEN in userdata if
TYPE_INTEGER is used.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
v2: add more tests.

 src/evaluate.c                                |  2 +-
 src/payload.c                                 | 15 ++++++-----
 .../testcases/maps/dumps/typeof_integer_0.nft | 20 ++++++++++++++
 tests/shell/testcases/maps/typeof_integer_0   | 27 +++++++++++++++++++
 4 files changed, 57 insertions(+), 7 deletions(-)
 create mode 100644 tests/shell/testcases/maps/dumps/typeof_integer_0.nft
 create mode 100755 tests/shell/testcases/maps/typeof_integer_0

diff --git a/src/evaluate.c b/src/evaluate.c
index 61dd4fea10e6..6b3b63662411 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3970,7 +3970,7 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
 			return expr_error(ctx->msgs, i,
 					  "specify either ip or ip6 for address matching");
 
-		if (i->etype == EXPR_PAYLOAD && i->payload.is_raw &&
+		if (i->etype == EXPR_PAYLOAD &&
 		    i->dtype->type == TYPE_INTEGER) {
 			struct datatype *dtype;
 
diff --git a/src/payload.c b/src/payload.c
index fd6f7011365d..66418cddb3b5 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -153,9 +153,9 @@ static int payload_expr_build_udata(struct nftnl_udata_buf *udbuf,
 				    expr->payload.base);
 		nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET,
 				    expr->payload.offset);
-		nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_LEN,
-				    expr->len);
 	}
+	if (expr->dtype->type == TYPE_INTEGER)
+		nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_KEY_PAYLOAD_LEN, expr->len);
 
 	return 0;
 }
@@ -191,7 +191,7 @@ static int payload_parse_udata(const struct nftnl_udata *attr, void *data)
 static struct expr *payload_expr_parse_udata(const struct nftnl_udata *attr)
 {
 	const struct nftnl_udata *ud[NFTNL_UDATA_SET_KEY_PAYLOAD_MAX + 1] = {};
-	unsigned int type, base, offset, len;
+	unsigned int type, base, offset, len = 0;
 	const struct proto_desc *desc;
 	bool is_raw = false;
 	struct expr *expr;
@@ -209,20 +209,23 @@ static struct expr *payload_expr_parse_udata(const struct nftnl_udata *attr)
 	desc = find_proto_desc(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_DESC]);
 	if (!desc) {
 		if (!ud[NFTNL_UDATA_SET_KEY_PAYLOAD_BASE] ||
-		    !ud[NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET] ||
-		    !ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN])
+		    !ud[NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET])
 			return NULL;
 
 		base = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_BASE]);
 		offset = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_OFFSET]);
-		len = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN]);
 		is_raw = true;
 	}
 
 	type = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_TYPE]);
+	if (ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN])
+		len = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_KEY_PAYLOAD_LEN]);
 
 	expr = payload_expr_alloc(&internal_location, desc, type);
 
+	if (len)
+		expr->len = len;
+
 	if (is_raw) {
 		struct datatype *dtype;
 
diff --git a/tests/shell/testcases/maps/dumps/typeof_integer_0.nft b/tests/shell/testcases/maps/dumps/typeof_integer_0.nft
new file mode 100644
index 000000000000..330415574c95
--- /dev/null
+++ b/tests/shell/testcases/maps/dumps/typeof_integer_0.nft
@@ -0,0 +1,20 @@
+table inet t {
+	map m1 {
+		typeof udp length . @ih,32,32 : verdict
+		flags interval
+		elements = { 20-80 . 0x14 : accept,
+			     1-10 . 0xa : drop }
+	}
+
+	map m2 {
+		typeof udp length . @ih,32,32 : verdict
+		elements = { 30 . 0x1e : drop,
+			     20 . 0x24 : accept }
+	}
+
+	chain c {
+		udp length . @ih,32,32 vmap @m1
+		udp length . @ih,32,32 vmap @m2
+		udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
+	}
+}
diff --git a/tests/shell/testcases/maps/typeof_integer_0 b/tests/shell/testcases/maps/typeof_integer_0
new file mode 100755
index 000000000000..d8781e39812a
--- /dev/null
+++ b/tests/shell/testcases/maps/typeof_integer_0
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+EXPECTED="table inet t {
+        map m1 {
+                typeof udp length . @ih,32,32 : verdict
+                flags interval
+                elements = { 20-80 . 0x14 : accept, 1-10 . 0xa : drop }
+        }
+
+        map m2 {
+                typeof udp length . @ih,32,32 : verdict
+                elements = { 20 . 0x24 : accept, 30 . 0x1e : drop }
+        }
+
+        chain c {
+                udp length . @ih,32,32 vmap @m1
+                udp length . @ih,32,32 vmap @m2
+		udp length . @th,160,128 vmap { 47-63 . 0xe373135363130333131303735353203 : accept }
+        }
+}"
+
+$NFT add element inet t m1 { 90-100 . 40 : drop }
+$NFT delete element inet t m2 { 20 . 20 : accept }
+
+set -e
+$NFT -f - <<< $EXPECTED
+
-- 
2.30.2




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux