simple_dns/dns/
mod.rs

1//! Provides parsing and manipulation for DNS packets
2
3mod character_string;
4pub use character_string::CharacterString;
5
6mod name;
7pub use name::{Label, Name};
8
9mod packet;
10pub use packet::Packet;
11
12mod header;
13use header::Header;
14
15pub mod header_buffer;
16
17mod wire_format;
18pub(crate) use wire_format::WireFormat;
19
20mod question;
21pub use question::Question;
22
23pub mod rdata;
24pub use rdata::TYPE;
25
26mod resource_record;
27pub use resource_record::ResourceRecord;
28
29use bitflags::bitflags;
30use std::convert::TryFrom;
31
32const MAX_LABEL_LENGTH: usize = 63;
33const MAX_NAME_LENGTH: usize = 255;
34const MAX_CHARACTER_STRING_LENGTH: usize = 255;
35const MAX_NULL_LENGTH: usize = 65535;
36
37bitflags! {
38    /// Possible Packet Flags
39    #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
40    pub struct PacketFlag: u16 {
41        /// Indicates if this packet is a query or a response. This is the QR flag in the DNS
42        /// specifications, this flag is called Response here to be more ergonomic
43        const RESPONSE = 0b1000_0000_0000_0000;
44
45        /// Authoritative Answer - this bit is valid in responses,
46        /// and specifies that the responding name server is an authority for the domain name in question section.
47        const AUTHORITATIVE_ANSWER = 0b0000_0100_0000_0000;
48        /// TrunCation - specifies that this message was truncated due to
49        /// length greater than that permitted on the transmission channel.
50        const TRUNCATION = 0b0000_0010_0000_0000;
51        /// Recursion Desired may be set in a query and is copied into the response.
52        /// If RD is set, it directs the name server to pursue the query recursively.
53        /// Recursive query support is optional.
54        const RECURSION_DESIRED = 0b0000_0001_0000_0000;
55        /// Recursion Available is set or cleared in a response.
56        /// It denotes whether recursive query support is available in the name server.
57        const RECURSION_AVAILABLE = 0b0000_0000_1000_0000;
58        #[allow(missing_docs)]
59        const AUTHENTIC_DATA = 0b0000_0000_0010_0000;
60        #[allow(missing_docs)]
61        const CHECKING_DISABLED = 0b0000_0000_0001_0000;
62    }
63}
64
65// /// The maximum DNS packet size is 9000 bytes less the maximum
66// /// sizes of the IP (60) and UDP (8) headers.
67// // const MAX_PACKET_SIZE: usize = 9000 - 68;
68
69/// Possible QTYPE values for a Question in a DNS packet  
70/// Each value is described according to its own RFC
71#[derive(Debug, Copy, Clone, PartialEq, Eq)]
72pub enum QTYPE {
73    /// Query for the specific [TYPE]
74    TYPE(TYPE),
75    /// A request for incremental transfer of a zone. [RFC 1995](https://tools.ietf.org/html/rfc1995)
76    IXFR,
77    /// A request for a transfer of an entire zone, [RFC 1035](https://tools.ietf.org/html/rfc1035)
78    AXFR,
79    /// A request for mailbox-related records (MB, MG or MR), [RFC 1035](https://tools.ietf.org/html/rfc1035)
80    MAILB,
81    /// A request for mail agent RRs (Obsolete - see MX), [RFC 1035](https://tools.ietf.org/html/rfc1035)
82    MAILA,
83    /// A request for all records, [RFC 1035](https://tools.ietf.org/html/rfc1035)
84    ANY,
85}
86
87impl From<TYPE> for QTYPE {
88    fn from(v: TYPE) -> Self {
89        Self::TYPE(v)
90    }
91}
92
93impl TryFrom<u16> for QTYPE {
94    type Error = crate::SimpleDnsError;
95
96    fn try_from(value: u16) -> Result<Self, Self::Error> {
97        match value {
98            251 => Ok(QTYPE::IXFR),
99            252 => Ok(QTYPE::AXFR),
100            253 => Ok(QTYPE::MAILB),
101            254 => Ok(QTYPE::MAILA),
102            255 => Ok(QTYPE::ANY),
103            v => match TYPE::from(v) {
104                TYPE::Unknown(_) => Err(Self::Error::InvalidQType(v)),
105                ty => Ok(ty.into()),
106            },
107        }
108    }
109}
110
111impl From<QTYPE> for u16 {
112    fn from(val: QTYPE) -> Self {
113        match val {
114            QTYPE::TYPE(ty) => ty.into(),
115            QTYPE::IXFR => 251,
116            QTYPE::AXFR => 252,
117            QTYPE::MAILB => 253,
118            QTYPE::MAILA => 254,
119            QTYPE::ANY => 255,
120        }
121    }
122}
123
124/// Possible CLASS values for a Resource in a DNS packet  
125/// Each value is described according to its own RFC
126#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
127pub enum CLASS {
128    /// The Internet, [RFC 1035](https://tools.ietf.org/html/rfc1035)
129    IN = 1,
130    /// The CSNET class (Obsolete - used only for examples in some obsolete RFCs), [RFC 1035](https://tools.ietf.org/html/rfc1035)
131    CS = 2,
132    /// The CHAOS class, [RFC 1035](https://tools.ietf.org/html/rfc1035)
133    CH = 3,
134    /// Hesiod [Dyer 87], [RFC 1035](https://tools.ietf.org/html/rfc1035)
135    HS = 4,
136    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
137    NONE = 254,
138}
139
140impl TryFrom<u16> for CLASS {
141    type Error = crate::SimpleDnsError;
142
143    fn try_from(value: u16) -> Result<Self, Self::Error> {
144        use self::CLASS::*;
145        match value {
146            1 => Ok(IN),
147            2 => Ok(CS),
148            3 => Ok(CH),
149            4 => Ok(HS),
150            254 => Ok(NONE),
151            v => Err(Self::Error::InvalidClass(v)),
152        }
153    }
154}
155
156/// Possible QCLASS values for a Question in a DNS packet  
157/// Each value is described according to its own RFC
158#[derive(Debug, Copy, Clone, PartialEq, Eq)]
159pub enum QCLASS {
160    /// Query for the specific [CLASS]
161    CLASS(CLASS),
162    /// [RFC 1035](https://tools.ietf.org/html/rfc1035)
163    ANY,
164}
165
166impl From<CLASS> for QCLASS {
167    fn from(v: CLASS) -> Self {
168        Self::CLASS(v)
169    }
170}
171
172impl TryFrom<u16> for QCLASS {
173    type Error = crate::SimpleDnsError;
174
175    fn try_from(value: u16) -> Result<Self, Self::Error> {
176        match value {
177            255 => Ok(QCLASS::ANY),
178            v => CLASS::try_from(v).map(|x| x.into()),
179        }
180    }
181}
182
183impl From<QCLASS> for u16 {
184    fn from(val: QCLASS) -> Self {
185        match val {
186            QCLASS::CLASS(class) => class as u16,
187            QCLASS::ANY => 255,
188        }
189    }
190}
191
192/// Possible OPCODE values for a DNS packet, use to specify the type of operation.  
193/// [RFC 1035](https://tools.ietf.org/html/rfc1035): A four bit field that specifies kind of query in this message.  
194/// This value is set by the originator of a query and copied into the response.
195#[derive(Debug, Copy, Clone, PartialEq, Eq)]
196pub enum OPCODE {
197    /// Normal query
198    StandardQuery = 0,
199    /// Inverse query (query a name by IP)
200    InverseQuery = 1,
201    /// Server status request
202    ServerStatusRequest = 2,
203    /// Notify query
204    Notify = 4,
205    /// Update query [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
206    Update = 5,
207    /// Reserved opcode for future use
208    Reserved,
209}
210
211impl From<u16> for OPCODE {
212    fn from(code: u16) -> Self {
213        match code {
214            0 => OPCODE::StandardQuery,
215            1 => OPCODE::InverseQuery,
216            2 => OPCODE::ServerStatusRequest,
217            4 => OPCODE::Notify,
218            5 => OPCODE::Update,
219            _ => OPCODE::Reserved,
220        }
221    }
222}
223
224/// Possible RCODE values for a DNS packet   
225/// [RFC 1035](https://tools.ietf.org/html/rfc1035) Response code - this 4 bit field is set as part of responses.  
226/// The values have the following interpretation
227#[derive(Debug, Copy, Clone, PartialEq, Eq)]
228pub enum RCODE {
229    /// No error condition
230    NoError = 0,
231    /// Format error - The name server was unable to interpret the query.
232    FormatError = 1,
233    /// Server failure - The name server was unable to process this query due to a problem with the name server.
234    ServerFailure = 2,
235    /// Name Error - Meaningful only for responses from an authoritative name server,  
236    /// this code signifies that the domain name referenced in the query does not exist.
237    NameError = 3,
238    /// Not Implemented - The name server does not support the requested kind of query.
239    NotImplemented = 4,
240    /// Refused - The name server refuses to perform the specified operation for policy reasons.  
241    /// For example, a name server may not wish to provide the information to the particular requester,   
242    /// or a name server may not wish to perform a particular operation (e.g., zone transfer) for particular data.
243    Refused = 5,
244    /// Some name that ought not to exist, does exist.
245    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
246    YXDOMAIN = 6,
247    /// Some RRset that ought not to exist, does exist.
248    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
249    YXRRSET = 7,
250    /// Some RRset that ought to exist, does not exist.
251    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
252    NXRRSET = 8,
253    /// The server is not authoritative for the zone named in the Zone Section.
254    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
255    NOTAUTH = 9,
256    /// A name used in the Prerequisite or Update Section is not within the zone denoted by the Zone Section.
257    /// [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136)
258    NOTZONE = 10,
259    /// EDNS Version not supported by the responder
260    /// [RFC 6891](https://datatracker.ietf.org/doc/html/rfc6891)
261    BADVERS = 16,
262
263    /// Reserved for future use.
264    Reserved,
265}
266
267impl From<u16> for RCODE {
268    fn from(code: u16) -> Self {
269        use RCODE::*;
270        match code {
271            0 => NoError,
272            1 => FormatError,
273            2 => ServerFailure,
274            3 => NameError,
275            4 => NotImplemented,
276            5 => Refused,
277            6 => YXDOMAIN,
278            7 => YXRRSET,
279            8 => NXRRSET,
280            9 => NOTAUTH,
281            10 => NOTZONE,
282            16 => BADVERS,
283            _ => RCODE::Reserved,
284        }
285    }
286}