]> Cypherpunks repositories - gostls13.git/commitdiff
net: set IsNotFound on windows and plan9 DNS queries
authorMateusz Poliwczak <mpoliwczak34@gmail.com>
Fri, 20 Oct 2023 08:35:15 +0000 (08:35 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 23 Oct 2023 09:03:09 +0000 (09:03 +0000)
Change-Id: I2a12acb3e4f31dd561d49f47a3b1ae3ac47ab894
GitHub-Last-Rev: 4733964f691c567ccad0279fb553442322543024
GitHub-Pull-Request: golang/go#63542
Reviewed-on: https://go-review.googlesource.com/c/go/+/534937
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Run-TryBot: Mateusz Poliwczak <mpoliwczak34@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
src/net/lookup_plan9.go
src/net/lookup_test.go
src/net/lookup_windows.go

index 9d2c4cda5bf53d73bb23745e90c82be16cadf20a..8cfc4f6bb3b02d3d99d073ed850be6b84483666f 100644 (file)
@@ -106,6 +106,22 @@ func queryDNS(ctx context.Context, addr string, typ string) (res []string, err e
        return query(ctx, netdir+"/dns", addr+" "+typ, 1024)
 }
 
+func handlePlan9DNSError(err error, name string) error {
+       if stringsHasSuffix(err.Error(), "dns: name does not exist") ||
+               stringsHasSuffix(err.Error(), "dns: resource does not exist; negrcode 0") ||
+               stringsHasSuffix(err.Error(), "dns: resource does not exist; negrcode") {
+               return &DNSError{
+                       Err:        errNoSuchHost.Error(),
+                       Name:       name,
+                       IsNotFound: true,
+               }
+       }
+       return &DNSError{
+               Err:  err.Error(),
+               Name: name,
+       }
+}
+
 // toLower returns a lower-case version of in. Restricting us to
 // ASCII is sufficient to handle the IP protocol names and allow
 // us to not depend on the strings and unicode packages.
@@ -153,12 +169,10 @@ func (*Resolver) lookupHost(ctx context.Context, host string) (addrs []string, e
        // host names in local network (e.g. from /lib/ndb/local)
        lines, err := queryCS(ctx, "net", host, "1")
        if err != nil {
-               dnsError := &DNSError{Err: err.Error(), Name: host}
                if stringsHasSuffix(err.Error(), "dns failure") {
-                       dnsError.Err = errNoSuchHost.Error()
-                       dnsError.IsNotFound = true
+                       return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
                }
-               return nil, dnsError
+               return nil, handlePlan9DNSError(err, host)
        }
 loop:
        for _, line := range lines {
@@ -252,10 +266,9 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (cname string,
        lines, err := queryDNS(ctx, name, "cname")
        if err != nil {
                if stringsHasSuffix(err.Error(), "dns failure") || stringsHasSuffix(err.Error(), "resource does not exist; negrcode 0") {
-                       cname = name + "."
-                       err = nil
+                       return absDomainName(name), nil
                }
-               return
+               return "", handlePlan9DNSError(err, cname)
        }
        if len(lines) > 0 {
                if f := getFields(lines[0]); len(f) >= 3 {
@@ -277,7 +290,7 @@ func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (
        }
        lines, err := queryDNS(ctx, target, "srv")
        if err != nil {
-               return
+               return "", nil, handlePlan9DNSError(err, name)
        }
        for _, line := range lines {
                f := getFields(line)
@@ -303,7 +316,7 @@ func (r *Resolver) lookupMX(ctx context.Context, name string) (mx []*MX, err err
        }
        lines, err := queryDNS(ctx, name, "mx")
        if err != nil {
-               return
+               return nil, handlePlan9DNSError(err, name)
        }
        for _, line := range lines {
                f := getFields(line)
@@ -324,7 +337,7 @@ func (r *Resolver) lookupNS(ctx context.Context, name string) (ns []*NS, err err
        }
        lines, err := queryDNS(ctx, name, "ns")
        if err != nil {
-               return
+               return nil, handlePlan9DNSError(err, name)
        }
        for _, line := range lines {
                f := getFields(line)
@@ -342,7 +355,7 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) (txt []string, er
        }
        lines, err := queryDNS(ctx, name, "txt")
        if err != nil {
-               return
+               return nil, handlePlan9DNSError(err, name)
        }
        for _, line := range lines {
                if i := bytealg.IndexByteString(line, '\t'); i >= 0 {
@@ -362,7 +375,7 @@ func (r *Resolver) lookupAddr(ctx context.Context, addr string) (name []string,
        }
        lines, err := queryDNS(ctx, arpa, "ptr")
        if err != nil {
-               return
+               return nil, handlePlan9DNSError(err, addr)
        }
        for _, line := range lines {
                f := getFields(line)
index 1e222763bd0d0df71bcc61863b410c3a2daeb129..57ac9a933a0d3492e79276298ac5cc1ae3b9a383 100644 (file)
@@ -1524,3 +1524,125 @@ func allResolvers(t *testing.T, f func(t *testing.T)) {
                }
        })
 }
+
+func TestLookupNoSuchHost(t *testing.T) {
+       mustHaveExternalNetwork(t)
+
+       const testNXDOMAIN = "invalid.invalid."
+       const testNODATA = "_ldap._tcp.google.com."
+
+       tests := []struct {
+               name  string
+               query func() error
+       }{
+               {
+                       name: "LookupCNAME NXDOMAIN",
+                       query: func() error {
+                               _, err := LookupCNAME(testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupHost NXDOMAIN",
+                       query: func() error {
+                               _, err := LookupHost(testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupHost NODATA",
+                       query: func() error {
+                               _, err := LookupHost(testNODATA)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupMX NXDOMAIN",
+                       query: func() error {
+                               _, err := LookupMX(testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupMX NODATA",
+                       query: func() error {
+                               _, err := LookupMX(testNODATA)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupNS NXDOMAIN",
+                       query: func() error {
+                               _, err := LookupNS(testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupNS NODATA",
+                       query: func() error {
+                               _, err := LookupNS(testNODATA)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupSRV NXDOMAIN",
+                       query: func() error {
+                               _, _, err := LookupSRV("unknown", "tcp", testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupTXT NXDOMAIN",
+                       query: func() error {
+                               _, err := LookupTXT(testNXDOMAIN)
+                               return err
+                       },
+               },
+               {
+                       name: "LookupTXT NODATA",
+                       query: func() error {
+                               _, err := LookupTXT(testNODATA)
+                               return err
+                       },
+               },
+       }
+
+       for _, v := range tests {
+               t.Run(v.name, func(t *testing.T) {
+                       allResolvers(t, func(t *testing.T) {
+                               attempts := 0
+                               for {
+                                       err := v.query()
+                                       if err == nil {
+                                               t.Errorf("unexpected success")
+                                               return
+                                       }
+                                       if dnsErr, ok := err.(*DNSError); ok {
+                                               succeeded := true
+                                               if !dnsErr.IsNotFound {
+                                                       succeeded = false
+                                                       t.Log("IsNotFound is set to false")
+                                               }
+                                               if dnsErr.Err != errNoSuchHost.Error() {
+                                                       succeeded = false
+                                                       t.Logf("error message is not equal to: %v", errNoSuchHost.Error())
+                                               }
+                                               if succeeded {
+                                                       return
+                                               }
+                                       }
+                                       testenv.SkipFlakyNet(t)
+                                       if attempts < len(backoffDuration) {
+                                               dur := backoffDuration[attempts]
+                                               t.Logf("backoff %v after failure %v\n", dur, err)
+                                               time.Sleep(dur)
+                                               attempts++
+                                               continue
+                                       }
+                                       t.Errorf("unexpected error: %v", err)
+                                       return
+                               }
+                       })
+               })
+       }
+}
index b6ef6da716edecadb9e1c7dffd3d9e1a328c7dda..3048f3269b003e05c34cb049411f3db72ff746c8 100644 (file)
@@ -20,6 +20,9 @@ import (
 const cgoAvailable = true
 
 const (
+       _DNS_ERROR_RCODE_NAME_ERROR = syscall.Errno(9003)
+       _DNS_INFO_NO_RECORDS        = syscall.Errno(9501)
+
        _WSAHOST_NOT_FOUND = syscall.Errno(11001)
        _WSATRY_AGAIN      = syscall.Errno(11002)
        _WSATYPE_NOT_FOUND = syscall.Errno(10109)
@@ -27,7 +30,7 @@ const (
 
 func winError(call string, err error) error {
        switch err {
-       case _WSAHOST_NOT_FOUND:
+       case _WSAHOST_NOT_FOUND, _DNS_ERROR_RCODE_NAME_ERROR, _DNS_INFO_NO_RECORDS:
                return errNoSuchHost
        }
        return os.NewSyscallError(call, err)
@@ -271,7 +274,8 @@ func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error)
                return absDomainName(name), nil
        }
        if e != nil {
-               return "", &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
+               err := winError("dnsquery", e)
+               return "", &DNSError{Err: err.Error(), Name: name, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)
 
@@ -296,7 +300,8 @@ func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (
        var rec *syscall.DNSRecord
        e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &rec, nil)
        if e != nil {
-               return "", nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: target}
+               err := winError("dnsquery", e)
+               return "", nil, &DNSError{Err: err.Error(), Name: name, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)
 
@@ -319,7 +324,8 @@ func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
        var rec *syscall.DNSRecord
        e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &rec, nil)
        if e != nil {
-               return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
+               err := winError("dnsquery", e)
+               return nil, &DNSError{Err: err.Error(), Name: name, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)
 
@@ -342,7 +348,8 @@ func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
        var rec *syscall.DNSRecord
        e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &rec, nil)
        if e != nil {
-               return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
+               err := winError("dnsquery", e)
+               return nil, &DNSError{Err: err.Error(), Name: name, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)
 
@@ -364,7 +371,8 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
        var rec *syscall.DNSRecord
        e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &rec, nil)
        if e != nil {
-               return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
+               err := winError("dnsquery", e)
+               return nil, &DNSError{Err: err.Error(), Name: name, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)
 
@@ -395,7 +403,8 @@ func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error
        var rec *syscall.DNSRecord
        e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &rec, nil)
        if e != nil {
-               return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: addr}
+               err := winError("dnsquery", e)
+               return nil, &DNSError{Err: err.Error(), Name: addr, IsNotFound: err == errNoSuchHost}
        }
        defer syscall.DnsRecordListFree(rec, 1)