]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
expression: propagate key datatype for anonymous sets
authorFlorian Westphal <fw@strlen.de>
Thu, 27 Feb 2025 14:52:08 +0000 (15:52 +0100)
committerFlorian Westphal <fw@strlen.de>
Thu, 6 Mar 2025 03:55:43 +0000 (04:55 +0100)
set s {
  typeof tcp option mptcp subtype
  elements = { mp-join, dss }
}

is listed correctly. The set key provides the 'mptcpopt_subtype'
information and listing can print all elements with symbolic names.

In anon set case this doesn't work:
  tcp option mptcp subtype { mp-join, dss }

is printed as "... subtype { 1, 2}" because the anon set only provides
plain integer type.

This change propagates the datatype to the individual members of the
anon set.

After this change, multiple existing data types such as TYPE_ICMP_TYPE
could theoretically be replaced by integer-type aliases.

However, those datatypes are already exposed to userspace via the
'set type' keyword.  Thus removing them will break set definitions that
use them.

Signed-off-by: Florian Westphal <fw@strlen.de>
src/expression.c
tests/py/any/tcpopt.t
tests/py/any/tcpopt.t.json
tests/py/any/tcpopt.t.payload

index 53d4c521ae183ab90ca90378b515d457c8b71a22..d2fa46509262bf5dd3c7c936cbe3323ff42243e8 100644 (file)
@@ -1485,6 +1485,32 @@ static void set_ref_expr_destroy(struct expr *expr)
        set_free(expr->set);
 }
 
+static void set_ref_expr_set_type(const struct expr *expr,
+                                 const struct datatype *dtype,
+                                 enum byteorder byteorder)
+{
+       const struct set *s = expr->set;
+
+       /* normal sets already have a precise datatype that is given in
+        * the set definition via type foo.
+        *
+        * Anon sets do not have this, and need to rely on type info
+        * generated at rule creation time.
+        *
+        * For most cases, the type info is correct.
+        * In some cases however, the kernel only stores TYPE_INTEGER.
+        *
+        * This happens with expressions that only use an integer alias
+        * type, e.g. the mptcpopt_subtype datatype.
+        *
+        * In this case nft will print the elements as numerical values
+        * because the base type lacks the ->sym_tbl information of the
+        * subtypes.
+        */
+       if (s->init && set_is_anonymous(s->flags))
+               expr_set_type(s->init, dtype, byteorder);
+}
+
 static const struct expr_ops set_ref_expr_ops = {
        .type           = EXPR_SET_REF,
        .name           = "set reference",
@@ -1492,6 +1518,7 @@ static const struct expr_ops set_ref_expr_ops = {
        .json           = set_ref_expr_json,
        .clone          = set_ref_expr_clone,
        .destroy        = set_ref_expr_destroy,
+       .set_type       = set_ref_expr_set_type,
 };
 
 struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set)
@@ -1556,6 +1583,13 @@ static void set_elem_expr_clone(struct expr *new, const struct expr *expr)
        __set_elem_expr_clone(new, expr);
 }
 
+static void set_elem_expr_set_type(const struct expr *expr,
+                                  const struct datatype *dtype,
+                                  enum byteorder byteorder)
+{
+       expr_set_type(expr->key, dtype, byteorder);
+}
+
 static const struct expr_ops set_elem_expr_ops = {
        .type           = EXPR_SET_ELEM,
        .name           = "set element",
@@ -1563,6 +1597,7 @@ static const struct expr_ops set_elem_expr_ops = {
        .print          = set_elem_expr_print,
        .json           = set_elem_expr_json,
        .destroy        = set_elem_expr_destroy,
+       .set_type       = set_elem_expr_set_type,
 };
 
 struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key)
index a2fcdb3afb25221cd35b77c2bec117bbcdc0ef13..79699e23a4b1efe4f74e9911c35b4b4baece67db 100644 (file)
@@ -53,7 +53,7 @@ tcp option mptcp exists;ok
 
 tcp option mptcp subtype mp-capable;ok
 tcp option mptcp subtype 1;ok;tcp option mptcp subtype mp-join
-tcp option mptcp subtype { 0, 2};ok
+tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst };ok
 
 reset tcp option mptcp;ok
 reset tcp option 2;ok;reset tcp option maxseg
index ea580473c8ade67ace907908ed96feea3f997333..a02e71b66c36b1ca1a77e00ba4ff07abd776a926 100644 (file)
     }
 ]
 
-# tcp option mptcp subtype { 0, 2}
+# tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst }
 [
     {
         "match": {
             "op": "==",
             "right": {
                 "set": [
-                    0,
-                    2
+                    "mp-capable",
+                    "mp-join",
+                    "remove-addr",
+                    "mp-prio",
+                    "mp-fail",
+                    "mp-fastclose",
+                    "mp-tcprst"
                 ]
             }
         }
index e3cf500b964b75fad731ac2e0631b3074002d675..af8c4317e56764f85dd48c5702e68cdf0a53489a 100644 (file)
@@ -180,11 +180,11 @@ inet
   [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
   [ cmp eq reg 1 0x00000010 ]
 
-# tcp option mptcp subtype { 0, 2}
-__set%d test-inet 3 size 2
-__set%d test-inet 0
-       element 00000000  : 0 [end]     element 00000020  : 0 [end]
-inet
+# tcp option mptcp subtype { mp-capable, mp-join, remove-addr, mp-prio, mp-fail, mp-fastclose, mp-tcprst }
+__set%d test-ip4 3 size 7
+__set%d test-ip4 0
+       element 00000000  : 0 [end]     element 00000010  : 0 [end]     element 00000040  : 0 [end]     element 00000050  : 0 [end]     element 00000060  : 0 [end]     element 00000070  : 0 [end]     element 00000080  : 0 [end]
+ip test-ip4 input
   [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
   [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
   [ lookup reg 1 set __set%d ]