]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: add support for native tcp flag matching
authorFlorian Westphal <fw@strlen.de>
Tue, 25 Jan 2022 16:53:01 +0000 (17:53 +0100)
committerFlorian Westphal <fw@strlen.de>
Sat, 29 Jan 2022 12:39:52 +0000 (13:39 +0100)
prefer payload + bitwise + cmp to nft_compat match.

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

index 4b5c4332c7c1d88c670231b1eba969561a101083..3e434549979448a8263e854e9c7dc3bd2139c973 100644 (file)
@@ -1346,6 +1346,26 @@ static int add_nft_udp(struct nftnl_rule *r, struct xt_entry_match *m)
                              udp->dpts, udp->invflags & XT_UDP_INV_DSTPT);
 }
 
+static int add_nft_tcpflags(struct nftnl_rule *r,
+                           uint8_t cmp, uint8_t mask,
+                           bool invert)
+{
+       struct nftnl_expr *e;
+
+       e = gen_payload(NFT_PAYLOAD_TRANSPORT_HEADER,
+                       13, 1, NFT_REG_1);
+
+       if (!e)
+               return -ENOMEM;
+
+       nftnl_rule_add_expr(r, e);
+
+       add_bitwise(r, &mask, 1);
+       add_cmp_u8(r, cmp, invert ? NFT_CMP_NEQ : NFT_CMP_EQ);
+
+       return 0;
+}
+
 static bool tcp_all_zero(const struct xt_tcp *t)
 {
        static const struct xt_tcp zero = {
@@ -1358,11 +1378,10 @@ static bool tcp_all_zero(const struct xt_tcp *t)
 
 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;
+       static const uint8_t supported = XT_TCP_INV_SRCPT | XT_TCP_INV_DSTPT | XT_TCP_INV_FLAGS;
        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;
@@ -1372,6 +1391,14 @@ static int add_nft_tcp(struct nftnl_rule *r, struct xt_entry_match *m)
                return ret;
        }
 
+       if (tcp->flg_mask) {
+               int ret = add_nft_tcpflags(r, tcp->flg_cmp, tcp->flg_mask,
+                                          tcp->invflags & XT_TCP_INV_FLAGS);
+
+               if (ret < 0)
+                       return ret;
+       }
+
        return add_nft_tcpudp(r, tcp->spts, tcp->invflags & XT_TCP_INV_SRCPT,
                              tcp->dpts, tcp->invflags & XT_TCP_INV_DSTPT);
 }