1#[cfg(feature = "logging")]
8use crate::log::trace;
9
10use crate::current_time_millis;
11use crate::error::{e_fmt, Error, Result};
12use crate::service_info::{is_unicast_link_local, DnsRegistry, MyIntf, ServiceInfo};
13
14use if_addrs::Interface;
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19use std::{
20 any::Any,
21 cmp,
22 collections::HashMap,
23 convert::TryInto,
24 fmt,
25 hash::Hash,
26 net::{IpAddr, Ipv4Addr, Ipv6Addr},
27 str,
28};
29
30#[derive(Clone, Debug, Eq, Hash, PartialEq, Default)]
32#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
33pub struct InterfaceId {
34 pub name: String,
36
37 pub index: u32,
39}
40
41impl InterfaceId {
42 pub fn get_addrs(&self) -> Vec<IpAddr> {
44 if_addrs::get_if_addrs()
45 .unwrap_or_default()
46 .into_iter()
47 .filter(|iface| iface.index == Some(self.index))
48 .map(|iface| iface.ip())
49 .collect()
50 }
51}
52
53impl fmt::Display for InterfaceId {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 write!(f, "{}('{}')", self.index, self.name)
56 }
57}
58
59impl From<&Interface> for InterfaceId {
60 fn from(interface: &Interface) -> Self {
61 InterfaceId {
62 name: interface.name.clone(),
63 index: interface.index.unwrap_or_default(),
64 }
65 }
66}
67
68#[derive(Debug, Clone, Eq, PartialEq, Hash)]
70#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
71pub struct ScopedIpV4 {
72 addr: Ipv4Addr,
73 interface_ids: Vec<InterfaceId>,
75}
76
77impl ScopedIpV4 {
78 pub fn new(addr: Ipv4Addr, interface_id: InterfaceId) -> Self {
80 Self {
81 addr,
82 interface_ids: vec![interface_id],
83 }
84 }
85
86 pub const fn addr(&self) -> &Ipv4Addr {
88 &self.addr
89 }
90
91 pub fn interface_ids(&self) -> &[InterfaceId] {
93 &self.interface_ids
94 }
95
96 pub(crate) fn add_interface_id(&mut self, id: InterfaceId) {
98 if !self.interface_ids.contains(&id) {
99 self.interface_ids.push(id);
100 }
101 }
102}
103
104#[derive(Debug, Clone, Eq, PartialEq, Hash)]
106#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
107pub struct ScopedIpV6 {
108 addr: Ipv6Addr,
109 scope_id: InterfaceId,
110}
111
112impl ScopedIpV6 {
113 pub const fn addr(&self) -> &Ipv6Addr {
115 &self.addr
116 }
117
118 pub const fn scope_id(&self) -> &InterfaceId {
120 &self.scope_id
121 }
122}
123
124#[derive(Debug, Clone, Eq, PartialEq, Hash)]
126#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
127#[cfg_attr(feature = "serde", serde(untagged))]
128#[non_exhaustive]
129pub enum ScopedIp {
130 V4(ScopedIpV4),
131 V6(ScopedIpV6),
132}
133
134impl ScopedIp {
135 pub const fn to_ip_addr(&self) -> IpAddr {
136 match self {
137 ScopedIp::V4(v4) => IpAddr::V4(v4.addr),
138 ScopedIp::V6(v6) => IpAddr::V6(v6.addr),
139 }
140 }
141
142 pub const fn is_ipv4(&self) -> bool {
143 matches!(self, ScopedIp::V4(_))
144 }
145
146 pub const fn is_ipv6(&self) -> bool {
147 matches!(self, ScopedIp::V6(_))
148 }
149
150 pub const fn is_loopback(&self) -> bool {
151 match self {
152 ScopedIp::V4(v4) => v4.addr.is_loopback(),
153 ScopedIp::V6(v6) => v6.addr.is_loopback(),
154 }
155 }
156}
157
158impl From<IpAddr> for ScopedIp {
159 fn from(ip: IpAddr) -> Self {
160 match ip {
161 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
162 addr: v4,
163 interface_ids: vec![],
164 }),
165 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
166 addr: v6,
167 scope_id: InterfaceId::default(),
168 }),
169 }
170 }
171}
172
173impl From<&Interface> for ScopedIp {
174 fn from(interface: &Interface) -> Self {
175 match interface.ip() {
176 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
177 addr: v4,
178 interface_ids: vec![InterfaceId::from(interface)],
179 }),
180 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
181 addr: v6,
182 scope_id: InterfaceId::from(interface),
183 }),
184 }
185 }
186}
187
188impl fmt::Display for ScopedIp {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 match self {
191 ScopedIp::V4(v4) => write!(f, "{}", v4.addr),
192 ScopedIp::V6(v6) => {
193 if v6.scope_id.index != 0 && is_unicast_link_local(&v6.addr) {
194 #[cfg(windows)]
195 {
196 write!(f, "{}%{}", v6.addr, v6.scope_id.index)
197 }
198 #[cfg(not(windows))]
199 {
200 write!(f, "{}%{}", v6.addr, v6.scope_id.name)
201 }
202 } else {
203 write!(f, "{}", v6.addr)
204 }
205 }
206 }
207 }
208}
209
210#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
214#[non_exhaustive]
215#[repr(u16)]
216pub enum RRType {
217 A = 1,
219
220 CNAME = 5,
222
223 PTR = 12,
225
226 HINFO = 13,
228
229 TXT = 16,
231
232 AAAA = 28,
234
235 SRV = 33,
237
238 NSEC = 47,
240
241 ANY = 255,
243}
244
245impl RRType {
246 pub const fn from_u16(value: u16) -> Option<Self> {
248 match value {
249 1 => Some(RRType::A),
250 5 => Some(RRType::CNAME),
251 12 => Some(RRType::PTR),
252 13 => Some(RRType::HINFO),
253 16 => Some(RRType::TXT),
254 28 => Some(RRType::AAAA),
255 33 => Some(RRType::SRV),
256 47 => Some(RRType::NSEC),
257 255 => Some(RRType::ANY),
258 _ => None,
259 }
260 }
261}
262
263impl fmt::Display for RRType {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 match self {
266 RRType::A => write!(f, "TYPE_A"),
267 RRType::CNAME => write!(f, "TYPE_CNAME"),
268 RRType::PTR => write!(f, "TYPE_PTR"),
269 RRType::HINFO => write!(f, "TYPE_HINFO"),
270 RRType::TXT => write!(f, "TYPE_TXT"),
271 RRType::AAAA => write!(f, "TYPE_AAAA"),
272 RRType::SRV => write!(f, "TYPE_SRV"),
273 RRType::NSEC => write!(f, "TYPE_NSEC"),
274 RRType::ANY => write!(f, "TYPE_ANY"),
275 }
276 }
277}
278
279pub const CLASS_IN: u16 = 1;
281pub const CLASS_MASK: u16 = 0x7FFF;
282
283pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
285
286pub const MAX_MSG_ABSOLUTE: usize = 8972;
291
292const MSG_HEADER_LEN: usize = 12;
293
294pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
306
307pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
309
310pub const FLAGS_AA: u16 = 0x0400;
312
313pub const FLAGS_TC: u16 = 0x0200;
324
325pub type DnsRecordBox = Box<dyn DnsRecordExt>;
327
328impl Clone for DnsRecordBox {
329 fn clone(&self) -> Self {
330 self.clone_box()
331 }
332}
333
334const U16_SIZE: usize = 2;
335
336#[inline]
338pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
339 match address {
340 IpAddr::V4(_) => RRType::A,
341 IpAddr::V6(_) => RRType::AAAA,
342 }
343}
344
345#[derive(Eq, PartialEq, Debug, Clone)]
346pub struct DnsEntry {
347 pub(crate) name: String, pub(crate) ty: RRType,
349 class: u16,
350 cache_flush: bool,
351}
352
353impl DnsEntry {
354 const fn new(name: String, ty: RRType, class: u16) -> Self {
355 Self {
356 name,
357 ty,
358 class: class & CLASS_MASK,
359 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
360 }
361 }
362}
363
364pub trait DnsEntryExt: fmt::Debug {
366 fn entry_name(&self) -> &str;
367
368 fn entry_type(&self) -> RRType;
369}
370
371#[derive(Debug)]
373pub struct DnsQuestion {
374 pub(crate) entry: DnsEntry,
375}
376
377impl DnsEntryExt for DnsQuestion {
378 fn entry_name(&self) -> &str {
379 &self.entry.name
380 }
381
382 fn entry_type(&self) -> RRType {
383 self.entry.ty
384 }
385}
386
387#[derive(Debug, Clone)]
391pub struct DnsRecord {
392 pub(crate) entry: DnsEntry,
393 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
403}
404
405impl DnsRecord {
406 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
407 let created = current_time_millis();
408
409 let refresh = get_expiration_time(created, ttl, 80);
413
414 let expires = get_expiration_time(created, ttl, 100);
415
416 Self {
417 entry: DnsEntry::new(name.to_string(), ty, class),
418 ttl,
419 created,
420 expires,
421 refresh,
422 new_name: None,
423 }
424 }
425
426 pub const fn get_ttl(&self) -> u32 {
427 self.ttl
428 }
429
430 pub const fn get_expire_time(&self) -> u64 {
431 self.expires
432 }
433
434 pub const fn get_refresh_time(&self) -> u64 {
435 self.refresh
436 }
437
438 pub const fn is_expired(&self, now: u64) -> bool {
439 now >= self.expires
440 }
441
442 pub const fn expires_soon(&self, now: u64) -> bool {
446 now + 1000 >= self.expires
447 }
448
449 pub const fn refresh_due(&self, now: u64) -> bool {
450 now >= self.refresh
451 }
452
453 pub fn halflife_passed(&self, now: u64) -> bool {
455 let halflife = get_expiration_time(self.created, self.ttl, 50);
456 now > halflife
457 }
458
459 pub fn is_unique(&self) -> bool {
460 self.entry.cache_flush
461 }
462
463 pub fn refresh_no_more(&mut self) {
466 self.refresh = get_expiration_time(self.created, self.ttl, 100);
467 }
468
469 pub fn refresh_maybe(&mut self, now: u64) -> bool {
471 if self.is_expired(now) || !self.refresh_due(now) {
472 return false;
473 }
474
475 trace!(
476 "{} qtype {} is due to refresh",
477 &self.entry.name,
478 self.entry.ty
479 );
480
481 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
488 self.refresh = get_expiration_time(self.created, self.ttl, 85);
489 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
490 self.refresh = get_expiration_time(self.created, self.ttl, 90);
491 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
492 self.refresh = get_expiration_time(self.created, self.ttl, 95);
493 } else {
494 self.refresh_no_more();
495 }
496
497 true
498 }
499
500 fn get_remaining_ttl(&self, now: u64) -> u32 {
502 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
503 cmp::max(0, remaining_millis / 1000) as u32
504 }
505
506 pub const fn get_created(&self) -> u64 {
508 self.created
509 }
510
511 fn set_expire(&mut self, expire_at: u64) {
513 self.expires = expire_at;
514 }
515
516 fn reset_ttl(&mut self, other: &Self) {
517 self.ttl = other.ttl;
518 self.created = other.created;
519 self.expires = get_expiration_time(self.created, self.ttl, 100);
520 self.refresh = if self.ttl > 1 {
521 get_expiration_time(self.created, self.ttl, 80)
522 } else {
523 self.expires
526 };
527 }
528
529 pub fn update_ttl(&mut self, now: u64) {
531 if now > self.created {
532 let elapsed = now - self.created;
533 self.ttl -= (elapsed / 1000) as u32;
534 }
535 }
536
537 pub fn set_new_name(&mut self, new_name: String) {
538 if new_name == self.entry.name {
539 self.new_name = None;
540 } else {
541 self.new_name = Some(new_name);
542 }
543 }
544
545 pub fn get_new_name(&self) -> Option<&str> {
546 self.new_name.as_deref()
547 }
548
549 pub(crate) fn get_name(&self) -> &str {
551 self.new_name.as_deref().unwrap_or(&self.entry.name)
552 }
553
554 pub fn get_original_name(&self) -> &str {
555 &self.entry.name
556 }
557}
558
559impl PartialEq for DnsRecord {
560 fn eq(&self, other: &Self) -> bool {
561 self.entry == other.entry
562 }
563}
564
565pub trait DnsRecordExt: fmt::Debug {
567 fn get_record(&self) -> &DnsRecord;
568 fn get_record_mut(&mut self) -> &mut DnsRecord;
569 fn write(&self, packet: &mut DnsOutPacket);
570 fn any(&self) -> &dyn Any;
571
572 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
574
575 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
577
578 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
581
582 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
584 match self.get_class().cmp(&other.get_class()) {
598 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
599 cmp::Ordering::Equal => self.compare_rdata(other),
600 not_equal => not_equal,
601 },
602 not_equal => not_equal,
603 }
604 }
605
606 fn rdata_print(&self) -> String;
608
609 fn get_class(&self) -> u16 {
611 self.get_record().entry.class
612 }
613
614 fn get_cache_flush(&self) -> bool {
615 self.get_record().entry.cache_flush
616 }
617
618 fn get_name(&self) -> &str {
620 self.get_record().get_name()
621 }
622
623 fn get_type(&self) -> RRType {
624 self.get_record().entry.ty
625 }
626
627 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
630 self.get_record_mut().reset_ttl(other.get_record());
631 }
632
633 fn get_created(&self) -> u64 {
634 self.get_record().get_created()
635 }
636
637 fn get_expire(&self) -> u64 {
638 self.get_record().get_expire_time()
639 }
640
641 fn set_expire(&mut self, expire_at: u64) {
642 self.get_record_mut().set_expire(expire_at);
643 }
644
645 fn set_expire_sooner(&mut self, expire_at: u64) {
647 if expire_at < self.get_expire() {
648 self.get_record_mut().set_expire(expire_at);
649 }
650 }
651
652 fn expires_soon(&self, now: u64) -> bool {
654 self.get_record().expires_soon(now)
655 }
656
657 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
660 if self.get_record_mut().refresh_maybe(now) {
661 Some(self.get_record().get_refresh_time())
662 } else {
663 None
664 }
665 }
666
667 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
670 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
671 }
672
673 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
675 for answer in msg.answers.iter() {
676 if self.suppressed_by_answer(answer.as_ref()) {
677 return true;
678 }
679 }
680 false
681 }
682
683 fn clone_box(&self) -> DnsRecordBox;
684
685 fn boxed(self) -> DnsRecordBox;
686}
687
688#[derive(Debug, Clone)]
690pub(crate) struct DnsAddress {
691 pub(crate) record: DnsRecord,
692 address: IpAddr,
693 pub(crate) interface_id: InterfaceId,
694}
695
696impl DnsAddress {
697 pub fn new(
698 name: &str,
699 ty: RRType,
700 class: u16,
701 ttl: u32,
702 address: IpAddr,
703 interface_id: InterfaceId,
704 ) -> Self {
705 let record = DnsRecord::new(name, ty, class, ttl);
706 Self {
707 record,
708 address,
709 interface_id,
710 }
711 }
712
713 pub fn address(&self) -> ScopedIp {
714 match self.address {
715 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
716 addr: v4,
717 interface_ids: vec![self.interface_id.clone()],
718 }),
719 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
720 addr: v6,
721 scope_id: self.interface_id.clone(),
722 }),
723 }
724 }
725}
726
727impl DnsRecordExt for DnsAddress {
728 fn get_record(&self) -> &DnsRecord {
729 &self.record
730 }
731
732 fn get_record_mut(&mut self) -> &mut DnsRecord {
733 &mut self.record
734 }
735
736 fn write(&self, packet: &mut DnsOutPacket) {
737 match self.address {
738 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
739 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
740 };
741 }
742
743 fn any(&self) -> &dyn Any {
744 self
745 }
746
747 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
748 if let Some(other_a) = other.any().downcast_ref::<Self>() {
749 return self.address == other_a.address
750 && self.record.entry == other_a.record.entry
751 && self.interface_id == other_a.interface_id;
752 }
753 false
754 }
755
756 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
757 if let Some(other_a) = other.any().downcast_ref::<Self>() {
758 return self.address == other_a.address;
759 }
760 false
761 }
762
763 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
764 if let Some(other_a) = other.any().downcast_ref::<Self>() {
765 self.address.cmp(&other_a.address)
766 } else {
767 cmp::Ordering::Greater
768 }
769 }
770
771 fn rdata_print(&self) -> String {
772 format!("{}", self.address)
773 }
774
775 fn clone_box(&self) -> DnsRecordBox {
776 Box::new(self.clone())
777 }
778
779 fn boxed(self) -> DnsRecordBox {
780 Box::new(self)
781 }
782}
783
784#[derive(Debug, Clone)]
786pub struct DnsPointer {
787 record: DnsRecord,
788 alias: String, }
790
791impl DnsPointer {
792 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
793 let record = DnsRecord::new(name, ty, class, ttl);
794 Self { record, alias }
795 }
796
797 pub fn alias(&self) -> &str {
798 &self.alias
799 }
800}
801
802impl DnsRecordExt for DnsPointer {
803 fn get_record(&self) -> &DnsRecord {
804 &self.record
805 }
806
807 fn get_record_mut(&mut self) -> &mut DnsRecord {
808 &mut self.record
809 }
810
811 fn write(&self, packet: &mut DnsOutPacket) {
812 packet.write_name(&self.alias);
813 }
814
815 fn any(&self) -> &dyn Any {
816 self
817 }
818
819 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
820 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
821 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
822 }
823 false
824 }
825
826 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
827 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
828 return self.alias == other_ptr.alias;
829 }
830 false
831 }
832
833 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
834 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
835 self.alias.cmp(&other_ptr.alias)
836 } else {
837 cmp::Ordering::Greater
838 }
839 }
840
841 fn rdata_print(&self) -> String {
842 self.alias.clone()
843 }
844
845 fn clone_box(&self) -> DnsRecordBox {
846 Box::new(self.clone())
847 }
848
849 fn boxed(self) -> DnsRecordBox {
850 Box::new(self)
851 }
852}
853
854#[derive(Debug, Clone)]
856pub struct DnsSrv {
857 pub(crate) record: DnsRecord,
858 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
861 port: u16,
862}
863
864impl DnsSrv {
865 pub fn new(
866 name: &str,
867 class: u16,
868 ttl: u32,
869 priority: u16,
870 weight: u16,
871 port: u16,
872 host: String,
873 ) -> Self {
874 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
875 Self {
876 record,
877 priority,
878 weight,
879 host,
880 port,
881 }
882 }
883
884 pub fn host(&self) -> &str {
885 &self.host
886 }
887
888 pub fn port(&self) -> u16 {
889 self.port
890 }
891
892 pub fn set_host(&mut self, host: String) {
893 self.host = host;
894 }
895}
896
897impl DnsRecordExt for DnsSrv {
898 fn get_record(&self) -> &DnsRecord {
899 &self.record
900 }
901
902 fn get_record_mut(&mut self) -> &mut DnsRecord {
903 &mut self.record
904 }
905
906 fn write(&self, packet: &mut DnsOutPacket) {
907 packet.write_short(self.priority);
908 packet.write_short(self.weight);
909 packet.write_short(self.port);
910 packet.write_name(&self.host);
911 }
912
913 fn any(&self) -> &dyn Any {
914 self
915 }
916
917 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
918 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
919 return self.host == other_svc.host
920 && self.port == other_svc.port
921 && self.weight == other_svc.weight
922 && self.priority == other_svc.priority
923 && self.record.entry == other_svc.record.entry;
924 }
925 false
926 }
927
928 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
929 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
930 return self.host == other_srv.host
931 && self.port == other_srv.port
932 && self.weight == other_srv.weight
933 && self.priority == other_srv.priority;
934 }
935 false
936 }
937
938 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
939 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
940 return cmp::Ordering::Greater;
941 };
942
943 match self
945 .priority
946 .to_be_bytes()
947 .cmp(&other_srv.priority.to_be_bytes())
948 {
949 cmp::Ordering::Equal => {
950 match self
952 .weight
953 .to_be_bytes()
954 .cmp(&other_srv.weight.to_be_bytes())
955 {
956 cmp::Ordering::Equal => {
957 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
959 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
960 not_equal => not_equal,
961 }
962 }
963 not_equal => not_equal,
964 }
965 }
966 not_equal => not_equal,
967 }
968 }
969
970 fn rdata_print(&self) -> String {
971 format!(
972 "priority: {}, weight: {}, port: {}, host: {}",
973 self.priority, self.weight, self.port, self.host
974 )
975 }
976
977 fn clone_box(&self) -> DnsRecordBox {
978 Box::new(self.clone())
979 }
980
981 fn boxed(self) -> DnsRecordBox {
982 Box::new(self)
983 }
984}
985
986#[derive(Clone)]
1001pub struct DnsTxt {
1002 pub(crate) record: DnsRecord,
1003 text: Vec<u8>,
1004}
1005
1006impl DnsTxt {
1007 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1008 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1009 Self { record, text }
1010 }
1011
1012 pub fn text(&self) -> &[u8] {
1013 &self.text
1014 }
1015}
1016
1017impl DnsRecordExt for DnsTxt {
1018 fn get_record(&self) -> &DnsRecord {
1019 &self.record
1020 }
1021
1022 fn get_record_mut(&mut self) -> &mut DnsRecord {
1023 &mut self.record
1024 }
1025
1026 fn write(&self, packet: &mut DnsOutPacket) {
1027 packet.write_bytes(&self.text);
1028 }
1029
1030 fn any(&self) -> &dyn Any {
1031 self
1032 }
1033
1034 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1035 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1036 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1037 }
1038 false
1039 }
1040
1041 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1042 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1043 return self.text == other_txt.text;
1044 }
1045 false
1046 }
1047
1048 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1049 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1050 self.text.cmp(&other_txt.text)
1051 } else {
1052 cmp::Ordering::Greater
1053 }
1054 }
1055
1056 fn rdata_print(&self) -> String {
1057 format!("{:?}", decode_txt(&self.text))
1058 }
1059
1060 fn clone_box(&self) -> DnsRecordBox {
1061 Box::new(self.clone())
1062 }
1063
1064 fn boxed(self) -> DnsRecordBox {
1065 Box::new(self)
1066 }
1067}
1068
1069impl fmt::Debug for DnsTxt {
1070 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071 let properties = decode_txt(&self.text);
1072 write!(
1073 f,
1074 "DnsTxt {{ record: {:?}, text: {:?} }}",
1075 self.record, properties
1076 )
1077 }
1078}
1079
1080fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
1082 let mut properties = Vec::new();
1083 let mut offset = 0;
1084 while offset < txt.len() {
1085 let length = txt[offset] as usize;
1086 if length == 0 {
1087 break; }
1089 offset += 1; let offset_end = offset + length;
1092 if offset_end > txt.len() {
1093 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
1094 break; }
1096 let kv_bytes = &txt[offset..offset_end];
1097
1098 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
1100 || (kv_bytes.to_vec(), None),
1101 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
1102 );
1103
1104 match String::from_utf8(k) {
1106 Ok(k_string) => {
1107 properties.push(TxtProperty {
1108 key: k_string,
1109 val: v,
1110 });
1111 }
1112 Err(e) => trace!("ERROR: convert to String from key: {}", e),
1113 }
1114
1115 offset += length;
1116 }
1117
1118 properties
1119}
1120
1121#[derive(Clone, PartialEq, Eq)]
1123pub struct TxtProperty {
1124 key: String,
1126
1127 val: Option<Vec<u8>>,
1131}
1132
1133impl TxtProperty {
1134 pub fn val_str(&self) -> &str {
1136 self.val
1137 .as_ref()
1138 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
1139 }
1140}
1141
1142impl<K, V> From<&(K, V)> for TxtProperty
1144where
1145 K: ToString,
1146 V: ToString,
1147{
1148 fn from(prop: &(K, V)) -> Self {
1149 Self {
1150 key: prop.0.to_string(),
1151 val: Some(prop.1.to_string().into_bytes()),
1152 }
1153 }
1154}
1155
1156impl<K, V> From<(K, V)> for TxtProperty
1157where
1158 K: ToString,
1159 V: AsRef<[u8]>,
1160{
1161 fn from(prop: (K, V)) -> Self {
1162 Self {
1163 key: prop.0.to_string(),
1164 val: Some(prop.1.as_ref().into()),
1165 }
1166 }
1167}
1168
1169impl From<&str> for TxtProperty {
1171 fn from(key: &str) -> Self {
1172 Self {
1173 key: key.to_string(),
1174 val: None,
1175 }
1176 }
1177}
1178
1179impl fmt::Display for TxtProperty {
1180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1181 write!(f, "{}={}", self.key, self.val_str())
1182 }
1183}
1184
1185impl fmt::Debug for TxtProperty {
1189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1190 let val_string = self.val.as_ref().map_or_else(
1191 || "None".to_string(),
1192 |v| {
1193 std::str::from_utf8(&v[..]).map_or_else(
1194 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1195 |s| format!("Some(\"{s}\")"),
1196 )
1197 },
1198 );
1199
1200 write!(
1201 f,
1202 "TxtProperty {{key: \"{}\", val: {}}}",
1203 &self.key, &val_string,
1204 )
1205 }
1206}
1207
1208const HEX_TABLE: [char; 16] = [
1209 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1210];
1211
1212fn u8_slice_to_hex(slice: &[u8]) -> String {
1216 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1217 hex.push_str("0x");
1218 for b in slice {
1219 hex.push(HEX_TABLE[(b >> 4) as usize]);
1220 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1221 }
1222 hex
1223}
1224
1225#[derive(Debug, Clone)]
1227struct DnsHostInfo {
1228 record: DnsRecord,
1229 cpu: String,
1230 os: String,
1231}
1232
1233impl DnsHostInfo {
1234 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1235 let record = DnsRecord::new(name, ty, class, ttl);
1236 Self { record, cpu, os }
1237 }
1238}
1239
1240impl DnsRecordExt for DnsHostInfo {
1241 fn get_record(&self) -> &DnsRecord {
1242 &self.record
1243 }
1244
1245 fn get_record_mut(&mut self) -> &mut DnsRecord {
1246 &mut self.record
1247 }
1248
1249 fn write(&self, packet: &mut DnsOutPacket) {
1250 println!("writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1251 packet.write_bytes(self.cpu.as_bytes());
1252 packet.write_bytes(self.os.as_bytes());
1253 }
1254
1255 fn any(&self) -> &dyn Any {
1256 self
1257 }
1258
1259 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1260 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1261 return self.cpu == other_hinfo.cpu
1262 && self.os == other_hinfo.os
1263 && self.record.entry == other_hinfo.record.entry;
1264 }
1265 false
1266 }
1267
1268 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1269 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1270 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1271 }
1272 false
1273 }
1274
1275 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1276 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1277 match self.cpu.cmp(&other_hinfo.cpu) {
1278 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1279 ordering => ordering,
1280 }
1281 } else {
1282 cmp::Ordering::Greater
1283 }
1284 }
1285
1286 fn rdata_print(&self) -> String {
1287 format!("cpu: {}, os: {}", self.cpu, self.os)
1288 }
1289
1290 fn clone_box(&self) -> DnsRecordBox {
1291 Box::new(self.clone())
1292 }
1293
1294 fn boxed(self) -> DnsRecordBox {
1295 Box::new(self)
1296 }
1297}
1298
1299#[derive(Debug, Clone)]
1305pub struct DnsNSec {
1306 record: DnsRecord,
1307 next_domain: String,
1308 type_bitmap: Vec<u8>,
1309}
1310
1311impl DnsNSec {
1312 pub fn new(
1313 name: &str,
1314 class: u16,
1315 ttl: u32,
1316 next_domain: String,
1317 type_bitmap: Vec<u8>,
1318 ) -> Self {
1319 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1320 Self {
1321 record,
1322 next_domain,
1323 type_bitmap,
1324 }
1325 }
1326
1327 pub fn _types(&self) -> Vec<u16> {
1329 let mut bit_num = 0;
1338 let mut results = Vec::new();
1339
1340 for byte in self.type_bitmap.iter() {
1341 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1345 if (byte & bit_mask) != 0 {
1346 results.push(bit_num);
1347 }
1348 bit_num += 1;
1349 bit_mask >>= 1; }
1351 }
1352 results
1353 }
1354}
1355
1356impl DnsRecordExt for DnsNSec {
1357 fn get_record(&self) -> &DnsRecord {
1358 &self.record
1359 }
1360
1361 fn get_record_mut(&mut self) -> &mut DnsRecord {
1362 &mut self.record
1363 }
1364
1365 fn write(&self, packet: &mut DnsOutPacket) {
1366 packet.write_bytes(self.next_domain.as_bytes());
1367 packet.write_bytes(&self.type_bitmap);
1368 }
1369
1370 fn any(&self) -> &dyn Any {
1371 self
1372 }
1373
1374 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1375 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1376 return self.next_domain == other_record.next_domain
1377 && self.type_bitmap == other_record.type_bitmap
1378 && self.record.entry == other_record.record.entry;
1379 }
1380 false
1381 }
1382
1383 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1384 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1385 return self.next_domain == other_record.next_domain
1386 && self.type_bitmap == other_record.type_bitmap;
1387 }
1388 false
1389 }
1390
1391 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1392 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1393 match self.next_domain.cmp(&other_nsec.next_domain) {
1394 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1395 ordering => ordering,
1396 }
1397 } else {
1398 cmp::Ordering::Greater
1399 }
1400 }
1401
1402 fn rdata_print(&self) -> String {
1403 format!(
1404 "next_domain: {}, type_bitmap len: {}",
1405 self.next_domain,
1406 self.type_bitmap.len()
1407 )
1408 }
1409
1410 fn clone_box(&self) -> DnsRecordBox {
1411 Box::new(self.clone())
1412 }
1413
1414 fn boxed(self) -> DnsRecordBox {
1415 Box::new(self)
1416 }
1417}
1418
1419#[derive(PartialEq)]
1420enum PacketState {
1421 Init = 0,
1422 Finished = 1,
1423}
1424
1425pub struct DnsOutPacket {
1427 data: Vec<Vec<u8>>,
1429
1430 size: usize,
1432
1433 state: PacketState,
1435
1436 names: HashMap<String, u16>,
1438}
1439
1440impl DnsOutPacket {
1441 fn new() -> Self {
1442 Self {
1443 data: Vec::new(),
1444 size: MSG_HEADER_LEN, state: PacketState::Init,
1446 names: HashMap::new(),
1447 }
1448 }
1449
1450 pub fn size(&self) -> usize {
1451 self.size
1452 }
1453
1454 pub fn to_bytes(&self) -> Vec<u8> {
1455 self.data.concat()
1456 }
1457
1458 fn write_question(&mut self, question: &DnsQuestion) {
1459 self.write_name(&question.entry.name);
1460 self.write_short(question.entry.ty as u16);
1461 self.write_short(question.entry.class);
1462 }
1463
1464 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> bool {
1468 let start_data_length = self.data.len();
1469 let start_size = self.size;
1470
1471 let record = record_ext.get_record();
1472 self.write_name(record.get_name());
1473 self.write_short(record.entry.ty as u16);
1474 if record.entry.cache_flush {
1475 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1477 } else {
1478 self.write_short(record.entry.class);
1479 }
1480
1481 if now == 0 {
1482 self.write_u32(record.ttl);
1483 } else {
1484 self.write_u32(record.get_remaining_ttl(now));
1485 }
1486
1487 let index = self.data.len();
1488
1489 self.size += 2;
1491 record_ext.write(self);
1492 self.size -= 2;
1493
1494 let length: usize = self.data[index..].iter().map(|x| x.len()).sum();
1495 self.insert_short(index, length as u16);
1496
1497 if self.size > MAX_MSG_ABSOLUTE {
1498 self.data.truncate(start_data_length);
1499 self.size = start_size;
1500 self.state = PacketState::Finished;
1501 return false;
1502 }
1503
1504 true
1505 }
1506
1507 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1508 self.data.insert(index, value.to_be_bytes().to_vec());
1509 self.size += 2;
1510 }
1511
1512 fn parse_escaped_name(name: &str) -> Vec<String> {
1519 let mut labels = Vec::new();
1520 let mut current_label = String::new();
1521 let mut chars = name.chars().peekable();
1522
1523 while let Some(ch) = chars.next() {
1524 match ch {
1525 '\\' => {
1526 if let Some(&next_ch) = chars.peek() {
1528 match next_ch {
1529 '.' | '\\' => {
1530 chars.next();
1532 current_label.push(next_ch);
1533 }
1534 _ => {
1535 current_label.push(ch);
1537 }
1538 }
1539 } else {
1540 current_label.push(ch);
1542 }
1543 }
1544 '.' => {
1545 if !current_label.is_empty() {
1547 labels.push(current_label.clone());
1548 current_label.clear();
1549 }
1550 }
1551 _ => {
1552 current_label.push(ch);
1553 }
1554 }
1555 }
1556
1557 if !current_label.is_empty() {
1559 labels.push(current_label);
1560 }
1561
1562 labels
1563 }
1564
1565 fn write_name(&mut self, name: &str) {
1591 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1593
1594 let labels = Self::parse_escaped_name(name_to_parse);
1596
1597 if labels.is_empty() {
1598 self.write_byte(0);
1599 return;
1600 }
1601
1602 for (i, label) in labels.iter().enumerate() {
1604 let remaining: String = labels[i..].join(".");
1606
1607 const POINTER_MASK: u16 = 0xC000;
1609 if let Some(&offset) = self.names.get(&remaining) {
1610 let pointer = offset | POINTER_MASK;
1611 self.write_short(pointer);
1612 return;
1613 }
1614
1615 self.names.insert(remaining, self.size as u16);
1617
1618 self.write_utf8(label);
1620 }
1621
1622 self.write_byte(0);
1624 }
1625
1626 fn write_utf8(&mut self, utf: &str) {
1627 assert!(utf.len() < 64);
1628 self.write_byte(utf.len() as u8);
1629 self.write_bytes(utf.as_bytes());
1630 }
1631
1632 fn write_bytes(&mut self, s: &[u8]) {
1633 self.data.push(s.to_vec());
1634 self.size += s.len();
1635 }
1636
1637 fn write_u32(&mut self, int: u32) {
1638 self.data.push(int.to_be_bytes().to_vec());
1639 self.size += 4;
1640 }
1641
1642 fn write_short(&mut self, short: u16) {
1643 self.data.push(short.to_be_bytes().to_vec());
1644 self.size += 2;
1645 }
1646
1647 fn write_byte(&mut self, byte: u8) {
1648 self.data.push(vec![byte]);
1649 self.size += 1;
1650 }
1651
1652 fn write_header(
1675 &mut self,
1676 id: u16,
1677 flags: u16,
1678 q_count: u16,
1679 a_count: u16,
1680 auth_count: u16,
1681 addi_count: u16,
1682 ) {
1683 self.insert_short(0, addi_count);
1684 self.insert_short(0, auth_count);
1685 self.insert_short(0, a_count);
1686 self.insert_short(0, q_count);
1687 self.insert_short(0, flags);
1688 self.insert_short(0, id);
1689
1690 self.size -= MSG_HEADER_LEN;
1692
1693 self.state = PacketState::Finished;
1694 }
1695}
1696
1697pub struct DnsOutgoing {
1699 flags: u16,
1700 id: u16,
1701 multicast: bool,
1702 questions: Vec<DnsQuestion>,
1703 answers: Vec<(DnsRecordBox, u64)>,
1704 authorities: Vec<DnsRecordBox>,
1705 additionals: Vec<DnsRecordBox>,
1706 known_answer_count: i64, }
1708
1709impl DnsOutgoing {
1710 pub fn new(flags: u16) -> Self {
1711 Self {
1712 flags,
1713 id: 0,
1714 multicast: true,
1715 questions: Vec::new(),
1716 answers: Vec::new(),
1717 authorities: Vec::new(),
1718 additionals: Vec::new(),
1719 known_answer_count: 0,
1720 }
1721 }
1722
1723 pub fn questions(&self) -> &[DnsQuestion] {
1724 &self.questions
1725 }
1726
1727 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1729 &self.answers
1730 }
1731
1732 pub fn answers_count(&self) -> usize {
1733 self.answers.len()
1734 }
1735
1736 pub fn authorities(&self) -> &[DnsRecordBox] {
1737 &self.authorities
1738 }
1739
1740 pub fn additionals(&self) -> &[DnsRecordBox] {
1741 &self.additionals
1742 }
1743
1744 pub fn known_answer_count(&self) -> i64 {
1745 self.known_answer_count
1746 }
1747
1748 pub fn set_id(&mut self, id: u16) {
1749 self.id = id;
1750 }
1751
1752 pub const fn is_query(&self) -> bool {
1753 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1754 }
1755
1756 const fn is_response(&self) -> bool {
1757 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1758 }
1759
1760 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1794 trace!("add_additional_answer: {:?}", &answer);
1795 self.additionals.push(answer.boxed());
1796 }
1797
1798 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1800 self.answers.push((answer_box, 0));
1801 }
1802
1803 pub fn add_authority(&mut self, record: DnsRecordBox) {
1804 self.authorities.push(record);
1805 }
1806
1807 pub fn add_answer(
1810 &mut self,
1811 msg: &DnsIncoming,
1812 answer: impl DnsRecordExt + Send + 'static,
1813 ) -> bool {
1814 trace!("Check for add_answer");
1815 if answer.suppressed_by(msg) {
1816 trace!("my answer is suppressed by incoming msg");
1817 self.known_answer_count += 1;
1818 return false;
1819 }
1820
1821 self.add_answer_at_time(answer, 0)
1822 }
1823
1824 pub fn add_answer_at_time(
1828 &mut self,
1829 answer: impl DnsRecordExt + Send + 'static,
1830 now: u64,
1831 ) -> bool {
1832 if now == 0 || !answer.get_record().is_expired(now) {
1833 trace!("add_answer push: {:?}", &answer);
1834 self.answers.push((answer.boxed(), now));
1835 return true;
1836 }
1837 false
1838 }
1839
1840 pub(crate) fn add_answer_with_additionals(
1849 &mut self,
1850 msg: &DnsIncoming,
1851 service: &ServiceInfo,
1852 intf: &MyIntf,
1853 dns_registry: &DnsRegistry,
1854 is_ipv4: bool,
1855 ) {
1856 let intf_addrs = if is_ipv4 {
1857 service.get_addrs_on_my_intf_v4(intf)
1858 } else {
1859 service.get_addrs_on_my_intf_v6(intf)
1860 };
1861 if intf_addrs.is_empty() {
1862 trace!("No addrs on LAN of intf {:?}", intf);
1863 return;
1864 }
1865
1866 let service_fullname = dns_registry.resolve_name(service.get_fullname());
1868 let hostname = dns_registry.resolve_name(service.get_hostname());
1869
1870 let ptr_added = self.add_answer(
1871 msg,
1872 DnsPointer::new(
1873 service.get_type(),
1874 RRType::PTR,
1875 CLASS_IN,
1876 service.get_other_ttl(),
1877 service_fullname.to_string(),
1878 ),
1879 );
1880
1881 if !ptr_added {
1882 trace!("answer was not added for msg {:?}", msg);
1883 return;
1884 }
1885
1886 if let Some(sub) = service.get_subtype() {
1887 trace!("Adding subdomain {}", sub);
1888 self.add_additional_answer(DnsPointer::new(
1889 sub,
1890 RRType::PTR,
1891 CLASS_IN,
1892 service.get_other_ttl(),
1893 service_fullname.to_string(),
1894 ));
1895 }
1896
1897 self.add_additional_answer(DnsSrv::new(
1900 service_fullname,
1901 CLASS_IN | CLASS_CACHE_FLUSH,
1902 service.get_host_ttl(),
1903 service.get_priority(),
1904 service.get_weight(),
1905 service.get_port(),
1906 hostname.to_string(),
1907 ));
1908
1909 self.add_additional_answer(DnsTxt::new(
1910 service_fullname,
1911 CLASS_IN | CLASS_CACHE_FLUSH,
1912 service.get_other_ttl(),
1913 service.generate_txt(),
1914 ));
1915
1916 for address in intf_addrs {
1917 self.add_additional_answer(DnsAddress::new(
1918 hostname,
1919 ip_address_rr_type(&address),
1920 CLASS_IN | CLASS_CACHE_FLUSH,
1921 service.get_host_ttl(),
1922 address,
1923 intf.into(),
1924 ));
1925 }
1926 }
1927
1928 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1929 let q = DnsQuestion {
1930 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1931 };
1932 self.questions.push(q);
1933 }
1934
1935 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
1937 let packet_list = self.to_packets();
1938 packet_list.iter().map(|p| p.data.concat()).collect()
1939 }
1940
1941 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
1943 let mut packet_list = Vec::new();
1944 let mut packet = DnsOutPacket::new();
1945
1946 let mut question_count = self.questions.len() as u16;
1947 let mut answer_count = 0;
1948 let mut auth_count = 0;
1949 let mut addi_count = 0;
1950 let id = if self.multicast { 0 } else { self.id };
1951
1952 for question in self.questions.iter() {
1953 packet.write_question(question);
1954 }
1955
1956 for (answer, time) in self.answers.iter() {
1957 if packet.write_record(answer.as_ref(), *time) {
1958 answer_count += 1;
1959 }
1960 }
1961
1962 for auth in self.authorities.iter() {
1963 auth_count += u16::from(packet.write_record(auth.as_ref(), 0));
1964 }
1965
1966 for addi in self.additionals.iter() {
1967 if packet.write_record(addi.as_ref(), 0) {
1968 addi_count += 1;
1969 continue;
1970 }
1971
1972 if self.is_response() {
1974 break;
1975 }
1976
1977 packet.write_header(
1982 id,
1983 self.flags | FLAGS_TC,
1984 question_count,
1985 answer_count,
1986 auth_count,
1987 addi_count,
1988 );
1989
1990 packet_list.push(packet);
1991
1992 packet = DnsOutPacket::new();
1994 packet.write_record(addi.as_ref(), 0);
1995
1996 question_count = 0;
1997 answer_count = 0;
1998 auth_count = 0;
1999 addi_count = 1;
2000 }
2001
2002 packet.write_header(
2003 id,
2004 self.flags,
2005 question_count,
2006 answer_count,
2007 auth_count,
2008 addi_count,
2009 );
2010
2011 packet_list.push(packet);
2012 packet_list
2013 }
2014}
2015
2016#[derive(Debug)]
2018pub struct DnsIncoming {
2019 offset: usize,
2020 data: Vec<u8>,
2021 questions: Vec<DnsQuestion>,
2022 answers: Vec<DnsRecordBox>,
2023 authorities: Vec<DnsRecordBox>,
2024 additional: Vec<DnsRecordBox>,
2025 id: u16,
2026 flags: u16,
2027 num_questions: u16,
2028 num_answers: u16,
2029 num_authorities: u16,
2030 num_additionals: u16,
2031 interface_id: InterfaceId,
2032}
2033
2034impl DnsIncoming {
2035 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2036 let mut incoming = Self {
2037 offset: 0,
2038 data,
2039 questions: Vec::new(),
2040 answers: Vec::new(),
2041 authorities: Vec::new(),
2042 additional: Vec::new(),
2043 id: 0,
2044 flags: 0,
2045 num_questions: 0,
2046 num_answers: 0,
2047 num_authorities: 0,
2048 num_additionals: 0,
2049 interface_id,
2050 };
2051
2052 incoming.read_header()?;
2072 incoming.read_questions()?;
2073 incoming.read_answers()?;
2074 incoming.read_authorities()?;
2075 incoming.read_additional()?;
2076
2077 Ok(incoming)
2078 }
2079
2080 pub fn id(&self) -> u16 {
2081 self.id
2082 }
2083
2084 pub fn questions(&self) -> &[DnsQuestion] {
2085 &self.questions
2086 }
2087
2088 pub fn answers(&self) -> &[DnsRecordBox] {
2089 &self.answers
2090 }
2091
2092 pub fn authorities(&self) -> &[DnsRecordBox] {
2093 &self.authorities
2094 }
2095
2096 pub fn additionals(&self) -> &[DnsRecordBox] {
2097 &self.additional
2098 }
2099
2100 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2101 &mut self.answers
2102 }
2103
2104 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2105 &mut self.authorities
2106 }
2107
2108 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2109 &mut self.additional
2110 }
2111
2112 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2113 self.answers
2114 .into_iter()
2115 .chain(self.authorities)
2116 .chain(self.additional)
2117 }
2118
2119 pub fn num_additionals(&self) -> u16 {
2120 self.num_additionals
2121 }
2122
2123 pub fn num_authorities(&self) -> u16 {
2124 self.num_authorities
2125 }
2126
2127 pub fn num_questions(&self) -> u16 {
2128 self.num_questions
2129 }
2130
2131 pub const fn is_query(&self) -> bool {
2132 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2133 }
2134
2135 pub const fn is_response(&self) -> bool {
2136 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2137 }
2138
2139 fn read_header(&mut self) -> Result<()> {
2140 if self.data.len() < MSG_HEADER_LEN {
2141 return Err(e_fmt!(
2142 "DNS incoming: header is too short: {} bytes",
2143 self.data.len()
2144 ));
2145 }
2146
2147 let data = &self.data[0..];
2148 self.id = u16_from_be_slice(&data[..2]);
2149 self.flags = u16_from_be_slice(&data[2..4]);
2150 self.num_questions = u16_from_be_slice(&data[4..6]);
2151 self.num_answers = u16_from_be_slice(&data[6..8]);
2152 self.num_authorities = u16_from_be_slice(&data[8..10]);
2153 self.num_additionals = u16_from_be_slice(&data[10..12]);
2154
2155 self.offset = MSG_HEADER_LEN;
2156
2157 trace!(
2158 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2159 self.id,
2160 self.num_questions,
2161 self.num_answers,
2162 self.num_authorities,
2163 self.num_additionals
2164 );
2165 Ok(())
2166 }
2167
2168 fn read_questions(&mut self) -> Result<()> {
2169 trace!("read_questions: {}", &self.num_questions);
2170 for i in 0..self.num_questions {
2171 let name = self.read_name()?;
2172
2173 let data = &self.data[self.offset..];
2174 if data.len() < 4 {
2175 return Err(Error::Msg(format!(
2176 "DNS incoming: question idx {} too short: {}",
2177 i,
2178 data.len()
2179 )));
2180 }
2181 let ty = u16_from_be_slice(&data[..2]);
2182 let class = u16_from_be_slice(&data[2..4]);
2183 self.offset += 4;
2184
2185 let Some(rr_type) = RRType::from_u16(ty) else {
2186 return Err(Error::Msg(format!(
2187 "DNS incoming: question idx {i} qtype unknown: {ty}",
2188 )));
2189 };
2190
2191 self.questions.push(DnsQuestion {
2192 entry: DnsEntry::new(name, rr_type, class),
2193 });
2194 }
2195 Ok(())
2196 }
2197
2198 fn read_answers(&mut self) -> Result<()> {
2199 self.answers = self.read_rr_records(self.num_answers)?;
2200 Ok(())
2201 }
2202
2203 fn read_authorities(&mut self) -> Result<()> {
2204 self.authorities = self.read_rr_records(self.num_authorities)?;
2205 Ok(())
2206 }
2207
2208 fn read_additional(&mut self) -> Result<()> {
2209 self.additional = self.read_rr_records(self.num_additionals)?;
2210 Ok(())
2211 }
2212
2213 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2215 trace!("read_rr_records: {}", count);
2216 let mut rr_records = Vec::new();
2217
2218 const RR_HEADER_REMAIN: usize = 10;
2244
2245 for _ in 0..count {
2246 let name = self.read_name()?;
2247 let slice = &self.data[self.offset..];
2248
2249 if slice.len() < RR_HEADER_REMAIN {
2250 return Err(Error::Msg(format!(
2251 "read_others: RR '{}' is too short after name: {} bytes",
2252 &name,
2253 slice.len()
2254 )));
2255 }
2256
2257 let ty = u16_from_be_slice(&slice[..2]);
2258 let class = u16_from_be_slice(&slice[2..4]);
2259 let mut ttl = u32_from_be_slice(&slice[4..8]);
2260 if ttl == 0 && self.is_response() {
2261 ttl = 1;
2268 }
2269 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2270 self.offset += RR_HEADER_REMAIN;
2271 let next_offset = self.offset + rdata_len;
2272
2273 if next_offset > self.data.len() {
2275 return Err(Error::Msg(format!(
2276 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2277 self.data.len() - self.offset
2278 )));
2279 }
2280
2281 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2283 None => None,
2284
2285 Some(rr_type) => match rr_type {
2286 RRType::CNAME | RRType::PTR => {
2287 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
2288 }
2289 RRType::TXT => {
2290 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
2291 }
2292 RRType::SRV => Some(
2293 DnsSrv::new(
2294 &name,
2295 class,
2296 ttl,
2297 self.read_u16()?,
2298 self.read_u16()?,
2299 self.read_u16()?,
2300 self.read_name()?,
2301 )
2302 .boxed(),
2303 ),
2304 RRType::HINFO => Some(
2305 DnsHostInfo::new(
2306 &name,
2307 rr_type,
2308 class,
2309 ttl,
2310 self.read_char_string()?,
2311 self.read_char_string()?,
2312 )
2313 .boxed(),
2314 ),
2315 RRType::A => Some(
2316 DnsAddress::new(
2317 &name,
2318 rr_type,
2319 class,
2320 ttl,
2321 self.read_ipv4()?.into(),
2322 self.interface_id.clone(),
2323 )
2324 .boxed(),
2325 ),
2326 RRType::AAAA => Some(
2327 DnsAddress::new(
2328 &name,
2329 rr_type,
2330 class,
2331 ttl,
2332 self.read_ipv6()?.into(),
2333 self.interface_id.clone(),
2334 )
2335 .boxed(),
2336 ),
2337 RRType::NSEC => Some(
2338 DnsNSec::new(
2339 &name,
2340 class,
2341 ttl,
2342 self.read_name()?,
2343 self.read_type_bitmap()?,
2344 )
2345 .boxed(),
2346 ),
2347 _ => None,
2348 },
2349 };
2350
2351 if let Some(record) = rec {
2352 trace!("read_rr_records: {:?}", &record);
2353 rr_records.push(record);
2354 } else {
2355 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2356 self.offset += rdata_len;
2357 }
2358
2359 if self.offset != next_offset {
2361 return Err(Error::Msg(format!(
2362 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2363 ty, self.offset, next_offset,
2364 )));
2365 }
2366 }
2367
2368 Ok(rr_records)
2369 }
2370
2371 fn read_char_string(&mut self) -> Result<String> {
2372 let length = self.data[self.offset];
2373 self.offset += 1;
2374 self.read_string(length as usize)
2375 }
2376
2377 fn read_u16(&mut self) -> Result<u16> {
2378 let slice = &self.data[self.offset..];
2379 if slice.len() < U16_SIZE {
2380 return Err(Error::Msg(format!(
2381 "read_u16: slice len is only {}",
2382 slice.len()
2383 )));
2384 }
2385 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2386 self.offset += U16_SIZE;
2387 Ok(num)
2388 }
2389
2390 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2392 if self.data.len() < self.offset + 2 {
2401 return Err(Error::Msg(format!(
2402 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2403 self.data.len(),
2404 self.offset
2405 )));
2406 }
2407
2408 let block_num = self.data[self.offset];
2409 self.offset += 1;
2410 if block_num != 0 {
2411 return Err(Error::Msg(format!(
2412 "NSEC block number is not 0: {block_num}"
2413 )));
2414 }
2415
2416 let block_len = self.data[self.offset] as usize;
2417 if !(1..=32).contains(&block_len) {
2418 return Err(Error::Msg(format!(
2419 "NSEC block length must be in the range 1-32: {block_len}"
2420 )));
2421 }
2422 self.offset += 1;
2423
2424 let end = self.offset + block_len;
2425 if end > self.data.len() {
2426 return Err(Error::Msg(format!(
2427 "NSEC block overflow: {} over RData len {}",
2428 end,
2429 self.data.len()
2430 )));
2431 }
2432 let bitmap = self.data[self.offset..end].to_vec();
2433 self.offset += block_len;
2434
2435 Ok(bitmap)
2436 }
2437
2438 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2439 if self.data.len() < self.offset + length {
2440 return Err(e_fmt!(
2441 "DNS Incoming: not enough data to read a chunk of data"
2442 ));
2443 }
2444
2445 let v = self.data[self.offset..self.offset + length].to_vec();
2446 self.offset += length;
2447 Ok(v)
2448 }
2449
2450 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2451 if self.data.len() < self.offset + 4 {
2452 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2453 }
2454
2455 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2456 .try_into()
2457 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2458 self.offset += bytes.len();
2459 Ok(Ipv4Addr::from(bytes))
2460 }
2461
2462 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2463 if self.data.len() < self.offset + 16 {
2464 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2465 }
2466
2467 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2468 .try_into()
2469 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2470 self.offset += bytes.len();
2471 Ok(Ipv6Addr::from(bytes))
2472 }
2473
2474 fn read_string(&mut self, length: usize) -> Result<String> {
2475 if self.data.len() < self.offset + length {
2476 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2477 }
2478
2479 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2480 .map_err(|e| Error::Msg(e.to_string()))?;
2481 self.offset += length;
2482 Ok(s.to_string())
2483 }
2484
2485 fn read_name(&mut self) -> Result<String> {
2490 let data = &self.data[..];
2491 let start_offset = self.offset;
2492 let mut offset = start_offset;
2493 let mut name = "".to_string();
2494 let mut at_end = false;
2495
2496 loop {
2507 if offset >= data.len() {
2508 return Err(Error::Msg(format!(
2509 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2510 offset,
2511 data.len(),
2512 self
2513 )));
2514 }
2515 let length = data[offset];
2516
2517 if length == 0 {
2521 if !at_end {
2522 self.offset = offset + 1;
2523 }
2524 break; }
2526
2527 match length & 0xC0 {
2529 0x00 => {
2530 offset += 1;
2532 let ending = offset + length as usize;
2533
2534 if ending > data.len() {
2536 return Err(Error::Msg(format!(
2537 "read_name: ending {} exceeds data length {}",
2538 ending,
2539 data.len()
2540 )));
2541 }
2542
2543 name += str::from_utf8(&data[offset..ending])
2544 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {e}")))?;
2545 name += ".";
2546 offset += length as usize;
2547 }
2548 0xC0 => {
2549 let slice = &data[offset..];
2552 if slice.len() < U16_SIZE {
2553 return Err(Error::Msg(format!(
2554 "read_name: u16 slice len is only {}",
2555 slice.len()
2556 )));
2557 }
2558 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2559 if pointer >= start_offset {
2560 return Err(Error::Msg(format!(
2562 "Invalid name compression: pointer {} must be less than the start offset {}",
2563 &pointer, &start_offset
2564 )));
2565 }
2566
2567 if !at_end {
2569 self.offset = offset + U16_SIZE;
2570 at_end = true;
2571 }
2572 offset = pointer;
2573 }
2574 _ => {
2575 return Err(Error::Msg(format!(
2576 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2577 length,
2578 offset,
2579 &data[..offset]
2580 )));
2581 }
2582 };
2583 }
2584
2585 Ok(name)
2586 }
2587}
2588
2589const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2590 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2591 u16::from_be_bytes(u8_array)
2592}
2593
2594const fn u32_from_be_slice(s: &[u8]) -> u32 {
2595 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2596 u32::from_be_bytes(u8_array)
2597}
2598
2599const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2602 created + (ttl * percent * 10) as u64
2605}