1 #ifndef DNS_RRS_DOT_HPP
2 #define DNS_RRS_DOT_HPP
11 #include <netinet/in.h>
13 #include "iobuffer.hpp"
17 enum class RR_type
: uint16_t {
18 // RFC 1035 section 3.2.2 “TYPE values”
36 RP
, // RFC 1183 Responsible Person
37 AFSDB
, // RFC 1183 AFS database record
40 SIG
= 24, // RFC 2535 Signature
41 KEY
= 25, // RFC 2535 and RFC 2930 Key record
43 // RFC 3596 section 2.1 “AAAA record type”
46 // RFC 2782 Service locator
49 // RFC 4398 Certificate record
52 // RFC 6891 EDNS(0) OPT pseudo-RR
55 // RFC 4255 SSH Public Key Fingerprint
59 RRSIG
= 46, // DNSSEC signature
60 NSEC
= 47, // Next Secure record
61 DNSKEY
= 48, // DNS Key record
63 // RFC 6698 section 7.1 “TLSA RRtype”
67 constexpr char const* RR_type_c_str(RR_type type
)
69 switch (type
) { // clang-format off
70 case RR_type::NONE
: return "NONE";
71 case RR_type::A
: return "A";
72 case RR_type::NS
: return "NS";
73 case RR_type::MD
: return "MD";
74 case RR_type::MF
: return "MF";
75 case RR_type::CNAME
: return "CNAME";
76 case RR_type::SOA
: return "SOA";
77 case RR_type::MB
: return "MB";
78 case RR_type::MG
: return "MG";
79 case RR_type::MR
: return "MR";
80 case RR_type::RR_NULL
:return "RR_NULL";
81 case RR_type::WKS
: return "WKS";
82 case RR_type::PTR
: return "PTR";
83 case RR_type::HINFO
: return "HINFO";
84 case RR_type::MINFO
: return "MINFO";
85 case RR_type::MX
: return "MX";
86 case RR_type::TXT
: return "TXT";
87 case RR_type::RP
: return "RP";
88 case RR_type::AFSDB
: return "AFSDB";
89 case RR_type::SIG
: return "SIG";
90 case RR_type::KEY
: return "KEY";
91 case RR_type::AAAA
: return "AAAA";
92 case RR_type::SRV
: return "SRV";
93 case RR_type::CERT
: return "CERT";
94 case RR_type::OPT
: return "OPT";
95 case RR_type::SSHFP
: return "SSHFP";
96 case RR_type::RRSIG
: return "RRSIG";
97 case RR_type::NSEC
: return "NSEC";
98 case RR_type::DNSKEY
: return "DNSKEY";
99 case RR_type::TLSA
: return "TLSA";
101 return "*** unknown RR_type ***";
104 constexpr char const* RR_type_c_str(uint16_t rcode
)
106 return RR_type_c_str(static_cast<RR_type
>(rcode
));
109 constexpr char const* rcode_c_str(uint16_t rcode
)
111 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
112 switch (rcode
) { // clang-format off
113 case 0: return "no error"; // [RFC1035]
114 case 1: return "format error"; // [RFC1035]
115 case 2: return "server failure"; // [RFC1035]
116 case 3: return "non-existent domain"; // [RFC1035]
117 case 4: return "not implemented"; // [RFC1035]
118 case 5: return "query Refused"; // [RFC1035]
119 case 6: return "name exists when it should not"; // [RFC2136][RFC6672]
120 case 7: return "RR set exists when it should not"; // [RFC2136]
121 case 8: return "RR set that should exist does not"; // [RFC2136]
122 case 9: return "server not authoritative for zone or not authorized"; // [RFC2136 & RFC2845]
123 case 10: return "name not contained in zone"; // [RFC2136]
124 case 11: return "unassigned-11";
125 case 12: return "unassigned-12";
126 case 13: return "unassigned-13";
127 case 14: return "unassigned-14";
128 case 15: return "unassigned-15";
129 case 16: return "bad OPT version or TSIG signature failure"; // [RFC6891 & RFC2845]
130 case 17: return "key not recognized"; // [RFC2845]
131 case 18: return "signature out of time window"; // [RFC2845]
132 case 19: return "bad TKEY mode"; // [RFC2930]
133 case 20: return "duplicate key name"; // [RFC2930]
134 case 21: return "algorithm not supported"; // [RFC2930]
135 case 22: return "bad truncation"; // [RFC4635]
136 case 23: return "bad/missing server cookie"; // [RFC7873]
138 if ((24 <= rcode
) && (rcode
<= 3840)) {
139 return "unassigned-24-3840";
141 if ((3841 <= rcode
) && (rcode
<= 4095)) {
142 return "reserved for private use"; // [RFC6895]
144 if ((4096 <= rcode
) && (rcode
<= 65534)) {
145 return "unassigned-4096-65534";
147 if (rcode
== 65535) {
148 return "reserved-65535"; // [RFC6895]
150 return "*** rcode out of range ***";
155 RR_A(uint8_t const* rd
, size_t sz
);
157 std::optional
<std::string
> as_str() const { return std::string
{str_
}; }
159 sockaddr_in
const& addr() const { return addr_
; }
160 char const* c_str() const { return str_
; }
161 static RR_type
rr_type() { return RR_type::A
; }
163 bool operator==(RR_A
const& rhs
) const { return strcmp(str_
, rhs
.str_
) == 0; }
164 bool operator<(RR_A
const& rhs
) const { return strcmp(str_
, rhs
.str_
) < 0; }
168 char str_
[INET_ADDRSTRLEN
];
173 explicit RR_CNAME(std::string cname
)
178 std::optional
<std::string
> as_str() const { return str(); }
180 std::string
const& str() const { return cname_
; }
181 char const* c_str() const { return str().c_str(); }
182 static RR_type
rr_type() { return RR_type::CNAME
; }
184 bool operator==(RR_CNAME
const& rhs
) const { return str() == rhs
.str(); }
185 bool operator<(RR_CNAME
const& rhs
) const { return str() < rhs
.str(); }
191 // RFC 2181 section 10.2 PTR records
194 explicit RR_PTR(std::string ptrdname
)
195 : ptrdname_(ptrdname
)
199 std::optional
<std::string
> as_str() const { return str(); }
201 std::string
const& str() const { return ptrdname_
; }
202 char const* c_str() const { return str().c_str(); }
203 constexpr static RR_type
rr_type() { return RR_type::PTR
; }
205 bool operator==(RR_PTR
const& rhs
) const { return str() == rhs
.str(); }
206 bool operator<(RR_PTR
const& rhs
) const { return str() < rhs
.str(); }
209 std::string ptrdname_
;
214 RR_MX(std::string exchange
, uint16_t preference
)
215 : exchange_(exchange
)
216 , preference_(preference
)
220 std::optional
<std::string
> as_str() const { return exchange(); }
222 std::string
const& exchange() const { return exchange_
; }
223 uint16_t preference() const { return preference_
; }
225 static RR_type
rr_type() { return RR_type::MX
; }
227 bool operator==(RR_MX
const& rhs
) const
229 return (preference() == rhs
.preference()) && (exchange() == rhs
.exchange());
231 bool operator<(RR_MX
const& rhs
) const
233 if (preference() < rhs
.preference())
235 if (preference() == rhs
.preference())
236 return exchange() < rhs
.exchange();
241 std::string exchange_
;
242 uint16_t preference_
;
247 explicit RR_TXT(std::string txt_data
)
248 : txt_data_(txt_data
)
252 std::optional
<std::string
> as_str() const { return str(); }
254 char const* c_str() const { return str().c_str(); }
255 std::string
const& str() const { return txt_data_
; }
256 static RR_type
rr_type() { return RR_type::TXT
; }
258 bool operator==(RR_TXT
const& rhs
) const { return str() == rhs
.str(); }
259 bool operator<(RR_TXT
const& rhs
) const { return str() < rhs
.str(); }
262 std::string txt_data_
;
267 RR_AAAA(uint8_t const* rd
, size_t sz
);
269 std::optional
<std::string
> as_str() const { return std::string
{c_str()}; }
271 sockaddr_in6
const& addr() const { return addr_
; }
272 char const* c_str() const { return str_
; }
273 static RR_type
rr_type() { return RR_type::AAAA
; }
275 bool operator==(RR_AAAA
const& rhs
) const
277 return strcmp(c_str(), rhs
.c_str()) == 0;
279 bool operator<(RR_AAAA
const& rhs
) const
281 return strcmp(c_str(), rhs
.c_str()) < 0;
286 char str_
[INET6_ADDRSTRLEN
];
291 using octet
= unsigned char;
293 using container_t
= iobuffer
<octet
>;
295 RR_TLSA(uint8_t cert_usage
,
297 uint8_t matching_type
,
298 uint8_t const* assoc_data
,
299 size_t assoc_data_sz
);
300 unsigned cert_usage() const { return cert_usage_
; }
301 unsigned selector() const { return selector_
; }
302 unsigned matching_type() const { return matching_type_
; }
304 container_t
const& assoc_data() const { return assoc_data_
; }
306 // doesn't have a string representation
307 std::optional
<std::string
> as_str() const { return {}; }
309 static RR_type
rr_type() { return RR_type::TLSA
; }
311 bool operator==(RR_TLSA
const& rhs
) const
313 return (cert_usage() == rhs
.cert_usage()) && (selector() == rhs
.selector())
314 && (matching_type() == rhs
.matching_type())
315 && (assoc_data() == rhs
.assoc_data());
317 bool operator<(RR_TLSA
const& rhs
) const
319 return assoc_data() < rhs
.assoc_data();
323 container_t assoc_data_
;
326 uint8_t matching_type_
;
330 = std::variant
<RR_A
, RR_CNAME
, RR_PTR
, RR_MX
, RR_TXT
, RR_AAAA
, RR_TLSA
>;
332 using RR_collection
= std::vector
<RR
>;
336 #endif // DNS_RRS_DOT_HPP