Source file
src/net/dnsclient_unix.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package net
14
15 import (
16 "context"
17 "errors"
18 "internal/bytealg"
19 "internal/itoa"
20 "io"
21 "os"
22 "runtime"
23 "sync"
24 "sync/atomic"
25 "time"
26
27 "golang.org/x/net/dns/dnsmessage"
28 )
29
30 const (
31
32 useTCPOnly = true
33 useUDPOrTCP = false
34
35
36
37 maxDNSPacketSize = 1232
38 )
39
40 var (
41 errLameReferral = errors.New("lame referral")
42 errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
43 errCannotMarshalDNSMessage = errors.New("cannot marshal DNS message")
44 errServerMisbehaving = errors.New("server misbehaving")
45 errInvalidDNSResponse = errors.New("invalid DNS response")
46 errNoAnswerFromDNSServer = errors.New("no answer from DNS server")
47
48
49
50
51 errServerTemporarilyMisbehaving = errors.New("server misbehaving")
52 )
53
54 func newRequest(q dnsmessage.Question, ad bool) (id uint16, udpReq, tcpReq []byte, err error) {
55 id = uint16(randInt())
56 b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true, AuthenticData: ad})
57 if err := b.StartQuestions(); err != nil {
58 return 0, nil, nil, err
59 }
60 if err := b.Question(q); err != nil {
61 return 0, nil, nil, err
62 }
63
64
65 if err := b.StartAdditionals(); err != nil {
66 return 0, nil, nil, err
67 }
68 var rh dnsmessage.ResourceHeader
69 if err := rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false); err != nil {
70 return 0, nil, nil, err
71 }
72 if err := b.OPTResource(rh, dnsmessage.OPTResource{}); err != nil {
73 return 0, nil, nil, err
74 }
75
76 tcpReq, err = b.Finish()
77 if err != nil {
78 return 0, nil, nil, err
79 }
80 udpReq = tcpReq[2:]
81 l := len(tcpReq) - 2
82 tcpReq[0] = byte(l >> 8)
83 tcpReq[1] = byte(l)
84 return id, udpReq, tcpReq, nil
85 }
86
87 func checkResponse(reqID uint16, reqQues dnsmessage.Question, respHdr dnsmessage.Header, respQues dnsmessage.Question) bool {
88 if !respHdr.Response {
89 return false
90 }
91 if reqID != respHdr.ID {
92 return false
93 }
94 if reqQues.Type != respQues.Type || reqQues.Class != respQues.Class || !equalASCIIName(reqQues.Name, respQues.Name) {
95 return false
96 }
97 return true
98 }
99
100 func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte) (dnsmessage.Parser, dnsmessage.Header, error) {
101 if _, err := c.Write(b); err != nil {
102 return dnsmessage.Parser{}, dnsmessage.Header{}, err
103 }
104
105 b = make([]byte, maxDNSPacketSize)
106 for {
107 n, err := c.Read(b)
108 if err != nil {
109 return dnsmessage.Parser{}, dnsmessage.Header{}, err
110 }
111 var p dnsmessage.Parser
112
113
114
115 h, err := p.Start(b[:n])
116 if err != nil {
117 continue
118 }
119 q, err := p.Question()
120 if err != nil || !checkResponse(id, query, h, q) {
121 continue
122 }
123 return p, h, nil
124 }
125 }
126
127 func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte) (dnsmessage.Parser, dnsmessage.Header, error) {
128 if _, err := c.Write(b); err != nil {
129 return dnsmessage.Parser{}, dnsmessage.Header{}, err
130 }
131
132 b = make([]byte, 1280)
133 if _, err := io.ReadFull(c, b[:2]); err != nil {
134 return dnsmessage.Parser{}, dnsmessage.Header{}, err
135 }
136 l := int(b[0])<<8 | int(b[1])
137 if l > len(b) {
138 b = make([]byte, l)
139 }
140 n, err := io.ReadFull(c, b[:l])
141 if err != nil {
142 return dnsmessage.Parser{}, dnsmessage.Header{}, err
143 }
144 var p dnsmessage.Parser
145 h, err := p.Start(b[:n])
146 if err != nil {
147 return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
148 }
149 q, err := p.Question()
150 if err != nil {
151 return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
152 }
153 if !checkResponse(id, query, h, q) {
154 return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
155 }
156 return p, h, nil
157 }
158
159
160 func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Question, timeout time.Duration, useTCP, ad bool) (dnsmessage.Parser, dnsmessage.Header, error) {
161 q.Class = dnsmessage.ClassINET
162 id, udpReq, tcpReq, err := newRequest(q, ad)
163 if err != nil {
164 return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
165 }
166 var networks []string
167 if useTCP {
168 networks = []string{"tcp"}
169 } else {
170 networks = []string{"udp", "tcp"}
171 }
172 for _, network := range networks {
173 ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
174 defer cancel()
175
176 c, err := r.dial(ctx, network, server)
177 if err != nil {
178 return dnsmessage.Parser{}, dnsmessage.Header{}, err
179 }
180 if d, ok := ctx.Deadline(); ok && !d.IsZero() {
181 c.SetDeadline(d)
182 }
183 var p dnsmessage.Parser
184 var h dnsmessage.Header
185 if _, ok := c.(PacketConn); ok {
186 p, h, err = dnsPacketRoundTrip(c, id, q, udpReq)
187 } else {
188 p, h, err = dnsStreamRoundTrip(c, id, q, tcpReq)
189 }
190 c.Close()
191 if err != nil {
192 return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
193 }
194 if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
195 return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
196 }
197 if h.Truncated {
198 continue
199 }
200 return p, h, nil
201 }
202 return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
203 }
204
205
206 func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header) error {
207 rcode := extractExtendedRCode(*p, h)
208
209 if rcode == dnsmessage.RCodeNameError {
210 return errNoSuchHost
211 }
212
213 _, err := p.AnswerHeader()
214 if err != nil && err != dnsmessage.ErrSectionDone {
215 return errCannotUnmarshalDNSMessage
216 }
217
218
219
220 if rcode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
221 return errLameReferral
222 }
223
224 if rcode != dnsmessage.RCodeSuccess && rcode != dnsmessage.RCodeNameError {
225
226
227
228
229
230 if rcode == dnsmessage.RCodeServerFailure {
231 return errServerTemporarilyMisbehaving
232 }
233 return errServerMisbehaving
234 }
235
236 return nil
237 }
238
239 func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type) error {
240 for {
241 h, err := p.AnswerHeader()
242 if err == dnsmessage.ErrSectionDone {
243 return errNoSuchHost
244 }
245 if err != nil {
246 return errCannotUnmarshalDNSMessage
247 }
248 if h.Type == qtype {
249 return nil
250 }
251 if err := p.SkipAnswer(); err != nil {
252 return errCannotUnmarshalDNSMessage
253 }
254 }
255 }
256
257
258
259 func extractExtendedRCode(p dnsmessage.Parser, hdr dnsmessage.Header) dnsmessage.RCode {
260 p.SkipAllAnswers()
261 p.SkipAllAuthorities()
262 for {
263 ahdr, err := p.AdditionalHeader()
264 if err != nil {
265 return hdr.RCode
266 }
267 if ahdr.Type == dnsmessage.TypeOPT {
268 return ahdr.ExtendedRCode(hdr.RCode)
269 }
270 p.SkipAdditional()
271 }
272 }
273
274
275
276 func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype dnsmessage.Type) (dnsmessage.Parser, string, error) {
277 var lastErr error
278 serverOffset := cfg.serverOffset()
279 sLen := uint32(len(cfg.servers))
280
281 n, err := dnsmessage.NewName(name)
282 if err != nil {
283 return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
284 }
285 q := dnsmessage.Question{
286 Name: n,
287 Type: qtype,
288 Class: dnsmessage.ClassINET,
289 }
290
291 for i := 0; i < cfg.attempts; i++ {
292 for j := uint32(0); j < sLen; j++ {
293 server := cfg.servers[(serverOffset+j)%sLen]
294
295 p, h, err := r.exchange(ctx, server, q, cfg.timeout, cfg.useTCP, cfg.trustAD)
296 if err != nil {
297 dnsErr := &DNSError{
298 Err: err.Error(),
299 Name: name,
300 Server: server,
301 }
302 if nerr, ok := err.(Error); ok && nerr.Timeout() {
303 dnsErr.IsTimeout = true
304 }
305
306
307 if _, ok := err.(*OpError); ok {
308 dnsErr.IsTemporary = true
309 }
310 lastErr = dnsErr
311 continue
312 }
313
314 if err := checkHeader(&p, h); err != nil {
315 dnsErr := &DNSError{
316 Err: err.Error(),
317 Name: name,
318 Server: server,
319 }
320 if err == errServerTemporarilyMisbehaving {
321 dnsErr.IsTemporary = true
322 }
323 if err == errNoSuchHost {
324
325
326
327 dnsErr.IsNotFound = true
328 return p, server, dnsErr
329 }
330 lastErr = dnsErr
331 continue
332 }
333
334 err = skipToAnswer(&p, qtype)
335 if err == nil {
336 return p, server, nil
337 }
338 lastErr = &DNSError{
339 Err: err.Error(),
340 Name: name,
341 Server: server,
342 }
343 if err == errNoSuchHost {
344
345
346
347 lastErr.(*DNSError).IsNotFound = true
348 return p, server, lastErr
349 }
350 }
351 }
352 return dnsmessage.Parser{}, "", lastErr
353 }
354
355
356 type resolverConfig struct {
357 initOnce sync.Once
358
359
360
361 ch chan struct{}
362 lastChecked time.Time
363
364 dnsConfig atomic.Pointer[dnsConfig]
365 }
366
367 var resolvConf resolverConfig
368
369 func getSystemDNSConfig() *dnsConfig {
370 resolvConf.tryUpdate("/etc/resolv.conf")
371 return resolvConf.dnsConfig.Load()
372 }
373
374
375 func (conf *resolverConfig) init() {
376
377
378 conf.dnsConfig.Store(dnsReadConfig("/etc/resolv.conf"))
379 conf.lastChecked = time.Now()
380
381
382
383 conf.ch = make(chan struct{}, 1)
384 }
385
386
387
388
389 func (conf *resolverConfig) tryUpdate(name string) {
390 conf.initOnce.Do(conf.init)
391
392 if conf.dnsConfig.Load().noReload {
393 return
394 }
395
396
397 if !conf.tryAcquireSema() {
398 return
399 }
400 defer conf.releaseSema()
401
402 now := time.Now()
403 if conf.lastChecked.After(now.Add(-5 * time.Second)) {
404 return
405 }
406 conf.lastChecked = now
407
408 switch runtime.GOOS {
409 case "windows":
410
411
412
413
414
415 default:
416 var mtime time.Time
417 if fi, err := os.Stat(name); err == nil {
418 mtime = fi.ModTime()
419 }
420 if mtime.Equal(conf.dnsConfig.Load().mtime) {
421 return
422 }
423 }
424
425 dnsConf := dnsReadConfig(name)
426 conf.dnsConfig.Store(dnsConf)
427 }
428
429 func (conf *resolverConfig) tryAcquireSema() bool {
430 select {
431 case conf.ch <- struct{}{}:
432 return true
433 default:
434 return false
435 }
436 }
437
438 func (conf *resolverConfig) releaseSema() {
439 <-conf.ch
440 }
441
442 func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Type, conf *dnsConfig) (dnsmessage.Parser, string, error) {
443 if !isDomainName(name) {
444
445
446
447
448
449 return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
450 }
451
452 if conf == nil {
453 conf = getSystemDNSConfig()
454 }
455
456 var (
457 p dnsmessage.Parser
458 server string
459 err error
460 )
461 for _, fqdn := range conf.nameList(name) {
462 p, server, err = r.tryOneName(ctx, conf, fqdn, qtype)
463 if err == nil {
464 break
465 }
466 if nerr, ok := err.(Error); ok && nerr.Temporary() && r.strictErrors() {
467
468
469 break
470 }
471 }
472 if err == nil {
473 return p, server, nil
474 }
475 if err, ok := err.(*DNSError); ok {
476
477
478
479 err.Name = name
480 }
481 return dnsmessage.Parser{}, "", err
482 }
483
484
485
486
487
488 func avoidDNS(name string) bool {
489 if name == "" {
490 return true
491 }
492 if name[len(name)-1] == '.' {
493 name = name[:len(name)-1]
494 }
495 return stringsHasSuffixFold(name, ".onion")
496 }
497
498
499 func (conf *dnsConfig) nameList(name string) []string {
500
501 l := len(name)
502 rooted := l > 0 && name[l-1] == '.'
503 if l > 254 || l == 254 && !rooted {
504 return nil
505 }
506
507
508 if rooted {
509 if avoidDNS(name) {
510 return nil
511 }
512 return []string{name}
513 }
514
515 hasNdots := bytealg.CountString(name, '.') >= conf.ndots
516 name += "."
517 l++
518
519
520 names := make([]string, 0, 1+len(conf.search))
521
522 if hasNdots && !avoidDNS(name) {
523 names = append(names, name)
524 }
525
526 for _, suffix := range conf.search {
527 fqdn := name + suffix
528 if !avoidDNS(fqdn) && len(fqdn) <= 254 {
529 names = append(names, fqdn)
530 }
531 }
532
533 if !hasNdots && !avoidDNS(name) {
534 names = append(names, name)
535 }
536 return names
537 }
538
539
540
541
542 type hostLookupOrder int
543
544 const (
545
546 hostLookupCgo hostLookupOrder = iota
547 hostLookupFilesDNS
548 hostLookupDNSFiles
549 hostLookupFiles
550 hostLookupDNS
551 )
552
553 var lookupOrderName = map[hostLookupOrder]string{
554 hostLookupCgo: "cgo",
555 hostLookupFilesDNS: "files,dns",
556 hostLookupDNSFiles: "dns,files",
557 hostLookupFiles: "files",
558 hostLookupDNS: "dns",
559 }
560
561 func (o hostLookupOrder) String() string {
562 if s, ok := lookupOrderName[o]; ok {
563 return s
564 }
565 return "hostLookupOrder=" + itoa.Itoa(int(o)) + "??"
566 }
567
568 func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder, conf *dnsConfig) (addrs []string, err error) {
569 if order == hostLookupFilesDNS || order == hostLookupFiles {
570
571 addrs, _ = lookupStaticHost(name)
572 if len(addrs) > 0 {
573 return
574 }
575
576 if order == hostLookupFiles {
577 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
578 }
579 }
580 ips, _, err := r.goLookupIPCNAMEOrder(ctx, "ip", name, order, conf)
581 if err != nil {
582 return
583 }
584 addrs = make([]string, 0, len(ips))
585 for _, ip := range ips {
586 addrs = append(addrs, ip.String())
587 }
588 return
589 }
590
591
592 func goLookupIPFiles(name string) (addrs []IPAddr, canonical string) {
593 addr, canonical := lookupStaticHost(name)
594 for _, haddr := range addr {
595 haddr, zone := splitHostZone(haddr)
596 if ip := ParseIP(haddr); ip != nil {
597 addr := IPAddr{IP: ip, Zone: zone}
598 addrs = append(addrs, addr)
599 }
600 }
601 sortByRFC6724(addrs)
602 return addrs, canonical
603 }
604
605
606
607 func (r *Resolver) goLookupIP(ctx context.Context, network, host string, order hostLookupOrder, conf *dnsConfig) (addrs []IPAddr, err error) {
608 addrs, _, err = r.goLookupIPCNAMEOrder(ctx, network, host, order, conf)
609 return
610 }
611
612 func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, network, name string, order hostLookupOrder, conf *dnsConfig) (addrs []IPAddr, cname dnsmessage.Name, err error) {
613 if order == hostLookupFilesDNS || order == hostLookupFiles {
614 var canonical string
615 addrs, canonical = goLookupIPFiles(name)
616
617 if len(addrs) > 0 {
618 var err error
619 cname, err = dnsmessage.NewName(canonical)
620 if err != nil {
621 return nil, dnsmessage.Name{}, err
622 }
623 return addrs, cname, nil
624 }
625
626 if order == hostLookupFiles {
627 return nil, dnsmessage.Name{}, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
628 }
629 }
630
631 if !isDomainName(name) {
632
633 return nil, dnsmessage.Name{}, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
634 }
635 type result struct {
636 p dnsmessage.Parser
637 server string
638 error
639 }
640
641 if conf == nil {
642 conf = getSystemDNSConfig()
643 }
644
645 lane := make(chan result, 1)
646 qtypes := []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
647 if network == "CNAME" {
648 qtypes = append(qtypes, dnsmessage.TypeCNAME)
649 }
650 switch ipVersion(network) {
651 case '4':
652 qtypes = []dnsmessage.Type{dnsmessage.TypeA}
653 case '6':
654 qtypes = []dnsmessage.Type{dnsmessage.TypeAAAA}
655 }
656 var queryFn func(fqdn string, qtype dnsmessage.Type)
657 var responseFn func(fqdn string, qtype dnsmessage.Type) result
658 if conf.singleRequest {
659 queryFn = func(fqdn string, qtype dnsmessage.Type) {}
660 responseFn = func(fqdn string, qtype dnsmessage.Type) result {
661 dnsWaitGroup.Add(1)
662 defer dnsWaitGroup.Done()
663 p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
664 return result{p, server, err}
665 }
666 } else {
667 queryFn = func(fqdn string, qtype dnsmessage.Type) {
668 dnsWaitGroup.Add(1)
669 go func(qtype dnsmessage.Type) {
670 p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
671 lane <- result{p, server, err}
672 dnsWaitGroup.Done()
673 }(qtype)
674 }
675 responseFn = func(fqdn string, qtype dnsmessage.Type) result {
676 return <-lane
677 }
678 }
679 var lastErr error
680 for _, fqdn := range conf.nameList(name) {
681 for _, qtype := range qtypes {
682 queryFn(fqdn, qtype)
683 }
684 hitStrictError := false
685 for _, qtype := range qtypes {
686 result := responseFn(fqdn, qtype)
687 if result.error != nil {
688 if nerr, ok := result.error.(Error); ok && nerr.Temporary() && r.strictErrors() {
689
690 hitStrictError = true
691 lastErr = result.error
692 } else if lastErr == nil || fqdn == name+"." {
693
694 lastErr = result.error
695 }
696 continue
697 }
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714 loop:
715 for {
716 h, err := result.p.AnswerHeader()
717 if err != nil && err != dnsmessage.ErrSectionDone {
718 lastErr = &DNSError{
719 Err: errCannotUnmarshalDNSMessage.Error(),
720 Name: name,
721 Server: result.server,
722 }
723 }
724 if err != nil {
725 break
726 }
727 switch h.Type {
728 case dnsmessage.TypeA:
729 a, err := result.p.AResource()
730 if err != nil {
731 lastErr = &DNSError{
732 Err: errCannotUnmarshalDNSMessage.Error(),
733 Name: name,
734 Server: result.server,
735 }
736 break loop
737 }
738 addrs = append(addrs, IPAddr{IP: IP(a.A[:])})
739 if cname.Length == 0 && h.Name.Length != 0 {
740 cname = h.Name
741 }
742
743 case dnsmessage.TypeAAAA:
744 aaaa, err := result.p.AAAAResource()
745 if err != nil {
746 lastErr = &DNSError{
747 Err: errCannotUnmarshalDNSMessage.Error(),
748 Name: name,
749 Server: result.server,
750 }
751 break loop
752 }
753 addrs = append(addrs, IPAddr{IP: IP(aaaa.AAAA[:])})
754 if cname.Length == 0 && h.Name.Length != 0 {
755 cname = h.Name
756 }
757
758 case dnsmessage.TypeCNAME:
759 c, err := result.p.CNAMEResource()
760 if err != nil {
761 lastErr = &DNSError{
762 Err: errCannotUnmarshalDNSMessage.Error(),
763 Name: name,
764 Server: result.server,
765 }
766 break loop
767 }
768 if cname.Length == 0 && c.CNAME.Length > 0 {
769 cname = c.CNAME
770 }
771
772 default:
773 if err := result.p.SkipAnswer(); err != nil {
774 lastErr = &DNSError{
775 Err: errCannotUnmarshalDNSMessage.Error(),
776 Name: name,
777 Server: result.server,
778 }
779 break loop
780 }
781 continue
782 }
783 }
784 }
785 if hitStrictError {
786
787
788
789 addrs = nil
790 break
791 }
792 if len(addrs) > 0 || network == "CNAME" && cname.Length > 0 {
793 break
794 }
795 }
796 if lastErr, ok := lastErr.(*DNSError); ok {
797
798
799
800 lastErr.Name = name
801 }
802 sortByRFC6724(addrs)
803 if len(addrs) == 0 && !(network == "CNAME" && cname.Length > 0) {
804 if order == hostLookupDNSFiles {
805 var canonical string
806 addrs, canonical = goLookupIPFiles(name)
807 if len(addrs) > 0 {
808 var err error
809 cname, err = dnsmessage.NewName(canonical)
810 if err != nil {
811 return nil, dnsmessage.Name{}, err
812 }
813 return addrs, cname, nil
814 }
815 }
816 if lastErr != nil {
817 return nil, dnsmessage.Name{}, lastErr
818 }
819 }
820 return addrs, cname, nil
821 }
822
823
824 func (r *Resolver) goLookupCNAME(ctx context.Context, host string, order hostLookupOrder, conf *dnsConfig) (string, error) {
825 _, cname, err := r.goLookupIPCNAMEOrder(ctx, "CNAME", host, order, conf)
826 return cname.String(), err
827 }
828
829
830 func (r *Resolver) goLookupPTR(ctx context.Context, addr string, order hostLookupOrder, conf *dnsConfig) ([]string, error) {
831 if order == hostLookupFiles || order == hostLookupFilesDNS {
832 names := lookupStaticAddr(addr)
833 if len(names) > 0 {
834 return names, nil
835 }
836
837 if order == hostLookupFiles {
838 return nil, &DNSError{Err: errNoSuchHost.Error(), Name: addr, IsNotFound: true}
839 }
840 }
841
842 arpa, err := reverseaddr(addr)
843 if err != nil {
844 return nil, err
845 }
846 p, server, err := r.lookup(ctx, arpa, dnsmessage.TypePTR, conf)
847 if err != nil {
848 var dnsErr *DNSError
849 if errors.As(err, &dnsErr) && dnsErr.IsNotFound {
850 if order == hostLookupDNSFiles {
851 names := lookupStaticAddr(addr)
852 if len(names) > 0 {
853 return names, nil
854 }
855 }
856 }
857 return nil, err
858 }
859 var ptrs []string
860 for {
861 h, err := p.AnswerHeader()
862 if err == dnsmessage.ErrSectionDone {
863 break
864 }
865 if err != nil {
866 return nil, &DNSError{
867 Err: errCannotUnmarshalDNSMessage.Error(),
868 Name: addr,
869 Server: server,
870 }
871 }
872 if h.Type != dnsmessage.TypePTR {
873 err := p.SkipAnswer()
874 if err != nil {
875 return nil, &DNSError{
876 Err: errCannotUnmarshalDNSMessage.Error(),
877 Name: addr,
878 Server: server,
879 }
880 }
881 continue
882 }
883 ptr, err := p.PTRResource()
884 if err != nil {
885 return nil, &DNSError{
886 Err: errCannotUnmarshalDNSMessage.Error(),
887 Name: addr,
888 Server: server,
889 }
890 }
891 ptrs = append(ptrs, ptr.PTR.String())
892
893 }
894
895 return ptrs, nil
896 }
897
View as plain text