1 // Copyright 2009 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.
11 "golang_org/x/net/dns/dnsmessage"
14 // reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP
15 // address addr suitable for rDNS (PTR) record lookup or an error if it fails
16 // to parse the IP address.
17 func reverseaddr(addr
string) (arpa
string, err error
) {
20 return "", &DNSError
{Err
: "unrecognized address", Name
: addr
}
23 return uitoa(uint(ip
[15])) + "." + uitoa(uint(ip
[14])) + "." + uitoa(uint(ip
[13])) + "." + uitoa(uint(ip
[12])) + ".in-addr.arpa.", nil
26 buf
:= make([]byte, 0, len(ip
)*4+len("ip6.arpa."))
27 // Add it, in reverse, to the buffer
28 for i
:= len(ip
) - 1; i
>= 0; i
-- {
30 buf
= append(buf
, hexDigit
[v
&0xF])
31 buf
= append(buf
, '.')
32 buf
= append(buf
, hexDigit
[v
>>4])
33 buf
= append(buf
, '.')
35 // Append "ip6.arpa." and return (buf already has the final .)
36 buf
= append(buf
, "ip6.arpa."...)
37 return string(buf
), nil
40 func equalASCIIName(x
, y dnsmessage
.Name
) bool {
41 if x
.Length
!= y
.Length
{
44 for i
:= 0; i
< int(x
.Length
); i
++ {
47 if 'A' <= a
&& a
<= 'Z' {
50 if 'A' <= b
&& b
<= 'Z' {
60 // isDomainName checks if a string is a presentation-format domain name
61 // (currently restricted to hostname-compatible "preferred name" LDH labels and
62 // SRV-like "underscore labels"; see golang.org/issue/12421).
63 func isDomainName(s
string) bool {
64 // See RFC 1035, RFC 3696.
65 // Presentation format has dots before every label except the first, and the
66 // terminal empty label is optional here because we assume fully-qualified
67 // (absolute) input. We must therefore reserve space for the first and last
68 // labels' length octets in wire format, where they are necessary and the
69 // maximum total length is 255.
70 // So our _effective_ maximum is 253, but 254 is not rejected if the last
71 // character is a dot.
73 if l
== 0 || l
> 254 || l
== 254 && s
[l
-1] != '.' {
78 ok
:= false // Ok once we've seen a letter.
80 for i
:= 0; i
< len(s
); i
++ {
85 case 'a' <= c
&& c
<= 'z' ||
'A' <= c
&& c
<= 'Z' || c
== '_':
88 case '0' <= c
&& c
<= '9':
92 // Byte before dash cannot be dot.
98 // Byte before dot cannot be dot, dash.
99 if last
== '.' || last
== '-' {
102 if partlen
> 63 || partlen
== 0 {
109 if last
== '-' || partlen
> 63 {
116 // absDomainName returns an absolute domain name which ends with a
117 // trailing dot to match pure Go reverse resolver and all other lookup
119 // See golang.org/issue/12189.
120 // But we don't want to add dots for local names from /etc/hosts.
121 // It's hard to tell so we settle on the heuristic that names without dots
122 // (like "localhost" or "myhost") do not get trailing dots, but any other
124 func absDomainName(b
[]byte) string {
126 for _
, x
:= range b
{
132 if hasDots
&& b
[len(b
)-1] != '.' {
138 // An SRV represents a single DNS SRV record.
146 // byPriorityWeight sorts SRV records by ascending priority and weight.
147 type byPriorityWeight
[]*SRV
149 func (s byPriorityWeight
) Len() int { return len(s
) }
150 func (s byPriorityWeight
) Less(i
, j
int) bool {
151 return s
[i
].Priority
< s
[j
].Priority ||
(s
[i
].Priority
== s
[j
].Priority
&& s
[i
].Weight
< s
[j
].Weight
)
153 func (s byPriorityWeight
) Swap(i
, j
int) { s
[i
], s
[j
] = s
[j
], s
[i
] }
155 // shuffleByWeight shuffles SRV records by weight using the algorithm
156 // described in RFC 2782.
157 func (addrs byPriorityWeight
) shuffleByWeight() {
159 for _
, addr
:= range addrs
{
160 sum
+= int(addr
.Weight
)
162 for sum
> 0 && len(addrs
) > 1 {
165 for i
:= range addrs
{
166 s
+= int(addrs
[i
].Weight
)
169 addrs
[0], addrs
[i
] = addrs
[i
], addrs
[0]
174 sum
-= int(addrs
[0].Weight
)
179 // sort reorders SRV records as specified in RFC 2782.
180 func (addrs byPriorityWeight
) sort() {
183 for j
:= 1; j
< len(addrs
); j
++ {
184 if addrs
[i
].Priority
!= addrs
[j
].Priority
{
185 addrs
[i
:j
].shuffleByWeight()
189 addrs
[i
:].shuffleByWeight()
192 // An MX represents a single DNS MX record.
198 // byPref implements sort.Interface to sort MX records by preference
201 func (s byPref
) Len() int { return len(s
) }
202 func (s byPref
) Less(i
, j
int) bool { return s
[i
].Pref
< s
[j
].Pref
}
203 func (s byPref
) Swap(i
, j
int) { s
[i
], s
[j
] = s
[j
], s
[i
] }
205 // sort reorders MX records as specified in RFC 5321.
206 func (s byPref
) sort() {
208 j
:= rand
.Intn(i
+ 1)
209 s
[i
], s
[j
] = s
[j
], s
[i
]
214 // An NS represents a single DNS NS record.