aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter_arp/arp_tables.h4
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h5
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h4
-rw-r--r--net/ipv4/netfilter/arp_tables.c22
-rw-r--r--net/ipv4/netfilter/arptable_filter.c15
-rw-r--r--net/ipv4/netfilter/ip_tables.c28
-rw-r--r--net/ipv4/netfilter/iptable_filter.c18
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c18
-rw-r--r--net/ipv4/netfilter/iptable_raw.c18
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c16
-rw-r--r--net/ipv6/netfilter/ip6_tables.c24
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c17
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c17
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c15
-rw-r--r--net/netfilter/x_tables.c12
15 files changed, 134 insertions, 99 deletions
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 53dd4df27aa1..f35486b3a7ca 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -271,8 +271,8 @@ struct arpt_error
271 xt_register_target(tgt); }) 271 xt_register_target(tgt); })
272#define arpt_unregister_target(tgt) xt_unregister_target(tgt) 272#define arpt_unregister_target(tgt) xt_unregister_target(tgt)
273 273
274extern int arpt_register_table(struct arpt_table *table, 274extern struct arpt_table *arpt_register_table(struct arpt_table *table,
275 const struct arpt_replace *repl); 275 const struct arpt_replace *repl);
276extern void arpt_unregister_table(struct arpt_table *table); 276extern void arpt_unregister_table(struct arpt_table *table);
277extern unsigned int arpt_do_table(struct sk_buff *skb, 277extern unsigned int arpt_do_table(struct sk_buff *skb,
278 unsigned int hook, 278 unsigned int hook,
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 45fcad91e67b..bfc889f90276 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -244,8 +244,9 @@ ipt_get_target(struct ipt_entry *e)
244#include <linux/init.h> 244#include <linux/init.h>
245extern void ipt_init(void) __init; 245extern void ipt_init(void) __init;
246 246
247extern int ipt_register_table(struct xt_table *table, 247extern struct xt_table *ipt_register_table(struct net *net,
248 const struct ipt_replace *repl); 248 struct xt_table *table,
249 const struct ipt_replace *repl);
249extern void ipt_unregister_table(struct xt_table *table); 250extern void ipt_unregister_table(struct xt_table *table);
250 251
251/* Standard entry. */ 252/* Standard entry. */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 110801d699ee..f716c7506245 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -305,8 +305,8 @@ ip6t_get_target(struct ip6t_entry *e)
305#include <linux/init.h> 305#include <linux/init.h>
306extern void ip6t_init(void) __init; 306extern void ip6t_init(void) __init;
307 307
308extern int ip6t_register_table(struct xt_table *table, 308extern struct xt_table *ip6t_register_table(struct xt_table *table,
309 const struct ip6t_replace *repl); 309 const struct ip6t_replace *repl);
310extern void ip6t_unregister_table(struct xt_table *table); 310extern void ip6t_unregister_table(struct xt_table *table);
311extern unsigned int ip6t_do_table(struct sk_buff *skb, 311extern unsigned int ip6t_do_table(struct sk_buff *skb,
312 unsigned int hook, 312 unsigned int hook,
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 0da50a4a6578..3a5afb84e69f 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1719,8 +1719,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1719 return ret; 1719 return ret;
1720} 1720}
1721 1721
1722int arpt_register_table(struct arpt_table *table, 1722struct arpt_table *arpt_register_table(struct arpt_table *table,
1723 const struct arpt_replace *repl) 1723 const struct arpt_replace *repl)
1724{ 1724{
1725 int ret; 1725 int ret;
1726 struct xt_table_info *newinfo; 1726 struct xt_table_info *newinfo;
@@ -1732,7 +1732,7 @@ int arpt_register_table(struct arpt_table *table,
1732 newinfo = xt_alloc_table_info(repl->size); 1732 newinfo = xt_alloc_table_info(repl->size);
1733 if (!newinfo) { 1733 if (!newinfo) {
1734 ret = -ENOMEM; 1734 ret = -ENOMEM;
1735 return ret; 1735 goto out;
1736 } 1736 }
1737 1737
1738 /* choose the copy on our node/cpu */ 1738 /* choose the copy on our node/cpu */
@@ -1746,18 +1746,20 @@ int arpt_register_table(struct arpt_table *table,
1746 repl->underflow); 1746 repl->underflow);
1747 1747
1748 duprintf("arpt_register_table: translate table gives %d\n", ret); 1748 duprintf("arpt_register_table: translate table gives %d\n", ret);
1749 if (ret != 0) { 1749 if (ret != 0)
1750 xt_free_table_info(newinfo); 1750 goto out_free;
1751 return ret;
1752 }
1753 1751
1754 new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); 1752 new_table = xt_register_table(&init_net, table, &bootstrap, newinfo);
1755 if (IS_ERR(new_table)) { 1753 if (IS_ERR(new_table)) {
1756 xt_free_table_info(newinfo); 1754 ret = PTR_ERR(new_table);
1757 return PTR_ERR(new_table); 1755 goto out_free;
1758 } 1756 }
1757 return new_table;
1759 1758
1760 return 0; 1759out_free:
1760 xt_free_table_info(newinfo);
1761out:
1762 return ERR_PTR(ret);
1761} 1763}
1762 1764
1763void arpt_unregister_table(struct arpt_table *table) 1765void arpt_unregister_table(struct arpt_table *table)
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 7201511d54d2..b00321506a92 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -45,7 +45,7 @@ static struct
45 .term = ARPT_ERROR_INIT, 45 .term = ARPT_ERROR_INIT,
46}; 46};
47 47
48static struct arpt_table packet_filter = { 48static struct arpt_table __packet_filter = {
49 .name = "filter", 49 .name = "filter",
50 .valid_hooks = FILTER_VALID_HOOKS, 50 .valid_hooks = FILTER_VALID_HOOKS,
51 .lock = RW_LOCK_UNLOCKED, 51 .lock = RW_LOCK_UNLOCKED,
@@ -53,6 +53,7 @@ static struct arpt_table packet_filter = {
53 .me = THIS_MODULE, 53 .me = THIS_MODULE,
54 .af = NF_ARP, 54 .af = NF_ARP,
55}; 55};
56static struct arpt_table *packet_filter;
56 57
57/* The work comes in here from netfilter.c */ 58/* The work comes in here from netfilter.c */
58static unsigned int arpt_hook(unsigned int hook, 59static unsigned int arpt_hook(unsigned int hook,
@@ -61,7 +62,7 @@ static unsigned int arpt_hook(unsigned int hook,
61 const struct net_device *out, 62 const struct net_device *out,
62 int (*okfn)(struct sk_buff *)) 63 int (*okfn)(struct sk_buff *))
63{ 64{
64 return arpt_do_table(skb, hook, in, out, &packet_filter); 65 return arpt_do_table(skb, hook, in, out, packet_filter);
65} 66}
66 67
67static struct nf_hook_ops arpt_ops[] __read_mostly = { 68static struct nf_hook_ops arpt_ops[] __read_mostly = {
@@ -90,9 +91,9 @@ static int __init arptable_filter_init(void)
90 int ret; 91 int ret;
91 92
92 /* Register table */ 93 /* Register table */
93 ret = arpt_register_table(&packet_filter, &initial_table.repl); 94 packet_filter = arpt_register_table(&__packet_filter, &initial_table.repl);
94 if (ret < 0) 95 if (IS_ERR(packet_filter))
95 return ret; 96 return PTR_ERR(packet_filter);
96 97
97 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 98 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
98 if (ret < 0) 99 if (ret < 0)
@@ -100,14 +101,14 @@ static int __init arptable_filter_init(void)
100 return ret; 101 return ret;
101 102
102cleanup_table: 103cleanup_table:
103 arpt_unregister_table(&packet_filter); 104 arpt_unregister_table(packet_filter);
104 return ret; 105 return ret;
105} 106}
106 107
107static void __exit arptable_filter_fini(void) 108static void __exit arptable_filter_fini(void)
108{ 109{
109 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 110 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
110 arpt_unregister_table(&packet_filter); 111 arpt_unregister_table(packet_filter);
111} 112}
112 113
113module_init(arptable_filter_init); 114module_init(arptable_filter_init);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index bc22ea421a94..99dd62d93f4b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2048,7 +2048,8 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2048 return ret; 2048 return ret;
2049} 2049}
2050 2050
2051int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) 2051struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2052 const struct ipt_replace *repl)
2052{ 2053{
2053 int ret; 2054 int ret;
2054 struct xt_table_info *newinfo; 2055 struct xt_table_info *newinfo;
@@ -2058,8 +2059,10 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2058 struct xt_table *new_table; 2059 struct xt_table *new_table;
2059 2060
2060 newinfo = xt_alloc_table_info(repl->size); 2061 newinfo = xt_alloc_table_info(repl->size);
2061 if (!newinfo) 2062 if (!newinfo) {
2062 return -ENOMEM; 2063 ret = -ENOMEM;
2064 goto out;
2065 }
2063 2066
2064 /* choose the copy on our node/cpu, but dont care about preemption */ 2067 /* choose the copy on our node/cpu, but dont care about preemption */
2065 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2068 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
@@ -2070,18 +2073,21 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2070 repl->num_entries, 2073 repl->num_entries,
2071 repl->hook_entry, 2074 repl->hook_entry,
2072 repl->underflow); 2075 repl->underflow);
2073 if (ret != 0) { 2076 if (ret != 0)
2074 xt_free_table_info(newinfo); 2077 goto out_free;
2075 return ret;
2076 }
2077 2078
2078 new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); 2079 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2079 if (IS_ERR(new_table)) { 2080 if (IS_ERR(new_table)) {
2080 xt_free_table_info(newinfo); 2081 ret = PTR_ERR(new_table);
2081 return PTR_ERR(new_table); 2082 goto out_free;
2082 } 2083 }
2083 2084
2084 return 0; 2085 return new_table;
2086
2087out_free:
2088 xt_free_table_info(newinfo);
2089out:
2090 return ERR_PTR(ret);
2085} 2091}
2086 2092
2087void ipt_unregister_table(struct xt_table *table) 2093void ipt_unregister_table(struct xt_table *table)
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 29bb4f9fbda0..3b43ca07a26c 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -53,13 +53,14 @@ static struct
53 .term = IPT_ERROR_INIT, /* ERROR */ 53 .term = IPT_ERROR_INIT, /* ERROR */
54}; 54};
55 55
56static struct xt_table packet_filter = { 56static struct xt_table __packet_filter = {
57 .name = "filter", 57 .name = "filter",
58 .valid_hooks = FILTER_VALID_HOOKS, 58 .valid_hooks = FILTER_VALID_HOOKS,
59 .lock = RW_LOCK_UNLOCKED, 59 .lock = RW_LOCK_UNLOCKED,
60 .me = THIS_MODULE, 60 .me = THIS_MODULE,
61 .af = AF_INET, 61 .af = AF_INET,
62}; 62};
63static struct xt_table *packet_filter;
63 64
64/* The work comes in here from netfilter.c. */ 65/* The work comes in here from netfilter.c. */
65static unsigned int 66static unsigned int
@@ -69,7 +70,7 @@ ipt_hook(unsigned int hook,
69 const struct net_device *out, 70 const struct net_device *out,
70 int (*okfn)(struct sk_buff *)) 71 int (*okfn)(struct sk_buff *))
71{ 72{
72 return ipt_do_table(skb, hook, in, out, &packet_filter); 73 return ipt_do_table(skb, hook, in, out, packet_filter);
73} 74}
74 75
75static unsigned int 76static unsigned int
@@ -88,7 +89,7 @@ ipt_local_out_hook(unsigned int hook,
88 return NF_ACCEPT; 89 return NF_ACCEPT;
89 } 90 }
90 91
91 return ipt_do_table(skb, hook, in, out, &packet_filter); 92 return ipt_do_table(skb, hook, in, out, packet_filter);
92} 93}
93 94
94static struct nf_hook_ops ipt_ops[] __read_mostly = { 95static struct nf_hook_ops ipt_ops[] __read_mostly = {
@@ -132,9 +133,10 @@ static int __init iptable_filter_init(void)
132 initial_table.entries[1].target.verdict = -forward - 1; 133 initial_table.entries[1].target.verdict = -forward - 1;
133 134
134 /* Register table */ 135 /* Register table */
135 ret = ipt_register_table(&packet_filter, &initial_table.repl); 136 packet_filter = ipt_register_table(&init_net, &__packet_filter,
136 if (ret < 0) 137 &initial_table.repl);
137 return ret; 138 if (IS_ERR(packet_filter))
139 return PTR_ERR(packet_filter);
138 140
139 /* Register hooks */ 141 /* Register hooks */
140 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 142 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
@@ -144,14 +146,14 @@ static int __init iptable_filter_init(void)
144 return ret; 146 return ret;
145 147
146 cleanup_table: 148 cleanup_table:
147 ipt_unregister_table(&packet_filter); 149 ipt_unregister_table(packet_filter);
148 return ret; 150 return ret;
149} 151}
150 152
151static void __exit iptable_filter_fini(void) 153static void __exit iptable_filter_fini(void)
152{ 154{
153 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 155 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
154 ipt_unregister_table(&packet_filter); 156 ipt_unregister_table(packet_filter);
155} 157}
156 158
157module_init(iptable_filter_init); 159module_init(iptable_filter_init);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 5c4be202430c..292f2ed4416f 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -64,13 +64,14 @@ static struct
64 .term = IPT_ERROR_INIT, /* ERROR */ 64 .term = IPT_ERROR_INIT, /* ERROR */
65}; 65};
66 66
67static struct xt_table packet_mangler = { 67static struct xt_table __packet_mangler = {
68 .name = "mangle", 68 .name = "mangle",
69 .valid_hooks = MANGLE_VALID_HOOKS, 69 .valid_hooks = MANGLE_VALID_HOOKS,
70 .lock = RW_LOCK_UNLOCKED, 70 .lock = RW_LOCK_UNLOCKED,
71 .me = THIS_MODULE, 71 .me = THIS_MODULE,
72 .af = AF_INET, 72 .af = AF_INET,
73}; 73};
74static struct xt_table *packet_mangler;
74 75
75/* The work comes in here from netfilter.c. */ 76/* The work comes in here from netfilter.c. */
76static unsigned int 77static unsigned int
@@ -80,7 +81,7 @@ ipt_route_hook(unsigned int hook,
80 const struct net_device *out, 81 const struct net_device *out,
81 int (*okfn)(struct sk_buff *)) 82 int (*okfn)(struct sk_buff *))
82{ 83{
83 return ipt_do_table(skb, hook, in, out, &packet_mangler); 84 return ipt_do_table(skb, hook, in, out, packet_mangler);
84} 85}
85 86
86static unsigned int 87static unsigned int
@@ -112,7 +113,7 @@ ipt_local_hook(unsigned int hook,
112 daddr = iph->daddr; 113 daddr = iph->daddr;
113 tos = iph->tos; 114 tos = iph->tos;
114 115
115 ret = ipt_do_table(skb, hook, in, out, &packet_mangler); 116 ret = ipt_do_table(skb, hook, in, out, packet_mangler);
116 /* Reroute for ANY change. */ 117 /* Reroute for ANY change. */
117 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { 118 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
118 iph = ip_hdr(skb); 119 iph = ip_hdr(skb);
@@ -171,9 +172,10 @@ static int __init iptable_mangle_init(void)
171 int ret; 172 int ret;
172 173
173 /* Register table */ 174 /* Register table */
174 ret = ipt_register_table(&packet_mangler, &initial_table.repl); 175 packet_mangler = ipt_register_table(&init_net, &__packet_mangler,
175 if (ret < 0) 176 &initial_table.repl);
176 return ret; 177 if (IS_ERR(packet_mangler))
178 return PTR_ERR(packet_mangler);
177 179
178 /* Register hooks */ 180 /* Register hooks */
179 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 181 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
@@ -183,14 +185,14 @@ static int __init iptable_mangle_init(void)
183 return ret; 185 return ret;
184 186
185 cleanup_table: 187 cleanup_table:
186 ipt_unregister_table(&packet_mangler); 188 ipt_unregister_table(packet_mangler);
187 return ret; 189 return ret;
188} 190}
189 191
190static void __exit iptable_mangle_fini(void) 192static void __exit iptable_mangle_fini(void)
191{ 193{
192 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 194 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
193 ipt_unregister_table(&packet_mangler); 195 ipt_unregister_table(packet_mangler);
194} 196}
195 197
196module_init(iptable_mangle_init); 198module_init(iptable_mangle_init);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index dc34aa274533..dab863dd0558 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -36,13 +36,14 @@ static struct
36 .term = IPT_ERROR_INIT, /* ERROR */ 36 .term = IPT_ERROR_INIT, /* ERROR */
37}; 37};
38 38
39static struct xt_table packet_raw = { 39static struct xt_table __packet_raw = {
40 .name = "raw", 40 .name = "raw",
41 .valid_hooks = RAW_VALID_HOOKS, 41 .valid_hooks = RAW_VALID_HOOKS,
42 .lock = RW_LOCK_UNLOCKED, 42 .lock = RW_LOCK_UNLOCKED,
43 .me = THIS_MODULE, 43 .me = THIS_MODULE,
44 .af = AF_INET, 44 .af = AF_INET,
45}; 45};
46static struct xt_table *packet_raw;
46 47
47/* The work comes in here from netfilter.c. */ 48/* The work comes in here from netfilter.c. */
48static unsigned int 49static unsigned int
@@ -52,7 +53,7 @@ ipt_hook(unsigned int hook,
52 const struct net_device *out, 53 const struct net_device *out,
53 int (*okfn)(struct sk_buff *)) 54 int (*okfn)(struct sk_buff *))
54{ 55{
55 return ipt_do_table(skb, hook, in, out, &packet_raw); 56 return ipt_do_table(skb, hook, in, out, packet_raw);
56} 57}
57 58
58static unsigned int 59static unsigned int
@@ -70,7 +71,7 @@ ipt_local_hook(unsigned int hook,
70 "packet.\n"); 71 "packet.\n");
71 return NF_ACCEPT; 72 return NF_ACCEPT;
72 } 73 }
73 return ipt_do_table(skb, hook, in, out, &packet_raw); 74 return ipt_do_table(skb, hook, in, out, packet_raw);
74} 75}
75 76
76/* 'raw' is the very first table. */ 77/* 'raw' is the very first table. */
@@ -96,9 +97,10 @@ static int __init iptable_raw_init(void)
96 int ret; 97 int ret;
97 98
98 /* Register table */ 99 /* Register table */
99 ret = ipt_register_table(&packet_raw, &initial_table.repl); 100 packet_raw = ipt_register_table(&init_net, &__packet_raw,
100 if (ret < 0) 101 &initial_table.repl);
101 return ret; 102 if (IS_ERR(packet_raw))
103 return PTR_ERR(packet_raw);
102 104
103 /* Register hooks */ 105 /* Register hooks */
104 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 106 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
@@ -108,14 +110,14 @@ static int __init iptable_raw_init(void)
108 return ret; 110 return ret;
109 111
110 cleanup_table: 112 cleanup_table:
111 ipt_unregister_table(&packet_raw); 113 ipt_unregister_table(packet_raw);
112 return ret; 114 return ret;
113} 115}
114 116
115static void __exit iptable_raw_fini(void) 117static void __exit iptable_raw_fini(void)
116{ 118{
117 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 119 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
118 ipt_unregister_table(&packet_raw); 120 ipt_unregister_table(packet_raw);
119} 121}
120 122
121module_init(iptable_raw_init); 123module_init(iptable_raw_init);
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 519182269e76..f8fda57ba20b 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -58,13 +58,14 @@ static struct
58 .term = IPT_ERROR_INIT, /* ERROR */ 58 .term = IPT_ERROR_INIT, /* ERROR */
59}; 59};
60 60
61static struct xt_table nat_table = { 61static struct xt_table __nat_table = {
62 .name = "nat", 62 .name = "nat",
63 .valid_hooks = NAT_VALID_HOOKS, 63 .valid_hooks = NAT_VALID_HOOKS,
64 .lock = RW_LOCK_UNLOCKED, 64 .lock = RW_LOCK_UNLOCKED,
65 .me = THIS_MODULE, 65 .me = THIS_MODULE,
66 .af = AF_INET, 66 .af = AF_INET,
67}; 67};
68static struct xt_table *nat_table;
68 69
69/* Source NAT */ 70/* Source NAT */
70static unsigned int ipt_snat_target(struct sk_buff *skb, 71static unsigned int ipt_snat_target(struct sk_buff *skb,
@@ -214,7 +215,7 @@ int nf_nat_rule_find(struct sk_buff *skb,
214{ 215{
215 int ret; 216 int ret;
216 217
217 ret = ipt_do_table(skb, hooknum, in, out, &nat_table); 218 ret = ipt_do_table(skb, hooknum, in, out, nat_table);
218 219
219 if (ret == NF_ACCEPT) { 220 if (ret == NF_ACCEPT) {
220 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) 221 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
@@ -248,9 +249,10 @@ int __init nf_nat_rule_init(void)
248{ 249{
249 int ret; 250 int ret;
250 251
251 ret = ipt_register_table(&nat_table, &nat_initial_table.repl); 252 nat_table = ipt_register_table(&init_net, &__nat_table,
252 if (ret != 0) 253 &nat_initial_table.repl);
253 return ret; 254 if (IS_ERR(nat_table))
255 return PTR_ERR(nat_table);
254 ret = xt_register_target(&ipt_snat_reg); 256 ret = xt_register_target(&ipt_snat_reg);
255 if (ret != 0) 257 if (ret != 0)
256 goto unregister_table; 258 goto unregister_table;
@@ -264,7 +266,7 @@ int __init nf_nat_rule_init(void)
264 unregister_snat: 266 unregister_snat:
265 xt_unregister_target(&ipt_snat_reg); 267 xt_unregister_target(&ipt_snat_reg);
266 unregister_table: 268 unregister_table:
267 ipt_unregister_table(&nat_table); 269 ipt_unregister_table(nat_table);
268 270
269 return ret; 271 return ret;
270} 272}
@@ -273,5 +275,5 @@ void nf_nat_rule_cleanup(void)
273{ 275{
274 xt_unregister_target(&ipt_dnat_reg); 276 xt_unregister_target(&ipt_dnat_reg);
275 xt_unregister_target(&ipt_snat_reg); 277 xt_unregister_target(&ipt_snat_reg);
276 ipt_unregister_table(&nat_table); 278 ipt_unregister_table(nat_table);
277} 279}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1aac3ef39414..b89f133f41d0 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -2074,7 +2074,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2074 return ret; 2074 return ret;
2075} 2075}
2076 2076
2077int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl) 2077struct xt_table *ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl)
2078{ 2078{
2079 int ret; 2079 int ret;
2080 struct xt_table_info *newinfo; 2080 struct xt_table_info *newinfo;
@@ -2084,8 +2084,10 @@ int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl)
2084 struct xt_table *new_table; 2084 struct xt_table *new_table;
2085 2085
2086 newinfo = xt_alloc_table_info(repl->size); 2086 newinfo = xt_alloc_table_info(repl->size);
2087 if (!newinfo) 2087 if (!newinfo) {
2088 return -ENOMEM; 2088 ret = -ENOMEM;
2089 goto out;
2090 }
2089 2091
2090 /* choose the copy on our node/cpu, but dont care about preemption */ 2092 /* choose the copy on our node/cpu, but dont care about preemption */
2091 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2093 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
@@ -2096,18 +2098,20 @@ int ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl)
2096 repl->num_entries, 2098 repl->num_entries,
2097 repl->hook_entry, 2099 repl->hook_entry,
2098 repl->underflow); 2100 repl->underflow);
2099 if (ret != 0) { 2101 if (ret != 0)
2100 xt_free_table_info(newinfo); 2102 goto out_free;
2101 return ret;
2102 }
2103 2103
2104 new_table = xt_register_table(&init_net, table, &bootstrap, newinfo); 2104 new_table = xt_register_table(&init_net, table, &bootstrap, newinfo);
2105 if (IS_ERR(new_table)) { 2105 if (IS_ERR(new_table)) {
2106 xt_free_table_info(newinfo); 2106 ret = PTR_ERR(new_table);
2107 return PTR_ERR(new_table); 2107 goto out_free;
2108 } 2108 }
2109 return new_table;
2109 2110
2110 return 0; 2111out_free:
2112 xt_free_table_info(newinfo);
2113out:
2114 return ERR_PTR(ret);
2111} 2115}
2112 2116
2113void ip6t_unregister_table(struct xt_table *table) 2117void ip6t_unregister_table(struct xt_table *table)
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 87d38d08aad0..bffd67f32359 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -51,13 +51,14 @@ static struct
51 .term = IP6T_ERROR_INIT, /* ERROR */ 51 .term = IP6T_ERROR_INIT, /* ERROR */
52}; 52};
53 53
54static struct xt_table packet_filter = { 54static struct xt_table __packet_filter = {
55 .name = "filter", 55 .name = "filter",
56 .valid_hooks = FILTER_VALID_HOOKS, 56 .valid_hooks = FILTER_VALID_HOOKS,
57 .lock = RW_LOCK_UNLOCKED, 57 .lock = RW_LOCK_UNLOCKED,
58 .me = THIS_MODULE, 58 .me = THIS_MODULE,
59 .af = AF_INET6, 59 .af = AF_INET6,
60}; 60};
61static struct xt_table *packet_filter;
61 62
62/* The work comes in here from netfilter.c. */ 63/* The work comes in here from netfilter.c. */
63static unsigned int 64static unsigned int
@@ -67,7 +68,7 @@ ip6t_hook(unsigned int hook,
67 const struct net_device *out, 68 const struct net_device *out,
68 int (*okfn)(struct sk_buff *)) 69 int (*okfn)(struct sk_buff *))
69{ 70{
70 return ip6t_do_table(skb, hook, in, out, &packet_filter); 71 return ip6t_do_table(skb, hook, in, out, packet_filter);
71} 72}
72 73
73static unsigned int 74static unsigned int
@@ -87,7 +88,7 @@ ip6t_local_out_hook(unsigned int hook,
87 } 88 }
88#endif 89#endif
89 90
90 return ip6t_do_table(skb, hook, in, out, &packet_filter); 91 return ip6t_do_table(skb, hook, in, out, packet_filter);
91} 92}
92 93
93static struct nf_hook_ops ip6t_ops[] __read_mostly = { 94static struct nf_hook_ops ip6t_ops[] __read_mostly = {
@@ -131,9 +132,9 @@ static int __init ip6table_filter_init(void)
131 initial_table.entries[1].target.verdict = -forward - 1; 132 initial_table.entries[1].target.verdict = -forward - 1;
132 133
133 /* Register table */ 134 /* Register table */
134 ret = ip6t_register_table(&packet_filter, &initial_table.repl); 135 packet_filter = ip6t_register_table(&__packet_filter, &initial_table.repl);
135 if (ret < 0) 136 if (IS_ERR(packet_filter))
136 return ret; 137 return PTR_ERR(packet_filter);
137 138
138 /* Register hooks */ 139 /* Register hooks */
139 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 140 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
@@ -143,14 +144,14 @@ static int __init ip6table_filter_init(void)
143 return ret; 144 return ret;
144 145
145 cleanup_table: 146 cleanup_table:
146 ip6t_unregister_table(&packet_filter); 147 ip6t_unregister_table(packet_filter);
147 return ret; 148 return ret;
148} 149}
149 150
150static void __exit ip6table_filter_fini(void) 151static void __exit ip6table_filter_fini(void)
151{ 152{
152 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 153 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
153 ip6t_unregister_table(&packet_filter); 154 ip6t_unregister_table(packet_filter);
154} 155}
155 156
156module_init(ip6table_filter_init); 157module_init(ip6table_filter_init);
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index d6082600bc5d..63d334df3b40 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -57,13 +57,14 @@ static struct
57 .term = IP6T_ERROR_INIT, /* ERROR */ 57 .term = IP6T_ERROR_INIT, /* ERROR */
58}; 58};
59 59
60static struct xt_table packet_mangler = { 60static struct xt_table __packet_mangler = {
61 .name = "mangle", 61 .name = "mangle",
62 .valid_hooks = MANGLE_VALID_HOOKS, 62 .valid_hooks = MANGLE_VALID_HOOKS,
63 .lock = RW_LOCK_UNLOCKED, 63 .lock = RW_LOCK_UNLOCKED,
64 .me = THIS_MODULE, 64 .me = THIS_MODULE,
65 .af = AF_INET6, 65 .af = AF_INET6,
66}; 66};
67static struct xt_table *packet_mangler;
67 68
68/* The work comes in here from netfilter.c. */ 69/* The work comes in here from netfilter.c. */
69static unsigned int 70static unsigned int
@@ -73,7 +74,7 @@ ip6t_route_hook(unsigned int hook,
73 const struct net_device *out, 74 const struct net_device *out,
74 int (*okfn)(struct sk_buff *)) 75 int (*okfn)(struct sk_buff *))
75{ 76{
76 return ip6t_do_table(skb, hook, in, out, &packet_mangler); 77 return ip6t_do_table(skb, hook, in, out, packet_mangler);
77} 78}
78 79
79static unsigned int 80static unsigned int
@@ -108,7 +109,7 @@ ip6t_local_hook(unsigned int hook,
108 /* flowlabel and prio (includes version, which shouldn't change either */ 109 /* flowlabel and prio (includes version, which shouldn't change either */
109 flowlabel = *((u_int32_t *)ipv6_hdr(skb)); 110 flowlabel = *((u_int32_t *)ipv6_hdr(skb));
110 111
111 ret = ip6t_do_table(skb, hook, in, out, &packet_mangler); 112 ret = ip6t_do_table(skb, hook, in, out, packet_mangler);
112 113
113 if (ret != NF_DROP && ret != NF_STOLEN 114 if (ret != NF_DROP && ret != NF_STOLEN
114 && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) 115 && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr))
@@ -163,9 +164,9 @@ static int __init ip6table_mangle_init(void)
163 int ret; 164 int ret;
164 165
165 /* Register table */ 166 /* Register table */
166 ret = ip6t_register_table(&packet_mangler, &initial_table.repl); 167 packet_mangler = ip6t_register_table(&__packet_mangler, &initial_table.repl);
167 if (ret < 0) 168 if (IS_ERR(packet_mangler))
168 return ret; 169 return PTR_ERR(packet_mangler);
169 170
170 /* Register hooks */ 171 /* Register hooks */
171 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 172 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
@@ -175,14 +176,14 @@ static int __init ip6table_mangle_init(void)
175 return ret; 176 return ret;
176 177
177 cleanup_table: 178 cleanup_table:
178 ip6t_unregister_table(&packet_mangler); 179 ip6t_unregister_table(packet_mangler);
179 return ret; 180 return ret;
180} 181}
181 182
182static void __exit ip6table_mangle_fini(void) 183static void __exit ip6table_mangle_fini(void)
183{ 184{
184 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 185 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
185 ip6t_unregister_table(&packet_mangler); 186 ip6t_unregister_table(packet_mangler);
186} 187}
187 188
188module_init(ip6table_mangle_init); 189module_init(ip6table_mangle_init);
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index eccbaaa104af..7f55b236440e 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -35,13 +35,14 @@ static struct
35 .term = IP6T_ERROR_INIT, /* ERROR */ 35 .term = IP6T_ERROR_INIT, /* ERROR */
36}; 36};
37 37
38static struct xt_table packet_raw = { 38static struct xt_table __packet_raw = {
39 .name = "raw", 39 .name = "raw",
40 .valid_hooks = RAW_VALID_HOOKS, 40 .valid_hooks = RAW_VALID_HOOKS,
41 .lock = RW_LOCK_UNLOCKED, 41 .lock = RW_LOCK_UNLOCKED,
42 .me = THIS_MODULE, 42 .me = THIS_MODULE,
43 .af = AF_INET6, 43 .af = AF_INET6,
44}; 44};
45static struct xt_table *packet_raw;
45 46
46/* The work comes in here from netfilter.c. */ 47/* The work comes in here from netfilter.c. */
47static unsigned int 48static unsigned int
@@ -51,7 +52,7 @@ ip6t_hook(unsigned int hook,
51 const struct net_device *out, 52 const struct net_device *out,
52 int (*okfn)(struct sk_buff *)) 53 int (*okfn)(struct sk_buff *))
53{ 54{
54 return ip6t_do_table(skb, hook, in, out, &packet_raw); 55 return ip6t_do_table(skb, hook, in, out, packet_raw);
55} 56}
56 57
57static struct nf_hook_ops ip6t_ops[] __read_mostly = { 58static struct nf_hook_ops ip6t_ops[] __read_mostly = {
@@ -76,9 +77,9 @@ static int __init ip6table_raw_init(void)
76 int ret; 77 int ret;
77 78
78 /* Register table */ 79 /* Register table */
79 ret = ip6t_register_table(&packet_raw, &initial_table.repl); 80 packet_raw = ip6t_register_table(&__packet_raw, &initial_table.repl);
80 if (ret < 0) 81 if (IS_ERR(packet_raw))
81 return ret; 82 return PTR_ERR(packet_raw);
82 83
83 /* Register hooks */ 84 /* Register hooks */
84 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 85 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
@@ -88,14 +89,14 @@ static int __init ip6table_raw_init(void)
88 return ret; 89 return ret;
89 90
90 cleanup_table: 91 cleanup_table:
91 ip6t_unregister_table(&packet_raw); 92 ip6t_unregister_table(packet_raw);
92 return ret; 93 return ret;
93} 94}
94 95
95static void __exit ip6table_raw_fini(void) 96static void __exit ip6table_raw_fini(void)
96{ 97{
97 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 98 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
98 ip6t_unregister_table(&packet_raw); 99 ip6t_unregister_table(packet_raw);
99} 100}
100 101
101module_init(ip6table_raw_init); 102module_init(ip6table_raw_init);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index d62f722ccccb..d7fbb1bb92ea 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -667,9 +667,16 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
667 struct xt_table_info *private; 667 struct xt_table_info *private;
668 struct xt_table *t; 668 struct xt_table *t;
669 669
670 /* Don't add one object to multiple lists. */
671 table = kmemdup(table, sizeof(struct xt_table), GFP_KERNEL);
672 if (!table) {
673 ret = -ENOMEM;
674 goto out;
675 }
676
670 ret = mutex_lock_interruptible(&xt[table->af].mutex); 677 ret = mutex_lock_interruptible(&xt[table->af].mutex);
671 if (ret != 0) 678 if (ret != 0)
672 goto out; 679 goto out_free;
673 680
674 /* Don't autoload: we'd eat our tail... */ 681 /* Don't autoload: we'd eat our tail... */
675 list_for_each_entry(t, &net->xt.tables[table->af], list) { 682 list_for_each_entry(t, &net->xt.tables[table->af], list) {
@@ -697,6 +704,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table,
697 704
698 unlock: 705 unlock:
699 mutex_unlock(&xt[table->af].mutex); 706 mutex_unlock(&xt[table->af].mutex);
707out_free:
708 kfree(table);
700out: 709out:
701 return ERR_PTR(ret); 710 return ERR_PTR(ret);
702} 711}
@@ -710,6 +719,7 @@ void *xt_unregister_table(struct xt_table *table)
710 private = table->private; 719 private = table->private;
711 list_del(&table->list); 720 list_del(&table->list);
712 mutex_unlock(&xt[table->af].mutex); 721 mutex_unlock(&xt[table->af].mutex);
722 kfree(table);
713 723
714 return private; 724 return private;
715} 725}