1#[cfg(feature = "logging")]
8use crate::log::trace;
9
10use crate::error::{e_fmt, Error, Result};
11
12use if_addrs::Interface;
13
14use std::{
15 any::Any,
16 cmp,
17 collections::HashMap,
18 convert::TryInto,
19 fmt,
20 net::{IpAddr, Ipv4Addr, Ipv6Addr},
21 str,
22 time::SystemTime,
23};
24
25#[derive(Clone, Debug, Eq, Hash, PartialEq, Default)]
27pub struct InterfaceId {
28 pub name: String,
30
31 pub index: u32,
33}
34
35impl fmt::Display for InterfaceId {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "{}('{}')", self.index, self.name)
38 }
39}
40
41impl From<&Interface> for InterfaceId {
42 fn from(interface: &Interface) -> Self {
43 InterfaceId {
44 name: interface.name.clone(),
45 index: interface.index.unwrap_or_default(),
46 }
47 }
48}
49
50#[derive(Debug, Clone, Eq, PartialEq, Hash)]
55pub struct ScopedIpV4 {
56 addr: Ipv4Addr,
57}
58
59impl ScopedIpV4 {
60 pub const fn addr(&self) -> &Ipv4Addr {
62 &self.addr
63 }
64}
65
66#[derive(Debug, Clone, Eq, PartialEq, Hash)]
68pub struct ScopedIpV6 {
69 addr: Ipv6Addr,
70 scope_id: InterfaceId,
71}
72
73impl ScopedIpV6 {
74 pub const fn addr(&self) -> &Ipv6Addr {
76 &self.addr
77 }
78
79 pub const fn scope_id(&self) -> &InterfaceId {
81 &self.scope_id
82 }
83}
84
85#[derive(Debug, Clone, Eq, PartialEq, Hash)]
87#[non_exhaustive]
88pub enum ScopedIp {
89 V4(ScopedIpV4),
90 V6(ScopedIpV6),
91}
92
93impl ScopedIp {
94 pub const fn to_ip_addr(&self) -> IpAddr {
95 match self {
96 ScopedIp::V4(v4) => IpAddr::V4(v4.addr),
97 ScopedIp::V6(v6) => IpAddr::V6(v6.addr),
98 }
99 }
100
101 pub const fn is_ipv4(&self) -> bool {
102 matches!(self, ScopedIp::V4(_))
103 }
104
105 pub const fn is_ipv6(&self) -> bool {
106 matches!(self, ScopedIp::V6(_))
107 }
108}
109
110impl From<IpAddr> for ScopedIp {
111 fn from(ip: IpAddr) -> Self {
112 match ip {
113 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 { addr: v4 }),
114 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
115 addr: v6,
116 scope_id: InterfaceId::default(),
117 }),
118 }
119 }
120}
121
122impl From<&Interface> for ScopedIp {
123 fn from(interface: &Interface) -> Self {
124 match interface.ip() {
125 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 { addr: v4 }),
126 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
127 addr: v6,
128 scope_id: InterfaceId::from(interface),
129 }),
130 }
131 }
132}
133
134impl fmt::Display for ScopedIp {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 match self {
137 ScopedIp::V4(v4) => write!(f, "{}", v4.addr),
138 ScopedIp::V6(v6) => {
139 if v6.scope_id.index != 0 {
140 #[cfg(windows)]
141 {
142 write!(f, "{}%{}", v6.addr, v6.scope_id.index)
143 }
144 #[cfg(not(windows))]
145 {
146 write!(f, "{}%{}", v6.addr, v6.scope_id.name)
147 }
148 } else {
149 write!(f, "{}", v6.addr)
150 }
151 }
152 }
153 }
154}
155
156#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
160#[non_exhaustive]
161#[repr(u16)]
162pub enum RRType {
163 A = 1,
165
166 CNAME = 5,
168
169 PTR = 12,
171
172 HINFO = 13,
174
175 TXT = 16,
177
178 AAAA = 28,
180
181 SRV = 33,
183
184 NSEC = 47,
186
187 ANY = 255,
189}
190
191impl RRType {
192 pub const fn from_u16(value: u16) -> Option<RRType> {
194 match value {
195 1 => Some(RRType::A),
196 5 => Some(RRType::CNAME),
197 12 => Some(RRType::PTR),
198 13 => Some(RRType::HINFO),
199 16 => Some(RRType::TXT),
200 28 => Some(RRType::AAAA),
201 33 => Some(RRType::SRV),
202 47 => Some(RRType::NSEC),
203 255 => Some(RRType::ANY),
204 _ => None,
205 }
206 }
207}
208
209impl fmt::Display for RRType {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 match self {
212 RRType::A => write!(f, "TYPE_A"),
213 RRType::CNAME => write!(f, "TYPE_CNAME"),
214 RRType::PTR => write!(f, "TYPE_PTR"),
215 RRType::HINFO => write!(f, "TYPE_HINFO"),
216 RRType::TXT => write!(f, "TYPE_TXT"),
217 RRType::AAAA => write!(f, "TYPE_AAAA"),
218 RRType::SRV => write!(f, "TYPE_SRV"),
219 RRType::NSEC => write!(f, "TYPE_NSEC"),
220 RRType::ANY => write!(f, "TYPE_ANY"),
221 }
222 }
223}
224
225pub const CLASS_IN: u16 = 1;
227pub const CLASS_MASK: u16 = 0x7FFF;
228
229pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
231
232pub const MAX_MSG_ABSOLUTE: usize = 8972;
237
238const MSG_HEADER_LEN: usize = 12;
239
240pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
252
253pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
255
256pub const FLAGS_AA: u16 = 0x0400;
258
259pub const FLAGS_TC: u16 = 0x0200;
270
271pub type DnsRecordBox = Box<dyn DnsRecordExt>;
273
274impl Clone for DnsRecordBox {
275 fn clone(&self) -> Self {
276 self.clone_box()
277 }
278}
279
280const U16_SIZE: usize = 2;
281
282#[inline]
284pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
285 match address {
286 IpAddr::V4(_) => RRType::A,
287 IpAddr::V6(_) => RRType::AAAA,
288 }
289}
290
291#[derive(Eq, PartialEq, Debug, Clone)]
292pub struct DnsEntry {
293 pub(crate) name: String, pub(crate) ty: RRType,
295 class: u16,
296 cache_flush: bool,
297}
298
299impl DnsEntry {
300 const fn new(name: String, ty: RRType, class: u16) -> Self {
301 Self {
302 name,
303 ty,
304 class: class & CLASS_MASK,
305 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
306 }
307 }
308}
309
310pub trait DnsEntryExt: fmt::Debug {
312 fn entry_name(&self) -> &str;
313
314 fn entry_type(&self) -> RRType;
315}
316
317#[derive(Debug)]
319pub struct DnsQuestion {
320 pub(crate) entry: DnsEntry,
321}
322
323impl DnsEntryExt for DnsQuestion {
324 fn entry_name(&self) -> &str {
325 &self.entry.name
326 }
327
328 fn entry_type(&self) -> RRType {
329 self.entry.ty
330 }
331}
332
333#[derive(Debug, Clone)]
337pub struct DnsRecord {
338 pub(crate) entry: DnsEntry,
339 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
349}
350
351impl DnsRecord {
352 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
353 let created = current_time_millis();
354
355 let refresh = get_expiration_time(created, ttl, 80);
359
360 let expires = get_expiration_time(created, ttl, 100);
361
362 Self {
363 entry: DnsEntry::new(name.to_string(), ty, class),
364 ttl,
365 created,
366 expires,
367 refresh,
368 new_name: None,
369 }
370 }
371
372 pub const fn get_ttl(&self) -> u32 {
373 self.ttl
374 }
375
376 pub const fn get_expire_time(&self) -> u64 {
377 self.expires
378 }
379
380 pub const fn get_refresh_time(&self) -> u64 {
381 self.refresh
382 }
383
384 pub const fn is_expired(&self, now: u64) -> bool {
385 now >= self.expires
386 }
387
388 pub const fn expires_soon(&self, now: u64) -> bool {
392 now + 1000 >= self.expires
393 }
394
395 pub const fn refresh_due(&self, now: u64) -> bool {
396 now >= self.refresh
397 }
398
399 pub fn halflife_passed(&self, now: u64) -> bool {
401 let halflife = get_expiration_time(self.created, self.ttl, 50);
402 now > halflife
403 }
404
405 pub fn is_unique(&self) -> bool {
406 self.entry.cache_flush
407 }
408
409 pub fn refresh_no_more(&mut self) {
412 self.refresh = get_expiration_time(self.created, self.ttl, 100);
413 }
414
415 pub fn refresh_maybe(&mut self, now: u64) -> bool {
417 if self.is_expired(now) || !self.refresh_due(now) {
418 return false;
419 }
420
421 trace!(
422 "{} qtype {} is due to refresh",
423 &self.entry.name,
424 self.entry.ty
425 );
426
427 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
434 self.refresh = get_expiration_time(self.created, self.ttl, 85);
435 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
436 self.refresh = get_expiration_time(self.created, self.ttl, 90);
437 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
438 self.refresh = get_expiration_time(self.created, self.ttl, 95);
439 } else {
440 self.refresh_no_more();
441 }
442
443 true
444 }
445
446 fn get_remaining_ttl(&self, now: u64) -> u32 {
448 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
449 cmp::max(0, remaining_millis / 1000) as u32
450 }
451
452 pub const fn get_created(&self) -> u64 {
454 self.created
455 }
456
457 fn set_expire(&mut self, expire_at: u64) {
459 self.expires = expire_at;
460 }
461
462 fn reset_ttl(&mut self, other: &Self) {
463 self.ttl = other.ttl;
464 self.created = other.created;
465 self.expires = get_expiration_time(self.created, self.ttl, 100);
466 self.refresh = if self.ttl > 1 {
467 get_expiration_time(self.created, self.ttl, 80)
468 } else {
469 self.expires
472 };
473 }
474
475 pub fn update_ttl(&mut self, now: u64) {
477 if now > self.created {
478 let elapsed = now - self.created;
479 self.ttl -= (elapsed / 1000) as u32;
480 }
481 }
482
483 pub fn set_new_name(&mut self, new_name: String) {
484 if new_name == self.entry.name {
485 self.new_name = None;
486 } else {
487 self.new_name = Some(new_name);
488 }
489 }
490
491 pub fn get_new_name(&self) -> Option<&str> {
492 self.new_name.as_deref()
493 }
494
495 pub(crate) fn get_name(&self) -> &str {
497 self.new_name.as_deref().unwrap_or(&self.entry.name)
498 }
499
500 pub fn get_original_name(&self) -> &str {
501 &self.entry.name
502 }
503}
504
505impl PartialEq for DnsRecord {
506 fn eq(&self, other: &Self) -> bool {
507 self.entry == other.entry
508 }
509}
510
511pub trait DnsRecordExt: fmt::Debug {
513 fn get_record(&self) -> &DnsRecord;
514 fn get_record_mut(&mut self) -> &mut DnsRecord;
515 fn write(&self, packet: &mut DnsOutPacket);
516 fn any(&self) -> &dyn Any;
517
518 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
520
521 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
523
524 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
527
528 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
530 match self.get_class().cmp(&other.get_class()) {
544 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
545 cmp::Ordering::Equal => self.compare_rdata(other),
546 not_equal => not_equal,
547 },
548 not_equal => not_equal,
549 }
550 }
551
552 fn rdata_print(&self) -> String;
554
555 fn get_class(&self) -> u16 {
557 self.get_record().entry.class
558 }
559
560 fn get_cache_flush(&self) -> bool {
561 self.get_record().entry.cache_flush
562 }
563
564 fn get_name(&self) -> &str {
566 self.get_record().get_name()
567 }
568
569 fn get_type(&self) -> RRType {
570 self.get_record().entry.ty
571 }
572
573 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
576 self.get_record_mut().reset_ttl(other.get_record());
577 }
578
579 fn get_created(&self) -> u64 {
580 self.get_record().get_created()
581 }
582
583 fn get_expire(&self) -> u64 {
584 self.get_record().get_expire_time()
585 }
586
587 fn set_expire(&mut self, expire_at: u64) {
588 self.get_record_mut().set_expire(expire_at);
589 }
590
591 fn set_expire_sooner(&mut self, expire_at: u64) {
593 if expire_at < self.get_expire() {
594 self.get_record_mut().set_expire(expire_at);
595 }
596 }
597
598 fn expires_soon(&self, now: u64) -> bool {
600 self.get_record().expires_soon(now)
601 }
602
603 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
606 if self.get_record_mut().refresh_maybe(now) {
607 Some(self.get_record().get_refresh_time())
608 } else {
609 None
610 }
611 }
612
613 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
616 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
617 }
618
619 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
621 for answer in msg.answers.iter() {
622 if self.suppressed_by_answer(answer.as_ref()) {
623 return true;
624 }
625 }
626 false
627 }
628
629 fn clone_box(&self) -> DnsRecordBox;
630
631 fn boxed(self) -> DnsRecordBox;
632}
633
634#[derive(Debug, Clone)]
636pub(crate) struct DnsAddress {
637 pub(crate) record: DnsRecord,
638 address: IpAddr,
639 pub(crate) interface_id: InterfaceId,
640}
641
642impl DnsAddress {
643 pub fn new(
644 name: &str,
645 ty: RRType,
646 class: u16,
647 ttl: u32,
648 address: IpAddr,
649 interface_id: InterfaceId,
650 ) -> Self {
651 let record = DnsRecord::new(name, ty, class, ttl);
652 Self {
653 record,
654 address,
655 interface_id,
656 }
657 }
658
659 pub fn address(&self) -> ScopedIp {
660 match self.address {
661 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 { addr: v4 }),
662 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
663 addr: v6,
664 scope_id: self.interface_id.clone(),
665 }),
666 }
667 }
668}
669
670impl DnsRecordExt for DnsAddress {
671 fn get_record(&self) -> &DnsRecord {
672 &self.record
673 }
674
675 fn get_record_mut(&mut self) -> &mut DnsRecord {
676 &mut self.record
677 }
678
679 fn write(&self, packet: &mut DnsOutPacket) {
680 match self.address {
681 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
682 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
683 };
684 }
685
686 fn any(&self) -> &dyn Any {
687 self
688 }
689
690 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
691 if let Some(other_a) = other.any().downcast_ref::<Self>() {
692 return self.address == other_a.address
693 && self.record.entry == other_a.record.entry
694 && self.interface_id == other_a.interface_id;
695 }
696 false
697 }
698
699 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
700 if let Some(other_a) = other.any().downcast_ref::<Self>() {
701 return self.address == other_a.address;
702 }
703 false
704 }
705
706 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
707 if let Some(other_a) = other.any().downcast_ref::<Self>() {
708 self.address.cmp(&other_a.address)
709 } else {
710 cmp::Ordering::Greater
711 }
712 }
713
714 fn rdata_print(&self) -> String {
715 format!("{}", self.address)
716 }
717
718 fn clone_box(&self) -> DnsRecordBox {
719 Box::new(self.clone())
720 }
721
722 fn boxed(self) -> DnsRecordBox {
723 Box::new(self)
724 }
725}
726
727#[derive(Debug, Clone)]
729pub struct DnsPointer {
730 record: DnsRecord,
731 alias: String, }
733
734impl DnsPointer {
735 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
736 let record = DnsRecord::new(name, ty, class, ttl);
737 Self { record, alias }
738 }
739
740 pub fn alias(&self) -> &str {
741 &self.alias
742 }
743}
744
745impl DnsRecordExt for DnsPointer {
746 fn get_record(&self) -> &DnsRecord {
747 &self.record
748 }
749
750 fn get_record_mut(&mut self) -> &mut DnsRecord {
751 &mut self.record
752 }
753
754 fn write(&self, packet: &mut DnsOutPacket) {
755 packet.write_name(&self.alias);
756 }
757
758 fn any(&self) -> &dyn Any {
759 self
760 }
761
762 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
763 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
764 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
765 }
766 false
767 }
768
769 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
770 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
771 return self.alias == other_ptr.alias;
772 }
773 false
774 }
775
776 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
777 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
778 self.alias.cmp(&other_ptr.alias)
779 } else {
780 cmp::Ordering::Greater
781 }
782 }
783
784 fn rdata_print(&self) -> String {
785 self.alias.clone()
786 }
787
788 fn clone_box(&self) -> DnsRecordBox {
789 Box::new(self.clone())
790 }
791
792 fn boxed(self) -> DnsRecordBox {
793 Box::new(self)
794 }
795}
796
797#[derive(Debug, Clone)]
799pub struct DnsSrv {
800 pub(crate) record: DnsRecord,
801 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
804 port: u16,
805}
806
807impl DnsSrv {
808 pub fn new(
809 name: &str,
810 class: u16,
811 ttl: u32,
812 priority: u16,
813 weight: u16,
814 port: u16,
815 host: String,
816 ) -> Self {
817 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
818 Self {
819 record,
820 priority,
821 weight,
822 host,
823 port,
824 }
825 }
826
827 pub fn host(&self) -> &str {
828 &self.host
829 }
830
831 pub fn port(&self) -> u16 {
832 self.port
833 }
834
835 pub fn set_host(&mut self, host: String) {
836 self.host = host;
837 }
838}
839
840impl DnsRecordExt for DnsSrv {
841 fn get_record(&self) -> &DnsRecord {
842 &self.record
843 }
844
845 fn get_record_mut(&mut self) -> &mut DnsRecord {
846 &mut self.record
847 }
848
849 fn write(&self, packet: &mut DnsOutPacket) {
850 packet.write_short(self.priority);
851 packet.write_short(self.weight);
852 packet.write_short(self.port);
853 packet.write_name(&self.host);
854 }
855
856 fn any(&self) -> &dyn Any {
857 self
858 }
859
860 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
861 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
862 return self.host == other_svc.host
863 && self.port == other_svc.port
864 && self.weight == other_svc.weight
865 && self.priority == other_svc.priority
866 && self.record.entry == other_svc.record.entry;
867 }
868 false
869 }
870
871 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
872 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
873 return self.host == other_srv.host
874 && self.port == other_srv.port
875 && self.weight == other_srv.weight
876 && self.priority == other_srv.priority;
877 }
878 false
879 }
880
881 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
882 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
883 return cmp::Ordering::Greater;
884 };
885
886 match self
888 .priority
889 .to_be_bytes()
890 .cmp(&other_srv.priority.to_be_bytes())
891 {
892 cmp::Ordering::Equal => {
893 match self
895 .weight
896 .to_be_bytes()
897 .cmp(&other_srv.weight.to_be_bytes())
898 {
899 cmp::Ordering::Equal => {
900 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
902 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
903 not_equal => not_equal,
904 }
905 }
906 not_equal => not_equal,
907 }
908 }
909 not_equal => not_equal,
910 }
911 }
912
913 fn rdata_print(&self) -> String {
914 format!(
915 "priority: {}, weight: {}, port: {}, host: {}",
916 self.priority, self.weight, self.port, self.host
917 )
918 }
919
920 fn clone_box(&self) -> DnsRecordBox {
921 Box::new(self.clone())
922 }
923
924 fn boxed(self) -> DnsRecordBox {
925 Box::new(self)
926 }
927}
928
929#[derive(Clone)]
944pub struct DnsTxt {
945 pub(crate) record: DnsRecord,
946 text: Vec<u8>,
947}
948
949impl DnsTxt {
950 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
951 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
952 Self { record, text }
953 }
954
955 pub fn text(&self) -> &[u8] {
956 &self.text
957 }
958}
959
960impl DnsRecordExt for DnsTxt {
961 fn get_record(&self) -> &DnsRecord {
962 &self.record
963 }
964
965 fn get_record_mut(&mut self) -> &mut DnsRecord {
966 &mut self.record
967 }
968
969 fn write(&self, packet: &mut DnsOutPacket) {
970 packet.write_bytes(&self.text);
971 }
972
973 fn any(&self) -> &dyn Any {
974 self
975 }
976
977 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
978 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
979 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
980 }
981 false
982 }
983
984 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
985 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
986 return self.text == other_txt.text;
987 }
988 false
989 }
990
991 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
992 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
993 self.text.cmp(&other_txt.text)
994 } else {
995 cmp::Ordering::Greater
996 }
997 }
998
999 fn rdata_print(&self) -> String {
1000 format!("{:?}", decode_txt(&self.text))
1001 }
1002
1003 fn clone_box(&self) -> DnsRecordBox {
1004 Box::new(self.clone())
1005 }
1006
1007 fn boxed(self) -> DnsRecordBox {
1008 Box::new(self)
1009 }
1010}
1011
1012impl fmt::Debug for DnsTxt {
1013 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1014 let properties = decode_txt(&self.text);
1015 write!(
1016 f,
1017 "DnsTxt {{ record: {:?}, text: {:?} }}",
1018 self.record, properties
1019 )
1020 }
1021}
1022
1023fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
1025 let mut properties = Vec::new();
1026 let mut offset = 0;
1027 while offset < txt.len() {
1028 let length = txt[offset] as usize;
1029 if length == 0 {
1030 break; }
1032 offset += 1; let offset_end = offset + length;
1035 if offset_end > txt.len() {
1036 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
1037 break; }
1039 let kv_bytes = &txt[offset..offset_end];
1040
1041 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
1043 || (kv_bytes.to_vec(), None),
1044 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
1045 );
1046
1047 match String::from_utf8(k) {
1049 Ok(k_string) => {
1050 properties.push(TxtProperty {
1051 key: k_string,
1052 val: v,
1053 });
1054 }
1055 Err(e) => trace!("ERROR: convert to String from key: {}", e),
1056 }
1057
1058 offset += length;
1059 }
1060
1061 properties
1062}
1063
1064#[derive(Clone, PartialEq, Eq)]
1066pub struct TxtProperty {
1067 key: String,
1069
1070 val: Option<Vec<u8>>,
1074}
1075
1076impl TxtProperty {
1077 pub fn val_str(&self) -> &str {
1079 self.val
1080 .as_ref()
1081 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
1082 }
1083}
1084
1085impl<K, V> From<&(K, V)> for TxtProperty
1087where
1088 K: ToString,
1089 V: ToString,
1090{
1091 fn from(prop: &(K, V)) -> Self {
1092 Self {
1093 key: prop.0.to_string(),
1094 val: Some(prop.1.to_string().into_bytes()),
1095 }
1096 }
1097}
1098
1099impl<K, V> From<(K, V)> for TxtProperty
1100where
1101 K: ToString,
1102 V: AsRef<[u8]>,
1103{
1104 fn from(prop: (K, V)) -> Self {
1105 Self {
1106 key: prop.0.to_string(),
1107 val: Some(prop.1.as_ref().into()),
1108 }
1109 }
1110}
1111
1112impl From<&str> for TxtProperty {
1114 fn from(key: &str) -> Self {
1115 Self {
1116 key: key.to_string(),
1117 val: None,
1118 }
1119 }
1120}
1121
1122impl fmt::Display for TxtProperty {
1123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1124 write!(f, "{}={}", self.key, self.val_str())
1125 }
1126}
1127
1128impl fmt::Debug for TxtProperty {
1132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1133 let val_string = self.val.as_ref().map_or_else(
1134 || "None".to_string(),
1135 |v| {
1136 std::str::from_utf8(&v[..]).map_or_else(
1137 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1138 |s| format!("Some(\"{s}\")"),
1139 )
1140 },
1141 );
1142
1143 write!(
1144 f,
1145 "TxtProperty {{key: \"{}\", val: {}}}",
1146 &self.key, &val_string,
1147 )
1148 }
1149}
1150
1151const HEX_TABLE: [char; 16] = [
1152 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1153];
1154
1155fn u8_slice_to_hex(slice: &[u8]) -> String {
1159 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1160 hex.push_str("0x");
1161 for b in slice {
1162 hex.push(HEX_TABLE[(b >> 4) as usize]);
1163 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1164 }
1165 hex
1166}
1167
1168#[derive(Debug, Clone)]
1170struct DnsHostInfo {
1171 record: DnsRecord,
1172 cpu: String,
1173 os: String,
1174}
1175
1176impl DnsHostInfo {
1177 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1178 let record = DnsRecord::new(name, ty, class, ttl);
1179 Self { record, cpu, os }
1180 }
1181}
1182
1183impl DnsRecordExt for DnsHostInfo {
1184 fn get_record(&self) -> &DnsRecord {
1185 &self.record
1186 }
1187
1188 fn get_record_mut(&mut self) -> &mut DnsRecord {
1189 &mut self.record
1190 }
1191
1192 fn write(&self, packet: &mut DnsOutPacket) {
1193 println!("writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1194 packet.write_bytes(self.cpu.as_bytes());
1195 packet.write_bytes(self.os.as_bytes());
1196 }
1197
1198 fn any(&self) -> &dyn Any {
1199 self
1200 }
1201
1202 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1203 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1204 return self.cpu == other_hinfo.cpu
1205 && self.os == other_hinfo.os
1206 && self.record.entry == other_hinfo.record.entry;
1207 }
1208 false
1209 }
1210
1211 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1212 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1213 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1214 }
1215 false
1216 }
1217
1218 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1219 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1220 match self.cpu.cmp(&other_hinfo.cpu) {
1221 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1222 ordering => ordering,
1223 }
1224 } else {
1225 cmp::Ordering::Greater
1226 }
1227 }
1228
1229 fn rdata_print(&self) -> String {
1230 format!("cpu: {}, os: {}", self.cpu, self.os)
1231 }
1232
1233 fn clone_box(&self) -> DnsRecordBox {
1234 Box::new(self.clone())
1235 }
1236
1237 fn boxed(self) -> DnsRecordBox {
1238 Box::new(self)
1239 }
1240}
1241
1242#[derive(Debug, Clone)]
1248pub struct DnsNSec {
1249 record: DnsRecord,
1250 next_domain: String,
1251 type_bitmap: Vec<u8>,
1252}
1253
1254impl DnsNSec {
1255 pub fn new(
1256 name: &str,
1257 class: u16,
1258 ttl: u32,
1259 next_domain: String,
1260 type_bitmap: Vec<u8>,
1261 ) -> Self {
1262 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1263 Self {
1264 record,
1265 next_domain,
1266 type_bitmap,
1267 }
1268 }
1269
1270 pub fn _types(&self) -> Vec<u16> {
1272 let mut bit_num = 0;
1281 let mut results = Vec::new();
1282
1283 for byte in self.type_bitmap.iter() {
1284 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1288 if (byte & bit_mask) != 0 {
1289 results.push(bit_num);
1290 }
1291 bit_num += 1;
1292 bit_mask >>= 1; }
1294 }
1295 results
1296 }
1297}
1298
1299impl DnsRecordExt for DnsNSec {
1300 fn get_record(&self) -> &DnsRecord {
1301 &self.record
1302 }
1303
1304 fn get_record_mut(&mut self) -> &mut DnsRecord {
1305 &mut self.record
1306 }
1307
1308 fn write(&self, packet: &mut DnsOutPacket) {
1309 packet.write_bytes(self.next_domain.as_bytes());
1310 packet.write_bytes(&self.type_bitmap);
1311 }
1312
1313 fn any(&self) -> &dyn Any {
1314 self
1315 }
1316
1317 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1318 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1319 return self.next_domain == other_record.next_domain
1320 && self.type_bitmap == other_record.type_bitmap
1321 && self.record.entry == other_record.record.entry;
1322 }
1323 false
1324 }
1325
1326 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1327 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1328 return self.next_domain == other_record.next_domain
1329 && self.type_bitmap == other_record.type_bitmap;
1330 }
1331 false
1332 }
1333
1334 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1335 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1336 match self.next_domain.cmp(&other_nsec.next_domain) {
1337 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1338 ordering => ordering,
1339 }
1340 } else {
1341 cmp::Ordering::Greater
1342 }
1343 }
1344
1345 fn rdata_print(&self) -> String {
1346 format!(
1347 "next_domain: {}, type_bitmap len: {}",
1348 self.next_domain,
1349 self.type_bitmap.len()
1350 )
1351 }
1352
1353 fn clone_box(&self) -> DnsRecordBox {
1354 Box::new(self.clone())
1355 }
1356
1357 fn boxed(self) -> DnsRecordBox {
1358 Box::new(self)
1359 }
1360}
1361
1362#[derive(PartialEq)]
1363enum PacketState {
1364 Init = 0,
1365 Finished = 1,
1366}
1367
1368pub struct DnsOutPacket {
1370 data: Vec<Vec<u8>>,
1372
1373 size: usize,
1375
1376 state: PacketState,
1378
1379 names: HashMap<String, u16>,
1381}
1382
1383impl DnsOutPacket {
1384 fn new() -> Self {
1385 Self {
1386 data: Vec::new(),
1387 size: MSG_HEADER_LEN, state: PacketState::Init,
1389 names: HashMap::new(),
1390 }
1391 }
1392
1393 pub fn size(&self) -> usize {
1394 self.size
1395 }
1396
1397 pub fn to_bytes(&self) -> Vec<u8> {
1398 self.data.concat()
1399 }
1400
1401 fn write_question(&mut self, question: &DnsQuestion) {
1402 self.write_name(&question.entry.name);
1403 self.write_short(question.entry.ty as u16);
1404 self.write_short(question.entry.class);
1405 }
1406
1407 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> bool {
1411 let start_data_length = self.data.len();
1412 let start_size = self.size;
1413
1414 let record = record_ext.get_record();
1415 self.write_name(record.get_name());
1416 self.write_short(record.entry.ty as u16);
1417 if record.entry.cache_flush {
1418 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1420 } else {
1421 self.write_short(record.entry.class);
1422 }
1423
1424 if now == 0 {
1425 self.write_u32(record.ttl);
1426 } else {
1427 self.write_u32(record.get_remaining_ttl(now));
1428 }
1429
1430 let index = self.data.len();
1431
1432 self.size += 2;
1434 record_ext.write(self);
1435 self.size -= 2;
1436
1437 let length: usize = self.data[index..].iter().map(|x| x.len()).sum();
1438 self.insert_short(index, length as u16);
1439
1440 if self.size > MAX_MSG_ABSOLUTE {
1441 self.data.truncate(start_data_length);
1442 self.size = start_size;
1443 self.state = PacketState::Finished;
1444 return false;
1445 }
1446
1447 true
1448 }
1449
1450 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1451 self.data.insert(index, value.to_be_bytes().to_vec());
1452 self.size += 2;
1453 }
1454
1455 fn write_name(&mut self, name: &str) {
1477 let end = name.len();
1479 let end = if end > 0 && &name[end - 1..] == "." {
1480 end - 1
1481 } else {
1482 end
1483 };
1484
1485 let mut here = 0;
1486 while here < end {
1487 const POINTER_MASK: u16 = 0xC000;
1488 let remaining = &name[here..end];
1489
1490 match self.names.get(remaining) {
1492 Some(offset) => {
1493 let pointer = *offset | POINTER_MASK;
1494 self.write_short(pointer);
1495 break;
1502 }
1503 None => {
1504 self.names.insert(remaining.to_string(), self.size as u16);
1506 let stop = remaining.find('.').map_or(end, |i| here + i);
1510 let label = &name[here..stop];
1511 self.write_utf8(label);
1512
1513 here = stop + 1; }
1515 }
1516
1517 if here >= end {
1518 self.write_byte(0); }
1520 }
1521 }
1522
1523 fn write_utf8(&mut self, utf: &str) {
1524 assert!(utf.len() < 64);
1525 self.write_byte(utf.len() as u8);
1526 self.write_bytes(utf.as_bytes());
1527 }
1528
1529 fn write_bytes(&mut self, s: &[u8]) {
1530 self.data.push(s.to_vec());
1531 self.size += s.len();
1532 }
1533
1534 fn write_u32(&mut self, int: u32) {
1535 self.data.push(int.to_be_bytes().to_vec());
1536 self.size += 4;
1537 }
1538
1539 fn write_short(&mut self, short: u16) {
1540 self.data.push(short.to_be_bytes().to_vec());
1541 self.size += 2;
1542 }
1543
1544 fn write_byte(&mut self, byte: u8) {
1545 self.data.push(vec![byte]);
1546 self.size += 1;
1547 }
1548
1549 fn write_header(
1572 &mut self,
1573 id: u16,
1574 flags: u16,
1575 q_count: u16,
1576 a_count: u16,
1577 auth_count: u16,
1578 addi_count: u16,
1579 ) {
1580 self.insert_short(0, addi_count);
1581 self.insert_short(0, auth_count);
1582 self.insert_short(0, a_count);
1583 self.insert_short(0, q_count);
1584 self.insert_short(0, flags);
1585 self.insert_short(0, id);
1586
1587 self.size -= MSG_HEADER_LEN;
1589
1590 self.state = PacketState::Finished;
1591 }
1592}
1593
1594pub struct DnsOutgoing {
1596 flags: u16,
1597 id: u16,
1598 multicast: bool,
1599 questions: Vec<DnsQuestion>,
1600 answers: Vec<(DnsRecordBox, u64)>,
1601 authorities: Vec<DnsRecordBox>,
1602 additionals: Vec<DnsRecordBox>,
1603 known_answer_count: i64, }
1605
1606impl DnsOutgoing {
1607 pub fn new(flags: u16) -> Self {
1608 Self {
1609 flags,
1610 id: 0,
1611 multicast: true,
1612 questions: Vec::new(),
1613 answers: Vec::new(),
1614 authorities: Vec::new(),
1615 additionals: Vec::new(),
1616 known_answer_count: 0,
1617 }
1618 }
1619
1620 pub fn questions(&self) -> &[DnsQuestion] {
1621 &self.questions
1622 }
1623
1624 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1626 &self.answers
1627 }
1628
1629 pub fn answers_count(&self) -> usize {
1630 self.answers.len()
1631 }
1632
1633 pub fn authorities(&self) -> &[DnsRecordBox] {
1634 &self.authorities
1635 }
1636
1637 pub fn additionals(&self) -> &[DnsRecordBox] {
1638 &self.additionals
1639 }
1640
1641 pub fn known_answer_count(&self) -> i64 {
1642 self.known_answer_count
1643 }
1644
1645 pub fn set_id(&mut self, id: u16) {
1646 self.id = id;
1647 }
1648
1649 pub const fn is_query(&self) -> bool {
1650 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1651 }
1652
1653 const fn is_response(&self) -> bool {
1654 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1655 }
1656
1657 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1691 trace!("add_additional_answer: {:?}", &answer);
1692 self.additionals.push(answer.boxed());
1693 }
1694
1695 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1697 self.answers.push((answer_box, 0));
1698 }
1699
1700 pub fn add_authority(&mut self, record: DnsRecordBox) {
1701 self.authorities.push(record);
1702 }
1703
1704 pub fn add_answer(
1707 &mut self,
1708 msg: &DnsIncoming,
1709 answer: impl DnsRecordExt + Send + 'static,
1710 ) -> bool {
1711 trace!("Check for add_answer");
1712 if answer.suppressed_by(msg) {
1713 trace!("my answer is suppressed by incoming msg");
1714 self.known_answer_count += 1;
1715 return false;
1716 }
1717
1718 self.add_answer_at_time(answer, 0)
1719 }
1720
1721 pub fn add_answer_at_time(
1725 &mut self,
1726 answer: impl DnsRecordExt + Send + 'static,
1727 now: u64,
1728 ) -> bool {
1729 if now == 0 || !answer.get_record().is_expired(now) {
1730 trace!("add_answer push: {:?}", &answer);
1731 self.answers.push((answer.boxed(), now));
1732 return true;
1733 }
1734 false
1735 }
1736
1737 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1738 let q = DnsQuestion {
1739 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1740 };
1741 self.questions.push(q);
1742 }
1743
1744 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
1746 let packet_list = self.to_packets();
1747 packet_list.iter().map(|p| p.data.concat()).collect()
1748 }
1749
1750 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
1752 let mut packet_list = Vec::new();
1753 let mut packet = DnsOutPacket::new();
1754
1755 let mut question_count = self.questions.len() as u16;
1756 let mut answer_count = 0;
1757 let mut auth_count = 0;
1758 let mut addi_count = 0;
1759 let id = if self.multicast { 0 } else { self.id };
1760
1761 for question in self.questions.iter() {
1762 packet.write_question(question);
1763 }
1764
1765 for (answer, time) in self.answers.iter() {
1766 if packet.write_record(answer.as_ref(), *time) {
1767 answer_count += 1;
1768 }
1769 }
1770
1771 for auth in self.authorities.iter() {
1772 auth_count += u16::from(packet.write_record(auth.as_ref(), 0));
1773 }
1774
1775 for addi in self.additionals.iter() {
1776 if packet.write_record(addi.as_ref(), 0) {
1777 addi_count += 1;
1778 continue;
1779 }
1780
1781 if self.is_response() {
1783 break;
1784 }
1785
1786 packet.write_header(
1791 id,
1792 self.flags | FLAGS_TC,
1793 question_count,
1794 answer_count,
1795 auth_count,
1796 addi_count,
1797 );
1798
1799 packet_list.push(packet);
1800
1801 packet = DnsOutPacket::new();
1803 packet.write_record(addi.as_ref(), 0);
1804
1805 question_count = 0;
1806 answer_count = 0;
1807 auth_count = 0;
1808 addi_count = 1;
1809 }
1810
1811 packet.write_header(
1812 id,
1813 self.flags,
1814 question_count,
1815 answer_count,
1816 auth_count,
1817 addi_count,
1818 );
1819
1820 packet_list.push(packet);
1821 packet_list
1822 }
1823}
1824
1825#[derive(Debug)]
1827pub struct DnsIncoming {
1828 offset: usize,
1829 data: Vec<u8>,
1830 questions: Vec<DnsQuestion>,
1831 answers: Vec<DnsRecordBox>,
1832 authorities: Vec<DnsRecordBox>,
1833 additional: Vec<DnsRecordBox>,
1834 id: u16,
1835 flags: u16,
1836 num_questions: u16,
1837 num_answers: u16,
1838 num_authorities: u16,
1839 num_additionals: u16,
1840 interface_id: InterfaceId,
1841}
1842
1843impl DnsIncoming {
1844 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
1845 let mut incoming = Self {
1846 offset: 0,
1847 data,
1848 questions: Vec::new(),
1849 answers: Vec::new(),
1850 authorities: Vec::new(),
1851 additional: Vec::new(),
1852 id: 0,
1853 flags: 0,
1854 num_questions: 0,
1855 num_answers: 0,
1856 num_authorities: 0,
1857 num_additionals: 0,
1858 interface_id,
1859 };
1860
1861 incoming.read_header()?;
1881 incoming.read_questions()?;
1882 incoming.read_answers()?;
1883 incoming.read_authorities()?;
1884 incoming.read_additional()?;
1885
1886 Ok(incoming)
1887 }
1888
1889 pub fn id(&self) -> u16 {
1890 self.id
1891 }
1892
1893 pub fn questions(&self) -> &[DnsQuestion] {
1894 &self.questions
1895 }
1896
1897 pub fn answers(&self) -> &[DnsRecordBox] {
1898 &self.answers
1899 }
1900
1901 pub fn authorities(&self) -> &[DnsRecordBox] {
1902 &self.authorities
1903 }
1904
1905 pub fn additionals(&self) -> &[DnsRecordBox] {
1906 &self.additional
1907 }
1908
1909 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1910 &mut self.answers
1911 }
1912
1913 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1914 &mut self.authorities
1915 }
1916
1917 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1918 &mut self.additional
1919 }
1920
1921 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
1922 self.answers
1923 .into_iter()
1924 .chain(self.authorities)
1925 .chain(self.additional)
1926 }
1927
1928 pub fn num_additionals(&self) -> u16 {
1929 self.num_additionals
1930 }
1931
1932 pub fn num_authorities(&self) -> u16 {
1933 self.num_authorities
1934 }
1935
1936 pub fn num_questions(&self) -> u16 {
1937 self.num_questions
1938 }
1939
1940 pub const fn is_query(&self) -> bool {
1941 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1942 }
1943
1944 pub const fn is_response(&self) -> bool {
1945 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1946 }
1947
1948 fn read_header(&mut self) -> Result<()> {
1949 if self.data.len() < MSG_HEADER_LEN {
1950 return Err(e_fmt!(
1951 "DNS incoming: header is too short: {} bytes",
1952 self.data.len()
1953 ));
1954 }
1955
1956 let data = &self.data[0..];
1957 self.id = u16_from_be_slice(&data[..2]);
1958 self.flags = u16_from_be_slice(&data[2..4]);
1959 self.num_questions = u16_from_be_slice(&data[4..6]);
1960 self.num_answers = u16_from_be_slice(&data[6..8]);
1961 self.num_authorities = u16_from_be_slice(&data[8..10]);
1962 self.num_additionals = u16_from_be_slice(&data[10..12]);
1963
1964 self.offset = MSG_HEADER_LEN;
1965
1966 trace!(
1967 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
1968 self.id,
1969 self.num_questions,
1970 self.num_answers,
1971 self.num_authorities,
1972 self.num_additionals
1973 );
1974 Ok(())
1975 }
1976
1977 fn read_questions(&mut self) -> Result<()> {
1978 trace!("read_questions: {}", &self.num_questions);
1979 for i in 0..self.num_questions {
1980 let name = self.read_name()?;
1981
1982 let data = &self.data[self.offset..];
1983 if data.len() < 4 {
1984 return Err(Error::Msg(format!(
1985 "DNS incoming: question idx {} too short: {}",
1986 i,
1987 data.len()
1988 )));
1989 }
1990 let ty = u16_from_be_slice(&data[..2]);
1991 let class = u16_from_be_slice(&data[2..4]);
1992 self.offset += 4;
1993
1994 let Some(rr_type) = RRType::from_u16(ty) else {
1995 return Err(Error::Msg(format!(
1996 "DNS incoming: question idx {i} qtype unknown: {ty}",
1997 )));
1998 };
1999
2000 self.questions.push(DnsQuestion {
2001 entry: DnsEntry::new(name, rr_type, class),
2002 });
2003 }
2004 Ok(())
2005 }
2006
2007 fn read_answers(&mut self) -> Result<()> {
2008 self.answers = self.read_rr_records(self.num_answers)?;
2009 Ok(())
2010 }
2011
2012 fn read_authorities(&mut self) -> Result<()> {
2013 self.authorities = self.read_rr_records(self.num_authorities)?;
2014 Ok(())
2015 }
2016
2017 fn read_additional(&mut self) -> Result<()> {
2018 self.additional = self.read_rr_records(self.num_additionals)?;
2019 Ok(())
2020 }
2021
2022 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2024 trace!("read_rr_records: {}", count);
2025 let mut rr_records = Vec::new();
2026
2027 const RR_HEADER_REMAIN: usize = 10;
2053
2054 for _ in 0..count {
2055 let name = self.read_name()?;
2056 let slice = &self.data[self.offset..];
2057
2058 if slice.len() < RR_HEADER_REMAIN {
2059 return Err(Error::Msg(format!(
2060 "read_others: RR '{}' is too short after name: {} bytes",
2061 &name,
2062 slice.len()
2063 )));
2064 }
2065
2066 let ty = u16_from_be_slice(&slice[..2]);
2067 let class = u16_from_be_slice(&slice[2..4]);
2068 let mut ttl = u32_from_be_slice(&slice[4..8]);
2069 if ttl == 0 && self.is_response() {
2070 ttl = 1;
2077 }
2078 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2079 self.offset += RR_HEADER_REMAIN;
2080 let next_offset = self.offset + rdata_len;
2081
2082 if next_offset > self.data.len() {
2084 return Err(Error::Msg(format!(
2085 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2086 self.data.len() - self.offset
2087 )));
2088 }
2089
2090 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2092 None => None,
2093
2094 Some(rr_type) => match rr_type {
2095 RRType::CNAME | RRType::PTR => {
2096 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
2097 }
2098 RRType::TXT => {
2099 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
2100 }
2101 RRType::SRV => Some(
2102 DnsSrv::new(
2103 &name,
2104 class,
2105 ttl,
2106 self.read_u16()?,
2107 self.read_u16()?,
2108 self.read_u16()?,
2109 self.read_name()?,
2110 )
2111 .boxed(),
2112 ),
2113 RRType::HINFO => Some(
2114 DnsHostInfo::new(
2115 &name,
2116 rr_type,
2117 class,
2118 ttl,
2119 self.read_char_string()?,
2120 self.read_char_string()?,
2121 )
2122 .boxed(),
2123 ),
2124 RRType::A => Some(
2125 DnsAddress::new(
2126 &name,
2127 rr_type,
2128 class,
2129 ttl,
2130 self.read_ipv4()?.into(),
2131 self.interface_id.clone(),
2132 )
2133 .boxed(),
2134 ),
2135 RRType::AAAA => Some(
2136 DnsAddress::new(
2137 &name,
2138 rr_type,
2139 class,
2140 ttl,
2141 self.read_ipv6()?.into(),
2142 self.interface_id.clone(),
2143 )
2144 .boxed(),
2145 ),
2146 RRType::NSEC => Some(
2147 DnsNSec::new(
2148 &name,
2149 class,
2150 ttl,
2151 self.read_name()?,
2152 self.read_type_bitmap()?,
2153 )
2154 .boxed(),
2155 ),
2156 _ => None,
2157 },
2158 };
2159
2160 if let Some(record) = rec {
2161 trace!("read_rr_records: {:?}", &record);
2162 rr_records.push(record);
2163 } else {
2164 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2165 self.offset += rdata_len;
2166 }
2167
2168 if self.offset != next_offset {
2170 return Err(Error::Msg(format!(
2171 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2172 ty, self.offset, next_offset,
2173 )));
2174 }
2175 }
2176
2177 Ok(rr_records)
2178 }
2179
2180 fn read_char_string(&mut self) -> Result<String> {
2181 let length = self.data[self.offset];
2182 self.offset += 1;
2183 self.read_string(length as usize)
2184 }
2185
2186 fn read_u16(&mut self) -> Result<u16> {
2187 let slice = &self.data[self.offset..];
2188 if slice.len() < U16_SIZE {
2189 return Err(Error::Msg(format!(
2190 "read_u16: slice len is only {}",
2191 slice.len()
2192 )));
2193 }
2194 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2195 self.offset += U16_SIZE;
2196 Ok(num)
2197 }
2198
2199 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2201 if self.data.len() < self.offset + 2 {
2210 return Err(Error::Msg(format!(
2211 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2212 self.data.len(),
2213 self.offset
2214 )));
2215 }
2216
2217 let block_num = self.data[self.offset];
2218 self.offset += 1;
2219 if block_num != 0 {
2220 return Err(Error::Msg(format!(
2221 "NSEC block number is not 0: {block_num}"
2222 )));
2223 }
2224
2225 let block_len = self.data[self.offset] as usize;
2226 if !(1..=32).contains(&block_len) {
2227 return Err(Error::Msg(format!(
2228 "NSEC block length must be in the range 1-32: {block_len}"
2229 )));
2230 }
2231 self.offset += 1;
2232
2233 let end = self.offset + block_len;
2234 if end > self.data.len() {
2235 return Err(Error::Msg(format!(
2236 "NSEC block overflow: {} over RData len {}",
2237 end,
2238 self.data.len()
2239 )));
2240 }
2241 let bitmap = self.data[self.offset..end].to_vec();
2242 self.offset += block_len;
2243
2244 Ok(bitmap)
2245 }
2246
2247 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2248 if self.data.len() < self.offset + length {
2249 return Err(e_fmt!(
2250 "DNS Incoming: not enough data to read a chunk of data"
2251 ));
2252 }
2253
2254 let v = self.data[self.offset..self.offset + length].to_vec();
2255 self.offset += length;
2256 Ok(v)
2257 }
2258
2259 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2260 if self.data.len() < self.offset + 4 {
2261 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2262 }
2263
2264 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2265 .try_into()
2266 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2267 self.offset += bytes.len();
2268 Ok(Ipv4Addr::from(bytes))
2269 }
2270
2271 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2272 if self.data.len() < self.offset + 16 {
2273 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2274 }
2275
2276 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2277 .try_into()
2278 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2279 self.offset += bytes.len();
2280 Ok(Ipv6Addr::from(bytes))
2281 }
2282
2283 fn read_string(&mut self, length: usize) -> Result<String> {
2284 if self.data.len() < self.offset + length {
2285 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2286 }
2287
2288 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2289 .map_err(|e| Error::Msg(e.to_string()))?;
2290 self.offset += length;
2291 Ok(s.to_string())
2292 }
2293
2294 fn read_name(&mut self) -> Result<String> {
2299 let data = &self.data[..];
2300 let start_offset = self.offset;
2301 let mut offset = start_offset;
2302 let mut name = "".to_string();
2303 let mut at_end = false;
2304
2305 loop {
2316 if offset >= data.len() {
2317 return Err(Error::Msg(format!(
2318 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2319 offset,
2320 data.len(),
2321 self
2322 )));
2323 }
2324 let length = data[offset];
2325
2326 if length == 0 {
2330 if !at_end {
2331 self.offset = offset + 1;
2332 }
2333 break; }
2335
2336 match length & 0xC0 {
2338 0x00 => {
2339 offset += 1;
2341 let ending = offset + length as usize;
2342
2343 if ending > data.len() {
2345 return Err(Error::Msg(format!(
2346 "read_name: ending {} exceeds data length {}",
2347 ending,
2348 data.len()
2349 )));
2350 }
2351
2352 name += str::from_utf8(&data[offset..ending])
2353 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {e}")))?;
2354 name += ".";
2355 offset += length as usize;
2356 }
2357 0xC0 => {
2358 let slice = &data[offset..];
2361 if slice.len() < U16_SIZE {
2362 return Err(Error::Msg(format!(
2363 "read_name: u16 slice len is only {}",
2364 slice.len()
2365 )));
2366 }
2367 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2368 if pointer >= start_offset {
2369 return Err(Error::Msg(format!(
2371 "Invalid name compression: pointer {} must be less than the start offset {}",
2372 &pointer, &start_offset
2373 )));
2374 }
2375
2376 if !at_end {
2378 self.offset = offset + U16_SIZE;
2379 at_end = true;
2380 }
2381 offset = pointer;
2382 }
2383 _ => {
2384 return Err(Error::Msg(format!(
2385 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2386 length,
2387 offset,
2388 &data[..offset]
2389 )));
2390 }
2391 };
2392 }
2393
2394 Ok(name)
2395 }
2396}
2397
2398fn current_time_millis() -> u64 {
2400 SystemTime::now()
2401 .duration_since(SystemTime::UNIX_EPOCH)
2402 .expect("failed to get current UNIX time")
2403 .as_millis() as u64
2404}
2405
2406const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2407 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2408 u16::from_be_bytes(u8_array)
2409}
2410
2411const fn u32_from_be_slice(s: &[u8]) -> u32 {
2412 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2413 u32::from_be_bytes(u8_array)
2414}
2415
2416const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2419 created + (ttl * percent * 10) as u64
2422}