]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
meta: allow resolving meta keys at run time
authorFlorian Westphal <fw@strlen.de>
Wed, 27 Jul 2016 07:42:38 +0000 (09:42 +0200)
committerFlorian Westphal <fw@strlen.de>
Thu, 27 Oct 2016 20:34:31 +0000 (22:34 +0200)
use the meta template to translate the textual token to the enum value.
This allows to remove two keywords from the scanner and also means we do
not need to introduce new keywords when more meta keys get added.

Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/meta.h
src/meta.c
src/parser_bison.y
src/scanner.l

index f25b147a624fa2ebdee9a20618d9c14a3e5aa26f..55784609e564c9359aa57ee937586a8e8b114cd6 100644 (file)
@@ -30,4 +30,8 @@ struct stmt *meta_stmt_meta_iiftype(const struct location *loc, uint16_t type);
 
 const struct datatype ifindex_type;
 
+struct error_record *meta_key_parse(const struct location *loc,
+                                   const char *name,
+                                   unsigned int *value);
+
 #endif /* NFTABLES_META_H */
index bd1e4f283823532f332fcd381899fb1e132550fc..574fc5000c91f47d1182cd232143f2cfe25f4997 100644 (file)
@@ -640,3 +640,39 @@ struct stmt *meta_stmt_meta_iiftype(const struct location *loc, uint16_t type)
        dep = relational_expr_alloc(loc, OP_EQ, left, right);
        return expr_stmt_alloc(&dep->location, dep);
 }
+
+struct error_record *meta_key_parse(const struct location *loc,
+                                    const char *str,
+                                    unsigned int *value)
+{
+       int ret, len, offset = 0;
+       const char *sep = "";
+       unsigned int i;
+       char buf[1024];
+       size_t size;
+
+       for (i = 0; i < array_size(meta_templates); i++) {
+               if (!meta_templates[i].token || strcmp(meta_templates[i].token, str))
+                       continue;
+
+               *value = i;
+               return NULL;
+       }
+
+       len = (int)sizeof(buf);
+       size = sizeof(buf);
+
+       for (i = 0; i < array_size(meta_templates); i++) {
+               if (!meta_templates[i].token)
+                       continue;
+
+               if (offset)
+                       sep = ", ";
+
+               ret = snprintf(buf+offset, len, "%s%s", sep, meta_templates[i].token);
+               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+               assert(offset < (int)sizeof(buf));
+       }
+
+       return error(loc, "syntax error, unexpected %s, known keys are %s", str, buf);
+}
index 1730b8d30d6df6b4f59d83655156d1418478bb72..ec9052afdeebdbdbda6cd35d0c85130e7abd24f4 100644 (file)
@@ -319,8 +319,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token MH                      "mh"
 
 %token META                    "meta"
-%token NFPROTO                 "nfproto"
-%token L4PROTO                 "l4proto"
 %token MARK                    "mark"
 %token IIF                     "iif"
 %token IIFNAME                 "iifname"
@@ -2443,15 +2441,25 @@ meta_expr               :       META    meta_key
                        {
                                $$ = meta_expr_alloc(&@$, $1);
                        }
-                       ;
+                       |       META    STRING
+                       {
+                               struct error_record *erec;
+                               unsigned int key;
+
+                               erec = meta_key_parse(&@$, $2, &key);
+                               if (erec != NULL) {
+                                       erec_queue(erec, state->msgs);
+                                       YYERROR;
+                               }
+
+                               $$ = meta_expr_alloc(&@$, key);
+                       }
 
 meta_key               :       meta_key_qualified
                        |       meta_key_unqualified
                        ;
 
 meta_key_qualified     :       LENGTH          { $$ = NFT_META_LEN; }
-                       |       NFPROTO         { $$ = NFT_META_NFPROTO; }
-                       |       L4PROTO         { $$ = NFT_META_L4PROTO; }
                        |       PROTOCOL        { $$ = NFT_META_PROTOCOL; }
                        |       PRIORITY        { $$ = NFT_META_PRIORITY; }
                        |       RANDOM          { $$ = NFT_META_PRANDOM; }
@@ -2485,6 +2493,19 @@ meta_stmt                :       META    meta_key        SET     expr
                        {
                                $$ = meta_stmt_alloc(&@$, $1, $3);
                        }
+                       |       META    STRING  SET     expr
+                       {
+                               struct error_record *erec;
+                               unsigned int key;
+
+                               erec = meta_key_parse(&@$, $2, &key);
+                               if (erec != NULL) {
+                                       erec_queue(erec, state->msgs);
+                                       YYERROR;
+                               }
+
+                               $$ = meta_stmt_alloc(&@$, key, $4);
+                       }
                        ;
 
 offset_opt             :       /* empty */     { $$ = 0; }
index 2ddcad946b7e9421ffb502c80f45b255ecb5c58d..8afddf15d3cc02c293c48cfafd47b6ba5cf87115 100644 (file)
@@ -427,8 +427,6 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "mh"                   { return MH; }
 
 "meta"                 { return META; }
-"nfproto"              { return NFPROTO; }
-"l4proto"              { return L4PROTO; }
 "mark"                 { return MARK; }
 "iif"                  { return IIF; }
 "iifname"              { return IIFNAME; }