]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: permit use of constant values in set lookup keys
authorFlorian Westphal <fw@strlen.de>
Wed, 24 May 2023 11:25:22 +0000 (13:25 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Jan 2025 23:41:55 +0000 (00:41 +0100)
commit b422b07ab2f96436001f33dfdfd937238033c799 upstream.

Something like:

Given: set s { type ipv4_addr . ipv4_addr . inet_service .. } something
like
   add rule ip saddr . 1.2.3.4 . 80 @s goto c1

fails with: "Error: Can't parse symbolic invalid expressions".

This fails because the relational expression first evaluates
the left hand side, so when concat evaluation sees '1.2.3.4'
no key context is available.

Check if the RHS is a set reference, and, if so, evaluate
the right hand side.

This sets a pointer to the set key in the evaluation context
structure which then makes the concat evaluation step parse
1.2.3.4 and 80 as ipv4 address and 16bit port number.

On delinearization, extend relop postprocessing to
copy the datatype from the rhs (set reference, has
proper datatype according to set->key) to the lhs (concat
expression).

Signed-off-by: Florian Westphal <fw@strlen.de>
src/evaluate.c
src/netlink_delinearize.c
tests/shell/testcases/sets/dumps/type_set_symbol.nft [new file with mode: 0644]
tests/shell/testcases/sets/type_set_symbol [new file with mode: 0755]

index 91c7ce07cd1a2b6694104284cd8d947d1de7d3f4..73f375c1f6f13a097d17184f7a062149f0640927 100644 (file)
@@ -2365,6 +2365,12 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
        struct expr *range;
        int ret;
 
+       right = rel->right;
+       if (right->etype == EXPR_SYMBOL &&
+           right->symtype == SYMBOL_SET &&
+           expr_evaluate(ctx, &rel->right) < 0)
+               return -1;
+
        if (expr_evaluate(ctx, &rel->left) < 0)
                return -1;
        left = rel->left;
index fbe84830882e80fa2033a77a73498e3ebeec2955..0d31ba46e4bf447b575d34b7d7afce4f6ee85211 100644 (file)
@@ -2709,6 +2709,15 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
                case EXPR_PAYLOAD:
                        payload_match_postprocess(ctx, expr, expr->left);
                        return;
+               case EXPR_CONCAT:
+                       if (expr->right->etype == EXPR_SET_REF) {
+                               assert(expr->left->dtype == &invalid_type);
+                               assert(expr->right->dtype != &invalid_type);
+
+                               datatype_set(expr->left, expr->right->dtype);
+                       }
+                       expr_postprocess(ctx, &expr->left);
+                       break;
                default:
                        expr_postprocess(ctx, &expr->left);
                        break;
diff --git a/tests/shell/testcases/sets/dumps/type_set_symbol.nft b/tests/shell/testcases/sets/dumps/type_set_symbol.nft
new file mode 100644 (file)
index 0000000..21209f6
--- /dev/null
@@ -0,0 +1,16 @@
+table ip t {
+       set s1 {
+               type ipv4_addr . ipv4_addr . inet_service
+               size 65535
+               flags dynamic,timeout
+               timeout 3h
+       }
+
+       chain c1 {
+               update @s1 { ip saddr . 10.180.0.4 . 80 }
+       }
+
+       chain c2 {
+               ip saddr . 1.2.3.4 . 80 @s1 goto c1
+       }
+}
diff --git a/tests/shell/testcases/sets/type_set_symbol b/tests/shell/testcases/sets/type_set_symbol
new file mode 100755 (executable)
index 0000000..07820b7
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -e
+dumpfile=$(dirname $0)/dumps/$(basename $0).nft
+
+$NFT -f "$dumpfile"