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 /net/ipv6/sysctl_net_ipv6.c | |
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>
Diffstat (limited to 'net/ipv6/sysctl_net_ipv6.c')
-rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 67 |
1 files changed, 57 insertions, 10 deletions
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 = { |