1
0
mirror of https://github.com/golang/go synced 2024-09-29 03:24:29 -06:00

net: rewrite and simplify resolver configuration

The resulting code behaves mostly the same. There are some minor
differences in error cases when the cgo resolver is not available:
instead of just falling back we keep trying to work out the right
nsswitch.conf order.

Change-Id: I17fadc940528fa2397043ac8f8ed7da3bd7a95c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/487196
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Mateusz Poliwczak <mpoliwczak34@gmail.com>
This commit is contained in:
Ian Lance Taylor 2023-04-20 16:55:13 -07:00 committed by Gopher Robot
parent 635839a17a
commit afe2d22219
19 changed files with 385 additions and 191 deletions

View File

@ -7,9 +7,12 @@
[short] skip # -compiled can be slow (because it compiles things)
[!cgo] skip
[GOOS:darwin] skip # net package does not import "C" on Darwin
[GOOS:windows] skip # net package does not import "C" on Windows
[GOOS:plan9] skip # net package does not import "C" on Plan 9
env CGO_ENABLED=1
env GOFLAGS=-tags=netcgo # Force net to use cgo even on Windows.
env GOFLAGS=-tags=netcgo # Force net to use cgo
# "runtime/cgo [runtime.test]" appears in the test dependencies of "runtime",

View File

@ -2,17 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (!cgo && !darwin) || netgo
// This file holds stub versions of the cgo functions called on Unix systems.
// We build this file if using the netgo build tag, or if cgo is not
// enabled and we are using a Unix system other than Darwin.
// Darwin is exempted because it always provides the cgo routines,
// in cgo_unix_syscall.go.
//go:build netgo || (!cgo && unix && !darwin)
package net
import "context"
type addrinfoErrno int
func (eai addrinfoErrno) Error() string { return "<nil>" }
func (eai addrinfoErrno) Temporary() bool { return false }
func (eai addrinfoErrno) Timeout() bool { return false }
// cgoAvailable set to false to indicate that the cgo resolver
// is not available on this system.
const cgoAvailable = false
func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, completed bool) {
return nil, nil, false

View File

@ -21,6 +21,10 @@ import (
"golang.org/x/net/dns/dnsmessage"
)
// cgoAvailable set to true to indicate that the cgo resolver
// is available on this system.
const cgoAvailable = true
// An addrinfoErrno represents a getaddrinfo, getnameinfo-specific
// error number. It's a signed number and a zero value is a non-error
// by convention.
@ -30,6 +34,9 @@ func (eai addrinfoErrno) Error() string { return _C_gai_strerror(_C_int(eai))
func (eai addrinfoErrno) Temporary() bool { return eai == _C_EAI_AGAIN }
func (eai addrinfoErrno) Timeout() bool { return false }
// isAddrinfoErrno is just for testing purposes.
func (eai addrinfoErrno) isAddrinfoErrno() {}
// doBlockingWithCtx executes a blocking function in a separate goroutine when the provided
// context is cancellable. It is intended for use with calls that don't support context
// cancellation (cgo, syscalls). blocking func may still be running after this function finishes.

View File

@ -1,13 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build cgo && !netgo
package net
type addrinfoErrno int
func (eai addrinfoErrno) Error() string { return "<nil>" }
func (eai addrinfoErrno) Temporary() bool { return false }
func (eai addrinfoErrno) Timeout() bool { return false }

View File

@ -7,29 +7,70 @@
package net
import (
"errors"
"internal/bytealg"
"internal/godebug"
"io/fs"
"os"
"runtime"
"sync"
"syscall"
)
// conf represents a system's network configuration.
// The net package's name resolution is rather complicated.
// There are two main approaches, go and cgo.
// The cgo resolver uses C functions like getaddrinfo.
// The go resolver reads system files directly and
// sends DNS packets directly to servers.
//
// The netgo build tag prefers the go resolver.
// The netcgo build tag prefers the cgo resolver.
//
// The netgo build tag also prohibits the use of the cgo tool.
// However, on Darwin, Plan 9, and Windows the cgo resolver is still available.
// On those systems the cgo resolver does not require the cgo tool.
// (The term "cgo resolver" was locked in by GODEBUG settings
// at a time when the cgo resolver did require the cgo tool.)
//
// Adding netdns=go to GODEBUG will prefer the go resolver.
// Adding netdns=cgo to GODEBUG will prefer the cgo resolver.
//
// The Resolver struct has a PreferGo field that user code
// may set to prefer the go resolver. It is documented as being
// equivalent to adding netdns=go to GODEBUG.
//
// When deciding which resolver to use, we first check the PreferGo field.
// If that is not set, we check the GODEBUG setting.
// If that is not set, we check the netgo or netcgo build tag.
// If none of those are set, we normally prefer the go resolver by default.
// However, if the cgo resolver is available,
// there is a complex set of conditions for which we prefer the cgo resolver.
//
// Other files define the netGoBuildTag, netCgoBuildTag, and cgoAvailable
// constants.
// conf is used to determine name resolution configuration.
type conf struct {
// forceCgoLookupHost forces CGO to always be used, if available.
forceCgoLookupHost bool
netGo bool // prefer go approach, based on build tag and GODEBUG
netCgo bool // prefer cgo approach, based on build tag and GODEBUG
netGo bool // go DNS resolution forced
netCgo bool // non-go DNS resolution forced (cgo, or win32)
dnsDebugLevel int // from GODEBUG
// machine has an /etc/mdns.allow file
hasMDNSAllow bool
preferCgo bool // if no explicit preference, use cgo
goos string // the runtime.GOOS, to ease testing
dnsDebugLevel int
goos string // copy of runtime.GOOS, used for testing
mdnsTest mdnsTest // assume /etc/mdns.allow exists, for testing
}
// mdnsTest is for testing only.
type mdnsTest int
const (
mdnsFromSystem mdnsTest = iota
mdnsAssumeExists
mdnsAssumeDoesNotExist
)
var (
confOnce sync.Once // guards init of confVal via initConfVal
confVal = &conf{goos: runtime.GOOS}
@ -41,22 +82,13 @@ func systemConf() *conf {
return confVal
}
// initConfVal initializes confVal based on the environment
// that will not change during program execution.
func initConfVal() {
dnsMode, debugLevel := goDebugNetDNS()
confVal.netGo = netGoBuildTag || dnsMode == "go"
confVal.netCgo = netCgoBuildTag || dnsMode == "cgo"
confVal.dnsDebugLevel = debugLevel
confVal.netGo = netGo || dnsMode == "go"
confVal.netCgo = netCgo || dnsMode == "cgo"
if !confVal.netGo && !confVal.netCgo && (runtime.GOOS == "windows" || runtime.GOOS == "plan9") {
// Neither of these platforms actually use cgo.
//
// The meaning of "cgo" mode in the net package is
// really "the native OS way", which for libc meant
// cgo on the original platforms that motivated
// PreferGo support before Windows and Plan9 got support,
// at which time the GODEBUG=netdns=go and GODEBUG=netdns=cgo
// names were already kinda locked in.
confVal.netCgo = true
}
if confVal.dnsDebugLevel > 0 {
defer func() {
@ -65,12 +97,14 @@ func initConfVal() {
}
switch {
case confVal.netGo:
if netGo {
if netGoBuildTag {
println("go package net: built with netgo build tag; using Go's DNS resolver")
} else {
println("go package net: GODEBUG setting forcing use of Go's resolver")
}
case confVal.forceCgoLookupHost:
case !cgoAvailable:
println("go package net: cgo resolver not supported; using Go's DNS resolver")
case confVal.netCgo || confVal.preferCgo:
println("go package net: using cgo DNS resolver")
default:
println("go package net: dynamic selection of DNS resolver")
@ -78,60 +112,100 @@ func initConfVal() {
}()
}
// Darwin pops up annoying dialog boxes if programs try to do
// their own DNS requests. So always use cgo instead, which
// avoids that.
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
confVal.forceCgoLookupHost = true
// The remainder of this function sets preferCgo based on
// conditions that will not change during program execution.
// By default, prefer the go resolver.
confVal.preferCgo = false
// If the cgo resolver is not available, we can't prefer it.
if !cgoAvailable {
return
}
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
// Some operating systems always prefer the cgo resolver.
if goosPrefersCgo(runtime.GOOS) {
confVal.preferCgo = true
return
}
// The remaining checks are specific to Unix systems.
switch runtime.GOOS {
case "plan9", "windows", "js", "wasip1":
return
}
// If any environment-specified resolver options are specified,
// force cgo. Note that LOCALDOMAIN can change behavior merely
// by being specified with the empty string.
// prefer the cgo resolver.
// Note that LOCALDOMAIN can change behavior merely by being
// specified with the empty string.
_, localDomainDefined := syscall.Getenv("LOCALDOMAIN")
if os.Getenv("RES_OPTIONS") != "" ||
os.Getenv("HOSTALIASES") != "" ||
confVal.netCgo ||
localDomainDefined {
confVal.forceCgoLookupHost = true
if localDomainDefined || os.Getenv("RES_OPTIONS") != "" || os.Getenv("HOSTALIASES") != "" {
confVal.preferCgo = true
return
}
// OpenBSD apparently lets you override the location of resolv.conf
// with ASR_CONFIG. If we notice that, defer to libc.
if runtime.GOOS == "openbsd" && os.Getenv("ASR_CONFIG") != "" {
confVal.forceCgoLookupHost = true
confVal.preferCgo = true
return
}
if _, err := os.Stat("/etc/mdns.allow"); err == nil {
confVal.hasMDNSAllow = true
}
}
// canUseCgo reports whether calling cgo functions is allowed
// for non-hostname lookups.
func (c *conf) canUseCgo() bool {
ret, _ := c.hostLookupOrder(nil, "")
return ret == hostLookupCgo
// goosPreferCgo reports whether the GOOS value passed in prefers
// the cgo resolver.
func goosPrefersCgo(goos string) bool {
switch goos {
// Historically on Windows and Plan 9 we prefer the
// cgo resolver (which doesn't use the cgo tool) rather than
// the go resolver. This is because originally these
// systems did not support the go resolver.
// Keep it this way for better compatibility.
// Perhaps we can revisit this some day.
case "windows", "plan9":
return true
// Darwin pops up annoying dialog boxes if programs try to
// do their own DNS requests, so prefer cgo.
case "darwin", "ios":
return true
// DNS requests don't work on Android, so prefer the cgo resolver.
// Issue #10714.
case "android":
return true
default:
return false
}
}
// mustUseGoResolver reports whether a DNS lookup of any sort is
// required to use the go resolver. The provided Resolver is optional.
// This will report true if the cgo resolver is not available.
func (c *conf) mustUseGoResolver(r *Resolver) bool {
return c.netGo || r.preferGo() || !cgoAvailable
}
// hostLookupOrder determines which strategy to use to resolve hostname.
// The provided Resolver is optional. nil means to not consider its options.
// It also returns dnsConfig when it was used to determine the lookup order.
func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, dnsConfig *dnsConfig) {
func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, dnsConf *dnsConfig) {
if c.dnsDebugLevel > 1 {
defer func() {
print("go package net: hostLookupOrder(", hostname, ") = ", ret.String(), "\n")
}()
}
fallbackOrder := hostLookupCgo
if c.netGo || r.preferGo() {
// fallbackOrder is the order we return if we can't figure it out.
var fallbackOrder hostLookupOrder
var canUseCgo bool
if c.mustUseGoResolver(r) {
// Go resolver was explicitly requested
// or cgo resolver is not available.
// Figure out the order below.
switch c.goos {
case "windows":
// TODO(bradfitz): implement files-based
@ -142,123 +216,161 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
default:
fallbackOrder = hostLookupFilesDNS
}
}
if c.forceCgoLookupHost || c.goos == "android" || c.goos == "windows" || c.goos == "plan9" {
return fallbackOrder, nil
}
if bytealg.IndexByteString(hostname, '\\') != -1 || bytealg.IndexByteString(hostname, '%') != -1 {
// Don't deal with special form hostnames with backslashes
// or '%'.
return fallbackOrder, nil
canUseCgo = false
} else if c.netCgo {
// Cgo resolver was explicitly requested.
return hostLookupCgo, nil
} else if c.preferCgo {
// Given a choice, we prefer the cgo resolver.
return hostLookupCgo, nil
} else {
// Neither resolver was explicitly requested
// and we have no preference.
// For testing purposes only, recheck the GOOS.
// This lets TestConfHostLookupOrder test different
// GOOS values.
if c.goos != runtime.GOOS && goosPrefersCgo(c.goos) {
return hostLookupCgo, nil
}
if bytealg.IndexByteString(hostname, '\\') != -1 || bytealg.IndexByteString(hostname, '%') != -1 {
// Don't deal with special form hostnames
// with backslashes or '%'.
return hostLookupCgo, nil
}
// If something is unrecognized, use cgo.
fallbackOrder = hostLookupCgo
canUseCgo = true
}
conf := getSystemDNSConfig()
if conf.err != nil && !os.IsNotExist(conf.err) && !os.IsPermission(conf.err) {
// If we can't read the resolv.conf file, assume it
// had something important in it and defer to cgo.
// libc's resolver might then fail too, but at least
// it wasn't our fault.
return fallbackOrder, conf
// Try to figure out the order to use for searches.
// If we don't recognize something, use fallbackOrder.
// That will use cgo unless the Go resolver was explicitly requested.
// If we do figure out the order, return something other
// than fallbackOrder to use the Go resolver with that order.
dnsConf = getSystemDNSConfig()
if canUseCgo && dnsConf.err != nil && !errors.Is(dnsConf.err, fs.ErrNotExist) && !errors.Is(dnsConf.err, fs.ErrPermission) {
// We can't read the resolv.conf file, so use cgo if we can.
return hostLookupCgo, dnsConf
}
if conf.unknownOpt {
return fallbackOrder, conf
if canUseCgo && dnsConf.unknownOpt {
// We didn't recognize something in resolv.conf,
// so use cgo if we can.
return hostLookupCgo, dnsConf
}
// OpenBSD is unique and doesn't use nsswitch.conf.
// It also doesn't support mDNS.
if c.goos == "openbsd" {
// OpenBSD's resolv.conf manpage says that a non-existent
// resolv.conf means "lookup" defaults to only "files",
// without DNS lookups.
if os.IsNotExist(conf.err) {
return hostLookupFiles, conf
// OpenBSD's resolv.conf manpage says that a
// non-existent resolv.conf means "lookup" defaults
// to only "files", without DNS lookups.
if errors.Is(dnsConf.err, fs.ErrNotExist) {
return hostLookupFiles, dnsConf
}
lookup := conf.lookup
lookup := dnsConf.lookup
if len(lookup) == 0 {
// https://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/resolv.conf.5
// "If the lookup keyword is not used in the
// system's resolv.conf file then the assumed
// order is 'bind file'"
return hostLookupDNSFiles, conf
return hostLookupDNSFiles, dnsConf
}
if len(lookup) < 1 || len(lookup) > 2 {
return fallbackOrder, conf
// We don't recognize this format.
return fallbackOrder, dnsConf
}
switch lookup[0] {
case "bind":
if len(lookup) == 2 {
if lookup[1] == "file" {
return hostLookupDNSFiles, conf
return hostLookupDNSFiles, dnsConf
}
return fallbackOrder, conf
// Unrecognized.
return fallbackOrder, dnsConf
}
return hostLookupDNS, conf
return hostLookupDNS, dnsConf
case "file":
if len(lookup) == 2 {
if lookup[1] == "bind" {
return hostLookupFilesDNS, conf
return hostLookupFilesDNS, dnsConf
}
return fallbackOrder, conf
// Unrecognized.
return fallbackOrder, dnsConf
}
return hostLookupFiles, conf
return hostLookupFiles, dnsConf
default:
return fallbackOrder, conf
// Unrecognized.
return fallbackOrder, dnsConf
}
// We always return before this point.
// The code below is for non-OpenBSD.
}
// Canonicalize the hostname by removing any trailing dot.
if stringsHasSuffix(hostname, ".") {
hostname = hostname[:len(hostname)-1]
}
if stringsHasSuffixFold(hostname, ".local") {
if canUseCgo && stringsHasSuffixFold(hostname, ".local") {
// Per RFC 6762, the ".local" TLD is special. And
// because Go's native resolver doesn't do mDNS or
// similar local resolution mechanisms, assume that
// libc might (via Avahi, etc) and use cgo.
return fallbackOrder, conf
return hostLookupCgo, dnsConf
}
nss := getSystemNSS()
srcs := nss.sources["hosts"]
// If /etc/nsswitch.conf doesn't exist or doesn't specify any
// sources for "hosts", assume Go's DNS will work fine.
if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
if c.goos == "solaris" {
// illumos defaults to "nis [NOTFOUND=return] files"
return fallbackOrder, conf
if errors.Is(nss.err, fs.ErrNotExist) || (nss.err == nil && len(srcs) == 0) {
if canUseCgo && c.goos == "solaris" {
// illumos defaults to
// "nis [NOTFOUND=return] files",
// which the go resolver doesn't support.
return hostLookupCgo, dnsConf
}
return hostLookupFilesDNS, conf
return hostLookupFilesDNS, dnsConf
}
if nss.err != nil {
// We failed to parse or open nsswitch.conf, so
// conservatively assume we should use cgo if it's
// available.
return fallbackOrder, conf
// we have nothing to base an order on.
return fallbackOrder, dnsConf
}
var mdnsSource, filesSource, dnsSource bool
var mdnsSource, filesSource, dnsSource, unknownSource bool
var first string
for _, src := range srcs {
if src.source == "myhostname" {
if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
return fallbackOrder, conf
}
hn, err := getHostname()
if err != nil || stringsEqualFold(hostname, hn) {
return fallbackOrder, conf
// Let the cgo resolver handle myhostname
// if we are looking up the local hostname.
if canUseCgo {
if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
return hostLookupCgo, dnsConf
}
hn, err := getHostname()
if err != nil || stringsEqualFold(hostname, hn) {
return hostLookupCgo, dnsConf
}
}
continue
}
if src.source == "files" || src.source == "dns" {
if !src.standardCriteria() {
return fallbackOrder, conf // non-standard; let libc deal with it.
if canUseCgo && !src.standardCriteria() {
// non-standard; let libc deal with it.
return hostLookupCgo, dnsConf
}
if src.source == "files" {
filesSource = true
} else if src.source == "dns" {
} else {
dnsSource = true
}
if first == "" {
@ -274,33 +386,62 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
continue
}
// Some source we don't know how to deal with.
return fallbackOrder, conf
if canUseCgo {
return hostLookupCgo, dnsConf
}
unknownSource = true
if first == "" {
first = src.source
}
}
// We don't parse mdns.allow files. They're rare. If one
// exists, it might list other TLDs (besides .local) or even
// '*', so just let libc deal with it.
if mdnsSource && c.hasMDNSAllow {
return fallbackOrder, conf
if canUseCgo && mdnsSource {
var haveMDNSAllow bool
switch c.mdnsTest {
case mdnsFromSystem:
_, err := os.Stat("/etc/mdns.allow")
if err != nil && !errors.Is(err, fs.ErrNotExist) {
// Let libc figure out what is going on.
return hostLookupCgo, dnsConf
}
haveMDNSAllow = err == nil
case mdnsAssumeExists:
haveMDNSAllow = true
case mdnsAssumeDoesNotExist:
haveMDNSAllow = false
}
if haveMDNSAllow {
return hostLookupCgo, dnsConf
}
}
// Cases where Go can handle it without cgo and C thread
// overhead.
// If we saw a source we don't recognize, which can only
// happen if we can't use the cgo resolver, treat it as DNS.
if unknownSource {
dnsSource = true
}
// Cases where Go can handle it without cgo and C thread overhead,
// or where the Go resolver has been forced.
switch {
case filesSource && dnsSource:
if first == "files" {
return hostLookupFilesDNS, conf
return hostLookupFilesDNS, dnsConf
} else {
return hostLookupDNSFiles, conf
return hostLookupDNSFiles, dnsConf
}
case filesSource:
return hostLookupFiles, conf
return hostLookupFiles, dnsConf
case dnsSource:
return hostLookupDNS, conf
return hostLookupDNS, dnsConf
}
// Something weird. Let libc deal with it.
return fallbackOrder, conf
// Something weird. Fallback to the default.
return fallbackOrder, dnsConf
}
var netdns = godebug.New("netdns")

View File

@ -1,18 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build netcgo
package net
/*
// Fail if cgo isn't available.
*/
import "C"
// The build tag "netcgo" forces use of the cgo DNS resolver.
// It is the opposite of "netgo".
func init() { netCgo = true }

View File

@ -43,6 +43,15 @@ var defaultResolvConf = &dnsConfig{
}
func TestConfHostLookupOrder(t *testing.T) {
// These tests are written for a system with cgo available,
// without using the netgo tag.
if netGoBuildTag {
t.Skip("skipping test because net package built with netgo tag")
}
if !cgoAvailable {
t.Skip("skipping test because cgo resolver not available")
}
tests := []struct {
name string
c *conf
@ -54,7 +63,8 @@ func TestConfHostLookupOrder(t *testing.T) {
{
name: "force",
c: &conf{
forceCgoLookupHost: true,
preferCgo: true,
netCgo: true,
},
resolv: defaultResolvConf,
nss: nssStr(t, "foo: bar"),
@ -82,12 +92,14 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: dns files something_custom"),
hostTests: []nssHostTest{
{"x.com", "myhostname", hostLookupFilesDNS},
{"x.com", "myhostname", hostLookupDNSFiles},
},
},
{
name: "ubuntu_trusty_avahi",
c: &conf{},
name: "ubuntu_trusty_avahi",
c: &conf{
mdnsTest: mdnsAssumeDoesNotExist,
},
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4"),
hostTests: []nssHostTest{
@ -203,8 +215,10 @@ func TestConfHostLookupOrder(t *testing.T) {
hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}},
},
{
name: "files_mdns_dns",
c: &conf{},
name: "files_mdns_dns",
c: &conf{
mdnsTest: mdnsAssumeDoesNotExist,
},
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: files mdns dns"),
hostTests: []nssHostTest{
@ -226,7 +240,7 @@ func TestConfHostLookupOrder(t *testing.T) {
{
name: "mdns_allow",
c: &conf{
hasMDNSAllow: true,
mdnsTest: mdnsAssumeExists,
},
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: files mdns dns"),
@ -294,8 +308,10 @@ func TestConfHostLookupOrder(t *testing.T) {
},
},
{
name: "ubuntu14.04.02",
c: &conf{},
name: "ubuntu14.04.02",
c: &conf{
mdnsTest: mdnsAssumeDoesNotExist,
},
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns mdns4"),
hostTests: []nssHostTest{
@ -342,9 +358,8 @@ func TestConfHostLookupOrder(t *testing.T) {
name: "resolver-prefergo",
resolver: &Resolver{PreferGo: true},
c: &conf{
goos: "darwin",
forceCgoLookupHost: true, // always true for darwin
netCgo: true,
preferCgo: true,
netCgo: true,
},
resolv: defaultResolvConf,
nss: nssStr(t, ""),
@ -352,6 +367,16 @@ func TestConfHostLookupOrder(t *testing.T) {
{"localhost", "myhostname", hostLookupFilesDNS},
},
},
{
name: "unknown-source",
resolver: &Resolver{PreferGo: true},
c: &conf{},
resolv: defaultResolvConf,
nss: nssStr(t, "hosts: resolve files"),
hostTests: []nssHostTest{
{"x.com", "myhostname", hostLookupDNSFiles},
},
},
}
origGetHostname := getHostname

View File

@ -92,7 +92,9 @@ second:
return nil
}
switch err := nestedErr.(type) {
case *AddrError, addrinfoErrno, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
case *AddrError, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
return nil
case interface{ isAddrinfoErrno() }:
return nil
case *os.SyscallError:
nestedErr = err.Err
@ -472,7 +474,9 @@ second:
return nil
}
switch err := nestedErr.(type) {
case *AddrError, addrinfoErrno, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
case *AddrError, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
return nil
case interface{ isAddrinfoErrno() }:
return nil
case *os.SyscallError:
nestedErr = err.Err

View File

@ -13,6 +13,11 @@ import (
"os"
)
// cgoAvailable set to true to indicate that the cgo resolver
// is available on Plan 9. Note that on Plan 9 the cgo resolver
// does not actually use cgo.
const cgoAvailable = true
func query(ctx context.Context, filename, query string, bufSize int) (addrs []string, err error) {
queryAddrs := func() (addrs []string, err error) {
file, err := os.OpenFile(filename, os.O_RDWR, 0)

View File

@ -792,7 +792,7 @@ func TestLookupPort(t *testing.T) {
switch runtime.GOOS {
case "android":
if netGo {
if netGoBuildTag {
t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
}
default:

View File

@ -55,7 +55,7 @@ func lookupProtocol(_ context.Context, name string) (int, error) {
func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
order, conf := systemConf().hostLookupOrder(r, host)
if !r.preferGo() && order == hostLookupCgo {
if order == hostLookupCgo {
if addrs, err, ok := cgoLookupHost(ctx, host); ok {
return addrs, err
}
@ -82,7 +82,9 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []
}
func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
if !r.preferGo() && systemConf().canUseCgo() {
// Port lookup is not a DNS operation.
// Prefer the cgo resolver if possible.
if !systemConf().mustUseGoResolver(r) {
if port, err, ok := cgoLookupPort(ctx, network, service); ok {
if err != nil {
// Issue 18213: if cgo fails, first check to see whether we
@ -99,7 +101,7 @@ func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int
func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
order, conf := systemConf().hostLookupOrder(r, name)
if !r.preferGo() && order == hostLookupCgo {
if order == hostLookupCgo {
if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
return cname, err
}
@ -125,7 +127,7 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
order, conf := systemConf().hostLookupOrder(r, "")
if !r.preferGo() && order == hostLookupCgo {
if order == hostLookupCgo {
if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
return ptrs, err
}

View File

@ -14,6 +14,11 @@ import (
"unsafe"
)
// cgoAvailable set to true to indicate that the cgo resolver
// is available on Windows. Note that on Windows the cgo resolver
// does not actually use cgo.
const cgoAvailable = true
const (
_WSAHOST_NOT_FOUND = syscall.Errno(11001)
_WSATRY_AGAIN = syscall.Errno(11002)

View File

@ -93,14 +93,6 @@ import (
"time"
)
// netGo and netCgo contain the state of the build tags used
// to build this binary, and whether cgo is available.
// conf.go mirrors these into conf for easier testing.
var (
netGo bool // set true in cgo_stub.go for build tag "netgo" (or no cgo)
netCgo bool // set true in conf_netcgo.go for build tag "netcgo"
)
// Addr represents a network end point address.
//
// The two methods Network and String conventionally return strings

9
src/net/netcgo_off.go Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !netcgo
package net
const netCgoBuildTag = false

9
src/net/netcgo_on.go Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build netcgo
package net
const netCgoBuildTag = true

View File

@ -1,13 +0,0 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Default netGo to true if the netgo build tag is being used, or the
// C library DNS routines are not available. Note that the C library
// routines are always available on Darwin and Windows.
//go:build netgo || (!cgo && !darwin && !windows)
package net
func init() { netGo = true }

14
src/net/netgo_netcgo.go Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build netgo && netcgo
package net
func init() {
// This will give a compile time error about the unused constant.
// The advantage of this approach is that the gc compiler
// actually prints the constant, making the problem obvious.
"Do not use both netgo and netcgo build tags."
}

9
src/net/netgo_off.go Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !netgo
package net
const netGoBuildTag = false

9
src/net/netgo_on.go Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build netgo
package net
const netGoBuildTag = true