// Copyright 2015 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris// Minimal RFC 6724 address selection.package netimportfunc ( []IPAddr) {iflen() < 2 {return }sortByRFC6724withSrcs(, srcAddrs())}func ( []IPAddr, []IP) {iflen() != len() {panic("internal error") } := make([]ipAttr, len()) := make([]ipAttr, len())for , := range { [] = ipAttrOf(.IP) [] = ipAttrOf([]) }sort.Stable(&byRFC6724{addrs: ,addrAttr: ,srcs: ,srcAttr: , })}// srcsAddrs tries to UDP-connect to each address to see if it has a// route. (This doesn't send any packets). The destination port// number is irrelevant.func ( []IPAddr) []IP { := make([]IP, len()) := UDPAddr{Port: 9}for := range { .IP = [].IP .Zone = [].Zone , := DialUDP("udp", nil, &)if == nil {if , := .LocalAddr().(*UDPAddr); { [] = .IP } .Close() } }return}typeipAttrstruct { Scope scope Precedence uint8 Label uint8}func ( IP) ipAttr {if == nil {returnipAttr{} } := rfc6724policyTable.Classify()returnipAttr{Scope: classifyScope(),Precedence: .Precedence,Label: .Label, }}typebyRFC6724struct { addrs []IPAddr// addrs to sort addrAttr []ipAttr srcs []IP// or nil if unreachable srcAttr []ipAttr}func ( *byRFC6724) () int { returnlen(.addrs) }func ( *byRFC6724) (, int) { .addrs[], .addrs[] = .addrs[], .addrs[] .srcs[], .srcs[] = .srcs[], .srcs[] .addrAttr[], .addrAttr[] = .addrAttr[], .addrAttr[] .srcAttr[], .srcAttr[] = .srcAttr[], .srcAttr[]}// Less reports whether i is a better destination address for this// host than j.//// The algorithm and variable names comes from RFC 6724 section 6.func ( *byRFC6724) (, int) bool { := .addrs[].IP := .addrs[].IP := .srcs[] := .srcs[] := &.addrAttr[] := &.addrAttr[] := &.srcAttr[] := &.srcAttr[]const = trueconst = false// Rule 1: Avoid unusable destinations. // If DB is known to be unreachable or if Source(DB) is undefined, then // prefer DA. Similarly, if DA is known to be unreachable or if // Source(DA) is undefined, then prefer DB.if == nil && == nil {returnfalse// "equal" }if == nil {return }if == nil {return }// Rule 2: Prefer matching scope. // If Scope(DA) = Scope(Source(DA)) and Scope(DB) <> Scope(Source(DB)), // then prefer DA. Similarly, if Scope(DA) <> Scope(Source(DA)) and // Scope(DB) = Scope(Source(DB)), then prefer DB.if .Scope == .Scope && .Scope != .Scope {return }if .Scope != .Scope && .Scope == .Scope {return }// Rule 3: Avoid deprecated addresses. // If Source(DA) is deprecated and Source(DB) is not, then prefer DB. // Similarly, if Source(DA) is not deprecated and Source(DB) is // deprecated, then prefer DA.// TODO(bradfitz): implement? low priority for now.// Rule 4: Prefer home addresses. // If Source(DA) is simultaneously a home address and care-of address // and Source(DB) is not, then prefer DA. Similarly, if Source(DB) is // simultaneously a home address and care-of address and Source(DA) is // not, then prefer DB.// TODO(bradfitz): implement? low priority for now.// Rule 5: Prefer matching label. // If Label(Source(DA)) = Label(DA) and Label(Source(DB)) <> Label(DB), // then prefer DA. Similarly, if Label(Source(DA)) <> Label(DA) and // Label(Source(DB)) = Label(DB), then prefer DB.if .Label == .Label && .Label != .Label {return }if .Label != .Label && .Label == .Label {return }// Rule 6: Prefer higher precedence. // If Precedence(DA) > Precedence(DB), then prefer DA. Similarly, if // Precedence(DA) < Precedence(DB), then prefer DB.if .Precedence > .Precedence {return }if .Precedence < .Precedence {return }// Rule 7: Prefer native transport. // If DA is reached via an encapsulating transition mechanism (e.g., // IPv6 in IPv4) and DB is not, then prefer DB. Similarly, if DB is // reached via encapsulation and DA is not, then prefer DA.// TODO(bradfitz): implement? low priority for now.// Rule 8: Prefer smaller scope. // If Scope(DA) < Scope(DB), then prefer DA. Similarly, if Scope(DA) > // Scope(DB), then prefer DB.if .Scope < .Scope {return }if .Scope > .Scope {return }// Rule 9: Use longest matching prefix. // When DA and DB belong to the same address family (both are IPv6 or // 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. // // However, applying this rule to IPv4 addresses causes // problems (see issues 13283 and 18518), so limit to IPv6.if .To4() == nil && .To4() == nil { := commonPrefixLen(, ) := commonPrefixLen(, )if > {return }if < {return } }// Rule 10: Otherwise, leave the order unchanged. // If DA preceded DB in the original list, prefer DA. // Otherwise, prefer DB.returnfalse// "equal"}typepolicyTableEntrystruct { Prefix *IPNet Precedence uint8 Label uint8}typepolicyTable []policyTableEntry// RFC 6724 section 2.1.varrfc6724policyTable = policyTable{ {Prefix: mustCIDR("::1/128"),Precedence: 50,Label: 0, }, {Prefix: mustCIDR("::/0"),Precedence: 40,Label: 1, }, {// IPv4-compatible, etc.Prefix: mustCIDR("::ffff:0:0/96"),Precedence: 35,Label: 4, }, {// 6to4Prefix: mustCIDR("2002::/16"),Precedence: 30,Label: 2, }, {// TeredoPrefix: mustCIDR("2001::/32"),Precedence: 5,Label: 5, }, {Prefix: mustCIDR("fc00::/7"),Precedence: 3,Label: 13, }, {Prefix: mustCIDR("::/96"),Precedence: 1,Label: 3, }, {Prefix: mustCIDR("fec0::/10"),Precedence: 1,Label: 11, }, {Prefix: mustCIDR("3ffe::/16"),Precedence: 1,Label: 12, },}func () {sort.Sort(sort.Reverse(byMaskLength(rfc6724policyTable)))}// byMaskLength sorts policyTableEntry by the size of their Prefix.Mask.Size,// from smallest mask, to largest.typebyMaskLength []policyTableEntryfunc ( byMaskLength) () int { returnlen() }func ( byMaskLength) (, int) { [], [] = [], [] }func ( byMaskLength) (, int) bool { , := [].Prefix.Mask.Size() , := [].Prefix.Mask.Size()return < }// mustCIDR calls ParseCIDR and panics on any error, or if the network// is not IPv6.func ( string) *IPNet { , , := ParseCIDR()if != nil {panic(.Error()) }iflen() != IPv6len {panic("unexpected IP length") }return}// Classify returns the policyTableEntry of the entry with the longest// matching prefix that contains ip.// The table t must be sorted from largest mask size to smallest.func ( policyTable) ( IP) policyTableEntry {for , := range {if .Prefix.Contains() {return } }returnpolicyTableEntry{}}// RFC 6724 section 3.1.typescopeuint8const (scopeInterfaceLocalscope = 0x1scopeLinkLocalscope = 0x2scopeAdminLocalscope = 0x4scopeSiteLocalscope = 0x5scopeOrgLocalscope = 0x8scopeGlobalscope = 0xe)func ( IP) scope {if .IsLoopback() || .IsLinkLocalUnicast() {returnscopeLinkLocal } := len() == IPv6len && .To4() == nilif && .IsMulticast() {returnscope([1] & 0xf) }// Site-local addresses are defined in RFC 3513 section 2.5.6 // (and deprecated in RFC 3879).if && [0] == 0xfe && [1]&0xc0 == 0xc0 {returnscopeSiteLocal }returnscopeGlobal}// commonPrefixLen reports the length of the longest prefix (looking// at the most significant, or leftmost, bits) that the// two addresses have in common, up to the length of a's prefix (i.e.,// the portion of the address not including the interface ID).//// If a or b is an IPv4 address as an IPv6 address, the IPv4 addresses// are compared (with max common prefix length of 32).// If a and b are different IP versions, 0 is returned.//// See https://tools.ietf.org/html/rfc6724#section-2.2func (, IP) ( int) {if := .To4(); != nil { = }if := .To4(); != nil { = }iflen() != len() {return0 }// If IPv6, only up to the prefix (first 64 bits)iflen() > 8 { = [:8] = [:8] }forlen() > 0 {if [0] == [0] { += 8 = [1:] = [1:]continue } := 8 , := [0], [0]for { >>= 1 >>= 1 --if == { += return } } }return}