[PATCH 091/103] netfilter: iptables: switch to xt2 tables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx>
---
 include/net/netns/x_tables.h          |    3 +
 net/ipv4/netfilter/ip_tables.c        |  201 ++++++++++++---------------------
 net/ipv4/netfilter/iptable_filter.c   |   21 +++-
 net/ipv4/netfilter/iptable_mangle.c   |   29 ++++--
 net/ipv4/netfilter/iptable_raw.c      |   21 +++-
 net/ipv4/netfilter/iptable_security.c |   22 +++-
 net/ipv4/netfilter/nf_nat_rule.c      |   18 ++-
 7 files changed, 154 insertions(+), 161 deletions(-)

diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h
index 5e38fcd..68b0b4f 100644
--- a/include/net/netns/x_tables.h
+++ b/include/net/netns/x_tables.h
@@ -17,6 +17,9 @@ struct netns_xt2 {
 	struct mutex table_lock;
 	struct list_head table_list[NFPROTO_NUMPROTO];
 	struct xt2_table_link
+		*ipv4_filter, *ipv4_mangle, *ipv4_raw, *ipv4_security,
+		*ipv4_nat;
+	struct xt2_table_link
 		*ipv6_filter, *ipv6_mangle, *ipv6_raw, *ipv6_security;
 };
 
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 7b7f1c3..6a45da8 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1191,11 +1191,51 @@ static int compat_table_info(const struct xt_table_info *info,
 }
 #endif
 
+static const struct xt1_xlat_info ipt_compat_xlat_info = {
+#ifdef CONFIG_COMPAT
+	.marker_size     = XT_ALIGN(sizeof(struct ipt_error_target)),
+	.entry_hdr_size  = sizeof(struct compat_ipt_entry),
+	.pmatch_size     = sizeof(struct ipt_ip),
+	.first_match     = "ipv4",
+	.ematch_size     = sizeof(struct xt_entry_match),
+	.etarget_size    = sizeof(struct xt_entry_target),
+	.standard_tgsize = COMPAT_XT_ALIGN(sizeof(struct xt_entry_target) +
+	                   sizeof(compat_uint_t)),
+	.compat          = true,
+#endif
+};
+
+static const struct xt1_xlat_info ipt_xlat_info = {
+	.marker_size     = XT_ALIGN(sizeof(struct ipt_error_target)),
+	.entry_hdr_size  = sizeof(struct ipt_entry),
+	.pmatch_size     = sizeof(struct ipt_ip),
+	.first_match     = "ipv4",
+	.ematch_size     = sizeof(struct xt_entry_match),
+	.etarget_size    = sizeof(struct xt_entry_target),
+	.standard_tgsize = XT_ALIGN(sizeof(struct xt_entry_target) +
+	                   sizeof(int)),
+};
+
+static int ipt2_get_info(void __user *uptr, int len,
+                         struct xt2_table *table, bool compat)
+{
+	struct ipt_getinfo info = {
+		.valid_hooks = table->valid_hooks,
+	};
+
+	strncpy(info.name, table->name,
+	        min(sizeof(info.name), sizeof(table->name)));
+	info.size = xts_blob_prep_table(table,
+	            compat ? &ipt_compat_xlat_info : &ipt_xlat_info,
+	            info.hook_entry, info.underflow, &info.num_entries);
+	return (copy_to_user(uptr, &info, sizeof(info)) != 0) ? -EFAULT : 0;
+}
+
 static int get_info(struct net *net, void __user *user,
                     const int *len, int compat)
 {
 	char name[IPT_TABLE_MAXNAMELEN];
-	struct xt_table *t;
+	struct xt2_table *table;
 	int ret;
 
 	if (*len != sizeof(struct ipt_getinfo)) {
@@ -1208,46 +1248,13 @@ static int get_info(struct net *net, void __user *user,
 		return -EFAULT;
 
 	name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-#ifdef CONFIG_COMPAT
-	if (compat)
-		xt_compat_lock(AF_INET);
-#endif
-	t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
-				    "iptable_%s", name);
-	if (t && !IS_ERR(t)) {
-		struct ipt_getinfo info;
-		const struct xt_table_info *private = t->private;
-
-#ifdef CONFIG_COMPAT
-		if (compat) {
-			struct xt_table_info tmp;
-			ret = compat_table_info(private, &tmp);
-			xt_compat_flush_offsets(AF_INET);
-			private = &tmp;
-		}
-#endif
-		info.valid_hooks = t->valid_hooks;
-		memcpy(info.hook_entry, private->hook_entry,
-		       sizeof(info.hook_entry));
-		memcpy(info.underflow, private->underflow,
-		       sizeof(info.underflow));
-		info.num_entries = private->number;
-		info.size = private->size;
-		strcpy(info.name, name);
-
-		if (copy_to_user(user, &info, *len) != 0)
-			ret = -EFAULT;
-		else
-			ret = 0;
-
-		xt_table_unlock(t);
-		module_put(t->me);
-	} else
-		ret = t ? PTR_ERR(t) : -ENOENT;
-#ifdef CONFIG_COMPAT
-	if (compat)
-		xt_compat_unlock(AF_INET);
-#endif
+	table = try_then_request_module(
+	        xt2_table_lookup(net, name, NFPROTO_IPV4, XT2_TAKE_RCULOCK),
+	        "iptable_%s", name);
+	if (table == NULL)
+		return -ENOENT;
+	ret = ipt2_get_info(user, *len, table, compat);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -1257,7 +1264,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,
 {
 	int ret;
 	struct ipt_get_entries get;
-	struct xt_table *t;
+	struct xt2_table *table;
 
 	if (*len < sizeof(get)) {
 		duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
@@ -1271,23 +1278,13 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,
 		return -EINVAL;
 	}
 
-	t = xt_find_table_lock(net, AF_INET, get.name);
-	if (t && !IS_ERR(t)) {
-		const struct xt_table_info *private = t->private;
-		duprintf("t->private->number = %u\n", private->number);
-		if (get.size == private->size)
-			ret = copy_entries_to_user(private->size,
-						   t, uptr->entrytable);
-		else {
-			duprintf("get_entries: I've got %u not %u!\n",
-				 private->size, get.size);
-			ret = -EAGAIN;
-		}
-		module_put(t->me);
-		xt_table_unlock(t);
-	} else
-		ret = t ? PTR_ERR(t) : -ENOENT;
-
+	table = xt2_table_lookup(net, get.name, NFPROTO_IPV4,
+	        XT2_TAKE_RCULOCK);
+	if (table == NULL)
+		return -ENOENT;
+	ret = ipt2_table_to_xt1(uptr->entrytable, get.size,
+	      table, &ipt_xlat_info);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -1416,18 +1413,13 @@ static int
 do_add_counters(struct net *net, const void __user *user,
                 unsigned int len, int compat)
 {
-	unsigned int i, curcpu;
 	struct xt_counters_info tmp;
-	struct xt_counters *paddc;
 	unsigned int num_counters;
 	const char *name;
 	int size;
 	void *ptmp;
-	struct xt_table *t;
-	const struct xt_table_info *private;
 	int ret = 0;
-	void *loc_cpu_entry;
-	struct ipt_entry *iter;
+	struct xt2_table *table;
 #ifdef CONFIG_COMPAT
 	struct compat_xt_counters_info compat_tmp;
 
@@ -1458,45 +1450,11 @@ do_add_counters(struct net *net, const void __user *user,
 	if (len != size + num_counters * sizeof(struct xt_counters))
 		return -EINVAL;
 
-	paddc = vmalloc_node(len - size, numa_node_id());
-	if (!paddc)
-		return -ENOMEM;
-
-	if (copy_from_user(paddc, user + size, len - size) != 0) {
-		ret = -EFAULT;
-		goto free;
-	}
-
-	t = xt_find_table_lock(net, AF_INET, name);
-	if (!t || IS_ERR(t)) {
-		ret = t ? PTR_ERR(t) : -ENOENT;
-		goto free;
-	}
-
-	local_bh_disable();
-	private = t->private;
-	if (private->number != num_counters) {
-		ret = -EINVAL;
-		goto unlock_up_free;
-	}
-
-	i = 0;
-	/* Choose the copy that is on our node */
-	curcpu = smp_processor_id();
-	loc_cpu_entry = private->entries[curcpu];
-	xt_info_wrlock(curcpu);
-	xt_entry_foreach(iter, loc_cpu_entry, private->size) {
-		ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
-		++i;
-	}
-	xt_info_wrunlock(curcpu);
- unlock_up_free:
-	local_bh_enable();
-	xt_table_unlock(t);
-	module_put(t->me);
- free:
-	vfree(paddc);
-
+	table = xt2_table_lookup(net, name, NFPROTO_IPV4, XT2_TAKE_RCULOCK);
+	if (table == NULL)
+		return -ENOENT;
+	ret = xts_get_counters(table, user + size, num_counters);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -1957,7 +1915,7 @@ compat_do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user,
 
 	switch (cmd) {
 	case IPT_SO_SET_REPLACE:
-		ret = compat_do_replace(sock_net(sk), user, len);
+		ret = ipt2_compat_do_replace(sock_net(sk), user, len);
 		break;
 
 	case IPT_SO_SET_ADD_COUNTERS:
@@ -2019,7 +1977,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
 {
 	int ret;
 	struct compat_ipt_get_entries get;
-	struct xt_table *t;
+	struct xt2_table *table;
 
 	if (*len < sizeof(get)) {
 		duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
@@ -2035,28 +1993,13 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
 		return -EINVAL;
 	}
 
-	xt_compat_lock(AF_INET);
-	t = xt_find_table_lock(net, AF_INET, get.name);
-	if (t && !IS_ERR(t)) {
-		const struct xt_table_info *private = t->private;
-		struct xt_table_info info;
-		duprintf("t->private->number = %u\n", private->number);
-		ret = compat_table_info(private, &info);
-		if (!ret && get.size == info.size) {
-			ret = compat_copy_entries_to_user(private->size,
-							  t, uptr->entrytable);
-		} else if (!ret) {
-			duprintf("compat_get_entries: I've got %u not %u!\n",
-				 private->size, get.size);
-			ret = -EAGAIN;
-		}
-		xt_compat_flush_offsets(AF_INET);
-		module_put(t->me);
-		xt_table_unlock(t);
-	} else
-		ret = t ? PTR_ERR(t) : -ENOENT;
-
-	xt_compat_unlock(AF_INET);
+	table = xt2_table_lookup(net, get.name, NFPROTO_IPV4,
+	        XT2_TAKE_RCULOCK);
+	if (table == NULL)
+		return -ENOENT;
+	ret = ipt2_compat_table_to_xt1(uptr->entrytable, get.size,
+	      table, &ipt_compat_xlat_info);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -2094,7 +2037,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
 	switch (cmd) {
 	case IPT_SO_SET_REPLACE:
-		ret = do_replace(sock_net(sk), user, len);
+		ret = ipt2_do_replace(sock_net(sk), user, len);
 		break;
 
 	case IPT_SO_SET_ADD_COUNTERS:
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 962d6f5..d79474d 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/rcupdate.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/ip.h>
 
@@ -38,7 +39,9 @@ iptable_filter_hook(unsigned int hook,
 	 const struct net_device *out,
 	 int (*okfn)(struct sk_buff *))
 {
+	const struct xt2_table_link *link;
 	const struct net *net;
+	unsigned int verdict;
 
 	if (hook == NF_INET_LOCAL_OUT)
 		/* root is playing with raw sockets. */
@@ -47,7 +50,11 @@ iptable_filter_hook(unsigned int hook,
 			return NF_ACCEPT;
 
 	net = dev_net((in != NULL) ? in : out);
-	return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
+	rcu_read_lock();
+	link    = rcu_dereference(net->xt2.ipv4_filter);
+	verdict = xt2_do_table(skb, hook, in, out, link->table);
+	rcu_read_unlock();
+	return verdict;
 }
 
 /* Default to forward because I got too much mail already. */
@@ -57,6 +64,7 @@ module_param(forward, bool, 0000);
 static int __net_init iptable_filter_net_init(struct net *net)
 {
 	struct ipt_replace *repl = xt_repldata_create(&packet_filter);
+	struct xt2_table *table;
 
 	if (repl == NULL)
 		return -ENOMEM;
@@ -64,17 +72,18 @@ static int __net_init iptable_filter_net_init(struct net *net)
 	((struct ipt_standard *)repl->entries)[1].target.verdict =
 		-forward - 1;
 
-	net->ipv4.iptable_filter =
-		ipt_register_table(net, &packet_filter, repl);
+	table = ipt2_register_table(net, &packet_filter, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.iptable_filter))
-		return PTR_ERR(net->ipv4.iptable_filter);
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+	net->xt2.ipv4_filter = xt2_tlink_lookup(net, table->name,
+		table->nfproto, XT2_NO_RCULOCK);
 	return 0;
 }
 
 static void __net_exit iptable_filter_net_exit(struct net *net)
 {
-	ipt_unregister_table(net->ipv4.iptable_filter);
+	xt2_table_destroy(net, net->xt2.ipv4_filter->table);
 }
 
 static struct pernet_operations iptable_filter_net_ops = {
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 8434f57..5a931c9 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
+#include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/route.h>
@@ -40,6 +41,7 @@ static unsigned int
 iptable_mangle_out_hook(struct sk_buff *skb, const struct net_device *out,
                         const struct net *net)
 {
+	const struct xt2_table_link *link;
 	unsigned int ret;
 	const struct iphdr *iph;
 	u_int8_t tos;
@@ -58,8 +60,11 @@ iptable_mangle_out_hook(struct sk_buff *skb, const struct net_device *out,
 	daddr = iph->daddr;
 	tos = iph->tos;
 
-	ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out,
-			   net->ipv4.iptable_mangle);
+	rcu_read_lock();
+	link = rcu_dereference(net->xt2.ipv4_mangle);
+	ret  = xt2_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, link->table);
+	rcu_read_unlock();
+
 	/* Reroute for ANY change. */
 	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
 		iph = ip_hdr(skb);
@@ -82,30 +87,38 @@ iptable_mangle_hook(unsigned int hook, struct sk_buff *skb,
                     int (*okfn)(struct sk_buff *))
 {
 	const struct net *net = dev_net((in != NULL) ? in : out);
+	const struct xt2_table_link *link;
+	unsigned int verdict;
 
 	if (hook == NF_INET_LOCAL_OUT)
 		return iptable_mangle_out_hook(skb, out, net);
 
-	return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_mangle);
+	rcu_read_lock();
+	link    = rcu_dereference(net->xt2.ipv4_mangle);
+	verdict = xt2_do_table(skb, hook, in, out, link->table);
+	rcu_read_unlock();
+	return verdict;
 }
 
 static int __net_init iptable_mangle_net_init(struct net *net)
 {
 	struct ipt_replace *repl = xt_repldata_create(&packet_mangler);
+	struct xt2_table *table;
 
 	if (repl == NULL)
 		return -ENOMEM;
-	net->ipv4.iptable_mangle =
-		ipt_register_table(net, &packet_mangler, repl);
+	table = ipt2_register_table(net, &packet_mangler, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.iptable_mangle))
-		return PTR_ERR(net->ipv4.iptable_mangle);
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+	net->xt2.ipv4_mangle = xt2_tlink_lookup(net, table->name,
+		table->nfproto, XT2_NO_RCULOCK);
 	return 0;
 }
 
 static void __net_exit iptable_mangle_net_exit(struct net *net)
 {
-	ipt_unregister_table(net->ipv4.iptable_mangle);
+	xt2_table_destroy(net, net->xt2.ipv4_mangle->table);
 }
 
 static struct pernet_operations iptable_mangle_net_ops = {
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 243329c..757da0f 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxxxxxx>
  */
 #include <linux/module.h>
+#include <linux/rcupdate.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/ip.h>
 
@@ -25,7 +26,9 @@ iptable_raw_hook(unsigned int hook,
 	 const struct net_device *out,
 	 int (*okfn)(struct sk_buff *))
 {
+	const struct xt2_table_link *link;
 	const struct net *net;
+	unsigned int verdict;
 
 	if (hook == NF_INET_LOCAL_OUT)
 		/* root is playing with raw sockets. */
@@ -34,26 +37,32 @@ iptable_raw_hook(unsigned int hook,
 			return NF_ACCEPT;
 
 	net = dev_net((in != NULL) ? in : out);
-	return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
+	rcu_read_lock();
+	link    = rcu_dereference(net->xt2.ipv4_raw);
+	verdict = xt2_do_table(skb, hook, in, out, link->table);
+	rcu_read_unlock();
+	return verdict;
 }
 
 static int __net_init iptable_raw_net_init(struct net *net)
 {
 	struct ipt_replace *repl = xt_repldata_create(&packet_raw);
+	struct xt2_table *table;
 
 	if (repl == NULL)
 		return -ENOMEM;
-	net->ipv4.iptable_raw =
-		ipt_register_table(net, &packet_raw, repl);
+	table = ipt2_register_table(net, &packet_raw, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.iptable_raw))
-		return PTR_ERR(net->ipv4.iptable_raw);
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+	net->xt2.ipv4_raw = xt2_tlink_lookup(net, table->name,
+		table->nfproto, XT2_NO_RCULOCK);
 	return 0;
 }
 
 static void __net_exit iptable_raw_net_exit(struct net *net)
 {
-	ipt_unregister_table(net->ipv4.iptable_raw);
+	xt2_table_destroy(net, net->xt2.ipv4_raw->table);
 }
 
 static struct pernet_operations iptable_raw_net_ops = {
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index d2aed39..a999c8a 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -16,6 +16,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/module.h>
+#include <linux/rcupdate.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/ip.h>
 
@@ -42,7 +43,9 @@ iptable_security_hook(unsigned int hook,
 		  const struct net_device *out,
 		  int (*okfn)(struct sk_buff *))
 {
+	const struct xt2_table_link *link;
 	const struct net *net;
+	unsigned int verdict;
 
 	if (hook == NF_INET_LOCAL_OUT)
 		/* Somebody is playing with raw sockets. */
@@ -51,27 +54,32 @@ iptable_security_hook(unsigned int hook,
 			return NF_ACCEPT;
 
 	net = dev_net((in != NULL) ? in : out);
-	return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
+	rcu_read_lock();
+	link    = rcu_dereference(net->xt2.ipv4_security);
+	verdict = xt2_do_table(skb, hook, in, out, link->table);
+	rcu_read_unlock();
+	return verdict;
 }
 
 static int __net_init iptable_security_net_init(struct net *net)
 {
 	struct ipt_replace *repl = xt_repldata_create(&security_table);
+	struct xt2_table *table;
 
 	if (repl == NULL)
 		return -ENOMEM;
-	net->ipv4.iptable_security =
-		ipt_register_table(net, &security_table, repl);
+	table = ipt2_register_table(net, &security_table, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.iptable_security))
-		return PTR_ERR(net->ipv4.iptable_security);
-
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+	net->xt2.ipv4_security = xt2_tlink_lookup(net, table->name,
+		table->nfproto, XT2_NO_RCULOCK);
 	return 0;
 }
 
 static void __net_exit iptable_security_net_exit(struct net *net)
 {
-	ipt_unregister_table(net->ipv4.iptable_security);
+	xt2_table_destroy(net, net->xt2.ipv4_security->table);
 }
 
 static struct pernet_operations iptable_security_net_ops = {
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 8b44f1a..db1f1c0 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -13,6 +13,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/module.h>
 #include <linux/kmod.h>
+#include <linux/rcupdate.h>
 #include <linux/skbuff.h>
 #include <linux/proc_fs.h>
 #include <net/checksum.h>
@@ -121,10 +122,14 @@ int nf_nat_rule_find(struct sk_buff *skb,
 		     const struct net_device *out,
 		     struct nf_conn *ct)
 {
+	const struct xt2_table_link *link;
 	struct net *net = nf_ct_net(ct);
 	int ret;
 
-	ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
+	rcu_read_lock();
+	link = rcu_dereference(net->xt2.ipv4_nat);
+	ret  = xt2_do_table(skb, hooknum, in, out, link->table);
+	rcu_read_unlock();
 
 	if (ret == NF_ACCEPT) {
 		if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
@@ -157,19 +162,22 @@ static struct xt_target ipt_dnat_reg __read_mostly = {
 static int __net_init nf_nat_rule_net_init(struct net *net)
 {
 	struct ipt_replace *repl = xt_repldata_create(&nat_table);
+	struct xt2_table *table;
 
 	if (repl == NULL)
 		return -ENOMEM;
-	net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
+	table = ipt2_register_table(net, &nat_table, repl);
 	kfree(repl);
-	if (IS_ERR(net->ipv4.nat_table))
-		return PTR_ERR(net->ipv4.nat_table);
+	if (IS_ERR(table))
+		return PTR_ERR(table);
+	net->xt2.ipv4_nat = xt2_tlink_lookup(net, table->name,
+		table->nfproto, XT2_NO_RCULOCK);
 	return 0;
 }
 
 static void __net_exit nf_nat_rule_net_exit(struct net *net)
 {
-	ipt_unregister_table(net->ipv4.nat_table);
+	xt2_table_destroy(net, net->xt2.ipv4_nat->table);
 }
 
 static struct pernet_operations nf_nat_rule_net_ops = {
-- 
1.6.3.3

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

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux