From: Paul Marks Date: Wed, 2 Nov 2016 04:01:08 +0000 (-0700) Subject: net: add Resolver.StrictErrors X-Git-Tag: go1.9beta1~1217 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=bfc164c64d33edfaf774b5c29b9bf5648a6447fb;p=gostls13.git net: add Resolver.StrictErrors When LookupIP is performing multiple subqueries, this option causes a timeout/servfail affecting a single query to abort the whole operation, instead of returning a partial (IPv4/IPv6-only) result. Similarly, operations that walk the DNS search list will also abort when encountering one of these errors. Fixes #17448 Change-Id: Ice22e4aceb555c5a80d19bd1fde8b8fe87ac9517 Reviewed-on: https://go-review.googlesource.com/32572 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 4dd4e16b0f..6613dc7593 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -200,6 +200,11 @@ func tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16) if nerr, ok := err.(Error); ok && nerr.Timeout() { lastErr.(*DNSError).IsTimeout = true } + // Set IsTemporary for socket-level errors. Note that this flag + // may also be used to indicate a SERVFAIL response. + if _, ok := err.(*OpError); ok { + lastErr.(*DNSError).IsTemporary = true + } continue } // libresolv continues to the next server when it receives @@ -314,7 +319,7 @@ func (conf *resolverConfig) releaseSema() { <-conf.ch } -func lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs []dnsRR, err error) { +func (r *Resolver) lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs []dnsRR, err error) { if !isDomainName(name) { // We used to use "invalid domain name" as the error, // but that is a detail of the specific lookup mechanism. @@ -332,6 +337,11 @@ func lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs [ if err == nil { break } + if nerr, ok := err.(Error); ok && nerr.Temporary() && r.StrictErrors { + // If we hit a temporary error with StrictErrors enabled, + // stop immediately instead of trying more names. + break + } } if err, ok := err.(*DNSError); ok { // Show original name passed to lookup, not suffixed one. @@ -432,11 +442,11 @@ func (o hostLookupOrder) String() string { // Normally we let cgo use the C library resolver instead of // depending on our lookup code, so that Go and C get the same // answers. -func goLookupHost(ctx context.Context, name string) (addrs []string, err error) { - return goLookupHostOrder(ctx, name, hostLookupFilesDNS) +func (r *Resolver) goLookupHost(ctx context.Context, name string) (addrs []string, err error) { + return r.goLookupHostOrder(ctx, name, hostLookupFilesDNS) } -func goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []string, err error) { +func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []string, err error) { if order == hostLookupFilesDNS || order == hostLookupFiles { // Use entries from /etc/hosts if they match. addrs = lookupStaticHost(name) @@ -444,7 +454,7 @@ func goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder) return } } - ips, _, err := goLookupIPCNAMEOrder(ctx, name, order) + ips, _, err := r.goLookupIPCNAMEOrder(ctx, name, order) if err != nil { return } @@ -470,13 +480,13 @@ func goLookupIPFiles(name string) (addrs []IPAddr) { // goLookupIP is the native Go implementation of LookupIP. // The libc versions are in cgo_*.go. -func goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { +func (r *Resolver) goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { order := systemConf().hostLookupOrder(host) - addrs, _, err = goLookupIPCNAMEOrder(ctx, host, order) + addrs, _, err = r.goLookupIPCNAMEOrder(ctx, host, order) return } -func goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname string, err error) { +func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname string, err error) { if order == hostLookupFilesDNS || order == hostLookupFiles { addrs = goLookupIPFiles(name) if len(addrs) > 0 || order == hostLookupFiles { @@ -506,11 +516,16 @@ func goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrde lane <- racer{cname, rrs, err} }(qtype) } + hitStrictError := false for range qtypes { racer := <-lane if racer.error != nil { - // Prefer error for original name. - if lastErr == nil || fqdn == name+"." { + if nerr, ok := racer.error.(Error); ok && nerr.Temporary() && r.StrictErrors { + // This error will abort the nameList loop. + hitStrictError = true + lastErr = racer.error + } else if lastErr == nil || fqdn == name+"." { + // Prefer error for original name. lastErr = racer.error } continue @@ -520,6 +535,13 @@ func goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrde cname = racer.cname } } + if hitStrictError { + // If either family hit an error with StrictErrors enabled, + // discard all addresses. This ensures that network flakiness + // cannot turn a dualstack hostname IPv4/IPv6-only. + addrs = nil + break + } if len(addrs) > 0 { break } @@ -543,9 +565,9 @@ func goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrde } // goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME. -func goLookupCNAME(ctx context.Context, host string) (cname string, err error) { +func (r *Resolver) goLookupCNAME(ctx context.Context, host string) (cname string, err error) { order := systemConf().hostLookupOrder(host) - _, cname, err = goLookupIPCNAMEOrder(ctx, host, order) + _, cname, err = r.goLookupIPCNAMEOrder(ctx, host, order) return } @@ -554,7 +576,7 @@ func goLookupCNAME(ctx context.Context, host string) (cname string, err error) { // only if cgoLookupPTR is the stub in cgo_stub.go). // Normally we let cgo use the C library resolver instead of depending // on our lookup code, so that Go and C get the same answers. -func goLookupPTR(ctx context.Context, addr string) ([]string, error) { +func (r *Resolver) goLookupPTR(ctx context.Context, addr string) ([]string, error) { names := lookupStaticAddr(addr) if len(names) > 0 { return names, nil @@ -563,7 +585,7 @@ func goLookupPTR(ctx context.Context, addr string) ([]string, error) { if err != nil { return nil, err } - _, rrs, err := lookup(ctx, arpa, dnsTypePTR) + _, rrs, err := r.lookup(ctx, arpa, dnsTypePTR) if err != nil { return nil, err } diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 4464804c70..ec28af68fb 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -24,6 +24,9 @@ import ( // Test address from 192.0.2.0/24 block, reserved by RFC 5737 for documentation. const TestAddr uint32 = 0xc0000201 +// Test address from 2001:db8::/32 block, reserved by RFC 3849 for documentation. +var TestAddr6 = [16]byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + var dnsTransportFallbackTests = []struct { server string name string @@ -142,7 +145,7 @@ func TestAvoidDNSName(t *testing.T) { // Issue 13705: don't try to resolve onion addresses, etc func TestLookupTorOnion(t *testing.T) { - addrs, err := goLookupIP(context.Background(), "foo.onion") + addrs, err := DefaultResolver.goLookupIP(context.Background(), "foo.onion") if len(addrs) > 0 { t.Errorf("unexpected addresses: %v", addrs) } @@ -258,7 +261,7 @@ func TestUpdateResolvConf(t *testing.T) { for j := 0; j < N; j++ { go func(name string) { defer wg.Done() - ips, err := goLookupIP(context.Background(), name) + ips, err := DefaultResolver.goLookupIP(context.Background(), name) if err != nil { t.Error(err) return @@ -406,7 +409,7 @@ func TestGoLookupIPWithResolverConfig(t *testing.T) { t.Error(err) continue } - addrs, err := goLookupIP(context.Background(), tt.name) + addrs, err := DefaultResolver.goLookupIP(context.Background(), tt.name) if err != nil { // This test uses external network connectivity. // We need to take care with errors on both @@ -456,14 +459,14 @@ func TestGoLookupIPOrderFallbackToFile(t *testing.T) { name := fmt.Sprintf("order %v", order) // First ensure that we get an error when contacting a non-existent host. - _, _, err := goLookupIPCNAMEOrder(context.Background(), "notarealhost", order) + _, _, err := DefaultResolver.goLookupIPCNAMEOrder(context.Background(), "notarealhost", order) if err == nil { t.Errorf("%s: expected error while looking up name not in hosts file", name) continue } // Now check that we get an address when the name appears in the hosts file. - addrs, _, err := goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts" + addrs, _, err := DefaultResolver.goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts" if err != nil { t.Errorf("%s: expected to successfully lookup host entry", name) continue @@ -519,14 +522,24 @@ func TestErrorForOriginalNameWhenSearching(t *testing.T) { return r, nil } - _, err = goLookupIP(context.Background(), fqdn) - if err == nil { - t.Fatal("expected an error") + cases := []struct { + strictErrors bool + wantErr *DNSError + }{ + {true, &DNSError{Name: fqdn, Err: "server misbehaving", IsTemporary: true}}, + {false, &DNSError{Name: fqdn, Err: errNoSuchHost.Error()}}, } + for _, tt := range cases { + r := Resolver{StrictErrors: tt.strictErrors} + _, err = r.goLookupIP(context.Background(), fqdn) + if err == nil { + t.Fatal("expected an error") + } - want := &DNSError{Name: fqdn, Err: errNoSuchHost.Error()} - if err, ok := err.(*DNSError); !ok || err.Name != want.Name || err.Err != want.Err { - t.Errorf("got %v; want %v", err, want) + want := tt.wantErr + if err, ok := err.(*DNSError); !ok || err.Name != want.Name || err.Err != want.Err || err.IsTemporary != want.IsTemporary { + t.Errorf("got %v; want %v", err, want) + } } } @@ -579,7 +592,7 @@ func TestIgnoreLameReferrals(t *testing.T) { return r, nil } - addrs, err := goLookupIP(context.Background(), "www.golang.org") + addrs, err := DefaultResolver.goLookupIP(context.Background(), "www.golang.org") if err != nil { t.Fatal(err) } @@ -598,7 +611,7 @@ func BenchmarkGoLookupIP(b *testing.B) { ctx := context.Background() for i := 0; i < b.N; i++ { - goLookupIP(ctx, "www.example.com") + DefaultResolver.goLookupIP(ctx, "www.example.com") } } @@ -607,7 +620,7 @@ func BenchmarkGoLookupIPNoSuchHost(b *testing.B) { ctx := context.Background() for i := 0; i < b.N; i++ { - goLookupIP(ctx, "some.nonexistent") + DefaultResolver.goLookupIP(ctx, "some.nonexistent") } } @@ -630,7 +643,7 @@ func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) { ctx := context.Background() for i := 0; i < b.N; i++ { - goLookupIP(ctx, "www.example.com") + DefaultResolver.goLookupIP(ctx, "www.example.com") } } @@ -861,3 +874,309 @@ func mockTXTResponse(q *dnsMsg) *dnsMsg { return r } + +// Issue 17448. With StrictErrors enabled, temporary errors should make +// LookupIP fail rather than return a partial result. +func TestStrictErrorsLookupIP(t *testing.T) { + origTestHookDNSDialer := testHookDNSDialer + defer func() { testHookDNSDialer = origTestHookDNSDialer }() + + conf, err := newResolvConfTest() + if err != nil { + t.Fatal(err) + } + defer conf.teardown() + + confData := []string{ + "nameserver 192.0.2.53", + "search x.golang.org y.golang.org", + } + if err := conf.writeAndUpdate(confData); err != nil { + t.Fatal(err) + } + + const name = "test" + const server = "192.0.2.53:53" + const searchX = "test.x.golang.org." + const searchY = "test.y.golang.org." + const ip4 = "192.0.2.1" + const ip6 = "2001:db8::1" + + type resolveWhichEnum int + const ( + resolveOK resolveWhichEnum = iota + resolveOpError + resolveServfail + resolveTimeout + ) + + makeTempError := func(err string) error { + return &DNSError{ + Err: err, + Name: name, + Server: server, + IsTemporary: true, + } + } + makeTimeout := func() error { + return &DNSError{ + Err: poll.ErrTimeout.Error(), + Name: name, + Server: server, + IsTimeout: true, + } + } + makeNxDomain := func() error { + return &DNSError{ + Err: errNoSuchHost.Error(), + Name: name, + Server: server, + } + } + + cases := []struct { + desc string + resolveWhich func(quest *dnsQuestion) resolveWhichEnum + wantStrictErr error + wantLaxErr error + wantIPs []string + }{ + { + desc: "No errors", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + return resolveOK + }, + wantIPs: []string{ip4, ip6}, + }, + { + desc: "searchX error fails in strict mode", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchX { + return resolveTimeout + } + return resolveOK + }, + wantStrictErr: makeTimeout(), + wantIPs: []string{ip4, ip6}, + }, + { + desc: "searchX IPv4-only timeout fails in strict mode", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchX && quest.Qtype == dnsTypeA { + return resolveTimeout + } + return resolveOK + }, + wantStrictErr: makeTimeout(), + wantIPs: []string{ip4, ip6}, + }, + { + desc: "searchX IPv6-only servfail fails in strict mode", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchX && quest.Qtype == dnsTypeAAAA { + return resolveServfail + } + return resolveOK + }, + wantStrictErr: makeTempError("server misbehaving"), + wantIPs: []string{ip4, ip6}, + }, + { + desc: "searchY error always fails", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchY { + return resolveTimeout + } + return resolveOK + }, + wantStrictErr: makeTimeout(), + wantLaxErr: makeNxDomain(), // This one reaches the "test." FQDN. + }, + { + desc: "searchY IPv4-only socket error fails in strict mode", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchY && quest.Qtype == dnsTypeA { + return resolveOpError + } + return resolveOK + }, + wantStrictErr: makeTempError("write: socket on fire"), + wantIPs: []string{ip6}, + }, + { + desc: "searchY IPv6-only timeout fails in strict mode", + resolveWhich: func(quest *dnsQuestion) resolveWhichEnum { + if quest.Name == searchY && quest.Qtype == dnsTypeAAAA { + return resolveTimeout + } + return resolveOK + }, + wantStrictErr: makeTimeout(), + wantIPs: []string{ip4}, + }, + } + + for i, tt := range cases { + d := &fakeDNSDialer{} + testHookDNSDialer = func() dnsDialer { return d } + + d.rh = func(s string, q *dnsMsg, deadline time.Time) (*dnsMsg, error) { + t.Log(s, q) + + switch tt.resolveWhich(&q.question[0]) { + case resolveOK: + // Handle below. + case resolveOpError: + return nil, &OpError{Op: "write", Err: fmt.Errorf("socket on fire")} + case resolveServfail: + return &dnsMsg{dnsMsgHdr: dnsMsgHdr{id: q.id, rcode: dnsRcodeServerFailure}}, nil + case resolveTimeout: + return nil, poll.ErrTimeout + default: + t.Fatal("Impossible resolveWhich") + } + + switch q.question[0].Name { + case searchX, name + ".": + // Return NXDOMAIN to utilize the search list. + return &dnsMsg{dnsMsgHdr: dnsMsgHdr{id: q.id, rcode: dnsRcodeNameError}}, nil + case searchY: + // Return records below. + default: + return nil, fmt.Errorf("Unexpected Name: %v", q.question[0].Name) + } + + r := &dnsMsg{ + dnsMsgHdr: dnsMsgHdr{ + id: q.id, + response: true, + }, + question: q.question, + } + switch q.question[0].Qtype { + case dnsTypeA: + r.answer = []dnsRR{ + &dnsRR_A{ + Hdr: dnsRR_Header{ + Name: q.question[0].Name, + Rrtype: dnsTypeA, + Class: dnsClassINET, + Rdlength: 4, + }, + A: TestAddr, + }, + } + case dnsTypeAAAA: + r.answer = []dnsRR{ + &dnsRR_AAAA{ + Hdr: dnsRR_Header{ + Name: q.question[0].Name, + Rrtype: dnsTypeAAAA, + Class: dnsClassINET, + Rdlength: 16, + }, + AAAA: TestAddr6, + }, + } + default: + return nil, fmt.Errorf("Unexpected Qtype: %v", q.question[0].Qtype) + } + return r, nil + } + + for _, strict := range []bool{true, false} { + r := Resolver{StrictErrors: strict} + ips, err := r.goLookupIP(context.Background(), name) + + var wantErr error + if strict { + wantErr = tt.wantStrictErr + } else { + wantErr = tt.wantLaxErr + } + if !reflect.DeepEqual(err, wantErr) { + t.Errorf("#%d (%s) strict=%v: got err %#v; want %#v", i, tt.desc, strict, err, wantErr) + } + + gotIPs := map[string]struct{}{} + for _, ip := range ips { + gotIPs[ip.String()] = struct{}{} + } + wantIPs := map[string]struct{}{} + if wantErr == nil { + for _, ip := range tt.wantIPs { + wantIPs[ip] = struct{}{} + } + } + if !reflect.DeepEqual(gotIPs, wantIPs) { + t.Errorf("#%d (%s) strict=%v: got ips %v; want %v", i, tt.desc, strict, gotIPs, wantIPs) + } + } + } +} + +// Issue 17448. With StrictErrors enabled, temporary errors should make +// LookupTXT stop walking the search list. +func TestStrictErrorsLookupTXT(t *testing.T) { + origTestHookDNSDialer := testHookDNSDialer + defer func() { testHookDNSDialer = origTestHookDNSDialer }() + + conf, err := newResolvConfTest() + if err != nil { + t.Fatal(err) + } + defer conf.teardown() + + confData := []string{ + "nameserver 192.0.2.53", + "search x.golang.org y.golang.org", + } + if err := conf.writeAndUpdate(confData); err != nil { + t.Fatal(err) + } + + const name = "test" + const server = "192.0.2.53:53" + const searchX = "test.x.golang.org." + const searchY = "test.y.golang.org." + const txt = "Hello World" + + d := &fakeDNSDialer{} + testHookDNSDialer = func() dnsDialer { return d } + + d.rh = func(s string, q *dnsMsg, deadline time.Time) (*dnsMsg, error) { + t.Log(s, q) + + switch q.question[0].Name { + case searchX: + return nil, poll.ErrTimeout + case searchY: + return mockTXTResponse(q), nil + default: + return nil, fmt.Errorf("Unexpected Name: %v", q.question[0].Name) + } + } + + for _, strict := range []bool{true, false} { + r := Resolver{StrictErrors: strict} + _, rrs, err := r.lookup(context.Background(), name, dnsTypeTXT) + var wantErr error + var wantRRs int + if strict { + wantErr = &DNSError{ + Err: poll.ErrTimeout.Error(), + Name: name, + Server: server, + IsTimeout: true, + } + } else { + wantRRs = 1 + } + if !reflect.DeepEqual(err, wantErr) { + t.Errorf("strict=%v: got err %#v; want %#v", strict, err, wantErr) + } + if len(rrs) != wantRRs { + t.Errorf("strict=%v: got %v; want %v", strict, len(rrs), wantRRs) + } + } +} diff --git a/src/net/lookup.go b/src/net/lookup.go index cc2013e432..463b374aff 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -97,6 +97,16 @@ type Resolver struct { // GODEBUG=netdns=go, but scoped to just this resolver. PreferGo bool + // StrictErrors controls the behavior of temporary errors + // (including timeout, socket errors, and SERVFAIL) when using + // Go's built-in resolver. For a query composed of multiple + // sub-queries (such as an A+AAAA address lookup, or walking the + // DNS search list), this option causes such errors to abort the + // whole query instead of returning a partial result. This is + // not enabled by default because it may affect compatibility + // with resolvers that process AAAA queries incorrectly. + StrictErrors bool + // TODO(bradfitz): optional interface impl override hook // TODO(bradfitz): Timeout time.Duration? } diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go index be2ced9c39..8d4b7bddf4 100644 --- a/src/net/lookup_unix.go +++ b/src/net/lookup_unix.go @@ -57,12 +57,12 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, // cgo not available (or netgo); fall back to Go's DNS resolver order = hostLookupFilesDNS } - return goLookupHostOrder(ctx, host, order) + return r.goLookupHostOrder(ctx, host, order) } func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { if r.PreferGo { - return goLookupIP(ctx, host) + return r.goLookupIP(ctx, host) } order := systemConf().hostLookupOrder(host) if order == hostLookupCgo { @@ -72,7 +72,7 @@ func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, e // cgo not available (or netgo); fall back to Go's DNS resolver order = hostLookupFilesDNS } - addrs, _, err = goLookupIPCNAMEOrder(ctx, host, order) + addrs, _, err = r.goLookupIPCNAMEOrder(ctx, host, order) return } @@ -98,17 +98,17 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) return cname, err } } - return goLookupCNAME(ctx, name) + return r.goLookupCNAME(ctx, name) } -func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { +func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { var target string if service == "" && proto == "" { target = name } else { target = "_" + service + "._" + proto + "." + name } - cname, rrs, err := lookup(ctx, target, dnsTypeSRV) + cname, rrs, err := r.lookup(ctx, target, dnsTypeSRV) if err != nil { return "", nil, err } @@ -121,8 +121,8 @@ func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (st return cname, srvs, nil } -func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { - _, rrs, err := lookup(ctx, name, dnsTypeMX) +func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { + _, rrs, err := r.lookup(ctx, name, dnsTypeMX) if err != nil { return nil, err } @@ -135,8 +135,8 @@ func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { return mxs, nil } -func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { - _, rrs, err := lookup(ctx, name, dnsTypeNS) +func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { + _, rrs, err := r.lookup(ctx, name, dnsTypeNS) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { } func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { - _, rrs, err := lookup(ctx, name, dnsTypeTXT) + _, rrs, err := r.lookup(ctx, name, dnsTypeTXT) if err != nil { return nil, err } @@ -165,5 +165,5 @@ func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error return ptrs, err } } - return goLookupPTR(ctx, addr) + return r.goLookupPTR(ctx, addr) } diff --git a/src/net/netgo_unix_test.go b/src/net/netgo_unix_test.go index 5f1eb19e12..47901b03cf 100644 --- a/src/net/netgo_unix_test.go +++ b/src/net/netgo_unix_test.go @@ -22,7 +22,7 @@ func TestGoLookupIP(t *testing.T) { if err != nil { t.Error(err) } - if _, err := goLookupIP(ctx, host); err != nil { + if _, err := DefaultResolver.goLookupIP(ctx, host); err != nil { t.Error(err) } }