Skip to main content

mtop_client/dns/
name.rs

1use crate::core::MtopError;
2use crate::dns::bytes::{read_be_u8, write_be_u8};
3use std::fmt;
4use std::io::{Read, Seek, SeekFrom, Write};
5use std::str::FromStr;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub struct Name {
9    labels: Vec<Vec<u8>>,
10    is_fqdn: bool,
11}
12
13impl Name {
14    const MAX_LENGTH: usize = 255;
15    const MAX_LABEL_LENGTH: usize = 63;
16    const MAX_POINTERS: u32 = 64;
17    const NUM_LABELS_HINT: usize = 4;
18
19    pub fn root() -> Self {
20        Name {
21            labels: Vec::new(),
22            is_fqdn: true,
23        }
24    }
25
26    pub fn size(&self) -> usize {
27        self.labels.iter().map(Vec::len).sum::<usize>() + self.labels.len() + 1
28    }
29
30    pub fn is_root(&self) -> bool {
31        self.labels.is_empty() && self.is_fqdn
32    }
33
34    pub fn is_fqdn(&self) -> bool {
35        self.is_fqdn
36    }
37
38    #[must_use]
39    pub fn to_fqdn(mut self) -> Self {
40        self.is_fqdn = true;
41        self
42    }
43
44    #[must_use]
45    pub fn append(mut self, other: Name) -> Self {
46        if self.is_fqdn {
47            return self;
48        }
49
50        self.labels.extend(other.labels);
51        Self {
52            labels: self.labels,
53            is_fqdn: other.is_fqdn,
54        }
55    }
56
57    pub fn write_network_bytes<T>(&self, mut out: T) -> Result<(), MtopError>
58    where
59        T: Write,
60    {
61        // We convert all incoming Names to fully qualified names. If we missed doing
62        // that, it's a bug and we should panic here. Encoded names all end with the
63        // root so trying to encode something that doesn't makes no sense.
64        assert!(self.is_fqdn, "only fully qualified domains can be encoded");
65        // It shouldn't be possible to create Name instances that exceed the max length
66        // so if we're being asked to encode one, it's a bug and we should panic here.
67        assert!(
68            self.size() <= Self::MAX_LENGTH,
69            "size {} of domain exceeds maximum of {}",
70            self.size(),
71            Self::MAX_LENGTH
72        );
73
74        for label in &self.labels {
75            // It shouldn't be possible to create Name instances with labels that
76            // exceed the max length for an individual label so if we're being asked
77            // to encode one, it's a bug and we should panic here.
78            assert!(
79                label.len() <= Self::MAX_LABEL_LENGTH,
80                "label length of {} exceeds maximum of {}",
81                label.len(),
82                Self::MAX_LABEL_LENGTH
83            );
84
85            write_be_u8(&mut out, u8::try_from(label.len()).unwrap())?;
86            out.write_all(label)?;
87        }
88
89        write_be_u8(&mut out, 0)
90    }
91
92    pub fn read_network_bytes<T>(mut inp: T) -> Result<Self, MtopError>
93    where
94        T: Read + Seek,
95    {
96        let mut labels = Vec::with_capacity(Self::NUM_LABELS_HINT);
97        Self::read_inner(&mut inp, &mut labels)?;
98
99        Ok(Self { labels, is_fqdn: true })
100    }
101
102    /// Read the DNS message format bytes for a `Name` and write them to `out`,
103    /// following any pointers (how names are compressed in DNS messages). The bytes
104    /// of each label is written into a `Vec<u8>`.
105    fn read_inner<T>(inp: &mut T, out: &mut Vec<Vec<u8>>) -> Result<(), MtopError>
106    where
107        T: Read + Seek,
108    {
109        let mut total_len = 0;
110        let mut pointers = 0;
111        let mut position = None;
112        loop {
113            // To avoid loops from badly behaved servers, only follow a fixed number of
114            // pointers when trying to resolve a single name. This number is picked to be
115            // much higher than most names will use but still finite.
116            if pointers > Self::MAX_POINTERS {
117                return Err(MtopError::runtime(format!(
118                    "reached max number of pointers ({}) while reading name",
119                    Self::MAX_POINTERS
120                )));
121            }
122
123            let len = read_be_u8(inp)?;
124            // If the length isn't a length but actually a pointer to another name
125            // or label within the message, seek to that position within the message
126            // and read the name from there. After resolving all pointers and reading
127            // labels, reset the stream back to immediately after the first pointer.
128            if Self::is_compressed_label(len) {
129                let offset = Self::get_offset(len, read_be_u8(inp)?);
130                if position.is_none() {
131                    position = Some(inp.stream_position()?);
132                }
133
134                inp.seek(SeekFrom::Start(u64::from(offset)))?;
135                pointers += 1;
136            } else if Self::is_standard_label(len) {
137                // If the length is a length, read the next label (segment) of the name
138                // returning early once we read the "root" label (`.`) signified by a
139                // length of 0.
140                let mut label = Vec::with_capacity(usize::from(len));
141                if Self::read_label_into(inp, total_len, len, &mut label)? {
142                    if let Some(p) = position {
143                        // If we followed a pointer to different part of the message while
144                        // parsing this name, seek to the position immediately after the
145                        // pointer now that we've finished parsing this name.
146                        inp.seek(SeekFrom::Start(p))?;
147                    }
148                    return Ok(());
149                }
150
151                total_len += label.len() + 1;
152                out.push(label);
153            } else {
154                // Binary labels are deprecated (RFC 6891) and there are (currently) no other
155                // types of labels that we should expect. Return an error to make this obvious.
156                return Err(MtopError::runtime(format!("unsupported Name label type: {}", len)));
157            }
158        }
159    }
160
161    /// If `len` doesn't indicate this is the root label, read the next name label into
162    /// `out` and return false, true if next label was the root.
163    fn read_label_into<T>(inp: &mut T, total_len: usize, len: u8, out: &mut Vec<u8>) -> Result<bool, MtopError>
164    where
165        T: Read + Seek,
166    {
167        if len == 0 {
168            return Ok(true);
169        }
170
171        // Only six bits of the length are supposed to be used to encode the
172        // length of a label so 63 is the max length but double check just in
173        // case one of the pointer bits was set for some reason.
174        if usize::from(len) > Self::MAX_LABEL_LENGTH {
175            return Err(MtopError::runtime(format!(
176                "max size for label would be exceeded reading {} bytes",
177                len,
178            )));
179        }
180
181        // Since we're only operating on a single label at a time, we need to be
182        // told the current total length of this name to validate it before we read
183        // the next label. Check the length of this label, one byte needed to record
184        // the length, the total so far, and one byte for the root.
185        if usize::from(len) + 1 + total_len + 1 > Self::MAX_LENGTH {
186            return Err(MtopError::runtime(format!(
187                "max size for name would be exceeded adding {} bytes to {}",
188                len, total_len
189            )));
190        }
191
192        let mut handle = inp.take(u64::from(len));
193        let n = handle.read_to_end(out)?;
194        if n != usize::from(len) {
195            return Err(MtopError::runtime(format!(
196                "short read for Name segment. expected {} got {}",
197                len, n
198            )));
199        }
200
201        Self::validate_label(out)?;
202        out.make_ascii_lowercase();
203        Ok(false)
204    }
205
206    fn validate_label(label: &[u8]) -> Result<(), MtopError> {
207        for (i, c) in label.iter().copied().map(char::from).enumerate() {
208            if i == 0 && c != '_' && !c.is_ascii_alphanumeric() {
209                return Err(MtopError::configuration(format!(
210                    "label must begin with ASCII letter, number, or underscore; got {}",
211                    c
212                )));
213            } else if i == label.len() - 1 && !c.is_ascii_alphanumeric() {
214                return Err(MtopError::configuration(format!(
215                    "label must end with ASCII letter or number; got {}",
216                    c
217                )));
218            } else if c != '-' && c != '_' && !c.is_ascii_alphanumeric() {
219                return Err(MtopError::configuration(format!(
220                    "label must be ASCII letter, number, hyphen, or underscore; got {}",
221                    c
222                )));
223            }
224        }
225
226        Ok(())
227    }
228
229    fn is_standard_label(len: u8) -> bool {
230        len & 0b1100_0000 == 0
231    }
232
233    fn is_compressed_label(len: u8) -> bool {
234        // The top two bits of the length byte of a name label (section) are used
235        // to indicate the name is actually an offset in the DNS message to a previous
236        // name to avoid duplicating the same names over and over.
237        len & 0b1100_0000 == 192
238    }
239
240    fn get_offset(len: u8, next: u8) -> u16 {
241        let pointer = u16::from(len & 0b0011_1111) << 8;
242        pointer | u16::from(next)
243    }
244
245    /// Construct a new `Name` from the bytes of a string representation of a domain
246    /// name, e.g. `"example.com.".as_bytes()`. This method validates the total length
247    /// of the name, the length of each label, and the characters used for each label.
248    /// An empty byte slice or a byte slice with only the ASCII `.` character are treated
249    /// as the root domain.
250    fn from_bytes(bytes: &[u8]) -> Result<Self, MtopError> {
251        if bytes.is_empty() || bytes == b"." {
252            return Ok(Self::root());
253        }
254
255        // Trim any trailing dot from the domain which indicates that it is fully qualified
256        // and make a note of it. This is required since we're splitting the domain into each
257        // individual label and need to know how to construct the correct string form afterward.
258        let (bytes, is_fqdn) = match bytes.strip_suffix(b".") {
259            Some(stripped) => (stripped, true),
260            None => (bytes, false),
261        };
262
263        // We add 2 to the length in bytes of the name since we need to account for the
264        // byte used for the length of the first label when in encoded form (as opposed
265        // to the text form using ASCII bytes) and the dot used to encode the root.
266        if bytes.len() + 2 > Self::MAX_LENGTH {
267            return Err(MtopError::configuration(format!(
268                "Name too long; max {} bytes, got {}",
269                Self::MAX_LENGTH,
270                bytes.len()
271            )));
272        }
273
274        let mut labels = Vec::with_capacity(Self::NUM_LABELS_HINT);
275        for label in bytes.split(|&b| b == b'.') {
276            if label.len() > Self::MAX_LABEL_LENGTH {
277                return Err(MtopError::configuration(format!(
278                    "label too long; max {} bytes, got {}",
279                    Self::MAX_LABEL_LENGTH,
280                    label.len(),
281                )));
282            }
283
284            Self::validate_label(label)?;
285            labels.push(label.to_ascii_lowercase());
286        }
287
288        Ok(Self { labels, is_fqdn })
289    }
290}
291
292impl fmt::Display for Name {
293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294        let len = self.labels.len();
295        for (i, l) in self.labels.iter().enumerate() {
296            // SAFETY: We only allow construction of Name instances with ASCII labels
297            unsafe { str::from_utf8_unchecked(l) }.fmt(f)?;
298            if i != len - 1 {
299                ".".fmt(f)?;
300            }
301        }
302        if self.is_fqdn {
303            ".".fmt(f)?;
304        }
305
306        Ok(())
307    }
308}
309
310impl FromStr for Name {
311    type Err = MtopError;
312
313    fn from_str(s: &str) -> Result<Self, Self::Err> {
314        Self::from_bytes(s.as_bytes())
315    }
316}
317
318#[cfg(test)]
319mod test {
320    use super::Name;
321    use std::io::Cursor;
322    use std::str::FromStr;
323
324    #[test]
325    fn test_name_from_str_error_max_length_fqdn() {
326        let parts = [
327            "a".repeat(Name::MAX_LABEL_LENGTH),
328            "b".repeat(Name::MAX_LABEL_LENGTH),
329            "c".repeat(Name::MAX_LABEL_LENGTH),
330            "d".repeat(Name::MAX_LABEL_LENGTH - 1),
331        ];
332
333        let complete = {
334            let mut s = parts.join(".");
335            s.push('.');
336            s
337        };
338
339        // We're testing a name with:
340        // 1b + 63b + 1b + 63b + 1b + 63b + 1b + 62b + 1b = 256b
341        // One byte for the length of each label and one byte for the root.
342        let res = Name::from_str(&complete);
343        assert!(res.is_err(), "expected an error, got {:?}", res);
344    }
345
346    #[test]
347    fn test_name_from_str_error_max_length_not_fqdn() {
348        let parts = [
349            "a".repeat(Name::MAX_LABEL_LENGTH),
350            "b".repeat(Name::MAX_LABEL_LENGTH),
351            "c".repeat(Name::MAX_LABEL_LENGTH),
352            "d".repeat(Name::MAX_LABEL_LENGTH - 1),
353        ];
354
355        let complete = parts.join(".");
356
357        // We're testing a name with:
358        // 1b + 63b + 1b + 63b + 1b + 63b + 1b + 62b = 255b
359        // that _omits_ the root from the end of the Name. We still need to
360        // validate that the Name is under the length limit including the root.
361        let res = Name::from_str(&complete);
362        assert!(res.is_err(), "expected an error, got {:?}", res);
363    }
364
365    #[test]
366    fn test_name_from_str_error_max_label() {
367        let parts = ["a".repeat(Name::MAX_LABEL_LENGTH + 1), "com.".to_owned()];
368        let res = Name::from_str(&parts.join("."));
369        assert!(res.is_err(), "expected an error, got {:?}", res);
370    }
371
372    #[test]
373    fn test_name_from_str_error_bad_label_start() {
374        let res = Name::from_str("-example.com.");
375        assert!(res.is_err(), "expected an error, got {:?}", res);
376    }
377
378    #[test]
379    fn test_name_from_str_error_bad_label_end() {
380        let res = Name::from_str("example-.com.");
381        assert!(res.is_err(), "expected an error, got {:?}", res);
382    }
383
384    #[test]
385    fn test_name_from_str_error_bad_label_char() {
386        let res = Name::from_str("exa%mple.com.");
387        assert!(res.is_err(), "expected an error, got {:?}", res);
388    }
389
390    #[test]
391    fn test_name_from_str_success_not_fqdn() {
392        let name = Name::from_str("example.com").unwrap();
393        assert!(!name.is_root());
394        assert!(!name.is_fqdn());
395    }
396
397    #[test]
398    fn test_name_from_str_success_fqdn() {
399        let name = Name::from_str("example.com.").unwrap();
400        assert!(!name.is_root());
401        assert!(name.is_fqdn());
402    }
403
404    #[test]
405    fn test_name_from_str_success_root_empty() {
406        let name = Name::from_str("").unwrap();
407        assert!(name.is_root());
408        assert!(name.is_fqdn());
409    }
410
411    #[test]
412    fn test_name_from_str_success_root_dot() {
413        let name = Name::from_str(".").unwrap();
414        assert!(name.is_root());
415        assert!(name.is_fqdn());
416    }
417
418    #[test]
419    fn test_name_to_string_not_fqdn() {
420        let name = Name::from_str("example.com").unwrap();
421        assert_eq!("example.com", name.to_string());
422        assert!(!name.is_fqdn());
423    }
424
425    #[test]
426    fn test_name_to_string_fqdn() {
427        let name = Name::from_str("example.com.").unwrap();
428        assert_eq!("example.com.", name.to_string());
429        assert!(name.is_fqdn());
430    }
431
432    #[test]
433    fn test_name_to_string_root() {
434        let name = Name::root();
435        assert_eq!(".", name.to_string());
436        assert!(name.is_fqdn());
437    }
438
439    #[test]
440    fn test_name_to_fqdn_not_fqdn() {
441        let name = Name::from_str("example.com").unwrap();
442        assert!(!name.is_fqdn());
443
444        let fqdn = name.to_fqdn();
445        assert!(fqdn.is_fqdn());
446    }
447
448    #[test]
449    fn test_name_to_fqdn_already_fqdn() {
450        let name = Name::from_str("example.com.").unwrap();
451        assert!(name.is_fqdn());
452
453        let fqdn = name.to_fqdn();
454        assert!(fqdn.is_fqdn());
455    }
456
457    #[test]
458    fn test_name_append_already_fqdn() {
459        let name1 = Name::from_str("example.com.").unwrap();
460        let name2 = Name::from_str("example.net.").unwrap();
461        let combined = name1.clone().append(name2);
462
463        assert_eq!(name1, combined);
464        assert!(combined.is_fqdn());
465    }
466
467    #[test]
468    fn test_name_append_with_non_fqdn() {
469        let name1 = Name::from_str("www").unwrap();
470        let name2 = Name::from_str("example").unwrap();
471        let combined = name1.clone().append(name2);
472
473        assert_eq!(Name::from_str("www.example").unwrap(), combined);
474        assert!(!combined.is_fqdn());
475    }
476
477    #[test]
478    fn test_name_append_with_fqdn() {
479        let name1 = Name::from_str("www").unwrap();
480        let name2 = Name::from_str("example.net.").unwrap();
481        let combined = name1.clone().append(name2);
482
483        assert_eq!(Name::from_str("www.example.net.").unwrap(), combined);
484        assert!(combined.is_fqdn());
485    }
486
487    #[test]
488    fn test_name_append_with_root() {
489        let name = Name::from_str("example.com").unwrap();
490        let combined = name.clone().append(Name::root());
491
492        assert_eq!(Name::from_str("example.com.").unwrap(), combined);
493        assert!(combined.is_fqdn());
494    }
495
496    #[test]
497    fn test_name_append_multiple() {
498        let name1 = Name::from_str("dev").unwrap();
499        let name2 = Name::from_str("www").unwrap();
500        let name3 = Name::from_str("example.com").unwrap();
501
502        let combined = name1.append(name2).append(name3).append(Name::root());
503        assert_eq!(Name::from_str("dev.www.example.com.").unwrap(), combined);
504        assert!(combined.is_fqdn());
505    }
506
507    #[test]
508    fn test_name_size_root() {
509        let name = Name::root();
510        assert_eq!(1, name.size());
511    }
512
513    #[test]
514    fn test_name_size_non_root() {
515        let name = Name::from_str("example.com.").unwrap();
516        assert_eq!(13, name.size());
517    }
518
519    #[test]
520    fn test_name_size_non_root_fqdn() {
521        let name = Name::from_str("example.com").unwrap();
522        assert!(!name.is_fqdn());
523        assert_eq!(13, name.size());
524
525        // The purpose of the .size() method is to figure out how many bytes this
526        // name would be when serialized to binary message format. Only FQDN can be
527        // serialized so we expect the size to be the same between the non-FQDN and
528        // FQDN version of this name.
529        let name = name.to_fqdn();
530        assert!(name.is_fqdn());
531        assert_eq!(13, name.size());
532    }
533
534    #[test]
535    fn test_name_equal_same_case() {
536        let name1 = Name::from_str("example.com.").unwrap();
537        let name2 = Name::from_str("example.com.").unwrap();
538
539        assert_eq!(name1, name2);
540    }
541
542    #[test]
543    fn test_name_equal_different_case() {
544        let name1 = Name::from_str("example.com.").unwrap();
545        let name2 = Name::from_str("EXAMPLE.cOm.").unwrap();
546
547        assert_eq!(name1, name2);
548    }
549
550    #[test]
551    fn test_name_equal_different_fqdn() {
552        let name1 = Name::from_str("example.com").unwrap();
553        let name2 = Name::from_str("example.com.").unwrap();
554
555        assert_ne!(name1, name2);
556    }
557
558    #[test]
559    fn test_name_write_network_bytes_root() {
560        let mut cur = Cursor::new(Vec::new());
561        let name = Name::root();
562        name.write_network_bytes(&mut cur).unwrap();
563        let buf = cur.into_inner();
564
565        assert_eq!(vec![0], buf);
566    }
567
568    #[rustfmt::skip]
569    #[test]
570    fn test_name_write_network_bytes_not_root() {
571        let mut cur = Cursor::new(Vec::new());
572        let name = Name::from_str("example.com.").unwrap();
573        name.write_network_bytes(&mut cur).unwrap();
574        let buf = cur.into_inner();
575
576        assert_eq!(
577            vec![
578                7,                                // length
579                101, 120, 97, 109, 112, 108, 101, // "example"
580                3,                                // length
581                99, 111, 109,                     // "com"
582                0,                                // root
583            ],
584            buf,
585        );
586    }
587
588    #[should_panic = "only fully qualified domains can be encoded"]
589    #[test]
590    fn test_name_write_network_bytes_not_fqdn() {
591        let mut cur = Cursor::new(Vec::new());
592        let name = Name::from_str("example.com").unwrap();
593        let _ = name.write_network_bytes(&mut cur);
594    }
595
596    #[rustfmt::skip]
597    #[test]
598    fn test_name_read_network_bytes_no_pointer() {
599        let cur = Cursor::new(vec![
600            7,                                // length
601            101, 120, 97, 109, 112, 108, 101, // "example"
602            3,                                // length
603            99, 111, 109,                     // "com"
604            0,                                // root
605        ]);
606
607        let name = Name::read_network_bytes(cur).unwrap();
608        assert_eq!("example.com.", name.to_string());
609        assert!(name.is_fqdn());
610    }
611
612    #[rustfmt::skip]
613    #[test]
614    fn test_name_read_network_bytes_bad_label_type() {
615        let cur = Cursor::new(vec![
616            64, // length, deprecated binary labels from RFC 2673
617            0,  // count of binary labels
618        ]);
619
620        let res = Name::read_network_bytes(cur);
621        assert!(res.is_err(), "expected an error, got {:?}", res);
622    }
623
624    #[rustfmt::skip]
625    #[test]
626    fn test_name_read_network_bytes_bad_label_type_after_single_pointer() {
627        let mut cur = Cursor::new(vec![
628            7,                                // length
629            101, 120, 97, 109, 112, 108, 101, // "example"
630            64,                               // length, deprecated binary labels from RFC 2673
631            0,                                // count of binary labels
632            3,                                // length
633            119, 119, 119,                    // "www"
634            192, 0,                           // pointer to offset 0
635        ]);
636
637        cur.set_position(10);
638
639        let res = Name::read_network_bytes(&mut cur);
640        assert!(res.is_err(), "expected an error, got {:?}", res);
641    }
642
643    #[rustfmt::skip]
644    #[test]
645    fn test_name_read_network_bytes_single_pointer() {
646        let mut cur = Cursor::new(vec![
647            7,                                // length
648            101, 120, 97, 109, 112, 108, 101, // "example"
649            3,                                // length
650            99, 111, 109,                     // "com"
651            0,                                // root
652            3,                                // length
653            119, 119, 119,                    // "www"
654            192, 0,                           // pointer to offset 0
655        ]);
656
657        cur.set_position(13);
658
659        let name = Name::read_network_bytes(&mut cur).unwrap();
660        assert_eq!("www.example.com.", name.to_string());
661        assert!(name.is_fqdn());
662        assert_eq!(19, cur.position());
663    }
664
665    #[rustfmt::skip]
666    #[test]
667    fn test_name_read_network_bytes_multiple_pointer() {
668        let mut cur = Cursor::new(vec![
669            7,                                // length
670            101, 120, 97, 109, 112, 108, 101, // "example"
671            3,                                // length
672            99, 111, 109,                     // "com"
673            0,                                // root
674            3,                                // length
675            119, 119, 119,                    // "www"
676            192, 0,                           // pointer to offset 0
677            3,                                // length
678            100, 101, 118,                    // "dev"
679            192, 13,                          // pointer to offset 13, "www"
680        ]);
681
682        cur.set_position(19);
683
684        let name = Name::read_network_bytes(&mut cur).unwrap();
685        assert_eq!("dev.www.example.com.", name.to_string());
686        assert!(name.is_fqdn());
687        assert_eq!(25, cur.position());
688    }
689
690    #[rustfmt::skip]
691    #[test]
692    fn test_name_read_network_bytes_multiple_pointer_multiple_name() {
693        let mut cur = Cursor::new(vec![
694            7,                                // length
695            101, 120, 97, 109, 112, 108, 101, // "example"
696            3,                                // length
697            99, 111, 109,                     // "com"
698            0,                                // root
699            3,                                // length
700            119, 119, 119,                    // "www"
701            192, 0,                           // pointer to offset 0
702            3,                                // length
703            100, 101, 118,                    // "dev"
704            192, 13,                          // pointer to offset 13, "www"
705        ]);
706
707        let name1 = Name::read_network_bytes(&mut cur).unwrap();
708        assert_eq!("example.com.", name1.to_string());
709        assert!(name1.is_fqdn());
710
711        let name2 = Name::read_network_bytes(&mut cur).unwrap();
712        assert_eq!("www.example.com.", name2.to_string());
713        assert!(name2.is_fqdn());
714
715        let name3 = Name::read_network_bytes(&mut cur).unwrap();
716        assert_eq!("dev.www.example.com.", name3.to_string());
717        assert!(name3.is_fqdn());
718
719        assert_eq!(25, cur.position());
720    }
721
722    #[rustfmt::skip]
723    #[test]
724    fn test_name_read_network_bytes_single_pointer_bad_chars() {
725        let mut cur = Cursor::new(vec![
726            7,                                // length
727            101, 120, 97, 37, 112, 108, 101, // "exa%ple"
728            3,                                // length
729            99, 111, 109,                     // "com"
730            0,                                // root
731            3,                                // length
732            119, 119, 119,                    // "www"
733            192, 0,                           // pointer to offset 0
734        ]);
735
736        cur.set_position(13);
737
738        let res = Name::read_network_bytes(&mut cur);
739        assert!(res.is_err(), "expected an error, got {:?}", res);
740    }
741
742    #[rustfmt::skip]
743    #[test]
744    fn test_name_read_network_bytes_single_pointer_normalize_case() {
745        let mut cur1 = Cursor::new(vec![
746            7,                                // length
747            101, 120, 97, 109, 112, 108, 101, // "example"
748            3,                                // length
749            99, 111, 109,                     // "com"
750            0,                                // root
751            3,                                // length
752            119, 119, 119,                    // "www"
753            192, 0,                           // pointer to offset 0
754        ]);
755
756        cur1.set_position(13);
757
758        let mut cur2 = Cursor::new(vec![
759            7,                                // length
760            101, 120, 97, 77, 112, 108, 101, // "exaMple"
761            3,                                // length
762            99, 111, 109,                     // "com"
763            0,                                // root
764            3,                                // length
765            119, 119, 119,                    // "www"
766            192, 0,                           // pointer to offset 0
767        ]);
768
769        cur2.set_position(13);
770
771        let name1 = Name::read_network_bytes(&mut cur1).unwrap();
772        let name2 = Name::read_network_bytes(&mut cur2).unwrap();
773        assert_eq!(name1, name2);
774    }
775
776    #[rustfmt::skip]
777    #[test]
778    fn test_name_read_network_bytes_invalid_label_length() {
779        let cur = Cursor::new(vec![
780            66,                               // length
781            101, 120, 97, 109, 112, 108, 101, // "example"
782            3,                                // length
783            99, 111, 109,                     // "com"
784            0,                                // root
785        ]);
786
787        let res = Name::read_network_bytes(cur);
788        assert!(res.is_err(), "expected an error, got {:?}", res);
789    }
790
791    #[rustfmt::skip]
792    #[test]
793    fn test_name_read_network_bytes_invalid_total_length() {
794        let label63 = vec![
795            63,                                // length
796            101, 120, 97, 109, 112, 108, 101, // "example"
797            101, 120, 97, 109, 112, 108, 101, // "example"
798            101, 120, 97, 109, 112, 108, 101, // "example"
799            101, 120, 97, 109, 112, 108, 101, // "example"
800            101, 120, 97, 109, 112, 108, 101, // "example"
801            101, 120, 97, 109, 112, 108, 101, // "example"
802            101, 120, 97, 109, 112, 108, 101, // "example"
803            101, 120, 97, 109, 112, 108, 101, // "example"
804            101, 120, 97, 109, 112, 108, 101, // "example"
805        ];
806
807        let label62 = vec![
808            62,                                // length
809            101, 120, 97, 109, 112, 108, 101, // "example"
810            101, 120, 97, 109, 112, 108, 101, // "example"
811            101, 120, 97, 109, 112, 108, 101, // "example"
812            101, 120, 97, 109, 112, 108, 101, // "example"
813            101, 120, 97, 109, 112, 108, 101, // "example"
814            101, 120, 97, 109, 112, 108, 101, // "example"
815            101, 120, 97, 109, 112, 108, 101, // "example"
816            101, 120, 97, 109, 112, 108, 101, // "example"
817            101, 120, 97, 109, 112, 108,      // "exampl"
818        ];
819
820        // Total length of label data and their length prefixes is 255 bytes.
821        // However, this should trigger an error since we need room for the root.
822        let mut complete = Vec::new();
823        complete.extend_from_slice(&label63); // label 1, 1+63 bytes
824        complete.extend_from_slice(&label63); // label 2, 1+63 bytes
825        complete.extend_from_slice(&label63); // label 3, 1+63 bytes
826        complete.extend_from_slice(&label62); // label 4, 1+62 bytes
827        complete.push(0u8);             // root
828
829        let res = Name::read_network_bytes(Cursor::new(complete));
830        assert!(res.is_err(), "expected an error, got {:?}", res);
831    }
832
833    #[test]
834    fn test_name_read_network_bytes_pointer_loop() {
835        let mut cur = Cursor::new(vec![
836            192, 2, // pointer to offset 2
837            192, 0, // pointer to offset 0
838        ]);
839
840        let res = Name::read_network_bytes(&mut cur);
841        assert!(res.is_err(), "expected an error, got {:?}", res);
842    }
843}