1 #![allow(dead_code)]
2
3 use bitflags::bitflags;
4 use byteorder::{ByteOrder, NetworkEndian};
5 use core::iter;
6 use core::iter::Iterator;
7
8 use super::{Error, Result};
9 #[cfg(feature = "proto-ipv4")]
10 use crate::wire::Ipv4Address;
11 #[cfg(feature = "proto-ipv6")]
12 use crate::wire::Ipv6Address;
13
14 enum_with_unknown! {
15 /// DNS OpCodes
16 pub enum Opcode(u8) {
17 Query = 0x00,
18 Status = 0x01,
19 }
20 }
21 enum_with_unknown! {
22 /// DNS OpCodes
23 pub enum Rcode(u8) {
24 NoError = 0x00,
25 FormErr = 0x01,
26 ServFail = 0x02,
27 NXDomain = 0x03,
28 NotImp = 0x04,
29 Refused = 0x05,
30 YXDomain = 0x06,
31 YXRRSet = 0x07,
32 NXRRSet = 0x08,
33 NotAuth = 0x09,
34 NotZone = 0x0a,
35 }
36 }
37
38 enum_with_unknown! {
39 /// DNS record types
40 pub enum Type(u16) {
41 A = 0x0001,
42 Ns = 0x0002,
43 Cname = 0x0005,
44 Soa = 0x0006,
45 Aaaa = 0x001c,
46 }
47 }
48
49 bitflags! {
50 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
51 pub struct Flags: u16 {
52 const RESPONSE = 0b1000_0000_0000_0000;
53 const AUTHORITATIVE = 0b0000_0100_0000_0000;
54 const TRUNCATED = 0b0000_0010_0000_0000;
55 const RECURSION_DESIRED = 0b0000_0001_0000_0000;
56 const RECURSION_AVAILABLE = 0b0000_0000_1000_0000;
57 const AUTHENTIC_DATA = 0b0000_0000_0010_0000;
58 const CHECK_DISABLED = 0b0000_0000_0001_0000;
59 }
60 }
61
62 mod field {
63 use crate::wire::field::*;
64
65 pub const ID: Field = 0..2;
66 pub const FLAGS: Field = 2..4;
67 pub const QDCOUNT: Field = 4..6;
68 pub const ANCOUNT: Field = 6..8;
69 pub const NSCOUNT: Field = 8..10;
70 pub const ARCOUNT: Field = 10..12;
71
72 pub const HEADER_END: usize = 12;
73 }
74
75 // DNS class IN (Internet)
76 const CLASS_IN: u16 = 1;
77
78 /// A read/write wrapper around a DNS packet buffer.
79 #[derive(Debug, PartialEq, Eq)]
80 pub struct Packet<T: AsRef<[u8]>> {
81 buffer: T,
82 }
83
84 impl<T: AsRef<[u8]>> Packet<T> {
85 /// Imbue a raw octet buffer with DNS packet structure.
new_unchecked(buffer: T) -> Packet<T>86 pub const fn new_unchecked(buffer: T) -> Packet<T> {
87 Packet { buffer }
88 }
89
90 /// Shorthand for a combination of [new_unchecked] and [check_len].
91 ///
92 /// [new_unchecked]: #method.new_unchecked
93 /// [check_len]: #method.check_len
new_checked(buffer: T) -> Result<Packet<T>>94 pub fn new_checked(buffer: T) -> Result<Packet<T>> {
95 let packet = Self::new_unchecked(buffer);
96 packet.check_len()?;
97 Ok(packet)
98 }
99
100 /// Ensure that no accessor method will panic if called.
101 /// Returns `Err(Error)` if the buffer is smaller than
102 /// the header length.
check_len(&self) -> Result<()>103 pub fn check_len(&self) -> Result<()> {
104 let len = self.buffer.as_ref().len();
105 if len < field::HEADER_END {
106 Err(Error)
107 } else {
108 Ok(())
109 }
110 }
111
112 /// Consume the packet, returning the underlying buffer.
into_inner(self) -> T113 pub fn into_inner(self) -> T {
114 self.buffer
115 }
116
payload(&self) -> &[u8]117 pub fn payload(&self) -> &[u8] {
118 &self.buffer.as_ref()[field::HEADER_END..]
119 }
120
transaction_id(&self) -> u16121 pub fn transaction_id(&self) -> u16 {
122 let field = &self.buffer.as_ref()[field::ID];
123 NetworkEndian::read_u16(field)
124 }
125
flags(&self) -> Flags126 pub fn flags(&self) -> Flags {
127 let field = &self.buffer.as_ref()[field::FLAGS];
128 Flags::from_bits_truncate(NetworkEndian::read_u16(field))
129 }
130
opcode(&self) -> Opcode131 pub fn opcode(&self) -> Opcode {
132 let field = &self.buffer.as_ref()[field::FLAGS];
133 let flags = NetworkEndian::read_u16(field);
134 Opcode::from((flags >> 11 & 0xF) as u8)
135 }
136
rcode(&self) -> Rcode137 pub fn rcode(&self) -> Rcode {
138 let field = &self.buffer.as_ref()[field::FLAGS];
139 let flags = NetworkEndian::read_u16(field);
140 Rcode::from((flags & 0xF) as u8)
141 }
142
question_count(&self) -> u16143 pub fn question_count(&self) -> u16 {
144 let field = &self.buffer.as_ref()[field::QDCOUNT];
145 NetworkEndian::read_u16(field)
146 }
147
answer_record_count(&self) -> u16148 pub fn answer_record_count(&self) -> u16 {
149 let field = &self.buffer.as_ref()[field::ANCOUNT];
150 NetworkEndian::read_u16(field)
151 }
152
authority_record_count(&self) -> u16153 pub fn authority_record_count(&self) -> u16 {
154 let field = &self.buffer.as_ref()[field::NSCOUNT];
155 NetworkEndian::read_u16(field)
156 }
157
additional_record_count(&self) -> u16158 pub fn additional_record_count(&self) -> u16 {
159 let field = &self.buffer.as_ref()[field::ARCOUNT];
160 NetworkEndian::read_u16(field)
161 }
162
163 /// Parse part of a name from `bytes`, following pointers if any.
parse_name<'a>(&'a self, mut bytes: &'a [u8]) -> impl Iterator<Item = Result<&'a [u8]>>164 pub fn parse_name<'a>(&'a self, mut bytes: &'a [u8]) -> impl Iterator<Item = Result<&'a [u8]>> {
165 let mut packet = self.buffer.as_ref();
166
167 iter::from_fn(move || loop {
168 if bytes.is_empty() {
169 return Some(Err(Error));
170 }
171 match bytes[0] {
172 0x00 => return None,
173 x if x & 0xC0 == 0x00 => {
174 let len = (x & 0x3F) as usize;
175 if bytes.len() < 1 + len {
176 return Some(Err(Error));
177 }
178 let label = &bytes[1..1 + len];
179 bytes = &bytes[1 + len..];
180 return Some(Ok(label));
181 }
182 x if x & 0xC0 == 0xC0 => {
183 if bytes.len() < 2 {
184 return Some(Err(Error));
185 }
186 let y = bytes[1];
187 let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
188 if packet.len() <= ptr {
189 return Some(Err(Error));
190 }
191
192 // RFC1035 says: "In this scheme, an entire domain name or a list of labels at
193 // the end of a domain name is replaced with a pointer to a ***prior*** occurance
194 // of the same name.
195 //
196 // Is it unclear if this means the pointer MUST point backwards in the packet or not. Either way,
197 // pointers that don't point backwards are never seen in the fields, so use this to check that
198 // there are no pointer loops.
199
200 // Split packet into parts before and after `ptr`.
201 // parse the part after, keep only the part before in `packet`. This ensure we never
202 // parse the same byte twice, therefore eliminating pointer loops.
203
204 bytes = &packet[ptr..];
205 packet = &packet[..ptr];
206 }
207 _ => return Some(Err(Error)),
208 }
209 })
210 }
211 }
212
213 impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
payload_mut(&mut self) -> &mut [u8]214 pub fn payload_mut(&mut self) -> &mut [u8] {
215 let data = self.buffer.as_mut();
216 &mut data[field::HEADER_END..]
217 }
218
set_transaction_id(&mut self, val: u16)219 pub fn set_transaction_id(&mut self, val: u16) {
220 let field = &mut self.buffer.as_mut()[field::ID];
221 NetworkEndian::write_u16(field, val)
222 }
223
set_flags(&mut self, val: Flags)224 pub fn set_flags(&mut self, val: Flags) {
225 let field = &mut self.buffer.as_mut()[field::FLAGS];
226 let mask = Flags::all().bits;
227 let old = NetworkEndian::read_u16(field);
228 NetworkEndian::write_u16(field, (old & !mask) | val.bits());
229 }
230
set_opcode(&mut self, val: Opcode)231 pub fn set_opcode(&mut self, val: Opcode) {
232 let field = &mut self.buffer.as_mut()[field::FLAGS];
233 let mask = 0x3800;
234 let val: u8 = val.into();
235 let val = (val as u16) << 11;
236 let old = NetworkEndian::read_u16(field);
237 NetworkEndian::write_u16(field, (old & !mask) | val);
238 }
239
set_question_count(&mut self, val: u16)240 pub fn set_question_count(&mut self, val: u16) {
241 let field = &mut self.buffer.as_mut()[field::QDCOUNT];
242 NetworkEndian::write_u16(field, val)
243 }
set_answer_record_count(&mut self, val: u16)244 pub fn set_answer_record_count(&mut self, val: u16) {
245 let field = &mut self.buffer.as_mut()[field::ANCOUNT];
246 NetworkEndian::write_u16(field, val)
247 }
set_authority_record_count(&mut self, val: u16)248 pub fn set_authority_record_count(&mut self, val: u16) {
249 let field = &mut self.buffer.as_mut()[field::NSCOUNT];
250 NetworkEndian::write_u16(field, val)
251 }
set_additional_record_count(&mut self, val: u16)252 pub fn set_additional_record_count(&mut self, val: u16) {
253 let field = &mut self.buffer.as_mut()[field::ARCOUNT];
254 NetworkEndian::write_u16(field, val)
255 }
256 }
257
258 /// Parse part of a name from `bytes`, not following pointers.
259 /// Returns the unused part of `bytes`, and the pointer offset if the sequence ends with a pointer.
parse_name_part<'a>( mut bytes: &'a [u8], mut f: impl FnMut(&'a [u8]), ) -> Result<(&'a [u8], Option<usize>)>260 fn parse_name_part<'a>(
261 mut bytes: &'a [u8],
262 mut f: impl FnMut(&'a [u8]),
263 ) -> Result<(&'a [u8], Option<usize>)> {
264 loop {
265 let x = *bytes.first().ok_or(Error)?;
266 bytes = &bytes[1..];
267 match x {
268 0x00 => return Ok((bytes, None)),
269 x if x & 0xC0 == 0x00 => {
270 let len = (x & 0x3F) as usize;
271 let label = bytes.get(..len).ok_or(Error)?;
272 bytes = &bytes[len..];
273 f(label);
274 }
275 x if x & 0xC0 == 0xC0 => {
276 let y = *bytes.first().ok_or(Error)?;
277 bytes = &bytes[1..];
278
279 let ptr = ((x & 0x3F) as usize) << 8 | (y as usize);
280 return Ok((bytes, Some(ptr)));
281 }
282 _ => return Err(Error),
283 }
284 }
285 }
286
287 #[derive(Debug, PartialEq, Eq)]
288 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
289 pub struct Question<'a> {
290 pub name: &'a [u8],
291 pub type_: Type,
292 }
293
294 impl<'a> Question<'a> {
parse(buffer: &'a [u8]) -> Result<(&'a [u8], Question<'a>)>295 pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], Question<'a>)> {
296 let (rest, _) = parse_name_part(buffer, |_| ())?;
297 let name = &buffer[..buffer.len() - rest.len()];
298
299 if rest.len() < 4 {
300 return Err(Error);
301 }
302 let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
303 let class = NetworkEndian::read_u16(&rest[2..4]);
304 let rest = &rest[4..];
305
306 if class != CLASS_IN {
307 return Err(Error);
308 }
309
310 Ok((rest, Question { name, type_ }))
311 }
312
313 /// Return the length of a packet that will be emitted from this high-level representation.
buffer_len(&self) -> usize314 pub const fn buffer_len(&self) -> usize {
315 self.name.len() + 4
316 }
317
318 /// Emit a high-level representation into a DNS packet.
emit(&self, packet: &mut [u8])319 pub fn emit(&self, packet: &mut [u8]) {
320 packet[..self.name.len()].copy_from_slice(self.name);
321 let rest = &mut packet[self.name.len()..];
322 NetworkEndian::write_u16(&mut rest[0..2], self.type_.into());
323 NetworkEndian::write_u16(&mut rest[2..4], CLASS_IN);
324 }
325 }
326
327 #[derive(Debug, PartialEq, Eq)]
328 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
329 pub struct Record<'a> {
330 pub name: &'a [u8],
331 pub ttl: u32,
332 pub data: RecordData<'a>,
333 }
334
335 impl<'a> RecordData<'a> {
parse(type_: Type, data: &'a [u8]) -> Result<RecordData<'a>>336 pub fn parse(type_: Type, data: &'a [u8]) -> Result<RecordData<'a>> {
337 match type_ {
338 #[cfg(feature = "proto-ipv4")]
339 Type::A => {
340 if data.len() != 4 {
341 return Err(Error);
342 }
343 Ok(RecordData::A(Ipv4Address::from_bytes(data)))
344 }
345 #[cfg(feature = "proto-ipv6")]
346 Type::Aaaa => {
347 if data.len() != 16 {
348 return Err(Error);
349 }
350 Ok(RecordData::Aaaa(Ipv6Address::from_bytes(data)))
351 }
352 Type::Cname => Ok(RecordData::Cname(data)),
353 x => Ok(RecordData::Other(x, data)),
354 }
355 }
356 }
357
358 #[derive(Debug, PartialEq, Eq)]
359 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
360 pub enum RecordData<'a> {
361 #[cfg(feature = "proto-ipv4")]
362 A(Ipv4Address),
363 #[cfg(feature = "proto-ipv6")]
364 Aaaa(Ipv6Address),
365 Cname(&'a [u8]),
366 Other(Type, &'a [u8]),
367 }
368
369 impl<'a> Record<'a> {
parse(buffer: &'a [u8]) -> Result<(&'a [u8], Record<'a>)>370 pub fn parse(buffer: &'a [u8]) -> Result<(&'a [u8], Record<'a>)> {
371 let (rest, _) = parse_name_part(buffer, |_| ())?;
372 let name = &buffer[..buffer.len() - rest.len()];
373
374 if rest.len() < 10 {
375 return Err(Error);
376 }
377 let type_ = NetworkEndian::read_u16(&rest[0..2]).into();
378 let class = NetworkEndian::read_u16(&rest[2..4]);
379 let ttl = NetworkEndian::read_u32(&rest[4..8]);
380 let len = NetworkEndian::read_u16(&rest[8..10]) as usize;
381 let rest = &rest[10..];
382
383 if class != CLASS_IN {
384 return Err(Error);
385 }
386
387 let data = rest.get(..len).ok_or(Error)?;
388 let rest = &rest[len..];
389
390 Ok((
391 rest,
392 Record {
393 name,
394 ttl,
395 data: RecordData::parse(type_, data)?,
396 },
397 ))
398 }
399 }
400
401 /// High-level DNS packet representation.
402 ///
403 /// Currently only supports query packets.
404 #[derive(Debug, PartialEq, Eq)]
405 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
406 pub struct Repr<'a> {
407 pub transaction_id: u16,
408 pub opcode: Opcode,
409 pub flags: Flags,
410 pub question: Question<'a>,
411 }
412
413 impl<'a> Repr<'a> {
414 /// Return the length of a packet that will be emitted from this high-level representation.
buffer_len(&self) -> usize415 pub const fn buffer_len(&self) -> usize {
416 field::HEADER_END + self.question.buffer_len()
417 }
418
419 /// Emit a high-level representation into a DNS packet.
emit<T: ?Sized>(&self, packet: &mut Packet<&mut T>) where T: AsRef<[u8]> + AsMut<[u8]>,420 pub fn emit<T: ?Sized>(&self, packet: &mut Packet<&mut T>)
421 where
422 T: AsRef<[u8]> + AsMut<[u8]>,
423 {
424 packet.set_transaction_id(self.transaction_id);
425 packet.set_flags(self.flags);
426 packet.set_opcode(self.opcode);
427 packet.set_question_count(1);
428 packet.set_answer_record_count(0);
429 packet.set_authority_record_count(0);
430 packet.set_additional_record_count(0);
431 self.question.emit(packet.payload_mut())
432 }
433 }
434
435 #[cfg(feature = "proto-ipv4")] // tests assume ipv4
436 #[cfg(test)]
437 mod test {
438 use super::*;
439 use std::vec::Vec;
440
441 #[test]
test_parse_name()442 fn test_parse_name() {
443 let bytes = &[
444 0x78, 0x6c, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77,
445 0x77, 0x77, 0x08, 0x66, 0x61, 0x63, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x03, 0x63, 0x6f,
446 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00,
447 0x05, 0xf3, 0x00, 0x11, 0x09, 0x73, 0x74, 0x61, 0x72, 0x2d, 0x6d, 0x69, 0x6e, 0x69,
448 0x04, 0x63, 0x31, 0x30, 0x72, 0xc0, 0x10, 0xc0, 0x2e, 0x00, 0x01, 0x00, 0x01, 0x00,
449 0x00, 0x00, 0x05, 0x00, 0x04, 0x1f, 0x0d, 0x53, 0x24,
450 ];
451 let packet = Packet::new_unchecked(bytes);
452
453 let name_vec = |bytes| {
454 let mut v = Vec::new();
455 packet
456 .parse_name(bytes)
457 .try_for_each(|label| label.map(|label| v.push(label)))
458 .map(|_| v)
459 };
460
461 //assert_eq!(parse_name_len(bytes, 0x0c), Ok(18));
462 assert_eq!(
463 name_vec(&bytes[0x0c..]),
464 Ok(vec![&b"www"[..], &b"facebook"[..], &b"com"[..]])
465 );
466 //assert_eq!(parse_name_len(bytes, 0x22), Ok(2));
467 assert_eq!(
468 name_vec(&bytes[0x22..]),
469 Ok(vec![&b"www"[..], &b"facebook"[..], &b"com"[..]])
470 );
471 //assert_eq!(parse_name_len(bytes, 0x2e), Ok(17));
472 assert_eq!(
473 name_vec(&bytes[0x2e..]),
474 Ok(vec![
475 &b"star-mini"[..],
476 &b"c10r"[..],
477 &b"facebook"[..],
478 &b"com"[..]
479 ])
480 );
481 //assert_eq!(parse_name_len(bytes, 0x3f), Ok(2));
482 assert_eq!(
483 name_vec(&bytes[0x3f..]),
484 Ok(vec![
485 &b"star-mini"[..],
486 &b"c10r"[..],
487 &b"facebook"[..],
488 &b"com"[..]
489 ])
490 );
491 }
492
493 struct Parsed<'a> {
494 packet: Packet<&'a [u8]>,
495 questions: Vec<Question<'a>>,
496 answers: Vec<Record<'a>>,
497 authorities: Vec<Record<'a>>,
498 additionals: Vec<Record<'a>>,
499 }
500
501 impl<'a> Parsed<'a> {
parse(bytes: &'a [u8]) -> Result<Self>502 fn parse(bytes: &'a [u8]) -> Result<Self> {
503 let packet = Packet::new_unchecked(bytes);
504 let mut questions = Vec::new();
505 let mut answers = Vec::new();
506 let mut authorities = Vec::new();
507 let mut additionals = Vec::new();
508
509 let mut payload = &bytes[12..];
510
511 for _ in 0..packet.question_count() {
512 let (p, r) = Question::parse(payload)?;
513 questions.push(r);
514 payload = p;
515 }
516 for _ in 0..packet.answer_record_count() {
517 let (p, r) = Record::parse(payload)?;
518 answers.push(r);
519 payload = p;
520 }
521 for _ in 0..packet.authority_record_count() {
522 let (p, r) = Record::parse(payload)?;
523 authorities.push(r);
524 payload = p;
525 }
526 for _ in 0..packet.additional_record_count() {
527 let (p, r) = Record::parse(payload)?;
528 additionals.push(r);
529 payload = p;
530 }
531
532 // Check that there are no bytes left
533 assert_eq!(payload.len(), 0);
534
535 Ok(Parsed {
536 packet,
537 questions,
538 answers,
539 authorities,
540 additionals,
541 })
542 }
543 }
544
545 #[test]
test_parse_request()546 fn test_parse_request() {
547 let p = Parsed::parse(&[
548 0x51, 0x84, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67,
549 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
550 ])
551 .unwrap();
552
553 assert_eq!(p.packet.transaction_id(), 0x5184);
554 assert_eq!(
555 p.packet.flags(),
556 Flags::RECURSION_DESIRED | Flags::AUTHENTIC_DATA
557 );
558 assert_eq!(p.packet.opcode(), Opcode::Query);
559 assert_eq!(p.packet.question_count(), 1);
560 assert_eq!(p.packet.answer_record_count(), 0);
561 assert_eq!(p.packet.authority_record_count(), 0);
562 assert_eq!(p.packet.additional_record_count(), 0);
563
564 assert_eq!(p.questions.len(), 1);
565 assert_eq!(
566 p.questions[0].name,
567 &[0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00]
568 );
569 assert_eq!(p.questions[0].type_, Type::A);
570
571 assert_eq!(p.answers.len(), 0);
572 assert_eq!(p.authorities.len(), 0);
573 assert_eq!(p.additionals.len(), 0);
574 }
575
576 #[test]
test_parse_response()577 fn test_parse_response() {
578 let p = Parsed::parse(&[
579 0x51, 0x84, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67,
580 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
581 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xca, 0x00, 0x04, 0xac, 0xd9,
582 0xa8, 0xae,
583 ])
584 .unwrap();
585
586 assert_eq!(p.packet.transaction_id(), 0x5184);
587 assert_eq!(
588 p.packet.flags(),
589 Flags::RESPONSE | Flags::RECURSION_DESIRED | Flags::RECURSION_AVAILABLE
590 );
591 assert_eq!(p.packet.opcode(), Opcode::Query);
592 assert_eq!(p.packet.rcode(), Rcode::NoError);
593 assert_eq!(p.packet.question_count(), 1);
594 assert_eq!(p.packet.answer_record_count(), 1);
595 assert_eq!(p.packet.authority_record_count(), 0);
596 assert_eq!(p.packet.additional_record_count(), 0);
597
598 assert_eq!(
599 p.questions[0].name,
600 &[0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00]
601 );
602 assert_eq!(p.questions[0].type_, Type::A);
603
604 assert_eq!(p.answers[0].name, &[0xc0, 0x0c]);
605 assert_eq!(p.answers[0].ttl, 202);
606 assert_eq!(
607 p.answers[0].data,
608 RecordData::A(Ipv4Address::new(0xac, 0xd9, 0xa8, 0xae))
609 );
610 }
611
612 #[test]
test_parse_response_multiple_a()613 fn test_parse_response_multiple_a() {
614 let p = Parsed::parse(&[
615 0x4b, 0x9e, 0x81, 0x80, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x72,
616 0x75, 0x73, 0x74, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00,
617 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00,
618 0x04, 0x0d, 0xe0, 0x77, 0x35, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
619 0x09, 0x00, 0x04, 0x0d, 0xe0, 0x77, 0x28, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,
620 0x00, 0x00, 0x09, 0x00, 0x04, 0x0d, 0xe0, 0x77, 0x43, 0xc0, 0x0c, 0x00, 0x01, 0x00,
621 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x04, 0x0d, 0xe0, 0x77, 0x62,
622 ])
623 .unwrap();
624
625 assert_eq!(p.packet.transaction_id(), 0x4b9e);
626 assert_eq!(
627 p.packet.flags(),
628 Flags::RESPONSE | Flags::RECURSION_DESIRED | Flags::RECURSION_AVAILABLE
629 );
630 assert_eq!(p.packet.opcode(), Opcode::Query);
631 assert_eq!(p.packet.rcode(), Rcode::NoError);
632 assert_eq!(p.packet.question_count(), 1);
633 assert_eq!(p.packet.answer_record_count(), 4);
634 assert_eq!(p.packet.authority_record_count(), 0);
635 assert_eq!(p.packet.additional_record_count(), 0);
636
637 assert_eq!(
638 p.questions[0].name,
639 &[
640 0x09, 0x72, 0x75, 0x73, 0x74, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x03, 0x6f, 0x72, 0x67,
641 0x00
642 ]
643 );
644 assert_eq!(p.questions[0].type_, Type::A);
645
646 assert_eq!(p.answers[0].name, &[0xc0, 0x0c]);
647 assert_eq!(p.answers[0].ttl, 9);
648 assert_eq!(
649 p.answers[0].data,
650 RecordData::A(Ipv4Address::new(0x0d, 0xe0, 0x77, 0x35))
651 );
652
653 assert_eq!(p.answers[1].name, &[0xc0, 0x0c]);
654 assert_eq!(p.answers[1].ttl, 9);
655 assert_eq!(
656 p.answers[1].data,
657 RecordData::A(Ipv4Address::new(0x0d, 0xe0, 0x77, 0x28))
658 );
659
660 assert_eq!(p.answers[2].name, &[0xc0, 0x0c]);
661 assert_eq!(p.answers[2].ttl, 9);
662 assert_eq!(
663 p.answers[2].data,
664 RecordData::A(Ipv4Address::new(0x0d, 0xe0, 0x77, 0x43))
665 );
666
667 assert_eq!(p.answers[3].name, &[0xc0, 0x0c]);
668 assert_eq!(p.answers[3].ttl, 9);
669 assert_eq!(
670 p.answers[3].data,
671 RecordData::A(Ipv4Address::new(0x0d, 0xe0, 0x77, 0x62))
672 );
673 }
674
675 #[test]
test_parse_response_cname()676 fn test_parse_response_cname() {
677 let p = Parsed::parse(&[
678 0x78, 0x6c, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77,
679 0x77, 0x77, 0x08, 0x66, 0x61, 0x63, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x03, 0x63, 0x6f,
680 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00,
681 0x05, 0xf3, 0x00, 0x11, 0x09, 0x73, 0x74, 0x61, 0x72, 0x2d, 0x6d, 0x69, 0x6e, 0x69,
682 0x04, 0x63, 0x31, 0x30, 0x72, 0xc0, 0x10, 0xc0, 0x2e, 0x00, 0x01, 0x00, 0x01, 0x00,
683 0x00, 0x00, 0x05, 0x00, 0x04, 0x1f, 0x0d, 0x53, 0x24,
684 ])
685 .unwrap();
686
687 assert_eq!(p.packet.transaction_id(), 0x786c);
688 assert_eq!(
689 p.packet.flags(),
690 Flags::RESPONSE | Flags::RECURSION_DESIRED | Flags::RECURSION_AVAILABLE
691 );
692 assert_eq!(p.packet.opcode(), Opcode::Query);
693 assert_eq!(p.packet.rcode(), Rcode::NoError);
694 assert_eq!(p.packet.question_count(), 1);
695 assert_eq!(p.packet.answer_record_count(), 2);
696 assert_eq!(p.packet.authority_record_count(), 0);
697 assert_eq!(p.packet.additional_record_count(), 0);
698
699 assert_eq!(
700 p.questions[0].name,
701 &[
702 0x03, 0x77, 0x77, 0x77, 0x08, 0x66, 0x61, 0x63, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x03,
703 0x63, 0x6f, 0x6d, 0x00
704 ]
705 );
706 assert_eq!(p.questions[0].type_, Type::A);
707
708 // cname
709 assert_eq!(p.answers[0].name, &[0xc0, 0x0c]);
710 assert_eq!(p.answers[0].ttl, 1523);
711 assert_eq!(
712 p.answers[0].data,
713 RecordData::Cname(&[
714 0x09, 0x73, 0x74, 0x61, 0x72, 0x2d, 0x6d, 0x69, 0x6e, 0x69, 0x04, 0x63, 0x31, 0x30,
715 0x72, 0xc0, 0x10
716 ])
717 );
718 // a
719 assert_eq!(p.answers[1].name, &[0xc0, 0x2e]);
720 assert_eq!(p.answers[1].ttl, 5);
721 assert_eq!(
722 p.answers[1].data,
723 RecordData::A(Ipv4Address::new(0x1f, 0x0d, 0x53, 0x24))
724 );
725 }
726
727 #[test]
test_parse_response_nxdomain()728 fn test_parse_response_nxdomain() {
729 let p = Parsed::parse(&[
730 0x63, 0xc4, 0x81, 0x83, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x61,
731 0x68, 0x61, 0x73, 0x64, 0x67, 0x68, 0x6c, 0x61, 0x6b, 0x73, 0x6a, 0x68, 0x62, 0x61,
732 0x61, 0x73, 0x6c, 0x64, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0,
733 0x20, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83, 0x00, 0x3d, 0x01, 0x61, 0x0c,
734 0x67, 0x74, 0x6c, 0x64, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x03, 0x6e,
735 0x65, 0x74, 0x00, 0x05, 0x6e, 0x73, 0x74, 0x6c, 0x64, 0x0c, 0x76, 0x65, 0x72, 0x69,
736 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0xc0, 0x20, 0x5f, 0xce, 0x8b, 0x85,
737 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x03, 0x84, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01,
738 0x51, 0x80,
739 ])
740 .unwrap();
741
742 assert_eq!(p.packet.transaction_id(), 0x63c4);
743 assert_eq!(
744 p.packet.flags(),
745 Flags::RESPONSE | Flags::RECURSION_DESIRED | Flags::RECURSION_AVAILABLE
746 );
747 assert_eq!(p.packet.opcode(), Opcode::Query);
748 assert_eq!(p.packet.rcode(), Rcode::NXDomain);
749 assert_eq!(p.packet.question_count(), 1);
750 assert_eq!(p.packet.answer_record_count(), 0);
751 assert_eq!(p.packet.authority_record_count(), 1);
752 assert_eq!(p.packet.additional_record_count(), 0);
753
754 assert_eq!(p.questions[0].type_, Type::A);
755
756 // SOA authority
757 assert_eq!(p.authorities[0].name, &[0xc0, 0x20]); // com.
758 assert_eq!(p.authorities[0].ttl, 899);
759 assert!(matches!(
760 p.authorities[0].data,
761 RecordData::Other(Type::Soa, _)
762 ));
763 }
764
765 #[test]
test_emit()766 fn test_emit() {
767 let name = &[
768 0x09, 0x72, 0x75, 0x73, 0x74, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x03, 0x6f, 0x72, 0x67,
769 0x00,
770 ];
771
772 let repr = Repr {
773 transaction_id: 0x1234,
774 flags: Flags::RECURSION_DESIRED,
775 opcode: Opcode::Query,
776 question: Question {
777 name,
778 type_: Type::A,
779 },
780 };
781
782 let mut buf = Vec::new();
783 buf.resize(repr.buffer_len(), 0);
784 repr.emit(&mut Packet::new_unchecked(&mut buf));
785
786 let want = &[
787 0x12, 0x34, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x72,
788 0x75, 0x73, 0x74, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00,
789 0x01, 0x00, 0x01,
790 ];
791 assert_eq!(&buf, want);
792 }
793 }
794