github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/net/addrselect.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 // Minimal RFC 6724 address selection. 8 9 package net 10 11 import "sort" 12 13 func sortByRFC6724(addrs []IPAddr) { 14 if len(addrs) < 2 { 15 return 16 } 17 sortByRFC6724withSrcs(addrs, srcAddrs(addrs)) 18 } 19 20 func sortByRFC6724withSrcs(addrs []IPAddr, srcs []IP) { 21 if len(addrs) != len(srcs) { 22 panic("internal error") 23 } 24 addrAttr := make([]ipAttr, len(addrs)) 25 srcAttr := make([]ipAttr, len(srcs)) 26 for i, v := range addrs { 27 addrAttr[i] = ipAttrOf(v.IP) 28 srcAttr[i] = ipAttrOf(srcs[i]) 29 } 30 sort.Stable(&byRFC6724{ 31 addrs: addrs, 32 addrAttr: addrAttr, 33 srcs: srcs, 34 srcAttr: srcAttr, 35 }) 36 } 37 38 // srcsAddrs tries to UDP-connect to each address to see if it has a 39 // route. (This doesn't send any packets). The destination port 40 // number is irrelevant. 41 func srcAddrs(addrs []IPAddr) []IP { 42 srcs := make([]IP, len(addrs)) 43 dst := UDPAddr{Port: 9} 44 for i := range addrs { 45 dst.IP = addrs[i].IP 46 dst.Zone = addrs[i].Zone 47 c, err := DialUDP("udp", nil, &dst) 48 if err == nil { 49 if src, ok := c.LocalAddr().(*UDPAddr); ok { 50 srcs[i] = src.IP 51 } 52 c.Close() 53 } 54 } 55 return srcs 56 } 57 58 type ipAttr struct { 59 Scope scope 60 Precedence uint8 61 Label uint8 62 } 63 64 func ipAttrOf(ip IP) ipAttr { 65 if ip == nil { 66 return ipAttr{} 67 } 68 match := rfc6724policyTable.Classify(ip) 69 return ipAttr{ 70 Scope: classifyScope(ip), 71 Precedence: match.Precedence, 72 Label: match.Label, 73 } 74 } 75 76 type byRFC6724 struct { 77 addrs []IPAddr // addrs to sort 78 addrAttr []ipAttr 79 srcs []IP // or nil if unreachable 80 srcAttr []ipAttr 81 } 82 83 func (s *byRFC6724) Len() int { return len(s.addrs) } 84 85 func (s *byRFC6724) Swap(i, j int) { 86 s.addrs[i], s.addrs[j] = s.addrs[j], s.addrs[i] 87 s.srcs[i], s.srcs[j] = s.srcs[j], s.srcs[i] 88 s.addrAttr[i], s.addrAttr[j] = s.addrAttr[j], s.addrAttr[i] 89 s.srcAttr[i], s.srcAttr[j] = s.srcAttr[j], s.srcAttr[i] 90 } 91 92 // Less reports whether i is a better destination address for this 93 // host than j. 94 // 95 // The algorithm and variable names comes from RFC 6724 section 6. 96 func (s *byRFC6724) Less(i, j int) bool { 97 DA := s.addrs[i].IP 98 DB := s.addrs[j].IP 99 SourceDA := s.srcs[i] 100 SourceDB := s.srcs[j] 101 attrDA := &s.addrAttr[i] 102 attrDB := &s.addrAttr[j] 103 attrSourceDA := &s.srcAttr[i] 104 attrSourceDB := &s.srcAttr[j] 105 106 const preferDA = true 107 const preferDB = false 108 109 // Rule 1: Avoid unusable destinations. 110 // If DB is known to be unreachable or if Source(DB) is undefined, then 111 // prefer DA. Similarly, if DA is known to be unreachable or if 112 // Source(DA) is undefined, then prefer DB. 113 if SourceDA == nil && SourceDB == nil { 114 return false // "equal" 115 } 116 if SourceDB == nil { 117 return preferDA 118 } 119 if SourceDA == nil { 120 return preferDB 121 } 122 123 // Rule 2: Prefer matching scope. 124 // If Scope(DA) = Scope(Source(DA)) and Scope(DB) <> Scope(Source(DB)), 125 // then prefer DA. Similarly, if Scope(DA) <> Scope(Source(DA)) and 126 // Scope(DB) = Scope(Source(DB)), then prefer DB. 127 if attrDA.Scope == attrSourceDA.Scope && attrDB.Scope != attrSourceDB.Scope { 128 return preferDA 129 } 130 if attrDA.Scope != attrSourceDA.Scope && attrDB.Scope == attrSourceDB.Scope { 131 return preferDB 132 } 133 134 // Rule 3: Avoid deprecated addresses. 135 // If Source(DA) is deprecated and Source(DB) is not, then prefer DB. 136 // Similarly, if Source(DA) is not deprecated and Source(DB) is 137 // deprecated, then prefer DA. 138 139 // TODO(bradfitz): implement? low priority for now. 140 141 // Rule 4: Prefer home addresses. 142 // If Source(DA) is simultaneously a home address and care-of address 143 // and Source(DB) is not, then prefer DA. Similarly, if Source(DB) is 144 // simultaneously a home address and care-of address and Source(DA) is 145 // not, then prefer DB. 146 147 // TODO(bradfitz): implement? low priority for now. 148 149 // Rule 5: Prefer matching label. 150 // If Label(Source(DA)) = Label(DA) and Label(Source(DB)) <> Label(DB), 151 // then prefer DA. Similarly, if Label(Source(DA)) <> Label(DA) and 152 // Label(Source(DB)) = Label(DB), then prefer DB. 153 if attrSourceDA.Label == attrDA.Label && 154 attrSourceDB.Label != attrDB.Label { 155 return preferDA 156 } 157 if attrSourceDA.Label != attrDA.Label && 158 attrSourceDB.Label == attrDB.Label { 159 return preferDB 160 } 161 162 // Rule 6: Prefer higher precedence. 163 // If Precedence(DA) > Precedence(DB), then prefer DA. Similarly, if 164 // Precedence(DA) < Precedence(DB), then prefer DB. 165 if attrDA.Precedence > attrDB.Precedence { 166 return preferDA 167 } 168 if attrDA.Precedence < attrDB.Precedence { 169 return preferDB 170 } 171 172 // Rule 7: Prefer native transport. 173 // If DA is reached via an encapsulating transition mechanism (e.g., 174 // IPv6 in IPv4) and DB is not, then prefer DB. Similarly, if DB is 175 // reached via encapsulation and DA is not, then prefer DA. 176 177 // TODO(bradfitz): implement? low priority for now. 178 179 // Rule 8: Prefer smaller scope. 180 // If Scope(DA) < Scope(DB), then prefer DA. Similarly, if Scope(DA) > 181 // Scope(DB), then prefer DB. 182 if attrDA.Scope < attrDB.Scope { 183 return preferDA 184 } 185 if attrDA.Scope > attrDB.Scope { 186 return preferDB 187 } 188 189 // Rule 9: Use longest matching prefix. 190 // When DA and DB belong to the same address family (both are IPv6 or 191 // both are IPv4): If CommonPrefixLen(Source(DA), DA) > 192 // CommonPrefixLen(Source(DB), DB), then prefer DA. Similarly, if 193 // CommonPrefixLen(Source(DA), DA) < CommonPrefixLen(Source(DB), DB), 194 // then prefer DB. 195 da4 := DA.To4() != nil 196 db4 := DB.To4() != nil 197 if da4 == db4 { 198 commonA := commonPrefixLen(SourceDA, DA) 199 commonB := commonPrefixLen(SourceDB, DB) 200 201 // CommonPrefixLen doesn't really make sense for IPv4, and even 202 // causes problems for common load balancing practices 203 // (e.g., https://golang.org/issue/13283). Glibc instead only 204 // uses CommonPrefixLen for IPv4 when the source and destination 205 // addresses are on the same subnet, but that requires extra 206 // work to find the netmask for our source addresses. As a 207 // simpler heuristic, we limit its use to when the source and 208 // destination belong to the same special purpose block. 209 if da4 { 210 if !sameIPv4SpecialPurposeBlock(SourceDA, DA) { 211 commonA = 0 212 } 213 if !sameIPv4SpecialPurposeBlock(SourceDB, DB) { 214 commonB = 0 215 } 216 } 217 218 if commonA > commonB { 219 return preferDA 220 } 221 if commonA < commonB { 222 return preferDB 223 } 224 } 225 226 // Rule 10: Otherwise, leave the order unchanged. 227 // If DA preceded DB in the original list, prefer DA. 228 // Otherwise, prefer DB. 229 return false // "equal" 230 } 231 232 type policyTableEntry struct { 233 Prefix *IPNet 234 Precedence uint8 235 Label uint8 236 } 237 238 type policyTable []policyTableEntry 239 240 // RFC 6724 section 2.1. 241 var rfc6724policyTable = policyTable{ 242 { 243 Prefix: mustCIDR("::1/128"), 244 Precedence: 50, 245 Label: 0, 246 }, 247 { 248 Prefix: mustCIDR("::/0"), 249 Precedence: 40, 250 Label: 1, 251 }, 252 { 253 // IPv4-compatible, etc. 254 Prefix: mustCIDR("::ffff:0:0/96"), 255 Precedence: 35, 256 Label: 4, 257 }, 258 { 259 // 6to4 260 Prefix: mustCIDR("2002::/16"), 261 Precedence: 30, 262 Label: 2, 263 }, 264 { 265 // Teredo 266 Prefix: mustCIDR("2001::/32"), 267 Precedence: 5, 268 Label: 5, 269 }, 270 { 271 Prefix: mustCIDR("fc00::/7"), 272 Precedence: 3, 273 Label: 13, 274 }, 275 { 276 Prefix: mustCIDR("::/96"), 277 Precedence: 1, 278 Label: 3, 279 }, 280 { 281 Prefix: mustCIDR("fec0::/10"), 282 Precedence: 1, 283 Label: 11, 284 }, 285 { 286 Prefix: mustCIDR("3ffe::/16"), 287 Precedence: 1, 288 Label: 12, 289 }, 290 } 291 292 func init() { 293 sort.Sort(sort.Reverse(byMaskLength(rfc6724policyTable))) 294 } 295 296 // byMaskLength sorts policyTableEntry by the size of their Prefix.Mask.Size, 297 // from smallest mask, to largest. 298 type byMaskLength []policyTableEntry 299 300 func (s byMaskLength) Len() int { return len(s) } 301 func (s byMaskLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 302 func (s byMaskLength) Less(i, j int) bool { 303 isize, _ := s[i].Prefix.Mask.Size() 304 jsize, _ := s[j].Prefix.Mask.Size() 305 return isize < jsize 306 } 307 308 // mustCIDR calls ParseCIDR and panics on any error, or if the network 309 // is not IPv6. 310 func mustCIDR(s string) *IPNet { 311 ip, ipNet, err := ParseCIDR(s) 312 if err != nil { 313 panic(err.Error()) 314 } 315 if len(ip) != IPv6len { 316 panic("unexpected IP length") 317 } 318 return ipNet 319 } 320 321 // Classify returns the policyTableEntry of the entry with the longest 322 // matching prefix that contains ip. 323 // The table t must be sorted from largest mask size to smallest. 324 func (t policyTable) Classify(ip IP) policyTableEntry { 325 for _, ent := range t { 326 if ent.Prefix.Contains(ip) { 327 return ent 328 } 329 } 330 return policyTableEntry{} 331 } 332 333 // RFC 6724 section 3.1. 334 type scope uint8 335 336 const ( 337 scopeInterfaceLocal scope = 0x1 338 scopeLinkLocal scope = 0x2 339 scopeAdminLocal scope = 0x4 340 scopeSiteLocal scope = 0x5 341 scopeOrgLocal scope = 0x8 342 scopeGlobal scope = 0xe 343 ) 344 345 func classifyScope(ip IP) scope { 346 if ip.IsLoopback() || ip.IsLinkLocalUnicast() { 347 return scopeLinkLocal 348 } 349 ipv6 := len(ip) == IPv6len && ip.To4() == nil 350 if ipv6 && ip.IsMulticast() { 351 return scope(ip[1] & 0xf) 352 } 353 // Site-local addresses are defined in RFC 3513 section 2.5.6 354 // (and deprecated in RFC 3879). 355 if ipv6 && ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 { 356 return scopeSiteLocal 357 } 358 return scopeGlobal 359 } 360 361 // commonPrefixLen reports the length of the longest prefix (looking 362 // at the most significant, or leftmost, bits) that the 363 // two addresses have in common, up to the length of a's prefix (i.e., 364 // the portion of the address not including the interface ID). 365 // 366 // If a or b is an IPv4 address as an IPv6 address, the IPv4 addresses 367 // are compared (with max common prefix length of 32). 368 // If a and b are different IP versions, 0 is returned. 369 // 370 // See https://tools.ietf.org/html/rfc6724#section-2.2 371 func commonPrefixLen(a, b IP) (cpl int) { 372 if a4 := a.To4(); a4 != nil { 373 a = a4 374 } 375 if b4 := b.To4(); b4 != nil { 376 b = b4 377 } 378 if len(a) != len(b) { 379 return 0 380 } 381 // If IPv6, only up to the prefix (first 64 bits) 382 if len(a) > 8 { 383 a = a[:8] 384 b = b[:8] 385 } 386 for len(a) > 0 { 387 if a[0] == b[0] { 388 cpl += 8 389 a = a[1:] 390 b = b[1:] 391 continue 392 } 393 bits := 8 394 ab, bb := a[0], b[0] 395 for { 396 ab >>= 1 397 bb >>= 1 398 bits-- 399 if ab == bb { 400 cpl += bits 401 return 402 } 403 } 404 } 405 return 406 } 407 408 // sameIPv4SpecialPurposeBlock reports whether a and b belong to the same 409 // address block reserved by the IANA IPv4 Special-Purpose Address Registry: 410 // http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml 411 func sameIPv4SpecialPurposeBlock(a, b IP) bool { 412 a, b = a.To4(), b.To4() 413 if a == nil || b == nil || a[0] != b[0] { 414 return false 415 } 416 // IANA defines more special-purpose blocks, but these are the only 417 // ones likely to be relevant to typical Go systems. 418 switch a[0] { 419 case 10: // 10.0.0.0/8: Private-Use 420 return true 421 case 127: // 127.0.0.0/8: Loopback 422 return true 423 case 169: // 169.254.0.0/16: Link Local 424 return a[1] == 254 && b[1] == 254 425 case 172: // 172.16.0.0/12: Private-Use 426 return a[1]&0xf0 == 16 && b[1]&0xf0 == 16 427 case 192: // 192.168.0.0/16: Private-Use 428 return a[1] == 168 && b[1] == 168 429 } 430 return false 431 }