]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: infer NAT mapping with concatenation from set
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 13 Jul 2021 18:18:27 +0000 (20:18 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 13 Jul 2021 18:25:33 +0000 (20:25 +0200)
If the map is anonymous, infer it from the set elements. Otherwise, the
set definition already have an explicit concatenation definition in the
data side of the mapping.

This update simplifies the NAT mapping syntax with concatenations, e.g.

 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
src/json.c
src/statement.c
tests/py/ip/snat.t
tests/py/ip/snat.t.payload
tests/shell/testcases/maps/dumps/0010concat_map_0.nft
tests/shell/testcases/maps/dumps/nat_addr_port.nft

index 13888e5b476dc5240221146cb43c6b0886ef2678..7d59e2600224598f415247d644972fded7e2568b 100644 (file)
@@ -1579,6 +1579,9 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
                        return expr_error(ctx->msgs, map->mappings,
                                          "Expression is not a map");
                break;
+       case EXPR_SET_REF:
+               /* symbol has been already evaluated to set reference */
+               break;
        default:
                BUG("invalid mapping expression %s\n",
                    expr_name(map->mappings));
@@ -3172,6 +3175,40 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt)
        return err;
 }
 
+static bool nat_concat_map(struct eval_ctx *ctx, struct stmt *stmt)
+{
+       struct expr *i;
+
+       if (stmt->nat.addr->etype != EXPR_MAP)
+               return false;
+
+       switch (stmt->nat.addr->mappings->etype) {
+       case EXPR_SET:
+               list_for_each_entry(i, &stmt->nat.addr->mappings->expressions, list) {
+                       if (i->etype == EXPR_MAPPING &&
+                           i->right->etype == EXPR_CONCAT) {
+                               stmt->nat.type_flags |= STMT_NAT_F_CONCAT;
+                               return true;
+                       }
+               }
+               break;
+       case EXPR_SYMBOL:
+               /* expr_evaluate_map() see EXPR_SET_REF after this evaluation. */
+               if (expr_evaluate(ctx, &stmt->nat.addr->mappings))
+                       return false;
+
+               if (stmt->nat.addr->mappings->set->data->etype == EXPR_CONCAT) {
+                       stmt->nat.type_flags |= STMT_NAT_F_CONCAT;
+                       return true;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return false;
+}
+
 static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
 {
        int err;
@@ -3185,7 +3222,9 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
                if (err < 0)
                        return err;
 
-               if (stmt->nat.type_flags & STMT_NAT_F_CONCAT) {
+               if (nat_concat_map(ctx, stmt) ||
+                   stmt->nat.type_flags & STMT_NAT_F_CONCAT) {
+
                        err = stmt_evaluate_nat_map(ctx, stmt);
                        if (err < 0)
                                return err;
index edc9d640bbbc05a1cf9cd5400eadc9bc1964305f..63b325afc8d1c173f876d255822d68a9075f6fae 100644 (file)
@@ -1331,8 +1331,6 @@ static json_t *nat_type_flags_json(uint32_t type_flags)
 
        if (type_flags & STMT_NAT_F_PREFIX)
                json_array_append_new(array, json_string("prefix"));
-       if (type_flags & STMT_NAT_F_CONCAT)
-               json_array_append_new(array, json_string("concat"));
 
        return array;
 }
index 6db7e397586007af3b72ac28d2003acc888fbb8b..06742c04f0274c5b4b6c5fcedebf98b5fd449c22 100644 (file)
@@ -673,9 +673,7 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
                        break;
                }
 
-               if (stmt->nat.type_flags & STMT_NAT_F_CONCAT)
-                       nft_print(octx, " addr . port");
-               else if (stmt->nat.type_flags & STMT_NAT_F_PREFIX)
+               if (stmt->nat.type_flags & STMT_NAT_F_PREFIX)
                        nft_print(octx, " prefix");
 
                nft_print(octx, " to");
index 56ab943e8b97e3ff65fa89b31222186407596131..8aa83111151622a2d21581f74fc47c5808d36c4a 100644 (file)
@@ -9,6 +9,6 @@ iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2;ok
 
 iifname "eth0" tcp dport != 23-34 snat to 192.168.3.2;ok
 
-snat ip addr . port to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 };ok
+snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 };ok
 snat ip to ip saddr map { 10.141.11.4 : 192.168.2.2-192.168.2.4 };ok
 snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24 };ok
index 2a03ff1f95a059825be6eb7a1c5727c1456519cf..15f737cdcd95967538b2beed892ce7433946e5a2 100644 (file)
@@ -60,7 +60,7 @@ ip test-ip4 postrouting
   [ immediate reg 1 0x0203a8c0 ]
   [ nat snat ip addr_min reg 1 ]
 
-# snat ip addr . port to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
+# snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
 __map%d test-ip4 b size 1
 __map%d test-ip4 0
        element 040b8d0a  : 0302a8c0 00005000 0 [end]
index 328c653c99139a2f2af446e6c531500eecefb6c6..b6bc338c55b7395945d708f45b8412d3b2079535 100644 (file)
@@ -6,6 +6,6 @@ table inet x {
 
        chain y {
                type nat hook prerouting priority dstnat; policy accept;
-               meta nfproto ipv4 dnat ip addr . port to ip saddr . ip protocol . tcp dport map @z
+               meta nfproto ipv4 dnat ip to ip saddr . ip protocol . tcp dport map @z
        }
 }
index 89c3bd145b4d7102efaa6a05c09738f80f2652a2..cf6b957f0a9ba5098112052c344b52c1a0871458 100644 (file)
@@ -27,10 +27,10 @@ table ip ipfoo {
                dnat to ip daddr map @x
                ip saddr 10.1.1.1 dnat to 10.2.3.4
                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
+               meta l4proto tcp dnat ip to ip saddr map @y
+               dnat ip 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
+               meta l4proto tcp dnat ip to numgen inc mod 2 map @t2
        }
 }
 table ip6 ip6foo {
@@ -60,10 +60,10 @@ table ip6 ip6foo {
                dnat to ip6 daddr map @x
                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 @y
-               dnat ip6 addr . port to ip6 saddr . tcp dport map @z
+               meta l4proto tcp dnat ip6 to ip6 saddr map @y
+               dnat ip6 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
+               meta l4proto tcp dnat ip6 to numgen inc mod 2 map @t2
        }
 }
 table inet inetfoo {
@@ -114,16 +114,16 @@ table inet inetfoo {
                dnat ip to ip daddr map @x4
                ip saddr 10.1.1.1 dnat ip to 10.2.3.4
                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
+               meta l4proto tcp meta nfproto ipv4 dnat ip to ip saddr map @y4
+               meta nfproto ipv4 dnat ip 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
+               meta l4proto tcp dnat ip 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
+               meta l4proto tcp meta nfproto ipv6 dnat ip6 to ip6 saddr map @y6
+               meta nfproto ipv6 dnat ip6 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
+               meta l4proto tcp dnat ip6 to numgen inc mod 2 map @t2v6
        }
 }