aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@sw.ru>2008-01-31 07:02:44 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:27:36 -0500
commit44d34e721e2c81ccdfb13cf34996309247ae2981 (patch)
treefec2063c8573700fd01cb6c11875769751744603 /net
parent8d870052079d255917ec4f8431f5ec102707b7af (diff)
[NETFILTER]: x_tables: return new table from {arp,ip,ip6}t_register_table()
Typical table module registers xt_table structure (i.e. packet_filter) and link it to list during it. We can't use one template for it because corresponding list_head will become corrupted. We also can't unregister with template because it wasn't changed at all and thus doesn't know in which list it is. So, we duplicate template at the very first step of table registration. Table modules will save it for use during unregistration time and actual filtering. Do it at once to not screw bisection. P.S.: renaming i.e. packet_filter => __packet_filter is temporary until full netnsization of table modules is done. Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-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
12 files changed, 127 insertions, 93 deletions
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}