diff options
author | Florian Westphal <fw@strlen.de> | 2021-04-06 18:34:19 +0200 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2021-04-29 17:20:57 +0200 |
commit | 7f7d5b999ed3f44ee8aec6b4d48051f048f326ab (patch) | |
tree | 57a2fd7fc4daba8471ae7ccf2cfb52b72b77acff | |
parent | 5f6f20913c862f6a844a8f7143ed074284423897 (diff) |
evaluate: check if nat statement map specifies a transport header expr
Importing the systemd nat table fails:
table ip io.systemd.nat {
map map_port_ipport {
type inet_proto . inet_service : ipv4_addr . inet_service
elements = { tcp . 8088 : 192.168.162.117 . 80 }
}
chain prerouting {
type nat hook prerouting priority dstnat + 1; policy accept;
fib daddr type local dnat ip addr . port to meta l4proto . th dport map @map_port_ipport
}
}
ruleset:9:48-59: Error: transport protocol mapping is only valid after transport protocol match
To resolve this (no transport header base specified), check if the
map itself contains a network base protocol expression.
This allows nft to import the ruleset.
Import still fails with same error if 'inet_service' is removed
from the map, as it should.
Reported-by: Henning Reich <henning.reich@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r-- | src/evaluate.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 85cf9e05..a6bb1792 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2971,12 +2971,48 @@ static int evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt, expr); } +static bool nat_evaluate_addr_has_th_expr(const struct expr *map) +{ + const struct expr *i, *concat; + + if (!map || map->etype != EXPR_MAP) + return false; + + concat = map->map; + if (concat ->etype != EXPR_CONCAT) + return false; + + list_for_each_entry(i, &concat->expressions, list) { + enum proto_bases base; + + if ((i->flags & EXPR_F_PROTOCOL) == 0) + continue; + + switch (i->etype) { + case EXPR_META: + base = i->meta.base; + break; + case EXPR_PAYLOAD: + base = i->payload.base; + break; + default: + return false; + } + + if (base == PROTO_BASE_NETWORK_HDR) + return true; + } + + return false; +} + static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt, struct expr **expr) { struct proto_ctx *pctx = &ctx->pctx; - if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL) + if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL && + !nat_evaluate_addr_has_th_expr(stmt->nat.addr)) return stmt_binary_error(ctx, *expr, stmt, "transport protocol mapping is only " "valid after transport protocol match"); |