diff options
| author | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
|---|---|---|
| committer | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
| commit | 64d2a7c8945ba05af859901f5e248f1befdd8621 (patch) | |
| tree | 013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/pkg/net/dnsclient_unix.go | |
| parent | b901efe83e212f0c34c769c079e41373da12d723 (diff) | |
| download | golang-64d2a7c8945ba05af859901f5e248f1befdd8621.tar.gz | |
Imported Upstream version 1.2upstream/1.2
Diffstat (limited to 'src/pkg/net/dnsclient_unix.go')
| -rw-r--r-- | src/pkg/net/dnsclient_unix.go | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/src/pkg/net/dnsclient_unix.go b/src/pkg/net/dnsclient_unix.go index 9e21bb4a0..16cf420dc 100644 --- a/src/pkg/net/dnsclient_unix.go +++ b/src/pkg/net/dnsclient_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin freebsd linux netbsd openbsd +// +build darwin dragonfly freebsd linux netbsd openbsd // DNS client: see RFC 1035. // Has to be linked into package net for Dial. @@ -17,6 +17,7 @@ package net import ( + "io" "math/rand" "sync" "time" @@ -25,6 +26,7 @@ import ( // Send a request on the connection and hope for a reply. // Up to cfg.attempts attempts. func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error) { + _, useTCP := c.(*TCPConn) if len(name) >= 256 { return nil, &DNSError{Err: "name too long", Name: name} } @@ -38,7 +40,10 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error if !ok { return nil, &DNSError{Err: "internal error - cannot pack message", Name: name} } - + if useTCP { + mlen := uint16(len(msg)) + msg = append([]byte{byte(mlen >> 8), byte(mlen)}, msg...) + } for attempt := 0; attempt < cfg.attempts; attempt++ { n, err := c.Write(msg) if err != nil { @@ -46,20 +51,33 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error } if cfg.timeout == 0 { - c.SetReadDeadline(time.Time{}) + c.SetReadDeadline(noDeadline) } else { c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second)) } - - buf := make([]byte, 2000) // More than enough. - n, err = c.Read(buf) + buf := make([]byte, 2000) + if useTCP { + n, err = io.ReadFull(c, buf[:2]) + if err != nil { + if e, ok := err.(Error); ok && e.Timeout() { + continue + } + } + mlen := int(buf[0])<<8 | int(buf[1]) + if mlen > len(buf) { + buf = make([]byte, mlen) + } + n, err = io.ReadFull(c, buf[:mlen]) + } else { + n, err = c.Read(buf) + } if err != nil { if e, ok := err.(Error); ok && e.Timeout() { continue } return nil, err } - buf = buf[0:n] + buf = buf[:n] in := new(dnsMsg) if !in.Unpack(buf) || in.id != out.id { continue @@ -98,6 +116,19 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs err = merr continue } + if msg.truncated { // see RFC 5966 + c, cerr = Dial("tcp", server) + if cerr != nil { + err = cerr + continue + } + msg, merr = exchange(cfg, c, name, qtype) + c.Close() + if merr != nil { + err = merr + continue + } + } cname, addrs, err = answer(name, server, msg, qtype) if err == nil || err.(*DNSError).Err == noSuchHost { break @@ -180,6 +211,12 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error) if err == nil { return } + if e, ok := err.(*DNSError); ok { + // Show original name passed to lookup, not suffixed one. + // In general we might have tried many suffixes; showing + // just one is misleading. See also golang.org/issue/6324. + e.Name = name + } return } |
