]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: infer family from mapping
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 16 Feb 2023 14:41:30 +0000 (15:41 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 21 Feb 2023 22:57:27 +0000 (23:57 +0100)
If the key in the nat mapping is either ip or ip6, then set the nat
family accordingly, no need for explicit family in the nat statement.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/shell/testcases/sets/0047nat_0

index 98f3e9263058570289d6a56e857d56e9ca191b34..d24f8b66b0de8df6ad41afb0c10eecb0b246aea1 100644 (file)
@@ -3524,16 +3524,48 @@ static int stmt_evaluate_l3proto(struct eval_ctx *ctx,
        return 0;
 }
 
+static void expr_family_infer(struct proto_ctx *pctx, const struct expr *expr,
+                             uint8_t *family)
+{
+       struct expr *i;
+
+       if (expr->etype == EXPR_MAP) {
+               switch (expr->map->etype) {
+               case EXPR_CONCAT:
+                       list_for_each_entry(i, &expr->map->expressions, list) {
+                               if (i->etype == EXPR_PAYLOAD) {
+                                       if (i->payload.desc == &proto_ip)
+                                               *family = NFPROTO_IPV4;
+                                       else if (i->payload.desc == &proto_ip6)
+                                               *family = NFPROTO_IPV6;
+                               }
+                       }
+                       break;
+               case EXPR_PAYLOAD:
+                       if (expr->map->payload.desc == &proto_ip)
+                               *family = NFPROTO_IPV4;
+                       else if (expr->map->payload.desc == &proto_ip6)
+                               *family = NFPROTO_IPV6;
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
 static int stmt_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt,
-                             uint8_t family,
-                             struct expr **addr)
+                             uint8_t *family, struct expr **addr)
 {
        struct proto_ctx *pctx = eval_proto_ctx(ctx);
        const struct datatype *dtype;
        int err;
 
        if (pctx->family == NFPROTO_INET) {
-               dtype = get_addr_dtype(family);
+               if (*family == NFPROTO_INET ||
+                   *family == NFPROTO_UNSPEC)
+                       expr_family_infer(pctx, *addr, family);
+
+               dtype = get_addr_dtype(*family);
                if (dtype->size == 0) {
                        return stmt_error(ctx, stmt,
                                          "specify `%s ip' or '%s ip6' in %s table to disambiguate",
@@ -3556,6 +3588,9 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt)
        const struct datatype *dtype;
        int addr_type, err;
 
+       if (stmt->nat.family == NFPROTO_INET)
+               expr_family_infer(pctx, stmt->nat.addr, &stmt->nat.family);
+
        switch (stmt->nat.family) {
        case NFPROTO_IPV4:
                addr_type = TYPE_IPADDR;
@@ -3682,7 +3717,7 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
                        return 0;
                }
 
-               err = stmt_evaluate_addr(ctx, stmt, stmt->nat.family,
+               err = stmt_evaluate_addr(ctx, stmt, &stmt->nat.family,
                                         &stmt->nat.addr);
                if (err < 0)
                        return err;
@@ -3733,7 +3768,7 @@ static int stmt_evaluate_tproxy(struct eval_ctx *ctx, struct stmt *stmt)
                if (stmt->tproxy.addr->etype == EXPR_RANGE)
                        return stmt_error(ctx, stmt, "Address ranges are not supported for tproxy.");
 
-               err = stmt_evaluate_addr(ctx, stmt, stmt->tproxy.family,
+               err = stmt_evaluate_addr(ctx, stmt, &stmt->tproxy.family,
                                         &stmt->tproxy.addr);
 
                if (err < 0)
index cb1d4d68d2d26734ecff68b3157402a6f946b7f8..d19f5b69fd3337f4e441cc8544aaa48bff4dde8a 100755 (executable)
@@ -18,3 +18,17 @@ EXPECTED="table ip x {
 set -e
 $NFT -f - <<< $EXPECTED
 $NFT add element x y { 10.141.12.0/24 : 192.168.5.10-192.168.5.20 }
+
+EXPECTED="table inet x {
+            chain x {
+                    type nat hook prerouting priority dstnat; policy accept;
+                    dnat 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 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-192.168.4.3 }
+            }
+}"
+
+$NFT -f - <<< $EXPECTED