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