aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c53
1 files changed, 17 insertions, 36 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f8f76d6e21cb..e83852ab4dc8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -493,15 +493,17 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
493 read_unlock(&dev_base_lock); 493 read_unlock(&dev_base_lock);
494} 494}
495 495
496static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 496static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
497{ 497{
498 struct net *net; 498 struct net *net;
499 499
500 net = (struct net *)table->extra2; 500 net = (struct net *)table->extra2;
501 if (p == &net->ipv6.devconf_dflt->forwarding) 501 if (p == &net->ipv6.devconf_dflt->forwarding)
502 return; 502 return 0;
503
504 if (!rtnl_trylock())
505 return -ERESTARTSYS;
503 506
504 rtnl_lock();
505 if (p == &net->ipv6.devconf_all->forwarding) { 507 if (p == &net->ipv6.devconf_all->forwarding) {
506 __s32 newf = net->ipv6.devconf_all->forwarding; 508 __s32 newf = net->ipv6.devconf_all->forwarding;
507 net->ipv6.devconf_dflt->forwarding = newf; 509 net->ipv6.devconf_dflt->forwarding = newf;
@@ -512,6 +514,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
512 514
513 if (*p) 515 if (*p)
514 rt6_purge_dflt_routers(net); 516 rt6_purge_dflt_routers(net);
517 return 1;
515} 518}
516#endif 519#endif
517 520
@@ -2599,9 +2602,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2599 2602
2600 ASSERT_RTNL(); 2603 ASSERT_RTNL();
2601 2604
2602 if ((dev->flags & IFF_LOOPBACK) && how == 1)
2603 how = 0;
2604
2605 rt6_ifdown(net, dev); 2605 rt6_ifdown(net, dev);
2606 neigh_ifdown(&nd_tbl, dev); 2606 neigh_ifdown(&nd_tbl, dev);
2607 2607
@@ -3977,7 +3977,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
3977 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); 3977 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
3978 3978
3979 if (write) 3979 if (write)
3980 addrconf_fixup_forwarding(ctl, valp, val); 3980 ret = addrconf_fixup_forwarding(ctl, valp, val);
3981 return ret; 3981 return ret;
3982} 3982}
3983 3983
@@ -4013,8 +4013,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
4013 } 4013 }
4014 4014
4015 *valp = new; 4015 *valp = new;
4016 addrconf_fixup_forwarding(table, valp, val); 4016 return addrconf_fixup_forwarding(table, valp, val);
4017 return 1;
4018} 4017}
4019 4018
4020static struct addrconf_sysctl_table 4019static struct addrconf_sysctl_table
@@ -4440,25 +4439,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
4440 4439
4441EXPORT_SYMBOL(unregister_inet6addr_notifier); 4440EXPORT_SYMBOL(unregister_inet6addr_notifier);
4442 4441
4443static void addrconf_net_exit(struct net *net)
4444{
4445 struct net_device *dev;
4446
4447 rtnl_lock();
4448 /* clean dev list */
4449 for_each_netdev(net, dev) {
4450 if (__in6_dev_get(dev) == NULL)
4451 continue;
4452 addrconf_ifdown(dev, 1);
4453 }
4454 addrconf_ifdown(net->loopback_dev, 2);
4455 rtnl_unlock();
4456}
4457
4458static struct pernet_operations addrconf_net_ops = {
4459 .exit = addrconf_net_exit,
4460};
4461
4462/* 4442/*
4463 * Init / cleanup code 4443 * Init / cleanup code
4464 */ 4444 */
@@ -4500,10 +4480,6 @@ int __init addrconf_init(void)
4500 if (err) 4480 if (err)
4501 goto errlo; 4481 goto errlo;
4502 4482
4503 err = register_pernet_device(&addrconf_net_ops);
4504 if (err)
4505 return err;
4506
4507 register_netdevice_notifier(&ipv6_dev_notf); 4483 register_netdevice_notifier(&ipv6_dev_notf);
4508 4484
4509 addrconf_verify(0); 4485 addrconf_verify(0);
@@ -4533,15 +4509,22 @@ errlo:
4533void addrconf_cleanup(void) 4509void addrconf_cleanup(void)
4534{ 4510{
4535 struct inet6_ifaddr *ifa; 4511 struct inet6_ifaddr *ifa;
4512 struct net_device *dev;
4536 int i; 4513 int i;
4537 4514
4538 unregister_netdevice_notifier(&ipv6_dev_notf); 4515 unregister_netdevice_notifier(&ipv6_dev_notf);
4539 unregister_pernet_device(&addrconf_net_ops);
4540
4541 unregister_pernet_subsys(&addrconf_ops); 4516 unregister_pernet_subsys(&addrconf_ops);
4542 4517
4543 rtnl_lock(); 4518 rtnl_lock();
4544 4519
4520 /* clean dev list */
4521 for_each_netdev(&init_net, dev) {
4522 if (__in6_dev_get(dev) == NULL)
4523 continue;
4524 addrconf_ifdown(dev, 1);
4525 }
4526 addrconf_ifdown(init_net.loopback_dev, 2);
4527
4545 /* 4528 /*
4546 * Check hash table. 4529 * Check hash table.
4547 */ 4530 */
@@ -4562,6 +4545,4 @@ void addrconf_cleanup(void)
4562 4545
4563 del_timer(&addr_chk_timer); 4546 del_timer(&addr_chk_timer);
4564 rtnl_unlock(); 4547 rtnl_unlock();
4565
4566 unregister_pernet_subsys(&addrconf_net_ops);
4567} 4548}