aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/dnsclient_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/dnsclient_unix.go')
-rw-r--r--libgo/go/net/dnsclient_unix.go41
1 files changed, 27 insertions, 14 deletions
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index c03c1b1..17188f0 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -20,14 +20,22 @@ import (
"io"
"math/rand"
"os"
- "strconv"
"sync"
"time"
)
+// A dnsDialer provides dialing suitable for DNS queries.
+type dnsDialer interface {
+ dialDNS(string, string) (dnsConn, error)
+}
+
+var testHookDNSDialer = func(d time.Duration) dnsDialer { return &Dialer{Timeout: d} }
+
// 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
@@ -122,7 +130,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,
@@ -165,9 +173,6 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, err
if len(cfg.servers) == 0 {
return "", nil, &DNSError{Err: "no DNS servers", Name: name}
}
- if len(name) >= 256 {
- return "", nil, &DNSError{Err: "DNS name too long", Name: name}
- }
timeout := time.Duration(cfg.timeout) * time.Second
var lastErr error
for i := 0; i < cfg.attempts; i++ {
@@ -186,7 +191,11 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, err
continue
}
cname, rrs, err := answer(name, server, msg, qtype)
- if err == nil || msg.rcode == dnsRcodeSuccess || msg.rcode == dnsRcodeNameError && msg.recursion_available {
+ // If answer errored for rcodes dnsRcodeSuccess or dnsRcodeNameError,
+ // it means the response in msg was not useful and trying another
+ // server probably won't help. Return now in those cases.
+ // TODO: indicate this in a more obvious way, such as a field on DNSError?
+ if err == nil || msg.rcode == dnsRcodeSuccess || msg.rcode == dnsRcodeNameError {
return cname, rrs, err
}
lastErr = err
@@ -374,7 +383,7 @@ func (o hostLookupOrder) String() string {
if s, ok := lookupOrderName[o]; ok {
return s
}
- return "hostLookupOrder=" + strconv.Itoa(int(o)) + "??"
+ return "hostLookupOrder=" + itoa(int(o)) + "??"
}
// goLookupHost is the native Go implementation of LookupHost.
@@ -440,7 +449,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 +460,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)...)
@@ -473,12 +486,12 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
}
sortByRFC6724(addrs)
if len(addrs) == 0 {
- if lastErr != nil {
- return nil, lastErr
- }
if order == hostLookupDNSFiles {
addrs = goLookupIPFiles(name)
}
+ if len(addrs) == 0 && lastErr != nil {
+ return nil, lastErr
+ }
}
return addrs, nil
}