From 83b388a80c430233c72c45c85517573177b7f716 Mon Sep 17 00:00:00 2001
From: Daniel Tang
Date: Fri, 9 Apr 2021 01:11:06 +1000
Subject: [PATCH] Add support for extended DNS errors (RFC 8914). (#1253)
Automatically submitted.
---
README.md | 1 +
edns.go | 101 +++++++++++++++++++++++++++++++++++++++++++++++++
msg_helpers.go | 2 +
3 files changed, 104 insertions(+)
diff --git a/README.md b/README.md
index 3594492b..d5b78ef4 100644
--- a/README.md
+++ b/README.md
@@ -171,6 +171,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 8080 - EdDSA for DNSSEC
* 8499 - DNS Terminology
* 8659 - DNS Certification Authority Authorization (CAA) Resource Record
+* 8914 - Extended DNS Errors
* 8976 - Message Digest for DNS Zones (ZONEMD RR)
## Loosely Based Upon
diff --git a/edns.go b/edns.go
index 1a87f4cb..8df0ec90 100644
--- a/edns.go
+++ b/edns.go
@@ -22,6 +22,7 @@ const (
EDNS0COOKIE = 0xa // EDNS0 Cookie
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
+ EDNS0EDE = 0xf // EDNS0 extended DNS errors (See RFC 8914)
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
_DO = 1 << 15 // DNSSEC OK
@@ -73,6 +74,8 @@ func (rr *OPT) String() string {
s += "\n; LOCAL OPT: " + o.String()
case *EDNS0_PADDING:
s += "\n; PADDING: " + o.String()
+ case *EDNS0_EDE:
+ s += "\n; EDE: " + o.String()
}
}
return s
@@ -673,3 +676,101 @@ func (e *EDNS0_PADDING) copy() EDNS0 {
copy(b, e.Padding)
return &EDNS0_PADDING{b}
}
+
+// Extended DNS Error Codes (RFC 8914).
+const (
+ ExtendedErrorCodeOther uint16 = iota
+ ExtendedErrorCodeUnsupportedDNSKEYAlgorithm
+ ExtendedErrorCodeUnsupportedDSDigestType
+ ExtendedErrorCodeStaleAnswer
+ ExtendedErrorCodeForgedAnswer
+ ExtendedErrorCodeDNSSECIndeterminate
+ ExtendedErrorCodeDNSBogus
+ ExtendedErrorCodeSignatureExpired
+ ExtendedErrorCodeSignatureNotYetValid
+ ExtendedErrorCodeDNSKEYMissing
+ ExtendedErrorCodeRRSIGsMissing
+ ExtendedErrorCodeNoZoneKeyBitSet
+ ExtendedErrorCodeNSECMissing
+ ExtendedErrorCodeCachedError
+ ExtendedErrorCodeNotReady
+ ExtendedErrorCodeBlocked
+ ExtendedErrorCodeCensored
+ ExtendedErrorCodeFiltered
+ ExtendedErrorCodeProhibited
+ ExtendedErrorCodeStaleNXDOMAINAnswer
+ ExtendedErrorCodeNotAuthoritative
+ ExtendedErrorCodeNotSupported
+ ExtendedErrorCodeNoReachableAuthority
+ ExtendedErrorCodeNetworkError
+ ExtendedErrorCodeInvalidData
+)
+
+// ExtendedErrorCodeToString maps extended error info codes to a human readable
+// description.
+var ExtendedErrorCodeToString = map[uint16]string{
+ ExtendedErrorCodeOther: "Other",
+ ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm",
+ ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type",
+ ExtendedErrorCodeStaleAnswer: "Stale Answer",
+ ExtendedErrorCodeForgedAnswer: "Forged Answer",
+ ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate",
+ ExtendedErrorCodeDNSBogus: "DNSSEC Bogus",
+ ExtendedErrorCodeSignatureExpired: "Signature Expired",
+ ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid",
+ ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing",
+ ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing",
+ ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set",
+ ExtendedErrorCodeNSECMissing: "NSEC Missing",
+ ExtendedErrorCodeCachedError: "Cached Error",
+ ExtendedErrorCodeNotReady: "Not Ready",
+ ExtendedErrorCodeBlocked: "Blocked",
+ ExtendedErrorCodeCensored: "Censored",
+ ExtendedErrorCodeFiltered: "Filtered",
+ ExtendedErrorCodeProhibited: "Prohibited",
+ ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer",
+ ExtendedErrorCodeNotAuthoritative: "Not Authoritative",
+ ExtendedErrorCodeNotSupported: "Not Supported",
+ ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority",
+ ExtendedErrorCodeNetworkError: "Network Error",
+ ExtendedErrorCodeInvalidData: "Invalid Data",
+}
+
+// StringToExtendedErrorCode is a map from human readable descriptions to
+// extended error info codes.
+var StringToExtendedErrorCode = reverseInt16(ExtendedErrorCodeToString)
+
+// EDNS0_EDE option is used to return additional information about the cause of
+// DNS errors.
+type EDNS0_EDE struct {
+ InfoCode uint16
+ ExtraText string
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_EDE) Option() uint16 { return EDNS0EDE }
+func (e *EDNS0_EDE) copy() EDNS0 { return &EDNS0_EDE{e.InfoCode, e.ExtraText} }
+
+func (e *EDNS0_EDE) String() string {
+ info := strconv.FormatUint(uint64(e.InfoCode), 10)
+ if s, ok := ExtendedErrorCodeToString[e.InfoCode]; ok {
+ info += fmt.Sprintf(" (%s)", s)
+ }
+ return fmt.Sprintf("%s: (%s)", info, e.ExtraText)
+}
+
+func (e *EDNS0_EDE) pack() ([]byte, error) {
+ b := make([]byte, 2+len(e.ExtraText))
+ binary.BigEndian.PutUint16(b[0:], e.InfoCode)
+ copy(b[2:], []byte(e.ExtraText))
+ return b, nil
+}
+
+func (e *EDNS0_EDE) unpack(b []byte) error {
+ if len(b) < 2 {
+ return ErrBuf
+ }
+ e.InfoCode = binary.BigEndian.Uint16(b[0:])
+ e.ExtraText = string(b[2:])
+ return nil
+}
diff --git a/msg_helpers.go b/msg_helpers.go
index 47625ed0..472ada5d 100644
--- a/msg_helpers.go
+++ b/msg_helpers.go
@@ -460,6 +460,8 @@ func makeDataOpt(code uint16) EDNS0 {
return new(EDNS0_N3U)
case EDNS0PADDING:
return new(EDNS0_PADDING)
+ case EDNS0EDE:
+ return new(EDNS0_EDE)
default:
e := new(EDNS0_LOCAL)
e.Code = code