From 1f3974ce5c77fb66bc0be94a2e03286f73ac0b5b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 24 Feb 2020 13:28:34 +0100 Subject: src: nat concatenation support with anonymous maps This patch extends the parser to define the mapping datatypes, eg. ... dnat ip addr . port to ip saddr map { 1.1.1.1 : 2.2.2.2 . 30 } ... dnat ip addr . port to ip saddr map @y Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 23 ++++++++++++++++++++--- src/netlink_delinearize.c | 1 + src/parser_bison.y | 7 +++++++ src/scanner.l | 1 + src/statement.c | 3 +++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index 0afd0403..2d4985c0 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2853,15 +2853,32 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt) { struct expr *one, *two, *data, *tmp; const struct datatype *dtype; - int err; + int addr_type, err; - dtype = get_addr_dtype(stmt->nat.family); + if (stmt->nat.ipportmap) { + switch (stmt->nat.family) { + case NFPROTO_IPV4: + addr_type = TYPE_IPADDR; + break; + case NFPROTO_IPV6: + addr_type = TYPE_IP6ADDR; + break; + default: + return -1; + } + dtype = concat_type_alloc((addr_type << TYPE_BITS) | + TYPE_INET_SERVICE); + } else { + dtype = get_addr_dtype(stmt->nat.family); + } expr_set_context(&ctx->ectx, dtype, dtype->size); if (expr_evaluate(ctx, &stmt->nat.addr)) return -1; data = stmt->nat.addr->mappings->set->data; + datatype_set(data, dtype); + if (expr_ops(data)->type != EXPR_CONCAT) return __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size, BYTEORDER_BIG_ENDIAN, @@ -2875,6 +2892,7 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt) BYTEORDER_BIG_ENDIAN, &stmt->nat.addr); + dtype = get_addr_dtype(stmt->nat.family); tmp = one; err = __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size, BYTEORDER_BIG_ENDIAN, @@ -2891,7 +2909,6 @@ static int stmt_evaluate_nat_map(struct eval_ctx *ctx, struct stmt *stmt) if (tmp != two) BUG("Internal error: Unexpected alteration of l4 expression"); - stmt->nat.ipportmap = true; return err; } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 6203a53c..0058e2cf 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -1065,6 +1065,7 @@ static void netlink_parse_nat(struct netlink_parse_ctx *ctx, } if (is_nat_proto_map(addr, family)) { + stmt->nat.family = family; stmt->nat.ipportmap = true; ctx->stmt = stmt; return; diff --git a/src/parser_bison.y b/src/parser_bison.y index fd00b40a..4c27fcc6 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -373,6 +373,7 @@ int nft_lex(void *, void *, void *); %token FLAGS "flags" %token CPI "cpi" +%token PORT "port" %token UDP "udp" %token SPORT "sport" %token DPORT "dport" @@ -3141,6 +3142,12 @@ nat_stmt_args : stmt_expr { $0->nat.flags = $2; } + | nf_key_proto ADDR DOT PORT TO stmt_expr + { + $0->nat.family = $1; + $0->nat.addr = $6; + $0->nat.ipportmap = true; + } ; masq_stmt : masq_stmt_alloc masq_stmt_args diff --git a/src/scanner.l b/src/scanner.l index 3932883b..45699c85 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -471,6 +471,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "udplite" { return UDPLITE; } "sport" { return SPORT; } "dport" { return DPORT; } +"port" { return PORT; } "tcp" { return TCP; } "ackseq" { return ACKSEQ; } diff --git a/src/statement.c b/src/statement.c index be35bcef..182edac8 100644 --- a/src/statement.c +++ b/src/statement.c @@ -607,6 +607,9 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx) break; } + if (stmt->nat.ipportmap) + nft_print(octx, " addr . port"); + nft_print(octx, " to"); } -- cgit v1.2.3