diff options
author | Brian Haley <brian.haley@hp.com> | 2006-07-11 02:25:51 +0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-07-13 00:58:37 +0400 |
commit | e55ffac6011731c455856072cb23aa20bd55c367 (patch) | |
tree | 0ee05b521586b74398023ee083c5f9efbc8bf271 /net | |
parent | 155dbfd8846bf165bb036c4492ad121c8b059f1d (diff) | |
download | linux-e55ffac6011731c455856072cb23aa20bd55c367.tar.xz |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c250d0af10d7..9d9a3c6056fa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -508,6 +508,25 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *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 */ 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); /* Add to inet6_dev unicast addr list. */ - ifa->if_next = idev->addr_list; - idev->addr_list = ifa; + ipv6_link_dev_addr(idev, ifa); #ifdef CONFIG_IPV6_PRIVACY if (ifa->flags&IFA_F_TEMPORARY) { @@ -987,7 +1005,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, continue; } else if (score.scope < hiscore.scope) { if (score.scope < daddr_scope) - continue; + break; /* addresses sorted by scope */ else { score.rule = 2; goto record_it; |