diff options
author | Brian Haley <brian.haley@hp.com> | 2006-07-10 18:25:51 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-07-12 16:58:37 -0400 |
commit | e55ffac6011731c455856072cb23aa20bd55c367 (patch) | |
tree | 0ee05b521586b74398023ee083c5f9efbc8bf271 /net/ipv6 | |
parent | 155dbfd8846bf165bb036c4492ad121c8b059f1d (diff) |
[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/ipv6')
-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) | |||
508 | kfree(ifp); | 508 | kfree(ifp); |
509 | } | 509 | } |
510 | 510 | ||
511 | static void | ||
512 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | ||
513 | { | ||
514 | struct inet6_ifaddr *ifa, **ifap; | ||
515 | |||
516 | /* | ||
517 | * Each device address list is sorted in order of scope - | ||
518 | * global before linklocal. | ||
519 | */ | ||
520 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | ||
521 | ifap = &ifa->if_next) { | ||
522 | if (ifp->scope > ifa->scope) | ||
523 | break; | ||
524 | } | ||
525 | |||
526 | ifp->if_next = *ifap; | ||
527 | *ifap = ifp; | ||
528 | } | ||
529 | |||
511 | /* On success it returns ifp with increased reference count */ | 530 | /* On success it returns ifp with increased reference count */ |
512 | 531 | ||
513 | static struct inet6_ifaddr * | 532 | static struct inet6_ifaddr * |
@@ -573,8 +592,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
573 | 592 | ||
574 | write_lock(&idev->lock); | 593 | write_lock(&idev->lock); |
575 | /* Add to inet6_dev unicast addr list. */ | 594 | /* Add to inet6_dev unicast addr list. */ |
576 | ifa->if_next = idev->addr_list; | 595 | ipv6_link_dev_addr(idev, ifa); |
577 | idev->addr_list = ifa; | ||
578 | 596 | ||
579 | #ifdef CONFIG_IPV6_PRIVACY | 597 | #ifdef CONFIG_IPV6_PRIVACY |
580 | if (ifa->flags&IFA_F_TEMPORARY) { | 598 | if (ifa->flags&IFA_F_TEMPORARY) { |
@@ -987,7 +1005,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
987 | continue; | 1005 | continue; |
988 | } else if (score.scope < hiscore.scope) { | 1006 | } else if (score.scope < hiscore.scope) { |
989 | if (score.scope < daddr_scope) | 1007 | if (score.scope < daddr_scope) |
990 | continue; | 1008 | break; /* addresses sorted by scope */ |
991 | else { | 1009 | else { |
992 | score.rule = 2; | 1010 | score.rule = 2; |
993 | goto record_it; | 1011 | goto record_it; |