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(crate) const MAX_PKT_ABSOLUTE_IPV4: usize = 8972;
293
294pub(crate) const MAX_PKT_ABSOLUTE_IPV6: usize = 8952;
299
300pub(crate) const fn max_pkt_absolute(is_ipv4: bool) -> usize {
302 if is_ipv4 {
303 MAX_PKT_ABSOLUTE_IPV4
304 } else {
305 MAX_PKT_ABSOLUTE_IPV6
306 }
307}
308
309pub const MAX_PKT_DEFAULT: usize = 1452;
316
317const MSG_HEADER_LEN: usize = 12;
318
319const MAX_LABEL_BYTES: usize = 63;
323
324#[derive(Debug, PartialEq, Eq)]
329pub enum WriteError {
330 NameTooLong,
332
333 PacketFull,
335}
336
337type WriteResult = core::result::Result<(), WriteError>;
339
340pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
352
353pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
355
356pub const FLAGS_AA: u16 = 0x0400;
358
359pub const FLAGS_TC: u16 = 0x0200;
370
371pub type DnsRecordBox = Box<dyn DnsRecordExt>;
373
374impl Clone for DnsRecordBox {
375 fn clone(&self) -> Self {
376 self.clone_box()
377 }
378}
379
380const U16_SIZE: usize = 2;
381
382#[inline]
384pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
385 match address {
386 IpAddr::V4(_) => RRType::A,
387 IpAddr::V6(_) => RRType::AAAA,
388 }
389}
390
391#[derive(Eq, PartialEq, Debug, Clone)]
392pub struct DnsEntry {
393 pub(crate) name: String, pub(crate) ty: RRType,
395 class: u16,
396 cache_flush: bool,
397}
398
399impl DnsEntry {
400 const fn new(name: String, ty: RRType, class: u16) -> Self {
401 Self {
402 name,
403 ty,
404 class: class & CLASS_MASK,
405 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
406 }
407 }
408}
409
410pub trait DnsEntryExt: fmt::Debug {
412 fn entry_name(&self) -> &str;
413
414 fn entry_type(&self) -> RRType;
415}
416
417#[derive(Debug)]
419pub struct DnsQuestion {
420 pub(crate) entry: DnsEntry,
421}
422
423impl DnsEntryExt for DnsQuestion {
424 fn entry_name(&self) -> &str {
425 &self.entry.name
426 }
427
428 fn entry_type(&self) -> RRType {
429 self.entry.ty
430 }
431}
432
433#[derive(Debug, Clone)]
437pub struct DnsRecord {
438 pub(crate) entry: DnsEntry,
439 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
449}
450
451impl DnsRecord {
452 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
453 let created = current_time_millis();
454
455 let refresh = get_expiration_time(created, ttl, 80);
459
460 let expires = get_expiration_time(created, ttl, 100);
461
462 Self {
463 entry: DnsEntry::new(name.to_string(), ty, class),
464 ttl,
465 created,
466 expires,
467 refresh,
468 new_name: None,
469 }
470 }
471
472 pub const fn get_ttl(&self) -> u32 {
473 self.ttl
474 }
475
476 pub const fn get_expire_time(&self) -> u64 {
477 self.expires
478 }
479
480 pub const fn get_refresh_time(&self) -> u64 {
481 self.refresh
482 }
483
484 pub const fn is_expired(&self, now: u64) -> bool {
485 now >= self.expires
486 }
487
488 pub const fn expires_soon(&self, now: u64) -> bool {
492 now + 1000 >= self.expires
493 }
494
495 pub const fn refresh_due(&self, now: u64) -> bool {
496 now >= self.refresh
497 }
498
499 pub fn halflife_passed(&self, now: u64) -> bool {
501 let halflife = get_expiration_time(self.created, self.ttl, 50);
502 now > halflife
503 }
504
505 pub fn is_unique(&self) -> bool {
506 self.entry.cache_flush
507 }
508
509 pub fn refresh_no_more(&mut self) {
512 self.refresh = get_expiration_time(self.created, self.ttl, 100);
513 }
514
515 pub fn refresh_maybe(&mut self, now: u64) -> bool {
517 if self.is_expired(now) || !self.refresh_due(now) {
518 return false;
519 }
520
521 trace!(
522 "{} qtype {} is due to refresh",
523 &self.entry.name,
524 self.entry.ty
525 );
526
527 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
534 self.refresh = get_expiration_time(self.created, self.ttl, 85);
535 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
536 self.refresh = get_expiration_time(self.created, self.ttl, 90);
537 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
538 self.refresh = get_expiration_time(self.created, self.ttl, 95);
539 } else {
540 self.refresh_no_more();
541 }
542
543 true
544 }
545
546 fn get_remaining_ttl(&self, now: u64) -> u32 {
548 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
549 cmp::max(0, remaining_millis / 1000) as u32
550 }
551
552 pub const fn get_created(&self) -> u64 {
554 self.created
555 }
556
557 fn set_expire(&mut self, expire_at: u64) {
559 self.expires = expire_at;
560 }
561
562 fn reset_ttl(&mut self, other: &Self) {
563 self.ttl = other.ttl;
564 self.created = other.created;
565 self.expires = get_expiration_time(self.created, self.ttl, 100);
566 self.refresh = if self.ttl > 1 {
567 get_expiration_time(self.created, self.ttl, 80)
568 } else {
569 self.expires
572 };
573 }
574
575 pub fn update_ttl(&mut self, now: u64) {
577 if now > self.created {
578 let elapsed = now - self.created;
579 self.ttl -= (elapsed / 1000) as u32;
580 }
581 }
582
583 pub fn set_new_name(&mut self, new_name: String) {
584 if new_name == self.entry.name {
585 self.new_name = None;
586 } else {
587 self.new_name = Some(new_name);
588 }
589 }
590
591 pub fn get_new_name(&self) -> Option<&str> {
592 self.new_name.as_deref()
593 }
594
595 pub(crate) fn get_name(&self) -> &str {
597 self.new_name.as_deref().unwrap_or(&self.entry.name)
598 }
599
600 pub fn get_original_name(&self) -> &str {
601 &self.entry.name
602 }
603}
604
605impl PartialEq for DnsRecord {
606 fn eq(&self, other: &Self) -> bool {
607 self.entry == other.entry
608 }
609}
610
611pub trait DnsRecordExt: fmt::Debug {
613 fn get_record(&self) -> &DnsRecord;
614 fn get_record_mut(&mut self) -> &mut DnsRecord;
615 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult;
617 fn any(&self) -> &dyn Any;
618
619 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
621
622 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
624
625 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
628
629 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
631 match self.get_class().cmp(&other.get_class()) {
645 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
646 cmp::Ordering::Equal => self.compare_rdata(other),
647 not_equal => not_equal,
648 },
649 not_equal => not_equal,
650 }
651 }
652
653 fn rdata_print(&self) -> String;
655
656 fn get_class(&self) -> u16 {
658 self.get_record().entry.class
659 }
660
661 fn get_cache_flush(&self) -> bool {
662 self.get_record().entry.cache_flush
663 }
664
665 fn get_name(&self) -> &str {
667 self.get_record().get_name()
668 }
669
670 fn get_type(&self) -> RRType {
671 self.get_record().entry.ty
672 }
673
674 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
677 self.get_record_mut().reset_ttl(other.get_record());
678 }
679
680 fn get_created(&self) -> u64 {
681 self.get_record().get_created()
682 }
683
684 fn get_expire(&self) -> u64 {
685 self.get_record().get_expire_time()
686 }
687
688 fn set_expire(&mut self, expire_at: u64) {
689 self.get_record_mut().set_expire(expire_at);
690 }
691
692 fn set_expire_sooner(&mut self, expire_at: u64) {
694 if expire_at < self.get_expire() {
695 self.get_record_mut().set_expire(expire_at);
696 }
697 }
698
699 fn expires_soon(&self, now: u64) -> bool {
701 self.get_record().expires_soon(now)
702 }
703
704 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
707 if self.get_record_mut().refresh_maybe(now) {
708 Some(self.get_record().get_refresh_time())
709 } else {
710 None
711 }
712 }
713
714 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
717 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
718 }
719
720 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
722 for answer in msg.answers.iter() {
723 if self.suppressed_by_answer(answer.as_ref()) {
724 return true;
725 }
726 }
727 false
728 }
729
730 fn clone_box(&self) -> DnsRecordBox;
731
732 fn boxed(self) -> DnsRecordBox;
733}
734
735#[derive(Debug, Clone)]
737pub(crate) struct DnsAddress {
738 pub(crate) record: DnsRecord,
739 address: IpAddr,
740 pub(crate) interface_id: InterfaceId,
741}
742
743impl DnsAddress {
744 pub fn new(
745 name: &str,
746 ty: RRType,
747 class: u16,
748 ttl: u32,
749 address: IpAddr,
750 interface_id: InterfaceId,
751 ) -> Self {
752 let record = DnsRecord::new(name, ty, class, ttl);
753 Self {
754 record,
755 address,
756 interface_id,
757 }
758 }
759
760 pub fn address(&self) -> ScopedIp {
761 match self.address {
762 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
763 addr: v4,
764 interface_ids: vec![self.interface_id.clone()],
765 }),
766 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
767 addr: v6,
768 scope_id: self.interface_id.clone(),
769 }),
770 }
771 }
772}
773
774impl DnsRecordExt for DnsAddress {
775 fn get_record(&self) -> &DnsRecord {
776 &self.record
777 }
778
779 fn get_record_mut(&mut self) -> &mut DnsRecord {
780 &mut self.record
781 }
782
783 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
784 match self.address {
785 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
786 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
787 };
788 Ok(())
789 }
790
791 fn any(&self) -> &dyn Any {
792 self
793 }
794
795 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
796 if let Some(other_a) = other.any().downcast_ref::<Self>() {
797 return self.address == other_a.address
798 && self.record.entry == other_a.record.entry
799 && self.interface_id == other_a.interface_id;
800 }
801 false
802 }
803
804 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
805 if let Some(other_a) = other.any().downcast_ref::<Self>() {
806 return self.address == other_a.address;
807 }
808 false
809 }
810
811 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
812 if let Some(other_a) = other.any().downcast_ref::<Self>() {
813 self.address.cmp(&other_a.address)
814 } else {
815 cmp::Ordering::Greater
816 }
817 }
818
819 fn rdata_print(&self) -> String {
820 format!("{}", self.address)
821 }
822
823 fn clone_box(&self) -> DnsRecordBox {
824 Box::new(self.clone())
825 }
826
827 fn boxed(self) -> DnsRecordBox {
828 Box::new(self)
829 }
830}
831
832#[derive(Debug, Clone)]
834pub struct DnsPointer {
835 record: DnsRecord,
836 alias: String, }
838
839impl DnsPointer {
840 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
841 let record = DnsRecord::new(name, ty, class, ttl);
842 Self { record, alias }
843 }
844
845 pub fn alias(&self) -> &str {
846 &self.alias
847 }
848}
849
850impl DnsRecordExt for DnsPointer {
851 fn get_record(&self) -> &DnsRecord {
852 &self.record
853 }
854
855 fn get_record_mut(&mut self) -> &mut DnsRecord {
856 &mut self.record
857 }
858
859 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
860 packet.write_name(&self.alias)
861 }
862
863 fn any(&self) -> &dyn Any {
864 self
865 }
866
867 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
868 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
869 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
870 }
871 false
872 }
873
874 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
875 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
876 return self.alias == other_ptr.alias;
877 }
878 false
879 }
880
881 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
882 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
883 self.alias.cmp(&other_ptr.alias)
884 } else {
885 cmp::Ordering::Greater
886 }
887 }
888
889 fn rdata_print(&self) -> String {
890 self.alias.clone()
891 }
892
893 fn clone_box(&self) -> DnsRecordBox {
894 Box::new(self.clone())
895 }
896
897 fn boxed(self) -> DnsRecordBox {
898 Box::new(self)
899 }
900}
901
902#[derive(Debug, Clone)]
904pub struct DnsSrv {
905 pub(crate) record: DnsRecord,
906 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
909 port: u16,
910}
911
912impl DnsSrv {
913 pub fn new(
914 name: &str,
915 class: u16,
916 ttl: u32,
917 priority: u16,
918 weight: u16,
919 port: u16,
920 host: String,
921 ) -> Self {
922 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
923 Self {
924 record,
925 priority,
926 weight,
927 host,
928 port,
929 }
930 }
931
932 pub fn host(&self) -> &str {
933 &self.host
934 }
935
936 pub fn port(&self) -> u16 {
937 self.port
938 }
939
940 pub fn set_host(&mut self, host: String) {
941 self.host = host;
942 }
943}
944
945impl DnsRecordExt for DnsSrv {
946 fn get_record(&self) -> &DnsRecord {
947 &self.record
948 }
949
950 fn get_record_mut(&mut self) -> &mut DnsRecord {
951 &mut self.record
952 }
953
954 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
955 packet.write_short(self.priority);
956 packet.write_short(self.weight);
957 packet.write_short(self.port);
958 packet.write_name(&self.host)
959 }
960
961 fn any(&self) -> &dyn Any {
962 self
963 }
964
965 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
966 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
967 return self.host == other_svc.host
968 && self.port == other_svc.port
969 && self.weight == other_svc.weight
970 && self.priority == other_svc.priority
971 && self.record.entry == other_svc.record.entry;
972 }
973 false
974 }
975
976 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
977 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
978 return self.host == other_srv.host
979 && self.port == other_srv.port
980 && self.weight == other_srv.weight
981 && self.priority == other_srv.priority;
982 }
983 false
984 }
985
986 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
987 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
988 return cmp::Ordering::Greater;
989 };
990
991 match self
993 .priority
994 .to_be_bytes()
995 .cmp(&other_srv.priority.to_be_bytes())
996 {
997 cmp::Ordering::Equal => {
998 match self
1000 .weight
1001 .to_be_bytes()
1002 .cmp(&other_srv.weight.to_be_bytes())
1003 {
1004 cmp::Ordering::Equal => {
1005 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
1007 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
1008 not_equal => not_equal,
1009 }
1010 }
1011 not_equal => not_equal,
1012 }
1013 }
1014 not_equal => not_equal,
1015 }
1016 }
1017
1018 fn rdata_print(&self) -> String {
1019 format!(
1020 "priority: {}, weight: {}, port: {}, host: {}",
1021 self.priority, self.weight, self.port, self.host
1022 )
1023 }
1024
1025 fn clone_box(&self) -> DnsRecordBox {
1026 Box::new(self.clone())
1027 }
1028
1029 fn boxed(self) -> DnsRecordBox {
1030 Box::new(self)
1031 }
1032}
1033
1034#[derive(Clone)]
1049pub struct DnsTxt {
1050 pub(crate) record: DnsRecord,
1051 text: Vec<u8>,
1052}
1053
1054impl DnsTxt {
1055 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1056 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1057 Self { record, text }
1058 }
1059
1060 pub fn text(&self) -> &[u8] {
1061 &self.text
1062 }
1063}
1064
1065impl DnsRecordExt for DnsTxt {
1066 fn get_record(&self) -> &DnsRecord {
1067 &self.record
1068 }
1069
1070 fn get_record_mut(&mut self) -> &mut DnsRecord {
1071 &mut self.record
1072 }
1073
1074 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1075 packet.write_bytes(&self.text);
1076 Ok(())
1077 }
1078
1079 fn any(&self) -> &dyn Any {
1080 self
1081 }
1082
1083 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1084 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1085 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1086 }
1087 false
1088 }
1089
1090 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1091 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1092 return self.text == other_txt.text;
1093 }
1094 false
1095 }
1096
1097 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1098 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1099 self.text.cmp(&other_txt.text)
1100 } else {
1101 cmp::Ordering::Greater
1102 }
1103 }
1104
1105 fn rdata_print(&self) -> String {
1106 format!("{:?}", decode_txt(&self.text))
1107 }
1108
1109 fn clone_box(&self) -> DnsRecordBox {
1110 Box::new(self.clone())
1111 }
1112
1113 fn boxed(self) -> DnsRecordBox {
1114 Box::new(self)
1115 }
1116}
1117
1118impl fmt::Debug for DnsTxt {
1119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1120 let properties = decode_txt(&self.text);
1121 write!(
1122 f,
1123 "DnsTxt {{ record: {:?}, text: {:?} }}",
1124 self.record, properties
1125 )
1126 }
1127}
1128
1129fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
1131 let mut properties = Vec::new();
1132 let mut offset = 0;
1133 while offset < txt.len() {
1134 let length = txt[offset] as usize;
1135 if length == 0 {
1136 break; }
1138 offset += 1; let offset_end = offset + length;
1141 if offset_end > txt.len() {
1142 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
1143 break; }
1145 let kv_bytes = &txt[offset..offset_end];
1146
1147 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
1149 || (kv_bytes.to_vec(), None),
1150 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
1151 );
1152
1153 match String::from_utf8(k) {
1155 Ok(k_string) => {
1156 properties.push(TxtProperty {
1157 key: k_string,
1158 val: v,
1159 });
1160 }
1161 Err(e) => trace!("ERROR: convert to String from key: {}", e),
1162 }
1163
1164 offset += length;
1165 }
1166
1167 properties
1168}
1169
1170#[derive(Clone, PartialEq, Eq)]
1172pub struct TxtProperty {
1173 key: String,
1175
1176 val: Option<Vec<u8>>,
1180}
1181
1182impl TxtProperty {
1183 pub fn val_str(&self) -> &str {
1185 self.val
1186 .as_ref()
1187 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
1188 }
1189}
1190
1191impl<K, V> From<&(K, V)> for TxtProperty
1193where
1194 K: ToString,
1195 V: ToString,
1196{
1197 fn from(prop: &(K, V)) -> Self {
1198 Self {
1199 key: prop.0.to_string(),
1200 val: Some(prop.1.to_string().into_bytes()),
1201 }
1202 }
1203}
1204
1205impl<K, V> From<(K, V)> for TxtProperty
1206where
1207 K: ToString,
1208 V: AsRef<[u8]>,
1209{
1210 fn from(prop: (K, V)) -> Self {
1211 Self {
1212 key: prop.0.to_string(),
1213 val: Some(prop.1.as_ref().into()),
1214 }
1215 }
1216}
1217
1218impl From<&str> for TxtProperty {
1220 fn from(key: &str) -> Self {
1221 Self {
1222 key: key.to_string(),
1223 val: None,
1224 }
1225 }
1226}
1227
1228impl fmt::Display for TxtProperty {
1229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1230 write!(f, "{}={}", self.key, self.val_str())
1231 }
1232}
1233
1234impl fmt::Debug for TxtProperty {
1238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1239 let val_string = self.val.as_ref().map_or_else(
1240 || "None".to_string(),
1241 |v| {
1242 std::str::from_utf8(&v[..]).map_or_else(
1243 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1244 |s| format!("Some(\"{s}\")"),
1245 )
1246 },
1247 );
1248
1249 write!(
1250 f,
1251 "TxtProperty {{key: \"{}\", val: {}}}",
1252 &self.key, &val_string,
1253 )
1254 }
1255}
1256
1257const HEX_TABLE: [char; 16] = [
1258 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1259];
1260
1261fn u8_slice_to_hex(slice: &[u8]) -> String {
1265 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1266 hex.push_str("0x");
1267 for b in slice {
1268 hex.push(HEX_TABLE[(b >> 4) as usize]);
1269 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1270 }
1271 hex
1272}
1273
1274#[derive(Debug, Clone)]
1276struct DnsHostInfo {
1277 record: DnsRecord,
1278 cpu: String,
1279 os: String,
1280}
1281
1282impl DnsHostInfo {
1283 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1284 let record = DnsRecord::new(name, ty, class, ttl);
1285 Self { record, cpu, os }
1286 }
1287}
1288
1289impl DnsRecordExt for DnsHostInfo {
1290 fn get_record(&self) -> &DnsRecord {
1291 &self.record
1292 }
1293
1294 fn get_record_mut(&mut self) -> &mut DnsRecord {
1295 &mut self.record
1296 }
1297
1298 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1299 debug!("Writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1300 packet.write_bytes(self.cpu.as_bytes());
1301 packet.write_bytes(self.os.as_bytes());
1302 Ok(())
1303 }
1304
1305 fn any(&self) -> &dyn Any {
1306 self
1307 }
1308
1309 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1310 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1311 return self.cpu == other_hinfo.cpu
1312 && self.os == other_hinfo.os
1313 && self.record.entry == other_hinfo.record.entry;
1314 }
1315 false
1316 }
1317
1318 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1319 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1320 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1321 }
1322 false
1323 }
1324
1325 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1326 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1327 match self.cpu.cmp(&other_hinfo.cpu) {
1328 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1329 ordering => ordering,
1330 }
1331 } else {
1332 cmp::Ordering::Greater
1333 }
1334 }
1335
1336 fn rdata_print(&self) -> String {
1337 format!("cpu: {}, os: {}", self.cpu, self.os)
1338 }
1339
1340 fn clone_box(&self) -> DnsRecordBox {
1341 Box::new(self.clone())
1342 }
1343
1344 fn boxed(self) -> DnsRecordBox {
1345 Box::new(self)
1346 }
1347}
1348
1349#[derive(Debug, Clone)]
1355pub struct DnsNSec {
1356 record: DnsRecord,
1357 next_domain: String,
1358 type_bitmap: Vec<u8>,
1359}
1360
1361impl DnsNSec {
1362 pub fn new(
1363 name: &str,
1364 class: u16,
1365 ttl: u32,
1366 next_domain: String,
1367 type_bitmap: Vec<u8>,
1368 ) -> Self {
1369 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1370 Self {
1371 record,
1372 next_domain,
1373 type_bitmap,
1374 }
1375 }
1376
1377 pub fn _types(&self) -> Vec<u16> {
1379 let mut bit_num = 0;
1388 let mut results = Vec::new();
1389
1390 for byte in self.type_bitmap.iter() {
1391 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1395 if (byte & bit_mask) != 0 {
1396 results.push(bit_num);
1397 }
1398 bit_num += 1;
1399 bit_mask >>= 1; }
1401 }
1402 results
1403 }
1404}
1405
1406impl DnsRecordExt for DnsNSec {
1407 fn get_record(&self) -> &DnsRecord {
1408 &self.record
1409 }
1410
1411 fn get_record_mut(&mut self) -> &mut DnsRecord {
1412 &mut self.record
1413 }
1414
1415 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1416 packet.write_bytes(self.next_domain.as_bytes());
1417 packet.write_bytes(&self.type_bitmap);
1418 Ok(())
1419 }
1420
1421 fn any(&self) -> &dyn Any {
1422 self
1423 }
1424
1425 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1426 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1427 return self.next_domain == other_record.next_domain
1428 && self.type_bitmap == other_record.type_bitmap
1429 && self.record.entry == other_record.record.entry;
1430 }
1431 false
1432 }
1433
1434 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1435 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1436 return self.next_domain == other_record.next_domain
1437 && self.type_bitmap == other_record.type_bitmap;
1438 }
1439 false
1440 }
1441
1442 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1443 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1444 match self.next_domain.cmp(&other_nsec.next_domain) {
1445 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1446 ordering => ordering,
1447 }
1448 } else {
1449 cmp::Ordering::Greater
1450 }
1451 }
1452
1453 fn rdata_print(&self) -> String {
1454 format!(
1455 "next_domain: {}, type_bitmap len: {}",
1456 self.next_domain,
1457 self.type_bitmap.len()
1458 )
1459 }
1460
1461 fn clone_box(&self) -> DnsRecordBox {
1462 Box::new(self.clone())
1463 }
1464
1465 fn boxed(self) -> DnsRecordBox {
1466 Box::new(self)
1467 }
1468}
1469
1470#[derive(Clone, Copy, Debug)]
1472enum Section {
1473 Question,
1474 Answer,
1475 Authority,
1476 Additional,
1477}
1478
1479pub struct DnsOutPacket {
1481 data: Vec<u8>,
1483
1484 names: HashMap<String, u16>,
1486
1487 max_size: usize,
1489
1490 question_count: u16,
1492 answer_count: u16,
1493 auth_count: u16,
1494 addi_count: u16,
1495}
1496
1497impl DnsOutPacket {
1498 fn new(max_size: usize) -> Self {
1499 Self {
1500 data: vec![0; MSG_HEADER_LEN],
1501 names: HashMap::new(),
1502 max_size,
1503 question_count: 0,
1504 answer_count: 0,
1505 auth_count: 0,
1506 addi_count: 0,
1507 }
1508 }
1509
1510 pub fn size(&self) -> usize {
1511 self.data.len()
1512 }
1513
1514 pub fn as_bytes(&self) -> &[u8] {
1515 &self.data
1516 }
1517
1518 fn is_empty(&self) -> bool {
1520 self.question_count == 0
1521 && self.answer_count == 0
1522 && self.auth_count == 0
1523 && self.addi_count == 0
1524 }
1525
1526 fn bump(&mut self, section: Section) {
1528 match section {
1529 Section::Question => self.question_count += 1,
1530 Section::Answer => self.answer_count += 1,
1531 Section::Authority => self.auth_count += 1,
1532 Section::Additional => self.addi_count += 1,
1533 }
1534 }
1535
1536 fn write_question(&mut self, question: &DnsQuestion) -> WriteResult {
1537 let start_size = self.size();
1538
1539 self.write_name(&question.entry.name).map_err(|e| {
1540 self.rollback(start_size);
1541 e
1542 })?;
1543 self.write_short(question.entry.ty as u16);
1544 self.write_short(question.entry.class);
1545
1546 if self.size() > self.max_size {
1547 self.rollback(start_size);
1548 return Err(WriteError::PacketFull);
1549 }
1550
1551 Ok(())
1552 }
1553
1554 fn rollback(&mut self, start_size: usize) {
1557 self.data.truncate(start_size);
1558 self.names
1559 .retain(|_, offset| (*offset as usize) < start_size);
1560 }
1561
1562 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> WriteResult {
1566 let start_size = self.size();
1567
1568 let record = record_ext.get_record();
1569 self.write_name(record.get_name())?;
1570 self.write_short(record.entry.ty as u16);
1571 if record.entry.cache_flush {
1572 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1574 } else {
1575 self.write_short(record.entry.class);
1576 }
1577
1578 if now == 0 {
1579 self.write_u32(record.ttl);
1580 } else {
1581 self.write_u32(record.get_remaining_ttl(now));
1582 }
1583
1584 self.write_short(0);
1586 let record_offset = self.size();
1587
1588 if let Err(e) = record_ext.write(self) {
1589 self.rollback(start_size);
1590 return Err(e);
1591 }
1592
1593 self.set_short_at(record_offset - 2, (self.size() - record_offset) as u16);
1594
1595 if self.size() > self.max_size {
1596 self.rollback(start_size);
1597 return Err(WriteError::PacketFull);
1598 }
1599
1600 Ok(())
1601 }
1602
1603 fn set_short_at(&mut self, index: usize, value: u16) {
1604 self.data[index..index + 2].copy_from_slice(&value.to_be_bytes());
1605 }
1606
1607 fn parse_escaped_name(name: &str) -> Vec<String> {
1614 let mut labels = Vec::new();
1615 let mut current_label = String::new();
1616 let mut chars = name.chars().peekable();
1617
1618 while let Some(ch) = chars.next() {
1619 match ch {
1620 '\\' => {
1621 if let Some(&next_ch) = chars.peek() {
1623 match next_ch {
1624 '.' | '\\' => {
1625 chars.next();
1627 current_label.push(next_ch);
1628 }
1629 _ => {
1630 current_label.push(ch);
1632 }
1633 }
1634 } else {
1635 current_label.push(ch);
1637 }
1638 }
1639 '.' => {
1640 if !current_label.is_empty() {
1642 labels.push(current_label.clone());
1643 current_label.clear();
1644 }
1645 }
1646 _ => {
1647 current_label.push(ch);
1648 }
1649 }
1650 }
1651
1652 if !current_label.is_empty() {
1654 labels.push(current_label);
1655 }
1656
1657 labels
1658 }
1659
1660 fn write_name(&mut self, name: &str) -> WriteResult {
1686 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1688
1689 let labels = Self::parse_escaped_name(name_to_parse);
1691
1692 if labels.is_empty() {
1693 self.write_byte(0);
1694 return Ok(());
1695 }
1696
1697 if labels.iter().any(|label| label.len() > MAX_LABEL_BYTES) {
1699 return Err(WriteError::NameTooLong);
1700 }
1701
1702 for (i, label) in labels.iter().enumerate() {
1704 let remaining: String = labels[i..].join(".");
1706
1707 const POINTER_MASK: u16 = 0xC000;
1709 if let Some(&offset) = self.names.get(&remaining) {
1710 let pointer = offset | POINTER_MASK;
1711 self.write_short(pointer);
1712 return Ok(());
1713 }
1714
1715 self.names.insert(remaining, self.size() as u16);
1717
1718 self.write_utf8(label)?;
1720 }
1721
1722 self.write_byte(0);
1724 Ok(())
1725 }
1726
1727 fn write_byte(&mut self, v: u8) {
1728 self.data.push(v);
1729 }
1730
1731 fn write_bytes(&mut self, s: &[u8]) {
1732 self.data.extend(s);
1733 }
1734
1735 fn write_utf8(&mut self, s: &str) -> WriteResult {
1738 if s.len() > MAX_LABEL_BYTES {
1739 return Err(WriteError::NameTooLong);
1740 }
1741 self.write_byte(s.len() as u8);
1742 self.write_bytes(s.as_bytes());
1743 Ok(())
1744 }
1745
1746 fn write_u32(&mut self, v: u32) {
1747 self.data.extend(&v.to_be_bytes());
1748 }
1749
1750 fn write_short(&mut self, v: u16) {
1751 self.data.extend(&v.to_be_bytes());
1752 }
1753
1754 fn set_truncated(&mut self) {
1757 let flags = u16::from_be_bytes([self.data[2], self.data[3]]);
1758 self.set_short_at(2, flags | FLAGS_TC);
1759 }
1760
1761 fn write_header(&mut self, id: u16, flags: u16) {
1784 self.set_short_at(0, id);
1785 self.set_short_at(2, flags);
1786 self.set_short_at(4, self.question_count);
1787 self.set_short_at(6, self.answer_count);
1788 self.set_short_at(8, self.auth_count);
1789 self.set_short_at(10, self.addi_count);
1790 }
1791}
1792
1793struct PacketBuilder<'a> {
1796 out: &'a DnsOutgoing,
1797
1798 max_size: usize,
1800
1801 is_ipv4: bool,
1804
1805 finished: Vec<DnsOutPacket>,
1806 current: DnsOutPacket,
1807}
1808
1809impl<'a> PacketBuilder<'a> {
1810 fn new(out: &'a DnsOutgoing, max_size: usize, is_ipv4: bool) -> Self {
1811 Self {
1812 out,
1813 max_size,
1814 is_ipv4,
1815 finished: Vec::new(),
1816 current: DnsOutPacket::new(max_size),
1817 }
1818 }
1819
1820 fn add<F>(&mut self, section: Section, write: F)
1827 where
1828 F: Fn(&mut DnsOutPacket) -> WriteResult,
1829 {
1830 match write(&mut self.current) {
1831 Ok(()) => {
1832 self.current.bump(section);
1833 return;
1834 }
1835 Err(WriteError::NameTooLong) => return,
1837 Err(WriteError::PacketFull) => {}
1838 }
1839
1840 if !self.current.is_empty() {
1842 self.flush();
1843
1844 match write(&mut self.current) {
1845 Ok(()) => {
1846 self.current.bump(section);
1847 return;
1848 }
1849 Err(WriteError::NameTooLong) => return,
1850 Err(WriteError::PacketFull) => {}
1851 }
1852 }
1853
1854 if matches!(section, Section::Question) {
1856 return;
1857 }
1858
1859 self.current.max_size = max_pkt_absolute(self.is_ipv4);
1865
1866 if write(&mut self.current).is_ok() {
1867 self.current.bump(section);
1868 self.flush();
1869 } else {
1870 self.current.max_size = self.max_size;
1872 debug!(
1873 "Record too big for absolute max size, skipping: {:?}",
1874 section
1875 );
1876 }
1877 }
1878
1879 fn flush(&mut self) {
1881 self.current
1882 .write_header(self.out.wire_id(), self.out.flags);
1883
1884 let next = DnsOutPacket::new(self.max_size);
1885 self.finished
1886 .push(std::mem::replace(&mut self.current, next));
1887 }
1888
1889 fn finish(mut self) -> Vec<DnsOutPacket> {
1890 if !self.current.is_empty() || self.finished.is_empty() {
1893 self.flush();
1894 }
1895
1896 let mut packets = self.finished;
1897
1898 if self.out.is_query() {
1906 if let Some((_last, rest)) = packets.split_last_mut() {
1907 for packet in rest {
1908 packet.set_truncated();
1909 }
1910 }
1911 }
1912
1913 packets
1914 }
1915}
1916
1917#[derive(Debug)]
1919pub struct DnsOutgoing {
1920 flags: u16,
1921 id: u16,
1922 multicast: bool,
1923 questions: Vec<DnsQuestion>,
1924 answers: Vec<(DnsRecordBox, u64)>,
1925 authorities: Vec<DnsRecordBox>,
1926 additionals: Vec<DnsRecordBox>,
1927 known_answer_count: i64, }
1929
1930impl DnsOutgoing {
1931 pub fn new(flags: u16) -> Self {
1932 Self {
1933 flags,
1934 id: 0,
1935 multicast: true,
1936 questions: Vec::new(),
1937 answers: Vec::new(),
1938 authorities: Vec::new(),
1939 additionals: Vec::new(),
1940 known_answer_count: 0,
1941 }
1942 }
1943
1944 pub fn questions(&self) -> &[DnsQuestion] {
1945 &self.questions
1946 }
1947
1948 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1950 &self.answers
1951 }
1952
1953 pub fn answers_count(&self) -> usize {
1954 self.answers.len()
1955 }
1956
1957 pub fn authorities(&self) -> &[DnsRecordBox] {
1958 &self.authorities
1959 }
1960
1961 pub fn additionals(&self) -> &[DnsRecordBox] {
1962 &self.additionals
1963 }
1964
1965 pub fn known_answer_count(&self) -> i64 {
1966 self.known_answer_count
1967 }
1968
1969 pub fn set_id(&mut self, id: u16) {
1970 self.id = id;
1971 }
1972
1973 const fn wire_id(&self) -> u16 {
1975 if self.multicast {
1976 0
1977 } else {
1978 self.id
1979 }
1980 }
1981
1982 pub const fn is_query(&self) -> bool {
1983 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1984 }
1985
1986 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
2020 trace!("add_additional_answer: {:?}", &answer);
2021 self.additionals.push(answer.boxed());
2022 }
2023
2024 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
2026 self.answers.push((answer_box, 0));
2027 }
2028
2029 pub fn add_authority(&mut self, record: DnsRecordBox) {
2030 self.authorities.push(record);
2031 }
2032
2033 pub(crate) fn retain_answers<F>(&mut self, mut keep: F)
2035 where
2036 F: FnMut(&DnsRecordBox) -> bool,
2037 {
2038 self.answers.retain(|(record, _)| keep(record));
2039 }
2040
2041 pub(crate) fn retain_additionals<F>(&mut self, mut keep: F)
2043 where
2044 F: FnMut(&DnsRecordBox) -> bool,
2045 {
2046 self.additionals.retain(|record| keep(record));
2047 }
2048
2049 pub fn add_answer(
2052 &mut self,
2053 msg: &DnsIncoming,
2054 answer: impl DnsRecordExt + Send + 'static,
2055 ) -> bool {
2056 trace!("Check for add_answer");
2057 if answer.suppressed_by(msg) {
2058 trace!("my answer is suppressed by incoming msg");
2059 self.known_answer_count += 1;
2060 return false;
2061 }
2062
2063 self.add_answer_at_time(answer, 0)
2064 }
2065
2066 pub fn add_answer_at_time(
2070 &mut self,
2071 answer: impl DnsRecordExt + Send + 'static,
2072 now: u64,
2073 ) -> bool {
2074 if now == 0 || !answer.get_record().is_expired(now) {
2075 trace!("add_answer push: {:?}", &answer);
2076 self.answers.push((answer.boxed(), now));
2077 return true;
2078 }
2079 false
2080 }
2081
2082 pub(crate) fn add_answer_with_additionals(
2091 &mut self,
2092 msg: &DnsIncoming,
2093 service: &ServiceInfo,
2094 intf: &MyIntf,
2095 dns_registry: &DnsRegistry,
2096 is_ipv4: bool,
2097 ) {
2098 let intf_addrs = if is_ipv4 {
2099 service.get_addrs_on_my_intf_v4(intf)
2100 } else {
2101 service.get_addrs_on_my_intf_v6(intf)
2102 };
2103 if intf_addrs.is_empty() {
2104 trace!("No addrs on LAN of intf {:?}", intf);
2105 return;
2106 }
2107
2108 let service_fullname = dns_registry.resolve_name(service.get_fullname());
2110 let hostname = dns_registry.resolve_name(service.get_hostname());
2111
2112 let ptr_added = self.add_answer(
2113 msg,
2114 DnsPointer::new(
2115 service.get_type(),
2116 RRType::PTR,
2117 CLASS_IN,
2118 service.get_other_ttl(),
2119 service_fullname.to_string(),
2120 ),
2121 );
2122
2123 if !ptr_added {
2124 trace!("answer was not added for msg {:?}", msg);
2125 return;
2126 }
2127
2128 if let Some(sub) = service.get_subtype() {
2129 trace!("Adding subdomain {}", sub);
2130 self.add_additional_answer(DnsPointer::new(
2131 sub,
2132 RRType::PTR,
2133 CLASS_IN,
2134 service.get_other_ttl(),
2135 service_fullname.to_string(),
2136 ));
2137 }
2138
2139 self.add_additional_answer(DnsSrv::new(
2142 service_fullname,
2143 CLASS_IN | CLASS_CACHE_FLUSH,
2144 service.get_host_ttl(),
2145 service.get_priority(),
2146 service.get_weight(),
2147 service.get_port(),
2148 hostname.to_string(),
2149 ));
2150
2151 self.add_additional_answer(DnsTxt::new(
2152 service_fullname,
2153 CLASS_IN | CLASS_CACHE_FLUSH,
2154 service.get_other_ttl(),
2155 service.generate_txt(),
2156 ));
2157
2158 for address in intf_addrs {
2159 self.add_additional_answer(DnsAddress::new(
2160 hostname,
2161 ip_address_rr_type(&address),
2162 CLASS_IN | CLASS_CACHE_FLUSH,
2163 service.get_host_ttl(),
2164 address,
2165 intf.into(),
2166 ));
2167 }
2168 }
2169
2170 pub fn add_question(&mut self, name: &str, qtype: RRType) {
2171 let q = DnsQuestion {
2172 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
2173 };
2174 self.questions.push(q);
2175 }
2176
2177 pub fn clear_cache_flush_bits(&mut self) {
2182 for (rec, _) in &mut self.answers {
2183 rec.get_record_mut().entry.cache_flush = false;
2184 }
2185 for rec in &mut self.additionals {
2186 rec.get_record_mut().entry.cache_flush = false;
2187 }
2188 for rec in &mut self.authorities {
2189 rec.get_record_mut().entry.cache_flush = false;
2190 }
2191 }
2192
2193 pub fn to_data_on_wire(&self, max_size: usize, is_ipv4: bool) -> Vec<Vec<u8>> {
2198 let packet_list = self.to_packets(max_size, is_ipv4);
2199 packet_list.into_iter().map(|p| p.data).collect()
2200 }
2201
2202 pub fn to_packets(&self, max_size: usize, is_ipv4: bool) -> Vec<DnsOutPacket> {
2219 debug_assert!(
2220 max_size <= MAX_PKT_ABSOLUTE_IPV6,
2221 "max_size {} exceeds the RFC 6762 section 17 ceiling",
2222 max_size
2223 );
2224 let mut builder = PacketBuilder::new(self, max_size, is_ipv4);
2225
2226 for question in self.questions.iter() {
2227 builder.add(Section::Question, |packet| packet.write_question(question));
2228 }
2229
2230 for (answer, time) in self.answers.iter() {
2231 builder.add(Section::Answer, |packet| {
2232 packet.write_record(answer.as_ref(), *time)
2233 });
2234 }
2235
2236 for auth in self.authorities.iter() {
2237 builder.add(Section::Authority, |packet| {
2238 packet.write_record(auth.as_ref(), 0)
2239 });
2240 }
2241
2242 for addi in self.additionals.iter() {
2243 builder.add(Section::Additional, |packet| {
2244 packet.write_record(addi.as_ref(), 0)
2245 });
2246 }
2247
2248 builder.finish()
2249 }
2250}
2251
2252#[derive(Debug)]
2254pub struct DnsIncoming {
2255 offset: usize,
2256 data: Vec<u8>,
2257 questions: Vec<DnsQuestion>,
2258 answers: Vec<DnsRecordBox>,
2259 authorities: Vec<DnsRecordBox>,
2260 additional: Vec<DnsRecordBox>,
2261 id: u16,
2262 flags: u16,
2263 num_questions: u16,
2264 num_answers: u16,
2265 num_authorities: u16,
2266 num_additionals: u16,
2267 interface_id: InterfaceId,
2268}
2269
2270impl DnsIncoming {
2271 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2272 let mut incoming = Self {
2273 offset: 0,
2274 data,
2275 questions: Vec::new(),
2276 answers: Vec::new(),
2277 authorities: Vec::new(),
2278 additional: Vec::new(),
2279 id: 0,
2280 flags: 0,
2281 num_questions: 0,
2282 num_answers: 0,
2283 num_authorities: 0,
2284 num_additionals: 0,
2285 interface_id,
2286 };
2287
2288 incoming.read_header()?;
2308 incoming.read_questions()?;
2309 incoming.read_answers()?;
2310 incoming.read_authorities()?;
2311 incoming.read_additional()?;
2312
2313 Ok(incoming)
2314 }
2315
2316 pub fn id(&self) -> u16 {
2317 self.id
2318 }
2319
2320 pub fn questions(&self) -> &[DnsQuestion] {
2321 &self.questions
2322 }
2323
2324 pub fn answers(&self) -> &[DnsRecordBox] {
2325 &self.answers
2326 }
2327
2328 pub fn authorities(&self) -> &[DnsRecordBox] {
2329 &self.authorities
2330 }
2331
2332 pub fn additionals(&self) -> &[DnsRecordBox] {
2333 &self.additional
2334 }
2335
2336 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2337 &mut self.answers
2338 }
2339
2340 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2341 &mut self.authorities
2342 }
2343
2344 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2345 &mut self.additional
2346 }
2347
2348 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2349 self.answers
2350 .into_iter()
2351 .chain(self.authorities)
2352 .chain(self.additional)
2353 }
2354
2355 pub fn num_additionals(&self) -> u16 {
2356 self.num_additionals
2357 }
2358
2359 pub fn num_authorities(&self) -> u16 {
2360 self.num_authorities
2361 }
2362
2363 pub fn num_questions(&self) -> u16 {
2364 self.num_questions
2365 }
2366
2367 pub const fn is_query(&self) -> bool {
2368 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2369 }
2370
2371 pub const fn is_response(&self) -> bool {
2372 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2373 }
2374
2375 fn read_header(&mut self) -> Result<()> {
2376 if self.data.len() < MSG_HEADER_LEN {
2377 return Err(e_fmt!(
2378 "DNS incoming: header is too short: {} bytes",
2379 self.data.len()
2380 ));
2381 }
2382
2383 let data = &self.data[0..];
2384 self.id = u16_from_be_slice(&data[..2]);
2385 self.flags = u16_from_be_slice(&data[2..4]);
2386 self.num_questions = u16_from_be_slice(&data[4..6]);
2387 self.num_answers = u16_from_be_slice(&data[6..8]);
2388 self.num_authorities = u16_from_be_slice(&data[8..10]);
2389 self.num_additionals = u16_from_be_slice(&data[10..12]);
2390
2391 self.offset = MSG_HEADER_LEN;
2392
2393 trace!(
2394 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2395 self.id,
2396 self.num_questions,
2397 self.num_answers,
2398 self.num_authorities,
2399 self.num_additionals
2400 );
2401 Ok(())
2402 }
2403
2404 fn read_questions(&mut self) -> Result<()> {
2405 trace!("read_questions: {}", &self.num_questions);
2406 for i in 0..self.num_questions {
2407 let name = self.read_name()?;
2408
2409 let data = &self.data[self.offset..];
2410 if data.len() < 4 {
2411 return Err(Error::Msg(format!(
2412 "DNS incoming: question idx {} too short: {}",
2413 i,
2414 data.len()
2415 )));
2416 }
2417 let ty = u16_from_be_slice(&data[..2]);
2418 let class = u16_from_be_slice(&data[2..4]);
2419 self.offset += 4;
2420
2421 let Some(rr_type) = RRType::from_u16(ty) else {
2422 return Err(Error::Msg(format!(
2423 "DNS incoming: question idx {i} qtype unknown: {ty}",
2424 )));
2425 };
2426
2427 self.questions.push(DnsQuestion {
2428 entry: DnsEntry::new(name, rr_type, class),
2429 });
2430 }
2431 Ok(())
2432 }
2433
2434 fn read_answers(&mut self) -> Result<()> {
2435 self.answers = self.read_rr_records(self.num_answers)?;
2436 Ok(())
2437 }
2438
2439 fn read_authorities(&mut self) -> Result<()> {
2440 self.authorities = self.read_rr_records(self.num_authorities)?;
2441 Ok(())
2442 }
2443
2444 fn read_additional(&mut self) -> Result<()> {
2445 self.additional = self.read_rr_records(self.num_additionals)?;
2446 Ok(())
2447 }
2448
2449 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2451 trace!("read_rr_records: {}", count);
2452 let mut rr_records = Vec::new();
2453
2454 const RR_HEADER_REMAIN: usize = 10;
2480
2481 for _ in 0..count {
2482 let name = self.read_name()?;
2483 let slice = &self.data[self.offset..];
2484
2485 if slice.len() < RR_HEADER_REMAIN {
2486 return Err(Error::Msg(format!(
2487 "read_others: RR '{}' is too short after name: {} bytes",
2488 &name,
2489 slice.len()
2490 )));
2491 }
2492
2493 let ty = u16_from_be_slice(&slice[..2]);
2494 let class = u16_from_be_slice(&slice[2..4]);
2495 let mut ttl = u32_from_be_slice(&slice[4..8]);
2496 if ttl == 0 && self.is_response() {
2497 ttl = 1;
2504 }
2505 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2506 self.offset += RR_HEADER_REMAIN;
2507 let next_offset = self.offset + rdata_len;
2508
2509 if next_offset > self.data.len() {
2511 return Err(Error::Msg(format!(
2512 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2513 self.data.len() - self.offset
2514 )));
2515 }
2516
2517 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2519 None => None,
2520
2521 Some(rr_type) => match rr_type {
2522 RRType::CNAME | RRType::PTR => {
2523 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
2524 }
2525 RRType::TXT => {
2526 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
2527 }
2528 RRType::SRV => Some(
2529 DnsSrv::new(
2530 &name,
2531 class,
2532 ttl,
2533 self.read_u16()?,
2534 self.read_u16()?,
2535 self.read_u16()?,
2536 self.read_name()?,
2537 )
2538 .boxed(),
2539 ),
2540 RRType::HINFO => Some(
2541 DnsHostInfo::new(
2542 &name,
2543 rr_type,
2544 class,
2545 ttl,
2546 self.read_char_string()?,
2547 self.read_char_string()?,
2548 )
2549 .boxed(),
2550 ),
2551 RRType::A => Some(
2552 DnsAddress::new(
2553 &name,
2554 rr_type,
2555 class,
2556 ttl,
2557 self.read_ipv4()?.into(),
2558 self.interface_id.clone(),
2559 )
2560 .boxed(),
2561 ),
2562 RRType::AAAA => Some(
2563 DnsAddress::new(
2564 &name,
2565 rr_type,
2566 class,
2567 ttl,
2568 self.read_ipv6()?.into(),
2569 self.interface_id.clone(),
2570 )
2571 .boxed(),
2572 ),
2573 RRType::NSEC => Some(
2574 DnsNSec::new(
2575 &name,
2576 class,
2577 ttl,
2578 self.read_name()?,
2579 self.read_type_bitmap()?,
2580 )
2581 .boxed(),
2582 ),
2583 _ => None,
2584 },
2585 };
2586
2587 if let Some(record) = rec {
2588 trace!("read_rr_records: {:?}", &record);
2589 rr_records.push(record);
2590 } else {
2591 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2592 self.offset += rdata_len;
2593 }
2594
2595 if self.offset != next_offset {
2597 return Err(Error::Msg(format!(
2598 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2599 ty, self.offset, next_offset,
2600 )));
2601 }
2602 }
2603
2604 Ok(rr_records)
2605 }
2606
2607 fn read_char_string(&mut self) -> Result<String> {
2608 let length = self.data[self.offset];
2609 self.offset += 1;
2610 self.read_string(length as usize)
2611 }
2612
2613 fn read_u16(&mut self) -> Result<u16> {
2614 let slice = &self.data[self.offset..];
2615 if slice.len() < U16_SIZE {
2616 return Err(Error::Msg(format!(
2617 "read_u16: slice len is only {}",
2618 slice.len()
2619 )));
2620 }
2621 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2622 self.offset += U16_SIZE;
2623 Ok(num)
2624 }
2625
2626 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2628 if self.data.len() < self.offset + 2 {
2637 return Err(Error::Msg(format!(
2638 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2639 self.data.len(),
2640 self.offset
2641 )));
2642 }
2643
2644 let block_num = self.data[self.offset];
2645 self.offset += 1;
2646 if block_num != 0 {
2647 return Err(Error::Msg(format!(
2648 "NSEC block number is not 0: {block_num}"
2649 )));
2650 }
2651
2652 let block_len = self.data[self.offset] as usize;
2653 if !(1..=32).contains(&block_len) {
2654 return Err(Error::Msg(format!(
2655 "NSEC block length must be in the range 1-32: {block_len}"
2656 )));
2657 }
2658 self.offset += 1;
2659
2660 let end = self.offset + block_len;
2661 if end > self.data.len() {
2662 return Err(Error::Msg(format!(
2663 "NSEC block overflow: {} over RData len {}",
2664 end,
2665 self.data.len()
2666 )));
2667 }
2668 let bitmap = self.data[self.offset..end].to_vec();
2669 self.offset += block_len;
2670
2671 Ok(bitmap)
2672 }
2673
2674 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2675 if self.data.len() < self.offset + length {
2676 return Err(e_fmt!(
2677 "DNS Incoming: not enough data to read a chunk of data"
2678 ));
2679 }
2680
2681 let v = self.data[self.offset..self.offset + length].to_vec();
2682 self.offset += length;
2683 Ok(v)
2684 }
2685
2686 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2687 if self.data.len() < self.offset + 4 {
2688 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2689 }
2690
2691 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2692 .try_into()
2693 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2694 self.offset += bytes.len();
2695 Ok(Ipv4Addr::from(bytes))
2696 }
2697
2698 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2699 if self.data.len() < self.offset + 16 {
2700 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2701 }
2702
2703 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2704 .try_into()
2705 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2706 self.offset += bytes.len();
2707 Ok(Ipv6Addr::from(bytes))
2708 }
2709
2710 fn read_string(&mut self, length: usize) -> Result<String> {
2711 if self.data.len() < self.offset + length {
2712 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2713 }
2714
2715 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2716 .map_err(|e| Error::Msg(e.to_string()))?;
2717 self.offset += length;
2718 Ok(s.to_string())
2719 }
2720
2721 fn read_name(&mut self) -> Result<String> {
2726 let data = &self.data[..];
2727 let start_offset = self.offset;
2728 let mut offset = start_offset;
2729 let mut name = "".to_string();
2730 let mut at_end = false;
2731
2732 loop {
2743 if offset >= data.len() {
2744 return Err(Error::Msg(format!(
2745 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2746 offset,
2747 data.len(),
2748 self
2749 )));
2750 }
2751 let length = data[offset];
2752
2753 if length == 0 {
2757 if !at_end {
2758 self.offset = offset + 1;
2759 }
2760 break; }
2762
2763 match length & 0xC0 {
2765 0x00 => {
2766 offset += 1;
2768 let ending = offset + length as usize;
2769
2770 if ending > data.len() {
2772 return Err(Error::Msg(format!(
2773 "read_name: ending {} exceeds data length {}",
2774 ending,
2775 data.len()
2776 )));
2777 }
2778
2779 name += str::from_utf8(&data[offset..ending])
2780 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {e}")))?;
2781 name += ".";
2782 offset += length as usize;
2783 }
2784 0xC0 => {
2785 let slice = &data[offset..];
2788 if slice.len() < U16_SIZE {
2789 return Err(Error::Msg(format!(
2790 "read_name: u16 slice len is only {}",
2791 slice.len()
2792 )));
2793 }
2794 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2795 if pointer >= start_offset {
2796 return Err(Error::Msg(format!(
2798 "Invalid name compression: pointer {} must be less than the start offset {}",
2799 &pointer, &start_offset
2800 )));
2801 }
2802
2803 if !at_end {
2805 self.offset = offset + U16_SIZE;
2806 at_end = true;
2807 }
2808 offset = pointer;
2809 }
2810 _ => {
2811 return Err(Error::Msg(format!(
2812 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2813 length,
2814 offset,
2815 &data[..offset]
2816 )));
2817 }
2818 };
2819 }
2820
2821 Ok(name)
2822 }
2823}
2824
2825const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2826 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2827 u16::from_be_bytes(u8_array)
2828}
2829
2830const fn u32_from_be_slice(s: &[u8]) -> u32 {
2831 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2832 u32::from_be_bytes(u8_array)
2833}
2834
2835const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2838 created + (ttl as u64 * percent as u64 * 10)
2841}
2842
2843#[cfg(test)]
2844mod tests {
2845 use super::{
2846 DnsAddress, DnsHostInfo, DnsIncoming, DnsOutPacket, DnsOutgoing, DnsPointer, DnsTxt,
2847 RRType, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE, FLAGS_TC,
2848 MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT, MSG_HEADER_LEN,
2849 };
2850 use crate::InterfaceId;
2851 use std::collections::HashMap;
2852 use std::net::{IpAddr, Ipv4Addr};
2853
2854 const IPV6: bool = false;
2857
2858 #[test]
2859 fn test_dns_outgoing_serialization_empty() {
2860 let out = DnsOutgoing::new(0);
2861 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2862 assert_eq!(packets.len(), 1);
2863 assert_eq!(packets[0].as_bytes(), &[0; 12]);
2864 let expected_names = HashMap::new();
2865 assert_eq!(&packets[0].names, &expected_names);
2866 }
2867
2868 #[test]
2869 fn test_dns_outgoing_serialization_question() {
2870 let mut out = DnsOutgoing::new(0);
2871 out.add_question("123.test", RRType::A);
2872 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2873 assert_eq!(packets.len(), 1);
2874 assert_eq!(
2875 packets[0].as_bytes(),
2876 &[
2877 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,
2880 ]
2881 );
2882 let mut expected_names = HashMap::new();
2883 expected_names.insert("123.test".to_string(), 12);
2884 expected_names.insert("test".to_string(), 16);
2885 assert_eq!(&packets[0].names, &expected_names);
2886 }
2887
2888 #[test]
2889 fn test_dns_outgoing_serialization_question_with_authority() {
2890 let mut out = DnsOutgoing::new(0);
2891 out.add_question("123.test", RRType::ANY);
2892 out.add_authority(Box::new(DnsTxt::new(
2893 "124.test",
2894 CLASS_IN,
2895 0x00112233,
2896 b"help".to_vec(),
2897 )));
2898 out.add_authority(Box::new(DnsHostInfo::new(
2899 "124.test",
2900 RRType::CNAME,
2901 CLASS_IN,
2902 0x00112233,
2903 "arm".to_string(),
2904 "linux".to_string(),
2905 )));
2906 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2907 assert_eq!(packets.len(), 1);
2908 assert_eq!(
2909 packets[0].as_bytes(),
2910 &[
2911 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,
2914 16, 0, 1, 0, 17, 34, 51, 0, 4, 104, 101, 108, 112, 192, 26, 0, 5, 0, 1, 0, 17, 34,
2915 51, 0, 8, 97, 114, 109, 108, 105, 110, 117, 120,
2916 ]
2917 );
2918 let mut expected_names = HashMap::new();
2919 expected_names.insert("123.test".to_string(), 12);
2920 expected_names.insert("test".to_string(), 16);
2921 expected_names.insert("124.test".to_string(), 26);
2922 assert_eq!(&packets[0].names, &expected_names);
2923 }
2924
2925 #[test]
2926 fn test_dns_outgoing_serialization_additional_answer() {
2927 let mut out = DnsOutgoing::new(0);
2928 out.add_additional_answer(DnsAddress::new(
2929 "test.local",
2930 RRType::A,
2931 CLASS_IN | CLASS_CACHE_FLUSH,
2932 0xdead_beef,
2933 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
2934 InterfaceId::default(),
2935 ));
2936 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2937 assert_eq!(packets.len(), 1);
2938 assert_eq!(
2939 packets[0].as_bytes(),
2940 &[
2941 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,
2944 239, 0, 4, 127, 0, 0, 1,
2945 ]
2946 );
2947 let mut expected_names = HashMap::new();
2948 expected_names.insert("test.local".to_string(), 12);
2949 expected_names.insert("local".to_string(), 17);
2950 assert_eq!(&packets[0].names, &expected_names);
2951 }
2952
2953 #[test]
2954 fn test_dns_outgoing_serialization_answer_at_time() {
2955 let mut out = DnsOutgoing::new(0);
2956 out.add_answer_at_time(
2957 DnsPointer::new(
2958 "test",
2959 RRType::PTR,
2960 CLASS_IN,
2961 0xaaaa5555,
2962 "test-service".to_string(),
2963 ),
2964 0,
2965 );
2966 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2967 assert_eq!(packets.len(), 1);
2968 assert_eq!(
2969 packets[0].as_bytes(),
2970 &[
2971 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,
2974 116, 45, 115, 101, 114, 118, 105, 99, 101, 0,
2975 ]
2976 );
2977
2978 let mut out = DnsOutgoing::new(0);
2979 out.add_answer_at_time(
2980 DnsPointer::new(
2981 "test",
2982 RRType::CNAME,
2983 CLASS_IN,
2984 0xaaaa5555,
2985 "test-service.local".to_string(),
2986 ),
2987 0,
2988 );
2989 out.add_answer_at_time(
2990 DnsPointer::new(
2991 "test",
2992 RRType::AAAA,
2993 CLASS_IN,
2994 0xffffffff,
2995 "test-service.local".to_string(),
2996 ),
2997 0,
2998 );
2999 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3000 assert_eq!(packets.len(), 1);
3001 assert_eq!(
3002 packets[0].as_bytes(),
3003 &[
3004 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,
3007 116, 45, 115, 101, 114, 118, 105, 99, 101, 5, 108, 111, 99, 97, 108, 0, 192, 12, 0,
3008 28, 0, 1, 255, 255, 255, 255, 0, 2, 192, 28,
3009 ]
3010 );
3011 let mut expected_names = HashMap::new();
3012 expected_names.insert("test".to_string(), 12);
3013 expected_names.insert("test-service.local".to_string(), 28);
3014 expected_names.insert("local".to_string(), 41);
3015 assert_eq!(&packets[0].names, &expected_names);
3016 }
3017
3018 #[test]
3022 fn test_dns_outgoing_question_label_too_long() {
3023 let long_label = "a".repeat(64);
3024 let mut out = DnsOutgoing::new(0);
3025 out.add_question(&format!("{long_label}.local"), RRType::PTR);
3026 out.add_question("123.test", RRType::A);
3027
3028 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3029 assert_eq!(packets.len(), 1);
3030 assert_eq!(
3031 packets[0].as_bytes(),
3032 &[
3033 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,
3036 ]
3037 );
3038
3039 let mut expected_names = HashMap::new();
3041 expected_names.insert("123.test".to_string(), 12);
3042 expected_names.insert("test".to_string(), 16);
3043 assert_eq!(&packets[0].names, &expected_names);
3044 }
3045
3046 #[test]
3049 fn test_dns_outgoing_record_label_too_long() {
3050 let long_label = "a".repeat(64);
3051 let mut out = DnsOutgoing::new(0);
3052 out.add_answer_at_time(
3053 DnsPointer::new(
3054 "_test._tcp.local.",
3055 RRType::PTR,
3056 CLASS_IN,
3057 0,
3058 format!("{long_label}._test._tcp.local."),
3059 ),
3060 0,
3061 );
3062 out.add_answer_at_time(
3063 DnsPointer::new(
3064 "_test._tcp.local.",
3065 RRType::PTR,
3066 CLASS_IN,
3067 0,
3068 "ok._test._tcp.local.".to_string(),
3069 ),
3070 0,
3071 );
3072
3073 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3074 assert_eq!(packets.len(), 1);
3075
3076 assert_eq!(&packets[0].as_bytes()[6..8], &[0, 1]);
3078
3079 let incoming = DnsIncoming::new(
3081 packets[0].as_bytes().to_vec(),
3082 InterfaceId {
3083 name: "test".to_string(),
3084 index: 1,
3085 },
3086 )
3087 .unwrap();
3088 assert_eq!(incoming.answers().len(), 1);
3089 }
3090
3091 #[test]
3096 fn test_incoming_name_with_merged_labels_does_not_panic() {
3097 let mut data: Vec<u8> = vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
3099 data.push(63);
3100 data.extend(vec![b'a'; 62]);
3101 data.push(b'\\');
3102 data.push(63);
3103 data.extend(vec![b'b'; 63]);
3104 data.push(0);
3105 data.extend([0, 12, 0, 1]); let incoming = DnsIncoming::new(
3108 data,
3109 InterfaceId {
3110 name: "test".to_string(),
3111 index: 1,
3112 },
3113 )
3114 .unwrap();
3115 let name = incoming.questions()[0].entry.name.clone();
3116
3117 assert!(name.starts_with("aaa"));
3119 assert!(name.contains("\\.bbb"));
3120
3121 let mut out = DnsOutgoing::new(0);
3123 out.add_question(&name, RRType::PTR);
3124 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3125 assert_eq!(packets.len(), 1);
3126 assert_eq!(packets[0].as_bytes(), &[0; MSG_HEADER_LEN]);
3127 }
3128
3129 fn test_interface_id() -> InterfaceId {
3130 InterfaceId {
3131 name: "test".to_string(),
3132 index: 1,
3133 }
3134 }
3135
3136 fn packet_flags(packet: &DnsOutPacket) -> u16 {
3138 let bytes = packet.as_bytes();
3139 u16::from_be_bytes([bytes[2], bytes[3]])
3140 }
3141
3142 fn ptr_answer(index: usize) -> DnsPointer {
3143 DnsPointer::new(
3144 "_spill._tcp.local.",
3145 RRType::PTR,
3146 CLASS_IN,
3147 4500,
3148 format!("instance-{index:04}._spill._tcp.local."),
3149 )
3150 }
3151
3152 fn parsed_answer_count(packets: &[DnsOutPacket]) -> usize {
3155 packets
3156 .iter()
3157 .map(|packet: &DnsOutPacket| {
3158 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id())
3159 .expect("each packet must parse on its own");
3160 assert!(
3161 !parsed.answers().is_empty(),
3162 "a spilled packet must not be empty"
3163 );
3164 parsed.answers().len()
3165 })
3166 .sum()
3167 }
3168
3169 #[test]
3172 fn test_dns_outgoing_response_spills_into_packets() {
3173 const ANSWER_COUNT: usize = 100;
3174
3175 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3176 for i in 0..ANSWER_COUNT {
3177 out.add_answer_at_time(ptr_answer(i), 0);
3178 }
3179
3180 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3181 assert!(
3182 packets.len() > 1,
3183 "{} answers should not fit in one packet",
3184 ANSWER_COUNT
3185 );
3186
3187 for packet in &packets {
3188 assert!(
3189 packet.size() <= MAX_PKT_DEFAULT,
3190 "packet of {} bytes exceeds the limit",
3191 packet.size()
3192 );
3193
3194 assert_eq!(packet_flags(packet) & FLAGS_TC, 0);
3197 }
3198
3199 assert_eq!(parsed_answer_count(&packets), ANSWER_COUNT);
3200 }
3201
3202 #[test]
3205 fn test_dns_outgoing_query_truncation_bit() {
3206 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
3207 out.add_question("_spill._tcp.local.", RRType::PTR);
3208 for i in 0..100 {
3209 out.add_answer_box(Box::new(ptr_answer(i)));
3210 }
3211
3212 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3213 assert!(
3214 packets.len() > 1,
3215 "known answers should not fit in one packet"
3216 );
3217
3218 let (last, rest) = packets.split_last().expect("at least one packet");
3219 for packet in rest {
3220 assert_ne!(
3221 packet_flags(packet) & FLAGS_TC,
3222 0,
3223 "a packet with more known answers to follow must set TC"
3224 );
3225 }
3226 assert_eq!(
3227 packet_flags(last) & FLAGS_TC,
3228 0,
3229 "the last packet must not set TC"
3230 );
3231
3232 assert_eq!(packets[0].as_bytes()[4..6], 1u16.to_be_bytes());
3234 for packet in rest.iter().skip(1) {
3235 assert_eq!(packet.as_bytes()[4..6], [0, 0]);
3236 }
3237 assert_eq!(parsed_answer_count(&packets), 100);
3238 }
3239
3240 #[test]
3244 fn test_dns_outgoing_oversized_record_sent_alone() {
3245 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3246 out.add_answer_at_time(ptr_answer(0), 0);
3247 out.add_answer_at_time(
3248 DnsTxt::new("big._spill._tcp.local.", CLASS_IN, 4500, vec![b'x'; 2000]),
3249 0,
3250 );
3251 out.add_answer_at_time(ptr_answer(1), 0);
3252
3253 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3254 assert_eq!(packets.len(), 3, "the big record needs a packet to itself");
3255
3256 assert!(packets[0].size() <= MAX_PKT_DEFAULT);
3257 assert!(
3258 packets[1].size() > MAX_PKT_DEFAULT,
3259 "the oversized record must not be dropped"
3260 );
3261 assert!(packets[1].size() <= MAX_PKT_ABSOLUTE_IPV6);
3263 assert!(packets[2].size() <= MAX_PKT_DEFAULT);
3264
3265 let parsed = DnsIncoming::new(packets[1].as_bytes().to_vec(), test_interface_id()).unwrap();
3267 assert_eq!(parsed.answers().len(), 1);
3268 assert_eq!(parsed.answers()[0].get_name(), "big._spill._tcp.local.");
3269 assert_eq!(parsed_answer_count(&packets), 3);
3270 }
3271
3272 #[test]
3275 fn test_dns_outgoing_record_over_absolute_ceiling_dropped() {
3276 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3277 out.add_answer_at_time(ptr_answer(0), 0);
3278 out.add_answer_at_time(
3279 DnsTxt::new(
3280 "huge._spill._tcp.local.",
3281 CLASS_IN,
3282 4500,
3283 vec![b'x'; MAX_PKT_ABSOLUTE_IPV6],
3284 ),
3285 0,
3286 );
3287 out.add_answer_at_time(ptr_answer(1), 0);
3288
3289 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3290 for packet in &packets {
3291 assert!(
3292 packet.size() <= MAX_PKT_ABSOLUTE_IPV6,
3293 "an unsendable packet must never be generated"
3294 );
3295 }
3296 assert_eq!(
3297 parsed_answer_count(&packets),
3298 2,
3299 "only the huge record is dropped"
3300 );
3301 }
3302
3303 #[test]
3305 fn test_dns_outgoing_all_sections_spill() {
3306 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3307 for i in 0..40 {
3308 out.add_answer_at_time(ptr_answer(i), 0);
3309 }
3310 for i in 40..80 {
3311 out.add_authority(Box::new(ptr_answer(i)));
3312 }
3313 for i in 80..120 {
3314 out.add_additional_answer(ptr_answer(i));
3315 }
3316
3317 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3318 assert!(packets.len() > 1);
3319
3320 let mut answers = 0;
3321 let mut authorities = 0;
3322 let mut additionals = 0;
3323 for packet in &packets {
3324 assert!(packet.size() <= MAX_PKT_DEFAULT);
3325 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id()).unwrap();
3326 answers += parsed.answers().len();
3327 authorities += parsed.authorities().len();
3328 additionals += parsed.additionals().len();
3329 }
3330
3331 assert_eq!(answers, 40);
3332 assert_eq!(authorities, 40);
3333 assert_eq!(additionals, 40);
3334 }
3335}