aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGao feng <gaofeng@cn.fujitus.com>2012-05-28 17:04:09 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2012-06-07 08:58:39 -0400
commit2c352f444ccfa966a1aa4fd8e9ee29381c467448 (patch)
treebefcba86ddf2cdbd73d15e1e2620439158c8e2f4
parentfdb694a01f1fcd30fd16d8aa290c34699fe98a17 (diff)
netfilter: nf_conntrack: prepare namespace support for l4 protocol trackers
This patch prepares the namespace support for layer 4 protocol trackers. Basically, this modifies the following interfaces: * nf_ct_[un]register_sysctl * nf_conntrack_l4proto_[un]register to include the namespace parameter. We still use init_net in this patch to prepare the ground for follow-up patches for each layer 4 protocol tracker. We add a new net_id field to struct nf_conntrack_l4proto that is used to store the pernet_operations id for each layer 4 protocol tracker. Note that AF_INET6's protocols do not need to do sysctl compat. Thus, we only register compat sysctl when l4proto.l3proto != AF_INET6. Acked-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h11
-rw-r--r--include/net/netns/conntrack.h12
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c18
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c18
-rw-r--r--net/netfilter/nf_conntrack_proto.c143
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c10
9 files changed, 159 insertions, 79 deletions
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 3b572bb20aa2..d621c91de5c8 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -12,6 +12,7 @@
12#include <linux/netlink.h> 12#include <linux/netlink.h>
13#include <net/netlink.h> 13#include <net/netlink.h>
14#include <net/netfilter/nf_conntrack.h> 14#include <net/netfilter/nf_conntrack.h>
15#include <net/netns/generic.h>
15 16
16struct seq_file; 17struct seq_file;
17 18
@@ -103,6 +104,10 @@ struct nf_conntrack_l4proto {
103 struct ctl_table *ctl_compat_table; 104 struct ctl_table *ctl_compat_table;
104#endif 105#endif
105#endif 106#endif
107 int *net_id;
108 /* Init l4proto pernet data */
109 int (*init_net)(struct net *net);
110
106 /* Protocol name */ 111 /* Protocol name */
107 const char *name; 112 const char *name;
108 113
@@ -123,8 +128,10 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
123extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); 128extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
124 129
125/* Protocol registration. */ 130/* Protocol registration. */
126extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); 131extern int nf_conntrack_l4proto_register(struct net *net,
127extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); 132 struct nf_conntrack_l4proto *proto);
133extern void nf_conntrack_l4proto_unregister(struct net *net,
134 struct nf_conntrack_l4proto *proto);
128 135
129/* Generic netlink helpers */ 136/* Generic netlink helpers */
130extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, 137extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index a053a19870cf..1f53038b0d1b 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -8,6 +8,18 @@
8struct ctl_table_header; 8struct ctl_table_header;
9struct nf_conntrack_ecache; 9struct nf_conntrack_ecache;
10 10
11struct nf_proto_net {
12#ifdef CONFIG_SYSCTL
13 struct ctl_table_header *ctl_table_header;
14 struct ctl_table *ctl_table;
15#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
16 struct ctl_table_header *ctl_compat_header;
17 struct ctl_table *ctl_compat_table;
18#endif
19#endif
20 unsigned int users;
21};
22
11struct netns_ct { 23struct netns_ct {
12 atomic_t count; 24 atomic_t count;
13 unsigned int expect_count; 25 unsigned int expect_count;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 91747d4ebc26..46ec515db129 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -391,19 +391,19 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
391 return ret; 391 return ret;
392 } 392 }
393 393
394 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); 394 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_tcp4);
395 if (ret < 0) { 395 if (ret < 0) {
396 pr_err("nf_conntrack_ipv4: can't register tcp.\n"); 396 pr_err("nf_conntrack_ipv4: can't register tcp.\n");
397 goto cleanup_sockopt; 397 goto cleanup_sockopt;
398 } 398 }
399 399
400 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4); 400 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_udp4);
401 if (ret < 0) { 401 if (ret < 0) {
402 pr_err("nf_conntrack_ipv4: can't register udp.\n"); 402 pr_err("nf_conntrack_ipv4: can't register udp.\n");
403 goto cleanup_tcp; 403 goto cleanup_tcp;
404 } 404 }
405 405
406 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp); 406 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_icmp);
407 if (ret < 0) { 407 if (ret < 0) {
408 pr_err("nf_conntrack_ipv4: can't register icmp.\n"); 408 pr_err("nf_conntrack_ipv4: can't register icmp.\n");
409 goto cleanup_udp; 409 goto cleanup_udp;
@@ -434,11 +434,11 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
434 cleanup_ipv4: 434 cleanup_ipv4:
435 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 435 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
436 cleanup_icmp: 436 cleanup_icmp:
437 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); 437 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_icmp);
438 cleanup_udp: 438 cleanup_udp:
439 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); 439 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udp4);
440 cleanup_tcp: 440 cleanup_tcp:
441 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); 441 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_tcp4);
442 cleanup_sockopt: 442 cleanup_sockopt:
443 nf_unregister_sockopt(&so_getorigdst); 443 nf_unregister_sockopt(&so_getorigdst);
444 return ret; 444 return ret;
@@ -452,9 +452,9 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
452#endif 452#endif
453 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 453 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
454 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 454 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
455 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); 455 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_icmp);
456 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); 456 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udp4);
457 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); 457 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_tcp4);
458 nf_unregister_sockopt(&so_getorigdst); 458 nf_unregister_sockopt(&so_getorigdst);
459} 459}
460 460
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 3224ef90a21a..51ad9f104421 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -340,19 +340,19 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
340 need_conntrack(); 340 need_conntrack();
341 nf_defrag_ipv6_enable(); 341 nf_defrag_ipv6_enable();
342 342
343 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); 343 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_tcp6);
344 if (ret < 0) { 344 if (ret < 0) {
345 pr_err("nf_conntrack_ipv6: can't register tcp.\n"); 345 pr_err("nf_conntrack_ipv6: can't register tcp.\n");
346 return ret; 346 return ret;
347 } 347 }
348 348
349 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); 349 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_udp6);
350 if (ret < 0) { 350 if (ret < 0) {
351 pr_err("nf_conntrack_ipv6: can't register udp.\n"); 351 pr_err("nf_conntrack_ipv6: can't register udp.\n");
352 goto cleanup_tcp; 352 goto cleanup_tcp;
353 } 353 }
354 354
355 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); 355 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_icmpv6);
356 if (ret < 0) { 356 if (ret < 0) {
357 pr_err("nf_conntrack_ipv6: can't register icmpv6.\n"); 357 pr_err("nf_conntrack_ipv6: can't register icmpv6.\n");
358 goto cleanup_udp; 358 goto cleanup_udp;
@@ -376,11 +376,11 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
376 cleanup_ipv6: 376 cleanup_ipv6:
377 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); 377 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
378 cleanup_icmpv6: 378 cleanup_icmpv6:
379 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); 379 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_icmpv6);
380 cleanup_udp: 380 cleanup_udp:
381 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); 381 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udp6);
382 cleanup_tcp: 382 cleanup_tcp:
383 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); 383 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_tcp6);
384 return ret; 384 return ret;
385} 385}
386 386
@@ -389,9 +389,9 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
389 synchronize_net(); 389 synchronize_net();
390 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); 390 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
391 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); 391 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
392 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); 392 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_icmpv6);
393 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); 393 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udp6);
394 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); 394 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_tcp6);
395} 395}
396 396
397module_init(nf_conntrack_l3proto_ipv6_init); 397module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 8b631b07a645..7ee31ac0a12c 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -36,28 +36,35 @@ static DEFINE_MUTEX(nf_ct_proto_mutex);
36 36
37#ifdef CONFIG_SYSCTL 37#ifdef CONFIG_SYSCTL
38static int 38static int
39nf_ct_register_sysctl(struct ctl_table_header **header, const char *path, 39nf_ct_register_sysctl(struct net *net,
40 struct ctl_table *table, unsigned int *users) 40 struct ctl_table_header **header,
41 const char *path,
42 struct ctl_table *table,
43 unsigned int *users)
41{ 44{
42 if (*header == NULL) { 45 if (*header == NULL) {
43 *header = register_net_sysctl(&init_net, path, table); 46 *header = register_net_sysctl(net, path, table);
44 if (*header == NULL) 47 if (*header == NULL)
45 return -ENOMEM; 48 return -ENOMEM;
46 } 49 }
47 if (users != NULL) 50 if (users != NULL)
48 (*users)++; 51 (*users)++;
52
49 return 0; 53 return 0;
50} 54}
51 55
52static void 56static void
53nf_ct_unregister_sysctl(struct ctl_table_header **header, 57nf_ct_unregister_sysctl(struct ctl_table_header **header,
54 struct ctl_table *table, unsigned int *users) 58 struct ctl_table **table,
59 unsigned int *users)
55{ 60{
56 if (users != NULL && --*users > 0) 61 if (users != NULL && --*users > 0)
57 return; 62 return;
58 63
59 unregister_net_sysctl_table(*header); 64 unregister_net_sysctl_table(*header);
65 kfree(*table);
60 *header = NULL; 66 *header = NULL;
67 *table = NULL;
61} 68}
62#endif 69#endif
63 70
@@ -167,7 +174,8 @@ static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
167 174
168#ifdef CONFIG_SYSCTL 175#ifdef CONFIG_SYSCTL
169 if (l3proto->ctl_table != NULL) { 176 if (l3proto->ctl_table != NULL) {
170 err = nf_ct_register_sysctl(&l3proto->ctl_table_header, 177 err = nf_ct_register_sysctl(&init_net,
178 &l3proto->ctl_table_header,
171 l3proto->ctl_table_path, 179 l3proto->ctl_table_path,
172 l3proto->ctl_table, NULL); 180 l3proto->ctl_table, NULL);
173 } 181 }
@@ -180,7 +188,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto
180#ifdef CONFIG_SYSCTL 188#ifdef CONFIG_SYSCTL
181 if (l3proto->ctl_table_header != NULL) 189 if (l3proto->ctl_table_header != NULL)
182 nf_ct_unregister_sysctl(&l3proto->ctl_table_header, 190 nf_ct_unregister_sysctl(&l3proto->ctl_table_header,
183 l3proto->ctl_table, NULL); 191 &l3proto->ctl_table, NULL);
184#endif 192#endif
185} 193}
186 194
@@ -243,29 +251,54 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
243} 251}
244EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); 252EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
245 253
246static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) 254static struct nf_proto_net *nf_ct_l4proto_net(struct net *net,
255 struct nf_conntrack_l4proto *l4proto)
256{
257 if (l4proto->net_id)
258 return net_generic(net, *l4proto->net_id);
259 else
260 return NULL;
261}
262
263static
264int nf_ct_l4proto_register_sysctl(struct net *net,
265 struct nf_conntrack_l4proto *l4proto)
247{ 266{
248 int err = 0; 267 int err = 0;
268 struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto);
269 if (pn == NULL)
270 return 0;
249 271
250#ifdef CONFIG_SYSCTL 272#ifdef CONFIG_SYSCTL
251 if (l4proto->ctl_table != NULL) { 273 if (pn->ctl_table != NULL) {
252 err = nf_ct_register_sysctl(l4proto->ctl_table_header, 274 err = nf_ct_register_sysctl(net,
275 &pn->ctl_table_header,
253 "net/netfilter", 276 "net/netfilter",
254 l4proto->ctl_table, 277 pn->ctl_table,
255 l4proto->ctl_table_users); 278 &pn->users);
256 if (err < 0) 279 if (err < 0) {
280 if (!pn->users) {
281 kfree(pn->ctl_table);
282 pn->ctl_table = NULL;
283 }
257 goto out; 284 goto out;
285 }
258 } 286 }
259#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 287#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
260 if (l4proto->ctl_compat_table != NULL) { 288 if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_table != NULL) {
261 err = nf_ct_register_sysctl(&l4proto->ctl_compat_table_header, 289 err = nf_ct_register_sysctl(net,
290 &pn->ctl_compat_header,
262 "net/ipv4/netfilter", 291 "net/ipv4/netfilter",
263 l4proto->ctl_compat_table, NULL); 292 pn->ctl_compat_table,
293 NULL);
264 if (err == 0) 294 if (err == 0)
265 goto out; 295 goto out;
266 nf_ct_unregister_sysctl(l4proto->ctl_table_header, 296
267 l4proto->ctl_table, 297 kfree(pn->ctl_compat_table);
268 l4proto->ctl_table_users); 298 pn->ctl_compat_table = NULL;
299 nf_ct_unregister_sysctl(&pn->ctl_table_header,
300 &pn->ctl_table,
301 &pn->users);
269 } 302 }
270#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 303#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
271out: 304out:
@@ -273,25 +306,34 @@ out:
273 return err; 306 return err;
274} 307}
275 308
276static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto) 309static
310void nf_ct_l4proto_unregister_sysctl(struct net *net,
311 struct nf_conntrack_l4proto *l4proto)
277{ 312{
313 struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto);
314 if (pn == NULL)
315 return;
278#ifdef CONFIG_SYSCTL 316#ifdef CONFIG_SYSCTL
279 if (l4proto->ctl_table_header != NULL && 317 if (pn->ctl_table_header != NULL)
280 *l4proto->ctl_table_header != NULL) 318 nf_ct_unregister_sysctl(&pn->ctl_table_header,
281 nf_ct_unregister_sysctl(l4proto->ctl_table_header, 319 &pn->ctl_table,
282 l4proto->ctl_table, 320 &pn->users);
283 l4proto->ctl_table_users); 321
284#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT 322#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
285 if (l4proto->ctl_compat_table_header != NULL) 323 if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_header != NULL)
286 nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header, 324 nf_ct_unregister_sysctl(&pn->ctl_compat_header,
287 l4proto->ctl_compat_table, NULL); 325 &pn->ctl_compat_table,
326 NULL);
288#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 327#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
328#else
329 pn->users--;
289#endif /* CONFIG_SYSCTL */ 330#endif /* CONFIG_SYSCTL */
290} 331}
291 332
292/* FIXME: Allow NULL functions and sub in pointers to generic for 333/* FIXME: Allow NULL functions and sub in pointers to generic for
293 them. --RR */ 334 them. --RR */
294int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) 335static int
336nf_conntrack_l4proto_register_net(struct nf_conntrack_l4proto *l4proto)
295{ 337{
296 int ret = 0; 338 int ret = 0;
297 339
@@ -333,10 +375,6 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
333 goto out_unlock; 375 goto out_unlock;
334 } 376 }
335 377
336 ret = nf_ct_l4proto_register_sysctl(l4proto);
337 if (ret < 0)
338 goto out_unlock;
339
340 l4proto->nla_size = 0; 378 l4proto->nla_size = 0;
341 if (l4proto->nlattr_size) 379 if (l4proto->nlattr_size)
342 l4proto->nla_size += l4proto->nlattr_size(); 380 l4proto->nla_size += l4proto->nlattr_size();
@@ -345,17 +383,34 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
345 383
346 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 384 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
347 l4proto); 385 l4proto);
348
349out_unlock: 386out_unlock:
350 mutex_unlock(&nf_ct_proto_mutex); 387 mutex_unlock(&nf_ct_proto_mutex);
351 return ret; 388 return ret;
352} 389}
353EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
354 390
355void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) 391int nf_conntrack_l4proto_register(struct net *net,
392 struct nf_conntrack_l4proto *l4proto)
356{ 393{
357 struct net *net; 394 int ret = 0;
395 if (net == &init_net)
396 ret = nf_conntrack_l4proto_register_net(l4proto);
397
398 if (ret < 0)
399 return ret;
400
401 if (l4proto->init_net)
402 ret = l4proto->init_net(net);
358 403
404 if (ret < 0)
405 return ret;
406
407 return nf_ct_l4proto_register_sysctl(net, l4proto);
408}
409EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register);
410
411static void
412nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto)
413{
359 BUG_ON(l4proto->l3proto >= PF_MAX); 414 BUG_ON(l4proto->l3proto >= PF_MAX);
360 415
361 mutex_lock(&nf_ct_proto_mutex); 416 mutex_lock(&nf_ct_proto_mutex);
@@ -365,15 +420,21 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
365 ) != l4proto); 420 ) != l4proto);
366 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 421 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
367 &nf_conntrack_l4proto_generic); 422 &nf_conntrack_l4proto_generic);
368 nf_ct_l4proto_unregister_sysctl(l4proto);
369 mutex_unlock(&nf_ct_proto_mutex); 423 mutex_unlock(&nf_ct_proto_mutex);
370 424
371 synchronize_rcu(); 425 synchronize_rcu();
426}
372 427
428void nf_conntrack_l4proto_unregister(struct net *net,
429 struct nf_conntrack_l4proto *l4proto)
430{
431 if (net == &init_net)
432 nf_conntrack_l4proto_unregister_net(l4proto);
433
434 nf_ct_l4proto_unregister_sysctl(net, l4proto);
373 /* Remove all contrack entries for this protocol */ 435 /* Remove all contrack entries for this protocol */
374 rtnl_lock(); 436 rtnl_lock();
375 for_each_net(net) 437 nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
376 nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
377 rtnl_unlock(); 438 rtnl_unlock();
378} 439}
379EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); 440EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
@@ -383,7 +444,7 @@ int nf_conntrack_proto_init(void)
383 unsigned int i; 444 unsigned int i;
384 int err; 445 int err;
385 446
386 err = nf_ct_l4proto_register_sysctl(&nf_conntrack_l4proto_generic); 447 err = nf_ct_l4proto_register_sysctl(&init_net, &nf_conntrack_l4proto_generic);
387 if (err < 0) 448 if (err < 0)
388 return err; 449 return err;
389 450
@@ -397,7 +458,7 @@ void nf_conntrack_proto_fini(void)
397{ 458{
398 unsigned int i; 459 unsigned int i;
399 460
400 nf_ct_l4proto_unregister_sysctl(&nf_conntrack_l4proto_generic); 461 nf_ct_l4proto_unregister_sysctl(&init_net, &nf_conntrack_l4proto_generic);
401 462
402 /* free l3proto protocol tables */ 463 /* free l3proto protocol tables */
403 for (i = 0; i < PF_MAX; i++) 464 for (i = 0; i < PF_MAX; i++)
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index ef706a485be1..5a8e03724289 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -945,17 +945,17 @@ static int __init nf_conntrack_proto_dccp_init(void)
945 if (err < 0) 945 if (err < 0)
946 goto err1; 946 goto err1;
947 947
948 err = nf_conntrack_l4proto_register(&dccp_proto4); 948 err = nf_conntrack_l4proto_register(&init_net, &dccp_proto4);
949 if (err < 0) 949 if (err < 0)
950 goto err2; 950 goto err2;
951 951
952 err = nf_conntrack_l4proto_register(&dccp_proto6); 952 err = nf_conntrack_l4proto_register(&init_net, &dccp_proto6);
953 if (err < 0) 953 if (err < 0)
954 goto err3; 954 goto err3;
955 return 0; 955 return 0;
956 956
957err3: 957err3:
958 nf_conntrack_l4proto_unregister(&dccp_proto4); 958 nf_conntrack_l4proto_unregister(&init_net, &dccp_proto4);
959err2: 959err2:
960 unregister_pernet_subsys(&dccp_net_ops); 960 unregister_pernet_subsys(&dccp_net_ops);
961err1: 961err1:
@@ -965,8 +965,8 @@ err1:
965static void __exit nf_conntrack_proto_dccp_fini(void) 965static void __exit nf_conntrack_proto_dccp_fini(void)
966{ 966{
967 unregister_pernet_subsys(&dccp_net_ops); 967 unregister_pernet_subsys(&dccp_net_ops);
968 nf_conntrack_l4proto_unregister(&dccp_proto6); 968 nf_conntrack_l4proto_unregister(&init_net, &dccp_proto6);
969 nf_conntrack_l4proto_unregister(&dccp_proto4); 969 nf_conntrack_l4proto_unregister(&init_net, &dccp_proto4);
970} 970}
971 971
972module_init(nf_conntrack_proto_dccp_init); 972module_init(nf_conntrack_proto_dccp_init);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 4bf6b4e4b776..132f0d2d82cc 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -396,18 +396,18 @@ static int __init nf_ct_proto_gre_init(void)
396{ 396{
397 int rv; 397 int rv;
398 398
399 rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4); 399 rv = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_gre4);
400 if (rv < 0) 400 if (rv < 0)
401 return rv; 401 return rv;
402 rv = register_pernet_subsys(&proto_gre_net_ops); 402 rv = register_pernet_subsys(&proto_gre_net_ops);
403 if (rv < 0) 403 if (rv < 0)
404 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); 404 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_gre4);
405 return rv; 405 return rv;
406} 406}
407 407
408static void __exit nf_ct_proto_gre_fini(void) 408static void __exit nf_ct_proto_gre_fini(void)
409{ 409{
410 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); 410 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_gre4);
411 unregister_pernet_subsys(&proto_gre_net_ops); 411 unregister_pernet_subsys(&proto_gre_net_ops);
412} 412}
413 413
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 996db2fa21f7..97bbc20e1a2b 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -791,12 +791,12 @@ static int __init nf_conntrack_proto_sctp_init(void)
791{ 791{
792 int ret; 792 int ret;
793 793
794 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4); 794 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp4);
795 if (ret) { 795 if (ret) {
796 pr_err("nf_conntrack_l4proto_sctp4: protocol register failed\n"); 796 pr_err("nf_conntrack_l4proto_sctp4: protocol register failed\n");
797 goto out; 797 goto out;
798 } 798 }
799 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6); 799 ret = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_sctp6);
800 if (ret) { 800 if (ret) {
801 pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n"); 801 pr_err("nf_conntrack_l4proto_sctp6: protocol register failed\n");
802 goto cleanup_sctp4; 802 goto cleanup_sctp4;
@@ -805,15 +805,15 @@ static int __init nf_conntrack_proto_sctp_init(void)
805 return ret; 805 return ret;
806 806
807 cleanup_sctp4: 807 cleanup_sctp4:
808 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); 808 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4);
809 out: 809 out:
810 return ret; 810 return ret;
811} 811}
812 812
813static void __exit nf_conntrack_proto_sctp_fini(void) 813static void __exit nf_conntrack_proto_sctp_fini(void)
814{ 814{
815 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6); 815 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp6);
816 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4); 816 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_sctp4);
817} 817}
818 818
819module_init(nf_conntrack_proto_sctp_init); 819module_init(nf_conntrack_proto_sctp_init);
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 4d60a5376aa6..fa142a81496c 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -299,23 +299,23 @@ static int __init nf_conntrack_proto_udplite_init(void)
299{ 299{
300 int err; 300 int err;
301 301
302 err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4); 302 err = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_udplite4);
303 if (err < 0) 303 if (err < 0)
304 goto err1; 304 goto err1;
305 err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6); 305 err = nf_conntrack_l4proto_register(&init_net, &nf_conntrack_l4proto_udplite6);
306 if (err < 0) 306 if (err < 0)
307 goto err2; 307 goto err2;
308 return 0; 308 return 0;
309err2: 309err2:
310 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); 310 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udplite4);
311err1: 311err1:
312 return err; 312 return err;
313} 313}
314 314
315static void __exit nf_conntrack_proto_udplite_exit(void) 315static void __exit nf_conntrack_proto_udplite_exit(void)
316{ 316{
317 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6); 317 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udplite6);
318 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); 318 nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udplite4);
319} 319}
320 320
321module_init(nf_conntrack_proto_udplite_init); 321module_init(nf_conntrack_proto_udplite_init);