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