update to latest github.com/mjl-/adns, synced to go1.24.1

This commit is contained in:
Mechiel Lukkien 2025-03-21 18:42:02 +01:00
parent 70aedddc90
commit 773d8cc959
No known key found for this signature in database
14 changed files with 188 additions and 159 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/mjl-/mox
go 1.22.0
require (
github.com/mjl-/adns v0.0.0-20240509092456-2dc8715bf4af
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea
github.com/mjl-/autocert v0.0.0-20231214125928-31b7400acb05
github.com/mjl-/bstore v0.0.6
github.com/mjl-/flate v0.0.0-20250221133712-6372d09eb978

4
go.sum
View File

@ -24,8 +24,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/mjl-/adns v0.0.0-20240509092456-2dc8715bf4af h1:sEDWZPIi5K1qKk7JQoAZyDwXkRQseIf7y5ony8JeYEQ=
github.com/mjl-/adns v0.0.0-20240509092456-2dc8715bf4af/go.mod h1:v47qUMJnipnmDTRGaHwpCwzE6oypa5K33mUvBfzZBn8=
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea h1:8dftsVL1tHhRksXzFZRhSJ7gSlcy/t87Nvucs3JnTGE=
github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea/go.mod h1:rWZMqGA2HoBm5b5q/A5J8u1sSVuEYh6zBz9tMoVs+RU=
github.com/mjl-/autocert v0.0.0-20231214125928-31b7400acb05 h1:s6ay4bh4tmpPLdxjyeWG45mcwHfEluBMuGPkqxHWUJ4=
github.com/mjl-/autocert v0.0.0-20231214125928-31b7400acb05/go.mod h1:taMFU86abMxKLPV4Bynhv8enbYmS67b8LG80qZv2Qus=
github.com/mjl-/bstore v0.0.6 h1:ntlu9MkfCkpm2XfBY4+Ws4KK9YzXzewr3+lCueFB+9c=

View File

@ -8,7 +8,8 @@ test:
check:
GOARCH=386 go vet
staticcheck ./...
# don't warn about using deprecated functions like net.Temporary
staticcheck -checks inherit,-SA1019 ./...
# having "err" shadowed is common, best to not have others
check-shadow:

58
vendor/github.com/mjl-/adns/conf.go generated vendored
View File

@ -11,8 +11,8 @@ import (
"io/fs"
"os"
"runtime"
"strings"
"sync"
"syscall"
"github.com/mjl-/adns/internal/bytealg"
)
@ -99,19 +99,30 @@ func initConfVal() {
if confVal.dnsDebugLevel > 1 {
println("go package net: confVal.netCgo =", confVal.netCgo, " netGo =", confVal.netGo)
}
if dnsMode != "go" && dnsMode != "cgo" && dnsMode != "" {
println("go package net: GODEBUG=netdns contains an invalid dns mode, ignoring it")
}
switch {
case confVal.netGo:
if netGoBuildTag {
println("go package net: built with netgo build tag; using Go's DNS resolver")
case netGoBuildTag || !cgoAvailable:
if dnsMode == "cgo" {
println("go package net: ignoring GODEBUG=netdns=cgo as the binary was compiled without support for the cgo resolver")
} else {
println("go package net: GODEBUG setting forcing use of Go's resolver")
println("go package net: using the Go DNS resolver")
}
case netCgoBuildTag:
if dnsMode == "go" {
println("go package net: GODEBUG setting forcing use of the Go resolver")
} else {
println("go package net: using the cgo DNS resolver")
}
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")
if dnsMode == "go" {
println("go package net: GODEBUG setting forcing use of the Go resolver")
} else if dnsMode == "cgo" {
println("go package net: GODEBUG setting forcing use of the cgo resolver")
} else {
println("go package net: dynamic selection of DNS resolver")
}
}
}()
}
@ -143,7 +154,7 @@ func initConfVal() {
// prefer the cgo resolver.
// Note that LOCALDOMAIN can change behavior merely by being
// specified with the empty string.
_, localDomainDefined := syscall.Getenv("LOCALDOMAIN")
_, localDomainDefined := os.LookupEnv("LOCALDOMAIN")
if localDomainDefined || os.Getenv("RES_OPTIONS") != "" || os.Getenv("HOSTALIASES") != "" {
confVal.preferCgo = true
return
@ -324,16 +335,7 @@ func (c *conf) lookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, d
}
// Canonicalize the hostname by removing any trailing dot.
if stringsHasSuffix(hostname, ".") {
hostname = hostname[:len(hostname)-1]
}
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 hostLookupCgo, dnsConf
}
hostname = strings.TrimSuffix(hostname, ".")
nss := getSystemNSS()
srcs := nss.sources["hosts"]
@ -392,10 +394,14 @@ func (c *conf) lookupOrder(r *Resolver, hostname string) (ret hostLookupOrder, d
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.
case hostname != "" && strings.HasPrefix(src.source, "mdns"):
if 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 hostLookupCgo, dnsConf
}
// We don't parse mdns.allow files. They're rare. If one
// exists, it might list other TLDs (besides .local) or even
@ -492,7 +498,7 @@ func isGateway(h string) bool {
return stringsEqualFold(h, "_gateway")
}
// isOutbound reports whether h should be considered a "outbound"
// isOutbound reports whether h should be considered an "outbound"
// name for the myhostname NSS module.
func isOutbound(h string) bool {
return stringsEqualFold(h, "_outbound")

View File

@ -5,9 +5,10 @@
package adns
import (
mathrand "math/rand"
"cmp"
mathrand "math/rand/v2"
"net"
"sort"
"slices"
"golang.org/x/net/dns/dnsmessage"
@ -16,7 +17,7 @@ import (
)
func randInt() int {
return mathrand.Int()
return int(uint(mathrand.Uint64()) >> 1) // clear sign bit
}
func randIntn(n int) int {
@ -72,6 +73,16 @@ func equalASCIIName(x, y dnsmessage.Name) bool {
// isDomainName checks if a string is a presentation-format domain name
// (currently restricted to hostname-compatible "preferred name" LDH labels and
// SRV-like "underscore labels"; see golang.org/issue/12421).
//
// isDomainName should be an internal detail,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/sagernet/sing
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
// disabled: go:linkname isDomainName
func isDomainName(s string) bool {
// The root domain name is valid. See golang.org/issue/45715.
if s == "." {
@ -149,12 +160,6 @@ func absDomainName(s string) string {
// byPriorityWeight sorts SRV records by ascending priority and weight.
type byPriorityWeight []*net.SRV
func (s byPriorityWeight) Len() int { return len(s) }
func (s byPriorityWeight) Less(i, j int) bool {
return s[i].Priority < s[j].Priority || (s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
}
func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// shuffleByWeight shuffles SRV records by weight using the algorithm
// described in RFC 2782.
func (addrs byPriorityWeight) shuffleByWeight() {
@ -181,7 +186,12 @@ func (addrs byPriorityWeight) shuffleByWeight() {
// sort reorders SRV records as specified in RFC 2782.
func (addrs byPriorityWeight) sort() {
sort.Sort(addrs)
slices.SortFunc(addrs, func(a, b *net.SRV) int {
if r := cmp.Compare(a.Priority, b.Priority); r != 0 {
return r
}
return cmp.Compare(a.Weight, b.Weight)
})
i := 0
for j := 1; j < len(addrs); j++ {
if addrs[i].Priority != addrs[j].Priority {
@ -192,18 +202,16 @@ func (addrs byPriorityWeight) sort() {
addrs[i:].shuffleByWeight()
}
// byPref implements sort.Interface to sort MX records by preference
// byPref sorts MX records by preference
type byPref []*net.MX
func (s byPref) Len() int { return len(s) }
func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref }
func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// sort reorders MX records as specified in RFC 5321.
func (s byPref) sort() {
for i := range s {
j := randIntn(i + 1)
s[i], s[j] = s[j], s[i]
}
sort.Sort(s)
slices.SortFunc(s, func(a, b *net.MX) int {
return cmp.Compare(a.Pref, b.Pref)
})
}

View File

@ -23,6 +23,7 @@ import (
"net"
"os"
"runtime"
"strings"
"sync"
"sync/atomic"
"time"
@ -54,7 +55,7 @@ var (
// errServerTemporarilyMisbehaving is like errServerMisbehaving, except
// that when it gets translated to a DNSError, the IsTemporary field
// gets set to true.
errServerTemporarilyMisbehaving = errors.New("server misbehaving")
errServerTemporarilyMisbehaving = &temporaryError{"server misbehaving"}
)
func newRequest(q dnsmessage.Question, ad bool) (id uint16, udpReq, tcpReq []byte, err error) {
@ -346,7 +347,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
n, err := dnsmessage.NewName(name)
if err != nil {
return dnsmessage.Parser{}, "", Result{}, errCannotMarshalDNSMessage
return dnsmessage.Parser{}, "", Result{}, &DNSError{Err: errCannotMarshalDNSMessage.Error(), Name: name}
}
q := dnsmessage.Question{
Name: n,
@ -360,14 +361,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
p, h, err := r.exchange(ctx, server, q, cfg.timeout, cfg.useTCP, cfg.trustAD)
if err != nil {
dnsErr := &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
dnsErr.IsTimeout = true
}
dnsErr := newDNSError(err, name, server)
// Set IsTemporary for socket-level errors. Note that this flag
// may also be used to indicate a SERVFAIL response.
if _, ok := err.(*net.OpError); ok {
@ -381,49 +375,27 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
result := Result{Authentic: cfg.trustAD && h.AuthenticData && useAD}
if err := checkHeader(&p, h); err != nil {
dnsErr := &DNSError{
Underlying: err,
Err: err.Error(),
Name: name,
Server: server,
}
if err == errServerTemporarilyMisbehaving {
dnsErr.IsTemporary = true
} else if edeErr, isEDE := err.(ExtendedError); isEDE && edeErr.IsTemporary() {
dnsErr.IsTemporary = true
} else if isEDE {
// Something wrong with the zone, no point asking another server or retrying.
return p, server, result, dnsErr
}
if err == errNoSuchHost {
// The name does not exist, so trying
// another server won't help.
dnsErr.IsNotFound = true
return p, server, result, dnsErr
return p, server, result, newDNSError(errNoSuchHost, name, server)
}
lastErr = dnsErr
lastErr = newDNSError(err, name, server)
lastResult = result
continue
}
err = skipToAnswer(&p, qtype)
if err == nil {
return p, server, result, nil
}
lastErr = &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
lastResult = result
if err == errNoSuchHost {
// The name does not exist, so trying another
// server won't help.
lastErr.(*DNSError).IsNotFound = true
return p, server, lastResult, lastErr
if err := skipToAnswer(&p, qtype); err != nil {
if err == errNoSuchHost {
// The name does not exist, so trying
// another server won't help.
return p, server, result, newDNSError(errNoSuchHost, name, server)
}
lastErr = newDNSError(err, name, server)
lastResult = result
continue
}
return p, server, result, nil
}
}
return dnsmessage.Parser{}, "", lastResult, lastErr
@ -523,7 +495,7 @@ func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Typ
// 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 dnsmessage.Parser{}, "", Result{}, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
return dnsmessage.Parser{}, "", Result{}, newDNSError(errNoSuchHost, name, "")
}
if conf == nil {
@ -568,9 +540,7 @@ func avoidDNS(name string) bool {
if name == "" {
return true
}
if name[len(name)-1] == '.' {
name = name[:len(name)-1]
}
name = strings.TrimSuffix(name, ".")
return stringsHasSuffixFold(name, ".onion")
}
@ -653,7 +623,7 @@ func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hos
}
if order == hostLookupFiles {
return nil, result, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
return nil, result, newDNSError(errNoSuchHost, name, "")
}
}
ips, _, result, err := r.goLookupIPCNAMEOrder(ctx, "ip", name, order, conf)
@ -704,13 +674,13 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, network, name strin
}
if order == hostLookupFiles {
return nil, dnsmessage.Name{}, result, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
return nil, dnsmessage.Name{}, result, newDNSError(errNoSuchHost, name, "")
}
}
if !isDomainName(name) {
// See comment in func lookup above about use of errNoSuchHost.
return nil, dnsmessage.Name{}, result, &DNSError{Err: errNoSuchHost.Error(), Name: name, IsNotFound: true}
return nil, dnsmessage.Name{}, result, newDNSError(errNoSuchHost, name, "")
}
type result0 struct {
p dnsmessage.Parser
@ -920,7 +890,7 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string, order hostLooku
}
if order == hostLookupFiles {
return nil, Result{}, &DNSError{Err: errNoSuchHost.Error(), Name: addr, IsNotFound: true}
return nil, Result{}, newDNSError(errNoSuchHost, addr, "")
}
}

View File

@ -10,10 +10,22 @@ import (
"time"
)
var (
defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
getHostname = os.Hostname // variable for testing
)
// defaultNS is the default name servers to use in the absence of DNS configuration.
//
// defaultNS should be an internal detail,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
// - github.com/pojntfx/hydrapp/hydrapp
// - github.com/mtibben/androiddnsfix
// - github.com/metacubex/mihomo
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
// disabled: go:linkname defaultNS
var defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
var getHostname = os.Hostname // variable for testing
type dnsConfig struct {
servers []string // server addresses (in host:port form) to use

View File

@ -27,16 +27,19 @@ func dnsReadConfig(ignoredFilename string) (conf *dnsConfig) {
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 {
// Only take interfaces whose OperStatus is IfOperStatusUp(0x01) into DNS configs.
if aa.OperStatus != windows.IfOperStatusUp {
continue
}
// Only take interfaces which have at least one gateway
if aa.FirstGatewayAddress == nil {
continue
}
for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next {
// Only take interfaces whose OperStatus is IfOperStatusUp(0x01) into DNS configs.
if aa.OperStatus != windows.IfOperStatusUp {
continue
}
sa, err := dns.Address.Sockaddr.Sockaddr()
if err != nil {
continue
@ -49,9 +52,11 @@ func dnsReadConfig(ignoredFilename string) (conf *dnsConfig) {
ip = make(net.IP, net.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.
// fec0/10 IPv6 addresses are site local anycast DNS
// addresses Microsoft sets by default if no other
// IPv6 DNS address is set. Site local anycast is
// deprecated since 2004, see
// https://datatracker.ietf.org/doc/html/rfc3879
continue
}
default:

3
vendor/github.com/mjl-/adns/doc.go generated vendored
View File

@ -14,7 +14,6 @@ Modifications
are still also trusted if /etc/resolv.conf has "trust-ad" in the "options".
- New function LookupTLSA, to support DANE which uses DNS records of type TLSA.
- Support Extended DNS Errors (EDE) for details about DNSSEC errors.
- adns uses its own DNSError type, with an additional "Underlying error" field
and Unwrap function, so callers can check for the new ExtendedError type.
- adns.DNSError wraps ExtendedError for EDE.
*/
package adns

View File

@ -21,7 +21,8 @@ func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
l := uint32(15000) // recommended initial size
for {
b = make([]byte, l)
err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
const flags = windows.GAA_FLAG_INCLUDE_PREFIX | windows.GAA_FLAG_INCLUDE_GATEWAYS
err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, flags, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
if err == nil {
if l == 0 {
return nil, nil

View File

@ -106,7 +106,7 @@ func lookupPortMapWithNetwork(network, errNetwork, service string) (port int, er
if port, ok := m[string(lowerService[:n])]; ok && n == len(service) {
return port, nil
}
return 0, &DNSError{Err: "unknown port", Name: errNetwork + "/" + service, IsNotFound: true}
return 0, newDNSError(errUnknownPort, errNetwork+"/"+service, "")
}
return 0, &DNSError{Err: "unknown network", Name: errNetwork + "/" + service}
}
@ -193,7 +193,7 @@ func LookupHost(host string) (addrs []string, result Result, err error) {
func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, result Result, err error) {
// Make sure that no matter what we do later, host=="" is rejected.
if host == "" {
return nil, result, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
return nil, result, newDNSError(errNoSuchHost, host, "")
}
if _, err := netip.ParseAddr(host); err == nil {
return []string{host}, result, nil
@ -237,7 +237,7 @@ func (r *Resolver) LookupIP(ctx context.Context, network, host string) ([]net.IP
}
if host == "" {
return nil, Result{}, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
return nil, Result{}, newDNSError(errNoSuchHost, host, "")
}
addrs, result, err := r.internetAddrList(ctx, afnet, host)
if err != nil {
@ -305,7 +305,7 @@ func withUnexpiredValuesPreserved(lookupCtx context.Context) context.Context {
func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]net.IPAddr, Result, error) {
// Make sure that no matter what we do later, host=="" is rejected.
if host == "" {
return nil, Result{}, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
return nil, Result{}, newDNSError(errNoSuchHost, host, "")
}
if ip, err := netip.ParseAddr(host); err == nil {
return []net.IPAddr{{IP: net.IP(ip.AsSlice()).To16(), Zone: ip.Zone()}}, Result{}, nil
@ -354,12 +354,7 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]ne
} else {
go dnsWaitGroupDone(ch, lookupGroupCancel)
}
ctxErr := ctx.Err()
err := &DNSError{
Err: mapErr(ctxErr).Error(),
Name: host,
IsTimeout: ctxErr == context.DeadlineExceeded,
}
err := newDNSError(mapErr(ctx.Err()), host, "")
return nil, Result{}, err
case r := <-ch:
dnsWaitGroup.Done()
@ -367,17 +362,7 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]ne
err := r.Err
if err != nil {
if _, ok := err.(*DNSError); !ok {
isTimeout := false
if err == context.DeadlineExceeded {
isTimeout = true
} else if terr, ok := err.(timeout); ok {
isTimeout = terr.Timeout()
}
err = &DNSError{
Err: err.Error(),
Name: host,
IsTimeout: isTimeout,
}
err = newDNSError(mapErr(err), host, "")
}
}
tuple := r.Val.(Tuple)
@ -614,6 +599,9 @@ func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*net.NS, Result
// LookupTXT returns the DNS TXT records for the given domain name.
//
// If a DNS TXT record holds multiple strings, they are concatenated as a
// single string.
//
// LookupTXT uses context.Background internally; to specify the context, use
// Resolver.LookupTXT.
func LookupTXT(name string) ([]string, Result, error) {
@ -621,6 +609,9 @@ func LookupTXT(name string) ([]string, Result, error) {
}
// LookupTXT returns the DNS TXT records for the given domain name.
//
// If a DNS TXT record holds multiple strings, they are concatenated as a
// single string.
func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, Result, error) {
return r.lookupTXT(ctx, name)
}

65
vendor/github.com/mjl-/adns/net.go generated vendored
View File

@ -7,6 +7,7 @@ package adns
import (
"context"
"errors"
"net"
)
// Various errors contained in OpError.
@ -39,15 +40,26 @@ func mapErr(err error) error {
}
}
type timeout interface {
Timeout() bool
}
// Various errors contained in DNSError.
var (
errNoSuchHost = errors.New("no such host")
errNoSuchHost = &notFoundError{"no such host"}
errUnknownPort = &notFoundError{"unknown port"}
)
// notFoundError is a special error understood by the newDNSError function,
// which causes a creation of a DNSError with IsNotFound field set to true.
type notFoundError struct{ s string }
func (e *notFoundError) Error() string { return e.s }
// temporaryError is an error type that implements the [Error] interface.
// It returns true from the Temporary method.
type temporaryError struct{ s string }
func (e *temporaryError) Error() string { return e.s }
func (e *temporaryError) Temporary() bool { return true }
func (e *temporaryError) Timeout() bool { return false }
// errTimeout exists to return the historical "i/o timeout" string
// for context.DeadlineExceeded. See mapErr.
// It is also used when Dialer.Deadline is exceeded.
@ -73,7 +85,7 @@ func (e *timeoutError) Is(err error) bool {
// DNSError represents a DNS lookup error.
type DNSError struct {
Underlying error // Underlying error, could be an ExtendedError.
UnwrapErr error // error returned by the [DNSError.Unwrap] method, might be nil
Err string // description of the error
Name string // name looked for
Server string // server used
@ -86,11 +98,46 @@ type DNSError struct {
IsNotFound bool
}
// Unwrap returns the underlying error, which could be an ExtendedError.
func (e *DNSError) Unwrap() error {
return e.Underlying
// newDNSError creates a new *DNSError.
// Based on the err, it sets the UnwrapErr, IsTimeout, IsTemporary, IsNotFound fields.
func newDNSError(err error, name, server string) *DNSError {
var (
isTimeout bool
isTemporary bool
unwrapErr error
)
if err, ok := err.(net.Error); ok {
isTimeout = err.Timeout()
isTemporary = err.Temporary()
}
// At this time, the only errors we wrap are context errors, to allow
// users to check for canceled/timed out requests.
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
unwrapErr = err
} else if edeErr, ok := err.(ExtendedError); ok {
unwrapErr = edeErr
if edeErr.IsTemporary() {
isTemporary = true
}
}
_, isNotFound := err.(*notFoundError)
return &DNSError{
UnwrapErr: unwrapErr,
Err: err.Error(),
Name: name,
Server: server,
IsTimeout: isTimeout,
IsTemporary: isTemporary,
IsNotFound: isNotFound,
}
}
// Unwrap returns e.UnwrapErr.
func (e *DNSError) Unwrap() error { return e.UnwrapErr }
func (e *DNSError) Error() string {
if e == nil {
return "<nil>"

11
vendor/github.com/mjl-/adns/parse.go generated vendored
View File

@ -213,23 +213,12 @@ func foreachField(x string, fn func(field string) error) error {
return nil
}
// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
// suffix.
func stringsHasSuffix(s, suffix string) bool {
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}
// stringsHasSuffixFold reports whether s ends in suffix,
// ASCII-case-insensitively.
func stringsHasSuffixFold(s, suffix string) bool {
return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix)
}
// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
func stringsHasPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
}
// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
// are equal, ASCII-case-insensitively.
func stringsEqualFold(s, t string) bool {

4
vendor/modules.txt vendored
View File

@ -7,8 +7,8 @@ github.com/cespare/xxhash/v2
# github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0
## explicit; go 1.19
github.com/matttproud/golang_protobuf_extensions/v2/pbutil
# github.com/mjl-/adns v0.0.0-20240509092456-2dc8715bf4af
## explicit; go 1.20
# github.com/mjl-/adns v0.0.0-20250321173553-ab04b05bdfea
## explicit; go 1.22
github.com/mjl-/adns
github.com/mjl-/adns/internal/bytealg
github.com/mjl-/adns/internal/itoa