1#![deny(missing_docs)]
22
23use packet_dissector_core::dissector::{DispatchHint, DissectResult, Dissector};
24use packet_dissector_core::error::PacketError;
25use packet_dissector_core::field::{FieldDescriptor, FieldType, FieldValue, FormatContext};
26use packet_dissector_core::packet::DissectBuffer;
27use packet_dissector_core::util::{read_be_u16, read_be_u32};
28
29const HEADER_SIZE: usize = 12;
31
32pub fn dns_type_name(v: u16) -> Option<&'static str> {
36 match v {
37 1 => Some("A"),
38 2 => Some("NS"),
39 5 => Some("CNAME"),
40 6 => Some("SOA"),
41 12 => Some("PTR"),
42 15 => Some("MX"),
43 16 => Some("TXT"),
44 28 => Some("AAAA"),
45 29 => Some("LOC"),
46 33 => Some("SRV"),
47 35 => Some("NAPTR"),
48 41 => Some("OPT"),
49 43 => Some("DS"),
50 46 => Some("RRSIG"),
51 47 => Some("NSEC"),
52 48 => Some("DNSKEY"),
53 50 => Some("NSEC3"),
54 52 => Some("TLSA"),
55 65 => Some("HTTPS"),
56 255 => Some("ANY"),
57 _ => None,
58 }
59}
60
61fn dns_class_name(v: u16) -> Option<&'static str> {
65 match v {
66 1 => Some("IN"),
67 3 => Some("CH"),
68 4 => Some("HS"),
69 255 => Some("ANY"),
70 _ => None,
71 }
72}
73
74fn dns_opcode_name(v: u8) -> Option<&'static str> {
78 match v {
79 0 => Some("QUERY"),
80 1 => Some("IQUERY"),
81 2 => Some("STATUS"),
82 4 => Some("NOTIFY"),
83 5 => Some("UPDATE"),
84 _ => None,
85 }
86}
87
88pub fn dns_rcode_name(v: u8) -> Option<&'static str> {
92 match v {
93 0 => Some("NOERROR"),
94 1 => Some("FORMERR"),
95 2 => Some("SERVFAIL"),
96 3 => Some("NXDOMAIN"),
97 4 => Some("NOTIMP"),
98 5 => Some("REFUSED"),
99 _ => None,
100 }
101}
102
103const MAX_POINTER_DEPTH: usize = 128;
105const TYPE_A: u16 = 1;
107const TYPE_NS: u16 = 2;
108const TYPE_CNAME: u16 = 5;
109const TYPE_SOA: u16 = 6;
110const TYPE_PTR: u16 = 12;
111const TYPE_MX: u16 = 15;
112const TYPE_TXT: u16 = 16;
113const TYPE_AAAA: u16 = 28;
115const TYPE_SRV: u16 = 33;
117const TYPE_NAPTR: u16 = 35;
119const TYPE_DNAME: u16 = 39;
121const TYPE_OPT: u16 = 41;
123const TYPE_DS: u16 = 43;
125const TYPE_RRSIG: u16 = 46;
126const TYPE_NSEC: u16 = 47;
127const TYPE_DNSKEY: u16 = 48;
128const TYPE_NSEC3: u16 = 50;
130const TYPE_NSEC3PARAM: u16 = 51;
131const TYPE_SSHFP: u16 = 44;
133const TYPE_TLSA: u16 = 52;
135const TYPE_CDS: u16 = 59;
137const TYPE_CDNSKEY: u16 = 60;
138const TYPE_SVCB: u16 = 64;
140const TYPE_HTTPS: u16 = 65;
141const TYPE_CAA: u16 = 257;
143
144const FD_ID: usize = 1;
146const FD_QR: usize = 2;
147const FD_OPCODE: usize = 3;
148const FD_AA: usize = 4;
149const FD_TC: usize = 5;
150const FD_RD: usize = 6;
151const FD_RA: usize = 7;
152const FD_Z: usize = 8;
153const FD_AD: usize = 9;
154const FD_CD: usize = 10;
155const FD_RCODE: usize = 11;
156const FD_QDCOUNT: usize = 12;
157const FD_ANCOUNT: usize = 13;
158const FD_NSCOUNT: usize = 14;
159const FD_ARCOUNT: usize = 15;
160const FD_QUESTIONS: usize = 16;
161const FD_ANSWERS: usize = 17;
162const FD_AUTHORITIES: usize = 18;
163const FD_ADDITIONALS: usize = 19;
164
165const QFD_NAME: usize = 0;
167const QFD_TYPE: usize = 1;
168const QFD_CLASS: usize = 2;
169const QFD_QU: usize = 3;
173const EOFD_CODE: usize = 0;
177const EOFD_LENGTH: usize = 1;
178const EOFD_DATA: usize = 2;
179const EOFD_TIMEOUT: usize = 3;
180const RRFD_NAME: usize = 0;
185const RRFD_TYPE: usize = 1;
186const RRFD_CLASS: usize = 2;
187const RRFD_TTL: usize = 3;
188const RRFD_RDLENGTH: usize = 4;
189const RRFD_RDATA: usize = 5;
190const RRFD_UDP_PAYLOAD_SIZE: usize = 6;
191const RRFD_EXTENDED_RCODE: usize = 7;
192const RRFD_EDNS_VERSION: usize = 8;
193const RRFD_DO_BIT: usize = 9;
194const RRFD_EDNS_OPTIONS: usize = 10;
195const RRFD_RDATA_PREFERENCE: usize = 11;
196const RRFD_RDATA_EXCHANGE: usize = 12;
197const RRFD_RDATA_MNAME: usize = 13;
198const RRFD_RDATA_RNAME: usize = 14;
199const RRFD_RDATA_SERIAL: usize = 15;
200const RRFD_RDATA_REFRESH: usize = 16;
201const RRFD_RDATA_RETRY: usize = 17;
202const RRFD_RDATA_EXPIRE: usize = 18;
203const RRFD_RDATA_MINIMUM: usize = 19;
204const RRFD_RDATA_PRIORITY: usize = 20;
205const RRFD_RDATA_WEIGHT: usize = 21;
206const RRFD_RDATA_PORT: usize = 22;
207const RRFD_RDATA_TARGET: usize = 23;
208const RRFD_RDATA_ORDER: usize = 24;
209const RRFD_RDATA_FLAGS: usize = 25;
210const RRFD_RDATA_SERVICES: usize = 26;
211const RRFD_RDATA_REGEXP: usize = 27;
212const RRFD_RDATA_REPLACEMENT: usize = 28;
213const RRFD_RDATA_ALGORITHM: usize = 29;
214const RRFD_RDATA_FINGERPRINT_TYPE: usize = 30;
215const RRFD_RDATA_FINGERPRINT: usize = 31;
216const RRFD_RDATA_KEY_TAG: usize = 32;
217const RRFD_RDATA_DIGEST_TYPE: usize = 33;
218const RRFD_RDATA_DIGEST: usize = 34;
219const RRFD_RDATA_TYPE_COVERED: usize = 35;
220const RRFD_RDATA_LABELS: usize = 36;
221const RRFD_RDATA_ORIGINAL_TTL: usize = 37;
222const RRFD_RDATA_SIGNATURE_EXPIRATION: usize = 38;
223const RRFD_RDATA_SIGNATURE_INCEPTION: usize = 39;
224const RRFD_RDATA_SIGNER_NAME: usize = 40;
225const RRFD_RDATA_SIGNATURE: usize = 41;
226const RRFD_RDATA_NEXT_DOMAIN_NAME: usize = 42;
227const RRFD_RDATA_TYPE_BITMAPS: usize = 43;
228const RRFD_RDATA_PROTOCOL: usize = 44;
229const RRFD_RDATA_PUBLIC_KEY: usize = 45;
230const RRFD_RDATA_HASH_ALGORITHM: usize = 46;
231const RRFD_RDATA_ITERATIONS: usize = 47;
232const RRFD_RDATA_SALT_LENGTH: usize = 48;
233const RRFD_RDATA_SALT: usize = 49;
234const RRFD_RDATA_HASH_LENGTH: usize = 50;
235const RRFD_RDATA_NEXT_HASHED_OWNER: usize = 51;
236const RRFD_RDATA_CERT_USAGE: usize = 52;
237const RRFD_RDATA_SELECTOR: usize = 53;
238const RRFD_RDATA_MATCHING_TYPE: usize = 54;
239const RRFD_RDATA_CERT_ASSOC_DATA: usize = 55;
240const RRFD_RDATA_TAG: usize = 56;
241const RRFD_RDATA_VALUE: usize = 57;
242const RRFD_RDATA_PARAMS: usize = 58;
243const RRFD_CACHE_FLUSH: usize = 59;
247
248pub struct DnsDissector;
250
251pub fn write_dns_name(
261 _value: &FieldValue<'_>,
262 ctx: &FormatContext<'_>,
263 w: &mut dyn std::io::Write,
264) -> std::io::Result<()> {
265 let layer_start = ctx.layer_range.start as usize;
266 let layer_end = ctx.layer_range.end.min(ctx.packet_data.len() as u32) as usize;
267 let msg = &ctx.packet_data[layer_start..layer_end];
268 let name_pos = (ctx.field_range.start as usize).saturating_sub(layer_start);
269
270 w.write_all(b"\"")?;
271
272 let mut cursor = name_pos;
273 let mut first = true;
274 let mut depth = 0u8;
275
276 loop {
277 if depth >= MAX_POINTER_DEPTH as u8 || cursor >= msg.len() {
278 break;
279 }
280 depth += 1;
281
282 let byte = msg[cursor];
283 match byte & 0xC0 {
284 0x00 => {
285 let len = byte as usize;
286 if len == 0 {
287 break; }
289 if cursor + 1 + len > msg.len() {
290 break;
291 }
292 if !first {
293 w.write_all(b".")?;
294 }
295 first = false;
296 w.write_all(&msg[cursor + 1..cursor + 1 + len])?;
297 cursor += 1 + len;
298 }
299 0xC0 => {
300 if cursor + 1 >= msg.len() {
301 break;
302 }
303 let offset = (((byte as usize) & 0x3F) << 8) | (msg[cursor + 1] as usize);
304 cursor = offset;
305 }
306 _ => break, }
308 }
309
310 if first {
311 w.write_all(b".")?;
313 }
314
315 w.write_all(b"\"")
316}
317
318fn parse_name(msg: &[u8], pos: usize) -> Result<usize, PacketError> {
324 let mut cursor = pos;
325 let mut consumed = 0;
326 let mut followed_pointer = false;
327 let mut depth = 0;
328 let mut wire_len: usize = 0;
330
331 loop {
332 if depth >= MAX_POINTER_DEPTH {
333 return Err(PacketError::InvalidHeader("DNS name pointer loop detected"));
334 }
335 depth += 1;
336
337 if cursor >= msg.len() {
338 return Err(PacketError::Truncated {
339 expected: cursor + 1,
340 actual: msg.len(),
341 });
342 }
343
344 let byte = msg[cursor];
345
346 match byte & 0xC0 {
347 0x00 => {
349 let len = byte as usize;
350 if len == 0 {
351 wire_len += 1;
353 if wire_len > 255 {
354 return Err(PacketError::InvalidHeader(
355 "DNS name too long (exceeds 255 octets)",
356 ));
357 }
358 if !followed_pointer {
359 consumed += 1;
360 }
361 break;
362 }
363 wire_len += 1 + len;
365 if wire_len > 255 {
366 return Err(PacketError::InvalidHeader(
367 "DNS name too long (exceeds 255 octets)",
368 ));
369 }
370 if cursor + 1 + len > msg.len() {
371 return Err(PacketError::Truncated {
372 expected: cursor + 1 + len,
373 actual: msg.len(),
374 });
375 }
376 cursor += 1 + len;
377 if !followed_pointer {
378 consumed += 1 + len;
379 }
380 }
381 0xC0 => {
383 if cursor + 1 >= msg.len() {
384 return Err(PacketError::Truncated {
385 expected: cursor + 2,
386 actual: msg.len(),
387 });
388 }
389 let offset = (read_be_u16(msg, cursor)? & 0x3FFF) as usize;
390 if !followed_pointer {
391 consumed += 2;
392 followed_pointer = true;
393 }
394 cursor = offset;
395 }
396 _ => {
398 return Err(PacketError::InvalidHeader("DNS name: reserved label type"));
399 }
400 }
401 }
402
403 Ok(consumed)
404}
405
406fn parse_rdata<'pkt>(
417 buf: &mut DissectBuffer<'pkt>,
418 msg: &'pkt [u8],
419 rdata_offset: usize,
420 rdata: &'pkt [u8],
421 rtype: u16,
422 abs_offset: usize,
423) {
424 let rdata_range = abs_offset..abs_offset + rdata.len();
425
426 match rtype {
427 TYPE_A if rdata.len() == 4 => {
429 buf.push_field(
430 &RR_CHILD_FIELDS[RRFD_RDATA],
431 FieldValue::Ipv4Addr([rdata[0], rdata[1], rdata[2], rdata[3]]),
432 rdata_range,
433 );
434 return;
435 }
436 TYPE_AAAA if rdata.len() == 16 => {
438 let addr: [u8; 16] = [
439 rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6], rdata[7],
440 rdata[8], rdata[9], rdata[10], rdata[11], rdata[12], rdata[13], rdata[14],
441 rdata[15],
442 ];
443 buf.push_field(
444 &RR_CHILD_FIELDS[RRFD_RDATA],
445 FieldValue::Ipv6Addr(addr),
446 rdata_range,
447 );
448 return;
449 }
450 TYPE_CNAME | TYPE_NS | TYPE_PTR | TYPE_DNAME => {
453 if let Ok(consumed) = parse_name(msg, rdata_offset) {
454 let _ = consumed;
455 buf.push_field(
456 &RR_CHILD_FIELDS[RRFD_RDATA],
457 FieldValue::Bytes(&msg[rdata_offset..rdata_offset + rdata.len()]),
458 rdata_range,
459 );
460 return;
461 }
462 }
463 TYPE_MX if rdata.len() >= 3 => {
465 let preference = read_be_u16(rdata, 0).unwrap_or_default();
466 if parse_name(msg, rdata_offset + 2).is_ok() {
467 buf.push_field(
468 &RR_CHILD_FIELDS[RRFD_RDATA_PREFERENCE],
469 FieldValue::U16(preference),
470 abs_offset..abs_offset + 2,
471 );
472 buf.push_field(
473 &RR_CHILD_FIELDS[RRFD_RDATA_EXCHANGE],
474 FieldValue::Bytes(&msg[rdata_offset + 2..rdata_offset + rdata.len()]),
475 abs_offset + 2..abs_offset + rdata.len(),
476 );
477 return;
478 }
479 }
480 TYPE_TXT => {
482 buf.push_field(
484 &RR_CHILD_FIELDS[RRFD_RDATA],
485 FieldValue::Bytes(rdata),
486 rdata_range,
487 );
488 return;
489 }
490 TYPE_SOA => {
492 if let Ok(mname_len) = parse_name(msg, rdata_offset) {
493 let rname_off = rdata_offset + mname_len;
494 if let Ok(rname_len) = parse_name(msg, rname_off) {
495 let timers_off = mname_len + rname_len;
496 if timers_off + 20 <= rdata.len() {
497 let t = timers_off;
498 let serial = read_be_u32(rdata, t).unwrap_or_default();
499 let refresh = read_be_u32(rdata, t + 4).unwrap_or_default();
500 let retry = read_be_u32(rdata, t + 8).unwrap_or_default();
501 let expire = read_be_u32(rdata, t + 12).unwrap_or_default();
502 let minimum = read_be_u32(rdata, t + 16).unwrap_or_default();
503 let mname_end = abs_offset + mname_len;
504 let rname_end = mname_end + rname_len;
505 buf.push_field(
506 &RR_CHILD_FIELDS[RRFD_RDATA_MNAME],
507 FieldValue::Bytes(&msg[rdata_offset..rdata_offset + mname_len]),
508 abs_offset..mname_end,
509 );
510 buf.push_field(
511 &RR_CHILD_FIELDS[RRFD_RDATA_RNAME],
512 FieldValue::Bytes(&msg[rname_off..rname_off + rname_len]),
513 mname_end..rname_end,
514 );
515 buf.push_field(
516 &RR_CHILD_FIELDS[RRFD_RDATA_SERIAL],
517 FieldValue::U32(serial),
518 rname_end..rname_end + 4,
519 );
520 buf.push_field(
521 &RR_CHILD_FIELDS[RRFD_RDATA_REFRESH],
522 FieldValue::U32(refresh),
523 rname_end + 4..rname_end + 8,
524 );
525 buf.push_field(
526 &RR_CHILD_FIELDS[RRFD_RDATA_RETRY],
527 FieldValue::U32(retry),
528 rname_end + 8..rname_end + 12,
529 );
530 buf.push_field(
531 &RR_CHILD_FIELDS[RRFD_RDATA_EXPIRE],
532 FieldValue::U32(expire),
533 rname_end + 12..rname_end + 16,
534 );
535 buf.push_field(
536 &RR_CHILD_FIELDS[RRFD_RDATA_MINIMUM],
537 FieldValue::U32(minimum),
538 rname_end + 16..rname_end + 20,
539 );
540 return;
541 }
542 }
543 }
544 }
545 TYPE_SRV if rdata.len() >= 7 => {
547 let priority = read_be_u16(rdata, 0).unwrap_or_default();
548 let weight = read_be_u16(rdata, 2).unwrap_or_default();
549 let port = read_be_u16(rdata, 4).unwrap_or_default();
550 if parse_name(msg, rdata_offset + 6).is_ok() {
551 buf.push_field(
552 &RR_CHILD_FIELDS[RRFD_RDATA_PRIORITY],
553 FieldValue::U16(priority),
554 abs_offset..abs_offset + 2,
555 );
556 buf.push_field(
557 &RR_CHILD_FIELDS[RRFD_RDATA_WEIGHT],
558 FieldValue::U16(weight),
559 abs_offset + 2..abs_offset + 4,
560 );
561 buf.push_field(
562 &RR_CHILD_FIELDS[RRFD_RDATA_PORT],
563 FieldValue::U16(port),
564 abs_offset + 4..abs_offset + 6,
565 );
566 buf.push_field(
567 &RR_CHILD_FIELDS[RRFD_RDATA_TARGET],
568 FieldValue::Bytes(&msg[rdata_offset + 6..rdata_offset + rdata.len()]),
569 abs_offset + 6..abs_offset + rdata.len(),
570 );
571 return;
572 }
573 }
574 TYPE_NAPTR if rdata.len() >= 7 => {
576 let order = read_be_u16(rdata, 0).unwrap_or_default();
577 let preference = read_be_u16(rdata, 2).unwrap_or_default();
578 let mut pos = 4;
579 let mut byte_ranges: [(usize, usize); 3] = [(0, 0); 3];
582 let mut n = 0usize;
583 for _ in 0..3 {
584 if pos >= rdata.len() {
585 break;
586 }
587 let str_len = rdata[pos] as usize;
588 let str_start = pos;
589 pos += 1;
590 if pos + str_len > rdata.len() {
591 break;
592 }
593 byte_ranges[n] = (str_start, pos + str_len);
594 n += 1;
595 pos += str_len;
596 }
597 if n == 3 && parse_name(msg, rdata_offset + pos).is_ok() {
598 buf.push_field(
599 &RR_CHILD_FIELDS[RRFD_RDATA_ORDER],
600 FieldValue::U16(order),
601 abs_offset..abs_offset + 2,
602 );
603 buf.push_field(
604 &RR_CHILD_FIELDS[RRFD_RDATA_PREFERENCE],
605 FieldValue::U16(preference),
606 abs_offset + 2..abs_offset + 4,
607 );
608 buf.push_field(
609 &RR_CHILD_FIELDS[RRFD_RDATA_FLAGS],
610 FieldValue::Bytes(&rdata[byte_ranges[0].0..byte_ranges[0].1]),
611 abs_offset + byte_ranges[0].0..abs_offset + byte_ranges[0].1,
612 );
613 buf.push_field(
614 &RR_CHILD_FIELDS[RRFD_RDATA_SERVICES],
615 FieldValue::Bytes(&rdata[byte_ranges[1].0..byte_ranges[1].1]),
616 abs_offset + byte_ranges[1].0..abs_offset + byte_ranges[1].1,
617 );
618 buf.push_field(
619 &RR_CHILD_FIELDS[RRFD_RDATA_REGEXP],
620 FieldValue::Bytes(&rdata[byte_ranges[2].0..byte_ranges[2].1]),
621 abs_offset + byte_ranges[2].0..abs_offset + byte_ranges[2].1,
622 );
623 buf.push_field(
624 &RR_CHILD_FIELDS[RRFD_RDATA_REPLACEMENT],
625 FieldValue::Bytes(&msg[rdata_offset + pos..rdata_offset + rdata.len()]),
626 abs_offset + pos..abs_offset + rdata.len(),
627 );
628 return;
629 }
630 }
631 TYPE_SSHFP if rdata.len() >= 2 => {
633 buf.push_field(
634 &RR_CHILD_FIELDS[RRFD_RDATA_ALGORITHM],
635 FieldValue::U8(rdata[0]),
636 abs_offset..abs_offset + 1,
637 );
638 buf.push_field(
639 &RR_CHILD_FIELDS[RRFD_RDATA_FINGERPRINT_TYPE],
640 FieldValue::U8(rdata[1]),
641 abs_offset + 1..abs_offset + 2,
642 );
643 buf.push_field(
644 &RR_CHILD_FIELDS[RRFD_RDATA_FINGERPRINT],
645 FieldValue::Bytes(&rdata[2..]),
646 abs_offset + 2..abs_offset + rdata.len(),
647 );
648 return;
649 }
650 TYPE_TLSA if rdata.len() >= 3 => {
652 buf.push_field(
653 &RR_CHILD_FIELDS[RRFD_RDATA_CERT_USAGE],
654 FieldValue::U8(rdata[0]),
655 abs_offset..abs_offset + 1,
656 );
657 buf.push_field(
658 &RR_CHILD_FIELDS[RRFD_RDATA_SELECTOR],
659 FieldValue::U8(rdata[1]),
660 abs_offset + 1..abs_offset + 2,
661 );
662 buf.push_field(
663 &RR_CHILD_FIELDS[RRFD_RDATA_MATCHING_TYPE],
664 FieldValue::U8(rdata[2]),
665 abs_offset + 2..abs_offset + 3,
666 );
667 buf.push_field(
668 &RR_CHILD_FIELDS[RRFD_RDATA_CERT_ASSOC_DATA],
669 FieldValue::Bytes(&rdata[3..]),
670 abs_offset + 3..abs_offset + rdata.len(),
671 );
672 return;
673 }
674 TYPE_DS | TYPE_CDS if rdata.len() >= 4 => {
676 let key_tag = read_be_u16(rdata, 0).unwrap_or_default();
677 buf.push_field(
678 &RR_CHILD_FIELDS[RRFD_RDATA_KEY_TAG],
679 FieldValue::U16(key_tag),
680 abs_offset..abs_offset + 2,
681 );
682 buf.push_field(
683 &RR_CHILD_FIELDS[RRFD_RDATA_ALGORITHM],
684 FieldValue::U8(rdata[2]),
685 abs_offset + 2..abs_offset + 3,
686 );
687 buf.push_field(
688 &RR_CHILD_FIELDS[RRFD_RDATA_DIGEST_TYPE],
689 FieldValue::U8(rdata[3]),
690 abs_offset + 3..abs_offset + 4,
691 );
692 buf.push_field(
693 &RR_CHILD_FIELDS[RRFD_RDATA_DIGEST],
694 FieldValue::Bytes(&rdata[4..]),
695 abs_offset + 4..abs_offset + rdata.len(),
696 );
697 return;
698 }
699 TYPE_RRSIG if rdata.len() >= 18 => {
702 let type_covered = read_be_u16(rdata, 0).unwrap_or_default();
703 let algorithm = rdata[2];
704 let labels = rdata[3];
705 let original_ttl = read_be_u32(rdata, 4).unwrap_or_default();
706 let sig_expiration = read_be_u32(rdata, 8).unwrap_or_default();
707 let sig_inception = read_be_u32(rdata, 12).unwrap_or_default();
708 let key_tag = read_be_u16(rdata, 16).unwrap_or_default();
709 if let Ok(signer_name_len) = parse_name(msg, rdata_offset + 18) {
710 let sig_start = 18 + signer_name_len;
711 buf.push_field(
712 &RR_CHILD_FIELDS[RRFD_RDATA_TYPE_COVERED],
713 FieldValue::U16(type_covered),
714 abs_offset..abs_offset + 2,
715 );
716 buf.push_field(
717 &RR_CHILD_FIELDS[RRFD_RDATA_ALGORITHM],
718 FieldValue::U8(algorithm),
719 abs_offset + 2..abs_offset + 3,
720 );
721 buf.push_field(
722 &RR_CHILD_FIELDS[RRFD_RDATA_LABELS],
723 FieldValue::U8(labels),
724 abs_offset + 3..abs_offset + 4,
725 );
726 buf.push_field(
727 &RR_CHILD_FIELDS[RRFD_RDATA_ORIGINAL_TTL],
728 FieldValue::U32(original_ttl),
729 abs_offset + 4..abs_offset + 8,
730 );
731 buf.push_field(
732 &RR_CHILD_FIELDS[RRFD_RDATA_SIGNATURE_EXPIRATION],
733 FieldValue::U32(sig_expiration),
734 abs_offset + 8..abs_offset + 12,
735 );
736 buf.push_field(
737 &RR_CHILD_FIELDS[RRFD_RDATA_SIGNATURE_INCEPTION],
738 FieldValue::U32(sig_inception),
739 abs_offset + 12..abs_offset + 16,
740 );
741 buf.push_field(
742 &RR_CHILD_FIELDS[RRFD_RDATA_KEY_TAG],
743 FieldValue::U16(key_tag),
744 abs_offset + 16..abs_offset + 18,
745 );
746 buf.push_field(
747 &RR_CHILD_FIELDS[RRFD_RDATA_SIGNER_NAME],
748 FieldValue::Bytes(&msg[rdata_offset + 18..rdata_offset + sig_start]),
749 abs_offset + 18..abs_offset + sig_start,
750 );
751 buf.push_field(
752 &RR_CHILD_FIELDS[RRFD_RDATA_SIGNATURE],
753 FieldValue::Bytes(&rdata[sig_start..]),
754 abs_offset + sig_start..abs_offset + rdata.len(),
755 );
756 return;
757 }
758 }
759 TYPE_NSEC => {
761 if let Ok(name_len) = parse_name(msg, rdata_offset) {
762 buf.push_field(
763 &RR_CHILD_FIELDS[RRFD_RDATA_NEXT_DOMAIN_NAME],
764 FieldValue::Bytes(&msg[rdata_offset..rdata_offset + name_len]),
765 abs_offset..abs_offset + name_len,
766 );
767 buf.push_field(
768 &RR_CHILD_FIELDS[RRFD_RDATA_TYPE_BITMAPS],
769 FieldValue::Bytes(&rdata[name_len..]),
770 abs_offset + name_len..abs_offset + rdata.len(),
771 );
772 return;
773 }
774 }
775 TYPE_DNSKEY | TYPE_CDNSKEY if rdata.len() >= 4 => {
777 let flags = read_be_u16(rdata, 0).unwrap_or_default();
778 buf.push_field(
779 &RR_CHILD_FIELDS[RRFD_RDATA_FLAGS],
780 FieldValue::U16(flags),
781 abs_offset..abs_offset + 2,
782 );
783 buf.push_field(
784 &RR_CHILD_FIELDS[RRFD_RDATA_PROTOCOL],
785 FieldValue::U8(rdata[2]),
786 abs_offset + 2..abs_offset + 3,
787 );
788 buf.push_field(
789 &RR_CHILD_FIELDS[RRFD_RDATA_ALGORITHM],
790 FieldValue::U8(rdata[3]),
791 abs_offset + 3..abs_offset + 4,
792 );
793 buf.push_field(
794 &RR_CHILD_FIELDS[RRFD_RDATA_PUBLIC_KEY],
795 FieldValue::Bytes(&rdata[4..]),
796 abs_offset + 4..abs_offset + rdata.len(),
797 );
798 return;
799 }
800 TYPE_NSEC3 if rdata.len() >= 5 => {
803 let hash_algorithm = rdata[0];
804 let flags = rdata[1];
805 let iterations = read_be_u16(rdata, 2).unwrap_or_default();
806 let salt_length = rdata[4] as usize;
807 let salt_end = 5 + salt_length;
808 if salt_end < rdata.len() {
809 let hash_length = rdata[salt_end] as usize;
810 let hash_start = salt_end + 1;
811 let hash_end = hash_start + hash_length;
812 if hash_end <= rdata.len() {
813 buf.push_field(
814 &RR_CHILD_FIELDS[RRFD_RDATA_HASH_ALGORITHM],
815 FieldValue::U8(hash_algorithm),
816 abs_offset..abs_offset + 1,
817 );
818 buf.push_field(
819 &RR_CHILD_FIELDS[RRFD_RDATA_FLAGS],
820 FieldValue::U8(flags),
821 abs_offset + 1..abs_offset + 2,
822 );
823 buf.push_field(
824 &RR_CHILD_FIELDS[RRFD_RDATA_ITERATIONS],
825 FieldValue::U16(iterations),
826 abs_offset + 2..abs_offset + 4,
827 );
828 buf.push_field(
829 &RR_CHILD_FIELDS[RRFD_RDATA_SALT_LENGTH],
830 FieldValue::U8(salt_length as u8),
831 abs_offset + 4..abs_offset + 5,
832 );
833 buf.push_field(
834 &RR_CHILD_FIELDS[RRFD_RDATA_SALT],
835 FieldValue::Bytes(&rdata[5..salt_end]),
836 abs_offset + 5..abs_offset + salt_end,
837 );
838 buf.push_field(
839 &RR_CHILD_FIELDS[RRFD_RDATA_HASH_LENGTH],
840 FieldValue::U8(hash_length as u8),
841 abs_offset + salt_end..abs_offset + hash_start,
842 );
843 buf.push_field(
844 &RR_CHILD_FIELDS[RRFD_RDATA_NEXT_HASHED_OWNER],
845 FieldValue::Bytes(&rdata[hash_start..hash_end]),
846 abs_offset + hash_start..abs_offset + hash_end,
847 );
848 buf.push_field(
849 &RR_CHILD_FIELDS[RRFD_RDATA_TYPE_BITMAPS],
850 FieldValue::Bytes(&rdata[hash_end..]),
851 abs_offset + hash_end..abs_offset + rdata.len(),
852 );
853 return;
854 }
855 }
856 }
857 TYPE_NSEC3PARAM if rdata.len() >= 5 => {
859 let hash_algorithm = rdata[0];
860 let flags = rdata[1];
861 let iterations = read_be_u16(rdata, 2).unwrap_or_default();
862 let salt_length = rdata[4] as usize;
863 if 5 + salt_length <= rdata.len() {
864 buf.push_field(
865 &RR_CHILD_FIELDS[RRFD_RDATA_HASH_ALGORITHM],
866 FieldValue::U8(hash_algorithm),
867 abs_offset..abs_offset + 1,
868 );
869 buf.push_field(
870 &RR_CHILD_FIELDS[RRFD_RDATA_FLAGS],
871 FieldValue::U8(flags),
872 abs_offset + 1..abs_offset + 2,
873 );
874 buf.push_field(
875 &RR_CHILD_FIELDS[RRFD_RDATA_ITERATIONS],
876 FieldValue::U16(iterations),
877 abs_offset + 2..abs_offset + 4,
878 );
879 buf.push_field(
880 &RR_CHILD_FIELDS[RRFD_RDATA_SALT_LENGTH],
881 FieldValue::U8(salt_length as u8),
882 abs_offset + 4..abs_offset + 5,
883 );
884 buf.push_field(
885 &RR_CHILD_FIELDS[RRFD_RDATA_SALT],
886 FieldValue::Bytes(&rdata[5..5 + salt_length]),
887 abs_offset + 5..abs_offset + 5 + salt_length,
888 );
889 return;
890 }
891 }
892 TYPE_SVCB | TYPE_HTTPS if rdata.len() >= 3 => {
894 let priority = read_be_u16(rdata, 0).unwrap_or_default();
895 if let Ok(target_len) = parse_name(msg, rdata_offset + 2) {
896 let params_start = 2 + target_len;
897 buf.push_field(
898 &RR_CHILD_FIELDS[RRFD_RDATA_PRIORITY],
899 FieldValue::U16(priority),
900 abs_offset..abs_offset + 2,
901 );
902 buf.push_field(
903 &RR_CHILD_FIELDS[RRFD_RDATA_TARGET],
904 FieldValue::Bytes(&msg[rdata_offset + 2..rdata_offset + params_start]),
905 abs_offset + 2..abs_offset + params_start,
906 );
907 if params_start <= rdata.len() {
908 buf.push_field(
909 &RR_CHILD_FIELDS[RRFD_RDATA_PARAMS],
910 FieldValue::Bytes(&rdata[params_start..]),
911 abs_offset + params_start..abs_offset + rdata.len(),
912 );
913 }
914 return;
915 }
916 }
917 TYPE_CAA if rdata.len() >= 2 => {
919 let flags = rdata[0];
920 let tag_len = rdata[1] as usize;
921 if 2 + tag_len <= rdata.len() {
922 buf.push_field(
923 &RR_CHILD_FIELDS[RRFD_RDATA_FLAGS],
924 FieldValue::U8(flags),
925 abs_offset..abs_offset + 1,
926 );
927 buf.push_field(
928 &RR_CHILD_FIELDS[RRFD_RDATA_TAG],
929 FieldValue::Bytes(&rdata[2..2 + tag_len]),
930 abs_offset + 2..abs_offset + 2 + tag_len,
931 );
932 buf.push_field(
933 &RR_CHILD_FIELDS[RRFD_RDATA_VALUE],
934 FieldValue::Bytes(&rdata[2 + tag_len..]),
935 abs_offset + 2 + tag_len..abs_offset + rdata.len(),
936 );
937 return;
938 }
939 }
940 _ => {}
941 }
942
943 buf.push_field(
945 &RR_CHILD_FIELDS[RRFD_RDATA],
946 FieldValue::Bytes(rdata),
947 rdata_range,
948 );
949}
950
951const EDNS_OPT_TCP_KEEPALIVE: u16 = 11;
955
956fn edns_option_code_name(code: u16) -> Option<&'static str> {
960 match code {
961 3 => Some("NSID"),
962 8 => Some("CLIENT-SUBNET"),
963 10 => Some("COOKIE"),
964 EDNS_OPT_TCP_KEEPALIVE => Some("TCP-KEEPALIVE"),
965 15 => Some("EXTENDED-DNS-ERROR"),
966 _ => None,
967 }
968}
969
970fn parse_edns_options<'pkt>(buf: &mut DissectBuffer<'pkt>, rdata: &'pkt [u8], abs_offset: usize) {
977 let mut pos = 0;
978 while pos + 4 <= rdata.len() {
979 let code = read_be_u16(rdata, pos).unwrap_or_default();
980 let length = read_be_u16(rdata, pos + 2).unwrap_or_default() as usize;
981 if pos + 4 + length > rdata.len() {
982 break;
983 }
984 let option_data = &rdata[pos + 4..pos + 4 + length];
985 let option_start = abs_offset + pos;
986 let option_end = option_start + 4 + length;
987
988 let obj_idx = buf.begin_container(
989 &FD_EDNS_OPTION,
990 FieldValue::Object(0..0),
991 option_start..option_end,
992 );
993
994 buf.push_field(
995 &EDNS_OPTION_CHILD_FIELDS[EOFD_CODE],
996 FieldValue::U16(code),
997 option_start..option_start + 2,
998 );
999 buf.push_field(
1000 &EDNS_OPTION_CHILD_FIELDS[EOFD_LENGTH],
1001 FieldValue::U16(length as u16),
1002 option_start + 2..option_start + 4,
1003 );
1004
1005 if code == EDNS_OPT_TCP_KEEPALIVE && length == 2 {
1010 let timeout = read_be_u16(option_data, 0).unwrap_or_default();
1011 buf.push_field(
1012 &EDNS_OPTION_CHILD_FIELDS[EOFD_TIMEOUT],
1013 FieldValue::U16(timeout),
1014 option_start + 4..option_end,
1015 );
1016 } else if code == EDNS_OPT_TCP_KEEPALIVE && length == 0 {
1017 } else {
1019 buf.push_field(
1020 &EDNS_OPTION_CHILD_FIELDS[EOFD_DATA],
1021 FieldValue::Bytes(option_data),
1022 option_start + 4..option_end,
1023 );
1024 }
1025
1026 buf.end_container(obj_idx);
1027 pos += 4 + length;
1028 }
1029}
1030
1031static FD_EDNS_OPTION: FieldDescriptor = FieldDescriptor {
1038 name: "edns_option",
1039 display_name: "EDNS Option",
1040 field_type: FieldType::Object,
1041 optional: false,
1042 children: None,
1043 display_fn: Some(|v, children| match v {
1044 FieldValue::Object(_) => children.iter().find_map(|f| match (f.name(), &f.value) {
1045 ("code", FieldValue::U16(c)) => edns_option_code_name(*c),
1046 _ => None,
1047 }),
1048 _ => None,
1049 }),
1050 format_fn: None,
1051};
1052
1053static EDNS_OPTION_CHILD_FIELDS: &[FieldDescriptor] = &[
1058 FieldDescriptor {
1059 name: "code",
1060 display_name: "Code",
1061 field_type: FieldType::U16,
1062 optional: false,
1063 children: None,
1064 display_fn: Some(|v, _siblings| match v {
1065 FieldValue::U16(c) => edns_option_code_name(*c),
1066 _ => None,
1067 }),
1068 format_fn: None,
1069 },
1070 FieldDescriptor::new("length", "Length", FieldType::U16),
1071 FieldDescriptor::new("data", "Data", FieldType::Bytes).optional(),
1072 FieldDescriptor::new("timeout", "Timeout", FieldType::U16).optional(),
1074];
1075
1076static QUESTION_CHILD_FIELDS: &[FieldDescriptor] = &[
1081 FieldDescriptor::new("name", "Name", FieldType::Bytes).with_format_fn(write_dns_name),
1082 FieldDescriptor {
1083 name: "type",
1084 display_name: "Type",
1085 field_type: FieldType::U16,
1086 optional: false,
1087 children: None,
1088 display_fn: Some(|v, _siblings| match v {
1089 FieldValue::U16(t) => dns_type_name(*t),
1090 _ => None,
1091 }),
1092 format_fn: None,
1093 },
1094 FieldDescriptor {
1095 name: "class",
1096 display_name: "Class",
1097 field_type: FieldType::U16,
1098 optional: false,
1099 children: None,
1100 display_fn: Some(|v, _siblings| match v {
1101 FieldValue::U16(c) => dns_class_name(*c),
1102 _ => None,
1103 }),
1104 format_fn: None,
1105 },
1106 FieldDescriptor::new("qu", "Unicast Response", FieldType::U8).optional(),
1109];
1110
1111static RR_CHILD_FIELDS: &[FieldDescriptor] = &[
1116 FieldDescriptor::new("name", "Name", FieldType::Bytes).with_format_fn(write_dns_name),
1118 FieldDescriptor {
1119 name: "type",
1120 display_name: "Type",
1121 field_type: FieldType::U16,
1122 optional: false,
1123 children: None,
1124 display_fn: Some(|v, _siblings| match v {
1125 FieldValue::U16(t) => dns_type_name(*t),
1126 _ => None,
1127 }),
1128 format_fn: None,
1129 },
1130 FieldDescriptor {
1131 name: "class",
1132 display_name: "Class",
1133 field_type: FieldType::U16,
1134 optional: true,
1135 children: None,
1136 display_fn: Some(|v, _siblings| match v {
1137 FieldValue::U16(c) => dns_class_name(*c),
1138 _ => None,
1139 }),
1140 format_fn: None,
1141 },
1142 FieldDescriptor::new("ttl", "TTL", FieldType::U32).optional(),
1143 FieldDescriptor::new("rdlength", "Data Length", FieldType::U16).optional(),
1144 FieldDescriptor::new("rdata", "Data", FieldType::Str).optional(),
1146 FieldDescriptor::new("udp_payload_size", "UDP Payload Size", FieldType::U16).optional(),
1148 FieldDescriptor::new("extended_rcode", "Extended RCODE", FieldType::U8).optional(),
1149 FieldDescriptor::new("edns_version", "EDNS Version", FieldType::U8).optional(),
1150 FieldDescriptor::new("do_bit", "DO Bit", FieldType::U8).optional(),
1151 FieldDescriptor::new("edns_options", "EDNS Options", FieldType::Array)
1152 .optional()
1153 .with_children(EDNS_OPTION_CHILD_FIELDS),
1154 FieldDescriptor::new("rdata_preference", "Preference", FieldType::U16).optional(),
1156 FieldDescriptor::new("rdata_exchange", "Mail Exchange", FieldType::Str).optional(),
1157 FieldDescriptor::new("rdata_mname", "Primary Name Server", FieldType::Str).optional(),
1159 FieldDescriptor::new(
1160 "rdata_rname",
1161 "Responsible Authority Mailbox",
1162 FieldType::Str,
1163 )
1164 .optional(),
1165 FieldDescriptor::new("rdata_serial", "Serial Number", FieldType::U32).optional(),
1166 FieldDescriptor::new("rdata_refresh", "Refresh Interval", FieldType::U32).optional(),
1167 FieldDescriptor::new("rdata_retry", "Retry Interval", FieldType::U32).optional(),
1168 FieldDescriptor::new("rdata_expire", "Expire Limit", FieldType::U32).optional(),
1169 FieldDescriptor::new("rdata_minimum", "Minimum TTL", FieldType::U32).optional(),
1170 FieldDescriptor::new("rdata_priority", "Priority", FieldType::U16).optional(),
1172 FieldDescriptor::new("rdata_weight", "Weight", FieldType::U16).optional(),
1173 FieldDescriptor::new("rdata_port", "Port", FieldType::U16).optional(),
1174 FieldDescriptor::new("rdata_target", "Target", FieldType::Str).optional(),
1175 FieldDescriptor::new("rdata_order", "Order", FieldType::U16).optional(),
1177 FieldDescriptor::new("rdata_flags", "Flags", FieldType::Str).optional(),
1178 FieldDescriptor::new("rdata_services", "Service", FieldType::Str).optional(),
1179 FieldDescriptor::new("rdata_regexp", "Regular Expression", FieldType::Str).optional(),
1180 FieldDescriptor::new("rdata_replacement", "Replacement", FieldType::Str).optional(),
1181 FieldDescriptor::new("rdata_algorithm", "Algorithm", FieldType::U8).optional(),
1183 FieldDescriptor::new("rdata_fingerprint_type", "Fingerprint Type", FieldType::U8).optional(),
1184 FieldDescriptor::new("rdata_fingerprint", "Fingerprint", FieldType::Bytes).optional(),
1185 FieldDescriptor::new("rdata_key_tag", "Key Tag", FieldType::U16).optional(),
1187 FieldDescriptor::new("rdata_digest_type", "Digest Type", FieldType::U8).optional(),
1188 FieldDescriptor::new("rdata_digest", "Digest", FieldType::Bytes).optional(),
1189 FieldDescriptor::new("rdata_type_covered", "Type Covered", FieldType::U16).optional(),
1191 FieldDescriptor::new("rdata_labels", "Labels", FieldType::U8).optional(),
1192 FieldDescriptor::new("rdata_original_ttl", "Original TTL", FieldType::U32).optional(),
1193 FieldDescriptor::new(
1194 "rdata_signature_expiration",
1195 "Signature Expiration",
1196 FieldType::U32,
1197 )
1198 .optional(),
1199 FieldDescriptor::new(
1200 "rdata_signature_inception",
1201 "Signature Inception",
1202 FieldType::U32,
1203 )
1204 .optional(),
1205 FieldDescriptor::new("rdata_signer_name", "Signer's Name", FieldType::Str).optional(),
1206 FieldDescriptor::new("rdata_signature", "Signature", FieldType::Bytes).optional(),
1207 FieldDescriptor::new("rdata_next_domain_name", "Next Domain Name", FieldType::Str).optional(),
1209 FieldDescriptor::new("rdata_type_bitmaps", "Type Bit Maps", FieldType::Bytes).optional(),
1210 FieldDescriptor::new("rdata_protocol", "Protocol", FieldType::U8).optional(),
1212 FieldDescriptor::new("rdata_public_key", "Public Key", FieldType::Bytes).optional(),
1213 FieldDescriptor::new("rdata_hash_algorithm", "Hash Algorithm", FieldType::U8).optional(),
1215 FieldDescriptor::new("rdata_iterations", "Iterations", FieldType::U16).optional(),
1216 FieldDescriptor::new("rdata_salt_length", "Salt Length", FieldType::U8).optional(),
1217 FieldDescriptor::new("rdata_salt", "Salt", FieldType::Bytes).optional(),
1218 FieldDescriptor::new("rdata_hash_length", "Hash Length", FieldType::U8).optional(),
1219 FieldDescriptor::new(
1220 "rdata_next_hashed_owner",
1221 "Next Hashed Owner Name",
1222 FieldType::Bytes,
1223 )
1224 .optional(),
1225 FieldDescriptor::new("rdata_cert_usage", "Certificate Usage", FieldType::U8).optional(),
1227 FieldDescriptor::new("rdata_selector", "Selector", FieldType::U8).optional(),
1228 FieldDescriptor::new("rdata_matching_type", "Matching Type", FieldType::U8).optional(),
1229 FieldDescriptor::new(
1230 "rdata_cert_assoc_data",
1231 "Certificate Association Data",
1232 FieldType::Bytes,
1233 )
1234 .optional(),
1235 FieldDescriptor::new("rdata_tag", "Tag", FieldType::Str).optional(),
1237 FieldDescriptor::new("rdata_value", "Value", FieldType::Str).optional(),
1238 FieldDescriptor::new("rdata_params", "SvcParams", FieldType::Bytes).optional(),
1240 FieldDescriptor::new("cache_flush", "Cache Flush", FieldType::U8).optional(),
1244];
1245
1246macro_rules! dns_field_descriptors {
1251 (tcp_length_optional: $opt:expr) => {
1252 &[
1253 FieldDescriptor {
1254 name: "tcp_length",
1255 display_name: "TCP Length",
1256 field_type: FieldType::U16,
1257 optional: $opt,
1258 children: None,
1259 display_fn: None,
1260 format_fn: None,
1261 },
1262 FieldDescriptor::new("id", "Transaction ID", FieldType::U16),
1263 FieldDescriptor {
1264 name: "qr",
1265 display_name: "QR",
1266 field_type: FieldType::U8,
1267 optional: false,
1268 children: None,
1269 display_fn: Some(|v, _siblings| match v {
1270 FieldValue::U8(0) => Some("Query"),
1271 FieldValue::U8(1) => Some("Response"),
1272 _ => None,
1273 }),
1274 format_fn: None,
1275 },
1276 FieldDescriptor {
1277 name: "opcode",
1278 display_name: "Opcode",
1279 field_type: FieldType::U8,
1280 optional: false,
1281 children: None,
1282 display_fn: Some(|v, _siblings| match v {
1283 FieldValue::U8(o) => dns_opcode_name(*o),
1284 _ => None,
1285 }),
1286 format_fn: None,
1287 },
1288 FieldDescriptor::new("aa", "Authoritative Answer", FieldType::U8),
1289 FieldDescriptor::new("tc", "Truncation", FieldType::U8),
1290 FieldDescriptor::new("rd", "Recursion Desired", FieldType::U8),
1291 FieldDescriptor::new("ra", "Recursion Available", FieldType::U8),
1292 FieldDescriptor::new("z", "Reserved", FieldType::U8),
1293 FieldDescriptor::new("ad", "Authentic Data", FieldType::U8),
1294 FieldDescriptor::new("cd", "Checking Disabled", FieldType::U8),
1295 FieldDescriptor {
1296 name: "rcode",
1297 display_name: "Response Code",
1298 field_type: FieldType::U8,
1299 optional: false,
1300 children: None,
1301 display_fn: Some(|v, _siblings| match v {
1302 FieldValue::U8(r) => dns_rcode_name(*r),
1303 _ => None,
1304 }),
1305 format_fn: None,
1306 },
1307 FieldDescriptor::new("qdcount", "Question Count", FieldType::U16),
1308 FieldDescriptor::new("ancount", "Answer Count", FieldType::U16),
1309 FieldDescriptor::new("nscount", "Authority Count", FieldType::U16),
1310 FieldDescriptor::new("arcount", "Additional Count", FieldType::U16),
1311 FieldDescriptor::new("questions", "Questions", FieldType::Array)
1312 .optional()
1313 .with_children(QUESTION_CHILD_FIELDS),
1314 FieldDescriptor::new("answers", "Answer Records", FieldType::Array)
1315 .optional()
1316 .with_children(RR_CHILD_FIELDS),
1317 FieldDescriptor::new("authorities", "Authority Records", FieldType::Array)
1318 .optional()
1319 .with_children(RR_CHILD_FIELDS),
1320 FieldDescriptor::new("additionals", "Additional Records", FieldType::Array)
1321 .optional()
1322 .with_children(RR_CHILD_FIELDS),
1323 ]
1324 };
1325}
1326
1327static DNS_FIELD_DESCRIPTORS: &[FieldDescriptor] =
1332 dns_field_descriptors!(tcp_length_optional: true);
1333
1334static DNS_TCP_FIELD_DESCRIPTORS: &[FieldDescriptor] =
1341 dns_field_descriptors!(tcp_length_optional: false);
1342
1343impl Dissector for DnsDissector {
1344 fn name(&self) -> &'static str {
1345 "Domain Name System"
1346 }
1347
1348 fn short_name(&self) -> &'static str {
1349 "DNS"
1350 }
1351
1352 fn field_descriptors(&self) -> &'static [FieldDescriptor] {
1353 DNS_FIELD_DESCRIPTORS
1354 }
1355
1356 fn dissect<'pkt>(
1357 &self,
1358 data: &'pkt [u8],
1359 buf: &mut DissectBuffer<'pkt>,
1360 offset: usize,
1361 ) -> Result<DissectResult, PacketError> {
1362 dissect_dns_core(data, buf, offset, self.short_name(), false)
1364 }
1365}
1366
1367pub fn dissect_as_mdns<'pkt>(
1386 data: &'pkt [u8],
1387 buf: &mut DissectBuffer<'pkt>,
1388 offset: usize,
1389) -> Result<DissectResult, PacketError> {
1390 dissect_dns_core(data, buf, offset, "mDNS", true)
1391}
1392
1393fn dissect_dns_core<'pkt>(
1401 data: &'pkt [u8],
1402 buf: &mut DissectBuffer<'pkt>,
1403 offset: usize,
1404 layer_name: &'static str,
1405 mdns_mode: bool,
1406) -> Result<DissectResult, PacketError> {
1407 if data.len() < HEADER_SIZE {
1408 return Err(PacketError::Truncated {
1409 expected: HEADER_SIZE,
1410 actual: data.len(),
1411 });
1412 }
1413
1414 let id = read_be_u16(data, 0)?;
1416 let flags = read_be_u16(data, 2)?;
1417
1418 let qr = ((flags >> 15) & 1) as u8;
1419 let opcode = ((flags >> 11) & 0x0F) as u8;
1420 let aa = ((flags >> 10) & 1) as u8;
1421 let tc = ((flags >> 9) & 1) as u8;
1422 let rd = ((flags >> 8) & 1) as u8;
1423 let ra = ((flags >> 7) & 1) as u8;
1424 let z = ((flags >> 6) & 1) as u8;
1426 let ad = ((flags >> 5) & 1) as u8;
1428 let cd = ((flags >> 4) & 1) as u8;
1429 let rcode = (flags & 0x0F) as u8;
1430
1431 let qdcount = read_be_u16(data, 4)?;
1432 let ancount = read_be_u16(data, 6)?;
1433 let nscount = read_be_u16(data, 8)?;
1434 let arcount = read_be_u16(data, 10)?;
1435
1436 buf.begin_layer(
1437 layer_name,
1438 None,
1439 DNS_FIELD_DESCRIPTORS,
1440 offset..offset + data.len(),
1441 );
1442
1443 buf.push_field(
1444 &DNS_FIELD_DESCRIPTORS[FD_ID],
1445 FieldValue::U16(id),
1446 offset..offset + 2,
1447 );
1448 buf.push_field(
1449 &DNS_FIELD_DESCRIPTORS[FD_QR],
1450 FieldValue::U8(qr),
1451 offset + 2..offset + 4,
1452 );
1453 buf.push_field(
1454 &DNS_FIELD_DESCRIPTORS[FD_OPCODE],
1455 FieldValue::U8(opcode),
1456 offset + 2..offset + 4,
1457 );
1458 buf.push_field(
1459 &DNS_FIELD_DESCRIPTORS[FD_AA],
1460 FieldValue::U8(aa),
1461 offset + 2..offset + 4,
1462 );
1463 buf.push_field(
1464 &DNS_FIELD_DESCRIPTORS[FD_TC],
1465 FieldValue::U8(tc),
1466 offset + 2..offset + 4,
1467 );
1468 buf.push_field(
1469 &DNS_FIELD_DESCRIPTORS[FD_RD],
1470 FieldValue::U8(rd),
1471 offset + 2..offset + 4,
1472 );
1473 buf.push_field(
1474 &DNS_FIELD_DESCRIPTORS[FD_RA],
1475 FieldValue::U8(ra),
1476 offset + 2..offset + 4,
1477 );
1478 buf.push_field(
1479 &DNS_FIELD_DESCRIPTORS[FD_Z],
1480 FieldValue::U8(z),
1481 offset + 2..offset + 4,
1482 );
1483 buf.push_field(
1484 &DNS_FIELD_DESCRIPTORS[FD_AD],
1485 FieldValue::U8(ad),
1486 offset + 2..offset + 4,
1487 );
1488 buf.push_field(
1489 &DNS_FIELD_DESCRIPTORS[FD_CD],
1490 FieldValue::U8(cd),
1491 offset + 2..offset + 4,
1492 );
1493 buf.push_field(
1494 &DNS_FIELD_DESCRIPTORS[FD_RCODE],
1495 FieldValue::U8(rcode),
1496 offset + 2..offset + 4,
1497 );
1498 buf.push_field(
1499 &DNS_FIELD_DESCRIPTORS[FD_QDCOUNT],
1500 FieldValue::U16(qdcount),
1501 offset + 4..offset + 6,
1502 );
1503 buf.push_field(
1504 &DNS_FIELD_DESCRIPTORS[FD_ANCOUNT],
1505 FieldValue::U16(ancount),
1506 offset + 6..offset + 8,
1507 );
1508 buf.push_field(
1509 &DNS_FIELD_DESCRIPTORS[FD_NSCOUNT],
1510 FieldValue::U16(nscount),
1511 offset + 8..offset + 10,
1512 );
1513 buf.push_field(
1514 &DNS_FIELD_DESCRIPTORS[FD_ARCOUNT],
1515 FieldValue::U16(arcount),
1516 offset + 10..offset + 12,
1517 );
1518
1519 let mut pos = HEADER_SIZE;
1520
1521 let questions_start = pos;
1523 let questions_count = qdcount as usize;
1524 let questions_array_idx = if questions_count > 0 {
1525 Some(buf.begin_container(
1526 &DNS_FIELD_DESCRIPTORS[FD_QUESTIONS],
1527 FieldValue::Array(0..0),
1528 offset + questions_start..offset + questions_start,
1529 ))
1530 } else {
1531 None
1532 };
1533 for _i in 0..questions_count {
1534 let name_len = parse_name(data, pos)?;
1535 let name_start = pos;
1536 pos += name_len;
1537
1538 if pos + 4 > data.len() {
1539 return Err(PacketError::Truncated {
1540 expected: pos + 4,
1541 actual: data.len(),
1542 });
1543 }
1544
1545 let qtype = read_be_u16(data, pos)?;
1546 let qclass_raw = read_be_u16(data, pos + 2)?;
1547 let (qclass, qu_bit) = if mdns_mode {
1551 (qclass_raw & 0x7FFF, ((qclass_raw >> 15) & 1) as u8)
1552 } else {
1553 (qclass_raw, 0)
1554 };
1555
1556 let obj_idx = buf.begin_container(
1557 &QUESTION_CHILD_FIELDS[QFD_NAME],
1558 FieldValue::Object(0..0),
1559 offset + name_start..offset + pos + 4,
1560 );
1561 buf.push_field(
1562 &QUESTION_CHILD_FIELDS[QFD_NAME],
1563 FieldValue::Bytes(&data[name_start..pos]),
1564 offset + name_start..offset + pos,
1565 );
1566 buf.push_field(
1567 &QUESTION_CHILD_FIELDS[QFD_TYPE],
1568 FieldValue::U16(qtype),
1569 offset + pos..offset + pos + 2,
1570 );
1571 buf.push_field(
1572 &QUESTION_CHILD_FIELDS[QFD_CLASS],
1573 FieldValue::U16(qclass),
1574 offset + pos + 2..offset + pos + 4,
1575 );
1576 if mdns_mode {
1577 buf.push_field(
1578 &QUESTION_CHILD_FIELDS[QFD_QU],
1579 FieldValue::U8(qu_bit),
1580 offset + pos + 2..offset + pos + 4,
1581 );
1582 }
1583 buf.end_container(obj_idx);
1584 pos += 4;
1585 }
1586 if let Some(idx) = questions_array_idx {
1587 if let Some(field) = buf.field_mut(idx as usize) {
1589 field.range = offset + questions_start..offset + pos;
1590 }
1591 buf.end_container(idx);
1592 }
1593
1594 let sections: &[(usize, u16)] = &[
1596 (FD_ANSWERS, ancount),
1597 (FD_AUTHORITIES, nscount),
1598 (FD_ADDITIONALS, arcount),
1599 ];
1600
1601 for &(section_fd, count) in sections {
1602 let section_start = pos;
1603 let count = count as usize;
1604 let array_idx = if count > 0 {
1605 Some(buf.begin_container(
1606 &DNS_FIELD_DESCRIPTORS[section_fd],
1607 FieldValue::Array(0..0),
1608 offset + section_start..offset + section_start,
1609 ))
1610 } else {
1611 None
1612 };
1613 for _i in 0..count {
1614 let name_len = parse_name(data, pos)?;
1615 let name_start = pos;
1616 pos += name_len;
1617
1618 if pos + 10 > data.len() {
1620 return Err(PacketError::Truncated {
1621 expected: pos + 10,
1622 actual: data.len(),
1623 });
1624 }
1625
1626 let rtype = read_be_u16(data, pos)?;
1627 let rclass_raw = read_be_u16(data, pos + 2)?;
1628 let ttl = read_be_u32(data, pos + 4)?;
1629 let rdlength = read_be_u16(data, pos + 8)? as usize;
1630
1631 if pos + 10 + rdlength > data.len() {
1632 return Err(PacketError::Truncated {
1633 expected: pos + 10 + rdlength,
1634 actual: data.len(),
1635 });
1636 }
1637
1638 let rdata = &data[pos + 10..pos + 10 + rdlength];
1639 let record_end = pos + 10 + rdlength;
1640
1641 let obj_idx = buf.begin_container(
1642 &RR_CHILD_FIELDS[RRFD_NAME],
1643 FieldValue::Object(0..0),
1644 offset + name_start..offset + record_end,
1645 );
1646
1647 if rtype == TYPE_OPT {
1653 let extended_rcode = ((ttl >> 24) & 0xFF) as u8;
1654 let edns_version = ((ttl >> 16) & 0xFF) as u8;
1655 let do_bit = ((ttl >> 15) & 1) as u8;
1656 buf.push_field(
1657 &RR_CHILD_FIELDS[RRFD_NAME],
1658 FieldValue::Bytes(&data[name_start..pos]),
1659 offset + name_start..offset + pos,
1660 );
1661 buf.push_field(
1662 &RR_CHILD_FIELDS[RRFD_TYPE],
1663 FieldValue::U16(rtype),
1664 offset + pos..offset + pos + 2,
1665 );
1666 buf.push_field(
1667 &RR_CHILD_FIELDS[RRFD_UDP_PAYLOAD_SIZE],
1668 FieldValue::U16(rclass_raw),
1669 offset + pos + 2..offset + pos + 4,
1670 );
1671 buf.push_field(
1672 &RR_CHILD_FIELDS[RRFD_EXTENDED_RCODE],
1673 FieldValue::U8(extended_rcode),
1674 offset + pos + 4..offset + pos + 8,
1675 );
1676 buf.push_field(
1677 &RR_CHILD_FIELDS[RRFD_EDNS_VERSION],
1678 FieldValue::U8(edns_version),
1679 offset + pos + 4..offset + pos + 8,
1680 );
1681 buf.push_field(
1682 &RR_CHILD_FIELDS[RRFD_DO_BIT],
1683 FieldValue::U8(do_bit),
1684 offset + pos + 4..offset + pos + 8,
1685 );
1686 buf.push_field(
1687 &RR_CHILD_FIELDS[RRFD_RDLENGTH],
1688 FieldValue::U16(rdlength as u16),
1689 offset + pos + 8..offset + pos + 10,
1690 );
1691 let edns_arr_idx = buf.begin_container(
1692 &RR_CHILD_FIELDS[RRFD_EDNS_OPTIONS],
1693 FieldValue::Array(0..0),
1694 offset + pos + 10..offset + pos + 10 + rdlength,
1695 );
1696 parse_edns_options(buf, rdata, offset + pos + 10);
1697 buf.end_container(edns_arr_idx);
1698 } else {
1699 let (rclass, cache_flush_bit) = if mdns_mode {
1703 (rclass_raw & 0x7FFF, ((rclass_raw >> 15) & 1) as u8)
1704 } else {
1705 (rclass_raw, 0)
1706 };
1707 buf.push_field(
1708 &RR_CHILD_FIELDS[RRFD_NAME],
1709 FieldValue::Bytes(&data[name_start..pos]),
1710 offset + name_start..offset + pos,
1711 );
1712 buf.push_field(
1713 &RR_CHILD_FIELDS[RRFD_TYPE],
1714 FieldValue::U16(rtype),
1715 offset + pos..offset + pos + 2,
1716 );
1717 buf.push_field(
1718 &RR_CHILD_FIELDS[RRFD_CLASS],
1719 FieldValue::U16(rclass),
1720 offset + pos + 2..offset + pos + 4,
1721 );
1722 if mdns_mode {
1723 buf.push_field(
1724 &RR_CHILD_FIELDS[RRFD_CACHE_FLUSH],
1725 FieldValue::U8(cache_flush_bit),
1726 offset + pos + 2..offset + pos + 4,
1727 );
1728 }
1729 buf.push_field(
1730 &RR_CHILD_FIELDS[RRFD_TTL],
1731 FieldValue::U32(ttl),
1732 offset + pos + 4..offset + pos + 8,
1733 );
1734 buf.push_field(
1735 &RR_CHILD_FIELDS[RRFD_RDLENGTH],
1736 FieldValue::U16(rdlength as u16),
1737 offset + pos + 8..offset + pos + 10,
1738 );
1739 parse_rdata(buf, data, pos + 10, rdata, rtype, offset + pos + 10);
1741 }
1742
1743 buf.end_container(obj_idx);
1744 pos += 10 + rdlength;
1745 }
1746 if let Some(idx) = array_idx {
1747 if let Some(field) = buf.field_mut(idx as usize) {
1748 field.range = offset + section_start..offset + pos;
1749 }
1750 buf.end_container(idx);
1751 }
1752 }
1753
1754 if let Some(layer) = buf.last_layer_mut() {
1756 layer.range = offset..offset + pos;
1757 }
1758 buf.end_layer();
1759
1760 Ok(DissectResult::new(pos, DispatchHint::End))
1761}
1762
1763fn dissect_dns_tcp_message<'pkt>(
1771 msg_data: &'pkt [u8],
1772 buf: &mut DissectBuffer<'pkt>,
1773 offset: usize,
1774) -> Result<DissectResult, PacketError> {
1775 let msg_len = read_be_u16(msg_data, 0)? as usize;
1776
1777 let tcp_len_field_idx = buf.field_count();
1781 buf.push_field(
1782 &DNS_TCP_FIELD_DESCRIPTORS[0], FieldValue::U16(msg_len as u16),
1784 offset..offset + 2,
1785 );
1786
1787 let result = DnsDissector.dissect(&msg_data[2..2 + msg_len], buf, offset + 2)?;
1788
1789 if let Some(layer) = buf.last_layer_mut() {
1792 layer.range = offset..layer.range.end;
1793 layer.field_range.start = tcp_len_field_idx;
1794 layer.field_descriptors = DNS_TCP_FIELD_DESCRIPTORS;
1795 }
1796
1797 Ok(DissectResult::new(
1798 2 + result.bytes_consumed,
1799 DispatchHint::End,
1800 ))
1801}
1802
1803pub struct DnsTcpDissector;
1811
1812impl Dissector for DnsTcpDissector {
1813 fn name(&self) -> &'static str {
1814 "DNS over TCP"
1815 }
1816
1817 fn short_name(&self) -> &'static str {
1818 "DNS"
1819 }
1820
1821 fn field_descriptors(&self) -> &'static [FieldDescriptor] {
1822 DNS_TCP_FIELD_DESCRIPTORS
1823 }
1824
1825 fn dissect<'pkt>(
1826 &self,
1827 data: &'pkt [u8],
1828 buf: &mut DissectBuffer<'pkt>,
1829 offset: usize,
1830 ) -> Result<DissectResult, PacketError> {
1831 if data.len() < 2 {
1835 return Err(PacketError::Truncated {
1836 expected: 2,
1837 actual: data.len(),
1838 });
1839 }
1840
1841 let msg_len = read_be_u16(data, 0)? as usize;
1842 let total_len = 2 + msg_len;
1843
1844 if data.len() < total_len {
1845 return Err(PacketError::Truncated {
1846 expected: total_len,
1847 actual: data.len(),
1848 });
1849 }
1850
1851 dissect_dns_tcp_message(&data[..total_len], buf, offset)
1852 }
1853}
1854
1855#[cfg(test)]
1856mod tests {
1857 use super::*;
1858 use packet_dissector_core::field::Field;
1859
1860 fn buf() -> DissectBuffer<'static> {
1901 DissectBuffer::new()
1902 }
1903
1904 fn find_child<'a, 'pkt>(
1906 buf: &'a DissectBuffer<'pkt>,
1907 parent: &Field<'pkt>,
1908 name: &str,
1909 ) -> Option<&'a Field<'pkt>> {
1910 let range = match &parent.value {
1911 FieldValue::Object(r) | FieldValue::Array(r) => r.clone(),
1912 _ => return None,
1913 };
1914 buf.nested_fields(&range).iter().find(|f| f.name() == name)
1915 }
1916
1917 fn first_array_entry<'a, 'pkt>(
1925 buf: &'a DissectBuffer<'pkt>,
1926 array: &Field<'pkt>,
1927 ) -> &'a Field<'pkt> {
1928 let range = match &array.value {
1929 FieldValue::Array(r) => r.clone(),
1930 _ => panic!("expected Array field"),
1931 };
1932 buf.nested_fields(&range)
1933 .iter()
1934 .find(|f| matches!(f.value, FieldValue::Object(_)))
1935 .expect("array must have at least one Object entry")
1936 }
1937
1938 fn wire_name(name: &str) -> Vec<u8> {
1940 let mut out = Vec::new();
1941 if !name.is_empty() {
1942 for label in name.split('.') {
1943 out.push(label.len() as u8);
1944 out.extend_from_slice(label.as_bytes());
1945 }
1946 }
1947 out.push(0); out
1949 }
1950
1951 fn header(qd: u16, an: u16, ns: u16, ar: u16) -> Vec<u8> {
1953 let mut h = Vec::with_capacity(12);
1954 h.extend_from_slice(&0u16.to_be_bytes()); h.extend_from_slice(&0u16.to_be_bytes()); h.extend_from_slice(&qd.to_be_bytes());
1957 h.extend_from_slice(&an.to_be_bytes());
1958 h.extend_from_slice(&ns.to_be_bytes());
1959 h.extend_from_slice(&ar.to_be_bytes());
1960 h
1961 }
1962
1963 #[test]
1966 fn parse_header_flags() {
1967 let flags: u16 = (1 << 15) | (5 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | 5; let mut data = Vec::new();
1983 data.extend_from_slice(&0xABCDu16.to_be_bytes());
1984 data.extend_from_slice(&flags.to_be_bytes());
1985 data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); let mut b = buf();
1988 DnsDissector.dissect(&data, &mut b, 0).unwrap();
1989
1990 let layer = &b.layers()[0];
1991 let get = |name: &str| b.field_by_name(layer, name).unwrap().value.clone();
1992
1993 assert_eq!(get("id"), FieldValue::U16(0xABCD));
1994 assert_eq!(get("qr"), FieldValue::U8(1));
1995 assert_eq!(get("opcode"), FieldValue::U8(5));
1996 assert_eq!(get("aa"), FieldValue::U8(1));
1997 assert_eq!(get("tc"), FieldValue::U8(1));
1998 assert_eq!(get("rd"), FieldValue::U8(1));
1999 assert_eq!(get("ra"), FieldValue::U8(1));
2000 assert_eq!(get("z"), FieldValue::U8(1));
2001 assert_eq!(get("ad"), FieldValue::U8(1));
2002 assert_eq!(get("cd"), FieldValue::U8(1));
2003 assert_eq!(get("rcode"), FieldValue::U8(5));
2004 }
2005
2006 #[test]
2007 fn parse_header_truncated() {
2008 let mut b = buf();
2010 let err = DnsDissector.dissect(&[0u8; 11], &mut b, 0).unwrap_err();
2011 assert!(matches!(
2012 err,
2013 PacketError::Truncated {
2014 expected: 12,
2015 actual: 11,
2016 }
2017 ));
2018 }
2019
2020 #[test]
2023 fn parse_question_a_in() {
2024 let mut data = header(1, 0, 0, 0);
2025 data.extend_from_slice(&wire_name("example.com"));
2026 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&1u16.to_be_bytes()); let mut b = buf();
2030 let res = DnsDissector.dissect(&data, &mut b, 0).unwrap();
2031 assert_eq!(res.bytes_consumed, data.len());
2032
2033 let layer = &b.layers()[0];
2034 let questions = b.field_by_name(layer, "questions").unwrap();
2035 let FieldValue::Array(ref q_range) = questions.value else {
2036 panic!("questions should be an Array");
2037 };
2038 let q_list = b.nested_fields(q_range);
2039
2040 let q = &q_list[0];
2041 assert_eq!(find_child(&b, q, "type").unwrap().value, FieldValue::U16(1));
2042 assert_eq!(
2043 find_child(&b, q, "class").unwrap().value,
2044 FieldValue::U16(1)
2045 );
2046 }
2047
2048 #[test]
2049 fn parse_a_record() {
2050 let mut data = header(0, 1, 0, 0);
2052 data.extend_from_slice(&wire_name("example.com"));
2053 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&3600u32.to_be_bytes()); data.extend_from_slice(&4u16.to_be_bytes()); data.extend_from_slice(&[192, 0, 2, 1]);
2058
2059 let mut b = buf();
2060 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2061 let layer = &b.layers()[0];
2062 let answers = b.field_by_name(layer, "answers").unwrap();
2063 let rr = first_array_entry(&b, answers);
2064 let rdata = find_child(&b, rr, "rdata").unwrap();
2065 assert_eq!(rdata.value, FieldValue::Ipv4Addr([192, 0, 2, 1]));
2066 }
2067
2068 #[test]
2071 fn parse_aaaa_record() {
2072 let addr: [u8; 16] = [
2073 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01,
2074 ];
2075 let mut data = header(0, 1, 0, 0);
2076 data.extend_from_slice(&wire_name("example.com"));
2077 data.extend_from_slice(&TYPE_AAAA.to_be_bytes());
2078 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&3600u32.to_be_bytes());
2080 data.extend_from_slice(&16u16.to_be_bytes());
2081 data.extend_from_slice(&addr);
2082
2083 let mut b = buf();
2084 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2085 let layer = &b.layers()[0];
2086 let answers = b.field_by_name(layer, "answers").unwrap();
2087 let rr = first_array_entry(&b, answers);
2088 let rdata = find_child(&b, rr, "rdata").unwrap();
2089 assert_eq!(rdata.value, FieldValue::Ipv6Addr(addr));
2090 }
2091
2092 #[test]
2095 fn parse_cname_ns_ptr_record() {
2096 for rtype in [TYPE_CNAME, TYPE_NS, TYPE_PTR, TYPE_DNAME] {
2098 let mut data = header(0, 1, 0, 0);
2099 data.extend_from_slice(&wire_name("a.test"));
2100 data.extend_from_slice(&rtype.to_be_bytes());
2101 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&0u32.to_be_bytes());
2103 let target = wire_name("b.test");
2104 data.extend_from_slice(&(target.len() as u16).to_be_bytes());
2105 data.extend_from_slice(&target);
2106
2107 let mut b = buf();
2108 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2109 let layer = &b.layers()[0];
2110 let answers = b.field_by_name(layer, "answers").unwrap();
2111 let rr = first_array_entry(&b, answers);
2112 let rdata = find_child(&b, rr, "rdata").unwrap();
2113 assert_eq!(rdata.value, FieldValue::Bytes(&target));
2115 }
2116 }
2117
2118 #[test]
2119 fn parse_mx_record() {
2120 let mut data = header(0, 1, 0, 0);
2121 data.extend_from_slice(&wire_name("ex.test"));
2122 data.extend_from_slice(&TYPE_MX.to_be_bytes());
2123 data.extend_from_slice(&1u16.to_be_bytes());
2124 data.extend_from_slice(&0u32.to_be_bytes());
2125 let exch = wire_name("mail.ex.test");
2126 let rdlen = (2 + exch.len()) as u16;
2127 data.extend_from_slice(&rdlen.to_be_bytes());
2128 data.extend_from_slice(&10u16.to_be_bytes()); data.extend_from_slice(&exch);
2130
2131 let mut b = buf();
2132 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2133 let layer = &b.layers()[0];
2134 let answers = b.field_by_name(layer, "answers").unwrap();
2135 let rr = first_array_entry(&b, answers);
2136 assert_eq!(
2137 find_child(&b, rr, "rdata_preference").unwrap().value,
2138 FieldValue::U16(10)
2139 );
2140 assert_eq!(
2141 find_child(&b, rr, "rdata_exchange").unwrap().value,
2142 FieldValue::Bytes(&exch)
2143 );
2144 }
2145
2146 #[test]
2147 fn parse_soa_record() {
2148 let mname = wire_name("ns1.ex.test");
2149 let rname = wire_name("hostmaster.ex.test");
2150 let mut rdata = Vec::new();
2151 rdata.extend_from_slice(&mname);
2152 rdata.extend_from_slice(&rname);
2153 rdata.extend_from_slice(&20_240_101u32.to_be_bytes()); rdata.extend_from_slice(&3600u32.to_be_bytes()); rdata.extend_from_slice(&1800u32.to_be_bytes()); rdata.extend_from_slice(&604_800u32.to_be_bytes()); rdata.extend_from_slice(&300u32.to_be_bytes()); let mut data = header(0, 1, 0, 0);
2160 data.extend_from_slice(&wire_name("ex.test"));
2161 data.extend_from_slice(&TYPE_SOA.to_be_bytes());
2162 data.extend_from_slice(&1u16.to_be_bytes());
2163 data.extend_from_slice(&0u32.to_be_bytes());
2164 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2165 data.extend_from_slice(&rdata);
2166
2167 let mut b = buf();
2168 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2169 let layer = &b.layers()[0];
2170 let answers = b.field_by_name(layer, "answers").unwrap();
2171 let rr = first_array_entry(&b, answers);
2172
2173 assert_eq!(
2174 find_child(&b, rr, "rdata_serial").unwrap().value,
2175 FieldValue::U32(20_240_101)
2176 );
2177 assert_eq!(
2178 find_child(&b, rr, "rdata_refresh").unwrap().value,
2179 FieldValue::U32(3600)
2180 );
2181 assert_eq!(
2182 find_child(&b, rr, "rdata_retry").unwrap().value,
2183 FieldValue::U32(1800)
2184 );
2185 assert_eq!(
2186 find_child(&b, rr, "rdata_expire").unwrap().value,
2187 FieldValue::U32(604_800)
2188 );
2189 assert_eq!(
2190 find_child(&b, rr, "rdata_minimum").unwrap().value,
2191 FieldValue::U32(300)
2192 );
2193 }
2194
2195 #[test]
2196 fn parse_txt_record() {
2197 let rdata: &[u8] = &[3, b'a', b'b', b'c', 2, b'd', b'e'];
2198 let mut data = header(0, 1, 0, 0);
2199 data.extend_from_slice(&wire_name("ex.test"));
2200 data.extend_from_slice(&TYPE_TXT.to_be_bytes());
2201 data.extend_from_slice(&1u16.to_be_bytes());
2202 data.extend_from_slice(&0u32.to_be_bytes());
2203 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2204 data.extend_from_slice(rdata);
2205
2206 let mut b = buf();
2207 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2208 let layer = &b.layers()[0];
2209 let answers = b.field_by_name(layer, "answers").unwrap();
2210 let rr = first_array_entry(&b, answers);
2211 assert_eq!(
2212 find_child(&b, rr, "rdata").unwrap().value,
2213 FieldValue::Bytes(rdata)
2214 );
2215 }
2216
2217 #[test]
2220 fn parse_srv_record() {
2221 let target = wire_name("sip.ex.test");
2222 let mut rdata = Vec::new();
2223 rdata.extend_from_slice(&10u16.to_be_bytes()); rdata.extend_from_slice(&20u16.to_be_bytes()); rdata.extend_from_slice(&5060u16.to_be_bytes()); rdata.extend_from_slice(&target);
2227
2228 let mut data = header(0, 1, 0, 0);
2229 data.extend_from_slice(&wire_name("_sip._udp.ex.test"));
2230 data.extend_from_slice(&TYPE_SRV.to_be_bytes());
2231 data.extend_from_slice(&1u16.to_be_bytes());
2232 data.extend_from_slice(&0u32.to_be_bytes());
2233 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2234 data.extend_from_slice(&rdata);
2235
2236 let mut b = buf();
2237 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2238 let layer = &b.layers()[0];
2239 let answers = b.field_by_name(layer, "answers").unwrap();
2240 let rr = first_array_entry(&b, answers);
2241 assert_eq!(
2242 find_child(&b, rr, "rdata_priority").unwrap().value,
2243 FieldValue::U16(10)
2244 );
2245 assert_eq!(
2246 find_child(&b, rr, "rdata_weight").unwrap().value,
2247 FieldValue::U16(20)
2248 );
2249 assert_eq!(
2250 find_child(&b, rr, "rdata_port").unwrap().value,
2251 FieldValue::U16(5060)
2252 );
2253 assert_eq!(
2254 find_child(&b, rr, "rdata_target").unwrap().value,
2255 FieldValue::Bytes(&target)
2256 );
2257 }
2258
2259 fn build_naptr_packet() -> Vec<u8> {
2262 let replacement = wire_name("ex.test");
2263 let mut rdata = Vec::new();
2264 rdata.extend_from_slice(&100u16.to_be_bytes()); rdata.extend_from_slice(&10u16.to_be_bytes()); rdata.extend_from_slice(&[1, b's']);
2268 let svc = b"SIP+D2U";
2270 rdata.push(svc.len() as u8);
2271 rdata.extend_from_slice(svc);
2272 rdata.push(0);
2274 rdata.extend_from_slice(&replacement);
2276
2277 let mut data = header(0, 1, 0, 0);
2278 data.extend_from_slice(&wire_name("ex.test"));
2279 data.extend_from_slice(&TYPE_NAPTR.to_be_bytes());
2280 data.extend_from_slice(&1u16.to_be_bytes());
2281 data.extend_from_slice(&0u32.to_be_bytes());
2282 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2283 data.extend_from_slice(&rdata);
2284 data
2285 }
2286
2287 #[test]
2288 fn parse_naptr_record() {
2289 let data = build_naptr_packet();
2290 let mut b = buf();
2291 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2292 let layer = &b.layers()[0];
2293 let answers = b.field_by_name(layer, "answers").unwrap();
2294 let rr = first_array_entry(&b, answers);
2295 assert_eq!(
2296 find_child(&b, rr, "rdata_order").unwrap().value,
2297 FieldValue::U16(100)
2298 );
2299 assert_eq!(
2300 find_child(&b, rr, "rdata_preference").unwrap().value,
2301 FieldValue::U16(10)
2302 );
2303 let flags = find_child(&b, rr, "rdata_flags").unwrap();
2306 assert_eq!(flags.value, FieldValue::Bytes(&[1, b's']));
2307 let services = find_child(&b, rr, "rdata_services").unwrap();
2308 let mut expected_svc = vec![7u8];
2309 expected_svc.extend_from_slice(b"SIP+D2U");
2310 assert_eq!(services.value, FieldValue::Bytes(&expected_svc));
2311 }
2312
2313 #[test]
2316 fn parse_opt_record_edns0() {
2317 let mut rdata = Vec::new();
2320 rdata.extend_from_slice(&10u16.to_be_bytes()); rdata.extend_from_slice(&8u16.to_be_bytes()); rdata.extend_from_slice(&[0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33]);
2323
2324 let mut data = header(0, 0, 0, 1);
2325 data.push(0);
2327 data.extend_from_slice(&TYPE_OPT.to_be_bytes());
2328 data.extend_from_slice(&4096u16.to_be_bytes()); data.extend_from_slice(&0x0000_8000u32.to_be_bytes());
2332 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2333 data.extend_from_slice(&rdata);
2334
2335 let mut b = buf();
2336 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2337 let layer = &b.layers()[0];
2338 let additionals = b.field_by_name(layer, "additionals").unwrap();
2339 let rr = first_array_entry(&b, additionals);
2340 assert_eq!(
2341 find_child(&b, rr, "udp_payload_size").unwrap().value,
2342 FieldValue::U16(4096)
2343 );
2344 assert_eq!(
2345 find_child(&b, rr, "extended_rcode").unwrap().value,
2346 FieldValue::U8(0)
2347 );
2348 assert_eq!(
2349 find_child(&b, rr, "edns_version").unwrap().value,
2350 FieldValue::U8(0)
2351 );
2352 assert_eq!(
2353 find_child(&b, rr, "do_bit").unwrap().value,
2354 FieldValue::U8(1)
2355 );
2356
2357 let opts = find_child(&b, rr, "edns_options").unwrap();
2358 let FieldValue::Array(ref opt_range) = opts.value else {
2359 unreachable!()
2360 };
2361 let opt_list = b.nested_fields(opt_range);
2362 assert_eq!(
2363 find_child(&b, &opt_list[0], "code").unwrap().value,
2364 FieldValue::U16(10) );
2366 assert_eq!(
2367 find_child(&b, &opt_list[0], "length").unwrap().value,
2368 FieldValue::U16(8)
2369 );
2370 }
2371
2372 #[test]
2373 fn edns_option_container_resolves_to_option_name() {
2374 let mut rdata = Vec::new();
2377 rdata.extend_from_slice(&10u16.to_be_bytes()); rdata.extend_from_slice(&8u16.to_be_bytes()); rdata.extend_from_slice(&[0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33]);
2380
2381 let mut data = header(0, 0, 0, 1);
2382 data.push(0);
2383 data.extend_from_slice(&TYPE_OPT.to_be_bytes());
2384 data.extend_from_slice(&4096u16.to_be_bytes());
2385 data.extend_from_slice(&0u32.to_be_bytes());
2386 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2387 data.extend_from_slice(&rdata);
2388
2389 let mut b = buf();
2390 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2391
2392 let (opt_idx, opt_field) = b
2393 .fields()
2394 .iter()
2395 .enumerate()
2396 .find(|(_, f)| f.name() == "edns_option")
2397 .expect("edns_option container not found");
2398 assert!(matches!(opt_field.value, FieldValue::Object(_)));
2399 assert_eq!(opt_field.display_name(), "EDNS Option");
2400 assert_eq!(
2401 b.resolve_container_display_name(opt_idx as u32),
2402 Some("COOKIE")
2403 );
2404 }
2405
2406 #[test]
2409 fn parse_edns_tcp_keepalive() {
2410 let mut rdata = Vec::new();
2412 rdata.extend_from_slice(&EDNS_OPT_TCP_KEEPALIVE.to_be_bytes()); rdata.extend_from_slice(&2u16.to_be_bytes()); rdata.extend_from_slice(&300u16.to_be_bytes()); let mut data = header(0, 0, 0, 1);
2417 data.push(0);
2418 data.extend_from_slice(&TYPE_OPT.to_be_bytes());
2419 data.extend_from_slice(&1232u16.to_be_bytes());
2420 data.extend_from_slice(&0u32.to_be_bytes());
2421 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2422 data.extend_from_slice(&rdata);
2423
2424 let mut b = buf();
2425 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2426 let layer = &b.layers()[0];
2427 let additionals = b.field_by_name(layer, "additionals").unwrap();
2428 let rr = first_array_entry(&b, additionals);
2429 let opts = find_child(&b, rr, "edns_options").unwrap();
2430 let opt = first_array_entry(&b, opts);
2431 assert_eq!(
2432 find_child(&b, opt, "timeout").unwrap().value,
2433 FieldValue::U16(300)
2434 );
2435 }
2436
2437 #[test]
2440 fn parse_sshfp_record() {
2441 let rdata: Vec<u8> = {
2443 let mut v = vec![2u8, 1u8];
2444 v.extend_from_slice(&[0u8; 20]);
2445 v
2446 };
2447 let mut data = header(0, 1, 0, 0);
2448 data.extend_from_slice(&wire_name("ex.test"));
2449 data.extend_from_slice(&TYPE_SSHFP.to_be_bytes());
2450 data.extend_from_slice(&1u16.to_be_bytes());
2451 data.extend_from_slice(&0u32.to_be_bytes());
2452 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2453 data.extend_from_slice(&rdata);
2454
2455 let mut b = buf();
2456 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2457 let layer = &b.layers()[0];
2458 let answers = b.field_by_name(layer, "answers").unwrap();
2459 let rr = first_array_entry(&b, answers);
2460 assert_eq!(
2461 find_child(&b, rr, "rdata_algorithm").unwrap().value,
2462 FieldValue::U8(2)
2463 );
2464 assert_eq!(
2465 find_child(&b, rr, "rdata_fingerprint_type").unwrap().value,
2466 FieldValue::U8(1)
2467 );
2468 assert_eq!(
2469 find_child(&b, rr, "rdata_fingerprint").unwrap().value,
2470 FieldValue::Bytes(&[0u8; 20])
2471 );
2472 }
2473
2474 #[test]
2477 fn parse_tlsa_record() {
2478 let rdata: Vec<u8> = {
2481 let mut v = vec![3u8, 1u8, 1u8];
2482 v.extend_from_slice(&[0xAAu8; 32]);
2483 v
2484 };
2485 let mut data = header(0, 1, 0, 0);
2486 data.extend_from_slice(&wire_name("_443._tcp.ex.test"));
2487 data.extend_from_slice(&TYPE_TLSA.to_be_bytes());
2488 data.extend_from_slice(&1u16.to_be_bytes());
2489 data.extend_from_slice(&0u32.to_be_bytes());
2490 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2491 data.extend_from_slice(&rdata);
2492
2493 let mut b = buf();
2494 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2495 let layer = &b.layers()[0];
2496 let answers = b.field_by_name(layer, "answers").unwrap();
2497 let rr = first_array_entry(&b, answers);
2498 assert_eq!(
2499 find_child(&b, rr, "rdata_cert_usage").unwrap().value,
2500 FieldValue::U8(3)
2501 );
2502 assert_eq!(
2503 find_child(&b, rr, "rdata_selector").unwrap().value,
2504 FieldValue::U8(1)
2505 );
2506 assert_eq!(
2507 find_child(&b, rr, "rdata_matching_type").unwrap().value,
2508 FieldValue::U8(1)
2509 );
2510 assert_eq!(
2511 find_child(&b, rr, "rdata_cert_assoc_data").unwrap().value,
2512 FieldValue::Bytes(&[0xAAu8; 32])
2513 );
2514 }
2515
2516 #[test]
2519 fn parse_ds_record() {
2520 let digest = [0x11u8; 20]; let rdata: Vec<u8> = {
2522 let mut v = Vec::new();
2523 v.extend_from_slice(&12345u16.to_be_bytes()); v.push(8); v.push(1); v.extend_from_slice(&digest);
2527 v
2528 };
2529 let mut data = header(0, 1, 0, 0);
2530 data.extend_from_slice(&wire_name("ex.test"));
2531 data.extend_from_slice(&TYPE_DS.to_be_bytes());
2532 data.extend_from_slice(&1u16.to_be_bytes());
2533 data.extend_from_slice(&0u32.to_be_bytes());
2534 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2535 data.extend_from_slice(&rdata);
2536
2537 let mut b = buf();
2538 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2539 let layer = &b.layers()[0];
2540 let answers = b.field_by_name(layer, "answers").unwrap();
2541 let rr = first_array_entry(&b, answers);
2542 assert_eq!(
2543 find_child(&b, rr, "rdata_key_tag").unwrap().value,
2544 FieldValue::U16(12345)
2545 );
2546 assert_eq!(
2547 find_child(&b, rr, "rdata_algorithm").unwrap().value,
2548 FieldValue::U8(8)
2549 );
2550 assert_eq!(
2551 find_child(&b, rr, "rdata_digest_type").unwrap().value,
2552 FieldValue::U8(1)
2553 );
2554 assert_eq!(
2555 find_child(&b, rr, "rdata_digest").unwrap().value,
2556 FieldValue::Bytes(&digest)
2557 );
2558 }
2559
2560 #[test]
2563 fn parse_cds_record() {
2564 let digest = [0x22u8; 20];
2565 let rdata: Vec<u8> = {
2566 let mut v = Vec::new();
2567 v.extend_from_slice(&65535u16.to_be_bytes());
2568 v.push(13); v.push(2); v.extend_from_slice(&digest);
2571 v
2572 };
2573 let mut data = header(0, 1, 0, 0);
2574 data.extend_from_slice(&wire_name("ex.test"));
2575 data.extend_from_slice(&TYPE_CDS.to_be_bytes());
2576 data.extend_from_slice(&1u16.to_be_bytes());
2577 data.extend_from_slice(&0u32.to_be_bytes());
2578 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2579 data.extend_from_slice(&rdata);
2580
2581 let mut b = buf();
2582 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2583 let layer = &b.layers()[0];
2584 let answers = b.field_by_name(layer, "answers").unwrap();
2585 let rr = first_array_entry(&b, answers);
2586 assert_eq!(
2587 find_child(&b, rr, "rdata_key_tag").unwrap().value,
2588 FieldValue::U16(65535)
2589 );
2590 assert_eq!(
2591 find_child(&b, rr, "rdata_digest").unwrap().value,
2592 FieldValue::Bytes(&digest)
2593 );
2594 }
2595
2596 #[test]
2599 fn parse_dnskey_record() {
2600 let pubkey = [0x33u8; 64];
2601 let rdata: Vec<u8> = {
2602 let mut v = Vec::new();
2603 v.extend_from_slice(&256u16.to_be_bytes()); v.push(3); v.push(13); v.extend_from_slice(&pubkey);
2607 v
2608 };
2609 let mut data = header(0, 1, 0, 0);
2610 data.extend_from_slice(&wire_name("ex.test"));
2611 data.extend_from_slice(&TYPE_DNSKEY.to_be_bytes());
2612 data.extend_from_slice(&1u16.to_be_bytes());
2613 data.extend_from_slice(&0u32.to_be_bytes());
2614 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2615 data.extend_from_slice(&rdata);
2616
2617 let mut b = buf();
2618 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2619 let layer = &b.layers()[0];
2620 let answers = b.field_by_name(layer, "answers").unwrap();
2621 let rr = first_array_entry(&b, answers);
2622 assert_eq!(
2623 find_child(&b, rr, "rdata_flags").unwrap().value,
2624 FieldValue::U16(256)
2625 );
2626 assert_eq!(
2627 find_child(&b, rr, "rdata_protocol").unwrap().value,
2628 FieldValue::U8(3)
2629 );
2630 assert_eq!(
2631 find_child(&b, rr, "rdata_algorithm").unwrap().value,
2632 FieldValue::U8(13)
2633 );
2634 assert_eq!(
2635 find_child(&b, rr, "rdata_public_key").unwrap().value,
2636 FieldValue::Bytes(&pubkey)
2637 );
2638 }
2639
2640 #[test]
2643 fn parse_rrsig_record() {
2644 let signer = wire_name("ex.test");
2645 let signature = [0x55u8; 64];
2646 let mut rdata = Vec::new();
2647 rdata.extend_from_slice(&TYPE_A.to_be_bytes()); rdata.push(13); rdata.push(2); rdata.extend_from_slice(&3600u32.to_be_bytes()); rdata.extend_from_slice(&2_000_000_000u32.to_be_bytes()); rdata.extend_from_slice(&1_000_000_000u32.to_be_bytes()); rdata.extend_from_slice(&4321u16.to_be_bytes()); rdata.extend_from_slice(&signer);
2655 rdata.extend_from_slice(&signature);
2656
2657 let mut data = header(0, 1, 0, 0);
2658 data.extend_from_slice(&wire_name("ex.test"));
2659 data.extend_from_slice(&TYPE_RRSIG.to_be_bytes());
2660 data.extend_from_slice(&1u16.to_be_bytes());
2661 data.extend_from_slice(&0u32.to_be_bytes());
2662 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2663 data.extend_from_slice(&rdata);
2664
2665 let mut b = buf();
2666 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2667 let layer = &b.layers()[0];
2668 let answers = b.field_by_name(layer, "answers").unwrap();
2669 let rr = first_array_entry(&b, answers);
2670 assert_eq!(
2671 find_child(&b, rr, "rdata_type_covered").unwrap().value,
2672 FieldValue::U16(TYPE_A)
2673 );
2674 assert_eq!(
2675 find_child(&b, rr, "rdata_labels").unwrap().value,
2676 FieldValue::U8(2)
2677 );
2678 assert_eq!(
2679 find_child(&b, rr, "rdata_original_ttl").unwrap().value,
2680 FieldValue::U32(3600)
2681 );
2682 assert_eq!(
2683 find_child(&b, rr, "rdata_signature_expiration")
2684 .unwrap()
2685 .value,
2686 FieldValue::U32(2_000_000_000)
2687 );
2688 assert_eq!(
2689 find_child(&b, rr, "rdata_signature_inception")
2690 .unwrap()
2691 .value,
2692 FieldValue::U32(1_000_000_000)
2693 );
2694 assert_eq!(
2695 find_child(&b, rr, "rdata_key_tag").unwrap().value,
2696 FieldValue::U16(4321)
2697 );
2698 assert_eq!(
2699 find_child(&b, rr, "rdata_signature").unwrap().value,
2700 FieldValue::Bytes(&signature)
2701 );
2702 }
2703
2704 #[test]
2707 fn parse_nsec_record() {
2708 let next_name = wire_name("next.ex.test");
2711 let bitmap = [0u8, 0, 0, 0x08, 0x40];
2714 let mut bitmaps = Vec::new();
2716 bitmaps.push(0u8); bitmaps.push(4u8); bitmaps.extend_from_slice(&[0x40, 0, 0, 0x08]); let _ = bitmap;
2720
2721 let mut rdata = Vec::new();
2722 rdata.extend_from_slice(&next_name);
2723 rdata.extend_from_slice(&bitmaps);
2724
2725 let mut data = header(0, 1, 0, 0);
2726 data.extend_from_slice(&wire_name("ex.test"));
2727 data.extend_from_slice(&TYPE_NSEC.to_be_bytes());
2728 data.extend_from_slice(&1u16.to_be_bytes());
2729 data.extend_from_slice(&0u32.to_be_bytes());
2730 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2731 data.extend_from_slice(&rdata);
2732
2733 let mut b = buf();
2734 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2735 let layer = &b.layers()[0];
2736 let answers = b.field_by_name(layer, "answers").unwrap();
2737 let rr = first_array_entry(&b, answers);
2738 assert_eq!(
2739 find_child(&b, rr, "rdata_next_domain_name").unwrap().value,
2740 FieldValue::Bytes(&next_name)
2741 );
2742 assert_eq!(
2743 find_child(&b, rr, "rdata_type_bitmaps").unwrap().value,
2744 FieldValue::Bytes(&bitmaps)
2745 );
2746 }
2747
2748 #[test]
2751 fn parse_nsec3_record() {
2752 let salt = [0xCAu8, 0xFE];
2753 let next_hash = [0x11u8; 20];
2754 let bitmaps = [0u8, 1u8, 0x40u8]; let mut rdata = Vec::new();
2756 rdata.push(1); rdata.push(0); rdata.extend_from_slice(&10u16.to_be_bytes()); rdata.push(salt.len() as u8);
2760 rdata.extend_from_slice(&salt);
2761 rdata.push(next_hash.len() as u8);
2762 rdata.extend_from_slice(&next_hash);
2763 rdata.extend_from_slice(&bitmaps);
2764
2765 let mut data = header(0, 1, 0, 0);
2766 data.extend_from_slice(&wire_name("ex.test"));
2767 data.extend_from_slice(&TYPE_NSEC3.to_be_bytes());
2768 data.extend_from_slice(&1u16.to_be_bytes());
2769 data.extend_from_slice(&0u32.to_be_bytes());
2770 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2771 data.extend_from_slice(&rdata);
2772
2773 let mut b = buf();
2774 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2775 let layer = &b.layers()[0];
2776 let answers = b.field_by_name(layer, "answers").unwrap();
2777 let rr = first_array_entry(&b, answers);
2778 assert_eq!(
2779 find_child(&b, rr, "rdata_hash_algorithm").unwrap().value,
2780 FieldValue::U8(1)
2781 );
2782 assert_eq!(
2783 find_child(&b, rr, "rdata_iterations").unwrap().value,
2784 FieldValue::U16(10)
2785 );
2786 assert_eq!(
2787 find_child(&b, rr, "rdata_salt_length").unwrap().value,
2788 FieldValue::U8(2)
2789 );
2790 assert_eq!(
2791 find_child(&b, rr, "rdata_salt").unwrap().value,
2792 FieldValue::Bytes(&salt)
2793 );
2794 assert_eq!(
2795 find_child(&b, rr, "rdata_hash_length").unwrap().value,
2796 FieldValue::U8(20)
2797 );
2798 assert_eq!(
2799 find_child(&b, rr, "rdata_next_hashed_owner").unwrap().value,
2800 FieldValue::Bytes(&next_hash)
2801 );
2802 assert_eq!(
2803 find_child(&b, rr, "rdata_type_bitmaps").unwrap().value,
2804 FieldValue::Bytes(&bitmaps)
2805 );
2806 }
2807
2808 #[test]
2811 fn parse_nsec3param_record() {
2812 let salt = [0x01u8, 0x02, 0x03];
2813 let mut rdata = Vec::new();
2814 rdata.push(1); rdata.push(0); rdata.extend_from_slice(&5u16.to_be_bytes()); rdata.push(salt.len() as u8);
2818 rdata.extend_from_slice(&salt);
2819
2820 let mut data = header(0, 1, 0, 0);
2821 data.extend_from_slice(&wire_name("ex.test"));
2822 data.extend_from_slice(&TYPE_NSEC3PARAM.to_be_bytes());
2823 data.extend_from_slice(&1u16.to_be_bytes());
2824 data.extend_from_slice(&0u32.to_be_bytes());
2825 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2826 data.extend_from_slice(&rdata);
2827
2828 let mut b = buf();
2829 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2830 let layer = &b.layers()[0];
2831 let answers = b.field_by_name(layer, "answers").unwrap();
2832 let rr = first_array_entry(&b, answers);
2833 assert_eq!(
2834 find_child(&b, rr, "rdata_hash_algorithm").unwrap().value,
2835 FieldValue::U8(1)
2836 );
2837 assert_eq!(
2838 find_child(&b, rr, "rdata_iterations").unwrap().value,
2839 FieldValue::U16(5)
2840 );
2841 assert_eq!(
2842 find_child(&b, rr, "rdata_salt").unwrap().value,
2843 FieldValue::Bytes(&salt)
2844 );
2845 }
2846
2847 #[test]
2850 fn parse_caa_record() {
2851 let tag = b"issue";
2853 let value = b"ca.example.net";
2854 let mut rdata = Vec::new();
2855 rdata.push(0x80); rdata.push(tag.len() as u8);
2857 rdata.extend_from_slice(tag);
2858 rdata.extend_from_slice(value);
2859
2860 let mut data = header(0, 1, 0, 0);
2861 data.extend_from_slice(&wire_name("ex.test"));
2862 data.extend_from_slice(&TYPE_CAA.to_be_bytes());
2863 data.extend_from_slice(&1u16.to_be_bytes());
2864 data.extend_from_slice(&0u32.to_be_bytes());
2865 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2866 let rdata_abs = data.len();
2868 data.extend_from_slice(&rdata);
2869
2870 let mut b = buf();
2871 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2872 let layer = &b.layers()[0];
2873 let answers = b.field_by_name(layer, "answers").unwrap();
2874 let rr = first_array_entry(&b, answers);
2875
2876 assert_eq!(
2877 find_child(&b, rr, "rdata_flags").unwrap().value,
2878 FieldValue::U8(0x80)
2879 );
2880
2881 let tag_field = find_child(&b, rr, "rdata_tag").unwrap();
2885 assert_eq!(tag_field.value, FieldValue::Bytes(tag));
2886 assert_eq!(
2887 tag_field.range,
2888 (rdata_abs + 2)..(rdata_abs + 2 + tag.len())
2889 );
2890 assert_eq!(tag_field.range.len(), tag.len());
2891
2892 let value_field = find_child(&b, rr, "rdata_value").unwrap();
2893 assert_eq!(value_field.value, FieldValue::Bytes(value));
2894 assert_eq!(
2895 value_field.range,
2896 (rdata_abs + 2 + tag.len())..(rdata_abs + 2 + tag.len() + value.len())
2897 );
2898 }
2899
2900 #[test]
2903 fn parse_svcb_record() {
2904 let target = wire_name("svc.ex.test");
2906 let mut rdata = Vec::new();
2907 rdata.extend_from_slice(&1u16.to_be_bytes()); rdata.extend_from_slice(&target);
2909 let mut data = header(0, 1, 0, 0);
2912 data.extend_from_slice(&wire_name("ex.test"));
2913 data.extend_from_slice(&TYPE_HTTPS.to_be_bytes());
2914 data.extend_from_slice(&1u16.to_be_bytes());
2915 data.extend_from_slice(&0u32.to_be_bytes());
2916 data.extend_from_slice(&(rdata.len() as u16).to_be_bytes());
2917 data.extend_from_slice(&rdata);
2918
2919 let mut b = buf();
2920 DnsDissector.dissect(&data, &mut b, 0).unwrap();
2921 let layer = &b.layers()[0];
2922 let answers = b.field_by_name(layer, "answers").unwrap();
2923 let rr = first_array_entry(&b, answers);
2924 assert_eq!(
2925 find_child(&b, rr, "rdata_priority").unwrap().value,
2926 FieldValue::U16(1)
2927 );
2928 assert_eq!(
2929 find_child(&b, rr, "rdata_target").unwrap().value,
2930 FieldValue::Bytes(&target)
2931 );
2932 }
2933
2934 #[test]
2937 fn reject_name_over_255_octets() {
2938 let label_63: Vec<u8> = core::iter::once(63u8)
2941 .chain(std::iter::repeat_n(b'a', 63))
2942 .collect();
2943 let label_62: Vec<u8> = core::iter::once(62u8)
2944 .chain(std::iter::repeat_n(b'a', 62))
2945 .collect();
2946 let mut name = Vec::new();
2947 name.extend_from_slice(&label_63);
2948 name.extend_from_slice(&label_63);
2949 name.extend_from_slice(&label_63);
2950 name.extend_from_slice(&label_62);
2951 name.push(0);
2952 assert_eq!(name.len(), 64 * 3 + 63 + 1); let mut data = header(1, 0, 0, 0);
2955 data.extend_from_slice(&name);
2956 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&1u16.to_be_bytes()); let mut b = buf();
2960 let err = DnsDissector.dissect(&data, &mut b, 0).unwrap_err();
2961 assert!(matches!(err, PacketError::InvalidHeader(_)));
2962 }
2963
2964 #[test]
2965 fn reject_name_pointer_loop() {
2966 let mut data = header(1, 0, 0, 0);
2969 data.push(0xC0);
2970 data.push(HEADER_SIZE as u8); data.extend_from_slice(&1u16.to_be_bytes());
2972 data.extend_from_slice(&1u16.to_be_bytes());
2973
2974 let mut b = buf();
2975 let err = DnsDissector.dissect(&data, &mut b, 0).unwrap_err();
2976 assert!(matches!(err, PacketError::InvalidHeader(_)));
2977 }
2978
2979 #[test]
2980 fn reject_reserved_label_type() {
2981 let mut data = header(1, 0, 0, 0);
2983 data.push(0x80); data.extend_from_slice(&1u16.to_be_bytes());
2985 data.extend_from_slice(&1u16.to_be_bytes());
2986
2987 let mut b = buf();
2988 let err = DnsDissector.dissect(&data, &mut b, 0).unwrap_err();
2989 assert!(matches!(err, PacketError::InvalidHeader(_)));
2990 }
2991
2992 #[test]
2995 fn parse_tcp_length_prefix() {
2996 let mut dns = header(1, 0, 0, 0);
2997 dns.extend_from_slice(&wire_name("ex.test"));
2998 dns.extend_from_slice(&1u16.to_be_bytes()); dns.extend_from_slice(&1u16.to_be_bytes()); let mut framed = Vec::new();
3001 framed.extend_from_slice(&(dns.len() as u16).to_be_bytes());
3002 framed.extend_from_slice(&dns);
3003
3004 let mut b = buf();
3005 let res = DnsTcpDissector.dissect(&framed, &mut b, 0).unwrap();
3006 assert_eq!(res.bytes_consumed, framed.len());
3007
3008 let layer = &b.layers()[0];
3009 assert_eq!(layer.name, "DNS");
3010 let tcp_len = b.field_by_name(layer, "tcp_length").unwrap();
3011 assert_eq!(tcp_len.value, FieldValue::U16(dns.len() as u16));
3012 assert_eq!(tcp_len.range, 0..2);
3013 }
3014
3015 #[test]
3016 fn tcp_truncated_length_prefix() {
3017 let mut b = buf();
3018 let err = DnsTcpDissector.dissect(&[0u8], &mut b, 0).unwrap_err();
3019 assert!(matches!(err, PacketError::Truncated { .. }));
3020 }
3021
3022 #[test]
3025 fn type_class_opcode_rcode_names() {
3026 assert_eq!(dns_type_name(TYPE_A), Some("A"));
3027 assert_eq!(dns_type_name(TYPE_AAAA), Some("AAAA"));
3028 assert_eq!(dns_type_name(TYPE_OPT), Some("OPT"));
3029 assert_eq!(dns_type_name(TYPE_HTTPS), Some("HTTPS"));
3030 assert_eq!(dns_type_name(9999), None);
3031
3032 assert_eq!(dns_class_name(1), Some("IN"));
3033 assert_eq!(dns_class_name(255), Some("ANY"));
3034 assert_eq!(dns_class_name(7), None);
3035
3036 assert_eq!(dns_opcode_name(0), Some("QUERY"));
3037 assert_eq!(dns_opcode_name(5), Some("UPDATE"));
3038 assert_eq!(dns_opcode_name(15), None);
3039
3040 assert_eq!(dns_rcode_name(0), Some("NOERROR"));
3041 assert_eq!(dns_rcode_name(3), Some("NXDOMAIN"));
3042 assert_eq!(dns_rcode_name(15), None);
3043
3044 assert_eq!(edns_option_code_name(10), Some("COOKIE"));
3045 assert_eq!(
3046 edns_option_code_name(EDNS_OPT_TCP_KEEPALIVE),
3047 Some("TCP-KEEPALIVE")
3048 );
3049 assert_eq!(edns_option_code_name(9999), None);
3050 }
3051
3052 #[test]
3053 fn dispatch_hint_is_end() {
3054 let mut data = header(0, 0, 0, 0);
3056 data.extend_from_slice(&[]);
3057 let mut b = buf();
3058 let res = DnsDissector.dissect(&data, &mut b, 0).unwrap();
3059 assert!(matches!(res.next, DispatchHint::End));
3060 }
3061
3062 #[test]
3063 fn write_dns_name_formats_output() {
3064 let target = wire_name("example.com");
3067 let mut data = Vec::new();
3068 data.extend_from_slice(&[0xBE, 0xEF, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]);
3069 let name_off = data.len();
3071 data.extend_from_slice(&target);
3072 data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&1u16.to_be_bytes()); let ctx = FormatContext {
3076 packet_data: &data,
3077 scratch: &[],
3078 layer_range: 0..data.len() as u32,
3079 field_range: name_off as u32..(name_off + target.len()) as u32,
3080 };
3081 let mut out = Vec::new();
3082 write_dns_name(&FieldValue::Bytes(&target), &ctx, &mut out).unwrap();
3083 assert_eq!(&out, b"\"example.com\"");
3084 }
3085}