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::{decode_txt, 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 LEGACY_UNICAST_MAX_TTL: u32 = 10;
288
289pub(crate) const MAX_PKT_ABSOLUTE_IPV4: usize = 8972;
297
298pub(crate) const MAX_PKT_ABSOLUTE_IPV6: usize = 8952;
303
304pub(crate) const fn max_pkt_absolute(is_ipv4: bool) -> usize {
306 if is_ipv4 {
307 MAX_PKT_ABSOLUTE_IPV4
308 } else {
309 MAX_PKT_ABSOLUTE_IPV6
310 }
311}
312
313pub const MAX_PKT_DEFAULT: usize = 1452;
320
321const MSG_HEADER_LEN: usize = 12;
322
323const MAX_LABEL_BYTES: usize = 63;
327
328const MAX_NAME_BYTES: usize = 255;
332
333#[derive(Debug, PartialEq, Eq)]
338pub enum WriteError {
339 NameTooLong,
341
342 PacketFull,
344}
345
346type WriteResult = core::result::Result<(), WriteError>;
348
349pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
361
362pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
364
365pub const FLAGS_AA: u16 = 0x0400;
367
368pub const FLAGS_TC: u16 = 0x0200;
379
380pub type DnsRecordBox = Box<dyn DnsRecordExt>;
382
383impl Clone for DnsRecordBox {
384 fn clone(&self) -> Self {
385 self.clone_box()
386 }
387}
388
389const U16_SIZE: usize = 2;
390
391#[inline]
393pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
394 match address {
395 IpAddr::V4(_) => RRType::A,
396 IpAddr::V6(_) => RRType::AAAA,
397 }
398}
399
400#[derive(Eq, PartialEq, Debug, Clone)]
401pub struct DnsEntry {
402 pub(crate) name: String, pub(crate) ty: RRType,
404 class: u16,
405 cache_flush: bool,
406}
407
408impl DnsEntry {
409 const fn new(name: String, ty: RRType, class: u16) -> Self {
410 Self {
411 name,
412 ty,
413 class: class & CLASS_MASK,
414 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
415 }
416 }
417}
418
419pub trait DnsEntryExt: fmt::Debug {
421 fn entry_name(&self) -> &str;
422
423 fn entry_type(&self) -> RRType;
424}
425
426#[derive(Debug)]
428pub struct DnsQuestion {
429 pub(crate) entry: DnsEntry,
430}
431
432impl DnsEntryExt for DnsQuestion {
433 fn entry_name(&self) -> &str {
434 &self.entry.name
435 }
436
437 fn entry_type(&self) -> RRType {
438 self.entry.ty
439 }
440}
441
442#[derive(Debug, Clone)]
446pub struct DnsRecord {
447 pub(crate) entry: DnsEntry,
448 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
458}
459
460impl DnsRecord {
461 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
462 let created = current_time_millis();
463
464 let refresh = get_expiration_time(created, ttl, 80);
468
469 let expires = get_expiration_time(created, ttl, 100);
470
471 Self {
472 entry: DnsEntry::new(name.to_string(), ty, class),
473 ttl,
474 created,
475 expires,
476 refresh,
477 new_name: None,
478 }
479 }
480
481 pub const fn get_ttl(&self) -> u32 {
482 self.ttl
483 }
484
485 pub const fn get_expire_time(&self) -> u64 {
486 self.expires
487 }
488
489 pub const fn get_refresh_time(&self) -> u64 {
490 self.refresh
491 }
492
493 pub const fn is_expired(&self, now: u64) -> bool {
494 now >= self.expires
495 }
496
497 pub const fn expires_soon(&self, now: u64) -> bool {
501 now + 1000 >= self.expires
502 }
503
504 pub const fn refresh_due(&self, now: u64) -> bool {
505 now >= self.refresh
506 }
507
508 pub fn halflife_passed(&self, now: u64) -> bool {
510 let halflife = get_expiration_time(self.created, self.ttl, 50);
511 now > halflife
512 }
513
514 pub fn is_unique(&self) -> bool {
515 self.entry.cache_flush
516 }
517
518 pub fn refresh_no_more(&mut self) {
521 self.refresh = get_expiration_time(self.created, self.ttl, 100);
522 }
523
524 pub fn refresh_maybe(&mut self, now: u64) -> bool {
526 if self.is_expired(now) || !self.refresh_due(now) {
527 return false;
528 }
529
530 trace!(
531 "{} qtype {} is due to refresh",
532 &self.entry.name,
533 self.entry.ty
534 );
535
536 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
543 self.refresh = get_expiration_time(self.created, self.ttl, 85);
544 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
545 self.refresh = get_expiration_time(self.created, self.ttl, 90);
546 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
547 self.refresh = get_expiration_time(self.created, self.ttl, 95);
548 } else {
549 self.refresh_no_more();
550 }
551
552 true
553 }
554
555 fn get_remaining_ttl(&self, now: u64) -> u32 {
557 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
558 cmp::max(0, remaining_millis / 1000) as u32
559 }
560
561 pub const fn get_created(&self) -> u64 {
563 self.created
564 }
565
566 fn set_expire(&mut self, expire_at: u64) {
568 self.expires = expire_at;
569 }
570
571 fn reset_ttl(&mut self, other: &Self) {
572 self.ttl = other.ttl;
573 self.created = other.created;
574 self.expires = get_expiration_time(self.created, self.ttl, 100);
575 self.refresh = if self.ttl > 1 {
576 get_expiration_time(self.created, self.ttl, 80)
577 } else {
578 self.expires
581 };
582 }
583
584 pub fn update_ttl(&mut self, now: u64) {
586 if now > self.created {
587 let elapsed = now - self.created;
588 self.ttl -= (elapsed / 1000) as u32;
589 }
590 }
591
592 pub fn set_new_name(&mut self, new_name: String) {
593 if new_name == self.entry.name {
594 self.new_name = None;
595 } else {
596 self.new_name = Some(new_name);
597 }
598 }
599
600 pub fn get_new_name(&self) -> Option<&str> {
601 self.new_name.as_deref()
602 }
603
604 pub(crate) fn get_name(&self) -> &str {
606 self.new_name.as_deref().unwrap_or(&self.entry.name)
607 }
608
609 pub fn get_original_name(&self) -> &str {
610 &self.entry.name
611 }
612}
613
614impl PartialEq for DnsRecord {
615 fn eq(&self, other: &Self) -> bool {
616 self.entry == other.entry
617 }
618}
619
620pub trait DnsRecordExt: fmt::Debug {
622 fn get_record(&self) -> &DnsRecord;
623 fn get_record_mut(&mut self) -> &mut DnsRecord;
624 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult;
626 fn any(&self) -> &dyn Any;
627
628 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
630
631 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
633
634 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
637
638 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
640 match self.get_class().cmp(&other.get_class()) {
654 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
655 cmp::Ordering::Equal => self.compare_rdata(other),
656 not_equal => not_equal,
657 },
658 not_equal => not_equal,
659 }
660 }
661
662 fn rdata_print(&self) -> String;
664
665 fn get_class(&self) -> u16 {
667 self.get_record().entry.class
668 }
669
670 fn get_cache_flush(&self) -> bool {
671 self.get_record().entry.cache_flush
672 }
673
674 fn get_name(&self) -> &str {
676 self.get_record().get_name()
677 }
678
679 fn get_type(&self) -> RRType {
680 self.get_record().entry.ty
681 }
682
683 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
686 self.get_record_mut().reset_ttl(other.get_record());
687 }
688
689 fn get_created(&self) -> u64 {
690 self.get_record().get_created()
691 }
692
693 fn get_expire(&self) -> u64 {
694 self.get_record().get_expire_time()
695 }
696
697 fn set_expire(&mut self, expire_at: u64) {
698 self.get_record_mut().set_expire(expire_at);
699 }
700
701 fn set_expire_sooner(&mut self, expire_at: u64) {
703 if expire_at < self.get_expire() {
704 self.get_record_mut().set_expire(expire_at);
705 }
706 }
707
708 fn expires_soon(&self, now: u64) -> bool {
710 self.get_record().expires_soon(now)
711 }
712
713 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
716 if self.get_record_mut().refresh_maybe(now) {
717 Some(self.get_record().get_refresh_time())
718 } else {
719 None
720 }
721 }
722
723 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
726 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
727 }
728
729 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
731 for answer in msg.answers.iter() {
732 if self.suppressed_by_answer(answer.as_ref()) {
733 return true;
734 }
735 }
736 false
737 }
738
739 fn clone_box(&self) -> DnsRecordBox;
740
741 fn boxed(self) -> DnsRecordBox;
742}
743
744#[derive(Debug, Clone)]
746pub(crate) struct DnsAddress {
747 pub(crate) record: DnsRecord,
748 address: IpAddr,
749 pub(crate) interface_id: InterfaceId,
750}
751
752impl DnsAddress {
753 pub fn new(
754 name: &str,
755 ty: RRType,
756 class: u16,
757 ttl: u32,
758 address: IpAddr,
759 interface_id: InterfaceId,
760 ) -> Self {
761 let record = DnsRecord::new(name, ty, class, ttl);
762 Self {
763 record,
764 address,
765 interface_id,
766 }
767 }
768
769 pub fn address(&self) -> ScopedIp {
770 match self.address {
771 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
772 addr: v4,
773 interface_ids: vec![self.interface_id.clone()],
774 }),
775 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
776 addr: v6,
777 scope_id: self.interface_id.clone(),
778 }),
779 }
780 }
781}
782
783impl DnsRecordExt for DnsAddress {
784 fn get_record(&self) -> &DnsRecord {
785 &self.record
786 }
787
788 fn get_record_mut(&mut self) -> &mut DnsRecord {
789 &mut self.record
790 }
791
792 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
793 match self.address {
794 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
795 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
796 };
797 Ok(())
798 }
799
800 fn any(&self) -> &dyn Any {
801 self
802 }
803
804 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
805 if let Some(other_a) = other.any().downcast_ref::<Self>() {
806 return self.address == other_a.address
807 && self.record.entry == other_a.record.entry
808 && self.interface_id == other_a.interface_id;
809 }
810 false
811 }
812
813 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
814 if let Some(other_a) = other.any().downcast_ref::<Self>() {
815 return self.address == other_a.address;
816 }
817 false
818 }
819
820 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
821 if let Some(other_a) = other.any().downcast_ref::<Self>() {
822 self.address.cmp(&other_a.address)
823 } else {
824 cmp::Ordering::Greater
825 }
826 }
827
828 fn rdata_print(&self) -> String {
829 format!("{}", self.address)
830 }
831
832 fn clone_box(&self) -> DnsRecordBox {
833 Box::new(self.clone())
834 }
835
836 fn boxed(self) -> DnsRecordBox {
837 Box::new(self)
838 }
839}
840
841#[derive(Debug, Clone)]
843pub struct DnsPointer {
844 record: DnsRecord,
845 alias: String, }
847
848impl DnsPointer {
849 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
850 let record = DnsRecord::new(name, ty, class, ttl);
851 Self { record, alias }
852 }
853
854 pub fn alias(&self) -> &str {
855 &self.alias
856 }
857}
858
859impl DnsRecordExt for DnsPointer {
860 fn get_record(&self) -> &DnsRecord {
861 &self.record
862 }
863
864 fn get_record_mut(&mut self) -> &mut DnsRecord {
865 &mut self.record
866 }
867
868 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
869 packet.write_name(&self.alias)
870 }
871
872 fn any(&self) -> &dyn Any {
873 self
874 }
875
876 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
877 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
878 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
879 }
880 false
881 }
882
883 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
884 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
885 return self.alias == other_ptr.alias;
886 }
887 false
888 }
889
890 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
891 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
892 self.alias.cmp(&other_ptr.alias)
893 } else {
894 cmp::Ordering::Greater
895 }
896 }
897
898 fn rdata_print(&self) -> String {
899 self.alias.clone()
900 }
901
902 fn clone_box(&self) -> DnsRecordBox {
903 Box::new(self.clone())
904 }
905
906 fn boxed(self) -> DnsRecordBox {
907 Box::new(self)
908 }
909}
910
911#[derive(Debug, Clone)]
913pub struct DnsSrv {
914 pub(crate) record: DnsRecord,
915 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
918 port: u16,
919}
920
921impl DnsSrv {
922 pub fn new(
923 name: &str,
924 class: u16,
925 ttl: u32,
926 priority: u16,
927 weight: u16,
928 port: u16,
929 host: String,
930 ) -> Self {
931 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
932 Self {
933 record,
934 priority,
935 weight,
936 host,
937 port,
938 }
939 }
940
941 pub fn host(&self) -> &str {
942 &self.host
943 }
944
945 pub fn port(&self) -> u16 {
946 self.port
947 }
948
949 pub fn set_host(&mut self, host: String) {
950 self.host = host;
951 }
952}
953
954impl DnsRecordExt for DnsSrv {
955 fn get_record(&self) -> &DnsRecord {
956 &self.record
957 }
958
959 fn get_record_mut(&mut self) -> &mut DnsRecord {
960 &mut self.record
961 }
962
963 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
964 packet.write_short(self.priority);
965 packet.write_short(self.weight);
966 packet.write_short(self.port);
967 packet.write_name(&self.host)
968 }
969
970 fn any(&self) -> &dyn Any {
971 self
972 }
973
974 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
975 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
976 return self.host == other_svc.host
977 && self.port == other_svc.port
978 && self.weight == other_svc.weight
979 && self.priority == other_svc.priority
980 && self.record.entry == other_svc.record.entry;
981 }
982 false
983 }
984
985 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
986 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
987 return self.host == other_srv.host
988 && self.port == other_srv.port
989 && self.weight == other_srv.weight
990 && self.priority == other_srv.priority;
991 }
992 false
993 }
994
995 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
996 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
997 return cmp::Ordering::Greater;
998 };
999
1000 match self
1002 .priority
1003 .to_be_bytes()
1004 .cmp(&other_srv.priority.to_be_bytes())
1005 {
1006 cmp::Ordering::Equal => {
1007 match self
1009 .weight
1010 .to_be_bytes()
1011 .cmp(&other_srv.weight.to_be_bytes())
1012 {
1013 cmp::Ordering::Equal => {
1014 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
1016 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
1017 not_equal => not_equal,
1018 }
1019 }
1020 not_equal => not_equal,
1021 }
1022 }
1023 not_equal => not_equal,
1024 }
1025 }
1026
1027 fn rdata_print(&self) -> String {
1028 format!(
1029 "priority: {}, weight: {}, port: {}, host: {}",
1030 self.priority, self.weight, self.port, self.host
1031 )
1032 }
1033
1034 fn clone_box(&self) -> DnsRecordBox {
1035 Box::new(self.clone())
1036 }
1037
1038 fn boxed(self) -> DnsRecordBox {
1039 Box::new(self)
1040 }
1041}
1042
1043#[derive(Clone)]
1058pub struct DnsTxt {
1059 pub(crate) record: DnsRecord,
1060 text: Vec<u8>,
1061}
1062
1063impl DnsTxt {
1064 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1065 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1066 Self { record, text }
1067 }
1068
1069 pub fn text(&self) -> &[u8] {
1070 &self.text
1071 }
1072}
1073
1074impl DnsRecordExt for DnsTxt {
1075 fn get_record(&self) -> &DnsRecord {
1076 &self.record
1077 }
1078
1079 fn get_record_mut(&mut self) -> &mut DnsRecord {
1080 &mut self.record
1081 }
1082
1083 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1084 packet.write_bytes(&self.text);
1085 Ok(())
1086 }
1087
1088 fn any(&self) -> &dyn Any {
1089 self
1090 }
1091
1092 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1093 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1094 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1095 }
1096 false
1097 }
1098
1099 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1100 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1101 return self.text == other_txt.text;
1102 }
1103 false
1104 }
1105
1106 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1107 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1108 self.text.cmp(&other_txt.text)
1109 } else {
1110 cmp::Ordering::Greater
1111 }
1112 }
1113
1114 fn rdata_print(&self) -> String {
1115 format!("{:?}", decode_txt(&self.text))
1116 }
1117
1118 fn clone_box(&self) -> DnsRecordBox {
1119 Box::new(self.clone())
1120 }
1121
1122 fn boxed(self) -> DnsRecordBox {
1123 Box::new(self)
1124 }
1125}
1126
1127impl fmt::Debug for DnsTxt {
1128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1129 let properties = decode_txt(&self.text);
1130 write!(
1131 f,
1132 "DnsTxt {{ record: {:?}, text: {:?} }}",
1133 self.record, properties
1134 )
1135 }
1136}
1137
1138#[derive(Debug, Clone)]
1140struct DnsHostInfo {
1141 record: DnsRecord,
1142 cpu: String,
1143 os: String,
1144}
1145
1146impl DnsHostInfo {
1147 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1148 let record = DnsRecord::new(name, ty, class, ttl);
1149 Self { record, cpu, os }
1150 }
1151}
1152
1153impl DnsRecordExt for DnsHostInfo {
1154 fn get_record(&self) -> &DnsRecord {
1155 &self.record
1156 }
1157
1158 fn get_record_mut(&mut self) -> &mut DnsRecord {
1159 &mut self.record
1160 }
1161
1162 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1163 debug!("Writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1164 packet.write_bytes(self.cpu.as_bytes());
1165 packet.write_bytes(self.os.as_bytes());
1166 Ok(())
1167 }
1168
1169 fn any(&self) -> &dyn Any {
1170 self
1171 }
1172
1173 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1174 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1175 return self.cpu == other_hinfo.cpu
1176 && self.os == other_hinfo.os
1177 && self.record.entry == other_hinfo.record.entry;
1178 }
1179 false
1180 }
1181
1182 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1183 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1184 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1185 }
1186 false
1187 }
1188
1189 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1190 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1191 match self.cpu.cmp(&other_hinfo.cpu) {
1192 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1193 ordering => ordering,
1194 }
1195 } else {
1196 cmp::Ordering::Greater
1197 }
1198 }
1199
1200 fn rdata_print(&self) -> String {
1201 format!("cpu: {}, os: {}", self.cpu, self.os)
1202 }
1203
1204 fn clone_box(&self) -> DnsRecordBox {
1205 Box::new(self.clone())
1206 }
1207
1208 fn boxed(self) -> DnsRecordBox {
1209 Box::new(self)
1210 }
1211}
1212
1213#[derive(Debug, Clone)]
1219pub struct DnsNSec {
1220 record: DnsRecord,
1221 next_domain: String,
1222 type_bitmap: Vec<u8>,
1223}
1224
1225impl DnsNSec {
1226 pub fn new(
1227 name: &str,
1228 class: u16,
1229 ttl: u32,
1230 next_domain: String,
1231 type_bitmap: Vec<u8>,
1232 ) -> Self {
1233 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1234 Self {
1235 record,
1236 next_domain,
1237 type_bitmap,
1238 }
1239 }
1240
1241 pub fn _types(&self) -> Vec<u16> {
1243 let mut bit_num = 0;
1252 let mut results = Vec::new();
1253
1254 for byte in self.type_bitmap.iter() {
1255 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1259 if (byte & bit_mask) != 0 {
1260 results.push(bit_num);
1261 }
1262 bit_num += 1;
1263 bit_mask >>= 1; }
1265 }
1266 results
1267 }
1268}
1269
1270impl DnsRecordExt for DnsNSec {
1271 fn get_record(&self) -> &DnsRecord {
1272 &self.record
1273 }
1274
1275 fn get_record_mut(&mut self) -> &mut DnsRecord {
1276 &mut self.record
1277 }
1278
1279 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1280 packet.write_bytes(self.next_domain.as_bytes());
1281 packet.write_bytes(&self.type_bitmap);
1282 Ok(())
1283 }
1284
1285 fn any(&self) -> &dyn Any {
1286 self
1287 }
1288
1289 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1290 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1291 return self.next_domain == other_record.next_domain
1292 && self.type_bitmap == other_record.type_bitmap
1293 && self.record.entry == other_record.record.entry;
1294 }
1295 false
1296 }
1297
1298 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1299 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1300 return self.next_domain == other_record.next_domain
1301 && self.type_bitmap == other_record.type_bitmap;
1302 }
1303 false
1304 }
1305
1306 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1307 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1308 match self.next_domain.cmp(&other_nsec.next_domain) {
1309 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1310 ordering => ordering,
1311 }
1312 } else {
1313 cmp::Ordering::Greater
1314 }
1315 }
1316
1317 fn rdata_print(&self) -> String {
1318 format!(
1319 "next_domain: {}, type_bitmap len: {}",
1320 self.next_domain,
1321 self.type_bitmap.len()
1322 )
1323 }
1324
1325 fn clone_box(&self) -> DnsRecordBox {
1326 Box::new(self.clone())
1327 }
1328
1329 fn boxed(self) -> DnsRecordBox {
1330 Box::new(self)
1331 }
1332}
1333
1334#[derive(Clone, Copy, Debug)]
1336enum Section {
1337 Question,
1338 Answer,
1339 Authority,
1340 Additional,
1341}
1342
1343pub struct DnsOutPacket {
1345 data: Vec<u8>,
1347
1348 names: HashMap<String, u16>,
1350
1351 max_size: usize,
1353
1354 question_count: u16,
1356 answer_count: u16,
1357 auth_count: u16,
1358 addi_count: u16,
1359}
1360
1361impl DnsOutPacket {
1362 fn new(max_size: usize) -> Self {
1363 Self {
1364 data: vec![0; MSG_HEADER_LEN],
1365 names: HashMap::new(),
1366 max_size,
1367 question_count: 0,
1368 answer_count: 0,
1369 auth_count: 0,
1370 addi_count: 0,
1371 }
1372 }
1373
1374 pub fn size(&self) -> usize {
1375 self.data.len()
1376 }
1377
1378 pub fn as_bytes(&self) -> &[u8] {
1379 &self.data
1380 }
1381
1382 fn is_empty(&self) -> bool {
1384 self.question_count == 0
1385 && self.answer_count == 0
1386 && self.auth_count == 0
1387 && self.addi_count == 0
1388 }
1389
1390 fn bump(&mut self, section: Section) {
1392 match section {
1393 Section::Question => self.question_count += 1,
1394 Section::Answer => self.answer_count += 1,
1395 Section::Authority => self.auth_count += 1,
1396 Section::Additional => self.addi_count += 1,
1397 }
1398 }
1399
1400 fn write_question(&mut self, question: &DnsQuestion) -> WriteResult {
1401 let start_size = self.size();
1402
1403 self.write_name(&question.entry.name).map_err(|e| {
1404 self.rollback(start_size);
1405 e
1406 })?;
1407 self.write_short(question.entry.ty as u16);
1408 self.write_short(question.entry.class);
1409
1410 if self.size() > self.max_size {
1411 self.rollback(start_size);
1412 return Err(WriteError::PacketFull);
1413 }
1414
1415 Ok(())
1416 }
1417
1418 fn rollback(&mut self, start_size: usize) {
1421 self.data.truncate(start_size);
1422 self.names
1423 .retain(|_, offset| (*offset as usize) < start_size);
1424 }
1425
1426 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> WriteResult {
1430 let start_size = self.size();
1431
1432 let record = record_ext.get_record();
1433 self.write_name(record.get_name())?;
1434 self.write_short(record.entry.ty as u16);
1435 if record.entry.cache_flush {
1436 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1438 } else {
1439 self.write_short(record.entry.class);
1440 }
1441
1442 if now == 0 {
1443 self.write_u32(record.ttl);
1444 } else {
1445 self.write_u32(record.get_remaining_ttl(now));
1446 }
1447
1448 self.write_short(0);
1450 let record_offset = self.size();
1451
1452 if let Err(e) = record_ext.write(self) {
1453 self.rollback(start_size);
1454 return Err(e);
1455 }
1456
1457 self.set_short_at(record_offset - 2, (self.size() - record_offset) as u16);
1458
1459 if self.size() > self.max_size {
1460 self.rollback(start_size);
1461 return Err(WriteError::PacketFull);
1462 }
1463
1464 Ok(())
1465 }
1466
1467 fn set_short_at(&mut self, index: usize, value: u16) {
1468 self.data[index..index + 2].copy_from_slice(&value.to_be_bytes());
1469 }
1470
1471 fn parse_escaped_name(name: &str) -> Vec<String> {
1478 let mut labels = Vec::new();
1479 let mut current_label = String::new();
1480 let mut chars = name.chars().peekable();
1481
1482 while let Some(ch) = chars.next() {
1483 match ch {
1484 '\\' => {
1485 if let Some(&next_ch) = chars.peek() {
1487 match next_ch {
1488 '.' | '\\' => {
1489 chars.next();
1491 current_label.push(next_ch);
1492 }
1493 _ => {
1494 current_label.push(ch);
1496 }
1497 }
1498 } else {
1499 current_label.push(ch);
1501 }
1502 }
1503 '.' => {
1504 if !current_label.is_empty() {
1506 labels.push(current_label.clone());
1507 current_label.clear();
1508 }
1509 }
1510 _ => {
1511 current_label.push(ch);
1512 }
1513 }
1514 }
1515
1516 if !current_label.is_empty() {
1518 labels.push(current_label);
1519 }
1520
1521 labels
1522 }
1523
1524 fn write_name(&mut self, name: &str) -> WriteResult {
1550 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1552
1553 let labels = Self::parse_escaped_name(name_to_parse);
1555
1556 if labels.is_empty() {
1557 self.write_byte(0);
1558 return Ok(());
1559 }
1560
1561 if labels.iter().any(|label| label.len() > MAX_LABEL_BYTES) {
1563 return Err(WriteError::NameTooLong);
1564 }
1565
1566 for (i, label) in labels.iter().enumerate() {
1568 let remaining: String = labels[i..].join(".");
1570
1571 const POINTER_MASK: u16 = 0xC000;
1573 if let Some(&offset) = self.names.get(&remaining) {
1574 let pointer = offset | POINTER_MASK;
1575 self.write_short(pointer);
1576 return Ok(());
1577 }
1578
1579 self.names.insert(remaining, self.size() as u16);
1581
1582 self.write_utf8(label)?;
1584 }
1585
1586 self.write_byte(0);
1588 Ok(())
1589 }
1590
1591 fn write_byte(&mut self, v: u8) {
1592 self.data.push(v);
1593 }
1594
1595 fn write_bytes(&mut self, s: &[u8]) {
1596 self.data.extend(s);
1597 }
1598
1599 fn write_utf8(&mut self, s: &str) -> WriteResult {
1602 if s.len() > MAX_LABEL_BYTES {
1603 return Err(WriteError::NameTooLong);
1604 }
1605 self.write_byte(s.len() as u8);
1606 self.write_bytes(s.as_bytes());
1607 Ok(())
1608 }
1609
1610 fn write_u32(&mut self, v: u32) {
1611 self.data.extend(&v.to_be_bytes());
1612 }
1613
1614 fn write_short(&mut self, v: u16) {
1615 self.data.extend(&v.to_be_bytes());
1616 }
1617
1618 fn set_truncated(&mut self) {
1621 let flags = u16::from_be_bytes([self.data[2], self.data[3]]);
1622 self.set_short_at(2, flags | FLAGS_TC);
1623 }
1624
1625 fn write_header(&mut self, id: u16, flags: u16) {
1648 self.set_short_at(0, id);
1649 self.set_short_at(2, flags);
1650 self.set_short_at(4, self.question_count);
1651 self.set_short_at(6, self.answer_count);
1652 self.set_short_at(8, self.auth_count);
1653 self.set_short_at(10, self.addi_count);
1654 }
1655}
1656
1657struct PacketBuilder<'a> {
1660 out: &'a DnsOutgoing,
1661
1662 max_size: usize,
1664
1665 is_ipv4: bool,
1668
1669 finished: Vec<DnsOutPacket>,
1670 current: DnsOutPacket,
1671}
1672
1673impl<'a> PacketBuilder<'a> {
1674 fn new(out: &'a DnsOutgoing, max_size: usize, is_ipv4: bool) -> Self {
1675 Self {
1676 out,
1677 max_size,
1678 is_ipv4,
1679 finished: Vec::new(),
1680 current: DnsOutPacket::new(max_size),
1681 }
1682 }
1683
1684 fn add<F>(&mut self, section: Section, write: F)
1691 where
1692 F: Fn(&mut DnsOutPacket) -> WriteResult,
1693 {
1694 match write(&mut self.current) {
1695 Ok(()) => {
1696 self.current.bump(section);
1697 return;
1698 }
1699 Err(WriteError::NameTooLong) => return,
1701 Err(WriteError::PacketFull) => {}
1702 }
1703
1704 if !self.current.is_empty() {
1706 self.flush();
1707
1708 match write(&mut self.current) {
1709 Ok(()) => {
1710 self.current.bump(section);
1711 return;
1712 }
1713 Err(WriteError::NameTooLong) => return,
1714 Err(WriteError::PacketFull) => {}
1715 }
1716 }
1717
1718 if matches!(section, Section::Question) {
1720 return;
1721 }
1722
1723 self.current.max_size = max_pkt_absolute(self.is_ipv4);
1729
1730 if write(&mut self.current).is_ok() {
1731 self.current.bump(section);
1732 self.flush();
1733 } else {
1734 self.current.max_size = self.max_size;
1736 debug!(
1737 "Record too big for absolute max size, skipping: {:?}",
1738 section
1739 );
1740 }
1741 }
1742
1743 fn flush(&mut self) {
1745 self.current
1746 .write_header(self.out.wire_id(), self.out.flags);
1747
1748 let next = DnsOutPacket::new(self.max_size);
1749 self.finished
1750 .push(std::mem::replace(&mut self.current, next));
1751 }
1752
1753 fn finish(mut self) -> Vec<DnsOutPacket> {
1754 if !self.current.is_empty() || self.finished.is_empty() {
1757 self.flush();
1758 }
1759
1760 let mut packets = self.finished;
1761
1762 if self.out.is_query() {
1770 if let Some((_last, rest)) = packets.split_last_mut() {
1771 for packet in rest {
1772 packet.set_truncated();
1773 }
1774 }
1775 }
1776
1777 packets
1778 }
1779}
1780
1781#[derive(Debug)]
1783pub struct DnsOutgoing {
1784 flags: u16,
1785 id: u16,
1786 multicast: bool,
1787 questions: Vec<DnsQuestion>,
1788 answers: Vec<(DnsRecordBox, u64)>,
1789 authorities: Vec<DnsRecordBox>,
1790 additionals: Vec<DnsRecordBox>,
1791 known_answer_count: i64, }
1793
1794impl DnsOutgoing {
1795 pub fn new(flags: u16) -> Self {
1796 Self {
1797 flags,
1798 id: 0,
1799 multicast: true,
1800 questions: Vec::new(),
1801 answers: Vec::new(),
1802 authorities: Vec::new(),
1803 additionals: Vec::new(),
1804 known_answer_count: 0,
1805 }
1806 }
1807
1808 pub fn questions(&self) -> &[DnsQuestion] {
1809 &self.questions
1810 }
1811
1812 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1814 &self.answers
1815 }
1816
1817 pub fn answers_count(&self) -> usize {
1818 self.answers.len()
1819 }
1820
1821 pub fn authorities(&self) -> &[DnsRecordBox] {
1822 &self.authorities
1823 }
1824
1825 pub fn additionals(&self) -> &[DnsRecordBox] {
1826 &self.additionals
1827 }
1828
1829 pub fn known_answer_count(&self) -> i64 {
1830 self.known_answer_count
1831 }
1832
1833 pub fn set_id(&mut self, id: u16) {
1834 self.id = id;
1835 }
1836
1837 pub fn set_multicast(&mut self, multicast: bool) {
1839 self.multicast = multicast;
1840 }
1841
1842 const fn wire_id(&self) -> u16 {
1844 if self.multicast {
1845 0
1846 } else {
1847 self.id
1850 }
1851 }
1852
1853 pub const fn is_query(&self) -> bool {
1854 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1855 }
1856
1857 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1891 trace!("add_additional_answer: {:?}", &answer);
1892 self.additionals.push(answer.boxed());
1893 }
1894
1895 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1897 self.answers.push((answer_box, 0));
1898 }
1899
1900 pub fn add_authority(&mut self, record: DnsRecordBox) {
1901 self.authorities.push(record);
1902 }
1903
1904 pub(crate) fn retain_answers<F>(&mut self, mut keep: F)
1906 where
1907 F: FnMut(&DnsRecordBox) -> bool,
1908 {
1909 self.answers.retain(|(record, _)| keep(record));
1910 }
1911
1912 pub(crate) fn retain_additionals<F>(&mut self, mut keep: F)
1914 where
1915 F: FnMut(&DnsRecordBox) -> bool,
1916 {
1917 self.additionals.retain(|record| keep(record));
1918 }
1919
1920 pub fn add_answer(
1923 &mut self,
1924 msg: &DnsIncoming,
1925 answer: impl DnsRecordExt + Send + 'static,
1926 ) -> bool {
1927 trace!("Check for add_answer");
1928 if answer.suppressed_by(msg) {
1929 trace!("my answer is suppressed by incoming msg");
1930 self.known_answer_count += 1;
1931 return false;
1932 }
1933
1934 self.add_answer_at_time(answer, 0)
1935 }
1936
1937 pub fn add_answer_at_time(
1941 &mut self,
1942 answer: impl DnsRecordExt + Send + 'static,
1943 now: u64,
1944 ) -> bool {
1945 if now == 0 || !answer.get_record().is_expired(now) {
1946 trace!("add_answer push: {:?}", &answer);
1947 self.answers.push((answer.boxed(), now));
1948 return true;
1949 }
1950 false
1951 }
1952
1953 pub(crate) fn add_answer_with_additionals(
1962 &mut self,
1963 msg: &DnsIncoming,
1964 service: &ServiceInfo,
1965 intf: &MyIntf,
1966 dns_registry: &DnsRegistry,
1967 is_ipv4: bool,
1968 ) {
1969 let intf_addrs = if is_ipv4 {
1970 service.get_addrs_on_my_intf_v4(intf)
1971 } else {
1972 service.get_addrs_on_my_intf_v6(intf)
1973 };
1974 if intf_addrs.is_empty() {
1975 trace!("No addrs on LAN of intf {:?}", intf);
1976 return;
1977 }
1978
1979 let service_fullname = dns_registry.resolve_name(service.get_fullname());
1981 let hostname = dns_registry.resolve_name(service.get_hostname());
1982
1983 let ptr_added = self.add_answer(
1984 msg,
1985 DnsPointer::new(
1986 service.get_type(),
1987 RRType::PTR,
1988 CLASS_IN,
1989 service.get_other_ttl(),
1990 service_fullname.to_string(),
1991 ),
1992 );
1993
1994 if !ptr_added {
1995 trace!("answer was not added for msg {:?}", msg);
1996 return;
1997 }
1998
1999 if let Some(sub) = service.get_subtype() {
2000 trace!("Adding subdomain {}", sub);
2001 self.add_additional_answer(DnsPointer::new(
2002 sub,
2003 RRType::PTR,
2004 CLASS_IN,
2005 service.get_other_ttl(),
2006 service_fullname.to_string(),
2007 ));
2008 }
2009
2010 self.add_additional_answer(DnsSrv::new(
2013 service_fullname,
2014 CLASS_IN | CLASS_CACHE_FLUSH,
2015 service.get_host_ttl(),
2016 service.get_priority(),
2017 service.get_weight(),
2018 service.get_port(),
2019 hostname.to_string(),
2020 ));
2021
2022 self.add_additional_answer(DnsTxt::new(
2023 service_fullname,
2024 CLASS_IN | CLASS_CACHE_FLUSH,
2025 service.get_other_ttl(),
2026 service.generate_txt(),
2027 ));
2028
2029 for address in intf_addrs {
2030 self.add_additional_answer(DnsAddress::new(
2031 hostname,
2032 ip_address_rr_type(&address),
2033 CLASS_IN | CLASS_CACHE_FLUSH,
2034 service.get_host_ttl(),
2035 address,
2036 intf.into(),
2037 ));
2038 }
2039 }
2040
2041 pub fn add_question(&mut self, name: &str, qtype: RRType) {
2042 let q = DnsQuestion {
2043 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
2044 };
2045 self.questions.push(q);
2046 }
2047
2048 pub fn update_records_for_legacy_unicast(&mut self) {
2058 let update = |rec: &mut DnsRecordBox| {
2059 let record = rec.get_record_mut();
2060 record.entry.cache_flush = false;
2061 record.ttl = record.ttl.min(LEGACY_UNICAST_MAX_TTL);
2062 };
2063 for (rec, _) in &mut self.answers {
2064 update(rec);
2065 }
2066 for rec in &mut self.additionals {
2067 update(rec);
2068 }
2069 for rec in &mut self.authorities {
2070 update(rec);
2071 }
2072 }
2073
2074 pub fn to_data_on_wire(&self, max_size: usize, is_ipv4: bool) -> Vec<Vec<u8>> {
2079 let packet_list = self.to_packets(max_size, is_ipv4);
2080 packet_list.into_iter().map(|p| p.data).collect()
2081 }
2082
2083 pub fn to_packets(&self, max_size: usize, is_ipv4: bool) -> Vec<DnsOutPacket> {
2100 debug_assert!(
2101 max_size <= MAX_PKT_ABSOLUTE_IPV6,
2102 "max_size {} exceeds the RFC 6762 section 17 ceiling",
2103 max_size
2104 );
2105 let mut builder = PacketBuilder::new(self, max_size, is_ipv4);
2106
2107 for question in self.questions.iter() {
2108 builder.add(Section::Question, |packet| packet.write_question(question));
2109 }
2110
2111 for (answer, time) in self.answers.iter() {
2112 builder.add(Section::Answer, |packet| {
2113 packet.write_record(answer.as_ref(), *time)
2114 });
2115 }
2116
2117 for auth in self.authorities.iter() {
2118 builder.add(Section::Authority, |packet| {
2119 packet.write_record(auth.as_ref(), 0)
2120 });
2121 }
2122
2123 for addi in self.additionals.iter() {
2124 builder.add(Section::Additional, |packet| {
2125 packet.write_record(addi.as_ref(), 0)
2126 });
2127 }
2128
2129 builder.finish()
2130 }
2131}
2132
2133pub struct DnsIncoming {
2135 offset: usize,
2136 data: Vec<u8>,
2137 questions: Vec<DnsQuestion>,
2138 answers: Vec<DnsRecordBox>,
2139 authorities: Vec<DnsRecordBox>,
2140 additional: Vec<DnsRecordBox>,
2141 id: u16,
2142 flags: u16,
2143 num_questions: u16,
2144 num_answers: u16,
2145 num_authorities: u16,
2146 num_additionals: u16,
2147 interface_id: InterfaceId,
2148}
2149
2150impl fmt::Debug for DnsIncoming {
2152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2153 f.debug_struct("DnsIncoming")
2154 .field("offset", &self.offset)
2155 .field("questions", &self.questions)
2156 .field("answers", &self.answers)
2157 .field("authorities", &self.authorities)
2158 .field("additional", &self.additional)
2159 .field("id", &self.id)
2160 .field("flags", &self.flags)
2161 .field("num_questions", &self.num_questions)
2162 .field("num_answers", &self.num_answers)
2163 .field("num_authorities", &self.num_authorities)
2164 .field("num_additionals", &self.num_additionals)
2165 .field("interface_id", &self.interface_id)
2166 .finish()
2167 }
2168}
2169
2170impl DnsIncoming {
2171 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2172 let mut incoming = Self {
2173 offset: 0,
2174 data,
2175 questions: Vec::new(),
2176 answers: Vec::new(),
2177 authorities: Vec::new(),
2178 additional: Vec::new(),
2179 id: 0,
2180 flags: 0,
2181 num_questions: 0,
2182 num_answers: 0,
2183 num_authorities: 0,
2184 num_additionals: 0,
2185 interface_id,
2186 };
2187
2188 if let Err(e) = incoming.read_sections() {
2208 return Err(Error::Msg(format!(
2209 "{e}; raw packet length: {}",
2210 incoming.data.len(),
2211 )));
2212 }
2213
2214 Ok(incoming)
2215 }
2216
2217 fn read_sections(&mut self) -> Result<()> {
2220 self.read_header()?;
2221 self.read_questions()?;
2222 self.read_answers()?;
2223 self.read_authorities()?;
2224 self.read_additional()?;
2225 Ok(())
2226 }
2227
2228 pub fn id(&self) -> u16 {
2229 self.id
2230 }
2231
2232 pub fn questions(&self) -> &[DnsQuestion] {
2233 &self.questions
2234 }
2235
2236 pub fn answers(&self) -> &[DnsRecordBox] {
2237 &self.answers
2238 }
2239
2240 pub fn authorities(&self) -> &[DnsRecordBox] {
2241 &self.authorities
2242 }
2243
2244 pub fn additionals(&self) -> &[DnsRecordBox] {
2245 &self.additional
2246 }
2247
2248 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2249 &mut self.answers
2250 }
2251
2252 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2253 &mut self.authorities
2254 }
2255
2256 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2257 &mut self.additional
2258 }
2259
2260 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2261 self.answers
2262 .into_iter()
2263 .chain(self.authorities)
2264 .chain(self.additional)
2265 }
2266
2267 pub fn num_additionals(&self) -> u16 {
2268 self.num_additionals
2269 }
2270
2271 pub fn num_authorities(&self) -> u16 {
2272 self.num_authorities
2273 }
2274
2275 pub fn num_questions(&self) -> u16 {
2276 self.num_questions
2277 }
2278
2279 pub const fn is_query(&self) -> bool {
2280 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2281 }
2282
2283 pub const fn is_response(&self) -> bool {
2284 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2285 }
2286
2287 fn read_header(&mut self) -> Result<()> {
2288 if self.data.len() < MSG_HEADER_LEN {
2289 return Err(e_fmt!(
2290 "DNS incoming: header is too short: {} bytes",
2291 self.data.len()
2292 ));
2293 }
2294
2295 let data = &self.data[0..];
2296 self.id = u16_from_be_slice(&data[..2]);
2297 self.flags = u16_from_be_slice(&data[2..4]);
2298 self.num_questions = u16_from_be_slice(&data[4..6]);
2299 self.num_answers = u16_from_be_slice(&data[6..8]);
2300 self.num_authorities = u16_from_be_slice(&data[8..10]);
2301 self.num_additionals = u16_from_be_slice(&data[10..12]);
2302
2303 self.offset = MSG_HEADER_LEN;
2304
2305 trace!(
2306 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2307 self.id,
2308 self.num_questions,
2309 self.num_answers,
2310 self.num_authorities,
2311 self.num_additionals
2312 );
2313 Ok(())
2314 }
2315
2316 fn read_questions(&mut self) -> Result<()> {
2317 trace!("read_questions: {}", &self.num_questions);
2318 for i in 0..self.num_questions {
2319 let name = self.read_name()?;
2320
2321 let data = &self.data[self.offset..];
2322 if data.len() < 4 {
2323 return Err(Error::Msg(format!(
2324 "DNS incoming: question idx {} too short: {}",
2325 i,
2326 data.len()
2327 )));
2328 }
2329 let ty = u16_from_be_slice(&data[..2]);
2330 let class = u16_from_be_slice(&data[2..4]);
2331 self.offset += 4;
2332
2333 let Some(rr_type) = RRType::from_u16(ty) else {
2334 return Err(Error::Msg(format!(
2335 "DNS incoming: question idx {i} qtype unknown: {ty}",
2336 )));
2337 };
2338
2339 self.questions.push(DnsQuestion {
2340 entry: DnsEntry::new(name, rr_type, class),
2341 });
2342 }
2343 Ok(())
2344 }
2345
2346 fn read_answers(&mut self) -> Result<()> {
2347 self.answers = self.read_rr_records(self.num_answers)?;
2348 Ok(())
2349 }
2350
2351 fn read_authorities(&mut self) -> Result<()> {
2352 self.authorities = self.read_rr_records(self.num_authorities)?;
2353 Ok(())
2354 }
2355
2356 fn read_additional(&mut self) -> Result<()> {
2357 self.additional = self.read_rr_records(self.num_additionals)?;
2358 Ok(())
2359 }
2360
2361 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2363 trace!("read_rr_records: {}", count);
2364 let mut rr_records = Vec::new();
2365
2366 const RR_HEADER_REMAIN: usize = 10;
2392
2393 for _ in 0..count {
2394 let name = self.read_name()?;
2395 let slice = &self.data[self.offset..];
2396
2397 if slice.len() < RR_HEADER_REMAIN {
2398 return Err(Error::Msg(format!(
2399 "read_others: RR '{}' is too short after name: {} bytes",
2400 &name,
2401 slice.len()
2402 )));
2403 }
2404
2405 let ty = u16_from_be_slice(&slice[..2]);
2406 let class = u16_from_be_slice(&slice[2..4]);
2407 let mut ttl = u32_from_be_slice(&slice[4..8]);
2408 if ttl == 0 && self.is_response() {
2409 ttl = 1;
2416 }
2417 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2418 self.offset += RR_HEADER_REMAIN;
2419 let next_offset = self.offset + rdata_len;
2420
2421 if next_offset > self.data.len() {
2423 return Err(Error::Msg(format!(
2424 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2425 self.data.len() - self.offset
2426 )));
2427 }
2428
2429 match self.read_rdata(ty, class, ttl, rdata_len, &name) {
2433 Ok(Some(record)) => {
2434 if self.offset == next_offset {
2435 trace!("read_rr_records: {:?}", &record);
2436 rr_records.push(record);
2437 } else {
2438 debug!(
2439 "skipping record '{}' (type {}): RDATA ended at {}, expected {}",
2440 &name, ty, self.offset, next_offset
2441 );
2442 }
2443 }
2444 Ok(None) => {
2445 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2446 }
2447 Err(e) => {
2448 debug!(
2449 "skipping record '{}' (type {}) with invalid RDATA: {}",
2450 &name, ty, e,
2451 );
2452 }
2453 }
2454
2455 self.offset = next_offset;
2459 }
2460
2461 Ok(rr_records)
2462 }
2463
2464 fn read_rdata(
2471 &mut self,
2472 ty: u16,
2473 class: u16,
2474 ttl: u32,
2475 rdata_len: usize,
2476 name: &str,
2477 ) -> Result<Option<DnsRecordBox>> {
2478 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2479 None => None,
2480
2481 Some(rr_type) => match rr_type {
2482 RRType::CNAME | RRType::PTR => {
2483 Some(DnsPointer::new(name, rr_type, class, ttl, self.read_name()?).boxed())
2484 }
2485 RRType::TXT => {
2486 Some(DnsTxt::new(name, class, ttl, self.read_vec(rdata_len)?).boxed())
2487 }
2488 RRType::SRV => Some(
2489 DnsSrv::new(
2490 name,
2491 class,
2492 ttl,
2493 self.read_u16()?,
2494 self.read_u16()?,
2495 self.read_u16()?,
2496 self.read_name()?,
2497 )
2498 .boxed(),
2499 ),
2500 RRType::HINFO => Some(
2501 DnsHostInfo::new(
2502 name,
2503 rr_type,
2504 class,
2505 ttl,
2506 self.read_char_string()?,
2507 self.read_char_string()?,
2508 )
2509 .boxed(),
2510 ),
2511 RRType::A => Some(
2512 DnsAddress::new(
2513 name,
2514 rr_type,
2515 class,
2516 ttl,
2517 self.read_ipv4()?.into(),
2518 self.interface_id.clone(),
2519 )
2520 .boxed(),
2521 ),
2522 RRType::AAAA => Some(
2523 DnsAddress::new(
2524 name,
2525 rr_type,
2526 class,
2527 ttl,
2528 self.read_ipv6()?.into(),
2529 self.interface_id.clone(),
2530 )
2531 .boxed(),
2532 ),
2533 RRType::NSEC => Some(
2534 DnsNSec::new(
2535 name,
2536 class,
2537 ttl,
2538 self.read_name()?,
2539 self.read_type_bitmap()?,
2540 )
2541 .boxed(),
2542 ),
2543 _ => None,
2544 },
2545 };
2546
2547 Ok(rec)
2548 }
2549
2550 fn read_char_string(&mut self) -> Result<String> {
2551 let Some(&length) = self.data.get(self.offset) else {
2552 return Err(e_fmt!(
2553 "read_char_string: no length byte at offset {}, data len {}",
2554 self.offset,
2555 self.data.len()
2556 ));
2557 };
2558 self.offset += 1;
2559 self.read_string(length as usize)
2560 }
2561
2562 fn read_u16(&mut self) -> Result<u16> {
2563 let slice = &self.data[self.offset..];
2564 if slice.len() < U16_SIZE {
2565 return Err(Error::Msg(format!(
2566 "read_u16: slice len is only {}",
2567 slice.len()
2568 )));
2569 }
2570 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2571 self.offset += U16_SIZE;
2572 Ok(num)
2573 }
2574
2575 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2577 if self.data.len() < self.offset + 2 {
2586 return Err(Error::Msg(format!(
2587 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2588 self.data.len(),
2589 self.offset
2590 )));
2591 }
2592
2593 let block_num = self.data[self.offset];
2594 self.offset += 1;
2595 if block_num != 0 {
2596 return Err(Error::Msg(format!(
2597 "NSEC block number is not 0: {block_num}"
2598 )));
2599 }
2600
2601 let block_len = self.data[self.offset] as usize;
2602 if !(1..=32).contains(&block_len) {
2603 return Err(Error::Msg(format!(
2604 "NSEC block length must be in the range 1-32: {block_len}"
2605 )));
2606 }
2607 self.offset += 1;
2608
2609 let end = self.offset + block_len;
2610 if end > self.data.len() {
2611 return Err(Error::Msg(format!(
2612 "NSEC block overflow: {} over RData len {}",
2613 end,
2614 self.data.len()
2615 )));
2616 }
2617 let bitmap = self.data[self.offset..end].to_vec();
2618 self.offset += block_len;
2619
2620 Ok(bitmap)
2621 }
2622
2623 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2624 if self.data.len() < self.offset + length {
2625 return Err(e_fmt!(
2626 "DNS Incoming: not enough data to read a chunk of data"
2627 ));
2628 }
2629
2630 let v = self.data[self.offset..self.offset + length].to_vec();
2631 self.offset += length;
2632 Ok(v)
2633 }
2634
2635 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2636 if self.data.len() < self.offset + 4 {
2637 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2638 }
2639
2640 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2641 .try_into()
2642 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2643 self.offset += bytes.len();
2644 Ok(Ipv4Addr::from(bytes))
2645 }
2646
2647 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2648 if self.data.len() < self.offset + 16 {
2649 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2650 }
2651
2652 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2653 .try_into()
2654 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2655 self.offset += bytes.len();
2656 Ok(Ipv6Addr::from(bytes))
2657 }
2658
2659 fn read_string(&mut self, length: usize) -> Result<String> {
2660 if self.data.len() < self.offset + length {
2661 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2662 }
2663
2664 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2665 .map_err(|e| Error::Msg(e.to_string()))?;
2666 self.offset += length;
2667 Ok(s.to_string())
2668 }
2669
2670 fn read_name(&mut self) -> Result<String> {
2675 let mut name = String::new();
2676 self.offset = self.read_labels(self.offset, &mut name)?;
2677 Ok(name)
2678 }
2679
2680 fn read_labels(&self, mut offset: usize, name: &mut String) -> Result<usize> {
2709 let data = &self.data[..];
2710
2711 loop {
2722 if offset >= data.len() {
2723 return Err(Error::Msg(format!(
2724 "read_labels: offset: {} data len {}",
2725 offset,
2726 data.len(),
2727 )));
2728 }
2729 let length = data[offset];
2730
2731 if length == 0 {
2734 return Ok(offset + 1); }
2736
2737 match length & 0xC0 {
2739 0x00 => {
2740 offset += 1;
2742 let ending = offset + length as usize;
2743
2744 if ending > data.len() {
2746 return Err(Error::Msg(format!(
2747 "read_labels: ending {} exceeds data length {}",
2748 ending,
2749 data.len()
2750 )));
2751 }
2752
2753 let label = str::from_utf8(&data[offset..ending])
2754 .map_err(|e| Error::Msg(format!("read_labels: from_utf8: {e}")))?;
2755
2756 if name.len() + label.len() + 1 > MAX_NAME_BYTES {
2765 return Err(Error::Msg(format!(
2766 "read_labels: name exceeds {MAX_NAME_BYTES} bytes: {name}"
2767 )));
2768 }
2769
2770 *name += label;
2771 *name += ".";
2772 offset = ending;
2773 }
2774 0xC0 => {
2775 self.follow_pointer(offset, name)?;
2777 return Ok(offset + U16_SIZE);
2778 }
2779 _ => {
2780 return Err(Error::Msg(format!(
2781 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2782 length,
2783 offset,
2784 &data[..offset]
2785 )));
2786 }
2787 };
2788 }
2789 }
2790
2791 fn follow_pointer(&self, at: usize, name: &mut String) -> Result<()> {
2797 let data = &self.data[..];
2798 let mut pointer_at = at;
2799
2800 let target = loop {
2803 let slice = &data[pointer_at..];
2804 if slice.len() < U16_SIZE {
2805 return Err(Error::Msg(format!(
2806 "follow_pointer: u16 slice len is only {}",
2807 slice.len()
2808 )));
2809 }
2810 let target = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2811
2812 if target >= pointer_at {
2815 return Err(Error::Msg(format!(
2816 "Invalid name compression: pointer {target} at offset {pointer_at} must point backwards"
2817 )));
2818 }
2819
2820 if data[target] & 0xC0 != 0xC0 {
2821 break target;
2822 }
2823
2824 pointer_at = target;
2826 };
2827
2828 self.read_labels(target, name)?;
2829 Ok(())
2830 }
2831}
2832
2833const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2834 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2835 u16::from_be_bytes(u8_array)
2836}
2837
2838const fn u32_from_be_slice(s: &[u8]) -> u32 {
2839 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2840 u32::from_be_bytes(u8_array)
2841}
2842
2843const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2846 created + (ttl as u64 * percent as u64 * 10)
2849}
2850
2851#[cfg(test)]
2852mod tests {
2853 use super::{
2854 u16_from_be_slice, DnsAddress, DnsHostInfo, DnsIncoming, DnsOutPacket, DnsOutgoing,
2855 DnsPointer, DnsTxt, RRType, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE,
2856 FLAGS_TC, MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT, MSG_HEADER_LEN,
2857 };
2858 use crate::InterfaceId;
2859 use std::collections::HashMap;
2860 use std::net::{IpAddr, Ipv4Addr};
2861
2862 const IPV6: bool = false;
2865
2866 #[test]
2872 fn test_hinfo_char_string_at_end_of_packet() {
2873 let mut data = Vec::new();
2874
2875 data.extend_from_slice(&0x0087u16.to_be_bytes()); data.extend_from_slice(&0x0084u16.to_be_bytes()); data.extend_from_slice(&0u16.to_be_bytes()); data.extend_from_slice(&0u16.to_be_bytes()); data.extend_from_slice(&1u16.to_be_bytes()); data.extend_from_slice(&0u16.to_be_bytes()); data.push(0); data.extend_from_slice(&(RRType::HINFO as u16).to_be_bytes());
2885 data.extend_from_slice(&CLASS_IN.to_be_bytes());
2886 data.extend_from_slice(&0u32.to_be_bytes()); data.extend_from_slice(&0u16.to_be_bytes()); assert_eq!(data.len(), 23);
2893
2894 let parsed = DnsIncoming::new(data, test_interface_id())
2895 .expect("a truncated HINFO must be skipped, not fail the packet");
2896
2897 assert_eq!(parsed.authorities().len(), 0);
2899 }
2900
2901 #[test]
2902 fn test_dns_outgoing_serialization_empty() {
2903 let out = DnsOutgoing::new(0);
2904 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2905 assert_eq!(packets.len(), 1);
2906 assert_eq!(packets[0].as_bytes(), &[0; 12]);
2907 let expected_names = HashMap::new();
2908 assert_eq!(&packets[0].names, &expected_names);
2909 }
2910
2911 #[test]
2912 fn test_dns_outgoing_serialization_question() {
2913 let mut out = DnsOutgoing::new(0);
2914 out.add_question("123.test", RRType::A);
2915 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2916 assert_eq!(packets.len(), 1);
2917 assert_eq!(
2918 packets[0].as_bytes(),
2919 &[
2920 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,
2923 ]
2924 );
2925 let mut expected_names = HashMap::new();
2926 expected_names.insert("123.test".to_string(), 12);
2927 expected_names.insert("test".to_string(), 16);
2928 assert_eq!(&packets[0].names, &expected_names);
2929 }
2930
2931 #[test]
2932 fn test_dns_outgoing_serialization_question_with_authority() {
2933 let mut out = DnsOutgoing::new(0);
2934 out.add_question("123.test", RRType::ANY);
2935 out.add_authority(Box::new(DnsTxt::new(
2936 "124.test",
2937 CLASS_IN,
2938 0x00112233,
2939 b"help".to_vec(),
2940 )));
2941 out.add_authority(Box::new(DnsHostInfo::new(
2942 "124.test",
2943 RRType::CNAME,
2944 CLASS_IN,
2945 0x00112233,
2946 "arm".to_string(),
2947 "linux".to_string(),
2948 )));
2949 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2950 assert_eq!(packets.len(), 1);
2951 assert_eq!(
2952 packets[0].as_bytes(),
2953 &[
2954 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,
2957 16, 0, 1, 0, 17, 34, 51, 0, 4, 104, 101, 108, 112, 192, 26, 0, 5, 0, 1, 0, 17, 34,
2958 51, 0, 8, 97, 114, 109, 108, 105, 110, 117, 120,
2959 ]
2960 );
2961 let mut expected_names = HashMap::new();
2962 expected_names.insert("123.test".to_string(), 12);
2963 expected_names.insert("test".to_string(), 16);
2964 expected_names.insert("124.test".to_string(), 26);
2965 assert_eq!(&packets[0].names, &expected_names);
2966 }
2967
2968 #[test]
2969 fn test_dns_outgoing_serialization_additional_answer() {
2970 let mut out = DnsOutgoing::new(0);
2971 out.add_additional_answer(DnsAddress::new(
2972 "test.local",
2973 RRType::A,
2974 CLASS_IN | CLASS_CACHE_FLUSH,
2975 0xdead_beef,
2976 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
2977 InterfaceId::default(),
2978 ));
2979 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2980 assert_eq!(packets.len(), 1);
2981 assert_eq!(
2982 packets[0].as_bytes(),
2983 &[
2984 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,
2987 239, 0, 4, 127, 0, 0, 1,
2988 ]
2989 );
2990 let mut expected_names = HashMap::new();
2991 expected_names.insert("test.local".to_string(), 12);
2992 expected_names.insert("local".to_string(), 17);
2993 assert_eq!(&packets[0].names, &expected_names);
2994 }
2995
2996 #[test]
2997 fn test_dns_outgoing_serialization_answer_at_time() {
2998 let mut out = DnsOutgoing::new(0);
2999 out.add_answer_at_time(
3000 DnsPointer::new(
3001 "test",
3002 RRType::PTR,
3003 CLASS_IN,
3004 0xaaaa5555,
3005 "test-service".to_string(),
3006 ),
3007 0,
3008 );
3009 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3010 assert_eq!(packets.len(), 1);
3011 assert_eq!(
3012 packets[0].as_bytes(),
3013 &[
3014 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,
3017 116, 45, 115, 101, 114, 118, 105, 99, 101, 0,
3018 ]
3019 );
3020
3021 let mut out = DnsOutgoing::new(0);
3022 out.add_answer_at_time(
3023 DnsPointer::new(
3024 "test",
3025 RRType::CNAME,
3026 CLASS_IN,
3027 0xaaaa5555,
3028 "test-service.local".to_string(),
3029 ),
3030 0,
3031 );
3032 out.add_answer_at_time(
3033 DnsPointer::new(
3034 "test",
3035 RRType::AAAA,
3036 CLASS_IN,
3037 0xffffffff,
3038 "test-service.local".to_string(),
3039 ),
3040 0,
3041 );
3042 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3043 assert_eq!(packets.len(), 1);
3044 assert_eq!(
3045 packets[0].as_bytes(),
3046 &[
3047 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,
3050 116, 45, 115, 101, 114, 118, 105, 99, 101, 5, 108, 111, 99, 97, 108, 0, 192, 12, 0,
3051 28, 0, 1, 255, 255, 255, 255, 0, 2, 192, 28,
3052 ]
3053 );
3054 let mut expected_names = HashMap::new();
3055 expected_names.insert("test".to_string(), 12);
3056 expected_names.insert("test-service.local".to_string(), 28);
3057 expected_names.insert("local".to_string(), 41);
3058 assert_eq!(&packets[0].names, &expected_names);
3059 }
3060
3061 #[test]
3065 fn test_dns_outgoing_question_label_too_long() {
3066 let long_label = "a".repeat(64);
3067 let mut out = DnsOutgoing::new(0);
3068 out.add_question(&format!("{long_label}.local"), RRType::PTR);
3069 out.add_question("123.test", RRType::A);
3070
3071 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3072 assert_eq!(packets.len(), 1);
3073 assert_eq!(
3074 packets[0].as_bytes(),
3075 &[
3076 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,
3079 ]
3080 );
3081
3082 let mut expected_names = HashMap::new();
3084 expected_names.insert("123.test".to_string(), 12);
3085 expected_names.insert("test".to_string(), 16);
3086 assert_eq!(&packets[0].names, &expected_names);
3087 }
3088
3089 #[test]
3092 fn test_dns_outgoing_record_label_too_long() {
3093 let long_label = "a".repeat(64);
3094 let mut out = DnsOutgoing::new(0);
3095 out.add_answer_at_time(
3096 DnsPointer::new(
3097 "_test._tcp.local.",
3098 RRType::PTR,
3099 CLASS_IN,
3100 0,
3101 format!("{long_label}._test._tcp.local."),
3102 ),
3103 0,
3104 );
3105 out.add_answer_at_time(
3106 DnsPointer::new(
3107 "_test._tcp.local.",
3108 RRType::PTR,
3109 CLASS_IN,
3110 0,
3111 "ok._test._tcp.local.".to_string(),
3112 ),
3113 0,
3114 );
3115
3116 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3117 assert_eq!(packets.len(), 1);
3118
3119 assert_eq!(&packets[0].as_bytes()[6..8], &[0, 1]);
3121
3122 let incoming = DnsIncoming::new(
3124 packets[0].as_bytes().to_vec(),
3125 InterfaceId {
3126 name: "test".to_string(),
3127 index: 1,
3128 },
3129 )
3130 .unwrap();
3131 assert_eq!(incoming.answers().len(), 1);
3132 }
3133
3134 #[test]
3139 fn test_incoming_name_with_merged_labels_does_not_panic() {
3140 let mut data: Vec<u8> = vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
3142 data.push(63);
3143 data.extend(vec![b'a'; 62]);
3144 data.push(b'\\');
3145 data.push(63);
3146 data.extend(vec![b'b'; 63]);
3147 data.push(0);
3148 data.extend([0, 12, 0, 1]); let incoming = DnsIncoming::new(
3151 data,
3152 InterfaceId {
3153 name: "test".to_string(),
3154 index: 1,
3155 },
3156 )
3157 .unwrap();
3158 let name = incoming.questions()[0].entry.name.clone();
3159
3160 assert!(name.starts_with("aaa"));
3162 assert!(name.contains("\\.bbb"));
3163
3164 let mut out = DnsOutgoing::new(0);
3166 out.add_question(&name, RRType::PTR);
3167 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3168 assert_eq!(packets.len(), 1);
3169 assert_eq!(packets[0].as_bytes(), &[0; MSG_HEADER_LEN]);
3170 }
3171
3172 #[test]
3176 fn test_read_name_pointer_loop_is_rejected() {
3177 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 1, 0, 0, 0, 0];
3181 data.extend_from_slice(&[5, b'l', b'o', b'c', b'a', b'l']); data.extend_from_slice(&[2, b'_', b'x']); data.extend_from_slice(&[0xC0, 12]); data.extend_from_slice(&[0, 12, 0, 1]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0, 2]); data.extend_from_slice(&[0xC0, 12]); assert!(DnsIncoming::new(data, test_interface_id()).is_err());
3190 }
3191
3192 #[test]
3200 fn test_read_name_pointer_after_backward_jump() {
3201 fn push_question(data: &mut Vec<u8>, label_len: usize) {
3203 data.push(label_len as u8);
3204 data.extend(vec![b'a'; label_len]);
3205 data.push(0); data.extend_from_slice(&[0, 12]); data.extend_from_slice(&[0, 1]); }
3209
3210 let mut data: Vec<u8> = vec![
3211 0, 0, 0, 0, 0, 11, 0, 1, 0, 0, 0, 0, ];
3217
3218 for _ in 0..10 {
3220 push_question(&mut data, 60);
3221 }
3222 assert_eq!(data.len(), 672);
3223
3224 push_question(&mut data, 22);
3226 assert_eq!(data.len(), 700);
3227
3228 data[640] = 62;
3230
3231 data.extend_from_slice(&[0xC2, 0x80]); data.extend_from_slice(&[0x00, 0xC2]); data.extend_from_slice(&[0xBE, 0x01]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0, 0]); assert_eq!(u16_from_be_slice(&data[700..702]) ^ 0xC000, 640);
3240 assert_eq!(u16_from_be_slice(&data[703..705]) ^ 0xC000, 702);
3241
3242 let incoming = DnsIncoming::new(data, test_interface_id())
3243 .expect("a name whose pointers all point backwards must parse");
3244 assert_eq!(incoming.questions().len(), 11);
3245
3246 assert_eq!(incoming.answers().len(), 0);
3248 }
3249
3250 #[test]
3257 fn test_read_name_mutual_pointers_are_rejected() {
3258 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 2, 0, 0, 0, 0];
3259
3260 data.push(0); data.extend_from_slice(&[0x00, 0xC2]); data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0x00, 0x04]); data.extend_from_slice(&[0xC0, 25]); data.extend_from_slice(&[0xC0, 23]); assert_eq!(data.len(), 27);
3269
3270 data.extend_from_slice(&[0xC0, 23]); data.extend_from_slice(&[0x00, 0xC2, 0x00, 0x01]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0, 0]); assert_eq!(u16_from_be_slice(&data[27..29]) ^ 0xC000, 23);
3278 assert_eq!(u16_from_be_slice(&data[23..25]) ^ 0xC000, 25);
3279 assert_eq!(u16_from_be_slice(&data[25..27]) ^ 0xC000, 23);
3280
3281 assert!(DnsIncoming::new(data, test_interface_id()).is_err());
3282 }
3283
3284 #[test]
3289 fn test_read_name_label_cycle_is_rejected() {
3290 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 2, 0, 0, 0, 0];
3291
3292 data.push(0); data.extend_from_slice(&[0x00, 0xC2]); data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0x00, 0x07]); data.push(0x04); data.extend_from_slice(b"aaaa"); data.extend_from_slice(&[0xC0, 23]); assert_eq!(data.len(), 30);
3302
3303 data.extend_from_slice(&[0xC0, 23]); data.extend_from_slice(&[0x00, 0xC2, 0x00, 0x01]); data.extend_from_slice(&[0, 0, 0, 120]); data.extend_from_slice(&[0, 0]); assert_eq!(u16_from_be_slice(&data[28..30]) ^ 0xC000, 23);
3312 assert_eq!(u16_from_be_slice(&data[30..32]) ^ 0xC000, 23);
3313
3314 assert!(DnsIncoming::new(data, test_interface_id()).is_err());
3315 }
3316
3317 #[test]
3327 fn test_malformed_nsec_record_is_skipped() {
3328 let data: Vec<u8> = vec![
3329 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x5f,
3330 0x6d, 0x69, 0x69, 0x6f, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61,
3331 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x24, 0x21, 0x64,
3332 0x72, 0x65, 0x61, 0x6d, 0x65, 0x2d, 0x76, 0x61, 0x63, 0x75, 0x75, 0x6d, 0x2d, 0x70,
3333 0x32, 0x30, 0x32, 0x39, 0x5f, 0x6d, 0x69, 0x69, 0x6f, 0x34, 0x34, 0x37, 0x33, 0x30,
3334 0x35, 0x32, 0x34, 0x37, 0xc0, 0x0c, 0x21, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x2d,
3335 0x76, 0x61, 0x63, 0x75, 0x75, 0x6d, 0x2d, 0x70, 0x32, 0x30, 0x32, 0x39, 0x5f, 0x6d,
3336 0x69, 0x69, 0x6f, 0x34, 0x34, 0x37, 0x33, 0x30, 0x35, 0x32, 0x34, 0x37, 0x00, 0x00,
3337 0x2f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x09, 0xc0, 0x79, 0x00, 0x05, 0x40,
3338 0x00, 0x00, 0x00, 0x00, 0xc0, 0x4c, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78,
3339 0x00, 0x04, 0x0a, 0x2a, 0x02, 0x32, 0xc0, 0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00,
3340 0x00, 0x78, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31, 0xc0, 0x4c, 0xc0, 0x28,
3341 0x00, 0x10, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x0e, 0x70, 0x61, 0x74,
3342 0x68, 0x3d, 0x2f, 0x6d, 0x79, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
3343 ];
3344
3345 assert_eq!(u16_from_be_slice(&data[121..123]) ^ 0xC000, 121);
3348
3349 let incoming = DnsIncoming::new(data, test_interface_id())
3350 .expect("one malformed record must not fail the whole packet");
3351
3352 assert_eq!(incoming.answers().len(), 4);
3354 assert!(
3355 !incoming
3356 .answers()
3357 .iter()
3358 .any(|r| r.get_type() == RRType::NSEC),
3359 "the malformed NSEC record must be skipped"
3360 );
3361 }
3362
3363 fn test_interface_id() -> InterfaceId {
3364 InterfaceId {
3365 name: "test".to_string(),
3366 index: 1,
3367 }
3368 }
3369
3370 fn packet_flags(packet: &DnsOutPacket) -> u16 {
3372 let bytes = packet.as_bytes();
3373 u16::from_be_bytes([bytes[2], bytes[3]])
3374 }
3375
3376 fn ptr_answer(index: usize) -> DnsPointer {
3377 DnsPointer::new(
3378 "_spill._tcp.local.",
3379 RRType::PTR,
3380 CLASS_IN,
3381 4500,
3382 format!("instance-{index:04}._spill._tcp.local."),
3383 )
3384 }
3385
3386 fn parsed_answer_count(packets: &[DnsOutPacket]) -> usize {
3389 packets
3390 .iter()
3391 .map(|packet: &DnsOutPacket| {
3392 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id())
3393 .expect("each packet must parse on its own");
3394 assert!(
3395 !parsed.answers().is_empty(),
3396 "a spilled packet must not be empty"
3397 );
3398 parsed.answers().len()
3399 })
3400 .sum()
3401 }
3402
3403 #[test]
3406 fn test_dns_outgoing_response_spills_into_packets() {
3407 const ANSWER_COUNT: usize = 100;
3408
3409 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3410 for i in 0..ANSWER_COUNT {
3411 out.add_answer_at_time(ptr_answer(i), 0);
3412 }
3413
3414 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3415 assert!(
3416 packets.len() > 1,
3417 "{} answers should not fit in one packet",
3418 ANSWER_COUNT
3419 );
3420
3421 for packet in &packets {
3422 assert!(
3423 packet.size() <= MAX_PKT_DEFAULT,
3424 "packet of {} bytes exceeds the limit",
3425 packet.size()
3426 );
3427
3428 assert_eq!(packet_flags(packet) & FLAGS_TC, 0);
3431 }
3432
3433 assert_eq!(parsed_answer_count(&packets), ANSWER_COUNT);
3434 }
3435
3436 #[test]
3439 fn test_dns_outgoing_query_truncation_bit() {
3440 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
3441 out.add_question("_spill._tcp.local.", RRType::PTR);
3442 for i in 0..100 {
3443 out.add_answer_box(Box::new(ptr_answer(i)));
3444 }
3445
3446 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3447 assert!(
3448 packets.len() > 1,
3449 "known answers should not fit in one packet"
3450 );
3451
3452 let (last, rest) = packets.split_last().expect("at least one packet");
3453 for packet in rest {
3454 assert_ne!(
3455 packet_flags(packet) & FLAGS_TC,
3456 0,
3457 "a packet with more known answers to follow must set TC"
3458 );
3459 }
3460 assert_eq!(
3461 packet_flags(last) & FLAGS_TC,
3462 0,
3463 "the last packet must not set TC"
3464 );
3465
3466 assert_eq!(packets[0].as_bytes()[4..6], 1u16.to_be_bytes());
3468 for packet in rest.iter().skip(1) {
3469 assert_eq!(packet.as_bytes()[4..6], [0, 0]);
3470 }
3471 assert_eq!(parsed_answer_count(&packets), 100);
3472 }
3473
3474 #[test]
3478 fn test_dns_outgoing_oversized_record_sent_alone() {
3479 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3480 out.add_answer_at_time(ptr_answer(0), 0);
3481 out.add_answer_at_time(
3482 DnsTxt::new("big._spill._tcp.local.", CLASS_IN, 4500, vec![b'x'; 2000]),
3483 0,
3484 );
3485 out.add_answer_at_time(ptr_answer(1), 0);
3486
3487 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3488 assert_eq!(packets.len(), 3, "the big record needs a packet to itself");
3489
3490 assert!(packets[0].size() <= MAX_PKT_DEFAULT);
3491 assert!(
3492 packets[1].size() > MAX_PKT_DEFAULT,
3493 "the oversized record must not be dropped"
3494 );
3495 assert!(packets[1].size() <= MAX_PKT_ABSOLUTE_IPV6);
3497 assert!(packets[2].size() <= MAX_PKT_DEFAULT);
3498
3499 let parsed = DnsIncoming::new(packets[1].as_bytes().to_vec(), test_interface_id()).unwrap();
3501 assert_eq!(parsed.answers().len(), 1);
3502 assert_eq!(parsed.answers()[0].get_name(), "big._spill._tcp.local.");
3503 assert_eq!(parsed_answer_count(&packets), 3);
3504 }
3505
3506 #[test]
3509 fn test_dns_outgoing_record_over_absolute_ceiling_dropped() {
3510 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3511 out.add_answer_at_time(ptr_answer(0), 0);
3512 out.add_answer_at_time(
3513 DnsTxt::new(
3514 "huge._spill._tcp.local.",
3515 CLASS_IN,
3516 4500,
3517 vec![b'x'; MAX_PKT_ABSOLUTE_IPV6],
3518 ),
3519 0,
3520 );
3521 out.add_answer_at_time(ptr_answer(1), 0);
3522
3523 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3524 for packet in &packets {
3525 assert!(
3526 packet.size() <= MAX_PKT_ABSOLUTE_IPV6,
3527 "an unsendable packet must never be generated"
3528 );
3529 }
3530 assert_eq!(
3531 parsed_answer_count(&packets),
3532 2,
3533 "only the huge record is dropped"
3534 );
3535 }
3536
3537 #[test]
3539 fn test_dns_outgoing_all_sections_spill() {
3540 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3541 for i in 0..40 {
3542 out.add_answer_at_time(ptr_answer(i), 0);
3543 }
3544 for i in 40..80 {
3545 out.add_authority(Box::new(ptr_answer(i)));
3546 }
3547 for i in 80..120 {
3548 out.add_additional_answer(ptr_answer(i));
3549 }
3550
3551 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3552 assert!(packets.len() > 1);
3553
3554 let mut answers = 0;
3555 let mut authorities = 0;
3556 let mut additionals = 0;
3557 for packet in &packets {
3558 assert!(packet.size() <= MAX_PKT_DEFAULT);
3559 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id()).unwrap();
3560 answers += parsed.answers().len();
3561 authorities += parsed.authorities().len();
3562 additionals += parsed.additionals().len();
3563 }
3564
3565 assert_eq!(answers, 40);
3566 assert_eq!(authorities, 40);
3567 assert_eq!(additionals, 40);
3568 }
3569}