All of lore.kernel.org
 help / color / mirror / Atom feed
* [iptables PATCH 0/6] Merge NAT extensions
@ 2022-11-03  1:41 Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 1/6] extensions: DNAT: Fix bad IP address error reporting Phil Sutter
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

Besides the three different data structures in use to store different
revisions' extensions data, the actual code is pretty similar in all the
different NAT "flavors".

Patch 1 fixes a minor bug introduced by a previous commit. Patch 2
eliminates some needless checks and some that seem not necessary.
Patches 3 to 5 prepare DNAT extension code for the actual merge
happening in patch 6.

Phil Sutter (6):
  extensions: DNAT: Fix bad IP address error reporting
  extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks
  extensions: DNAT: Use __DNAT_xlate for REDIRECT, too
  extensions: DNAT: Generate print, save and xlate callbacks
  extensions: DNAT: Rename some symbols
  extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE

 extensions/GNUmakefile.in                |  10 +-
 extensions/libip6t_MASQUERADE.c          | 188 ----------
 extensions/libip6t_MASQUERADE.txlate     |   9 +
 extensions/libip6t_SNAT.c                | 308 ----------------
 extensions/libip6t_SNAT.t                |   6 +
 extensions/libipt_MASQUERADE.c           | 190 ----------
 extensions/libipt_MASQUERADE.txlate      |   9 +
 extensions/libipt_SNAT.c                 | 280 ---------------
 extensions/libipt_SNAT.t                 |   6 +
 extensions/{libxt_DNAT.c => libxt_NAT.c} | 440 +++++++++++------------
 extensions/libxt_REDIRECT.t              |   1 +
 extensions/libxt_REDIRECT.txlate         |   3 +
 12 files changed, 262 insertions(+), 1188 deletions(-)
 delete mode 100644 extensions/libip6t_MASQUERADE.c
 delete mode 100644 extensions/libip6t_SNAT.c
 delete mode 100644 extensions/libipt_MASQUERADE.c
 delete mode 100644 extensions/libipt_SNAT.c
 rename extensions/{libxt_DNAT.c => libxt_NAT.c} (59%)

-- 
2.38.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [iptables PATCH 1/6] extensions: DNAT: Fix bad IP address error reporting
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 2/6] extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks Phil Sutter
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

When introducing 'start' variable to cover for IPv6 addresses enclosed
in brackets, this single spot was missed.

Fixes: 14d77c8aa29a7 ("extensions: Merge IPv4 and IPv6 DNAT targets")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libxt_DNAT.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c
index 5696d31f2b0c5..7bfefc7961fac 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_DNAT.c
@@ -197,7 +197,7 @@ parse_to(const char *orig_arg, bool portok,
 
 	if (!inet_pton(family, start, &range->min_addr))
 		xtables_error(PARAMETER_PROBLEM,
-			      "Bad IP address \"%s\"", arg);
+			      "Bad IP address \"%s\"", start);
 	if (dash) {
 		if (!inet_pton(family, dash + 1, &range->max_addr))
 			xtables_error(PARAMETER_PROBLEM,
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [iptables PATCH 2/6] extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 1/6] extensions: DNAT: Fix bad IP address error reporting Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 3/6] extensions: DNAT: Use __DNAT_xlate for REDIRECT, too Phil Sutter
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

SNAT, DNAT and REDIRECT extensions tried to prevent
NF_NAT_RANGE_PROTO_RANDOM flag from being set if no port or address was
also given.

With SNAT and DNAT, this is not possible as the respective
--to-destination or --to-source parameters are mandatory anyway.

Looking at the kernel code, doing so with REDIRECT seems harmless.
Moreover, nftables supports 'redirect random' without specifying a
port-range.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libip6t_SNAT.c        | 20 +++++---------------
 extensions/libipt_SNAT.c         | 16 ++++++----------
 extensions/libxt_DNAT.c          | 28 ++++------------------------
 extensions/libxt_REDIRECT.t      |  1 +
 extensions/libxt_REDIRECT.txlate |  3 +++
 5 files changed, 19 insertions(+), 49 deletions(-)

diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
index 4fe272b262a3d..8bf7b035f84b6 100644
--- a/extensions/libip6t_SNAT.c
+++ b/extensions/libip6t_SNAT.c
@@ -20,9 +20,6 @@ enum {
 	O_RANDOM,
 	O_RANDOM_FULLY,
 	O_PERSISTENT,
-	F_TO_SRC       = 1 << O_TO_SRC,
-	F_RANDOM       = 1 << O_RANDOM,
-	F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
 };
 
 static void SNAT_help(void)
@@ -166,19 +163,13 @@ static void SNAT_parse(struct xt_option_call *cb)
 	case O_PERSISTENT:
 		range->flags |= NF_NAT_RANGE_PERSISTENT;
 		break;
-	}
-}
-
-static void SNAT_fcheck(struct xt_fcheck_call *cb)
-{
-	static const unsigned int f = F_TO_SRC | F_RANDOM;
-	static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
-	struct nf_nat_range *range = cb->data;
-
-	if ((cb->xflags & f) == f)
+	case O_RANDOM:
 		range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
-	if ((cb->xflags & r) == r)
+		break;
+	case O_RANDOM_FULLY:
 		range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+		break;
+	}
 }
 
 static void print_range(const struct nf_nat_range *range)
@@ -295,7 +286,6 @@ static struct xtables_target snat_tg_reg = {
 	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
 	.help		= SNAT_help,
 	.x6_parse	= SNAT_parse,
-	.x6_fcheck	= SNAT_fcheck,
 	.print		= SNAT_print,
 	.save		= SNAT_save,
 	.x6_options	= SNAT_opts,
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index 211a20bc45bfe..9c8cdb46a1585 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -13,9 +13,6 @@ enum {
 	O_RANDOM,
 	O_RANDOM_FULLY,
 	O_PERSISTENT,
-	F_TO_SRC       = 1 << O_TO_SRC,
-	F_RANDOM       = 1 << O_RANDOM,
-	F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
 };
 
 static void SNAT_help(void)
@@ -141,20 +138,19 @@ static void SNAT_parse(struct xt_option_call *cb)
 	case O_PERSISTENT:
 		mr->range->flags |= NF_NAT_RANGE_PERSISTENT;
 		break;
+	case O_RANDOM:
+		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+		break;
+	case O_RANDOM_FULLY:
+		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+		break;
 	}
 }
 
 static void SNAT_fcheck(struct xt_fcheck_call *cb)
 {
-	static const unsigned int f = F_TO_SRC | F_RANDOM;
-	static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
 	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
 
-	if ((cb->xflags & f) == f)
-		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
-	if ((cb->xflags & r) == r)
-		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-
 	mr->rangesize = 1;
 }
 
diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c
index 7bfefc7961fac..af44518798aef 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_DNAT.c
@@ -31,9 +31,6 @@ enum {
 	O_TO_PORTS,
 	O_RANDOM,
 	O_PERSISTENT,
-	F_TO_DEST  = 1 << O_TO_DEST,
-	F_TO_PORTS = 1 << O_TO_PORTS,
-	F_RANDOM   = 1 << O_RANDOM,
 };
 
 static void DNAT_help(void)
@@ -229,6 +226,9 @@ static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
 	case O_PERSISTENT:
 		range->flags |= NF_NAT_RANGE_PERSISTENT;
 		break;
+	case O_RANDOM:
+		range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+		break;
 	}
 }
 
@@ -250,21 +250,12 @@ static void DNAT_parse(struct xt_option_call *cb)
 		mr->range->max = range.max_proto;
 		/* fall through */
 	case O_PERSISTENT:
+	case O_RANDOM:
 		mr->range->flags |= range.flags;
 		break;
 	}
 }
 
-static void __DNAT_fcheck(struct xt_fcheck_call *cb, unsigned int *flags)
-{
-	static const unsigned int redir_f = F_TO_PORTS | F_RANDOM;
-	static const unsigned int dnat_f = F_TO_DEST | F_RANDOM;
-
-	if ((cb->xflags & redir_f) == redir_f ||
-	    (cb->xflags & dnat_f) == dnat_f)
-		*flags |= NF_NAT_RANGE_PROTO_RANDOM;
-}
-
 static void DNAT_fcheck(struct xt_fcheck_call *cb)
 {
 	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
@@ -274,8 +265,6 @@ static void DNAT_fcheck(struct xt_fcheck_call *cb)
 	if (mr->range[0].flags & NF_NAT_RANGE_PROTO_OFFSET)
 		xtables_error(PARAMETER_PROBLEM,
 			      "Shifted portmap ranges not supported with this kernel");
-
-	__DNAT_fcheck(cb, &mr->range[0].flags);
 }
 
 static char *sprint_range(const struct nf_nat_range2 *r, int family)
@@ -388,11 +377,6 @@ static void DNAT_parse_v2(struct xt_option_call *cb)
 	__DNAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
 }
 
-static void DNAT_fcheck_v2(struct xt_fcheck_call *cb)
-{
-	__DNAT_fcheck(cb, &((struct nf_nat_range2 *)cb->data)->flags);
-}
-
 static void DNAT_print_v2(const void *ip, const struct xt_entry_target *target,
                        int numeric)
 {
@@ -428,8 +412,6 @@ static void DNAT_fcheck6(struct xt_fcheck_call *cb)
 	if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
 		xtables_error(PARAMETER_PROBLEM,
 			      "Shifted portmap ranges not supported with this kernel");
-
-	__DNAT_fcheck(cb, &range->flags);
 }
 
 static void DNAT_print6(const void *ip, const struct xt_entry_target *target,
@@ -619,7 +601,6 @@ static struct xtables_target dnat_tg_reg[] = {
 		.print		= DNAT_print_v2,
 		.save		= DNAT_save_v2,
 		.x6_parse	= DNAT_parse_v2,
-		.x6_fcheck	= DNAT_fcheck_v2,
 		.x6_options	= DNAT_opts,
 		.xlate		= DNAT_xlate_v2,
 	},
@@ -634,7 +615,6 @@ static struct xtables_target dnat_tg_reg[] = {
 		.print		= DNAT_print6_v2,
 		.save		= DNAT_save6_v2,
 		.x6_parse	= DNAT_parse6_v2,
-		.x6_fcheck	= DNAT_fcheck_v2,
 		.x6_options	= DNAT_opts,
 		.xlate		= DNAT_xlate6_v2,
 	},
diff --git a/extensions/libxt_REDIRECT.t b/extensions/libxt_REDIRECT.t
index f607dd0a12c51..362efa8428ed4 100644
--- a/extensions/libxt_REDIRECT.t
+++ b/extensions/libxt_REDIRECT.t
@@ -14,3 +14,4 @@
 -p tcp -j REDIRECT --to-ports ftp-ssh;;FAIL
 -p tcp -j REDIRECT --to-ports 10-ssh;;FAIL
 -j REDIRECT --to-ports 42;;FAIL
+-j REDIRECT --random;=;OK
diff --git a/extensions/libxt_REDIRECT.txlate b/extensions/libxt_REDIRECT.txlate
index 2c536495b35a2..36419a46bb366 100644
--- a/extensions/libxt_REDIRECT.txlate
+++ b/extensions/libxt_REDIRECT.txlate
@@ -16,6 +16,9 @@ nft add rule ip nat prerouting tcp dport 80 counter redirect to :10-22
 iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
 nft add rule ip nat prerouting tcp dport 80 counter redirect to :8080 random
 
+iptables-translate -t nat -A prerouting -j REDIRECT --random
+nft add rule ip nat prerouting counter redirect random
+
 ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT
 nft add rule ip6 nat prerouting tcp dport 80 counter redirect
 
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [iptables PATCH 3/6] extensions: DNAT: Use __DNAT_xlate for REDIRECT, too
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 1/6] extensions: DNAT: Fix bad IP address error reporting Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 2/6] extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 4/6] extensions: DNAT: Generate print, save and xlate callbacks Phil Sutter
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

Make the common function a bit more versatile and give it a more
generic name, then use it for REDIRECT target, too.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libxt_DNAT.c | 33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c
index af44518798aef..9b94062512c09 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_DNAT.c
@@ -338,7 +338,8 @@ static void DNAT_save(const void *ip, const struct xt_entry_target *target)
 }
 
 static int
-__DNAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r, int family)
+__NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
+	     int family, const char *tgt)
 {
 	char *range_str = sprint_range(r, family);
 	const char *sep = " ";
@@ -347,7 +348,7 @@ __DNAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r, int family)
 	if (r->flags & NF_NAT_RANGE_PROTO_OFFSET)
 		return 0;
 
-	xt_xlate_add(xl, "dnat");
+	xt_xlate_add(xl, tgt);
 	if (strlen(range_str))
 		xt_xlate_add(xl, " to %s", range_str);
 	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) {
@@ -367,7 +368,7 @@ static int DNAT_xlate(struct xt_xlate *xl,
 	struct nf_nat_range2 range =
 		RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
 
-	return __DNAT_xlate(xl, &range, AF_INET);
+	return __NAT_xlate(xl, &range, AF_INET, "dnat");
 }
 
 static void DNAT_parse_v2(struct xt_option_call *cb)
@@ -391,7 +392,8 @@ static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target)
 static int DNAT_xlate_v2(struct xt_xlate *xl,
 			  const struct xt_xlate_tg_params *params)
 {
-	return __DNAT_xlate(xl, (const void *)params->target->data, AF_INET);
+	return __NAT_xlate(xl, (const void *)params->target->data,
+			   AF_INET, "dnat");
 }
 
 static void DNAT_parse6(struct xt_option_call *cb)
@@ -438,7 +440,7 @@ static int DNAT_xlate6(struct xt_xlate *xl,
 
 	memcpy(&range, (const void *)params->target->data,
 	       sizeof(struct nf_nat_range));
-	return __DNAT_xlate(xl, &range, AF_INET6);
+	return __NAT_xlate(xl, &range, AF_INET6, "dnat");
 }
 
 static void DNAT_parse6_v2(struct xt_option_call *cb)
@@ -462,21 +464,8 @@ static void DNAT_save6_v2(const void *ip, const struct xt_entry_target *target)
 static int DNAT_xlate6_v2(struct xt_xlate *xl,
 			  const struct xt_xlate_tg_params *params)
 {
-	return __DNAT_xlate(xl, (const void *)params->target->data, AF_INET6);
-}
-
-static int __REDIRECT_xlate(struct xt_xlate *xl,
-			    const struct nf_nat_range2 *range)
-{
-	char *range_str = sprint_range(range, AF_INET);
-
-	xt_xlate_add(xl, "redirect");
-	if (strlen(range_str))
-		xt_xlate_add(xl, " to %s", range_str);
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		xt_xlate_add(xl, " random");
-
-	return 1;
+	return __NAT_xlate(xl, (const void *)params->target->data,
+			   AF_INET6, "dnat");
 }
 
 static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
@@ -500,7 +489,7 @@ static int REDIRECT_xlate(struct xt_xlate *xl,
 	struct nf_nat_range2 range =
 		RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
 
-	return __REDIRECT_xlate(xl, &range);
+	return __NAT_xlate(xl, &range, AF_INET, "redirect");
 }
 
 static void REDIRECT_print6(const void *ip, const struct xt_entry_target *target,
@@ -527,7 +516,7 @@ static int REDIRECT_xlate6(struct xt_xlate *xl,
 
 	memcpy(&range, (const void *)params->target->data,
 	       sizeof(struct nf_nat_range));
-	return __REDIRECT_xlate(xl, &range);
+	return __NAT_xlate(xl, &range, AF_INET6, "redirect");
 }
 
 static struct xtables_target dnat_tg_reg[] = {
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [iptables PATCH 4/6] extensions: DNAT: Generate print, save and xlate callbacks
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
                   ` (2 preceding siblings ...)
  2022-11-03  1:41 ` [iptables PATCH 3/6] extensions: DNAT: Use __DNAT_xlate for REDIRECT, too Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 5/6] extensions: DNAT: Rename some symbols Phil Sutter
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

Each extension's callbacks follow the same scheme so introduce a
generator which accepts the specifics as parameter - including the
method to transform from per-extension data into struct nf_nat_range2.

Also move the different parser frontends and fcheck callbacks in one
spot for clarity.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libxt_DNAT.c | 266 +++++++++++++---------------------------
 1 file changed, 86 insertions(+), 180 deletions(-)

diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c
index 9b94062512c09..e53002541ee03 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_DNAT.c
@@ -25,6 +25,14 @@
 	.min_proto	= TO_IPV4_MRC(ptr)->range[0].min,	\
 	.max_proto	= TO_IPV4_MRC(ptr)->range[0].max,	\
 };
+#define TO_NF_NAT_RANGE(ptr) ((const struct nf_nat_range *)(ptr))
+#define RANGE2_INIT_FROM_RANGE(ptr) {				\
+	.flags		= TO_NF_NAT_RANGE(ptr)->flags,		\
+	.min_addr	= TO_NF_NAT_RANGE(ptr)->min_addr,	\
+	.max_addr	= TO_NF_NAT_RANGE(ptr)->max_addr,	\
+	.min_proto	= TO_NF_NAT_RANGE(ptr)->min_proto,	\
+	.max_proto	= TO_NF_NAT_RANGE(ptr)->max_proto,	\
+};
 
 enum {
 	O_TO_DEST = 0,
@@ -256,6 +264,30 @@ static void DNAT_parse(struct xt_option_call *cb)
 	}
 }
 
+static void DNAT_parse6(struct xt_option_call *cb)
+{
+	struct nf_nat_range2 range = RANGE2_INIT_FROM_RANGE(cb->data);
+	struct nf_nat_range *range_v1 = (void *)cb->data;
+	const struct ip6t_entry *entry = cb->xt_entry;
+
+	__DNAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
+	memcpy(range_v1, &range, sizeof(*range_v1));
+}
+
+static void DNAT_parse_v2(struct xt_option_call *cb)
+{
+	const struct ipt_entry *entry = cb->xt_entry;
+
+	__DNAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
+}
+
+static void DNAT_parse6_v2(struct xt_option_call *cb)
+{
+	const struct ip6t_entry *entry = cb->xt_entry;
+
+	__DNAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
+}
+
 static void DNAT_fcheck(struct xt_fcheck_call *cb)
 {
 	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
@@ -267,6 +299,15 @@ static void DNAT_fcheck(struct xt_fcheck_call *cb)
 			      "Shifted portmap ranges not supported with this kernel");
 }
 
+static void DNAT_fcheck6(struct xt_fcheck_call *cb)
+{
+	struct nf_nat_range *range = (void *)cb->data;
+
+	if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
+		xtables_error(PARAMETER_PROBLEM,
+			      "Shifted portmap ranges not supported with this kernel");
+}
+
 static char *sprint_range(const struct nf_nat_range2 *r, int family)
 {
 	bool brackets = family == AF_INET6 &&
@@ -317,25 +358,6 @@ static void __NAT_print(const struct nf_nat_range2 *r, int family,
 	if (r->flags & NF_NAT_RANGE_PERSISTENT)
 		printf(" %spersistent", flag_pfx);
 }
-#define __DNAT_print(r, family) __NAT_print(r, family, "to:", "", false)
-#define __DNAT_save(r, family) __NAT_print(r, family, "--to-destination ", "--", false)
-#define __REDIRECT_print(r) __NAT_print(r, AF_INET, "redir ports ", "", true)
-#define __REDIRECT_save(r) __NAT_print(r, AF_INET, "--to-ports ", "--", true)
-
-static void DNAT_print(const void *ip, const struct xt_entry_target *target,
-                       int numeric)
-{
-	struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
-	__DNAT_print(&range, AF_INET);
-}
-
-static void DNAT_save(const void *ip, const struct xt_entry_target *target)
-{
-	struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
-	__DNAT_save(&range, AF_INET);
-}
 
 static int
 __NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
@@ -362,162 +384,46 @@ __NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
 	return 1;
 }
 
-static int DNAT_xlate(struct xt_xlate *xl,
-		      const struct xt_xlate_tg_params *params)
-{
-	struct nf_nat_range2 range =
-		RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
-
-	return __NAT_xlate(xl, &range, AF_INET, "dnat");
-}
-
-static void DNAT_parse_v2(struct xt_option_call *cb)
-{
-	const struct ipt_entry *entry = cb->xt_entry;
-
-	__DNAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
-}
-
-static void DNAT_print_v2(const void *ip, const struct xt_entry_target *target,
-                       int numeric)
-{
-	__DNAT_print((const void *)target->data, AF_INET);
-}
-
-static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target)
-{
-	__DNAT_save((const void *)target->data, AF_INET);
-}
-
-static int DNAT_xlate_v2(struct xt_xlate *xl,
-			  const struct xt_xlate_tg_params *params)
-{
-	return __NAT_xlate(xl, (const void *)params->target->data,
-			   AF_INET, "dnat");
-}
-
-static void DNAT_parse6(struct xt_option_call *cb)
-{
-	const struct ip6t_entry *entry = cb->xt_entry;
-	struct nf_nat_range *range_v1 = (void *)cb->data;
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, range_v1, sizeof(*range_v1));
-	__DNAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
-	memcpy(range_v1, &range, sizeof(*range_v1));
-}
-
-static void DNAT_fcheck6(struct xt_fcheck_call *cb)
-{
-	struct nf_nat_range *range = (void *)cb->data;
-
-	if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
-		xtables_error(PARAMETER_PROBLEM,
-			      "Shifted portmap ranges not supported with this kernel");
+#define PSX_GEN(name, converter, family,                                       \
+		print_rangeopt, save_rangeopt, skip_colon, xlate)              \
+static void name##_print(const void *ip, const struct xt_entry_target *target, \
+			 int numeric)                                          \
+{                                                                              \
+	struct nf_nat_range2 range = converter(target->data);                  \
+	                                                                       \
+	__NAT_print(&range, family, print_rangeopt, "", skip_colon);           \
+}                                                                              \
+static void name##_save(const void *ip, const struct xt_entry_target *target)  \
+{                                                                              \
+	struct nf_nat_range2 range = converter(target->data);                  \
+	                                                                       \
+	__NAT_print(&range, family, save_rangeopt, "--", skip_colon);          \
+}                                                                              \
+static int name##_xlate(struct xt_xlate *xl,                                   \
+			const struct xt_xlate_tg_params *params)               \
+{                                                                              \
+	struct nf_nat_range2 range = converter(params->target->data);          \
+	                                                                       \
+	return __NAT_xlate(xl, &range, family, xlate);                         \
 }
 
-static void DNAT_print6(const void *ip, const struct xt_entry_target *target,
-			int numeric)
-{
-	struct nf_nat_range2 range = {};
+PSX_GEN(DNAT, RANGE2_INIT_FROM_IPV4_MRC, \
+	AF_INET, "to:", "--to-destination ", false, "dnat")
 
-	memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
-	__DNAT_print(&range, AF_INET6);
-}
+PSX_GEN(DNATv2, *(struct nf_nat_range2 *), \
+	AF_INET, "to:", "--to-destination ", false, "dnat")
 
-static void DNAT_save6(const void *ip, const struct xt_entry_target *target)
-{
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
-	__DNAT_save(&range, AF_INET6);
-}
-
-static int DNAT_xlate6(struct xt_xlate *xl,
-		       const struct xt_xlate_tg_params *params)
-{
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, (const void *)params->target->data,
-	       sizeof(struct nf_nat_range));
-	return __NAT_xlate(xl, &range, AF_INET6, "dnat");
-}
+PSX_GEN(DNAT6, RANGE2_INIT_FROM_RANGE, \
+	AF_INET6, "to:", "--to-destination ", false, "dnat")
 
-static void DNAT_parse6_v2(struct xt_option_call *cb)
-{
-	const struct ip6t_entry *entry = cb->xt_entry;
-
-	__DNAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
-}
+PSX_GEN(DNAT6v2, *(struct nf_nat_range2 *), \
+	AF_INET6, "to:", "--to-destination ", false, "dnat")
 
-static void DNAT_print6_v2(const void *ip, const struct xt_entry_target *target,
-			   int numeric)
-{
-	__DNAT_print((const void *)target->data, AF_INET6);
-}
+PSX_GEN(REDIRECT, RANGE2_INIT_FROM_IPV4_MRC, \
+	AF_INET, "redir ports ", "--to-ports ", true, "redirect")
 
-static void DNAT_save6_v2(const void *ip, const struct xt_entry_target *target)
-{
-	__DNAT_save((const void *)target->data, AF_INET6);
-}
-
-static int DNAT_xlate6_v2(struct xt_xlate *xl,
-			  const struct xt_xlate_tg_params *params)
-{
-	return __NAT_xlate(xl, (const void *)params->target->data,
-			   AF_INET6, "dnat");
-}
-
-static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
-                           int numeric)
-{
-	struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
-	__REDIRECT_print(&range);
-}
-
-static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
-{
-	struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
-	__REDIRECT_save(&range);
-}
-
-static int REDIRECT_xlate(struct xt_xlate *xl,
-			   const struct xt_xlate_tg_params *params)
-{
-	struct nf_nat_range2 range =
-		RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
-
-	return __NAT_xlate(xl, &range, AF_INET, "redirect");
-}
-
-static void REDIRECT_print6(const void *ip, const struct xt_entry_target *target,
-                            int numeric)
-{
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
-	__REDIRECT_print(&range);
-}
-
-static void REDIRECT_save6(const void *ip, const struct xt_entry_target *target)
-{
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
-	__REDIRECT_save(&range);
-}
-
-static int REDIRECT_xlate6(struct xt_xlate *xl,
-			   const struct xt_xlate_tg_params *params)
-{
-	struct nf_nat_range2 range = {};
-
-	memcpy(&range, (const void *)params->target->data,
-	       sizeof(struct nf_nat_range));
-	return __NAT_xlate(xl, &range, AF_INET6, "redirect");
-}
+PSX_GEN(REDIRECT6, RANGE2_INIT_FROM_RANGE, \
+	AF_INET6, "redir ports ", "--to-ports ", true, "redirect")
 
 static struct xtables_target dnat_tg_reg[] = {
 	{
@@ -558,12 +464,12 @@ static struct xtables_target dnat_tg_reg[] = {
 		.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
 		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
 		.help		= DNAT_help,
-		.print		= DNAT_print6,
-		.save		= DNAT_save6,
+		.print		= DNAT6_print,
+		.save		= DNAT6_save,
 		.x6_parse	= DNAT_parse6,
 		.x6_fcheck	= DNAT_fcheck6,
 		.x6_options	= DNAT_opts,
-		.xlate		= DNAT_xlate6,
+		.xlate		= DNAT6_xlate,
 	},
 	{
 		.name		= "REDIRECT",
@@ -572,12 +478,12 @@ static struct xtables_target dnat_tg_reg[] = {
 		.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
 		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
 		.help		= REDIRECT_help,
-		.print		= REDIRECT_print6,
-		.save		= REDIRECT_save6,
+		.print		= REDIRECT6_print,
+		.save		= REDIRECT6_save,
 		.x6_parse	= DNAT_parse6,
 		.x6_fcheck	= DNAT_fcheck6,
 		.x6_options	= REDIRECT_opts,
-		.xlate		= REDIRECT_xlate6,
+		.xlate		= REDIRECT6_xlate,
 	},
 	{
 		.name		= "DNAT",
@@ -587,11 +493,11 @@ static struct xtables_target dnat_tg_reg[] = {
 		.size		= XT_ALIGN(sizeof(struct nf_nat_range2)),
 		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range2)),
 		.help		= DNAT_help_v2,
-		.print		= DNAT_print_v2,
-		.save		= DNAT_save_v2,
+		.print		= DNATv2_print,
+		.save		= DNATv2_save,
 		.x6_parse	= DNAT_parse_v2,
 		.x6_options	= DNAT_opts,
-		.xlate		= DNAT_xlate_v2,
+		.xlate		= DNATv2_xlate,
 	},
 	{
 		.name		= "DNAT",
@@ -601,11 +507,11 @@ static struct xtables_target dnat_tg_reg[] = {
 		.size		= XT_ALIGN(sizeof(struct nf_nat_range2)),
 		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range2)),
 		.help		= DNAT_help_v2,
-		.print		= DNAT_print6_v2,
-		.save		= DNAT_save6_v2,
+		.print		= DNAT6v2_print,
+		.save		= DNAT6v2_save,
 		.x6_parse	= DNAT_parse6_v2,
 		.x6_options	= DNAT_opts,
-		.xlate		= DNAT_xlate6_v2,
+		.xlate		= DNAT6v2_xlate,
 	},
 };
 
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [iptables PATCH 5/6] extensions: DNAT: Rename some symbols
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
                   ` (3 preceding siblings ...)
  2022-11-03  1:41 ` [iptables PATCH 4/6] extensions: DNAT: Generate print, save and xlate callbacks Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-03  1:41 ` [iptables PATCH 6/6] extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE Phil Sutter
  2022-11-11 18:16 ` [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

No functional change intended, just a more generic name for some symbols
which won't be DNAT-specific soon.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libxt_DNAT.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_DNAT.c
index e53002541ee03..fbb10e410a221 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_DNAT.c
@@ -214,8 +214,8 @@ parse_to(const char *orig_arg, bool portok,
 	return;
 }
 
-static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
-			 struct nf_nat_range2 *range, int family)
+static void __NAT_parse(struct xt_option_call *cb, __u16 proto,
+			struct nf_nat_range2 *range, int family)
 {
 	bool portok = proto == IPPROTO_TCP ||
 		      proto == IPPROTO_UDP ||
@@ -240,13 +240,13 @@ static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
 	}
 }
 
-static void DNAT_parse(struct xt_option_call *cb)
+static void NAT_parse(struct xt_option_call *cb)
 {
 	struct nf_nat_ipv4_multi_range_compat *mr = (void *)cb->data;
 	const struct ipt_entry *entry = cb->xt_entry;
 	struct nf_nat_range2 range = {};
 
-	__DNAT_parse(cb, entry->ip.proto, &range, AF_INET);
+	__NAT_parse(cb, entry->ip.proto, &range, AF_INET);
 
 	switch (cb->entry->id) {
 	case O_TO_DEST:
@@ -264,13 +264,13 @@ static void DNAT_parse(struct xt_option_call *cb)
 	}
 }
 
-static void DNAT_parse6(struct xt_option_call *cb)
+static void NAT_parse6(struct xt_option_call *cb)
 {
 	struct nf_nat_range2 range = RANGE2_INIT_FROM_RANGE(cb->data);
 	struct nf_nat_range *range_v1 = (void *)cb->data;
 	const struct ip6t_entry *entry = cb->xt_entry;
 
-	__DNAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
+	__NAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
 	memcpy(range_v1, &range, sizeof(*range_v1));
 }
 
@@ -278,14 +278,14 @@ static void DNAT_parse_v2(struct xt_option_call *cb)
 {
 	const struct ipt_entry *entry = cb->xt_entry;
 
-	__DNAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
+	__NAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
 }
 
 static void DNAT_parse6_v2(struct xt_option_call *cb)
 {
 	const struct ip6t_entry *entry = cb->xt_entry;
 
-	__DNAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
+	__NAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
 }
 
 static void DNAT_fcheck(struct xt_fcheck_call *cb)
@@ -425,7 +425,7 @@ PSX_GEN(REDIRECT, RANGE2_INIT_FROM_IPV4_MRC, \
 PSX_GEN(REDIRECT6, RANGE2_INIT_FROM_RANGE, \
 	AF_INET6, "redir ports ", "--to-ports ", true, "redirect")
 
-static struct xtables_target dnat_tg_reg[] = {
+static struct xtables_target nat_tg_reg[] = {
 	{
 		.name		= "DNAT",
 		.version	= XTABLES_VERSION,
@@ -436,7 +436,7 @@ static struct xtables_target dnat_tg_reg[] = {
 		.help		= DNAT_help,
 		.print		= DNAT_print,
 		.save		= DNAT_save,
-		.x6_parse	= DNAT_parse,
+		.x6_parse	= NAT_parse,
 		.x6_fcheck	= DNAT_fcheck,
 		.x6_options	= DNAT_opts,
 		.xlate		= DNAT_xlate,
@@ -451,7 +451,7 @@ static struct xtables_target dnat_tg_reg[] = {
 		.help		= REDIRECT_help,
 		.print		= REDIRECT_print,
 		.save		= REDIRECT_save,
-		.x6_parse	= DNAT_parse,
+		.x6_parse	= NAT_parse,
 		.x6_fcheck	= DNAT_fcheck,
 		.x6_options	= REDIRECT_opts,
 		.xlate		= REDIRECT_xlate,
@@ -466,7 +466,7 @@ static struct xtables_target dnat_tg_reg[] = {
 		.help		= DNAT_help,
 		.print		= DNAT6_print,
 		.save		= DNAT6_save,
-		.x6_parse	= DNAT_parse6,
+		.x6_parse	= NAT_parse6,
 		.x6_fcheck	= DNAT_fcheck6,
 		.x6_options	= DNAT_opts,
 		.xlate		= DNAT6_xlate,
@@ -480,7 +480,7 @@ static struct xtables_target dnat_tg_reg[] = {
 		.help		= REDIRECT_help,
 		.print		= REDIRECT6_print,
 		.save		= REDIRECT6_save,
-		.x6_parse	= DNAT_parse6,
+		.x6_parse	= NAT_parse6,
 		.x6_fcheck	= DNAT_fcheck6,
 		.x6_options	= REDIRECT_opts,
 		.xlate		= REDIRECT6_xlate,
@@ -517,5 +517,5 @@ static struct xtables_target dnat_tg_reg[] = {
 
 void _init(void)
 {
-	xtables_register_targets(dnat_tg_reg, ARRAY_SIZE(dnat_tg_reg));
+	xtables_register_targets(nat_tg_reg, ARRAY_SIZE(nat_tg_reg));
 }
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [iptables PATCH 6/6] extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
                   ` (4 preceding siblings ...)
  2022-11-03  1:41 ` [iptables PATCH 5/6] extensions: DNAT: Rename some symbols Phil Sutter
@ 2022-11-03  1:41 ` Phil Sutter
  2022-11-11 18:16 ` [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-03  1:41 UTC (permalink / raw)
  To: netfilter-devel

REDIRECT was already merged into DNAT. Given the callback generator and
generalized inner parsing routines, merging the other "flavors" is
relatively simple. Rename the extension into "libxt_NAT.so" while doing
so and turn the old DSOs into symlinks.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/GNUmakefile.in                |  10 +-
 extensions/libip6t_MASQUERADE.c          | 188 --------------
 extensions/libip6t_MASQUERADE.txlate     |   9 +
 extensions/libip6t_SNAT.c                | 298 -----------------------
 extensions/libip6t_SNAT.t                |   6 +
 extensions/libipt_MASQUERADE.c           | 190 ---------------
 extensions/libipt_MASQUERADE.txlate      |   9 +
 extensions/libipt_SNAT.c                 | 276 ---------------------
 extensions/libipt_SNAT.t                 |   6 +
 extensions/{libxt_DNAT.c => libxt_NAT.c} | 125 ++++++++++
 10 files changed, 163 insertions(+), 954 deletions(-)
 delete mode 100644 extensions/libip6t_MASQUERADE.c
 delete mode 100644 extensions/libip6t_SNAT.c
 delete mode 100644 extensions/libipt_MASQUERADE.c
 delete mode 100644 extensions/libipt_SNAT.c
 rename extensions/{libxt_DNAT.c => libxt_NAT.c} (80%)

diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 3c68f8decd13f..0239a06a90cd1 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -42,7 +42,7 @@ endif
 pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
 @ENABLE_NFTABLES_TRUE@ pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c)))
 @ENABLE_NFTABLES_TRUE@ pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c)))
-pfx_symlinks  := NOTRACK state REDIRECT
+pfx_symlinks  := NOTRACK state REDIRECT MASQUERADE SNAT DNAT
 @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
 @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
 pfx_build_mod := $(filter-out @blacklist_modules@ @blacklist_x_modules@,${pfx_build_mod})
@@ -130,7 +130,13 @@ libxt_NOTRACK.so: libxt_CT.so
 	ln -fs $< $@
 libxt_state.so: libxt_conntrack.so
 	ln -fs $< $@
-libxt_REDIRECT.so: libxt_DNAT.so
+libxt_REDIRECT.so: libxt_NAT.so
+	ln -fs $< $@
+libxt_MASQUERADE.so: libxt_NAT.so
+	ln -fs $< $@
+libxt_SNAT.so: libxt_NAT.so
+	ln -fs $< $@
+libxt_DNAT.so: libxt_NAT.so
 	ln -fs $< $@
 
 # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c
deleted file mode 100644
index f28f071b047e1..0000000000000
--- a/extensions/libip6t_MASQUERADE.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
- *
- * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT
- * funded by Astaro.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <xtables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
-	O_TO_PORTS = 0,
-	O_RANDOM,
-	O_RANDOM_FULLY,
-};
-
-static void MASQUERADE_help(void)
-{
-	printf(
-"MASQUERADE target options:\n"
-" --to-ports <port>[-<port>]\n"
-"				Port (range) to map to.\n"
-" --random\n"
-"				Randomize source port.\n"
-" --random-fully\n"
-"				Fully randomize source port.\n");
-}
-
-static const struct xt_option_entry MASQUERADE_opts[] = {
-	{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
-	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
-	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
-	XTOPT_TABLEEND,
-};
-
-/* Parses ports */
-static void
-parse_ports(const char *arg, struct nf_nat_range *r)
-{
-	char *end;
-	unsigned int port, maxport;
-
-	r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
-	if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
-		xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-
-	switch (*end) {
-	case '\0':
-		r->min_proto.tcp.port
-			= r->max_proto.tcp.port
-			= htons(port);
-		return;
-	case '-':
-		if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
-			break;
-
-		if (maxport < port)
-			break;
-
-		r->min_proto.tcp.port = htons(port);
-		r->max_proto.tcp.port = htons(maxport);
-		return;
-	default:
-		break;
-	}
-	xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-}
-
-static void MASQUERADE_parse(struct xt_option_call *cb)
-{
-	const struct ip6t_entry *entry = cb->xt_entry;
-	struct nf_nat_range *r = cb->data;
-	int portok;
-
-	if (entry->ipv6.proto == IPPROTO_TCP ||
-	    entry->ipv6.proto == IPPROTO_UDP ||
-	    entry->ipv6.proto == IPPROTO_SCTP ||
-	    entry->ipv6.proto == IPPROTO_DCCP ||
-	    entry->ipv6.proto == IPPROTO_ICMP)
-		portok = 1;
-	else
-		portok = 0;
-
-	xtables_option_parse(cb);
-	switch (cb->entry->id) {
-	case O_TO_PORTS:
-		if (!portok)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Need TCP, UDP, SCTP or DCCP with port specification");
-		parse_ports(cb->arg, r);
-		break;
-	case O_RANDOM:
-		r->flags |=  NF_NAT_RANGE_PROTO_RANDOM;
-		break;
-	case O_RANDOM_FULLY:
-		r->flags |=  NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-		break;
-	}
-}
-
-static void
-MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
-                 int numeric)
-{
-	const struct nf_nat_range *r = (const void *)target->data;
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(" masq ports: ");
-		printf("%hu", ntohs(r->min_proto.tcp.port));
-		if (r->max_proto.tcp.port != r->min_proto.tcp.port)
-			printf("-%hu", ntohs(r->max_proto.tcp.port));
-	}
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" random");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" random-fully");
-}
-
-static void
-MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct nf_nat_range *r = (const void *)target->data;
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port));
-		if (r->max_proto.tcp.port != r->min_proto.tcp.port)
-			printf("-%hu", ntohs(r->max_proto.tcp.port));
-	}
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" --random");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" --random-fully");
-}
-
-static int MASQUERADE_xlate(struct xt_xlate *xl,
-			    const struct xt_xlate_tg_params *params)
-{
-	const struct nf_nat_range *r = (const void *)params->target->data;
-
-	xt_xlate_add(xl, "masquerade");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		xt_xlate_add(xl, " to :%hu", ntohs(r->min_proto.tcp.port));
-		if (r->max_proto.tcp.port != r->min_proto.tcp.port)
-			xt_xlate_add(xl, "-%hu", ntohs(r->max_proto.tcp.port));
-	}
-
-	xt_xlate_add(xl, " ");
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		xt_xlate_add(xl, "random ");
-
-	xt_xlate_add(xl, " ");
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		xt_xlate_add(xl, "fully-random ");
-
-	return 1;
-}
-
-static struct xtables_target masquerade_tg_reg = {
-	.name		= "MASQUERADE",
-	.version	= XTABLES_VERSION,
-	.family		= NFPROTO_IPV6,
-	.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
-	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
-	.help		= MASQUERADE_help,
-	.x6_parse	= MASQUERADE_parse,
-	.print		= MASQUERADE_print,
-	.save		= MASQUERADE_save,
-	.x6_options	= MASQUERADE_opts,
-	.xlate		= MASQUERADE_xlate,
-};
-
-void _init(void)
-{
-	xtables_register_target(&masquerade_tg_reg);
-}
diff --git a/extensions/libip6t_MASQUERADE.txlate b/extensions/libip6t_MASQUERADE.txlate
index 6c289c2bdaee3..a2f9808036ebf 100644
--- a/extensions/libip6t_MASQUERADE.txlate
+++ b/extensions/libip6t_MASQUERADE.txlate
@@ -6,3 +6,12 @@ nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10
 
 ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
 nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random
+nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random-fully
+nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade fully-random
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random --random-fully
+nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random,fully-random
diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
deleted file mode 100644
index 8bf7b035f84b6..0000000000000
--- a/extensions/libip6t_SNAT.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
- *
- * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT
- * funded by Astaro.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <xtables.h>
-#include <iptables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
-	O_TO_SRC = 0,
-	O_RANDOM,
-	O_RANDOM_FULLY,
-	O_PERSISTENT,
-};
-
-static void SNAT_help(void)
-{
-	printf(
-"SNAT target options:\n"
-" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
-"				Address to map source to.\n"
-"[--random] [--random-fully] [--persistent]\n");
-}
-
-static const struct xt_option_entry SNAT_opts[] = {
-	{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
-	 .flags = XTOPT_MAND},
-	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
-	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
-	{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
-	XTOPT_TABLEEND,
-};
-
-/* Ranges expected in network order. */
-static void
-parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
-{
-	char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
-	const struct in6_addr *ip;
-
-	arg = xtables_strdup(orig_arg);
-
-	start = strchr(arg, '[');
-	if (start == NULL) {
-		start = arg;
-		/* Lets assume one colon is port information. Otherwise its an IPv6 address */
-		colon = strchr(arg, ':');
-		if (colon && strchr(colon+1, ':'))
-			colon = NULL;
-	}
-	else {
-		start++;
-		end = strchr(start, ']');
-		if (end == NULL)
-			xtables_error(PARAMETER_PROBLEM,
-				      "Invalid address format");
-
-		*end = '\0';
-		colon = strchr(end + 1, ':');
-	}
-
-	if (colon) {
-		int port;
-
-		if (!portok)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Need TCP, UDP, SCTP or DCCP with port specification");
-
-		range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
-		port = atoi(colon+1);
-		if (port <= 0 || port > 65535)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Port `%s' not valid\n", colon+1);
-
-		error = strchr(colon+1, ':');
-		if (error)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Invalid port:port syntax - use dash\n");
-
-		dash = strchr(colon, '-');
-		if (!dash) {
-			range->min_proto.tcp.port
-				= range->max_proto.tcp.port
-				= htons(port);
-		} else {
-			int maxport;
-
-			maxport = atoi(dash + 1);
-			if (maxport <= 0 || maxport > 65535)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Port `%s' not valid\n", dash+1);
-			if (maxport < port)
-				/* People are stupid. */
-				xtables_error(PARAMETER_PROBLEM,
-					   "Port range `%s' funky\n", colon+1);
-			range->min_proto.tcp.port = htons(port);
-			range->max_proto.tcp.port = htons(maxport);
-		}
-		/* Starts with colon or [] colon? No IP info...*/
-		if (colon == arg || colon == arg+2) {
-			free(arg);
-			return;
-		}
-		*colon = '\0';
-	}
-
-	range->flags |= NF_NAT_RANGE_MAP_IPS;
-	dash = strchr(start, '-');
-	if (colon && dash && dash > colon)
-		dash = NULL;
-
-	if (dash)
-		*dash = '\0';
-
-	ip = xtables_numeric_to_ip6addr(start);
-	if (!ip)
-		xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
-			      start);
-	range->min_addr.in6 = *ip;
-	if (dash) {
-		ip = xtables_numeric_to_ip6addr(dash + 1);
-		if (!ip)
-			xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
-				      dash+1);
-		range->max_addr.in6 = *ip;
-	} else
-		range->max_addr = range->min_addr;
-
-	free(arg);
-	return;
-}
-
-static void SNAT_parse(struct xt_option_call *cb)
-{
-	const struct ip6t_entry *entry = cb->xt_entry;
-	struct nf_nat_range *range = cb->data;
-	int portok;
-
-	if (entry->ipv6.proto == IPPROTO_TCP ||
-	    entry->ipv6.proto == IPPROTO_UDP ||
-	    entry->ipv6.proto == IPPROTO_SCTP ||
-	    entry->ipv6.proto == IPPROTO_DCCP ||
-	    entry->ipv6.proto == IPPROTO_ICMP)
-		portok = 1;
-	else
-		portok = 0;
-
-	xtables_option_parse(cb);
-	switch (cb->entry->id) {
-	case O_TO_SRC:
-		parse_to(cb->arg, portok, range);
-		break;
-	case O_PERSISTENT:
-		range->flags |= NF_NAT_RANGE_PERSISTENT;
-		break;
-	case O_RANDOM:
-		range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
-		break;
-	case O_RANDOM_FULLY:
-		range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-		break;
-	}
-}
-
-static void print_range(const struct nf_nat_range *range)
-{
-	if (range->flags & NF_NAT_RANGE_MAP_IPS) {
-		if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
-			printf("[");
-		printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
-		if (memcmp(&range->min_addr, &range->max_addr,
-			   sizeof(range->min_addr)))
-			printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
-		if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
-			printf("]");
-	}
-	if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(":");
-		printf("%hu", ntohs(range->min_proto.tcp.port));
-		if (range->max_proto.tcp.port != range->min_proto.tcp.port)
-			printf("-%hu", ntohs(range->max_proto.tcp.port));
-	}
-}
-
-static void SNAT_print(const void *ip, const struct xt_entry_target *target,
-                       int numeric)
-{
-	const struct nf_nat_range *range = (const void *)target->data;
-
-	printf(" to:");
-	print_range(range);
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" random");
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" random-fully");
-	if (range->flags & NF_NAT_RANGE_PERSISTENT)
-		printf(" persistent");
-}
-
-static void SNAT_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct nf_nat_range *range = (const void *)target->data;
-
-	printf(" --to-source ");
-	print_range(range);
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" --random");
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" --random-fully");
-	if (range->flags & NF_NAT_RANGE_PERSISTENT)
-		printf(" --persistent");
-}
-
-static void print_range_xlate(const struct nf_nat_range *range,
-			      struct xt_xlate *xl)
-{
-	bool proto_specified = range->flags & NF_NAT_RANGE_PROTO_SPECIFIED;
-
-	if (range->flags & NF_NAT_RANGE_MAP_IPS) {
-		xt_xlate_add(xl, "%s%s%s",
-			     proto_specified ? "[" : "",
-			     xtables_ip6addr_to_numeric(&range->min_addr.in6),
-			     proto_specified ? "]" : "");
-
-		if (memcmp(&range->min_addr, &range->max_addr,
-			   sizeof(range->min_addr))) {
-			xt_xlate_add(xl, "-%s%s%s",
-				     proto_specified ? "[" : "",
-				     xtables_ip6addr_to_numeric(&range->max_addr.in6),
-				     proto_specified ? "]" : "");
-		}
-	}
-	if (proto_specified) {
-		xt_xlate_add(xl, ":%hu", ntohs(range->min_proto.tcp.port));
-
-		if (range->max_proto.tcp.port != range->min_proto.tcp.port)
-			xt_xlate_add(xl, "-%hu",
-				   ntohs(range->max_proto.tcp.port));
-	}
-}
-
-static int SNAT_xlate(struct xt_xlate *xl,
-		      const struct xt_xlate_tg_params *params)
-{
-	const struct nf_nat_range *range = (const void *)params->target->data;
-	bool sep_need = false;
-	const char *sep = " ";
-
-	xt_xlate_add(xl, "snat to ");
-	print_range_xlate(range, xl);
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
-		xt_xlate_add(xl, " random");
-		sep_need = true;
-	}
-	if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
-		if (sep_need)
-			sep = ",";
-		xt_xlate_add(xl, "%sfully-random", sep);
-		sep_need = true;
-	}
-	if (range->flags & NF_NAT_RANGE_PERSISTENT) {
-		if (sep_need)
-			sep = ",";
-		xt_xlate_add(xl, "%spersistent", sep);
-	}
-
-	return 1;
-}
-
-static struct xtables_target snat_tg_reg = {
-	.name		= "SNAT",
-	.version	= XTABLES_VERSION,
-	.family		= NFPROTO_IPV6,
-	.revision	= 1,
-	.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
-	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
-	.help		= SNAT_help,
-	.x6_parse	= SNAT_parse,
-	.print		= SNAT_print,
-	.save		= SNAT_save,
-	.x6_options	= SNAT_opts,
-	.xlate		= SNAT_xlate,
-};
-
-void _init(void)
-{
-	xtables_register_target(&snat_tg_reg);
-}
diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t
index d188a6bb3d559..98aa7602e784f 100644
--- a/extensions/libip6t_SNAT.t
+++ b/extensions/libip6t_SNAT.t
@@ -4,6 +4,12 @@
 -j SNAT --to-source dead::beef-dead::fee7;=;OK
 -j SNAT --to-source [dead::beef]:1025-65535;;FAIL
 -j SNAT --to-source [dead::beef] --to-source [dead::fee7];;FAIL
+-j SNAT --to-source dead::beef --random;=;OK
+-j SNAT --to-source dead::beef --random-fully;=;OK
+-j SNAT --to-source dead::beef --persistent;=;OK
+-j SNAT --to-source dead::beef --random --persistent;=;OK
+-j SNAT --to-source dead::beef --random --random-fully;=;OK
+-j SNAT --to-source dead::beef --random --random-fully --persistent;=;OK
 -p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK
 -p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK
 -p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
deleted file mode 100644
index 90bf60659c4f4..0000000000000
--- a/extensions/libipt_MASQUERADE.c
+++ /dev/null
@@ -1,190 +0,0 @@
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <xtables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
-	O_TO_PORTS = 0,
-	O_RANDOM,
-	O_RANDOM_FULLY,
-};
-
-static void MASQUERADE_help(void)
-{
-	printf(
-"MASQUERADE target options:\n"
-" --to-ports <port>[-<port>]\n"
-"				Port (range) to map to.\n"
-" --random\n"
-"				Randomize source port.\n"
-" --random-fully\n"
-"				Fully randomize source port.\n");
-}
-
-static const struct xt_option_entry MASQUERADE_opts[] = {
-	{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
-	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
-	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
-	XTOPT_TABLEEND,
-};
-
-static void MASQUERADE_init(struct xt_entry_target *t)
-{
-	struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
-
-	/* Actually, it's 0, but it's ignored at the moment. */
-	mr->rangesize = 1;
-}
-
-/* Parses ports */
-static void
-parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
-{
-	char *end;
-	unsigned int port, maxport;
-
-	mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
-	if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
-		xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-
-	switch (*end) {
-	case '\0':
-		mr->range[0].min.tcp.port
-			= mr->range[0].max.tcp.port
-			= htons(port);
-		return;
-	case '-':
-		if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
-			break;
-
-		if (maxport < port)
-			break;
-
-		mr->range[0].min.tcp.port = htons(port);
-		mr->range[0].max.tcp.port = htons(maxport);
-		return;
-	default:
-		break;
-	}
-	xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-}
-
-static void MASQUERADE_parse(struct xt_option_call *cb)
-{
-	const struct ipt_entry *entry = cb->xt_entry;
-	int portok;
-	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
-
-	if (entry->ip.proto == IPPROTO_TCP
-	    || entry->ip.proto == IPPROTO_UDP
-	    || entry->ip.proto == IPPROTO_SCTP
-	    || entry->ip.proto == IPPROTO_DCCP
-	    || entry->ip.proto == IPPROTO_ICMP)
-		portok = 1;
-	else
-		portok = 0;
-
-	xtables_option_parse(cb);
-	switch (cb->entry->id) {
-	case O_TO_PORTS:
-		if (!portok)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Need TCP, UDP, SCTP or DCCP with port specification");
-		parse_ports(cb->arg, mr);
-		break;
-	case O_RANDOM:
-		mr->range[0].flags |=  NF_NAT_RANGE_PROTO_RANDOM;
-		break;
-	case O_RANDOM_FULLY:
-		mr->range[0].flags |=  NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-		break;
-	}
-}
-
-static void
-MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
-                 int numeric)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
-	const struct nf_nat_ipv4_range *r = &mr->range[0];
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(" masq ports: ");
-		printf("%hu", ntohs(r->min.tcp.port));
-		if (r->max.tcp.port != r->min.tcp.port)
-			printf("-%hu", ntohs(r->max.tcp.port));
-	}
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" random");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" random-fully");
-}
-
-static void
-MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
-	const struct nf_nat_ipv4_range *r = &mr->range[0];
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(" --to-ports %hu", ntohs(r->min.tcp.port));
-		if (r->max.tcp.port != r->min.tcp.port)
-			printf("-%hu", ntohs(r->max.tcp.port));
-	}
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" --random");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" --random-fully");
-}
-
-static int MASQUERADE_xlate(struct xt_xlate *xl,
-			    const struct xt_xlate_tg_params *params)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr =
-		(const void *)params->target->data;
-	const struct nf_nat_ipv4_range *r = &mr->range[0];
-
-	xt_xlate_add(xl, "masquerade");
-
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		xt_xlate_add(xl, " to :%hu", ntohs(r->min.tcp.port));
-		if (r->max.tcp.port != r->min.tcp.port)
-			xt_xlate_add(xl, "-%hu", ntohs(r->max.tcp.port));
-        }
-
-	xt_xlate_add(xl, " ");
-	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		xt_xlate_add(xl, "random ");
-
-	return 1;
-}
-
-static struct xtables_target masquerade_tg_reg = {
-	.name		= "MASQUERADE",
-	.version	= XTABLES_VERSION,
-	.family		= NFPROTO_IPV4,
-	.size		= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
-	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
-	.help		= MASQUERADE_help,
-	.init		= MASQUERADE_init,
-	.x6_parse	= MASQUERADE_parse,
-	.print		= MASQUERADE_print,
-	.save		= MASQUERADE_save,
-	.x6_options	= MASQUERADE_opts,
-	.xlate		= MASQUERADE_xlate,
-};
-
-void _init(void)
-{
-	xtables_register_target(&masquerade_tg_reg);
-}
diff --git a/extensions/libipt_MASQUERADE.txlate b/extensions/libipt_MASQUERADE.txlate
index 40b6958a55cad..49f79d33dcfa8 100644
--- a/extensions/libipt_MASQUERADE.txlate
+++ b/extensions/libipt_MASQUERADE.txlate
@@ -6,3 +6,12 @@ nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10
 
 iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
 nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10-20 random
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random
+nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade random
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random-fully
+nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade fully-random
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random --random-fully
+nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade random,fully-random
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
deleted file mode 100644
index 9c8cdb46a1585..0000000000000
--- a/extensions/libipt_SNAT.c
+++ /dev/null
@@ -1,276 +0,0 @@
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <xtables.h>
-#include <iptables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
-	O_TO_SRC = 0,
-	O_RANDOM,
-	O_RANDOM_FULLY,
-	O_PERSISTENT,
-};
-
-static void SNAT_help(void)
-{
-	printf(
-"SNAT target options:\n"
-" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
-"				Address to map source to.\n"
-"[--random] [--random-fully] [--persistent]\n");
-}
-
-static const struct xt_option_entry SNAT_opts[] = {
-	{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
-	 .flags = XTOPT_MAND},
-	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
-	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
-	{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
-	XTOPT_TABLEEND,
-};
-
-/* Ranges expected in network order. */
-static void
-parse_to(const char *orig_arg, int portok, struct nf_nat_ipv4_range *range)
-{
-	char *arg, *colon, *dash, *error;
-	const struct in_addr *ip;
-
-	arg = xtables_strdup(orig_arg);
-	colon = strchr(arg, ':');
-
-	if (colon) {
-		int port;
-
-		if (!portok)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Need TCP, UDP, SCTP or DCCP with port specification");
-
-		range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
-		port = atoi(colon+1);
-		if (port <= 0 || port > 65535)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Port `%s' not valid\n", colon+1);
-
-		error = strchr(colon+1, ':');
-		if (error)
-			xtables_error(PARAMETER_PROBLEM,
-				   "Invalid port:port syntax - use dash\n");
-
-		dash = strchr(colon, '-');
-		if (!dash) {
-			range->min.tcp.port
-				= range->max.tcp.port
-				= htons(port);
-		} else {
-			int maxport;
-
-			maxport = atoi(dash + 1);
-			if (maxport <= 0 || maxport > 65535)
-				xtables_error(PARAMETER_PROBLEM,
-					   "Port `%s' not valid\n", dash+1);
-			if (maxport < port)
-				/* People are stupid. */
-				xtables_error(PARAMETER_PROBLEM,
-					   "Port range `%s' funky\n", colon+1);
-			range->min.tcp.port = htons(port);
-			range->max.tcp.port = htons(maxport);
-		}
-		/* Starts with a colon? No IP info...*/
-		if (colon == arg) {
-			free(arg);
-			return;
-		}
-		*colon = '\0';
-	}
-
-	range->flags |= NF_NAT_RANGE_MAP_IPS;
-	dash = strchr(arg, '-');
-	if (colon && dash && dash > colon)
-		dash = NULL;
-
-	if (dash)
-		*dash = '\0';
-
-	ip = xtables_numeric_to_ipaddr(arg);
-	if (!ip)
-		xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
-			   arg);
-	range->min_ip = ip->s_addr;
-	if (dash) {
-		ip = xtables_numeric_to_ipaddr(dash+1);
-		if (!ip)
-			xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
-				   dash+1);
-		range->max_ip = ip->s_addr;
-	} else
-		range->max_ip = range->min_ip;
-
-	free(arg);
-	return;
-}
-
-static void SNAT_parse(struct xt_option_call *cb)
-{
-	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
-	const struct ipt_entry *entry = cb->xt_entry;
-	int portok;
-
-	if (entry->ip.proto == IPPROTO_TCP
-	    || entry->ip.proto == IPPROTO_UDP
-	    || entry->ip.proto == IPPROTO_SCTP
-	    || entry->ip.proto == IPPROTO_DCCP
-	    || entry->ip.proto == IPPROTO_ICMP)
-		portok = 1;
-	else
-		portok = 0;
-
-	xtables_option_parse(cb);
-	switch (cb->entry->id) {
-	case O_TO_SRC:
-		parse_to(cb->arg, portok, mr->range);
-		break;
-	case O_PERSISTENT:
-		mr->range->flags |= NF_NAT_RANGE_PERSISTENT;
-		break;
-	case O_RANDOM:
-		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
-		break;
-	case O_RANDOM_FULLY:
-		mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-		break;
-	}
-}
-
-static void SNAT_fcheck(struct xt_fcheck_call *cb)
-{
-	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
-
-	mr->rangesize = 1;
-}
-
-static void print_range(const struct nf_nat_ipv4_range *r)
-{
-	if (r->flags & NF_NAT_RANGE_MAP_IPS) {
-		struct in_addr a;
-
-		a.s_addr = r->min_ip;
-		printf("%s", xtables_ipaddr_to_numeric(&a));
-		if (r->max_ip != r->min_ip) {
-			a.s_addr = r->max_ip;
-			printf("-%s", xtables_ipaddr_to_numeric(&a));
-		}
-	}
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		printf(":");
-		printf("%hu", ntohs(r->min.tcp.port));
-		if (r->max.tcp.port != r->min.tcp.port)
-			printf("-%hu", ntohs(r->max.tcp.port));
-	}
-}
-
-static void SNAT_print(const void *ip, const struct xt_entry_target *target,
-                       int numeric)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr =
-				(const void *)target->data;
-
-	printf(" to:");
-	print_range(mr->range);
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" random");
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" random-fully");
-	if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
-		printf(" persistent");
-}
-
-static void SNAT_save(const void *ip, const struct xt_entry_target *target)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr =
-				(const void *)target->data;
-
-	printf(" --to-source ");
-	print_range(mr->range);
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
-		printf(" --random");
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-		printf(" --random-fully");
-	if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
-		printf(" --persistent");
-}
-
-static void print_range_xlate(const struct nf_nat_ipv4_range *r,
-			      struct xt_xlate *xl)
-{
-	if (r->flags & NF_NAT_RANGE_MAP_IPS) {
-		struct in_addr a;
-
-		a.s_addr = r->min_ip;
-		xt_xlate_add(xl, "%s", xtables_ipaddr_to_numeric(&a));
-		if (r->max_ip != r->min_ip) {
-			a.s_addr = r->max_ip;
-			xt_xlate_add(xl, "-%s", xtables_ipaddr_to_numeric(&a));
-		}
-	}
-	if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
-		xt_xlate_add(xl, ":");
-		xt_xlate_add(xl, "%hu", ntohs(r->min.tcp.port));
-		if (r->max.tcp.port != r->min.tcp.port)
-			xt_xlate_add(xl, "-%hu", ntohs(r->max.tcp.port));
-	}
-}
-
-static int SNAT_xlate(struct xt_xlate *xl,
-		      const struct xt_xlate_tg_params *params)
-{
-	const struct nf_nat_ipv4_multi_range_compat *mr =
-				(const void *)params->target->data;
-	bool sep_need = false;
-	const char *sep = " ";
-
-	xt_xlate_add(xl, "snat to ");
-	print_range_xlate(mr->range, xl);
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
-		xt_xlate_add(xl, " random");
-		sep_need = true;
-	}
-	if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
-		if (sep_need)
-			sep = ",";
-		xt_xlate_add(xl, "%sfully-random", sep);
-		sep_need = true;
-	}
-	if (mr->range->flags & NF_NAT_RANGE_PERSISTENT) {
-		if (sep_need)
-			sep = ",";
-		xt_xlate_add(xl, "%spersistent", sep);
-	}
-
-	return 1;
-}
-
-static struct xtables_target snat_tg_reg = {
-	.name		= "SNAT",
-	.version	= XTABLES_VERSION,
-	.family		= NFPROTO_IPV4,
-	.size		= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
-	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
-	.help		= SNAT_help,
-	.x6_parse	= SNAT_parse,
-	.x6_fcheck	= SNAT_fcheck,
-	.print		= SNAT_print,
-	.save		= SNAT_save,
-	.x6_options	= SNAT_opts,
-	.xlate		= SNAT_xlate,
-};
-
-void _init(void)
-{
-	xtables_register_target(&snat_tg_reg);
-}
diff --git a/extensions/libipt_SNAT.t b/extensions/libipt_SNAT.t
index 186e1cb82c3f3..c31d6e7c2cce8 100644
--- a/extensions/libipt_SNAT.t
+++ b/extensions/libipt_SNAT.t
@@ -4,6 +4,12 @@
 -j SNAT --to-source 1.1.1.1-1.1.1.10;=;OK
 -j SNAT --to-source 1.1.1.1:1025-65535;;FAIL
 -j SNAT --to-source 1.1.1.1 --to-source 2.2.2.2;;FAIL
+-j SNAT --to-source 1.1.1.1 --random;=;OK
+-j SNAT --to-source 1.1.1.1 --random-fully;=;OK
+-j SNAT --to-source 1.1.1.1 --persistent;=;OK
+-j SNAT --to-source 1.1.1.1 --random --persistent;=;OK
+-j SNAT --to-source 1.1.1.1 --random --random-fully;=;OK
+-j SNAT --to-source 1.1.1.1 --random --random-fully --persistent;=;OK
 -p tcp -j SNAT --to-source 1.1.1.1:1025-65535;=;OK
 -p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535;=;OK
 -p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65536;;FAIL
diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_NAT.c
similarity index 80%
rename from extensions/libxt_DNAT.c
rename to extensions/libxt_NAT.c
index fbb10e410a221..da9f22012c5d6 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_NAT.c
@@ -36,11 +36,34 @@
 
 enum {
 	O_TO_DEST = 0,
+	O_TO_SRC,
 	O_TO_PORTS,
 	O_RANDOM,
+	O_RANDOM_FULLY,
 	O_PERSISTENT,
 };
 
+static void SNAT_help(void)
+{
+	printf(
+"SNAT target options:\n"
+" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+"				Address to map source to.\n"
+"[--random] [--random-fully] [--persistent]\n");
+}
+
+static void MASQUERADE_help(void)
+{
+	printf(
+"MASQUERADE target options:\n"
+" --to-ports <port>[-<port>]\n"
+"				Port (range) to map to.\n"
+" --random\n"
+"				Randomize source port.\n"
+" --random-fully\n"
+"				Fully randomize source port.\n");
+}
+
 static void DNAT_help(void)
 {
 	printf(
@@ -68,6 +91,22 @@ static void REDIRECT_help(void)
 " [--random]\n");
 }
 
+static const struct xt_option_entry SNAT_opts[] = {
+	{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND},
+	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
+	{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
+};
+
+static const struct xt_option_entry MASQUERADE_opts[] = {
+	{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+	{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
+};
+
 static const struct xt_option_entry DNAT_opts[] = {
 	{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
 	 .flags = XTOPT_MAND},
@@ -226,6 +265,7 @@ static void __NAT_parse(struct xt_option_call *cb, __u16 proto,
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
 	case O_TO_DEST:
+	case O_TO_SRC:
 		parse_to(cb->arg, portok, range, family);
 		break;
 	case O_TO_PORTS:
@@ -237,6 +277,9 @@ static void __NAT_parse(struct xt_option_call *cb, __u16 proto,
 	case O_RANDOM:
 		range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
 		break;
+	case O_RANDOM_FULLY:
+		range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+		break;
 	}
 }
 
@@ -250,6 +293,7 @@ static void NAT_parse(struct xt_option_call *cb)
 
 	switch (cb->entry->id) {
 	case O_TO_DEST:
+	case O_TO_SRC:
 		mr->range->min_ip = range.min_addr.ip;
 		mr->range->max_ip = range.max_addr.ip;
 		/* fall through */
@@ -259,6 +303,7 @@ static void NAT_parse(struct xt_option_call *cb)
 		/* fall through */
 	case O_PERSISTENT:
 	case O_RANDOM:
+	case O_RANDOM_FULLY:
 		mr->range->flags |= range.flags;
 		break;
 	}
@@ -288,6 +333,13 @@ static void DNAT_parse6_v2(struct xt_option_call *cb)
 	__NAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
 }
 
+static void SNAT_fcheck(struct xt_fcheck_call *cb)
+{
+	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
+
+	mr->rangesize = 1;
+}
+
 static void DNAT_fcheck(struct xt_fcheck_call *cb)
 {
 	struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
@@ -355,6 +407,8 @@ static void __NAT_print(const struct nf_nat_range2 *r, int family,
 	}
 	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
 		printf(" %srandom", flag_pfx);
+	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+		printf(" %srandom-fully", flag_pfx);
 	if (r->flags & NF_NAT_RANGE_PERSISTENT)
 		printf(" %spersistent", flag_pfx);
 }
@@ -377,6 +431,10 @@ __NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
 		xt_xlate_add(xl, "%srandom", sep);
 		sep = ",";
 	}
+	if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
+		xt_xlate_add(xl, "%sfully-random", sep);
+		sep = ",";
+	}
 	if (r->flags & NF_NAT_RANGE_PERSISTENT) {
 		xt_xlate_add(xl, "%spersistent", sep);
 		sep = ",";
@@ -425,7 +483,33 @@ PSX_GEN(REDIRECT, RANGE2_INIT_FROM_IPV4_MRC, \
 PSX_GEN(REDIRECT6, RANGE2_INIT_FROM_RANGE, \
 	AF_INET6, "redir ports ", "--to-ports ", true, "redirect")
 
+PSX_GEN(SNAT, RANGE2_INIT_FROM_IPV4_MRC, \
+	AF_INET, "to:", "--to-source ", false, "snat")
+
+PSX_GEN(SNAT6, RANGE2_INIT_FROM_RANGE, \
+	AF_INET6, "to:", "--to-source ", false, "snat")
+
+PSX_GEN(MASQUERADE, RANGE2_INIT_FROM_IPV4_MRC, \
+	AF_INET, "masq ports: ", "--to-ports ", true, "masquerade")
+
+PSX_GEN(MASQUERADE6, RANGE2_INIT_FROM_RANGE, \
+	AF_INET6, "masq ports: ", "--to-ports ", true, "masquerade")
+
 static struct xtables_target nat_tg_reg[] = {
+	{
+		.name		= "SNAT",
+		.version	= XTABLES_VERSION,
+		.family		= NFPROTO_IPV4,
+		.size		= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+		.help		= SNAT_help,
+		.x6_parse	= NAT_parse,
+		.x6_fcheck	= SNAT_fcheck,
+		.print		= SNAT_print,
+		.save		= SNAT_save,
+		.x6_options	= SNAT_opts,
+		.xlate		= SNAT_xlate,
+	},
 	{
 		.name		= "DNAT",
 		.version	= XTABLES_VERSION,
@@ -441,6 +525,33 @@ static struct xtables_target nat_tg_reg[] = {
 		.x6_options	= DNAT_opts,
 		.xlate		= DNAT_xlate,
 	},
+	{
+		.name		= "MASQUERADE",
+		.version	= XTABLES_VERSION,
+		.family		= NFPROTO_IPV4,
+		.size		= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+		.help		= MASQUERADE_help,
+		.x6_parse	= NAT_parse,
+		.x6_fcheck	= SNAT_fcheck,
+		.print		= MASQUERADE_print,
+		.save		= MASQUERADE_save,
+		.x6_options	= MASQUERADE_opts,
+		.xlate		= MASQUERADE_xlate,
+	},
+	{
+		.name		= "MASQUERADE",
+		.version	= XTABLES_VERSION,
+		.family		= NFPROTO_IPV6,
+		.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
+		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
+		.help		= MASQUERADE_help,
+		.x6_parse	= NAT_parse6,
+		.print		= MASQUERADE6_print,
+		.save		= MASQUERADE6_save,
+		.x6_options	= MASQUERADE_opts,
+		.xlate		= MASQUERADE6_xlate,
+	},
 	{
 		.name		= "REDIRECT",
 		.version	= XTABLES_VERSION,
@@ -456,6 +567,20 @@ static struct xtables_target nat_tg_reg[] = {
 		.x6_options	= REDIRECT_opts,
 		.xlate		= REDIRECT_xlate,
 	},
+	{
+		.name		= "SNAT",
+		.version	= XTABLES_VERSION,
+		.family		= NFPROTO_IPV6,
+		.revision	= 1,
+		.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
+		.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
+		.help		= SNAT_help,
+		.x6_parse	= NAT_parse6,
+		.print		= SNAT6_print,
+		.save		= SNAT6_save,
+		.x6_options	= SNAT_opts,
+		.xlate		= SNAT6_xlate,
+	},
 	{
 		.name		= "DNAT",
 		.version	= XTABLES_VERSION,
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [iptables PATCH 0/6] Merge NAT extensions
  2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
                   ` (5 preceding siblings ...)
  2022-11-03  1:41 ` [iptables PATCH 6/6] extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE Phil Sutter
@ 2022-11-11 18:16 ` Phil Sutter
  6 siblings, 0 replies; 8+ messages in thread
From: Phil Sutter @ 2022-11-11 18:16 UTC (permalink / raw)
  To: netfilter-devel

On Thu, Nov 03, 2022 at 02:41:07AM +0100, Phil Sutter wrote:
> Besides the three different data structures in use to store different
> revisions' extensions data, the actual code is pretty similar in all the
> different NAT "flavors".
> 
> Patch 1 fixes a minor bug introduced by a previous commit. Patch 2
> eliminates some needless checks and some that seem not necessary.
> Patches 3 to 5 prepare DNAT extension code for the actual merge
> happening in patch 6.
> 
> Phil Sutter (6):
>   extensions: DNAT: Fix bad IP address error reporting
>   extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks
>   extensions: DNAT: Use __DNAT_xlate for REDIRECT, too
>   extensions: DNAT: Generate print, save and xlate callbacks
>   extensions: DNAT: Rename some symbols
>   extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE

Series applied.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-11-11 18:16 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-03  1:41 [iptables PATCH 0/6] Merge NAT extensions Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 1/6] extensions: DNAT: Fix bad IP address error reporting Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 2/6] extensions: *NAT: Drop NF_NAT_RANGE_PROTO_RANDOM* flag checks Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 3/6] extensions: DNAT: Use __DNAT_xlate for REDIRECT, too Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 4/6] extensions: DNAT: Generate print, save and xlate callbacks Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 5/6] extensions: DNAT: Rename some symbols Phil Sutter
2022-11-03  1:41 ` [iptables PATCH 6/6] extensions: Merge SNAT, DNAT, REDIRECT and MASQUERADE Phil Sutter
2022-11-11 18:16 ` [iptables PATCH 0/6] Merge NAT extensions Phil Sutter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.