Skip to content

Commit

Permalink
net: permit use of Resolver.PreferGo, netgo on Windows and Plan 9
Browse files Browse the repository at this point in the history
This reverts commit CL 401754 (440c931) which reverted CL 400654,
thus reapplying CL 400654, re-adding the func init() { netGo = true }
to cgo_stub.go CL 400654 had originally removed (mistakenly during
development?) that had broken the darwin nocgo builder.

Fixes golang#33097

Change-Id: I90f59746d2ceb6b5d2bd832c9fc90068f8ff7417
Reviewed-on: https://go-review.googlesource.com/c/go/+/409234
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Keith Randall <khr@google.com>
  • Loading branch information
bradfitz committed May 30, 2022
1 parent a21cf91 commit af88fb6
Show file tree
Hide file tree
Showing 15 changed files with 835 additions and 290 deletions.
2 changes: 0 additions & 2 deletions src/net/addrselect.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build unix

// Minimal RFC 6724 address selection.

package net
Expand Down
36 changes: 33 additions & 3 deletions src/net/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 unix
//go:build !js

package net

Expand All @@ -21,7 +21,7 @@ type conf struct {
forceCgoLookupHost bool

netGo bool // go DNS resolution forced
netCgo bool // cgo DNS resolution forced
netCgo bool // non-go DNS resolution forced (cgo, or win32)

// machine has an /etc/mdns.allow file
hasMDNSAllow bool
Expand Down Expand Up @@ -49,9 +49,23 @@ func initConfVal() {
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() {
if confVal.dnsDebugLevel > 1 {
println("go package net: confVal.netCgo =", confVal.netCgo, " netGo =", confVal.netGo)
}
switch {
case confVal.netGo:
if netGo {
Expand All @@ -75,6 +89,10 @@ func initConfVal() {
return
}

if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
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.
Expand Down Expand Up @@ -129,7 +147,19 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
}
fallbackOrder := hostLookupCgo
if c.netGo || r.preferGo() {
fallbackOrder = hostLookupFilesDNS
switch c.goos {
case "windows":
// TODO(bradfitz): implement files-based
// lookup on Windows too? I guess /etc/hosts
// kinda exists on Windows. But for now, only
// do DNS.
fallbackOrder = hostLookupDNS
default:
fallbackOrder = hostLookupFilesDNS
}
}
if c.goos == "windows" || c.goos == "plan9" {
return fallbackOrder
}
if c.forceCgoLookupHost || c.resolv.unknownOpt || c.goos == "android" {
return fallbackOrder
Expand Down
24 changes: 17 additions & 7 deletions src/net/dnsclient_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 unix
//go:build !js

// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
Expand All @@ -20,6 +20,7 @@ import (
"internal/itoa"
"io"
"os"
"runtime"
"sync"
"time"

Expand Down Expand Up @@ -381,12 +382,21 @@ func (conf *resolverConfig) tryUpdate(name string) {
}
conf.lastChecked = now

var mtime time.Time
if fi, err := os.Stat(name); err == nil {
mtime = fi.ModTime()
}
if mtime.Equal(conf.dnsConfig.mtime) {
return
switch runtime.GOOS {
case "windows":
// There's no file on disk, so don't bother checking
// and failing.
//
// The Windows implementation of dnsReadConfig (called
// below) ignores the name.
default:
var mtime time.Time
if fi, err := os.Stat(name); err == nil {
mtime = fi.ModTime()
}
if mtime.Equal(conf.dnsConfig.mtime) {
return
}
}

dnsConf := dnsReadConfig(name)
Expand Down
43 changes: 43 additions & 0 deletions src/net/dnsconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.

package net

import (
"os"
"sync/atomic"
"time"
)

var (
defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
getHostname = os.Hostname // variable for testing
)

type dnsConfig struct {
servers []string // server addresses (in host:port form) to use
search []string // rooted suffixes to append to local name
ndots int // number of dots in name to trigger absolute lookup
timeout time.Duration // wait before giving up on a query, including retries
attempts int // lost packets before giving up on server
rotate bool // round robin among servers
unknownOpt bool // anything unknown was encountered
lookup []string // OpenBSD top-level database "lookup" order
err error // any error that occurs during open of resolv.conf
mtime time.Time // time of resolv.conf modification
soffset uint32 // used by serverOffset
singleRequest bool // use sequential A and AAAA queries instead of parallel queries
useTCP bool // force usage of TCP for DNS resolutions
}

// serverOffset returns an offset that can be used to determine
// indices of servers in c.servers when making queries.
// When the rotate option is enabled, this offset increases.
// Otherwise it is always 0.
func (c *dnsConfig) serverOffset() uint32 {
if c.rotate {
return atomic.AddUint32(&c.soffset, 1) - 1 // return 0 to start
}
return 0
}
36 changes: 1 addition & 35 deletions src/net/dnsconfig_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build unix
//go:build !js && !windows

// Read system DNS config from /etc/resolv.conf

package net

import (
"internal/bytealg"
"os"
"sync/atomic"
"time"
)

var (
defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
getHostname = os.Hostname // variable for testing
)

type dnsConfig struct {
servers []string // server addresses (in host:port form) to use
search []string // rooted suffixes to append to local name
ndots int // number of dots in name to trigger absolute lookup
timeout time.Duration // wait before giving up on a query, including retries
attempts int // lost packets before giving up on server
rotate bool // round robin among servers
unknownOpt bool // anything unknown was encountered
lookup []string // OpenBSD top-level database "lookup" order
err error // any error that occurs during open of resolv.conf
mtime time.Time // time of resolv.conf modification
soffset uint32 // used by serverOffset
singleRequest bool // use sequential A and AAAA queries instead of parallel queries
useTCP bool // force usage of TCP for DNS resolutions
}

// See resolv.conf(5) on a Linux machine.
func dnsReadConfig(filename string) *dnsConfig {
conf := &dnsConfig{
Expand Down Expand Up @@ -156,17 +133,6 @@ func dnsReadConfig(filename string) *dnsConfig {
return conf
}

// serverOffset returns an offset that can be used to determine
// indices of servers in c.servers when making queries.
// When the rotate option is enabled, this offset increases.
// Otherwise it is always 0.
func (c *dnsConfig) serverOffset() uint32 {
if c.rotate {
return atomic.AddUint32(&c.soffset, 1) - 1 // return 0 to start
}
return 0
}

func dnsDefaultSearch() []string {
hn, err := getHostname()
if err != nil {
Expand Down
58 changes: 58 additions & 0 deletions src/net/dnsconfig_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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.

package net

import (
"syscall"
"time"
)

func dnsReadConfig(ignoredFilename string) (conf *dnsConfig) {
conf = &dnsConfig{
ndots: 1,
timeout: 5 * time.Second,
attempts: 2,
}
defer func() {
if len(conf.servers) == 0 {
conf.servers = defaultNS
}
}()
aas, err := adapterAddresses()
if err != nil {
return
}
// TODO(bradfitz): this just collects all the DNS servers on all
// the interfaces in some random order. It should order it by
// default route, or only use the default route(s) instead.
// In practice, however, it mostly works.
for _, aa := range aas {
for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next {
sa, err := dns.Address.Sockaddr.Sockaddr()
if err != nil {
continue
}
var ip IP
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
ip = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
case *syscall.SockaddrInet6:
ip = make(IP, IPv6len)
copy(ip, sa.Addr[:])
if ip[0] == 0xfe && ip[1] == 0xc0 {
// Ignore these fec0/10 ones. Windows seems to
// populate them as defaults on its misc rando
// interfaces.
continue
}
default:
// Unexpected type.
continue
}
conf.servers = append(conf.servers, JoinHostPort(ip.String(), "53"))
}
}
return conf
}
Loading

0 comments on commit af88fb6

Please sign in to comment.