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