doge_dns/record/
mod.rs

1//! All the DNS record types, as well as how to parse each type.
2
3use crate::wire::*;
4
5
6mod a;
7pub use self::a::A;
8
9mod aaaa;
10pub use self::aaaa::AAAA;
11
12mod caa;
13pub use self::caa::CAA;
14
15mod cname;
16pub use self::cname::CNAME;
17
18mod eui48;
19pub use self::eui48::EUI48;
20
21mod eui64;
22pub use self::eui64::EUI64;
23
24mod hinfo;
25pub use self::hinfo::HINFO;
26
27mod loc;
28pub use self::loc::LOC;
29
30mod mx;
31pub use self::mx::MX;
32
33mod naptr;
34pub use self::naptr::NAPTR;
35
36mod ns;
37pub use self::ns::NS;
38
39mod openpgpkey;
40pub use self::openpgpkey::OPENPGPKEY;
41
42mod opt;
43pub use self::opt::OPT;
44
45mod ptr;
46pub use self::ptr::PTR;
47
48mod sshfp;
49pub use self::sshfp::SSHFP;
50
51mod soa;
52pub use self::soa::SOA;
53
54mod srv;
55pub use self::srv::SRV;
56
57mod tlsa;
58pub use self::tlsa::TLSA;
59
60mod txt;
61pub use self::txt::TXT;
62
63mod uri;
64pub use self::uri::URI;
65
66
67mod others;
68pub use self::others::UnknownQtype;
69
70
71/// A record that’s been parsed from a byte buffer.
72#[derive(PartialEq, Debug)]
73#[allow(missing_docs)]
74pub enum Record {
75    A(A),
76    AAAA(AAAA),
77    CAA(CAA),
78    CNAME(CNAME),
79    EUI48(EUI48),
80    EUI64(EUI64),
81    HINFO(HINFO),
82    LOC(LOC),
83    MX(MX),
84    NAPTR(NAPTR),
85    NS(NS),
86    OPENPGPKEY(OPENPGPKEY),
87    // OPT is not included here.
88    PTR(PTR),
89    SSHFP(SSHFP),
90    SOA(SOA),
91    SRV(SRV),
92    TLSA(TLSA),
93    TXT(TXT),
94    URI(URI),
95
96    /// A record with a type that we don’t recognise.
97    Other {
98
99        /// The number that’s meant to represent the record type.
100        type_number: UnknownQtype,
101
102        /// The undecodable bytes that were in this record.
103        bytes: Vec<u8>,
104    },
105}
106
107
108/// The type of a record that may or may not be one of the known ones. Has no
109/// data associated with it other than what type of record it is.
110#[derive(PartialEq, Debug, Copy, Clone)]
111#[allow(missing_docs)]
112pub enum RecordType {
113    A,
114    AAAA,
115    CAA,
116    CNAME,
117    EUI48,
118    EUI64,
119    HINFO,
120    LOC,
121    MX,
122    NAPTR,
123    NS,
124    OPENPGPKEY,
125    PTR,
126    SSHFP,
127    SOA,
128    SRV,
129    TLSA,
130    TXT,
131    URI,
132
133    /// A record type we don’t recognise.
134    Other(UnknownQtype),
135}
136
137impl From<u16> for RecordType {
138    fn from(type_number: u16) -> Self {
139        macro_rules! try_record {
140            ($record:tt) => {
141                if $record::RR_TYPE == type_number {
142                    return RecordType::$record;
143                }
144            }
145        }
146
147        try_record!(A);
148        try_record!(AAAA);
149        try_record!(CAA);
150        try_record!(CNAME);
151        try_record!(EUI48);
152        try_record!(EUI64);
153        try_record!(HINFO);
154        try_record!(LOC);
155        try_record!(MX);
156        try_record!(NAPTR);
157        try_record!(NS);
158        try_record!(OPENPGPKEY);
159        // OPT is handled separately
160        try_record!(PTR);
161        try_record!(SSHFP);
162        try_record!(SOA);
163        try_record!(SRV);
164        try_record!(TLSA);
165        try_record!(TXT);
166        try_record!(URI);
167
168        RecordType::Other(UnknownQtype::from(type_number))
169    }
170}
171
172
173impl RecordType {
174
175    /// Determines the record type with a given name, or `None` if none is
176    /// known. Matches names case-insensitively.
177    pub fn from_type_name(type_name: &str) -> Option<Self> {
178        macro_rules! try_record {
179            ($record:tt) => {
180                if $record::NAME.eq_ignore_ascii_case(type_name) {
181                    return Some(Self::$record);
182                }
183            }
184        }
185
186        try_record!(A);
187        try_record!(AAAA);
188        try_record!(CAA);
189        try_record!(CNAME);
190        try_record!(EUI48);
191        try_record!(EUI64);
192        try_record!(HINFO);
193        try_record!(LOC);
194        try_record!(MX);
195        try_record!(NAPTR);
196        try_record!(NS);
197        try_record!(OPENPGPKEY);
198        // OPT is elsewhere
199        try_record!(PTR);
200        try_record!(SSHFP);
201        try_record!(SOA);
202        try_record!(SRV);
203        try_record!(TLSA);
204        try_record!(TXT);
205        try_record!(URI);
206
207        UnknownQtype::from_type_name(type_name).map(Self::Other)
208    }
209
210    /// Returns the record type number associated with this record type.
211    pub fn type_number(self) -> u16 {
212        match self {
213            Self::A           => A::RR_TYPE,
214            Self::AAAA        => AAAA::RR_TYPE,
215            Self::CAA         => CAA::RR_TYPE,
216            Self::CNAME       => CNAME::RR_TYPE,
217            Self::EUI48       => EUI48::RR_TYPE,
218            Self::EUI64       => EUI64::RR_TYPE,
219            Self::HINFO       => HINFO::RR_TYPE,
220            Self::LOC         => LOC::RR_TYPE,
221            Self::MX          => MX::RR_TYPE,
222            Self::NAPTR       => NAPTR::RR_TYPE,
223            Self::NS          => NS::RR_TYPE,
224            Self::OPENPGPKEY  => OPENPGPKEY::RR_TYPE,
225            // Wherefore art thou, OPT
226            Self::PTR         => PTR::RR_TYPE,
227            Self::SSHFP       => SSHFP::RR_TYPE,
228            Self::SOA         => SOA::RR_TYPE,
229            Self::SRV         => SRV::RR_TYPE,
230            Self::TLSA        => TLSA::RR_TYPE,
231            Self::TXT         => TXT::RR_TYPE,
232            Self::URI         => URI::RR_TYPE,
233            Self::Other(o)    => o.type_number(),
234        }
235    }
236}
237
238// This code is really repetitive, I know, I know