1 #[cfg(test)] 2 mod message_test; 3 4 pub mod builder; 5 pub mod header; 6 pub mod name; 7 mod packer; 8 pub mod parser; 9 pub mod question; 10 pub mod resource; 11 12 use crate::error::*; 13 use header::*; 14 use packer::*; 15 use parser::*; 16 use question::*; 17 use resource::*; 18 19 use std::collections::HashMap; 20 use std::fmt; 21 22 // Message formats 23 24 // A Type is a type of DNS request and response. 25 #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] 26 pub enum DnsType { 27 // ResourceHeader.Type and question.Type 28 A = 1, 29 Ns = 2, 30 Cname = 5, 31 Soa = 6, 32 Ptr = 12, 33 Mx = 15, 34 Txt = 16, 35 Aaaa = 28, 36 Srv = 33, 37 Opt = 41, 38 39 // question.Type 40 Wks = 11, 41 Hinfo = 13, 42 Minfo = 14, 43 Axfr = 252, 44 All = 255, 45 46 #[default] 47 Unsupported = 0, 48 } 49 50 impl From<u16> for DnsType { from(v: u16) -> Self51 fn from(v: u16) -> Self { 52 match v { 53 1 => DnsType::A, 54 2 => DnsType::Ns, 55 5 => DnsType::Cname, 56 6 => DnsType::Soa, 57 12 => DnsType::Ptr, 58 15 => DnsType::Mx, 59 16 => DnsType::Txt, 60 28 => DnsType::Aaaa, 61 33 => DnsType::Srv, 62 41 => DnsType::Opt, 63 64 // question.Type 65 11 => DnsType::Wks, 66 13 => DnsType::Hinfo, 67 14 => DnsType::Minfo, 68 252 => DnsType::Axfr, 69 255 => DnsType::All, 70 71 _ => DnsType::Unsupported, 72 } 73 } 74 } 75 76 impl fmt::Display for DnsType { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 78 let s = match *self { 79 DnsType::A => "A", 80 DnsType::Ns => "NS", 81 DnsType::Cname => "CNAME", 82 DnsType::Soa => "SOA", 83 DnsType::Ptr => "PTR", 84 DnsType::Mx => "MX", 85 DnsType::Txt => "TXT", 86 DnsType::Aaaa => "AAAA", 87 DnsType::Srv => "SRV", 88 DnsType::Opt => "OPT", 89 DnsType::Wks => "WKS", 90 DnsType::Hinfo => "HINFO", 91 DnsType::Minfo => "MINFO", 92 DnsType::Axfr => "AXFR", 93 DnsType::All => "ALL", 94 _ => "Unsupported", 95 }; 96 write!(f, "{s}") 97 } 98 } 99 100 impl DnsType { 101 // pack_type appends the wire format of field to msg. pack(&self, msg: Vec<u8>) -> Vec<u8>102 pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> { 103 pack_uint16(msg, *self as u16) 104 } 105 unpack(&mut self, msg: &[u8], off: usize) -> Result<usize>106 pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> { 107 let (t, o) = unpack_uint16(msg, off)?; 108 *self = DnsType::from(t); 109 Ok(o) 110 } 111 skip(msg: &[u8], off: usize) -> Result<usize>112 pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> { 113 skip_uint16(msg, off) 114 } 115 } 116 117 // A Class is a type of network. 118 #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] 119 pub struct DnsClass(pub u16); 120 121 // ResourceHeader.Class and question.Class 122 pub const DNSCLASS_INET: DnsClass = DnsClass(1); 123 pub const DNSCLASS_CSNET: DnsClass = DnsClass(2); 124 pub const DNSCLASS_CHAOS: DnsClass = DnsClass(3); 125 pub const DNSCLASS_HESIOD: DnsClass = DnsClass(4); 126 // question.Class 127 pub const DNSCLASS_ANY: DnsClass = DnsClass(255); 128 129 impl fmt::Display for DnsClass { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 131 let other = format!("{}", self.0); 132 let s = match *self { 133 DNSCLASS_INET => "ClassINET", 134 DNSCLASS_CSNET => "ClassCSNET", 135 DNSCLASS_CHAOS => "ClassCHAOS", 136 DNSCLASS_HESIOD => "ClassHESIOD", 137 DNSCLASS_ANY => "ClassANY", 138 _ => other.as_str(), 139 }; 140 write!(f, "{s}") 141 } 142 } 143 144 impl DnsClass { 145 // pack_class appends the wire format of field to msg. pack(&self, msg: Vec<u8>) -> Vec<u8>146 pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> { 147 pack_uint16(msg, self.0) 148 } 149 unpack(&mut self, msg: &[u8], off: usize) -> Result<usize>150 pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> { 151 let (c, o) = unpack_uint16(msg, off)?; 152 *self = DnsClass(c); 153 Ok(o) 154 } 155 skip(msg: &[u8], off: usize) -> Result<usize>156 pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> { 157 skip_uint16(msg, off) 158 } 159 } 160 161 // An OpCode is a DNS operation code. 162 pub type OpCode = u16; 163 164 // An RCode is a DNS response status code. 165 #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] 166 pub enum RCode { 167 // Message.Rcode 168 #[default] 169 Success = 0, 170 FormatError = 1, 171 ServerFailure = 2, 172 NameError = 3, 173 NotImplemented = 4, 174 Refused = 5, 175 Unsupported, 176 } 177 178 impl From<u8> for RCode { from(v: u8) -> Self179 fn from(v: u8) -> Self { 180 match v { 181 0 => RCode::Success, 182 1 => RCode::FormatError, 183 2 => RCode::ServerFailure, 184 3 => RCode::NameError, 185 4 => RCode::NotImplemented, 186 5 => RCode::Refused, 187 _ => RCode::Unsupported, 188 } 189 } 190 } 191 192 impl fmt::Display for RCode { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 194 let s = match *self { 195 RCode::Success => "RCodeSuccess", 196 RCode::FormatError => "RCodeFormatError", 197 RCode::ServerFailure => "RCodeServerFailure", 198 RCode::NameError => "RCodeNameError", 199 RCode::NotImplemented => "RCodeNotImplemented", 200 RCode::Refused => "RCodeRefused", 201 RCode::Unsupported => "RCodeUnsupported", 202 }; 203 write!(f, "{s}") 204 } 205 } 206 207 // Internal constants. 208 209 // PACK_STARTING_CAP is the default initial buffer size allocated during 210 // packing. 211 // 212 // The starting capacity doesn't matter too much, but most DNS responses 213 // Will be <= 512 bytes as it is the limit for DNS over UDP. 214 const PACK_STARTING_CAP: usize = 512; 215 216 // UINT16LEN is the length (in bytes) of a uint16. 217 const UINT16LEN: usize = 2; 218 219 // UINT32LEN is the length (in bytes) of a uint32. 220 const UINT32LEN: usize = 4; 221 222 // HEADER_LEN is the length (in bytes) of a DNS header. 223 // 224 // A header is comprised of 6 uint16s and no padding. 225 const HEADER_LEN: usize = 6 * UINT16LEN; 226 227 const HEADER_BIT_QR: u16 = 1 << 15; // query/response (response=1) 228 const HEADER_BIT_AA: u16 = 1 << 10; // authoritative 229 const HEADER_BIT_TC: u16 = 1 << 9; // truncated 230 const HEADER_BIT_RD: u16 = 1 << 8; // recursion desired 231 const HEADER_BIT_RA: u16 = 1 << 7; // recursion available 232 233 // Message is a representation of a DNS message. 234 #[derive(Default, Debug)] 235 pub struct Message { 236 pub header: Header, 237 pub questions: Vec<Question>, 238 pub answers: Vec<Resource>, 239 pub authorities: Vec<Resource>, 240 pub additionals: Vec<Resource>, 241 } 242 243 impl fmt::Display for Message { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 245 let mut s = "dnsmessage.Message{Header: ".to_owned(); 246 s += self.header.to_string().as_str(); 247 248 s += ", Questions: "; 249 let v: Vec<String> = self.questions.iter().map(|q| q.to_string()).collect(); 250 s += &v.join(", "); 251 252 s += ", Answers: "; 253 let v: Vec<String> = self.answers.iter().map(|q| q.to_string()).collect(); 254 s += &v.join(", "); 255 256 s += ", Authorities: "; 257 let v: Vec<String> = self.authorities.iter().map(|q| q.to_string()).collect(); 258 s += &v.join(", "); 259 260 s += ", Additionals: "; 261 let v: Vec<String> = self.additionals.iter().map(|q| q.to_string()).collect(); 262 s += &v.join(", "); 263 264 write!(f, "{s}") 265 } 266 } 267 268 impl Message { 269 // Unpack parses a full Message. unpack(&mut self, msg: &[u8]) -> Result<()>270 pub fn unpack(&mut self, msg: &[u8]) -> Result<()> { 271 let mut p = Parser::default(); 272 self.header = p.start(msg)?; 273 self.questions = p.all_questions()?; 274 self.answers = p.all_answers()?; 275 self.authorities = p.all_authorities()?; 276 self.additionals = p.all_additionals()?; 277 Ok(()) 278 } 279 280 // Pack packs a full Message. pack(&mut self) -> Result<Vec<u8>>281 pub fn pack(&mut self) -> Result<Vec<u8>> { 282 self.append_pack(vec![]) 283 } 284 285 // append_pack is like Pack but appends the full Message to b and returns the 286 // extended buffer. append_pack(&mut self, b: Vec<u8>) -> Result<Vec<u8>>287 pub fn append_pack(&mut self, b: Vec<u8>) -> Result<Vec<u8>> { 288 // Validate the lengths. It is very unlikely that anyone will try to 289 // pack more than 65535 of any particular type, but it is possible and 290 // we should fail gracefully. 291 if self.questions.len() > u16::MAX as usize { 292 return Err(Error::ErrTooManyQuestions); 293 } 294 if self.answers.len() > u16::MAX as usize { 295 return Err(Error::ErrTooManyAnswers); 296 } 297 if self.authorities.len() > u16::MAX as usize { 298 return Err(Error::ErrTooManyAuthorities); 299 } 300 if self.additionals.len() > u16::MAX as usize { 301 return Err(Error::ErrTooManyAdditionals); 302 } 303 304 let (id, bits) = self.header.pack(); 305 306 let questions = self.questions.len() as u16; 307 let answers = self.answers.len() as u16; 308 let authorities = self.authorities.len() as u16; 309 let additionals = self.additionals.len() as u16; 310 311 let h = HeaderInternal { 312 id, 313 bits, 314 questions, 315 answers, 316 authorities, 317 additionals, 318 }; 319 320 let compression_off = b.len(); 321 let mut msg = h.pack(b); 322 323 // RFC 1035 allows (but does not require) compression for packing. RFC 324 // 1035 requires unpacking implementations to support compression, so 325 // unconditionally enabling it is fine. 326 // 327 // DNS lookups are typically done over UDP, and RFC 1035 states that UDP 328 // DNS messages can be a maximum of 512 bytes long. Without compression, 329 // many DNS response messages are over this limit, so enabling 330 // compression will help ensure compliance. 331 let mut compression = Some(HashMap::new()); 332 333 for question in &self.questions { 334 msg = question.pack(msg, &mut compression, compression_off)?; 335 } 336 for answer in &mut self.answers { 337 msg = answer.pack(msg, &mut compression, compression_off)?; 338 } 339 for authority in &mut self.authorities { 340 msg = authority.pack(msg, &mut compression, compression_off)?; 341 } 342 for additional in &mut self.additionals { 343 msg = additional.pack(msg, &mut compression, compression_off)?; 344 } 345 346 Ok(msg) 347 } 348 } 349