1#[cfg(feature = "logging")]
8use crate::log::{debug, 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#[non_exhaustive]
128pub enum ScopedIp {
129 V4(ScopedIpV4),
130 V6(ScopedIpV6),
131}
132
133impl ScopedIp {
134 pub const fn to_ip_addr(&self) -> IpAddr {
135 match self {
136 ScopedIp::V4(v4) => IpAddr::V4(v4.addr),
137 ScopedIp::V6(v6) => IpAddr::V6(v6.addr),
138 }
139 }
140
141 pub const fn is_ipv4(&self) -> bool {
142 matches!(self, ScopedIp::V4(_))
143 }
144
145 pub const fn is_ipv6(&self) -> bool {
146 matches!(self, ScopedIp::V6(_))
147 }
148
149 pub const fn is_loopback(&self) -> bool {
150 match self {
151 ScopedIp::V4(v4) => v4.addr.is_loopback(),
152 ScopedIp::V6(v6) => v6.addr.is_loopback(),
153 }
154 }
155}
156
157impl From<IpAddr> for ScopedIp {
158 fn from(ip: IpAddr) -> Self {
159 match ip {
160 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
161 addr: v4,
162 interface_ids: vec![],
163 }),
164 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
165 addr: v6,
166 scope_id: InterfaceId::default(),
167 }),
168 }
169 }
170}
171
172impl From<&Interface> for ScopedIp {
173 fn from(interface: &Interface) -> Self {
174 match interface.ip() {
175 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
176 addr: v4,
177 interface_ids: vec![InterfaceId::from(interface)],
178 }),
179 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
180 addr: v6,
181 scope_id: InterfaceId::from(interface),
182 }),
183 }
184 }
185}
186
187impl fmt::Display for ScopedIp {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 match self {
190 ScopedIp::V4(v4) => write!(f, "{}", v4.addr),
191 ScopedIp::V6(v6) => {
192 if v6.scope_id.index != 0 && is_unicast_link_local(&v6.addr) {
193 #[cfg(windows)]
194 {
195 write!(f, "{}%{}", v6.addr, v6.scope_id.index)
196 }
197 #[cfg(not(windows))]
198 {
199 write!(f, "{}%{}", v6.addr, v6.scope_id.name)
200 }
201 } else {
202 write!(f, "{}", v6.addr)
203 }
204 }
205 }
206 }
207}
208
209#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
213#[non_exhaustive]
214#[repr(u16)]
215pub enum RRType {
216 A = 1,
218
219 CNAME = 5,
221
222 PTR = 12,
224
225 HINFO = 13,
227
228 TXT = 16,
230
231 AAAA = 28,
233
234 SRV = 33,
236
237 NSEC = 47,
239
240 ANY = 255,
242}
243
244impl RRType {
245 pub const fn from_u16(value: u16) -> Option<Self> {
247 match value {
248 1 => Some(RRType::A),
249 5 => Some(RRType::CNAME),
250 12 => Some(RRType::PTR),
251 13 => Some(RRType::HINFO),
252 16 => Some(RRType::TXT),
253 28 => Some(RRType::AAAA),
254 33 => Some(RRType::SRV),
255 47 => Some(RRType::NSEC),
256 255 => Some(RRType::ANY),
257 _ => None,
258 }
259 }
260}
261
262impl fmt::Display for RRType {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 match self {
265 RRType::A => write!(f, "TYPE_A"),
266 RRType::CNAME => write!(f, "TYPE_CNAME"),
267 RRType::PTR => write!(f, "TYPE_PTR"),
268 RRType::HINFO => write!(f, "TYPE_HINFO"),
269 RRType::TXT => write!(f, "TYPE_TXT"),
270 RRType::AAAA => write!(f, "TYPE_AAAA"),
271 RRType::SRV => write!(f, "TYPE_SRV"),
272 RRType::NSEC => write!(f, "TYPE_NSEC"),
273 RRType::ANY => write!(f, "TYPE_ANY"),
274 }
275 }
276}
277
278pub const CLASS_IN: u16 = 1;
280pub const CLASS_MASK: u16 = 0x7FFF;
281
282pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
284
285pub const MAX_MSG_ABSOLUTE: usize = 8972;
290
291const MSG_HEADER_LEN: usize = 12;
292
293pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
305
306pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
308
309pub const FLAGS_AA: u16 = 0x0400;
311
312pub const FLAGS_TC: u16 = 0x0200;
323
324pub type DnsRecordBox = Box<dyn DnsRecordExt>;
326
327impl Clone for DnsRecordBox {
328 fn clone(&self) -> Self {
329 self.clone_box()
330 }
331}
332
333const U16_SIZE: usize = 2;
334
335#[inline]
337pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
338 match address {
339 IpAddr::V4(_) => RRType::A,
340 IpAddr::V6(_) => RRType::AAAA,
341 }
342}
343
344#[derive(Eq, PartialEq, Debug, Clone)]
345pub struct DnsEntry {
346 pub(crate) name: String, pub(crate) ty: RRType,
348 class: u16,
349 cache_flush: bool,
350}
351
352impl DnsEntry {
353 const fn new(name: String, ty: RRType, class: u16) -> Self {
354 Self {
355 name,
356 ty,
357 class: class & CLASS_MASK,
358 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
359 }
360 }
361}
362
363pub trait DnsEntryExt: fmt::Debug {
365 fn entry_name(&self) -> &str;
366
367 fn entry_type(&self) -> RRType;
368}
369
370#[derive(Debug)]
372pub struct DnsQuestion {
373 pub(crate) entry: DnsEntry,
374}
375
376impl DnsEntryExt for DnsQuestion {
377 fn entry_name(&self) -> &str {
378 &self.entry.name
379 }
380
381 fn entry_type(&self) -> RRType {
382 self.entry.ty
383 }
384}
385
386#[derive(Debug, Clone)]
390pub struct DnsRecord {
391 pub(crate) entry: DnsEntry,
392 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
402}
403
404impl DnsRecord {
405 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
406 let created = current_time_millis();
407
408 let refresh = get_expiration_time(created, ttl, 80);
412
413 let expires = get_expiration_time(created, ttl, 100);
414
415 Self {
416 entry: DnsEntry::new(name.to_string(), ty, class),
417 ttl,
418 created,
419 expires,
420 refresh,
421 new_name: None,
422 }
423 }
424
425 pub const fn get_ttl(&self) -> u32 {
426 self.ttl
427 }
428
429 pub const fn get_expire_time(&self) -> u64 {
430 self.expires
431 }
432
433 pub const fn get_refresh_time(&self) -> u64 {
434 self.refresh
435 }
436
437 pub const fn is_expired(&self, now: u64) -> bool {
438 now >= self.expires
439 }
440
441 pub const fn expires_soon(&self, now: u64) -> bool {
445 now + 1000 >= self.expires
446 }
447
448 pub const fn refresh_due(&self, now: u64) -> bool {
449 now >= self.refresh
450 }
451
452 pub fn halflife_passed(&self, now: u64) -> bool {
454 let halflife = get_expiration_time(self.created, self.ttl, 50);
455 now > halflife
456 }
457
458 pub fn is_unique(&self) -> bool {
459 self.entry.cache_flush
460 }
461
462 pub fn refresh_no_more(&mut self) {
465 self.refresh = get_expiration_time(self.created, self.ttl, 100);
466 }
467
468 pub fn refresh_maybe(&mut self, now: u64) -> bool {
470 if self.is_expired(now) || !self.refresh_due(now) {
471 return false;
472 }
473
474 trace!(
475 "{} qtype {} is due to refresh",
476 &self.entry.name,
477 self.entry.ty
478 );
479
480 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
487 self.refresh = get_expiration_time(self.created, self.ttl, 85);
488 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
489 self.refresh = get_expiration_time(self.created, self.ttl, 90);
490 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
491 self.refresh = get_expiration_time(self.created, self.ttl, 95);
492 } else {
493 self.refresh_no_more();
494 }
495
496 true
497 }
498
499 fn get_remaining_ttl(&self, now: u64) -> u32 {
501 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
502 cmp::max(0, remaining_millis / 1000) as u32
503 }
504
505 pub const fn get_created(&self) -> u64 {
507 self.created
508 }
509
510 fn set_expire(&mut self, expire_at: u64) {
512 self.expires = expire_at;
513 }
514
515 fn reset_ttl(&mut self, other: &Self) {
516 self.ttl = other.ttl;
517 self.created = other.created;
518 self.expires = get_expiration_time(self.created, self.ttl, 100);
519 self.refresh = if self.ttl > 1 {
520 get_expiration_time(self.created, self.ttl, 80)
521 } else {
522 self.expires
525 };
526 }
527
528 pub fn update_ttl(&mut self, now: u64) {
530 if now > self.created {
531 let elapsed = now - self.created;
532 self.ttl -= (elapsed / 1000) as u32;
533 }
534 }
535
536 pub fn set_new_name(&mut self, new_name: String) {
537 if new_name == self.entry.name {
538 self.new_name = None;
539 } else {
540 self.new_name = Some(new_name);
541 }
542 }
543
544 pub fn get_new_name(&self) -> Option<&str> {
545 self.new_name.as_deref()
546 }
547
548 pub(crate) fn get_name(&self) -> &str {
550 self.new_name.as_deref().unwrap_or(&self.entry.name)
551 }
552
553 pub fn get_original_name(&self) -> &str {
554 &self.entry.name
555 }
556}
557
558impl PartialEq for DnsRecord {
559 fn eq(&self, other: &Self) -> bool {
560 self.entry == other.entry
561 }
562}
563
564pub trait DnsRecordExt: fmt::Debug {
566 fn get_record(&self) -> &DnsRecord;
567 fn get_record_mut(&mut self) -> &mut DnsRecord;
568 fn write(&self, packet: &mut DnsOutPacket);
569 fn any(&self) -> &dyn Any;
570
571 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
573
574 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
576
577 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
580
581 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
583 match self.get_class().cmp(&other.get_class()) {
597 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
598 cmp::Ordering::Equal => self.compare_rdata(other),
599 not_equal => not_equal,
600 },
601 not_equal => not_equal,
602 }
603 }
604
605 fn rdata_print(&self) -> String;
607
608 fn get_class(&self) -> u16 {
610 self.get_record().entry.class
611 }
612
613 fn get_cache_flush(&self) -> bool {
614 self.get_record().entry.cache_flush
615 }
616
617 fn get_name(&self) -> &str {
619 self.get_record().get_name()
620 }
621
622 fn get_type(&self) -> RRType {
623 self.get_record().entry.ty
624 }
625
626 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
629 self.get_record_mut().reset_ttl(other.get_record());
630 }
631
632 fn get_created(&self) -> u64 {
633 self.get_record().get_created()
634 }
635
636 fn get_expire(&self) -> u64 {
637 self.get_record().get_expire_time()
638 }
639
640 fn set_expire(&mut self, expire_at: u64) {
641 self.get_record_mut().set_expire(expire_at);
642 }
643
644 fn set_expire_sooner(&mut self, expire_at: u64) {
646 if expire_at < self.get_expire() {
647 self.get_record_mut().set_expire(expire_at);
648 }
649 }
650
651 fn expires_soon(&self, now: u64) -> bool {
653 self.get_record().expires_soon(now)
654 }
655
656 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
659 if self.get_record_mut().refresh_maybe(now) {
660 Some(self.get_record().get_refresh_time())
661 } else {
662 None
663 }
664 }
665
666 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
669 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
670 }
671
672 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
674 for answer in msg.answers.iter() {
675 if self.suppressed_by_answer(answer.as_ref()) {
676 return true;
677 }
678 }
679 false
680 }
681
682 fn clone_box(&self) -> DnsRecordBox;
683
684 fn boxed(self) -> DnsRecordBox;
685}
686
687#[derive(Debug, Clone)]
689pub(crate) struct DnsAddress {
690 pub(crate) record: DnsRecord,
691 address: IpAddr,
692 pub(crate) interface_id: InterfaceId,
693}
694
695impl DnsAddress {
696 pub fn new(
697 name: &str,
698 ty: RRType,
699 class: u16,
700 ttl: u32,
701 address: IpAddr,
702 interface_id: InterfaceId,
703 ) -> Self {
704 let record = DnsRecord::new(name, ty, class, ttl);
705 Self {
706 record,
707 address,
708 interface_id,
709 }
710 }
711
712 pub fn address(&self) -> ScopedIp {
713 match self.address {
714 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
715 addr: v4,
716 interface_ids: vec![self.interface_id.clone()],
717 }),
718 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
719 addr: v6,
720 scope_id: self.interface_id.clone(),
721 }),
722 }
723 }
724}
725
726impl DnsRecordExt for DnsAddress {
727 fn get_record(&self) -> &DnsRecord {
728 &self.record
729 }
730
731 fn get_record_mut(&mut self) -> &mut DnsRecord {
732 &mut self.record
733 }
734
735 fn write(&self, packet: &mut DnsOutPacket) {
736 match self.address {
737 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
738 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
739 };
740 }
741
742 fn any(&self) -> &dyn Any {
743 self
744 }
745
746 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
747 if let Some(other_a) = other.any().downcast_ref::<Self>() {
748 return self.address == other_a.address
749 && self.record.entry == other_a.record.entry
750 && self.interface_id == other_a.interface_id;
751 }
752 false
753 }
754
755 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
756 if let Some(other_a) = other.any().downcast_ref::<Self>() {
757 return self.address == other_a.address;
758 }
759 false
760 }
761
762 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
763 if let Some(other_a) = other.any().downcast_ref::<Self>() {
764 self.address.cmp(&other_a.address)
765 } else {
766 cmp::Ordering::Greater
767 }
768 }
769
770 fn rdata_print(&self) -> String {
771 format!("{}", self.address)
772 }
773
774 fn clone_box(&self) -> DnsRecordBox {
775 Box::new(self.clone())
776 }
777
778 fn boxed(self) -> DnsRecordBox {
779 Box::new(self)
780 }
781}
782
783#[derive(Debug, Clone)]
785pub struct DnsPointer {
786 record: DnsRecord,
787 alias: String, }
789
790impl DnsPointer {
791 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
792 let record = DnsRecord::new(name, ty, class, ttl);
793 Self { record, alias }
794 }
795
796 pub fn alias(&self) -> &str {
797 &self.alias
798 }
799}
800
801impl DnsRecordExt for DnsPointer {
802 fn get_record(&self) -> &DnsRecord {
803 &self.record
804 }
805
806 fn get_record_mut(&mut self) -> &mut DnsRecord {
807 &mut self.record
808 }
809
810 fn write(&self, packet: &mut DnsOutPacket) {
811 packet.write_name(&self.alias);
812 }
813
814 fn any(&self) -> &dyn Any {
815 self
816 }
817
818 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
819 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
820 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
821 }
822 false
823 }
824
825 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
826 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
827 return self.alias == other_ptr.alias;
828 }
829 false
830 }
831
832 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
833 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
834 self.alias.cmp(&other_ptr.alias)
835 } else {
836 cmp::Ordering::Greater
837 }
838 }
839
840 fn rdata_print(&self) -> String {
841 self.alias.clone()
842 }
843
844 fn clone_box(&self) -> DnsRecordBox {
845 Box::new(self.clone())
846 }
847
848 fn boxed(self) -> DnsRecordBox {
849 Box::new(self)
850 }
851}
852
853#[derive(Debug, Clone)]
855pub struct DnsSrv {
856 pub(crate) record: DnsRecord,
857 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
860 port: u16,
861}
862
863impl DnsSrv {
864 pub fn new(
865 name: &str,
866 class: u16,
867 ttl: u32,
868 priority: u16,
869 weight: u16,
870 port: u16,
871 host: String,
872 ) -> Self {
873 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
874 Self {
875 record,
876 priority,
877 weight,
878 host,
879 port,
880 }
881 }
882
883 pub fn host(&self) -> &str {
884 &self.host
885 }
886
887 pub fn port(&self) -> u16 {
888 self.port
889 }
890
891 pub fn set_host(&mut self, host: String) {
892 self.host = host;
893 }
894}
895
896impl DnsRecordExt for DnsSrv {
897 fn get_record(&self) -> &DnsRecord {
898 &self.record
899 }
900
901 fn get_record_mut(&mut self) -> &mut DnsRecord {
902 &mut self.record
903 }
904
905 fn write(&self, packet: &mut DnsOutPacket) {
906 packet.write_short(self.priority);
907 packet.write_short(self.weight);
908 packet.write_short(self.port);
909 packet.write_name(&self.host);
910 }
911
912 fn any(&self) -> &dyn Any {
913 self
914 }
915
916 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
917 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
918 return self.host == other_svc.host
919 && self.port == other_svc.port
920 && self.weight == other_svc.weight
921 && self.priority == other_svc.priority
922 && self.record.entry == other_svc.record.entry;
923 }
924 false
925 }
926
927 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
928 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
929 return self.host == other_srv.host
930 && self.port == other_srv.port
931 && self.weight == other_srv.weight
932 && self.priority == other_srv.priority;
933 }
934 false
935 }
936
937 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
938 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
939 return cmp::Ordering::Greater;
940 };
941
942 match self
944 .priority
945 .to_be_bytes()
946 .cmp(&other_srv.priority.to_be_bytes())
947 {
948 cmp::Ordering::Equal => {
949 match self
951 .weight
952 .to_be_bytes()
953 .cmp(&other_srv.weight.to_be_bytes())
954 {
955 cmp::Ordering::Equal => {
956 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
958 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
959 not_equal => not_equal,
960 }
961 }
962 not_equal => not_equal,
963 }
964 }
965 not_equal => not_equal,
966 }
967 }
968
969 fn rdata_print(&self) -> String {
970 format!(
971 "priority: {}, weight: {}, port: {}, host: {}",
972 self.priority, self.weight, self.port, self.host
973 )
974 }
975
976 fn clone_box(&self) -> DnsRecordBox {
977 Box::new(self.clone())
978 }
979
980 fn boxed(self) -> DnsRecordBox {
981 Box::new(self)
982 }
983}
984
985#[derive(Clone)]
1000pub struct DnsTxt {
1001 pub(crate) record: DnsRecord,
1002 text: Vec<u8>,
1003}
1004
1005impl DnsTxt {
1006 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1007 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1008 Self { record, text }
1009 }
1010
1011 pub fn text(&self) -> &[u8] {
1012 &self.text
1013 }
1014}
1015
1016impl DnsRecordExt for DnsTxt {
1017 fn get_record(&self) -> &DnsRecord {
1018 &self.record
1019 }
1020
1021 fn get_record_mut(&mut self) -> &mut DnsRecord {
1022 &mut self.record
1023 }
1024
1025 fn write(&self, packet: &mut DnsOutPacket) {
1026 packet.write_bytes(&self.text);
1027 }
1028
1029 fn any(&self) -> &dyn Any {
1030 self
1031 }
1032
1033 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1034 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1035 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1036 }
1037 false
1038 }
1039
1040 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1041 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1042 return self.text == other_txt.text;
1043 }
1044 false
1045 }
1046
1047 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1048 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1049 self.text.cmp(&other_txt.text)
1050 } else {
1051 cmp::Ordering::Greater
1052 }
1053 }
1054
1055 fn rdata_print(&self) -> String {
1056 format!("{:?}", decode_txt(&self.text))
1057 }
1058
1059 fn clone_box(&self) -> DnsRecordBox {
1060 Box::new(self.clone())
1061 }
1062
1063 fn boxed(self) -> DnsRecordBox {
1064 Box::new(self)
1065 }
1066}
1067
1068impl fmt::Debug for DnsTxt {
1069 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1070 let properties = decode_txt(&self.text);
1071 write!(
1072 f,
1073 "DnsTxt {{ record: {:?}, text: {:?} }}",
1074 self.record, properties
1075 )
1076 }
1077}
1078
1079fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
1081 let mut properties = Vec::new();
1082 let mut offset = 0;
1083 while offset < txt.len() {
1084 let length = txt[offset] as usize;
1085 if length == 0 {
1086 break; }
1088 offset += 1; let offset_end = offset + length;
1091 if offset_end > txt.len() {
1092 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
1093 break; }
1095 let kv_bytes = &txt[offset..offset_end];
1096
1097 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
1099 || (kv_bytes.to_vec(), None),
1100 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
1101 );
1102
1103 match String::from_utf8(k) {
1105 Ok(k_string) => {
1106 properties.push(TxtProperty {
1107 key: k_string,
1108 val: v,
1109 });
1110 }
1111 Err(e) => trace!("ERROR: convert to String from key: {}", e),
1112 }
1113
1114 offset += length;
1115 }
1116
1117 properties
1118}
1119
1120#[derive(Clone, PartialEq, Eq)]
1122pub struct TxtProperty {
1123 key: String,
1125
1126 val: Option<Vec<u8>>,
1130}
1131
1132impl TxtProperty {
1133 pub fn val_str(&self) -> &str {
1135 self.val
1136 .as_ref()
1137 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
1138 }
1139}
1140
1141impl<K, V> From<&(K, V)> for TxtProperty
1143where
1144 K: ToString,
1145 V: ToString,
1146{
1147 fn from(prop: &(K, V)) -> Self {
1148 Self {
1149 key: prop.0.to_string(),
1150 val: Some(prop.1.to_string().into_bytes()),
1151 }
1152 }
1153}
1154
1155impl<K, V> From<(K, V)> for TxtProperty
1156where
1157 K: ToString,
1158 V: AsRef<[u8]>,
1159{
1160 fn from(prop: (K, V)) -> Self {
1161 Self {
1162 key: prop.0.to_string(),
1163 val: Some(prop.1.as_ref().into()),
1164 }
1165 }
1166}
1167
1168impl From<&str> for TxtProperty {
1170 fn from(key: &str) -> Self {
1171 Self {
1172 key: key.to_string(),
1173 val: None,
1174 }
1175 }
1176}
1177
1178impl fmt::Display for TxtProperty {
1179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1180 write!(f, "{}={}", self.key, self.val_str())
1181 }
1182}
1183
1184impl fmt::Debug for TxtProperty {
1188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1189 let val_string = self.val.as_ref().map_or_else(
1190 || "None".to_string(),
1191 |v| {
1192 std::str::from_utf8(&v[..]).map_or_else(
1193 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1194 |s| format!("Some(\"{s}\")"),
1195 )
1196 },
1197 );
1198
1199 write!(
1200 f,
1201 "TxtProperty {{key: \"{}\", val: {}}}",
1202 &self.key, &val_string,
1203 )
1204 }
1205}
1206
1207const HEX_TABLE: [char; 16] = [
1208 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1209];
1210
1211fn u8_slice_to_hex(slice: &[u8]) -> String {
1215 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1216 hex.push_str("0x");
1217 for b in slice {
1218 hex.push(HEX_TABLE[(b >> 4) as usize]);
1219 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1220 }
1221 hex
1222}
1223
1224#[derive(Debug, Clone)]
1226struct DnsHostInfo {
1227 record: DnsRecord,
1228 cpu: String,
1229 os: String,
1230}
1231
1232impl DnsHostInfo {
1233 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1234 let record = DnsRecord::new(name, ty, class, ttl);
1235 Self { record, cpu, os }
1236 }
1237}
1238
1239impl DnsRecordExt for DnsHostInfo {
1240 fn get_record(&self) -> &DnsRecord {
1241 &self.record
1242 }
1243
1244 fn get_record_mut(&mut self) -> &mut DnsRecord {
1245 &mut self.record
1246 }
1247
1248 fn write(&self, packet: &mut DnsOutPacket) {
1249 debug!("Writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1250 packet.write_bytes(self.cpu.as_bytes());
1251 packet.write_bytes(self.os.as_bytes());
1252 }
1253
1254 fn any(&self) -> &dyn Any {
1255 self
1256 }
1257
1258 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1259 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1260 return self.cpu == other_hinfo.cpu
1261 && self.os == other_hinfo.os
1262 && self.record.entry == other_hinfo.record.entry;
1263 }
1264 false
1265 }
1266
1267 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1268 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1269 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1270 }
1271 false
1272 }
1273
1274 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1275 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1276 match self.cpu.cmp(&other_hinfo.cpu) {
1277 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1278 ordering => ordering,
1279 }
1280 } else {
1281 cmp::Ordering::Greater
1282 }
1283 }
1284
1285 fn rdata_print(&self) -> String {
1286 format!("cpu: {}, os: {}", self.cpu, self.os)
1287 }
1288
1289 fn clone_box(&self) -> DnsRecordBox {
1290 Box::new(self.clone())
1291 }
1292
1293 fn boxed(self) -> DnsRecordBox {
1294 Box::new(self)
1295 }
1296}
1297
1298#[derive(Debug, Clone)]
1304pub struct DnsNSec {
1305 record: DnsRecord,
1306 next_domain: String,
1307 type_bitmap: Vec<u8>,
1308}
1309
1310impl DnsNSec {
1311 pub fn new(
1312 name: &str,
1313 class: u16,
1314 ttl: u32,
1315 next_domain: String,
1316 type_bitmap: Vec<u8>,
1317 ) -> Self {
1318 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1319 Self {
1320 record,
1321 next_domain,
1322 type_bitmap,
1323 }
1324 }
1325
1326 pub fn _types(&self) -> Vec<u16> {
1328 let mut bit_num = 0;
1337 let mut results = Vec::new();
1338
1339 for byte in self.type_bitmap.iter() {
1340 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1344 if (byte & bit_mask) != 0 {
1345 results.push(bit_num);
1346 }
1347 bit_num += 1;
1348 bit_mask >>= 1; }
1350 }
1351 results
1352 }
1353}
1354
1355impl DnsRecordExt for DnsNSec {
1356 fn get_record(&self) -> &DnsRecord {
1357 &self.record
1358 }
1359
1360 fn get_record_mut(&mut self) -> &mut DnsRecord {
1361 &mut self.record
1362 }
1363
1364 fn write(&self, packet: &mut DnsOutPacket) {
1365 packet.write_bytes(self.next_domain.as_bytes());
1366 packet.write_bytes(&self.type_bitmap);
1367 }
1368
1369 fn any(&self) -> &dyn Any {
1370 self
1371 }
1372
1373 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1374 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1375 return self.next_domain == other_record.next_domain
1376 && self.type_bitmap == other_record.type_bitmap
1377 && self.record.entry == other_record.record.entry;
1378 }
1379 false
1380 }
1381
1382 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1383 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1384 return self.next_domain == other_record.next_domain
1385 && self.type_bitmap == other_record.type_bitmap;
1386 }
1387 false
1388 }
1389
1390 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1391 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1392 match self.next_domain.cmp(&other_nsec.next_domain) {
1393 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1394 ordering => ordering,
1395 }
1396 } else {
1397 cmp::Ordering::Greater
1398 }
1399 }
1400
1401 fn rdata_print(&self) -> String {
1402 format!(
1403 "next_domain: {}, type_bitmap len: {}",
1404 self.next_domain,
1405 self.type_bitmap.len()
1406 )
1407 }
1408
1409 fn clone_box(&self) -> DnsRecordBox {
1410 Box::new(self.clone())
1411 }
1412
1413 fn boxed(self) -> DnsRecordBox {
1414 Box::new(self)
1415 }
1416}
1417
1418#[derive(PartialEq)]
1419enum PacketState {
1420 Init = 0,
1421 Finished = 1,
1422}
1423
1424pub struct DnsOutPacket {
1426 data: Vec<u8>,
1428
1429 state: PacketState,
1431
1432 names: HashMap<String, u16>,
1434}
1435
1436impl DnsOutPacket {
1437 fn new() -> Self {
1438 Self {
1439 data: vec![0; MSG_HEADER_LEN],
1440 state: PacketState::Init,
1441 names: HashMap::new(),
1442 }
1443 }
1444
1445 pub fn size(&self) -> usize {
1446 self.data.len()
1447 }
1448
1449 pub fn as_bytes(&self) -> &[u8] {
1450 &self.data
1451 }
1452
1453 fn write_question(&mut self, question: &DnsQuestion) {
1454 self.write_name(&question.entry.name);
1455 self.write_short(question.entry.ty as u16);
1456 self.write_short(question.entry.class);
1457 }
1458
1459 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> bool {
1463 let start_size = self.size();
1464
1465 let record = record_ext.get_record();
1466 self.write_name(record.get_name());
1467 self.write_short(record.entry.ty as u16);
1468 if record.entry.cache_flush {
1469 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1471 } else {
1472 self.write_short(record.entry.class);
1473 }
1474
1475 if now == 0 {
1476 self.write_u32(record.ttl);
1477 } else {
1478 self.write_u32(record.get_remaining_ttl(now));
1479 }
1480
1481 self.write_short(0);
1483 let record_offset = self.size();
1484 record_ext.write(self);
1485 self.insert_short(record_offset - 2, (self.size() - record_offset) as u16);
1486
1487 if self.size() > MAX_MSG_ABSOLUTE {
1488 self.data.truncate(start_size);
1489 self.state = PacketState::Finished;
1490 return false;
1491 }
1492
1493 true
1494 }
1495
1496 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1497 self.data[index..index + 2].copy_from_slice(&value.to_be_bytes());
1498 }
1499
1500 fn parse_escaped_name(name: &str) -> Vec<String> {
1507 let mut labels = Vec::new();
1508 let mut current_label = String::new();
1509 let mut chars = name.chars().peekable();
1510
1511 while let Some(ch) = chars.next() {
1512 match ch {
1513 '\\' => {
1514 if let Some(&next_ch) = chars.peek() {
1516 match next_ch {
1517 '.' | '\\' => {
1518 chars.next();
1520 current_label.push(next_ch);
1521 }
1522 _ => {
1523 current_label.push(ch);
1525 }
1526 }
1527 } else {
1528 current_label.push(ch);
1530 }
1531 }
1532 '.' => {
1533 if !current_label.is_empty() {
1535 labels.push(current_label.clone());
1536 current_label.clear();
1537 }
1538 }
1539 _ => {
1540 current_label.push(ch);
1541 }
1542 }
1543 }
1544
1545 if !current_label.is_empty() {
1547 labels.push(current_label);
1548 }
1549
1550 labels
1551 }
1552
1553 fn write_name(&mut self, name: &str) {
1579 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1581
1582 let labels = Self::parse_escaped_name(name_to_parse);
1584
1585 if labels.is_empty() {
1586 self.write_byte(0);
1587 return;
1588 }
1589
1590 for (i, label) in labels.iter().enumerate() {
1592 let remaining: String = labels[i..].join(".");
1594
1595 const POINTER_MASK: u16 = 0xC000;
1597 if let Some(&offset) = self.names.get(&remaining) {
1598 let pointer = offset | POINTER_MASK;
1599 self.write_short(pointer);
1600 return;
1601 }
1602
1603 self.names.insert(remaining, self.size() as u16);
1605
1606 self.write_utf8(label);
1608 }
1609
1610 self.write_byte(0);
1612 }
1613
1614 fn write_byte(&mut self, v: u8) {
1615 self.data.push(v);
1616 }
1617
1618 fn write_bytes(&mut self, s: &[u8]) {
1619 self.data.extend(s);
1620 }
1621
1622 fn write_utf8(&mut self, s: &str) {
1623 assert!(s.len() < 64);
1624 self.write_byte(s.len() as u8);
1625 self.write_bytes(s.as_bytes());
1626 }
1627
1628 fn write_u32(&mut self, v: u32) {
1629 self.data.extend(&v.to_be_bytes());
1630 }
1631
1632 fn write_short(&mut self, v: u16) {
1633 self.data.extend(&v.to_be_bytes());
1634 }
1635
1636 fn write_header(
1659 &mut self,
1660 id: u16,
1661 flags: u16,
1662 q_count: u16,
1663 a_count: u16,
1664 auth_count: u16,
1665 addi_count: u16,
1666 ) {
1667 self.insert_short(0, id);
1668 self.insert_short(2, flags);
1669 self.insert_short(4, q_count);
1670 self.insert_short(6, a_count);
1671 self.insert_short(8, auth_count);
1672 self.insert_short(10, addi_count);
1673
1674 self.state = PacketState::Finished;
1675 }
1676}
1677
1678#[derive(Debug)]
1680pub struct DnsOutgoing {
1681 flags: u16,
1682 id: u16,
1683 multicast: bool,
1684 questions: Vec<DnsQuestion>,
1685 answers: Vec<(DnsRecordBox, u64)>,
1686 authorities: Vec<DnsRecordBox>,
1687 additionals: Vec<DnsRecordBox>,
1688 known_answer_count: i64, }
1690
1691impl DnsOutgoing {
1692 pub fn new(flags: u16) -> Self {
1693 Self {
1694 flags,
1695 id: 0,
1696 multicast: true,
1697 questions: Vec::new(),
1698 answers: Vec::new(),
1699 authorities: Vec::new(),
1700 additionals: Vec::new(),
1701 known_answer_count: 0,
1702 }
1703 }
1704
1705 pub fn questions(&self) -> &[DnsQuestion] {
1706 &self.questions
1707 }
1708
1709 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1711 &self.answers
1712 }
1713
1714 pub fn answers_count(&self) -> usize {
1715 self.answers.len()
1716 }
1717
1718 pub fn authorities(&self) -> &[DnsRecordBox] {
1719 &self.authorities
1720 }
1721
1722 pub fn additionals(&self) -> &[DnsRecordBox] {
1723 &self.additionals
1724 }
1725
1726 pub fn known_answer_count(&self) -> i64 {
1727 self.known_answer_count
1728 }
1729
1730 pub fn set_id(&mut self, id: u16) {
1731 self.id = id;
1732 }
1733
1734 pub const fn is_query(&self) -> bool {
1735 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1736 }
1737
1738 const fn is_response(&self) -> bool {
1739 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1740 }
1741
1742 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1776 trace!("add_additional_answer: {:?}", &answer);
1777 self.additionals.push(answer.boxed());
1778 }
1779
1780 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1782 self.answers.push((answer_box, 0));
1783 }
1784
1785 pub fn add_authority(&mut self, record: DnsRecordBox) {
1786 self.authorities.push(record);
1787 }
1788
1789 pub(crate) fn retain_answers<F>(&mut self, mut keep: F)
1791 where
1792 F: FnMut(&DnsRecordBox) -> bool,
1793 {
1794 self.answers.retain(|(record, _)| keep(record));
1795 }
1796
1797 pub(crate) fn retain_additionals<F>(&mut self, mut keep: F)
1799 where
1800 F: FnMut(&DnsRecordBox) -> bool,
1801 {
1802 self.additionals.retain(|record| keep(record));
1803 }
1804
1805 pub fn add_answer(
1808 &mut self,
1809 msg: &DnsIncoming,
1810 answer: impl DnsRecordExt + Send + 'static,
1811 ) -> bool {
1812 trace!("Check for add_answer");
1813 if answer.suppressed_by(msg) {
1814 trace!("my answer is suppressed by incoming msg");
1815 self.known_answer_count += 1;
1816 return false;
1817 }
1818
1819 self.add_answer_at_time(answer, 0)
1820 }
1821
1822 pub fn add_answer_at_time(
1826 &mut self,
1827 answer: impl DnsRecordExt + Send + 'static,
1828 now: u64,
1829 ) -> bool {
1830 if now == 0 || !answer.get_record().is_expired(now) {
1831 trace!("add_answer push: {:?}", &answer);
1832 self.answers.push((answer.boxed(), now));
1833 return true;
1834 }
1835 false
1836 }
1837
1838 pub(crate) fn add_answer_with_additionals(
1847 &mut self,
1848 msg: &DnsIncoming,
1849 service: &ServiceInfo,
1850 intf: &MyIntf,
1851 dns_registry: &DnsRegistry,
1852 is_ipv4: bool,
1853 ) {
1854 let intf_addrs = if is_ipv4 {
1855 service.get_addrs_on_my_intf_v4(intf)
1856 } else {
1857 service.get_addrs_on_my_intf_v6(intf)
1858 };
1859 if intf_addrs.is_empty() {
1860 trace!("No addrs on LAN of intf {:?}", intf);
1861 return;
1862 }
1863
1864 let service_fullname = dns_registry.resolve_name(service.get_fullname());
1866 let hostname = dns_registry.resolve_name(service.get_hostname());
1867
1868 let ptr_added = self.add_answer(
1869 msg,
1870 DnsPointer::new(
1871 service.get_type(),
1872 RRType::PTR,
1873 CLASS_IN,
1874 service.get_other_ttl(),
1875 service_fullname.to_string(),
1876 ),
1877 );
1878
1879 if !ptr_added {
1880 trace!("answer was not added for msg {:?}", msg);
1881 return;
1882 }
1883
1884 if let Some(sub) = service.get_subtype() {
1885 trace!("Adding subdomain {}", sub);
1886 self.add_additional_answer(DnsPointer::new(
1887 sub,
1888 RRType::PTR,
1889 CLASS_IN,
1890 service.get_other_ttl(),
1891 service_fullname.to_string(),
1892 ));
1893 }
1894
1895 self.add_additional_answer(DnsSrv::new(
1898 service_fullname,
1899 CLASS_IN | CLASS_CACHE_FLUSH,
1900 service.get_host_ttl(),
1901 service.get_priority(),
1902 service.get_weight(),
1903 service.get_port(),
1904 hostname.to_string(),
1905 ));
1906
1907 self.add_additional_answer(DnsTxt::new(
1908 service_fullname,
1909 CLASS_IN | CLASS_CACHE_FLUSH,
1910 service.get_other_ttl(),
1911 service.generate_txt(),
1912 ));
1913
1914 for address in intf_addrs {
1915 self.add_additional_answer(DnsAddress::new(
1916 hostname,
1917 ip_address_rr_type(&address),
1918 CLASS_IN | CLASS_CACHE_FLUSH,
1919 service.get_host_ttl(),
1920 address,
1921 intf.into(),
1922 ));
1923 }
1924 }
1925
1926 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1927 let q = DnsQuestion {
1928 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1929 };
1930 self.questions.push(q);
1931 }
1932
1933 pub fn clear_cache_flush_bits(&mut self) {
1938 for (rec, _) in &mut self.answers {
1939 rec.get_record_mut().entry.cache_flush = false;
1940 }
1941 for rec in &mut self.additionals {
1942 rec.get_record_mut().entry.cache_flush = false;
1943 }
1944 for rec in &mut self.authorities {
1945 rec.get_record_mut().entry.cache_flush = false;
1946 }
1947 }
1948
1949 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
1951 let packet_list = self.to_packets();
1952 packet_list.into_iter().map(|p| p.data).collect()
1953 }
1954
1955 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
1957 let mut packet_list = Vec::new();
1958 let mut packet = DnsOutPacket::new();
1959
1960 let mut question_count = self.questions.len() as u16;
1961 let mut answer_count = 0;
1962 let mut auth_count = 0;
1963 let mut addi_count = 0;
1964 let id = if self.multicast { 0 } else { self.id };
1965
1966 for question in self.questions.iter() {
1967 packet.write_question(question);
1968 }
1969
1970 for (answer, time) in self.answers.iter() {
1971 if packet.write_record(answer.as_ref(), *time) {
1972 answer_count += 1;
1973 }
1974 }
1975
1976 for auth in self.authorities.iter() {
1977 auth_count += u16::from(packet.write_record(auth.as_ref(), 0));
1978 }
1979
1980 for addi in self.additionals.iter() {
1981 if packet.write_record(addi.as_ref(), 0) {
1982 addi_count += 1;
1983 continue;
1984 }
1985
1986 if self.is_response() {
1988 break;
1989 }
1990
1991 packet.write_header(
1996 id,
1997 self.flags | FLAGS_TC,
1998 question_count,
1999 answer_count,
2000 auth_count,
2001 addi_count,
2002 );
2003
2004 packet_list.push(packet);
2005
2006 packet = DnsOutPacket::new();
2008 packet.write_record(addi.as_ref(), 0);
2009
2010 question_count = 0;
2011 answer_count = 0;
2012 auth_count = 0;
2013 addi_count = 1;
2014 }
2015
2016 packet.write_header(
2017 id,
2018 self.flags,
2019 question_count,
2020 answer_count,
2021 auth_count,
2022 addi_count,
2023 );
2024
2025 packet_list.push(packet);
2026 packet_list
2027 }
2028}
2029
2030#[derive(Debug)]
2032pub struct DnsIncoming {
2033 offset: usize,
2034 data: Vec<u8>,
2035 questions: Vec<DnsQuestion>,
2036 answers: Vec<DnsRecordBox>,
2037 authorities: Vec<DnsRecordBox>,
2038 additional: Vec<DnsRecordBox>,
2039 id: u16,
2040 flags: u16,
2041 num_questions: u16,
2042 num_answers: u16,
2043 num_authorities: u16,
2044 num_additionals: u16,
2045 interface_id: InterfaceId,
2046}
2047
2048impl DnsIncoming {
2049 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2050 let mut incoming = Self {
2051 offset: 0,
2052 data,
2053 questions: Vec::new(),
2054 answers: Vec::new(),
2055 authorities: Vec::new(),
2056 additional: Vec::new(),
2057 id: 0,
2058 flags: 0,
2059 num_questions: 0,
2060 num_answers: 0,
2061 num_authorities: 0,
2062 num_additionals: 0,
2063 interface_id,
2064 };
2065
2066 incoming.read_header()?;
2086 incoming.read_questions()?;
2087 incoming.read_answers()?;
2088 incoming.read_authorities()?;
2089 incoming.read_additional()?;
2090
2091 Ok(incoming)
2092 }
2093
2094 pub fn id(&self) -> u16 {
2095 self.id
2096 }
2097
2098 pub fn questions(&self) -> &[DnsQuestion] {
2099 &self.questions
2100 }
2101
2102 pub fn answers(&self) -> &[DnsRecordBox] {
2103 &self.answers
2104 }
2105
2106 pub fn authorities(&self) -> &[DnsRecordBox] {
2107 &self.authorities
2108 }
2109
2110 pub fn additionals(&self) -> &[DnsRecordBox] {
2111 &self.additional
2112 }
2113
2114 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2115 &mut self.answers
2116 }
2117
2118 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2119 &mut self.authorities
2120 }
2121
2122 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2123 &mut self.additional
2124 }
2125
2126 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2127 self.answers
2128 .into_iter()
2129 .chain(self.authorities)
2130 .chain(self.additional)
2131 }
2132
2133 pub fn num_additionals(&self) -> u16 {
2134 self.num_additionals
2135 }
2136
2137 pub fn num_authorities(&self) -> u16 {
2138 self.num_authorities
2139 }
2140
2141 pub fn num_questions(&self) -> u16 {
2142 self.num_questions
2143 }
2144
2145 pub const fn is_query(&self) -> bool {
2146 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2147 }
2148
2149 pub const fn is_response(&self) -> bool {
2150 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2151 }
2152
2153 fn read_header(&mut self) -> Result<()> {
2154 if self.data.len() < MSG_HEADER_LEN {
2155 return Err(e_fmt!(
2156 "DNS incoming: header is too short: {} bytes",
2157 self.data.len()
2158 ));
2159 }
2160
2161 let data = &self.data[0..];
2162 self.id = u16_from_be_slice(&data[..2]);
2163 self.flags = u16_from_be_slice(&data[2..4]);
2164 self.num_questions = u16_from_be_slice(&data[4..6]);
2165 self.num_answers = u16_from_be_slice(&data[6..8]);
2166 self.num_authorities = u16_from_be_slice(&data[8..10]);
2167 self.num_additionals = u16_from_be_slice(&data[10..12]);
2168
2169 self.offset = MSG_HEADER_LEN;
2170
2171 trace!(
2172 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2173 self.id,
2174 self.num_questions,
2175 self.num_answers,
2176 self.num_authorities,
2177 self.num_additionals
2178 );
2179 Ok(())
2180 }
2181
2182 fn read_questions(&mut self) -> Result<()> {
2183 trace!("read_questions: {}", &self.num_questions);
2184 for i in 0..self.num_questions {
2185 let name = self.read_name()?;
2186
2187 let data = &self.data[self.offset..];
2188 if data.len() < 4 {
2189 return Err(Error::Msg(format!(
2190 "DNS incoming: question idx {} too short: {}",
2191 i,
2192 data.len()
2193 )));
2194 }
2195 let ty = u16_from_be_slice(&data[..2]);
2196 let class = u16_from_be_slice(&data[2..4]);
2197 self.offset += 4;
2198
2199 let Some(rr_type) = RRType::from_u16(ty) else {
2200 return Err(Error::Msg(format!(
2201 "DNS incoming: question idx {i} qtype unknown: {ty}",
2202 )));
2203 };
2204
2205 self.questions.push(DnsQuestion {
2206 entry: DnsEntry::new(name, rr_type, class),
2207 });
2208 }
2209 Ok(())
2210 }
2211
2212 fn read_answers(&mut self) -> Result<()> {
2213 self.answers = self.read_rr_records(self.num_answers)?;
2214 Ok(())
2215 }
2216
2217 fn read_authorities(&mut self) -> Result<()> {
2218 self.authorities = self.read_rr_records(self.num_authorities)?;
2219 Ok(())
2220 }
2221
2222 fn read_additional(&mut self) -> Result<()> {
2223 self.additional = self.read_rr_records(self.num_additionals)?;
2224 Ok(())
2225 }
2226
2227 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2229 trace!("read_rr_records: {}", count);
2230 let mut rr_records = Vec::new();
2231
2232 const RR_HEADER_REMAIN: usize = 10;
2258
2259 for _ in 0..count {
2260 let name = self.read_name()?;
2261 let slice = &self.data[self.offset..];
2262
2263 if slice.len() < RR_HEADER_REMAIN {
2264 return Err(Error::Msg(format!(
2265 "read_others: RR '{}' is too short after name: {} bytes",
2266 &name,
2267 slice.len()
2268 )));
2269 }
2270
2271 let ty = u16_from_be_slice(&slice[..2]);
2272 let class = u16_from_be_slice(&slice[2..4]);
2273 let mut ttl = u32_from_be_slice(&slice[4..8]);
2274 if ttl == 0 && self.is_response() {
2275 ttl = 1;
2282 }
2283 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2284 self.offset += RR_HEADER_REMAIN;
2285 let next_offset = self.offset + rdata_len;
2286
2287 if next_offset > self.data.len() {
2289 return Err(Error::Msg(format!(
2290 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2291 self.data.len() - self.offset
2292 )));
2293 }
2294
2295 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2297 None => None,
2298
2299 Some(rr_type) => match rr_type {
2300 RRType::CNAME | RRType::PTR => {
2301 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
2302 }
2303 RRType::TXT => {
2304 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
2305 }
2306 RRType::SRV => Some(
2307 DnsSrv::new(
2308 &name,
2309 class,
2310 ttl,
2311 self.read_u16()?,
2312 self.read_u16()?,
2313 self.read_u16()?,
2314 self.read_name()?,
2315 )
2316 .boxed(),
2317 ),
2318 RRType::HINFO => Some(
2319 DnsHostInfo::new(
2320 &name,
2321 rr_type,
2322 class,
2323 ttl,
2324 self.read_char_string()?,
2325 self.read_char_string()?,
2326 )
2327 .boxed(),
2328 ),
2329 RRType::A => Some(
2330 DnsAddress::new(
2331 &name,
2332 rr_type,
2333 class,
2334 ttl,
2335 self.read_ipv4()?.into(),
2336 self.interface_id.clone(),
2337 )
2338 .boxed(),
2339 ),
2340 RRType::AAAA => Some(
2341 DnsAddress::new(
2342 &name,
2343 rr_type,
2344 class,
2345 ttl,
2346 self.read_ipv6()?.into(),
2347 self.interface_id.clone(),
2348 )
2349 .boxed(),
2350 ),
2351 RRType::NSEC => Some(
2352 DnsNSec::new(
2353 &name,
2354 class,
2355 ttl,
2356 self.read_name()?,
2357 self.read_type_bitmap()?,
2358 )
2359 .boxed(),
2360 ),
2361 _ => None,
2362 },
2363 };
2364
2365 if let Some(record) = rec {
2366 trace!("read_rr_records: {:?}", &record);
2367 rr_records.push(record);
2368 } else {
2369 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2370 self.offset += rdata_len;
2371 }
2372
2373 if self.offset != next_offset {
2375 return Err(Error::Msg(format!(
2376 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2377 ty, self.offset, next_offset,
2378 )));
2379 }
2380 }
2381
2382 Ok(rr_records)
2383 }
2384
2385 fn read_char_string(&mut self) -> Result<String> {
2386 let length = self.data[self.offset];
2387 self.offset += 1;
2388 self.read_string(length as usize)
2389 }
2390
2391 fn read_u16(&mut self) -> Result<u16> {
2392 let slice = &self.data[self.offset..];
2393 if slice.len() < U16_SIZE {
2394 return Err(Error::Msg(format!(
2395 "read_u16: slice len is only {}",
2396 slice.len()
2397 )));
2398 }
2399 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2400 self.offset += U16_SIZE;
2401 Ok(num)
2402 }
2403
2404 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2406 if self.data.len() < self.offset + 2 {
2415 return Err(Error::Msg(format!(
2416 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2417 self.data.len(),
2418 self.offset
2419 )));
2420 }
2421
2422 let block_num = self.data[self.offset];
2423 self.offset += 1;
2424 if block_num != 0 {
2425 return Err(Error::Msg(format!(
2426 "NSEC block number is not 0: {block_num}"
2427 )));
2428 }
2429
2430 let block_len = self.data[self.offset] as usize;
2431 if !(1..=32).contains(&block_len) {
2432 return Err(Error::Msg(format!(
2433 "NSEC block length must be in the range 1-32: {block_len}"
2434 )));
2435 }
2436 self.offset += 1;
2437
2438 let end = self.offset + block_len;
2439 if end > self.data.len() {
2440 return Err(Error::Msg(format!(
2441 "NSEC block overflow: {} over RData len {}",
2442 end,
2443 self.data.len()
2444 )));
2445 }
2446 let bitmap = self.data[self.offset..end].to_vec();
2447 self.offset += block_len;
2448
2449 Ok(bitmap)
2450 }
2451
2452 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2453 if self.data.len() < self.offset + length {
2454 return Err(e_fmt!(
2455 "DNS Incoming: not enough data to read a chunk of data"
2456 ));
2457 }
2458
2459 let v = self.data[self.offset..self.offset + length].to_vec();
2460 self.offset += length;
2461 Ok(v)
2462 }
2463
2464 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2465 if self.data.len() < self.offset + 4 {
2466 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2467 }
2468
2469 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2470 .try_into()
2471 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2472 self.offset += bytes.len();
2473 Ok(Ipv4Addr::from(bytes))
2474 }
2475
2476 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2477 if self.data.len() < self.offset + 16 {
2478 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2479 }
2480
2481 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2482 .try_into()
2483 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2484 self.offset += bytes.len();
2485 Ok(Ipv6Addr::from(bytes))
2486 }
2487
2488 fn read_string(&mut self, length: usize) -> Result<String> {
2489 if self.data.len() < self.offset + length {
2490 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2491 }
2492
2493 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2494 .map_err(|e| Error::Msg(e.to_string()))?;
2495 self.offset += length;
2496 Ok(s.to_string())
2497 }
2498
2499 fn read_name(&mut self) -> Result<String> {
2504 let data = &self.data[..];
2505 let start_offset = self.offset;
2506 let mut offset = start_offset;
2507 let mut name = "".to_string();
2508 let mut at_end = false;
2509
2510 loop {
2521 if offset >= data.len() {
2522 return Err(Error::Msg(format!(
2523 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2524 offset,
2525 data.len(),
2526 self
2527 )));
2528 }
2529 let length = data[offset];
2530
2531 if length == 0 {
2535 if !at_end {
2536 self.offset = offset + 1;
2537 }
2538 break; }
2540
2541 match length & 0xC0 {
2543 0x00 => {
2544 offset += 1;
2546 let ending = offset + length as usize;
2547
2548 if ending > data.len() {
2550 return Err(Error::Msg(format!(
2551 "read_name: ending {} exceeds data length {}",
2552 ending,
2553 data.len()
2554 )));
2555 }
2556
2557 name += str::from_utf8(&data[offset..ending])
2558 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {e}")))?;
2559 name += ".";
2560 offset += length as usize;
2561 }
2562 0xC0 => {
2563 let slice = &data[offset..];
2566 if slice.len() < U16_SIZE {
2567 return Err(Error::Msg(format!(
2568 "read_name: u16 slice len is only {}",
2569 slice.len()
2570 )));
2571 }
2572 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2573 if pointer >= start_offset {
2574 return Err(Error::Msg(format!(
2576 "Invalid name compression: pointer {} must be less than the start offset {}",
2577 &pointer, &start_offset
2578 )));
2579 }
2580
2581 if !at_end {
2583 self.offset = offset + U16_SIZE;
2584 at_end = true;
2585 }
2586 offset = pointer;
2587 }
2588 _ => {
2589 return Err(Error::Msg(format!(
2590 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2591 length,
2592 offset,
2593 &data[..offset]
2594 )));
2595 }
2596 };
2597 }
2598
2599 Ok(name)
2600 }
2601}
2602
2603const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2604 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2605 u16::from_be_bytes(u8_array)
2606}
2607
2608const fn u32_from_be_slice(s: &[u8]) -> u32 {
2609 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2610 u32::from_be_bytes(u8_array)
2611}
2612
2613const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2616 created + (ttl as u64 * percent as u64 * 10)
2619}
2620
2621#[cfg(test)]
2622mod tests {
2623 use super::{
2624 DnsAddress, DnsHostInfo, DnsOutgoing, DnsPointer, DnsTxt, RRType, CLASS_CACHE_FLUSH,
2625 CLASS_IN,
2626 };
2627 use crate::InterfaceId;
2628 use std::collections::HashMap;
2629 use std::net::{IpAddr, Ipv4Addr};
2630
2631 #[test]
2632 fn test_dns_outgoing_serialization_empty() {
2633 let out = DnsOutgoing::new(0);
2634 let packets = out.to_packets();
2635 assert_eq!(packets.len(), 1);
2636 assert_eq!(packets[0].as_bytes(), &[0; 12]);
2637 let expected_names = HashMap::new();
2638 assert_eq!(&packets[0].names, &expected_names);
2639 }
2640
2641 #[test]
2642 fn test_dns_outgoing_serialization_question() {
2643 let mut out = DnsOutgoing::new(0);
2644 out.add_question("123.test", RRType::A);
2645 let packets = out.to_packets();
2646 assert_eq!(packets.len(), 1);
2647 assert_eq!(
2648 packets[0].as_bytes(),
2649 &[
2650 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 49, 50, 51, 4, 116, 101, 115, 116, 0, 0, 1, 0, 1,
2653 ]
2654 );
2655 let mut expected_names = HashMap::new();
2656 expected_names.insert("123.test".to_string(), 12);
2657 expected_names.insert("test".to_string(), 16);
2658 assert_eq!(&packets[0].names, &expected_names);
2659 }
2660
2661 #[test]
2662 fn test_dns_outgoing_serialization_question_with_authority() {
2663 let mut out = DnsOutgoing::new(0);
2664 out.add_question("123.test", RRType::ANY);
2665 out.add_authority(Box::new(DnsTxt::new(
2666 "124.test",
2667 CLASS_IN,
2668 0x00112233,
2669 b"help".to_vec(),
2670 )));
2671 out.add_authority(Box::new(DnsHostInfo::new(
2672 "124.test",
2673 RRType::CNAME,
2674 CLASS_IN,
2675 0x00112233,
2676 "arm".to_string(),
2677 "linux".to_string(),
2678 )));
2679 let packets = out.to_packets();
2680 assert_eq!(packets.len(), 1);
2681 assert_eq!(
2682 packets[0].as_bytes(),
2683 &[
2684 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 3, 49, 50, 51, 4, 116, 101, 115, 116, 0, 0, 255, 0, 1, 3, 49, 50, 52, 192, 16, 0,
2687 16, 0, 1, 0, 17, 34, 51, 0, 4, 104, 101, 108, 112, 192, 26, 0, 5, 0, 1, 0, 17, 34,
2688 51, 0, 8, 97, 114, 109, 108, 105, 110, 117, 120,
2689 ]
2690 );
2691 let mut expected_names = HashMap::new();
2692 expected_names.insert("123.test".to_string(), 12);
2693 expected_names.insert("test".to_string(), 16);
2694 expected_names.insert("124.test".to_string(), 26);
2695 assert_eq!(&packets[0].names, &expected_names);
2696 }
2697
2698 #[test]
2699 fn test_dns_outgoing_serialization_additional_answer() {
2700 let mut out = DnsOutgoing::new(0);
2701 out.add_additional_answer(DnsAddress::new(
2702 "test.local",
2703 RRType::A,
2704 CLASS_IN | CLASS_CACHE_FLUSH,
2705 0xdead_beef,
2706 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
2707 InterfaceId::default(),
2708 ));
2709 let packets = out.to_packets();
2710 assert_eq!(packets.len(), 1);
2711 assert_eq!(
2712 packets[0].as_bytes(),
2713 &[
2714 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 116, 101, 115, 116, 5, 108, 111, 99, 97, 108, 0, 0, 1, 128, 1, 222, 173, 190,
2717 239, 0, 4, 127, 0, 0, 1,
2718 ]
2719 );
2720 let mut expected_names = HashMap::new();
2721 expected_names.insert("test.local".to_string(), 12);
2722 expected_names.insert("local".to_string(), 17);
2723 assert_eq!(&packets[0].names, &expected_names);
2724 }
2725
2726 #[test]
2727 fn test_dns_outgoing_serialization_answer_at_time() {
2728 let mut out = DnsOutgoing::new(0);
2729 out.add_answer_at_time(
2730 DnsPointer::new(
2731 "test",
2732 RRType::PTR,
2733 CLASS_IN,
2734 0xaaaa5555,
2735 "test-service".to_string(),
2736 ),
2737 0,
2738 );
2739 let packets = out.to_packets();
2740 assert_eq!(packets.len(), 1);
2741 assert_eq!(
2742 packets[0].as_bytes(),
2743 &[
2744 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, 12, 0, 1, 170, 170, 85, 85, 0, 14, 12, 116, 101, 115,
2747 116, 45, 115, 101, 114, 118, 105, 99, 101, 0,
2748 ]
2749 );
2750
2751 let mut out = DnsOutgoing::new(0);
2752 out.add_answer_at_time(
2753 DnsPointer::new(
2754 "test",
2755 RRType::CNAME,
2756 CLASS_IN,
2757 0xaaaa5555,
2758 "test-service.local".to_string(),
2759 ),
2760 0,
2761 );
2762 out.add_answer_at_time(
2763 DnsPointer::new(
2764 "test",
2765 RRType::AAAA,
2766 CLASS_IN,
2767 0xffffffff,
2768 "test-service.local".to_string(),
2769 ),
2770 0,
2771 );
2772 let packets = out.to_packets();
2773 assert_eq!(packets.len(), 1);
2774 assert_eq!(
2775 packets[0].as_bytes(),
2776 &[
2777 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, 5, 0, 1, 170, 170, 85, 85, 0, 20, 12, 116, 101, 115,
2780 116, 45, 115, 101, 114, 118, 105, 99, 101, 5, 108, 111, 99, 97, 108, 0, 192, 12, 0,
2781 28, 0, 1, 255, 255, 255, 255, 0, 2, 192, 28,
2782 ]
2783 );
2784 let mut expected_names = HashMap::new();
2785 expected_names.insert("test".to_string(), 12);
2786 expected_names.insert("test-service.local".to_string(), 28);
2787 expected_names.insert("local".to_string(), 41);
2788 assert_eq!(&packets[0].names, &expected_names);
2789 }
2790}