smoltcp/wire/
dns.rs

1#![allow(dead_code)]
2
3use bitflags::bitflags;
4use byteorder::{ByteOrder, NetworkEndian};
5use core::iter;
6use core::iter::Iterator;
7
8use super::{Error, Result};
9#[cfg(feature = "proto-ipv4")]
10use crate::wire::Ipv4Address;
11#[cfg(feature = "proto-ipv6")]
12use crate::wire::Ipv6Address;
13
14enum_with_unknown! {
15    /// DNS OpCodes
16    pub enum Opcode(u8) {
17        Query  = 0x00,
18        Status = 0x01,
19    }
20}
21enum_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
38enum_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
49bitflags! {
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
62mod 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)
76const CLASS_IN: u16 = 1;
77
78/// A read/write wrapper around a DNS packet buffer.
79#[derive(Debug, PartialEq, Eq)]
80pub struct Packet<T: AsRef<[u8]>> {
81    buffer: T,
82}
83
84impl<T: AsRef<[u8]>> Packet<T> {
85    /// Imbue a raw octet buffer with DNS packet structure.
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
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.
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.
113    pub fn into_inner(self) -> T {
114        self.buffer
115    }
116
117    pub fn payload(&self) -> &[u8] {
118        &self.buffer.as_ref()[field::HEADER_END..]
119    }
120
121    pub fn transaction_id(&self) -> u16 {
122        let field = &self.buffer.as_ref()[field::ID];
123        NetworkEndian::read_u16(field)
124    }
125
126    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
131    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
137    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
143    pub fn question_count(&self) -> u16 {
144        let field = &self.buffer.as_ref()[field::QDCOUNT];
145        NetworkEndian::read_u16(field)
146    }
147
148    pub fn answer_record_count(&self) -> u16 {
149        let field = &self.buffer.as_ref()[field::ANCOUNT];
150        NetworkEndian::read_u16(field)
151    }
152
153    pub fn authority_record_count(&self) -> u16 {
154        let field = &self.buffer.as_ref()[field::NSCOUNT];
155        NetworkEndian::read_u16(field)
156    }
157
158    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.
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*** occurrence
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
213impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
214    pub fn payload_mut(&mut self) -> &mut [u8] {
215        let data = self.buffer.as_mut();
216        &mut data[field::HEADER_END..]
217    }
218
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
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
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
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    }
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    }
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    }
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.
260fn 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))]
289pub struct Question<'a> {
290    pub name: &'a [u8],
291    pub type_: Type,
292}
293
294impl<'a> 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.
314    pub const fn buffer_len(&self) -> usize {
315        self.name.len() + 4
316    }
317
318    /// Emit a high-level representation into a DNS packet.
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))]
329pub struct Record<'a> {
330    pub name: &'a [u8],
331    pub ttl: u32,
332    pub data: RecordData<'a>,
333}
334
335impl<'a> 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))]
360pub 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
369impl<'a> 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))]
406pub struct Repr<'a> {
407    pub transaction_id: u16,
408    pub opcode: Opcode,
409    pub flags: Flags,
410    pub question: Question<'a>,
411}
412
413impl<'a> Repr<'a> {
414    /// Return the length of a packet that will be emitted from this high-level representation.
415    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.
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)]
437mod test {
438    use super::*;
439    use std::vec::Vec;
440
441    #[test]
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> {
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]
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]
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]
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]
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]
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]
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}