boulder/bdns/problem.go

58 lines
1.5 KiB
Go

package bdns
import (
"context"
"fmt"
"net"
"github.com/miekg/dns"
)
// DNSError wraps a DNS error with various relevant information
type DNSError struct {
recordType uint16
hostname string
// Exactly one of rCode or underlying should be set.
underlying error
rCode int
}
func (d DNSError) Error() string {
var detail string
if d.underlying != nil {
if netErr, ok := d.underlying.(*net.OpError); ok {
if netErr.Timeout() {
detail = detailDNSTimeout
} else {
detail = detailDNSNetFailure
}
// Note: we check d.underlying here even though `Timeout()` does this because the call to `netErr.Timeout()` above only
// happens for `*net.OpError` underlying types!
} else if d.underlying == context.Canceled || d.underlying == context.DeadlineExceeded {
detail = detailDNSTimeout
} else {
detail = detailServerFailure
}
} else if d.rCode != dns.RcodeSuccess {
detail = dns.RcodeToString[d.rCode]
} else {
detail = detailServerFailure
}
return fmt.Sprintf("DNS problem: %s looking up %s for %s", detail,
dns.TypeToString[d.recordType], d.hostname)
}
// Timeout returns true if the underlying error was a timeout
func (d DNSError) Timeout() bool {
if netErr, ok := d.underlying.(*net.OpError); ok {
return netErr.Timeout()
} else if d.underlying == context.Canceled || d.underlying == context.DeadlineExceeded {
return true
}
return false
}
const detailDNSTimeout = "query timed out"
const detailDNSNetFailure = "networking error"
const detailServerFailure = "server failure at resolver"