]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: prefer native expressions instead of tcp match
authorFlorian Westphal <fw@strlen.de>
Tue, 25 Jan 2022 16:52:59 +0000 (17:52 +0100)
committerFlorian Westphal <fw@strlen.de>
Sat, 29 Jan 2022 12:38:11 +0000 (13:38 +0100)
Instead of using nft_compat+xtables tcp match, prefer to
emit payload+cmp or payload+range expression.

Unlike udp, tcp has flag bits that can be matched too but
we have to fall back to the xt expression for now.
We also don't support tcp option match, but thats a rarely
used feature anyway.

Delinearization support for ports was added in previous patches.

Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/nft.c

index 9f181de53678f2a65767822e4ff85a28c095ebff..4b5c4332c7c1d88c670231b1eba969561a101083 100644 (file)
@@ -1346,6 +1346,36 @@ static int add_nft_udp(struct nftnl_rule *r, struct xt_entry_match *m)
                              udp->dpts, udp->invflags & XT_UDP_INV_DSTPT);
 }
 
+static bool tcp_all_zero(const struct xt_tcp *t)
+{
+       static const struct xt_tcp zero = {
+               .spts[1] = 0xffff,
+               .dpts[1] = 0xffff,
+       };
+
+       return memcmp(t, &zero, sizeof(*t)) == 0;
+}
+
+static int add_nft_tcp(struct nftnl_rule *r, struct xt_entry_match *m)
+{
+       static const uint8_t supported = XT_TCP_INV_SRCPT | XT_TCP_INV_DSTPT;
+       struct xt_tcp *tcp = (void *)m->data;
+
+       if (tcp->invflags & ~supported || tcp->option ||
+           tcp->flg_mask || tcp->flg_cmp ||
+           tcp_all_zero(tcp)) {
+               struct nftnl_expr *expr = nftnl_expr_alloc("match");
+               int ret;
+
+               ret = __add_match(expr, m);
+               nftnl_rule_add_expr(r, expr);
+               return ret;
+       }
+
+       return add_nft_tcpudp(r, tcp->spts, tcp->invflags & XT_TCP_INV_SRCPT,
+                             tcp->dpts, tcp->invflags & XT_TCP_INV_DSTPT);
+}
+
 int add_match(struct nft_handle *h,
              struct nftnl_rule *r, struct xt_entry_match *m)
 {
@@ -1358,6 +1388,8 @@ int add_match(struct nft_handle *h,
                return add_nft_among(h, r, m);
        else if (!strcmp(m->u.user.name, "udp"))
                return add_nft_udp(r, m);
+       else if (!strcmp(m->u.user.name, "tcp"))
+               return add_nft_tcp(r, m);
 
        expr = nftnl_expr_alloc("match");
        if (expr == NULL)