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