1
0
mirror of https://github.com/golang/go synced 2024-11-23 05:00:07 -07:00

net: set IsNotFound on windows and plan9 DNS queries

Change-Id: I2a12acb3e4f31dd561d49f47a3b1ae3ac47ab894
GitHub-Last-Rev: 4733964f69
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>
This commit is contained in:
Mateusz Poliwczak 2023-10-20 08:35:15 +00:00 committed by Gopher Robot
parent 3839447ac3
commit 95974b379f
3 changed files with 163 additions and 19 deletions

View 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)

View 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
}
})
})
}
}

View 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)