aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c53
-rw-r--r--net/ipv6/af_inet6.c21
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
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}
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");
72static struct list_head inetsw6[SOCK_MAX]; 72static struct list_head inetsw6[SOCK_MAX];
73static DEFINE_SPINLOCK(inetsw6_lock); 73static DEFINE_SPINLOCK(inetsw6_lock);
74 74
75static int disable_ipv6 = 0;
76module_param_named(disable, disable_ipv6, int, 0);
77MODULE_PARM_DESC(disable, "Disable IPv6 such that it is non-functional");
78
75static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) 79static __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 */