dnsclient_unix.go 22 KB

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