diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 53 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 21 |
2 files changed, 33 insertions, 41 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 | ||
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 | ||
@@ -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 | ||
4020 | static struct addrconf_sysctl_table | 4019 | static struct addrconf_sysctl_table |
@@ -4440,25 +4439,6 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4440 | 4439 | ||
4441 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4440 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4442 | 4441 | ||
4443 | static 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 | |||
4458 | static 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: | |||
4533 | void addrconf_cleanup(void) | 4509 | void 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 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index fa2ac7ee662f..57b07da1212a 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -72,6 +72,10 @@ MODULE_LICENSE("GPL"); | |||
72 | static struct list_head inetsw6[SOCK_MAX]; | 72 | static struct list_head inetsw6[SOCK_MAX]; |
73 | static DEFINE_SPINLOCK(inetsw6_lock); | 73 | static DEFINE_SPINLOCK(inetsw6_lock); |
74 | 74 | ||
75 | static int disable_ipv6 = 0; | ||
76 | module_param_named(disable, disable_ipv6, int, 0); | ||
77 | MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional"); | ||
78 | |||
75 | static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) | 79 | static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) |
76 | { | 80 | { |
77 | const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo); | 81 | const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo); |
@@ -1001,10 +1005,21 @@ static int __init inet6_init(void) | |||
1001 | { | 1005 | { |
1002 | struct sk_buff *dummy_skb; | 1006 | struct sk_buff *dummy_skb; |
1003 | struct list_head *r; | 1007 | struct list_head *r; |
1004 | int err; | 1008 | int err = 0; |
1005 | 1009 | ||
1006 | BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)); | 1010 | BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)); |
1007 | 1011 | ||
1012 | /* Register the socket-side information for inet6_create. */ | ||
1013 | for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) | ||
1014 | INIT_LIST_HEAD(r); | ||
1015 | |||
1016 | if (disable_ipv6) { | ||
1017 | printk(KERN_INFO | ||
1018 | "IPv6: Loaded, but administratively disabled, " | ||
1019 | "reboot required to enable\n"); | ||
1020 | goto out; | ||
1021 | } | ||
1022 | |||
1008 | err = proto_register(&tcpv6_prot, 1); | 1023 | err = proto_register(&tcpv6_prot, 1); |
1009 | if (err) | 1024 | if (err) |
1010 | goto out; | 1025 | goto out; |
@@ -1022,10 +1037,6 @@ static int __init inet6_init(void) | |||
1022 | goto out_unregister_udplite_proto; | 1037 | goto out_unregister_udplite_proto; |
1023 | 1038 | ||
1024 | 1039 | ||
1025 | /* Register the socket-side information for inet6_create. */ | ||
1026 | for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) | ||
1027 | INIT_LIST_HEAD(r); | ||
1028 | |||
1029 | /* We MUST register RAW sockets before we create the ICMP6, | 1040 | /* We MUST register RAW sockets before we create the ICMP6, |
1030 | * IGMP6, or NDISC control sockets. | 1041 | * IGMP6, or NDISC control sockets. |
1031 | */ | 1042 | */ |