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)]
27pub struct InterfaceId {
28 name: String,
29 index: u32,
30}
31
32impl InterfaceId {
33 pub fn index(&self) -> u32 {
34 self.index
35 }
36}
37
38impl fmt::Display for InterfaceId {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 write!(f, "{}: {}", self.index, self.name)
41 }
42}
43
44impl From<&Interface> for InterfaceId {
45 fn from(interface: &Interface) -> Self {
46 InterfaceId {
47 name: interface.name.clone(),
48 index: interface.index.unwrap_or_default(),
49 }
50 }
51}
52
53#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
57#[non_exhaustive]
58#[repr(u16)]
59pub enum RRType {
60 A = 1,
62
63 CNAME = 5,
65
66 PTR = 12,
68
69 HINFO = 13,
71
72 TXT = 16,
74
75 AAAA = 28,
77
78 SRV = 33,
80
81 NSEC = 47,
83
84 ANY = 255,
86}
87
88impl RRType {
89 pub const fn from_u16(value: u16) -> Option<RRType> {
91 match value {
92 1 => Some(RRType::A),
93 5 => Some(RRType::CNAME),
94 12 => Some(RRType::PTR),
95 13 => Some(RRType::HINFO),
96 16 => Some(RRType::TXT),
97 28 => Some(RRType::AAAA),
98 33 => Some(RRType::SRV),
99 47 => Some(RRType::NSEC),
100 255 => Some(RRType::ANY),
101 _ => None,
102 }
103 }
104}
105
106impl fmt::Display for RRType {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match self {
109 RRType::A => write!(f, "TYPE_A"),
110 RRType::CNAME => write!(f, "TYPE_CNAME"),
111 RRType::PTR => write!(f, "TYPE_PTR"),
112 RRType::HINFO => write!(f, "TYPE_HINFO"),
113 RRType::TXT => write!(f, "TYPE_TXT"),
114 RRType::AAAA => write!(f, "TYPE_AAAA"),
115 RRType::SRV => write!(f, "TYPE_SRV"),
116 RRType::NSEC => write!(f, "TYPE_NSEC"),
117 RRType::ANY => write!(f, "TYPE_ANY"),
118 }
119 }
120}
121
122pub const CLASS_IN: u16 = 1;
124pub const CLASS_MASK: u16 = 0x7FFF;
125
126pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
128
129pub const MAX_MSG_ABSOLUTE: usize = 8972;
134
135const MSG_HEADER_LEN: usize = 12;
136
137pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
149
150pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
152
153pub const FLAGS_AA: u16 = 0x0400;
155
156pub const FLAGS_TC: u16 = 0x0200;
167
168pub type DnsRecordBox = Box<dyn DnsRecordExt>;
170
171impl Clone for DnsRecordBox {
172 fn clone(&self) -> Self {
173 self.clone_box()
174 }
175}
176
177const U16_SIZE: usize = 2;
178
179#[inline]
181pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
182 match address {
183 IpAddr::V4(_) => RRType::A,
184 IpAddr::V6(_) => RRType::AAAA,
185 }
186}
187
188#[derive(Eq, PartialEq, Debug, Clone)]
189pub struct DnsEntry {
190 pub(crate) name: String, pub(crate) ty: RRType,
192 class: u16,
193 cache_flush: bool,
194}
195
196impl DnsEntry {
197 const fn new(name: String, ty: RRType, class: u16) -> Self {
198 Self {
199 name,
200 ty,
201 class: class & CLASS_MASK,
202 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
203 }
204 }
205}
206
207pub trait DnsEntryExt: fmt::Debug {
209 fn entry_name(&self) -> &str;
210
211 fn entry_type(&self) -> RRType;
212}
213
214#[derive(Debug)]
216pub struct DnsQuestion {
217 pub(crate) entry: DnsEntry,
218}
219
220impl DnsEntryExt for DnsQuestion {
221 fn entry_name(&self) -> &str {
222 &self.entry.name
223 }
224
225 fn entry_type(&self) -> RRType {
226 self.entry.ty
227 }
228}
229
230#[derive(Debug, Clone)]
234pub struct DnsRecord {
235 pub(crate) entry: DnsEntry,
236 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
246}
247
248impl DnsRecord {
249 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
250 let created = current_time_millis();
251
252 let refresh = get_expiration_time(created, ttl, 80);
256
257 let expires = get_expiration_time(created, ttl, 100);
258
259 Self {
260 entry: DnsEntry::new(name.to_string(), ty, class),
261 ttl,
262 created,
263 expires,
264 refresh,
265 new_name: None,
266 }
267 }
268
269 pub const fn get_ttl(&self) -> u32 {
270 self.ttl
271 }
272
273 pub const fn get_expire_time(&self) -> u64 {
274 self.expires
275 }
276
277 pub const fn get_refresh_time(&self) -> u64 {
278 self.refresh
279 }
280
281 pub const fn is_expired(&self, now: u64) -> bool {
282 now >= self.expires
283 }
284
285 pub const fn expires_soon(&self, now: u64) -> bool {
289 now + 1000 >= self.expires
290 }
291
292 pub const fn refresh_due(&self, now: u64) -> bool {
293 now >= self.refresh
294 }
295
296 pub fn halflife_passed(&self, now: u64) -> bool {
298 let halflife = get_expiration_time(self.created, self.ttl, 50);
299 now > halflife
300 }
301
302 pub fn is_unique(&self) -> bool {
303 self.entry.cache_flush
304 }
305
306 pub fn refresh_no_more(&mut self) {
309 self.refresh = get_expiration_time(self.created, self.ttl, 100);
310 }
311
312 pub fn refresh_maybe(&mut self, now: u64) -> bool {
314 if self.is_expired(now) || !self.refresh_due(now) {
315 return false;
316 }
317
318 trace!(
319 "{} qtype {} is due to refresh",
320 &self.entry.name,
321 self.entry.ty
322 );
323
324 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
331 self.refresh = get_expiration_time(self.created, self.ttl, 85);
332 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
333 self.refresh = get_expiration_time(self.created, self.ttl, 90);
334 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
335 self.refresh = get_expiration_time(self.created, self.ttl, 95);
336 } else {
337 self.refresh_no_more();
338 }
339
340 true
341 }
342
343 fn get_remaining_ttl(&self, now: u64) -> u32 {
345 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
346 cmp::max(0, remaining_millis / 1000) as u32
347 }
348
349 pub const fn get_created(&self) -> u64 {
351 self.created
352 }
353
354 fn set_expire(&mut self, expire_at: u64) {
356 self.expires = expire_at;
357 }
358
359 fn reset_ttl(&mut self, other: &Self) {
360 self.ttl = other.ttl;
361 self.created = other.created;
362 self.expires = get_expiration_time(self.created, self.ttl, 100);
363 self.refresh = if self.ttl > 1 {
364 get_expiration_time(self.created, self.ttl, 80)
365 } else {
366 self.expires
369 };
370 }
371
372 pub fn update_ttl(&mut self, now: u64) {
374 if now > self.created {
375 let elapsed = now - self.created;
376 self.ttl -= (elapsed / 1000) as u32;
377 }
378 }
379
380 pub fn set_new_name(&mut self, new_name: String) {
381 if new_name == self.entry.name {
382 self.new_name = None;
383 } else {
384 self.new_name = Some(new_name);
385 }
386 }
387
388 pub fn get_new_name(&self) -> Option<&str> {
389 self.new_name.as_deref()
390 }
391
392 pub(crate) fn get_name(&self) -> &str {
394 self.new_name.as_deref().unwrap_or(&self.entry.name)
395 }
396
397 pub fn get_original_name(&self) -> &str {
398 &self.entry.name
399 }
400}
401
402impl PartialEq for DnsRecord {
403 fn eq(&self, other: &Self) -> bool {
404 self.entry == other.entry
405 }
406}
407
408pub trait DnsRecordExt: fmt::Debug {
410 fn get_record(&self) -> &DnsRecord;
411 fn get_record_mut(&mut self) -> &mut DnsRecord;
412 fn write(&self, packet: &mut DnsOutPacket);
413 fn any(&self) -> &dyn Any;
414
415 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
417
418 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
420
421 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
424
425 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
427 match self.get_class().cmp(&other.get_class()) {
441 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
442 cmp::Ordering::Equal => self.compare_rdata(other),
443 not_equal => not_equal,
444 },
445 not_equal => not_equal,
446 }
447 }
448
449 fn rdata_print(&self) -> String;
451
452 fn get_class(&self) -> u16 {
454 self.get_record().entry.class
455 }
456
457 fn get_cache_flush(&self) -> bool {
458 self.get_record().entry.cache_flush
459 }
460
461 fn get_name(&self) -> &str {
463 self.get_record().get_name()
464 }
465
466 fn get_type(&self) -> RRType {
467 self.get_record().entry.ty
468 }
469
470 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
473 self.get_record_mut().reset_ttl(other.get_record());
474 }
475
476 fn get_created(&self) -> u64 {
477 self.get_record().get_created()
478 }
479
480 fn get_expire(&self) -> u64 {
481 self.get_record().get_expire_time()
482 }
483
484 fn set_expire(&mut self, expire_at: u64) {
485 self.get_record_mut().set_expire(expire_at);
486 }
487
488 fn set_expire_sooner(&mut self, expire_at: u64) {
490 if expire_at < self.get_expire() {
491 self.get_record_mut().set_expire(expire_at);
492 }
493 }
494
495 fn expires_soon(&self, now: u64) -> bool {
497 self.get_record().expires_soon(now)
498 }
499
500 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
503 if self.get_record_mut().refresh_maybe(now) {
504 Some(self.get_record().get_refresh_time())
505 } else {
506 None
507 }
508 }
509
510 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
513 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
514 }
515
516 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
518 for answer in msg.answers.iter() {
519 if self.suppressed_by_answer(answer.as_ref()) {
520 return true;
521 }
522 }
523 false
524 }
525
526 fn clone_box(&self) -> DnsRecordBox;
527
528 fn boxed(self) -> DnsRecordBox;
529}
530
531#[derive(Debug, Clone)]
533pub struct DnsAddress {
534 pub(crate) record: DnsRecord,
535 address: IpAddr,
536 interface_id: InterfaceId,
537}
538
539impl DnsAddress {
540 pub fn new(
541 name: &str,
542 ty: RRType,
543 class: u16,
544 ttl: u32,
545 address: IpAddr,
546 interface_id: InterfaceId,
547 ) -> Self {
548 let record = DnsRecord::new(name, ty, class, ttl);
549 Self {
550 record,
551 address,
552 interface_id,
553 }
554 }
555
556 pub fn address(&self) -> IpAddr {
557 self.address
558 }
559}
560
561impl DnsRecordExt for DnsAddress {
562 fn get_record(&self) -> &DnsRecord {
563 &self.record
564 }
565
566 fn get_record_mut(&mut self) -> &mut DnsRecord {
567 &mut self.record
568 }
569
570 fn write(&self, packet: &mut DnsOutPacket) {
571 match self.address {
572 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
573 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
574 };
575 }
576
577 fn any(&self) -> &dyn Any {
578 self
579 }
580
581 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
582 if let Some(other_a) = other.any().downcast_ref::<Self>() {
583 return self.address == other_a.address
584 && self.record.entry == other_a.record.entry
585 && self.interface_id == other_a.interface_id;
586 }
587 false
588 }
589
590 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
591 if let Some(other_a) = other.any().downcast_ref::<Self>() {
592 return self.address == other_a.address;
593 }
594 false
595 }
596
597 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
598 if let Some(other_a) = other.any().downcast_ref::<Self>() {
599 self.address.cmp(&other_a.address)
600 } else {
601 cmp::Ordering::Greater
602 }
603 }
604
605 fn rdata_print(&self) -> String {
606 format!("{}", self.address)
607 }
608
609 fn clone_box(&self) -> DnsRecordBox {
610 Box::new(self.clone())
611 }
612
613 fn boxed(self) -> DnsRecordBox {
614 Box::new(self)
615 }
616}
617
618#[derive(Debug, Clone)]
620pub struct DnsPointer {
621 record: DnsRecord,
622 alias: String, }
624
625impl DnsPointer {
626 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
627 let record = DnsRecord::new(name, ty, class, ttl);
628 Self { record, alias }
629 }
630
631 pub fn alias(&self) -> &str {
632 &self.alias
633 }
634}
635
636impl DnsRecordExt for DnsPointer {
637 fn get_record(&self) -> &DnsRecord {
638 &self.record
639 }
640
641 fn get_record_mut(&mut self) -> &mut DnsRecord {
642 &mut self.record
643 }
644
645 fn write(&self, packet: &mut DnsOutPacket) {
646 packet.write_name(&self.alias);
647 }
648
649 fn any(&self) -> &dyn Any {
650 self
651 }
652
653 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
654 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
655 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
656 }
657 false
658 }
659
660 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
661 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
662 return self.alias == other_ptr.alias;
663 }
664 false
665 }
666
667 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
668 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
669 self.alias.cmp(&other_ptr.alias)
670 } else {
671 cmp::Ordering::Greater
672 }
673 }
674
675 fn rdata_print(&self) -> String {
676 self.alias.clone()
677 }
678
679 fn clone_box(&self) -> DnsRecordBox {
680 Box::new(self.clone())
681 }
682
683 fn boxed(self) -> DnsRecordBox {
684 Box::new(self)
685 }
686}
687
688#[derive(Debug, Clone)]
690pub struct DnsSrv {
691 pub(crate) record: DnsRecord,
692 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
695 port: u16,
696}
697
698impl DnsSrv {
699 pub fn new(
700 name: &str,
701 class: u16,
702 ttl: u32,
703 priority: u16,
704 weight: u16,
705 port: u16,
706 host: String,
707 ) -> Self {
708 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
709 Self {
710 record,
711 priority,
712 weight,
713 host,
714 port,
715 }
716 }
717
718 pub fn host(&self) -> &str {
719 &self.host
720 }
721
722 pub fn port(&self) -> u16 {
723 self.port
724 }
725
726 pub fn set_host(&mut self, host: String) {
727 self.host = host;
728 }
729}
730
731impl DnsRecordExt for DnsSrv {
732 fn get_record(&self) -> &DnsRecord {
733 &self.record
734 }
735
736 fn get_record_mut(&mut self) -> &mut DnsRecord {
737 &mut self.record
738 }
739
740 fn write(&self, packet: &mut DnsOutPacket) {
741 packet.write_short(self.priority);
742 packet.write_short(self.weight);
743 packet.write_short(self.port);
744 packet.write_name(&self.host);
745 }
746
747 fn any(&self) -> &dyn Any {
748 self
749 }
750
751 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
752 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
753 return self.host == other_svc.host
754 && self.port == other_svc.port
755 && self.weight == other_svc.weight
756 && self.priority == other_svc.priority
757 && self.record.entry == other_svc.record.entry;
758 }
759 false
760 }
761
762 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
763 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
764 return self.host == other_srv.host
765 && self.port == other_srv.port
766 && self.weight == other_srv.weight
767 && self.priority == other_srv.priority;
768 }
769 false
770 }
771
772 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
773 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
774 return cmp::Ordering::Greater;
775 };
776
777 match self
779 .priority
780 .to_be_bytes()
781 .cmp(&other_srv.priority.to_be_bytes())
782 {
783 cmp::Ordering::Equal => {
784 match self
786 .weight
787 .to_be_bytes()
788 .cmp(&other_srv.weight.to_be_bytes())
789 {
790 cmp::Ordering::Equal => {
791 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
793 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
794 not_equal => not_equal,
795 }
796 }
797 not_equal => not_equal,
798 }
799 }
800 not_equal => not_equal,
801 }
802 }
803
804 fn rdata_print(&self) -> String {
805 format!(
806 "priority: {}, weight: {}, port: {}, host: {}",
807 self.priority, self.weight, self.port, self.host
808 )
809 }
810
811 fn clone_box(&self) -> DnsRecordBox {
812 Box::new(self.clone())
813 }
814
815 fn boxed(self) -> DnsRecordBox {
816 Box::new(self)
817 }
818}
819
820#[derive(Clone)]
835pub struct DnsTxt {
836 pub(crate) record: DnsRecord,
837 text: Vec<u8>,
838}
839
840impl DnsTxt {
841 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
842 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
843 Self { record, text }
844 }
845
846 pub fn text(&self) -> &[u8] {
847 &self.text
848 }
849}
850
851impl DnsRecordExt for DnsTxt {
852 fn get_record(&self) -> &DnsRecord {
853 &self.record
854 }
855
856 fn get_record_mut(&mut self) -> &mut DnsRecord {
857 &mut self.record
858 }
859
860 fn write(&self, packet: &mut DnsOutPacket) {
861 packet.write_bytes(&self.text);
862 }
863
864 fn any(&self) -> &dyn Any {
865 self
866 }
867
868 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
869 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
870 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
871 }
872 false
873 }
874
875 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
876 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
877 return self.text == other_txt.text;
878 }
879 false
880 }
881
882 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
883 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
884 self.text.cmp(&other_txt.text)
885 } else {
886 cmp::Ordering::Greater
887 }
888 }
889
890 fn rdata_print(&self) -> String {
891 format!("{:?}", decode_txt(&self.text))
892 }
893
894 fn clone_box(&self) -> DnsRecordBox {
895 Box::new(self.clone())
896 }
897
898 fn boxed(self) -> DnsRecordBox {
899 Box::new(self)
900 }
901}
902
903impl fmt::Debug for DnsTxt {
904 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
905 let properties = decode_txt(&self.text);
906 write!(
907 f,
908 "DnsTxt {{ record: {:?}, text: {:?} }}",
909 self.record, properties
910 )
911 }
912}
913
914fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
916 let mut properties = Vec::new();
917 let mut offset = 0;
918 while offset < txt.len() {
919 let length = txt[offset] as usize;
920 if length == 0 {
921 break; }
923 offset += 1; let offset_end = offset + length;
926 if offset_end > txt.len() {
927 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
928 break; }
930 let kv_bytes = &txt[offset..offset_end];
931
932 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
934 || (kv_bytes.to_vec(), None),
935 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
936 );
937
938 match String::from_utf8(k) {
940 Ok(k_string) => {
941 properties.push(TxtProperty {
942 key: k_string,
943 val: v,
944 });
945 }
946 Err(e) => trace!("ERROR: convert to String from key: {}", e),
947 }
948
949 offset += length;
950 }
951
952 properties
953}
954
955#[derive(Clone, PartialEq, Eq)]
957pub struct TxtProperty {
958 key: String,
960
961 val: Option<Vec<u8>>,
965}
966
967impl TxtProperty {
968 pub fn val_str(&self) -> &str {
970 self.val
971 .as_ref()
972 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
973 }
974}
975
976impl<K, V> From<&(K, V)> for TxtProperty
978where
979 K: ToString,
980 V: ToString,
981{
982 fn from(prop: &(K, V)) -> Self {
983 Self {
984 key: prop.0.to_string(),
985 val: Some(prop.1.to_string().into_bytes()),
986 }
987 }
988}
989
990impl<K, V> From<(K, V)> for TxtProperty
991where
992 K: ToString,
993 V: AsRef<[u8]>,
994{
995 fn from(prop: (K, V)) -> Self {
996 Self {
997 key: prop.0.to_string(),
998 val: Some(prop.1.as_ref().into()),
999 }
1000 }
1001}
1002
1003impl From<&str> for TxtProperty {
1005 fn from(key: &str) -> Self {
1006 Self {
1007 key: key.to_string(),
1008 val: None,
1009 }
1010 }
1011}
1012
1013impl fmt::Display for TxtProperty {
1014 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1015 write!(f, "{}={}", self.key, self.val_str())
1016 }
1017}
1018
1019impl fmt::Debug for TxtProperty {
1023 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1024 let val_string = self.val.as_ref().map_or_else(
1025 || "None".to_string(),
1026 |v| {
1027 std::str::from_utf8(&v[..]).map_or_else(
1028 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1029 |s| format!("Some(\"{}\")", s),
1030 )
1031 },
1032 );
1033
1034 write!(
1035 f,
1036 "TxtProperty {{key: \"{}\", val: {}}}",
1037 &self.key, &val_string,
1038 )
1039 }
1040}
1041
1042const HEX_TABLE: [char; 16] = [
1043 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1044];
1045
1046fn u8_slice_to_hex(slice: &[u8]) -> String {
1050 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1051 hex.push_str("0x");
1052 for b in slice {
1053 hex.push(HEX_TABLE[(b >> 4) as usize]);
1054 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1055 }
1056 hex
1057}
1058
1059#[derive(Debug, Clone)]
1061struct DnsHostInfo {
1062 record: DnsRecord,
1063 cpu: String,
1064 os: String,
1065}
1066
1067impl DnsHostInfo {
1068 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1069 let record = DnsRecord::new(name, ty, class, ttl);
1070 Self { record, cpu, os }
1071 }
1072}
1073
1074impl DnsRecordExt for DnsHostInfo {
1075 fn get_record(&self) -> &DnsRecord {
1076 &self.record
1077 }
1078
1079 fn get_record_mut(&mut self) -> &mut DnsRecord {
1080 &mut self.record
1081 }
1082
1083 fn write(&self, packet: &mut DnsOutPacket) {
1084 println!("writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1085 packet.write_bytes(self.cpu.as_bytes());
1086 packet.write_bytes(self.os.as_bytes());
1087 }
1088
1089 fn any(&self) -> &dyn Any {
1090 self
1091 }
1092
1093 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1094 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1095 return self.cpu == other_hinfo.cpu
1096 && self.os == other_hinfo.os
1097 && self.record.entry == other_hinfo.record.entry;
1098 }
1099 false
1100 }
1101
1102 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1103 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1104 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1105 }
1106 false
1107 }
1108
1109 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1110 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1111 match self.cpu.cmp(&other_hinfo.cpu) {
1112 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1113 ordering => ordering,
1114 }
1115 } else {
1116 cmp::Ordering::Greater
1117 }
1118 }
1119
1120 fn rdata_print(&self) -> String {
1121 format!("cpu: {}, os: {}", self.cpu, self.os)
1122 }
1123
1124 fn clone_box(&self) -> DnsRecordBox {
1125 Box::new(self.clone())
1126 }
1127
1128 fn boxed(self) -> DnsRecordBox {
1129 Box::new(self)
1130 }
1131}
1132
1133#[derive(Debug, Clone)]
1139pub struct DnsNSec {
1140 record: DnsRecord,
1141 next_domain: String,
1142 type_bitmap: Vec<u8>,
1143}
1144
1145impl DnsNSec {
1146 pub fn new(
1147 name: &str,
1148 class: u16,
1149 ttl: u32,
1150 next_domain: String,
1151 type_bitmap: Vec<u8>,
1152 ) -> Self {
1153 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1154 Self {
1155 record,
1156 next_domain,
1157 type_bitmap,
1158 }
1159 }
1160
1161 pub fn _types(&self) -> Vec<u16> {
1163 let mut bit_num = 0;
1172 let mut results = Vec::new();
1173
1174 for byte in self.type_bitmap.iter() {
1175 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1179 if (byte & bit_mask) != 0 {
1180 results.push(bit_num);
1181 }
1182 bit_num += 1;
1183 bit_mask >>= 1; }
1185 }
1186 results
1187 }
1188}
1189
1190impl DnsRecordExt for DnsNSec {
1191 fn get_record(&self) -> &DnsRecord {
1192 &self.record
1193 }
1194
1195 fn get_record_mut(&mut self) -> &mut DnsRecord {
1196 &mut self.record
1197 }
1198
1199 fn write(&self, packet: &mut DnsOutPacket) {
1200 packet.write_bytes(self.next_domain.as_bytes());
1201 packet.write_bytes(&self.type_bitmap);
1202 }
1203
1204 fn any(&self) -> &dyn Any {
1205 self
1206 }
1207
1208 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1209 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1210 return self.next_domain == other_record.next_domain
1211 && self.type_bitmap == other_record.type_bitmap
1212 && self.record.entry == other_record.record.entry;
1213 }
1214 false
1215 }
1216
1217 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1218 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1219 return self.next_domain == other_record.next_domain
1220 && self.type_bitmap == other_record.type_bitmap;
1221 }
1222 false
1223 }
1224
1225 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1226 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1227 match self.next_domain.cmp(&other_nsec.next_domain) {
1228 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1229 ordering => ordering,
1230 }
1231 } else {
1232 cmp::Ordering::Greater
1233 }
1234 }
1235
1236 fn rdata_print(&self) -> String {
1237 format!(
1238 "next_domain: {}, type_bitmap len: {}",
1239 self.next_domain,
1240 self.type_bitmap.len()
1241 )
1242 }
1243
1244 fn clone_box(&self) -> DnsRecordBox {
1245 Box::new(self.clone())
1246 }
1247
1248 fn boxed(self) -> DnsRecordBox {
1249 Box::new(self)
1250 }
1251}
1252
1253#[derive(PartialEq)]
1254enum PacketState {
1255 Init = 0,
1256 Finished = 1,
1257}
1258
1259pub struct DnsOutPacket {
1261 data: Vec<Vec<u8>>,
1263
1264 size: usize,
1266
1267 state: PacketState,
1269
1270 names: HashMap<String, u16>,
1272}
1273
1274impl DnsOutPacket {
1275 fn new() -> Self {
1276 Self {
1277 data: Vec::new(),
1278 size: MSG_HEADER_LEN, state: PacketState::Init,
1280 names: HashMap::new(),
1281 }
1282 }
1283
1284 pub fn size(&self) -> usize {
1285 self.size
1286 }
1287
1288 pub fn to_bytes(&self) -> Vec<u8> {
1289 self.data.concat()
1290 }
1291
1292 fn write_question(&mut self, question: &DnsQuestion) {
1293 self.write_name(&question.entry.name);
1294 self.write_short(question.entry.ty as u16);
1295 self.write_short(question.entry.class);
1296 }
1297
1298 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> bool {
1302 let start_data_length = self.data.len();
1303 let start_size = self.size;
1304
1305 let record = record_ext.get_record();
1306 self.write_name(record.get_name());
1307 self.write_short(record.entry.ty as u16);
1308 if record.entry.cache_flush {
1309 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1311 } else {
1312 self.write_short(record.entry.class);
1313 }
1314
1315 if now == 0 {
1316 self.write_u32(record.ttl);
1317 } else {
1318 self.write_u32(record.get_remaining_ttl(now));
1319 }
1320
1321 let index = self.data.len();
1322
1323 self.size += 2;
1325 record_ext.write(self);
1326 self.size -= 2;
1327
1328 let length: usize = self.data[index..].iter().map(|x| x.len()).sum();
1329 self.insert_short(index, length as u16);
1330
1331 if self.size > MAX_MSG_ABSOLUTE {
1332 self.data.truncate(start_data_length);
1333 self.size = start_size;
1334 self.state = PacketState::Finished;
1335 return false;
1336 }
1337
1338 true
1339 }
1340
1341 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1342 self.data.insert(index, value.to_be_bytes().to_vec());
1343 self.size += 2;
1344 }
1345
1346 fn write_name(&mut self, name: &str) {
1368 let end = name.len();
1370 let end = if end > 0 && &name[end - 1..] == "." {
1371 end - 1
1372 } else {
1373 end
1374 };
1375
1376 let mut here = 0;
1377 while here < end {
1378 const POINTER_MASK: u16 = 0xC000;
1379 let remaining = &name[here..end];
1380
1381 match self.names.get(remaining) {
1383 Some(offset) => {
1384 let pointer = *offset | POINTER_MASK;
1385 self.write_short(pointer);
1386 break;
1393 }
1394 None => {
1395 self.names.insert(remaining.to_string(), self.size as u16);
1397 let stop = remaining.find('.').map_or(end, |i| here + i);
1401 let label = &name[here..stop];
1402 self.write_utf8(label);
1403
1404 here = stop + 1; }
1406 }
1407
1408 if here >= end {
1409 self.write_byte(0); }
1411 }
1412 }
1413
1414 fn write_utf8(&mut self, utf: &str) {
1415 assert!(utf.len() < 64);
1416 self.write_byte(utf.len() as u8);
1417 self.write_bytes(utf.as_bytes());
1418 }
1419
1420 fn write_bytes(&mut self, s: &[u8]) {
1421 self.data.push(s.to_vec());
1422 self.size += s.len();
1423 }
1424
1425 fn write_u32(&mut self, int: u32) {
1426 self.data.push(int.to_be_bytes().to_vec());
1427 self.size += 4;
1428 }
1429
1430 fn write_short(&mut self, short: u16) {
1431 self.data.push(short.to_be_bytes().to_vec());
1432 self.size += 2;
1433 }
1434
1435 fn write_byte(&mut self, byte: u8) {
1436 self.data.push(vec![byte]);
1437 self.size += 1;
1438 }
1439
1440 fn write_header(
1463 &mut self,
1464 id: u16,
1465 flags: u16,
1466 q_count: u16,
1467 a_count: u16,
1468 auth_count: u16,
1469 addi_count: u16,
1470 ) {
1471 self.insert_short(0, addi_count);
1472 self.insert_short(0, auth_count);
1473 self.insert_short(0, a_count);
1474 self.insert_short(0, q_count);
1475 self.insert_short(0, flags);
1476 self.insert_short(0, id);
1477
1478 self.size -= MSG_HEADER_LEN;
1480
1481 self.state = PacketState::Finished;
1482 }
1483}
1484
1485pub struct DnsOutgoing {
1487 flags: u16,
1488 id: u16,
1489 multicast: bool,
1490 questions: Vec<DnsQuestion>,
1491 answers: Vec<(DnsRecordBox, u64)>,
1492 authorities: Vec<DnsRecordBox>,
1493 additionals: Vec<DnsRecordBox>,
1494 known_answer_count: i64, }
1496
1497impl DnsOutgoing {
1498 pub fn new(flags: u16) -> Self {
1499 Self {
1500 flags,
1501 id: 0,
1502 multicast: true,
1503 questions: Vec::new(),
1504 answers: Vec::new(),
1505 authorities: Vec::new(),
1506 additionals: Vec::new(),
1507 known_answer_count: 0,
1508 }
1509 }
1510
1511 pub fn questions(&self) -> &[DnsQuestion] {
1512 &self.questions
1513 }
1514
1515 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1517 &self.answers
1518 }
1519
1520 pub fn answers_count(&self) -> usize {
1521 self.answers.len()
1522 }
1523
1524 pub fn authorities(&self) -> &[DnsRecordBox] {
1525 &self.authorities
1526 }
1527
1528 pub fn additionals(&self) -> &[DnsRecordBox] {
1529 &self.additionals
1530 }
1531
1532 pub fn known_answer_count(&self) -> i64 {
1533 self.known_answer_count
1534 }
1535
1536 pub fn set_id(&mut self, id: u16) {
1537 self.id = id;
1538 }
1539
1540 pub const fn is_query(&self) -> bool {
1541 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1542 }
1543
1544 const fn is_response(&self) -> bool {
1545 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1546 }
1547
1548 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1582 trace!("add_additional_answer: {:?}", &answer);
1583 self.additionals.push(answer.boxed());
1584 }
1585
1586 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1588 self.answers.push((answer_box, 0));
1589 }
1590
1591 pub fn add_authority(&mut self, record: DnsRecordBox) {
1592 self.authorities.push(record);
1593 }
1594
1595 pub fn add_answer(
1598 &mut self,
1599 msg: &DnsIncoming,
1600 answer: impl DnsRecordExt + Send + 'static,
1601 ) -> bool {
1602 trace!("Check for add_answer");
1603 if answer.suppressed_by(msg) {
1604 trace!("my answer is suppressed by incoming msg");
1605 self.known_answer_count += 1;
1606 return false;
1607 }
1608
1609 self.add_answer_at_time(answer, 0)
1610 }
1611
1612 pub fn add_answer_at_time(
1616 &mut self,
1617 answer: impl DnsRecordExt + Send + 'static,
1618 now: u64,
1619 ) -> bool {
1620 if now == 0 || !answer.get_record().is_expired(now) {
1621 trace!("add_answer push: {:?}", &answer);
1622 self.answers.push((answer.boxed(), now));
1623 return true;
1624 }
1625 false
1626 }
1627
1628 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1629 let q = DnsQuestion {
1630 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1631 };
1632 self.questions.push(q);
1633 }
1634
1635 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
1637 let packet_list = self.to_packets();
1638 packet_list.iter().map(|p| p.data.concat()).collect()
1639 }
1640
1641 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
1643 let mut packet_list = Vec::new();
1644 let mut packet = DnsOutPacket::new();
1645
1646 let mut question_count = self.questions.len() as u16;
1647 let mut answer_count = 0;
1648 let mut auth_count = 0;
1649 let mut addi_count = 0;
1650 let id = if self.multicast { 0 } else { self.id };
1651
1652 for question in self.questions.iter() {
1653 packet.write_question(question);
1654 }
1655
1656 for (answer, time) in self.answers.iter() {
1657 if packet.write_record(answer.as_ref(), *time) {
1658 answer_count += 1;
1659 }
1660 }
1661
1662 for auth in self.authorities.iter() {
1663 auth_count += u16::from(packet.write_record(auth.as_ref(), 0));
1664 }
1665
1666 for addi in self.additionals.iter() {
1667 if packet.write_record(addi.as_ref(), 0) {
1668 addi_count += 1;
1669 continue;
1670 }
1671
1672 if self.is_response() {
1674 break;
1675 }
1676
1677 packet.write_header(
1682 id,
1683 self.flags | FLAGS_TC,
1684 question_count,
1685 answer_count,
1686 auth_count,
1687 addi_count,
1688 );
1689
1690 packet_list.push(packet);
1691
1692 packet = DnsOutPacket::new();
1694 packet.write_record(addi.as_ref(), 0);
1695
1696 question_count = 0;
1697 answer_count = 0;
1698 auth_count = 0;
1699 addi_count = 1;
1700 }
1701
1702 packet.write_header(
1703 id,
1704 self.flags,
1705 question_count,
1706 answer_count,
1707 auth_count,
1708 addi_count,
1709 );
1710
1711 packet_list.push(packet);
1712 packet_list
1713 }
1714}
1715
1716#[derive(Debug)]
1718pub struct DnsIncoming {
1719 offset: usize,
1720 data: Vec<u8>,
1721 questions: Vec<DnsQuestion>,
1722 answers: Vec<DnsRecordBox>,
1723 authorities: Vec<DnsRecordBox>,
1724 additional: Vec<DnsRecordBox>,
1725 id: u16,
1726 flags: u16,
1727 num_questions: u16,
1728 num_answers: u16,
1729 num_authorities: u16,
1730 num_additionals: u16,
1731 interface_id: InterfaceId,
1732}
1733
1734impl DnsIncoming {
1735 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
1736 let mut incoming = Self {
1737 offset: 0,
1738 data,
1739 questions: Vec::new(),
1740 answers: Vec::new(),
1741 authorities: Vec::new(),
1742 additional: Vec::new(),
1743 id: 0,
1744 flags: 0,
1745 num_questions: 0,
1746 num_answers: 0,
1747 num_authorities: 0,
1748 num_additionals: 0,
1749 interface_id,
1750 };
1751
1752 incoming.read_header()?;
1772 incoming.read_questions()?;
1773 incoming.read_answers()?;
1774 incoming.read_authorities()?;
1775 incoming.read_additional()?;
1776
1777 Ok(incoming)
1778 }
1779
1780 pub fn id(&self) -> u16 {
1781 self.id
1782 }
1783
1784 pub fn questions(&self) -> &[DnsQuestion] {
1785 &self.questions
1786 }
1787
1788 pub fn answers(&self) -> &[DnsRecordBox] {
1789 &self.answers
1790 }
1791
1792 pub fn authorities(&self) -> &[DnsRecordBox] {
1793 &self.authorities
1794 }
1795
1796 pub fn additionals(&self) -> &[DnsRecordBox] {
1797 &self.additional
1798 }
1799
1800 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1801 &mut self.answers
1802 }
1803
1804 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1805 &mut self.authorities
1806 }
1807
1808 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
1809 &mut self.additional
1810 }
1811
1812 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
1813 self.answers
1814 .into_iter()
1815 .chain(self.authorities)
1816 .chain(self.additional)
1817 }
1818
1819 pub fn num_additionals(&self) -> u16 {
1820 self.num_additionals
1821 }
1822
1823 pub fn num_authorities(&self) -> u16 {
1824 self.num_authorities
1825 }
1826
1827 pub fn num_questions(&self) -> u16 {
1828 self.num_questions
1829 }
1830
1831 pub const fn is_query(&self) -> bool {
1832 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1833 }
1834
1835 pub const fn is_response(&self) -> bool {
1836 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1837 }
1838
1839 fn read_header(&mut self) -> Result<()> {
1840 if self.data.len() < MSG_HEADER_LEN {
1841 return Err(e_fmt!(
1842 "DNS incoming: header is too short: {} bytes",
1843 self.data.len()
1844 ));
1845 }
1846
1847 let data = &self.data[0..];
1848 self.id = u16_from_be_slice(&data[..2]);
1849 self.flags = u16_from_be_slice(&data[2..4]);
1850 self.num_questions = u16_from_be_slice(&data[4..6]);
1851 self.num_answers = u16_from_be_slice(&data[6..8]);
1852 self.num_authorities = u16_from_be_slice(&data[8..10]);
1853 self.num_additionals = u16_from_be_slice(&data[10..12]);
1854
1855 self.offset = MSG_HEADER_LEN;
1856
1857 trace!(
1858 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
1859 self.id,
1860 self.num_questions,
1861 self.num_answers,
1862 self.num_authorities,
1863 self.num_additionals
1864 );
1865 Ok(())
1866 }
1867
1868 fn read_questions(&mut self) -> Result<()> {
1869 trace!("read_questions: {}", &self.num_questions);
1870 for i in 0..self.num_questions {
1871 let name = self.read_name()?;
1872
1873 let data = &self.data[self.offset..];
1874 if data.len() < 4 {
1875 return Err(Error::Msg(format!(
1876 "DNS incoming: question idx {} too short: {}",
1877 i,
1878 data.len()
1879 )));
1880 }
1881 let ty = u16_from_be_slice(&data[..2]);
1882 let class = u16_from_be_slice(&data[2..4]);
1883 self.offset += 4;
1884
1885 let Some(rr_type) = RRType::from_u16(ty) else {
1886 return Err(Error::Msg(format!(
1887 "DNS incoming: question idx {} qtype unknown: {}",
1888 i, ty
1889 )));
1890 };
1891
1892 self.questions.push(DnsQuestion {
1893 entry: DnsEntry::new(name, rr_type, class),
1894 });
1895 }
1896 Ok(())
1897 }
1898
1899 fn read_answers(&mut self) -> Result<()> {
1900 self.answers = self.read_rr_records(self.num_answers)?;
1901 Ok(())
1902 }
1903
1904 fn read_authorities(&mut self) -> Result<()> {
1905 self.authorities = self.read_rr_records(self.num_authorities)?;
1906 Ok(())
1907 }
1908
1909 fn read_additional(&mut self) -> Result<()> {
1910 self.additional = self.read_rr_records(self.num_additionals)?;
1911 Ok(())
1912 }
1913
1914 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
1916 trace!("read_rr_records: {}", count);
1917 let mut rr_records = Vec::new();
1918
1919 const RR_HEADER_REMAIN: usize = 10;
1945
1946 for _ in 0..count {
1947 let name = self.read_name()?;
1948 let slice = &self.data[self.offset..];
1949
1950 if slice.len() < RR_HEADER_REMAIN {
1951 return Err(Error::Msg(format!(
1952 "read_others: RR '{}' is too short after name: {} bytes",
1953 &name,
1954 slice.len()
1955 )));
1956 }
1957
1958 let ty = u16_from_be_slice(&slice[..2]);
1959 let class = u16_from_be_slice(&slice[2..4]);
1960 let mut ttl = u32_from_be_slice(&slice[4..8]);
1961 if ttl == 0 && self.is_response() {
1962 ttl = 1;
1969 }
1970 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
1971 self.offset += RR_HEADER_REMAIN;
1972 let next_offset = self.offset + rdata_len;
1973
1974 if next_offset > self.data.len() {
1976 return Err(Error::Msg(format!(
1977 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
1978 self.data.len() - self.offset
1979 )));
1980 }
1981
1982 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
1984 None => None,
1985
1986 Some(rr_type) => match rr_type {
1987 RRType::CNAME | RRType::PTR => {
1988 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
1989 }
1990 RRType::TXT => {
1991 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
1992 }
1993 RRType::SRV => Some(
1994 DnsSrv::new(
1995 &name,
1996 class,
1997 ttl,
1998 self.read_u16()?,
1999 self.read_u16()?,
2000 self.read_u16()?,
2001 self.read_name()?,
2002 )
2003 .boxed(),
2004 ),
2005 RRType::HINFO => Some(
2006 DnsHostInfo::new(
2007 &name,
2008 rr_type,
2009 class,
2010 ttl,
2011 self.read_char_string()?,
2012 self.read_char_string()?,
2013 )
2014 .boxed(),
2015 ),
2016 RRType::A => Some(
2017 DnsAddress::new(
2018 &name,
2019 rr_type,
2020 class,
2021 ttl,
2022 self.read_ipv4()?.into(),
2023 self.interface_id.clone(),
2024 )
2025 .boxed(),
2026 ),
2027 RRType::AAAA => Some(
2028 DnsAddress::new(
2029 &name,
2030 rr_type,
2031 class,
2032 ttl,
2033 self.read_ipv6()?.into(),
2034 self.interface_id.clone(),
2035 )
2036 .boxed(),
2037 ),
2038 RRType::NSEC => Some(
2039 DnsNSec::new(
2040 &name,
2041 class,
2042 ttl,
2043 self.read_name()?,
2044 self.read_type_bitmap()?,
2045 )
2046 .boxed(),
2047 ),
2048 _ => None,
2049 },
2050 };
2051
2052 if let Some(record) = rec {
2053 trace!("read_rr_records: {:?}", &record);
2054 rr_records.push(record);
2055 } else {
2056 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2057 self.offset += rdata_len;
2058 }
2059
2060 if self.offset != next_offset {
2062 return Err(Error::Msg(format!(
2063 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2064 ty, self.offset, next_offset,
2065 )));
2066 }
2067 }
2068
2069 Ok(rr_records)
2070 }
2071
2072 fn read_char_string(&mut self) -> Result<String> {
2073 let length = self.data[self.offset];
2074 self.offset += 1;
2075 self.read_string(length as usize)
2076 }
2077
2078 fn read_u16(&mut self) -> Result<u16> {
2079 let slice = &self.data[self.offset..];
2080 if slice.len() < U16_SIZE {
2081 return Err(Error::Msg(format!(
2082 "read_u16: slice len is only {}",
2083 slice.len()
2084 )));
2085 }
2086 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2087 self.offset += U16_SIZE;
2088 Ok(num)
2089 }
2090
2091 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2093 if self.data.len() < self.offset + 2 {
2102 return Err(Error::Msg(format!(
2103 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2104 self.data.len(),
2105 self.offset
2106 )));
2107 }
2108
2109 let block_num = self.data[self.offset];
2110 self.offset += 1;
2111 if block_num != 0 {
2112 return Err(Error::Msg(format!(
2113 "NSEC block number is not 0: {}",
2114 block_num
2115 )));
2116 }
2117
2118 let block_len = self.data[self.offset] as usize;
2119 if !(1..=32).contains(&block_len) {
2120 return Err(Error::Msg(format!(
2121 "NSEC block length must be in the range 1-32: {}",
2122 block_len
2123 )));
2124 }
2125 self.offset += 1;
2126
2127 let end = self.offset + block_len;
2128 if end > self.data.len() {
2129 return Err(Error::Msg(format!(
2130 "NSEC block overflow: {} over RData len {}",
2131 end,
2132 self.data.len()
2133 )));
2134 }
2135 let bitmap = self.data[self.offset..end].to_vec();
2136 self.offset += block_len;
2137
2138 Ok(bitmap)
2139 }
2140
2141 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2142 if self.data.len() < self.offset + length {
2143 return Err(e_fmt!(
2144 "DNS Incoming: not enough data to read a chunk of data"
2145 ));
2146 }
2147
2148 let v = self.data[self.offset..self.offset + length].to_vec();
2149 self.offset += length;
2150 Ok(v)
2151 }
2152
2153 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2154 if self.data.len() < self.offset + 4 {
2155 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2156 }
2157
2158 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2159 .try_into()
2160 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2161 self.offset += bytes.len();
2162 Ok(Ipv4Addr::from(bytes))
2163 }
2164
2165 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2166 if self.data.len() < self.offset + 16 {
2167 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2168 }
2169
2170 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2171 .try_into()
2172 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2173 self.offset += bytes.len();
2174 Ok(Ipv6Addr::from(bytes))
2175 }
2176
2177 fn read_string(&mut self, length: usize) -> Result<String> {
2178 if self.data.len() < self.offset + length {
2179 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2180 }
2181
2182 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2183 .map_err(|e| Error::Msg(e.to_string()))?;
2184 self.offset += length;
2185 Ok(s.to_string())
2186 }
2187
2188 fn read_name(&mut self) -> Result<String> {
2193 let data = &self.data[..];
2194 let start_offset = self.offset;
2195 let mut offset = start_offset;
2196 let mut name = "".to_string();
2197 let mut at_end = false;
2198
2199 loop {
2210 if offset >= data.len() {
2211 return Err(Error::Msg(format!(
2212 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2213 offset,
2214 data.len(),
2215 self
2216 )));
2217 }
2218 let length = data[offset];
2219
2220 if length == 0 {
2224 if !at_end {
2225 self.offset = offset + 1;
2226 }
2227 break; }
2229
2230 match length & 0xC0 {
2232 0x00 => {
2233 offset += 1;
2235 let ending = offset + length as usize;
2236
2237 if ending > data.len() {
2239 return Err(Error::Msg(format!(
2240 "read_name: ending {} exceeds data length {}",
2241 ending,
2242 data.len()
2243 )));
2244 }
2245
2246 name += str::from_utf8(&data[offset..ending])
2247 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {}", e)))?;
2248 name += ".";
2249 offset += length as usize;
2250 }
2251 0xC0 => {
2252 let slice = &data[offset..];
2255 if slice.len() < U16_SIZE {
2256 return Err(Error::Msg(format!(
2257 "read_name: u16 slice len is only {}",
2258 slice.len()
2259 )));
2260 }
2261 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2262 if pointer >= start_offset {
2263 return Err(Error::Msg(format!(
2265 "Invalid name compression: pointer {} must be less than the start offset {}",
2266 &pointer, &start_offset
2267 )));
2268 }
2269
2270 if !at_end {
2272 self.offset = offset + U16_SIZE;
2273 at_end = true;
2274 }
2275 offset = pointer;
2276 }
2277 _ => {
2278 return Err(Error::Msg(format!(
2279 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2280 length,
2281 offset,
2282 &data[..offset]
2283 )));
2284 }
2285 };
2286 }
2287
2288 Ok(name)
2289 }
2290}
2291
2292fn current_time_millis() -> u64 {
2294 SystemTime::now()
2295 .duration_since(SystemTime::UNIX_EPOCH)
2296 .expect("failed to get current UNIX time")
2297 .as_millis() as u64
2298}
2299
2300const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2301 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2302 u16::from_be_bytes(u8_array)
2303}
2304
2305const fn u32_from_be_slice(s: &[u8]) -> u32 {
2306 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2307 u32::from_be_bytes(u8_array)
2308}
2309
2310const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2313 created + (ttl * percent * 10) as u64
2316}