dns_server/
dns_type.rs

1use crate::{read_u16_be, write_u16_be, DnsError};
2use core::fmt::{Display, Formatter};
3use fixed_buffer::FixedBuf;
4
5/// > TYPE fields are used in resource records.  Note that these types are a subset of QTYPEs.
6///
7/// <https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2>
8///
9/// > A record type is defined to store a host's IPv6 address.  A host that has more than one
10/// > IPv6 address must have more than one such record.
11///
12/// <https://datatracker.ietf.org/doc/html/rfc3596#section-2>
13///
14/// > QTYPE fields appear in the question part of a query.  QTYPES are a superset of TYPEs, hence
15/// > all TYPEs are valid QTYPEs.
16///
17/// <https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.3>
18#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
19pub enum DnsType {
20    /// IPv4 address
21    A,
22    /// IPv6 address
23    AAAA,
24    /// The canonical name for an alias
25    CNAME,
26    /// Mail exchange
27    MX,
28    /// Authoritative name server
29    NS,
30    /// Domain name pointer
31    PTR,
32    /// Marks the start of a zone of authority
33    SOA,
34    /// Text string
35    TXT,
36    ANY,
37    Unknown(u16),
38}
39impl DnsType {
40    #[must_use]
41    pub fn new(value: u16) -> Self {
42        match value {
43            1 => DnsType::A,
44            28 => DnsType::AAAA,
45            5 => DnsType::CNAME,
46            15 => DnsType::MX,
47            2 => DnsType::NS,
48            12 => DnsType::PTR,
49            6 => DnsType::SOA,
50            16 => DnsType::TXT,
51            255 => DnsType::ANY,
52            other => DnsType::Unknown(other),
53        }
54    }
55
56    #[must_use]
57    pub fn num(&self) -> u16 {
58        match self {
59            DnsType::A => 1,
60            DnsType::AAAA => 28,
61            DnsType::CNAME => 5,
62            DnsType::MX => 15,
63            DnsType::NS => 2,
64            DnsType::PTR => 12,
65            DnsType::SOA => 6,
66            DnsType::TXT => 16,
67            DnsType::ANY => 255,
68            DnsType::Unknown(other) => *other,
69        }
70    }
71
72    /// # Errors
73    /// Returns an error when `buf` does not contain a valid two-byte type code.
74    pub fn read<const N: usize>(buf: &mut FixedBuf<N>) -> Result<Self, DnsError> {
75        Ok(Self::new(read_u16_be(buf)?))
76    }
77
78    /// # Errors
79    /// Returns an error when `buf` fills up.
80    pub fn write<const N: usize>(&self, out: &mut FixedBuf<N>) -> Result<(), DnsError> {
81        write_u16_be(out, self.num())
82    }
83}
84impl Display for DnsType {
85    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
86        match self {
87            DnsType::A => write!(f, "A"),
88            DnsType::AAAA => write!(f, "AAAA"),
89            DnsType::CNAME => write!(f, "CNAME"),
90            DnsType::MX => write!(f, "MX"),
91            DnsType::NS => write!(f, "NS"),
92            DnsType::PTR => write!(f, "PTR"),
93            DnsType::SOA => write!(f, "SOA"),
94            DnsType::TXT => write!(f, "TXT"),
95            DnsType::ANY => write!(f, "ANY"),
96            DnsType::Unknown(n) => write!(f, "Unknown({n})"),
97        }
98    }
99}