diff --git a/filter/filter.c b/filter/filter.c index 2a626188..fd2c16b1 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -112,7 +112,7 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; * TWOARGS macro to get both of them evaluated. */ static enum filter_return -interpret(struct filter_state *fs, const struct f_line *line, uint argc, const struct f_val *argv, struct f_val *val) +interpret(struct filter_state *fs, const struct f_line *line, uint argc, const struct f_val *argv, uint resc, struct f_val *resv) { /* Check of appropriate number of arguments */ ASSERT(line->args == argc); @@ -178,21 +178,14 @@ interpret(struct filter_state *fs, const struct f_line *line, uint argc, const s fstk->ecnt--; } - if (fstk->vcnt == 0) { - if (val) { - log_rl(&rl_runtime_err, L_ERR "filters: No value left on stack"); - return F_ERROR; - } - return F_NOP; + if (fstk->vcnt != resc) + { + log_rl(&rl_runtime_err, L_ERR "Filter expected to leave %d values on stack but %d left instead", resc, fstk->vcnt); + return F_ERROR; } - if (val && (fstk->vcnt == 1)) { - *val = fstk->vstk[0]; - return F_NOP; - } - - log_rl(&rl_runtime_err, L_ERR "Too many items left on stack: %u", fstk->vcnt); - return F_ERROR; + memcpy(resv, fstk->vstk, sizeof(struct f_val) * resc); + return F_NOP; } @@ -232,7 +225,7 @@ f_run_args(const struct filter *filter, struct rte *rte, uint argc, const struct f_stack_init(filter_state); /* Run the interpreter itself */ - enum filter_return fret = interpret(&filter_state, filter->root, argc, argv, NULL); + enum filter_return fret = interpret(&filter_state, filter->root, argc, argv, 0, NULL); /* Process the filter output, log it and return */ if (fret < F_ACCEPT) { @@ -258,7 +251,7 @@ f_run_args(const struct filter *filter, struct rte *rte, uint argc, const struct */ enum filter_return -f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, struct f_val *pres) +f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, uint resc, struct f_val *resv) { filter_state = (struct filter_state) { .rte = rte, @@ -266,14 +259,14 @@ f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f f_stack_init(filter_state); - return interpret(&filter_state, expr, argc, argv, pres); + return interpret(&filter_state, expr, argc, argv, resc, resv); } /* * f_eval - get a value of a term * @expr: filter line containing the term * @tmp_pool: long data may get allocated from this pool - * @pres: here the output will be stored + * @pres: here the output will be stored if requested */ enum filter_return f_eval(const struct f_line *expr, struct f_val *pres) @@ -282,7 +275,7 @@ f_eval(const struct f_line *expr, struct f_val *pres) f_stack_init(filter_state); - enum filter_return fret = interpret(&filter_state, expr, 0, NULL, pres); + enum filter_return fret = interpret(&filter_state, expr, 0, NULL, !!pres, pres); return fret; } diff --git a/filter/filter.h b/filter/filter.h index 121da468..8d495e2d 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -54,7 +54,7 @@ struct rte; enum filter_return f_run(const struct filter *filter, struct rte *rte, int flags); enum filter_return f_run_args(const struct filter *filter, struct rte *rte, uint argc, const struct f_val *argv, int flags); -enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, struct f_val *pres); +enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, uint resc, struct f_val *resv); enum filter_return f_eval_buf(const struct f_line *expr, buffer *buf); struct f_val cf_eval_tmp(const struct f_inst *inst, int type); diff --git a/proto/static/static.c b/proto/static/static.c index 27b9a26f..c43f098c 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -122,7 +122,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) /* Evaluate the filter */ if (r->cmds) - f_eval_rte(r->cmds, e, 0, NULL, NULL); + f_eval_rte(r->cmds, e, 0, NULL, 0, NULL); rte_update(p->p.main_channel, r->net, e, src); static_free_source(src, r->index);