netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute
@ 2014-09-04 12:06 Arturo Borrero Gonzalez
  2014-09-04 12:06 ` [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization Arturo Borrero Gonzalez
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 12:06 UTC (permalink / raw)
  To: netfilter-devel; +Cc: kaber, pablo

Both SNAT and DNAT (and the upcoming masquerade) can have additional
configuration parameters, such as port randomization or NAT addressing
persistence.
We can cover these scenarios by simply adding a flag attribute for
userspace to fill when needed.

The flags to use are defined in include/uapi/linux/netfilter/nf_nat.h,
 NF_NAT_RANGE_MAP_IPS
 NF_NAT_RANGE_PROTO_SPECIFIED
 NF_NAT_RANGE_PROTO_RANDOM
 NF_NAT_RANGE_PERSISTENT
 NF_NAT_RANGE_PROTO_RANDOM_FULLY
 NF_NAT_RANGE_PROTO_RANDOM_ALL

The caller must take care of not messing up with the flags, as they are
added unconditionally to the final resulting nf_nat_range.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
v2: address Florian Westphal's comments: check all flag bits to be known.
v3: style cleanup requested by Pablo Neira. Mask name shortened.
v4: nf-next rebase.

 include/uapi/linux/netfilter/nf_nat.h    |    5 +++++
 include/uapi/linux/netfilter/nf_tables.h |    2 ++
 net/netfilter/nft_nat.c                  |   16 ++++++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h
index 1ad3659..898db2d 100644
--- a/include/uapi/linux/netfilter/nf_nat.h
+++ b/include/uapi/linux/netfilter/nf_nat.h
@@ -13,6 +13,11 @@
 #define NF_NAT_RANGE_PROTO_RANDOM_ALL		\
 	(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
 
+#define NF_NAT_RANGE_MASK					\
+	(NF_NAT_RANGE_MAP_IPS|NF_NAT_RANGE_PROTO_SPECIFIED	\
+	 |NF_NAT_RANGE_PROTO_RANDOM|NF_NAT_RANGE_PERSISTENT	\
+	 |NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+
 struct nf_nat_ipv4_range {
 	unsigned int			flags;
 	__be32				min_ip;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index c000947..62ea48d 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -785,6 +785,7 @@ enum nft_nat_types {
  * @NFTA_NAT_REG_ADDR_MAX: source register of address range end (NLA_U32: nft_registers)
  * @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: additional NAT configuration (NF_NAT_RANGE_*) (NLA_U32)
  */
 enum nft_nat_attributes {
 	NFTA_NAT_UNSPEC,
@@ -794,6 +795,7 @@ enum nft_nat_attributes {
 	NFTA_NAT_REG_ADDR_MAX,
 	NFTA_NAT_REG_PROTO_MIN,
 	NFTA_NAT_REG_PROTO_MAX,
+	NFTA_NAT_FLAGS,
 	__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 79ff58c..799550b 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -33,6 +33,7 @@ struct nft_nat {
 	enum nft_registers      sreg_proto_max:8;
 	enum nf_nat_manip_type  type:8;
 	u8			family;
+	u16			flags;
 };
 
 static void nft_nat_eval(const struct nft_expr *expr,
@@ -71,6 +72,8 @@ static void nft_nat_eval(const struct nft_expr *expr,
 		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
 	}
 
+	range.flags |= priv->flags;
+
 	data[NFT_REG_VERDICT].verdict =
 		nf_nat_setup_info(ct, &range, priv->type);
 }
@@ -82,6 +85,7 @@ static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
 	[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 },
 };
 
 static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
@@ -149,6 +153,12 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	} else
 		priv->sreg_proto_max = priv->sreg_proto_min;
 
+	if (tb[NFTA_NAT_FLAGS]) {
+		priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
+		if (priv->flags & ~NF_NAT_RANGE_MASK)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -183,6 +193,12 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 				 htonl(priv->sreg_proto_max)))
 			goto nla_put_failure;
 	}
+
+	if (priv->flags != 0) {
+		if (nla_put_be32(skb, NFTA_NAT_FLAGS, htonl(priv->flags)))
+			goto nla_put_failure;
+	}
+
 	return 0;
 
 nla_put_failure:


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

* [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization
  2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
@ 2014-09-04 12:06 ` Arturo Borrero Gonzalez
  2014-09-09  9:52   ` Pablo Neira Ayuso
  2014-09-04 12:06 ` [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: " Arturo Borrero Gonzalez
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 12:06 UTC (permalink / raw)
  To: netfilter-devel; +Cc: kaber, pablo

Let's refactor the code so we can reach the masquerade functionality from
outside the xt context (ie, nftables).

The patch includes adding an atomic counter to the masquerade notifier: the
stuff to be done by the notifier is the same in any case, and agnostic
about who called it. Only one notification handler is needed.

This factorization only involves IPv4; a similar patch will follow to handle
IPv6.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
v2: no changes.
v3: no changes.
v4: nf-next rebased.

 .../net/netfilter/ipv4/nf_nat_masquerade_ipv4.h    |   14 ++
 net/ipv4/netfilter/Kconfig                         |    7 +
 net/ipv4/netfilter/Makefile                        |    1 
 net/ipv4/netfilter/ipt_MASQUERADE.c                |  108 +-------------
 net/ipv4/netfilter/nf_nat_masquerade_ipv4.c        |  154 ++++++++++++++++++++
 5 files changed, 185 insertions(+), 99 deletions(-)
 create mode 100644 include/net/netfilter/ipv4/nf_nat_masquerade_ipv4.h
 create mode 100644 net/ipv4/netfilter/nf_nat_masquerade_ipv4.c

diff --git a/include/net/netfilter/ipv4/nf_nat_masquerade_ipv4.h b/include/net/netfilter/ipv4/nf_nat_masquerade_ipv4.h
new file mode 100644
index 0000000..a9c001c
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_nat_masquerade_ipv4.h
@@ -0,0 +1,14 @@
+#ifndef _NF_NAT_MASQUERADE_IPV4_H_
+#define _NF_NAT_MASQUERADE_IPV4_H_
+
+#include <net/netfilter/nf_nat.h>
+
+unsigned int
+nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
+		       const struct nf_nat_range *range,
+		       const struct net_device *out);
+
+void nf_nat_masquerade_ipv4_register_notifier(void);
+void nf_nat_masquerade_ipv4_unregister_notifier(void);
+
+#endif /*_NF_NAT_MASQUERADE_IPV4_H_ */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index fb17312..4be3e54 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -184,8 +184,15 @@ config NF_NAT_IPV4
 
 if NF_NAT_IPV4
 
+config NF_NAT_MASQUERADE_IPV4
+	tristate "IPv4 masquerade support"
+	help
+	This is the kernel functionality to provide NAT in the masquerade
+	flavour (automatic source address selection).
+
 config IP_NF_TARGET_MASQUERADE
 	tristate "MASQUERADE target support"
+	select NF_NAT_MASQUERADE_IPV4
 	default m if NETFILTER_ADVANCED=n
 	help
 	  Masquerading is a special case of NAT: all outgoing connections are
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3300162..42056b2 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o
 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
 obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
 obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
+obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o
 
 # NAT protocols (nf_nat)
 obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 00352ce..78bb32e 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -22,6 +22,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter/x_tables.h>
 #include <net/netfilter/nf_nat.h>
+#include <net/netfilter/ipv4/nf_nat_masquerade_ipv4.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -46,103 +47,17 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par)
 static unsigned int
 masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	struct nf_conn *ct;
-	struct nf_conn_nat *nat;
-	enum ip_conntrack_info ctinfo;
-	struct nf_nat_range newrange;
+	struct nf_nat_range range;
 	const struct nf_nat_ipv4_multi_range_compat *mr;
-	const struct rtable *rt;
-	__be32 newsrc, nh;
-
-	NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
-
-	ct = nf_ct_get(skb, &ctinfo);
-	nat = nfct_nat(ct);
-
-	NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
-			    ctinfo == IP_CT_RELATED_REPLY));
-
-	/* Source address is 0.0.0.0 - locally generated packet that is
-	 * probably not supposed to be masqueraded.
-	 */
-	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
-		return NF_ACCEPT;
 
 	mr = par->targinfo;
-	rt = skb_rtable(skb);
-	nh = rt_nexthop(rt, ip_hdr(skb)->daddr);
-	newsrc = inet_select_addr(par->out, nh, RT_SCOPE_UNIVERSE);
-	if (!newsrc) {
-		pr_info("%s ate my IP address\n", par->out->name);
-		return NF_DROP;
-	}
-
-	nat->masq_index = par->out->ifindex;
-
-	/* 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 = newsrc;
-	newrange.max_addr.ip = newsrc;
-	newrange.min_proto   = mr->range[0].min;
-	newrange.max_proto   = mr->range[0].max;
+	range.flags = mr->range[0].flags;
+	range.min_proto = mr->range[0].min;
+	range.max_proto = mr->range[0].max;
 
-	/* Hand modified range to generic setup. */
-	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
+	return nf_nat_masquerade_ipv4(skb, par->hooknum, &range, par->out);
 }
 
-static int
-device_cmp(struct nf_conn *i, void *ifindex)
-{
-	const struct nf_conn_nat *nat = nfct_nat(i);
-
-	if (!nat)
-		return 0;
-	if (nf_ct_l3num(i) != NFPROTO_IPV4)
-		return 0;
-	return nat->masq_index == (int)(long)ifindex;
-}
-
-static int masq_device_event(struct notifier_block *this,
-			     unsigned long event,
-			     void *ptr)
-{
-	const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct net *net = dev_net(dev);
-
-	if (event == NETDEV_DOWN) {
-		/* Device was downed.  Search entire table for
-		   conntracks which were associated with that device,
-		   and forget them. */
-		NF_CT_ASSERT(dev->ifindex != 0);
-
-		nf_ct_iterate_cleanup(net, device_cmp,
-				      (void *)(long)dev->ifindex, 0, 0);
-	}
-
-	return NOTIFY_DONE;
-}
-
-static int masq_inet_event(struct notifier_block *this,
-			   unsigned long event,
-			   void *ptr)
-{
-	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
-	struct netdev_notifier_info info;
-
-	netdev_notifier_info_init(&info, dev);
-	return masq_device_event(this, event, &info);
-}
-
-static struct notifier_block masq_dev_notifier = {
-	.notifier_call	= masq_device_event,
-};
-
-static struct notifier_block masq_inet_notifier = {
-	.notifier_call	= masq_inet_event,
-};
-
 static struct xt_target masquerade_tg_reg __read_mostly = {
 	.name		= "MASQUERADE",
 	.family		= NFPROTO_IPV4,
@@ -160,12 +75,8 @@ static int __init masquerade_tg_init(void)
 
 	ret = xt_register_target(&masquerade_tg_reg);
 
-	if (ret == 0) {
-		/* Register for device down reports */
-		register_netdevice_notifier(&masq_dev_notifier);
-		/* Register IP address change reports */
-		register_inetaddr_notifier(&masq_inet_notifier);
-	}
+	if (ret == 0)
+		nf_nat_masquerade_ipv4_register_notifier();
 
 	return ret;
 }
@@ -173,8 +84,7 @@ static int __init masquerade_tg_init(void)
 static void __exit masquerade_tg_exit(void)
 {
 	xt_unregister_target(&masquerade_tg_reg);
-	unregister_netdevice_notifier(&masq_dev_notifier);
-	unregister_inetaddr_notifier(&masq_inet_notifier);
+	nf_nat_masquerade_ipv4_unregister_notifier();
 }
 
 module_init(masquerade_tg_init);
diff --git a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
new file mode 100644
index 0000000..c381f56
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
@@ -0,0 +1,154 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/inetdevice.h>
+#include <linux/ip.h>
+#include <linux/timer.h>
+#include <linux/netfilter.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/checksum.h>
+#include <net/route.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/x_tables.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/ipv4/nf_nat_masquerade_ipv4.h>
+
+unsigned int
+nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
+		       const struct nf_nat_range *range,
+		       const struct net_device *out)
+{
+	struct nf_conn *ct;
+	struct nf_conn_nat *nat;
+	enum ip_conntrack_info ctinfo;
+	struct nf_nat_range newrange;
+	const struct rtable *rt;
+	__be32 newsrc, nh;
+
+	NF_CT_ASSERT(hooknum == NF_INET_POST_ROUTING);
+
+	ct = nf_ct_get(skb, &ctinfo);
+	nat = nfct_nat(ct);
+
+	NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
+			    ctinfo == IP_CT_RELATED_REPLY));
+
+	/* Source address is 0.0.0.0 - locally generated packet that is
+	 * probably not supposed to be masqueraded.
+	 */
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
+		return NF_ACCEPT;
+
+	rt = skb_rtable(skb);
+	nh = rt_nexthop(rt, ip_hdr(skb)->daddr);
+	newsrc = inet_select_addr(out, nh, RT_SCOPE_UNIVERSE);
+	if (!newsrc) {
+		pr_info("%s ate my IP address\n", out->name);
+		return NF_DROP;
+	}
+
+	nat->masq_index = out->ifindex;
+
+	/* Transfer from original range. */
+	memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
+	memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
+	newrange.flags       = range->flags | NF_NAT_RANGE_MAP_IPS;
+	newrange.min_addr.ip = newsrc;
+	newrange.max_addr.ip = newsrc;
+	newrange.min_proto   = range->min_proto;
+	newrange.max_proto   = range->max_proto;
+
+	/* Hand modified range to generic setup. */
+	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4);
+
+static int
+device_cmp(struct nf_conn *i, void *ifindex)
+{
+	const struct nf_conn_nat *nat = nfct_nat(i);
+
+	if (!nat)
+		return 0;
+	if (nf_ct_l3num(i) != NFPROTO_IPV4)
+		return 0;
+	return nat->masq_index == (int)(long)ifindex;
+}
+
+static int masq_device_event(struct notifier_block *this,
+			     unsigned long event,
+			     void *ptr)
+{
+	const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct net *net = dev_net(dev);
+
+	if (event == NETDEV_DOWN) {
+		/* Device was downed.  Search entire table for
+		 * conntracks which were associated with that device,
+		 * and forget them.
+		 */
+		NF_CT_ASSERT(dev->ifindex != 0);
+
+		nf_ct_iterate_cleanup(net, device_cmp,
+				      (void *)(long)dev->ifindex, 0, 0);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int masq_inet_event(struct notifier_block *this,
+			   unsigned long event,
+			   void *ptr)
+{
+	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+	struct netdev_notifier_info info;
+
+	netdev_notifier_info_init(&info, dev);
+	return masq_device_event(this, event, &info);
+}
+
+static struct notifier_block masq_dev_notifier = {
+	.notifier_call	= masq_device_event,
+};
+
+static struct notifier_block masq_inet_notifier = {
+	.notifier_call	= masq_inet_event,
+};
+
+static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0);
+
+void nf_nat_masquerade_ipv4_register_notifier(void)
+{
+	/* check if the notifier was already set */
+	if (atomic_inc_return(&masquerade_notifier_refcount) > 1)
+		return;
+
+	/* Register for device down reports */
+	register_netdevice_notifier(&masq_dev_notifier);
+	/* Register IP address change reports */
+	register_inetaddr_notifier(&masq_inet_notifier);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_register_notifier);
+
+void nf_nat_masquerade_ipv4_unregister_notifier(void)
+{
+	/* check if the notifier still has clients */
+	if (atomic_dec_return(&masquerade_notifier_refcount) > 0)
+		return;
+
+	unregister_netdevice_notifier(&masq_dev_notifier);
+	unregister_inetaddr_notifier(&masq_inet_notifier);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_unregister_notifier);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");


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

* [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: code factorization
  2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
  2014-09-04 12:06 ` [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization Arturo Borrero Gonzalez
@ 2014-09-04 12:06 ` Arturo Borrero Gonzalez
  2014-09-09  9:52   ` Pablo Neira Ayuso
  2014-09-04 12:07 ` [nf_tables PATCH v4 4/5] netfilter: nft_nat: split code in AF parts Arturo Borrero Gonzalez
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 12:06 UTC (permalink / raw)
  To: netfilter-devel; +Cc: kaber, pablo

Let's refactor the code so we can reach the masquerade functionality from
outside the xt context (ie, nftables).

The patch includes adding an atomic counter to the masquerade notifier: the
stuff to be done by the notifier is the same in any case, and agnostic
about who called it. Only one notification handler is needed.

This factorization only involves IPv6; a similar patch exists to handle IPv4.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
v2: no changes.
v3: no changes.
v4: nf-next rebased.

 .../net/netfilter/ipv6/nf_nat_masquerade_ipv6.h    |   10 ++
 net/ipv6/netfilter/Kconfig                         |    7 +
 net/ipv6/netfilter/Makefile                        |    1 
 net/ipv6/netfilter/ip6t_MASQUERADE.c               |   76 +------------
 net/ipv6/netfilter/nf_nat_masquerade_ipv6.c        |  120 ++++++++++++++++++++
 5 files changed, 143 insertions(+), 71 deletions(-)
 create mode 100644 include/net/netfilter/ipv6/nf_nat_masquerade_ipv6.h
 create mode 100644 net/ipv6/netfilter/nf_nat_masquerade_ipv6.c

diff --git a/include/net/netfilter/ipv6/nf_nat_masquerade_ipv6.h b/include/net/netfilter/ipv6/nf_nat_masquerade_ipv6.h
new file mode 100644
index 0000000..0a13396
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_nat_masquerade_ipv6.h
@@ -0,0 +1,10 @@
+#ifndef _NF_NAT_MASQUERADE_IPV6_H_
+#define _NF_NAT_MASQUERADE_IPV6_H_
+
+unsigned int
+nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
+		       const struct net_device *out);
+void nf_nat_masquerade_ipv6_register_notifier(void);
+void nf_nat_masquerade_ipv6_unregister_notifier(void);
+
+#endif /* _NF_NAT_MASQUERADE_IPV6_H_ */
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index ac93df1..6c8cfec 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -246,8 +246,15 @@ config NF_NAT_IPV6
 
 if NF_NAT_IPV6
 
+config NF_NAT_MASQUERADE_IPV6
+	tristate "IPv6 masquerade support"
+	help
+	 This is the kernel functionality to provide NAT in the masquerade
+	 flavour (automatic source address selection) for IPv6.
+
 config IP6_NF_TARGET_MASQUERADE
 	tristate "MASQUERADE target support"
+	select NF_NAT_MASQUERADE_IPV6
 	help
 	  Masquerading is a special case of NAT: all outgoing connections are
 	  changed to seem to come from a particular interface's address, and
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index c0b2631..89a0bd7 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
 
 nf_nat_ipv6-y		:= nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o
 obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
+obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o
 
 # defrag
 nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c
index 3e4e92d..c37501b 100644
--- a/net/ipv6/netfilter/ip6t_MASQUERADE.c
+++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c
@@ -19,33 +19,12 @@
 #include <net/netfilter/nf_nat.h>
 #include <net/addrconf.h>
 #include <net/ipv6.h>
+#include <net/netfilter/ipv6/nf_nat_masquerade_ipv6.h>
 
 static unsigned int
 masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	const struct nf_nat_range *range = par->targinfo;
-	enum ip_conntrack_info ctinfo;
-	struct in6_addr src;
-	struct nf_conn *ct;
-	struct nf_nat_range newrange;
-
-	ct = nf_ct_get(skb, &ctinfo);
-	NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
-			    ctinfo == IP_CT_RELATED_REPLY));
-
-	if (ipv6_dev_get_saddr(dev_net(par->out), par->out,
-			       &ipv6_hdr(skb)->daddr, 0, &src) < 0)
-		return NF_DROP;
-
-	nfct_nat(ct)->masq_index = par->out->ifindex;
-
-	newrange.flags		= range->flags | NF_NAT_RANGE_MAP_IPS;
-	newrange.min_addr.in6	= src;
-	newrange.max_addr.in6	= src;
-	newrange.min_proto	= range->min_proto;
-	newrange.max_proto	= range->max_proto;
-
-	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
+	return nf_nat_masquerade_ipv6(skb, par->targinfo, par->out);
 }
 
 static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -57,48 +36,6 @@ static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
 	return 0;
 }
 
-static int device_cmp(struct nf_conn *ct, void *ifindex)
-{
-	const struct nf_conn_nat *nat = nfct_nat(ct);
-
-	if (!nat)
-		return 0;
-	if (nf_ct_l3num(ct) != NFPROTO_IPV6)
-		return 0;
-	return nat->masq_index == (int)(long)ifindex;
-}
-
-static int masq_device_event(struct notifier_block *this,
-			     unsigned long event, void *ptr)
-{
-	const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-	struct net *net = dev_net(dev);
-
-	if (event == NETDEV_DOWN)
-		nf_ct_iterate_cleanup(net, device_cmp,
-				      (void *)(long)dev->ifindex, 0, 0);
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block masq_dev_notifier = {
-	.notifier_call	= masq_device_event,
-};
-
-static int masq_inet_event(struct notifier_block *this,
-			   unsigned long event, void *ptr)
-{
-	struct inet6_ifaddr *ifa = ptr;
-	struct netdev_notifier_info info;
-
-	netdev_notifier_info_init(&info, ifa->idev->dev);
-	return masq_device_event(this, event, &info);
-}
-
-static struct notifier_block masq_inet_notifier = {
-	.notifier_call	= masq_inet_event,
-};
-
 static struct xt_target masquerade_tg6_reg __read_mostly = {
 	.name		= "MASQUERADE",
 	.family		= NFPROTO_IPV6,
@@ -115,17 +52,14 @@ static int __init masquerade_tg6_init(void)
 	int err;
 
 	err = xt_register_target(&masquerade_tg6_reg);
-	if (err == 0) {
-		register_netdevice_notifier(&masq_dev_notifier);
-		register_inet6addr_notifier(&masq_inet_notifier);
-	}
+	if (err == 0)
+		nf_nat_masquerade_ipv6_register_notifier();
 
 	return err;
 }
 static void __exit masquerade_tg6_exit(void)
 {
-	unregister_inet6addr_notifier(&masq_inet_notifier);
-	unregister_netdevice_notifier(&masq_dev_notifier);
+	nf_nat_masquerade_ipv6_unregister_notifier();
 	xt_unregister_target(&masquerade_tg6_reg);
 }
 
diff --git a/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
new file mode 100644
index 0000000..a798123
--- /dev/null
+++ b/net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6
+ * NAT funded by Astaro.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/addrconf.h>
+#include <net/ipv6.h>
+#include <net/netfilter/ipv6/nf_nat_masquerade_ipv6.h>
+
+unsigned int
+nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
+		       const struct net_device *out)
+{
+	enum ip_conntrack_info ctinfo;
+	struct in6_addr src;
+	struct nf_conn *ct;
+	struct nf_nat_range newrange;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
+			    ctinfo == IP_CT_RELATED_REPLY));
+
+	if (ipv6_dev_get_saddr(dev_net(out), out,
+			       &ipv6_hdr(skb)->daddr, 0, &src) < 0)
+		return NF_DROP;
+
+	nfct_nat(ct)->masq_index = out->ifindex;
+
+	newrange.flags		= range->flags | NF_NAT_RANGE_MAP_IPS;
+	newrange.min_addr.in6	= src;
+	newrange.max_addr.in6	= src;
+	newrange.min_proto	= range->min_proto;
+	newrange.max_proto	= range->max_proto;
+
+	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6);
+
+static int device_cmp(struct nf_conn *ct, void *ifindex)
+{
+	const struct nf_conn_nat *nat = nfct_nat(ct);
+
+	if (!nat)
+		return 0;
+	if (nf_ct_l3num(ct) != NFPROTO_IPV6)
+		return 0;
+	return nat->masq_index == (int)(long)ifindex;
+}
+
+static int masq_device_event(struct notifier_block *this,
+			     unsigned long event, void *ptr)
+{
+	const struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct net *net = dev_net(dev);
+
+	if (event == NETDEV_DOWN)
+		nf_ct_iterate_cleanup(net, device_cmp,
+				      (void *)(long)dev->ifindex, 0, 0);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block masq_dev_notifier = {
+	.notifier_call	= masq_device_event,
+};
+
+static int masq_inet_event(struct notifier_block *this,
+			   unsigned long event, void *ptr)
+{
+	struct inet6_ifaddr *ifa = ptr;
+	struct netdev_notifier_info info;
+
+	netdev_notifier_info_init(&info, ifa->idev->dev);
+	return masq_device_event(this, event, &info);
+}
+
+static struct notifier_block masq_inet_notifier = {
+	.notifier_call	= masq_inet_event,
+};
+
+static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0);
+
+void nf_nat_masquerade_ipv6_register_notifier(void)
+{
+	/* check if the notifier is already set */
+	if (atomic_inc_return(&masquerade_notifier_refcount) > 1)
+		return;
+
+	register_netdevice_notifier(&masq_dev_notifier);
+	register_inet6addr_notifier(&masq_inet_notifier);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier);
+
+void nf_nat_masquerade_ipv6_unregister_notifier(void)
+{
+	/* check if the notifier still has clients */
+	if (atomic_dec_return(&masquerade_notifier_refcount) > 0)
+		return;
+
+	unregister_inet6addr_notifier(&masq_inet_notifier);
+	unregister_netdevice_notifier(&masq_dev_notifier);
+}
+EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");


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

* [nf_tables PATCH v4 4/5] netfilter: nft_nat: split code in AF parts
  2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
  2014-09-04 12:06 ` [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization Arturo Borrero Gonzalez
  2014-09-04 12:06 ` [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: " Arturo Borrero Gonzalez
@ 2014-09-04 12:07 ` Arturo Borrero Gonzalez
  2014-09-04 12:07 ` [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support Arturo Borrero Gonzalez
  2014-09-09  9:50 ` [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Pablo Neira Ayuso
  4 siblings, 0 replies; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 12:07 UTC (permalink / raw)
  To: netfilter-devel; +Cc: kaber, pablo

This patch refactorices the nft_nat code into AF specific parts,
allowing further work in the AF specific zones, like adding masquerade support.

While at it, fix coding style in several places.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
v2: no changes.
v3: flags is u16. This also applies to the patch 1/5. Common _dump() function.
v4: nf-next rebased.

 include/net/netfilter/nft_nat.h   |   22 ++++++
 net/ipv4/netfilter/Kconfig        |    7 ++
 net/ipv4/netfilter/Makefile       |    1 
 net/ipv4/netfilter/nft_nat_ipv4.c |   98 ++++++++++++++++++++++++++++
 net/ipv6/netfilter/Kconfig        |    7 ++
 net/ipv6/netfilter/Makefile       |    1 
 net/ipv6/netfilter/nft_nat_ipv6.c |   98 ++++++++++++++++++++++++++++
 net/netfilter/nft_nat.c           |  129 +++++++------------------------------
 8 files changed, 260 insertions(+), 103 deletions(-)
 create mode 100644 include/net/netfilter/nft_nat.h
 create mode 100644 net/ipv4/netfilter/nft_nat_ipv4.c
 create mode 100644 net/ipv6/netfilter/nft_nat_ipv6.c

diff --git a/include/net/netfilter/nft_nat.h b/include/net/netfilter/nft_nat.h
new file mode 100644
index 0000000..0ac1546
--- /dev/null
+++ b/include/net/netfilter/nft_nat.h
@@ -0,0 +1,22 @@
+#ifndef _NFT_NAT_H_
+#define _NFT_NAT_H_
+
+struct nft_nat {
+	enum nft_registers      sreg_addr_min:8;
+	enum nft_registers      sreg_addr_max:8;
+	enum nft_registers      sreg_proto_min:8;
+	enum nft_registers      sreg_proto_max:8;
+	enum nf_nat_manip_type  type:8;
+	u8			family;
+	u16			flags;
+};
+
+extern const struct nla_policy nft_nat_policy[];
+
+int nft_nat_init(const struct nft_ctx *ctx,
+		 const struct nft_expr *expr,
+		 const struct nlattr * const tb[]);
+
+int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr);
+
+#endif /* _NFT_NAT_H_ */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 4be3e54..8167f31 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -190,6 +190,13 @@ config NF_NAT_MASQUERADE_IPV4
 	This is the kernel functionality to provide NAT in the masquerade
 	flavour (automatic source address selection).
 
+config NFT_NAT_IPV4
+	tristate "nft_nat IPv4 support"
+	depends on NFT_NAT
+	select NF_NAT_MASQUERADE_IPV4
+	help
+	  This is the nftables expression that handles NAT in IPv4.
+
 config IP_NF_TARGET_MASQUERADE
 	tristate "MASQUERADE target support"
 	select NF_NAT_MASQUERADE_IPV4
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 42056b2..4ad0a40 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
 obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
+obj-$(CONFIG_NFT_NAT_IPV4) += nft_nat_ipv4.o
 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
 
 # generic IP tables 
diff --git a/net/ipv4/netfilter/nft_nat_ipv4.c b/net/ipv4/netfilter/nft_nat_ipv4.c
new file mode 100644
index 0000000..feba0eb
--- /dev/null
+++ b/net/ipv4/netfilter/nft_nat_ipv4.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
+ * Copyright (c) 2012 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/string.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_nat_l3proto.h>
+#include <net/ip.h>
+#include <net/netfilter/nft_nat.h>
+#include <net/netfilter/ipv4/nf_nat_masquerade_ipv4.h>
+
+static void nft_nat_ipv4_eval(const struct nft_expr *expr,
+			      struct nft_data data[NFT_REG_MAX + 1],
+			      const struct nft_pktinfo *pkt)
+{
+	const struct nft_nat *priv = nft_expr_priv(expr);
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
+	struct nf_nat_range range;
+
+	memset(&range, 0, sizeof(range));
+	if (priv->sreg_addr_min) {
+		range.min_addr.ip =
+			(__force __be32)data[priv->sreg_addr_min].data[0];
+		range.max_addr.ip =
+			(__force __be32)data[priv->sreg_addr_max].data[0];
+
+		range.flags |= NF_NAT_RANGE_MAP_IPS;
+	}
+
+	if (priv->sreg_proto_min) {
+		range.min_proto.all =
+			(__force __be16)data[priv->sreg_proto_min].data[0];
+		range.max_proto.all =
+			(__force __be16)data[priv->sreg_proto_max].data[0];
+
+		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+	}
+
+	range.flags |= priv->flags;
+
+	data[NFT_REG_VERDICT].verdict =
+				nf_nat_setup_info(ct, &range, priv->type);
+}
+
+static struct nft_expr_type nft_nat_ipv4_type;
+static const struct nft_expr_ops nft_nat_ipv4_ops = {
+	.type           = &nft_nat_ipv4_type,
+	.size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
+	.eval           = nft_nat_ipv4_eval,
+	.init           = nft_nat_init,
+	.dump           = nft_nat_dump,
+};
+
+static struct nft_expr_type nft_nat_ipv4_type __read_mostly = {
+	.family		= NFPROTO_IPV4,
+	.name           = "nat",
+	.ops            = &nft_nat_ipv4_ops,
+	.policy         = nft_nat_policy,
+	.maxattr        = NFTA_NAT_MAX,
+	.owner          = THIS_MODULE,
+};
+
+static int __init nft_nat_ipv4_module_init(void)
+{
+	return nft_register_expr(&nft_nat_ipv4_type);
+}
+
+static void __exit nft_nat_ipv4_module_exit(void)
+{
+	nft_unregister_expr(&nft_nat_ipv4_type);
+}
+
+module_init(nft_nat_ipv4_module_init);
+module_exit(nft_nat_ipv4_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
+MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "nat");
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 6c8cfec..c8f1daf 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -252,6 +252,13 @@ config NF_NAT_MASQUERADE_IPV6
 	 This is the kernel functionality to provide NAT in the masquerade
 	 flavour (automatic source address selection) for IPv6.
 
+config NFT_NAT_IPV6
+	tristate "nft_nat IPv6 support"
+	depends on NFT_NAT
+	select NF_NAT_MASQUERADE_IPV6
+	help
+	 This is the nftables expression that handles NAT in IPv6.
+
 config IP6_NF_TARGET_MASQUERADE
 	tristate "MASQUERADE target support"
 	select NF_NAT_MASQUERADE_IPV6
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 89a0bd7..43dc399 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
 obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
+obj-$(CONFIG_NFT_NAT_IPV6) += nft_nat_ipv6.o
 
 # matches
 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/nft_nat_ipv6.c b/net/ipv6/netfilter/nft_nat_ipv6.c
new file mode 100644
index 0000000..1bcc578
--- /dev/null
+++ b/net/ipv6/netfilter/nft_nat_ipv6.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
+ * Copyright (c) 2012 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/string.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_nat_l3proto.h>
+#include <net/ip.h>
+#include <net/netfilter/nft_nat.h>
+
+static void nft_nat_ipv6_eval(const struct nft_expr *expr,
+			      struct nft_data data[NFT_REG_MAX + 1],
+			      const struct nft_pktinfo *pkt)
+{
+	const struct nft_nat *priv = nft_expr_priv(expr);
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
+	struct nf_nat_range range;
+
+	memset(&range, 0, sizeof(range));
+	if (priv->sreg_addr_min) {
+		memcpy(range.min_addr.ip6,
+		       data[priv->sreg_addr_min].data,
+		       sizeof(struct nft_data));
+		memcpy(range.max_addr.ip6,
+		       data[priv->sreg_addr_max].data,
+		       sizeof(struct nft_data));
+		range.flags |= NF_NAT_RANGE_MAP_IPS;
+	}
+
+	if (priv->sreg_proto_min) {
+		range.min_proto.all =
+			(__force __be16)data[priv->sreg_proto_min].data[0];
+		range.max_proto.all =
+			(__force __be16)data[priv->sreg_proto_max].data[0];
+
+		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+	}
+
+	range.flags |= priv->flags;
+
+	data[NFT_REG_VERDICT].verdict =
+				nf_nat_setup_info(ct, &range, priv->type);
+}
+
+static struct nft_expr_type nft_nat_ipv6_type;
+static const struct nft_expr_ops nft_nat_ipv6_ops = {
+	.type           = &nft_nat_ipv6_type,
+	.size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
+	.eval           = nft_nat_ipv6_eval,
+	.init           = nft_nat_init,
+	.dump           = nft_nat_dump,
+};
+
+static struct nft_expr_type nft_nat_ipv6_type __read_mostly = {
+	.family		= NFPROTO_IPV6,
+	.name           = "nat",
+	.ops            = &nft_nat_ipv6_ops,
+	.policy         = nft_nat_policy,
+	.maxattr        = NFTA_NAT_MAX,
+	.owner          = THIS_MODULE,
+};
+
+static int __init nft_nat_ipv6_module_init(void)
+{
+	return nft_register_expr(&nft_nat_ipv6_type);
+}
+
+static void __exit nft_nat_ipv6_module_exit(void)
+{
+	nft_unregister_expr(&nft_nat_ipv6_type);
+}
+
+module_init(nft_nat_ipv6_module_init);
+module_exit(nft_nat_ipv6_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
+MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "nat");
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index 799550b..fc3f8c8 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -25,60 +25,9 @@
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_nat_l3proto.h>
 #include <net/ip.h>
+#include <net/netfilter/nft_nat.h>
 
-struct nft_nat {
-	enum nft_registers      sreg_addr_min:8;
-	enum nft_registers      sreg_addr_max:8;
-	enum nft_registers      sreg_proto_min:8;
-	enum nft_registers      sreg_proto_max:8;
-	enum nf_nat_manip_type  type:8;
-	u8			family;
-	u16			flags;
-};
-
-static void nft_nat_eval(const struct nft_expr *expr,
-			 struct nft_data data[NFT_REG_MAX + 1],
-			 const struct nft_pktinfo *pkt)
-{
-	const struct nft_nat *priv = nft_expr_priv(expr);
-	enum ip_conntrack_info ctinfo;
-	struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
-	struct nf_nat_range range;
-
-	memset(&range, 0, sizeof(range));
-	if (priv->sreg_addr_min) {
-		if (priv->family == AF_INET) {
-			range.min_addr.ip = (__force __be32)
-					data[priv->sreg_addr_min].data[0];
-			range.max_addr.ip = (__force __be32)
-					data[priv->sreg_addr_max].data[0];
-
-		} else {
-			memcpy(range.min_addr.ip6,
-			       data[priv->sreg_addr_min].data,
-			       sizeof(struct nft_data));
-			memcpy(range.max_addr.ip6,
-			       data[priv->sreg_addr_max].data,
-			       sizeof(struct nft_data));
-		}
-		range.flags |= NF_NAT_RANGE_MAP_IPS;
-	}
-
-	if (priv->sreg_proto_min) {
-		range.min_proto.all = (__force __be16)
-					data[priv->sreg_proto_min].data[0];
-		range.max_proto.all = (__force __be16)
-					data[priv->sreg_proto_max].data[0];
-		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-	}
-
-	range.flags |= priv->flags;
-
-	data[NFT_REG_VERDICT].verdict =
-		nf_nat_setup_info(ct, &range, priv->type);
-}
-
-static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
+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 },
@@ -87,9 +36,10 @@ static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
 	[NFTA_NAT_REG_PROTO_MAX] = { .type = NLA_U32 },
 	[NFTA_NAT_FLAGS]	 = { .type = NLA_U32 },
 };
+EXPORT_SYMBOL_GPL(nft_nat_policy);
 
-static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
-			const struct nlattr * const tb[])
+int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+		 const struct nlattr * const tb[])
 {
 	struct nft_nat *priv = nft_expr_priv(expr);
 	u32 family;
@@ -120,16 +70,18 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	priv->family = family;
 
 	if (tb[NFTA_NAT_REG_ADDR_MIN]) {
-		priv->sreg_addr_min = ntohl(nla_get_be32(
-						tb[NFTA_NAT_REG_ADDR_MIN]));
+		priv->sreg_addr_min =
+				ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));
+
 		err = nft_validate_input_register(priv->sreg_addr_min);
 		if (err < 0)
 			return err;
 	}
 
 	if (tb[NFTA_NAT_REG_ADDR_MAX]) {
-		priv->sreg_addr_max = ntohl(nla_get_be32(
-						tb[NFTA_NAT_REG_ADDR_MAX]));
+		priv->sreg_addr_max =
+				ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));
+
 		err = nft_validate_input_register(priv->sreg_addr_max);
 		if (err < 0)
 			return err;
@@ -137,16 +89,18 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 		priv->sreg_addr_max = priv->sreg_addr_min;
 
 	if (tb[NFTA_NAT_REG_PROTO_MIN]) {
-		priv->sreg_proto_min = ntohl(nla_get_be32(
-						tb[NFTA_NAT_REG_PROTO_MIN]));
+		priv->sreg_proto_min =
+			ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));
+
 		err = nft_validate_input_register(priv->sreg_proto_min);
 		if (err < 0)
 			return err;
 	}
 
 	if (tb[NFTA_NAT_REG_PROTO_MAX]) {
-		priv->sreg_proto_max = ntohl(nla_get_be32(
-						tb[NFTA_NAT_REG_PROTO_MAX]));
+		priv->sreg_proto_max =
+			ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));
+
 		err = nft_validate_input_register(priv->sreg_proto_max);
 		if (err < 0)
 			return err;
@@ -161,8 +115,9 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(nft_nat_init);
 
-static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
+int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
 	const struct nft_nat *priv = nft_expr_priv(expr);
 
@@ -185,14 +140,12 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 	if (nla_put_be32(skb,
 			 NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max)))
 		goto nla_put_failure;
-	if (priv->sreg_proto_min) {
-		if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN,
-				 htonl(priv->sreg_proto_min)))
-			goto nla_put_failure;
-		if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
-				 htonl(priv->sreg_proto_max)))
-			goto nla_put_failure;
-	}
+	if (nla_put_be32(skb,
+			 NFTA_NAT_REG_PROTO_MIN, htonl(priv->sreg_proto_min)))
+		goto nla_put_failure;
+	if (nla_put_be32(skb,
+			 NFTA_NAT_REG_PROTO_MAX, htonl(priv->sreg_proto_max)))
+		goto nla_put_failure;
 
 	if (priv->flags != 0) {
 		if (nla_put_be32(skb, NFTA_NAT_FLAGS, htonl(priv->flags)))
@@ -204,37 +157,7 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 nla_put_failure:
 	return -1;
 }
-
-static struct nft_expr_type nft_nat_type;
-static const struct nft_expr_ops nft_nat_ops = {
-	.type           = &nft_nat_type,
-	.size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
-	.eval           = nft_nat_eval,
-	.init           = nft_nat_init,
-	.dump           = nft_nat_dump,
-};
-
-static struct nft_expr_type nft_nat_type __read_mostly = {
-	.name           = "nat",
-	.ops            = &nft_nat_ops,
-	.policy         = nft_nat_policy,
-	.maxattr        = NFTA_NAT_MAX,
-	.owner          = THIS_MODULE,
-};
-
-static int __init nft_nat_module_init(void)
-{
-	return nft_register_expr(&nft_nat_type);
-}
-
-static void __exit nft_nat_module_exit(void)
-{
-	nft_unregister_expr(&nft_nat_type);
-}
-
-module_init(nft_nat_module_init);
-module_exit(nft_nat_module_exit);
+EXPORT_SYMBOL_GPL(nft_nat_dump);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
-MODULE_ALIAS_NFT_EXPR("nat");


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

* [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support
  2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
                   ` (2 preceding siblings ...)
  2014-09-04 12:07 ` [nf_tables PATCH v4 4/5] netfilter: nft_nat: split code in AF parts Arturo Borrero Gonzalez
@ 2014-09-04 12:07 ` Arturo Borrero Gonzalez
  2014-09-04 12:21   ` Patrick McHardy
  2014-09-09  9:50 ` [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Pablo Neira Ayuso
  4 siblings, 1 reply; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 12:07 UTC (permalink / raw)
  To: netfilter-devel; +Cc: kaber, pablo

This patch adds masquerade support to nft_nat.

Note that enum nf_nat_manip_type is replaced by enum nft_nat_types in order
to support masquerade.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
v2: fix missing htonl() conversion for NFTA_NAT_TYPE in _ipv6_dump().
v3: no changes.
v4: nf-next rebased.

 include/net/netfilter/nft_nat.h          |    2 +-
 include/uapi/linux/netfilter/nf_tables.h |    8 ++++--
 net/ipv4/netfilter/nft_nat_ipv4.c        |   40 ++++++++++++++++++++++++++++--
 net/ipv6/netfilter/nft_nat_ipv6.c        |   39 +++++++++++++++++++++++++++--
 net/netfilter/nft_nat.c                  |   20 ++++-----------
 5 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/include/net/netfilter/nft_nat.h b/include/net/netfilter/nft_nat.h
index 0ac1546..f5e108c 100644
--- a/include/net/netfilter/nft_nat.h
+++ b/include/net/netfilter/nft_nat.h
@@ -6,7 +6,7 @@ struct nft_nat {
 	enum nft_registers      sreg_addr_max:8;
 	enum nft_registers      sreg_proto_min:8;
 	enum nft_registers      sreg_proto_max:8;
-	enum nf_nat_manip_type  type:8;
+	enum nft_nat_types	type:8;
 	u8			family;
 	u16			flags;
 };
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 62ea48d..41d7241 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -766,14 +766,16 @@ enum nft_reject_attributes {
 #define NFTA_REJECT_MAX		(__NFTA_REJECT_MAX - 1)
 
 /**
- * enum nft_nat_types - nf_tables nat expression NAT types
+ * enum nft_nat_types - nf_tables nat expression NAT types.
  *
  * @NFT_NAT_SNAT: source NAT
  * @NFT_NAT_DNAT: destination NAT
+ * @NFT_NAT_MASQUERADE: masquerade NAT
  */
 enum nft_nat_types {
-	NFT_NAT_SNAT,
-	NFT_NAT_DNAT,
+	NFT_NAT_SNAT,		/* NF_NAT_MANIP_SRC */
+	NFT_NAT_DNAT,		/* NF_NAT_MANIP_DST */
+	NFT_NAT_MASQUERADE,
 };
 
 /**
diff --git a/net/ipv4/netfilter/nft_nat_ipv4.c b/net/ipv4/netfilter/nft_nat_ipv4.c
index feba0eb..bf45327 100644
--- a/net/ipv4/netfilter/nft_nat_ipv4.c
+++ b/net/ipv4/netfilter/nft_nat_ipv4.c
@@ -36,6 +36,7 @@ static void nft_nat_ipv4_eval(const struct nft_expr *expr,
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
 	struct nf_nat_range range;
+	unsigned int verdict;
 
 	memset(&range, 0, sizeof(range));
 	if (priv->sreg_addr_min) {
@@ -58,8 +59,40 @@ static void nft_nat_ipv4_eval(const struct nft_expr *expr,
 
 	range.flags |= priv->flags;
 
-	data[NFT_REG_VERDICT].verdict =
-				nf_nat_setup_info(ct, &range, priv->type);
+	if (priv->type == NFT_NAT_MASQUERADE) {
+		verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum,
+						 &range, pkt->out);
+	} else {
+		verdict = nf_nat_setup_info(ct, &range, priv->type);
+	}
+
+	data[NFT_REG_VERDICT].verdict = verdict;
+}
+
+static int nft_nat_ipv4_init(const struct nft_ctx *ctx,
+			     const struct nft_expr *expr,
+			     const struct nlattr * const tb[])
+{
+	int ret;
+	struct nft_nat *priv = nft_expr_priv(expr);
+
+	ret = nft_nat_init(ctx, expr, tb);
+	if (ret < 0)
+		goto out;
+
+	if (priv->type == NFT_NAT_MASQUERADE)
+		nf_nat_masquerade_ipv4_register_notifier();
+out:
+	return ret;
+}
+
+static void nft_nat_ipv4_destroy(const struct nft_ctx *ctx,
+				 const struct nft_expr *expr)
+{
+	struct nft_nat *priv = nft_expr_priv(expr);
+
+	if (priv->type == NFT_NAT_MASQUERADE)
+		nf_nat_masquerade_ipv4_unregister_notifier();
 }
 
 static struct nft_expr_type nft_nat_ipv4_type;
@@ -67,7 +100,8 @@ static const struct nft_expr_ops nft_nat_ipv4_ops = {
 	.type           = &nft_nat_ipv4_type,
 	.size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
 	.eval           = nft_nat_ipv4_eval,
-	.init           = nft_nat_init,
+	.init           = nft_nat_ipv4_init,
+	.destroy	= nft_nat_ipv4_destroy,
 	.dump           = nft_nat_dump,
 };
 
diff --git a/net/ipv6/netfilter/nft_nat_ipv6.c b/net/ipv6/netfilter/nft_nat_ipv6.c
index 1bcc578..909687f 100644
--- a/net/ipv6/netfilter/nft_nat_ipv6.c
+++ b/net/ipv6/netfilter/nft_nat_ipv6.c
@@ -26,6 +26,7 @@
 #include <net/netfilter/nf_nat_l3proto.h>
 #include <net/ip.h>
 #include <net/netfilter/nft_nat.h>
+#include <net/netfilter/ipv6/nf_nat_masquerade_ipv6.h>
 
 static void nft_nat_ipv6_eval(const struct nft_expr *expr,
 			      struct nft_data data[NFT_REG_MAX + 1],
@@ -35,6 +36,7 @@ static void nft_nat_ipv6_eval(const struct nft_expr *expr,
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(pkt->skb, &ctinfo);
 	struct nf_nat_range range;
+	unsigned int verdict;
 
 	memset(&range, 0, sizeof(range));
 	if (priv->sreg_addr_min) {
@@ -58,8 +60,38 @@ static void nft_nat_ipv6_eval(const struct nft_expr *expr,
 
 	range.flags |= priv->flags;
 
-	data[NFT_REG_VERDICT].verdict =
-				nf_nat_setup_info(ct, &range, priv->type);
+	if (priv->type == NFT_NAT_MASQUERADE)
+		verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
+	else
+		verdict = nf_nat_setup_info(ct, &range, priv->type);
+
+	data[NFT_REG_VERDICT].verdict = verdict;
+}
+
+static int nft_nat_ipv6_init(const struct nft_ctx *ctx,
+			     const struct nft_expr *expr,
+			     const struct nlattr * const tb[])
+{
+	int ret;
+	struct nft_nat *priv = nft_expr_priv(expr);
+
+	ret = nft_nat_init(ctx, expr, tb);
+	if (ret < 0)
+		goto out;
+
+	if (priv->type == NFT_NAT_MASQUERADE)
+		nf_nat_masquerade_ipv6_register_notifier();
+out:
+	return ret;
+}
+
+static void nft_nat_ipv6_destroy(const struct nft_ctx *ctx,
+				 const struct nft_expr *expr)
+{
+	struct nft_nat *priv = nft_expr_priv(expr);
+
+	if (priv->type == NFT_NAT_MASQUERADE)
+		nf_nat_masquerade_ipv6_unregister_notifier();
 }
 
 static struct nft_expr_type nft_nat_ipv6_type;
@@ -67,7 +99,8 @@ static const struct nft_expr_ops nft_nat_ipv6_ops = {
 	.type           = &nft_nat_ipv6_type,
 	.size           = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
 	.eval           = nft_nat_ipv6_eval,
-	.init           = nft_nat_init,
+	.init           = nft_nat_ipv6_init,
+	.destroy	= nft_nat_ipv6_destroy,
 	.dump           = nft_nat_dump,
 };
 
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index fc3f8c8..d912919 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -48,12 +48,11 @@ int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	if (tb[NFTA_NAT_TYPE] == NULL)
 		return -EINVAL;
 
-	switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
+	priv->type = ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]));
+	switch (priv->type) {
 	case NFT_NAT_SNAT:
-		priv->type = NF_NAT_MANIP_SRC;
-		break;
 	case NFT_NAT_DNAT:
-		priv->type = NF_NAT_MANIP_DST;
+	case NFT_NAT_MASQUERADE:
 		break;
 	default:
 		return -EINVAL;
@@ -121,17 +120,8 @@ int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
 	const struct nft_nat *priv = nft_expr_priv(expr);
 
-	switch (priv->type) {
-	case NF_NAT_MANIP_SRC:
-		if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_SNAT)))
-			goto nla_put_failure;
-		break;
-	case NF_NAT_MANIP_DST:
-		if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(NFT_NAT_DNAT)))
-			goto nla_put_failure;
-		break;
-	}
-
+	if (nla_put_be32(skb, NFTA_NAT_TYPE, htonl(priv->type)))
+		goto nla_put_failure;
 	if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family)))
 		goto nla_put_failure;
 	if (nla_put_be32(skb,


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

* Re: [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support
  2014-09-04 12:07 ` [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support Arturo Borrero Gonzalez
@ 2014-09-04 12:21   ` Patrick McHardy
  2014-09-04 12:40     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 14+ messages in thread
From: Patrick McHardy @ 2014-09-04 12:21 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, pablo

On Thu, Sep 04, 2014 at 02:07:21PM +0200, Arturo Borrero Gonzalez wrote:
> This patch adds masquerade support to nft_nat.
> 
> Note that enum nf_nat_manip_type is replaced by enum nft_nat_types in order
> to support masquerade.

Is it really worth combining them? We have lots of code churn to move
them into a single module, and static NAT and masquerading have some
fundamental differences in the data they need, so now we're adding
new code to validate all of this, we're adding a new NAT type which
is actually not a new NAT type but simply a special case of SNAT etc.

Why not simply create a new masquerade expression?

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

* Re: [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support
  2014-09-04 12:21   ` Patrick McHardy
@ 2014-09-04 12:40     ` Pablo Neira Ayuso
  2014-09-04 13:54       ` Arturo Borrero Gonzalez
  0 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-09-04 12:40 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Arturo Borrero Gonzalez, netfilter-devel

On Thu, Sep 04, 2014 at 01:21:51PM +0100, Patrick McHardy wrote:
> On Thu, Sep 04, 2014 at 02:07:21PM +0200, Arturo Borrero Gonzalez wrote:
> > This patch adds masquerade support to nft_nat.
> > 
> > Note that enum nf_nat_manip_type is replaced by enum nft_nat_types in order
> > to support masquerade.
> 
> Is it really worth combining them? We have lots of code churn to move
> them into a single module, and static NAT and masquerading have some
> fundamental differences in the data they need, so now we're adding
> new code to validate all of this, we're adding a new NAT type which
> is actually not a new NAT type but simply a special case of SNAT etc.
> 
> Why not simply create a new masquerade expression?

Indeed. We're going to have four unused fields in the nft_nat
expression:

+       enum nft_registers      sreg_addr_min:8;
+       enum nft_registers      sreg_addr_max:8;
+       enum nft_registers      sreg_proto_min:8;
+       enum nft_registers      sreg_proto_max:8;

And we can skip the nft_nat per family split that happens in patch 4/5.

I like the idea of the masquerade expression.

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

* Re: [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support
  2014-09-04 12:40     ` Pablo Neira Ayuso
@ 2014-09-04 13:54       ` Arturo Borrero Gonzalez
  2014-09-04 14:31         ` Patrick McHardy
  0 siblings, 1 reply; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-04 13:54 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Patrick McHardy, Netfilter Development Mailing list

On 4 September 2014 14:40, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>
> I like the idea of the masquerade expression.

Ok, I also like the idea.

Suggestions for the name of the new expression?

I would bet for nft_masq.
-- 
Arturo Borrero González
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support
  2014-09-04 13:54       ` Arturo Borrero Gonzalez
@ 2014-09-04 14:31         ` Patrick McHardy
  0 siblings, 0 replies; 14+ messages in thread
From: Patrick McHardy @ 2014-09-04 14:31 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez
  Cc: Pablo Neira Ayuso, Netfilter Development Mailing list

On Thu, Sep 04, 2014 at 03:54:49PM +0200, Arturo Borrero Gonzalez wrote:
> On 4 September 2014 14:40, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> >
> > I like the idea of the masquerade expression.
> 
> Ok, I also like the idea.
> 
> Suggestions for the name of the new expression?
> 
> I would bet for nft_masq.

Sounds good.

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

* Re: [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute
  2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
                   ` (3 preceding siblings ...)
  2014-09-04 12:07 ` [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support Arturo Borrero Gonzalez
@ 2014-09-09  9:50 ` Pablo Neira Ayuso
  2014-09-09 10:14   ` Arturo Borrero Gonzalez
  4 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-09-09  9:50 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, kaber

On Thu, Sep 04, 2014 at 02:06:14PM +0200, Arturo Borrero Gonzalez wrote:
> Both SNAT and DNAT (and the upcoming masquerade) can have additional
> configuration parameters, such as port randomization or NAT addressing
> persistence.
> We can cover these scenarios by simply adding a flag attribute for
> userspace to fill when needed.
> 
> The flags to use are defined in include/uapi/linux/netfilter/nf_nat.h,
>  NF_NAT_RANGE_MAP_IPS
>  NF_NAT_RANGE_PROTO_SPECIFIED
>  NF_NAT_RANGE_PROTO_RANDOM
>  NF_NAT_RANGE_PERSISTENT
>  NF_NAT_RANGE_PROTO_RANDOM_FULLY
>  NF_NAT_RANGE_PROTO_RANDOM_ALL
> 
> The caller must take care of not messing up with the flags, as they are
> added unconditionally to the final resulting nf_nat_range.

Not sure this comment is relevant. Of course, userspace should select
the flags accordingly :-). Let me know if the intention was other than
insisting on the fact that the flags alter the way the NAT is done.

> Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
> ---
> v2: address Florian Westphal's comments: check all flag bits to be known.
> v3: style cleanup requested by Pablo Neira. Mask name shortened.
> v4: nf-next rebase.
> 
>  include/uapi/linux/netfilter/nf_nat.h    |    5 +++++
>  include/uapi/linux/netfilter/nf_tables.h |    2 ++
>  net/netfilter/nft_nat.c                  |   16 ++++++++++++++++
>  3 files changed, 23 insertions(+)
> 
> diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h
> index 1ad3659..898db2d 100644
> --- a/include/uapi/linux/netfilter/nf_nat.h
> +++ b/include/uapi/linux/netfilter/nf_nat.h
> @@ -13,6 +13,11 @@
>  #define NF_NAT_RANGE_PROTO_RANDOM_ALL		\
>  	(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
>  
> +#define NF_NAT_RANGE_MASK					\
> +	(NF_NAT_RANGE_MAP_IPS|NF_NAT_RANGE_PROTO_SPECIFIED	\
> +	 |NF_NAT_RANGE_PROTO_RANDOM|NF_NAT_RANGE_PERSISTENT	\
> +	 |NF_NAT_RANGE_PROTO_RANDOM_FULLY)

I'm going to make the following comestic change:

#define NF_NAT_RANGE_MASK                                      \
     (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED |    \
      NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT |    \
      NF_NAT_RANGE_PROTO_RANDOM_FULLY)

Next time, place the '|' '&' and so on after at the end of the line.

If no more comments, I'll push this to nf-next. Thanks.

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

* Re: [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization
  2014-09-04 12:06 ` [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization Arturo Borrero Gonzalez
@ 2014-09-09  9:52   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-09-09  9:52 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, kaber

On Thu, Sep 04, 2014 at 02:06:33PM +0200, Arturo Borrero Gonzalez wrote:
> Let's refactor the code so we can reach the masquerade functionality from
> outside the xt context (ie, nftables).
> 
> The patch includes adding an atomic counter to the masquerade notifier: the
> stuff to be done by the notifier is the same in any case, and agnostic
> about who called it. Only one notification handler is needed.
> 
> This factorization only involves IPv4; a similar patch will follow to handle
> IPv6.

Applied, thanks.


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

* Re: [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: code factorization
  2014-09-04 12:06 ` [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: " Arturo Borrero Gonzalez
@ 2014-09-09  9:52   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-09-09  9:52 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez; +Cc: netfilter-devel, kaber

On Thu, Sep 04, 2014 at 02:06:49PM +0200, Arturo Borrero Gonzalez wrote:
> Let's refactor the code so we can reach the masquerade functionality from
> outside the xt context (ie, nftables).
> 
> The patch includes adding an atomic counter to the masquerade notifier: the
> stuff to be done by the notifier is the same in any case, and agnostic
> about who called it. Only one notification handler is needed.
> 
> This factorization only involves IPv6; a similar patch exists to handle IPv4.
> 

Also applied, thanks.


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

* Re: [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute
  2014-09-09  9:50 ` [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Pablo Neira Ayuso
@ 2014-09-09 10:14   ` Arturo Borrero Gonzalez
  2014-09-09 11:08     ` Pablo Neira Ayuso
  0 siblings, 1 reply; 14+ messages in thread
From: Arturo Borrero Gonzalez @ 2014-09-09 10:14 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Netfilter Development Mailing list, Patrick McHardy

On 9 September 2014 11:50, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Thu, Sep 04, 2014 at 02:06:14PM +0200, Arturo Borrero Gonzalez wrote:
>> Both SNAT and DNAT (and the upcoming masquerade) can have additional
>> configuration parameters, such as port randomization or NAT addressing
>> persistence.
>> We can cover these scenarios by simply adding a flag attribute for
>> userspace to fill when needed.
>>
>> The flags to use are defined in include/uapi/linux/netfilter/nf_nat.h,
>>  NF_NAT_RANGE_MAP_IPS
>>  NF_NAT_RANGE_PROTO_SPECIFIED
>>  NF_NAT_RANGE_PROTO_RANDOM
>>  NF_NAT_RANGE_PERSISTENT
>>  NF_NAT_RANGE_PROTO_RANDOM_FULLY
>>  NF_NAT_RANGE_PROTO_RANDOM_ALL
>>
>> The caller must take care of not messing up with the flags, as they are
>> added unconditionally to the final resulting nf_nat_range.
>
> Not sure this comment is relevant. Of course, userspace should select
> the flags accordingly :-). Let me know if the intention was other than
> insisting on the fact that the flags alter the way the NAT is done.
>

Yes, I meant that no additional check is done to know if the flags
combination makes sense.

>
> I'm going to make the following comestic change:
>
> #define NF_NAT_RANGE_MASK                                      \
>      (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED |    \
>       NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT |    \
>       NF_NAT_RANGE_PROTO_RANDOM_FULLY)
>
> Next time, place the '|' '&' and so on after at the end of the line.
>

Ok, thanks.

-- 
Arturo Borrero González
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute
  2014-09-09 10:14   ` Arturo Borrero Gonzalez
@ 2014-09-09 11:08     ` Pablo Neira Ayuso
  0 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2014-09-09 11:08 UTC (permalink / raw)
  To: Arturo Borrero Gonzalez
  Cc: Netfilter Development Mailing list, Patrick McHardy

On Tue, Sep 09, 2014 at 12:14:25PM +0200, Arturo Borrero Gonzalez wrote:
> On 9 September 2014 11:50, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Thu, Sep 04, 2014 at 02:06:14PM +0200, Arturo Borrero Gonzalez wrote:
> >> Both SNAT and DNAT (and the upcoming masquerade) can have additional
> >> configuration parameters, such as port randomization or NAT addressing
> >> persistence.
> >> We can cover these scenarios by simply adding a flag attribute for
> >> userspace to fill when needed.
> >>
> >> The flags to use are defined in include/uapi/linux/netfilter/nf_nat.h,
> >>  NF_NAT_RANGE_MAP_IPS
> >>  NF_NAT_RANGE_PROTO_SPECIFIED
> >>  NF_NAT_RANGE_PROTO_RANDOM
> >>  NF_NAT_RANGE_PERSISTENT
> >>  NF_NAT_RANGE_PROTO_RANDOM_FULLY
> >>  NF_NAT_RANGE_PROTO_RANDOM_ALL
> >>
> >> The caller must take care of not messing up with the flags, as they are
> >> added unconditionally to the final resulting nf_nat_range.
> >
> > Not sure this comment is relevant. Of course, userspace should select
> > the flags accordingly :-). Let me know if the intention was other than
> > insisting on the fact that the flags alter the way the NAT is done.
> >
> 
> Yes, I meant that no additional check is done to know if the flags
> combination makes sense.

I see. iptables does exactly the same thing at this moment. At quick
glance I think random flag combinations should not puzzle
nf_nat_setup_info(), but it would be good to give it a closer look.


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

end of thread, other threads:[~2014-09-09 11:07 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-04 12:06 [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Arturo Borrero Gonzalez
2014-09-04 12:06 ` [nf_tables PATCH v4 2/5] netfilter: nf_nat_masquerade_ipv4: code factorization Arturo Borrero Gonzalez
2014-09-09  9:52   ` Pablo Neira Ayuso
2014-09-04 12:06 ` [nf_tables PATCH v4 3/5] netfilter: nf_nat_masquerade_ipv6: " Arturo Borrero Gonzalez
2014-09-09  9:52   ` Pablo Neira Ayuso
2014-09-04 12:07 ` [nf_tables PATCH v4 4/5] netfilter: nft_nat: split code in AF parts Arturo Borrero Gonzalez
2014-09-04 12:07 ` [nf_tables PATCH v4 5/5] netfilter: nft_nat: add masquerade support Arturo Borrero Gonzalez
2014-09-04 12:21   ` Patrick McHardy
2014-09-04 12:40     ` Pablo Neira Ayuso
2014-09-04 13:54       ` Arturo Borrero Gonzalez
2014-09-04 14:31         ` Patrick McHardy
2014-09-09  9:50 ` [nf_tables PATCH v4 1/5] netfilter: nft_nat: include a flag attribute Pablo Neira Ayuso
2014-09-09 10:14   ` Arturo Borrero Gonzalez
2014-09-09 11:08     ` Pablo Neira Ayuso

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).