summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-02-16 15:41:30 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2023-02-21 23:57:27 +0100
commit2f4935a8d7aeb6b2e019aebb961a579d9950c74a (patch)
tree96c0d55f7e6d7e43a01071188fe275f564e153c0
parent6968c2632e0c7a625ca57cd4501b6b980fdebc55 (diff)
evaluate: infer family from mapping
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>
-rw-r--r--src/evaluate.c45
-rwxr-xr-xtests/shell/testcases/sets/0047nat_014
2 files changed, 54 insertions, 5 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 98f3e926..d24f8b66 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -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)
diff --git a/tests/shell/testcases/sets/0047nat_0 b/tests/shell/testcases/sets/0047nat_0
index cb1d4d68..d19f5b69 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