Skip to content

net: force cgo for myhostname and mdns nss modules for LookupAddr on unix #59921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 59 additions & 47 deletions src/net/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ func (c *conf) mustUseGoResolver(r *Resolver) bool {
return c.netGo || r.preferGo() || !cgoAvailable
}

// addrLookupOrder determines which strategy to use to resolve addresses.
// 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) addrLookupOrder(r *Resolver, addr string) (ret hostLookupOrder, dnsConf *dnsConfig) {
if c.dnsDebugLevel > 1 {
defer func() {
print("go package net: addrLookupOrder(", addr, ") = ", ret.String(), "\n")
}()
}
return c.lookupOrder(r, "")
}

// 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.
Expand All @@ -197,7 +209,10 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
print("go package net: hostLookupOrder(", hostname, ") = ", ret.String(), "\n")
}()
}
return c.lookupOrder(r, hostname)
}

func (c *conf) lookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, dnsConf *dnsConfig) {
// fallbackOrder is the order we return if we can't figure it out.
var fallbackOrder hostLookupOrder

Expand Down Expand Up @@ -339,23 +354,9 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
return fallbackOrder, dnsConf
}

var mdnsSource, filesSource, dnsSource, unknownSource bool
var filesSource, dnsSource, unknownSource bool
var first string
for _, src := range srcs {
if src.source == "myhostname" {
// 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 canUseCgo && !src.standardCriteria() {
// non-standard; let libc deal with it.
Expand All @@ -371,16 +372,50 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
}
continue
}
if stringsHasPrefix(src.source, "mdns") {
// e.g. "mdns4", "mdns4_minimal"
// We already returned true before if it was *.local.
// libc wouldn't have found a hit on this anyway.
mdnsSource = true
continue
}
// Some source we don't know how to deal with.

if canUseCgo {
return hostLookupCgo, dnsConf
switch {
case hostname != "" && src.source == "myhostname":
// Let the cgo resolver handle myhostname
// if we are looking up the local hostname.
if isLocalhost(hostname) || isGateway(hostname) || isOutbound(hostname) {
return hostLookupCgo, dnsConf
}
hn, err := getHostname()
if err != nil || stringsEqualFold(hostname, hn) {
return hostLookupCgo, dnsConf
}
continue
case hostname != "" && stringsHasPrefix(src.source, "mdns"):
// e.g. "mdns4", "mdns4_minimal"
// We already returned true before if it was *.local.
// libc wouldn't have found a hit on this anyway.

// 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.
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
}
continue
default:
// Some source we don't know how to deal with.
return hostLookupCgo, dnsConf
}
}

unknownSource = true
Expand All @@ -389,29 +424,6 @@ func (c *conf) hostLookupOrder(r *Resolver, hostname string) (ret hostLookupOrde
}
}

// 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 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
}
}

// 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 {
Expand Down
37 changes: 36 additions & 1 deletion src/net/conf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,6 @@ func TestConfHostLookupOrder(t *testing.T) {
{"anything.localhost.localdomain", "myhostname", hostLookupCgo},
{"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo},
{"somehostname", "myhostname", hostLookupFilesDNS},
{"", "myhostname", hostLookupFilesDNS}, // Issue 13623
},
},
{
Expand Down Expand Up @@ -392,6 +391,42 @@ func TestConfHostLookupOrder(t *testing.T) {
}
}

func TestAddrLookupOrder(t *testing.T) {
// This test is 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")
}

defer setSystemNSS(getSystemNSS(), 0)
c, err := newResolvConfTest()
if err != nil {
t.Fatal(err)
}
defer c.teardown()

if !c.forceUpdateConf(defaultResolvConf, time.Now().Add(time.Hour)) {
t.Fatal("failed to change resolv config")
}

setSystemNSS(nssStr(t, "hosts: files myhostname dns"), time.Hour)
cnf := &conf{}
order, _ := cnf.addrLookupOrder(nil, "192.0.2.1")
if order != hostLookupCgo {
t.Errorf("addrLookupOrder returned: %v, want cgo", order)
}

setSystemNSS(nssStr(t, "hosts: files mdns4 dns"), time.Hour)
order, _ = cnf.addrLookupOrder(nil, "192.0.2.1")
if order != hostLookupCgo {
t.Errorf("addrLookupOrder returned: %v, want cgo", order)
}

}

func setSystemNSS(nss *nssConf, addDur time.Duration) {
nssConfig.mu.Lock()
nssConfig.nssConf = nss
Expand Down
2 changes: 1 addition & 1 deletion src/net/lookup_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,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, "")
order, conf := systemConf().addrLookupOrder(r, addr)
if order == hostLookupCgo {
if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
return ptrs, err
Expand Down