[IPV6]: Fix source address selection for ORCHID addresses
authorJuha-Matti Tapio <jmtapio@verkkotelakka.net>
Fri, 29 Feb 2008 04:55:46 +0000 (20:55 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 29 Feb 2008 04:55:46 +0000 (20:55 -0800)
Skip the prefix length matching in source address selection for
orchid -> non-orchid addresses.

Overlay Routable Cryptographic Hash IDentifiers (RFC 4843,
2001:10::/28) are currenty not globally reachable. Without this
check a host with an ORCHID address can end up preferring those over
regular addresses when talking to other regular hosts in the 2001::/16
range thus breaking non-orchid connections.

Signed-off-by: Juha-Matti Tapio <jmtapio@verkkotelakka.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ipv6.h
net/ipv6/addrconf.c

index c0c019f72ba95a1896cdf7c77c1312491318210b..8b05c65415cb3c9bd02289294e7e601a46cc74f1 100644 (file)
@@ -383,6 +383,16 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
                 a->s6_addr32[2] == htonl(0x0000ffff));
 }
 
+/*
+ * Check for a RFC 4843 ORCHID address
+ * (Overlay Routable Cryptographic Hash Identifiers)
+ */
+static inline int ipv6_addr_orchid(const struct in6_addr *a)
+{
+       return ((a->s6_addr32[0] & htonl(0xfffffff0))
+               == htonl(0x20010010));
+}
+
 /*
  * find the first different bit between two addresses
  * length of address must be a multiple of 32bits
index 101e0e70ba276966a281b99601c17cfaf648f0c5..18e3a9825d8124347d26957e100e5d527a13075e 100644 (file)
@@ -1125,6 +1125,11 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
                        if (hiscore.rule < 7)
                                hiscore.rule++;
 #endif
+
+                       /* Skip rule 8 for orchid -> non-orchid address pairs. */
+                       if (ipv6_addr_orchid(&ifa->addr) && !ipv6_addr_orchid(daddr))
+                               continue;
+
                        /* Rule 8: Use longest matching prefix */
                        if (hiscore.rule < 8) {
                                hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);