1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
6
7// DNS client: see RFC 1035.
8// Has to be linked into package net for Dial.
9
10// TODO(rsc):
11//	Could potentially handle many outstanding lookups faster.
12//	Random UDP source port (net.Dial should do that for us).
13//	Random request IDs.
14
15package net
16
17import (
18	"context"
19	"errors"
20	"io"
21	"os"
22	"sync"
23	"time"
24
25	"golang.org/x/net/dns/dnsmessage"
26)
27
28const (
29	// to be used as a useTCP parameter to exchange
30	useTCPOnly  = true
31	useUDPOrTCP = false
32)
33
34var (
35	errLameReferral              = errors.New("lame referral")
36	errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
37	errCannotMarshalDNSMessage   = errors.New("cannot marshal DNS message")
38	errServerMisbehaving         = errors.New("server misbehaving")
39	errInvalidDNSResponse        = errors.New("invalid DNS response")
40	errNoAnswerFromDNSServer     = errors.New("no answer from DNS server")
41
42	// errServerTemporarilyMisbehaving is like errServerMisbehaving, except
43	// that when it gets translated to a DNSError, the IsTemporary field
44	// gets set to true.
45	errServerTemporarilyMisbehaving = errors.New("server misbehaving")
46)
47
48func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
49	id = uint16(randInt())
50	b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
51	b.EnableCompression()
52	if err := b.StartQuestions(); err != nil {
53		return 0, nil, nil, err
54	}
55	if err := b.Question(q); err != nil {
56		return 0, nil, nil, err
57	}
58	tcpReq, err = b.Finish()
59	udpReq = tcpReq[2:]
60	l := len(tcpReq) - 2
61	tcpReq[0] = byte(l >> 8)
62	tcpReq[1] = byte(l)
63	return id, udpReq, tcpReq, err
64}
65
66func checkResponse(reqID uint16, reqQues dnsmessage.Question, respHdr dnsmessage.Header, respQues dnsmessage.Question) bool {
67	if !respHdr.Response {
68		return false
69	}
70	if reqID != respHdr.ID {
71		return false
72	}
73	if reqQues.Type != respQues.Type || reqQues.Class != respQues.Class || !equalASCIIName(reqQues.Name, respQues.Name) {
74		return false
75	}
76	return true
77}
78
79func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte) (dnsmessage.Parser, dnsmessage.Header, error) {
80	if _, err := c.Write(b); err != nil {
81		return dnsmessage.Parser{}, dnsmessage.Header{}, err
82	}
83
84	b = make([]byte, 512) // see RFC 1035
85	for {
86		n, err := c.Read(b)
87		if err != nil {
88			return dnsmessage.Parser{}, dnsmessage.Header{}, err
89		}
90		var p dnsmessage.Parser
91		// Ignore invalid responses as they may be malicious
92		// forgery attempts. Instead continue waiting until
93		// timeout. See golang.org/issue/13281.
94		h, err := p.Start(b[:n])
95		if err != nil {
96			continue
97		}
98		q, err := p.Question()
99		if err != nil || !checkResponse(id, query, h, q) {
100			continue
101		}
102		return p, h, nil
103	}
104}
105
106func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte) (dnsmessage.Parser, dnsmessage.Header, error) {
107	if _, err := c.Write(b); err != nil {
108		return dnsmessage.Parser{}, dnsmessage.Header{}, err
109	}
110
111	b = make([]byte, 1280) // 1280 is a reasonable initial size for IP over Ethernet, see RFC 4035
112	if _, err := io.ReadFull(c, b[:2]); err != nil {
113		return dnsmessage.Parser{}, dnsmessage.Header{}, err
114	}
115	l := int(b[0])<<8 | int(b[1])
116	if l > len(b) {
117		b = make([]byte, l)
118	}
119	n, err := io.ReadFull(c, b[:l])
120	if err != nil {
121		return dnsmessage.Parser{}, dnsmessage.Header{}, err
122	}
123	var p dnsmessage.Parser
124	h, err := p.Start(b[:n])
125	if err != nil {
126		return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
127	}
128	q, err := p.Question()
129	if err != nil {
130		return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
131	}
132	if !checkResponse(id, query, h, q) {
133		return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
134	}
135	return p, h, nil
136}
137
138// exchange sends a query on the connection and hopes for a response.
139func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Question, timeout time.Duration, useTCP bool) (dnsmessage.Parser, dnsmessage.Header, error) {
140	q.Class = dnsmessage.ClassINET
141	id, udpReq, tcpReq, err := newRequest(q)
142	if err != nil {
143		return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
144	}
145	var networks []string
146	if useTCP {
147		networks = []string{"tcp"}
148	} else {
149		networks = []string{"udp", "tcp"}
150	}
151	for _, network := range networks {
152		ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
153		defer cancel()
154
155		c, err := r.dial(ctx, network, server)
156		if err != nil {
157			return dnsmessage.Parser{}, dnsmessage.Header{}, err
158		}
159		if d, ok := ctx.Deadline(); ok && !d.IsZero() {
160			c.SetDeadline(d)
161		}
162		var p dnsmessage.Parser
163		var h dnsmessage.Header
164		if _, ok := c.(PacketConn); ok {
165			p, h, err = dnsPacketRoundTrip(c, id, q, udpReq)
166		} else {
167			p, h, err = dnsStreamRoundTrip(c, id, q, tcpReq)
168		}
169		c.Close()
170		if err != nil {
171			return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
172		}
173		if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
174			return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
175		}
176		if h.Truncated { // see RFC 5966
177			continue
178		}
179		return p, h, nil
180	}
181	return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
182}
183
184// checkHeader performs basic sanity checks on the header.
185func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header) error {
186	if h.RCode == dnsmessage.RCodeNameError {
187		return errNoSuchHost
188	}
189
190	_, err := p.AnswerHeader()
191	if err != nil && err != dnsmessage.ErrSectionDone {
192		return errCannotUnmarshalDNSMessage
193	}
194
195	// libresolv continues to the next server when it receives
196	// an invalid referral response. See golang.org/issue/15434.
197	if h.RCode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
198		return errLameReferral
199	}
200
201	if h.RCode != dnsmessage.RCodeSuccess && h.RCode != dnsmessage.RCodeNameError {
202		// None of the error codes make sense
203		// for the query we sent. If we didn't get
204		// a name error and we didn't get success,
205		// the server is behaving incorrectly or
206		// having temporary trouble.
207		if h.RCode == dnsmessage.RCodeServerFailure {
208			return errServerTemporarilyMisbehaving
209		}
210		return errServerMisbehaving
211	}
212
213	return nil
214}
215
216func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type) error {
217	for {
218		h, err := p.AnswerHeader()
219		if err == dnsmessage.ErrSectionDone {
220			return errNoSuchHost
221		}
222		if err != nil {
223			return errCannotUnmarshalDNSMessage
224		}
225		if h.Type == qtype {
226			return nil
227		}
228		if err := p.SkipAnswer(); err != nil {
229			return errCannotUnmarshalDNSMessage
230		}
231	}
232}
233
234// Do a lookup for a single name, which must be rooted
235// (otherwise answer will not find the answers).
236func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype dnsmessage.Type) (dnsmessage.Parser, string, error) {
237	var lastErr error
238	serverOffset := cfg.serverOffset()
239	sLen := uint32(len(cfg.servers))
240
241	n, err := dnsmessage.NewName(name)
242	if err != nil {
243		return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
244	}
245	q := dnsmessage.Question{
246		Name:  n,
247		Type:  qtype,
248		Class: dnsmessage.ClassINET,
249	}
250
251	for i := 0; i < cfg.attempts; i++ {
252		for j := uint32(0); j < sLen; j++ {
253			server := cfg.servers[(serverOffset+j)%sLen]
254
255			p, h, err := r.exchange(ctx, server, q, cfg.timeout, cfg.useTCP)
256			if err != nil {
257				dnsErr := &DNSError{
258					Err:    err.Error(),
259					Name:   name,
260					Server: server,
261				}
262				if nerr, ok := err.(Error); ok && nerr.Timeout() {
263					dnsErr.IsTimeout = true
264				}
265				// Set IsTemporary for socket-level errors. Note that this flag
266				// may also be used to indicate a SERVFAIL response.
267				if _, ok := err.(*OpError); ok {
268					dnsErr.IsTemporary = true
269				}
270				lastErr = dnsErr
271				continue
272			}
273
274			if err := checkHeader(&p, h); err != nil {
275				dnsErr := &DNSError{
276					Err:    err.Error(),
277					Name:   name,
278					Server: server,
279				}
280				if err == errServerTemporarilyMisbehaving {
281					dnsErr.IsTemporary = true
282				}
283				if err == errNoSuchHost {
284					// The name does not exist, so trying
285					// another server won't help.
286
287					dnsErr.IsNotFound = true
288					return p, server, dnsErr
289				}
290				lastErr = dnsErr
291				continue
292			}
293
294			err = skipToAnswer(&p, qtype)
295			if err == nil {
296				return p, server, nil
297			}
298			lastErr = &DNSError{
299				Err:    err.Error(),
300				Name:   name,
301				Server: server,
302			}
303			if err == errNoSuchHost {
304				// The name does not exist, so trying another
305				// server won't help.
306
307				lastErr.(*DNSError).IsNotFound = true
308				return p, server, lastErr
309			}
310		}
311	}
312	return dnsmessage.Parser{}, "", lastErr
313}
314
315// A resolverConfig represents a DNS stub resolver configuration.
316type resolverConfig struct {
317	initOnce sync.Once // guards init of resolverConfig
318
319	// ch is used as a semaphore that only allows one lookup at a
320	// time to recheck resolv.conf.
321	ch          chan struct{} // guards lastChecked and modTime
322	lastChecked time.Time     // last time resolv.conf was checked
323
324	mu        sync.RWMutex // protects dnsConfig
325	dnsConfig *dnsConfig   // parsed resolv.conf structure used in lookups
326}
327
328var resolvConf resolverConfig
329
330// init initializes conf and is only called via conf.initOnce.
331func (conf *resolverConfig) init() {
332	// Set dnsConfig and lastChecked so we don't parse
333	// resolv.conf twice the first time.
334	conf.dnsConfig = systemConf().resolv
335	if conf.dnsConfig == nil {
336		conf.dnsConfig = dnsReadConfig("/etc/resolv.conf")
337	}
338	conf.lastChecked = time.Now()
339
340	// Prepare ch so that only one update of resolverConfig may
341	// run at once.
342	conf.ch = make(chan struct{}, 1)
343}
344
345// tryUpdate tries to update conf with the named resolv.conf file.
346// The name variable only exists for testing. It is otherwise always
347// "/etc/resolv.conf".
348func (conf *resolverConfig) tryUpdate(name string) {
349	conf.initOnce.Do(conf.init)
350
351	// Ensure only one update at a time checks resolv.conf.
352	if !conf.tryAcquireSema() {
353		return
354	}
355	defer conf.releaseSema()
356
357	now := time.Now()
358	if conf.lastChecked.After(now.Add(-5 * time.Second)) {
359		return
360	}
361	conf.lastChecked = now
362
363	var mtime time.Time
364	if fi, err := os.Stat(name); err == nil {
365		mtime = fi.ModTime()
366	}
367	if mtime.Equal(conf.dnsConfig.mtime) {
368		return
369	}
370
371	dnsConf := dnsReadConfig(name)
372	conf.mu.Lock()
373	conf.dnsConfig = dnsConf
374	conf.mu.Unlock()
375}
376
377func (conf *resolverConfig) tryAcquireSema() bool {
378	select {
379	case conf.ch <- struct{}{}:
380		return true
381	default:
382		return false
383	}
384}
385
386func (conf *resolverConfig) releaseSema() {
387	<-conf.ch
388}
389
390func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Type) (dnsmessage.Parser, string, error) {
391	if !isDomainName(name) {
392		// We used to use "invalid domain name" as the error,
393		// but that is a detail of the specific lookup mechanism.
394		// Other lookups might allow broader name syntax
395		// (for example Multicast DNS allows UTF-8; see RFC 6762).
396		// For consistency with libc resolvers, report no such host.
397		return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
398	}
399	resolvConf.tryUpdate("/etc/resolv.conf")
400	resolvConf.mu.RLock()
401	conf := resolvConf.dnsConfig
402	resolvConf.mu.RUnlock()
403	var (
404		p      dnsmessage.Parser
405		server string
406		err    error
407	)
408	for _, fqdn := range conf.nameList(name) {
409		p, server, err = r.tryOneName(ctx, conf, fqdn, qtype)
410		if err == nil {
411			break
412		}
413		if nerr, ok := err.(Error); ok && nerr.Temporary() && r.strictErrors() {
414			// If we hit a temporary error with StrictErrors enabled,
415			// stop immediately instead of trying more names.
416			break
417		}
418	}
419	if err == nil {
420		return p, server, nil
421	}
422	if err, ok := err.(*DNSError); ok {
423		// Show original name passed to lookup, not suffixed one.
424		// In general we might have tried many suffixes; showing
425		// just one is misleading. See also golang.org/issue/6324.
426		err.Name = name
427	}
428	return dnsmessage.Parser{}, "", err
429}
430
431// avoidDNS reports whether this is a hostname for which we should not
432// use DNS. Currently this includes only .onion, per RFC 7686. See
433// golang.org/issue/13705. Does not cover .local names (RFC 6762),
434// see golang.org/issue/16739.
435func avoidDNS(name string) bool {
436	if name == "" {
437		return true
438	}
439	if name[len(name)-1] == '.' {
440		name = name[:len(name)-1]
441	}
442	return stringsHasSuffixFold(name, ".onion")
443}
444
445// nameList returns a list of names for sequential DNS queries.
446func (conf *dnsConfig) nameList(name string) []string {
447	if avoidDNS(name) {
448		return nil
449	}
450
451	// Check name length (see isDomainName).
452	l := len(name)
453	rooted := l > 0 && name[l-1] == '.'
454	if l > 254 || l == 254 && rooted {
455		return nil
456	}
457
458	// If name is rooted (trailing dot), try only that name.
459	if rooted {
460		return []string{name}
461	}
462
463	hasNdots := count(name, '.') >= conf.ndots
464	name += "."
465	l++
466
467	// Build list of search choices.
468	names := make([]string, 0, 1+len(conf.search))
469	// If name has enough dots, try unsuffixed first.
470	if hasNdots {
471		names = append(names, name)
472	}
473	// Try suffixes that are not too long (see isDomainName).
474	for _, suffix := range conf.search {
475		if l+len(suffix) <= 254 {
476			names = append(names, name+suffix)
477		}
478	}
479	// Try unsuffixed, if not tried first above.
480	if !hasNdots {
481		names = append(names, name)
482	}
483	return names
484}
485
486// hostLookupOrder specifies the order of LookupHost lookup strategies.
487// It is basically a simplified representation of nsswitch.conf.
488// "files" means /etc/hosts.
489type hostLookupOrder int
490
491const (
492	// hostLookupCgo means defer to cgo.
493	hostLookupCgo      hostLookupOrder = iota
494	hostLookupFilesDNS                 // files first
495	hostLookupDNSFiles                 // dns first
496	hostLookupFiles                    // only files
497	hostLookupDNS                      // only DNS
498)
499
500var lookupOrderName = map[hostLookupOrder]string{
501	hostLookupCgo:      "cgo",
502	hostLookupFilesDNS: "files,dns",
503	hostLookupDNSFiles: "dns,files",
504	hostLookupFiles:    "files",
505	hostLookupDNS:      "dns",
506}
507
508func (o hostLookupOrder) String() string {
509	if s, ok := lookupOrderName[o]; ok {
510		return s
511	}
512	return "hostLookupOrder=" + itoa(int(o)) + "??"
513}
514
515// goLookupHost is the native Go implementation of LookupHost.
516// Used only if cgoLookupHost refuses to handle the request
517// (that is, only if cgoLookupHost is the stub in cgo_stub.go).
518// Normally we let cgo use the C library resolver instead of
519// depending on our lookup code, so that Go and C get the same
520// answers.
521func (r *Resolver) goLookupHost(ctx context.Context, name string) (addrs []string, err error) {
522	return r.goLookupHostOrder(ctx, name, hostLookupFilesDNS)
523}
524
525func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []string, err error) {
526	if order == hostLookupFilesDNS || order == hostLookupFiles {
527		// Use entries from /etc/hosts if they match.
528		addrs = lookupStaticHost(name)
529		if len(addrs) > 0 || order == hostLookupFiles {
530			return
531		}
532	}
533	ips, _, err := r.goLookupIPCNAMEOrder(ctx, name, order)
534	if err != nil {
535		return
536	}
537	addrs = make([]string, 0, len(ips))
538	for _, ip := range ips {
539		addrs = append(addrs, ip.String())
540	}
541	return
542}
543
544// lookup entries from /etc/hosts
545func goLookupIPFiles(name string) (addrs []IPAddr) {
546	for _, haddr := range lookupStaticHost(name) {
547		haddr, zone := splitHostZone(haddr)
548		if ip := ParseIP(haddr); ip != nil {
549			addr := IPAddr{IP: ip, Zone: zone}
550			addrs = append(addrs, addr)
551		}
552	}
553	sortByRFC6724(addrs)
554	return
555}
556
557// goLookupIP is the native Go implementation of LookupIP.
558// The libc versions are in cgo_*.go.
559func (r *Resolver) goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
560	order := systemConf().hostLookupOrder(r, host)
561	addrs, _, err = r.goLookupIPCNAMEOrder(ctx, host, order)
562	return
563}
564
565func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname dnsmessage.Name, err error) {
566	if order == hostLookupFilesDNS || order == hostLookupFiles {
567		addrs = goLookupIPFiles(name)
568		if len(addrs) > 0 || order == hostLookupFiles {
569			return addrs, dnsmessage.Name{}, nil
570		}
571	}
572	if !isDomainName(name) {
573		// See comment in func lookup above about use of errNoSuchHost.
574		return nil, dnsmessage.Name{}, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
575	}
576	resolvConf.tryUpdate("/etc/resolv.conf")
577	resolvConf.mu.RLock()
578	conf := resolvConf.dnsConfig
579	resolvConf.mu.RUnlock()
580	type result struct {
581		p      dnsmessage.Parser
582		server string
583		error
584	}
585	lane := make(chan result, 1)
586	qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA}
587	var queryFn func(fqdn string, qtype dnsmessage.Type)
588	var responseFn func(fqdn string, qtype dnsmessage.Type) result
589	if conf.singleRequest {
590		queryFn = func(fqdn string, qtype dnsmessage.Type) {}
591		responseFn = func(fqdn string, qtype dnsmessage.Type) result {
592			dnsWaitGroup.Add(1)
593			defer dnsWaitGroup.Done()
594			p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
595			return result{p, server, err}
596		}
597	} else {
598		queryFn = func(fqdn string, qtype dnsmessage.Type) {
599			dnsWaitGroup.Add(1)
600			go func(qtype dnsmessage.Type) {
601				p, server, err := r.tryOneName(ctx, conf, fqdn, qtype)
602				lane <- result{p, server, err}
603				dnsWaitGroup.Done()
604			}(qtype)
605		}
606		responseFn = func(fqdn string, qtype dnsmessage.Type) result {
607			return <-lane
608		}
609	}
610	var lastErr error
611	for _, fqdn := range conf.nameList(name) {
612		for _, qtype := range qtypes {
613			queryFn(fqdn, qtype)
614		}
615		hitStrictError := false
616		for _, qtype := range qtypes {
617			result := responseFn(fqdn, qtype)
618			if result.error != nil {
619				if nerr, ok := result.error.(Error); ok && nerr.Temporary() && r.strictErrors() {
620					// This error will abort the nameList loop.
621					hitStrictError = true
622					lastErr = result.error
623				} else if lastErr == nil || fqdn == name+"." {
624					// Prefer error for original name.
625					lastErr = result.error
626				}
627				continue
628			}
629
630			// Presotto says it's okay to assume that servers listed in
631			// /etc/resolv.conf are recursive resolvers.
632			//
633			// We asked for recursion, so it should have included all the
634			// answers we need in this one packet.
635			//
636			// Further, RFC 1035 section 4.3.1 says that "the recursive
637			// response to a query will be... The answer to the query,
638			// possibly preface by one or more CNAME RRs that specify
639			// aliases encountered on the way to an answer."
640			//
641			// Therefore, we should be able to assume that we can ignore
642			// CNAMEs and that the A and AAAA records we requested are
643			// for the canonical name.
644
645		loop:
646			for {
647				h, err := result.p.AnswerHeader()
648				if err != nil && err != dnsmessage.ErrSectionDone {
649					lastErr = &DNSError{
650						Err:    "cannot marshal DNS message",
651						Name:   name,
652						Server: result.server,
653					}
654				}
655				if err != nil {
656					break
657				}
658				switch h.Type {
659				case dnsmessage.TypeA:
660					a, err := result.p.AResource()
661					if err != nil {
662						lastErr = &DNSError{
663							Err:    "cannot marshal DNS message",
664							Name:   name,
665							Server: result.server,
666						}
667						break loop
668					}
669					addrs = append(addrs, IPAddr{IP: IP(a.A[:])})
670
671				case dnsmessage.TypeAAAA:
672					aaaa, err := result.p.AAAAResource()
673					if err != nil {
674						lastErr = &DNSError{
675							Err:    "cannot marshal DNS message",
676							Name:   name,
677							Server: result.server,
678						}
679						break loop
680					}
681					addrs = append(addrs, IPAddr{IP: IP(aaaa.AAAA[:])})
682
683				default:
684					if err := result.p.SkipAnswer(); err != nil {
685						lastErr = &DNSError{
686							Err:    "cannot marshal DNS message",
687							Name:   name,
688							Server: result.server,
689						}
690						break loop
691					}
692					continue
693				}
694				if cname.Length == 0 && h.Name.Length != 0 {
695					cname = h.Name
696				}
697			}
698		}
699		if hitStrictError {
700			// If either family hit an error with StrictErrors enabled,
701			// discard all addresses. This ensures that network flakiness
702			// cannot turn a dualstack hostname IPv4/IPv6-only.
703			addrs = nil
704			break
705		}
706		if len(addrs) > 0 {
707			break
708		}
709	}
710	if lastErr, ok := lastErr.(*DNSError); ok {
711		// Show original name passed to lookup, not suffixed one.
712		// In general we might have tried many suffixes; showing
713		// just one is misleading. See also golang.org/issue/6324.
714		lastErr.Name = name
715	}
716	sortByRFC6724(addrs)
717	if len(addrs) == 0 {
718		if order == hostLookupDNSFiles {
719			addrs = goLookupIPFiles(name)
720		}
721		if len(addrs) == 0 && lastErr != nil {
722			return nil, dnsmessage.Name{}, lastErr
723		}
724	}
725	return addrs, cname, nil
726}
727
728// goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME.
729func (r *Resolver) goLookupCNAME(ctx context.Context, host string) (string, error) {
730	order := systemConf().hostLookupOrder(r, host)
731	_, cname, err := r.goLookupIPCNAMEOrder(ctx, host, order)
732	return cname.String(), err
733}
734
735// goLookupPTR is the native Go implementation of LookupAddr.
736// Used only if cgoLookupPTR refuses to handle the request (that is,
737// only if cgoLookupPTR is the stub in cgo_stub.go).
738// Normally we let cgo use the C library resolver instead of depending
739// on our lookup code, so that Go and C get the same answers.
740func (r *Resolver) goLookupPTR(ctx context.Context, addr string) ([]string, error) {
741	names := lookupStaticAddr(addr)
742	if len(names) > 0 {
743		return names, nil
744	}
745	arpa, err := reverseaddr(addr)
746	if err != nil {
747		return nil, err
748	}
749	p, server, err := r.lookup(ctx, arpa, dnsmessage.TypePTR)
750	if err != nil {
751		return nil, err
752	}
753	var ptrs []string
754	for {
755		h, err := p.AnswerHeader()
756		if err == dnsmessage.ErrSectionDone {
757			break
758		}
759		if err != nil {
760			return nil, &DNSError{
761				Err:    "cannot marshal DNS message",
762				Name:   addr,
763				Server: server,
764			}
765		}
766		if h.Type != dnsmessage.TypePTR {
767			err := p.SkipAnswer()
768			if err != nil {
769				return nil, &DNSError{
770					Err:    "cannot marshal DNS message",
771					Name:   addr,
772					Server: server,
773				}
774			}
775			continue
776		}
777		ptr, err := p.PTRResource()
778		if err != nil {
779			return nil, &DNSError{
780				Err:    "cannot marshal DNS message",
781				Name:   addr,
782				Server: server,
783			}
784		}
785		ptrs = append(ptrs, ptr.PTR.String())
786
787	}
788	return ptrs, nil
789}
790