]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
optimize: infer family for nat mapping
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 15 Feb 2023 18:20:22 +0000 (19:20 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 21 Feb 2023 22:57:27 +0000 (23:57 +0100)
Infer family from key in nat mapping, otherwise nat mapping via merge
breaks since family is not specified.

Merging:
fw-test-bug2.nft:4:9-78:         iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
fw-test-bug2.nft:5:9-77:         iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
fw-test-bug2.nft:6:9-75:         iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
into:
        dnat ip to iifname . ip daddr . tcp dport map { enp2s0 . 72.2.3.66 . 53122 : 10.1.1.10 . 22, enp2s0 . 72.2.3.66 . 443 : 10.1.1.52 . 443, enp2s0 . 72.2.3.70 . 80 : 10.1.1.52 . 80 }

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1657
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/optimize.c
tests/shell/testcases/optimizations/dumps/merge_nat.nft
tests/shell/testcases/optimizations/merge_nat
tests/shell/testcases/sets/dumps/0047nat_0.nft

index d60aa8f22c07360f6b4f285929a6c1155cdf5297..3548719031e60425645995cf00f4f15084c25e07 100644 (file)
@@ -21,6 +21,7 @@
 #include <statement.h>
 #include <utils.h>
 #include <erec.h>
+#include <linux/netfilter.h>
 
 #define MAX_STMTS      32
 
@@ -872,9 +873,9 @@ static void merge_nat(const struct optimize_ctx *ctx,
                      const struct merge *merge)
 {
        struct expr *expr, *set, *elem, *nat_expr, *mapping, *left;
+       int k, family = NFPROTO_UNSPEC;
        struct stmt *stmt, *nat_stmt;
        uint32_t i;
-       int k;
 
        k = stmt_nat_find(ctx);
        assert(k >= 0);
@@ -896,9 +897,18 @@ static void merge_nat(const struct optimize_ctx *ctx,
 
        stmt = ctx->stmt_matrix[from][merge->stmt[0]];
        left = expr_get(stmt->expr->left);
+       if (left->etype == EXPR_PAYLOAD) {
+               if (left->payload.desc == &proto_ip)
+                       family = NFPROTO_IPV4;
+               else if (left->payload.desc == &proto_ip6)
+                       family = NFPROTO_IPV6;
+       }
        expr = map_expr_alloc(&internal_location, left, set);
 
        nat_stmt = ctx->stmt_matrix[from][k];
+       if (nat_stmt->nat.family == NFPROTO_UNSPEC)
+               nat_stmt->nat.family = family;
+
        expr_free(nat_stmt->nat.addr);
        nat_stmt->nat.addr = expr;
 
@@ -912,9 +922,9 @@ static void merge_concat_nat(const struct optimize_ctx *ctx,
                             const struct merge *merge)
 {
        struct expr *expr, *set, *elem, *nat_expr, *mapping, *left, *concat;
+       int k, family = NFPROTO_UNSPEC;
        struct stmt *stmt, *nat_stmt;
        uint32_t i, j;
-       int k;
 
        k = stmt_nat_find(ctx);
        assert(k >= 0);
@@ -943,11 +953,20 @@ static void merge_concat_nat(const struct optimize_ctx *ctx,
        for (j = 0; j < merge->num_stmts; j++) {
                stmt = ctx->stmt_matrix[from][merge->stmt[j]];
                left = stmt->expr->left;
+               if (left->etype == EXPR_PAYLOAD) {
+                       if (left->payload.desc == &proto_ip)
+                               family = NFPROTO_IPV4;
+                       else if (left->payload.desc == &proto_ip6)
+                               family = NFPROTO_IPV6;
+               }
                compound_expr_add(concat, expr_get(left));
        }
        expr = map_expr_alloc(&internal_location, concat, set);
 
        nat_stmt = ctx->stmt_matrix[from][k];
+       if (nat_stmt->nat.family == NFPROTO_UNSPEC)
+               nat_stmt->nat.family = family;
+
        expr_free(nat_stmt->nat.addr);
        nat_stmt->nat.addr = expr;
 
index 96e38ccd798a9093dd8e1661d5c8c0b7cca8a449..dd17905dbfeb2a74879fc13d28d4cb3780142e15 100644 (file)
@@ -23,3 +23,14 @@ table ip test4 {
                dnat ip to ip daddr . tcp dport map { 1.1.1.1 . 80 : 4.4.4.4 . 8000, 2.2.2.2 . 81 : 3.3.3.3 . 9000 }
        }
 }
+table inet nat {
+       chain prerouting {
+               oif "lo" accept
+               dnat ip to iifname . ip daddr . tcp dport map { "enp2s0" . 72.2.3.70 . 80 : 10.1.1.52 . 80, "enp2s0" . 72.2.3.66 . 53122 : 10.1.1.10 . 22, "enp2s0" . 72.2.3.66 . 443 : 10.1.1.52 . 443 }
+       }
+
+       chain postrouting {
+               oif "lo" accept
+               snat ip to ip daddr map { 72.2.3.66 : 10.2.2.2, 72.2.3.67 : 10.2.3.3 }
+       }
+}
index 1484b7d39d48e98af0700fbadc431bf407f842bf..edf7f4c438b9c41449150a290a67dc71d58c07a2 100755 (executable)
@@ -42,3 +42,19 @@ RULESET="table ip test4 {
 }"
 
 $NFT -o -f - <<< $RULESET
+
+RULESET="table inet nat {
+       chain prerouting {
+               oif lo accept
+               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 53122 dnat to 10.1.1.10:22
+               iifname enp2s0 ip daddr 72.2.3.66 tcp dport 443 dnat to 10.1.1.52:443
+               iifname enp2s0 ip daddr 72.2.3.70 tcp dport 80 dnat to 10.1.1.52:80
+       }
+       chain postrouting {
+               oif lo accept
+               ip daddr 72.2.3.66 snat to 10.2.2.2
+               ip daddr 72.2.3.67 snat to 10.2.3.3
+       }
+}"
+
+$NFT -o -f - <<< $RULESET
index e796805471a3e844e31a68f373ed4332efde6c5c..97c04a1637a2e06759fc4bd180f32ace121a8f6c 100644 (file)
@@ -11,3 +11,14 @@ table ip x {
                snat ip to ip saddr map @y
        }
 }
+table inet x {
+       chain x {
+               type nat hook prerouting priority dstnat; policy accept;
+               dnat ip to ip daddr . tcp dport map { 10.141.10.1 . 22 : 192.168.2.2, 10.141.11.2 . 2222 : 192.168.4.2 }
+       }
+
+       chain y {
+               type nat hook postrouting priority srcnat; policy accept;
+               snat ip to ip saddr map { 10.141.10.0/24 : 192.168.2.2-192.168.2.4, 10.141.11.0/24 : 192.168.4.2/31 }
+       }
+}