]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
tcpopt: add symbol table for mptcp suboptions
authorFlorian Westphal <fw@strlen.de>
Thu, 27 Feb 2025 14:52:07 +0000 (15:52 +0100)
committerFlorian Westphal <fw@strlen.de>
Thu, 6 Mar 2025 03:55:43 +0000 (04:55 +0100)
nft can be used t match on specific multipath tcp subtypes:

  tcp option mptcp subtype 0

However, depending on which subtype to match, users need to look up the
type/value to use in rfc8684. Add support for mnemonics and
"nft describe tcp option mptcp subtype" to get the subtype list.

Because the number of unique 'enum datatypes' is limited by ABI contraints
this adds a new mptcp suboption type as integer alias.

After this patch, nft supports all of the following:
 add element t s { mp-capable }
 add rule t c tcp option mptcp subtype mp-capable
 add rule t c tcp option mptcp subtype { mp-capable, mp-fail }

For the 3rd case, listing will break because unlike for named sets, nft
lacks the type information needed to pretty-print the integer values,
i.e. nft will print the 3rd rule as 'subtype { 0, 6 }'.

This is resolved in a followup patch.

Other problematic constructs are:
  set s1 {
    typeof tcp option mptcp subtype . ip saddr
    elements = { mp-fail . 1.2.3.4 }
  }

Followed by:
  tcp option mptcp subtype . ip saddr @s1

nft will print this as:
  tcp option mptcp unknown & 240) >> 4 . ip saddr @s1

All of these issues are not related to this patch, however, they also occur
with other bit-sized extheader fields.

Signed-off-by: Florian Westphal <fw@strlen.de>
include/datatype.h
src/tcpopt.c
tests/py/any/tcpopt.t
tests/py/any/tcpopt.t.json
tests/py/any/tcpopt.t.payload
tests/shell/testcases/sets/dumps/typeof_sets_0.nft
tests/shell/testcases/sets/typeof_sets_0

index 8b950f9165a583bb3521dfdd79f278f6587519d0..4fb47f158fc2f5a2bd16a7270ea009396a9cb22d 100644 (file)
@@ -251,7 +251,6 @@ extern const struct datatype verdict_type;
 extern const struct datatype nfproto_type;
 extern const struct datatype bitmask_type;
 extern const struct datatype integer_type;
-extern const struct datatype xinteger_type;
 extern const struct datatype string_type;
 extern const struct datatype lladdr_type;
 extern const struct datatype ipaddr_type;
@@ -279,6 +278,10 @@ extern const struct datatype reject_icmp_code_type;
 extern const struct datatype reject_icmpv6_code_type;
 extern const struct datatype reject_icmpx_code_type;
 
+/* TYPE_INTEGER aliases: */
+extern const struct datatype xinteger_type;
+extern const struct datatype mptcpopt_subtype;
+
 void inet_service_type_print(const struct expr *expr, struct output_ctx *octx);
 
 extern const struct datatype *concat_type_alloc(uint32_t type);
index f977e417536adaf582bfdc52481242ff31e41210..d8139337cc20d603825054c57c2dc472ebcda38f 100644 (file)
@@ -108,6 +108,31 @@ static const struct exthdr_desc tcpopt_md5sig = {
        },
 };
 
+static const struct symbol_table mptcp_subtype_tbl = {
+       .base           = BASE_DECIMAL,
+       .symbols        = {
+               SYMBOL("mp-capable",    0),
+               SYMBOL("mp-join",       1),
+               SYMBOL("dss",           2),
+               SYMBOL("add-addr",      3),
+               SYMBOL("remove-addr",   4),
+               SYMBOL("mp-prio",       5),
+               SYMBOL("mp-fail",       6),
+               SYMBOL("mp-fastclose",  7),
+               SYMBOL("mp-tcprst",     8),
+               SYMBOL_LIST_END
+       },
+};
+
+/* alias of integer_type to parse mptcp subtypes */
+const struct datatype mptcpopt_subtype = {
+       .type           = TYPE_INTEGER,
+       .name           = "integer",
+       .desc           = "mptcp option subtype",
+       .size           = 4,
+       .basetype       = &integer_type,
+       .sym_tbl        = &mptcp_subtype_tbl,
+};
 
 static const struct exthdr_desc tcpopt_mptcp = {
        .name           = "mptcp",
@@ -115,7 +140,10 @@ static const struct exthdr_desc tcpopt_mptcp = {
        .templates      = {
                [TCPOPT_MPTCP_KIND]     = PHT("kind",   0,   8),
                [TCPOPT_MPTCP_LENGTH]   = PHT("length", 8,  8),
-               [TCPOPT_MPTCP_SUBTYPE]  = PHT("subtype", 16, 4),
+               [TCPOPT_MPTCP_SUBTYPE]  = PROTO_HDR_TEMPLATE("subtype",
+                                                            &mptcpopt_subtype,
+                                                            BYTEORDER_BIG_ENDIAN,
+                                                            16, 4),
        },
 };
 
index 177f01c455066d9eec395be4ee72694ff870d31f..a2fcdb3afb25221cd35b77c2bec117bbcdc0ef13 100644 (file)
@@ -51,8 +51,8 @@ tcp option md5sig exists;ok
 tcp option fastopen exists;ok
 tcp option mptcp exists;ok
 
-tcp option mptcp subtype 0;ok
-tcp option mptcp subtype 1;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
 
 reset tcp option mptcp;ok
index 87074b9d216a3a1358b57a818b4071ac964addd4..ea580473c8ade67ace907908ed96feea3f997333 100644 (file)
     }
 ]
 
-# tcp option mptcp subtype 0
+# tcp option mptcp subtype mp-capable
 [
     {
         "match": {
                 }
             },
             "op": "==",
-            "right": 0
+            "right": "mp-capable"
         }
     }
 ]
                 }
             },
             "op": "==",
-            "right": 1
+            "right": "mp-join"
         }
     }
 ]
index 99b8985f0f68ae92824fc228483ff086561c8865..e3cf500b964b75fad731ac2e0631b3074002d675 100644 (file)
@@ -168,7 +168,7 @@ inet
   [ exthdr load tcpopt 1b @ 30 + 0 present => reg 1 ]
   [ cmp eq reg 1 0x00000001 ]
 
-# tcp option mptcp subtype 0
+# tcp option mptcp subtype mp-capable
 inet
   [ exthdr load tcpopt 1b @ 30 + 2 => reg 1 ]
   [ bitwise reg 1 = ( reg 1 & 0x000000f0 ) ^ 0x00000000 ]
index 63fc5b14513730038891d61200dc04282a3e9f5a..ed45d84a0effe603b7cb27ce93ef07107cc3d073 100644 (file)
@@ -60,6 +60,11 @@ table inet t {
                elements = { "eth0" . 10.1.1.2 . exists }
        }
 
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
+       }
+
        chain c1 {
                osf name @s1 accept
        }
@@ -103,4 +108,8 @@ table inet t {
        chain c12 {
                iifname . ip saddr . meta ipsec @s12 accept
        }
+
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
 }
index a105acffde48c4225e05e96ba4ff2f39d459106b..5ba7fc76ce15380303e3c3177e1f43b775c1a89f 100755 (executable)
@@ -119,6 +119,11 @@ INPUT="table inet t {$INPUT_OSF_SET
                typeof meta iifname . ip saddr . meta ipsec
                elements = { \"eth0\" . 10.1.1.2 . 1 }
        }
+
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
+       }
 $INPUT_OSF_CHAIN
        chain c2 {
                ether type vlan vlan id @s2 accept
@@ -148,6 +153,10 @@ $INPUT_VERSION_CHAIN
        chain c12 {
                meta iifname . ip saddr . meta ipsec @s12 accept
        }
+
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
 }"
 
 EXPECTED="table inet t {$INPUT_OSF_SET
@@ -196,6 +205,11 @@ $INPUT_VERSION_SET
                typeof iifname . ip saddr . meta ipsec
                elements = { \"eth0\" . 10.1.1.2 . exists }
        }
+
+       set s13 {
+               typeof tcp option mptcp subtype
+               elements = { mp-join, dss }
+       }
 $INPUT_OSF_CHAIN
        chain c2 {
                vlan id @s2 accept
@@ -224,6 +238,10 @@ $INPUT_SCTP_CHAIN$INPUT_VERSION_CHAIN
        chain c12 {
                iifname . ip saddr . meta ipsec @s12 accept
        }
+
+       chain c13 {
+               tcp option mptcp subtype @s13 accept
+       }
 }"