Commit 6fab4b45 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPV6]: Handle loopback restration errors in addrconf_init()

Let's also clean up loopback's ipv6 structure in addrconf_cleanup
even though it never happens currently :)
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9184092a
...@@ -49,7 +49,7 @@ struct prefix_info { ...@@ -49,7 +49,7 @@ struct prefix_info {
#define IN6_ADDR_HSIZE 16 #define IN6_ADDR_HSIZE 16
extern void addrconf_init(void); extern int addrconf_init(void);
extern void addrconf_cleanup(void); extern void addrconf_cleanup(void);
extern int addrconf_add_ifaddr(void __user *arg); extern int addrconf_add_ifaddr(void __user *arg);
......
...@@ -1924,11 +1924,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, ...@@ -1924,11 +1924,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
struct inet6_dev *idev = __in6_dev_get(dev); struct inet6_dev *idev = __in6_dev_get(dev);
switch(event) { switch(event) {
case NETDEV_REGISTER:
if (dev == &loopback_dev && !ipv6_find_idev(dev))
panic("addrconf: Failed to create loopback\n");
break;
case NETDEV_UP: case NETDEV_UP:
switch(dev->type) { switch(dev->type) {
case ARPHRD_SIT: case ARPHRD_SIT:
...@@ -2013,7 +2008,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2013,7 +2008,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
ASSERT_RTNL(); ASSERT_RTNL();
if (dev == &loopback_dev) if (dev == &loopback_dev && how == 1)
how = 0; how = 0;
rt6_ifdown(dev); rt6_ifdown(dev);
...@@ -3446,8 +3441,10 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) ...@@ -3446,8 +3441,10 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
* Init / cleanup code * Init / cleanup code
*/ */
void __init addrconf_init(void) int __init addrconf_init(void)
{ {
int err = 0;
/* The addrconf netdev notifier requires that loopback_dev /* The addrconf netdev notifier requires that loopback_dev
* has it's ipv6 private information allocated and setup * has it's ipv6 private information allocated and setup
* before it can bring up and give link-local addresses * before it can bring up and give link-local addresses
...@@ -3461,13 +3458,17 @@ void __init addrconf_init(void) ...@@ -3461,13 +3458,17 @@ void __init addrconf_init(void)
* first, then loopback_dev, which cases all the non-loopback_dev * first, then loopback_dev, which cases all the non-loopback_dev
* devices to fail to get a link-local address. * devices to fail to get a link-local address.
* *
* So, as a temporary fix, register loopback_dev first by hand. * So, as a temporary fix, allocate the ipv6 structure for
* loopback_dev first by hand.
* Longer term, all of the dependencies ipv6 has upon the loopback * Longer term, all of the dependencies ipv6 has upon the loopback
* device and it being up should be removed. * device and it being up should be removed.
*/ */
rtnl_lock(); rtnl_lock();
addrconf_notify(&ipv6_dev_notf, NETDEV_REGISTER, &loopback_dev); if (!ipv6_add_dev(&loopback_dev))
err = -ENOMEM;
rtnl_unlock(); rtnl_unlock();
if (err)
return err;
register_netdevice_notifier(&ipv6_dev_notf); register_netdevice_notifier(&ipv6_dev_notf);
...@@ -3485,6 +3486,8 @@ void __init addrconf_init(void) ...@@ -3485,6 +3486,8 @@ void __init addrconf_init(void)
register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0); register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);
addrconf_sysctl_register(NULL, &ipv6_devconf_dflt); addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
#endif #endif
return 0;
} }
void __exit addrconf_cleanup(void) void __exit addrconf_cleanup(void)
...@@ -3513,6 +3516,7 @@ void __exit addrconf_cleanup(void) ...@@ -3513,6 +3516,7 @@ void __exit addrconf_cleanup(void)
continue; continue;
addrconf_ifdown(dev, 1); addrconf_ifdown(dev, 1);
} }
addrconf_ifdown(&loopback_dev, 2);
/* /*
* Check hash table. * Check hash table.
......
...@@ -784,7 +784,9 @@ static int __init inet6_init(void) ...@@ -784,7 +784,9 @@ static int __init inet6_init(void)
ipv6_packet_init(); ipv6_packet_init();
ip6_route_init(); ip6_route_init();
ip6_flowlabel_init(); ip6_flowlabel_init();
addrconf_init(); err = addrconf_init();
if (err)
goto addrconf_fail;
sit_init(); sit_init();
/* Init v6 extension headers. */ /* Init v6 extension headers. */
...@@ -800,7 +802,12 @@ static int __init inet6_init(void) ...@@ -800,7 +802,12 @@ static int __init inet6_init(void)
out: out:
return err; return err;
addrconf_fail:
ip6_flowlabel_cleanup();
ip6_route_cleanup();
ipv6_packet_cleanup();
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if6_proc_exit();
proc_if6_fail: proc_if6_fail:
ac6_proc_exit(); ac6_proc_exit();
proc_anycast6_fail: proc_anycast6_fail:
...@@ -812,8 +819,8 @@ static int __init inet6_init(void) ...@@ -812,8 +819,8 @@ static int __init inet6_init(void)
proc_tcp6_fail: proc_tcp6_fail:
raw6_proc_exit(); raw6_proc_exit();
proc_raw6_fail: proc_raw6_fail:
igmp6_cleanup();
#endif #endif
igmp6_cleanup();
igmp_fail: igmp_fail:
ndisc_cleanup(); ndisc_cleanup();
ndisc_fail: ndisc_fail:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment