net: prefer error for original name on lookups

With certain names and search domain configurations the
returned error would be one encountered while querying a
generated name instead of the original name. This caused
confusion when a manual check of the same name produced
different results.

Now prefer errors encountered for the original name.

Also makes the low-level DNS connection plumbing swappable
in tests enabling tighter control over responses without
relying on the network.

Fixes #12712
Updates #13295

Change-Id: I780d628a762006bb11899caf20b5f97b462a717f
Reviewed-on: https://go-review.googlesource.com/16953
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Dan Peterson 2015-11-19 15:24:42 -04:00 committed by Russ Cox
parent be7544be23
commit 5c0629b503
3 changed files with 98 additions and 5 deletions

View file

@ -24,9 +24,16 @@ import (
"time"
)
// A dnsDialer provides dialing suitable for DNS queries.
type dnsDialer interface {
dialDNS(string, string) (dnsConn, error)
}
// A dnsConn represents a DNS transport endpoint.
type dnsConn interface {
Conn
io.Closer
SetDeadline(time.Time) error
// readDNSResponse reads a DNS response message from the DNS
// transport endpoint and returns the received DNS response
@ -121,7 +128,7 @@ func (d *Dialer) dialDNS(network, server string) (dnsConn, error) {
// exchange sends a query on the connection and hopes for a response.
func exchange(server, name string, qtype uint16, timeout time.Duration) (*dnsMsg, error) {
d := Dialer{Timeout: timeout}
d := testHookDNSDialer(timeout)
out := dnsMsg{
dnsMsgHdr: dnsMsgHdr{
recursion_desired: true,
@ -440,7 +447,8 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
conf := resolvConf.dnsConfig
resolvConf.mu.RUnlock()
type racer struct {
rrs []dnsRR
fqdn string
rrs []dnsRR
error
}
lane := make(chan racer, 1)
@ -450,13 +458,16 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
for _, qtype := range qtypes {
go func(qtype uint16) {
_, rrs, err := tryOneName(conf, fqdn, qtype)
lane <- racer{rrs, err}
lane <- racer{fqdn, rrs, err}
}(qtype)
}
for range qtypes {
racer := <-lane
if racer.error != nil {
lastErr = racer.error
// Prefer error for original name.
if lastErr == nil || racer.fqdn == name+"." {
lastErr = racer.error
}
continue
}
addrs = append(addrs, addrRecordList(racer.rrs)...)