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