diff --git a/src/net/conf_test.go b/src/net/conf_test.go index 9228b34a39..3736709295 100644 --- a/src/net/conf_test.go +++ b/src/net/conf_test.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. -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +//go:build unix package net diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 88f8d34e1a..20da8f1970 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -551,9 +551,13 @@ func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hos if order == hostLookupFilesDNS || order == hostLookupFiles { // Use entries from /etc/hosts if they match. addrs, _ = lookupStaticHost(name) - if len(addrs) > 0 || order == hostLookupFiles { + if len(addrs) > 0 { return } + + if order == hostLookupFiles { + return nil, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true} + } } ips, _, err := r.goLookupIPCNAMEOrder(ctx, "ip", name, order, conf) if err != nil { diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 2a15845ea1..3ba19eb813 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -12,7 +12,9 @@ import ( "fmt" "os" "path" + "path/filepath" "reflect" + "runtime" "strings" "sync" "sync/atomic" @@ -2503,3 +2505,92 @@ func TestDNSConfigNoReload(t *testing.T) { t.Fatal(err) } } + +func TestLookupOrderFilesNoSuchHost(t *testing.T) { + defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath) + if runtime.GOOS != "openbsd" { + defer setSystemNSS(getSystemNSS(), 0) + setSystemNSS(nssStr(t, "hosts: files"), time.Hour) + } + + conf, err := newResolvConfTest() + if err != nil { + t.Fatal(err) + } + defer conf.teardown() + + resolvConf := dnsConfig{servers: defaultNS} + if runtime.GOOS == "openbsd" { + // Set error to ErrNotExist, so that the hostLookupOrder + // returns hostLookupFiles for openbsd. + resolvConf.err = os.ErrNotExist + } + + if !conf.forceUpdateConf(&resolvConf, time.Now().Add(time.Hour)) { + t.Fatal("failed to update resolv config") + } + + tmpFile := filepath.Join(t.TempDir(), "hosts") + if err := os.WriteFile(tmpFile, []byte{}, 0660); err != nil { + t.Fatal(err) + } + testHookHostsPath = tmpFile + + const testName = "test.invalid" + + order, _ := systemConf().hostLookupOrder(DefaultResolver, testName) + if order != hostLookupFiles { + // skip test for systems which do not return hostLookupFiles + t.Skipf("hostLookupOrder did not return hostLookupFiles") + } + + var lookupTests = []struct { + name string + lookup func(name string) error + }{ + { + name: "Host", + lookup: func(name string) error { + _, err = DefaultResolver.LookupHost(context.Background(), name) + return err + }, + }, + { + name: "IP", + lookup: func(name string) error { + _, err = DefaultResolver.LookupIP(context.Background(), "ip", name) + return err + }, + }, + { + name: "IPAddr", + lookup: func(name string) error { + _, err = DefaultResolver.LookupIPAddr(context.Background(), name) + return err + }, + }, + { + name: "NetIP", + lookup: func(name string) error { + _, err = DefaultResolver.LookupNetIP(context.Background(), "ip", name) + return err + }, + }, + } + + for _, v := range lookupTests { + err := v.lookup(testName) + + if err == nil { + t.Errorf("Lookup%v: unexpected success", v.name) + continue + } + + expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: testName, IsNotFound: true} + var dnsErr *DNSError + errors.As(err, &dnsErr) + if dnsErr == nil || *dnsErr != expectedErr { + t.Errorf("Lookup%v: unexpected error: %v", v.name, err) + } + } +}