summaryrefslogtreecommitdiff
path: root/libgo/go/net/addrselect.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/addrselect.go')
-rw-r--r--libgo/go/net/addrselect.go51
1 files changed, 5 insertions, 46 deletions
diff --git a/libgo/go/net/addrselect.go b/libgo/go/net/addrselect.go
index 0b9d160fd43..1ab9fc53261 100644
--- a/libgo/go/net/addrselect.go
+++ b/libgo/go/net/addrselect.go
@@ -188,33 +188,17 @@ func (s *byRFC6724) Less(i, j int) bool {
// Rule 9: Use longest matching prefix.
// When DA and DB belong to the same address family (both are IPv6 or
- // both are IPv4): If CommonPrefixLen(Source(DA), DA) >
+ // both are IPv4 [but see below]): If CommonPrefixLen(Source(DA), DA) >
// CommonPrefixLen(Source(DB), DB), then prefer DA. Similarly, if
// CommonPrefixLen(Source(DA), DA) < CommonPrefixLen(Source(DB), DB),
// then prefer DB.
- da4 := DA.To4() != nil
- db4 := DB.To4() != nil
- if da4 == db4 {
+ //
+ // However, applying this rule to IPv4 addresses causes
+ // problems (see issues 13283 and 18518), so limit to IPv6.
+ if DA.To4() == nil && DB.To4() == nil {
commonA := commonPrefixLen(SourceDA, DA)
commonB := commonPrefixLen(SourceDB, DB)
- // CommonPrefixLen doesn't really make sense for IPv4, and even
- // causes problems for common load balancing practices
- // (e.g., https://golang.org/issue/13283). Glibc instead only
- // uses CommonPrefixLen for IPv4 when the source and destination
- // addresses are on the same subnet, but that requires extra
- // work to find the netmask for our source addresses. As a
- // simpler heuristic, we limit its use to when the source and
- // destination belong to the same special purpose block.
- if da4 {
- if !sameIPv4SpecialPurposeBlock(SourceDA, DA) {
- commonA = 0
- }
- if !sameIPv4SpecialPurposeBlock(SourceDB, DB) {
- commonB = 0
- }
- }
-
if commonA > commonB {
return preferDA
}
@@ -404,28 +388,3 @@ func commonPrefixLen(a, b IP) (cpl int) {
}
return
}
-
-// sameIPv4SpecialPurposeBlock reports whether a and b belong to the same
-// address block reserved by the IANA IPv4 Special-Purpose Address Registry:
-// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-func sameIPv4SpecialPurposeBlock(a, b IP) bool {
- a, b = a.To4(), b.To4()
- if a == nil || b == nil || a[0] != b[0] {
- return false
- }
- // IANA defines more special-purpose blocks, but these are the only
- // ones likely to be relevant to typical Go systems.
- switch a[0] {
- case 10: // 10.0.0.0/8: Private-Use
- return true
- case 127: // 127.0.0.0/8: Loopback
- return true
- case 169: // 169.254.0.0/16: Link Local
- return a[1] == 254 && b[1] == 254
- case 172: // 172.16.0.0/12: Private-Use
- return a[1]&0xf0 == 16 && b[1]&0xf0 == 16
- case 192: // 192.168.0.0/16: Private-Use
- return a[1] == 168 && b[1] == 168
- }
- return false
-}