]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: allow use of 'verdict' in typeof definitions
authorFlorian Westphal <fw@strlen.de>
Sat, 30 Jan 2021 18:58:42 +0000 (19:58 +0100)
committerFlorian Westphal <fw@strlen.de>
Mon, 22 Feb 2021 13:57:49 +0000 (14:57 +0100)
'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 <fmyhr@fhmtech.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
src/expression.c
src/parser_bison.y
tests/shell/testcases/maps/dumps/typeof_maps_0.nft
tests/shell/testcases/maps/typeof_maps_0

index a90a89ca9f740e3d2323782be12b85500aecca1d..8c6beef9a5e51bda0d220e14434fe2c0ccf03718 100644 (file)
@@ -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,
index 11e899ff2f20e04050e88bb65efd414e7ddadb19..3c8013b2493e13d7e2f068a6c7b171d3c3d19e10 100644 (file)
@@ -672,8 +672,8 @@ int nft_lex(void *, void *, void *);
 
 %type <expr>                   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 <expr>                   primary_expr shift_expr and_expr typeof_expr
-%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr
+%type <expr>                   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 <expr>                   exclusive_or_expr inclusive_or_expr
 %destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
 %type <expr>                   basic_expr
@@ -1739,6 +1739,29 @@ subchain_block           :       /* empty */     { $$ = $<chain>-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 */     { $$ = $<set>-1; }
                                $$ = $1;
                        }
                        |       map_block       TYPEOF
-                                               typeof_expr     COLON   typeof_expr
+                                               typeof_expr     COLON   typeof_data_expr
                                                stmt_separator
                        {
                                $1->key = $3;
index faa73cd1af84b41c9e22090c41a96e5319b5e000..438b9829db907a0246d68567f92db66e193aa578 100644 (file)
@@ -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
index e1c4bba9f182ac6f82b620f1af17bce0f64cc867..f024ebe0f9f64c0658bddc2dacffe4e529494754 100755 (executable)
@@ -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