diff options
author | Gao feng <gaofeng@cn.fujitus.com> | 2012-05-28 17:04:09 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-06-07 08:58:39 -0400 |
commit | 2c352f444ccfa966a1aa4fd8e9ee29381c467448 (patch) | |
tree | befcba86ddf2cdbd73d15e1e2620439158c8e2f4 | |
parent | fdb694a01f1fcd30fd16d8aa290c34699fe98a17 (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.h | 11 | ||||
-rw-r--r-- | include/net/netns/conntrack.h | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 18 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 18 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 143 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_dccp.c | 10 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 6 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_sctp.c | 10 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_udplite.c | 10 |
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 | ||
16 | struct seq_file; | 17 | struct 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); | |||
123 | extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); | 128 | extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); |
124 | 129 | ||
125 | /* Protocol registration. */ | 130 | /* Protocol registration. */ |
126 | extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); | 131 | extern int nf_conntrack_l4proto_register(struct net *net, |
127 | extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); | 132 | struct nf_conntrack_l4proto *proto); |
133 | extern void nf_conntrack_l4proto_unregister(struct net *net, | ||
134 | struct nf_conntrack_l4proto *proto); | ||
128 | 135 | ||
129 | /* Generic netlink helpers */ | 136 | /* Generic netlink helpers */ |
130 | extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, | 137 | extern 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 @@ | |||
8 | struct ctl_table_header; | 8 | struct ctl_table_header; |
9 | struct nf_conntrack_ecache; | 9 | struct nf_conntrack_ecache; |
10 | 10 | ||
11 | struct 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 | |||
11 | struct netns_ct { | 23 | struct 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 | ||
397 | module_init(nf_conntrack_l3proto_ipv6_init); | 397 | module_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 |
38 | static int | 38 | static int |
39 | nf_ct_register_sysctl(struct ctl_table_header **header, const char *path, | 39 | nf_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 | ||
52 | static void | 56 | static void |
53 | nf_ct_unregister_sysctl(struct ctl_table_header **header, | 57 | nf_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 | } |
244 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); | 252 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); |
245 | 253 | ||
246 | static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto) | 254 | static 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 | |||
263 | static | ||
264 | int 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 */ |
271 | out: | 304 | out: |
@@ -273,25 +306,34 @@ out: | |||
273 | return err; | 306 | return err; |
274 | } | 307 | } |
275 | 308 | ||
276 | static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto) | 309 | static |
310 | void 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 */ |
294 | int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) | 335 | static int |
336 | nf_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 | |||
349 | out_unlock: | 386 | out_unlock: |
350 | mutex_unlock(&nf_ct_proto_mutex); | 387 | mutex_unlock(&nf_ct_proto_mutex); |
351 | return ret; | 388 | return ret; |
352 | } | 389 | } |
353 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); | ||
354 | 390 | ||
355 | void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) | 391 | int 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 | } | ||
409 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); | ||
410 | |||
411 | static void | ||
412 | nf_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 | ||
428 | void 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 | } |
379 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); | 440 | EXPORT_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 | ||
957 | err3: | 957 | err3: |
958 | nf_conntrack_l4proto_unregister(&dccp_proto4); | 958 | nf_conntrack_l4proto_unregister(&init_net, &dccp_proto4); |
959 | err2: | 959 | err2: |
960 | unregister_pernet_subsys(&dccp_net_ops); | 960 | unregister_pernet_subsys(&dccp_net_ops); |
961 | err1: | 961 | err1: |
@@ -965,8 +965,8 @@ err1: | |||
965 | static void __exit nf_conntrack_proto_dccp_fini(void) | 965 | static 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 | ||
972 | module_init(nf_conntrack_proto_dccp_init); | 972 | module_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 | ||
408 | static void __exit nf_ct_proto_gre_fini(void) | 408 | static 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 | ||
813 | static void __exit nf_conntrack_proto_sctp_fini(void) | 813 | static 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 | ||
819 | module_init(nf_conntrack_proto_sctp_init); | 819 | module_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; |
309 | err2: | 309 | err2: |
310 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); | 310 | nf_conntrack_l4proto_unregister(&init_net, &nf_conntrack_l4proto_udplite4); |
311 | err1: | 311 | err1: |
312 | return err; | 312 | return err; |
313 | } | 313 | } |
314 | 314 | ||
315 | static void __exit nf_conntrack_proto_udplite_exit(void) | 315 | static 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 | ||
321 | module_init(nf_conntrack_proto_udplite_init); | 321 | module_init(nf_conntrack_proto_udplite_init); |