1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
//! Provides parsing and manipulation for DNS packets mod character_string; mod name; mod packet; mod packet_header; mod question; pub mod rdata; mod resource_record; use std::{collections::HashMap, convert::TryFrom}; pub use name::Name; pub use packet::{Packet, PacketBuf, QuestionsIter}; pub use packet_header::PacketHeader; pub use question::Question; pub use resource_record::ResourceRecord; // pub use rdata::RData; pub use character_string::CharacterString; const MAX_LABEL_LENGTH: usize = 63; const MAX_NAME_LENGTH: usize = 255; const MAX_CHARACTER_STRING_LENGTH: usize = 255; const MAX_NULL_LENGTH: usize = 65535; /// The maximum DNS packet size is 9000 bytes less the maximum /// sizes of the IP (60) and UDP (8) headers. // const MAX_PACKET_SIZE: usize = 9000 - 68; /// Represents anything that can be part of a dns packet (Question, Resource Record, RData) pub(crate) trait DnsPacketContent<'a> { /// Parse the contents of the data buffer begining in the given position /// It is necessary to pass the full buffer to this function, to be able to correctly implement name compression fn parse(data: &'a [u8], position: usize) -> crate::Result<Self> where Self: Sized; /// Append the bytes of this content to a given vector fn append_to_vec(&self, out: &mut Vec<u8>) -> crate::Result<()>; /// Append the bytes of this content to a given vector, compress Names before appending fn compress_append_to_vec( &self, out: &mut Vec<u8>, _name_refs: &mut HashMap<u64, usize>, ) -> crate::Result<()> { self.append_to_vec(out) } /// Returns the length in bytes of this content fn len(&self) -> usize; } /// Possible TYPE values in DNS Resource Records /// Each value is described according to its own RFC #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum TYPE { /// Host address, [RFC 1035](https://tools.ietf.org/html/rfc1035) A, /// Host address (IPv6) [rfc3596](https://tools.ietf.org/html/rfc3596) AAAA, /// Authoritative name server, [RFC 1035](https://tools.ietf.org/html/rfc1035) NS, /// Mail destination (Obsolete - use MX), [RFC 1035](https://tools.ietf.org/html/rfc1035) MD, /// Mail forwarder (Obsolete - use MX), [RFC 1035](https://tools.ietf.org/html/rfc1035) MF, /// Canonical name for an alias, [RFC 1035](https://tools.ietf.org/html/rfc1035) CNAME, /// Marks the start of a zone of authority, [RFC 1035](https://tools.ietf.org/html/rfc1035) SOA, /// Mailbox domain name (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MB, /// Mail group member (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MG, /// Mail rename domain name (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MR, /// Null RR (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) NULL, /// Well known service description, [RFC 1035](https://tools.ietf.org/html/rfc1035) WKS, /// Domain name pointer, [RFC 1035](https://tools.ietf.org/html/rfc1035) PTR, /// Host information, [RFC 1035](https://tools.ietf.org/html/rfc1035) HINFO, /// Mailbox or mail list information, [RFC 1035](https://tools.ietf.org/html/rfc1035) MINFO, /// Mail exchange, [RFC 1035](https://tools.ietf.org/html/rfc1035) MX, /// Text strings, [RFC 1035](https://tools.ietf.org/html/rfc1035) TXT, /// SRV specifies the location of the server(s) for a specific protocol and domain. [RFC 2780](https://tools.ietf.org/html/rfc2782) SRV, /// Unknown value, for future (or unimplemented RFC) compatibility Unknown(u16), } impl From<TYPE> for u16 { fn from(value: TYPE) -> Self { match value { TYPE::A => 1, TYPE::AAAA => 28, TYPE::NS => 2, TYPE::MD => 3, TYPE::MF => 4, TYPE::CNAME => 5, TYPE::SOA => 6, TYPE::MB => 7, TYPE::MG => 8, TYPE::MR => 9, TYPE::NULL => 10, TYPE::WKS => 11, TYPE::PTR => 12, TYPE::HINFO => 13, TYPE::MINFO => 14, TYPE::MX => 15, TYPE::TXT => 16, TYPE::SRV => 33, TYPE::Unknown(x) => x, } } } impl From<u16> for TYPE { fn from(value: u16) -> Self { use self::TYPE::*; match value { 1 => A, 2 => NS, 3 => MD, 4 => MF, 5 => CNAME, 6 => SOA, 7 => MB, 8 => MG, 9 => MR, 10 => NULL, 11 => WKS, 12 => PTR, 13 => HINFO, 14 => MINFO, 15 => MX, 16 => TXT, 28 => AAAA, 33 => SRV, v => TYPE::Unknown(v), } } } /// Possible QTYPE values for a Question in a DNS packet /// Each value is described according to its own RFC #[derive(Debug, Copy, Clone, PartialEq)] pub enum QTYPE { /// Host address, [RFC 1035](https://tools.ietf.org/html/rfc1035) A = 1, /// Host address (IPv6) [rfc3596](https://tools.ietf.org/html/rfc3596) AAAA = 28, /// Authoritative name server, [RFC 1035](https://tools.ietf.org/html/rfc1035) NS = 2, /// Mail destination (Obsolete - use MX), [RFC 1035](https://tools.ietf.org/html/rfc1035) MD = 3, /// Mail forwarder (Obsolete - use MX), [RFC 1035](https://tools.ietf.org/html/rfc1035) MF = 4, /// Canonical name for an alias, [RFC 1035](https://tools.ietf.org/html/rfc1035) CNAME = 5, /// Marks the start of a zone of authority, [RFC 1035](https://tools.ietf.org/html/rfc1035) SOA = 6, /// Mailbox domain name (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MB = 7, /// Mail group member (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MG = 8, /// Mail rename domain name (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) MR = 9, /// Null RR (EXPERIMENTAL), [RFC 1035](https://tools.ietf.org/html/rfc1035) NULL = 10, /// Well known service description, [RFC 1035](https://tools.ietf.org/html/rfc1035) WKS = 11, /// Domain name pointer, [RFC 1035](https://tools.ietf.org/html/rfc1035) PTR = 12, /// Host Information, [RFC 1035](https://tools.ietf.org/html/rfc1035) HINFO = 13, /// Mailbox or mail list information, [RFC 1035](https://tools.ietf.org/html/rfc1035) MINFO = 14, /// Mail exchange, [RFC 1035](https://tools.ietf.org/html/rfc1035) MX = 15, /// Text strings, [RFC 1035](https://tools.ietf.org/html/rfc1035) TXT = 16, /// SRV specifies the location of the server(s) for a specific protocol and domain. [RFC 2780](https://tools.ietf.org/html/rfc2782) SRV = 33, /// A request for a transfer of an entire zone, [RFC 1035](https://tools.ietf.org/html/rfc1035) AXFR = 252, /// A request for mailbox-related records (MB, MG or MR), [RFC 1035](https://tools.ietf.org/html/rfc1035) MAILB = 253, /// A request for mail agent RRs (Obsolete - see MX), [RFC 1035](https://tools.ietf.org/html/rfc1035) MAILA = 254, /// A request for all records, [RFC 1035](https://tools.ietf.org/html/rfc1035) ANY = 255, } impl TryFrom<u16> for QTYPE { type Error = crate::SimpleDnsError; fn try_from(value: u16) -> Result<Self, Self::Error> { use self::QTYPE::*; match value { 1 => Ok(A), 2 => Ok(NS), 3 => Ok(MD), 4 => Ok(MF), 5 => Ok(CNAME), 6 => Ok(SOA), 7 => Ok(MB), 8 => Ok(MG), 9 => Ok(MR), 10 => Ok(NULL), 11 => Ok(WKS), 12 => Ok(PTR), 13 => Ok(HINFO), 14 => Ok(MINFO), 15 => Ok(MX), 16 => Ok(TXT), 28 => Ok(AAAA), 33 => Ok(SRV), 252 => Ok(AXFR), 253 => Ok(MAILB), 254 => Ok(MAILA), 255 => Ok(ANY), v => Err(Self::Error::InvalidQType(v)), } } } /// Possible CLASS values for a Resource in a DNS packet /// Each value is described according to its own RFC #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum CLASS { /// The Internet, [RFC 1035](https://tools.ietf.org/html/rfc1035) IN = 1, /// The CSNET class (Obsolete - used only for examples in some obsolete RFCs), [RFC 1035](https://tools.ietf.org/html/rfc1035) CS = 2, /// The CHAOS class, [RFC 1035](https://tools.ietf.org/html/rfc1035) CH = 3, /// Hesiod [Dyer 87], [RFC 1035](https://tools.ietf.org/html/rfc1035) HS = 4, } impl TryFrom<u16> for CLASS { type Error = crate::SimpleDnsError; fn try_from(value: u16) -> Result<Self, Self::Error> { use self::CLASS::*; match value { 1 => Ok(IN), 2 => Ok(CS), 3 => Ok(CH), 4 => Ok(HS), v => Err(Self::Error::InvalidClass(v)), } } } /// Possible QCLASS values for a Question in a DNS packet /// Each value is described according to its own RFC #[derive(Debug, Copy, Clone, PartialEq)] pub enum QCLASS { /// The Internet, [RFC 1035](https://tools.ietf.org/html/rfc1035) IN = 1, /// The CSNET class (Obsolete - used only for examples in some obsolete RFCs), [RFC 1035](https://tools.ietf.org/html/rfc1035) CS = 2, /// The CHAOS class, [RFC 1035](https://tools.ietf.org/html/rfc1035) CH = 3, /// Hesiod [Dyer 87], [RFC 1035](https://tools.ietf.org/html/rfc1035) HS = 4, /// [RFC 1035](https://tools.ietf.org/html/rfc1035) ANY = 255, } impl TryFrom<u16> for QCLASS { type Error = crate::SimpleDnsError; fn try_from(value: u16) -> Result<Self, Self::Error> { use self::QCLASS::*; match value { 1 => Ok(IN), 2 => Ok(CS), 3 => Ok(CH), 4 => Ok(HS), 255 => Ok(ANY), v => Err(Self::Error::InvalidQClass(v)), } } } /// Possible OPCODE values for a DNS packet, use to specify the type of operation. /// [RFC 1035](https://tools.ietf.org/html/rfc1035): A four bit field that specifies kind of query in this message. /// This value is set by the originator of a query and copied into the response. #[derive(Debug, Copy, Clone, PartialEq)] pub enum OPCODE { /// Normal query StandardQuery = 0, /// Inverse query (query a name by IP) InverseQuery = 1, /// Server status request ServerStatusRequest = 2, /// Reserved opcode for future use Reserved, } impl From<u16> for OPCODE { fn from(code: u16) -> Self { match code { 0 => OPCODE::StandardQuery, 1 => OPCODE::InverseQuery, 2 => OPCODE::ServerStatusRequest, _ => OPCODE::Reserved, } } } /// Possible RCODE values for a DNS packet /// [RFC 1035](https://tools.ietf.org/html/rfc1035) Response code - this 4 bit field is set as part of responses. /// The values have the following interpretation #[derive(Debug, Copy, Clone, PartialEq)] pub enum RCODE { /// No error condition NoError = 0, /// Format error - The name server was unable to interpret the query. FormatError = 1, /// Server failure - The name server was unable to process this query due to a problem with the name server. ServerFailure = 2, /// Name Error - Meaningful only for responses from an authoritative name server, /// this code signifies that the domain name referenced in the query does not exist. NameError = 3, /// Not Implemented - The name server does not support the requested kind of query. NotImplemented = 4, /// Refused - The name server refuses to perform the specified operation for policy reasons. /// For example, a name server may not wish to provide the information to the particular requester, /// or a name server may not wish to perform a particular operation (e.g., zone transfer) for particular data. Refused = 5, /// Reserved for future use. Reserved, } impl From<u16> for RCODE { fn from(code: u16) -> Self { match code { 0 => RCODE::NoError, 1 => RCODE::FormatError, 2 => RCODE::ServerFailure, 3 => RCODE::NameError, 4 => RCODE::NotImplemented, 5 => RCODE::Refused, _ => RCODE::Reserved, } } }