1#[cfg(feature = "logging")]
8use crate::log::trace;
9
10use std::{
11 any::Any,
12 cmp,
13 collections::HashMap,
14 convert::TryInto,
15 fmt,
16 net::{IpAddr, Ipv4Addr, Ipv6Addr},
17 str,
18 time::SystemTime,
19};
20
21#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
25#[non_exhaustive]
26#[repr(u16)]
27pub enum RRType {
28 A = 1,
30
31 CNAME = 5,
33
34 PTR = 12,
36
37 HINFO = 13,
39
40 TXT = 16,
42
43 AAAA = 28,
45
46 SRV = 33,
48
49 NSEC = 47,
51
52 ANY = 255,
54}
55
56impl RRType {
57 pub const fn from_u16(value: u16) -> Option<RRType> {
59 match value {
60 1 => Some(RRType::A),
61 5 => Some(RRType::CNAME),
62 12 => Some(RRType::PTR),
63 13 => Some(RRType::HINFO),
64 16 => Some(RRType::TXT),
65 28 => Some(RRType::AAAA),
66 33 => Some(RRType::SRV),
67 47 => Some(RRType::NSEC),
68 255 => Some(RRType::ANY),
69 _ => None,
70 }
71 }
72}
73
74impl fmt::Display for RRType {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 RRType::A => write!(f, "TYPE_A"),
78 RRType::CNAME => write!(f, "TYPE_CNAME"),
79 RRType::PTR => write!(f, "TYPE_PTR"),
80 RRType::HINFO => write!(f, "TYPE_HINFO"),
81 RRType::TXT => write!(f, "TYPE_TXT"),
82 RRType::AAAA => write!(f, "TYPE_AAAA"),
83 RRType::SRV => write!(f, "TYPE_SRV"),
84 RRType::NSEC => write!(f, "TYPE_NSEC"),
85 RRType::ANY => write!(f, "TYPE_ANY"),
86 }
87 }
88}
89
90pub const CLASS_IN: u16 = 1;
92pub const CLASS_MASK: u16 = 0x7FFF;
93
94pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
96
97pub const MAX_MSG_ABSOLUTE: usize = 8972;
102
103const MSG_HEADER_LEN: usize = 12;
104
105pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
117
118pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
120
121pub const FLAGS_AA: u16 = 0x0400;
123
124pub const FLAGS_TC: u16 = 0x0200;
135
136pub type DnsRecordBox = Box<dyn DnsRecordExt>;
138
139impl Clone for DnsRecordBox {
140 fn clone(&self) -> Self {
141 self.clone_box()
142 }
143}
144
145const U16_SIZE: usize = 2;
146
147#[inline]
149pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
150 match address {
151 IpAddr::V4(_) => RRType::A,
152 IpAddr::V6(_) => RRType::AAAA,
153 }
154}
155
156#[derive(Eq, PartialEq, Debug, Clone)]
157pub struct DnsEntry {
158 pub(crate) name: String, pub(crate) ty: RRType,
160 class: u16,
161 cache_flush: bool,
162}
163
164impl DnsEntry {
165 const fn new(name: String, ty: RRType, class: u16) -> Self {
166 Self {
167 name,
168 ty,
169 class: class & CLASS_MASK,
170 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
171 }
172 }
173}
174
175pub trait DnsEntryExt: fmt::Debug {
177 fn entry_name(&self) -> &str;
178
179 fn entry_type(&self) -> RRType;
180}
181
182#[derive(Debug)]
184pub struct DnsQuestion {
185 pub(crate) entry: DnsEntry,
186}
187
188impl DnsEntryExt for DnsQuestion {
189 fn entry_name(&self) -> &str {
190 &self.entry.name
191 }
192
193 fn entry_type(&self) -> RRType {
194 self.entry.ty
195 }
196}
197
198#[derive(Debug, Clone)]
202pub struct DnsRecord {
203 pub(crate) entry: DnsEntry,
204 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
214}
215
216impl DnsRecord {
217 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
218 let created = current_time_millis();
219
220 let refresh = get_expiration_time(created, ttl, 80);
224
225 let expires = get_expiration_time(created, ttl, 100);
226
227 Self {
228 entry: DnsEntry::new(name.to_string(), ty, class),
229 ttl,
230 created,
231 expires,
232 refresh,
233 new_name: None,
234 }
235 }
236
237 pub const fn get_ttl(&self) -> u32 {
238 self.ttl
239 }
240
241 pub const fn get_expire_time(&self) -> u64 {
242 self.expires
243 }
244
245 pub const fn get_refresh_time(&self) -> u64 {
246 self.refresh
247 }
248
249 pub const fn is_expired(&self, now: u64) -> bool {
250 now >= self.expires
251 }
252
253 pub const fn refresh_due(&self, now: u64) -> bool {
254 now >= self.refresh
255 }
256
257 pub fn halflife_passed(&self, now: u64) -> bool {
259 let halflife = get_expiration_time(self.created, self.ttl, 50);
260 now > halflife
261 }
262
263 pub fn is_unique(&self) -> bool {
264 self.entry.cache_flush
265 }
266
267 pub fn refresh_no_more(&mut self) {
270 self.refresh = get_expiration_time(self.created, self.ttl, 100);
271 }
272
273 pub fn refresh_maybe(&mut self, now: u64) -> bool {
275 if self.is_expired(now) || !self.refresh_due(now) {
276 return false;
277 }
278
279 trace!(
280 "{} qtype {} is due to refresh",
281 &self.entry.name,
282 self.entry.ty
283 );
284
285 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
292 self.refresh = get_expiration_time(self.created, self.ttl, 85);
293 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
294 self.refresh = get_expiration_time(self.created, self.ttl, 90);
295 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
296 self.refresh = get_expiration_time(self.created, self.ttl, 95);
297 } else {
298 self.refresh_no_more();
299 }
300
301 true
302 }
303
304 fn get_remaining_ttl(&self, now: u64) -> u32 {
306 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
307 cmp::max(0, remaining_millis / 1000) as u32
308 }
309
310 pub const fn get_created(&self) -> u64 {
312 self.created
313 }
314
315 fn set_expire(&mut self, expire_at: u64) {
317 self.expires = expire_at;
318 }
319
320 fn reset_ttl(&mut self, other: &Self) {
321 self.ttl = other.ttl;
322 self.created = other.created;
323 self.refresh = get_expiration_time(self.created, self.ttl, 80);
324 self.expires = get_expiration_time(self.created, self.ttl, 100);
325 }
326
327 pub fn update_ttl(&mut self, now: u64) {
329 if now > self.created {
330 let elapsed = now - self.created;
331 self.ttl -= (elapsed / 1000) as u32;
332 }
333 }
334
335 pub fn set_new_name(&mut self, new_name: String) {
336 if new_name == self.entry.name {
337 self.new_name = None;
338 } else {
339 self.new_name = Some(new_name);
340 }
341 }
342
343 pub fn get_new_name(&self) -> Option<&str> {
344 self.new_name.as_deref()
345 }
346
347 pub(crate) fn get_name(&self) -> &str {
349 self.new_name.as_deref().unwrap_or(&self.entry.name)
350 }
351
352 pub fn get_original_name(&self) -> &str {
353 &self.entry.name
354 }
355}
356
357impl PartialEq for DnsRecord {
358 fn eq(&self, other: &Self) -> bool {
359 self.entry == other.entry
360 }
361}
362
363pub trait DnsRecordExt: fmt::Debug {
365 fn get_record(&self) -> &DnsRecord;
366 fn get_record_mut(&mut self) -> &mut DnsRecord;
367 fn write(&self, packet: &mut DnsOutPacket);
368 fn any(&self) -> &dyn Any;
369
370 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
372
373 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
375
376 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
379
380 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
382 match self.get_class().cmp(&other.get_class()) {
396 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
397 cmp::Ordering::Equal => self.compare_rdata(other),
398 not_equal => not_equal,
399 },
400 not_equal => not_equal,
401 }
402 }
403
404 fn rdata_print(&self) -> String;
406
407 fn get_class(&self) -> u16 {
409 self.get_record().entry.class
410 }
411
412 fn get_cache_flush(&self) -> bool {
413 self.get_record().entry.cache_flush
414 }
415
416 fn get_name(&self) -> &str {
418 self.get_record().get_name()
419 }
420
421 fn get_type(&self) -> RRType {
422 self.get_record().entry.ty
423 }
424
425 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
428 self.get_record_mut().reset_ttl(other.get_record());
429 }
430
431 fn get_created(&self) -> u64 {
432 self.get_record().get_created()
433 }
434
435 fn get_expire(&self) -> u64 {
436 self.get_record().get_expire_time()
437 }
438
439 fn set_expire(&mut self, expire_at: u64) {
440 self.get_record_mut().set_expire(expire_at);
441 }
442
443 fn set_expire_sooner(&mut self, expire_at: u64) {
445 if expire_at < self.get_expire() {
446 self.get_record_mut().set_expire(expire_at);
447 }
448 }
449
450 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
453 if self.get_record_mut().refresh_maybe(now) {
454 Some(self.get_record().get_refresh_time())
455 } else {
456 None
457 }
458 }
459
460 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
463 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
464 }
465
466 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
468 for answer in msg.answers.iter() {
469 if self.suppressed_by_answer(answer.as_ref()) {
470 return true;
471 }
472 }
473 false
474 }
475
476 fn clone_box(&self) -> DnsRecordBox;
477}
478
479#[derive(Debug, Clone)]
481pub struct DnsAddress {
482 pub(crate) record: DnsRecord,
483 address: IpAddr,
484}
485
486impl DnsAddress {
487 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, address: IpAddr) -> Self {
488 let record = DnsRecord::new(name, ty, class, ttl);
489 Self { record, address }
490 }
491
492 pub fn address(&self) -> IpAddr {
493 self.address
494 }
495}
496
497impl DnsRecordExt for DnsAddress {
498 fn get_record(&self) -> &DnsRecord {
499 &self.record
500 }
501
502 fn get_record_mut(&mut self) -> &mut DnsRecord {
503 &mut self.record
504 }
505
506 fn write(&self, packet: &mut DnsOutPacket) {
507 match self.address {
508 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
509 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
510 };
511 }
512
513 fn any(&self) -> &dyn Any {
514 self
515 }
516
517 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
518 if let Some(other_a) = other.any().downcast_ref::<Self>() {
519 return self.address == other_a.address && self.record.entry == other_a.record.entry;
520 }
521 false
522 }
523
524 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
525 if let Some(other_a) = other.any().downcast_ref::<Self>() {
526 return self.address == other_a.address;
527 }
528 false
529 }
530
531 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
532 if let Some(other_a) = other.any().downcast_ref::<Self>() {
533 self.address.cmp(&other_a.address)
534 } else {
535 cmp::Ordering::Greater
536 }
537 }
538
539 fn rdata_print(&self) -> String {
540 format!("{}", self.address)
541 }
542
543 fn clone_box(&self) -> DnsRecordBox {
544 Box::new(self.clone())
545 }
546}
547
548#[derive(Debug, Clone)]
550pub struct DnsPointer {
551 record: DnsRecord,
552 alias: String, }
554
555impl DnsPointer {
556 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
557 let record = DnsRecord::new(name, ty, class, ttl);
558 Self { record, alias }
559 }
560
561 pub fn alias(&self) -> &str {
562 &self.alias
563 }
564}
565
566impl DnsRecordExt for DnsPointer {
567 fn get_record(&self) -> &DnsRecord {
568 &self.record
569 }
570
571 fn get_record_mut(&mut self) -> &mut DnsRecord {
572 &mut self.record
573 }
574
575 fn write(&self, packet: &mut DnsOutPacket) {
576 packet.write_name(&self.alias);
577 }
578
579 fn any(&self) -> &dyn Any {
580 self
581 }
582
583 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
584 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
585 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
586 }
587 false
588 }
589
590 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
591 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
592 return self.alias == other_ptr.alias;
593 }
594 false
595 }
596
597 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
598 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
599 self.alias.cmp(&other_ptr.alias)
600 } else {
601 cmp::Ordering::Greater
602 }
603 }
604
605 fn rdata_print(&self) -> String {
606 self.alias.clone()
607 }
608
609 fn clone_box(&self) -> DnsRecordBox {
610 Box::new(self.clone())
611 }
612}
613
614#[derive(Debug, Clone)]
616pub struct DnsSrv {
617 pub(crate) record: DnsRecord,
618 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
621 port: u16,
622}
623
624impl DnsSrv {
625 pub fn new(
626 name: &str,
627 class: u16,
628 ttl: u32,
629 priority: u16,
630 weight: u16,
631 port: u16,
632 host: String,
633 ) -> Self {
634 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
635 Self {
636 record,
637 priority,
638 weight,
639 host,
640 port,
641 }
642 }
643
644 pub fn host(&self) -> &str {
645 &self.host
646 }
647
648 pub fn port(&self) -> u16 {
649 self.port
650 }
651
652 pub fn set_host(&mut self, host: String) {
653 self.host = host;
654 }
655}
656
657impl DnsRecordExt for DnsSrv {
658 fn get_record(&self) -> &DnsRecord {
659 &self.record
660 }
661
662 fn get_record_mut(&mut self) -> &mut DnsRecord {
663 &mut self.record
664 }
665
666 fn write(&self, packet: &mut DnsOutPacket) {
667 packet.write_short(self.priority);
668 packet.write_short(self.weight);
669 packet.write_short(self.port);
670 packet.write_name(&self.host);
671 }
672
673 fn any(&self) -> &dyn Any {
674 self
675 }
676
677 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
678 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
679 return self.host == other_svc.host
680 && self.port == other_svc.port
681 && self.weight == other_svc.weight
682 && self.priority == other_svc.priority
683 && self.record.entry == other_svc.record.entry;
684 }
685 false
686 }
687
688 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
689 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
690 return self.host == other_srv.host
691 && self.port == other_srv.port
692 && self.weight == other_srv.weight
693 && self.priority == other_srv.priority;
694 }
695 false
696 }
697
698 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
699 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
700 return cmp::Ordering::Greater;
701 };
702
703 match self
705 .priority
706 .to_be_bytes()
707 .cmp(&other_srv.priority.to_be_bytes())
708 {
709 cmp::Ordering::Equal => {
710 match self
712 .weight
713 .to_be_bytes()
714 .cmp(&other_srv.weight.to_be_bytes())
715 {
716 cmp::Ordering::Equal => {
717 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
719 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
720 not_equal => not_equal,
721 }
722 }
723 not_equal => not_equal,
724 }
725 }
726 not_equal => not_equal,
727 }
728 }
729
730 fn rdata_print(&self) -> String {
731 format!(
732 "priority: {}, weight: {}, port: {}, host: {}",
733 self.priority, self.weight, self.port, self.host
734 )
735 }
736
737 fn clone_box(&self) -> DnsRecordBox {
738 Box::new(self.clone())
739 }
740}
741
742#[derive(Clone)]
757pub struct DnsTxt {
758 pub(crate) record: DnsRecord,
759 text: Vec<u8>,
760}
761
762impl DnsTxt {
763 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
764 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
765 Self { record, text }
766 }
767
768 pub fn text(&self) -> &[u8] {
769 &self.text
770 }
771}
772
773impl DnsRecordExt for DnsTxt {
774 fn get_record(&self) -> &DnsRecord {
775 &self.record
776 }
777
778 fn get_record_mut(&mut self) -> &mut DnsRecord {
779 &mut self.record
780 }
781
782 fn write(&self, packet: &mut DnsOutPacket) {
783 packet.write_bytes(&self.text);
784 }
785
786 fn any(&self) -> &dyn Any {
787 self
788 }
789
790 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
791 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
792 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
793 }
794 false
795 }
796
797 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
798 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
799 return self.text == other_txt.text;
800 }
801 false
802 }
803
804 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
805 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
806 self.text.cmp(&other_txt.text)
807 } else {
808 cmp::Ordering::Greater
809 }
810 }
811
812 fn rdata_print(&self) -> String {
813 format!("{:?}", decode_txt(&self.text))
814 }
815
816 fn clone_box(&self) -> DnsRecordBox {
817 Box::new(self.clone())
818 }
819}
820
821impl fmt::Debug for DnsTxt {
822 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823 let properties = decode_txt(&self.text);
824 write!(
825 f,
826 "DnsTxt {{ record: {:?}, text: {:?} }}",
827 self.record, properties
828 )
829 }
830}
831
832fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
834 let mut properties = Vec::new();
835 let mut offset = 0;
836 while offset < txt.len() {
837 let length = txt[offset] as usize;
838 if length == 0 {
839 break; }
841 offset += 1; let offset_end = offset + length;
844 if offset_end > txt.len() {
845 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
846 break; }
848 let kv_bytes = &txt[offset..offset_end];
849
850 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
852 || (kv_bytes.to_vec(), None),
853 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
854 );
855
856 match String::from_utf8(k) {
858 Ok(k_string) => {
859 properties.push(TxtProperty {
860 key: k_string,
861 val: v,
862 });
863 }
864 Err(e) => trace!("ERROR: convert to String from key: {}", e),
865 }
866
867 offset += length;
868 }
869
870 properties
871}
872
873#[derive(Clone, PartialEq, Eq)]
875pub struct TxtProperty {
876 key: String,
878
879 val: Option<Vec<u8>>,
883}
884
885impl TxtProperty {
886 pub fn key(&self) -> &str {
888 &self.key
889 }
890
891 pub fn val(&self) -> Option<&[u8]> {
895 self.val.as_deref()
896 }
897
898 pub fn val_str(&self) -> &str {
900 self.val
901 .as_ref()
902 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
903 }
904}
905
906impl<K, V> From<&(K, V)> for TxtProperty
908where
909 K: ToString,
910 V: ToString,
911{
912 fn from(prop: &(K, V)) -> Self {
913 Self {
914 key: prop.0.to_string(),
915 val: Some(prop.1.to_string().into_bytes()),
916 }
917 }
918}
919
920impl<K, V> From<(K, V)> for TxtProperty
921where
922 K: ToString,
923 V: AsRef<[u8]>,
924{
925 fn from(prop: (K, V)) -> Self {
926 Self {
927 key: prop.0.to_string(),
928 val: Some(prop.1.as_ref().into()),
929 }
930 }
931}
932
933impl From<&str> for TxtProperty {
935 fn from(key: &str) -> Self {
936 Self {
937 key: key.to_string(),
938 val: None,
939 }
940 }
941}
942
943impl fmt::Display for TxtProperty {
944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945 write!(f, "{}={}", self.key, self.val_str())
946 }
947}
948
949impl fmt::Debug for TxtProperty {
953 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
954 let val_string = self.val.as_ref().map_or_else(
955 || "None".to_string(),
956 |v| {
957 std::str::from_utf8(&v[..]).map_or_else(
958 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
959 |s| format!("Some(\"{}\")", s),
960 )
961 },
962 );
963
964 write!(
965 f,
966 "TxtProperty {{key: \"{}\", val: {}}}",
967 &self.key, &val_string,
968 )
969 }
970}
971
972const HEX_TABLE: [char; 16] = [
973 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
974];
975
976fn u8_slice_to_hex(slice: &[u8]) -> String {
980 let mut hex = String::with_capacity(slice.len() * 2 + 2);
981 hex.push_str("0x");
982 for b in slice {
983 hex.push(HEX_TABLE[(b >> 4) as usize]);
984 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
985 }
986 hex
987}
988
989#[derive(Debug, Clone)]
991struct DnsHostInfo {
992 record: DnsRecord,
993 cpu: String,
994 os: String,
995}
996
997impl DnsHostInfo {
998 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
999 let record = DnsRecord::new(name, ty, class, ttl);
1000 Self { record, cpu, os }
1001 }
1002}
1003
1004impl DnsRecordExt for DnsHostInfo {
1005 fn get_record(&self) -> &DnsRecord {
1006 &self.record
1007 }
1008
1009 fn get_record_mut(&mut self) -> &mut DnsRecord {
1010 &mut self.record
1011 }
1012
1013 fn write(&self, packet: &mut DnsOutPacket) {
1014 println!("writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1015 packet.write_bytes(self.cpu.as_bytes());
1016 packet.write_bytes(self.os.as_bytes());
1017 }
1018
1019 fn any(&self) -> &dyn Any {
1020 self
1021 }
1022
1023 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1024 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1025 return self.cpu == other_hinfo.cpu
1026 && self.os == other_hinfo.os
1027 && self.record.entry == other_hinfo.record.entry;
1028 }
1029 false
1030 }
1031
1032 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1033 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1034 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1035 }
1036 false
1037 }
1038
1039 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1040 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1041 match self.cpu.cmp(&other_hinfo.cpu) {
1042 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1043 ordering => ordering,
1044 }
1045 } else {
1046 cmp::Ordering::Greater
1047 }
1048 }
1049
1050 fn rdata_print(&self) -> String {
1051 format!("cpu: {}, os: {}", self.cpu, self.os)
1052 }
1053
1054 fn clone_box(&self) -> DnsRecordBox {
1055 Box::new(self.clone())
1056 }
1057}
1058
1059#[derive(Debug, Clone)]
1065pub struct DnsNSec {
1066 record: DnsRecord,
1067 next_domain: String,
1068 type_bitmap: Vec<u8>,
1069}
1070
1071impl DnsNSec {
1072 pub fn new(
1073 name: &str,
1074 class: u16,
1075 ttl: u32,
1076 next_domain: String,
1077 type_bitmap: Vec<u8>,
1078 ) -> Self {
1079 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1080 Self {
1081 record,
1082 next_domain,
1083 type_bitmap,
1084 }
1085 }
1086
1087 pub fn types(&self) -> Vec<u16> {
1089 let mut bit_num = 0;
1098 let mut results = Vec::new();
1099
1100 for byte in self.type_bitmap.iter() {
1101 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1105 if (byte & bit_mask) != 0 {
1106 results.push(bit_num);
1107 }
1108 bit_num += 1;
1109 bit_mask >>= 1; }
1111 }
1112 results
1113 }
1114}
1115
1116impl DnsRecordExt for DnsNSec {
1117 fn get_record(&self) -> &DnsRecord {
1118 &self.record
1119 }
1120
1121 fn get_record_mut(&mut self) -> &mut DnsRecord {
1122 &mut self.record
1123 }
1124
1125 fn write(&self, packet: &mut DnsOutPacket) {
1126 packet.write_bytes(self.next_domain.as_bytes());
1127 packet.write_bytes(&self.type_bitmap);
1128 }
1129
1130 fn any(&self) -> &dyn Any {
1131 self
1132 }
1133
1134 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1135 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1136 return self.next_domain == other_record.next_domain
1137 && self.type_bitmap == other_record.type_bitmap
1138 && self.record.entry == other_record.record.entry;
1139 }
1140 false
1141 }
1142
1143 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1144 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1145 return self.next_domain == other_record.next_domain
1146 && self.type_bitmap == other_record.type_bitmap;
1147 }
1148 false
1149 }
1150
1151 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1152 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1153 match self.next_domain.cmp(&other_nsec.next_domain) {
1154 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1155 ordering => ordering,
1156 }
1157 } else {
1158 cmp::Ordering::Greater
1159 }
1160 }
1161
1162 fn rdata_print(&self) -> String {
1163 format!(
1164 "next_domain: {}, type_bitmap len: {}",
1165 self.next_domain,
1166 self.type_bitmap.len()
1167 )
1168 }
1169
1170 fn clone_box(&self) -> DnsRecordBox {
1171 Box::new(self.clone())
1172 }
1173}
1174
1175#[derive(PartialEq)]
1176enum PacketState {
1177 Init = 0,
1178 Finished = 1,
1179}
1180
1181pub struct DnsOutPacket {
1183 data: Vec<Vec<u8>>,
1185
1186 size: usize,
1188
1189 state: PacketState,
1191
1192 names: HashMap<String, u16>,
1194}
1195
1196impl DnsOutPacket {
1197 fn new() -> Self {
1198 Self {
1199 data: Vec::new(),
1200 size: MSG_HEADER_LEN, state: PacketState::Init,
1202 names: HashMap::new(),
1203 }
1204 }
1205
1206 pub fn size(&self) -> usize {
1207 self.size
1208 }
1209
1210 pub fn to_bytes(&self) -> Vec<u8> {
1211 self.data.concat()
1212 }
1213
1214 fn write_question(&mut self, question: &DnsQuestion) {
1215 self.write_name(&question.entry.name);
1216 self.write_short(question.entry.ty as u16);
1217 self.write_short(question.entry.class);
1218 }
1219
1220 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> bool {
1224 let start_data_length = self.data.len();
1225 let start_size = self.size;
1226
1227 let record = record_ext.get_record();
1228 self.write_name(record.get_name());
1229 self.write_short(record.entry.ty as u16);
1230 if record.entry.cache_flush {
1231 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1233 } else {
1234 self.write_short(record.entry.class);
1235 }
1236
1237 if now == 0 {
1238 self.write_u32(record.ttl);
1239 } else {
1240 self.write_u32(record.get_remaining_ttl(now));
1241 }
1242
1243 let index = self.data.len();
1244
1245 self.size += 2;
1247 record_ext.write(self);
1248 self.size -= 2;
1249
1250 let length: usize = self.data[index..].iter().map(|x| x.len()).sum();
1251 self.insert_short(index, length as u16);
1252
1253 if self.size > MAX_MSG_ABSOLUTE {
1254 self.data.truncate(start_data_length);
1255 self.size = start_size;
1256 self.state = PacketState::Finished;
1257 return false;
1258 }
1259
1260 true
1261 }
1262
1263 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1264 self.data.insert(index, value.to_be_bytes().to_vec());
1265 self.size += 2;
1266 }
1267
1268 fn write_name(&mut self, name: &str) {
1290 let end = name.len();
1292 let end = if end > 0 && &name[end - 1..] == "." {
1293 end - 1
1294 } else {
1295 end
1296 };
1297
1298 let mut here = 0;
1299 while here < end {
1300 const POINTER_MASK: u16 = 0xC000;
1301 let remaining = &name[here..end];
1302
1303 match self.names.get(remaining) {
1305 Some(offset) => {
1306 let pointer = *offset | POINTER_MASK;
1307 self.write_short(pointer);
1308 break;
1315 }
1316 None => {
1317 self.names.insert(remaining.to_string(), self.size as u16);
1319 let stop = remaining.find('.').map_or(end, |i| here + i);
1323 let label = &name[here..stop];
1324 self.write_utf8(label);
1325
1326 here = stop + 1; }
1328 }
1329
1330 if here >= end {
1331 self.write_byte(0); }
1333 }
1334 }
1335
1336 fn write_utf8(&mut self, utf: &str) {
1337 assert!(utf.len() < 64);
1338 self.write_byte(utf.len() as u8);
1339 self.write_bytes(utf.as_bytes());
1340 }
1341
1342 fn write_bytes(&mut self, s: &[u8]) {
1343 self.data.push(s.to_vec());
1344 self.size += s.len();
1345 }
1346
1347 fn write_u32(&mut self, int: u32) {
1348 self.data.push(int.to_be_bytes().to_vec());
1349 self.size += 4;
1350 }
1351
1352 fn write_short(&mut self, short: u16) {
1353 self.data.push(short.to_be_bytes().to_vec());
1354 self.size += 2;
1355 }
1356
1357 fn write_byte(&mut self, byte: u8) {
1358 self.data.push(vec![byte]);
1359 self.size += 1;
1360 }
1361
1362 fn write_header(
1385 &mut self,
1386 id: u16,
1387 flags: u16,
1388 q_count: u16,
1389 a_count: u16,
1390 auth_count: u16,
1391 addi_count: u16,
1392 ) {
1393 self.insert_short(0, addi_count);
1394 self.insert_short(0, auth_count);
1395 self.insert_short(0, a_count);
1396 self.insert_short(0, q_count);
1397 self.insert_short(0, flags);
1398 self.insert_short(0, id);
1399
1400 self.size -= MSG_HEADER_LEN;
1402
1403 self.state = PacketState::Finished;
1404 }
1405}
1406
1407pub struct DnsOutgoing {
1409 flags: u16,
1410 id: u16,
1411 multicast: bool,
1412 questions: Vec<DnsQuestion>,
1413 answers: Vec<(DnsRecordBox, u64)>,
1414 authorities: Vec<DnsRecordBox>,
1415 additionals: Vec<DnsRecordBox>,
1416 known_answer_count: i64, }
1418
1419impl DnsOutgoing {
1420 pub fn new(flags: u16) -> Self {
1421 Self {
1422 flags,
1423 id: 0,
1424 multicast: true,
1425 questions: Vec::new(),
1426 answers: Vec::new(),
1427 authorities: Vec::new(),
1428 additionals: Vec::new(),
1429 known_answer_count: 0,
1430 }
1431 }
1432
1433 pub fn questions(&self) -> &[DnsQuestion] {
1434 &self.questions
1435 }
1436
1437 pub fn answers_count(&self) -> usize {
1438 self.answers.len()
1439 }
1440
1441 pub fn authorities(&self) -> &[DnsRecordBox] {
1442 &self.authorities
1443 }
1444
1445 pub fn additionals(&self) -> &[DnsRecordBox] {
1446 &self.additionals
1447 }
1448
1449 pub fn known_answer_count(&self) -> i64 {
1450 self.known_answer_count
1451 }
1452
1453 pub fn set_id(&mut self, id: u16) {
1454 self.id = id;
1455 }
1456
1457 pub const fn is_query(&self) -> bool {
1458 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1459 }
1460
1461 const fn is_response(&self) -> bool {
1462 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1463 }
1464
1465 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1499 trace!("add_additional_answer: {:?}", &answer);
1500 self.additionals.push(Box::new(answer));
1501 }
1502
1503 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1505 self.answers.push((answer_box, 0));
1506 }
1507
1508 pub fn add_authority(&mut self, record: DnsRecordBox) {
1509 self.authorities.push(record);
1510 }
1511
1512 pub fn add_answer(
1515 &mut self,
1516 msg: &DnsIncoming,
1517 answer: impl DnsRecordExt + Send + 'static,
1518 ) -> bool {
1519 trace!("Check for add_answer");
1520 if answer.suppressed_by(msg) {
1521 trace!("my answer is suppressed by incoming msg");
1522 self.known_answer_count += 1;
1523 return false;
1524 }
1525
1526 self.add_answer_at_time(answer, 0)
1527 }
1528
1529 pub fn add_answer_at_time(
1533 &mut self,
1534 answer: impl DnsRecordExt + Send + 'static,
1535 now: u64,
1536 ) -> bool {
1537 if now == 0 || !answer.get_record().is_expired(now) {
1538 trace!("add_answer push: {:?}", &answer);
1539 self.answers.push((Box::new(answer), now));
1540 return true;
1541 }
1542 false
1543 }
1544
1545 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1546 let q = DnsQuestion {
1547 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1548 };
1549 self.questions.push(q);
1550 }
1551
1552 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
1554 let packet_list = self.to_packets();
1555 packet_list.iter().map(|p| p.data.concat()).collect()
1556 }
1557
1558 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
1560 let mut packet_list = Vec::new();
1561 let mut packet = DnsOutPacket::new();
1562
1563 let mut question_count = self.questions.len() as u16;
1564 let mut answer_count = 0;
1565 let mut auth_count = 0;
1566 let mut addi_count = 0;
1567 let id = if self.multicast { 0 } else { self.id };
1568
1569 for question in self.questions.iter() {
1570 packet.write_question(question);
1571 }
1572
1573 for (answer, time) in self.answers.iter() {
1574 if packet.write_record(answer.as_ref(), *time) {
1575 answer_count += 1;
1576 }
1577 }
1578
1579 for auth in self.authorities.iter() {
1580 auth_count += u16::from(packet.write_record(auth.as_ref(), 0));
1581 }
1582
1583 for addi in self.additionals.iter() {
1584 if packet.write_record(addi.as_ref(), 0) {
1585 addi_count += 1;
1586 continue;
1587 }
1588
1589 if self.is_response() {
1591 break;
1592 }
1593
1594 packet.write_header(
1599 id,
1600 self.flags | FLAGS_TC,
1601 question_count,
1602 answer_count,
1603 auth_count,
1604 addi_count,
1605 );
1606
1607 packet_list.push(packet);
1608
1609 packet = DnsOutPacket::new();
1611 packet.write_record(addi.as_ref(), 0);
1612
1613 question_count = 0;
1614 answer_count = 0;
1615 auth_count = 0;
1616 addi_count = 1;
1617 }
1618
1619 packet.write_header(
1620 id,
1621 self.flags,
1622 question_count,
1623 answer_count,
1624 auth_count,
1625 addi_count,
1626 );
1627
1628 packet_list.push(packet);
1629 packet_list
1630 }
1631}
1632
1633#[derive(Debug)]
1635pub struct DnsIncoming {
1636 offset: usize,
1637 data: Vec<u8>,
1638 questions: Vec<DnsQuestion>,
1639 answers: Vec<DnsRecordBox>,
1640 authorities: Vec<DnsRecordBox>,
1641 additional: Vec<DnsRecordBox>,
1642 id: u16,
1643 flags: u16,
1644 num_questions: u16,
1645 num_answers: u16,
1646 num_authorities: u16,
1647 num_additionals: u16,
1648}
1649
1650impl DnsIncoming {
1651 pub fn new(data: Vec<u8>) -> Result<Self> {
1652 let mut incoming = Self {
1653 offset: 0,
1654 data,
1655 questions: Vec::new(),
1656 answers: Vec::new(),
1657 authorities: Vec::new(),
1658 additional: Vec::new(),
1659 id: 0,
1660 flags: 0,
1661 num_questions: 0,
1662 num_answers: 0,
1663 num_authorities: 0,
1664 num_additionals: 0,
1665 };
1666
1667 incoming.read_header()?;
1687 incoming.read_questions()?;
1688 incoming.read_answers()?;
1689 incoming.read_authorities()?;
1690 incoming.read_additional()?;
1691
1692 Ok(incoming)
1693 }
1694
1695 pub fn id(&self) -> u16 {
1696 self.id
1697 }
1698
1699 pub fn questions(&self) -> &[DnsQuestion] {
1700 &self.questions
1701 }
1702
1703 pub fn answers(&self) -> &[DnsRecordBox] {
1704 &self.answers
1705 }
1706
1707 pub fn authorities(&self) -> &[DnsRecordBox] {
1708 &self.authorities
1709 }
1710
1711 pub fn additionals(&self) -> &[DnsRecordBox] {
1712 &self.additional
1713 }
1714
1715 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1716 &mut self.answers
1717 }
1718
1719 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1720 &mut self.authorities
1721 }
1722
1723 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1724 &mut self.additional
1725 }
1726
1727 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
1728 self.answers
1729 .into_iter()
1730 .chain(self.authorities)
1731 .chain(self.additional)
1732 }
1733
1734 pub fn num_additionals(&self) -> u16 {
1735 self.num_additionals
1736 }
1737
1738 pub fn num_authorities(&self) -> u16 {
1739 self.num_authorities
1740 }
1741
1742 pub fn num_questions(&self) -> u16 {
1743 self.num_questions
1744 }
1745
1746 pub const fn is_query(&self) -> bool {
1747 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1748 }
1749
1750 pub const fn is_response(&self) -> bool {
1751 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1752 }
1753
1754 fn read_header(&mut self) -> Result<()> {
1755 if self.data.len() < MSG_HEADER_LEN {
1756 return Err(Error::Msg(format!(
1757 "DNS incoming: header is too short: {} bytes",
1758 self.data.len()
1759 )));
1760 }
1761
1762 let data = &self.data[0..];
1763 self.id = u16_from_be_slice(&data[..2]);
1764 self.flags = u16_from_be_slice(&data[2..4]);
1765 self.num_questions = u16_from_be_slice(&data[4..6]);
1766 self.num_answers = u16_from_be_slice(&data[6..8]);
1767 self.num_authorities = u16_from_be_slice(&data[8..10]);
1768 self.num_additionals = u16_from_be_slice(&data[10..12]);
1769
1770 self.offset = MSG_HEADER_LEN;
1771
1772 trace!(
1773 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
1774 self.id,
1775 self.num_questions,
1776 self.num_answers,
1777 self.num_authorities,
1778 self.num_additionals
1779 );
1780 Ok(())
1781 }
1782
1783 fn read_questions(&mut self) -> Result<()> {
1784 trace!("read_questions: {}", &self.num_questions);
1785 for i in 0..self.num_questions {
1786 let name = self.read_name()?;
1787
1788 let data = &self.data[self.offset..];
1789 if data.len() < 4 {
1790 return Err(Error::Msg(format!(
1791 "DNS incoming: question idx {} too short: {}",
1792 i,
1793 data.len()
1794 )));
1795 }
1796 let ty = u16_from_be_slice(&data[..2]);
1797 let class = u16_from_be_slice(&data[2..4]);
1798 self.offset += 4;
1799
1800 let Some(rr_type) = RRType::from_u16(ty) else {
1801 return Err(Error::Msg(format!(
1802 "DNS incoming: question idx {} qtype unknown: {}",
1803 i, ty
1804 )));
1805 };
1806
1807 self.questions.push(DnsQuestion {
1808 entry: DnsEntry::new(name, rr_type, class),
1809 });
1810 }
1811 Ok(())
1812 }
1813
1814 fn read_answers(&mut self) -> Result<()> {
1815 self.answers = self.read_rr_records(self.num_answers)?;
1816 Ok(())
1817 }
1818
1819 fn read_authorities(&mut self) -> Result<()> {
1820 self.authorities = self.read_rr_records(self.num_authorities)?;
1821 Ok(())
1822 }
1823
1824 fn read_additional(&mut self) -> Result<()> {
1825 self.additional = self.read_rr_records(self.num_additionals)?;
1826 Ok(())
1827 }
1828
1829 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
1831 trace!("read_rr_records: {}", count);
1832 let mut rr_records = Vec::new();
1833
1834 const RR_HEADER_REMAIN: usize = 10;
1860
1861 for _ in 0..count {
1862 let name = self.read_name()?;
1863 let slice = &self.data[self.offset..];
1864
1865 if slice.len() < RR_HEADER_REMAIN {
1866 return Err(Error::Msg(format!(
1867 "read_others: RR '{}' is too short after name: {} bytes",
1868 &name,
1869 slice.len()
1870 )));
1871 }
1872
1873 let ty = u16_from_be_slice(&slice[..2]);
1874 let class = u16_from_be_slice(&slice[2..4]);
1875 let mut ttl = u32_from_be_slice(&slice[4..8]);
1876 if ttl == 0 && self.is_response() {
1877 ttl = 1;
1884 }
1885 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
1886 self.offset += RR_HEADER_REMAIN;
1887 let next_offset = self.offset + rdata_len;
1888
1889 if next_offset > self.data.len() {
1891 return Err(Error::Msg(format!(
1892 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
1893 self.data.len() - self.offset
1894 )));
1895 }
1896
1897 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
1899 None => None,
1900
1901 Some(rr_type) => match rr_type {
1902 RRType::CNAME | RRType::PTR => Some(Box::new(DnsPointer::new(
1903 &name,
1904 rr_type,
1905 class,
1906 ttl,
1907 self.read_name()?,
1908 ))),
1909 RRType::TXT => Some(Box::new(DnsTxt::new(
1910 &name,
1911 class,
1912 ttl,
1913 self.read_vec(rdata_len),
1914 ))),
1915 RRType::SRV => Some(Box::new(DnsSrv::new(
1916 &name,
1917 class,
1918 ttl,
1919 self.read_u16()?,
1920 self.read_u16()?,
1921 self.read_u16()?,
1922 self.read_name()?,
1923 ))),
1924 RRType::HINFO => Some(Box::new(DnsHostInfo::new(
1925 &name,
1926 rr_type,
1927 class,
1928 ttl,
1929 self.read_char_string(),
1930 self.read_char_string(),
1931 ))),
1932 RRType::A => Some(Box::new(DnsAddress::new(
1933 &name,
1934 rr_type,
1935 class,
1936 ttl,
1937 self.read_ipv4().into(),
1938 ))),
1939 RRType::AAAA => Some(Box::new(DnsAddress::new(
1940 &name,
1941 rr_type,
1942 class,
1943 ttl,
1944 self.read_ipv6().into(),
1945 ))),
1946 RRType::NSEC => Some(Box::new(DnsNSec::new(
1947 &name,
1948 class,
1949 ttl,
1950 self.read_name()?,
1951 self.read_type_bitmap()?,
1952 ))),
1953 _ => None,
1954 },
1955 };
1956
1957 if let Some(record) = rec {
1958 trace!("read_rr_records: {:?}", &record);
1959 rr_records.push(record);
1960 } else {
1961 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
1962 self.offset += rdata_len;
1963 }
1964
1965 if self.offset != next_offset {
1967 return Err(Error::Msg(format!(
1968 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
1969 ty, self.offset, next_offset,
1970 )));
1971 }
1972 }
1973
1974 Ok(rr_records)
1975 }
1976
1977 fn read_char_string(&mut self) -> String {
1978 let length = self.data[self.offset];
1979 self.offset += 1;
1980 self.read_string(length as usize)
1981 }
1982
1983 fn read_u16(&mut self) -> Result<u16> {
1984 let slice = &self.data[self.offset..];
1985 if slice.len() < U16_SIZE {
1986 return Err(Error::Msg(format!(
1987 "read_u16: slice len is only {}",
1988 slice.len()
1989 )));
1990 }
1991 let num = u16_from_be_slice(&slice[..U16_SIZE]);
1992 self.offset += U16_SIZE;
1993 Ok(num)
1994 }
1995
1996 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
1998 if self.data.len() < self.offset + 2 {
2007 return Err(Error::Msg(format!(
2008 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2009 self.data.len(),
2010 self.offset
2011 )));
2012 }
2013
2014 let block_num = self.data[self.offset];
2015 self.offset += 1;
2016 if block_num != 0 {
2017 return Err(Error::Msg(format!(
2018 "NSEC block number is not 0: {}",
2019 block_num
2020 )));
2021 }
2022
2023 let block_len = self.data[self.offset] as usize;
2024 if !(1..=32).contains(&block_len) {
2025 return Err(Error::Msg(format!(
2026 "NSEC block length must be in the range 1-32: {}",
2027 block_len
2028 )));
2029 }
2030 self.offset += 1;
2031
2032 let end = self.offset + block_len;
2033 if end > self.data.len() {
2034 return Err(Error::Msg(format!(
2035 "NSEC block overflow: {} over RData len {}",
2036 end,
2037 self.data.len()
2038 )));
2039 }
2040 let bitmap = self.data[self.offset..end].to_vec();
2041 self.offset += block_len;
2042
2043 Ok(bitmap)
2044 }
2045
2046 fn read_vec(&mut self, length: usize) -> Vec<u8> {
2047 let v = self.data[self.offset..self.offset + length].to_vec();
2048 self.offset += length;
2049 v
2050 }
2051
2052 fn read_ipv4(&mut self) -> Ipv4Addr {
2053 let bytes: [u8; 4] = (&self.data)[self.offset..self.offset + 4]
2054 .try_into()
2055 .unwrap();
2056 self.offset += bytes.len();
2057 Ipv4Addr::from(bytes)
2058 }
2059
2060 fn read_ipv6(&mut self) -> Ipv6Addr {
2061 let bytes: [u8; 16] = (&self.data)[self.offset..self.offset + 16]
2062 .try_into()
2063 .unwrap();
2064 self.offset += bytes.len();
2065 Ipv6Addr::from(bytes)
2066 }
2067
2068 fn read_string(&mut self, length: usize) -> String {
2069 let s = str::from_utf8(&self.data[self.offset..self.offset + length]).unwrap();
2070 self.offset += length;
2071 s.to_string()
2072 }
2073
2074 fn read_name(&mut self) -> Result<String> {
2079 let data = &self.data[..];
2080 let start_offset = self.offset;
2081 let mut offset = start_offset;
2082 let mut name = "".to_string();
2083 let mut at_end = false;
2084
2085 loop {
2096 if offset >= data.len() {
2097 return Err(Error::Msg(format!(
2098 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2099 offset,
2100 data.len(),
2101 self
2102 )));
2103 }
2104 let length = data[offset];
2105
2106 if length == 0 {
2110 if !at_end {
2111 self.offset = offset + 1;
2112 }
2113 break; }
2115
2116 match length & 0xC0 {
2118 0x00 => {
2119 offset += 1;
2121 let ending = offset + length as usize;
2122
2123 if ending > data.len() {
2125 return Err(Error::Msg(format!(
2126 "read_name: ending {} exceeds data length {}",
2127 ending,
2128 data.len()
2129 )));
2130 }
2131
2132 name += str::from_utf8(&data[offset..ending])
2133 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {}", e)))?;
2134 name += ".";
2135 offset += length as usize;
2136 }
2137 0xC0 => {
2138 let slice = &data[offset..];
2141 if slice.len() < U16_SIZE {
2142 return Err(Error::Msg(format!(
2143 "read_name: u16 slice len is only {}",
2144 slice.len()
2145 )));
2146 }
2147 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2148 if pointer >= start_offset {
2149 return Err(Error::Msg(format!(
2151 "Invalid name compression: pointer {} must be less than the start offset {}",
2152 &pointer, &start_offset
2153 )));
2154 }
2155
2156 if !at_end {
2158 self.offset = offset + U16_SIZE;
2159 at_end = true;
2160 }
2161 offset = pointer;
2162 }
2163 _ => {
2164 return Err(Error::Msg(format!(
2165 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2166 length,
2167 offset,
2168 &data[..offset]
2169 )));
2170 }
2171 };
2172 }
2173
2174 Ok(name)
2175 }
2176}
2177
2178fn current_time_millis() -> u64 {
2180 SystemTime::now()
2181 .duration_since(SystemTime::UNIX_EPOCH)
2182 .expect("failed to get current UNIX time")
2183 .as_millis() as u64
2184}
2185
2186const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2187 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2188 u16::from_be_bytes(u8_array)
2189}
2190
2191const fn u32_from_be_slice(s: &[u8]) -> u32 {
2192 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2193 u32::from_be_bytes(u8_array)
2194}
2195
2196const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2199 created + (ttl * percent * 10) as u64
2202}
2203
2204#[derive(Clone, Debug, PartialEq, Eq)]
2206#[non_exhaustive]
2207pub enum Error {
2208 Again,
2210
2211 Msg(String),
2213
2214 ParseIpAddr(String),
2216}
2217
2218impl fmt::Display for Error {
2219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2220 match self {
2221 Self::Msg(s) => write!(f, "{}", s),
2222 Self::ParseIpAddr(s) => write!(f, "parsing of ip addr failed, reason: {}", s),
2223 Self::Again => write!(f, "try again"),
2224 }
2225 }
2226}
2227
2228impl std::error::Error for Error {}
2229
2230pub type Result<T> = core::result::Result<T, Error>;