1 #ifndef DNS_RRS_DOT_HPP
2 #define DNS_RRS_DOT_HPP
12 #include <netinet/in.h>
14 #include "iobuffer.hpp"
18 enum class RR_type
: uint16_t {
19 // RFC 1035 section 3.2.2 “TYPE values”
37 RP
, // RFC 1183 Responsible Person
38 AFSDB
, // RFC 1183 AFS database record
41 SIG
= 24, // RFC 2535 Signature
42 KEY
= 25, // RFC 2535 and RFC 2930 Key record
44 // RFC 3596 section 2.1 “AAAA record type”
47 // RFC 2782 Service locator
50 // RFC 4398 Certificate record
53 // RFC 6891 EDNS(0) OPT pseudo-RR
56 // RFC 4255 SSH Public Key Fingerprint
60 RRSIG
= 46, // DNSSEC signature
61 NSEC
= 47, // Next Secure record
62 DNSKEY
= 48, // DNS Key record
64 // RFC 6698 section 7.1 “TLSA RRtype”
68 constexpr char const* RR_type_c_str(RR_type type
)
70 switch (type
) { // clang-format off
71 case RR_type::NONE
: return "NONE";
72 case RR_type::A
: return "A";
73 case RR_type::NS
: return "NS";
74 case RR_type::MD
: return "MD";
75 case RR_type::MF
: return "MF";
76 case RR_type::CNAME
: return "CNAME";
77 case RR_type::SOA
: return "SOA";
78 case RR_type::MB
: return "MB";
79 case RR_type::MG
: return "MG";
80 case RR_type::MR
: return "MR";
81 case RR_type::RR_NULL
:return "RR_NULL";
82 case RR_type::WKS
: return "WKS";
83 case RR_type::PTR
: return "PTR";
84 case RR_type::HINFO
: return "HINFO";
85 case RR_type::MINFO
: return "MINFO";
86 case RR_type::MX
: return "MX";
87 case RR_type::TXT
: return "TXT";
88 case RR_type::RP
: return "RP";
89 case RR_type::AFSDB
: return "AFSDB";
90 case RR_type::SIG
: return "SIG";
91 case RR_type::KEY
: return "KEY";
92 case RR_type::AAAA
: return "AAAA";
93 case RR_type::SRV
: return "SRV";
94 case RR_type::CERT
: return "CERT";
95 case RR_type::OPT
: return "OPT";
96 case RR_type::SSHFP
: return "SSHFP";
97 case RR_type::RRSIG
: return "RRSIG";
98 case RR_type::NSEC
: return "NSEC";
99 case RR_type::DNSKEY
: return "DNSKEY";
100 case RR_type::TLSA
: return "TLSA";
102 return "*** unknown RR_type ***";
105 constexpr char const* RR_type_c_str(uint16_t rcode
)
107 return RR_type_c_str(static_cast<RR_type
>(rcode
));
110 constexpr char const* rcode_c_str(uint16_t rcode
)
112 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
113 switch (rcode
) { // clang-format off
114 case 0: return "no error"; // [RFC1035]
115 case 1: return "format error"; // [RFC1035]
116 case 2: return "server failure"; // [RFC1035]
117 case 3: return "non-existent domain"; // [RFC1035]
118 case 4: return "not implemented"; // [RFC1035]
119 case 5: return "query Refused"; // [RFC1035]
120 case 6: return "name exists when it should not"; // [RFC2136][RFC6672]
121 case 7: return "RR set exists when it should not"; // [RFC2136]
122 case 8: return "RR set that should exist does not"; // [RFC2136]
123 case 9: return "server not authoritative for zone or not authorized"; // [RFC2136 & RFC2845]
124 case 10: return "name not contained in zone"; // [RFC2136]
125 case 11: return "unassigned-11";
126 case 12: return "unassigned-12";
127 case 13: return "unassigned-13";
128 case 14: return "unassigned-14";
129 case 15: return "unassigned-15";
130 case 16: return "bad OPT version or TSIG signature failure"; // [RFC6891 & RFC2845]
131 case 17: return "key not recognized"; // [RFC2845]
132 case 18: return "signature out of time window"; // [RFC2845]
133 case 19: return "bad TKEY mode"; // [RFC2930]
134 case 20: return "duplicate key name"; // [RFC2930]
135 case 21: return "algorithm not supported"; // [RFC2930]
136 case 22: return "bad truncation"; // [RFC4635]
137 case 23: return "bad/missing server cookie"; // [RFC7873]
139 if ((24 <= rcode
) && (rcode
<= 3840)) {
140 return "unassigned-24-3840";
142 if ((3841 <= rcode
) && (rcode
<= 4095)) {
143 return "reserved for private use"; // [RFC6895]
145 if ((4096 <= rcode
) && (rcode
<= 65534)) {
146 return "unassigned-4096-65534";
148 if (rcode
== 65535) {
149 return "reserved-65535"; // [RFC6895]
151 return "*** rcode out of range ***";
156 RR_A(uint8_t const* rd
, size_t sz
);
158 std::optional
<std::string
> as_str() const { return std::string
{str_
}; }
160 sockaddr_in
const& addr() const { return addr_
; }
161 char const* c_str() const { return str_
; }
162 constexpr static RR_type
rr_type() { return RR_type::A
; }
164 bool operator==(RR_A
const& rhs
) const { return strcmp(str_
, rhs
.str_
) == 0; }
165 bool operator<(RR_A
const& rhs
) const { return strcmp(str_
, rhs
.str_
) < 0; }
169 char str_
[INET_ADDRSTRLEN
];
174 explicit RR_CNAME(std::string cname
)
179 std::optional
<std::string
> as_str() const { return str(); }
181 std::string
const& str() const { return cname_
; }
182 char const* c_str() const { return str().c_str(); }
183 constexpr static RR_type
rr_type() { return RR_type::CNAME
; }
185 bool operator==(RR_CNAME
const& rhs
) const { return str() == rhs
.str(); }
186 bool operator<(RR_CNAME
const& rhs
) const { return str() < rhs
.str(); }
192 // RFC 2181 section 10.2 PTR records
195 explicit RR_PTR(std::string ptrdname
)
196 : ptrdname_(ptrdname
)
200 std::optional
<std::string
> as_str() const { return str(); }
202 std::string
const& str() const { return ptrdname_
; }
203 char const* c_str() const { return str().c_str(); }
204 constexpr static RR_type
rr_type() { return RR_type::PTR
; }
206 bool operator==(RR_PTR
const& rhs
) const { return str() == rhs
.str(); }
207 bool operator<(RR_PTR
const& rhs
) const { return str() < rhs
.str(); }
210 std::string ptrdname_
;
215 RR_MX(std::string exchange
, uint16_t preference
)
216 : exchange_(exchange
)
217 , preference_(preference
)
221 std::optional
<std::string
> as_str() const { return exchange(); }
223 std::string
const& exchange() const { return exchange_
; }
224 uint16_t preference() const { return preference_
; }
226 constexpr static RR_type
rr_type() { return RR_type::MX
; }
228 bool operator==(RR_MX
const& rhs
) const
230 return (preference() == rhs
.preference()) && (exchange() == rhs
.exchange());
232 bool operator<(RR_MX
const& rhs
) const
234 if (preference() == rhs
.preference())
235 return exchange() < rhs
.exchange();
236 return preference() < rhs
.preference();
240 std::string exchange_
;
241 uint16_t preference_
;
246 explicit RR_TXT(std::string txt_data
)
247 : txt_data_(txt_data
)
251 std::optional
<std::string
> as_str() const { return str(); }
253 char const* c_str() const { return str().c_str(); }
254 std::string
const& str() const { return txt_data_
; }
255 constexpr static RR_type
rr_type() { return RR_type::TXT
; }
257 bool operator==(RR_TXT
const& rhs
) const { return str() == rhs
.str(); }
258 bool operator<(RR_TXT
const& rhs
) const { return str() < rhs
.str(); }
261 std::string txt_data_
;
266 RR_AAAA(uint8_t const* rd
, size_t sz
);
268 std::optional
<std::string
> as_str() const { return std::string
{c_str()}; }
270 sockaddr_in6
const& addr() const { return addr_
; }
271 char const* c_str() const { return str_
; }
272 constexpr static RR_type
rr_type() { return RR_type::AAAA
; }
274 bool operator==(RR_AAAA
const& rhs
) const
276 return strcmp(c_str(), rhs
.c_str()) == 0;
278 bool operator<(RR_AAAA
const& rhs
) const
280 return strcmp(c_str(), rhs
.c_str()) < 0;
285 char str_
[INET6_ADDRSTRLEN
];
290 using octet
= unsigned char;
291 using container_t
= iobuffer
<octet
>;
293 RR_TLSA(uint8_t cert_usage
,
295 uint8_t matching_type
,
296 std::span
<octet
const> data
);
297 unsigned cert_usage() const { return cert_usage_
; }
298 unsigned selector() const { return selector_
; }
299 unsigned matching_type() const { return matching_type_
; }
301 // container_t const& assoc_data() const { return assoc_data_; }
303 // doesn't have a string representation
304 std::optional
<std::string
> as_str() const { return {}; }
306 constexpr static RR_type
rr_type() { return RR_type::TLSA
; }
308 std::span
<octet
const> assoc_data() const
310 return {assoc_data_
.data(), assoc_data_
.size()};
313 bool operator==(RR_TLSA
const& rhs
) const
315 return (cert_usage() == rhs
.cert_usage()) &&
316 (selector() == rhs
.selector()) &&
317 (matching_type() == rhs
.matching_type()) &&
318 (assoc_data_
== rhs
.assoc_data_
);
320 bool operator<(RR_TLSA
const& rhs
) const
323 return assoc_data_
< rhs
.assoc_data_
;
328 container_t assoc_data_
;
331 uint8_t matching_type_
;
335 std::variant
<RR_A
, RR_CNAME
, RR_PTR
, RR_MX
, RR_TXT
, RR_AAAA
, RR_TLSA
>;
337 using RR_collection
= std::vector
<RR
>;
341 #endif // DNS_RRS_DOT_HPP