diff options
author | Patrick McHardy <kaber@trash.net> | 2015-01-10 14:41:55 +0000 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2015-01-10 14:41:55 +0000 |
commit | 405746b606e12390b2efebf3ab878ba433395e01 (patch) | |
tree | 001596d8ed0b17ab8240dbabc4797579cc0c8c4d | |
parent | c48a519da2a85d11d76217aed6e78395dd7f7f57 (diff) |
eval: refactor NAT evaluation functions
The redir and masq evaluation functions include some useless context
updates and checks.
Refactor the NAT code to have a single instance of address and transport
evaluation functions for simplicity and unified error reporting.
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | src/evaluate.c | 110 |
1 files changed, 54 insertions, 56 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 43fb9681..4cfe749a 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1496,32 +1496,61 @@ static int stmt_evaluate_reject(struct eval_ctx *ctx, struct stmt *stmt) return stmt_evaluate_reject_family(ctx, stmt, expr); } +static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt) +{ + switch (ctx->pctx.family) { + case AF_INET: + case AF_INET6: + return 0; + default: + return stmt_error(ctx, stmt, + "NAT is only supported for IPv4/IPv6"); + } +} + +static int nat_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt, + struct expr **expr) +{ + struct proto_ctx *pctx = &ctx->pctx; + + if (pctx->family == AF_INET) + expr_set_context(&ctx->ectx, &ipaddr_type, 4 * BITS_PER_BYTE); + else + expr_set_context(&ctx->ectx, &ip6addr_type, 16 * BITS_PER_BYTE); + + return expr_evaluate(ctx, expr); +} + +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) + return stmt_binary_error(ctx, *expr, stmt, + "transport protocol mapping is only " + "valid after transport protocol match"); + + expr_set_context(&ctx->ectx, &inet_service_type, 2 * BITS_PER_BYTE); + return expr_evaluate(ctx, expr); +} + static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt) { struct proto_ctx *pctx = &ctx->pctx; int err; + err = nat_evaluate_family(ctx, stmt); + if (err < 0) + return err; + if (stmt->nat.addr != NULL) { - if (pctx && (pctx->family == AF_INET)) - expr_set_context(&ctx->ectx, &ipaddr_type, - 4 * BITS_PER_BYTE); - else - expr_set_context(&ctx->ectx, &ip6addr_type, - 16 * BITS_PER_BYTE); - err = expr_evaluate(ctx, &stmt->nat.addr); + err = nat_evaluate_addr(ctx, stmt, &stmt->nat.addr); if (err < 0) return err; } - if (stmt->nat.proto != NULL) { - if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL) - return stmt_binary_error(ctx, stmt->nat.proto, stmt, - "transport protocol mapping is only " - "valid after transport protocol match"); - - expr_set_context(&ctx->ectx, &inet_service_type, - 2 * BITS_PER_BYTE); - err = expr_evaluate(ctx, &stmt->nat.proto); + err = nat_evaluate_transport(ctx, stmt, &stmt->nat.proto); if (err < 0) return err; } @@ -1533,62 +1562,31 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt) static int stmt_evaluate_masq(struct eval_ctx *ctx, struct stmt *stmt) { struct proto_ctx *pctx = &ctx->pctx; + int err; - if (!pctx) - goto out; - - switch (pctx->family) { - case AF_INET: - expr_set_context(&ctx->ectx, &ipaddr_type, - 4 * BITS_PER_BYTE); - break; - case AF_INET6: - expr_set_context(&ctx->ectx, &ip6addr_type, - 16 * BITS_PER_BYTE); - break; - default: - return stmt_error(ctx, stmt, "ip and ip6 support only"); - } + err = nat_evaluate_family(ctx, stmt); + if (err < 0) + return err; -out: stmt->flags |= STMT_F_TERMINAL; return 0; } static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt) { - int err; struct proto_ctx *pctx = &ctx->pctx; + int err; - if (!pctx) - goto out; - - switch (pctx->family) { - case AF_INET: - expr_set_context(&ctx->ectx, &ipaddr_type, - 4 * BITS_PER_BYTE); - break; - case AF_INET6: - expr_set_context(&ctx->ectx, &ip6addr_type, - 16 * BITS_PER_BYTE); - break; - default: - return stmt_error(ctx, stmt, "ip and ip6 support only"); - } + err = nat_evaluate_family(ctx, stmt); + if (err < 0) + return err; if (stmt->redir.proto != NULL) { - if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL) - return stmt_binary_error(ctx, stmt->redir.proto, stmt, - "missing transport protocol match"); - - expr_set_context(&ctx->ectx, &inet_service_type, - 2 * BITS_PER_BYTE); - err = expr_evaluate(ctx, &stmt->redir.proto); + err = nat_evaluate_transport(ctx, stmt, &stmt->redir.proto); if (err < 0) return err; } -out: stmt->flags |= STMT_F_TERMINAL; return 0; } |