Skip to content
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

proposal: net: make LookupCNAME consistent between Unix and Windows, document #50101

Open
bradfitz opened this issue Dec 11, 2021 · 4 comments
Open

Comments

@bradfitz
Copy link
Contributor

@bradfitz bradfitz commented Dec 11, 2021

LookupCNAME is pretty weird right now.

Despite the name, it entirely ignores CNAME records on Unix. It launches A and AAAA record lookups to recursive resolvers and returns the first response name found in the A and AAAA, skipping over any CNAME. (and not even asking for a CNAME)

But it documents that it does that...

https://pkg.go.dev/net#LookupCNAME

A canonical name is the final name after following zero or more CNAME records. LookupCNAME does not return an error if host does not contain DNS "CNAME" records, as long as host resolves to address records.

OTOH, on Windows, it does what you would expect from the name itself: it looks up CNAME records:

func (*Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
        // TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
        acquireThread()
        defer releaseThread()
        var r *syscall.DNSRecord
        e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)

Here's a demo of a program behaving differently:

func main() {
	txt, err := net.LookupTXT("cname-to-txt.go4.org")
	log.Printf("LookupTXT = %q, %v", txt, err)

	cname, err := net.LookupCNAME("cname-to-txt.go4.org")
	log.Printf("cname = %q, %v", cname, err)
}

On Linux/Mac:

2021/12/10 21:19:45 LookupTXT = ["foo=bar"], <nil>
2021/12/10 21:19:45 cname = "", lookup cname-to-txt.go4.org: no such host

On Windows:

2021/12/10 21:11:45 LookupTXT = ["foo=bar"], <nil>
2021/12/10 21:11:45 cname = "test-txt-record.go4.org.", <nil>

I like the Windows behavior better, FWIW. That's what I was looking for, but apparently it doesn't exist.

Can we either:

  1. add LookupCNAMERecord that actually looks up a CNAME record
  2. redefine LookupCNAME to be like Windows, perhaps adding a LookupCanonicalName with the current weird Unix behavior of LookupCNAME?

But at minimum: document whatever the rules are and make Unix and Windows match? At least in Resolver.PreferGo mode?

@rsc
Copy link
Contributor

@rsc rsc commented Dec 15, 2021

I think LookupCNAME came about that way because we are using getaddrinfo, and it returns the underlying name almost as a side effect of the lookup, in res.ai_canonname. Should we stop using glibc for this call and make it match Windows? It might make it fail where it was succeeding before? Not sure.

@rsc
Copy link
Contributor

@rsc rsc commented Dec 15, 2021

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc rsc moved this from Incoming to Active in Proposals Dec 15, 2021
@rsc
Copy link
Contributor

@rsc rsc commented Jan 5, 2022

The problem we have is that we need to use getaddrinfo(AI_CANONNAME) on Macs, because port 53 is blocked to non-libc code. Is there some way to make getaddrinfo succeed for hosts that have a CNAME record but for which that named host has no A/AAAA records? If not, it's very hard to implement the Windows LookupCNAME behavior on systems like Macs.

@rsc
Copy link
Contributor

@rsc rsc commented Jan 12, 2022

Looks like even though it's not in the man pages, macOS may have res_ninit. So maybe we should look into using that in place of getaddrinfo(AI_CANONNAME). If that's possible, then it would seem OK to change this.

The specific case being changed is when the name has a CNAME but no A/AAAA record, which is currently an error on Unix but succeeds on Windows. With this change, it would succeed everywhere in this (unusual) case.

Does anyone want to look into how hard it would be to make the Go code use libresolv on Mac? That might also help for things like MX lookups.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants