forgedns_proto/types.rs
1/*
2 * SPDX-FileCopyrightText: 2025 Sven Shi
3 * SPDX-License-Identifier: GPL-3.0-or-later
4 */
5
6//! DNS enums used by the owned message model.
7
8use crate::core::error::{DnsError, Result as DnsResult};
9use std::fmt;
10use std::fmt::{Display, Formatter};
11use std::str::FromStr;
12
13/// DNS message direction.
14#[derive(Debug, Eq, PartialEq, PartialOrd, Copy, Clone, Hash)]
15pub enum MessageType {
16 /// Query message sent by a client or intermediate resolver.
17 Query,
18 /// Response message sent back to the requester.
19 Response,
20}
21
22/// DNS operation code.
23#[derive(Debug, PartialEq, Eq, PartialOrd, Copy, Clone, Hash)]
24#[allow(dead_code)]
25pub enum Opcode {
26 /// Query request [RFC 1035](https://tools.ietf.org/html/rfc1035)
27 Query,
28
29 /// Inverse query (obsolete) [RFC 3425]
30 IQuery,
31
32 /// Status message [RFC 1035](https://tools.ietf.org/html/rfc1035)
33 Status,
34
35 /// Notify of change [RFC 1996](https://tools.ietf.org/html/rfc1996)
36 Notify,
37
38 /// Update message [RFC 2136](https://tools.ietf.org/html/rfc2136)
39 Update,
40
41 /// Any other opcode
42 Unknown(u8),
43}
44
45impl Display for Opcode {
46 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
47 match self {
48 Self::Query => f.write_str("QUERY"),
49 Self::IQuery => f.write_str("IQUERY"),
50 Self::Status => f.write_str("STATUS"),
51 Self::Notify => f.write_str("NOTIFY"),
52 Self::Update => f.write_str("UPDATE"),
53 Self::Unknown(opcode) => write!(f, "Unknown opcode ({opcode})"),
54 }
55 }
56}
57
58/// Convert from `OpCode` to `u8`
59impl From<Opcode> for u8 {
60 fn from(rt: Opcode) -> Self {
61 match rt {
62 Opcode::Query => 0,
63 Opcode::IQuery => 1,
64 // 1 IQuery (Inverse Query, OBSOLETE) [RFC3425]
65 Opcode::Status => 2,
66 // 3 Unassigned
67 Opcode::Notify => 4,
68 Opcode::Update => 5,
69 // 6-15 Unassigned
70 Opcode::Unknown(opcode) => opcode,
71 }
72 }
73}
74
75/// Convert from `u8` to `OpCode`
76impl From<u8> for Opcode {
77 fn from(value: u8) -> Self {
78 match value {
79 0 => Self::Query,
80 1 => Self::IQuery,
81 2 => Self::Status,
82 4 => Self::Notify,
83 5 => Self::Update,
84 _ => Self::Unknown(value),
85 }
86 }
87}
88
89#[derive(Debug, Eq, PartialEq, PartialOrd, Copy, Clone, Hash, Default)]
90#[allow(dead_code)]
91pub enum Rcode {
92 /// No Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
93 #[default]
94 NoError,
95
96 /// Format Error [RFC 1035](https://tools.ietf.org/html/rfc1035)
97 FormErr,
98
99 /// Server Failure [RFC 1035](https://tools.ietf.org/html/rfc1035)
100 ServFail,
101
102 /// Non-Existent Domain [RFC 1035](https://tools.ietf.org/html/rfc1035)
103 NXDomain,
104
105 /// Not Implemented [RFC 1035](https://tools.ietf.org/html/rfc1035)
106 NotImp,
107
108 /// Query Refused [RFC 1035](https://tools.ietf.org/html/rfc1035)
109 Refused,
110
111 /// Name Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
112 YXDomain,
113
114 /// RR Set Exists when it should not [RFC 2136](https://tools.ietf.org/html/rfc2136)
115 YXRRSet,
116
117 /// RR Set that should exist does not [RFC 2136](https://tools.ietf.org/html/rfc2136)
118 NXRRSet,
119
120 /// Server Not Authoritative for zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
121 /// or Not Authorized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
122 NotAuth,
123
124 /// Name not contained in zone [RFC 2136](https://tools.ietf.org/html/rfc2136)
125 NotZone,
126
127 /// Bad OPT Version [RFC 6891](https://tools.ietf.org/html/rfc6891#section-9)
128 BADVERS,
129
130 /// TSIG Signature Failure [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
131 BADSIG,
132
133 /// Key not recognized [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
134 BADKEY,
135
136 /// Signature out of time window [RFC 8945](https://www.rfc-editor.org/rfc/rfc8945)
137 BADTIME,
138
139 /// Bad TKEY Mode [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
140 BADMODE,
141
142 /// Duplicate key name [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
143 BADNAME,
144
145 /// Algorithm not supported [RFC 2930](https://tools.ietf.org/html/rfc2930#section-2.6)
146 BADALG,
147
148 /// Bad Truncation [RFC 4635](https://tools.ietf.org/html/rfc4635#section-4)
149 BADTRUNC,
150
151 /// Bad/missing Server Cookie [RFC 7873](https://datatracker.ietf.org/doc/html/rfc7873)
152 BADCOOKIE,
153 // 24-3840 Unassigned
154 // 3841-4095 Reserved for Private Use [RFC6895]
155 // 4096-65534 Unassigned
156 // 65535 Reserved, can be allocated by Standards Action [RFC6895]
157 /// An unknown or unregistered response code was received.
158 Unknown(u16),
159}
160
161impl Rcode {
162 #[inline]
163 pub fn value(self) -> u16 {
164 u16::from(self)
165 }
166
167 #[inline]
168 pub fn low(self) -> u8 {
169 match self {
170 Self::NoError => 0,
171 Self::FormErr => 1,
172 Self::ServFail => 2,
173 Self::NXDomain => 3,
174 Self::NotImp => 4,
175 Self::Refused => 5,
176 Self::YXDomain => 6,
177 Self::YXRRSet => 7,
178 Self::NXRRSet => 8,
179 Self::NotAuth => 9,
180 Self::NotZone => 10,
181 Self::BADVERS | Self::BADSIG => 0,
182 Self::BADKEY => 1,
183 Self::BADTIME => 2,
184 Self::BADMODE => 3,
185 Self::BADNAME => 4,
186 Self::BADALG => 5,
187 Self::BADTRUNC => 6,
188 Self::BADCOOKIE => 7,
189 Self::Unknown(code) => (code & 0x000f) as u8,
190 }
191 }
192
193 #[inline]
194 pub fn high(self) -> u8 {
195 match self {
196 Self::NoError
197 | Self::FormErr
198 | Self::ServFail
199 | Self::NXDomain
200 | Self::NotImp
201 | Self::Refused
202 | Self::YXDomain
203 | Self::YXRRSet
204 | Self::NXRRSet
205 | Self::NotAuth
206 | Self::NotZone => 0,
207 Self::BADVERS | Self::BADSIG => 1,
208 Self::BADKEY => 1,
209 Self::BADTIME => 1,
210 Self::BADMODE => 1,
211 Self::BADNAME => 1,
212 Self::BADALG => 1,
213 Self::BADTRUNC => 1,
214 Self::BADCOOKIE => 1,
215 Self::Unknown(code) => ((code >> 4) & 0x00ff) as u8,
216 }
217 }
218
219 #[inline]
220 pub fn has_extended_bits(self) -> bool {
221 self.high() != 0
222 }
223
224 #[inline]
225 pub fn from_parts(high: u8, low: u8) -> Self {
226 Self::from((u16::from(high) << 4) | u16::from(low & 0x0f))
227 }
228
229 /// Transforms the response code into the human message
230 pub fn to_str(self) -> &'static str {
231 match self {
232 Self::NoError => "No Error",
233 Self::FormErr => "Form Error", // 1 FormErr Format Error [RFC1035]
234 Self::ServFail => "Server Failure", // 2 ServFail Server Failure [RFC1035]
235 Self::NXDomain => "Non-Existent Domain", // 3 NXDomain Non-Existent Domain [RFC1035]
236 Self::NotImp => "Not Implemented", // 4 NotImp Not Implemented [RFC1035]
237 Self::Refused => "Query Refused", // 5 Refused Query Refused [RFC1035]
238 Self::YXDomain => "Name should not exist", // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
239 Self::YXRRSet => "RR Set should not exist", // 7 YXRRSet RR Set Exists when it should not [RFC2136]
240 Self::NXRRSet => "RR Set does not exist", // 8 NXRRSet RR Set that should exist does not [RFC2136]
241 Self::NotAuth => "Not authorized", // 9 NotAuth Server Not Authoritative for zone [RFC2136]
242 Self::NotZone => "Name not in zone", // 10 NotZone Name not contained in zone [RFC2136]
243 Self::BADVERS => "Bad OPT Version",
244 Self::BADSIG => "TSIG Signature Failure",
245 Self::BADKEY => "Key not recognized", // 17 BADKEY Key not recognized [RFC2845]
246 Self::BADTIME => "Signature out of time window", // 18 BADTIME Signature out of time window [RFC2845]
247 Self::BADMODE => "Bad TKEY mode", // 19 BADMODE Bad TKEY Mode [RFC2930]
248 Self::BADNAME => "Duplicate key name", // 20 BADNAME Duplicate key name [RFC2930]
249 Self::BADALG => "Algorithm not supported", // 21 BADALG Algorithm not supported [RFC2930]
250 Self::BADTRUNC => "Bad truncation", // 22 BADTRUNC Bad Truncation [RFC4635]
251 Self::BADCOOKIE => "Bad server cookie", // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
252 Self::Unknown(_) => "Unknown response code",
253 }
254 }
255}
256
257impl Display for Rcode {
258 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
259 f.write_str(self.to_str())
260 }
261}
262
263impl From<u16> for Rcode {
264 fn from(value: u16) -> Self {
265 match value {
266 0 => Self::NoError, // 0 NoError No Error [RFC1035]
267 1 => Self::FormErr, // 1 FormErr Format Error [RFC1035]
268 2 => Self::ServFail, // 2 ServFail Server Failure [RFC1035]
269 3 => Self::NXDomain, // 3 NXDomain Non-Existent Domain [RFC1035]
270 4 => Self::NotImp, // 4 NotImp Not Implemented [RFC1035]
271 5 => Self::Refused, // 5 Refused Query Refused [RFC1035]
272 6 => Self::YXDomain, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
273 7 => Self::YXRRSet, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
274 8 => Self::NXRRSet, // 8 NXRRSet RR Set that should exist does not [RFC2136]
275 9 => Self::NotAuth, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
276 10 => Self::NotZone, // 10 NotZone Name not contained in zone [RFC2136]
277 16 => Self::BADVERS, // 16 BADVERS/BADSIG context-dependent; default to EDNS BADVERS
278 17 => Self::BADKEY, // 17 BADKEY Key not recognized [RFC2845]
279 18 => Self::BADTIME, // 18 BADTIME Signature out of time window [RFC2845]
280 19 => Self::BADMODE, // 19 BADMODE Bad TKEY Mode [RFC2930]
281 20 => Self::BADNAME, // 20 BADNAME Duplicate key name [RFC2930]
282 21 => Self::BADALG, // 21 BADALG Algorithm not supported [RFC2930]
283 22 => Self::BADTRUNC, // 22 BADTRUNC Bad Truncation [RFC4635]
284 23 => Self::BADCOOKIE, // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
285 code => Self::Unknown(code),
286 }
287 }
288}
289
290impl From<Rcode> for u16 {
291 fn from(rt: Rcode) -> Self {
292 match rt {
293 Rcode::NoError => 0, // 0 NoError No Error [RFC1035]
294 Rcode::FormErr => 1, // 1 FormErr Format Error [RFC1035]
295 Rcode::ServFail => 2, // 2 ServFail Server Failure [RFC1035]
296 Rcode::NXDomain => 3, // 3 NXDomain Non-Existent Domain [RFC1035]
297 Rcode::NotImp => 4, // 4 NotImp Not Implemented [RFC1035]
298 Rcode::Refused => 5, // 5 Refused Query Refused [RFC1035]
299 Rcode::YXDomain => 6, // 6 YXDomain Name Exists when it should not [RFC2136][RFC6672]
300 Rcode::YXRRSet => 7, // 7 YXRRSet RR Set Exists when it should not [RFC2136]
301 Rcode::NXRRSet => 8, // 8 NXRRSet RR Set that should exist does not [RFC2136]
302 Rcode::NotAuth => 9, // 9 NotAuth Server Not Authoritative for zone [RFC2136]
303 Rcode::NotZone => 10, // 10 NotZone Name not contained in zone [RFC2136]
304 //
305 // 11-15 Unassigned
306 //
307 // 16 BADVERS Bad OPT Version [RFC6891]
308 // 16 BADSIG TSIG Signature Failure [RFC2845]
309 Rcode::BADVERS | Rcode::BADSIG => 16,
310 Rcode::BADKEY => 17, // 17 BADKEY Key not recognized [RFC2845]
311 Rcode::BADTIME => 18, // 18 BADTIME Signature out of time window [RFC2845]
312 Rcode::BADMODE => 19, // 19 BADMODE Bad TKEY Mode [RFC2930]
313 Rcode::BADNAME => 20, // 20 BADNAME Duplicate key name [RFC2930]
314 Rcode::BADALG => 21, // 21 BADALG Algorithm not supported [RFC2930]
315 Rcode::BADTRUNC => 22, // 22 BADTRUNC Bad Truncation [RFC4635]
316 Rcode::BADCOOKIE => 23, // 23 BADCOOKIE Bad/missing Server Cookie [RFC7873]
317 Rcode::Unknown(code) => code,
318 }
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::Rcode;
325
326 #[test]
327 fn rcode_parts_roundtrip_matches_known_layout() {
328 assert_eq!(Rcode::NoError.low(), 0);
329 assert_eq!(Rcode::NoError.high(), 0);
330 assert!(!Rcode::NoError.has_extended_bits());
331
332 assert_eq!(Rcode::BADVERS.low(), 0);
333 assert_eq!(Rcode::BADVERS.high(), 1);
334 assert!(Rcode::BADVERS.has_extended_bits());
335
336 assert_eq!(Rcode::Unknown(0x03af).low(), 0x0f);
337 assert_eq!(Rcode::Unknown(0x03af).high(), 0x3a);
338 assert_eq!(Rcode::from_parts(0x3a, 0x0f), Rcode::Unknown(0x03af));
339 assert_eq!(Rcode::from_parts(1, 0), Rcode::BADVERS);
340 }
341}
342
343/// DNS class values supported by ForgeDNS.
344#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
345#[allow(dead_code)]
346pub enum DNSClass {
347 /// Internet
348 IN,
349 /// CSNET
350 CS,
351 /// Chaos
352 CH,
353 /// Hesiod
354 HS,
355 /// QCLASS NONE
356 NONE,
357 /// QCLASS * (ANY)
358 ANY,
359 /// Special class for OPT Version, it was overloaded for EDNS - RFC 6891
360 /// From the RFC: `Values lower than 512 MUST be treated as equal to 512`
361 OPT(u16),
362 /// Unknown DNSClass was parsed
363 Unknown(u16),
364}
365
366impl FromStr for DNSClass {
367 type Err = DnsError;
368
369 fn from_str(str: &str) -> DnsResult<Self> {
370 debug_assert!(str.chars().all(|x| !char::is_ascii_lowercase(&x)));
371 match str {
372 "IN" => Ok(Self::IN),
373 "CS" => Ok(Self::CS),
374 "CH" => Ok(Self::CH),
375 "HS" => Ok(Self::HS),
376 "NONE" => Ok(Self::NONE),
377 "ANY" | "*" => Ok(Self::ANY),
378 _ => Err(DnsError::UnknownDnsClassStr(str.to_string())),
379 }
380 }
381}
382impl From<u16> for DNSClass {
383 fn from(value: u16) -> Self {
384 match value {
385 1 => Self::IN,
386 2 => Self::CS,
387 3 => Self::CH,
388 4 => Self::HS,
389 254 => Self::NONE,
390 255 => Self::ANY,
391 _ => Self::Unknown(value),
392 }
393 }
394}
395
396impl From<DNSClass> for u16 {
397 fn from(rt: DNSClass) -> Self {
398 match rt {
399 DNSClass::IN => 1,
400 DNSClass::CS => 2,
401 DNSClass::CH => 3,
402 DNSClass::HS => 4,
403 DNSClass::NONE => 254,
404 DNSClass::ANY => 255,
405 // see https://tools.ietf.org/html/rfc6891#section-6.1.2
406 DNSClass::OPT(max_payload_len) => max_payload_len.max(512),
407 DNSClass::Unknown(unknown) => unknown,
408 }
409 }
410}
411
412impl DNSClass {
413 /// Return the OPT version from value
414 pub fn for_opt(value: u16) -> Self {
415 // From RFC 6891: `Values lower than 512 MUST be treated as equal to 512`
416 let value = value.max(512);
417 Self::OPT(value)
418 }
419}
420
421/// Convert from `DNSClass` to `&str`
422impl From<DNSClass> for &'static str {
423 fn from(rt: DNSClass) -> &'static str {
424 match rt {
425 DNSClass::IN => "IN",
426 DNSClass::CS => "CS",
427 DNSClass::CH => "CH",
428 DNSClass::HS => "HS",
429 DNSClass::NONE => "NONE",
430 DNSClass::ANY => "ANY",
431 DNSClass::OPT(_) => "OPT",
432 DNSClass::Unknown(..) => "UNKNOWN",
433 }
434 }
435}
436impl Display for DNSClass {
437 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
438 f.write_str(Into::<&str>::into(*self))
439 }
440}
441
442/// The type of the resource record.
443///
444/// This specifies the type of data in the RData field of the Resource Record
445#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
446#[allow(dead_code)]
447pub enum RecordType {
448 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) IPv4 Address record
449 A,
450 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Name server record
451 NS,
452 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail destination record (obsolete)
453 MD,
454 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail forwarder record (obsolete)
455 MF,
456 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Canonical name record
457 CNAME,
458 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) and [RFC 2308](https://tools.ietf.org/html/rfc2308) Start of [a zone of] authority record
459 SOA,
460 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mailbox domain name (experimental)
461 MB,
462 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail group member (experimental)
463 MG,
464 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail rename domain name (experimental)
465 MR,
466 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Null server record, for testing
467 NULL,
468 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Well-known services
469 WKS,
470 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Pointer record
471 PTR,
472 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) host information
473 HINFO,
474 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mailbox or mail list information
475 MINFO,
476 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail exchange record
477 MX,
478 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Text record
479 TXT,
480 /// [RFC 1183](https://tools.ietf.org/html/rfc1183) Responsible person
481 RP,
482 /// [RFC 1183](https://tools.ietf.org/html/rfc1183) AFS database server
483 AFSDB,
484 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) X.25 PSDN address
485 X25,
486 /// [RFC 1706](https://tools.ietf.org/html/rfc1706) NSAP address
487 NSAP,
488 /// [RFC 1183](https://tools.ietf.org/html/rfc1183) ISDN address
489 ISDN,
490 /// [RFC 1183](https://tools.ietf.org/html/rfc1183) Route through record
491 RT,
492 /// [RFC 2673](https://tools.ietf.org/html/rfc2673) Endpoint identifier
493 EID,
494 /// [RFC 2673](https://tools.ietf.org/html/rfc2673) Nimrod locator
495 NIMLOC,
496 /// [RFC 1706](https://tools.ietf.org/html/rfc1706) NSAP-PTR record
497 NSAPPTR,
498 /// [RFC 2535](https://tools.ietf.org/html/rfc2535) (and [RFC 2931](https://tools.ietf.org/html/rfc2931)) Signature, to support [RFC 2137](https://tools.ietf.org/html/rfc2137) Update
499 SIG,
500 /// [RFC 2535](https://tools.ietf.org/html/rfc2535) and [RFC 2930](https://tools.ietf.org/html/rfc2930) Key record
501 KEY,
502 /// [RFC 2163](https://tools.ietf.org/html/rfc2163) X.400 mail mapping
503 PX,
504 /// [RFC 1712](https://tools.ietf.org/html/rfc1712) Geographical position
505 GPOS,
506 /// [RFC 3596](https://tools.ietf.org/html/rfc3596) IPv6 address record
507 AAAA,
508 /// [RFC 1876](https://tools.ietf.org/html/rfc1876) Location record
509 LOC,
510 /// [RFC 2535](https://tools.ietf.org/html/rfc2535) Next domain record (obsolete)
511 NXT,
512 /// [RFC 2672](https://tools.ietf.org/html/rfc2672) Service locator
513 SRV,
514 /// [RFC 3403](https://tools.ietf.org/html/rfc3403) Naming Authority Pointer
515 NAPTR,
516 /// [RFC 2230](https://tools.ietf.org/html/rfc2230) Key exchanger
517 KX,
518 /// [RFC 4398](https://tools.ietf.org/html/rfc4398) Storing Certificates in the Domain Name System (DNS)
519 CERT,
520 /// [RFC 2648](https://tools.ietf.org/html/rfc2648) ATM address
521 ATMA,
522 /// [RFC 2874](https://tools.ietf.org/html/rfc2874) A6 IPv6 address (historic)
523 A6,
524 /// [RFC 2535](https://tools.ietf.org/html/rfc2535) Kitchen sink (obsolete)
525 SINK,
526 /// [RFC 6672](https://tools.ietf.org/html/rfc6672) Delegation name
527 DNAME,
528 /// [RFC 6891](https://tools.ietf.org/html/rfc6891) Option
529 OPT,
530 /// [RFC 3123](https://tools.ietf.org/html/rfc3123) Address Prefix List
531 APL,
532 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) Delegation signer
533 DS,
534 /// [RFC 4255](https://tools.ietf.org/html/rfc4255) SSH Public Key Fingerprint
535 SSHFP,
536 /// [RFC 4025](https://tools.ietf.org/html/rfc4025) IPsec Key
537 IPSECKEY,
538 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) DNSSEC signature
539 RRSIG,
540 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) Next-Secure record
541 NSEC,
542 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) DNS Key record
543 DNSKEY,
544 /// [RFC 4701](https://tools.ietf.org/html/rfc4701) DHCP identifier
545 DHCID,
546 /// [RFC 5155](https://tools.ietf.org/html/rfc5155) NSEC record version 3
547 NSEC3,
548 /// [RFC 5155](https://tools.ietf.org/html/rfc5155) NSEC3 parameters
549 NSEC3PARAM,
550 /// [RFC 6698](https://tools.ietf.org/html/rfc6698) TLSA certificate association
551 TLSA,
552 /// [RFC 8162](https://tools.ietf.org/html/rfc8162) S/MIME cert association
553 SMIMEA,
554 /// [RFC 5205](https://tools.ietf.org/html/rfc5205) Host Identity Protocol
555 HIP,
556 /// [RFC 3755](https://tools.ietf.org/html/rfc3755) no implementation
557 NINFO,
558 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) reserved key record
559 RKEY,
560 /// [RFC 4034](https://tools.ietf.org/html/rfc4034) trust anchor linkage
561 TALINK,
562 /// [RFC 7344](https://tools.ietf.org/html/rfc7344) Child DS
563 CDS,
564 /// [RFC 7344](https://tools.ietf.org/html/rfc7344) Child DNSKEY
565 CDNSKEY,
566 /// [RFC 7929](https://tools.ietf.org/html/rfc7929) OpenPGP public key
567 OPENPGPKEY,
568 /// [RFC 7477](https://tools.ietf.org/html/rfc7477) Child-to-parent synchronization record
569 CSYNC,
570 /// [RFC 8976](https://tools.ietf.org/html/rfc8976) Message digest for DNS zones
571 ZONEMD,
572 /// [RFC 9460](https://tools.ietf.org/html/rfc9460) DNS SVCB and HTTPS RRs
573 SVCB,
574 /// [RFC 9460](https://tools.ietf.org/html/rfc9460) DNS SVCB and HTTPS RRs
575 HTTPS,
576 /// [RFC 7208](https://tools.ietf.org/html/rfc7208) Sender Policy Framework
577 SPF,
578 /// [RFC 1712](https://tools.ietf.org/html/rfc1712) User information
579 UINFO,
580 /// [RFC 1712](https://tools.ietf.org/html/rfc1712) User ID
581 UID,
582 /// [RFC 1712](https://tools.ietf.org/html/rfc1712) Group ID
583 GID,
584 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Binary unspecified payload
585 UNSPEC,
586 /// [RFC 6742](https://tools.ietf.org/html/rfc6742) ILNP node identifier
587 NID,
588 /// [RFC 6742](https://tools.ietf.org/html/rfc6742) ILNP 32-bit locator
589 L32,
590 /// [RFC 6742](https://tools.ietf.org/html/rfc6742) ILNP 64-bit locator
591 L64,
592 /// [RFC 6742](https://tools.ietf.org/html/rfc6742) ILNP locator pointer
593 LP,
594 /// [RFC 7043](https://tools.ietf.org/html/rfc7043) EUI-48 address
595 EUI48,
596 /// [RFC 7043](https://tools.ietf.org/html/rfc7043) EUI-64 address
597 EUI64,
598 /// [draft-ietf-dnsop-aname](https://tools.ietf.org/html/draft-ietf-dnsop-aname-04) ANAME pseudo-record
599 ANAME,
600 /// [RFC 7553](https://tools.ietf.org/html/rfc7553) URI record
601 URI,
602 /// [RFC 6844](https://tools.ietf.org/html/rfc6844) Certification Authority Authorization
603 CAA,
604 /// [RFC 6844](https://tools.ietf.org/html/rfc6844) Application visibility and control
605 AVC,
606 /// [RFC 8490](https://tools.ietf.org/html/rfc8490) Digital object architecture
607 DOA,
608 /// [RFC 8777](https://tools.ietf.org/html/rfc8777) Automatic multicast tunneling relay
609 AMTRELAY,
610 /// [RFC 9606](https://tools.ietf.org/html/rfc9606) Resolver information
611 RESINFO,
612 /// [RFC 2930](https://tools.ietf.org/html/rfc2930) Secret key record
613 TKEY,
614 /// [RFC 8945](https://tools.ietf.org/html/rfc8945) Transaction Signature
615 TSIG,
616 /// [RFC 1995](https://tools.ietf.org/html/rfc1995) Incremental Zone Transfer
617 IXFR,
618 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Authoritative Zone Transfer
619 AXFR,
620 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mailbox-related records (obsolete)
621 MAILB,
622 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Mail agent records (obsolete)
623 MAILA,
624 /// [RFC 1035](https://tools.ietf.org/html/rfc1035) All cached records, aka ANY
625 ANY,
626 /// [RFC 6895](https://www.rfc-editor.org/rfc/rfc6895) DNSSEC trust anchor
627 TA,
628 /// [RFC 4431](https://tools.ietf.org/html/rfc4431) DNSSEC lookaside validation
629 DLV,
630 /// Unknown Record type, or unsupported
631 Unknown(u16),
632
633 /// This corresponds to a record type of 0, unspecified
634 ZERO,
635}
636
637impl From<u16> for RecordType {
638 /// Convert from `u16` to `RecordType`
639 fn from(value: u16) -> Self {
640 match value {
641 0 => Self::ZERO,
642 1 => Self::A,
643 2 => Self::NS,
644 3 => Self::MD,
645 4 => Self::MF,
646 5 => Self::CNAME,
647 6 => Self::SOA,
648 7 => Self::MB,
649 8 => Self::MG,
650 9 => Self::MR,
651 10 => Self::NULL,
652 11 => Self::WKS,
653 12 => Self::PTR,
654 13 => Self::HINFO,
655 14 => Self::MINFO,
656 15 => Self::MX,
657 16 => Self::TXT,
658 17 => Self::RP,
659 18 => Self::AFSDB,
660 19 => Self::X25,
661 22 => Self::NSAP,
662 20 => Self::ISDN,
663 21 => Self::RT,
664 31 => Self::EID,
665 32 => Self::NIMLOC,
666 23 => Self::NSAPPTR,
667 24 => Self::SIG,
668 25 => Self::KEY,
669 26 => Self::PX,
670 27 => Self::GPOS,
671 28 => Self::AAAA,
672 29 => Self::LOC,
673 30 => Self::NXT,
674 33 => Self::SRV,
675 35 => Self::NAPTR,
676 36 => Self::KX,
677 37 => Self::CERT,
678 34 => Self::ATMA,
679 38 => Self::A6,
680 40 => Self::SINK,
681 39 => Self::DNAME,
682 41 => Self::OPT,
683 42 => Self::APL,
684 43 => Self::DS,
685 44 => Self::SSHFP,
686 45 => Self::IPSECKEY,
687 46 => Self::RRSIG,
688 47 => Self::NSEC,
689 48 => Self::DNSKEY,
690 49 => Self::DHCID,
691 50 => Self::NSEC3,
692 51 => Self::NSEC3PARAM,
693 52 => Self::TLSA,
694 53 => Self::SMIMEA,
695 55 => Self::HIP,
696 56 => Self::NINFO,
697 57 => Self::RKEY,
698 58 => Self::TALINK,
699 59 => Self::CDS,
700 60 => Self::CDNSKEY,
701 61 => Self::OPENPGPKEY,
702 62 => Self::CSYNC,
703 63 => Self::ZONEMD,
704 64 => Self::SVCB,
705 65 => Self::HTTPS,
706 99 => Self::SPF,
707 100 => Self::UINFO,
708 101 => Self::UID,
709 102 => Self::GID,
710 103 => Self::UNSPEC,
711 104 => Self::NID,
712 105 => Self::L32,
713 106 => Self::L64,
714 107 => Self::LP,
715 108 => Self::EUI48,
716 109 => Self::EUI64,
717 249 => Self::TKEY,
718 250 => Self::TSIG,
719 251 => Self::IXFR,
720 252 => Self::AXFR,
721 253 => Self::MAILB,
722 254 => Self::MAILA,
723 255 => Self::ANY,
724 256 => Self::URI,
725 257 => Self::CAA,
726 258 => Self::AVC,
727 259 => Self::DOA,
728 260 => Self::AMTRELAY,
729 261 => Self::RESINFO,
730 32768 => Self::TA,
731 32769 => Self::DLV,
732 65305 => Self::ANAME,
733 _ => Self::Unknown(value),
734 }
735 }
736}
737impl From<RecordType> for u16 {
738 fn from(rt: RecordType) -> Self {
739 match rt {
740 RecordType::A => 1,
741 RecordType::NS => 2,
742 RecordType::MD => 3,
743 RecordType::MF => 4,
744 RecordType::CNAME => 5,
745 RecordType::SOA => 6,
746 RecordType::MB => 7,
747 RecordType::MG => 8,
748 RecordType::MR => 9,
749 RecordType::NULL => 10,
750 RecordType::WKS => 11,
751 RecordType::PTR => 12,
752 RecordType::HINFO => 13,
753 RecordType::MINFO => 14,
754 RecordType::MX => 15,
755 RecordType::TXT => 16,
756 RecordType::RP => 17,
757 RecordType::AFSDB => 18,
758 RecordType::X25 => 19,
759 RecordType::NSAP => 22,
760 RecordType::ISDN => 20,
761 RecordType::RT => 21,
762 RecordType::EID => 31,
763 RecordType::NIMLOC => 32,
764 RecordType::NSAPPTR => 23,
765 RecordType::SIG => 24,
766 RecordType::KEY => 25,
767 RecordType::PX => 26,
768 RecordType::GPOS => 27,
769 RecordType::AAAA => 28,
770 RecordType::LOC => 29,
771 RecordType::NXT => 30,
772 RecordType::SRV => 33,
773 RecordType::NAPTR => 35,
774 RecordType::KX => 36,
775 RecordType::CERT => 37,
776 RecordType::ATMA => 34,
777 RecordType::A6 => 38,
778 RecordType::SINK => 40,
779 RecordType::DNAME => 39,
780 RecordType::OPT => 41,
781 RecordType::APL => 42,
782 RecordType::DS => 43,
783 RecordType::SSHFP => 44,
784 RecordType::IPSECKEY => 45,
785 RecordType::RRSIG => 46,
786 RecordType::NSEC => 47,
787 RecordType::DNSKEY => 48,
788 RecordType::DHCID => 49,
789 RecordType::NSEC3 => 50,
790 RecordType::NSEC3PARAM => 51,
791 RecordType::TLSA => 52,
792 RecordType::SMIMEA => 53,
793 RecordType::HIP => 55,
794 RecordType::NINFO => 56,
795 RecordType::RKEY => 57,
796 RecordType::TALINK => 58,
797 RecordType::CDS => 59,
798 RecordType::CDNSKEY => 60,
799 RecordType::OPENPGPKEY => 61,
800 RecordType::CSYNC => 62,
801 RecordType::ZONEMD => 63,
802 RecordType::SVCB => 64,
803 RecordType::HTTPS => 65,
804 RecordType::SPF => 99,
805 RecordType::UINFO => 100,
806 RecordType::UID => 101,
807 RecordType::GID => 102,
808 RecordType::UNSPEC => 103,
809 RecordType::NID => 104,
810 RecordType::L32 => 105,
811 RecordType::L64 => 106,
812 RecordType::LP => 107,
813 RecordType::EUI48 => 108,
814 RecordType::EUI64 => 109,
815 RecordType::ANAME => 65305,
816 RecordType::URI => 256,
817 RecordType::CAA => 257,
818 RecordType::AVC => 258,
819 RecordType::DOA => 259,
820 RecordType::AMTRELAY => 260,
821 RecordType::RESINFO => 261,
822 RecordType::TKEY => 249,
823 RecordType::TSIG => 250,
824 RecordType::IXFR => 251,
825 RecordType::AXFR => 252,
826 RecordType::MAILB => 253,
827 RecordType::MAILA => 254,
828 RecordType::ANY => 255,
829 RecordType::TA => 32768,
830 RecordType::DLV => 32769,
831 RecordType::ZERO => 0,
832 RecordType::Unknown(code) => code,
833 }
834 }
835}
836
837impl FromStr for RecordType {
838 type Err = DnsError;
839
840 /// Convert `&str` to `RecordType`
841 fn from_str(str: &str) -> DnsResult<Self> {
842 match str {
843 "A" => Ok(Self::A),
844 "NS" => Ok(Self::NS),
845 "MD" => Ok(Self::MD),
846 "MF" => Ok(Self::MF),
847 "CNAME" => Ok(Self::CNAME),
848 "SOA" => Ok(Self::SOA),
849 "MB" => Ok(Self::MB),
850 "MG" => Ok(Self::MG),
851 "MR" => Ok(Self::MR),
852 "NULL" => Ok(Self::NULL),
853 "WKS" => Ok(Self::WKS),
854 "PTR" => Ok(Self::PTR),
855 "HINFO" => Ok(Self::HINFO),
856 "MINFO" => Ok(Self::MINFO),
857 "MX" => Ok(Self::MX),
858 "TXT" => Ok(Self::TXT),
859 "RP" => Ok(Self::RP),
860 "AFSDB" => Ok(Self::AFSDB),
861 "X25" => Ok(Self::X25),
862 "NSAP" => Ok(Self::NSAP),
863 "ISDN" => Ok(Self::ISDN),
864 "RT" => Ok(Self::RT),
865 "EID" => Ok(Self::EID),
866 "NIMLOC" => Ok(Self::NIMLOC),
867 "NSAPPTR" => Ok(Self::NSAPPTR),
868 "SIG" => Ok(Self::SIG),
869 "KEY" => Ok(Self::KEY),
870 "PX" => Ok(Self::PX),
871 "GPOS" => Ok(Self::GPOS),
872 "AAAA" => Ok(Self::AAAA),
873 "LOC" => Ok(Self::LOC),
874 "NXT" => Ok(Self::NXT),
875 "SRV" => Ok(Self::SRV),
876 "NAPTR" => Ok(Self::NAPTR),
877 "KX" => Ok(Self::KX),
878 "CERT" => Ok(Self::CERT),
879 "ATMA" => Ok(Self::ATMA),
880 "A6" => Ok(Self::A6),
881 "SINK" => Ok(Self::SINK),
882 "DNAME" => Ok(Self::DNAME),
883 "OPT" => Ok(Self::OPT),
884 "APL" => Ok(Self::APL),
885 "DS" => Ok(Self::DS),
886 "SSHFP" => Ok(Self::SSHFP),
887 "IPSECKEY" => Ok(Self::IPSECKEY),
888 "RRSIG" => Ok(Self::RRSIG),
889 "NSEC" => Ok(Self::NSEC),
890 "DNSKEY" => Ok(Self::DNSKEY),
891 "DHCID" => Ok(Self::DHCID),
892 "NSEC3" => Ok(Self::NSEC3),
893 "NSEC3PARAM" => Ok(Self::NSEC3PARAM),
894 "TLSA" => Ok(Self::TLSA),
895 "SMIMEA" => Ok(Self::SMIMEA),
896 "HIP" => Ok(Self::HIP),
897 "NINFO" => Ok(Self::NINFO),
898 "RKEY" => Ok(Self::RKEY),
899 "TALINK" => Ok(Self::TALINK),
900 "CDS" => Ok(Self::CDS),
901 "CDNSKEY" => Ok(Self::CDNSKEY),
902 "OPENPGPKEY" => Ok(Self::OPENPGPKEY),
903 "CSYNC" => Ok(Self::CSYNC),
904 "ZONEMD" => Ok(Self::ZONEMD),
905 "SVCB" => Ok(Self::SVCB),
906 "HTTPS" => Ok(Self::HTTPS),
907 "SPF" => Ok(Self::SPF),
908 "UINFO" => Ok(Self::UINFO),
909 "UID" => Ok(Self::UID),
910 "GID" => Ok(Self::GID),
911 "UNSPEC" => Ok(Self::UNSPEC),
912 "NID" => Ok(Self::NID),
913 "L32" => Ok(Self::L32),
914 "L64" => Ok(Self::L64),
915 "LP" => Ok(Self::LP),
916 "EUI48" => Ok(Self::EUI48),
917 "EUI64" => Ok(Self::EUI64),
918 "ANAME" => Ok(Self::ANAME),
919 "URI" => Ok(Self::URI),
920 "CAA" => Ok(Self::CAA),
921 "AVC" => Ok(Self::AVC),
922 "DOA" => Ok(Self::DOA),
923 "AMTRELAY" => Ok(Self::AMTRELAY),
924 "RESINFO" => Ok(Self::RESINFO),
925 "TKEY" => Ok(Self::TKEY),
926 "TSIG" => Ok(Self::TSIG),
927 "IXFR" => Ok(Self::IXFR),
928 "AXFR" => Ok(Self::AXFR),
929 "MAILB" => Ok(Self::MAILB),
930 "MAILA" => Ok(Self::MAILA),
931 "ANY" | "*" => Ok(Self::ANY),
932 "TA" => Ok(Self::TA),
933 "DLV" => Ok(Self::DLV),
934 _ => Err(DnsError::UnknownRecordTypeStr(str.to_string())),
935 }
936 }
937}
938
939/// Convert from `RecordType` to `&str`
940impl From<RecordType> for &'static str {
941 fn from(rt: RecordType) -> &'static str {
942 match rt {
943 RecordType::A => "A",
944 RecordType::NS => "NS",
945 RecordType::MD => "MD",
946 RecordType::MF => "MF",
947 RecordType::CNAME => "CNAME",
948 RecordType::SOA => "SOA",
949 RecordType::MB => "MB",
950 RecordType::MG => "MG",
951 RecordType::MR => "MR",
952 RecordType::NULL => "NULL",
953 RecordType::WKS => "WKS",
954 RecordType::PTR => "PTR",
955 RecordType::HINFO => "HINFO",
956 RecordType::MINFO => "MINFO",
957 RecordType::MX => "MX",
958 RecordType::TXT => "TXT",
959 RecordType::RP => "RP",
960 RecordType::AFSDB => "AFSDB",
961 RecordType::X25 => "X25",
962 RecordType::NSAP => "NSAP",
963 RecordType::ISDN => "ISDN",
964 RecordType::RT => "RT",
965 RecordType::EID => "EID",
966 RecordType::NIMLOC => "NIMLOC",
967 RecordType::NSAPPTR => "NSAPPTR",
968 RecordType::SIG => "SIG",
969 RecordType::KEY => "KEY",
970 RecordType::PX => "PX",
971 RecordType::GPOS => "GPOS",
972 RecordType::AAAA => "AAAA",
973 RecordType::LOC => "LOC",
974 RecordType::NXT => "NXT",
975 RecordType::SRV => "SRV",
976 RecordType::NAPTR => "NAPTR",
977 RecordType::KX => "KX",
978 RecordType::CERT => "CERT",
979 RecordType::ATMA => "ATMA",
980 RecordType::A6 => "A6",
981 RecordType::SINK => "SINK",
982 RecordType::DNAME => "DNAME",
983 RecordType::OPT => "OPT",
984 RecordType::APL => "APL",
985 RecordType::DS => "DS",
986 RecordType::SSHFP => "SSHFP",
987 RecordType::IPSECKEY => "IPSECKEY",
988 RecordType::RRSIG => "RRSIG",
989 RecordType::NSEC => "NSEC",
990 RecordType::DNSKEY => "DNSKEY",
991 RecordType::DHCID => "DHCID",
992 RecordType::NSEC3 => "NSEC3",
993 RecordType::NSEC3PARAM => "NSEC3PARAM",
994 RecordType::TLSA => "TLSA",
995 RecordType::SMIMEA => "SMIMEA",
996 RecordType::HIP => "HIP",
997 RecordType::NINFO => "NINFO",
998 RecordType::RKEY => "RKEY",
999 RecordType::TALINK => "TALINK",
1000 RecordType::CDS => "CDS",
1001 RecordType::CDNSKEY => "CDNSKEY",
1002 RecordType::OPENPGPKEY => "OPENPGPKEY",
1003 RecordType::CSYNC => "CSYNC",
1004 RecordType::ZONEMD => "ZONEMD",
1005 RecordType::SVCB => "SVCB",
1006 RecordType::HTTPS => "HTTPS",
1007 RecordType::SPF => "SPF",
1008 RecordType::UINFO => "UINFO",
1009 RecordType::UID => "UID",
1010 RecordType::GID => "GID",
1011 RecordType::UNSPEC => "UNSPEC",
1012 RecordType::NID => "NID",
1013 RecordType::L32 => "L32",
1014 RecordType::L64 => "L64",
1015 RecordType::LP => "LP",
1016 RecordType::EUI48 => "EUI48",
1017 RecordType::EUI64 => "EUI64",
1018 RecordType::ANAME => "ANAME",
1019 RecordType::URI => "URI",
1020 RecordType::CAA => "CAA",
1021 RecordType::AVC => "AVC",
1022 RecordType::DOA => "DOA",
1023 RecordType::AMTRELAY => "AMTRELAY",
1024 RecordType::RESINFO => "RESINFO",
1025 RecordType::TKEY => "TKEY",
1026 RecordType::TSIG => "TSIG",
1027 RecordType::IXFR => "IXFR",
1028 RecordType::AXFR => "AXFR",
1029 RecordType::MAILB => "MAILB",
1030 RecordType::MAILA => "MAILA",
1031 RecordType::ANY => "ANY",
1032 RecordType::TA => "TA",
1033 RecordType::DLV => "DLV",
1034 RecordType::ZERO => "ZERO",
1035 RecordType::Unknown(_) => "Unknown",
1036 }
1037 }
1038}
1039
1040impl Display for RecordType {
1041 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
1042 f.write_str(Into::<&str>::into(*self))
1043 }
1044}