From 28d3d0ea260e8a9ab4fc319f8ae0ce15cfc8204b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 15 Feb 2023 19:20:22 +0100 Subject: [PATCH nft,v1.0.6 13/41] optimize: infer family for nat mapping commit 114ba9606cb5ad85b2215e59f8af8ad97a16cac8 upstream. 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 --- src/optimize.c | 23 +++++++++++++++++-- .../optimizations/dumps/merge_nat.nft | 11 +++++++++ tests/shell/testcases/optimizations/merge_nat | 16 +++++++++++++ .../shell/testcases/sets/dumps/0047nat_0.nft | 11 +++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/optimize.c b/src/optimize.c index 98977f03f28a..e54693fdf67c 100644 --- a/src/optimize.c +++ b/src/optimize.c @@ -21,6 +21,7 @@ #include #include #include +#include #define MAX_STMTS 32 @@ -870,9 +871,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); @@ -894,9 +895,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; @@ -910,9 +920,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); @@ -941,11 +951,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; diff --git a/tests/shell/testcases/optimizations/dumps/merge_nat.nft b/tests/shell/testcases/optimizations/dumps/merge_nat.nft index 96e38ccd798a..dd17905dbfeb 100644 --- a/tests/shell/testcases/optimizations/dumps/merge_nat.nft +++ b/tests/shell/testcases/optimizations/dumps/merge_nat.nft @@ -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 } + } +} diff --git a/tests/shell/testcases/optimizations/merge_nat b/tests/shell/testcases/optimizations/merge_nat index 1484b7d39d48..edf7f4c438b9 100755 --- a/tests/shell/testcases/optimizations/merge_nat +++ b/tests/shell/testcases/optimizations/merge_nat @@ -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 diff --git a/tests/shell/testcases/sets/dumps/0047nat_0.nft b/tests/shell/testcases/sets/dumps/0047nat_0.nft index e796805471a3..97c04a1637a2 100644 --- a/tests/shell/testcases/sets/dumps/0047nat_0.nft +++ b/tests/shell/testcases/sets/dumps/0047nat_0.nft @@ -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 } + } +} -- 2.30.2