From 4ab1e5e6077918b5b0b4553daa907a725d4cd0fe Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 30 Jan 2021 19:58:42 +0100 Subject: src: allow use of 'verdict' in typeof definitions 'verdict' cannot be used as part of a map typeof-based key definition, its a datatype and not an expression, e.g.: typeof iifname . ip protocol . th dport : verdic ... will fail. Make the parser convert a 'verdict' symbol to a verdict expression and allow to store its presence as part of the typeof key definition. Reported-by: Frank Myhr Signed-off-by: Florian Westphal --- src/expression.c | 17 +++++++++++++ src/parser_bison.y | 29 +++++++++++++++++++--- tests/shell/testcases/maps/dumps/typeof_maps_0.nft | 4 +++ tests/shell/testcases/maps/typeof_maps_0 | 4 +++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/expression.c b/src/expression.c index a90a89ca..8c6beef9 100644 --- a/src/expression.c +++ b/src/expression.c @@ -252,6 +252,21 @@ static void verdict_expr_destroy(struct expr *expr) expr_free(expr->chain); } +static int verdict_expr_build_udata(struct nftnl_udata_buf *udbuf, + const struct expr *expr) +{ + return 0; +} + +static struct expr *verdict_expr_parse_udata(const struct nftnl_udata *attr) +{ + struct expr *e = verdict_expr_alloc(&internal_location, 0, NULL); + + e = symbol_expr_alloc(&internal_location, SYMBOL_VALUE, NULL, "verdict"); + e->len = NFT_REG_SIZE * BITS_PER_BYTE; + return e; +} + static const struct expr_ops verdict_expr_ops = { .type = EXPR_VERDICT, .name = "verdict", @@ -260,6 +275,8 @@ static const struct expr_ops verdict_expr_ops = { .cmp = verdict_expr_cmp, .clone = verdict_expr_clone, .destroy = verdict_expr_destroy, + .build_udata = verdict_expr_build_udata, + .parse_udata = verdict_expr_parse_udata, }; struct expr *verdict_expr_alloc(const struct location *loc, diff --git a/src/parser_bison.y b/src/parser_bison.y index 11e899ff..3c8013b2 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -672,8 +672,8 @@ int nft_lex(void *, void *, void *); %type symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr %destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr -%type primary_expr shift_expr and_expr typeof_expr -%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr +%type primary_expr shift_expr and_expr typeof_expr typeof_data_expr +%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr %type exclusive_or_expr inclusive_or_expr %destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr %type basic_expr @@ -1739,6 +1739,29 @@ subchain_block : /* empty */ { $$ = $-1; } } ; +typeof_data_expr : primary_expr + { + struct expr *e = $1; + + if (e->etype == EXPR_SYMBOL && + strcmp("verdict", e->identifier) == 0) { + struct expr *v = verdict_expr_alloc(&@1, NF_ACCEPT, NULL); + + expr_free(e); + v->flags &= ~EXPR_F_CONSTANT; + e = v; + } + + if (expr_ops(e)->build_udata == NULL) { + erec_queue(error(&@1, "map data type '%s' lacks typeof serialization", expr_ops(e)->name), + state->msgs); + expr_free(e); + YYERROR; + } + $$ = e; + } + ; + typeof_expr : primary_expr { if (expr_ops($1)->build_udata == NULL) { @@ -1878,7 +1901,7 @@ map_block : /* empty */ { $$ = $-1; } $$ = $1; } | map_block TYPEOF - typeof_expr COLON typeof_expr + typeof_expr COLON typeof_data_expr stmt_separator { $1->key = $3; diff --git a/tests/shell/testcases/maps/dumps/typeof_maps_0.nft b/tests/shell/testcases/maps/dumps/typeof_maps_0.nft index faa73cd1..438b9829 100644 --- a/tests/shell/testcases/maps/dumps/typeof_maps_0.nft +++ b/tests/shell/testcases/maps/dumps/typeof_maps_0.nft @@ -15,6 +15,10 @@ table inet t { 2.3.4.5 . 6.7.8.9 : 0x00000002 } } + map m4 { + typeof iifname . ip protocol . th dport : verdict + } + chain c { ct mark set osf name map @m1 meta mark set vlan id map @m2 diff --git a/tests/shell/testcases/maps/typeof_maps_0 b/tests/shell/testcases/maps/typeof_maps_0 index e1c4bba9..f024ebe0 100755 --- a/tests/shell/testcases/maps/typeof_maps_0 +++ b/tests/shell/testcases/maps/typeof_maps_0 @@ -22,6 +22,10 @@ EXPECTED="table inet t { 2.3.4.5 . 6.7.8.9 : 0x00000002 } } + map m4 { + typeof iifname . ip protocol . th dport : verdict + } + chain c { ct mark set osf name map @m1 ether type vlan meta mark set vlan id map @m2 -- cgit v1.2.3