Source file
src/net/dnsclient.go
1
2
3
4
5 package net
6
7 import (
8 "internal/bytealg"
9 "internal/itoa"
10 "sort"
11
12 "golang.org/x/net/dns/dnsmessage"
13 )
14
15
16 func fastrandu() uint
17
18 func randInt() int {
19 return int(fastrandu() >> 1)
20 }
21
22 func randIntn(n int) int {
23 return randInt() % n
24 }
25
26
27
28
29 func reverseaddr(addr string) (arpa string, err error) {
30 ip := ParseIP(addr)
31 if ip == nil {
32 return "", &DNSError{Err: "unrecognized address", Name: addr}
33 }
34 if ip.To4() != nil {
35 return itoa.Uitoa(uint(ip[15])) + "." + itoa.Uitoa(uint(ip[14])) + "." + itoa.Uitoa(uint(ip[13])) + "." + itoa.Uitoa(uint(ip[12])) + ".in-addr.arpa.", nil
36 }
37
38 buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
39
40 for i := len(ip) - 1; i >= 0; i-- {
41 v := ip[i]
42 buf = append(buf, hexDigit[v&0xF],
43 '.',
44 hexDigit[v>>4],
45 '.')
46 }
47
48 buf = append(buf, "ip6.arpa."...)
49 return string(buf), nil
50 }
51
52 func equalASCIIName(x, y dnsmessage.Name) bool {
53 if x.Length != y.Length {
54 return false
55 }
56 for i := 0; i < int(x.Length); i++ {
57 a := x.Data[i]
58 b := y.Data[i]
59 if 'A' <= a && a <= 'Z' {
60 a += 0x20
61 }
62 if 'A' <= b && b <= 'Z' {
63 b += 0x20
64 }
65 if a != b {
66 return false
67 }
68 }
69 return true
70 }
71
72
73
74
75 func isDomainName(s string) bool {
76
77 if s == "." {
78 return true
79 }
80
81
82
83
84
85
86
87
88
89 l := len(s)
90 if l == 0 || l > 254 || l == 254 && s[l-1] != '.' {
91 return false
92 }
93
94 last := byte('.')
95 nonNumeric := false
96 partlen := 0
97 for i := 0; i < len(s); i++ {
98 c := s[i]
99 switch {
100 default:
101 return false
102 case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
103 nonNumeric = true
104 partlen++
105 case '0' <= c && c <= '9':
106
107 partlen++
108 case c == '-':
109
110 if last == '.' {
111 return false
112 }
113 partlen++
114 nonNumeric = true
115 case c == '.':
116
117 if last == '.' || last == '-' {
118 return false
119 }
120 if partlen > 63 || partlen == 0 {
121 return false
122 }
123 partlen = 0
124 }
125 last = c
126 }
127 if last == '-' || partlen > 63 {
128 return false
129 }
130
131 return nonNumeric
132 }
133
134
135
136
137
138
139
140
141
142 func absDomainName(s string) string {
143 if bytealg.IndexByteString(s, '.') != -1 && s[len(s)-1] != '.' {
144 s += "."
145 }
146 return s
147 }
148
149
150 type SRV struct {
151 Target string
152 Port uint16
153 Priority uint16
154 Weight uint16
155 }
156
157
158 type byPriorityWeight []*SRV
159
160 func (s byPriorityWeight) Len() int { return len(s) }
161 func (s byPriorityWeight) Less(i, j int) bool {
162 return s[i].Priority < s[j].Priority || (s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
163 }
164 func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
165
166
167
168 func (addrs byPriorityWeight) shuffleByWeight() {
169 sum := 0
170 for _, addr := range addrs {
171 sum += int(addr.Weight)
172 }
173 for sum > 0 && len(addrs) > 1 {
174 s := 0
175 n := randIntn(sum)
176 for i := range addrs {
177 s += int(addrs[i].Weight)
178 if s > n {
179 if i > 0 {
180 addrs[0], addrs[i] = addrs[i], addrs[0]
181 }
182 break
183 }
184 }
185 sum -= int(addrs[0].Weight)
186 addrs = addrs[1:]
187 }
188 }
189
190
191 func (addrs byPriorityWeight) sort() {
192 sort.Sort(addrs)
193 i := 0
194 for j := 1; j < len(addrs); j++ {
195 if addrs[i].Priority != addrs[j].Priority {
196 addrs[i:j].shuffleByWeight()
197 i = j
198 }
199 }
200 addrs[i:].shuffleByWeight()
201 }
202
203
204 type MX struct {
205 Host string
206 Pref uint16
207 }
208
209
210 type byPref []*MX
211
212 func (s byPref) Len() int { return len(s) }
213 func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref }
214 func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
215
216
217 func (s byPref) sort() {
218 for i := range s {
219 j := randIntn(i + 1)
220 s[i], s[j] = s[j], s[i]
221 }
222 sort.Sort(s)
223 }
224
225
226 type NS struct {
227 Host string
228 }
229
View as plain text