diff options
author | Matt Harden <matt.harden@gmail.com> | 2017-02-20 05:58:55 -0800 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2017-05-12 18:08:12 +0000 |
commit | 380aa884b8b2935137eee266d0a44e9083fae71f (patch) | |
tree | 9bfc6df0b2812945abbb77dfe7fd505fff93cbe8 /src/net/dnsclient_unix.go | |
parent | 3b5637ff2bd5c03479780995e7a35c48222157c1 (diff) | |
download | go-380aa884b8b2935137eee266d0a44e9083fae71f.tar.gz go-380aa884b8b2935137eee266d0a44e9083fae71f.zip |
net: allow Resolver to use a custom dialer
In some cases it is desirable to customize the way the DNS server is
contacted, for instance to use a specific LocalAddr. While most
operating-system level resolvers do not allow this, we have the
opportunity to do so with the Go resolver. Most of the code was
already in place to allow tests to override the dialer. This exposes
that functionality, and as a side effect eliminates the need for a
testing hook.
Fixes #17404
Change-Id: I1c5e570f8edbcf630090f8ec6feb52e379e3e5c0
Reviewed-on: https://go-review.googlesource.com/37260
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/dnsclient_unix.go')
-rw-r--r-- | src/net/dnsclient_unix.go | 44 |
1 files changed, 6 insertions, 38 deletions
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 6613dc7593..75d70d3989 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -25,13 +25,6 @@ import ( "time" ) -// A dnsDialer provides dialing suitable for DNS queries. -type dnsDialer interface { - dialDNS(ctx context.Context, network, addr string) (dnsConn, error) -} - -var testHookDNSDialer = func() dnsDialer { return &Dialer{} } - // A dnsConn represents a DNS transport endpoint. type dnsConn interface { io.Closer @@ -116,33 +109,8 @@ func dnsRoundTripTCP(c io.ReadWriter, query *dnsMsg) (*dnsMsg, error) { return resp, nil } -func (d *Dialer) dialDNS(ctx context.Context, network, server string) (dnsConn, error) { - switch network { - case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6": - default: - return nil, UnknownNetworkError(network) - } - // Calling Dial here is scary -- we have to be sure not to - // dial a name that will require a DNS lookup, or Dial will - // call back here to translate it. The DNS config parser has - // already checked that all the cfg.servers are IP - // addresses, which Dial will use without a DNS lookup. - c, err := d.DialContext(ctx, network, server) - if err != nil { - return nil, mapErr(err) - } - switch network { - case "tcp", "tcp4", "tcp6": - return c.(*TCPConn), nil - case "udp", "udp4", "udp6": - return c.(*UDPConn), nil - } - panic("unreachable") -} - // exchange sends a query on the connection and hopes for a response. -func exchange(ctx context.Context, server, name string, qtype uint16, timeout time.Duration) (*dnsMsg, error) { - d := testHookDNSDialer() +func (r *Resolver) exchange(ctx context.Context, server, name string, qtype uint16, timeout time.Duration) (*dnsMsg, error) { out := dnsMsg{ dnsMsgHdr: dnsMsgHdr{ recursion_desired: true, @@ -158,7 +126,7 @@ func exchange(ctx context.Context, server, name string, qtype uint16, timeout ti ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout)) defer cancel() - c, err := d.dialDNS(ctx, network, server) + c, err := r.dial(ctx, network, server) if err != nil { return nil, err } @@ -181,7 +149,7 @@ func exchange(ctx context.Context, server, name string, qtype uint16, timeout ti // Do a lookup for a single name, which must be rooted // (otherwise answer will not find the answers). -func tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, error) { +func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, error) { var lastErr error serverOffset := cfg.serverOffset() sLen := uint32(len(cfg.servers)) @@ -190,7 +158,7 @@ func tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16) for j := uint32(0); j < sLen; j++ { server := cfg.servers[(serverOffset+j)%sLen] - msg, err := exchange(ctx, server, name, qtype, cfg.timeout) + msg, err := r.exchange(ctx, server, name, qtype, cfg.timeout) if err != nil { lastErr = &DNSError{ Err: err.Error(), @@ -333,7 +301,7 @@ func (r *Resolver) lookup(ctx context.Context, name string, qtype uint16) (cname conf := resolvConf.dnsConfig resolvConf.mu.RUnlock() for _, fqdn := range conf.nameList(name) { - cname, rrs, err = tryOneName(ctx, conf, fqdn, qtype) + cname, rrs, err = r.tryOneName(ctx, conf, fqdn, qtype) if err == nil { break } @@ -512,7 +480,7 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order for _, fqdn := range conf.nameList(name) { for _, qtype := range qtypes { go func(qtype uint16) { - cname, rrs, err := tryOneName(ctx, conf, fqdn, qtype) + cname, rrs, err := r.tryOneName(ctx, conf, fqdn, qtype) lane <- racer{cname, rrs, err} }(qtype) } |