summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
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 /src/evaluate.c
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>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c45
1 files changed, 40 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)