1#[cfg(feature = "logging")]
8use crate::log::{debug, trace};
9
10use crate::current_time_millis;
11use crate::error::{e_fmt, Error, Result};
12use crate::service_info::{is_unicast_link_local, DnsRegistry, MyIntf, ServiceInfo};
13
14use if_addrs::Interface;
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19use std::{
20 any::Any,
21 cmp,
22 collections::HashMap,
23 convert::TryInto,
24 fmt,
25 hash::Hash,
26 net::{IpAddr, Ipv4Addr, Ipv6Addr},
27 str,
28};
29
30#[derive(Clone, Debug, Eq, Hash, PartialEq, Default)]
32#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
33pub struct InterfaceId {
34 pub name: String,
36
37 pub index: u32,
39}
40
41impl InterfaceId {
42 pub fn get_addrs(&self) -> Vec<IpAddr> {
44 if_addrs::get_if_addrs()
45 .unwrap_or_default()
46 .into_iter()
47 .filter(|iface| iface.index == Some(self.index))
48 .map(|iface| iface.ip())
49 .collect()
50 }
51}
52
53impl fmt::Display for InterfaceId {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 write!(f, "{}('{}')", self.index, self.name)
56 }
57}
58
59impl From<&Interface> for InterfaceId {
60 fn from(interface: &Interface) -> Self {
61 InterfaceId {
62 name: interface.name.clone(),
63 index: interface.index.unwrap_or_default(),
64 }
65 }
66}
67
68#[derive(Debug, Clone, Eq, PartialEq, Hash)]
70#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
71pub struct ScopedIpV4 {
72 addr: Ipv4Addr,
73 interface_ids: Vec<InterfaceId>,
75}
76
77impl ScopedIpV4 {
78 pub fn new(addr: Ipv4Addr, interface_id: InterfaceId) -> Self {
80 Self {
81 addr,
82 interface_ids: vec![interface_id],
83 }
84 }
85
86 pub const fn addr(&self) -> &Ipv4Addr {
88 &self.addr
89 }
90
91 pub fn interface_ids(&self) -> &[InterfaceId] {
93 &self.interface_ids
94 }
95
96 pub(crate) fn add_interface_id(&mut self, id: InterfaceId) {
98 if !self.interface_ids.contains(&id) {
99 self.interface_ids.push(id);
100 }
101 }
102}
103
104#[derive(Debug, Clone, Eq, PartialEq, Hash)]
106#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
107pub struct ScopedIpV6 {
108 addr: Ipv6Addr,
109 scope_id: InterfaceId,
110}
111
112impl ScopedIpV6 {
113 pub const fn addr(&self) -> &Ipv6Addr {
115 &self.addr
116 }
117
118 pub const fn scope_id(&self) -> &InterfaceId {
120 &self.scope_id
121 }
122}
123
124#[derive(Debug, Clone, Eq, PartialEq, Hash)]
126#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
127#[non_exhaustive]
128pub enum ScopedIp {
129 V4(ScopedIpV4),
130 V6(ScopedIpV6),
131}
132
133impl ScopedIp {
134 pub const fn to_ip_addr(&self) -> IpAddr {
135 match self {
136 ScopedIp::V4(v4) => IpAddr::V4(v4.addr),
137 ScopedIp::V6(v6) => IpAddr::V6(v6.addr),
138 }
139 }
140
141 pub const fn is_ipv4(&self) -> bool {
142 matches!(self, ScopedIp::V4(_))
143 }
144
145 pub const fn is_ipv6(&self) -> bool {
146 matches!(self, ScopedIp::V6(_))
147 }
148
149 pub const fn is_loopback(&self) -> bool {
150 match self {
151 ScopedIp::V4(v4) => v4.addr.is_loopback(),
152 ScopedIp::V6(v6) => v6.addr.is_loopback(),
153 }
154 }
155}
156
157impl From<IpAddr> for ScopedIp {
158 fn from(ip: IpAddr) -> Self {
159 match ip {
160 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
161 addr: v4,
162 interface_ids: vec![],
163 }),
164 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
165 addr: v6,
166 scope_id: InterfaceId::default(),
167 }),
168 }
169 }
170}
171
172impl From<&Interface> for ScopedIp {
173 fn from(interface: &Interface) -> Self {
174 match interface.ip() {
175 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
176 addr: v4,
177 interface_ids: vec![InterfaceId::from(interface)],
178 }),
179 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
180 addr: v6,
181 scope_id: InterfaceId::from(interface),
182 }),
183 }
184 }
185}
186
187impl fmt::Display for ScopedIp {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 match self {
190 ScopedIp::V4(v4) => write!(f, "{}", v4.addr),
191 ScopedIp::V6(v6) => {
192 if v6.scope_id.index != 0 && is_unicast_link_local(&v6.addr) {
193 #[cfg(windows)]
194 {
195 write!(f, "{}%{}", v6.addr, v6.scope_id.index)
196 }
197 #[cfg(not(windows))]
198 {
199 write!(f, "{}%{}", v6.addr, v6.scope_id.name)
200 }
201 } else {
202 write!(f, "{}", v6.addr)
203 }
204 }
205 }
206 }
207}
208
209#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
213#[non_exhaustive]
214#[repr(u16)]
215pub enum RRType {
216 A = 1,
218
219 CNAME = 5,
221
222 PTR = 12,
224
225 HINFO = 13,
227
228 TXT = 16,
230
231 AAAA = 28,
233
234 SRV = 33,
236
237 NSEC = 47,
239
240 ANY = 255,
242}
243
244impl RRType {
245 pub const fn from_u16(value: u16) -> Option<Self> {
247 match value {
248 1 => Some(RRType::A),
249 5 => Some(RRType::CNAME),
250 12 => Some(RRType::PTR),
251 13 => Some(RRType::HINFO),
252 16 => Some(RRType::TXT),
253 28 => Some(RRType::AAAA),
254 33 => Some(RRType::SRV),
255 47 => Some(RRType::NSEC),
256 255 => Some(RRType::ANY),
257 _ => None,
258 }
259 }
260}
261
262impl fmt::Display for RRType {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 match self {
265 RRType::A => write!(f, "TYPE_A"),
266 RRType::CNAME => write!(f, "TYPE_CNAME"),
267 RRType::PTR => write!(f, "TYPE_PTR"),
268 RRType::HINFO => write!(f, "TYPE_HINFO"),
269 RRType::TXT => write!(f, "TYPE_TXT"),
270 RRType::AAAA => write!(f, "TYPE_AAAA"),
271 RRType::SRV => write!(f, "TYPE_SRV"),
272 RRType::NSEC => write!(f, "TYPE_NSEC"),
273 RRType::ANY => write!(f, "TYPE_ANY"),
274 }
275 }
276}
277
278pub const CLASS_IN: u16 = 1;
280pub const CLASS_MASK: u16 = 0x7FFF;
281
282pub const CLASS_CACHE_FLUSH: u16 = 0x8000;
284
285pub const MAX_MSG_ABSOLUTE: usize = 8972;
290
291const MSG_HEADER_LEN: usize = 12;
292
293const MAX_LABEL_BYTES: usize = 63;
297
298#[derive(Debug, PartialEq, Eq)]
303pub enum WriteError {
304 NameTooLong,
306
307 PacketFull,
309}
310
311type WriteResult = core::result::Result<(), WriteError>;
313
314pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
326
327pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
329
330pub const FLAGS_AA: u16 = 0x0400;
332
333pub const FLAGS_TC: u16 = 0x0200;
344
345pub type DnsRecordBox = Box<dyn DnsRecordExt>;
347
348impl Clone for DnsRecordBox {
349 fn clone(&self) -> Self {
350 self.clone_box()
351 }
352}
353
354const U16_SIZE: usize = 2;
355
356#[inline]
358pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
359 match address {
360 IpAddr::V4(_) => RRType::A,
361 IpAddr::V6(_) => RRType::AAAA,
362 }
363}
364
365#[derive(Eq, PartialEq, Debug, Clone)]
366pub struct DnsEntry {
367 pub(crate) name: String, pub(crate) ty: RRType,
369 class: u16,
370 cache_flush: bool,
371}
372
373impl DnsEntry {
374 const fn new(name: String, ty: RRType, class: u16) -> Self {
375 Self {
376 name,
377 ty,
378 class: class & CLASS_MASK,
379 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
380 }
381 }
382}
383
384pub trait DnsEntryExt: fmt::Debug {
386 fn entry_name(&self) -> &str;
387
388 fn entry_type(&self) -> RRType;
389}
390
391#[derive(Debug)]
393pub struct DnsQuestion {
394 pub(crate) entry: DnsEntry,
395}
396
397impl DnsEntryExt for DnsQuestion {
398 fn entry_name(&self) -> &str {
399 &self.entry.name
400 }
401
402 fn entry_type(&self) -> RRType {
403 self.entry.ty
404 }
405}
406
407#[derive(Debug, Clone)]
411pub struct DnsRecord {
412 pub(crate) entry: DnsEntry,
413 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
423}
424
425impl DnsRecord {
426 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
427 let created = current_time_millis();
428
429 let refresh = get_expiration_time(created, ttl, 80);
433
434 let expires = get_expiration_time(created, ttl, 100);
435
436 Self {
437 entry: DnsEntry::new(name.to_string(), ty, class),
438 ttl,
439 created,
440 expires,
441 refresh,
442 new_name: None,
443 }
444 }
445
446 pub const fn get_ttl(&self) -> u32 {
447 self.ttl
448 }
449
450 pub const fn get_expire_time(&self) -> u64 {
451 self.expires
452 }
453
454 pub const fn get_refresh_time(&self) -> u64 {
455 self.refresh
456 }
457
458 pub const fn is_expired(&self, now: u64) -> bool {
459 now >= self.expires
460 }
461
462 pub const fn expires_soon(&self, now: u64) -> bool {
466 now + 1000 >= self.expires
467 }
468
469 pub const fn refresh_due(&self, now: u64) -> bool {
470 now >= self.refresh
471 }
472
473 pub fn halflife_passed(&self, now: u64) -> bool {
475 let halflife = get_expiration_time(self.created, self.ttl, 50);
476 now > halflife
477 }
478
479 pub fn is_unique(&self) -> bool {
480 self.entry.cache_flush
481 }
482
483 pub fn refresh_no_more(&mut self) {
486 self.refresh = get_expiration_time(self.created, self.ttl, 100);
487 }
488
489 pub fn refresh_maybe(&mut self, now: u64) -> bool {
491 if self.is_expired(now) || !self.refresh_due(now) {
492 return false;
493 }
494
495 trace!(
496 "{} qtype {} is due to refresh",
497 &self.entry.name,
498 self.entry.ty
499 );
500
501 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
508 self.refresh = get_expiration_time(self.created, self.ttl, 85);
509 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
510 self.refresh = get_expiration_time(self.created, self.ttl, 90);
511 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
512 self.refresh = get_expiration_time(self.created, self.ttl, 95);
513 } else {
514 self.refresh_no_more();
515 }
516
517 true
518 }
519
520 fn get_remaining_ttl(&self, now: u64) -> u32 {
522 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
523 cmp::max(0, remaining_millis / 1000) as u32
524 }
525
526 pub const fn get_created(&self) -> u64 {
528 self.created
529 }
530
531 fn set_expire(&mut self, expire_at: u64) {
533 self.expires = expire_at;
534 }
535
536 fn reset_ttl(&mut self, other: &Self) {
537 self.ttl = other.ttl;
538 self.created = other.created;
539 self.expires = get_expiration_time(self.created, self.ttl, 100);
540 self.refresh = if self.ttl > 1 {
541 get_expiration_time(self.created, self.ttl, 80)
542 } else {
543 self.expires
546 };
547 }
548
549 pub fn update_ttl(&mut self, now: u64) {
551 if now > self.created {
552 let elapsed = now - self.created;
553 self.ttl -= (elapsed / 1000) as u32;
554 }
555 }
556
557 pub fn set_new_name(&mut self, new_name: String) {
558 if new_name == self.entry.name {
559 self.new_name = None;
560 } else {
561 self.new_name = Some(new_name);
562 }
563 }
564
565 pub fn get_new_name(&self) -> Option<&str> {
566 self.new_name.as_deref()
567 }
568
569 pub(crate) fn get_name(&self) -> &str {
571 self.new_name.as_deref().unwrap_or(&self.entry.name)
572 }
573
574 pub fn get_original_name(&self) -> &str {
575 &self.entry.name
576 }
577}
578
579impl PartialEq for DnsRecord {
580 fn eq(&self, other: &Self) -> bool {
581 self.entry == other.entry
582 }
583}
584
585pub trait DnsRecordExt: fmt::Debug {
587 fn get_record(&self) -> &DnsRecord;
588 fn get_record_mut(&mut self) -> &mut DnsRecord;
589 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult;
591 fn any(&self) -> &dyn Any;
592
593 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
595
596 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
598
599 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
602
603 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
605 match self.get_class().cmp(&other.get_class()) {
619 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
620 cmp::Ordering::Equal => self.compare_rdata(other),
621 not_equal => not_equal,
622 },
623 not_equal => not_equal,
624 }
625 }
626
627 fn rdata_print(&self) -> String;
629
630 fn get_class(&self) -> u16 {
632 self.get_record().entry.class
633 }
634
635 fn get_cache_flush(&self) -> bool {
636 self.get_record().entry.cache_flush
637 }
638
639 fn get_name(&self) -> &str {
641 self.get_record().get_name()
642 }
643
644 fn get_type(&self) -> RRType {
645 self.get_record().entry.ty
646 }
647
648 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
651 self.get_record_mut().reset_ttl(other.get_record());
652 }
653
654 fn get_created(&self) -> u64 {
655 self.get_record().get_created()
656 }
657
658 fn get_expire(&self) -> u64 {
659 self.get_record().get_expire_time()
660 }
661
662 fn set_expire(&mut self, expire_at: u64) {
663 self.get_record_mut().set_expire(expire_at);
664 }
665
666 fn set_expire_sooner(&mut self, expire_at: u64) {
668 if expire_at < self.get_expire() {
669 self.get_record_mut().set_expire(expire_at);
670 }
671 }
672
673 fn expires_soon(&self, now: u64) -> bool {
675 self.get_record().expires_soon(now)
676 }
677
678 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
681 if self.get_record_mut().refresh_maybe(now) {
682 Some(self.get_record().get_refresh_time())
683 } else {
684 None
685 }
686 }
687
688 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
691 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
692 }
693
694 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
696 for answer in msg.answers.iter() {
697 if self.suppressed_by_answer(answer.as_ref()) {
698 return true;
699 }
700 }
701 false
702 }
703
704 fn clone_box(&self) -> DnsRecordBox;
705
706 fn boxed(self) -> DnsRecordBox;
707}
708
709#[derive(Debug, Clone)]
711pub(crate) struct DnsAddress {
712 pub(crate) record: DnsRecord,
713 address: IpAddr,
714 pub(crate) interface_id: InterfaceId,
715}
716
717impl DnsAddress {
718 pub fn new(
719 name: &str,
720 ty: RRType,
721 class: u16,
722 ttl: u32,
723 address: IpAddr,
724 interface_id: InterfaceId,
725 ) -> Self {
726 let record = DnsRecord::new(name, ty, class, ttl);
727 Self {
728 record,
729 address,
730 interface_id,
731 }
732 }
733
734 pub fn address(&self) -> ScopedIp {
735 match self.address {
736 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
737 addr: v4,
738 interface_ids: vec![self.interface_id.clone()],
739 }),
740 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
741 addr: v6,
742 scope_id: self.interface_id.clone(),
743 }),
744 }
745 }
746}
747
748impl DnsRecordExt for DnsAddress {
749 fn get_record(&self) -> &DnsRecord {
750 &self.record
751 }
752
753 fn get_record_mut(&mut self) -> &mut DnsRecord {
754 &mut self.record
755 }
756
757 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
758 match self.address {
759 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
760 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
761 };
762 Ok(())
763 }
764
765 fn any(&self) -> &dyn Any {
766 self
767 }
768
769 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
770 if let Some(other_a) = other.any().downcast_ref::<Self>() {
771 return self.address == other_a.address
772 && self.record.entry == other_a.record.entry
773 && self.interface_id == other_a.interface_id;
774 }
775 false
776 }
777
778 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
779 if let Some(other_a) = other.any().downcast_ref::<Self>() {
780 return self.address == other_a.address;
781 }
782 false
783 }
784
785 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
786 if let Some(other_a) = other.any().downcast_ref::<Self>() {
787 self.address.cmp(&other_a.address)
788 } else {
789 cmp::Ordering::Greater
790 }
791 }
792
793 fn rdata_print(&self) -> String {
794 format!("{}", self.address)
795 }
796
797 fn clone_box(&self) -> DnsRecordBox {
798 Box::new(self.clone())
799 }
800
801 fn boxed(self) -> DnsRecordBox {
802 Box::new(self)
803 }
804}
805
806#[derive(Debug, Clone)]
808pub struct DnsPointer {
809 record: DnsRecord,
810 alias: String, }
812
813impl DnsPointer {
814 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
815 let record = DnsRecord::new(name, ty, class, ttl);
816 Self { record, alias }
817 }
818
819 pub fn alias(&self) -> &str {
820 &self.alias
821 }
822}
823
824impl DnsRecordExt for DnsPointer {
825 fn get_record(&self) -> &DnsRecord {
826 &self.record
827 }
828
829 fn get_record_mut(&mut self) -> &mut DnsRecord {
830 &mut self.record
831 }
832
833 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
834 packet.write_name(&self.alias)
835 }
836
837 fn any(&self) -> &dyn Any {
838 self
839 }
840
841 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
842 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
843 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
844 }
845 false
846 }
847
848 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
849 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
850 return self.alias == other_ptr.alias;
851 }
852 false
853 }
854
855 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
856 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
857 self.alias.cmp(&other_ptr.alias)
858 } else {
859 cmp::Ordering::Greater
860 }
861 }
862
863 fn rdata_print(&self) -> String {
864 self.alias.clone()
865 }
866
867 fn clone_box(&self) -> DnsRecordBox {
868 Box::new(self.clone())
869 }
870
871 fn boxed(self) -> DnsRecordBox {
872 Box::new(self)
873 }
874}
875
876#[derive(Debug, Clone)]
878pub struct DnsSrv {
879 pub(crate) record: DnsRecord,
880 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
883 port: u16,
884}
885
886impl DnsSrv {
887 pub fn new(
888 name: &str,
889 class: u16,
890 ttl: u32,
891 priority: u16,
892 weight: u16,
893 port: u16,
894 host: String,
895 ) -> Self {
896 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
897 Self {
898 record,
899 priority,
900 weight,
901 host,
902 port,
903 }
904 }
905
906 pub fn host(&self) -> &str {
907 &self.host
908 }
909
910 pub fn port(&self) -> u16 {
911 self.port
912 }
913
914 pub fn set_host(&mut self, host: String) {
915 self.host = host;
916 }
917}
918
919impl DnsRecordExt for DnsSrv {
920 fn get_record(&self) -> &DnsRecord {
921 &self.record
922 }
923
924 fn get_record_mut(&mut self) -> &mut DnsRecord {
925 &mut self.record
926 }
927
928 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
929 packet.write_short(self.priority);
930 packet.write_short(self.weight);
931 packet.write_short(self.port);
932 packet.write_name(&self.host)
933 }
934
935 fn any(&self) -> &dyn Any {
936 self
937 }
938
939 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
940 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
941 return self.host == other_svc.host
942 && self.port == other_svc.port
943 && self.weight == other_svc.weight
944 && self.priority == other_svc.priority
945 && self.record.entry == other_svc.record.entry;
946 }
947 false
948 }
949
950 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
951 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
952 return self.host == other_srv.host
953 && self.port == other_srv.port
954 && self.weight == other_srv.weight
955 && self.priority == other_srv.priority;
956 }
957 false
958 }
959
960 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
961 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
962 return cmp::Ordering::Greater;
963 };
964
965 match self
967 .priority
968 .to_be_bytes()
969 .cmp(&other_srv.priority.to_be_bytes())
970 {
971 cmp::Ordering::Equal => {
972 match self
974 .weight
975 .to_be_bytes()
976 .cmp(&other_srv.weight.to_be_bytes())
977 {
978 cmp::Ordering::Equal => {
979 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
981 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
982 not_equal => not_equal,
983 }
984 }
985 not_equal => not_equal,
986 }
987 }
988 not_equal => not_equal,
989 }
990 }
991
992 fn rdata_print(&self) -> String {
993 format!(
994 "priority: {}, weight: {}, port: {}, host: {}",
995 self.priority, self.weight, self.port, self.host
996 )
997 }
998
999 fn clone_box(&self) -> DnsRecordBox {
1000 Box::new(self.clone())
1001 }
1002
1003 fn boxed(self) -> DnsRecordBox {
1004 Box::new(self)
1005 }
1006}
1007
1008#[derive(Clone)]
1023pub struct DnsTxt {
1024 pub(crate) record: DnsRecord,
1025 text: Vec<u8>,
1026}
1027
1028impl DnsTxt {
1029 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1030 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1031 Self { record, text }
1032 }
1033
1034 pub fn text(&self) -> &[u8] {
1035 &self.text
1036 }
1037}
1038
1039impl DnsRecordExt for DnsTxt {
1040 fn get_record(&self) -> &DnsRecord {
1041 &self.record
1042 }
1043
1044 fn get_record_mut(&mut self) -> &mut DnsRecord {
1045 &mut self.record
1046 }
1047
1048 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1049 packet.write_bytes(&self.text);
1050 Ok(())
1051 }
1052
1053 fn any(&self) -> &dyn Any {
1054 self
1055 }
1056
1057 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1058 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1059 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1060 }
1061 false
1062 }
1063
1064 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1065 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1066 return self.text == other_txt.text;
1067 }
1068 false
1069 }
1070
1071 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1072 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1073 self.text.cmp(&other_txt.text)
1074 } else {
1075 cmp::Ordering::Greater
1076 }
1077 }
1078
1079 fn rdata_print(&self) -> String {
1080 format!("{:?}", decode_txt(&self.text))
1081 }
1082
1083 fn clone_box(&self) -> DnsRecordBox {
1084 Box::new(self.clone())
1085 }
1086
1087 fn boxed(self) -> DnsRecordBox {
1088 Box::new(self)
1089 }
1090}
1091
1092impl fmt::Debug for DnsTxt {
1093 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1094 let properties = decode_txt(&self.text);
1095 write!(
1096 f,
1097 "DnsTxt {{ record: {:?}, text: {:?} }}",
1098 self.record, properties
1099 )
1100 }
1101}
1102
1103fn decode_txt(txt: &[u8]) -> Vec<TxtProperty> {
1105 let mut properties = Vec::new();
1106 let mut offset = 0;
1107 while offset < txt.len() {
1108 let length = txt[offset] as usize;
1109 if length == 0 {
1110 break; }
1112 offset += 1; let offset_end = offset + length;
1115 if offset_end > txt.len() {
1116 trace!("ERROR: DNS TXT: size given for property is out of range. (offset={}, length={}, offset_end={}, record length={})", offset, length, offset_end, txt.len());
1117 break; }
1119 let kv_bytes = &txt[offset..offset_end];
1120
1121 let (k, v) = kv_bytes.iter().position(|&x| x == b'=').map_or_else(
1123 || (kv_bytes.to_vec(), None),
1124 |idx| (kv_bytes[..idx].to_vec(), Some(kv_bytes[idx + 1..].to_vec())),
1125 );
1126
1127 match String::from_utf8(k) {
1129 Ok(k_string) => {
1130 properties.push(TxtProperty {
1131 key: k_string,
1132 val: v,
1133 });
1134 }
1135 Err(e) => trace!("ERROR: convert to String from key: {}", e),
1136 }
1137
1138 offset += length;
1139 }
1140
1141 properties
1142}
1143
1144#[derive(Clone, PartialEq, Eq)]
1146pub struct TxtProperty {
1147 key: String,
1149
1150 val: Option<Vec<u8>>,
1154}
1155
1156impl TxtProperty {
1157 pub fn val_str(&self) -> &str {
1159 self.val
1160 .as_ref()
1161 .map_or("", |v| std::str::from_utf8(&v[..]).unwrap_or_default())
1162 }
1163}
1164
1165impl<K, V> From<&(K, V)> for TxtProperty
1167where
1168 K: ToString,
1169 V: ToString,
1170{
1171 fn from(prop: &(K, V)) -> Self {
1172 Self {
1173 key: prop.0.to_string(),
1174 val: Some(prop.1.to_string().into_bytes()),
1175 }
1176 }
1177}
1178
1179impl<K, V> From<(K, V)> for TxtProperty
1180where
1181 K: ToString,
1182 V: AsRef<[u8]>,
1183{
1184 fn from(prop: (K, V)) -> Self {
1185 Self {
1186 key: prop.0.to_string(),
1187 val: Some(prop.1.as_ref().into()),
1188 }
1189 }
1190}
1191
1192impl From<&str> for TxtProperty {
1194 fn from(key: &str) -> Self {
1195 Self {
1196 key: key.to_string(),
1197 val: None,
1198 }
1199 }
1200}
1201
1202impl fmt::Display for TxtProperty {
1203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1204 write!(f, "{}={}", self.key, self.val_str())
1205 }
1206}
1207
1208impl fmt::Debug for TxtProperty {
1212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1213 let val_string = self.val.as_ref().map_or_else(
1214 || "None".to_string(),
1215 |v| {
1216 std::str::from_utf8(&v[..]).map_or_else(
1217 |_| format!("Some({})", u8_slice_to_hex(&v[..])),
1218 |s| format!("Some(\"{s}\")"),
1219 )
1220 },
1221 );
1222
1223 write!(
1224 f,
1225 "TxtProperty {{key: \"{}\", val: {}}}",
1226 &self.key, &val_string,
1227 )
1228 }
1229}
1230
1231const HEX_TABLE: [char; 16] = [
1232 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
1233];
1234
1235fn u8_slice_to_hex(slice: &[u8]) -> String {
1239 let mut hex = String::with_capacity(slice.len() * 2 + 2);
1240 hex.push_str("0x");
1241 for b in slice {
1242 hex.push(HEX_TABLE[(b >> 4) as usize]);
1243 hex.push(HEX_TABLE[(b & 0x0F) as usize]);
1244 }
1245 hex
1246}
1247
1248#[derive(Debug, Clone)]
1250struct DnsHostInfo {
1251 record: DnsRecord,
1252 cpu: String,
1253 os: String,
1254}
1255
1256impl DnsHostInfo {
1257 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1258 let record = DnsRecord::new(name, ty, class, ttl);
1259 Self { record, cpu, os }
1260 }
1261}
1262
1263impl DnsRecordExt for DnsHostInfo {
1264 fn get_record(&self) -> &DnsRecord {
1265 &self.record
1266 }
1267
1268 fn get_record_mut(&mut self) -> &mut DnsRecord {
1269 &mut self.record
1270 }
1271
1272 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1273 debug!("Writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1274 packet.write_bytes(self.cpu.as_bytes());
1275 packet.write_bytes(self.os.as_bytes());
1276 Ok(())
1277 }
1278
1279 fn any(&self) -> &dyn Any {
1280 self
1281 }
1282
1283 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1284 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1285 return self.cpu == other_hinfo.cpu
1286 && self.os == other_hinfo.os
1287 && self.record.entry == other_hinfo.record.entry;
1288 }
1289 false
1290 }
1291
1292 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1293 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1294 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1295 }
1296 false
1297 }
1298
1299 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1300 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1301 match self.cpu.cmp(&other_hinfo.cpu) {
1302 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1303 ordering => ordering,
1304 }
1305 } else {
1306 cmp::Ordering::Greater
1307 }
1308 }
1309
1310 fn rdata_print(&self) -> String {
1311 format!("cpu: {}, os: {}", self.cpu, self.os)
1312 }
1313
1314 fn clone_box(&self) -> DnsRecordBox {
1315 Box::new(self.clone())
1316 }
1317
1318 fn boxed(self) -> DnsRecordBox {
1319 Box::new(self)
1320 }
1321}
1322
1323#[derive(Debug, Clone)]
1329pub struct DnsNSec {
1330 record: DnsRecord,
1331 next_domain: String,
1332 type_bitmap: Vec<u8>,
1333}
1334
1335impl DnsNSec {
1336 pub fn new(
1337 name: &str,
1338 class: u16,
1339 ttl: u32,
1340 next_domain: String,
1341 type_bitmap: Vec<u8>,
1342 ) -> Self {
1343 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1344 Self {
1345 record,
1346 next_domain,
1347 type_bitmap,
1348 }
1349 }
1350
1351 pub fn _types(&self) -> Vec<u16> {
1353 let mut bit_num = 0;
1362 let mut results = Vec::new();
1363
1364 for byte in self.type_bitmap.iter() {
1365 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1369 if (byte & bit_mask) != 0 {
1370 results.push(bit_num);
1371 }
1372 bit_num += 1;
1373 bit_mask >>= 1; }
1375 }
1376 results
1377 }
1378}
1379
1380impl DnsRecordExt for DnsNSec {
1381 fn get_record(&self) -> &DnsRecord {
1382 &self.record
1383 }
1384
1385 fn get_record_mut(&mut self) -> &mut DnsRecord {
1386 &mut self.record
1387 }
1388
1389 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1390 packet.write_bytes(self.next_domain.as_bytes());
1391 packet.write_bytes(&self.type_bitmap);
1392 Ok(())
1393 }
1394
1395 fn any(&self) -> &dyn Any {
1396 self
1397 }
1398
1399 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1400 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1401 return self.next_domain == other_record.next_domain
1402 && self.type_bitmap == other_record.type_bitmap
1403 && self.record.entry == other_record.record.entry;
1404 }
1405 false
1406 }
1407
1408 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1409 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1410 return self.next_domain == other_record.next_domain
1411 && self.type_bitmap == other_record.type_bitmap;
1412 }
1413 false
1414 }
1415
1416 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1417 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1418 match self.next_domain.cmp(&other_nsec.next_domain) {
1419 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1420 ordering => ordering,
1421 }
1422 } else {
1423 cmp::Ordering::Greater
1424 }
1425 }
1426
1427 fn rdata_print(&self) -> String {
1428 format!(
1429 "next_domain: {}, type_bitmap len: {}",
1430 self.next_domain,
1431 self.type_bitmap.len()
1432 )
1433 }
1434
1435 fn clone_box(&self) -> DnsRecordBox {
1436 Box::new(self.clone())
1437 }
1438
1439 fn boxed(self) -> DnsRecordBox {
1440 Box::new(self)
1441 }
1442}
1443
1444#[derive(PartialEq)]
1445enum PacketState {
1446 Init = 0,
1447 Finished = 1,
1448}
1449
1450pub struct DnsOutPacket {
1452 data: Vec<u8>,
1454
1455 state: PacketState,
1457
1458 names: HashMap<String, u16>,
1460}
1461
1462impl DnsOutPacket {
1463 fn new() -> Self {
1464 Self {
1465 data: vec![0; MSG_HEADER_LEN],
1466 state: PacketState::Init,
1467 names: HashMap::new(),
1468 }
1469 }
1470
1471 pub fn size(&self) -> usize {
1472 self.data.len()
1473 }
1474
1475 pub fn as_bytes(&self) -> &[u8] {
1476 &self.data
1477 }
1478
1479 fn write_question(&mut self, question: &DnsQuestion) -> WriteResult {
1480 self.write_name(&question.entry.name)?;
1481 self.write_short(question.entry.ty as u16);
1482 self.write_short(question.entry.class);
1483 Ok(())
1484 }
1485
1486 fn rollback(&mut self, start_size: usize) {
1489 self.data.truncate(start_size);
1490 self.names
1491 .retain(|_, offset| (*offset as usize) < start_size);
1492 }
1493
1494 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> WriteResult {
1498 let start_size = self.size();
1499
1500 let record = record_ext.get_record();
1501 self.write_name(record.get_name())?;
1502 self.write_short(record.entry.ty as u16);
1503 if record.entry.cache_flush {
1504 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1506 } else {
1507 self.write_short(record.entry.class);
1508 }
1509
1510 if now == 0 {
1511 self.write_u32(record.ttl);
1512 } else {
1513 self.write_u32(record.get_remaining_ttl(now));
1514 }
1515
1516 self.write_short(0);
1518 let record_offset = self.size();
1519
1520 if let Err(e) = record_ext.write(self) {
1521 self.rollback(start_size);
1522 return Err(e);
1523 }
1524
1525 self.insert_short(record_offset - 2, (self.size() - record_offset) as u16);
1526
1527 if self.size() > MAX_MSG_ABSOLUTE {
1528 self.rollback(start_size);
1529 self.state = PacketState::Finished;
1530 return Err(WriteError::PacketFull);
1531 }
1532
1533 Ok(())
1534 }
1535
1536 pub(crate) fn insert_short(&mut self, index: usize, value: u16) {
1537 self.data[index..index + 2].copy_from_slice(&value.to_be_bytes());
1538 }
1539
1540 fn parse_escaped_name(name: &str) -> Vec<String> {
1547 let mut labels = Vec::new();
1548 let mut current_label = String::new();
1549 let mut chars = name.chars().peekable();
1550
1551 while let Some(ch) = chars.next() {
1552 match ch {
1553 '\\' => {
1554 if let Some(&next_ch) = chars.peek() {
1556 match next_ch {
1557 '.' | '\\' => {
1558 chars.next();
1560 current_label.push(next_ch);
1561 }
1562 _ => {
1563 current_label.push(ch);
1565 }
1566 }
1567 } else {
1568 current_label.push(ch);
1570 }
1571 }
1572 '.' => {
1573 if !current_label.is_empty() {
1575 labels.push(current_label.clone());
1576 current_label.clear();
1577 }
1578 }
1579 _ => {
1580 current_label.push(ch);
1581 }
1582 }
1583 }
1584
1585 if !current_label.is_empty() {
1587 labels.push(current_label);
1588 }
1589
1590 labels
1591 }
1592
1593 fn write_name(&mut self, name: &str) -> WriteResult {
1619 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1621
1622 let labels = Self::parse_escaped_name(name_to_parse);
1624
1625 if labels.is_empty() {
1626 self.write_byte(0);
1627 return Ok(());
1628 }
1629
1630 if labels.iter().any(|label| label.len() > MAX_LABEL_BYTES) {
1632 return Err(WriteError::NameTooLong);
1633 }
1634
1635 for (i, label) in labels.iter().enumerate() {
1637 let remaining: String = labels[i..].join(".");
1639
1640 const POINTER_MASK: u16 = 0xC000;
1642 if let Some(&offset) = self.names.get(&remaining) {
1643 let pointer = offset | POINTER_MASK;
1644 self.write_short(pointer);
1645 return Ok(());
1646 }
1647
1648 self.names.insert(remaining, self.size() as u16);
1650
1651 self.write_utf8(label)?;
1653 }
1654
1655 self.write_byte(0);
1657 Ok(())
1658 }
1659
1660 fn write_byte(&mut self, v: u8) {
1661 self.data.push(v);
1662 }
1663
1664 fn write_bytes(&mut self, s: &[u8]) {
1665 self.data.extend(s);
1666 }
1667
1668 fn write_utf8(&mut self, s: &str) -> WriteResult {
1671 if s.len() > MAX_LABEL_BYTES {
1672 return Err(WriteError::NameTooLong);
1673 }
1674 self.write_byte(s.len() as u8);
1675 self.write_bytes(s.as_bytes());
1676 Ok(())
1677 }
1678
1679 fn write_u32(&mut self, v: u32) {
1680 self.data.extend(&v.to_be_bytes());
1681 }
1682
1683 fn write_short(&mut self, v: u16) {
1684 self.data.extend(&v.to_be_bytes());
1685 }
1686
1687 fn write_header(
1710 &mut self,
1711 id: u16,
1712 flags: u16,
1713 q_count: u16,
1714 a_count: u16,
1715 auth_count: u16,
1716 addi_count: u16,
1717 ) {
1718 self.insert_short(0, id);
1719 self.insert_short(2, flags);
1720 self.insert_short(4, q_count);
1721 self.insert_short(6, a_count);
1722 self.insert_short(8, auth_count);
1723 self.insert_short(10, addi_count);
1724
1725 self.state = PacketState::Finished;
1726 }
1727}
1728
1729#[derive(Debug)]
1731pub struct DnsOutgoing {
1732 flags: u16,
1733 id: u16,
1734 multicast: bool,
1735 questions: Vec<DnsQuestion>,
1736 answers: Vec<(DnsRecordBox, u64)>,
1737 authorities: Vec<DnsRecordBox>,
1738 additionals: Vec<DnsRecordBox>,
1739 known_answer_count: i64, }
1741
1742impl DnsOutgoing {
1743 pub fn new(flags: u16) -> Self {
1744 Self {
1745 flags,
1746 id: 0,
1747 multicast: true,
1748 questions: Vec::new(),
1749 answers: Vec::new(),
1750 authorities: Vec::new(),
1751 additionals: Vec::new(),
1752 known_answer_count: 0,
1753 }
1754 }
1755
1756 pub fn questions(&self) -> &[DnsQuestion] {
1757 &self.questions
1758 }
1759
1760 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1762 &self.answers
1763 }
1764
1765 pub fn answers_count(&self) -> usize {
1766 self.answers.len()
1767 }
1768
1769 pub fn authorities(&self) -> &[DnsRecordBox] {
1770 &self.authorities
1771 }
1772
1773 pub fn additionals(&self) -> &[DnsRecordBox] {
1774 &self.additionals
1775 }
1776
1777 pub fn known_answer_count(&self) -> i64 {
1778 self.known_answer_count
1779 }
1780
1781 pub fn set_id(&mut self, id: u16) {
1782 self.id = id;
1783 }
1784
1785 pub const fn is_query(&self) -> bool {
1786 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1787 }
1788
1789 const fn is_response(&self) -> bool {
1790 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
1791 }
1792
1793 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1827 trace!("add_additional_answer: {:?}", &answer);
1828 self.additionals.push(answer.boxed());
1829 }
1830
1831 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1833 self.answers.push((answer_box, 0));
1834 }
1835
1836 pub fn add_authority(&mut self, record: DnsRecordBox) {
1837 self.authorities.push(record);
1838 }
1839
1840 pub(crate) fn retain_answers<F>(&mut self, mut keep: F)
1842 where
1843 F: FnMut(&DnsRecordBox) -> bool,
1844 {
1845 self.answers.retain(|(record, _)| keep(record));
1846 }
1847
1848 pub(crate) fn retain_additionals<F>(&mut self, mut keep: F)
1850 where
1851 F: FnMut(&DnsRecordBox) -> bool,
1852 {
1853 self.additionals.retain(|record| keep(record));
1854 }
1855
1856 pub fn add_answer(
1859 &mut self,
1860 msg: &DnsIncoming,
1861 answer: impl DnsRecordExt + Send + 'static,
1862 ) -> bool {
1863 trace!("Check for add_answer");
1864 if answer.suppressed_by(msg) {
1865 trace!("my answer is suppressed by incoming msg");
1866 self.known_answer_count += 1;
1867 return false;
1868 }
1869
1870 self.add_answer_at_time(answer, 0)
1871 }
1872
1873 pub fn add_answer_at_time(
1877 &mut self,
1878 answer: impl DnsRecordExt + Send + 'static,
1879 now: u64,
1880 ) -> bool {
1881 if now == 0 || !answer.get_record().is_expired(now) {
1882 trace!("add_answer push: {:?}", &answer);
1883 self.answers.push((answer.boxed(), now));
1884 return true;
1885 }
1886 false
1887 }
1888
1889 pub(crate) fn add_answer_with_additionals(
1898 &mut self,
1899 msg: &DnsIncoming,
1900 service: &ServiceInfo,
1901 intf: &MyIntf,
1902 dns_registry: &DnsRegistry,
1903 is_ipv4: bool,
1904 ) {
1905 let intf_addrs = if is_ipv4 {
1906 service.get_addrs_on_my_intf_v4(intf)
1907 } else {
1908 service.get_addrs_on_my_intf_v6(intf)
1909 };
1910 if intf_addrs.is_empty() {
1911 trace!("No addrs on LAN of intf {:?}", intf);
1912 return;
1913 }
1914
1915 let service_fullname = dns_registry.resolve_name(service.get_fullname());
1917 let hostname = dns_registry.resolve_name(service.get_hostname());
1918
1919 let ptr_added = self.add_answer(
1920 msg,
1921 DnsPointer::new(
1922 service.get_type(),
1923 RRType::PTR,
1924 CLASS_IN,
1925 service.get_other_ttl(),
1926 service_fullname.to_string(),
1927 ),
1928 );
1929
1930 if !ptr_added {
1931 trace!("answer was not added for msg {:?}", msg);
1932 return;
1933 }
1934
1935 if let Some(sub) = service.get_subtype() {
1936 trace!("Adding subdomain {}", sub);
1937 self.add_additional_answer(DnsPointer::new(
1938 sub,
1939 RRType::PTR,
1940 CLASS_IN,
1941 service.get_other_ttl(),
1942 service_fullname.to_string(),
1943 ));
1944 }
1945
1946 self.add_additional_answer(DnsSrv::new(
1949 service_fullname,
1950 CLASS_IN | CLASS_CACHE_FLUSH,
1951 service.get_host_ttl(),
1952 service.get_priority(),
1953 service.get_weight(),
1954 service.get_port(),
1955 hostname.to_string(),
1956 ));
1957
1958 self.add_additional_answer(DnsTxt::new(
1959 service_fullname,
1960 CLASS_IN | CLASS_CACHE_FLUSH,
1961 service.get_other_ttl(),
1962 service.generate_txt(),
1963 ));
1964
1965 for address in intf_addrs {
1966 self.add_additional_answer(DnsAddress::new(
1967 hostname,
1968 ip_address_rr_type(&address),
1969 CLASS_IN | CLASS_CACHE_FLUSH,
1970 service.get_host_ttl(),
1971 address,
1972 intf.into(),
1973 ));
1974 }
1975 }
1976
1977 pub fn add_question(&mut self, name: &str, qtype: RRType) {
1978 let q = DnsQuestion {
1979 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
1980 };
1981 self.questions.push(q);
1982 }
1983
1984 pub fn clear_cache_flush_bits(&mut self) {
1989 for (rec, _) in &mut self.answers {
1990 rec.get_record_mut().entry.cache_flush = false;
1991 }
1992 for rec in &mut self.additionals {
1993 rec.get_record_mut().entry.cache_flush = false;
1994 }
1995 for rec in &mut self.authorities {
1996 rec.get_record_mut().entry.cache_flush = false;
1997 }
1998 }
1999
2000 pub fn to_data_on_wire(&self) -> Vec<Vec<u8>> {
2002 let packet_list = self.to_packets();
2003 packet_list.into_iter().map(|p| p.data).collect()
2004 }
2005
2006 pub fn to_packets(&self) -> Vec<DnsOutPacket> {
2008 let mut packet_list = Vec::new();
2009 let mut packet = DnsOutPacket::new();
2010
2011 let mut question_count = 0;
2012 let mut answer_count = 0;
2013 let mut auth_count = 0;
2014 let mut addi_count = 0;
2015 let id = if self.multicast { 0 } else { self.id };
2016
2017 for question in self.questions.iter() {
2018 question_count += u16::from(packet.write_question(question).is_ok());
2019 }
2020
2021 for (answer, time) in self.answers.iter() {
2022 answer_count += u16::from(packet.write_record(answer.as_ref(), *time).is_ok());
2023 }
2024
2025 for auth in self.authorities.iter() {
2026 auth_count += u16::from(packet.write_record(auth.as_ref(), 0).is_ok());
2027 }
2028
2029 for addi in self.additionals.iter() {
2030 match packet.write_record(addi.as_ref(), 0) {
2031 Ok(()) => {
2032 addi_count += 1;
2033 continue;
2034 }
2035 Err(WriteError::NameTooLong) => continue,
2037 Err(WriteError::PacketFull) => {}
2038 }
2039
2040 if self.is_response() {
2042 break;
2043 }
2044
2045 packet.write_header(
2050 id,
2051 self.flags | FLAGS_TC,
2052 question_count,
2053 answer_count,
2054 auth_count,
2055 addi_count,
2056 );
2057
2058 packet_list.push(packet);
2059
2060 packet = DnsOutPacket::new();
2062 addi_count = u16::from(packet.write_record(addi.as_ref(), 0).is_ok());
2063
2064 question_count = 0;
2065 answer_count = 0;
2066 auth_count = 0;
2067 }
2068
2069 packet.write_header(
2070 id,
2071 self.flags,
2072 question_count,
2073 answer_count,
2074 auth_count,
2075 addi_count,
2076 );
2077
2078 packet_list.push(packet);
2079 packet_list
2080 }
2081}
2082
2083#[derive(Debug)]
2085pub struct DnsIncoming {
2086 offset: usize,
2087 data: Vec<u8>,
2088 questions: Vec<DnsQuestion>,
2089 answers: Vec<DnsRecordBox>,
2090 authorities: Vec<DnsRecordBox>,
2091 additional: Vec<DnsRecordBox>,
2092 id: u16,
2093 flags: u16,
2094 num_questions: u16,
2095 num_answers: u16,
2096 num_authorities: u16,
2097 num_additionals: u16,
2098 interface_id: InterfaceId,
2099}
2100
2101impl DnsIncoming {
2102 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2103 let mut incoming = Self {
2104 offset: 0,
2105 data,
2106 questions: Vec::new(),
2107 answers: Vec::new(),
2108 authorities: Vec::new(),
2109 additional: Vec::new(),
2110 id: 0,
2111 flags: 0,
2112 num_questions: 0,
2113 num_answers: 0,
2114 num_authorities: 0,
2115 num_additionals: 0,
2116 interface_id,
2117 };
2118
2119 incoming.read_header()?;
2139 incoming.read_questions()?;
2140 incoming.read_answers()?;
2141 incoming.read_authorities()?;
2142 incoming.read_additional()?;
2143
2144 Ok(incoming)
2145 }
2146
2147 pub fn id(&self) -> u16 {
2148 self.id
2149 }
2150
2151 pub fn questions(&self) -> &[DnsQuestion] {
2152 &self.questions
2153 }
2154
2155 pub fn answers(&self) -> &[DnsRecordBox] {
2156 &self.answers
2157 }
2158
2159 pub fn authorities(&self) -> &[DnsRecordBox] {
2160 &self.authorities
2161 }
2162
2163 pub fn additionals(&self) -> &[DnsRecordBox] {
2164 &self.additional
2165 }
2166
2167 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2168 &mut self.answers
2169 }
2170
2171 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2172 &mut self.authorities
2173 }
2174
2175 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2176 &mut self.additional
2177 }
2178
2179 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2180 self.answers
2181 .into_iter()
2182 .chain(self.authorities)
2183 .chain(self.additional)
2184 }
2185
2186 pub fn num_additionals(&self) -> u16 {
2187 self.num_additionals
2188 }
2189
2190 pub fn num_authorities(&self) -> u16 {
2191 self.num_authorities
2192 }
2193
2194 pub fn num_questions(&self) -> u16 {
2195 self.num_questions
2196 }
2197
2198 pub const fn is_query(&self) -> bool {
2199 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2200 }
2201
2202 pub const fn is_response(&self) -> bool {
2203 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2204 }
2205
2206 fn read_header(&mut self) -> Result<()> {
2207 if self.data.len() < MSG_HEADER_LEN {
2208 return Err(e_fmt!(
2209 "DNS incoming: header is too short: {} bytes",
2210 self.data.len()
2211 ));
2212 }
2213
2214 let data = &self.data[0..];
2215 self.id = u16_from_be_slice(&data[..2]);
2216 self.flags = u16_from_be_slice(&data[2..4]);
2217 self.num_questions = u16_from_be_slice(&data[4..6]);
2218 self.num_answers = u16_from_be_slice(&data[6..8]);
2219 self.num_authorities = u16_from_be_slice(&data[8..10]);
2220 self.num_additionals = u16_from_be_slice(&data[10..12]);
2221
2222 self.offset = MSG_HEADER_LEN;
2223
2224 trace!(
2225 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2226 self.id,
2227 self.num_questions,
2228 self.num_answers,
2229 self.num_authorities,
2230 self.num_additionals
2231 );
2232 Ok(())
2233 }
2234
2235 fn read_questions(&mut self) -> Result<()> {
2236 trace!("read_questions: {}", &self.num_questions);
2237 for i in 0..self.num_questions {
2238 let name = self.read_name()?;
2239
2240 let data = &self.data[self.offset..];
2241 if data.len() < 4 {
2242 return Err(Error::Msg(format!(
2243 "DNS incoming: question idx {} too short: {}",
2244 i,
2245 data.len()
2246 )));
2247 }
2248 let ty = u16_from_be_slice(&data[..2]);
2249 let class = u16_from_be_slice(&data[2..4]);
2250 self.offset += 4;
2251
2252 let Some(rr_type) = RRType::from_u16(ty) else {
2253 return Err(Error::Msg(format!(
2254 "DNS incoming: question idx {i} qtype unknown: {ty}",
2255 )));
2256 };
2257
2258 self.questions.push(DnsQuestion {
2259 entry: DnsEntry::new(name, rr_type, class),
2260 });
2261 }
2262 Ok(())
2263 }
2264
2265 fn read_answers(&mut self) -> Result<()> {
2266 self.answers = self.read_rr_records(self.num_answers)?;
2267 Ok(())
2268 }
2269
2270 fn read_authorities(&mut self) -> Result<()> {
2271 self.authorities = self.read_rr_records(self.num_authorities)?;
2272 Ok(())
2273 }
2274
2275 fn read_additional(&mut self) -> Result<()> {
2276 self.additional = self.read_rr_records(self.num_additionals)?;
2277 Ok(())
2278 }
2279
2280 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2282 trace!("read_rr_records: {}", count);
2283 let mut rr_records = Vec::new();
2284
2285 const RR_HEADER_REMAIN: usize = 10;
2311
2312 for _ in 0..count {
2313 let name = self.read_name()?;
2314 let slice = &self.data[self.offset..];
2315
2316 if slice.len() < RR_HEADER_REMAIN {
2317 return Err(Error::Msg(format!(
2318 "read_others: RR '{}' is too short after name: {} bytes",
2319 &name,
2320 slice.len()
2321 )));
2322 }
2323
2324 let ty = u16_from_be_slice(&slice[..2]);
2325 let class = u16_from_be_slice(&slice[2..4]);
2326 let mut ttl = u32_from_be_slice(&slice[4..8]);
2327 if ttl == 0 && self.is_response() {
2328 ttl = 1;
2335 }
2336 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2337 self.offset += RR_HEADER_REMAIN;
2338 let next_offset = self.offset + rdata_len;
2339
2340 if next_offset > self.data.len() {
2342 return Err(Error::Msg(format!(
2343 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2344 self.data.len() - self.offset
2345 )));
2346 }
2347
2348 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2350 None => None,
2351
2352 Some(rr_type) => match rr_type {
2353 RRType::CNAME | RRType::PTR => {
2354 Some(DnsPointer::new(&name, rr_type, class, ttl, self.read_name()?).boxed())
2355 }
2356 RRType::TXT => {
2357 Some(DnsTxt::new(&name, class, ttl, self.read_vec(rdata_len)?).boxed())
2358 }
2359 RRType::SRV => Some(
2360 DnsSrv::new(
2361 &name,
2362 class,
2363 ttl,
2364 self.read_u16()?,
2365 self.read_u16()?,
2366 self.read_u16()?,
2367 self.read_name()?,
2368 )
2369 .boxed(),
2370 ),
2371 RRType::HINFO => Some(
2372 DnsHostInfo::new(
2373 &name,
2374 rr_type,
2375 class,
2376 ttl,
2377 self.read_char_string()?,
2378 self.read_char_string()?,
2379 )
2380 .boxed(),
2381 ),
2382 RRType::A => Some(
2383 DnsAddress::new(
2384 &name,
2385 rr_type,
2386 class,
2387 ttl,
2388 self.read_ipv4()?.into(),
2389 self.interface_id.clone(),
2390 )
2391 .boxed(),
2392 ),
2393 RRType::AAAA => Some(
2394 DnsAddress::new(
2395 &name,
2396 rr_type,
2397 class,
2398 ttl,
2399 self.read_ipv6()?.into(),
2400 self.interface_id.clone(),
2401 )
2402 .boxed(),
2403 ),
2404 RRType::NSEC => Some(
2405 DnsNSec::new(
2406 &name,
2407 class,
2408 ttl,
2409 self.read_name()?,
2410 self.read_type_bitmap()?,
2411 )
2412 .boxed(),
2413 ),
2414 _ => None,
2415 },
2416 };
2417
2418 if let Some(record) = rec {
2419 trace!("read_rr_records: {:?}", &record);
2420 rr_records.push(record);
2421 } else {
2422 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2423 self.offset += rdata_len;
2424 }
2425
2426 if self.offset != next_offset {
2428 return Err(Error::Msg(format!(
2429 "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}",
2430 ty, self.offset, next_offset,
2431 )));
2432 }
2433 }
2434
2435 Ok(rr_records)
2436 }
2437
2438 fn read_char_string(&mut self) -> Result<String> {
2439 let length = self.data[self.offset];
2440 self.offset += 1;
2441 self.read_string(length as usize)
2442 }
2443
2444 fn read_u16(&mut self) -> Result<u16> {
2445 let slice = &self.data[self.offset..];
2446 if slice.len() < U16_SIZE {
2447 return Err(Error::Msg(format!(
2448 "read_u16: slice len is only {}",
2449 slice.len()
2450 )));
2451 }
2452 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2453 self.offset += U16_SIZE;
2454 Ok(num)
2455 }
2456
2457 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2459 if self.data.len() < self.offset + 2 {
2468 return Err(Error::Msg(format!(
2469 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2470 self.data.len(),
2471 self.offset
2472 )));
2473 }
2474
2475 let block_num = self.data[self.offset];
2476 self.offset += 1;
2477 if block_num != 0 {
2478 return Err(Error::Msg(format!(
2479 "NSEC block number is not 0: {block_num}"
2480 )));
2481 }
2482
2483 let block_len = self.data[self.offset] as usize;
2484 if !(1..=32).contains(&block_len) {
2485 return Err(Error::Msg(format!(
2486 "NSEC block length must be in the range 1-32: {block_len}"
2487 )));
2488 }
2489 self.offset += 1;
2490
2491 let end = self.offset + block_len;
2492 if end > self.data.len() {
2493 return Err(Error::Msg(format!(
2494 "NSEC block overflow: {} over RData len {}",
2495 end,
2496 self.data.len()
2497 )));
2498 }
2499 let bitmap = self.data[self.offset..end].to_vec();
2500 self.offset += block_len;
2501
2502 Ok(bitmap)
2503 }
2504
2505 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2506 if self.data.len() < self.offset + length {
2507 return Err(e_fmt!(
2508 "DNS Incoming: not enough data to read a chunk of data"
2509 ));
2510 }
2511
2512 let v = self.data[self.offset..self.offset + length].to_vec();
2513 self.offset += length;
2514 Ok(v)
2515 }
2516
2517 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2518 if self.data.len() < self.offset + 4 {
2519 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2520 }
2521
2522 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2523 .try_into()
2524 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2525 self.offset += bytes.len();
2526 Ok(Ipv4Addr::from(bytes))
2527 }
2528
2529 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2530 if self.data.len() < self.offset + 16 {
2531 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2532 }
2533
2534 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2535 .try_into()
2536 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2537 self.offset += bytes.len();
2538 Ok(Ipv6Addr::from(bytes))
2539 }
2540
2541 fn read_string(&mut self, length: usize) -> Result<String> {
2542 if self.data.len() < self.offset + length {
2543 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2544 }
2545
2546 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2547 .map_err(|e| Error::Msg(e.to_string()))?;
2548 self.offset += length;
2549 Ok(s.to_string())
2550 }
2551
2552 fn read_name(&mut self) -> Result<String> {
2557 let data = &self.data[..];
2558 let start_offset = self.offset;
2559 let mut offset = start_offset;
2560 let mut name = "".to_string();
2561 let mut at_end = false;
2562
2563 loop {
2574 if offset >= data.len() {
2575 return Err(Error::Msg(format!(
2576 "read_name: offset: {} data len {}. DnsIncoming: {:?}",
2577 offset,
2578 data.len(),
2579 self
2580 )));
2581 }
2582 let length = data[offset];
2583
2584 if length == 0 {
2588 if !at_end {
2589 self.offset = offset + 1;
2590 }
2591 break; }
2593
2594 match length & 0xC0 {
2596 0x00 => {
2597 offset += 1;
2599 let ending = offset + length as usize;
2600
2601 if ending > data.len() {
2603 return Err(Error::Msg(format!(
2604 "read_name: ending {} exceeds data length {}",
2605 ending,
2606 data.len()
2607 )));
2608 }
2609
2610 name += str::from_utf8(&data[offset..ending])
2611 .map_err(|e| Error::Msg(format!("read_name: from_utf8: {e}")))?;
2612 name += ".";
2613 offset += length as usize;
2614 }
2615 0xC0 => {
2616 let slice = &data[offset..];
2619 if slice.len() < U16_SIZE {
2620 return Err(Error::Msg(format!(
2621 "read_name: u16 slice len is only {}",
2622 slice.len()
2623 )));
2624 }
2625 let pointer = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2626 if pointer >= start_offset {
2627 return Err(Error::Msg(format!(
2629 "Invalid name compression: pointer {} must be less than the start offset {}",
2630 &pointer, &start_offset
2631 )));
2632 }
2633
2634 if !at_end {
2636 self.offset = offset + U16_SIZE;
2637 at_end = true;
2638 }
2639 offset = pointer;
2640 }
2641 _ => {
2642 return Err(Error::Msg(format!(
2643 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2644 length,
2645 offset,
2646 &data[..offset]
2647 )));
2648 }
2649 };
2650 }
2651
2652 Ok(name)
2653 }
2654}
2655
2656const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2657 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2658 u16::from_be_bytes(u8_array)
2659}
2660
2661const fn u32_from_be_slice(s: &[u8]) -> u32 {
2662 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2663 u32::from_be_bytes(u8_array)
2664}
2665
2666const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2669 created + (ttl as u64 * percent as u64 * 10)
2672}
2673
2674#[cfg(test)]
2675mod tests {
2676 use super::{
2677 DnsAddress, DnsHostInfo, DnsIncoming, DnsOutgoing, DnsPointer, DnsTxt, RRType,
2678 CLASS_CACHE_FLUSH, CLASS_IN, MSG_HEADER_LEN,
2679 };
2680 use crate::InterfaceId;
2681 use std::collections::HashMap;
2682 use std::net::{IpAddr, Ipv4Addr};
2683
2684 #[test]
2685 fn test_dns_outgoing_serialization_empty() {
2686 let out = DnsOutgoing::new(0);
2687 let packets = out.to_packets();
2688 assert_eq!(packets.len(), 1);
2689 assert_eq!(packets[0].as_bytes(), &[0; 12]);
2690 let expected_names = HashMap::new();
2691 assert_eq!(&packets[0].names, &expected_names);
2692 }
2693
2694 #[test]
2695 fn test_dns_outgoing_serialization_question() {
2696 let mut out = DnsOutgoing::new(0);
2697 out.add_question("123.test", RRType::A);
2698 let packets = out.to_packets();
2699 assert_eq!(packets.len(), 1);
2700 assert_eq!(
2701 packets[0].as_bytes(),
2702 &[
2703 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,
2706 ]
2707 );
2708 let mut expected_names = HashMap::new();
2709 expected_names.insert("123.test".to_string(), 12);
2710 expected_names.insert("test".to_string(), 16);
2711 assert_eq!(&packets[0].names, &expected_names);
2712 }
2713
2714 #[test]
2715 fn test_dns_outgoing_serialization_question_with_authority() {
2716 let mut out = DnsOutgoing::new(0);
2717 out.add_question("123.test", RRType::ANY);
2718 out.add_authority(Box::new(DnsTxt::new(
2719 "124.test",
2720 CLASS_IN,
2721 0x00112233,
2722 b"help".to_vec(),
2723 )));
2724 out.add_authority(Box::new(DnsHostInfo::new(
2725 "124.test",
2726 RRType::CNAME,
2727 CLASS_IN,
2728 0x00112233,
2729 "arm".to_string(),
2730 "linux".to_string(),
2731 )));
2732 let packets = out.to_packets();
2733 assert_eq!(packets.len(), 1);
2734 assert_eq!(
2735 packets[0].as_bytes(),
2736 &[
2737 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,
2740 16, 0, 1, 0, 17, 34, 51, 0, 4, 104, 101, 108, 112, 192, 26, 0, 5, 0, 1, 0, 17, 34,
2741 51, 0, 8, 97, 114, 109, 108, 105, 110, 117, 120,
2742 ]
2743 );
2744 let mut expected_names = HashMap::new();
2745 expected_names.insert("123.test".to_string(), 12);
2746 expected_names.insert("test".to_string(), 16);
2747 expected_names.insert("124.test".to_string(), 26);
2748 assert_eq!(&packets[0].names, &expected_names);
2749 }
2750
2751 #[test]
2752 fn test_dns_outgoing_serialization_additional_answer() {
2753 let mut out = DnsOutgoing::new(0);
2754 out.add_additional_answer(DnsAddress::new(
2755 "test.local",
2756 RRType::A,
2757 CLASS_IN | CLASS_CACHE_FLUSH,
2758 0xdead_beef,
2759 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
2760 InterfaceId::default(),
2761 ));
2762 let packets = out.to_packets();
2763 assert_eq!(packets.len(), 1);
2764 assert_eq!(
2765 packets[0].as_bytes(),
2766 &[
2767 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,
2770 239, 0, 4, 127, 0, 0, 1,
2771 ]
2772 );
2773 let mut expected_names = HashMap::new();
2774 expected_names.insert("test.local".to_string(), 12);
2775 expected_names.insert("local".to_string(), 17);
2776 assert_eq!(&packets[0].names, &expected_names);
2777 }
2778
2779 #[test]
2780 fn test_dns_outgoing_serialization_answer_at_time() {
2781 let mut out = DnsOutgoing::new(0);
2782 out.add_answer_at_time(
2783 DnsPointer::new(
2784 "test",
2785 RRType::PTR,
2786 CLASS_IN,
2787 0xaaaa5555,
2788 "test-service".to_string(),
2789 ),
2790 0,
2791 );
2792 let packets = out.to_packets();
2793 assert_eq!(packets.len(), 1);
2794 assert_eq!(
2795 packets[0].as_bytes(),
2796 &[
2797 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,
2800 116, 45, 115, 101, 114, 118, 105, 99, 101, 0,
2801 ]
2802 );
2803
2804 let mut out = DnsOutgoing::new(0);
2805 out.add_answer_at_time(
2806 DnsPointer::new(
2807 "test",
2808 RRType::CNAME,
2809 CLASS_IN,
2810 0xaaaa5555,
2811 "test-service.local".to_string(),
2812 ),
2813 0,
2814 );
2815 out.add_answer_at_time(
2816 DnsPointer::new(
2817 "test",
2818 RRType::AAAA,
2819 CLASS_IN,
2820 0xffffffff,
2821 "test-service.local".to_string(),
2822 ),
2823 0,
2824 );
2825 let packets = out.to_packets();
2826 assert_eq!(packets.len(), 1);
2827 assert_eq!(
2828 packets[0].as_bytes(),
2829 &[
2830 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,
2833 116, 45, 115, 101, 114, 118, 105, 99, 101, 5, 108, 111, 99, 97, 108, 0, 192, 12, 0,
2834 28, 0, 1, 255, 255, 255, 255, 0, 2, 192, 28,
2835 ]
2836 );
2837 let mut expected_names = HashMap::new();
2838 expected_names.insert("test".to_string(), 12);
2839 expected_names.insert("test-service.local".to_string(), 28);
2840 expected_names.insert("local".to_string(), 41);
2841 assert_eq!(&packets[0].names, &expected_names);
2842 }
2843
2844 #[test]
2848 fn test_dns_outgoing_question_label_too_long() {
2849 let long_label = "a".repeat(64);
2850 let mut out = DnsOutgoing::new(0);
2851 out.add_question(&format!("{long_label}.local"), RRType::PTR);
2852 out.add_question("123.test", RRType::A);
2853
2854 let packets = out.to_packets();
2855 assert_eq!(packets.len(), 1);
2856 assert_eq!(
2857 packets[0].as_bytes(),
2858 &[
2859 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,
2862 ]
2863 );
2864
2865 let mut expected_names = HashMap::new();
2867 expected_names.insert("123.test".to_string(), 12);
2868 expected_names.insert("test".to_string(), 16);
2869 assert_eq!(&packets[0].names, &expected_names);
2870 }
2871
2872 #[test]
2875 fn test_dns_outgoing_record_label_too_long() {
2876 let long_label = "a".repeat(64);
2877 let mut out = DnsOutgoing::new(0);
2878 out.add_answer_at_time(
2879 DnsPointer::new(
2880 "_test._tcp.local.",
2881 RRType::PTR,
2882 CLASS_IN,
2883 0,
2884 format!("{long_label}._test._tcp.local."),
2885 ),
2886 0,
2887 );
2888 out.add_answer_at_time(
2889 DnsPointer::new(
2890 "_test._tcp.local.",
2891 RRType::PTR,
2892 CLASS_IN,
2893 0,
2894 "ok._test._tcp.local.".to_string(),
2895 ),
2896 0,
2897 );
2898
2899 let packets = out.to_packets();
2900 assert_eq!(packets.len(), 1);
2901
2902 assert_eq!(&packets[0].as_bytes()[6..8], &[0, 1]);
2904
2905 let incoming = DnsIncoming::new(
2907 packets[0].as_bytes().to_vec(),
2908 InterfaceId {
2909 name: "test".to_string(),
2910 index: 1,
2911 },
2912 )
2913 .unwrap();
2914 assert_eq!(incoming.answers().len(), 1);
2915 }
2916
2917 #[test]
2922 fn test_incoming_name_with_merged_labels_does_not_panic() {
2923 let mut data: Vec<u8> = vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
2925 data.push(63);
2926 data.extend(vec![b'a'; 62]);
2927 data.push(b'\\');
2928 data.push(63);
2929 data.extend(vec![b'b'; 63]);
2930 data.push(0);
2931 data.extend([0, 12, 0, 1]); let incoming = DnsIncoming::new(
2934 data,
2935 InterfaceId {
2936 name: "test".to_string(),
2937 index: 1,
2938 },
2939 )
2940 .unwrap();
2941 let name = incoming.questions()[0].entry.name.clone();
2942
2943 assert!(name.starts_with("aaa"));
2945 assert!(name.contains("\\.bbb"));
2946
2947 let mut out = DnsOutgoing::new(0);
2949 out.add_question(&name, RRType::PTR);
2950 let packets = out.to_packets();
2951 assert_eq!(packets.len(), 1);
2952 assert_eq!(packets[0].as_bytes(), &[0; MSG_HEADER_LEN]);
2953 }
2954}