It is possible to use a variable to initialize a map, which is then used in a map statement: define m = { ::1234 : 5678 } table ip6 nat { map m { typeof ip6 daddr : tcp dport; elements = $m } chain prerouting { ip6 nexthdr tcp redirect to ip6 daddr map @m } } However, if one tries to use the variable directly in the statement: define m = { ::1234 : 5678 } table ip6 nat { chain prerouting { ip6 nexthdr tcp redirect to ip6 daddr map $m } } nft rejects it: /space/azazel/tmp/ruleset.1067161.nft:5:47-48: Error: invalid mapping expression variable ip6 nexthdr tcp redirect to ip6 daddr map $m ~~~~~~~~~ ^^ Extend `expr_evaluate_map` to allow it. Add a test-case. Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1067161 Signed-off-by: Jeremy Sowden <jeremy@xxxxxxxxxx> --- src/evaluate.c | 1 + .../shell/testcases/maps/anonymous_snat_map_1 | 16 +++++ .../maps/dumps/anonymous_snat_map_1.json-nft | 58 +++++++++++++++++++ .../maps/dumps/anonymous_snat_map_1.nft | 5 ++ 4 files changed, 80 insertions(+) create mode 100755 tests/shell/testcases/maps/anonymous_snat_map_1 create mode 100644 tests/shell/testcases/maps/dumps/anonymous_snat_map_1.json-nft create mode 100644 tests/shell/testcases/maps/dumps/anonymous_snat_map_1.nft diff --git a/src/evaluate.c b/src/evaluate.c index 1682ba58989e..d49213f8d6bd 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2061,6 +2061,7 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) mappings->set_flags |= NFT_SET_MAP; switch (map->mappings->etype) { + case EXPR_VARIABLE: case EXPR_SET: if (ctx->ectx.key && ctx->ectx.key->etype == EXPR_CONCAT) { key = expr_clone(ctx->ectx.key); diff --git a/tests/shell/testcases/maps/anonymous_snat_map_1 b/tests/shell/testcases/maps/anonymous_snat_map_1 new file mode 100755 index 000000000000..031de0c1a83f --- /dev/null +++ b/tests/shell/testcases/maps/anonymous_snat_map_1 @@ -0,0 +1,16 @@ +#!/bin/bash + +# Variable containing anonymous map can be added to a snat rule + +set -e + +RULESET=' +define m = {1.1.1.1 : 2.2.2.2} +table nat { + chain postrouting { + snat ip saddr map $m + } +} +' + +$NFT -f - <<< "$RULESET" diff --git a/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.json-nft b/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.json-nft new file mode 100644 index 000000000000..f4c55706787c --- /dev/null +++ b/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.json-nft @@ -0,0 +1,58 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "nat", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "nat", + "name": "postrouting", + "handle": 0 + } + }, + { + "rule": { + "family": "ip", + "table": "nat", + "chain": "postrouting", + "handle": 0, + "expr": [ + { + "snat": { + "addr": { + "map": { + "key": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "data": { + "set": [ + [ + "1.1.1.1", + "2.2.2.2" + ] + ] + } + } + } + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.nft b/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.nft new file mode 100644 index 000000000000..5009560c9d69 --- /dev/null +++ b/tests/shell/testcases/maps/dumps/anonymous_snat_map_1.nft @@ -0,0 +1,5 @@ +table ip nat { + chain postrouting { + snat to ip saddr map { 1.1.1.1 : 2.2.2.2 } + } +} -- 2.43.0