[PATCH nft 1/3] evaluate: infer family from mapping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Print error message in case family cannot be inferred, before this
patch, $? shows 1 after nft execution but no error message was printed.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/evaluate.c                       | 47 +++++++++++++++++++++++++---
 tests/shell/testcases/sets/0047nat_0 | 14 +++++++++
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index f92b160ce3a4..da8131d706d6 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3502,16 +3502,50 @@ static int stmt_evaluate_l3proto(struct eval_ctx *ctx,
 	return 0;
 }
 
+static int expr_family_infer(struct proto_ctx *pctx, const struct expr *expr)
+{
+	int family = pctx->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;
+		}
+	}
+
+	return family;
+}
+
 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)
+			*family = expr_family_infer(pctx, *addr);
+
+		dtype = get_addr_dtype(*family);
 		if (dtype->size == 0)
 			return stmt_error(ctx, stmt,
 					  "ip or ip6 must be specified with address for inet tables.");
@@ -3532,6 +3566,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)
+		stmt->nat.family = expr_family_infer(pctx, stmt->nat.addr);
+
 	switch (stmt->nat.family) {
 	case NFPROTO_IPV4:
 		addr_type = TYPE_IPADDR;
@@ -3658,7 +3695,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;
@@ -3709,7 +3746,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)
diff --git a/tests/shell/testcases/sets/0047nat_0 b/tests/shell/testcases/sets/0047nat_0
index cb1d4d68d2d2..d19f5b69fd33 100755
--- a/tests/shell/testcases/sets/0047nat_0
+++ b/tests/shell/testcases/sets/0047nat_0
@@ -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
-- 
2.30.2




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux