diff options
Diffstat (limited to 'src/evaluate.c')
-rw-r--r-- | src/evaluate.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index ce1e65f4..0afd0403 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2849,6 +2849,52 @@ static int stmt_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt, return err; } +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; + + 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; + if (expr_ops(data)->type != EXPR_CONCAT) + return __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size, + BYTEORDER_BIG_ENDIAN, + &stmt->nat.addr); + + one = list_first_entry(&data->expressions, struct expr, list); + two = list_entry(one->list.next, struct expr, list); + + if (one == two || !list_is_last(&two->list, &data->expressions)) + return __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size, + BYTEORDER_BIG_ENDIAN, + &stmt->nat.addr); + + tmp = one; + err = __stmt_evaluate_arg(ctx, stmt, dtype, dtype->size, + BYTEORDER_BIG_ENDIAN, + &tmp); + if (err < 0) + return err; + if (tmp != one) + BUG("Internal error: Unexpected alteration of l3 expression"); + + tmp = two; + err = nat_evaluate_transport(ctx, stmt, &tmp); + if (err < 0) + return err; + if (tmp != two) + BUG("Internal error: Unexpected alteration of l4 expression"); + + stmt->nat.ipportmap = true; + return err; +} + static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt) { int err; @@ -2862,6 +2908,16 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt) if (err < 0) return err; + if (stmt->nat.proto == NULL && + expr_ops(stmt->nat.addr)->type == EXPR_MAP) { + err = stmt_evaluate_nat_map(ctx, stmt); + if (err < 0) + return err; + + stmt->flags |= STMT_F_TERMINAL; + return 0; + } + err = stmt_evaluate_addr(ctx, stmt, stmt->nat.family, &stmt->nat.addr); if (err < 0) |