diff options
author | Daniel Lezcano <dlezcano@fr.ibm.com> | 2008-01-10 05:53:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:01:17 -0500 |
commit | 760f2d0186225f06d46e07232d65219c5055cad3 (patch) | |
tree | 56096a88e003753434c135d22ffab8f4f9904bc6 | |
parent | 89918fc270bb77cb1a0703f0ea566a692b32e324 (diff) |
[NETNS][IPV6]: Make multiple instance of sysctl tables.
Each network namespace wants its own set of sysctl value, eg. we
should not be able from a namespace to set a sysctl value for another
namespace , especially for the initial network namespace.
This patch duplicates the sysctl table when we register a new network
namespace for ipv6. The duplicated table are postfixed with the
"template" word to notify the developper the table is cloned.
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ipv6.h | 4 | ||||
-rw-r--r-- | include/net/netns/ipv6.h | 9 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 12 | ||||
-rw-r--r-- | net/ipv6/route.c | 11 | ||||
-rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 67 |
5 files changed, 89 insertions, 14 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 3e086f8bb449..5519035491e7 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -619,8 +619,8 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) | |||
619 | #endif | 619 | #endif |
620 | 620 | ||
621 | #ifdef CONFIG_SYSCTL | 621 | #ifdef CONFIG_SYSCTL |
622 | extern ctl_table ipv6_route_table[]; | 622 | extern ctl_table ipv6_route_table_template[]; |
623 | extern ctl_table ipv6_icmp_table[]; | 623 | extern ctl_table ipv6_icmp_table_template[]; |
624 | 624 | ||
625 | extern int ipv6_sysctl_register(void); | 625 | extern int ipv6_sysctl_register(void); |
626 | extern void ipv6_sysctl_unregister(void); | 626 | extern void ipv6_sysctl_unregister(void); |
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 6f82046e3013..58fbf30d9fdb 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h | |||
@@ -5,6 +5,15 @@ | |||
5 | #ifndef __NETNS_IPV6_H__ | 5 | #ifndef __NETNS_IPV6_H__ |
6 | #define __NETNS_IPV6_H__ | 6 | #define __NETNS_IPV6_H__ |
7 | 7 | ||
8 | struct ctl_table_header; | ||
9 | |||
10 | struct netns_sysctl_ipv6 { | ||
11 | #ifdef CONFIG_SYSCTL | ||
12 | struct ctl_table_header *table; | ||
13 | #endif | ||
14 | }; | ||
15 | |||
8 | struct netns_ipv6 { | 16 | struct netns_ipv6 { |
17 | struct netns_sysctl_ipv6 sysctl; | ||
9 | }; | 18 | }; |
10 | #endif | 19 | #endif |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index c3bbd8687307..dfe3b37c43e9 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -907,7 +907,7 @@ int icmpv6_err_convert(int type, int code, int *err) | |||
907 | EXPORT_SYMBOL(icmpv6_err_convert); | 907 | EXPORT_SYMBOL(icmpv6_err_convert); |
908 | 908 | ||
909 | #ifdef CONFIG_SYSCTL | 909 | #ifdef CONFIG_SYSCTL |
910 | ctl_table ipv6_icmp_table[] = { | 910 | ctl_table ipv6_icmp_table_template[] = { |
911 | { | 911 | { |
912 | .ctl_name = NET_IPV6_ICMP_RATELIMIT, | 912 | .ctl_name = NET_IPV6_ICMP_RATELIMIT, |
913 | .procname = "ratelimit", | 913 | .procname = "ratelimit", |
@@ -918,5 +918,15 @@ ctl_table ipv6_icmp_table[] = { | |||
918 | }, | 918 | }, |
919 | { .ctl_name = 0 }, | 919 | { .ctl_name = 0 }, |
920 | }; | 920 | }; |
921 | |||
922 | struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) | ||
923 | { | ||
924 | struct ctl_table *table; | ||
925 | |||
926 | table = kmemdup(ipv6_icmp_table_template, | ||
927 | sizeof(ipv6_icmp_table_template), | ||
928 | GFP_KERNEL); | ||
929 | return table; | ||
930 | } | ||
921 | #endif | 931 | #endif |
922 | 932 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b80ef5784207..0c7382f4fb85 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2409,7 +2409,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, | |||
2409 | return -EINVAL; | 2409 | return -EINVAL; |
2410 | } | 2410 | } |
2411 | 2411 | ||
2412 | ctl_table ipv6_route_table[] = { | 2412 | ctl_table ipv6_route_table_template[] = { |
2413 | { | 2413 | { |
2414 | .procname = "flush", | 2414 | .procname = "flush", |
2415 | .data = &flush_delay, | 2415 | .data = &flush_delay, |
@@ -2499,6 +2499,15 @@ ctl_table ipv6_route_table[] = { | |||
2499 | { .ctl_name = 0 } | 2499 | { .ctl_name = 0 } |
2500 | }; | 2500 | }; |
2501 | 2501 | ||
2502 | struct ctl_table *ipv6_route_sysctl_init(struct net *net) | ||
2503 | { | ||
2504 | struct ctl_table *table; | ||
2505 | |||
2506 | table = kmemdup(ipv6_route_table_template, | ||
2507 | sizeof(ipv6_route_table_template), | ||
2508 | GFP_KERNEL); | ||
2509 | return table; | ||
2510 | } | ||
2502 | #endif | 2511 | #endif |
2503 | 2512 | ||
2504 | int __init ip6_route_init(void) | 2513 | int __init ip6_route_init(void) |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 7329decf1f9d..7970f3366f87 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -14,20 +14,23 @@ | |||
14 | #include <net/addrconf.h> | 14 | #include <net/addrconf.h> |
15 | #include <net/inet_frag.h> | 15 | #include <net/inet_frag.h> |
16 | 16 | ||
17 | static ctl_table ipv6_table[] = { | 17 | extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); |
18 | extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); | ||
19 | |||
20 | static ctl_table ipv6_table_template[] = { | ||
18 | { | 21 | { |
19 | .ctl_name = NET_IPV6_ROUTE, | 22 | .ctl_name = NET_IPV6_ROUTE, |
20 | .procname = "route", | 23 | .procname = "route", |
21 | .maxlen = 0, | 24 | .maxlen = 0, |
22 | .mode = 0555, | 25 | .mode = 0555, |
23 | .child = ipv6_route_table | 26 | .child = ipv6_route_table_template |
24 | }, | 27 | }, |
25 | { | 28 | { |
26 | .ctl_name = NET_IPV6_ICMP, | 29 | .ctl_name = NET_IPV6_ICMP, |
27 | .procname = "icmp", | 30 | .procname = "icmp", |
28 | .maxlen = 0, | 31 | .maxlen = 0, |
29 | .mode = 0555, | 32 | .mode = 0555, |
30 | .child = ipv6_icmp_table | 33 | .child = ipv6_icmp_table_template |
31 | }, | 34 | }, |
32 | { | 35 | { |
33 | .ctl_name = NET_IPV6_BINDV6ONLY, | 36 | .ctl_name = NET_IPV6_BINDV6ONLY, |
@@ -89,22 +92,66 @@ struct ctl_path net_ipv6_ctl_path[] = { | |||
89 | }; | 92 | }; |
90 | EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); | 93 | EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); |
91 | 94 | ||
92 | static struct ctl_table_header *ipv6_sysctl_header; | ||
93 | |||
94 | static int ipv6_sysctl_net_init(struct net *net) | 95 | static int ipv6_sysctl_net_init(struct net *net) |
95 | { | 96 | { |
96 | ipv6_sysctl_header = register_net_sysctl_table(net, net_ipv6_ctl_path, | 97 | struct ctl_table *ipv6_table; |
97 | ipv6_table); | 98 | struct ctl_table *ipv6_route_table; |
98 | if (!ipv6_sysctl_header) | 99 | struct ctl_table *ipv6_icmp_table; |
100 | int err; | ||
101 | |||
102 | err = -ENOMEM; | ||
103 | ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template), | ||
104 | GFP_KERNEL); | ||
105 | if (!ipv6_table) | ||
106 | goto out; | ||
107 | |||
108 | ipv6_route_table = ipv6_route_sysctl_init(net); | ||
109 | if (!ipv6_route_table) | ||
110 | goto out_ipv6_table; | ||
111 | |||
112 | ipv6_icmp_table = ipv6_icmp_sysctl_init(net); | ||
113 | if (!ipv6_icmp_table) | ||
114 | goto out_ipv6_route_table; | ||
115 | |||
116 | ipv6_table[0].child = ipv6_route_table; | ||
117 | ipv6_table[1].child = ipv6_icmp_table; | ||
118 | |||
119 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, | ||
120 | ipv6_table); | ||
121 | if (!net->ipv6.sysctl.table) | ||
99 | return -ENOMEM; | 122 | return -ENOMEM; |
100 | 123 | ||
101 | return 0; | 124 | if (!net->ipv6.sysctl.table) |
125 | goto out_ipv6_icmp_table; | ||
126 | |||
127 | err = 0; | ||
128 | out: | ||
129 | return err; | ||
102 | 130 | ||
131 | out_ipv6_icmp_table: | ||
132 | kfree(ipv6_icmp_table); | ||
133 | out_ipv6_route_table: | ||
134 | kfree(ipv6_route_table); | ||
135 | out_ipv6_table: | ||
136 | kfree(ipv6_table); | ||
137 | goto out; | ||
103 | } | 138 | } |
104 | 139 | ||
105 | static void ipv6_sysctl_net_exit(struct net *net) | 140 | static void ipv6_sysctl_net_exit(struct net *net) |
106 | { | 141 | { |
107 | unregister_net_sysctl_table(ipv6_sysctl_header); | 142 | struct ctl_table *ipv6_table; |
143 | struct ctl_table *ipv6_route_table; | ||
144 | struct ctl_table *ipv6_icmp_table; | ||
145 | |||
146 | ipv6_table = net->ipv6.sysctl.table->ctl_table_arg; | ||
147 | ipv6_route_table = ipv6_table[0].child; | ||
148 | ipv6_icmp_table = ipv6_table[1].child; | ||
149 | |||
150 | unregister_net_sysctl_table(net->ipv6.sysctl.table); | ||
151 | |||
152 | kfree(ipv6_table); | ||
153 | kfree(ipv6_route_table); | ||
154 | kfree(ipv6_icmp_table); | ||
108 | } | 155 | } |
109 | 156 | ||
110 | static struct pernet_operations ipv6_sysctl_net_ops = { | 157 | static struct pernet_operations ipv6_sysctl_net_ops = { |