1use crate::core::MtopError;
2use crate::dns::bytes::{read_be_u8, write_be_u8};
3use std::fmt;
4use std::io::{Read, Seek, SeekFrom, Write};
5use std::str::FromStr;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub struct Name {
9 labels: Vec<Vec<u8>>,
10 is_fqdn: bool,
11}
12
13impl Name {
14 const MAX_LENGTH: usize = 255;
15 const MAX_LABEL_LENGTH: usize = 63;
16 const MAX_POINTERS: u32 = 64;
17 const NUM_LABELS_HINT: usize = 4;
18
19 pub fn root() -> Self {
20 Name {
21 labels: Vec::new(),
22 is_fqdn: true,
23 }
24 }
25
26 pub fn size(&self) -> usize {
27 self.labels.iter().map(Vec::len).sum::<usize>() + self.labels.len() + 1
28 }
29
30 pub fn is_root(&self) -> bool {
31 self.labels.is_empty() && self.is_fqdn
32 }
33
34 pub fn is_fqdn(&self) -> bool {
35 self.is_fqdn
36 }
37
38 #[must_use]
39 pub fn to_fqdn(mut self) -> Self {
40 self.is_fqdn = true;
41 self
42 }
43
44 #[must_use]
45 pub fn append(mut self, other: Name) -> Self {
46 if self.is_fqdn {
47 return self;
48 }
49
50 self.labels.extend(other.labels);
51 Self {
52 labels: self.labels,
53 is_fqdn: other.is_fqdn,
54 }
55 }
56
57 pub fn write_network_bytes<T>(&self, mut out: T) -> Result<(), MtopError>
58 where
59 T: Write,
60 {
61 assert!(self.is_fqdn, "only fully qualified domains can be encoded");
65 assert!(
68 self.size() <= Self::MAX_LENGTH,
69 "size {} of domain exceeds maximum of {}",
70 self.size(),
71 Self::MAX_LENGTH
72 );
73
74 for label in &self.labels {
75 assert!(
79 label.len() <= Self::MAX_LABEL_LENGTH,
80 "label length of {} exceeds maximum of {}",
81 label.len(),
82 Self::MAX_LABEL_LENGTH
83 );
84
85 write_be_u8(&mut out, u8::try_from(label.len()).unwrap())?;
86 out.write_all(label)?;
87 }
88
89 write_be_u8(&mut out, 0)
90 }
91
92 pub fn read_network_bytes<T>(mut inp: T) -> Result<Self, MtopError>
93 where
94 T: Read + Seek,
95 {
96 let mut labels = Vec::with_capacity(Self::NUM_LABELS_HINT);
97 Self::read_inner(&mut inp, &mut labels)?;
98
99 Ok(Self { labels, is_fqdn: true })
100 }
101
102 fn read_inner<T>(inp: &mut T, out: &mut Vec<Vec<u8>>) -> Result<(), MtopError>
106 where
107 T: Read + Seek,
108 {
109 let mut total_len = 0;
110 let mut pointers = 0;
111 let mut position = None;
112 loop {
113 if pointers > Self::MAX_POINTERS {
117 return Err(MtopError::runtime(format!(
118 "reached max number of pointers ({}) while reading name",
119 Self::MAX_POINTERS
120 )));
121 }
122
123 let len = read_be_u8(inp)?;
124 if Self::is_compressed_label(len) {
129 let offset = Self::get_offset(len, read_be_u8(inp)?);
130 if position.is_none() {
131 position = Some(inp.stream_position()?);
132 }
133
134 inp.seek(SeekFrom::Start(u64::from(offset)))?;
135 pointers += 1;
136 } else if Self::is_standard_label(len) {
137 let mut label = Vec::with_capacity(usize::from(len));
141 if Self::read_label_into(inp, total_len, len, &mut label)? {
142 if let Some(p) = position {
143 inp.seek(SeekFrom::Start(p))?;
147 }
148 return Ok(());
149 }
150
151 total_len += label.len() + 1;
152 out.push(label);
153 } else {
154 return Err(MtopError::runtime(format!("unsupported Name label type: {}", len)));
157 }
158 }
159 }
160
161 fn read_label_into<T>(inp: &mut T, total_len: usize, len: u8, out: &mut Vec<u8>) -> Result<bool, MtopError>
164 where
165 T: Read + Seek,
166 {
167 if len == 0 {
168 return Ok(true);
169 }
170
171 if usize::from(len) > Self::MAX_LABEL_LENGTH {
175 return Err(MtopError::runtime(format!(
176 "max size for label would be exceeded reading {} bytes",
177 len,
178 )));
179 }
180
181 if usize::from(len) + 1 + total_len + 1 > Self::MAX_LENGTH {
186 return Err(MtopError::runtime(format!(
187 "max size for name would be exceeded adding {} bytes to {}",
188 len, total_len
189 )));
190 }
191
192 let mut handle = inp.take(u64::from(len));
193 let n = handle.read_to_end(out)?;
194 if n != usize::from(len) {
195 return Err(MtopError::runtime(format!(
196 "short read for Name segment. expected {} got {}",
197 len, n
198 )));
199 }
200
201 Self::validate_label(out)?;
202 out.make_ascii_lowercase();
203 Ok(false)
204 }
205
206 fn validate_label(label: &[u8]) -> Result<(), MtopError> {
207 for (i, c) in label.iter().copied().map(char::from).enumerate() {
208 if i == 0 && c != '_' && !c.is_ascii_alphanumeric() {
209 return Err(MtopError::configuration(format!(
210 "label must begin with ASCII letter, number, or underscore; got {}",
211 c
212 )));
213 } else if i == label.len() - 1 && !c.is_ascii_alphanumeric() {
214 return Err(MtopError::configuration(format!(
215 "label must end with ASCII letter or number; got {}",
216 c
217 )));
218 } else if c != '-' && c != '_' && !c.is_ascii_alphanumeric() {
219 return Err(MtopError::configuration(format!(
220 "label must be ASCII letter, number, hyphen, or underscore; got {}",
221 c
222 )));
223 }
224 }
225
226 Ok(())
227 }
228
229 fn is_standard_label(len: u8) -> bool {
230 len & 0b1100_0000 == 0
231 }
232
233 fn is_compressed_label(len: u8) -> bool {
234 len & 0b1100_0000 == 192
238 }
239
240 fn get_offset(len: u8, next: u8) -> u16 {
241 let pointer = u16::from(len & 0b0011_1111) << 8;
242 pointer | u16::from(next)
243 }
244
245 fn from_bytes(bytes: &[u8]) -> Result<Self, MtopError> {
251 if bytes.is_empty() || bytes == b"." {
252 return Ok(Self::root());
253 }
254
255 let (bytes, is_fqdn) = match bytes.strip_suffix(b".") {
259 Some(stripped) => (stripped, true),
260 None => (bytes, false),
261 };
262
263 if bytes.len() + 2 > Self::MAX_LENGTH {
267 return Err(MtopError::configuration(format!(
268 "Name too long; max {} bytes, got {}",
269 Self::MAX_LENGTH,
270 bytes.len()
271 )));
272 }
273
274 let mut labels = Vec::with_capacity(Self::NUM_LABELS_HINT);
275 for label in bytes.split(|&b| b == b'.') {
276 if label.len() > Self::MAX_LABEL_LENGTH {
277 return Err(MtopError::configuration(format!(
278 "label too long; max {} bytes, got {}",
279 Self::MAX_LABEL_LENGTH,
280 label.len(),
281 )));
282 }
283
284 Self::validate_label(label)?;
285 labels.push(label.to_ascii_lowercase());
286 }
287
288 Ok(Self { labels, is_fqdn })
289 }
290}
291
292impl fmt::Display for Name {
293 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294 let len = self.labels.len();
295 for (i, l) in self.labels.iter().enumerate() {
296 unsafe { str::from_utf8_unchecked(l) }.fmt(f)?;
298 if i != len - 1 {
299 ".".fmt(f)?;
300 }
301 }
302 if self.is_fqdn {
303 ".".fmt(f)?;
304 }
305
306 Ok(())
307 }
308}
309
310impl FromStr for Name {
311 type Err = MtopError;
312
313 fn from_str(s: &str) -> Result<Self, Self::Err> {
314 Self::from_bytes(s.as_bytes())
315 }
316}
317
318#[cfg(test)]
319mod test {
320 use super::Name;
321 use std::io::Cursor;
322 use std::str::FromStr;
323
324 #[test]
325 fn test_name_from_str_error_max_length_fqdn() {
326 let parts = [
327 "a".repeat(Name::MAX_LABEL_LENGTH),
328 "b".repeat(Name::MAX_LABEL_LENGTH),
329 "c".repeat(Name::MAX_LABEL_LENGTH),
330 "d".repeat(Name::MAX_LABEL_LENGTH - 1),
331 ];
332
333 let complete = {
334 let mut s = parts.join(".");
335 s.push('.');
336 s
337 };
338
339 let res = Name::from_str(&complete);
343 assert!(res.is_err(), "expected an error, got {:?}", res);
344 }
345
346 #[test]
347 fn test_name_from_str_error_max_length_not_fqdn() {
348 let parts = [
349 "a".repeat(Name::MAX_LABEL_LENGTH),
350 "b".repeat(Name::MAX_LABEL_LENGTH),
351 "c".repeat(Name::MAX_LABEL_LENGTH),
352 "d".repeat(Name::MAX_LABEL_LENGTH - 1),
353 ];
354
355 let complete = parts.join(".");
356
357 let res = Name::from_str(&complete);
362 assert!(res.is_err(), "expected an error, got {:?}", res);
363 }
364
365 #[test]
366 fn test_name_from_str_error_max_label() {
367 let parts = ["a".repeat(Name::MAX_LABEL_LENGTH + 1), "com.".to_owned()];
368 let res = Name::from_str(&parts.join("."));
369 assert!(res.is_err(), "expected an error, got {:?}", res);
370 }
371
372 #[test]
373 fn test_name_from_str_error_bad_label_start() {
374 let res = Name::from_str("-example.com.");
375 assert!(res.is_err(), "expected an error, got {:?}", res);
376 }
377
378 #[test]
379 fn test_name_from_str_error_bad_label_end() {
380 let res = Name::from_str("example-.com.");
381 assert!(res.is_err(), "expected an error, got {:?}", res);
382 }
383
384 #[test]
385 fn test_name_from_str_error_bad_label_char() {
386 let res = Name::from_str("exa%mple.com.");
387 assert!(res.is_err(), "expected an error, got {:?}", res);
388 }
389
390 #[test]
391 fn test_name_from_str_success_not_fqdn() {
392 let name = Name::from_str("example.com").unwrap();
393 assert!(!name.is_root());
394 assert!(!name.is_fqdn());
395 }
396
397 #[test]
398 fn test_name_from_str_success_fqdn() {
399 let name = Name::from_str("example.com.").unwrap();
400 assert!(!name.is_root());
401 assert!(name.is_fqdn());
402 }
403
404 #[test]
405 fn test_name_from_str_success_root_empty() {
406 let name = Name::from_str("").unwrap();
407 assert!(name.is_root());
408 assert!(name.is_fqdn());
409 }
410
411 #[test]
412 fn test_name_from_str_success_root_dot() {
413 let name = Name::from_str(".").unwrap();
414 assert!(name.is_root());
415 assert!(name.is_fqdn());
416 }
417
418 #[test]
419 fn test_name_to_string_not_fqdn() {
420 let name = Name::from_str("example.com").unwrap();
421 assert_eq!("example.com", name.to_string());
422 assert!(!name.is_fqdn());
423 }
424
425 #[test]
426 fn test_name_to_string_fqdn() {
427 let name = Name::from_str("example.com.").unwrap();
428 assert_eq!("example.com.", name.to_string());
429 assert!(name.is_fqdn());
430 }
431
432 #[test]
433 fn test_name_to_string_root() {
434 let name = Name::root();
435 assert_eq!(".", name.to_string());
436 assert!(name.is_fqdn());
437 }
438
439 #[test]
440 fn test_name_to_fqdn_not_fqdn() {
441 let name = Name::from_str("example.com").unwrap();
442 assert!(!name.is_fqdn());
443
444 let fqdn = name.to_fqdn();
445 assert!(fqdn.is_fqdn());
446 }
447
448 #[test]
449 fn test_name_to_fqdn_already_fqdn() {
450 let name = Name::from_str("example.com.").unwrap();
451 assert!(name.is_fqdn());
452
453 let fqdn = name.to_fqdn();
454 assert!(fqdn.is_fqdn());
455 }
456
457 #[test]
458 fn test_name_append_already_fqdn() {
459 let name1 = Name::from_str("example.com.").unwrap();
460 let name2 = Name::from_str("example.net.").unwrap();
461 let combined = name1.clone().append(name2);
462
463 assert_eq!(name1, combined);
464 assert!(combined.is_fqdn());
465 }
466
467 #[test]
468 fn test_name_append_with_non_fqdn() {
469 let name1 = Name::from_str("www").unwrap();
470 let name2 = Name::from_str("example").unwrap();
471 let combined = name1.clone().append(name2);
472
473 assert_eq!(Name::from_str("www.example").unwrap(), combined);
474 assert!(!combined.is_fqdn());
475 }
476
477 #[test]
478 fn test_name_append_with_fqdn() {
479 let name1 = Name::from_str("www").unwrap();
480 let name2 = Name::from_str("example.net.").unwrap();
481 let combined = name1.clone().append(name2);
482
483 assert_eq!(Name::from_str("www.example.net.").unwrap(), combined);
484 assert!(combined.is_fqdn());
485 }
486
487 #[test]
488 fn test_name_append_with_root() {
489 let name = Name::from_str("example.com").unwrap();
490 let combined = name.clone().append(Name::root());
491
492 assert_eq!(Name::from_str("example.com.").unwrap(), combined);
493 assert!(combined.is_fqdn());
494 }
495
496 #[test]
497 fn test_name_append_multiple() {
498 let name1 = Name::from_str("dev").unwrap();
499 let name2 = Name::from_str("www").unwrap();
500 let name3 = Name::from_str("example.com").unwrap();
501
502 let combined = name1.append(name2).append(name3).append(Name::root());
503 assert_eq!(Name::from_str("dev.www.example.com.").unwrap(), combined);
504 assert!(combined.is_fqdn());
505 }
506
507 #[test]
508 fn test_name_size_root() {
509 let name = Name::root();
510 assert_eq!(1, name.size());
511 }
512
513 #[test]
514 fn test_name_size_non_root() {
515 let name = Name::from_str("example.com.").unwrap();
516 assert_eq!(13, name.size());
517 }
518
519 #[test]
520 fn test_name_size_non_root_fqdn() {
521 let name = Name::from_str("example.com").unwrap();
522 assert!(!name.is_fqdn());
523 assert_eq!(13, name.size());
524
525 let name = name.to_fqdn();
530 assert!(name.is_fqdn());
531 assert_eq!(13, name.size());
532 }
533
534 #[test]
535 fn test_name_equal_same_case() {
536 let name1 = Name::from_str("example.com.").unwrap();
537 let name2 = Name::from_str("example.com.").unwrap();
538
539 assert_eq!(name1, name2);
540 }
541
542 #[test]
543 fn test_name_equal_different_case() {
544 let name1 = Name::from_str("example.com.").unwrap();
545 let name2 = Name::from_str("EXAMPLE.cOm.").unwrap();
546
547 assert_eq!(name1, name2);
548 }
549
550 #[test]
551 fn test_name_equal_different_fqdn() {
552 let name1 = Name::from_str("example.com").unwrap();
553 let name2 = Name::from_str("example.com.").unwrap();
554
555 assert_ne!(name1, name2);
556 }
557
558 #[test]
559 fn test_name_write_network_bytes_root() {
560 let mut cur = Cursor::new(Vec::new());
561 let name = Name::root();
562 name.write_network_bytes(&mut cur).unwrap();
563 let buf = cur.into_inner();
564
565 assert_eq!(vec![0], buf);
566 }
567
568 #[rustfmt::skip]
569 #[test]
570 fn test_name_write_network_bytes_not_root() {
571 let mut cur = Cursor::new(Vec::new());
572 let name = Name::from_str("example.com.").unwrap();
573 name.write_network_bytes(&mut cur).unwrap();
574 let buf = cur.into_inner();
575
576 assert_eq!(
577 vec![
578 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ],
584 buf,
585 );
586 }
587
588 #[should_panic = "only fully qualified domains can be encoded"]
589 #[test]
590 fn test_name_write_network_bytes_not_fqdn() {
591 let mut cur = Cursor::new(Vec::new());
592 let name = Name::from_str("example.com").unwrap();
593 let _ = name.write_network_bytes(&mut cur);
594 }
595
596 #[rustfmt::skip]
597 #[test]
598 fn test_name_read_network_bytes_no_pointer() {
599 let cur = Cursor::new(vec![
600 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ]);
606
607 let name = Name::read_network_bytes(cur).unwrap();
608 assert_eq!("example.com.", name.to_string());
609 assert!(name.is_fqdn());
610 }
611
612 #[rustfmt::skip]
613 #[test]
614 fn test_name_read_network_bytes_bad_label_type() {
615 let cur = Cursor::new(vec![
616 64, 0, ]);
619
620 let res = Name::read_network_bytes(cur);
621 assert!(res.is_err(), "expected an error, got {:?}", res);
622 }
623
624 #[rustfmt::skip]
625 #[test]
626 fn test_name_read_network_bytes_bad_label_type_after_single_pointer() {
627 let mut cur = Cursor::new(vec![
628 7, 101, 120, 97, 109, 112, 108, 101, 64, 0, 3, 119, 119, 119, 192, 0, ]);
636
637 cur.set_position(10);
638
639 let res = Name::read_network_bytes(&mut cur);
640 assert!(res.is_err(), "expected an error, got {:?}", res);
641 }
642
643 #[rustfmt::skip]
644 #[test]
645 fn test_name_read_network_bytes_single_pointer() {
646 let mut cur = Cursor::new(vec![
647 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, ]);
656
657 cur.set_position(13);
658
659 let name = Name::read_network_bytes(&mut cur).unwrap();
660 assert_eq!("www.example.com.", name.to_string());
661 assert!(name.is_fqdn());
662 assert_eq!(19, cur.position());
663 }
664
665 #[rustfmt::skip]
666 #[test]
667 fn test_name_read_network_bytes_multiple_pointer() {
668 let mut cur = Cursor::new(vec![
669 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, 3, 100, 101, 118, 192, 13, ]);
681
682 cur.set_position(19);
683
684 let name = Name::read_network_bytes(&mut cur).unwrap();
685 assert_eq!("dev.www.example.com.", name.to_string());
686 assert!(name.is_fqdn());
687 assert_eq!(25, cur.position());
688 }
689
690 #[rustfmt::skip]
691 #[test]
692 fn test_name_read_network_bytes_multiple_pointer_multiple_name() {
693 let mut cur = Cursor::new(vec![
694 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, 3, 100, 101, 118, 192, 13, ]);
706
707 let name1 = Name::read_network_bytes(&mut cur).unwrap();
708 assert_eq!("example.com.", name1.to_string());
709 assert!(name1.is_fqdn());
710
711 let name2 = Name::read_network_bytes(&mut cur).unwrap();
712 assert_eq!("www.example.com.", name2.to_string());
713 assert!(name2.is_fqdn());
714
715 let name3 = Name::read_network_bytes(&mut cur).unwrap();
716 assert_eq!("dev.www.example.com.", name3.to_string());
717 assert!(name3.is_fqdn());
718
719 assert_eq!(25, cur.position());
720 }
721
722 #[rustfmt::skip]
723 #[test]
724 fn test_name_read_network_bytes_single_pointer_bad_chars() {
725 let mut cur = Cursor::new(vec![
726 7, 101, 120, 97, 37, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, ]);
735
736 cur.set_position(13);
737
738 let res = Name::read_network_bytes(&mut cur);
739 assert!(res.is_err(), "expected an error, got {:?}", res);
740 }
741
742 #[rustfmt::skip]
743 #[test]
744 fn test_name_read_network_bytes_single_pointer_normalize_case() {
745 let mut cur1 = Cursor::new(vec![
746 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, ]);
755
756 cur1.set_position(13);
757
758 let mut cur2 = Cursor::new(vec![
759 7, 101, 120, 97, 77, 112, 108, 101, 3, 99, 111, 109, 0, 3, 119, 119, 119, 192, 0, ]);
768
769 cur2.set_position(13);
770
771 let name1 = Name::read_network_bytes(&mut cur1).unwrap();
772 let name2 = Name::read_network_bytes(&mut cur2).unwrap();
773 assert_eq!(name1, name2);
774 }
775
776 #[rustfmt::skip]
777 #[test]
778 fn test_name_read_network_bytes_invalid_label_length() {
779 let cur = Cursor::new(vec![
780 66, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ]);
786
787 let res = Name::read_network_bytes(cur);
788 assert!(res.is_err(), "expected an error, got {:?}", res);
789 }
790
791 #[rustfmt::skip]
792 #[test]
793 fn test_name_read_network_bytes_invalid_total_length() {
794 let label63 = vec![
795 63, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, ];
806
807 let label62 = vec![
808 62, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, 101, 101, 120, 97, 109, 112, 108, ];
819
820 let mut complete = Vec::new();
823 complete.extend_from_slice(&label63); complete.extend_from_slice(&label63); complete.extend_from_slice(&label63); complete.extend_from_slice(&label62); complete.push(0u8); let res = Name::read_network_bytes(Cursor::new(complete));
830 assert!(res.is_err(), "expected an error, got {:?}", res);
831 }
832
833 #[test]
834 fn test_name_read_network_bytes_pointer_loop() {
835 let mut cur = Cursor::new(vec![
836 192, 2, 192, 0, ]);
839
840 let res = Name::read_network_bytes(&mut cur);
841 assert!(res.is_err(), "expected an error, got {:?}", res);
842 }
843}