]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: expand variable containing set into multiple mappings
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 11 Aug 2021 10:08:41 +0000 (12:08 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 12 Aug 2021 14:49:04 +0000 (16:49 +0200)
 # cat x.nft
 define interfaces = { eth0, eth1 }

 table ip x {
        chain y {
type filter hook input priority 0; policy accept;
                iifname vmap { lo : accept, $interfaces : drop }
        }
 }
 # nft -f x.nft
 # nft list ruleset
 table ip x {
        chain y {
type filter hook input priority 0; policy accept;
                iifname vmap { "lo" : accept, "eth0" : drop, "eth1" : drop }
        }
 }

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/shell/testcases/maps/0012map_0 [new file with mode: 0755]
tests/shell/testcases/maps/dumps/0012map_0.nft [new file with mode: 0644]

index 8b5f51cee01ce459f44af3bbe72aa90f7791f4b5..8ebc75617b1c5fe1de1595f3737925bc9e30499c 100644 (file)
@@ -1431,6 +1431,23 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
                if (list_member_evaluate(ctx, &i) < 0)
                        return -1;
 
+               if (i->etype == EXPR_MAPPING &&
+                   i->left->etype == EXPR_SET_ELEM &&
+                   i->left->key->etype == EXPR_SET) {
+                       struct expr *new, *j;
+
+                       list_for_each_entry(j, &i->left->key->expressions, list) {
+                               new = mapping_expr_alloc(&i->location,
+                                                        expr_get(j),
+                                                        expr_clone(i->right));
+                               list_add_tail(&new->list, &set->expressions);
+                               set->size++;
+                       }
+                       list_del(&i->list);
+                       expr_free(i);
+                       continue;
+               }
+
                elem = expr_set_elem(i);
 
                if (elem->etype == EXPR_SET_ELEM &&
diff --git a/tests/shell/testcases/maps/0012map_0 b/tests/shell/testcases/maps/0012map_0
new file mode 100755 (executable)
index 0000000..dd93c48
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -e
+
+EXPECTED="define interfaces = { eth0, eth1 }
+
+table ip x {
+       map z {
+               type ifname : verdict
+               elements = { \$interfaces : drop, lo : accept }
+       }
+       chain y {
+               iifname vmap { lo : accept, \$interfaces : drop }
+       }
+}"
+
+$NFT -f - <<< "$EXPECTED"
diff --git a/tests/shell/testcases/maps/dumps/0012map_0.nft b/tests/shell/testcases/maps/dumps/0012map_0.nft
new file mode 100644 (file)
index 0000000..e734fc1
--- /dev/null
@@ -0,0 +1,12 @@
+table ip x {
+       map z {
+               type ifname : verdict
+               elements = { "lo" : accept,
+                            "eth0" : drop,
+                            "eth1" : drop }
+       }
+
+       chain y {
+               iifname vmap { "lo" : accept, "eth0" : drop, "eth1" : drop }
+       }
+}