netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf-next 00/13] Support for shifted port-ranges in NAT
@ 2023-03-05 12:18 Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 01/13] netfilter: conntrack: fix typo Jeremy Sowden
                   ` (13 more replies)
  0 siblings, 14 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

Commit 2eb0f624b709 ("netfilter: add NAT support for shifted portmap
ranges") introduced support for shifting port-ranges in DNAT.  This
allows one to redirect packets intended for one port to another in a
range in such a way that the new port chosen has the same offset in the
range as the original port had from a specified base value.

For example, by using the base value 2000, one could redirect packets
intended for 10.0.0.1:2000-3000 to 10.10.0.1:12000-13000 so that the old
and new ports were at the same offset in their respective ranges, i.e.:

  10.0.0.1:2345 -> 10.10.0.1:12345

However, while support for this was added to the common DNAT infra-
structure, only the xt_nat module was updated to make use of it.  This
patch-set extends the core support and updates all the nft NAT modules
to support it too.

Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=970672
Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1501

* Patches 1 & 2 contain small tidy-ups.
* Patch 3 extends the core NAT support for shifted port-ranges to SNAT.
* Patches 4 & 5 correct the size in a `nft_parse_register_load` call and
  add shifted port-range support to nft_nat.
* Patches 6-8 correct the size in a `nft_parse_register_load` call and
  add shifted port-range support to nft_masq.
* Patch 9 corrects a C&P mistake in an nft_redir `nft_expr_type`
  definition.
* Patch 10-13 correct the size in a `nft_parse_register_load` call and
  add shifted port-range support to nft_redir.

Jeremy Sowden (13):
  netfilter: conntrack: fix typo
  netfilter: nat: fix indentation of function arguments
  netfilter: nat: extend core support for shifted port-ranges
  netfilter: nft_nat: correct length for loading protocol registers
  netfilter: nft_nat: add support for shifted port-ranges
  netfilter: nft_masq: correct length for loading protocol registers
  netfilter: nft_masq: deduplicate eval call-backs
  netfilter: nft_masq: add support for shifted port-ranges
  netfilter: nft_redir: correct value of inet type `.maxattrs`
  netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API
  netfilter: nft_redir: correct length for loading protocol registers
  netfilter: nft_redir: deduplicate eval call-backs
  netfilter: nft_redir: add support for shifted port-ranges

 include/net/netfilter/nf_nat_redirect.h  |   3 +-
 include/uapi/linux/netfilter/nf_tables.h |   6 ++
 net/netfilter/nf_conntrack_core.c        |   2 +-
 net/netfilter/nf_nat_core.c              |   7 +-
 net/netfilter/nf_nat_masquerade.c        |   2 +
 net/netfilter/nf_nat_redirect.c          |  59 ++++++-------
 net/netfilter/nft_masq.c                 |  97 ++++++++++-----------
 net/netfilter/nft_nat.c                  |  38 ++++++---
 net/netfilter/nft_redir.c                | 104 +++++++++++------------
 net/netfilter/xt_REDIRECT.c              |  10 ++-
 10 files changed, 177 insertions(+), 151 deletions(-)

-- 
2.39.2


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

* [PATCH nf-next 01/13] netfilter: conntrack: fix typo
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 02/13] netfilter: nat: fix indentation of function arguments Jeremy Sowden
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

There's a spelling mistake in a comment.  Fix it.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nf_conntrack_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 7250082e7de5..004c54132a3b 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1294,7 +1294,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(__nf_conntrack_confirm);
 
-/* Returns true if a connection correspondings to the tuple (required
+/* Returns true if a connection corresponds to the tuple (required
    for NAT). */
 int
 nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
-- 
2.39.2


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

* [PATCH nf-next 02/13] netfilter: nat: fix indentation of function arguments
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 01/13] netfilter: conntrack: fix typo Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 03/13] netfilter: nat: extend core support for shifted port-ranges Jeremy Sowden
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

A couple of arguments to a function call are incorrectly indented.
Fix them.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nf_nat_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index e29e4ccb5c5a..ce829d434f13 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -549,8 +549,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
 		if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
 			if (!(range->flags & NF_NAT_RANGE_PROTO_OFFSET) &&
 			    l4proto_in_range(tuple, maniptype,
-			          &range->min_proto,
-			          &range->max_proto) &&
+					     &range->min_proto,
+					     &range->max_proto) &&
 			    (range->min_proto.all == range->max_proto.all ||
 			     !nf_nat_used_tuple(tuple, ct)))
 				return;
-- 
2.39.2


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

* [PATCH nf-next 03/13] netfilter: nat: extend core support for shifted port-ranges
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 01/13] netfilter: conntrack: fix typo Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 02/13] netfilter: nat: fix indentation of function arguments Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 04/13] netfilter: nft_nat: correct length for loading protocol registers Jeremy Sowden
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

Commit 2eb0f624b709 ("netfilter: add NAT support for shifted portmap
ranges") makes changes in the NAT core to add support for shifted
port-ranges to iptables DNAT.  Before adding support for these to the
nft NAT modules extend the core changes to support SNAT as well.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nf_nat_core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index ce829d434f13..9e3a9472df2f 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -255,6 +255,9 @@ static int in_range(const struct nf_conntrack_tuple *tuple,
 	if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED))
 		return 1;
 
+	if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
+		return 0;
+
 	return l4proto_in_range(tuple, NF_NAT_MANIP_SRC,
 				&range->min_proto, &range->max_proto);
 }
-- 
2.39.2


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

* [PATCH nf-next 04/13] netfilter: nft_nat: correct length for loading protocol registers
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (2 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 03/13] netfilter: nat: extend core support for shifted port-ranges Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges Jeremy Sowden
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

The values in the protocol registers are two bytes wide.  However, when
parsing the register loads, the code currently uses the larger 16-byte
size of a `union nf_inet_addr`.  Change it to use the (correct) size of
a `union nf_conntrack_man_proto` instead.

Fixes: d07db9884a5f ("netfilter: nf_tables: introduce nft_validate_register_load()")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_nat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index 047999150390..5c29915ab028 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -226,7 +226,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 		priv->flags |= NF_NAT_RANGE_MAP_IPS;
 	}
 
-	plen = sizeof_field(struct nf_nat_range, min_addr.all);
+	plen = sizeof_field(struct nf_nat_range, min_proto.all);
 	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
 		err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
 					      &priv->sreg_proto_min, plen);
-- 
2.39.2


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

* [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (3 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 04/13] netfilter: nft_nat: correct length for loading protocol registers Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-07 12:27   ` Florian Westphal
  2023-03-05 12:18 ` [PATCH nf-next 06/13] netfilter: nft_masq: correct length for loading protocol registers Jeremy Sowden
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

Commit 2eb0f624b709 ("netfilter: add NAT support for shifted portmap
ranges") introduced support for shifting port-ranges in NAT.  This
allows one to redirect packets intended for one port to another in a
range in such a way that the new port chosen has the same offset in the
range as the original port had from a specified base value.

For example, by using the base value 2000, one could redirect packets
intended for 10.0.0.1:2000-3000 to 10.10.0.1:12000-13000 so that the old
and new ports were at the same offset in their respective ranges, i.e.:

  10.0.0.1:2345 -> 10.10.0.1:12345

However, while support for this was added to the common NAT infra-
structure, only the xt_nat module was updated to make use of it.  This
commit updates the nft_nat module to allow shifted port-ranges to be
used by nftables.

In contrast to xt_nat, where shifting is only available for DNAT, both
DNAT and SNAT are supported.

Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=970672
Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1501
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nft_nat.c                  | 38 +++++++++++++++++-------
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index ff677f3a6cad..af6032720c78 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1432,6 +1432,7 @@ enum nft_nat_types {
  * @NFTA_NAT_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
  * @NFTA_NAT_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
  * @NFTA_NAT_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
+ * @NFTA_NAT_REG_PROTO_BASE: source register of proto range base offset (NLA_U32: nft_registers)
  */
 enum nft_nat_attributes {
 	NFTA_NAT_UNSPEC,
@@ -1442,6 +1443,7 @@ enum nft_nat_attributes {
 	NFTA_NAT_REG_PROTO_MIN,
 	NFTA_NAT_REG_PROTO_MAX,
 	NFTA_NAT_FLAGS,
+	NFTA_NAT_REG_PROTO_BASE,
 	__NFTA_NAT_MAX
 };
 #define NFTA_NAT_MAX		(__NFTA_NAT_MAX - 1)
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index 5c29915ab028..0517a3efb259 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -25,6 +25,7 @@ struct nft_nat {
 	u8			sreg_addr_max;
 	u8			sreg_proto_min;
 	u8			sreg_proto_max;
+	u8			sreg_proto_base;
 	enum nf_nat_manip_type  type:8;
 	u8			family;
 	u16			flags;
@@ -58,6 +59,8 @@ static void nft_nat_setup_proto(struct nf_nat_range2 *range,
 		nft_reg_load16(&regs->data[priv->sreg_proto_min]);
 	range->max_proto.all = (__force __be16)
 		nft_reg_load16(&regs->data[priv->sreg_proto_max]);
+	range->base_proto.all = (__force __be16)
+		nft_reg_load16(&regs->data[priv->sreg_proto_base]);
 }
 
 static void nft_nat_setup_netmap(struct nf_nat_range2 *range,
@@ -126,13 +129,14 @@ static void nft_nat_eval(const struct nft_expr *expr,
 }
 
 static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
-	[NFTA_NAT_TYPE]		 = { .type = NLA_U32 },
-	[NFTA_NAT_FAMILY]	 = { .type = NLA_U32 },
-	[NFTA_NAT_REG_ADDR_MIN]	 = { .type = NLA_U32 },
-	[NFTA_NAT_REG_ADDR_MAX]	 = { .type = NLA_U32 },
-	[NFTA_NAT_REG_PROTO_MIN] = { .type = NLA_U32 },
-	[NFTA_NAT_REG_PROTO_MAX] = { .type = NLA_U32 },
-	[NFTA_NAT_FLAGS]	 = { .type = NLA_U32 },
+	[NFTA_NAT_TYPE]		  = { .type = NLA_U32 },
+	[NFTA_NAT_FAMILY]	  = { .type = NLA_U32 },
+	[NFTA_NAT_REG_ADDR_MIN]	  = { .type = NLA_U32 },
+	[NFTA_NAT_REG_ADDR_MAX]	  = { .type = NLA_U32 },
+	[NFTA_NAT_REG_PROTO_MIN]  = { .type = NLA_U32 },
+	[NFTA_NAT_REG_PROTO_MAX]  = { .type = NLA_U32 },
+	[NFTA_NAT_REG_PROTO_BASE] = { .type = NLA_U32 },
+	[NFTA_NAT_FLAGS]	  = { .type = NLA_U32 },
 };
 
 static int nft_nat_validate(const struct nft_ctx *ctx,
@@ -195,10 +199,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 
 	switch (family) {
 	case NFPROTO_IPV4:
-		alen = sizeof_field(struct nf_nat_range, min_addr.ip);
+		alen = sizeof_field(struct nf_nat_range2, min_addr.ip);
 		break;
 	case NFPROTO_IPV6:
-		alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
+		alen = sizeof_field(struct nf_nat_range2, min_addr.ip6);
 		break;
 	default:
 		if (tb[NFTA_NAT_REG_ADDR_MIN])
@@ -226,7 +230,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 		priv->flags |= NF_NAT_RANGE_MAP_IPS;
 	}
 
-	plen = sizeof_field(struct nf_nat_range, min_proto.all);
+	plen = sizeof_field(struct nf_nat_range2, min_proto.all);
 	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
 		err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
 					      &priv->sreg_proto_min, plen);
@@ -239,6 +243,16 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 						      plen);
 			if (err < 0)
 				return err;
+
+			if (tb[NFTA_NAT_REG_PROTO_BASE]) {
+				err = nft_parse_register_load
+					(tb[NFTA_NAT_REG_PROTO_BASE],
+					 &priv->sreg_proto_base, plen);
+				if (err < 0)
+					return err;
+
+				priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;
+			}
 		} else {
 			priv->sreg_proto_max = priv->sreg_proto_min;
 		}
@@ -286,7 +300,9 @@ static int nft_nat_dump(struct sk_buff *skb,
 		if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN,
 				      priv->sreg_proto_min) ||
 		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX,
-				      priv->sreg_proto_max))
+				      priv->sreg_proto_max) ||
+		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_BASE,
+				      priv->sreg_proto_base))
 			goto nla_put_failure;
 	}
 
-- 
2.39.2


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

* [PATCH nf-next 06/13] netfilter: nft_masq: correct length for loading protocol registers
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (4 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 07/13] netfilter: nft_masq: deduplicate eval call-backs Jeremy Sowden
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

The values in the protocol registers are two bytes wide.  However, when
parsing the register loads, the code currently uses the larger 16-byte
size of a `union nf_inet_addr`.  Change it to use the (correct) size of
a `union nf_conntrack_man_proto` instead.

Fixes: 8a6bf5da1aef ("netfilter: nft_masq: support port range")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_masq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index e55e455275c4..9544c2f16998 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -43,7 +43,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
 			 const struct nft_expr *expr,
 			 const struct nlattr * const tb[])
 {
-	u32 plen = sizeof_field(struct nf_nat_range, min_addr.all);
+	u32 plen = sizeof_field(struct nf_nat_range, min_proto.all);
 	struct nft_masq *priv = nft_expr_priv(expr);
 	int err;
 
-- 
2.39.2


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

* [PATCH nf-next 07/13] netfilter: nft_masq: deduplicate eval call-backs
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (5 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 06/13] netfilter: nft_masq: correct length for loading protocol registers Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 08/13] netfilter: nft_masq: add support for shifted port-ranges Jeremy Sowden
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

nft_masq has separate ipv4 and ipv6 call-backs which share much of their
code, and an inet one switch containing a switch that calls one of the
others based on the family of the packet.  Merge the ipv4 and ipv6 ones
into the inet one in order to get rid of the duplicate code.

Const-qualify the `priv` pointer since we don't need to write through
it.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_masq.c | 75 ++++++++++++++++------------------------
 1 file changed, 29 insertions(+), 46 deletions(-)

diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index 9544c2f16998..b115d77fbbc7 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -96,23 +96,39 @@ static int nft_masq_dump(struct sk_buff *skb,
 	return -1;
 }
 
-static void nft_masq_ipv4_eval(const struct nft_expr *expr,
-			       struct nft_regs *regs,
-			       const struct nft_pktinfo *pkt)
+static void nft_masq_eval(const struct nft_expr *expr,
+			  struct nft_regs *regs,
+			  const struct nft_pktinfo *pkt)
 {
-	struct nft_masq *priv = nft_expr_priv(expr);
+	const struct nft_masq *priv = nft_expr_priv(expr);
 	struct nf_nat_range2 range;
 
 	memset(&range, 0, sizeof(range));
 	range.flags = priv->flags;
 	if (priv->sreg_proto_min) {
-		range.min_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_min]);
-		range.max_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_max]);
+		range.min_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
+		range.max_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
+	}
+
+	switch (nft_pf(pkt)) {
+	case NFPROTO_IPV4:
+		regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb,
+							    nft_hook(pkt),
+							    &range,
+							    nft_out(pkt));
+		break;
+#ifdef CONFIG_NF_TABLES_IPV6
+	case NFPROTO_IPV6:
+		regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
+							    nft_out(pkt));
+		break;
+#endif
+	default:
+		WARN_ON_ONCE(1);
+		break;
 	}
-	regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, nft_hook(pkt),
-						    &range, nft_out(pkt));
 }
 
 static void
@@ -125,7 +141,7 @@ static struct nft_expr_type nft_masq_ipv4_type;
 static const struct nft_expr_ops nft_masq_ipv4_ops = {
 	.type		= &nft_masq_ipv4_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_masq)),
-	.eval		= nft_masq_ipv4_eval,
+	.eval		= nft_masq_eval,
 	.init		= nft_masq_init,
 	.destroy	= nft_masq_ipv4_destroy,
 	.dump		= nft_masq_dump,
@@ -143,25 +159,6 @@ static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
 };
 
 #ifdef CONFIG_NF_TABLES_IPV6
-static void nft_masq_ipv6_eval(const struct nft_expr *expr,
-			       struct nft_regs *regs,
-			       const struct nft_pktinfo *pkt)
-{
-	struct nft_masq *priv = nft_expr_priv(expr);
-	struct nf_nat_range2 range;
-
-	memset(&range, 0, sizeof(range));
-	range.flags = priv->flags;
-	if (priv->sreg_proto_min) {
-		range.min_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_min]);
-		range.max_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_max]);
-	}
-	regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
-						    nft_out(pkt));
-}
-
 static void
 nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -172,7 +169,7 @@ static struct nft_expr_type nft_masq_ipv6_type;
 static const struct nft_expr_ops nft_masq_ipv6_ops = {
 	.type		= &nft_masq_ipv6_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_masq)),
-	.eval		= nft_masq_ipv6_eval,
+	.eval		= nft_masq_eval,
 	.init		= nft_masq_init,
 	.destroy	= nft_masq_ipv6_destroy,
 	.dump		= nft_masq_dump,
@@ -204,20 +201,6 @@ static inline void nft_masq_module_exit_ipv6(void) {}
 #endif
 
 #ifdef CONFIG_NF_TABLES_INET
-static void nft_masq_inet_eval(const struct nft_expr *expr,
-			       struct nft_regs *regs,
-			       const struct nft_pktinfo *pkt)
-{
-	switch (nft_pf(pkt)) {
-	case NFPROTO_IPV4:
-		return nft_masq_ipv4_eval(expr, regs, pkt);
-	case NFPROTO_IPV6:
-		return nft_masq_ipv6_eval(expr, regs, pkt);
-	}
-
-	WARN_ON_ONCE(1);
-}
-
 static void
 nft_masq_inet_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -228,7 +211,7 @@ static struct nft_expr_type nft_masq_inet_type;
 static const struct nft_expr_ops nft_masq_inet_ops = {
 	.type		= &nft_masq_inet_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_masq)),
-	.eval		= nft_masq_inet_eval,
+	.eval		= nft_masq_eval,
 	.init		= nft_masq_init,
 	.destroy	= nft_masq_inet_destroy,
 	.dump		= nft_masq_dump,
-- 
2.39.2


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

* [PATCH nf-next 08/13] netfilter: nft_masq: add support for shifted port-ranges
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (6 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 07/13] netfilter: nft_masq: deduplicate eval call-backs Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 09/13] netfilter: nft_redir: correct value of inet type `.maxattrs` Jeremy Sowden
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

Support was recently added to nft_nat to allow shifting port-ranges
during NAT.  Extend this support to allow them to used in masquerading
as well.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nf_nat_masquerade.c        |  2 ++
 net/netfilter/nft_masq.c                 | 22 ++++++++++++++++++++--
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index af6032720c78..bab3e3c6de74 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1470,12 +1470,14 @@ enum nft_tproxy_attributes {
  * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
  * @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
  * @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_PROTO_BASE: source register of proto range base offset (NLA_U32: nft_registers)
  */
 enum nft_masq_attributes {
 	NFTA_MASQ_UNSPEC,
 	NFTA_MASQ_FLAGS,
 	NFTA_MASQ_REG_PROTO_MIN,
 	NFTA_MASQ_REG_PROTO_MAX,
+	NFTA_MASQ_REG_PROTO_BASE,
 	__NFTA_MASQ_MAX
 };
 #define NFTA_MASQ_MAX		(__NFTA_MASQ_MAX - 1)
diff --git a/net/netfilter/nf_nat_masquerade.c b/net/netfilter/nf_nat_masquerade.c
index 1a506b0c6511..8d40b507d4ad 100644
--- a/net/netfilter/nf_nat_masquerade.c
+++ b/net/netfilter/nf_nat_masquerade.c
@@ -69,6 +69,7 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
 	newrange.max_addr.ip = newsrc;
 	newrange.min_proto   = range->min_proto;
 	newrange.max_proto   = range->max_proto;
+	newrange.base_proto  = range->base_proto;
 
 	/* Hand modified range to generic setup. */
 	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
@@ -264,6 +265,7 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
 	newrange.max_addr.in6	= src;
 	newrange.min_proto	= range->min_proto;
 	newrange.max_proto	= range->max_proto;
+	newrange.base_proto     = range->base_proto;
 
 	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
 }
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index b115d77fbbc7..80cf5d59b917 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,12 +17,14 @@ struct nft_masq {
 	u32			flags;
 	u8			sreg_proto_min;
 	u8			sreg_proto_max;
+	u8			sreg_proto_base;
 };
 
 static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
 	[NFTA_MASQ_FLAGS]		= { .type = NLA_U32 },
 	[NFTA_MASQ_REG_PROTO_MIN]	= { .type = NLA_U32 },
 	[NFTA_MASQ_REG_PROTO_MAX]	= { .type = NLA_U32 },
+	[NFTA_MASQ_REG_PROTO_BASE]	= { .type = NLA_U32 },
 };
 
 static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -43,7 +45,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
 			 const struct nft_expr *expr,
 			 const struct nlattr * const tb[])
 {
-	u32 plen = sizeof_field(struct nf_nat_range, min_proto.all);
+	u32 plen = sizeof_field(struct nf_nat_range2, min_proto.all);
 	struct nft_masq *priv = nft_expr_priv(expr);
 	int err;
 
@@ -65,9 +67,21 @@ static int nft_masq_init(const struct nft_ctx *ctx,
 						      plen);
 			if (err < 0)
 				return err;
+
+			if (tb[NFTA_MASQ_REG_PROTO_BASE]) {
+				err = nft_parse_register_load
+					(tb[NFTA_MASQ_REG_PROTO_BASE],
+					 &priv->sreg_proto_base, plen);
+				if (err < 0)
+					return err;
+
+				priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;
+			}
 		} else {
 			priv->sreg_proto_max = priv->sreg_proto_min;
 		}
+
+		priv->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
 	}
 
 	return nf_ct_netns_get(ctx->net, ctx->family);
@@ -86,7 +100,9 @@ static int nft_masq_dump(struct sk_buff *skb,
 		if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
 				      priv->sreg_proto_min) ||
 		    nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX,
-				      priv->sreg_proto_max))
+				      priv->sreg_proto_max) ||
+		    nft_dump_register(skb, NFTA_MASQ_REG_PROTO_BASE,
+				      priv->sreg_proto_base))
 			goto nla_put_failure;
 	}
 
@@ -110,6 +126,8 @@ static void nft_masq_eval(const struct nft_expr *expr,
 			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
 		range.max_proto.all = (__force __be16)
 			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
+		range.base_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_base]);
 	}
 
 	switch (nft_pf(pkt)) {
-- 
2.39.2


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

* [PATCH nf-next 09/13] netfilter: nft_redir: correct value of inet type `.maxattrs`
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (7 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 08/13] netfilter: nft_masq: add support for shifted port-ranges Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API Jeremy Sowden
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

`nft_redir_inet_type.maxattrs` was being set, presumably because of a
cut-and-paste error, to `NFTA_MASQ_MAX`, instead of `NFTA_REDIR_MAX`.

Fixes: 63ce3940f3ab ("netfilter: nft_redir: add inet support")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_redir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 5f7739987559..aa8545775ae7 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -236,7 +236,7 @@ static struct nft_expr_type nft_redir_inet_type __read_mostly = {
 	.name		= "redir",
 	.ops		= &nft_redir_inet_ops,
 	.policy		= nft_redir_policy,
-	.maxattr	= NFTA_MASQ_MAX,
+	.maxattr	= NFTA_REDIR_MAX,
 	.owner		= THIS_MODULE,
 };
 
-- 
2.39.2


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

* [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (8 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 09/13] netfilter: nft_redir: correct value of inet type `.maxattrs` Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-07 12:35   ` Florian Westphal
  2023-03-05 12:18 ` [PATCH nf-next 11/13] netfilter: nft_redir: correct length for loading protocol registers Jeremy Sowden
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

`nf_nat_redirect_ipv4` takes a `struct nf_nat_ipv4_multi_range_compat`,
but converts it internally to a `struct nf_nat_range2`.  Change the
function to take the latter, factor out the code now shared with
`nf_nat_redirect_ipv6`, move the conversion to the xt_REDIRECT module,
and update the ipv4 range initialization in the nft_redir module.

Replace a bare hex constant for 127.0.0.1 with a macro.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 include/net/netfilter/nf_nat_redirect.h |  3 +-
 net/netfilter/nf_nat_redirect.c         | 58 ++++++++++++-------------
 net/netfilter/nft_redir.c               | 15 ++++---
 net/netfilter/xt_REDIRECT.c             | 10 ++++-
 4 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/include/net/netfilter/nf_nat_redirect.h b/include/net/netfilter/nf_nat_redirect.h
index 2418653a66db..279380de904c 100644
--- a/include/net/netfilter/nf_nat_redirect.h
+++ b/include/net/netfilter/nf_nat_redirect.h
@@ -6,8 +6,7 @@
 #include <uapi/linux/netfilter/nf_nat.h>
 
 unsigned int
-nf_nat_redirect_ipv4(struct sk_buff *skb,
-		     const struct nf_nat_ipv4_multi_range_compat *mr,
+nf_nat_redirect_ipv4(struct sk_buff *skb, const struct nf_nat_range2 *range,
 		     unsigned int hooknum);
 unsigned int
 nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
diff --git a/net/netfilter/nf_nat_redirect.c b/net/netfilter/nf_nat_redirect.c
index f91579c821e9..54ce8e6113ed 100644
--- a/net/netfilter/nf_nat_redirect.c
+++ b/net/netfilter/nf_nat_redirect.c
@@ -10,6 +10,7 @@
 
 #include <linux/if.h>
 #include <linux/inetdevice.h>
+#include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
@@ -24,25 +25,38 @@
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_redirect.h>
 
+static unsigned int
+nf_nat_redirect(struct sk_buff *skb, const struct nf_nat_range2 *range,
+		const union nf_inet_addr *newdst)
+{
+	struct nf_nat_range2 newrange;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
+
+	newrange.flags		= range->flags | NF_NAT_RANGE_MAP_IPS;
+	newrange.min_addr	= *newdst;
+	newrange.max_addr	= *newdst;
+	newrange.min_proto	= range->min_proto;
+	newrange.max_proto	= range->max_proto;
+
+	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
+}
+
 unsigned int
-nf_nat_redirect_ipv4(struct sk_buff *skb,
-		     const struct nf_nat_ipv4_multi_range_compat *mr,
+nf_nat_redirect_ipv4(struct sk_buff *skb, const struct nf_nat_range2 *range,
 		     unsigned int hooknum)
 {
-	struct nf_conn *ct;
-	enum ip_conntrack_info ctinfo;
 	__be32 newdst;
-	struct nf_nat_range2 newrange;
 
 	WARN_ON(hooknum != NF_INET_PRE_ROUTING &&
 		hooknum != NF_INET_LOCAL_OUT);
 
-	ct = nf_ct_get(skb, &ctinfo);
-	WARN_ON(!(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)));
-
 	/* Local packets: make them go to loopback */
 	if (hooknum == NF_INET_LOCAL_OUT) {
-		newdst = htonl(0x7F000001);
+		newdst = htonl(INADDR_LOOPBACK);
 	} else {
 		const struct in_device *indev;
 
@@ -61,17 +75,8 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,
 			return NF_DROP;
 	}
 
-	/* Transfer from original range. */
-	memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
-	memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
-	newrange.flags	     = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
-	newrange.min_addr.ip = newdst;
-	newrange.max_addr.ip = newdst;
-	newrange.min_proto   = mr->range[0].min;
-	newrange.max_proto   = mr->range[0].max;
-
-	/* Hand modified range to generic setup. */
-	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
+	return nf_nat_redirect(skb, range,
+			       &(union nf_inet_addr) { .ip = newdst });
 }
 EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);
 
@@ -81,12 +86,8 @@ unsigned int
 nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
 		     unsigned int hooknum)
 {
-	struct nf_nat_range2 newrange;
 	struct in6_addr newdst;
-	enum ip_conntrack_info ctinfo;
-	struct nf_conn *ct;
 
-	ct = nf_ct_get(skb, &ctinfo);
 	if (hooknum == NF_INET_LOCAL_OUT) {
 		newdst = loopback_addr;
 	} else {
@@ -109,12 +110,7 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
 			return NF_DROP;
 	}
 
-	newrange.flags		= range->flags | NF_NAT_RANGE_MAP_IPS;
-	newrange.min_addr.in6	= newdst;
-	newrange.max_addr.in6	= newdst;
-	newrange.min_proto	= range->min_proto;
-	newrange.max_proto	= range->max_proto;
-
-	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
+	return nf_nat_redirect(skb, range,
+			       &(union nf_inet_addr) { .in6 = newdst });
 }
 EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6);
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index aa8545775ae7..2f300e0eec32 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -104,20 +104,21 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
 				const struct nft_pktinfo *pkt)
 {
 	struct nft_redir *priv = nft_expr_priv(expr);
-	struct nf_nat_ipv4_multi_range_compat mr;
+	struct nf_nat_range2 range;
 
-	memset(&mr, 0, sizeof(mr));
+	memset(&range, 0, sizeof(range));
 	if (priv->sreg_proto_min) {
-		mr.range[0].min.all = (__force __be16)nft_reg_load16(
+		range.min_proto.all = (__force __be16)nft_reg_load16(
 			&regs->data[priv->sreg_proto_min]);
-		mr.range[0].max.all = (__force __be16)nft_reg_load16(
+		range.max_proto.all = (__force __be16)nft_reg_load16(
 			&regs->data[priv->sreg_proto_max]);
-		mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
 	}
 
-	mr.range[0].flags |= priv->flags;
+	range.flags |= priv->flags;
 
-	regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));
+	regs->verdict.code =
+		nf_nat_redirect_ipv4(pkt->skb, &range, nft_hook(pkt));
 }
 
 static void
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c
index 353ca7801251..ff66b56a3f97 100644
--- a/net/netfilter/xt_REDIRECT.c
+++ b/net/netfilter/xt_REDIRECT.c
@@ -46,7 +46,6 @@ static void redirect_tg_destroy(const struct xt_tgdtor_param *par)
 	nf_ct_netns_put(par->net, par->family);
 }
 
-/* FIXME: Take multiple ranges --RR */
 static int redirect_tg4_check(const struct xt_tgchk_param *par)
 {
 	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
@@ -65,7 +64,14 @@ static int redirect_tg4_check(const struct xt_tgchk_param *par)
 static unsigned int
 redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	return nf_nat_redirect_ipv4(skb, par->targinfo, xt_hooknum(par));
+	const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
+	struct nf_nat_range2 range = {
+		.flags       = mr->range[0].flags,
+		.min_proto   = mr->range[0].min,
+		.max_proto   = mr->range[0].max,
+	};
+
+	return nf_nat_redirect_ipv4(skb, &range, xt_hooknum(par));
 }
 
 static struct xt_target redirect_tg_reg[] __read_mostly = {
-- 
2.39.2


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

* [PATCH nf-next 11/13] netfilter: nft_redir: correct length for loading protocol registers
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (9 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-05 12:18 ` [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs Jeremy Sowden
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

The values in the protocol registers are two bytes wide.  However, when
parsing the register loads, the code currently uses the larger 16-byte
size of a `union nf_inet_addr`.  Change it to use the (correct) size of
a `union nf_conntrack_man_proto` instead.

Fixes: d07db9884a5f ("netfilter: nf_tables: introduce nft_validate_register_load()")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_redir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 2f300e0eec32..32a74576fd22 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -48,7 +48,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
 	unsigned int plen;
 	int err;
 
-	plen = sizeof_field(struct nf_nat_range, min_addr.all);
+	plen = sizeof_field(struct nf_nat_range, min_proto.all);
 	if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
 		err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
 					      &priv->sreg_proto_min, plen);
-- 
2.39.2


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

* [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (10 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 11/13] netfilter: nft_redir: correct length for loading protocol registers Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-07 12:37   ` Florian Westphal
  2023-03-05 12:18 ` [PATCH nf-next 13/13] netfilter: nft_redir: add support for shifted port-ranges Jeremy Sowden
  2023-03-07 12:46 ` [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Florian Westphal
  13 siblings, 1 reply; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

nft_redir has separate ipv4 and ipv6 call-backs which share much of
their code, and an inet one switch containing a switch that calls one of
the others based on the family of the packet.  Merge the ipv4 and ipv6
ones into the inet one in order to get rid of the duplicate code.

Const-qualify the `priv` pointer since we don't need to write through
it.

Set the `NF_NAT_RANGE_PROTO_SPECIFIED` flag once during init, rather
than on every eval.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 net/netfilter/nft_redir.c | 78 ++++++++++++++-------------------------
 1 file changed, 28 insertions(+), 50 deletions(-)

diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 32a74576fd22..24f14771f9ab 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -64,6 +64,8 @@ static int nft_redir_init(const struct nft_ctx *ctx,
 		} else {
 			priv->sreg_proto_max = priv->sreg_proto_min;
 		}
+
+		priv->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
 	}
 
 	if (tb[NFTA_REDIR_FLAGS]) {
@@ -99,26 +101,38 @@ static int nft_redir_dump(struct sk_buff *skb,
 	return -1;
 }
 
-static void nft_redir_ipv4_eval(const struct nft_expr *expr,
-				struct nft_regs *regs,
-				const struct nft_pktinfo *pkt)
+static void nft_redir_eval(const struct nft_expr *expr,
+			   struct nft_regs *regs,
+			   const struct nft_pktinfo *pkt)
 {
-	struct nft_redir *priv = nft_expr_priv(expr);
+	const struct nft_redir *priv = nft_expr_priv(expr);
 	struct nf_nat_range2 range;
 
 	memset(&range, 0, sizeof(range));
 	if (priv->sreg_proto_min) {
-		range.min_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_min]);
-		range.max_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_max]);
-		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+		range.min_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
+		range.max_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
 	}
 
 	range.flags |= priv->flags;
 
-	regs->verdict.code =
-		nf_nat_redirect_ipv4(pkt->skb, &range, nft_hook(pkt));
+	switch (nft_pf(pkt)) {
+	case NFPROTO_IPV4:
+		regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &range,
+							  nft_hook(pkt));
+		break;
+#ifdef CONFIG_NF_TABLES_IPV6
+	case NFPROTO_IPV6:
+		regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range,
+							  nft_hook(pkt));
+		break;
+#endif
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
 }
 
 static void
@@ -131,7 +145,7 @@ static struct nft_expr_type nft_redir_ipv4_type;
 static const struct nft_expr_ops nft_redir_ipv4_ops = {
 	.type		= &nft_redir_ipv4_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_redir)),
-	.eval		= nft_redir_ipv4_eval,
+	.eval		= nft_redir_eval,
 	.init		= nft_redir_init,
 	.destroy	= nft_redir_ipv4_destroy,
 	.dump		= nft_redir_dump,
@@ -149,28 +163,6 @@ static struct nft_expr_type nft_redir_ipv4_type __read_mostly = {
 };
 
 #ifdef CONFIG_NF_TABLES_IPV6
-static void nft_redir_ipv6_eval(const struct nft_expr *expr,
-				struct nft_regs *regs,
-				const struct nft_pktinfo *pkt)
-{
-	struct nft_redir *priv = nft_expr_priv(expr);
-	struct nf_nat_range2 range;
-
-	memset(&range, 0, sizeof(range));
-	if (priv->sreg_proto_min) {
-		range.min_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_min]);
-		range.max_proto.all = (__force __be16)nft_reg_load16(
-			&regs->data[priv->sreg_proto_max]);
-		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-	}
-
-	range.flags |= priv->flags;
-
-	regs->verdict.code =
-		nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));
-}
-
 static void
 nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -181,7 +173,7 @@ static struct nft_expr_type nft_redir_ipv6_type;
 static const struct nft_expr_ops nft_redir_ipv6_ops = {
 	.type		= &nft_redir_ipv6_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_redir)),
-	.eval		= nft_redir_ipv6_eval,
+	.eval		= nft_redir_eval,
 	.init		= nft_redir_init,
 	.destroy	= nft_redir_ipv6_destroy,
 	.dump		= nft_redir_dump,
@@ -200,20 +192,6 @@ static struct nft_expr_type nft_redir_ipv6_type __read_mostly = {
 #endif
 
 #ifdef CONFIG_NF_TABLES_INET
-static void nft_redir_inet_eval(const struct nft_expr *expr,
-				struct nft_regs *regs,
-				const struct nft_pktinfo *pkt)
-{
-	switch (nft_pf(pkt)) {
-	case NFPROTO_IPV4:
-		return nft_redir_ipv4_eval(expr, regs, pkt);
-	case NFPROTO_IPV6:
-		return nft_redir_ipv6_eval(expr, regs, pkt);
-	}
-
-	WARN_ON_ONCE(1);
-}
-
 static void
 nft_redir_inet_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -224,7 +202,7 @@ static struct nft_expr_type nft_redir_inet_type;
 static const struct nft_expr_ops nft_redir_inet_ops = {
 	.type		= &nft_redir_inet_type,
 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_redir)),
-	.eval		= nft_redir_inet_eval,
+	.eval		= nft_redir_eval,
 	.init		= nft_redir_init,
 	.destroy	= nft_redir_inet_destroy,
 	.dump		= nft_redir_dump,
-- 
2.39.2


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

* [PATCH nf-next 13/13] netfilter: nft_redir: add support for shifted port-ranges
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (11 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs Jeremy Sowden
@ 2023-03-05 12:18 ` Jeremy Sowden
  2023-03-07 12:46 ` [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Florian Westphal
  13 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-05 12:18 UTC (permalink / raw)
  To: Netfilter Devel

Support was recently added to nft_nat to allow shifting port-ranges
during NAT.  Extend this support to allow them to used in redirecting
as well.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nf_nat_redirect.c          |  1 +
 net/netfilter/nft_redir.c                | 19 ++++++++++++++++++-
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index bab3e3c6de74..7249b67acd67 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1488,12 +1488,14 @@ enum nft_masq_attributes {
  * @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
  * @NFTA_REDIR_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
  * @NFTA_REDIR_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
+ * @NFTA_REDIR_REG_PROTO_BASE: source register of proto range base offset (NLA_U32: nft_registers)
  */
 enum nft_redir_attributes {
 	NFTA_REDIR_UNSPEC,
 	NFTA_REDIR_REG_PROTO_MIN,
 	NFTA_REDIR_REG_PROTO_MAX,
 	NFTA_REDIR_FLAGS,
+	NFTA_REDIR_REG_PROTO_BASE,
 	__NFTA_REDIR_MAX
 };
 #define NFTA_REDIR_MAX		(__NFTA_REDIR_MAX - 1)
diff --git a/net/netfilter/nf_nat_redirect.c b/net/netfilter/nf_nat_redirect.c
index 54ce8e6113ed..5641078da2cb 100644
--- a/net/netfilter/nf_nat_redirect.c
+++ b/net/netfilter/nf_nat_redirect.c
@@ -41,6 +41,7 @@ nf_nat_redirect(struct sk_buff *skb, const struct nf_nat_range2 *range,
 	newrange.max_addr	= *newdst;
 	newrange.min_proto	= range->min_proto;
 	newrange.max_proto	= range->max_proto;
+	newrange.base_proto	= range->base_proto;
 
 	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
 }
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 24f14771f9ab..ff62691cc2e5 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -16,12 +16,14 @@
 struct nft_redir {
 	u8			sreg_proto_min;
 	u8			sreg_proto_max;
+	u8			sreg_proto_base;
 	u16			flags;
 };
 
 static const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = {
 	[NFTA_REDIR_REG_PROTO_MIN]	= { .type = NLA_U32 },
 	[NFTA_REDIR_REG_PROTO_MAX]	= { .type = NLA_U32 },
+	[NFTA_REDIR_REG_PROTO_BASE]	= { .type = NLA_U32 },
 	[NFTA_REDIR_FLAGS]		= { .type = NLA_U32 },
 };
 
@@ -48,7 +50,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
 	unsigned int plen;
 	int err;
 
-	plen = sizeof_field(struct nf_nat_range, min_proto.all);
+	plen = sizeof_field(struct nf_nat_range2, min_proto.all);
 	if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
 		err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
 					      &priv->sreg_proto_min, plen);
@@ -61,6 +63,16 @@ static int nft_redir_init(const struct nft_ctx *ctx,
 						      plen);
 			if (err < 0)
 				return err;
+
+			if (tb[NFTA_REDIR_REG_PROTO_BASE]) {
+				err = nft_parse_register_load
+					(tb[NFTA_REDIR_REG_PROTO_BASE],
+					 &priv->sreg_proto_base, plen);
+				if (err < 0)
+					return err;
+
+				priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;
+			}
 		} else {
 			priv->sreg_proto_max = priv->sreg_proto_min;
 		}
@@ -89,6 +101,9 @@ static int nft_redir_dump(struct sk_buff *skb,
 		if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MAX,
 				      priv->sreg_proto_max))
 			goto nla_put_failure;
+		if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_BASE,
+				      priv->sreg_proto_base))
+			goto nla_put_failure;
 	}
 
 	if (priv->flags != 0 &&
@@ -114,6 +129,8 @@ static void nft_redir_eval(const struct nft_expr *expr,
 			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
 		range.max_proto.all = (__force __be16)
 			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
+		range.base_proto.all = (__force __be16)
+			nft_reg_load16(&regs->data[priv->sreg_proto_base]);
 	}
 
 	range.flags |= priv->flags;
-- 
2.39.2


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

* Re: [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges
  2023-03-05 12:18 ` [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges Jeremy Sowden
@ 2023-03-07 12:27   ` Florian Westphal
  2023-03-07 18:42     ` Jeremy Sowden
  0 siblings, 1 reply; 21+ messages in thread
From: Florian Westphal @ 2023-03-07 12:27 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Netfilter Devel

Jeremy Sowden <jeremy@azazel.net> wrote:
> index 5c29915ab028..0517a3efb259 100644
> --- a/net/netfilter/nft_nat.c
> +++ b/net/netfilter/nft_nat.c
> @@ -25,6 +25,7 @@ struct nft_nat {
>  	u8			sreg_addr_max;
>  	u8			sreg_proto_min;
>  	u8			sreg_proto_max;
> +	u8			sreg_proto_base;
>  	enum nf_nat_manip_type  type:8;
>  	u8			family;
>  	u16			flags;
> @@ -58,6 +59,8 @@ static void nft_nat_setup_proto(struct nf_nat_range2 *range,
>  		nft_reg_load16(&regs->data[priv->sreg_proto_min]);
>  	range->max_proto.all = (__force __be16)
>  		nft_reg_load16(&regs->data[priv->sreg_proto_max]);
> +	range->base_proto.all = (__force __be16)
> +		nft_reg_load16(&regs->data[priv->sreg_proto_base]);

Hmmm!  See below.

> -	plen = sizeof_field(struct nf_nat_range, min_proto.all);
> +	plen = sizeof_field(struct nf_nat_range2, min_proto.all);
>  	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
>  		err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
>  					      &priv->sreg_proto_min, plen);
> @@ -239,6 +243,16 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
>  						      plen);
>  			if (err < 0)
>  				return err;
> +
> +			if (tb[NFTA_NAT_REG_PROTO_BASE]) {
> +				err = nft_parse_register_load
> +					(tb[NFTA_NAT_REG_PROTO_BASE],
> +					 &priv->sreg_proto_base, plen);
> +				if (err < 0)
> +					return err;
> +
> +				priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;

So sreg_proto_base is only set if tb[NFTA_NAT_REG_PROTO_BASE] gets
passed.

So, I would expect that all accesses to priv->sreg_proto_base are
guarded with a 'if (priv->sreg_proto_base)' check.

> @@ -286,7 +300,9 @@ static int nft_nat_dump(struct sk_buff *skb,
>  		if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN,
>  				      priv->sreg_proto_min) ||
>  		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX,
> -				      priv->sreg_proto_max))
> +				      priv->sreg_proto_max) ||
> +		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_BASE,
> +				      priv->sreg_proto_base))

sreg_proto_min/max are only dumped when set, so NFTA_NAT_REG_PROTO_BASE
should not be dumped unconditionally either?

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

* Re: [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API
  2023-03-05 12:18 ` [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API Jeremy Sowden
@ 2023-03-07 12:35   ` Florian Westphal
  0 siblings, 0 replies; 21+ messages in thread
From: Florian Westphal @ 2023-03-07 12:35 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Netfilter Devel

Jeremy Sowden <jeremy@azazel.net> wrote:
> `nf_nat_redirect_ipv4` takes a `struct nf_nat_ipv4_multi_range_compat`,
> but converts it internally to a `struct nf_nat_range2`.  Change the
> function to take the latter, factor out the code now shared with
> `nf_nat_redirect_ipv6`, move the conversion to the xt_REDIRECT module,
> and update the ipv4 range initialization in the nft_redir module.

Reviewed-by: Florian Westphal <fw@strlen.de>

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

* Re: [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs
  2023-03-05 12:18 ` [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs Jeremy Sowden
@ 2023-03-07 12:37   ` Florian Westphal
  2023-03-07 18:42     ` Jeremy Sowden
  0 siblings, 1 reply; 21+ messages in thread
From: Florian Westphal @ 2023-03-07 12:37 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Netfilter Devel

Jeremy Sowden <jeremy@azazel.net> wrote:
> nft_redir has separate ipv4 and ipv6 call-backs which share much of
> their code, and an inet one switch containing a switch that calls one of
> the others based on the family of the packet.  Merge the ipv4 and ipv6
> ones into the inet one in order to get rid of the duplicate code.
> 
> Const-qualify the `priv` pointer since we don't need to write through
> it.
> 
> Set the `NF_NAT_RANGE_PROTO_SPECIFIED` flag once during init, rather
> than on every eval.

Reviewed-by: Florian Westphal <fw@strlen.de>

> -	struct nft_redir *priv = nft_expr_priv(expr);
> +	const struct nft_redir *priv = nft_expr_priv(expr);
>  	struct nf_nat_range2 range;
>  
>  	memset(&range, 0, sizeof(range));
>  	if (priv->sreg_proto_min) {
> -		range.min_proto.all = (__force __be16)nft_reg_load16(
> -			&regs->data[priv->sreg_proto_min]);
> -		range.max_proto.all = (__force __be16)nft_reg_load16(
> -			&regs->data[priv->sreg_proto_max]);
> -		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
> +		range.min_proto.all = (__force __be16)
> +			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
> +		range.max_proto.all = (__force __be16)
> +			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
>  	}
>  
>  	range.flags |= priv->flags;

Nit: This could be updated to 'range.flags = priv->flags'

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

* Re: [PATCH nf-next 00/13] Support for shifted port-ranges in NAT
  2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
                   ` (12 preceding siblings ...)
  2023-03-05 12:18 ` [PATCH nf-next 13/13] netfilter: nft_redir: add support for shifted port-ranges Jeremy Sowden
@ 2023-03-07 12:46 ` Florian Westphal
  2023-03-07 19:35   ` Jeremy Sowden
  13 siblings, 1 reply; 21+ messages in thread
From: Florian Westphal @ 2023-03-07 12:46 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Netfilter Devel

Jeremy Sowden <jeremy@azazel.net> wrote:
> Jeremy Sowden (13):
>   netfilter: nft_nat: correct length for loading protocol registers
>   netfilter: nft_masq: correct length for loading protocol registers
>   netfilter: nft_redir: correct value of inet type `.maxattrs`
>   netfilter: nft_redir: correct length for loading protocol registers

I think the fixess above should be routed through the 'nf' tree, I
don't see why we need to hold them in -next trees for another 3 months.


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

* Re: [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges
  2023-03-07 12:27   ` Florian Westphal
@ 2023-03-07 18:42     ` Jeremy Sowden
  0 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-07 18:42 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Netfilter Devel

[-- Attachment #1: Type: text/plain, Size: 2359 bytes --]

On 2023-03-07, at 13:27:51 +0100, Florian Westphal wrote:
> Jeremy Sowden <jeremy@azazel.net> wrote:
> > index 5c29915ab028..0517a3efb259 100644
> > --- a/net/netfilter/nft_nat.c
> > +++ b/net/netfilter/nft_nat.c
> > @@ -25,6 +25,7 @@ struct nft_nat {
> >  	u8			sreg_addr_max;
> >  	u8			sreg_proto_min;
> >  	u8			sreg_proto_max;
> > +	u8			sreg_proto_base;
> >  	enum nf_nat_manip_type  type:8;
> >  	u8			family;
> >  	u16			flags;
> > @@ -58,6 +59,8 @@ static void nft_nat_setup_proto(struct nf_nat_range2 *range,
> >  		nft_reg_load16(&regs->data[priv->sreg_proto_min]);
> >  	range->max_proto.all = (__force __be16)
> >  		nft_reg_load16(&regs->data[priv->sreg_proto_max]);
> > +	range->base_proto.all = (__force __be16)
> > +		nft_reg_load16(&regs->data[priv->sreg_proto_base]);
> 
> Hmmm!  See below.
> 
> > -	plen = sizeof_field(struct nf_nat_range, min_proto.all);
> > +	plen = sizeof_field(struct nf_nat_range2, min_proto.all);
> >  	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
> >  		err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
> >  					      &priv->sreg_proto_min, plen);
> > @@ -239,6 +243,16 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
> >  						      plen);
> >  			if (err < 0)
> >  				return err;
> > +
> > +			if (tb[NFTA_NAT_REG_PROTO_BASE]) {
> > +				err = nft_parse_register_load
> > +					(tb[NFTA_NAT_REG_PROTO_BASE],
> > +					 &priv->sreg_proto_base, plen);
> > +				if (err < 0)
> > +					return err;
> > +
> > +				priv->flags |= NF_NAT_RANGE_PROTO_OFFSET;
> 
> So sreg_proto_base is only set if tb[NFTA_NAT_REG_PROTO_BASE] gets
> passed.
> 
> So, I would expect that all accesses to priv->sreg_proto_base are
> guarded with a 'if (priv->sreg_proto_base)' check.
> 
> > @@ -286,7 +300,9 @@ static int nft_nat_dump(struct sk_buff *skb,
> >  		if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN,
> >  				      priv->sreg_proto_min) ||
> >  		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX,
> > -				      priv->sreg_proto_max))
> > +				      priv->sreg_proto_max) ||
> > +		    nft_dump_register(skb, NFTA_NAT_REG_PROTO_BASE,
> > +				      priv->sreg_proto_base))
> 
> sreg_proto_min/max are only dumped when set, so NFTA_NAT_REG_PROTO_BASE
> should not be dumped unconditionally either?
> 

Agreed.  Will fix.

J.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs
  2023-03-07 12:37   ` Florian Westphal
@ 2023-03-07 18:42     ` Jeremy Sowden
  0 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-07 18:42 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Netfilter Devel

[-- Attachment #1: Type: text/plain, Size: 1498 bytes --]

On 2023-03-07, at 13:37:40 +0100, Florian Westphal wrote:
> Jeremy Sowden <jeremy@azazel.net> wrote:
> > nft_redir has separate ipv4 and ipv6 call-backs which share much of
> > their code, and an inet one switch containing a switch that calls one of
> > the others based on the family of the packet.  Merge the ipv4 and ipv6
> > ones into the inet one in order to get rid of the duplicate code.
> > 
> > Const-qualify the `priv` pointer since we don't need to write through
> > it.
> > 
> > Set the `NF_NAT_RANGE_PROTO_SPECIFIED` flag once during init, rather
> > than on every eval.
> 
> Reviewed-by: Florian Westphal <fw@strlen.de>
> 
> > -	struct nft_redir *priv = nft_expr_priv(expr);
> > +	const struct nft_redir *priv = nft_expr_priv(expr);
> >  	struct nf_nat_range2 range;
> >  
> >  	memset(&range, 0, sizeof(range));
> >  	if (priv->sreg_proto_min) {
> > -		range.min_proto.all = (__force __be16)nft_reg_load16(
> > -			&regs->data[priv->sreg_proto_min]);
> > -		range.max_proto.all = (__force __be16)nft_reg_load16(
> > -			&regs->data[priv->sreg_proto_max]);
> > -		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
> > +		range.min_proto.all = (__force __be16)
> > +			nft_reg_load16(&regs->data[priv->sreg_proto_min]);
> > +		range.max_proto.all = (__force __be16)
> > +			nft_reg_load16(&regs->data[priv->sreg_proto_max]);
> >  	}
> >  
> >  	range.flags |= priv->flags;
> 
> Nit: This could be updated to 'range.flags = priv->flags'

Will fix.

J.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH nf-next 00/13] Support for shifted port-ranges in NAT
  2023-03-07 12:46 ` [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Florian Westphal
@ 2023-03-07 19:35   ` Jeremy Sowden
  0 siblings, 0 replies; 21+ messages in thread
From: Jeremy Sowden @ 2023-03-07 19:35 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Netfilter Devel

[-- Attachment #1: Type: text/plain, Size: 607 bytes --]

On 2023-03-07, at 13:46:38 +0100, Florian Westphal wrote:
> Jeremy Sowden wrote:
> > Jeremy Sowden (13):
> >   netfilter: nft_nat: correct length for loading protocol registers
> >   netfilter: nft_masq: correct length for loading protocol registers
> >   netfilter: nft_redir: correct value of inet type `.maxattrs`
> >   netfilter: nft_redir: correct length for loading protocol
> >   registers
> 
> I think the fixess above should be routed through the 'nf' tree, I
> don't see why we need to hold them in -next trees for another 3
> months.

When I send v2, I'll separate these out.

J.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2023-03-07 19:45 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-05 12:18 [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 01/13] netfilter: conntrack: fix typo Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 02/13] netfilter: nat: fix indentation of function arguments Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 03/13] netfilter: nat: extend core support for shifted port-ranges Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 04/13] netfilter: nft_nat: correct length for loading protocol registers Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 05/13] netfilter: nft_nat: add support for shifted port-ranges Jeremy Sowden
2023-03-07 12:27   ` Florian Westphal
2023-03-07 18:42     ` Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 06/13] netfilter: nft_masq: correct length for loading protocol registers Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 07/13] netfilter: nft_masq: deduplicate eval call-backs Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 08/13] netfilter: nft_masq: add support for shifted port-ranges Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 09/13] netfilter: nft_redir: correct value of inet type `.maxattrs` Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 10/13] netfilter: nf_nat_redirect: use `struct nf_nat_range2` in ipv4 API Jeremy Sowden
2023-03-07 12:35   ` Florian Westphal
2023-03-05 12:18 ` [PATCH nf-next 11/13] netfilter: nft_redir: correct length for loading protocol registers Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 12/13] netfilter: nft_redir: deduplicate eval call-backs Jeremy Sowden
2023-03-07 12:37   ` Florian Westphal
2023-03-07 18:42     ` Jeremy Sowden
2023-03-05 12:18 ` [PATCH nf-next 13/13] netfilter: nft_redir: add support for shifted port-ranges Jeremy Sowden
2023-03-07 12:46 ` [PATCH nf-next 00/13] Support for shifted port-ranges in NAT Florian Westphal
2023-03-07 19:35   ` Jeremy Sowden

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).