From d100e2d811749bf34bb6aeac322052c56661c124 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Jul 2020 14:36:28 +0200 Subject: src: allow to use variables in flowtable and chain devices This patch adds support for using variables for devices in the chain and flowtable definitions, eg. define if_main = lo table netdev filter1 { chain Main_Ingress1 { type filter hook ingress device $if_main priority -500; policy accept; } } Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/parser_bison.y | 16 +++++++++++++ 2 files changed, 85 insertions(+) (limited to 'src') diff --git a/src/evaluate.c b/src/evaluate.c index 67eb5d60..c9601f17 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3719,6 +3719,69 @@ static bool evaluate_priority(struct eval_ctx *ctx, struct prio_spec *prio, return true; } +static bool evaluate_expr_variable(struct eval_ctx *ctx, struct expr **exprp) +{ + struct expr *expr; + + if (expr_evaluate(ctx, exprp) < 0) + return false; + + expr = *exprp; + if (expr->etype != EXPR_VALUE && + expr->etype != EXPR_SET) { + expr_error(ctx->msgs, expr, "%s is not a valid " + "variable expression", expr_name(expr)); + return false; + } + + return true; +} + +static bool evaluate_device_expr(struct eval_ctx *ctx, struct expr **dev_expr) +{ + struct expr *expr, *next, *key; + LIST_HEAD(tmp); + + if ((*dev_expr)->etype == EXPR_VARIABLE) { + expr_set_context(&ctx->ectx, &ifname_type, + IFNAMSIZ * BITS_PER_BYTE); + if (!evaluate_expr_variable(ctx, dev_expr)) + return false; + } + + if ((*dev_expr)->etype != EXPR_SET && + (*dev_expr)->etype != EXPR_LIST) + return true; + + list_for_each_entry_safe(expr, next, &(*dev_expr)->expressions, list) { + list_del(&expr->list); + + switch (expr->etype) { + case EXPR_VARIABLE: + expr_set_context(&ctx->ectx, &ifname_type, + IFNAMSIZ * BITS_PER_BYTE); + if (!evaluate_expr_variable(ctx, &expr)) + return false; + break; + case EXPR_SET_ELEM: + key = expr_clone(expr->key); + expr_free(expr); + expr = key; + break; + case EXPR_VALUE: + break; + default: + BUG("invalid expresion type %s\n", expr_name(expr)); + break; + } + + list_add(&expr->list, &tmp); + } + list_splice_init(&tmp, &(*dev_expr)->expressions); + + return true; +} + static uint32_t str2hooknum(uint32_t family, const char *hook); static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft) @@ -3740,6 +3803,9 @@ static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft) expr_name(ft->priority.expr)); } + if (ft->dev_expr && !evaluate_device_expr(ctx, &ft->dev_expr)) + return -1; + return 0; } @@ -3965,6 +4031,9 @@ static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain) if (!chain->dev_expr) return __stmt_binary_error(ctx, &chain->loc, NULL, "Missing `device' in this chain definition"); + + if (!evaluate_device_expr(ctx, &chain->dev_expr)) + return -1; } else if (chain->dev_expr) { return __stmt_binary_error(ctx, &chain->dev_expr->location, NULL, "This chain type cannot be bound to device"); diff --git a/src/parser_bison.y b/src/parser_bison.y index 572e584c..d2d7694a 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1945,6 +1945,11 @@ flowtable_expr : '{' flowtable_list_expr '}' $2->location = @$; $$ = $2; } + | variable_expr + { + $1->location = @$; + $$ = $1; + } ; flowtable_list_expr : flowtable_expr_member @@ -1967,6 +1972,11 @@ flowtable_expr_member : STRING strlen($1) * BITS_PER_BYTE, $1); xfree($1); } + | variable_expr + { + datatype_set($1->sym->expr, &ifname_type); + $$ = $1; + } ; data_type_atom_expr : type_identifier @@ -2206,6 +2216,12 @@ dev_spec : DEVICE string compound_expr_add($$, expr); } + | DEVICE variable_expr + { + datatype_set($2->sym->expr, &ifname_type); + $$ = compound_expr_alloc(&@$, EXPR_LIST); + compound_expr_add($$, $2); + } | DEVICES '=' flowtable_expr { $$ = $3; -- cgit v1.2.3