diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 53 |
1 files changed, 17 insertions, 36 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f9afb452249c..1220e2c7831e 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 | ||
| 496 | static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 496 | static 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 | ||
| @@ -2608,9 +2611,6 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2608 | 2611 | ||
| 2609 | ASSERT_RTNL(); | 2612 | ASSERT_RTNL(); |
| 2610 | 2613 | ||
| 2611 | if ((dev->flags & IFF_LOOPBACK) && how == 1) | ||
| 2612 | how = 0; | ||
| 2613 | |||
| 2614 | rt6_ifdown(net, dev); | 2614 | rt6_ifdown(net, dev); |
| 2615 | neigh_ifdown(&nd_tbl, dev); | 2615 | neigh_ifdown(&nd_tbl, dev); |
| 2616 | 2616 | ||
| @@ -3983,7 +3983,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, | |||
| 3983 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 3983 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
| 3984 | 3984 | ||
| 3985 | if (write) | 3985 | if (write) |
| 3986 | addrconf_fixup_forwarding(ctl, valp, val); | 3986 | ret = addrconf_fixup_forwarding(ctl, valp, val); |
| 3987 | return ret; | 3987 | return ret; |
| 3988 | } | 3988 | } |
| 3989 | 3989 | ||
| @@ -4019,8 +4019,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table, | |||
| 4019 | } | 4019 | } |
| 4020 | 4020 | ||
| 4021 | *valp = new; | 4021 | *valp = new; |
| 4022 | addrconf_fixup_forwarding(table, valp, val); | 4022 | return addrconf_fixup_forwarding(table, valp, val); |
| 4023 | return 1; | ||
| 4024 | } | 4023 | } |
| 4025 | 4024 | ||
| 4026 | static struct addrconf_sysctl_table | 4025 | static struct addrconf_sysctl_table |
| @@ -4446,25 +4445,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
| 4446 | 4445 | ||
| 4447 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4446 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
| 4448 | 4447 | ||
| 4449 | static void addrconf_net_exit(struct net *net) | ||
| 4450 | { | ||
| 4451 | struct net_device *dev; | ||
| 4452 | |||
| 4453 | rtnl_lock(); | ||
| 4454 | /* clean dev list */ | ||
| 4455 | for_each_netdev(net, dev) { | ||
| 4456 | if (__in6_dev_get(dev) == NULL) | ||
| 4457 | continue; | ||
| 4458 | addrconf_ifdown(dev, 1); | ||
| 4459 | } | ||
| 4460 | addrconf_ifdown(net->loopback_dev, 2); | ||
| 4461 | rtnl_unlock(); | ||
| 4462 | } | ||
| 4463 | |||
| 4464 | static struct pernet_operations addrconf_net_ops = { | ||
| 4465 | .exit = addrconf_net_exit, | ||
| 4466 | }; | ||
| 4467 | |||
| 4468 | /* | 4448 | /* |
| 4469 | * Init / cleanup code | 4449 | * Init / cleanup code |
| 4470 | */ | 4450 | */ |
| @@ -4506,10 +4486,6 @@ int __init addrconf_init(void) | |||
| 4506 | if (err) | 4486 | if (err) |
| 4507 | goto errlo; | 4487 | goto errlo; |
| 4508 | 4488 | ||
| 4509 | err = register_pernet_device(&addrconf_net_ops); | ||
| 4510 | if (err) | ||
| 4511 | return err; | ||
| 4512 | |||
| 4513 | register_netdevice_notifier(&ipv6_dev_notf); | 4489 | register_netdevice_notifier(&ipv6_dev_notf); |
| 4514 | 4490 | ||
| 4515 | addrconf_verify(0); | 4491 | addrconf_verify(0); |
| @@ -4539,15 +4515,22 @@ errlo: | |||
| 4539 | void addrconf_cleanup(void) | 4515 | void addrconf_cleanup(void) |
| 4540 | { | 4516 | { |
| 4541 | struct inet6_ifaddr *ifa; | 4517 | struct inet6_ifaddr *ifa; |
| 4518 | struct net_device *dev; | ||
| 4542 | int i; | 4519 | int i; |
| 4543 | 4520 | ||
| 4544 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4521 | unregister_netdevice_notifier(&ipv6_dev_notf); |
| 4545 | unregister_pernet_device(&addrconf_net_ops); | ||
| 4546 | |||
| 4547 | unregister_pernet_subsys(&addrconf_ops); | 4522 | unregister_pernet_subsys(&addrconf_ops); |
| 4548 | 4523 | ||
| 4549 | rtnl_lock(); | 4524 | rtnl_lock(); |
| 4550 | 4525 | ||
| 4526 | /* clean dev list */ | ||
| 4527 | for_each_netdev(&init_net, dev) { | ||
| 4528 | if (__in6_dev_get(dev) == NULL) | ||
| 4529 | continue; | ||
| 4530 | addrconf_ifdown(dev, 1); | ||
| 4531 | } | ||
| 4532 | addrconf_ifdown(init_net.loopback_dev, 2); | ||
| 4533 | |||
| 4551 | /* | 4534 | /* |
| 4552 | * Check hash table. | 4535 | * Check hash table. |
| 4553 | */ | 4536 | */ |
| @@ -4568,6 +4551,4 @@ void addrconf_cleanup(void) | |||
| 4568 | 4551 | ||
| 4569 | del_timer(&addr_chk_timer); | 4552 | del_timer(&addr_chk_timer); |
| 4570 | rtnl_unlock(); | 4553 | rtnl_unlock(); |
| 4571 | |||
| 4572 | unregister_pernet_subsys(&addrconf_net_ops); | ||
| 4573 | } | 4554 | } |
