From fa90f9b909286dc815fde1f83f77b80bd686127d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 19 Oct 2016 16:48:21 -0400 Subject: [PATCH] net: there are no invalid domain names anymore The Go resolver reports invalid domain name for '!!!.local', but that is allowed by multicast DNS. In general we can't predict what future relaxations might come along, and libc resolvers do not distinguish 'no such host' from 'invalid name', so stop making that distinction here too. Always use 'no such host'. Fixes #12421. Change-Id: I8f22604767ec9e270434e483da52b337833bad71 Reviewed-on: https://go-review.googlesource.com/31468 Run-TryBot: Russ Cox TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/net/dnsclient_unix.go | 10 ++++++++-- src/net/lookup_test.go | 17 +++++++++++++++++ src/net/lookup_windows.go | 28 +++++++++++++++++++--------- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 130e4c958a0..dd39a78f45b 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -316,7 +316,12 @@ func (conf *resolverConfig) releaseSema() { func lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs []dnsRR, err error) { if !isDomainName(name) { - return "", nil, &DNSError{Err: "invalid domain name", Name: name} + // We used to use "invalid domain name" as the error, + // but that is a detail of the specific lookup mechanism. + // Other lookups might allow broader name syntax + // (for example Multicast DNS allows UTF-8; see RFC 6762). + // For consistency with libc resolvers, report no such host. + return "", nil, &DNSError{Err: errNoSuchHost.Error(), Name: name} } resolvConf.tryUpdate("/etc/resolv.conf") resolvConf.mu.RLock() @@ -469,7 +474,8 @@ func goLookupIPOrder(ctx context.Context, name string, order hostLookupOrder) (a } } if !isDomainName(name) { - return nil, &DNSError{Err: "invalid domain name", Name: name} + // See comment in func lookup above about use of errNoSuchHost. + return nil, &DNSError{Err: errNoSuchHost.Error(), Name: name} } resolvConf.tryUpdate("/etc/resolv.conf") resolvConf.mu.RLock() diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index acf7ffdf790..c59ecad2f0c 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -717,3 +717,20 @@ func TestLookupProtocol_Minimal(t *testing.T) { } } + +func TestLookupNonLDH(t *testing.T) { + if runtime.GOOS == "nacl" { + t.Skip("skip on nacl") + } + // "LDH" stands for letters, digits, and hyphens and is the usual + // description of standard DNS names. + // This test is checking that other kinds of names are reported + // as not found, not reported as invalid names. + addrs, err := LookupHost("!!!.###.bogus..domain.") + if err == nil { + t.Fatalf("lookup succeeded: %v", addrs) + } + if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) { + t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost) + } +} diff --git a/src/net/lookup_windows.go b/src/net/lookup_windows.go index 4bf748e7260..5808293058a 100644 --- a/src/net/lookup_windows.go +++ b/src/net/lookup_windows.go @@ -12,10 +12,20 @@ import ( "unsafe" ) +const _WSAHOST_NOT_FOUND = syscall.Errno(11001) + +func winError(call string, err error) error { + switch err { + case _WSAHOST_NOT_FOUND: + return errNoSuchHost + } + return os.NewSyscallError(call, err) +} + func getprotobyname(name string) (proto int, err error) { p, err := syscall.GetProtoByName(name) if err != nil { - return 0, os.NewSyscallError("getprotobyname", err) + return 0, winError("getprotobyname", err) } return int(p.Proto), nil } @@ -85,7 +95,7 @@ func (r *Resolver) lookupIP(ctx context.Context, name string) ([]IPAddr, error) var result *syscall.AddrinfoW e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &result) if e != nil { - ch <- ret{err: &DNSError{Err: os.NewSyscallError("getaddrinfow", e).Error(), Name: name}} + ch <- ret{err: &DNSError{Err: winError("getaddrinfow", e).Error(), Name: name}} } defer syscall.FreeAddrInfoW(result) addrs := make([]IPAddr, 0, 5) @@ -151,7 +161,7 @@ func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int if port, err := lookupPortMap(network, service); err == nil { return port, nil } - return 0, &DNSError{Err: os.NewSyscallError("getaddrinfow", e).Error(), Name: network + "/" + service} + return 0, &DNSError{Err: winError("getaddrinfow", e).Error(), Name: network + "/" + service} } defer syscall.FreeAddrInfoW(result) if result == nil { @@ -181,7 +191,7 @@ func (*Resolver) lookupCNAME(ctx context.Context, name string) (string, error) { return absDomainName([]byte(name)), nil } if e != nil { - return "", &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name} + return "", &DNSError{Err: winError("dnsquery", e).Error(), Name: name} } defer syscall.DnsRecordListFree(r, 1) @@ -203,7 +213,7 @@ func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (st var r *syscall.DNSRecord e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil) if e != nil { - return "", nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: target} + return "", nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: target} } defer syscall.DnsRecordListFree(r, 1) @@ -223,7 +233,7 @@ func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) { var r *syscall.DNSRecord e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil) if e != nil { - return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name} + return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name} } defer syscall.DnsRecordListFree(r, 1) @@ -243,7 +253,7 @@ func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) { var r *syscall.DNSRecord e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil) if e != nil { - return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name} + return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name} } defer syscall.DnsRecordListFree(r, 1) @@ -262,7 +272,7 @@ func (*Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) { var r *syscall.DNSRecord e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil) if e != nil { - return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name} + return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name} } defer syscall.DnsRecordListFree(r, 1) @@ -288,7 +298,7 @@ func (*Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) var r *syscall.DNSRecord e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil) if e != nil { - return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: addr} + return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: addr} } defer syscall.DnsRecordListFree(r, 1)