Source file
src/net/conf.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "internal/bytealg"
11 "internal/godebug"
12 "os"
13 "runtime"
14 "sync"
15 "syscall"
16 )
17
18
19 type conf struct {
20
21 forceCgoLookupHost bool
22
23 netGo bool
24 netCgo bool
25
26
27 hasMDNSAllow bool
28
29 goos string
30 dnsDebugLevel int
31 }
32
33 var (
34 confOnce sync.Once
35 confVal = &conf{goos: runtime.GOOS}
36 )
37
38
39 func systemConf() *conf {
40 confOnce.Do(initConfVal)
41 return confVal
42 }
43
44 func initConfVal() {
45 dnsMode, debugLevel := goDebugNetDNS()
46 confVal.dnsDebugLevel = debugLevel
47 confVal.netGo = netGo || dnsMode == "go"
48 confVal.netCgo = netCgo || dnsMode == "cgo"
49 if !confVal.netGo && !confVal.netCgo && (runtime.GOOS == "windows" || runtime.GOOS == "plan9") {
50
51
52
53
54
55
56
57
58 confVal.netCgo = true
59 }
60
61 if confVal.dnsDebugLevel > 0 {
62 defer func() {
63 if confVal.dnsDebugLevel > 1 {
64 println("go package net: confVal.netCgo =", confVal.netCgo, " netGo =", confVal.netGo)
65 }
66 switch {
67 case confVal.netGo:
68 if netGo {
69 println("go package net: built with netgo build tag; using Go's DNS resolver")
70 } else {
71 println("go package net: GODEBUG setting forcing use of Go's resolver")
72 }
73 case confVal.forceCgoLookupHost:
74 println("go package net: using cgo DNS resolver")
75 default:
76 println("go package net: dynamic selection of DNS resolver")
77 }
78 }()
79 }
80
81
82
83
84 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
85 confVal.forceCgoLookupHost = true
86 return
87 }
88
89 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
90 return
91 }
92
93
94
95
96 _, localDomainDefined := syscall.Getenv("LOCALDOMAIN")
97 if os.Getenv("RES_OPTIONS") != "" ||
98 os.Getenv("HOSTALIASES") != "" ||
99 confVal.netCgo ||
100 localDomainDefined {
101 confVal.forceCgoLookupHost = true
102 return
103 }
104
105
106
107 if runtime.GOOS == "openbsd" && os.Getenv("ASR_CONFIG") != "" {
108 confVal.forceCgoLookupHost = true
109 return
110 }
111
112 if _, err := os.Stat("/etc/mdns.allow"); err == nil {
113 confVal.hasMDNSAllow = true
114 }
115 }
116
117
118
119 func (c *conf) canUseCgo() bool {
120 ret, _ := c.hostLookupOrder(nil, "")
121 return ret == hostLookupCgo
122 }
123
124
125
126
127 func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, dnsConfig *dnsConfig) {
128 if c.dnsDebugLevel > 1 {
129 defer func() {
130 print("go package net: hostLookupOrder(", hostname, ") = ", ret.String(), "\n")
131 }()
132 }
133 fallbackOrder := hostLookupCgo
134 if c.netGo || r.preferGo() {
135 switch c.goos {
136 case "windows":
137
138
139
140
141 fallbackOrder = hostLookupDNS
142 default:
143 fallbackOrder = hostLookupFilesDNS
144 }
145 }
146 if c.forceCgoLookupHost || c.goos == "android" || c.goos == "windows" || c.goos == "plan9" {
147 return fallbackOrder, nil
148 }
149 if bytealg.IndexByteString(hostname, '\\') != -1 || bytealg.IndexByteString(hostname, '%') != -1 {
150
151
152 return fallbackOrder, nil
153 }
154
155 conf := getSystemDNSConfig()
156 if conf.err != nil && !os.IsNotExist(conf.err) && !os.IsPermission(conf.err) {
157
158
159
160
161 return fallbackOrder, conf
162 }
163
164 if conf.unknownOpt {
165 return fallbackOrder, conf
166 }
167
168
169
170 if c.goos == "openbsd" {
171
172
173
174 if os.IsNotExist(conf.err) {
175 return hostLookupFiles, conf
176 }
177
178 lookup := conf.lookup
179 if len(lookup) == 0 {
180
181
182
183
184 return hostLookupDNSFiles, conf
185 }
186 if len(lookup) < 1 || len(lookup) > 2 {
187 return fallbackOrder, conf
188 }
189 switch lookup[0] {
190 case "bind":
191 if len(lookup) == 2 {
192 if lookup[1] == "file" {
193 return hostLookupDNSFiles, conf
194 }
195 return fallbackOrder, conf
196 }
197 return hostLookupDNS, conf
198 case "file":
199 if len(lookup) == 2 {
200 if lookup[1] == "bind" {
201 return hostLookupFilesDNS, conf
202 }
203 return fallbackOrder, conf
204 }
205 return hostLookupFiles, conf
206 default:
207 return fallbackOrder, conf
208 }
209 }
210
211
212 if stringsHasSuffix(hostname, ".") {
213 hostname = hostname[:len(hostname)-1]
214 }
215 if stringsHasSuffixFold(hostname, ".local") {
216
217
218
219
220 return fallbackOrder, conf
221 }
222
223 nss := getSystemNSS()
224 srcs := nss.sources["hosts"]
225
226
227 if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
228 if c.goos == "solaris" {
229
230 return fallbackOrder, conf
231 }
232
233 return hostLookupFilesDNS, conf
234 }
235 if nss.err != nil {
236
237
238
239 return fallbackOrder, conf
240 }
241
242 var mdnsSource, filesSource, dnsSource bool
243 var first string
244 for _, src := range srcs {
245 if src.source == "myhostname" {
246 if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
247 return fallbackOrder, conf
248 }
249 hn, err := getHostname()
250 if err != nil || stringsEqualFold(hostname, hn) {
251 return fallbackOrder, conf
252 }
253 continue
254 }
255 if src.source == "files" || src.source == "dns" {
256 if !src.standardCriteria() {
257 return fallbackOrder, conf
258 }
259 if src.source == "files" {
260 filesSource = true
261 } else if src.source == "dns" {
262 dnsSource = true
263 }
264 if first == "" {
265 first = src.source
266 }
267 continue
268 }
269 if stringsHasPrefix(src.source, "mdns") {
270
271
272
273 mdnsSource = true
274 continue
275 }
276
277 return fallbackOrder, conf
278 }
279
280
281
282
283 if mdnsSource && c.hasMDNSAllow {
284 return fallbackOrder, conf
285 }
286
287
288
289 switch {
290 case filesSource && dnsSource:
291 if first == "files" {
292 return hostLookupFilesDNS, conf
293 } else {
294 return hostLookupDNSFiles, conf
295 }
296 case filesSource:
297 return hostLookupFiles, conf
298 case dnsSource:
299 return hostLookupDNS, conf
300 }
301
302
303 return fallbackOrder, conf
304 }
305
306 var netdns = godebug.New("netdns")
307
308
309
310
311
312
313
314
315
316
317
318
319
320 func goDebugNetDNS() (dnsMode string, debugLevel int) {
321 goDebug := netdns.Value()
322 parsePart := func(s string) {
323 if s == "" {
324 return
325 }
326 if '0' <= s[0] && s[0] <= '9' {
327 debugLevel, _, _ = dtoi(s)
328 } else {
329 dnsMode = s
330 }
331 }
332 if i := bytealg.IndexByteString(goDebug, '+'); i != -1 {
333 parsePart(goDebug[:i])
334 parsePart(goDebug[i+1:])
335 return
336 }
337 parsePart(goDebug)
338 return
339 }
340
341
342
343 func isLocalhost(h string) bool {
344 return stringsEqualFold(h, "localhost") || stringsEqualFold(h, "localhost.localdomain") || stringsHasSuffixFold(h, ".localhost") || stringsHasSuffixFold(h, ".localhost.localdomain")
345 }
346
347
348
349 func isGateway(h string) bool {
350 return stringsEqualFold(h, "_gateway")
351 }
352
353
354
355 func isOutbound(h string) bool {
356 return stringsEqualFold(h, "_outbound")
357 }
358
View as plain text