1use core::convert::TryInto;
4use core::fmt;
5
6use serde::{Serialize, Serializer};
7
8use crate::errors::Error;
9use crate::layers::udp;
10use crate::types::{IPv4Address, IPv6Address};
11use crate::Layer;
12
13#[derive(Default, Debug, Serialize)]
14pub struct DNSSOA {
15 mname: DNSName,
16 rname: DNSName,
17 serial: u32,
18 refresh: u32,
19 retry: u32,
20 expire: u32,
21 minimum: u32,
22}
23
24#[derive(Debug, Serialize)]
25pub enum DNSRecordData {
26 Empty,
27 A(IPv4Address),
28 AAAA(IPv6Address),
29 CNAME(DNSName),
30 MB(DNSName),
31 MD(DNSName),
32 MF(DNSName),
33 MG(DNSName),
34 MINFO((DNSName, DNSName)),
35 MR(DNSName),
36 MX((u16, DNSName)),
37 PTR(DNSName),
38 NULL(Vec<u8>),
39 SOA(DNSSOA),
40}
41
42pub(crate) fn register_defaults() -> Result<(), Error> {
44 udp::register_app(53, DNS::creator)
45}
46
47#[derive(Default)]
48pub struct DNSName(Vec<u8>);
49
50impl fmt::Display for DNSName {
51 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52 let mut i = 0_usize;
53 let mut name_parts: Vec<&str> = Vec::new();
54 while self.0[i] != 0 {
55 let x = self.0[i] as usize;
56 let out_str = core::str::from_utf8(&self.0[i + 1..=i + x]);
57 if let Ok(out_str) = out_str {
58 name_parts.push(out_str);
59 i += x + 1;
60 }
61 }
62 let name = name_parts.join(".");
63 write!(f, "{}", name)
64 }
65}
66
67impl fmt::Debug for DNSName {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 fmt::Display::fmt(self, f)
70 }
71}
72
73impl Serialize for DNSName {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 serializer.serialize_str(format!("{}", self).as_str())
79 }
80}
81
82#[derive(Debug, Default, Serialize)]
83pub struct DNSQRecord {
84 name: DNSName,
85 #[serde(rename = "type")]
86 type_: u16,
87 class: u16,
88}
89
90#[derive(Debug, Serialize)]
91pub struct DNSResRecord {
92 name: DNSName,
93 #[serde(rename = "type")]
94 type_: u16,
95 class: u16,
96 ttl: u32,
97 rdlength: u16,
98 #[serde(flatten)]
99 rdata: DNSRecordData,
100}
101
102#[derive(Debug, Default, Serialize)]
103pub struct DNS {
104 #[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u16")]
105 id: u16,
106 qr: bool,
107 opcode: u8,
108 aa: bool,
109 tc: bool,
110 rd: bool,
111 ra: bool,
112 z: u8,
113 rcode: u8,
114 qdcount: u16,
115 ancount: u16,
116 nscount: u16,
117 arcount: u16,
118 questions: Vec<DNSQRecord>,
119 answers: Vec<DNSResRecord>,
120 nameservers: Vec<DNSResRecord>,
121 additional: Vec<DNSResRecord>,
122}
123
124impl DNS {
125 pub(crate) fn creator() -> Box<dyn Layer + Send> {
126 Box::<DNS>::default()
127 }
128
129 fn dns_name_from_bytes(
132 bytes: &[u8],
133 start: usize,
134 remaining: usize,
135 ) -> Result<(DNSName, usize), Error> {
136 fn labels_from_offset(
138 bytes: &[u8],
139 offset: usize,
140 labels: &mut Vec<u8>,
141 mut remaining: usize,
142 check_remaining: bool,
143 ) -> Result<usize, Error> {
144 let mut i = offset;
145
146 if offset > bytes.len() {
147 return Err(Error::ParseError(format!(
148 "Offset is : {}, remaining : {}",
149 offset,
150 bytes.len(),
151 )));
152 }
153
154 let mut consumed = 0;
155 let _ = loop {
156 let ptr = bytes[i] & 0xC0;
157 match ptr {
158 0xC0 => {
159 let previous =
166 ((bytes[i] & 0x3f) as u16) << 8 | ((bytes[i + 1] as u16) - 12);
167 let _ = labels_from_offset(bytes, previous as usize, labels, 0, false)?;
168 consumed += 2;
169 break true;
170 }
171 0x00 => {
172 if bytes[i] == 0x00 {
173 consumed += 1;
174 labels.push(bytes[i]);
175 break false;
176 }
177
178 let count = bytes[i] as usize + 1_usize;
180 if check_remaining {
181 if remaining < count {
182 return Err(Error::TooShort {
183 required: count,
184 available: remaining,
185 data: hex::encode(&bytes[i..]),
186 });
187 }
188 consumed += count;
189 remaining -= count;
190 }
191
192 labels.extend_from_slice(&bytes[i..i + count]);
193 i += count;
194 }
195 _ => {
196 return Err(Error::ParseError(format!("Unknown DNS PTR: {:x}", ptr)));
197 }
198 }
199 };
200
201 Ok(consumed)
202 }
203
204 let mut labels = Vec::with_capacity(24);
206 let consumed = labels_from_offset(bytes, start, &mut labels, remaining, true)?;
207
208 Ok((DNSName(labels), consumed))
209 }
210
211 fn dns_resrecord_from_bytes(
212 bytes: &[u8],
213 start: usize,
214 mut remaining: usize,
215 ) -> Result<(DNSResRecord, usize), Error> {
216 let mut i = 0;
217 let mut offset = start;
218 let (name, consumed) = Self::dns_name_from_bytes(bytes, start, remaining)?;
219
220 i += consumed;
221 remaining -= consumed;
222 offset += consumed;
223
224 if remaining < 10 {
225 return Err(Error::TooShort {
226 required: 10,
227 available: remaining,
228 data: hex::encode(&bytes[i..]),
229 });
230 }
231
232 let type_ = (bytes[offset] as u16) << 8 | (bytes[offset + 1] as u16);
233 let class = (bytes[offset + 2] as u16) << 8 | (bytes[offset + 3] as u16);
234 let ttl = (bytes[offset + 4] as u32) << 24
235 | (bytes[offset + 5] as u32) << 16
236 | (bytes[offset + 6] as u32) << 8
237 | (bytes[offset + 7] as u32);
238 let rdlength = (bytes[offset + 8] as u16) << 8 | (bytes[offset + 9] as u16);
239 offset += 10;
240 if remaining < (rdlength as usize) {
241 return Err(Error::TooShort {
242 required: rdlength as usize,
243 available: remaining,
244 data: hex::encode(&bytes[offset..]),
245 });
246 }
247 let rdata_buffer = &bytes[offset..offset + rdlength as usize];
248
249 i += 10;
250 remaining -= 10;
251
252 let rdata = match type_ {
253 1 => DNSRecordData::A(rdata_buffer.try_into().unwrap()), 28 => DNSRecordData::AAAA(rdata_buffer.try_into().unwrap()), 2 | 3 | 4 | 5 | 7 | 8 | 9 => {
256 let (name, _) = Self::dns_name_from_bytes(bytes, offset, remaining)?;
257 DNSRecordData::CNAME(name)
258 }
259 6 =>
260 {
262 let mut offset = offset;
264 let mut remaining = remaining;
265 let (mname, consumed) = Self::dns_name_from_bytes(bytes, offset, remaining)?;
266 offset += consumed;
267 remaining -= consumed;
268 let (rname, consumed) = Self::dns_name_from_bytes(bytes, offset, remaining)?;
269 offset += consumed;
270 remaining -= consumed;
271 if remaining < 20 {
272 return Err(Error::TooShort {
273 required: 20,
274 available: remaining,
275 data: hex::encode(&bytes[offset..]),
276 });
277 }
278 let serial = (bytes[offset] as u32) << 24
280 | (bytes[offset + 1] as u32) << 16
281 | (bytes[offset + 2] as u32) << 8
282 | (bytes[offset + 3] as u32);
283 let refresh = (bytes[offset + 4] as u32) << 24
284 | (bytes[offset + 5] as u32) << 16
285 | (bytes[offset + 6] as u32) << 8
286 | (bytes[offset + 7] as u32);
287 let retry = (bytes[offset + 8] as u32) << 24
288 | (bytes[offset + 9] as u32) << 16
289 | (bytes[offset + 10] as u32) << 8
290 | (bytes[offset + 11] as u32);
291 let expire = (bytes[offset + 12] as u32) << 24
292 | (bytes[offset + 13] as u32) << 16
293 | (bytes[offset + 14] as u32) << 8
294 | (bytes[offset + 15] as u32);
295 let minimum = (bytes[offset + 16] as u32) << 24
296 | (bytes[offset + 17] as u32) << 16
297 | (bytes[offset + 18] as u32) << 8
298 | (bytes[offset + 19] as u32);
299
300 DNSRecordData::SOA(DNSSOA {
304 mname,
305 rname,
306 serial,
307 refresh,
308 retry,
309 expire,
310 minimum,
311 })
312 }
313 _ => DNSRecordData::NULL(rdata_buffer.into()),
315 };
316 i += rdlength as usize;
317 Ok((
320 DNSResRecord {
321 name,
322 type_,
323 class,
324 ttl,
325 rdlength,
326 rdata,
327 },
328 i,
329 ))
330 }
331
332 fn records_from_bytes(&mut self, bytes: &[u8], mut remaining: usize) -> Result<usize, Error> {
333 let mut i = 0;
334
335 for _ in 0..self.qdcount {
337 let (name, consumed) = Self::dns_name_from_bytes(bytes, i, remaining)?;
338
339 i += consumed;
340 remaining -= consumed;
341
342 let type_ = (bytes[i] as u16) << 8 | (bytes[i + 1] as u16);
343 let class = (bytes[i + 2] as u16) << 8 | (bytes[i + 3] as u16);
344
345 self.questions.push(DNSQRecord { name, type_, class });
346 i += 4;
347 remaining -= 4;
348 }
349
350 for _ in 0..self.ancount {
351 let (record, consumed) = Self::dns_resrecord_from_bytes(bytes, i, remaining)?;
352
353 i += consumed;
354 remaining -= consumed;
355 self.answers.push(record);
356 }
357
358 for _ in 0..self.nscount {
359 let (record, consumed) = Self::dns_resrecord_from_bytes(bytes, i, remaining)?;
360
361 i += consumed;
362 remaining -= consumed;
363 self.nameservers.push(record);
364 }
365
366 for _ in 0..self.arcount {
367 let (record, consumed) = Self::dns_resrecord_from_bytes(bytes, i, remaining)?;
368
369 i += consumed;
370 remaining -= consumed;
371 self.additional.push(record);
372 }
373
374 Ok(i)
375 }
376}
377
378impl Layer for DNS {
379 fn decode_bytes(
380 &mut self,
381 bytes: &[u8],
382 ) -> Result<(Option<Box<dyn Layer + Send>>, usize), Error> {
383 let mut decoded;
384
385 if bytes.len() < 12 {
386 return Err(Error::TooShort {
387 required: 12,
388 available: bytes.len(),
389 data: hex::encode(bytes),
390 });
391 }
392
393 self.id = (bytes[0] as u16) << 8 | (bytes[1] as u16);
395
396 let first = bytes[2];
397 self.qr = (first & 0x80) != 0x00;
398 self.opcode = (first & 0x78) >> 3;
399 self.aa = (first & 0x04) != 0x00;
400 self.tc = (first & 0x02) != 0x00;
401 self.rd = (first & 0x01) != 0x00;
402
403 let second = bytes[3];
404 self.ra = (second & 0x80) != 0x80;
405 self.z = 0;
406 self.rcode = second & 0x0f;
407
408 self.qdcount = (bytes[4] as u16) << 8 | (bytes[5] as u16);
409 self.ancount = (bytes[6] as u16) << 8 | (bytes[7] as u16);
410 self.nscount = (bytes[8] as u16) << 8 | (bytes[9] as u16);
411 self.arcount = (bytes[10] as u16) << 8 | (bytes[11] as u16);
412
413 decoded = 12;
414
415 let remaining = bytes.len() - 12;
416 let record_bytes = self.records_from_bytes(&bytes[decoded..], remaining)?;
417 decoded += record_bytes;
418
419 Ok((None, decoded))
420 }
421
422 fn name(&self) -> &'static str {
423 "DNS"
424 }
425
426 fn short_name(&self) -> &'static str {
427 "dns"
428 }
429}
430
431#[cfg(test)]
432mod tests {
433
434 use crate::layers;
435 use crate::{Layer, Packet, ENCAP_TYPE_ETH};
436
437 wasm_tests! {
438 #[test]
439 fn parse_valid_dns_packet() {
440 let _ = layers::register_defaults();
441
442 let dns_query = vec![
443 0x52, 0x54, 0x00, 0xbd, 0x1c, 0x70, 0xfe, 0x54, 0x00, 0x3e, 0x00, 0x96, 0x08, 0x00, 0x45, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11, 0xc4, 0x74, 0xc0, 0xa8, 0x7a, 0x01, 0xc0, 0xa8, 0x7a, 0x46, 0x00, 0x35, 0xdb, 0x13, 0x00, 0xcc, 0x76, 0x76, 0xf3, 0x03, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x04, 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x10, 0x2a, 0x00, 0x14, 0x50, 0x40, 0x0c, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0xc0, 0x10, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x06, 0x03, 0x6e, 0x73, 0x34, 0xc0, 0x10, 0xc0, 0x10, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x06, 0x03, 0x6e, 0x73, 0x32, 0xc0, 0x10, 0xc0, 0x10, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x06, 0x03, 0x6e, 0x73, 0x31, 0xc0, 0x10, 0xc0, 0x10, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x06, 0x03, 0x6e, 0x73, 0x33, 0xc0, 0x10, 0xc0, 0x6c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x04, 0xd8, 0xef, 0x20, 0x0a, 0xc0, 0x5a, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x04, 0xd8, 0xef, 0x22, 0x0a, 0xc0, 0x7e, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x04, 0xd8, 0xef, 0x24, 0x0a, 0xc0, 0x48, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xa3, 0x00, 0x00, 0x04, 0xd8, 0xef, 0x26, 0x0a, ];
474
475 let mut dns: Box<dyn Layer> = Box::new(super::DNS::default());
476
477 let p = dns.decode_bytes(&dns_query[42..]);
478 assert!(p.is_ok(), "{:#?}", dns);
479 }
480
481 #[test]
482 fn test_dns_parse_gopacket_regression() {
483 let _ = layers::register_defaults();
484
485 let test_packet_dns_regression = vec![
494 0x00, 0x22, 0x19, 0xb6, 0x7e, 0x22, 0x00, 0x0f, 0x35, 0xbb, 0x0b, 0x40, 0x08, 0x00,
495 0x45, 0x00, 0x00, 0x44, 0x89, 0xc4, 0x00, 0x00, 0x38, 0x11, 0x2f, 0x3d, 0x6d, 0xc2,
496 0xa0, 0x04, 0x5f, 0xd3, 0x5c, 0x0e, 0xe1, 0xa6, 0x00, 0x35, 0x00, 0x30, 0xa5, 0x97,
497 0xf6, 0x18, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x70,
498 0x69, 0x63, 0x73, 0x6c, 0x69, 0x66, 0x65, 0x02, 0x72, 0x75, 0x00, 0x00, 0x01, 0x00,
499 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
500 ];
501 let p = Packet::from_bytes(&test_packet_dns_regression, ENCAP_TYPE_ETH);
502 assert!(p.is_ok());
503 let p = p.unwrap();
504 assert!(p.layers.len() == 4, "{:#?}", p);
505 }
506 }
507}