Skip to main content

mtop_client/dns/
rdata.rs

1use crate::core::MtopError;
2use crate::dns::bytes::{read_be_u8, read_be_u16, read_be_u32, write_be_u8, write_be_u16, write_be_u32};
3use crate::dns::core::RecordType;
4use crate::dns::name::Name;
5use std::fmt::{self, Display};
6use std::io::{Read, Seek, Write};
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: Write,
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: Read + 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: Write,
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: Read + 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: Write,
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: Read + 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: Write,
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: Read + 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: Write,
261    {
262        self.mname.write_network_bytes(&mut buf)?;
263        self.rname.write_network_bytes(&mut buf)?;
264        write_be_u32(&mut buf, self.serial)?;
265        write_be_u32(&mut buf, self.refresh)?;
266        write_be_u32(&mut buf, self.retry)?;
267        write_be_u32(&mut buf, self.expire)?;
268        write_be_u32(&mut buf, self.minimum)?;
269        Ok(())
270    }
271
272    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
273    where
274        T: Read + Seek,
275    {
276        let mname = Name::read_network_bytes(&mut buf)?;
277        let rname = Name::read_network_bytes(&mut buf)?;
278        let serial = read_be_u32(&mut buf)?;
279        let refresh = read_be_u32(&mut buf)?;
280        let retry = read_be_u32(&mut buf)?;
281        let expire = read_be_u32(&mut buf)?;
282        let minimum = read_be_u32(&mut buf)?;
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(Vec::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: Write,
354    {
355        for txt in &self.0 {
356            assert!(
357                txt.len() <= Self::MAX_SEGMENT_LENGTH,
358                "segment size of {} exceeds maximum of {}",
359                txt.len(),
360                Self::MAX_SEGMENT_LENGTH,
361            );
362
363            write_be_u8(&mut buf, u8::try_from(txt.len()).unwrap())?;
364            buf.write_all(txt)?;
365        }
366
367        Ok(())
368    }
369
370    pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
371    where
372        T: Read + Seek,
373    {
374        let rdata_len = usize::from(rdata_len);
375        let mut all = Vec::new();
376        let mut consumed = 0;
377
378        while consumed < rdata_len {
379            let len = read_be_u8(&mut buf)?;
380            if usize::from(len) + consumed > rdata_len {
381                return Err(MtopError::runtime(format!(
382                    "text for RecordDataTXT exceeds rdata size; len: {}, consumed: {}, rdata: {}",
383                    len, consumed, rdata_len
384                )));
385            }
386
387            let mut txt = Vec::with_capacity(usize::from(len));
388            let mut handle = buf.take(u64::from(len));
389            let n = handle.read_to_end(&mut txt)?;
390            if n != usize::from(len) {
391                return Err(MtopError::runtime(format!(
392                    "short read for RecordDataTXT text; expected {}, got {}",
393                    len, n
394                )));
395            }
396
397            all.push(txt);
398            consumed += n + 1;
399            buf = handle.into_inner();
400        }
401
402        Self::new(all)
403    }
404}
405
406impl Display for RecordDataTXT {
407    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408        for txt in &self.0 {
409            // We're trying to display the record so make an attempt at converting to
410            // a string but don't return an error or panic if there's invalid UTF-8. We
411            // also escape any double quotes within the string since we use those to
412            // delimit the string.
413            write!(f, "\"{}\"", String::from_utf8_lossy(txt).replace('\"', "\\\""))?;
414        }
415
416        Ok(())
417    }
418}
419
420#[derive(Debug, Clone, Eq, PartialEq)]
421pub struct RecordDataAAAA(Ipv6Addr);
422
423impl RecordDataAAAA {
424    pub fn new(addr: Ipv6Addr) -> Self {
425        Self(addr)
426    }
427
428    pub fn addr(&self) -> Ipv6Addr {
429        self.0
430    }
431
432    pub fn size(&self) -> usize {
433        16
434    }
435
436    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
437    where
438        T: Write,
439    {
440        Ok(buf.write_all(&self.0.octets())?)
441    }
442
443    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
444    where
445        T: Read + Seek,
446    {
447        let mut bytes = [0_u8; 16];
448        buf.read_exact(&mut bytes)?;
449        Ok(RecordDataAAAA::new(Ipv6Addr::from(bytes)))
450    }
451}
452
453impl Display for RecordDataAAAA {
454    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455        Display::fmt(&self.0, f)
456    }
457}
458
459#[derive(Debug, Clone, Eq, PartialEq)]
460pub struct RecordDataSRV {
461    priority: u16,
462    weight: u16,
463    port: u16,
464    target: Name,
465}
466
467impl RecordDataSRV {
468    pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> Self {
469        Self {
470            priority,
471            weight,
472            port,
473            target,
474        }
475    }
476
477    pub fn priority(&self) -> u16 {
478        self.priority
479    }
480
481    pub fn weight(&self) -> u16 {
482        self.weight
483    }
484
485    pub fn port(&self) -> u16 {
486        self.port
487    }
488
489    pub fn target(&self) -> &Name {
490        &self.target
491    }
492
493    pub fn size(&self) -> usize {
494        (2 * 3) + self.target.size()
495    }
496
497    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
498    where
499        T: Write,
500    {
501        write_be_u16(&mut buf, self.priority)?;
502        write_be_u16(&mut buf, self.weight)?;
503        write_be_u16(&mut buf, self.port)?;
504        self.target.write_network_bytes(buf)
505    }
506
507    pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
508    where
509        T: Read + Seek,
510    {
511        let priority = read_be_u16(&mut buf)?;
512        let weight = read_be_u16(&mut buf)?;
513        let port = read_be_u16(&mut buf)?;
514        let target = Name::read_network_bytes(buf)?;
515
516        Ok(Self::new(priority, weight, port, target))
517    }
518}
519
520impl Display for RecordDataSRV {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        write!(f, "{} {} {} {}", self.priority, self.weight, self.port, self.target)
523    }
524}
525
526#[derive(Debug, Clone, Eq, PartialEq)]
527pub struct RecordDataOptPair {
528    code: u16,
529    data: Vec<u8>,
530}
531
532impl RecordDataOptPair {
533    const MAX_DATA_LENGTH: usize = 65535;
534
535    pub fn new(code: u16, data: Vec<u8>) -> Result<Self, MtopError> {
536        if data.len() > Self::MAX_DATA_LENGTH {
537            Err(MtopError::runtime(format!(
538                "OPT attribute data too long; {} bytes, max {} bytes",
539                data.len(),
540                Self::MAX_DATA_LENGTH,
541            )))
542        } else {
543            Ok(Self { code, data })
544        }
545    }
546
547    pub fn code(&self) -> u16 {
548        self.code
549    }
550
551    pub fn data(&self) -> &[u8] {
552        &self.data
553    }
554
555    fn size(&self) -> usize {
556        2 + 2 + self.data.len() // code + data length + data
557    }
558
559    fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
560    where
561        T: Write,
562    {
563        assert!(
564            self.data.len() <= Self::MAX_DATA_LENGTH,
565            "data size of {} exceeds maximum of {}",
566            self.data.len(),
567            Self::MAX_DATA_LENGTH,
568        );
569
570        write_be_u16(&mut buf, self.code)?;
571        write_be_u16(&mut buf, u16::try_from(self.data.len()).unwrap())?;
572        Ok(buf.write_all(&self.data)?)
573    }
574
575    fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
576    where
577        T: Read + Seek,
578    {
579        let code = read_be_u16(&mut buf)?;
580        let data_len = read_be_u16(&mut buf)?;
581        let mut data = Vec::with_capacity(usize::from(data_len));
582        buf.take(u64::from(data_len)).read_to_end(&mut data)?;
583        Ok(Self { code, data })
584    }
585}
586
587impl Display for RecordDataOptPair {
588    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589        write!(f, "{}: {}", self.code, String::from_utf8_lossy(&self.data))
590    }
591}
592
593#[derive(Debug, Clone, Eq, PartialEq)]
594pub struct RecordDataOpt {
595    options: Vec<RecordDataOptPair>,
596}
597
598impl RecordDataOpt {
599    const MAX_LENGTH: usize = 65535;
600
601    pub fn new(options: Vec<RecordDataOptPair>) -> Result<Self, MtopError> {
602        let size = Self::options_size(&options);
603        if size > Self::MAX_LENGTH {
604            Err(MtopError::runtime(format!(
605                "OPT record data too long; {} bytes, max {} bytes",
606                size,
607                Self::MAX_LENGTH,
608            )))
609        } else {
610            Ok(Self { options })
611        }
612    }
613
614    fn options_size(opts: &[RecordDataOptPair]) -> usize {
615        opts.iter().map(RecordDataOptPair::size).sum()
616    }
617
618    pub fn options(&self) -> &[RecordDataOptPair] {
619        &self.options
620    }
621
622    pub fn size(&self) -> usize {
623        Self::options_size(&self.options)
624    }
625
626    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
627    where
628        T: Write,
629    {
630        for opt in &self.options {
631            opt.write_network_bytes(&mut buf)?;
632        }
633
634        Ok(())
635    }
636
637    pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
638    where
639        T: Read + Seek,
640    {
641        let rdata_len = usize::from(rdata_len);
642        let mut options = Vec::new();
643        let mut consumed = 0;
644
645        while consumed < rdata_len {
646            let opt = RecordDataOptPair::read_network_bytes(&mut buf)?;
647            consumed += opt.size();
648            options.push(opt);
649        }
650
651        Ok(Self { options })
652    }
653}
654
655impl Display for RecordDataOpt {
656    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657        for opt in &self.options {
658            write!(f, "{}", opt)?;
659        }
660
661        Ok(())
662    }
663}
664
665#[derive(Debug, Clone, Eq, PartialEq)]
666pub struct RecordDataUnknown(Vec<u8>);
667
668impl RecordDataUnknown {
669    const MAX_LENGTH: usize = 65535;
670
671    pub fn new(bytes: Vec<u8>) -> Result<Self, MtopError> {
672        if bytes.len() > Self::MAX_LENGTH {
673            Err(MtopError::runtime(format!(
674                "record data too long; {} bytes, max {} bytes",
675                bytes.len(),
676                Self::MAX_LENGTH
677            )))
678        } else {
679            Ok(Self(bytes))
680        }
681    }
682
683    pub fn size(&self) -> usize {
684        self.0.len()
685    }
686
687    pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
688    where
689        T: Write,
690    {
691        buf.write_all(&self.0)?;
692        Ok(())
693    }
694
695    pub fn read_network_bytes<T>(rdata_len: u16, buf: T) -> Result<Self, MtopError>
696    where
697        T: Read + Seek,
698    {
699        let mut bytes = Vec::with_capacity(usize::from(rdata_len));
700        let n = buf.take(u64::from(rdata_len)).read_to_end(&mut bytes)?;
701
702        if n == usize::from(rdata_len) {
703            Self::new(bytes)
704        } else {
705            Err(MtopError::runtime(format!(
706                "short read for RecordDataUnknown; expected {} got {}",
707                rdata_len, n
708            )))
709        }
710    }
711}
712
713impl Display for RecordDataUnknown {
714    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
715        write!(f, "[unknown]")
716    }
717}
718
719#[cfg(test)]
720mod test {
721    use super::{
722        RecordDataA, RecordDataAAAA, RecordDataCNAME, RecordDataNS, RecordDataOptPair, RecordDataSOA, RecordDataSRV,
723        RecordDataTXT,
724    };
725    use crate::dns::RecordDataOpt;
726    use crate::dns::name::Name;
727    use std::io::Cursor;
728    use std::net::{Ipv4Addr, Ipv6Addr};
729    use std::str::FromStr;
730
731    #[test]
732    fn test_record_data_a_write_network_bytes() {
733        let rdata = RecordDataA::new(Ipv4Addr::LOCALHOST);
734
735        let mut cur = Cursor::new(Vec::new());
736        rdata.write_network_bytes(&mut cur).unwrap();
737        let buf = cur.into_inner();
738
739        assert_eq!(vec![127, 0, 0, 1], buf);
740    }
741    #[test]
742    fn test_record_data_a_read_network_bytes() {
743        let cur = Cursor::new(vec![127, 0, 0, 1]);
744        let rdata = RecordDataA::read_network_bytes(cur).unwrap();
745
746        assert_eq!(Ipv4Addr::LOCALHOST, rdata.addr());
747    }
748
749    #[rustfmt::skip]
750    #[test]
751    fn test_record_data_ns_write_network_bytes() {
752        let name = Name::from_str("ns.example.com.").unwrap();
753        let ns = RecordDataNS::new(name);
754
755        let mut cur = Cursor::new(Vec::new());
756        ns.write_network_bytes(&mut cur).unwrap();
757        let buf = cur.into_inner();
758
759        assert_eq!(
760            vec![
761                2,                                // length
762                110, 115,                         // "ns"
763                7,                                // length
764                101, 120, 97, 109, 112, 108, 101, // "example"
765                3,                                // length
766                99, 111, 109,                     // "com"
767                0,                                // root
768            ],
769            buf,
770        );
771    }
772
773    #[rustfmt::skip]
774    #[test]
775    fn test_record_data_ns_read_network_bytes() {
776        let cur = Cursor::new(vec![
777            2,                                // length
778            110, 115,                         // "ns"
779            7,                                // length
780            101, 120, 97, 109, 112, 108, 101, // "example"
781            3,                                // length
782            99, 111, 109,                     // "com"
783            0,                                // root
784        ]);
785
786        let rdata = RecordDataNS::read_network_bytes(cur).unwrap();
787        assert_eq!("ns.example.com.", rdata.name().to_string());
788    }
789
790    #[rustfmt::skip]
791    #[test]
792    fn test_record_data_cname_write_network_bytes() {
793        let name = Name::from_str("www.example.com.").unwrap();
794        let ns = RecordDataCNAME::new(name);
795
796        let mut cur = Cursor::new(Vec::new());
797        ns.write_network_bytes(&mut cur).unwrap();
798        let buf = cur.into_inner();
799
800        assert_eq!(
801            vec![
802                3,                                // length
803                119, 119, 119,                    // "www"
804                7,                                // length
805                101, 120, 97, 109, 112, 108, 101, // "example"
806                3,                                // length
807                99, 111, 109,                     // "com"
808                0,                                // root
809            ],
810            buf,
811        );
812    }
813
814    #[rustfmt::skip]
815    #[test]
816    fn test_record_data_cname_read_network_bytes() {
817        let cur = Cursor::new(vec![
818            3,                                // length
819            119, 119, 119,                    // "www"
820            7,                                // length
821            101, 120, 97, 109, 112, 108, 101, // "example"
822            3,                                // length
823            99, 111, 109,                     // "com"
824            0,                                // root
825        ]);
826
827        let rdata = RecordDataCNAME::read_network_bytes(cur).unwrap();
828        assert_eq!("www.example.com.", rdata.name().to_string());
829    }
830
831    #[rustfmt::skip]
832    #[test]
833    fn test_record_data_soa_write_network_bytes() {
834        let mname = Name::from_str("m.example.com.").unwrap();
835        let rname = Name::from_str("r.example.com.").unwrap();
836        let serial = 123_456_790;
837        let refresh = 3000;
838        let retry = 300;
839        let expire = 3600;
840        let minimum = 600;
841
842        let soa = RecordDataSOA::new(mname, rname, serial, refresh, retry, expire, minimum);
843        let mut cur = Cursor::new(Vec::new());
844        soa.write_network_bytes(&mut cur).unwrap();
845        let buf = cur.into_inner();
846
847        assert_eq!(
848             vec![
849                1,                                // length
850                109,                              // "m"
851                7,                                // length
852                101, 120, 97, 109, 112, 108, 101, // "example"
853                3,                                // length
854                99, 111, 109,                     // "com"
855                0,                                // root
856                1,                                // length
857                114,                              // "r"
858                7,                                // length
859                101, 120, 97, 109, 112, 108, 101, // "example"
860                3,                                // length
861                99, 111, 109,                     // "com"
862                0,                                // root
863                7, 91, 205, 22,                   // serial
864                0, 0, 11, 184,                    // refresh
865                0, 0, 1, 44,                      // retry
866                0, 0, 14, 16,                     // expire
867                0, 0, 2, 88                       // minimum
868             ],
869             buf,
870         );
871    }
872
873    #[rustfmt::skip]
874    #[test]
875    fn test_record_data_soa_read_network_bytes() {
876        let cur = Cursor::new(vec![
877            1,                                // length
878            109,                              // "m"
879            7,                                // length
880            101, 120, 97, 109, 112, 108, 101, // "example"
881            3,                                // length
882            99, 111, 109,                     // "com"
883            0,                                // root
884            1,                                // length
885            114,                              // "r"
886            7,                                // length
887            101, 120, 97, 109, 112, 108, 101, // "example"
888            3,                                // length
889            99, 111, 109,                     // "com"
890            0,                                // root
891            7, 91, 205, 22,                   // serial
892            0, 0, 11, 184,                    // refresh
893            0, 0, 1, 44,                      // retry
894            0, 0, 14, 16,                     // expire
895            0, 0, 2, 88                       // minimum
896        ]);
897
898        let rdata = RecordDataSOA::read_network_bytes(cur).unwrap();
899        assert_eq!("m.example.com.", rdata.mname().to_string());
900        assert_eq!("r.example.com.", rdata.rname().to_string());
901        assert_eq!(123_456_790, rdata.serial());
902        assert_eq!(3000, rdata.refresh());
903        assert_eq!(300, rdata.retry());
904        assert_eq!(3600, rdata.expire());
905        assert_eq!(600, rdata.minimum());
906    }
907
908    #[test]
909    fn test_record_data_txt_new_exceeds_max_size() {
910        // Max total size of TXT record data is 65535 bytes. 255 bytes * 256 segments is
911        // 65280 bytes. BUT this doesn't account for the extra byte needed for each segment
912        // to store the length of the segment. In reality, we need 256 bytes for each segment
913        // so having 256 bytes * 256 segments should be an error.
914        let segment = "a".repeat(255);
915        let data: Vec<String> = (0..256).map(|_| segment.clone()).collect();
916        let res = RecordDataTXT::new(data);
917
918        assert!(res.is_err());
919    }
920
921    #[test]
922    fn test_record_data_txt_new_success() {
923        let segment = "a".repeat(255);
924        let data: Vec<String> = (0..255).map(|_| segment.clone()).collect();
925        let txt = RecordDataTXT::new(data).unwrap();
926
927        assert_eq!(65280, txt.size());
928    }
929
930    #[test]
931    fn test_record_data_txt_size() {
932        let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
933        assert_eq!(20, txt.size());
934    }
935
936    #[rustfmt::skip]
937    #[test]
938    fn test_record_data_txt_write_network_bytes() {
939        let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
940        let mut cur = Cursor::new(Vec::new());
941        txt.write_network_bytes(&mut cur).unwrap();
942        let buf = cur.into_inner();
943
944        assert_eq!(
945            vec![
946                8,                                               // length
947                105, 100, 61, 104, 101, 108, 108, 111,           // id=hello
948                10,                                              // length
949                117, 115, 101, 114, 61, 119, 111, 114, 108, 100, // user=world
950            ],
951            buf,
952        );
953    }
954
955    #[rustfmt::skip]
956    #[test]
957    fn test_record_data_txt_read_network_bytes() {
958        let bytes = vec![
959            8,                                               // length
960            105, 100, 61, 104, 101, 108, 108, 111,           // id=hello
961            10,                                              // length
962            117, 115, 101, 114, 61, 119, 111, 114, 108, 100, // user=world
963        ];
964        let bytes_len = u16::try_from(bytes.len()).unwrap();
965        let cur = Cursor::new(bytes);
966
967        let rdata = RecordDataTXT::read_network_bytes(bytes_len, cur).unwrap();
968        let contents = rdata.bytes();
969        assert_eq!("id=hello".as_bytes(), contents[0]);
970        assert_eq!("user=world".as_bytes(), contents[1]);
971    }
972
973    #[test]
974    fn test_record_data_aaaa_write_network_bytes() {
975        let addr = Ipv6Addr::LOCALHOST;
976        let rdata = RecordDataAAAA::new(addr);
977
978        let mut cur = Cursor::new(Vec::new());
979        rdata.write_network_bytes(&mut cur).unwrap();
980        let buf = cur.into_inner();
981
982        assert_eq!(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], buf);
983    }
984
985    #[test]
986    fn test_record_data_aaaa_read_network_bytes() {
987        let cur = Cursor::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
988        let rdata = RecordDataAAAA::read_network_bytes(cur).unwrap();
989
990        assert_eq!(Ipv6Addr::LOCALHOST, rdata.addr());
991    }
992
993    #[rustfmt::skip]
994    #[test]
995    fn test_record_data_srv_write_network_bytes() {
996        let srv = RecordDataSRV::new(100, 20, 11211, Name::from_str("_cache.example.com.").unwrap());
997        let mut cur = Cursor::new(Vec::new());
998        srv.write_network_bytes(&mut cur).unwrap();
999        let buf = cur.into_inner();
1000
1001        assert_eq!(
1002            vec![
1003                0, 100,                           // priority
1004                0, 20,                            // weight
1005                43, 203,                          // port
1006                6,                                // length
1007                95, 99, 97, 99, 104, 101,         // "_cache"
1008                7,                                // length
1009                101, 120, 97, 109, 112, 108, 101, // "example"
1010                3,                                // length
1011                99, 111, 109,                     // "com"
1012                0,                                // root
1013            ],
1014            buf,
1015        );
1016    }
1017
1018    #[rustfmt::skip]
1019    #[test]
1020    fn test_record_data_srv_read_network_bytes() {
1021        let cur = Cursor::new(vec![
1022            0, 100,                           // priority
1023            0, 20,                            // weight
1024            43, 203,                          // port
1025            6,                                // length
1026            95, 99, 97, 99, 104, 101,         // "_cache"
1027            7,                                // length
1028            101, 120, 97, 109, 112, 108, 101, // "example"
1029            3,                                // length
1030            99, 111, 109,                     // "com"
1031            0,                                // root
1032        ]);
1033
1034        let rdata = RecordDataSRV::read_network_bytes(cur).unwrap();
1035        assert_eq!(100, rdata.priority());
1036        assert_eq!(20, rdata.weight());
1037        assert_eq!(11211, rdata.port());
1038        assert_eq!("_cache.example.com.", rdata.target().to_string());
1039    }
1040
1041    #[test]
1042    fn test_record_data_opt_pair_new_exceeds_max_size() {
1043        let res = RecordDataOptPair::new(0, "a".repeat(65536).into_bytes());
1044        assert!(res.is_err());
1045    }
1046
1047    #[test]
1048    fn test_record_data_opt_pair_new_success() {
1049        let opt = RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap();
1050        assert_eq!(0, opt.code());
1051        assert_eq!(2 + 2 + 100, opt.size());
1052    }
1053
1054    #[test]
1055    fn test_record_data_opt_new_exceeds_max_size() {
1056        let opts = vec![
1057            RecordDataOptPair::new(0, "a".repeat(65535).into_bytes()).unwrap(),
1058            RecordDataOptPair::new(1, "a".repeat(65535).into_bytes()).unwrap(),
1059        ];
1060
1061        let res = RecordDataOpt::new(opts);
1062        assert!(res.is_err());
1063    }
1064
1065    #[test]
1066    fn test_record_data_opt_new_success() {
1067        let opts = vec![
1068            RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap(),
1069            RecordDataOptPair::new(1, "a".repeat(100).into_bytes()).unwrap(),
1070        ];
1071
1072        let res = RecordDataOpt::new(opts).unwrap();
1073        assert_eq!(2 * (2 + 2 + 100), res.size());
1074    }
1075
1076    #[rustfmt::skip]
1077    #[test]
1078    fn test_record_data_opt_write_network_bytes() {
1079        let opt = RecordDataOpt::new(vec![RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap()]).unwrap();
1080        let mut cur = Cursor::new(Vec::new());
1081        opt.write_network_bytes(&mut cur).unwrap();
1082        let buf = cur.into_inner();
1083
1084        assert_eq!(
1085            vec![
1086                0, 1,       // code
1087                0, 3,       // size
1088                97, 98, 99, // data
1089            ],
1090            buf,
1091        );
1092    }
1093
1094    #[rustfmt::skip]
1095    #[test]
1096    fn test_record_data_opt_read_network_bytes() {
1097        let cur = Cursor::new(vec![
1098            0, 1,       // code
1099            0, 3,       // size
1100            97, 98, 99, // data
1101        ]);
1102
1103        let rdata = RecordDataOpt::read_network_bytes(7, cur).unwrap();
1104        let options = rdata.options();
1105
1106        assert_eq!(
1107            RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap(),
1108            options[0]
1109        );
1110    }
1111}