github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/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 if commonA > commonB { 201 return preferDA 202 } 203 if commonA < commonB { 204 return preferDB 205 } 206 } 207 208 // Rule 10: Otherwise, leave the order unchanged. 209 // If DA preceded DB in the original list, prefer DA. 210 // Otherwise, prefer DB. 211 return false // "equal" 212 } 213 214 type policyTableEntry struct { 215 Prefix *IPNet 216 Precedence uint8 217 Label uint8 218 } 219 220 type policyTable []policyTableEntry 221 222 // RFC 6724 section 2.1. 223 var rfc6724policyTable = policyTable{ 224 { 225 Prefix: mustCIDR("::1/128"), 226 Precedence: 50, 227 Label: 0, 228 }, 229 { 230 Prefix: mustCIDR("::/0"), 231 Precedence: 40, 232 Label: 1, 233 }, 234 { 235 // IPv4-compatible, etc. 236 Prefix: mustCIDR("::ffff:0:0/96"), 237 Precedence: 35, 238 Label: 4, 239 }, 240 { 241 // 6to4 242 Prefix: mustCIDR("2002::/16"), 243 Precedence: 30, 244 Label: 2, 245 }, 246 { 247 // Teredo 248 Prefix: mustCIDR("2001::/32"), 249 Precedence: 5, 250 Label: 5, 251 }, 252 { 253 Prefix: mustCIDR("fc00::/7"), 254 Precedence: 3, 255 Label: 13, 256 }, 257 { 258 Prefix: mustCIDR("::/96"), 259 Precedence: 1, 260 Label: 3, 261 }, 262 { 263 Prefix: mustCIDR("fec0::/10"), 264 Precedence: 1, 265 Label: 11, 266 }, 267 { 268 Prefix: mustCIDR("3ffe::/16"), 269 Precedence: 1, 270 Label: 12, 271 }, 272 } 273 274 func init() { 275 sort.Sort(sort.Reverse(byMaskLength(rfc6724policyTable))) 276 } 277 278 // byMaskLength sorts policyTableEntry by the size of their Prefix.Mask.Size, 279 // from smallest mask, to largest. 280 type byMaskLength []policyTableEntry 281 282 func (s byMaskLength) Len() int { return len(s) } 283 func (s byMaskLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 284 func (s byMaskLength) Less(i, j int) bool { 285 isize, _ := s[i].Prefix.Mask.Size() 286 jsize, _ := s[j].Prefix.Mask.Size() 287 return isize < jsize 288 } 289 290 // mustCIDR calls ParseCIDR and panics on any error, or if the network 291 // is not IPv6. 292 func mustCIDR(s string) *IPNet { 293 ip, ipNet, err := ParseCIDR(s) 294 if err != nil { 295 panic(err.Error()) 296 } 297 if len(ip) != IPv6len { 298 panic("unexpected IP length") 299 } 300 return ipNet 301 } 302 303 // Classify returns the policyTableEntry of the entry with the longest 304 // matching prefix that contains ip. 305 // The table t must be sorted from largest mask size to smallest. 306 func (t policyTable) Classify(ip IP) policyTableEntry { 307 for _, ent := range t { 308 if ent.Prefix.Contains(ip) { 309 return ent 310 } 311 } 312 return policyTableEntry{} 313 } 314 315 // RFC 6724 section 3.1. 316 type scope uint8 317 318 const ( 319 scopeInterfaceLocal scope = 0x1 320 scopeLinkLocal scope = 0x2 321 scopeAdminLocal scope = 0x4 322 scopeSiteLocal scope = 0x5 323 scopeOrgLocal scope = 0x8 324 scopeGlobal scope = 0xe 325 ) 326 327 func classifyScope(ip IP) scope { 328 if ip.IsLoopback() || ip.IsLinkLocalUnicast() { 329 return scopeLinkLocal 330 } 331 ipv6 := len(ip) == IPv6len && ip.To4() == nil 332 if ipv6 && ip.IsMulticast() { 333 return scope(ip[1] & 0xf) 334 } 335 // Site-local addresses are defined in RFC 3513 section 2.5.6 336 // (and deprecated in RFC 3879). 337 if ipv6 && ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 { 338 return scopeSiteLocal 339 } 340 return scopeGlobal 341 } 342 343 // commonPrefixLen reports the length of the longest prefix (looking 344 // at the most significant, or leftmost, bits) that the 345 // two addresses have in common, up to the length of a's prefix (i.e., 346 // the portion of the address not including the interface ID). 347 // 348 // If a or b is an IPv4 address as an IPv6 address, the IPv4 addresses 349 // are compared (with max common prefix length of 32). 350 // If a and b are different IP versions, 0 is returned. 351 // 352 // See https://tools.ietf.org/html/rfc6724#section-2.2 353 func commonPrefixLen(a, b IP) (cpl int) { 354 if a4 := a.To4(); a4 != nil { 355 a = a4 356 } 357 if b4 := b.To4(); b4 != nil { 358 b = b4 359 } 360 if len(a) != len(b) { 361 return 0 362 } 363 // If IPv6, only up to the prefix (first 64 bits) 364 if len(a) > 8 { 365 a = a[:8] 366 b = b[:8] 367 } 368 for len(a) > 0 { 369 if a[0] == b[0] { 370 cpl += 8 371 a = a[1:] 372 b = b[1:] 373 continue 374 } 375 bits := 8 376 ab, bb := a[0], b[0] 377 for { 378 ab >>= 1 379 bb >>= 1 380 bits-- 381 if ab == bb { 382 cpl += bits 383 return 384 } 385 } 386 } 387 return 388 }