hickory_proto/rr/domain/
name.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! domain name, aka labels, implementation
9
10use std::char;
11use std::cmp::{Ordering, PartialEq};
12use std::fmt::{self, Write};
13use std::hash::{Hash, Hasher};
14use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
15use std::str::FromStr;
16
17use crate::error::*;
18use crate::rr::domain::label::{CaseInsensitive, CaseSensitive, IntoLabel, Label, LabelCmp};
19use crate::rr::domain::usage::LOCALHOST as LOCALHOST_usage;
20use crate::serialize::binary::*;
21use ipnet::{IpNet, Ipv4Net, Ipv6Net};
22#[cfg(feature = "serde-config")]
23use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
24use tinyvec::TinyVec;
25
26/// A domain name
27#[derive(Clone, Default, Eq)]
28pub struct Name {
29    is_fqdn: bool,
30    label_data: TinyVec<[u8; 32]>,
31    // This 24 is chosen because TinyVec accommodates an inline buffer up to 24 bytes without
32    // increasing its stack footprint
33    label_ends: TinyVec<[u8; 24]>,
34}
35
36impl Name {
37    /// Create a new domain::Name, i.e. label
38    pub fn new() -> Self {
39        Self::default()
40    }
41
42    /// Returns the root label, i.e. no labels, can probably make this better in the future.
43    pub fn root() -> Self {
44        let mut this = Self::new();
45        this.is_fqdn = true;
46        this
47    }
48
49    /// Extend the name with the offered label, and ensure maximum name length is not exceeded.
50    fn extend_name(&mut self, label: &[u8]) -> Result<(), ProtoError> {
51        self.label_data.extend_from_slice(label);
52        self.label_ends.push(self.label_data.len() as u8);
53        if self.len() > 255 {
54            return Err(ProtoErrorKind::DomainNameTooLong(self.len()).into());
55        };
56        Ok(())
57    }
58
59    /// Returns true if there are no labels, i.e. it's empty.
60    ///
61    /// In DNS the root is represented by `.`
62    ///
63    /// # Examples
64    ///
65    /// ```
66    /// use hickory_proto::rr::domain::Name;
67    ///
68    /// let root = Name::root();
69    /// assert_eq!(&root.to_string(), ".");
70    /// ```
71    pub fn is_root(&self) -> bool {
72        self.label_ends.is_empty() && self.is_fqdn()
73    }
74
75    /// Returns true if the name is a fully qualified domain name.
76    ///
77    /// If this is true, it has effects like only querying for this single name, as opposed to building
78    ///  up a search list in resolvers.
79    ///
80    /// *warning: this interface is unstable and may change in the future*
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use std::str::FromStr;
86    /// use hickory_proto::rr::domain::Name;
87    ///
88    /// let name = Name::from_str("www").unwrap();
89    /// assert!(!name.is_fqdn());
90    ///
91    /// let name = Name::from_str("www.example.com").unwrap();
92    /// assert!(!name.is_fqdn());
93    ///
94    /// let name = Name::from_str("www.example.com.").unwrap();
95    /// assert!(name.is_fqdn());
96    /// ```
97    pub fn is_fqdn(&self) -> bool {
98        self.is_fqdn
99    }
100
101    /// Specifies this name is a fully qualified domain name
102    ///
103    /// *warning: this interface is unstable and may change in the future*
104    pub fn set_fqdn(&mut self, val: bool) {
105        self.is_fqdn = val
106    }
107
108    /// Returns an iterator over the labels
109    pub fn iter(&self) -> LabelIter<'_> {
110        LabelIter {
111            name: self,
112            start: 0,
113            end: self.label_ends.len() as u8,
114        }
115    }
116
117    /// Appends the label to the end of this name
118    ///
119    /// # Example
120    ///
121    /// ```rust
122    /// use std::str::FromStr;
123    /// use hickory_proto::rr::domain::Name;
124    ///
125    /// let name = Name::from_str("www.example").unwrap();
126    /// let name = name.append_label("com").unwrap();
127    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
128    /// ```
129    pub fn append_label<L: IntoLabel>(mut self, label: L) -> ProtoResult<Self> {
130        self.extend_name(label.into_label()?.as_bytes())?;
131        Ok(self)
132    }
133
134    /// Creates a new Name from the specified labels
135    ///
136    /// # Arguments
137    ///
138    /// * `labels` - vector of items which will be stored as Strings.
139    ///
140    /// # Examples
141    ///
142    /// ```rust
143    /// use std::str::FromStr;
144    /// use hickory_proto::rr::domain::Name;
145    ///
146    /// // From strings, uses utf8 conversion
147    /// let from_labels = Name::from_labels(vec!["www", "example", "com"]).unwrap();
148    /// assert_eq!(from_labels, Name::from_str("www.example.com").unwrap());
149    ///
150    /// // Force a set of bytes into labels (this is none-standard and potentially dangerous)
151    /// let from_labels = Name::from_labels(vec!["bad chars".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
152    /// assert_eq!(from_labels.iter().next(), Some(&b"bad chars"[..]));
153    ///
154    /// let root = Name::from_labels(Vec::<&str>::new()).unwrap();
155    /// assert!(root.is_root());
156    /// ```
157    pub fn from_labels<I, L>(labels: I) -> ProtoResult<Self>
158    where
159        I: IntoIterator<Item = L>,
160        L: IntoLabel,
161    {
162        let (labels, errors): (Vec<_>, Vec<_>) = labels
163            .into_iter()
164            .map(IntoLabel::into_label)
165            .partition(Result::is_ok);
166        let labels: Vec<_> = labels.into_iter().map(Result::unwrap).collect();
167        let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
168
169        if labels.len() > 255 {
170            return Err(ProtoErrorKind::DomainNameTooLong(labels.len()).into());
171        };
172        if !errors.is_empty() {
173            return Err(format!("error converting some labels: {errors:?}").into());
174        };
175
176        let mut name = Self {
177            is_fqdn: true,
178            ..Self::default()
179        };
180        for label in labels {
181            name = name.append_label(label)?;
182        }
183
184        Ok(name)
185    }
186
187    /// Appends `other` to `self`, returning a new `Name`
188    ///
189    /// Carries forward `is_fqdn` from `other`.
190    ///
191    /// # Examples
192    ///
193    /// ```rust
194    /// use std::str::FromStr;
195    /// use hickory_proto::rr::domain::Name;
196    ///
197    /// let local = Name::from_str("www").unwrap();
198    /// let domain = Name::from_str("example.com").unwrap();
199    /// assert!(!domain.is_fqdn());
200    ///
201    /// let name = local.clone().append_name(&domain).unwrap();
202    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
203    /// assert!(!name.is_fqdn());
204    ///
205    /// // see also `Name::append_domain`
206    /// let domain = Name::from_str("example.com.").unwrap();
207    /// assert!(domain.is_fqdn());
208    /// let name = local.append_name(&domain).unwrap();
209    /// assert_eq!(name, Name::from_str("www.example.com.").unwrap());
210    /// assert!(name.is_fqdn());
211    /// ```
212    pub fn append_name(mut self, other: &Self) -> Result<Self, ProtoError> {
213        for label in other.iter() {
214            self.extend_name(label)?;
215        }
216
217        self.is_fqdn = other.is_fqdn;
218        Ok(self)
219    }
220
221    /// Appends the `domain` to `self`, making the new `Name` an FQDN
222    ///
223    /// This is an alias for `append_name` with the added effect of marking the new `Name` as
224    /// a fully-qualified-domain-name.
225    ///
226    /// # Examples
227    ///
228    /// ```rust
229    /// use std::str::FromStr;
230    /// use hickory_proto::rr::domain::Name;
231    ///
232    /// let local = Name::from_str("www").unwrap();
233    /// let domain = Name::from_str("example.com").unwrap();
234    /// let name = local.append_domain(&domain).unwrap();
235    /// assert_eq!(name, Name::from_str("www.example.com").unwrap());
236    /// assert!(name.is_fqdn())
237    /// ```
238    pub fn append_domain(self, domain: &Self) -> Result<Self, ProtoError> {
239        let mut this = self.append_name(domain)?;
240        this.set_fqdn(true);
241        Ok(this)
242    }
243
244    /// Creates a new Name with all labels lowercased
245    ///
246    /// # Examples
247    ///
248    /// ```
249    /// use std::cmp::Ordering;
250    /// use std::str::FromStr;
251    ///
252    /// use hickory_proto::rr::domain::{Label, Name};
253    ///
254    /// let example_com = Name::from_ascii("Example.Com").unwrap();
255    /// assert_eq!(example_com.cmp_case(&Name::from_str("example.com").unwrap()), Ordering::Less);
256    /// assert!(example_com.to_lowercase().eq_case(&Name::from_str("example.com").unwrap()));
257    /// ```
258    pub fn to_lowercase(&self) -> Self {
259        let new_label_data = self
260            .label_data
261            .iter()
262            .map(|c| c.to_ascii_lowercase())
263            .collect();
264        Self {
265            is_fqdn: self.is_fqdn,
266            label_data: new_label_data,
267            label_ends: self.label_ends.clone(),
268        }
269    }
270
271    /// Trims off the first part of the name, to help with searching for the domain piece
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// use std::str::FromStr;
277    /// use hickory_proto::rr::domain::Name;
278    ///
279    /// let example_com = Name::from_str("example.com.").unwrap();
280    /// assert_eq!(example_com.base_name(), Name::from_str("com.").unwrap());
281    /// assert_eq!(Name::from_str("com.").unwrap().base_name(), Name::root());
282    /// assert_eq!(Name::root().base_name(), Name::root());
283    /// ```
284    pub fn base_name(&self) -> Self {
285        let length = self.label_ends.len();
286        if length > 0 {
287            return self.trim_to(length - 1);
288        }
289        self.clone()
290    }
291
292    /// Trims to the number of labels specified
293    ///
294    /// # Examples
295    ///
296    /// ```
297    /// use std::str::FromStr;
298    /// use hickory_proto::rr::domain::Name;
299    ///
300    /// let example_com = Name::from_str("example.com.").unwrap();
301    /// assert_eq!(example_com.trim_to(2), Name::from_str("example.com.").unwrap());
302    /// assert_eq!(example_com.trim_to(1), Name::from_str("com.").unwrap());
303    /// assert_eq!(example_com.trim_to(0), Name::root());
304    /// assert_eq!(example_com.trim_to(3), Name::from_str("example.com.").unwrap());
305    /// ```
306    pub fn trim_to(&self, num_labels: usize) -> Self {
307        if num_labels > self.label_ends.len() {
308            self.clone()
309        } else {
310            Self::from_labels(self.iter().skip(self.label_ends.len() - num_labels)).unwrap()
311        }
312    }
313
314    /// same as `zone_of` allows for case sensitive call
315    pub fn zone_of_case(&self, name: &Self) -> bool {
316        let self_len = self.label_ends.len();
317        let name_len = name.label_ends.len();
318        if self_len == 0 {
319            return true;
320        }
321        if name_len == 0 {
322            // self_len != 0
323            return false;
324        }
325        if self_len > name_len {
326            return false;
327        }
328
329        let self_iter = self.iter().rev();
330        let name_iter = name.iter().rev();
331
332        let zip_iter = self_iter.zip(name_iter);
333
334        for (self_label, name_label) in zip_iter {
335            if self_label != name_label {
336                return false;
337            }
338        }
339
340        true
341    }
342
343    /// returns true if the name components of self are all present at the end of name
344    ///
345    /// # Example
346    ///
347    /// ```rust
348    /// use std::str::FromStr;
349    /// use hickory_proto::rr::domain::Name;
350    ///
351    /// let name = Name::from_str("www.example.com").unwrap();
352    /// let name = Name::from_str("www.example.com").unwrap();
353    /// let zone = Name::from_str("example.com").unwrap();
354    /// let another = Name::from_str("example.net").unwrap();
355    /// assert!(zone.zone_of(&name));
356    /// assert!(!name.zone_of(&zone));
357    /// assert!(!another.zone_of(&name));
358    /// ```
359    pub fn zone_of(&self, name: &Self) -> bool {
360        let self_lower = self.to_lowercase();
361        let name_lower = name.to_lowercase();
362
363        self_lower.zone_of_case(&name_lower)
364    }
365
366    /// Returns the number of labels in the name, discounting `*`.
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// use std::str::FromStr;
372    /// use hickory_proto::rr::domain::Name;
373    ///
374    /// let root = Name::root();
375    /// assert_eq!(root.num_labels(), 0);
376    ///
377    /// let example_com = Name::from_str("example.com").unwrap();
378    /// assert_eq!(example_com.num_labels(), 2);
379    ///
380    /// let star_example_com = Name::from_str("*.example.com.").unwrap();
381    /// assert_eq!(star_example_com.num_labels(), 2);
382    /// ```
383    pub fn num_labels(&self) -> u8 {
384        // it is illegal to have more than 256 labels.
385
386        let num = self.label_ends.len() as u8;
387
388        self.iter()
389            .next()
390            .map(|l| if l == b"*" { num - 1 } else { num })
391            .unwrap_or(num)
392    }
393
394    /// returns the length in bytes of the labels. '.' counts as 1
395    ///
396    /// This can be used as an estimate, when serializing labels, they will often be compressed
397    /// and/or escaped causing the exact length to be different.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use std::str::FromStr;
403    /// use hickory_proto::rr::domain::Name;
404    ///
405    /// assert_eq!(Name::from_str("www.example.com.").unwrap().len(), 16);
406    /// assert_eq!(Name::from_str(".").unwrap().len(), 1);
407    /// assert_eq!(Name::root().len(), 1);
408    /// ```
409    pub fn len(&self) -> usize {
410        let dots = if !self.label_ends.is_empty() {
411            self.label_ends.len()
412        } else {
413            1
414        };
415        dots + self.label_data.len()
416    }
417
418    /// Returns whether the length of the labels, in bytes is 0. In practice, since '.' counts as
419    /// 1, this is never the case so the method returns false.
420    pub fn is_empty(&self) -> bool {
421        false
422    }
423
424    /// attempts to parse a name such as `"example.com."` or `"subdomain.example.com."`
425    ///
426    /// # Examples
427    ///
428    /// ```rust
429    /// use std::str::FromStr;
430    /// use hickory_proto::rr::domain::Name;
431    ///
432    /// let name = Name::from_str("example.com.").unwrap();
433    /// assert_eq!(name.base_name(), Name::from_str("com.").unwrap());
434    /// assert_eq!(name.iter().next(), Some(&b"example"[..]));
435    /// ```
436    pub fn parse(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
437        Self::from_encoded_str::<LabelEncUtf8>(local, origin)
438    }
439
440    /// Will convert the string to a name only allowing ascii as valid input
441    ///
442    /// This method will also preserve the case of the name where that's desirable
443    ///
444    /// # Examples
445    ///
446    /// ```
447    /// use hickory_proto::rr::Name;
448    ///
449    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
450    /// let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
451    /// let lower_name = Name::from_ascii("www.example.com.").unwrap();
452    ///
453    /// assert!(bytes_name.eq_case(&ascii_name));
454    /// assert!(!lower_name.eq_case(&ascii_name));
455    ///
456    /// // escaped values
457    /// let bytes_name = Name::from_labels(vec!["email.name".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
458    /// let name = Name::from_ascii("email\\.name.example.com.").unwrap();
459    ///
460    /// assert_eq!(bytes_name, name);
461    ///
462    /// let bytes_name = Name::from_labels(vec!["bad.char".as_bytes(), "example".as_bytes(), "com".as_bytes()]).unwrap();
463    /// let name = Name::from_ascii("bad\\056char.example.com.").unwrap();
464    ///
465    /// assert_eq!(bytes_name, name);
466    /// ```
467    pub fn from_ascii<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
468        Self::from_encoded_str::<LabelEncAscii>(name.as_ref(), None)
469    }
470
471    // TODO: currently reserved to be private to the crate, due to confusion of IDNA vs. utf8 in https://tools.ietf.org/html/rfc6762#appendix-F
472    /// Will convert the string to a name using IDNA, punycode, to encode the UTF8 as necessary
473    ///
474    /// When making names IDNA compatible, there is a side-effect of lowercasing the name.
475    ///
476    /// # Examples
477    ///
478    /// ```
479    /// use std::str::FromStr;
480    /// use hickory_proto::rr::Name;
481    ///
482    /// let bytes_name = Name::from_labels(vec!["WWW".as_bytes(), "example".as_bytes(), "COM".as_bytes()]).unwrap();
483    ///
484    /// // from_str calls through to from_utf8
485    /// let utf8_name = Name::from_str("WWW.example.COM.").unwrap();
486    /// let lower_name = Name::from_str("www.example.com.").unwrap();
487    ///
488    /// assert!(!bytes_name.eq_case(&utf8_name));
489    /// assert!(lower_name.eq_case(&utf8_name));
490    /// ```
491    pub fn from_utf8<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
492        Self::from_encoded_str::<LabelEncUtf8>(name.as_ref(), None)
493    }
494
495    /// First attempts to decode via `from_utf8`, if that fails IDNA checks, then falls back to
496    /// ascii decoding.
497    ///
498    /// # Examples
499    ///
500    /// ```
501    /// use std::str::FromStr;
502    /// use hickory_proto::rr::Name;
503    ///
504    /// // Ok, underscore in the beginning of a name
505    /// assert!(Name::from_utf8("_allows.example.com.").is_ok());
506    ///
507    /// // Error, underscore in the end
508    /// assert!(Name::from_utf8("dis_allowed.example.com.").is_err());
509    ///
510    /// // Ok, relaxed mode
511    /// assert!(Name::from_str_relaxed("allow_in_.example.com.").is_ok());
512    /// ```
513    pub fn from_str_relaxed<S: AsRef<str>>(name: S) -> ProtoResult<Self> {
514        let name = name.as_ref();
515        Self::from_utf8(name).or_else(|_| Self::from_ascii(name))
516    }
517
518    fn from_encoded_str<E: LabelEnc>(local: &str, origin: Option<&Self>) -> ProtoResult<Self> {
519        let mut name = Self::new();
520        let mut label = String::new();
521
522        let mut state = ParseState::Label;
523
524        // short circuit root parse
525        if local == "." {
526            name.set_fqdn(true);
527            return Ok(name);
528        }
529
530        // TODO: it would be nice to relocate this to Label, but that is hard because the label boundary can only be detected after processing escapes...
531        // evaluate all characters
532        for ch in local.chars() {
533            match state {
534                ParseState::Label => match ch {
535                    '.' => {
536                        name = name.append_label(E::to_label(&label)?)?;
537                        label.clear();
538                    }
539                    '\\' => state = ParseState::Escape1,
540                    ch if !ch.is_control() && !ch.is_whitespace() => label.push(ch),
541                    _ => return Err(format!("unrecognized char: {ch}").into()),
542                },
543                ParseState::Escape1 => {
544                    if ch.is_numeric() {
545                        state = ParseState::Escape2(
546                            ch.to_digit(8)
547                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
548                        );
549                    } else {
550                        // it's a single escaped char
551                        label.push(ch);
552                        state = ParseState::Label;
553                    }
554                }
555                ParseState::Escape2(i) => {
556                    if ch.is_numeric() {
557                        state = ParseState::Escape3(
558                            i,
559                            ch.to_digit(8)
560                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?,
561                        );
562                    } else {
563                        return Err(ProtoError::from(format!("unrecognized char: {ch}")));
564                    }
565                }
566                ParseState::Escape3(i, ii) => {
567                    if ch.is_numeric() {
568                        // octal conversion
569                        let val: u32 = (i * 8 * 8)
570                            + (ii * 8)
571                            + ch.to_digit(8)
572                                .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
573                        let new: char = char::from_u32(val)
574                            .ok_or_else(|| ProtoError::from(format!("illegal char: {ch}")))?;
575                        label.push(new);
576                        state = ParseState::Label;
577                    } else {
578                        return Err(format!("unrecognized char: {ch}").into());
579                    }
580                }
581            }
582        }
583
584        if !label.is_empty() {
585            name = name.append_label(E::to_label(&label)?)?;
586        }
587
588        if local.ends_with('.') {
589            name.set_fqdn(true);
590        } else if let Some(other) = origin {
591            return name.append_domain(other);
592        }
593
594        Ok(name)
595    }
596
597    /// Emits the canonical version of the name to the encoder.
598    ///
599    /// In canonical form, there will be no pointers written to the encoder (i.e. no compression).
600    pub fn emit_as_canonical(
601        &self,
602        encoder: &mut BinEncoder<'_>,
603        canonical: bool,
604    ) -> ProtoResult<()> {
605        let buf_len = encoder.len(); // lazily assert the size is less than 255...
606                                     // lookup the label in the BinEncoder
607                                     // if it exists, write the Pointer
608        let labels = self.iter();
609
610        // start index of each label
611        let mut labels_written = Vec::with_capacity(self.label_ends.len());
612        // we're going to write out each label, tracking the indexes of the start to each label
613        //   then we'll look to see if we can remove them and recapture the capacity in the buffer...
614        for label in labels {
615            if label.len() > 63 {
616                return Err(ProtoErrorKind::LabelBytesTooLong(label.len()).into());
617            }
618
619            labels_written.push(encoder.offset());
620            encoder.emit_character_data(label)?;
621        }
622        let last_index = encoder.offset();
623        // now search for other labels already stored matching from the beginning label, strip then to the end
624        //   if it's not found, then store this as a new label
625        for label_idx in &labels_written {
626            match encoder.get_label_pointer(*label_idx, last_index) {
627                // if writing canonical and already found, continue
628                Some(_) if canonical => continue,
629                Some(loc) if !canonical => {
630                    // reset back to the beginning of this label, and then write the pointer...
631                    encoder.set_offset(*label_idx);
632                    encoder.trim();
633
634                    // write out the pointer marker
635                    //  or'd with the location which shouldn't be larger than this 2^14 or 16k
636                    encoder.emit_u16(0xC000u16 | (loc & 0x3FFFu16))?;
637
638                    // we found a pointer don't write more, break
639                    return Ok(());
640                }
641                _ => {
642                    // no existing label exists, store this new one.
643                    encoder.store_label_pointer(*label_idx, last_index);
644                }
645            }
646        }
647
648        // if we're getting here, then we didn't write out a pointer and are ending the name
649        // the end of the list of names
650        encoder.emit(0)?;
651
652        // the entire name needs to be less than 256.
653        let length = encoder.len() - buf_len;
654        if length > 255 {
655            return Err(ProtoErrorKind::DomainNameTooLong(length).into());
656        }
657
658        Ok(())
659    }
660
661    /// Writes the labels, as lower case, to the encoder
662    ///
663    /// # Arguments
664    ///
665    /// * `encoder` - encoder for writing this name
666    /// * `lowercase` - if true the name will be lowercased, otherwise it will not be changed when writing
667    pub fn emit_with_lowercase(
668        &self,
669        encoder: &mut BinEncoder<'_>,
670        lowercase: bool,
671    ) -> ProtoResult<()> {
672        let is_canonical_names = encoder.is_canonical_names();
673        if lowercase {
674            self.to_lowercase()
675                .emit_as_canonical(encoder, is_canonical_names)
676        } else {
677            self.emit_as_canonical(encoder, is_canonical_names)
678        }
679    }
680
681    /// compares with the other label, ignoring case
682    fn cmp_with_f<F: LabelCmp>(&self, other: &Self) -> Ordering {
683        if self.label_ends.is_empty() && other.label_ends.is_empty() {
684            return Ordering::Equal;
685        }
686
687        // we reverse the iters so that we are comparing from the root/domain to the local...
688        let self_labels = self.iter().rev();
689        let other_labels = other.iter().rev();
690
691        for (l, r) in self_labels.zip(other_labels) {
692            let l = Label::from_raw_bytes(l).unwrap();
693            let r = Label::from_raw_bytes(r).unwrap();
694            match l.cmp_with_f::<F>(&r) {
695                Ordering::Equal => continue,
696                not_eq => return not_eq,
697            }
698        }
699
700        self.label_ends.len().cmp(&other.label_ends.len())
701    }
702
703    /// Case sensitive comparison
704    pub fn cmp_case(&self, other: &Self) -> Ordering {
705        self.cmp_with_f::<CaseSensitive>(other)
706    }
707
708    /// Compares the Names, in a case sensitive manner
709    pub fn eq_case(&self, other: &Self) -> bool {
710        self.cmp_with_f::<CaseSensitive>(other) == Ordering::Equal
711    }
712
713    /// Converts this name into an ascii safe string.
714    ///
715    /// If the name is an IDNA name, then the name labels will be returned with the `xn--` prefix.
716    ///  see `to_utf8` or the `Display` impl for methods which convert labels to utf8.
717    pub fn to_ascii(&self) -> String {
718        let mut s = String::with_capacity(self.len());
719        self.write_labels::<String, LabelEncAscii>(&mut s)
720            .expect("string conversion of name should not fail");
721        s
722    }
723
724    /// Converts the Name labels to the utf8 String form.
725    ///
726    /// This converts the name to an unescaped format, that could be used with parse. If, the name is
727    ///  is followed by the final `.`, e.g. as in `www.example.com.`, which represents a fully
728    ///  qualified Name.
729    pub fn to_utf8(&self) -> String {
730        format!("{self}")
731    }
732
733    /// Converts a *.arpa Name in a PTR record back into an IpNet if possible.
734    pub fn parse_arpa_name(&self) -> Result<IpNet, ProtoError> {
735        if !self.is_fqdn() {
736            return Err("PQDN cannot be valid arpa name".into());
737        }
738        let mut iter = self.iter().rev();
739        let first = iter
740            .next()
741            .ok_or_else(|| ProtoError::from("not an arpa address"))?;
742        if !"arpa".eq_ignore_ascii_case(std::str::from_utf8(first)?) {
743            return Err("not an arpa address".into());
744        }
745        let second = iter
746            .next()
747            .ok_or_else(|| ProtoError::from("invalid arpa address"))?;
748        let mut prefix_len: u8 = 0;
749        match &std::str::from_utf8(second)?.to_ascii_lowercase()[..] {
750            "in-addr" => {
751                let mut octets: [u8; 4] = [0; 4];
752                for octet in octets.iter_mut() {
753                    match iter.next() {
754                        Some(label) => *octet = std::str::from_utf8(label)?.parse()?,
755                        None => break,
756                    }
757                    prefix_len += 8;
758                }
759                if iter.next().is_some() {
760                    return Err("unrecognized in-addr.arpa.".into());
761                }
762                Ok(IpNet::V4(
763                    Ipv4Net::new(octets.into(), prefix_len).expect("Ipv4Net::new"),
764                ))
765            }
766            "ip6" => {
767                let mut address: u128 = 0;
768                while prefix_len < 128 {
769                    match iter.next() {
770                        Some(label) => {
771                            if label.len() == 1 {
772                                prefix_len += 4;
773                                let hex = u8::from_str_radix(std::str::from_utf8(label)?, 16)?;
774                                address |= u128::from(hex) << (128 - prefix_len);
775                            } else {
776                                return Err("invalid label length for ip6.arpa".into());
777                            }
778                        }
779                        None => break,
780                    }
781                }
782                if iter.next().is_some() {
783                    return Err("unrecognized ip6.arpa.".into());
784                }
785                Ok(IpNet::V6(
786                    Ipv6Net::new(address.into(), prefix_len).expect("Ipv6Net::new"),
787                ))
788            }
789            _ => Err("unrecognized arpa address".into()),
790        }
791    }
792
793    fn write_labels<W: Write, E: LabelEnc>(&self, f: &mut W) -> Result<(), fmt::Error> {
794        let mut iter = self.iter().map(|b| Label::from_raw_bytes(b).unwrap());
795        if let Some(label) = iter.next() {
796            E::write_label(f, &label)?;
797        }
798
799        for label in iter {
800            write!(f, ".")?;
801            E::write_label(f, &label)?;
802        }
803
804        // if it was the root name
805        if self.is_root() || self.is_fqdn() {
806            write!(f, ".")?;
807        }
808        Ok(())
809    }
810
811    /// Returns true if the `Name` is either localhost or in the localhost zone.
812    ///
813    /// # Example
814    ///
815    /// ```
816    /// use std::str::FromStr;
817    /// use hickory_proto::rr::Name;
818    ///
819    /// let name = Name::from_str("localhost").unwrap();
820    /// assert!(name.is_localhost());
821    ///
822    /// let name = Name::from_str("localhost.").unwrap();
823    /// assert!(name.is_localhost());
824    ///
825    /// let name = Name::from_str("my.localhost.").unwrap();
826    /// assert!(name.is_localhost());
827    /// ```
828    pub fn is_localhost(&self) -> bool {
829        LOCALHOST_usage.zone_of(self)
830    }
831
832    /// True if the first label of this name is the wildcard, i.e. '*'
833    ///
834    /// # Example
835    ///
836    /// ```
837    /// use std::str::FromStr;
838    /// use hickory_proto::rr::Name;
839    ///
840    /// let name = Name::from_str("www.example.com").unwrap();
841    /// assert!(!name.is_wildcard());
842    ///
843    /// let name = Name::from_str("*.example.com").unwrap();
844    /// assert!(name.is_wildcard());
845    ///
846    /// let name = Name::root();
847    /// assert!(!name.is_wildcard());
848    /// ```
849    pub fn is_wildcard(&self) -> bool {
850        self.iter().next().is_some_and(|l| l == b"*")
851    }
852
853    /// Converts a name to a wildcard, by replacing the first label with `*`
854    ///
855    /// # Example
856    ///
857    /// ```
858    /// use std::str::FromStr;
859    /// use hickory_proto::rr::Name;
860    ///
861    /// let name = Name::from_str("www.example.com").unwrap().into_wildcard();
862    /// assert_eq!(name, Name::from_str("*.example.com.").unwrap());
863    ///
864    /// // does nothing if the root
865    /// let name = Name::root().into_wildcard();
866    /// assert_eq!(name, Name::root());
867    /// ```
868    pub fn into_wildcard(self) -> Self {
869        if self.label_ends.is_empty() {
870            return Self::root();
871        }
872        let mut label_data = TinyVec::new();
873        label_data.push(b'*');
874        let mut label_ends = TinyVec::new();
875        label_ends.push(1);
876
877        // this is not using the Name::extend_name function as it should always be shorter than the original name, so length check is unnecessary
878        for label in self.iter().skip(1) {
879            label_data.extend_from_slice(label);
880            label_ends.push(label_data.len() as u8);
881        }
882        Self {
883            label_data,
884            label_ends,
885            is_fqdn: self.is_fqdn,
886        }
887    }
888}
889
890impl std::fmt::Debug for Name {
891    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
892        f.write_str("Name(\"")?;
893        self.write_labels::<_, LabelEncUtf8>(f)?;
894        f.write_str("\")")
895    }
896}
897
898trait LabelEnc {
899    #[allow(clippy::wrong_self_convention)]
900    fn to_label(name: &str) -> ProtoResult<Label>;
901    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error>;
902}
903
904struct LabelEncAscii;
905impl LabelEnc for LabelEncAscii {
906    #[allow(clippy::wrong_self_convention)]
907    fn to_label(name: &str) -> ProtoResult<Label> {
908        Label::from_ascii(name)
909    }
910
911    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
912        label.write_ascii(f)
913    }
914}
915
916struct LabelEncUtf8;
917impl LabelEnc for LabelEncUtf8 {
918    #[allow(clippy::wrong_self_convention)]
919    fn to_label(name: &str) -> ProtoResult<Label> {
920        Label::from_utf8(name)
921    }
922
923    fn write_label<W: Write>(f: &mut W, label: &Label) -> Result<(), fmt::Error> {
924        write!(f, "{label}")
925    }
926}
927
928/// An iterator over labels in a name
929pub struct LabelIter<'a> {
930    name: &'a Name,
931    start: u8,
932    end: u8,
933}
934
935impl<'a> Iterator for LabelIter<'a> {
936    type Item = &'a [u8];
937
938    fn next(&mut self) -> Option<Self::Item> {
939        if self.start >= self.end {
940            return None;
941        }
942
943        let end = *self.name.label_ends.get(self.start as usize)?;
944        let start = match self.start {
945            0 => 0,
946            _ => self.name.label_ends[(self.start - 1) as usize],
947        };
948        self.start += 1;
949        Some(&self.name.label_data[start as usize..end as usize])
950    }
951
952    fn size_hint(&self) -> (usize, Option<usize>) {
953        let len = self.end.saturating_sub(self.start) as usize;
954        (len, Some(len))
955    }
956}
957
958impl ExactSizeIterator for LabelIter<'_> {}
959
960impl DoubleEndedIterator for LabelIter<'_> {
961    fn next_back(&mut self) -> Option<Self::Item> {
962        if self.end <= self.start {
963            return None;
964        }
965
966        self.end -= 1;
967
968        let end = *self.name.label_ends.get(self.end as usize)?;
969        let start = match self.end {
970            0 => 0,
971            _ => self.name.label_ends[(self.end - 1) as usize],
972        };
973
974        Some(&self.name.label_data[start as usize..end as usize])
975    }
976}
977
978impl<'a> IntoIterator for &'a Name {
979    type Item = &'a [u8];
980    type IntoIter = LabelIter<'a>;
981
982    fn into_iter(self) -> Self::IntoIter {
983        self.iter()
984    }
985}
986
987impl From<IpAddr> for Name {
988    fn from(addr: IpAddr) -> Self {
989        match addr {
990            IpAddr::V4(ip) => ip.into(),
991            IpAddr::V6(ip) => ip.into(),
992        }
993    }
994}
995
996impl From<Ipv4Addr> for Name {
997    fn from(addr: Ipv4Addr) -> Self {
998        let octets = addr.octets();
999
1000        let mut labels =
1001            octets
1002                .iter()
1003                .rev()
1004                .fold(Vec::<Label>::with_capacity(6), |mut labels, o| {
1005                    let label: Label = format!("{o}")
1006                        .as_bytes()
1007                        .into_label()
1008                        .expect("IP octet to label should never fail");
1009                    labels.push(label);
1010                    labels
1011                });
1012
1013        labels.push(
1014            b"in-addr"
1015                .into_label()
1016                .expect("simple name should never fail"),
1017        );
1018        labels.push(b"arpa".into_label().expect("simple name should never fail"));
1019
1020        Self::from_labels(labels).expect("a translation of Ipv4Addr should never fail")
1021    }
1022}
1023
1024impl From<Ipv6Addr> for Name {
1025    fn from(addr: Ipv6Addr) -> Self {
1026        let segments = addr.segments();
1027
1028        let mut labels =
1029            segments
1030                .iter()
1031                .rev()
1032                .fold(Vec::<Label>::with_capacity(34), |mut labels, o| {
1033                    labels.push(
1034                        format!("{:x}", (*o & 0x000F) as u8)
1035                            .as_bytes()
1036                            .into_label()
1037                            .expect("IP octet to label should never fail"),
1038                    );
1039                    labels.push(
1040                        format!("{:x}", (*o >> 4 & 0x000F) as u8)
1041                            .as_bytes()
1042                            .into_label()
1043                            .expect("IP octet to label should never fail"),
1044                    );
1045                    labels.push(
1046                        format!("{:x}", (*o >> 8 & 0x000F) as u8)
1047                            .as_bytes()
1048                            .into_label()
1049                            .expect("IP octet to label should never fail"),
1050                    );
1051                    labels.push(
1052                        format!("{:x}", (*o >> 12 & 0x000F) as u8)
1053                            .as_bytes()
1054                            .into_label()
1055                            .expect("IP octet to label should never fail"),
1056                    );
1057                    labels
1058                });
1059
1060        labels.push(b"ip6".into_label().expect("simple name should never fail"));
1061        labels.push(b"arpa".into_label().expect("simple name should never fail"));
1062
1063        Self::from_labels(labels).expect("a translation of Ipv6Addr should never fail")
1064    }
1065}
1066
1067impl PartialEq<Self> for Name {
1068    fn eq(&self, other: &Self) -> bool {
1069        self.cmp_with_f::<CaseInsensitive>(other) == Ordering::Equal
1070    }
1071}
1072
1073impl Hash for Name {
1074    fn hash<H: Hasher>(&self, state: &mut H) {
1075        self.is_fqdn.hash(state);
1076
1077        // this needs to be CaseInsensitive like PartialEq
1078        for l in self
1079            .iter()
1080            .map(|l| Label::from_raw_bytes(l).unwrap().to_lowercase())
1081        {
1082            l.hash(state);
1083        }
1084    }
1085}
1086
1087enum ParseState {
1088    Label,
1089    Escape1,
1090    Escape2(u32),
1091    Escape3(u32, u32),
1092}
1093
1094impl BinEncodable for Name {
1095    fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
1096        let is_canonical_names = encoder.is_canonical_names();
1097        self.emit_as_canonical(encoder, is_canonical_names)
1098    }
1099}
1100
1101impl<'r> BinDecodable<'r> for Name {
1102    /// parses the chain of labels
1103    ///  this has a max of 255 octets, with each label being less than 63.
1104    ///  all names will be stored lowercase internally.
1105    /// This will consume the portions of the `Vec` which it is reading...
1106    fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
1107        let mut name = Self::root(); // this is FQDN
1108
1109        read_inner(decoder, &mut name, None)?;
1110        Ok(name)
1111    }
1112}
1113
1114fn read_inner(
1115    decoder: &mut BinDecoder<'_>,
1116    name: &mut Name,
1117    max_idx: Option<usize>,
1118) -> Result<(), DecodeError> {
1119    let mut state: LabelParseState = LabelParseState::LabelLengthOrPointer;
1120    let name_start = decoder.index();
1121
1122    // assume all chars are utf-8. We're doing byte-by-byte operations, no endianess issues...
1123    // reserved: (1000 0000 aka 0800) && (0100 0000 aka 0400)
1124    // pointer: (slice == 1100 0000 aka C0) & C0 == true, then 03FF & slice = offset
1125    // label: 03FF & slice = length; slice.next(length) = label
1126    // root: 0000
1127    loop {
1128        // this protects against overlapping labels
1129        if let Some(max_idx) = max_idx {
1130            if decoder.index() >= max_idx {
1131                return Err(DecodeError::LabelOverlapsWithOther {
1132                    label: name_start,
1133                    other: max_idx,
1134                });
1135            }
1136        }
1137
1138        state = match state {
1139            LabelParseState::LabelLengthOrPointer => {
1140                // determine what the next label is
1141                match decoder
1142                    .peek()
1143                    .map(Restrict::unverified /*verified in this usage*/)
1144                {
1145                    Some(0) | None => LabelParseState::Root,
1146                    Some(byte) if byte & 0b1100_0000 == 0b1100_0000 => LabelParseState::Pointer,
1147                    Some(byte) if byte & 0b1100_0000 == 0b0000_0000 => LabelParseState::Label,
1148                    Some(byte) => return Err(DecodeError::UnrecognizedLabelCode(byte)),
1149                }
1150            }
1151            // labels must have a maximum length of 63
1152            LabelParseState::Label => {
1153                let label = decoder
1154                    .read_character_data()?
1155                    .verify_unwrap(|l| l.len() <= 63)
1156                    .map_err(|l| DecodeError::LabelBytesTooLong(l.len()))?;
1157
1158                name.extend_name(label)
1159                    .map_err(|_| DecodeError::DomainNameTooLong(label.len()))?;
1160
1161                // reset to collect more data
1162                LabelParseState::LabelLengthOrPointer
1163            }
1164            //         4.1.4. Message compression
1165            //
1166            // In order to reduce the size of messages, the domain system utilizes a
1167            // compression scheme which eliminates the repetition of domain names in a
1168            // message.  In this scheme, an entire domain name or a list of labels at
1169            // the end of a domain name is replaced with a pointer to a prior occurrence
1170            // of the same name.
1171            //
1172            // The pointer takes the form of a two octet sequence:
1173            //
1174            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1175            //     | 1  1|                OFFSET                   |
1176            //     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1177            //
1178            // The first two bits are ones.  This allows a pointer to be distinguished
1179            // from a label, since the label must begin with two zero bits because
1180            // labels are restricted to 63 octets or less.  (The 10 and 01 combinations
1181            // are reserved for future use.)  The OFFSET field specifies an offset from
1182            // the start of the message (i.e., the first octet of the ID field in the
1183            // domain header).  A zero offset specifies the first byte of the ID field,
1184            // etc.
1185            LabelParseState::Pointer => {
1186                let pointer_location = decoder.index();
1187                let location = decoder
1188                    .read_u16()?
1189                    .map(|u| {
1190                        // get rid of the two high order bits, they are markers for length or pointers
1191                        u & 0x3FFF
1192                    })
1193                    .verify_unwrap(|ptr| {
1194                        // all labels must appear "prior" to this Name
1195                        (*ptr as usize) < name_start
1196                    })
1197                    .map_err(|e| DecodeError::PointerNotPriorToLabel {
1198                        idx: pointer_location,
1199                        ptr: e,
1200                    })?;
1201
1202                let mut pointer = decoder.clone(location);
1203                read_inner(&mut pointer, name, Some(name_start))?;
1204
1205                // Pointers always finish the name, break like Root.
1206                break;
1207            }
1208            LabelParseState::Root => {
1209                // need to pop() the 0 off the stack...
1210                decoder.pop()?;
1211                break;
1212            }
1213        }
1214    }
1215
1216    // TODO: should we consider checking this while the name is parsed?
1217    let len = name.len();
1218    if len >= 255 {
1219        return Err(DecodeError::DomainNameTooLong(len));
1220    }
1221
1222    Ok(())
1223}
1224
1225impl fmt::Display for Name {
1226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1227        self.write_labels::<fmt::Formatter<'_>, LabelEncUtf8>(f)
1228    }
1229}
1230
1231impl PartialOrd<Self> for Name {
1232    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1233        Some(self.cmp(other))
1234    }
1235}
1236
1237impl Ord for Name {
1238    /// Case insensitive comparison, see [`Name::cmp_case`] for case sensitive comparisons
1239    ///
1240    /// RFC 4034                DNSSEC Resource Records               March 2005
1241    ///
1242    /// ```text
1243    /// 6.1.  Canonical DNS Name Order
1244    ///
1245    ///  For the purposes of DNS security, owner names are ordered by treating
1246    ///  individual labels as unsigned left-justified octet strings.  The
1247    ///  absence of a octet sorts before a zero value octet, and uppercase
1248    ///  US-ASCII letters are treated as if they were lowercase US-ASCII
1249    ///  letters.
1250    ///
1251    ///  To compute the canonical ordering of a set of DNS names, start by
1252    ///  sorting the names according to their most significant (rightmost)
1253    ///  labels.  For names in which the most significant label is identical,
1254    ///  continue sorting according to their next most significant label, and
1255    ///  so forth.
1256    ///
1257    ///  For example, the following names are sorted in canonical DNS name
1258    ///  order.  The most significant label is "example".  At this level,
1259    ///  "example" sorts first, followed by names ending in "a.example", then
1260    ///  by names ending "z.example".  The names within each level are sorted
1261    ///  in the same way.
1262    ///
1263    ///            example
1264    ///            a.example
1265    ///            yljkjljk.a.example
1266    ///            Z.a.example
1267    ///            zABC.a.EXAMPLE
1268    ///            z.example
1269    ///            \001.z.example
1270    ///            *.z.example
1271    ///            \200.z.example
1272    /// ```
1273    fn cmp(&self, other: &Self) -> Ordering {
1274        self.cmp_with_f::<CaseInsensitive>(other)
1275    }
1276}
1277
1278/// This is the list of states for the label parsing state machine
1279enum LabelParseState {
1280    LabelLengthOrPointer, // basically the start of the FSM
1281    Label,                // storing length of the label, must be < 63
1282    Pointer,              // location of pointer in slice,
1283    Root,                 // root is the end of the labels list, aka null
1284}
1285
1286impl FromStr for Name {
1287    type Err = ProtoError;
1288
1289    /// Uses the Name::from_utf8 conversion on this string, see [Name::from_ascii] for ascii only, or for preserving case
1290    fn from_str(s: &str) -> Result<Self, Self::Err> {
1291        Self::from_str_relaxed(s)
1292    }
1293}
1294
1295/// Conversion into a Name
1296pub trait IntoName: Sized {
1297    /// Convert this into Name
1298    fn into_name(self) -> ProtoResult<Name>;
1299}
1300
1301impl IntoName for &str {
1302    /// Performs a utf8, IDNA or punycode, translation of the `str` into `Name`
1303    fn into_name(self) -> ProtoResult<Name> {
1304        Name::from_utf8(self)
1305    }
1306}
1307
1308impl IntoName for String {
1309    /// Performs a utf8, IDNA or punycode, translation of the `String` into `Name`
1310    fn into_name(self) -> ProtoResult<Name> {
1311        Name::from_utf8(self)
1312    }
1313}
1314
1315impl IntoName for &String {
1316    /// Performs a utf8, IDNA or punycode, translation of the `&String` into `Name`
1317    fn into_name(self) -> ProtoResult<Name> {
1318        Name::from_utf8(self)
1319    }
1320}
1321
1322impl<T> IntoName for T
1323where
1324    T: Into<Name>,
1325{
1326    fn into_name(self) -> ProtoResult<Name> {
1327        Ok(self.into())
1328    }
1329}
1330
1331#[cfg(feature = "serde-config")]
1332impl Serialize for Name {
1333    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1334    where
1335        S: Serializer,
1336    {
1337        serializer.serialize_str(&self.to_string())
1338    }
1339}
1340
1341#[cfg(feature = "serde-config")]
1342impl<'de> Deserialize<'de> for Name {
1343    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1344    where
1345        D: Deserializer<'de>,
1346    {
1347        let s = String::deserialize(deserializer)?;
1348        FromStr::from_str(&s).map_err(de::Error::custom)
1349    }
1350}
1351
1352#[cfg(test)]
1353mod tests {
1354    #![allow(clippy::dbg_macro, clippy::print_stdout)]
1355
1356    use std::cmp::Ordering;
1357    use std::iter;
1358    use std::str::FromStr;
1359
1360    use super::*;
1361
1362    use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
1363    #[allow(clippy::useless_attribute)]
1364    #[allow(unused)]
1365    use crate::serialize::binary::*;
1366
1367    fn get_data() -> Vec<(Name, Vec<u8>)> {
1368        vec![
1369            (Name::new(), vec![0]),                           // base case, only the root
1370            (Name::from_str("a").unwrap(), vec![1, b'a', 0]), // a single 'a' label
1371            (
1372                Name::from_str("a.bc").unwrap(),
1373                vec![1, b'a', 2, b'b', b'c', 0],
1374            ), // two labels, 'a.bc'
1375            (
1376                Name::from_str("a.♥").unwrap(),
1377                vec![1, b'a', 7, b'x', b'n', b'-', b'-', b'g', b'6', b'h', 0],
1378            ), // two labels utf8, 'a.♥'
1379        ]
1380    }
1381
1382    #[test]
1383    fn test_num_labels() {
1384        assert_eq!(Name::from_str("*").unwrap().num_labels(), 0);
1385        assert_eq!(Name::from_str("a").unwrap().num_labels(), 1);
1386        assert_eq!(Name::from_str("*.b").unwrap().num_labels(), 1);
1387        assert_eq!(Name::from_str("a.b").unwrap().num_labels(), 2);
1388        assert_eq!(Name::from_str("*.b.c").unwrap().num_labels(), 2);
1389        assert_eq!(Name::from_str("a.b.c").unwrap().num_labels(), 3);
1390    }
1391
1392    #[test]
1393    fn test_read() {
1394        test_read_data_set(get_data(), |ref mut d| Name::read(d));
1395    }
1396
1397    #[test]
1398    fn test_write_to() {
1399        test_emit_data_set(get_data(), |e, n| n.emit(e));
1400    }
1401
1402    #[test]
1403    fn test_pointer() {
1404        let mut bytes: Vec<u8> = Vec::with_capacity(512);
1405
1406        let first = Name::from_str("ra.rb.rc").unwrap();
1407        let second = Name::from_str("rb.rc").unwrap();
1408        let third = Name::from_str("rc").unwrap();
1409        let fourth = Name::from_str("z.ra.rb.rc").unwrap();
1410
1411        {
1412            let mut e = BinEncoder::new(&mut bytes);
1413
1414            first.emit(&mut e).unwrap();
1415            assert_eq!(e.len(), 10); // should be 7 u8s...
1416
1417            second.emit(&mut e).unwrap();
1418            // if this wrote the entire thing, then it would be +5... but a pointer should be +2
1419            assert_eq!(e.len(), 12);
1420
1421            third.emit(&mut e).unwrap();
1422            assert_eq!(e.len(), 14);
1423
1424            fourth.emit(&mut e).unwrap();
1425            assert_eq!(e.len(), 18);
1426        }
1427
1428        // now read them back
1429        let mut d = BinDecoder::new(&bytes);
1430
1431        let r_test = Name::read(&mut d).unwrap();
1432        assert_eq!(first, r_test);
1433
1434        let r_test = Name::read(&mut d).unwrap();
1435        assert_eq!(second, r_test);
1436
1437        let r_test = Name::read(&mut d).unwrap();
1438        assert_eq!(third, r_test);
1439
1440        let r_test = Name::read(&mut d).unwrap();
1441        assert_eq!(fourth, r_test);
1442    }
1443
1444    #[test]
1445    fn test_pointer_with_pointer_ending_labels() {
1446        let mut bytes: Vec<u8> = Vec::with_capacity(512);
1447
1448        let first = Name::from_str("ra.rb.rc").unwrap();
1449        let second = Name::from_str("ra.rc").unwrap();
1450        let third = Name::from_str("ra.rc").unwrap();
1451
1452        {
1453            let mut e = BinEncoder::new(&mut bytes);
1454
1455            first.emit(&mut e).unwrap();
1456            assert_eq!(e.len(), 10);
1457
1458            second.emit(&mut e).unwrap();
1459            // +5 with the first +3 being the text form of "ra" and +2 for the pointer to "rc".
1460            assert_eq!(e.len(), 15);
1461
1462            // +2 with the pointer to "ra.rc" as previously seen.
1463            third.emit(&mut e).unwrap();
1464            assert_eq!(e.len(), 17);
1465        }
1466
1467        // now read them back
1468        let mut d = BinDecoder::new(&bytes);
1469
1470        let r_test = Name::read(&mut d).unwrap();
1471        assert_eq!(first, r_test);
1472
1473        let r_test = Name::read(&mut d).unwrap();
1474        assert_eq!(second, r_test);
1475
1476        let r_test = Name::read(&mut d).unwrap();
1477        assert_eq!(third, r_test);
1478    }
1479
1480    #[test]
1481    fn test_recursive_pointer() {
1482        // points to an invalid beginning label marker
1483        let bytes = vec![0xC0, 0x01];
1484        let mut d = BinDecoder::new(&bytes);
1485
1486        assert!(Name::read(&mut d).is_err());
1487
1488        // formerly a stack overflow, recursing back on itself
1489        let bytes = vec![0xC0, 0x00];
1490        let mut d = BinDecoder::new(&bytes);
1491
1492        assert!(Name::read(&mut d).is_err());
1493
1494        // formerly a stack overflow, recursing back on itself
1495        let bytes = vec![0x01, 0x41, 0xC0, 0x00];
1496        let mut d = BinDecoder::new(&bytes);
1497
1498        assert!(Name::read(&mut d).is_err());
1499
1500        // formerly a stack overflow, recursing by going past the end, then back to the beginning.
1501        //   this is disallowed based on the rule that all labels must be "prior" to the current label.
1502        let bytes = vec![0xC0, 0x02, 0xC0, 0x00];
1503        let mut d = BinDecoder::new(&bytes);
1504
1505        assert!(Name::read(&mut d).is_err());
1506    }
1507
1508    #[test]
1509    fn test_bin_overlap_enforced() {
1510        let mut bytes: Vec<u8> = Vec::with_capacity(512);
1511        let n: u8 = 31;
1512        for _ in 0..=5 {
1513            bytes.extend(iter::repeat(n).take(n as usize));
1514        }
1515        bytes.push(n + 1);
1516        for b in 0..n {
1517            bytes.push(1 + n + b);
1518        }
1519        bytes.extend_from_slice(&[1, 0]);
1520        for b in 0..n {
1521            bytes.extend_from_slice(&[0xC0, b]);
1522        }
1523        let mut d = BinDecoder::new(&bytes);
1524        d.read_slice(n as usize).unwrap();
1525        assert!(Name::read(&mut d).is_err());
1526    }
1527
1528    #[test]
1529    fn test_bin_max_octets() {
1530        let mut bytes = Vec::with_capacity(512);
1531        for _ in 0..256 {
1532            bytes.extend_from_slice(&[1, b'a']);
1533        }
1534        bytes.push(0);
1535
1536        let mut d = BinDecoder::new(&bytes);
1537        assert!(Name::read(&mut d).is_err());
1538    }
1539
1540    #[test]
1541    fn test_base_name() {
1542        let zone = Name::from_str("example.com.").unwrap();
1543
1544        assert_eq!(zone.base_name(), Name::from_str("com").unwrap());
1545        assert!(zone.base_name().base_name().is_root());
1546        assert!(zone.base_name().base_name().base_name().is_root());
1547    }
1548
1549    #[test]
1550    fn test_zone_of() {
1551        let zone = Name::from_str("example.com").unwrap();
1552        let www = Name::from_str("www.example.com").unwrap();
1553        let none = Name::from_str("none.com").unwrap();
1554        let root = Name::root();
1555
1556        assert!(zone.zone_of(&zone));
1557        assert!(zone.zone_of(&www));
1558        assert!(!zone.zone_of(&none));
1559        assert!(root.zone_of(&zone));
1560        assert!(!zone.zone_of(&root));
1561    }
1562
1563    #[test]
1564    fn test_zone_of_case() {
1565        let zone = Name::from_ascii("examplE.cOm").unwrap();
1566        let www = Name::from_str("www.example.com").unwrap();
1567        let none = Name::from_str("none.com").unwrap();
1568
1569        assert!(zone.zone_of(&zone));
1570        assert!(zone.zone_of(&www));
1571        assert!(!zone.zone_of(&none))
1572    }
1573
1574    #[test]
1575    fn test_partial_cmp_eq() {
1576        let root = Some(Name::from_labels(Vec::<&str>::new()).unwrap());
1577        let comparisons: Vec<(Name, Name)> = vec![
1578            (root.clone().unwrap(), root.clone().unwrap()),
1579            (
1580                Name::parse("example.", root.as_ref()).unwrap(),
1581                Name::parse("example", root.as_ref()).unwrap(),
1582            ),
1583        ];
1584
1585        for (left, right) in comparisons {
1586            println!("left: {left}, right: {right}");
1587            assert_eq!(left.partial_cmp(&right), Some(Ordering::Equal));
1588        }
1589    }
1590
1591    #[test]
1592    fn test_partial_cmp() {
1593        let comparisons: Vec<(Name, Name)> = vec![
1594            (
1595                Name::from_str("example.").unwrap(),
1596                Name::from_str("a.example.").unwrap(),
1597            ),
1598            (
1599                Name::from_str("a.example.").unwrap(),
1600                Name::from_str("yljkjljk.a.example.").unwrap(),
1601            ),
1602            (
1603                Name::from_str("yljkjljk.a.example.").unwrap(),
1604                Name::from_ascii("Z.a.example.").unwrap(),
1605            ),
1606            (
1607                Name::from_ascii("Z.a.example.").unwrap(),
1608                Name::from_ascii("zABC.a.EXAMPLE").unwrap(),
1609            ),
1610            (
1611                Name::from_ascii("zABC.a.EXAMPLE.").unwrap(),
1612                Name::from_str("z.example.").unwrap(),
1613            ),
1614            (
1615                Name::from_str("z.example.").unwrap(),
1616                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example"]).unwrap(),
1617            ),
1618            (
1619                Name::from_labels(vec![&[1u8] as &[u8], b"z", b"example"]).unwrap(),
1620                Name::from_str("*.z.example.").unwrap(),
1621            ),
1622            (
1623                Name::from_str("*.z.example.").unwrap(),
1624                Name::from_labels(vec![&[200u8] as &[u8], b"z", b"example"]).unwrap(),
1625            ),
1626        ];
1627
1628        for (left, right) in comparisons {
1629            println!("left: {left}, right: {right}");
1630            assert_eq!(left.cmp(&right), Ordering::Less);
1631        }
1632    }
1633
1634    #[test]
1635    fn test_cmp_ignore_case() {
1636        let comparisons: Vec<(Name, Name)> = vec![
1637            (
1638                Name::from_ascii("ExAmPle.").unwrap(),
1639                Name::from_ascii("example.").unwrap(),
1640            ),
1641            (
1642                Name::from_ascii("A.example.").unwrap(),
1643                Name::from_ascii("a.example.").unwrap(),
1644            ),
1645        ];
1646
1647        for (left, right) in comparisons {
1648            println!("left: {left}, right: {right}");
1649            assert_eq!(left, right);
1650        }
1651    }
1652
1653    #[test]
1654    fn test_from_ipv4() {
1655        let ip = IpAddr::V4(Ipv4Addr::new(26, 3, 0, 103));
1656        let name = Name::from_str("103.0.3.26.in-addr.arpa").unwrap();
1657
1658        assert_eq!(Into::<Name>::into(ip), name);
1659    }
1660
1661    #[test]
1662    fn test_from_ipv6() {
1663        let ip = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1));
1664        let name = Name::from_str(
1665            "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa",
1666        )
1667        .unwrap();
1668
1669        assert_eq!(Into::<Name>::into(ip), name);
1670    }
1671
1672    #[test]
1673    fn test_from_str() {
1674        assert_eq!(
1675            Name::from_str("www.example.com.").unwrap(),
1676            Name::from_labels(vec![b"www" as &[u8], b"example", b"com"]).unwrap()
1677        );
1678        assert_eq!(
1679            Name::from_str(".").unwrap(),
1680            Name::from_labels(Vec::<&str>::new()).unwrap()
1681        );
1682    }
1683
1684    #[test]
1685    fn test_fqdn() {
1686        assert!(Name::root().is_fqdn());
1687        assert!(Name::from_str(".").unwrap().is_fqdn());
1688        assert!(Name::from_str("www.example.com.").unwrap().is_fqdn());
1689        assert!(Name::from_labels(vec![b"www" as &[u8], b"example", b"com"])
1690            .unwrap()
1691            .is_fqdn());
1692
1693        assert!(!Name::new().is_fqdn());
1694        assert!(!Name::from_str("www.example.com").unwrap().is_fqdn());
1695        assert!(!Name::from_str("www.example").unwrap().is_fqdn());
1696        assert!(!Name::from_str("www").unwrap().is_fqdn());
1697    }
1698
1699    #[test]
1700    fn test_to_string() {
1701        assert_eq!(
1702            Name::from_str("www.example.com.").unwrap().to_string(),
1703            "www.example.com."
1704        );
1705        assert_eq!(
1706            Name::from_str("www.example.com").unwrap().to_string(),
1707            "www.example.com"
1708        );
1709    }
1710
1711    #[test]
1712    fn test_from_ascii() {
1713        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
1714        let ascii_name = Name::from_ascii("WWW.example.COM.").unwrap();
1715        let lower_name = Name::from_ascii("www.example.com.").unwrap();
1716
1717        assert!(bytes_name.eq_case(&ascii_name));
1718        assert!(!lower_name.eq_case(&ascii_name));
1719    }
1720
1721    #[test]
1722    fn test_from_utf8() {
1723        let bytes_name = Name::from_labels(vec![b"WWW" as &[u8], b"example", b"COM"]).unwrap();
1724        let utf8_name = Name::from_utf8("WWW.example.COM.").unwrap();
1725        let lower_name = Name::from_utf8("www.example.com.").unwrap();
1726
1727        assert!(!bytes_name.eq_case(&utf8_name));
1728        assert!(lower_name.eq_case(&utf8_name));
1729    }
1730
1731    #[test]
1732    fn test_into_name() {
1733        let name = Name::from_utf8("www.example.com").unwrap();
1734        assert_eq!(Name::from_utf8("www.example.com").unwrap(), name);
1735        assert_eq!(
1736            Name::from_utf8("www.example.com").unwrap(),
1737            Name::from_utf8("www.example.com")
1738                .unwrap()
1739                .into_name()
1740                .unwrap()
1741        );
1742        assert_eq!(
1743            Name::from_utf8("www.example.com").unwrap(),
1744            "www.example.com".into_name().unwrap()
1745        );
1746        assert_eq!(
1747            Name::from_utf8("www.example.com").unwrap(),
1748            "www.example.com".to_string().into_name().unwrap()
1749        );
1750    }
1751
1752    #[test]
1753    fn test_encoding() {
1754        assert_eq!(
1755            Name::from_ascii("WWW.example.COM.").unwrap().to_ascii(),
1756            "WWW.example.COM."
1757        );
1758        assert_eq!(
1759            Name::from_utf8("WWW.example.COM.").unwrap().to_ascii(),
1760            "www.example.com."
1761        );
1762        assert_eq!(
1763            Name::from_ascii("WWW.example.COM.").unwrap().to_utf8(),
1764            "WWW.example.COM."
1765        );
1766    }
1767
1768    #[test]
1769    fn test_excessive_encoding_len() {
1770        use crate::error::ProtoErrorKind;
1771
1772        // u16 max value is where issues start being tickled...
1773        let mut buf = Vec::with_capacity(u16::MAX as usize);
1774        let mut encoder = BinEncoder::new(&mut buf);
1775
1776        let mut result = Ok(());
1777        for i in 0..10000 {
1778            let name = Name::from_ascii(format!("name{i}.example.com.")).unwrap();
1779            result = name.emit(&mut encoder);
1780            if result.is_err() {
1781                break;
1782            }
1783        }
1784
1785        assert!(result.is_err());
1786        match *result.unwrap_err().kind() {
1787            ProtoErrorKind::MaxBufferSizeExceeded(_) => (),
1788            _ => panic!(),
1789        }
1790    }
1791
1792    #[test]
1793    fn test_underscore() {
1794        Name::from_str("_begin.example.com").expect("failed at beginning");
1795        Name::from_str_relaxed("mid_dle.example.com").expect("failed in the middle");
1796        Name::from_str_relaxed("end_.example.com").expect("failed at the end");
1797    }
1798
1799    #[test]
1800    fn test_parse_arpa_name() {
1801        assert!(Name::from_ascii("168.192.in-addr.arpa")
1802            .unwrap()
1803            .parse_arpa_name()
1804            .is_err());
1805        assert!(Name::from_ascii("host.example.com.")
1806            .unwrap()
1807            .parse_arpa_name()
1808            .is_err());
1809        assert!(Name::from_ascii("caffee.ip6.arpa.")
1810            .unwrap()
1811            .parse_arpa_name()
1812            .is_err());
1813        assert!(Name::from_ascii(
1814            "1.4.3.3.7.0.7.3.0.E.2.A.8.9.1.3.1.3.D.8.0.3.A.5.8.8.B.D.0.1.0.0.2.ip6.arpa."
1815        )
1816        .unwrap()
1817        .parse_arpa_name()
1818        .is_err());
1819        assert!(Name::from_ascii("caffee.in-addr.arpa.")
1820            .unwrap()
1821            .parse_arpa_name()
1822            .is_err());
1823        assert!(Name::from_ascii("1.2.3.4.5.in-addr.arpa.")
1824            .unwrap()
1825            .parse_arpa_name()
1826            .is_err());
1827        assert!(Name::from_ascii("1.2.3.4.home.arpa.")
1828            .unwrap()
1829            .parse_arpa_name()
1830            .is_err());
1831        assert_eq!(
1832            Name::from_ascii("168.192.in-addr.arpa.")
1833                .unwrap()
1834                .parse_arpa_name()
1835                .unwrap(),
1836            IpNet::V4(Ipv4Net::new("192.168.0.0".parse().unwrap(), 16).unwrap())
1837        );
1838        assert_eq!(
1839            Name::from_ascii("1.0.168.192.in-addr.arpa.")
1840                .unwrap()
1841                .parse_arpa_name()
1842                .unwrap(),
1843            IpNet::V4(Ipv4Net::new("192.168.0.1".parse().unwrap(), 32).unwrap())
1844        );
1845        assert_eq!(
1846            Name::from_ascii("0.1.0.0.2.ip6.arpa.")
1847                .unwrap()
1848                .parse_arpa_name()
1849                .unwrap(),
1850            IpNet::V6(Ipv6Net::new("2001::".parse().unwrap(), 20).unwrap())
1851        );
1852        assert_eq!(
1853            Name::from_ascii("D.0.1.0.0.2.ip6.arpa.")
1854                .unwrap()
1855                .parse_arpa_name()
1856                .unwrap(),
1857            IpNet::V6(Ipv6Net::new("2001:d00::".parse().unwrap(), 24).unwrap())
1858        );
1859        assert_eq!(
1860            Name::from_ascii("B.D.0.1.0.0.2.ip6.arpa.")
1861                .unwrap()
1862                .parse_arpa_name()
1863                .unwrap(),
1864            IpNet::V6(Ipv6Net::new("2001:db0::".parse().unwrap(), 28).unwrap())
1865        );
1866        assert_eq!(
1867            Name::from_ascii("8.B.D.0.1.0.0.2.ip6.arpa.")
1868                .unwrap()
1869                .parse_arpa_name()
1870                .unwrap(),
1871            IpNet::V6(Ipv6Net::new("2001:db8::".parse().unwrap(), 32).unwrap())
1872        );
1873        assert_eq!(
1874            Name::from_ascii(
1875                "4.3.3.7.0.7.3.0.E.2.A.8.9.1.3.1.3.D.8.0.3.A.5.8.8.B.D.0.1.0.0.2.ip6.arpa."
1876            )
1877            .unwrap()
1878            .parse_arpa_name()
1879            .unwrap(),
1880            IpNet::V6(
1881                Ipv6Net::new("2001:db8:85a3:8d3:1319:8a2e:370:7334".parse().unwrap(), 128).unwrap()
1882            )
1883        );
1884    }
1885
1886    #[test]
1887    fn test_name_too_long_with_append() {
1888        // from https://github.com/hickory-dns/hickory-dns/issues/1447
1889        let n = Name::from_ascii("Llocainvannnnnnaxgtezqzqznnnnnn1na.nnntnninvannnnnnaxgtezqzqznnnnnn1na.nnntnnnnnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.innnnnaxgtezqzqznnnnnn1na.nnntnaaaaaaaaaaaaaaaaaaaaaaaaiK.iaaaaaaaaaaaaaaaaaaaaaaaaiKa.in").unwrap();
1890        let sfx = Name::from_ascii("xxxxxxx.yyyyy.zzz").unwrap();
1891
1892        let error = n
1893            .append_domain(&sfx)
1894            .expect_err("should have errored, too long");
1895
1896        match error.kind() {
1897            ProtoErrorKind::DomainNameTooLong(_) => (),
1898            _ => panic!("expected too long message"),
1899        }
1900    }
1901
1902    #[test]
1903    fn test_double_ended_iterator() {
1904        let name = Name::from_ascii("www.example.com").unwrap();
1905        let mut iter = name.iter();
1906
1907        assert_eq!(iter.next().unwrap(), b"www");
1908        assert_eq!(iter.next_back().unwrap(), b"com");
1909        assert_eq!(iter.next().unwrap(), b"example");
1910        assert!(iter.next_back().is_none());
1911        assert!(iter.next().is_none());
1912    }
1913
1914    #[test]
1915    fn test_size_hint() {
1916        let name = Name::from_ascii("www.example.com").unwrap();
1917        let mut iter = name.iter();
1918
1919        assert_eq!(iter.size_hint().0, 3);
1920        assert_eq!(iter.next().unwrap(), b"www");
1921        assert_eq!(iter.size_hint().0, 2);
1922        assert_eq!(iter.next_back().unwrap(), b"com");
1923        assert_eq!(iter.size_hint().0, 1);
1924        assert_eq!(iter.next().unwrap(), b"example");
1925        assert_eq!(iter.size_hint().0, 0);
1926        assert!(iter.next_back().is_none());
1927        assert_eq!(iter.size_hint().0, 0);
1928        assert!(iter.next().is_none());
1929        assert_eq!(iter.size_hint().0, 0);
1930    }
1931}