summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 759b1736..a116f7b6 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1446,6 +1446,9 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr)
if (binop_transfer(ctx, expr) < 0)
return -1;
+ if (ctx->set->data->flags & EXPR_F_INTERVAL)
+ ctx->set->data->len *= 2;
+
ctx->set->key->len = ctx->ectx.len;
ctx->set = NULL;
map = *expr;
@@ -1486,6 +1489,7 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
{
struct expr *mapping = *expr;
struct set *set = ctx->set;
+ uint32_t datalen;
if (set == NULL)
return expr_error(ctx->msgs, mapping,
@@ -1502,7 +1506,13 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
mapping->flags |= mapping->left->flags & EXPR_F_SINGLETON;
if (set->data) {
- expr_set_context(&ctx->ectx, set->data->dtype, set->data->len);
+ if (!set_is_anonymous(set->flags) &&
+ set->data->flags & EXPR_F_INTERVAL)
+ datalen = set->data->len / 2;
+ else
+ datalen = set->data->len;
+
+ expr_set_context(&ctx->ectx, set->data->dtype, datalen);
} else {
assert((set->flags & NFT_SET_MAP) == 0);
}
@@ -1512,7 +1522,14 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr)
if (!expr_is_constant(mapping->right))
return expr_error(ctx->msgs, mapping->right,
"Value must be a constant");
- if (!expr_is_singleton(mapping->right))
+
+ if (set_is_anonymous(set->flags) &&
+ (mapping->right->etype == EXPR_RANGE ||
+ mapping->right->etype == EXPR_PREFIX))
+ set->data->flags |= EXPR_F_INTERVAL;
+
+ if (!(set->data->flags & EXPR_F_INTERVAL) &&
+ !expr_is_singleton(mapping->right))
return expr_error(ctx->msgs, mapping->right,
"Value must be a singleton");
@@ -2970,6 +2987,27 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
if (err < 0)
return err;
}
+
+ if (stmt->nat.type_flags & STMT_NAT_F_INTERVAL) {
+ switch (stmt->nat.addr->etype) {
+ case EXPR_MAP:
+ if (!(stmt->nat.addr->mappings->set->data->flags & EXPR_F_INTERVAL))
+ return expr_error(ctx->msgs, stmt->nat.addr,
+ "map is not defined as interval");
+ break;
+ case EXPR_RANGE:
+ case EXPR_PREFIX:
+ break;
+ default:
+ return expr_error(ctx->msgs, stmt->nat.addr,
+ "neither prefix, range nor map expression");
+ }
+
+ stmt->flags |= STMT_F_TERMINAL;
+
+ return 0;
+ }
+
if (stmt->nat.proto != NULL) {
err = nat_evaluate_transport(ctx, stmt, &stmt->nat.proto);
if (err < 0)
@@ -3477,6 +3515,9 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
return set_error(ctx, set, "map definition does not "
"specify mapping data type");
+ if (set->data->flags & EXPR_F_INTERVAL)
+ set->data->len *= 2;
+
if (set->data->etype == EXPR_CONCAT &&
expr_evaluate_concat(ctx, &set->data, false) < 0)
return -1;