[IPV6]: order addresses by scope
If IPv6 addresses are ordered by scope, then ipv6_dev_get_saddr() can break-out of the device addr_list for() loop when the candidate source address scope is less than the destination address scope. Signed-off-by: Brian Haley <brian.haley@hp.com> Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
155dbfd884
commit
e55ffac601
@@ -508,6 +508,25 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
|
|||||||
kfree(ifp);
|
kfree(ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
|
||||||
|
{
|
||||||
|
struct inet6_ifaddr *ifa, **ifap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each device address list is sorted in order of scope -
|
||||||
|
* global before linklocal.
|
||||||
|
*/
|
||||||
|
for (ifap = &idev->addr_list; (ifa = *ifap) != NULL;
|
||||||
|
ifap = &ifa->if_next) {
|
||||||
|
if (ifp->scope > ifa->scope)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp->if_next = *ifap;
|
||||||
|
*ifap = ifp;
|
||||||
|
}
|
||||||
|
|
||||||
/* On success it returns ifp with increased reference count */
|
/* On success it returns ifp with increased reference count */
|
||||||
|
|
||||||
static struct inet6_ifaddr *
|
static struct inet6_ifaddr *
|
||||||
@@ -573,8 +592,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
|
|||||||
|
|
||||||
write_lock(&idev->lock);
|
write_lock(&idev->lock);
|
||||||
/* Add to inet6_dev unicast addr list. */
|
/* Add to inet6_dev unicast addr list. */
|
||||||
ifa->if_next = idev->addr_list;
|
ipv6_link_dev_addr(idev, ifa);
|
||||||
idev->addr_list = ifa;
|
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6_PRIVACY
|
#ifdef CONFIG_IPV6_PRIVACY
|
||||||
if (ifa->flags&IFA_F_TEMPORARY) {
|
if (ifa->flags&IFA_F_TEMPORARY) {
|
||||||
@@ -987,7 +1005,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
|
|||||||
continue;
|
continue;
|
||||||
} else if (score.scope < hiscore.scope) {
|
} else if (score.scope < hiscore.scope) {
|
||||||
if (score.scope < daddr_scope)
|
if (score.scope < daddr_scope)
|
||||||
continue;
|
break; /* addresses sorted by scope */
|
||||||
else {
|
else {
|
||||||
score.rule = 2;
|
score.rule = 2;
|
||||||
goto record_it;
|
goto record_it;
|
||||||
|
Reference in New Issue
Block a user