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