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