diff mbox series

[iptables] xtables-compat: fix ipv4 frag (-f)

Message ID 20180505085427.27040-1-fw@strlen.de
State Accepted
Headers show
Series [iptables] xtables-compat: fix ipv4 frag (-f) | expand

Commit Message

Florian Westphal May 5, 2018, 8:54 a.m. UTC
iptables-translate -A I -f
nft add rule ip filter I ip frag-off != 0 counter

iptables however checks:
frag_off = ntohs(iph->frag_off) & IP_OFFSET;

if (NF_INVF(ipinfo, IPT_INV_FRAG,
    (ipinfo->flags & IPT_F_FRAG) && !frag_off))
       return false;

So we need to mask off non-offset bits.

Second issue is that we negated the meaning in ipt-restore.

-f should match if (frag_off & IP_OFFSET) NE 0
  ! -f matches non-fragmented packets, i.e.
  frag_off & IP_OFFSET == 0.

So we cannot use nft_invflags2cmp(), as that will use
NEQ for negation, but we need EQ instead here.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 iptables/nft-ipv4.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index ef8c06eaa369..bdf478d1be5b 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -65,10 +65,13 @@  static int nft_ipv4_add(struct nftnl_rule *r, void *data)
 		add_payload(r, offsetof(struct iphdr, frag_off), 2,
 			    NFT_PAYLOAD_NETWORK_HEADER);
 		/* get the 13 bits that contain the fragment offset */
-		add_bitwise_u16(r, 0x1fff, !0x1fff);
+		add_bitwise_u16(r, 0x1fff, 0);
 
 		/* if offset is non-zero, this is a fragment */
-		op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_FRAG);
+		op = NFT_CMP_NEQ;
+		if (cs->fw.ip.invflags & IPT_INV_FRAG)
+			op = NFT_CMP_EQ;
+
 		add_cmp_u16(r, 0, op);
 	}
 
@@ -459,7 +462,7 @@  static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
 		     cs->fw.ip.invflags & IPT_INV_VIA_OUT);
 
 	if (cs->fw.ip.flags & IPT_F_FRAG) {
-		xt_xlate_add(xl, "ip frag-off %s%x ",
+		xt_xlate_add(xl, "ip frag-off & 0x1fff %s%x ",
 			   cs->fw.ip.invflags & IPT_INV_FRAG? "" : "!= ", 0);
 	}