Blame SOURCES/0002-xtables-translate-Fix-translation-of-odd-netmasks.patch

3a00e5
From 14aed83fa22c5322637ec87a18d0d022d34b8d13 Mon Sep 17 00:00:00 2001
3a00e5
From: Phil Sutter <phil@nwl.cc>
3a00e5
Date: Tue, 2 Mar 2021 14:50:07 +0100
3a00e5
Subject: [PATCH] xtables-translate: Fix translation of odd netmasks
3a00e5
3a00e5
Iptables supports netmasks which are not prefixes to match on (or
3a00e5
ignore) arbitrary bits in an address. Yet nftables' prefix notation is
3a00e5
available for real prefixes only, so translation is not as trivial -
3a00e5
print bitmask syntax for those cases.
3a00e5
3a00e5
Signed-off-by: Phil Sutter <phil@nwl.cc>
3a00e5
(cherry picked from commit 46f9d3a9a61ee80fa94b7fa7b3b36045c92606ae)
3a00e5
---
3a00e5
 extensions/generic.txlate   | 48 +++++++++++++++++++++++++++++++++++++
3a00e5
 extensions/libxt_standard.t | 12 ++++++++++
3a00e5
 iptables/nft-ipv4.c         | 42 ++++++++++++++++++++++----------
3a00e5
 iptables/nft-ipv6.c         | 19 ++++++++++++---
3a00e5
 4 files changed, 106 insertions(+), 15 deletions(-)
3a00e5
3a00e5
diff --git a/extensions/generic.txlate b/extensions/generic.txlate
3a00e5
index 0e256c3727559..9ae9a5b54c1b9 100644
3a00e5
--- a/extensions/generic.txlate
3a00e5
+++ b/extensions/generic.txlate
3a00e5
@@ -10,6 +10,54 @@ nft insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter
3a00e5
 iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8
3a00e5
 nft add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter
3a00e5
 
3a00e5
+iptables-translate -I INPUT -s 10.11.12.13/255.255.0.0
3a00e5
+nft insert rule ip filter INPUT ip saddr 10.11.0.0/16 counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT -s 10.11.12.13/255.0.255.0
3a00e5
+nft insert rule ip filter INPUT ip saddr & 255.0.255.0 == 10.0.12.0 counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT -s 10.11.12.13/0.255.0.255
3a00e5
+nft insert rule ip filter INPUT ip saddr & 0.255.0.255 == 0.11.0.13 counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT ! -s 10.11.12.13/0.255.0.255
3a00e5
+nft insert rule ip filter INPUT ip saddr & 0.255.0.255 != 0.11.0.13 counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT -s 0.0.0.0/16
3a00e5
+nft insert rule ip filter INPUT ip saddr 0.0.0.0/16 counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT -s 0.0.0.0/0
3a00e5
+nft insert rule ip filter INPUT counter
3a00e5
+
3a00e5
+iptables-translate -I INPUT ! -s 0.0.0.0/0
3a00e5
+nft insert rule ip filter INPUT ip saddr != 0.0.0.0/0 counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -i iifname -s feed::/16
3a00e5
+nft insert rule ip6 filter INPUT iifname "iifname" ip6 saddr feed::/16 counter
3a00e5
+
3a00e5
+ip6tables-translate -A INPUT -i iif+ ! -d feed::/16
3a00e5
+nft add rule ip6 filter INPUT iifname "iif*" ip6 daddr != feed::/16 counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -s feed:babe::1/ffff:ff00::
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr feed:ba00::/24 counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/ffff:0:ffff:0:ffff:0:ffff:0
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr & ffff:0:ffff:0:ffff:0:ffff:0 == feed:0:c0ff:0:c0be:0:5678:0 counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff == 0:babe:0:ee00:0:1234:0:90ab counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT ! -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff != 0:babe:0:ee00:0:1234:0:90ab counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -s ::/16
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr ::/16 counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT -s ::/0
3a00e5
+nft insert rule ip6 filter INPUT counter
3a00e5
+
3a00e5
+ip6tables-translate -I INPUT ! -s ::/0
3a00e5
+nft insert rule ip6 filter INPUT ip6 saddr != ::/0 counter
3a00e5
+
3a00e5
 ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0
3a00e5
 nft insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter
3a00e5
 
3a00e5
diff --git a/extensions/libxt_standard.t b/extensions/libxt_standard.t
3a00e5
index 4313f7b7bac9d..56d6da2e5884e 100644
3a00e5
--- a/extensions/libxt_standard.t
3a00e5
+++ b/extensions/libxt_standard.t
3a00e5
@@ -9,3 +9,15 @@
3a00e5
 -j ACCEPT;=;OK
3a00e5
 -j RETURN;=;OK
3a00e5
 ! -p 0 -j ACCEPT;=;FAIL
3a00e5
+-s 10.11.12.13/8;-s 10.0.0.0/8;OK
3a00e5
+-s 10.11.12.13/9;-s 10.0.0.0/9;OK
3a00e5
+-s 10.11.12.13/10;-s 10.0.0.0/10;OK
3a00e5
+-s 10.11.12.13/11;-s 10.0.0.0/11;OK
3a00e5
+-s 10.11.12.13/12;-s 10.0.0.0/12;OK
3a00e5
+-s 10.11.12.13/30;-s 10.11.12.12/30;OK
3a00e5
+-s 10.11.12.13/31;-s 10.11.12.12/31;OK
3a00e5
+-s 10.11.12.13/32;-s 10.11.12.13/32;OK
3a00e5
+-s 10.11.12.13/255.0.0.0;-s 10.0.0.0/8;OK
3a00e5
+-s 10.11.12.13/255.128.0.0;-s 10.0.0.0/9;OK
3a00e5
+-s 10.11.12.13/255.0.255.0;-s 10.0.12.0/255.0.255.0;OK
3a00e5
+-s 10.11.12.13/255.0.12.0;-s 10.0.12.0/255.0.12.0;OK
3a00e5
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
3a00e5
index fdc15c6f04066..0d32a30010519 100644
3a00e5
--- a/iptables/nft-ipv4.c
3a00e5
+++ b/iptables/nft-ipv4.c
3a00e5
@@ -383,6 +383,32 @@ static void nft_ipv4_post_parse(int command,
3a00e5
 			      " source or destination IP addresses");
3a00e5
 }
3a00e5
 
3a00e5
+static void xlate_ipv4_addr(const char *selector, const struct in_addr *addr,
3a00e5
+			    const struct in_addr *mask,
3a00e5
+			    bool inv, struct xt_xlate *xl)
3a00e5
+{
3a00e5
+	const char *op = inv ? "!= " : "";
3a00e5
+	int cidr;
3a00e5
+
3a00e5
+	if (!inv && !addr->s_addr && !mask->s_addr)
3a00e5
+		return;
3a00e5
+
3a00e5
+	cidr = xtables_ipmask_to_cidr(mask);
3a00e5
+	switch (cidr) {
3a00e5
+	case -1:
3a00e5
+		/* inet_ntoa() is not reentrant */
3a00e5
+		xt_xlate_add(xl, "%s & %s ", selector, inet_ntoa(*mask));
3a00e5
+		xt_xlate_add(xl, "%s %s ", inv ? "!=" : "==", inet_ntoa(*addr));
3a00e5
+		break;
3a00e5
+	case 32:
3a00e5
+		xt_xlate_add(xl, "%s %s%s ", selector, op, inet_ntoa(*addr));
3a00e5
+		break;
3a00e5
+	default:
3a00e5
+		xt_xlate_add(xl, "%s %s%s/%d ", selector, op, inet_ntoa(*addr),
3a00e5
+			     cidr);
3a00e5
+	}
3a00e5
+}
3a00e5
+
3a00e5
 static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
3a00e5
 {
3a00e5
 	const struct iptables_command_state *cs = data;
3a00e5
@@ -417,18 +443,10 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl)
3a00e5
 		}
3a00e5
 	}
3a00e5
 
3a00e5
-	if (cs->fw.ip.src.s_addr != 0) {
3a00e5
-		xt_xlate_add(xl, "ip saddr %s%s%s ",
3a00e5
-			   cs->fw.ip.invflags & IPT_INV_SRCIP ? "!= " : "",
3a00e5
-			   inet_ntoa(cs->fw.ip.src),
3a00e5
-			   xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
3a00e5
-	}
3a00e5
-	if (cs->fw.ip.dst.s_addr != 0) {
3a00e5
-		xt_xlate_add(xl, "ip daddr %s%s%s ",
3a00e5
-			   cs->fw.ip.invflags & IPT_INV_DSTIP ? "!= " : "",
3a00e5
-			   inet_ntoa(cs->fw.ip.dst),
3a00e5
-			   xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
3a00e5
-	}
3a00e5
+	xlate_ipv4_addr("ip saddr", &cs->fw.ip.src, &cs->fw.ip.smsk,
3a00e5
+			cs->fw.ip.invflags & IPT_INV_SRCIP, xl);
3a00e5
+	xlate_ipv4_addr("ip daddr", &cs->fw.ip.dst, &cs->fw.ip.dmsk,
3a00e5
+			cs->fw.ip.invflags & IPT_INV_DSTIP, xl);
3a00e5
 
3a00e5
 	ret = xlate_matches(cs, xl);
3a00e5
 	if (!ret)
3a00e5
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
3a00e5
index 130ad3e6e7c44..46008fc5e762a 100644
3a00e5
--- a/iptables/nft-ipv6.c
3a00e5
+++ b/iptables/nft-ipv6.c
3a00e5
@@ -337,14 +337,27 @@ static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr,
3a00e5
 			    const struct in6_addr *mask,
3a00e5
 			    int invert, struct xt_xlate *xl)
3a00e5
 {
3a00e5
+	const char *op = invert ? "!= " : "";
3a00e5
 	char addr_str[INET6_ADDRSTRLEN];
3a00e5
+	int cidr;
3a00e5
 
3a00e5
-	if (!invert && IN6_IS_ADDR_UNSPECIFIED(addr))
3a00e5
+	if (!invert && IN6_IS_ADDR_UNSPECIFIED(addr) && IN6_IS_ADDR_UNSPECIFIED(mask))
3a00e5
 		return;
3a00e5
 
3a00e5
 	inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
3a00e5
-	xt_xlate_add(xl, "%s %s%s%s ", selector, invert ? "!= " : "", addr_str,
3a00e5
-			xtables_ip6mask_to_numeric(mask));
3a00e5
+	cidr = xtables_ip6mask_to_cidr(mask);
3a00e5
+	switch (cidr) {
3a00e5
+	case -1:
3a00e5
+		xt_xlate_add(xl, "%s & %s %s %s ", selector,
3a00e5
+			     xtables_ip6addr_to_numeric(mask),
3a00e5
+			     invert ? "!=" : "==", addr_str);
3a00e5
+		break;
3a00e5
+	case 128:
3a00e5
+		xt_xlate_add(xl, "%s %s%s ", selector, op, addr_str);
3a00e5
+		break;
3a00e5
+	default:
3a00e5
+		xt_xlate_add(xl, "%s %s%s/%d ", selector, op, addr_str, cidr);
3a00e5
+	}
3a00e5
 }
3a00e5
 
3a00e5
 static int nft_ipv6_xlate(const void *data, struct xt_xlate *xl)
3a00e5
-- 
3a00e5
2.31.1
3a00e5