diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index bde50c686722..3ad081e9366b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4135,6 +4135,70 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
4135 | 4135 | ||
4136 | #endif | 4136 | #endif |
4137 | 4137 | ||
4138 | static int addrconf_init_net(struct net *net) | ||
4139 | { | ||
4140 | int err; | ||
4141 | struct ipv6_devconf *all, *dflt; | ||
4142 | |||
4143 | err = -ENOMEM; | ||
4144 | all = &ipv6_devconf; | ||
4145 | dflt = &ipv6_devconf_dflt; | ||
4146 | |||
4147 | if (net != &init_net) { | ||
4148 | all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); | ||
4149 | if (all == NULL) | ||
4150 | goto err_alloc_all; | ||
4151 | |||
4152 | dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); | ||
4153 | if (dflt == NULL) | ||
4154 | goto err_alloc_dflt; | ||
4155 | } | ||
4156 | |||
4157 | net->ipv6.devconf_all = all; | ||
4158 | net->ipv6.devconf_dflt = dflt; | ||
4159 | |||
4160 | #ifdef CONFIG_SYSCTL | ||
4161 | err = __addrconf_sysctl_register(net, "all", NET_PROTO_CONF_ALL, | ||
4162 | NULL, all); | ||
4163 | if (err < 0) | ||
4164 | goto err_reg_all; | ||
4165 | |||
4166 | err = __addrconf_sysctl_register(net, "default", NET_PROTO_CONF_DEFAULT, | ||
4167 | NULL, dflt); | ||
4168 | if (err < 0) | ||
4169 | goto err_reg_dflt; | ||
4170 | #endif | ||
4171 | return 0; | ||
4172 | |||
4173 | #ifdef CONFIG_SYSCTL | ||
4174 | err_reg_dflt: | ||
4175 | __addrconf_sysctl_unregister(all); | ||
4176 | err_reg_all: | ||
4177 | kfree(dflt); | ||
4178 | #endif | ||
4179 | err_alloc_dflt: | ||
4180 | kfree(all); | ||
4181 | err_alloc_all: | ||
4182 | return err; | ||
4183 | } | ||
4184 | |||
4185 | static void addrconf_exit_net(struct net *net) | ||
4186 | { | ||
4187 | #ifdef CONFIG_SYSCTL | ||
4188 | __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); | ||
4189 | __addrconf_sysctl_unregister(net->ipv6.devconf_all); | ||
4190 | #endif | ||
4191 | if (net != &init_net) { | ||
4192 | kfree(net->ipv6.devconf_dflt); | ||
4193 | kfree(net->ipv6.devconf_all); | ||
4194 | } | ||
4195 | } | ||
4196 | |||
4197 | static struct pernet_operations addrconf_ops = { | ||
4198 | .init = addrconf_init_net, | ||
4199 | .exit = addrconf_exit_net, | ||
4200 | }; | ||
4201 | |||
4138 | /* | 4202 | /* |
4139 | * Device notifier | 4203 | * Device notifier |
4140 | */ | 4204 | */ |
@@ -4167,6 +4231,8 @@ int __init addrconf_init(void) | |||
4167 | return err; | 4231 | return err; |
4168 | } | 4232 | } |
4169 | 4233 | ||
4234 | register_pernet_subsys(&addrconf_ops); | ||
4235 | |||
4170 | /* The addrconf netdev notifier requires that loopback_dev | 4236 | /* The addrconf netdev notifier requires that loopback_dev |
4171 | * has it's ipv6 private information allocated and setup | 4237 | * has it's ipv6 private information allocated and setup |
4172 | * before it can bring up and give link-local addresses | 4238 | * before it can bring up and give link-local addresses |
@@ -4190,7 +4256,7 @@ int __init addrconf_init(void) | |||
4190 | err = -ENOMEM; | 4256 | err = -ENOMEM; |
4191 | rtnl_unlock(); | 4257 | rtnl_unlock(); |
4192 | if (err) | 4258 | if (err) |
4193 | return err; | 4259 | goto errlo; |
4194 | 4260 | ||
4195 | ip6_null_entry.u.dst.dev = init_net.loopback_dev; | 4261 | ip6_null_entry.u.dst.dev = init_net.loopback_dev; |
4196 | ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); | 4262 | ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev); |
@@ -4218,16 +4284,11 @@ int __init addrconf_init(void) | |||
4218 | 4284 | ||
4219 | ipv6_addr_label_rtnl_register(); | 4285 | ipv6_addr_label_rtnl_register(); |
4220 | 4286 | ||
4221 | #ifdef CONFIG_SYSCTL | ||
4222 | __addrconf_sysctl_register(&init_net, "all", NET_PROTO_CONF_ALL, | ||
4223 | NULL, &ipv6_devconf); | ||
4224 | __addrconf_sysctl_register(&init_net, "default", NET_PROTO_CONF_DEFAULT, | ||
4225 | NULL, &ipv6_devconf_dflt); | ||
4226 | #endif | ||
4227 | |||
4228 | return 0; | 4287 | return 0; |
4229 | errout: | 4288 | errout: |
4230 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4289 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4290 | errlo: | ||
4291 | unregister_pernet_subsys(&addrconf_ops); | ||
4231 | 4292 | ||
4232 | return err; | 4293 | return err; |
4233 | } | 4294 | } |
@@ -4240,10 +4301,7 @@ void addrconf_cleanup(void) | |||
4240 | 4301 | ||
4241 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4302 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4242 | 4303 | ||
4243 | #ifdef CONFIG_SYSCTL | 4304 | unregister_pernet_subsys(&addrconf_ops); |
4244 | __addrconf_sysctl_unregister(&ipv6_devconf_dflt); | ||
4245 | __addrconf_sysctl_unregister(&ipv6_devconf); | ||
4246 | #endif | ||
4247 | 4305 | ||
4248 | rtnl_lock(); | 4306 | rtnl_lock(); |
4249 | 4307 | ||