diff options
Diffstat (limited to 'src/evaluate.c')
-rw-r--r-- | src/evaluate.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index b722567c..3eeb614c 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1546,6 +1546,44 @@ out: return 0; } +static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt) +{ + int err; + struct proto_ctx *pctx = &ctx->pctx; + + 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"); + } + + 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); + if (err < 0) + return err; + } + +out: + stmt->flags |= STMT_F_TERMINAL; + return 0; +} + static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt) { expr_set_context(&ctx->ectx, stmt->ct.tmpl->dtype, @@ -1608,6 +1646,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt) return stmt_evaluate_nat(ctx, stmt); case STMT_MASQ: return stmt_evaluate_masq(ctx, stmt); + case STMT_REDIR: + return stmt_evaluate_redir(ctx, stmt); case STMT_QUEUE: return stmt_evaluate_queue(ctx, stmt); case STMT_CT: |