summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2022-01-25 17:52:59 +0100
committerFlorian Westphal <fw@strlen.de>2022-01-29 13:38:11 +0100
commit6aba94ef5f50734dc72f455f195787b9c8540a78 (patch)
tree7e1dca5c4a1117a797705b9176a58210d846195e /iptables
parentc034cf31dd1a9079e197e4e6bb72bc7d19448114 (diff)
nft: prefer native expressions instead of tcp match
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>
Diffstat (limited to 'iptables')
-rw-r--r--iptables/nft.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 9f181de5..4b5c4332 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -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)