mtop_client/dns/
rdata.rs

1use crate::core::MtopError;
2use crate::dns::core::RecordType;
3use crate::dns::name::Name;
4use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
5use std::fmt::{self, Display};
6use std::io::{Read, Seek};
7use std::net::{Ipv4Addr, Ipv6Addr};
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub enum RecordData {
11    A(RecordDataA),
12    NS(RecordDataNS),
13    CNAME(RecordDataCNAME),
14    SOA(RecordDataSOA),
15    TXT(RecordDataTXT),
16    AAAA(RecordDataAAAA),
17    SRV(RecordDataSRV),
18    OPT(RecordDataOpt),
19    Unknown(RecordDataUnknown),
20}
21
22impl RecordData {
23    pub fn size(&self) -> usize {
24        match self {
25            Self::A(rd) => rd.size(),
26            Self::NS(rd) => rd.size(),
27            Self::CNAME(rd) => rd.size(),
28            Self::SOA(rd) => rd.size(),
29            Self::TXT(rd) => rd.size(),
30            Self::AAAA(rd) => rd.size(),
31            Self::SRV(rd) => rd.size(),
32            Self::OPT(rd) => rd.size(),
33            Self::Unknown(rd) => rd.size(),
34        }
35    }
36
37    pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
38    where
39        T: WriteBytesExt,
40    {
41        match self {
42            Self::A(rd) => rd.write_network_bytes(buf),
43            Self::NS(rd) => rd.write_network_bytes(buf),
44            Self::CNAME(rd) => rd.write_network_bytes(buf),
45            Self::SOA(rd) => rd.write_network_bytes(buf),
46            Self::TXT(rd) => rd.write_network_bytes(buf),
47            Self::AAAA(rd) => rd.write_network_bytes(buf),
48            Self::SRV(rd) => rd.write_network_bytes(buf),
49            Self::OPT(rd) => rd.write_network_bytes(buf),
50            Self::Unknown(rd) => rd.write_network_bytes(buf),
51        }
52    }
53
54    pub fn read_network_bytes<T>(rtype: RecordType, rdata_len: u16, buf: T) -> Result<Self, MtopError>
55    where
56        T: ReadBytesExt + Seek,
57    {
58        match rtype {
59            RecordType::A => Ok(RecordData::A(RecordDataA::read_network_bytes(buf)?)),
60            RecordType::NS => Ok(RecordData::NS(RecordDataNS::read_network_bytes(buf)?)),
61            RecordType::CNAME => Ok(RecordData::CNAME(RecordDataCNAME::read_network_bytes(buf)?)),
62            RecordType::SOA => Ok(RecordData::SOA(RecordDataSOA::read_network_bytes(buf)?)),
63            RecordType::TXT => Ok(RecordData::TXT(RecordDataTXT::read_network_bytes(rdata_len, buf)?)),
64            RecordType::AAAA => Ok(RecordData::AAAA(RecordDataAAAA::read_network_bytes(buf)?)),
65            RecordType::SRV => Ok(RecordData::SRV(RecordDataSRV::read_network_bytes(buf)?)),
66            RecordType::OPT => Ok(RecordData::OPT(RecordDataOpt::read_network_bytes(rdata_len, buf)?)),
67            RecordType::Unknown(_) => Ok(RecordData::Unknown(RecordDataUnknown::read_network_bytes(
68                rdata_len, buf,
69            )?)),
70        }
71    }
72}
73
74impl Display for RecordData {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            RecordData::A(rd) => Display::fmt(rd, f),
78            RecordData::NS(rd) => Display::fmt(rd, f),
79            RecordData::CNAME(rd) => Display::fmt(rd, f),
80            RecordData::SOA(rd) => Display::fmt(rd, f),
81            RecordData::TXT(rd) => Display::fmt(rd, f),
82            RecordData::AAAA(rd) => Display::fmt(rd, f),
83            RecordData::SRV(rd) => Display::fmt(rd, f),
84            RecordData::OPT(rd) => Display::fmt(rd, f),
85            RecordData::Unknown(rd) => Display::fmt(rd, f),
86        }
87    }
88}
89
90#[derive(Debug, Clone, Eq, PartialEq)]
91pub struct RecordDataA(Ipv4Addr);
92
93impl RecordDataA {
94    pub fn new(addr: Ipv4Addr) -> Self {
95        Self(addr)
96    }
97
98    pub fn addr(&self) -> Ipv4Addr {
99        self.0
100    }
101
102    pub fn size(&self) -> usize {
103        4
104    }
105
106    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
107    where
108        T: WriteBytesExt,
109    {
110        Ok(buf.write_all(&self.0.octets())?)
111    }
112
113    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
114    where
115        T: ReadBytesExt + Seek,
116    {
117        let mut bytes = [0_u8; 4];
118        buf.read_exact(&mut bytes)?;
119        Ok(RecordDataA::new(Ipv4Addr::from(bytes)))
120    }
121}
122
123impl Display for RecordDataA {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        Display::fmt(&self.0, f)
126    }
127}
128
129#[derive(Debug, Clone, Eq, PartialEq)]
130pub struct RecordDataNS(Name);
131
132impl RecordDataNS {
133    pub fn new(name: Name) -> Self {
134        Self(name)
135    }
136
137    pub fn name(&self) -> &Name {
138        &self.0
139    }
140
141    pub fn size(&self) -> usize {
142        self.0.size()
143    }
144
145    pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
146    where
147        T: WriteBytesExt,
148    {
149        self.0.write_network_bytes(buf)
150    }
151
152    pub fn read_network_bytes<T>(buf: T) -> Result<Self, MtopError>
153    where
154        T: ReadBytesExt + Seek,
155    {
156        Ok(Self::new(Name::read_network_bytes(buf)?))
157    }
158}
159
160impl Display for RecordDataNS {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        Display::fmt(&self.0, f)
163    }
164}
165
166#[derive(Debug, Clone, Eq, PartialEq)]
167pub struct RecordDataCNAME(Name);
168
169impl RecordDataCNAME {
170    pub fn new(name: Name) -> Self {
171        Self(name)
172    }
173
174    pub fn name(&self) -> &Name {
175        &self.0
176    }
177
178    pub fn size(&self) -> usize {
179        self.0.size()
180    }
181
182    pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
183    where
184        T: WriteBytesExt,
185    {
186        self.0.write_network_bytes(buf)
187    }
188
189    pub fn read_network_bytes<T>(buf: T) -> Result<Self, MtopError>
190    where
191        T: ReadBytesExt + Seek,
192    {
193        Ok(Self::new(Name::read_network_bytes(buf)?))
194    }
195}
196impl Display for RecordDataCNAME {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        Display::fmt(&self.0, f)
199    }
200}
201
202#[derive(Debug, Clone, Eq, PartialEq)]
203pub struct RecordDataSOA {
204    mname: Name,
205    rname: Name,
206    serial: u32,
207    refresh: u32,
208    retry: u32,
209    expire: u32,
210    minimum: u32,
211}
212
213impl RecordDataSOA {
214    pub fn new(mname: Name, rname: Name, serial: u32, refresh: u32, retry: u32, expire: u32, minimum: u32) -> Self {
215        Self {
216            mname,
217            rname,
218            serial,
219            refresh,
220            retry,
221            expire,
222            minimum,
223        }
224    }
225
226    pub fn mname(&self) -> &Name {
227        &self.mname
228    }
229
230    pub fn rname(&self) -> &Name {
231        &self.rname
232    }
233
234    pub fn serial(&self) -> u32 {
235        self.serial
236    }
237
238    pub fn refresh(&self) -> u32 {
239        self.refresh
240    }
241
242    pub fn retry(&self) -> u32 {
243        self.retry
244    }
245
246    pub fn expire(&self) -> u32 {
247        self.expire
248    }
249
250    pub fn minimum(&self) -> u32 {
251        self.minimum
252    }
253
254    pub fn size(&self) -> usize {
255        self.mname.size() + self.rname.size() + (4 * 5)
256    }
257
258    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
259    where
260        T: WriteBytesExt,
261    {
262        self.mname.write_network_bytes(&mut buf)?;
263        self.rname.write_network_bytes(&mut buf)?;
264        buf.write_u32::<NetworkEndian>(self.serial)?;
265        buf.write_u32::<NetworkEndian>(self.refresh)?;
266        buf.write_u32::<NetworkEndian>(self.retry)?;
267        buf.write_u32::<NetworkEndian>(self.expire)?;
268        buf.write_u32::<NetworkEndian>(self.minimum)?;
269        Ok(())
270    }
271
272    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
273    where
274        T: ReadBytesExt + Seek,
275    {
276        let mname = Name::read_network_bytes(&mut buf)?;
277        let rname = Name::read_network_bytes(&mut buf)?;
278        let serial = buf.read_u32::<NetworkEndian>()?;
279        let refresh = buf.read_u32::<NetworkEndian>()?;
280        let retry = buf.read_u32::<NetworkEndian>()?;
281        let expire = buf.read_u32::<NetworkEndian>()?;
282        let minimum = buf.read_u32::<NetworkEndian>()?;
283
284        Ok(Self::new(mname, rname, serial, refresh, retry, expire, minimum))
285    }
286}
287
288impl Display for RecordDataSOA {
289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290        write!(
291            f,
292            "{} {} {} {} {} {} {}",
293            self.mname, self.rname, self.serial, self.refresh, self.retry, self.expire, self.minimum
294        )
295    }
296}
297
298#[derive(Debug, Clone, Eq, PartialEq)]
299pub struct RecordDataTXT(Vec<Vec<u8>>);
300
301impl RecordDataTXT {
302    const MAX_LENGTH: usize = 65535;
303    const MAX_SEGMENT_LENGTH: usize = 255;
304
305    pub fn new<I, B>(items: I) -> Result<Self, MtopError>
306    where
307        I: IntoIterator<Item = B>,
308        B: Into<Vec<u8>>,
309    {
310        let mut segments = Vec::new();
311        let mut total = 0;
312
313        for txt in items {
314            let bytes = txt.into();
315            if bytes.len() > Self::MAX_SEGMENT_LENGTH {
316                return Err(MtopError::runtime(format!(
317                    "TXT record segment too long; {} bytes, max {} bytes",
318                    bytes.len(),
319                    Self::MAX_SEGMENT_LENGTH
320                )));
321            }
322
323            // One extra byte for each segment to store the length as a u8. This
324            // ensures that we don't allow the creation of RecordDataTXT objects
325            // that can't actually be serialized because they're too large.
326            total += 1 + bytes.len();
327            if total > Self::MAX_LENGTH {
328                return Err(MtopError::runtime(format!(
329                    "TXT record too long; {} bytes, max {} bytes",
330                    total,
331                    Self::MAX_LENGTH
332                )));
333            }
334
335            segments.push(bytes);
336        }
337
338        Ok(Self(segments))
339    }
340
341    pub fn bytes(&self) -> &Vec<Vec<u8>> {
342        &self.0
343    }
344
345    pub fn size(&self) -> usize {
346        // Total size is the size in bytes of each segment plus number of segments
347        // since the length of each is stored as a single u8
348        self.0.iter().map(|v| v.len()).sum::<usize>() + self.0.len()
349    }
350
351    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
352    where
353        T: WriteBytesExt,
354    {
355        for txt in self.0.iter() {
356            buf.write_u8(txt.len() as u8)?;
357            buf.write_all(txt)?;
358        }
359
360        Ok(())
361    }
362
363    pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
364    where
365        T: ReadBytesExt + Seek,
366    {
367        let rdata_len = usize::from(rdata_len);
368        let mut all = Vec::new();
369        let mut consumed = 0;
370
371        while consumed < rdata_len {
372            let len = buf.read_u8()?;
373            if usize::from(len) + consumed > rdata_len {
374                return Err(MtopError::runtime(format!(
375                    "text for RecordDataTXT exceeds rdata size; len: {}, consumed: {}, rdata: {}",
376                    len, consumed, rdata_len
377                )));
378            }
379
380            let mut txt = Vec::with_capacity(usize::from(len));
381            let mut handle = buf.take(u64::from(len));
382            let n = handle.read_to_end(&mut txt)?;
383            if n != usize::from(len) {
384                return Err(MtopError::runtime(format!(
385                    "short read for RecordDataTXT text; expected {}, got {}",
386                    len, n
387                )));
388            }
389
390            all.push(txt);
391            consumed += n + 1;
392            buf = handle.into_inner();
393        }
394
395        Self::new(all)
396    }
397}
398
399impl Display for RecordDataTXT {
400    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401        for txt in self.0.iter() {
402            // We're trying to display the record so make an attempt at converting to
403            // a string but don't return an error or panic if there's invalid UTF-8. We
404            // also escape any double quotes within the string since we use those to
405            // delimit the string.
406            write!(f, "\"{}\"", String::from_utf8_lossy(txt).replace('\"', "\\\""))?;
407        }
408
409        Ok(())
410    }
411}
412
413#[derive(Debug, Clone, Eq, PartialEq)]
414pub struct RecordDataAAAA(Ipv6Addr);
415
416impl RecordDataAAAA {
417    pub fn new(addr: Ipv6Addr) -> Self {
418        Self(addr)
419    }
420
421    pub fn addr(&self) -> Ipv6Addr {
422        self.0
423    }
424
425    pub fn size(&self) -> usize {
426        16
427    }
428
429    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
430    where
431        T: WriteBytesExt,
432    {
433        Ok(buf.write_all(&self.0.octets())?)
434    }
435
436    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
437    where
438        T: ReadBytesExt + Seek,
439    {
440        let mut bytes = [0_u8; 16];
441        buf.read_exact(&mut bytes)?;
442        Ok(RecordDataAAAA::new(Ipv6Addr::from(bytes)))
443    }
444}
445
446impl Display for RecordDataAAAA {
447    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448        Display::fmt(&self.0, f)
449    }
450}
451
452#[derive(Debug, Clone, Eq, PartialEq)]
453pub struct RecordDataSRV {
454    priority: u16,
455    weight: u16,
456    port: u16,
457    target: Name,
458}
459
460impl RecordDataSRV {
461    pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> Self {
462        Self {
463            priority,
464            weight,
465            port,
466            target,
467        }
468    }
469
470    pub fn priority(&self) -> u16 {
471        self.priority
472    }
473
474    pub fn weight(&self) -> u16 {
475        self.weight
476    }
477
478    pub fn port(&self) -> u16 {
479        self.port
480    }
481
482    pub fn target(&self) -> &Name {
483        &self.target
484    }
485
486    pub fn size(&self) -> usize {
487        (2 * 3) + self.target.size()
488    }
489
490    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
491    where
492        T: WriteBytesExt,
493    {
494        buf.write_u16::<NetworkEndian>(self.priority)?;
495        buf.write_u16::<NetworkEndian>(self.weight)?;
496        buf.write_u16::<NetworkEndian>(self.port)?;
497        self.target.write_network_bytes(buf)
498    }
499
500    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
501    where
502        T: ReadBytesExt + Seek,
503    {
504        let priority = buf.read_u16::<NetworkEndian>()?;
505        let weight = buf.read_u16::<NetworkEndian>()?;
506        let port = buf.read_u16::<NetworkEndian>()?;
507        let target = Name::read_network_bytes(buf)?;
508
509        Ok(Self::new(priority, weight, port, target))
510    }
511}
512
513impl Display for RecordDataSRV {
514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
515        write!(f, "{} {} {} {}", self.priority, self.weight, self.port, self.target)
516    }
517}
518
519#[derive(Debug, Clone, Eq, PartialEq)]
520pub struct RecordDataOptPair {
521    code: u16,
522    data: Vec<u8>,
523}
524
525impl RecordDataOptPair {
526    const MAX_DATA_LENGTH: usize = 65535;
527
528    pub fn new(code: u16, data: Vec<u8>) -> Result<Self, MtopError> {
529        if data.len() > Self::MAX_DATA_LENGTH {
530            Err(MtopError::runtime(format!(
531                "OPT attribute data too long; {} bytes, max {} bytes",
532                data.len(),
533                Self::MAX_DATA_LENGTH,
534            )))
535        } else {
536            Ok(Self { code, data })
537        }
538    }
539
540    pub fn code(&self) -> u16 {
541        self.code
542    }
543
544    pub fn data(&self) -> &[u8] {
545        &self.data
546    }
547
548    fn size(&self) -> usize {
549        2 + 2 + self.data.len() // code + data length + data
550    }
551
552    fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
553    where
554        T: WriteBytesExt,
555    {
556        buf.write_u16::<NetworkEndian>(self.code)?;
557        buf.write_u16::<NetworkEndian>(self.data.len() as u16)?;
558        Ok(buf.write_all(&self.data)?)
559    }
560
561    fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
562    where
563        T: ReadBytesExt + Seek,
564    {
565        let code = buf.read_u16::<NetworkEndian>()?;
566        let data_len = buf.read_u16::<NetworkEndian>()?;
567        let mut data = Vec::with_capacity(usize::from(data_len));
568        buf.take(u64::from(data_len)).read_to_end(&mut data)?;
569        Ok(Self { code, data })
570    }
571}
572
573impl Display for RecordDataOptPair {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        write!(f, "{}: {}", self.code, String::from_utf8_lossy(&self.data))
576    }
577}
578
579#[derive(Debug, Clone, Eq, PartialEq)]
580pub struct RecordDataOpt {
581    options: Vec<RecordDataOptPair>,
582}
583
584impl RecordDataOpt {
585    const MAX_LENGTH: usize = 65535;
586
587    pub fn new(options: Vec<RecordDataOptPair>) -> Result<Self, MtopError> {
588        let size = Self::options_size(&options);
589        if size > Self::MAX_LENGTH {
590            Err(MtopError::runtime(format!(
591                "OPT record data too long; {} bytes, max {} bytes",
592                size,
593                Self::MAX_LENGTH,
594            )))
595        } else {
596            Ok(Self { options })
597        }
598    }
599
600    fn options_size(opts: &[RecordDataOptPair]) -> usize {
601        opts.iter().map(|o| o.size()).sum()
602    }
603
604    pub fn options(&self) -> &[RecordDataOptPair] {
605        &self.options
606    }
607
608    pub fn size(&self) -> usize {
609        Self::options_size(&self.options)
610    }
611
612    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
613    where
614        T: WriteBytesExt,
615    {
616        for opt in self.options.iter() {
617            opt.write_network_bytes(&mut buf)?;
618        }
619
620        Ok(())
621    }
622
623    pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
624    where
625        T: ReadBytesExt + Seek,
626    {
627        let rdata_len = usize::from(rdata_len);
628        let mut options = Vec::new();
629        let mut consumed = 0;
630
631        while consumed < rdata_len {
632            let opt = RecordDataOptPair::read_network_bytes(&mut buf)?;
633            consumed += opt.size();
634            options.push(opt);
635        }
636
637        Ok(Self { options })
638    }
639}
640
641impl Display for RecordDataOpt {
642    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
643        for opt in self.options.iter() {
644            write!(f, "{}", opt)?;
645        }
646
647        Ok(())
648    }
649}
650
651#[derive(Debug, Clone, Eq, PartialEq)]
652pub struct RecordDataUnknown(Vec<u8>);
653
654impl RecordDataUnknown {
655    const MAX_LENGTH: usize = 65535;
656
657    pub fn new(bytes: Vec<u8>) -> Result<Self, MtopError> {
658        if bytes.len() > Self::MAX_LENGTH {
659            Err(MtopError::runtime(format!(
660                "record data too long; {} bytes, max {} bytes",
661                bytes.len(),
662                Self::MAX_LENGTH
663            )))
664        } else {
665            Ok(Self(bytes))
666        }
667    }
668
669    pub fn size(&self) -> usize {
670        self.0.len()
671    }
672
673    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
674    where
675        T: WriteBytesExt,
676    {
677        buf.write_all(&self.0)?;
678        Ok(())
679    }
680
681    pub fn read_network_bytes<T>(rdata_len: u16, buf: T) -> Result<Self, MtopError>
682    where
683        T: ReadBytesExt + Seek,
684    {
685        let mut bytes = Vec::with_capacity(usize::from(rdata_len));
686        let n = buf.take(u64::from(rdata_len)).read_to_end(&mut bytes)?;
687        if n != usize::from(rdata_len) {
688            Err(MtopError::runtime(format!(
689                "short read for RecordDataUnknown; expected {} got {}",
690                rdata_len, n
691            )))
692        } else {
693            Self::new(bytes)
694        }
695    }
696}
697
698impl Display for RecordDataUnknown {
699    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
700        write!(f, "[unknown]")
701    }
702}
703
704#[cfg(test)]
705mod test {
706    use super::{
707        RecordDataA, RecordDataAAAA, RecordDataCNAME, RecordDataNS, RecordDataOptPair, RecordDataSOA, RecordDataSRV,
708        RecordDataTXT,
709    };
710    use crate::dns::RecordDataOpt;
711    use crate::dns::name::Name;
712    use std::io::Cursor;
713    use std::net::{Ipv4Addr, Ipv6Addr};
714    use std::str::FromStr;
715
716    #[test]
717    fn test_record_data_a_write_network_bytes() {
718        let rdata = RecordDataA::new(Ipv4Addr::new(127, 0, 0, 1));
719
720        let mut cur = Cursor::new(Vec::new());
721        rdata.write_network_bytes(&mut cur).unwrap();
722        let buf = cur.into_inner();
723
724        assert_eq!(vec![127, 0, 0, 1], buf);
725    }
726    #[test]
727    fn test_record_data_a_read_network_bytes() {
728        let cur = Cursor::new(vec![127, 0, 0, 53]);
729        let rdata = RecordDataA::read_network_bytes(cur).unwrap();
730
731        assert_eq!(Ipv4Addr::new(127, 0, 0, 53), rdata.addr());
732    }
733
734    #[rustfmt::skip]
735    #[test]
736    fn test_record_data_ns_write_network_bytes() {
737        let name = Name::from_str("ns.example.com.").unwrap();
738        let ns = RecordDataNS::new(name);
739
740        let mut cur = Cursor::new(Vec::new());
741        ns.write_network_bytes(&mut cur).unwrap();
742        let buf = cur.into_inner();
743
744        assert_eq!(
745            vec![
746                2,                                // length
747                110, 115,                         // "ns"
748                7,                                // length
749                101, 120, 97, 109, 112, 108, 101, // "example"
750                3,                                // length
751                99, 111, 109,                     // "com"
752                0,                                // root
753            ],
754            buf,
755        );
756    }
757
758    #[rustfmt::skip]
759    #[test]
760    fn test_record_data_ns_read_network_bytes() {
761        let cur = Cursor::new(vec![
762            2,                                // length
763            110, 115,                         // "ns"
764            7,                                // length
765            101, 120, 97, 109, 112, 108, 101, // "example"
766            3,                                // length
767            99, 111, 109,                     // "com"
768            0,                                // root
769        ]);
770
771        let rdata = RecordDataNS::read_network_bytes(cur).unwrap();
772        assert_eq!("ns.example.com.", rdata.name().to_string());
773    }
774
775    #[rustfmt::skip]
776    #[test]
777    fn test_record_data_cname_write_network_bytes() {
778        let name = Name::from_str("www.example.com.").unwrap();
779        let ns = RecordDataCNAME::new(name);
780
781        let mut cur = Cursor::new(Vec::new());
782        ns.write_network_bytes(&mut cur).unwrap();
783        let buf = cur.into_inner();
784
785        assert_eq!(
786            vec![
787                3,                                // length
788                119, 119, 119,                    // "www"
789                7,                                // length
790                101, 120, 97, 109, 112, 108, 101, // "example"
791                3,                                // length
792                99, 111, 109,                     // "com"
793                0,                                // root
794            ],
795            buf,
796        );
797    }
798
799    #[rustfmt::skip]
800    #[test]
801    fn test_record_data_cname_read_network_bytes() {
802        let cur = Cursor::new(vec![
803            3,                                // length
804            119, 119, 119,                    // "www"
805            7,                                // length
806            101, 120, 97, 109, 112, 108, 101, // "example"
807            3,                                // length
808            99, 111, 109,                     // "com"
809            0,                                // root
810        ]);
811
812        let rdata = RecordDataCNAME::read_network_bytes(cur).unwrap();
813        assert_eq!("www.example.com.", rdata.name().to_string());
814    }
815
816    #[rustfmt::skip]
817    #[test]
818    fn test_record_data_soa_write_network_bytes() {
819        let mname = Name::from_str("m.example.com.").unwrap();
820        let rname = Name::from_str("r.example.com.").unwrap();
821        let serial = 123456790;
822        let refresh = 3000;
823        let retry = 300;
824        let expire = 3600;
825        let minimum = 600;
826
827        let soa = RecordDataSOA::new(mname, rname, serial, refresh, retry, expire, minimum);
828        let mut cur = Cursor::new(Vec::new());
829        soa.write_network_bytes(&mut cur).unwrap();
830        let buf = cur.into_inner();
831
832        assert_eq!(
833             vec![
834                1,                                // length
835                109,                              // "m"
836                7,                                // length
837                101, 120, 97, 109, 112, 108, 101, // "example"
838                3,                                // length
839                99, 111, 109,                     // "com"
840                0,                                // root
841                1,                                // length
842                114,                              // "r"
843                7,                                // length
844                101, 120, 97, 109, 112, 108, 101, // "example"
845                3,                                // length
846                99, 111, 109,                     // "com"
847                0,                                // root
848                7, 91, 205, 22,                   // serial
849                0, 0, 11, 184,                    // refresh
850                0, 0, 1, 44,                      // retry
851                0, 0, 14, 16,                     // expire
852                0, 0, 2, 88                       // minimum
853             ],
854             buf,
855         );
856    }
857
858    #[rustfmt::skip]
859    #[test]
860    fn test_record_data_soa_read_network_bytes() {
861        let cur = Cursor::new(vec![
862            1,                                // length
863            109,                              // "m"
864            7,                                // length
865            101, 120, 97, 109, 112, 108, 101, // "example"
866            3,                                // length
867            99, 111, 109,                     // "com"
868            0,                                // root
869            1,                                // length
870            114,                              // "r"
871            7,                                // length
872            101, 120, 97, 109, 112, 108, 101, // "example"
873            3,                                // length
874            99, 111, 109,                     // "com"
875            0,                                // root
876            7, 91, 205, 22,                   // serial
877            0, 0, 11, 184,                    // refresh
878            0, 0, 1, 44,                      // retry
879            0, 0, 14, 16,                     // expire
880            0, 0, 2, 88                       // minimum
881        ]);
882
883        let rdata = RecordDataSOA::read_network_bytes(cur).unwrap();
884        assert_eq!("m.example.com.", rdata.mname().to_string());
885        assert_eq!("r.example.com.", rdata.rname().to_string());
886        assert_eq!(123456790, rdata.serial());
887        assert_eq!(3000, rdata.refresh());
888        assert_eq!(300, rdata.retry());
889        assert_eq!(3600, rdata.expire());
890        assert_eq!(600, rdata.minimum());
891    }
892
893    #[test]
894    fn test_record_data_txt_new_exceeds_max_size() {
895        // Max total size of TXT record data is 65535 bytes. 255 bytes * 256 segments is
896        // 65280 bytes. BUT this doesn't account for the extra byte needed for each segment
897        // to store the length of the segment. In reality, we need 256 bytes for each segment
898        // so having 256 bytes * 256 segments should be an error.
899        let segment = "a".repeat(255);
900        let data: Vec<String> = (0..256).map(|_| segment.clone()).collect();
901        let res = RecordDataTXT::new(data);
902
903        assert!(res.is_err());
904    }
905
906    #[test]
907    fn test_record_data_txt_new_success() {
908        let segment = "a".repeat(255);
909        let data: Vec<String> = (0..255).map(|_| segment.clone()).collect();
910        let txt = RecordDataTXT::new(data).unwrap();
911
912        assert_eq!(65280, txt.size());
913    }
914
915    #[test]
916    fn test_record_data_txt_size() {
917        let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
918        assert_eq!(20, txt.size());
919    }
920
921    #[rustfmt::skip]
922    #[test]
923    fn test_record_data_txt_write_network_bytes() {
924        let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
925        let mut cur = Cursor::new(Vec::new());
926        txt.write_network_bytes(&mut cur).unwrap();
927        let buf = cur.into_inner();
928
929        assert_eq!(
930            vec![
931                8,                                               // length
932                105, 100, 61, 104, 101, 108, 108, 111,           // id=hello
933                10,                                              // length
934                117, 115, 101, 114, 61, 119, 111, 114, 108, 100, // user=world
935            ],
936            buf,
937        )
938    }
939
940    #[rustfmt::skip]
941    #[test]
942    fn test_record_data_txt_read_network_bytes() {
943        let bytes = vec![
944            8,                                               // length
945            105, 100, 61, 104, 101, 108, 108, 111,           // id=hello
946            10,                                              // length
947            117, 115, 101, 114, 61, 119, 111, 114, 108, 100, // user=world
948        ];
949        let bytes_len = bytes.len() as u16;
950        let cur = Cursor::new(bytes);
951
952        let rdata = RecordDataTXT::read_network_bytes(bytes_len, cur).unwrap();
953        let contents = rdata.bytes();
954        assert_eq!("id=hello".as_bytes(), contents[0]);
955        assert_eq!("user=world".as_bytes(), contents[1]);
956    }
957
958    #[test]
959    fn test_record_data_aaaa_write_network_bytes() {
960        let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
961        let rdata = RecordDataAAAA::new(addr);
962
963        let mut cur = Cursor::new(Vec::new());
964        rdata.write_network_bytes(&mut cur).unwrap();
965        let buf = cur.into_inner();
966
967        assert_eq!(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], buf);
968    }
969
970    #[test]
971    fn test_record_data_aaaa_read_network_bytes() {
972        let cur = Cursor::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
973        let rdata = RecordDataAAAA::read_network_bytes(cur).unwrap();
974
975        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), rdata.addr());
976    }
977
978    #[rustfmt::skip]
979    #[test]
980    fn test_record_data_srv_write_network_bytes() {
981        let srv = RecordDataSRV::new(100, 20, 11211, Name::from_str("_cache.example.com.").unwrap());
982        let mut cur = Cursor::new(Vec::new());
983        srv.write_network_bytes(&mut cur).unwrap();
984        let buf = cur.into_inner();
985
986        assert_eq!(
987            vec![
988                0, 100,                           // priority
989                0, 20,                            // weight
990                43, 203,                          // port
991                6,                                // length
992                95, 99, 97, 99, 104, 101,         // "_cache"
993                7,                                // length
994                101, 120, 97, 109, 112, 108, 101, // "example"
995                3,                                // length
996                99, 111, 109,                     // "com"
997                0,                                // root
998            ],
999            buf,
1000        )
1001    }
1002
1003    #[rustfmt::skip]
1004    #[test]
1005    fn test_record_data_srv_read_network_bytes() {
1006        let cur = Cursor::new(vec![
1007            0, 100,                           // priority
1008            0, 20,                            // weight
1009            43, 203,                          // port
1010            6,                                // length
1011            95, 99, 97, 99, 104, 101,         // "_cache"
1012            7,                                // length
1013            101, 120, 97, 109, 112, 108, 101, // "example"
1014            3,                                // length
1015            99, 111, 109,                     // "com"
1016            0,                                // root
1017        ]);
1018
1019        let rdata = RecordDataSRV::read_network_bytes(cur).unwrap();
1020        assert_eq!(100, rdata.priority());
1021        assert_eq!(20, rdata.weight());
1022        assert_eq!(11211, rdata.port());
1023        assert_eq!("_cache.example.com.", rdata.target().to_string());
1024    }
1025
1026    #[test]
1027    fn test_record_data_opt_pair_new_exceeds_max_size() {
1028        let res = RecordDataOptPair::new(0, "a".repeat(65536).into_bytes());
1029        assert!(res.is_err());
1030    }
1031
1032    #[test]
1033    fn test_record_data_opt_pair_new_success() {
1034        let opt = RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap();
1035        assert_eq!(0, opt.code());
1036        assert_eq!(2 + 2 + 100, opt.size());
1037    }
1038
1039    #[test]
1040    fn test_record_data_opt_new_exceeds_max_size() {
1041        let opts = vec![
1042            RecordDataOptPair::new(0, "a".repeat(65535).into_bytes()).unwrap(),
1043            RecordDataOptPair::new(1, "a".repeat(65535).into_bytes()).unwrap(),
1044        ];
1045
1046        let res = RecordDataOpt::new(opts);
1047        assert!(res.is_err());
1048    }
1049
1050    #[test]
1051    fn test_record_data_opt_new_success() {
1052        let opts = vec![
1053            RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap(),
1054            RecordDataOptPair::new(1, "a".repeat(100).into_bytes()).unwrap(),
1055        ];
1056
1057        let res = RecordDataOpt::new(opts).unwrap();
1058        assert_eq!(2 * (2 + 2 + 100), res.size());
1059    }
1060
1061    #[rustfmt::skip]
1062    #[test]
1063    fn test_record_data_opt_write_network_bytes() {
1064        let opt = RecordDataOpt::new(vec![RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap()]).unwrap();
1065        let mut cur = Cursor::new(Vec::new());
1066        opt.write_network_bytes(&mut cur).unwrap();
1067        let buf = cur.into_inner();
1068
1069        assert_eq!(
1070            vec![
1071                0, 1,       // code
1072                0, 3,       // size
1073                97, 98, 99, // data
1074            ],
1075            buf,
1076        )
1077    }
1078
1079    #[rustfmt::skip]
1080    #[test]
1081    fn test_record_data_opt_read_network_bytes() {
1082        let cur = Cursor::new(vec![
1083            0, 1,       // code
1084            0, 3,       // size
1085            97, 98, 99, // data
1086        ]);
1087
1088        let rdata = RecordDataOpt::read_network_bytes(7, cur).unwrap();
1089        let options = rdata.options();
1090
1091        assert_eq!(
1092            RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap(),
1093            options[0]
1094        );
1095    }
1096}