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.
5 // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
7 // Minimal RFC 6724 address selection.
13 func sortByRFC6724(addrs
[]IPAddr
) {
17 sortByRFC6724withSrcs(addrs
, srcAddrs(addrs
))
20 func sortByRFC6724withSrcs(addrs
[]IPAddr
, srcs
[]IP
) {
21 if len(addrs
) != len(srcs
) {
22 panic("internal error")
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
])
30 sort
.Stable(&byRFC6724
{
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
{
46 dst
.Zone
= addrs
[i
].Zone
47 c
, err
:= DialUDP("udp", nil, &dst
)
49 if src
, ok
:= c
.LocalAddr().(*UDPAddr
); ok
{
64 func ipAttrOf(ip IP
) ipAttr
{
68 match
:= rfc6724policyTable
.Classify(ip
)
70 Scope
: classifyScope(ip
),
71 Precedence
: match
.Precedence
,
76 type byRFC6724
struct {
77 addrs
[]IPAddr
// addrs to sort
79 srcs
[]IP
// or nil if unreachable
83 func (s
*byRFC6724
) Len() int { return len(s
.addrs
) }
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
]
92 // Less reports whether i is a better destination address for this
95 // The algorithm and variable names comes from RFC 6724 section 6.
96 func (s
*byRFC6724
) Less(i
, j
int) bool {
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
]
106 const preferDA
= true
107 const preferDB
= false
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"
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
{
130 if attrDA
.Scope
!= attrSourceDA
.Scope
&& attrDB
.Scope
== attrSourceDB
.Scope
{
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.
139 // TODO(bradfitz): implement? low priority for now.
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.
147 // TODO(bradfitz): implement? low priority for now.
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
{
157 if attrSourceDA
.Label
!= attrDA
.Label
&&
158 attrSourceDB
.Label
== attrDB
.Label
{
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
{
168 if attrDA
.Precedence
< attrDB
.Precedence
{
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.
177 // TODO(bradfitz): implement? low priority for now.
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
{
185 if attrDA
.Scope
> attrDB
.Scope
{
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 [but see below]): If CommonPrefixLen(Source(DA), DA) >
192 // CommonPrefixLen(Source(DB), DB), then prefer DA. Similarly, if
193 // CommonPrefixLen(Source(DA), DA) < CommonPrefixLen(Source(DB), DB),
196 // However, applying this rule to IPv4 addresses causes
197 // problems (see issues 13283 and 18518), so limit to IPv6.
198 if DA
.To4() == nil && DB
.To4() == nil {
199 commonA
:= commonPrefixLen(SourceDA
, DA
)
200 commonB
:= commonPrefixLen(SourceDB
, DB
)
202 if commonA
> commonB
{
205 if commonA
< commonB
{
210 // Rule 10: Otherwise, leave the order unchanged.
211 // If DA preceded DB in the original list, prefer DA.
212 // Otherwise, prefer DB.
213 return false // "equal"
216 type policyTableEntry
struct {
222 type policyTable
[]policyTableEntry
224 // RFC 6724 section 2.1.
225 var rfc6724policyTable
= policyTable
{
227 Prefix
: mustCIDR("::1/128"),
232 Prefix
: mustCIDR("::/0"),
237 // IPv4-compatible, etc.
238 Prefix
: mustCIDR("::ffff:0:0/96"),
244 Prefix
: mustCIDR("2002::/16"),
250 Prefix
: mustCIDR("2001::/32"),
255 Prefix
: mustCIDR("fc00::/7"),
260 Prefix
: mustCIDR("::/96"),
265 Prefix
: mustCIDR("fec0::/10"),
270 Prefix
: mustCIDR("3ffe::/16"),
277 sort
.Sort(sort
.Reverse(byMaskLength(rfc6724policyTable
)))
280 // byMaskLength sorts policyTableEntry by the size of their Prefix.Mask.Size,
281 // from smallest mask, to largest.
282 type byMaskLength
[]policyTableEntry
284 func (s byMaskLength
) Len() int { return len(s
) }
285 func (s byMaskLength
) Swap(i
, j
int) { s
[i
], s
[j
] = s
[j
], s
[i
] }
286 func (s byMaskLength
) Less(i
, j
int) bool {
287 isize
, _
:= s
[i
].Prefix
.Mask
.Size()
288 jsize
, _
:= s
[j
].Prefix
.Mask
.Size()
292 // mustCIDR calls ParseCIDR and panics on any error, or if the network
294 func mustCIDR(s
string) *IPNet
{
295 ip
, ipNet
, err
:= ParseCIDR(s
)
299 if len(ip
) != IPv6len
{
300 panic("unexpected IP length")
305 // Classify returns the policyTableEntry of the entry with the longest
306 // matching prefix that contains ip.
307 // The table t must be sorted from largest mask size to smallest.
308 func (t policyTable
) Classify(ip IP
) policyTableEntry
{
309 for _
, ent
:= range t
{
310 if ent
.Prefix
.Contains(ip
) {
314 return policyTableEntry
{}
317 // RFC 6724 section 3.1.
321 scopeInterfaceLocal scope
= 0x1
322 scopeLinkLocal scope
= 0x2
323 scopeAdminLocal scope
= 0x4
324 scopeSiteLocal scope
= 0x5
325 scopeOrgLocal scope
= 0x8
326 scopeGlobal scope
= 0xe
329 func classifyScope(ip IP
) scope
{
330 if ip
.IsLoopback() || ip
.IsLinkLocalUnicast() {
331 return scopeLinkLocal
333 ipv6
:= len(ip
) == IPv6len
&& ip
.To4() == nil
334 if ipv6
&& ip
.IsMulticast() {
335 return scope(ip
[1] & 0xf)
337 // Site-local addresses are defined in RFC 3513 section 2.5.6
338 // (and deprecated in RFC 3879).
339 if ipv6
&& ip
[0] == 0xfe && ip
[1]&0xc0 == 0xc0 {
340 return scopeSiteLocal
345 // commonPrefixLen reports the length of the longest prefix (looking
346 // at the most significant, or leftmost, bits) that the
347 // two addresses have in common, up to the length of a's prefix (i.e.,
348 // the portion of the address not including the interface ID).
350 // If a or b is an IPv4 address as an IPv6 address, the IPv4 addresses
351 // are compared (with max common prefix length of 32).
352 // If a and b are different IP versions, 0 is returned.
354 // See https://tools.ietf.org/html/rfc6724#section-2.2
355 func commonPrefixLen(a
, b IP
) (cpl
int) {
356 if a4
:= a
.To4(); a4
!= nil {
359 if b4
:= b
.To4(); b4
!= nil {
362 if len(a
) != len(b
) {
365 // If IPv6, only up to the prefix (first 64 bits)