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 f2c7e615f90..a459c4f5b76 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)  static void init_loopback(struct net_device *dev)  {  	struct inet6_dev  *idev; +	struct net_device *sp_dev; +	struct inet6_ifaddr *sp_ifa; +	struct rt6_info *sp_rt;  	/* ::1 */ @@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev)  	}  	add_addr(idev, &in6addr_loopback, 128, IFA_HOST); + +	/* Add routes to other interface's IPv6 addresses */ +	for_each_netdev(dev_net(dev), sp_dev) { +		if (!strcmp(sp_dev->name, dev->name)) +			continue; + +		idev = __in6_dev_get(sp_dev); +		if (!idev) +			continue; + +		read_lock_bh(&idev->lock); +		list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { + +			if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) +				continue; + +			sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); + +			/* Failure cases are ignored */ +			if (!IS_ERR(sp_rt)) +				ip6_ins_rt(sp_rt); +		} +		read_unlock_bh(&idev->lock); +	}  }  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)  static int __net_init addrconf_init_net(struct net *net)  { -	int err; +	int err = -ENOMEM;  	struct ipv6_devconf *all, *dflt; -	err = -ENOMEM; -	all = &ipv6_devconf; -	dflt = &ipv6_devconf_dflt; +	all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); +	if (all == NULL) +		goto err_alloc_all; -	if (!net_eq(net, &init_net)) { -		all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); -		if (all == NULL) -			goto err_alloc_all; +	dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); +	if (dflt == NULL) +		goto err_alloc_dflt; -		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); -		if (dflt == NULL) -			goto err_alloc_dflt; -	} else { -		/* these will be inherited by all namespaces */ -		dflt->autoconf = ipv6_defaults.autoconf; -		dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; -	} +	/* these will be inherited by all namespaces */ +	dflt->autoconf = ipv6_defaults.autoconf; +	dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;  	net->ipv6.devconf_all = all;  	net->ipv6.devconf_dflt = dflt;  |