diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f2c7e615f902..a459c4f5b769 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
2529 | static void init_loopback(struct net_device *dev) | 2529 | static void init_loopback(struct net_device *dev) |
2530 | { | 2530 | { |
2531 | struct inet6_dev *idev; | 2531 | struct inet6_dev *idev; |
2532 | struct net_device *sp_dev; | ||
2533 | struct inet6_ifaddr *sp_ifa; | ||
2534 | struct rt6_info *sp_rt; | ||
2532 | 2535 | ||
2533 | /* ::1 */ | 2536 | /* ::1 */ |
2534 | 2537 | ||
@@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev) | |||
2540 | } | 2543 | } |
2541 | 2544 | ||
2542 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); | 2545 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
2546 | |||
2547 | /* Add routes to other interface's IPv6 addresses */ | ||
2548 | for_each_netdev(dev_net(dev), sp_dev) { | ||
2549 | if (!strcmp(sp_dev->name, dev->name)) | ||
2550 | continue; | ||
2551 | |||
2552 | idev = __in6_dev_get(sp_dev); | ||
2553 | if (!idev) | ||
2554 | continue; | ||
2555 | |||
2556 | read_lock_bh(&idev->lock); | ||
2557 | list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { | ||
2558 | |||
2559 | if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) | ||
2560 | continue; | ||
2561 | |||
2562 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | ||
2563 | |||
2564 | /* Failure cases are ignored */ | ||
2565 | if (!IS_ERR(sp_rt)) | ||
2566 | ip6_ins_rt(sp_rt); | ||
2567 | } | ||
2568 | read_unlock_bh(&idev->lock); | ||
2569 | } | ||
2543 | } | 2570 | } |
2544 | 2571 | ||
2545 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) | 2572 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) |
@@ -4784,26 +4811,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
4784 | 4811 | ||
4785 | static int __net_init addrconf_init_net(struct net *net) | 4812 | static int __net_init addrconf_init_net(struct net *net) |
4786 | { | 4813 | { |
4787 | int err; | 4814 | int err = -ENOMEM; |
4788 | struct ipv6_devconf *all, *dflt; | 4815 | struct ipv6_devconf *all, *dflt; |
4789 | 4816 | ||
4790 | err = -ENOMEM; | 4817 | all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); |
4791 | all = &ipv6_devconf; | 4818 | if (all == NULL) |
4792 | dflt = &ipv6_devconf_dflt; | 4819 | goto err_alloc_all; |
4793 | 4820 | ||
4794 | if (!net_eq(net, &init_net)) { | 4821 | dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); |
4795 | all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); | 4822 | if (dflt == NULL) |
4796 | if (all == NULL) | 4823 | goto err_alloc_dflt; |
4797 | goto err_alloc_all; | ||
4798 | 4824 | ||
4799 | dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); | 4825 | /* these will be inherited by all namespaces */ |
4800 | if (dflt == NULL) | 4826 | dflt->autoconf = ipv6_defaults.autoconf; |
4801 | goto err_alloc_dflt; | 4827 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; |
4802 | } else { | ||
4803 | /* these will be inherited by all namespaces */ | ||
4804 | dflt->autoconf = ipv6_defaults.autoconf; | ||
4805 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; | ||
4806 | } | ||
4807 | 4828 | ||
4808 | net->ipv6.devconf_all = all; | 4829 | net->ipv6.devconf_all = all; |
4809 | net->ipv6.devconf_dflt = dflt; | 4830 | net->ipv6.devconf_dflt = dflt; |