dns_parser_revived/
name.rs1use std::fmt;
2use std::fmt::Write;
3use std::str::from_utf8;
4
5#[allow(unused_imports, deprecated)]
7use std::ascii::AsciiExt;
8
9use byteorder::{BigEndian, ByteOrder};
10
11use crate::Error;
12
13#[derive(Clone, Copy)]
18pub struct Name<'a> {
19 labels: &'a [u8],
20 original: &'a [u8],
23}
24
25impl<'a> Name<'a> {
26 pub fn scan(data: &'a [u8], original: &'a [u8]) -> Result<Name<'a>, Error> {
32 let mut parse_data = data;
33 let mut return_pos = None;
34 let mut pos = 0;
35 if parse_data.len() <= pos {
36 return Err(Error::UnexpectedEOF);
37 }
38 let mut largest_pos = original.len();
41 let mut byte = parse_data[pos];
42 while byte != 0 {
43 if parse_data.len() <= pos {
44 return Err(Error::UnexpectedEOF);
45 }
46 if byte & 0b1100_0000 == 0b1100_0000 {
47 if parse_data.len() < pos + 2 {
48 return Err(Error::UnexpectedEOF);
49 }
50 let off = (BigEndian::read_u16(&parse_data[pos..pos + 2]) & !0b1100_0000_0000_0000)
51 as usize;
52 if off >= original.len() {
53 return Err(Error::UnexpectedEOF);
54 }
55 if return_pos.is_none() {
59 return_pos = Some(pos);
60 }
61
62 if off >= largest_pos {
65 return Err(Error::BadPointer);
66 }
67 largest_pos = off;
68 pos = 0;
69 parse_data = &original[off..];
70 } else if byte & 0b1100_0000 == 0 {
71 let end = pos + byte as usize + 1;
72 if parse_data.len() < end {
73 return Err(Error::UnexpectedEOF);
74 }
75 if !parse_data[pos + 1..end].is_ascii() {
76 return Err(Error::LabelIsNotAscii);
77 }
78 pos = end;
79 if parse_data.len() <= pos {
80 return Err(Error::UnexpectedEOF);
81 }
82 } else {
83 return Err(Error::UnknownLabelFormat);
84 }
85 byte = parse_data[pos];
86 }
87 if let Some(return_pos) = return_pos {
88 Ok(Name {
89 labels: &data[..return_pos + 2],
90 original,
91 })
92 } else {
93 Ok(Name {
94 labels: &data[..pos + 1],
95 original,
96 })
97 }
98 }
99 pub fn byte_len(&self) -> usize {
101 self.labels.len()
102 }
103}
104
105impl fmt::Display for Name<'_> {
106 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
107 let data = self.labels;
108 let original = self.original;
109 let mut pos = 0;
110 loop {
111 let byte = data[pos];
112 if byte == 0 {
113 return Ok(());
114 } else if byte & 0b1100_0000 == 0b1100_0000 {
115 let off =
116 (BigEndian::read_u16(&data[pos..pos + 2]) & !0b1100_0000_0000_0000) as usize;
117 if pos != 0 {
118 fmt.write_char('.')?;
119 }
120 return fmt::Display::fmt(&Name::scan(&original[off..], original).unwrap(), fmt);
121 } else if byte & 0b1100_0000 == 0 {
122 if pos != 0 {
123 fmt.write_char('.')?;
124 }
125 let end = pos + byte as usize + 1;
126 fmt.write_str(from_utf8(&data[pos + 1..end]).unwrap())?;
127 pos = end;
128 continue;
129 } else {
130 unreachable!();
131 }
132 }
133 }
134}
135impl fmt::Debug for Name<'_> {
136 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
137 fmt.debug_tuple("Name").field(&format!("{}", self)).finish()
138 }
139}
140
141#[cfg(test)]
142mod test {
143 use crate::Error;
144 use crate::Name;
145
146 #[test]
147 fn parse_badpointer_same_offset() {
148 let same_offset = vec![192, 2, 192, 2];
151 let is_match = matches!(
152 Name::scan(&same_offset, &same_offset),
153 Err(Error::BadPointer)
154 );
155
156 assert!(is_match);
157 }
158
159 #[test]
160 fn parse_badpointer_forward_offset() {
161 let forwards_offset = vec![192, 2, 192, 4, 192, 2];
164 let is_match = matches!(
165 Name::scan(&forwards_offset, &forwards_offset),
166 Err(Error::BadPointer)
167 );
168
169 assert!(is_match);
170 }
171
172 #[test]
173 fn nested_names() {
174 let buf = b"\x02xx\x00\x02yy\xc0\x00\x02zz\xc0\x04";
176
177 assert_eq!(Name::scan(&buf[..], buf).unwrap().to_string(), "xx");
178 assert_eq!(Name::scan(&buf[..], buf).unwrap().labels, b"\x02xx\x00");
179 assert_eq!(Name::scan(&buf[4..], buf).unwrap().to_string(), "yy.xx");
180 assert_eq!(
181 Name::scan(&buf[4..], buf).unwrap().labels,
182 b"\x02yy\xc0\x00"
183 );
184 assert_eq!(Name::scan(&buf[9..], buf).unwrap().to_string(), "zz.yy.xx");
185 assert_eq!(
186 Name::scan(&buf[9..], buf).unwrap().labels,
187 b"\x02zz\xc0\x04"
188 );
189 }
190}