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