Source file
src/net/lookup_unix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/bytealg"
12 "sync"
13 "syscall"
14
15 "golang.org/x/net/dns/dnsmessage"
16 )
17
18 var onceReadProtocols sync.Once
19
20
21
22 func readProtocols() {
23 file, err := open("/etc/protocols")
24 if err != nil {
25 return
26 }
27 defer file.close()
28
29 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
30
31 if i := bytealg.IndexByteString(line, '#'); i >= 0 {
32 line = line[0:i]
33 }
34 f := getFields(line)
35 if len(f) < 2 {
36 continue
37 }
38 if proto, _, ok := dtoi(f[1]); ok {
39 if _, ok := protocols[f[0]]; !ok {
40 protocols[f[0]] = proto
41 }
42 for _, alias := range f[2:] {
43 if _, ok := protocols[alias]; !ok {
44 protocols[alias] = proto
45 }
46 }
47 }
48 }
49 }
50
51
52
53 func lookupProtocol(_ context.Context, name string) (int, error) {
54 onceReadProtocols.Do(readProtocols)
55 return lookupProtocolMap(name)
56 }
57
58 func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) {
59
60
61
62
63
64 var c Conn
65 var err error
66 if r != nil && r.Dial != nil {
67 c, err = r.Dial(ctx, network, server)
68 } else {
69 var d Dialer
70 c, err = d.DialContext(ctx, network, server)
71 }
72 if err != nil {
73 return nil, mapErr(err)
74 }
75 return c, nil
76 }
77
78 func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
79 order := systemConf().hostLookupOrder(r, host)
80 if !r.preferGo() && order == hostLookupCgo {
81 if addrs, err, ok := cgoLookupHost(ctx, host); ok {
82 return addrs, err
83 }
84
85 order = hostLookupFilesDNS
86 }
87 return r.goLookupHostOrder(ctx, host, order)
88 }
89
90 func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) {
91 if r.preferGo() {
92 return r.goLookupIP(ctx, network, host)
93 }
94 order := systemConf().hostLookupOrder(r, host)
95 if order == hostLookupCgo {
96 if addrs, err, ok := cgoLookupIP(ctx, network, host); ok {
97 return addrs, err
98 }
99
100 order = hostLookupFilesDNS
101 }
102 ips, _, err := r.goLookupIPCNAMEOrder(ctx, network, host, order)
103 return ips, err
104 }
105
106 func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
107 if !r.preferGo() && systemConf().canUseCgo() {
108 if port, err, ok := cgoLookupPort(ctx, network, service); ok {
109 if err != nil {
110
111
112 if port, err := goLookupPort(network, service); err == nil {
113 return port, nil
114 }
115 }
116 return port, err
117 }
118 }
119 return goLookupPort(network, service)
120 }
121
122 func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
123 if !r.preferGo() && systemConf().canUseCgo() {
124 if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
125 return cname, err
126 }
127 }
128 return r.goLookupCNAME(ctx, name)
129 }
130
131 func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
132 var target string
133 if service == "" && proto == "" {
134 target = name
135 } else {
136 target = "_" + service + "._" + proto + "." + name
137 }
138 p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV)
139 if err != nil {
140 return "", nil, err
141 }
142 var srvs []*SRV
143 var cname dnsmessage.Name
144 for {
145 h, err := p.AnswerHeader()
146 if err == dnsmessage.ErrSectionDone {
147 break
148 }
149 if err != nil {
150 return "", nil, &DNSError{
151 Err: "cannot unmarshal DNS message",
152 Name: name,
153 Server: server,
154 }
155 }
156 if h.Type != dnsmessage.TypeSRV {
157 if err := p.SkipAnswer(); err != nil {
158 return "", nil, &DNSError{
159 Err: "cannot unmarshal DNS message",
160 Name: name,
161 Server: server,
162 }
163 }
164 continue
165 }
166 if cname.Length == 0 && h.Name.Length != 0 {
167 cname = h.Name
168 }
169 srv, err := p.SRVResource()
170 if err != nil {
171 return "", nil, &DNSError{
172 Err: "cannot unmarshal DNS message",
173 Name: name,
174 Server: server,
175 }
176 }
177 srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight})
178 }
179 byPriorityWeight(srvs).sort()
180 return cname.String(), srvs, nil
181 }
182
183 func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
184 p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX)
185 if err != nil {
186 return nil, err
187 }
188 var mxs []*MX
189 for {
190 h, err := p.AnswerHeader()
191 if err == dnsmessage.ErrSectionDone {
192 break
193 }
194 if err != nil {
195 return nil, &DNSError{
196 Err: "cannot unmarshal DNS message",
197 Name: name,
198 Server: server,
199 }
200 }
201 if h.Type != dnsmessage.TypeMX {
202 if err := p.SkipAnswer(); err != nil {
203 return nil, &DNSError{
204 Err: "cannot unmarshal DNS message",
205 Name: name,
206 Server: server,
207 }
208 }
209 continue
210 }
211 mx, err := p.MXResource()
212 if err != nil {
213 return nil, &DNSError{
214 Err: "cannot unmarshal DNS message",
215 Name: name,
216 Server: server,
217 }
218 }
219 mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref})
220
221 }
222 byPref(mxs).sort()
223 return mxs, nil
224 }
225
226 func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
227 p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS)
228 if err != nil {
229 return nil, err
230 }
231 var nss []*NS
232 for {
233 h, err := p.AnswerHeader()
234 if err == dnsmessage.ErrSectionDone {
235 break
236 }
237 if err != nil {
238 return nil, &DNSError{
239 Err: "cannot unmarshal DNS message",
240 Name: name,
241 Server: server,
242 }
243 }
244 if h.Type != dnsmessage.TypeNS {
245 if err := p.SkipAnswer(); err != nil {
246 return nil, &DNSError{
247 Err: "cannot unmarshal DNS message",
248 Name: name,
249 Server: server,
250 }
251 }
252 continue
253 }
254 ns, err := p.NSResource()
255 if err != nil {
256 return nil, &DNSError{
257 Err: "cannot unmarshal DNS message",
258 Name: name,
259 Server: server,
260 }
261 }
262 nss = append(nss, &NS{Host: ns.NS.String()})
263 }
264 return nss, nil
265 }
266
267 func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) {
268 p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT)
269 if err != nil {
270 return nil, err
271 }
272 var txts []string
273 for {
274 h, err := p.AnswerHeader()
275 if err == dnsmessage.ErrSectionDone {
276 break
277 }
278 if err != nil {
279 return nil, &DNSError{
280 Err: "cannot unmarshal DNS message",
281 Name: name,
282 Server: server,
283 }
284 }
285 if h.Type != dnsmessage.TypeTXT {
286 if err := p.SkipAnswer(); err != nil {
287 return nil, &DNSError{
288 Err: "cannot unmarshal DNS message",
289 Name: name,
290 Server: server,
291 }
292 }
293 continue
294 }
295 txt, err := p.TXTResource()
296 if err != nil {
297 return nil, &DNSError{
298 Err: "cannot unmarshal DNS message",
299 Name: name,
300 Server: server,
301 }
302 }
303
304
305
306 n := 0
307 for _, s := range txt.TXT {
308 n += len(s)
309 }
310 txtJoin := make([]byte, 0, n)
311 for _, s := range txt.TXT {
312 txtJoin = append(txtJoin, s...)
313 }
314 if len(txts) == 0 {
315 txts = make([]string, 0, 1)
316 }
317 txts = append(txts, string(txtJoin))
318 }
319 return txts, nil
320 }
321
322 func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
323 if !r.preferGo() && systemConf().canUseCgo() {
324 if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
325 return ptrs, err
326 }
327 }
328 return r.goLookupPTR(ctx, addr)
329 }
330
331
332
333
334
335
336
337
338
339
340
341 func concurrentThreadsLimit() int {
342 var rlim syscall.Rlimit
343 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil {
344 return 500
345 }
346 r := int(rlim.Cur)
347 if r > 500 {
348 r = 500
349 } else if r > 30 {
350 r -= 30
351 }
352 return r
353 }
354
View as plain text