summaryrefslogtreecommitdiffstats
path: root/src/parser_bison.y
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2024-03-01 13:59:37 +0100
committerFlorian Westphal <fw@strlen.de>2024-03-05 21:55:21 +0100
commitacbac5e3ada4bdf16cf24056a8a7a7739429a8ab (patch)
treeb9ee801870bf3e3dcd4a525e5b9b3d4745404a81 /src/parser_bison.y
parentbb2054cfd99097973d98e231066297e9e8632a61 (diff)
parser: allow to define maps that contain ct helpers
Its currently not possible to use ct helpers in objref maps. Simply adding "CT HELPER" to "map_block_obj_type" does not work due to a conflict with the "ct helper" ct_expr block. map m { type ipv4_addr : ct helper .. ... declares a map storing ip addresses and conntrack helper names (string type). This does not make sense, there is no way to use the associated value (the names) in any sensible way: ct helper "ftp" - this matches if the packet has a conntrack entry that was accepted via the "ftp" conntrack helper. In nft vm terms, this is translated to: [ ct load helper => reg 1 ] [ cmp eq reg 1 0x00707466 0x00000000 0x00000000 0x00000000 ] Or one can query a set, e.g. 'ct helper { "ftp", "sip" }'. "ftp" and "sip" are the kernel-defined names of these connection tracking helpers. ct helper set "ftp" is something else, however: This is used to assign a *userspace defined helper objrect reference*. Nftables will translate this to: [ objref type 3 name ftp ] .. where "ftp" is a arbitrary user-chosen name. ct helper "ftp" { type "ftp" protocol tcp l3proto ip } IOW, "ct helper" is ambiguous. Without the "set" keyword (first case), it places the kernel-defined name of the active connection tracking helper in the chosen register (or it will cancel rule evaluation if no helper was active). With the set keyword (second case), the expected argument is a user-defined object reference which will then tell the connection tracking engine to monitor all further packets of the new flow with the given helper template. This change makes it so that map m { type ipv4_addr : ct helper .. declares a map storing ct helper object references suitable for 'ct helper set'. The better alternative would be to resolve the ambiguity by adding an additional postfix keyword, for example ct helper name (case one) ct helper object (case two). But this needs a kernel change that adds NFT_CT_HELPER_NAME and NFT_CT_HELPER_OBJECT to enum nft_ct_keys. While a new kernel could handle old nftables binaries that still use NFT_CT_HELPER key, new nftables would need to probe support first. Furthermore, ct helper name set "foo" ... would make no sense, as the kernel-defined helper names are readonly. ct helper object "foo" ... would make no sense, unless we extend the kernel to store the nftables userspace-defined name in a well-known location in the kernel. Userdata area cannot work for this, because the nft conntrack expression in the kernel would need to know how to retrieve this info again. Also, I cannot think of a sensible use case for this. So the only remaining, useful commands are: ct helper name "ftp" ct helper object set "foo" ... which is identical to what we already support, just with extra keyword. So a much simpler solution that does not need any kernel changes is make "ct helper" have different meaning depending on wheter it is placed on the key side, i.e.: "typeof ct helper", "typeof ct helper : $value" versus when its on placed on the data (value) side of maps: "typeof $key : ct helper". Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/parser_bison.y')
-rw-r--r--src/parser_bison.y11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 05861c3e..bdb73911 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2329,9 +2329,16 @@ map_block : /* empty */ { $$ = $<set>-1; }
}
$1->key = $3;
- $1->data = $5;
- $1->flags |= NFT_SET_MAP;
+ if ($5->etype == EXPR_CT && $5->ct.key == NFT_CT_HELPER) {
+ $1->objtype = NFT_OBJECT_CT_HELPER;
+ $1->flags |= NFT_SET_OBJECT;
+ expr_free($5);
+ } else {
+ $1->data = $5;
+ $1->flags |= NFT_SET_MAP;
+ }
+
$$ = $1;
}
| map_block TYPE