diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2020-12-16 16:39:09 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2020-12-18 12:33:22 +0100 |
commit | e6d1d0d6119585a5cd63fcc02c0eb98e30b095cb (patch) | |
tree | 3b8c7c29b6b80a54dbfd4d485b73ce00d0f417f5 /src/evaluate.c | |
parent | 242965f452e64fef9faff6689df4b2c205823209 (diff) |
src: add set element multi-statement support
Extend the set element infrastructure to support for several statements.
This patch places the statements right after the key when printing it.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r-- | src/evaluate.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 03f060eb..ab9357fa 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1340,27 +1340,56 @@ static int expr_evaluate_list(struct eval_ctx *ctx, struct expr **expr) return 0; } -static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr) +static int __expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr *elem) { + int num_elem_exprs = 0, num_set_exprs = 0; struct set *set = ctx->set; - struct expr *elem = *expr; + struct stmt *stmt; + + list_for_each_entry(stmt, &elem->stmt_list, list) + num_elem_exprs++; + list_for_each_entry(stmt, &set->stmt_list, list) + num_set_exprs++; + + if (num_elem_exprs > 0) { + struct stmt *set_stmt, *elem_stmt; - if (elem->stmt) { - if (set->stmt && set->stmt->ops != elem->stmt->ops) { - return stmt_error(ctx, elem->stmt, - "statement mismatch, element expects %s, " - "but %s has type %s", - elem->stmt->ops->name, - set_is_map(set->flags) ? "map" : "set", - set->stmt->ops->name); - } else if (!set->stmt && !(set->flags & NFT_SET_EVAL)) { - return stmt_error(ctx, elem->stmt, - "missing %s statement in %s definition", - elem->stmt->ops->name, + if (num_set_exprs > 0 && num_elem_exprs != num_set_exprs) { + return expr_error(ctx->msgs, elem, + "number of statements mismatch, set expects %d " + "but element has %d", num_set_exprs, + num_elem_exprs); + } else if (num_set_exprs == 0 && !(set->flags & NFT_SET_EVAL)) { + return expr_error(ctx->msgs, elem, + "missing statements in %s definition", set_is_map(set->flags) ? "map" : "set"); } + + set_stmt = list_first_entry(&set->stmt_list, struct stmt, list); + + list_for_each_entry(elem_stmt, &elem->stmt_list, list) { + if (set_stmt->ops != elem_stmt->ops) { + return stmt_error(ctx, elem_stmt, + "statement mismatch, element expects %s, " + "but %s has type %s", + elem_stmt->ops->name, + set_is_map(set->flags) ? "map" : "set", + set_stmt->ops->name); + } + set_stmt = list_next_entry(set_stmt, list); + } } + return 0; +} + +static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr) +{ + struct expr *elem = *expr; + + if (ctx->set && __expr_evaluate_set_elem(ctx, elem) < 0) + return -1; + if (expr_evaluate(ctx, &elem->key) < 0) return -1; |