Skip to main content

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