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(crate) const MAX_PKT_ABSOLUTE_IPV4: usize = 8972;
293
294pub(crate) const MAX_PKT_ABSOLUTE_IPV6: usize = 8952;
299
300pub(crate) const fn max_pkt_absolute(is_ipv4: bool) -> usize {
302 if is_ipv4 {
303 MAX_PKT_ABSOLUTE_IPV4
304 } else {
305 MAX_PKT_ABSOLUTE_IPV6
306 }
307}
308
309pub const MAX_PKT_DEFAULT: usize = 1452;
316
317const MSG_HEADER_LEN: usize = 12;
318
319const MAX_LABEL_BYTES: usize = 63;
323
324const MAX_NAME_BYTES: usize = 255;
328
329#[derive(Debug, PartialEq, Eq)]
334pub enum WriteError {
335 NameTooLong,
337
338 PacketFull,
340}
341
342type WriteResult = core::result::Result<(), WriteError>;
344
345pub const FLAGS_QR_MASK: u16 = 0x8000; pub const FLAGS_QR_QUERY: u16 = 0x0000;
357
358pub const FLAGS_QR_RESPONSE: u16 = 0x8000;
360
361pub const FLAGS_AA: u16 = 0x0400;
363
364pub const FLAGS_TC: u16 = 0x0200;
375
376pub type DnsRecordBox = Box<dyn DnsRecordExt>;
378
379impl Clone for DnsRecordBox {
380 fn clone(&self) -> Self {
381 self.clone_box()
382 }
383}
384
385const U16_SIZE: usize = 2;
386
387#[inline]
389pub const fn ip_address_rr_type(address: &IpAddr) -> RRType {
390 match address {
391 IpAddr::V4(_) => RRType::A,
392 IpAddr::V6(_) => RRType::AAAA,
393 }
394}
395
396#[derive(Eq, PartialEq, Debug, Clone)]
397pub struct DnsEntry {
398 pub(crate) name: String, pub(crate) ty: RRType,
400 class: u16,
401 cache_flush: bool,
402}
403
404impl DnsEntry {
405 const fn new(name: String, ty: RRType, class: u16) -> Self {
406 Self {
407 name,
408 ty,
409 class: class & CLASS_MASK,
410 cache_flush: (class & CLASS_CACHE_FLUSH) != 0,
411 }
412 }
413}
414
415pub trait DnsEntryExt: fmt::Debug {
417 fn entry_name(&self) -> &str;
418
419 fn entry_type(&self) -> RRType;
420}
421
422#[derive(Debug)]
424pub struct DnsQuestion {
425 pub(crate) entry: DnsEntry,
426}
427
428impl DnsEntryExt for DnsQuestion {
429 fn entry_name(&self) -> &str {
430 &self.entry.name
431 }
432
433 fn entry_type(&self) -> RRType {
434 self.entry.ty
435 }
436}
437
438#[derive(Debug, Clone)]
442pub struct DnsRecord {
443 pub(crate) entry: DnsEntry,
444 ttl: u32, created: u64, expires: u64, refresh: u64, new_name: Option<String>,
454}
455
456impl DnsRecord {
457 fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self {
458 let created = current_time_millis();
459
460 let refresh = get_expiration_time(created, ttl, 80);
464
465 let expires = get_expiration_time(created, ttl, 100);
466
467 Self {
468 entry: DnsEntry::new(name.to_string(), ty, class),
469 ttl,
470 created,
471 expires,
472 refresh,
473 new_name: None,
474 }
475 }
476
477 pub const fn get_ttl(&self) -> u32 {
478 self.ttl
479 }
480
481 pub const fn get_expire_time(&self) -> u64 {
482 self.expires
483 }
484
485 pub const fn get_refresh_time(&self) -> u64 {
486 self.refresh
487 }
488
489 pub const fn is_expired(&self, now: u64) -> bool {
490 now >= self.expires
491 }
492
493 pub const fn expires_soon(&self, now: u64) -> bool {
497 now + 1000 >= self.expires
498 }
499
500 pub const fn refresh_due(&self, now: u64) -> bool {
501 now >= self.refresh
502 }
503
504 pub fn halflife_passed(&self, now: u64) -> bool {
506 let halflife = get_expiration_time(self.created, self.ttl, 50);
507 now > halflife
508 }
509
510 pub fn is_unique(&self) -> bool {
511 self.entry.cache_flush
512 }
513
514 pub fn refresh_no_more(&mut self) {
517 self.refresh = get_expiration_time(self.created, self.ttl, 100);
518 }
519
520 pub fn refresh_maybe(&mut self, now: u64) -> bool {
522 if self.is_expired(now) || !self.refresh_due(now) {
523 return false;
524 }
525
526 trace!(
527 "{} qtype {} is due to refresh",
528 &self.entry.name,
529 self.entry.ty
530 );
531
532 if self.refresh == get_expiration_time(self.created, self.ttl, 80) {
539 self.refresh = get_expiration_time(self.created, self.ttl, 85);
540 } else if self.refresh == get_expiration_time(self.created, self.ttl, 85) {
541 self.refresh = get_expiration_time(self.created, self.ttl, 90);
542 } else if self.refresh == get_expiration_time(self.created, self.ttl, 90) {
543 self.refresh = get_expiration_time(self.created, self.ttl, 95);
544 } else {
545 self.refresh_no_more();
546 }
547
548 true
549 }
550
551 fn get_remaining_ttl(&self, now: u64) -> u32 {
553 let remaining_millis = get_expiration_time(self.created, self.ttl, 100) - now;
554 cmp::max(0, remaining_millis / 1000) as u32
555 }
556
557 pub const fn get_created(&self) -> u64 {
559 self.created
560 }
561
562 fn set_expire(&mut self, expire_at: u64) {
564 self.expires = expire_at;
565 }
566
567 fn reset_ttl(&mut self, other: &Self) {
568 self.ttl = other.ttl;
569 self.created = other.created;
570 self.expires = get_expiration_time(self.created, self.ttl, 100);
571 self.refresh = if self.ttl > 1 {
572 get_expiration_time(self.created, self.ttl, 80)
573 } else {
574 self.expires
577 };
578 }
579
580 pub fn update_ttl(&mut self, now: u64) {
582 if now > self.created {
583 let elapsed = now - self.created;
584 self.ttl -= (elapsed / 1000) as u32;
585 }
586 }
587
588 pub fn set_new_name(&mut self, new_name: String) {
589 if new_name == self.entry.name {
590 self.new_name = None;
591 } else {
592 self.new_name = Some(new_name);
593 }
594 }
595
596 pub fn get_new_name(&self) -> Option<&str> {
597 self.new_name.as_deref()
598 }
599
600 pub(crate) fn get_name(&self) -> &str {
602 self.new_name.as_deref().unwrap_or(&self.entry.name)
603 }
604
605 pub fn get_original_name(&self) -> &str {
606 &self.entry.name
607 }
608}
609
610impl PartialEq for DnsRecord {
611 fn eq(&self, other: &Self) -> bool {
612 self.entry == other.entry
613 }
614}
615
616pub trait DnsRecordExt: fmt::Debug {
618 fn get_record(&self) -> &DnsRecord;
619 fn get_record_mut(&mut self) -> &mut DnsRecord;
620 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult;
622 fn any(&self) -> &dyn Any;
623
624 fn matches(&self, other: &dyn DnsRecordExt) -> bool;
626
627 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool;
629
630 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering;
633
634 fn compare(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
636 match self.get_class().cmp(&other.get_class()) {
650 cmp::Ordering::Equal => match self.get_type().cmp(&other.get_type()) {
651 cmp::Ordering::Equal => self.compare_rdata(other),
652 not_equal => not_equal,
653 },
654 not_equal => not_equal,
655 }
656 }
657
658 fn rdata_print(&self) -> String;
660
661 fn get_class(&self) -> u16 {
663 self.get_record().entry.class
664 }
665
666 fn get_cache_flush(&self) -> bool {
667 self.get_record().entry.cache_flush
668 }
669
670 fn get_name(&self) -> &str {
672 self.get_record().get_name()
673 }
674
675 fn get_type(&self) -> RRType {
676 self.get_record().entry.ty
677 }
678
679 fn reset_ttl(&mut self, other: &dyn DnsRecordExt) {
682 self.get_record_mut().reset_ttl(other.get_record());
683 }
684
685 fn get_created(&self) -> u64 {
686 self.get_record().get_created()
687 }
688
689 fn get_expire(&self) -> u64 {
690 self.get_record().get_expire_time()
691 }
692
693 fn set_expire(&mut self, expire_at: u64) {
694 self.get_record_mut().set_expire(expire_at);
695 }
696
697 fn set_expire_sooner(&mut self, expire_at: u64) {
699 if expire_at < self.get_expire() {
700 self.get_record_mut().set_expire(expire_at);
701 }
702 }
703
704 fn expires_soon(&self, now: u64) -> bool {
706 self.get_record().expires_soon(now)
707 }
708
709 fn updated_refresh_time(&mut self, now: u64) -> Option<u64> {
712 if self.get_record_mut().refresh_maybe(now) {
713 Some(self.get_record().get_refresh_time())
714 } else {
715 None
716 }
717 }
718
719 fn suppressed_by_answer(&self, other: &dyn DnsRecordExt) -> bool {
722 self.matches(other) && (other.get_record().ttl > self.get_record().ttl / 2)
723 }
724
725 fn suppressed_by(&self, msg: &DnsIncoming) -> bool {
727 for answer in msg.answers.iter() {
728 if self.suppressed_by_answer(answer.as_ref()) {
729 return true;
730 }
731 }
732 false
733 }
734
735 fn clone_box(&self) -> DnsRecordBox;
736
737 fn boxed(self) -> DnsRecordBox;
738}
739
740#[derive(Debug, Clone)]
742pub(crate) struct DnsAddress {
743 pub(crate) record: DnsRecord,
744 address: IpAddr,
745 pub(crate) interface_id: InterfaceId,
746}
747
748impl DnsAddress {
749 pub fn new(
750 name: &str,
751 ty: RRType,
752 class: u16,
753 ttl: u32,
754 address: IpAddr,
755 interface_id: InterfaceId,
756 ) -> Self {
757 let record = DnsRecord::new(name, ty, class, ttl);
758 Self {
759 record,
760 address,
761 interface_id,
762 }
763 }
764
765 pub fn address(&self) -> ScopedIp {
766 match self.address {
767 IpAddr::V4(v4) => ScopedIp::V4(ScopedIpV4 {
768 addr: v4,
769 interface_ids: vec![self.interface_id.clone()],
770 }),
771 IpAddr::V6(v6) => ScopedIp::V6(ScopedIpV6 {
772 addr: v6,
773 scope_id: self.interface_id.clone(),
774 }),
775 }
776 }
777}
778
779impl DnsRecordExt for DnsAddress {
780 fn get_record(&self) -> &DnsRecord {
781 &self.record
782 }
783
784 fn get_record_mut(&mut self) -> &mut DnsRecord {
785 &mut self.record
786 }
787
788 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
789 match self.address {
790 IpAddr::V4(addr) => packet.write_bytes(addr.octets().as_ref()),
791 IpAddr::V6(addr) => packet.write_bytes(addr.octets().as_ref()),
792 };
793 Ok(())
794 }
795
796 fn any(&self) -> &dyn Any {
797 self
798 }
799
800 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
801 if let Some(other_a) = other.any().downcast_ref::<Self>() {
802 return self.address == other_a.address
803 && self.record.entry == other_a.record.entry
804 && self.interface_id == other_a.interface_id;
805 }
806 false
807 }
808
809 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
810 if let Some(other_a) = other.any().downcast_ref::<Self>() {
811 return self.address == other_a.address;
812 }
813 false
814 }
815
816 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
817 if let Some(other_a) = other.any().downcast_ref::<Self>() {
818 self.address.cmp(&other_a.address)
819 } else {
820 cmp::Ordering::Greater
821 }
822 }
823
824 fn rdata_print(&self) -> String {
825 format!("{}", self.address)
826 }
827
828 fn clone_box(&self) -> DnsRecordBox {
829 Box::new(self.clone())
830 }
831
832 fn boxed(self) -> DnsRecordBox {
833 Box::new(self)
834 }
835}
836
837#[derive(Debug, Clone)]
839pub struct DnsPointer {
840 record: DnsRecord,
841 alias: String, }
843
844impl DnsPointer {
845 pub fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self {
846 let record = DnsRecord::new(name, ty, class, ttl);
847 Self { record, alias }
848 }
849
850 pub fn alias(&self) -> &str {
851 &self.alias
852 }
853}
854
855impl DnsRecordExt for DnsPointer {
856 fn get_record(&self) -> &DnsRecord {
857 &self.record
858 }
859
860 fn get_record_mut(&mut self) -> &mut DnsRecord {
861 &mut self.record
862 }
863
864 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
865 packet.write_name(&self.alias)
866 }
867
868 fn any(&self) -> &dyn Any {
869 self
870 }
871
872 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
873 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
874 return self.alias == other_ptr.alias && self.record.entry == other_ptr.record.entry;
875 }
876 false
877 }
878
879 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
880 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
881 return self.alias == other_ptr.alias;
882 }
883 false
884 }
885
886 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
887 if let Some(other_ptr) = other.any().downcast_ref::<Self>() {
888 self.alias.cmp(&other_ptr.alias)
889 } else {
890 cmp::Ordering::Greater
891 }
892 }
893
894 fn rdata_print(&self) -> String {
895 self.alias.clone()
896 }
897
898 fn clone_box(&self) -> DnsRecordBox {
899 Box::new(self.clone())
900 }
901
902 fn boxed(self) -> DnsRecordBox {
903 Box::new(self)
904 }
905}
906
907#[derive(Debug, Clone)]
909pub struct DnsSrv {
910 pub(crate) record: DnsRecord,
911 pub(crate) priority: u16, pub(crate) weight: u16, host: String,
914 port: u16,
915}
916
917impl DnsSrv {
918 pub fn new(
919 name: &str,
920 class: u16,
921 ttl: u32,
922 priority: u16,
923 weight: u16,
924 port: u16,
925 host: String,
926 ) -> Self {
927 let record = DnsRecord::new(name, RRType::SRV, class, ttl);
928 Self {
929 record,
930 priority,
931 weight,
932 host,
933 port,
934 }
935 }
936
937 pub fn host(&self) -> &str {
938 &self.host
939 }
940
941 pub fn port(&self) -> u16 {
942 self.port
943 }
944
945 pub fn set_host(&mut self, host: String) {
946 self.host = host;
947 }
948}
949
950impl DnsRecordExt for DnsSrv {
951 fn get_record(&self) -> &DnsRecord {
952 &self.record
953 }
954
955 fn get_record_mut(&mut self) -> &mut DnsRecord {
956 &mut self.record
957 }
958
959 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
960 packet.write_short(self.priority);
961 packet.write_short(self.weight);
962 packet.write_short(self.port);
963 packet.write_name(&self.host)
964 }
965
966 fn any(&self) -> &dyn Any {
967 self
968 }
969
970 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
971 if let Some(other_svc) = other.any().downcast_ref::<Self>() {
972 return self.host == other_svc.host
973 && self.port == other_svc.port
974 && self.weight == other_svc.weight
975 && self.priority == other_svc.priority
976 && self.record.entry == other_svc.record.entry;
977 }
978 false
979 }
980
981 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
982 if let Some(other_srv) = other.any().downcast_ref::<Self>() {
983 return self.host == other_srv.host
984 && self.port == other_srv.port
985 && self.weight == other_srv.weight
986 && self.priority == other_srv.priority;
987 }
988 false
989 }
990
991 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
992 let Some(other_srv) = other.any().downcast_ref::<Self>() else {
993 return cmp::Ordering::Greater;
994 };
995
996 match self
998 .priority
999 .to_be_bytes()
1000 .cmp(&other_srv.priority.to_be_bytes())
1001 {
1002 cmp::Ordering::Equal => {
1003 match self
1005 .weight
1006 .to_be_bytes()
1007 .cmp(&other_srv.weight.to_be_bytes())
1008 {
1009 cmp::Ordering::Equal => {
1010 match self.port.to_be_bytes().cmp(&other_srv.port.to_be_bytes()) {
1012 cmp::Ordering::Equal => self.host.cmp(&other_srv.host),
1013 not_equal => not_equal,
1014 }
1015 }
1016 not_equal => not_equal,
1017 }
1018 }
1019 not_equal => not_equal,
1020 }
1021 }
1022
1023 fn rdata_print(&self) -> String {
1024 format!(
1025 "priority: {}, weight: {}, port: {}, host: {}",
1026 self.priority, self.weight, self.port, self.host
1027 )
1028 }
1029
1030 fn clone_box(&self) -> DnsRecordBox {
1031 Box::new(self.clone())
1032 }
1033
1034 fn boxed(self) -> DnsRecordBox {
1035 Box::new(self)
1036 }
1037}
1038
1039#[derive(Clone)]
1054pub struct DnsTxt {
1055 pub(crate) record: DnsRecord,
1056 text: Vec<u8>,
1057}
1058
1059impl DnsTxt {
1060 pub fn new(name: &str, class: u16, ttl: u32, text: Vec<u8>) -> Self {
1061 let record = DnsRecord::new(name, RRType::TXT, class, ttl);
1062 Self { record, text }
1063 }
1064
1065 pub fn text(&self) -> &[u8] {
1066 &self.text
1067 }
1068}
1069
1070impl DnsRecordExt for DnsTxt {
1071 fn get_record(&self) -> &DnsRecord {
1072 &self.record
1073 }
1074
1075 fn get_record_mut(&mut self) -> &mut DnsRecord {
1076 &mut self.record
1077 }
1078
1079 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1080 packet.write_bytes(&self.text);
1081 Ok(())
1082 }
1083
1084 fn any(&self) -> &dyn Any {
1085 self
1086 }
1087
1088 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1089 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1090 return self.text == other_txt.text && self.record.entry == other_txt.record.entry;
1091 }
1092 false
1093 }
1094
1095 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1096 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1097 return self.text == other_txt.text;
1098 }
1099 false
1100 }
1101
1102 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1103 if let Some(other_txt) = other.any().downcast_ref::<Self>() {
1104 self.text.cmp(&other_txt.text)
1105 } else {
1106 cmp::Ordering::Greater
1107 }
1108 }
1109
1110 fn rdata_print(&self) -> String {
1111 format!("{:?}", decode_txt(&self.text))
1112 }
1113
1114 fn clone_box(&self) -> DnsRecordBox {
1115 Box::new(self.clone())
1116 }
1117
1118 fn boxed(self) -> DnsRecordBox {
1119 Box::new(self)
1120 }
1121}
1122
1123impl fmt::Debug for DnsTxt {
1124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125 let properties = decode_txt(&self.text);
1126 write!(
1127 f,
1128 "DnsTxt {{ record: {:?}, text: {:?} }}",
1129 self.record, properties
1130 )
1131 }
1132}
1133
1134#[derive(Debug, Clone)]
1136struct DnsHostInfo {
1137 record: DnsRecord,
1138 cpu: String,
1139 os: String,
1140}
1141
1142impl DnsHostInfo {
1143 fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self {
1144 let record = DnsRecord::new(name, ty, class, ttl);
1145 Self { record, cpu, os }
1146 }
1147}
1148
1149impl DnsRecordExt for DnsHostInfo {
1150 fn get_record(&self) -> &DnsRecord {
1151 &self.record
1152 }
1153
1154 fn get_record_mut(&mut self) -> &mut DnsRecord {
1155 &mut self.record
1156 }
1157
1158 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1159 debug!("Writing HInfo: cpu {} os {}", &self.cpu, &self.os);
1160 packet.write_bytes(self.cpu.as_bytes());
1161 packet.write_bytes(self.os.as_bytes());
1162 Ok(())
1163 }
1164
1165 fn any(&self) -> &dyn Any {
1166 self
1167 }
1168
1169 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1170 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1171 return self.cpu == other_hinfo.cpu
1172 && self.os == other_hinfo.os
1173 && self.record.entry == other_hinfo.record.entry;
1174 }
1175 false
1176 }
1177
1178 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1179 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1180 return self.cpu == other_hinfo.cpu && self.os == other_hinfo.os;
1181 }
1182 false
1183 }
1184
1185 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1186 if let Some(other_hinfo) = other.any().downcast_ref::<Self>() {
1187 match self.cpu.cmp(&other_hinfo.cpu) {
1188 cmp::Ordering::Equal => self.os.cmp(&other_hinfo.os),
1189 ordering => ordering,
1190 }
1191 } else {
1192 cmp::Ordering::Greater
1193 }
1194 }
1195
1196 fn rdata_print(&self) -> String {
1197 format!("cpu: {}, os: {}", self.cpu, self.os)
1198 }
1199
1200 fn clone_box(&self) -> DnsRecordBox {
1201 Box::new(self.clone())
1202 }
1203
1204 fn boxed(self) -> DnsRecordBox {
1205 Box::new(self)
1206 }
1207}
1208
1209#[derive(Debug, Clone)]
1215pub struct DnsNSec {
1216 record: DnsRecord,
1217 next_domain: String,
1218 type_bitmap: Vec<u8>,
1219}
1220
1221impl DnsNSec {
1222 pub fn new(
1223 name: &str,
1224 class: u16,
1225 ttl: u32,
1226 next_domain: String,
1227 type_bitmap: Vec<u8>,
1228 ) -> Self {
1229 let record = DnsRecord::new(name, RRType::NSEC, class, ttl);
1230 Self {
1231 record,
1232 next_domain,
1233 type_bitmap,
1234 }
1235 }
1236
1237 pub fn _types(&self) -> Vec<u16> {
1239 let mut bit_num = 0;
1248 let mut results = Vec::new();
1249
1250 for byte in self.type_bitmap.iter() {
1251 let mut bit_mask: u8 = 0x80; for _ in 0..8 {
1255 if (byte & bit_mask) != 0 {
1256 results.push(bit_num);
1257 }
1258 bit_num += 1;
1259 bit_mask >>= 1; }
1261 }
1262 results
1263 }
1264}
1265
1266impl DnsRecordExt for DnsNSec {
1267 fn get_record(&self) -> &DnsRecord {
1268 &self.record
1269 }
1270
1271 fn get_record_mut(&mut self) -> &mut DnsRecord {
1272 &mut self.record
1273 }
1274
1275 fn write(&self, packet: &mut DnsOutPacket) -> WriteResult {
1276 packet.write_bytes(self.next_domain.as_bytes());
1277 packet.write_bytes(&self.type_bitmap);
1278 Ok(())
1279 }
1280
1281 fn any(&self) -> &dyn Any {
1282 self
1283 }
1284
1285 fn matches(&self, other: &dyn DnsRecordExt) -> bool {
1286 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1287 return self.next_domain == other_record.next_domain
1288 && self.type_bitmap == other_record.type_bitmap
1289 && self.record.entry == other_record.record.entry;
1290 }
1291 false
1292 }
1293
1294 fn rrdata_match(&self, other: &dyn DnsRecordExt) -> bool {
1295 if let Some(other_record) = other.any().downcast_ref::<Self>() {
1296 return self.next_domain == other_record.next_domain
1297 && self.type_bitmap == other_record.type_bitmap;
1298 }
1299 false
1300 }
1301
1302 fn compare_rdata(&self, other: &dyn DnsRecordExt) -> cmp::Ordering {
1303 if let Some(other_nsec) = other.any().downcast_ref::<Self>() {
1304 match self.next_domain.cmp(&other_nsec.next_domain) {
1305 cmp::Ordering::Equal => self.type_bitmap.cmp(&other_nsec.type_bitmap),
1306 ordering => ordering,
1307 }
1308 } else {
1309 cmp::Ordering::Greater
1310 }
1311 }
1312
1313 fn rdata_print(&self) -> String {
1314 format!(
1315 "next_domain: {}, type_bitmap len: {}",
1316 self.next_domain,
1317 self.type_bitmap.len()
1318 )
1319 }
1320
1321 fn clone_box(&self) -> DnsRecordBox {
1322 Box::new(self.clone())
1323 }
1324
1325 fn boxed(self) -> DnsRecordBox {
1326 Box::new(self)
1327 }
1328}
1329
1330#[derive(Clone, Copy, Debug)]
1332enum Section {
1333 Question,
1334 Answer,
1335 Authority,
1336 Additional,
1337}
1338
1339pub struct DnsOutPacket {
1341 data: Vec<u8>,
1343
1344 names: HashMap<String, u16>,
1346
1347 max_size: usize,
1349
1350 question_count: u16,
1352 answer_count: u16,
1353 auth_count: u16,
1354 addi_count: u16,
1355}
1356
1357impl DnsOutPacket {
1358 fn new(max_size: usize) -> Self {
1359 Self {
1360 data: vec![0; MSG_HEADER_LEN],
1361 names: HashMap::new(),
1362 max_size,
1363 question_count: 0,
1364 answer_count: 0,
1365 auth_count: 0,
1366 addi_count: 0,
1367 }
1368 }
1369
1370 pub fn size(&self) -> usize {
1371 self.data.len()
1372 }
1373
1374 pub fn as_bytes(&self) -> &[u8] {
1375 &self.data
1376 }
1377
1378 fn is_empty(&self) -> bool {
1380 self.question_count == 0
1381 && self.answer_count == 0
1382 && self.auth_count == 0
1383 && self.addi_count == 0
1384 }
1385
1386 fn bump(&mut self, section: Section) {
1388 match section {
1389 Section::Question => self.question_count += 1,
1390 Section::Answer => self.answer_count += 1,
1391 Section::Authority => self.auth_count += 1,
1392 Section::Additional => self.addi_count += 1,
1393 }
1394 }
1395
1396 fn write_question(&mut self, question: &DnsQuestion) -> WriteResult {
1397 let start_size = self.size();
1398
1399 self.write_name(&question.entry.name).map_err(|e| {
1400 self.rollback(start_size);
1401 e
1402 })?;
1403 self.write_short(question.entry.ty as u16);
1404 self.write_short(question.entry.class);
1405
1406 if self.size() > self.max_size {
1407 self.rollback(start_size);
1408 return Err(WriteError::PacketFull);
1409 }
1410
1411 Ok(())
1412 }
1413
1414 fn rollback(&mut self, start_size: usize) {
1417 self.data.truncate(start_size);
1418 self.names
1419 .retain(|_, offset| (*offset as usize) < start_size);
1420 }
1421
1422 fn write_record(&mut self, record_ext: &dyn DnsRecordExt, now: u64) -> WriteResult {
1426 let start_size = self.size();
1427
1428 let record = record_ext.get_record();
1429 self.write_name(record.get_name())?;
1430 self.write_short(record.entry.ty as u16);
1431 if record.entry.cache_flush {
1432 self.write_short(record.entry.class | CLASS_CACHE_FLUSH);
1434 } else {
1435 self.write_short(record.entry.class);
1436 }
1437
1438 if now == 0 {
1439 self.write_u32(record.ttl);
1440 } else {
1441 self.write_u32(record.get_remaining_ttl(now));
1442 }
1443
1444 self.write_short(0);
1446 let record_offset = self.size();
1447
1448 if let Err(e) = record_ext.write(self) {
1449 self.rollback(start_size);
1450 return Err(e);
1451 }
1452
1453 self.set_short_at(record_offset - 2, (self.size() - record_offset) as u16);
1454
1455 if self.size() > self.max_size {
1456 self.rollback(start_size);
1457 return Err(WriteError::PacketFull);
1458 }
1459
1460 Ok(())
1461 }
1462
1463 fn set_short_at(&mut self, index: usize, value: u16) {
1464 self.data[index..index + 2].copy_from_slice(&value.to_be_bytes());
1465 }
1466
1467 fn parse_escaped_name(name: &str) -> Vec<String> {
1474 let mut labels = Vec::new();
1475 let mut current_label = String::new();
1476 let mut chars = name.chars().peekable();
1477
1478 while let Some(ch) = chars.next() {
1479 match ch {
1480 '\\' => {
1481 if let Some(&next_ch) = chars.peek() {
1483 match next_ch {
1484 '.' | '\\' => {
1485 chars.next();
1487 current_label.push(next_ch);
1488 }
1489 _ => {
1490 current_label.push(ch);
1492 }
1493 }
1494 } else {
1495 current_label.push(ch);
1497 }
1498 }
1499 '.' => {
1500 if !current_label.is_empty() {
1502 labels.push(current_label.clone());
1503 current_label.clear();
1504 }
1505 }
1506 _ => {
1507 current_label.push(ch);
1508 }
1509 }
1510 }
1511
1512 if !current_label.is_empty() {
1514 labels.push(current_label);
1515 }
1516
1517 labels
1518 }
1519
1520 fn write_name(&mut self, name: &str) -> WriteResult {
1546 let name_to_parse = name.strip_suffix('.').unwrap_or(name);
1548
1549 let labels = Self::parse_escaped_name(name_to_parse);
1551
1552 if labels.is_empty() {
1553 self.write_byte(0);
1554 return Ok(());
1555 }
1556
1557 if labels.iter().any(|label| label.len() > MAX_LABEL_BYTES) {
1559 return Err(WriteError::NameTooLong);
1560 }
1561
1562 for (i, label) in labels.iter().enumerate() {
1564 let remaining: String = labels[i..].join(".");
1566
1567 const POINTER_MASK: u16 = 0xC000;
1569 if let Some(&offset) = self.names.get(&remaining) {
1570 let pointer = offset | POINTER_MASK;
1571 self.write_short(pointer);
1572 return Ok(());
1573 }
1574
1575 self.names.insert(remaining, self.size() as u16);
1577
1578 self.write_utf8(label)?;
1580 }
1581
1582 self.write_byte(0);
1584 Ok(())
1585 }
1586
1587 fn write_byte(&mut self, v: u8) {
1588 self.data.push(v);
1589 }
1590
1591 fn write_bytes(&mut self, s: &[u8]) {
1592 self.data.extend(s);
1593 }
1594
1595 fn write_utf8(&mut self, s: &str) -> WriteResult {
1598 if s.len() > MAX_LABEL_BYTES {
1599 return Err(WriteError::NameTooLong);
1600 }
1601 self.write_byte(s.len() as u8);
1602 self.write_bytes(s.as_bytes());
1603 Ok(())
1604 }
1605
1606 fn write_u32(&mut self, v: u32) {
1607 self.data.extend(&v.to_be_bytes());
1608 }
1609
1610 fn write_short(&mut self, v: u16) {
1611 self.data.extend(&v.to_be_bytes());
1612 }
1613
1614 fn set_truncated(&mut self) {
1617 let flags = u16::from_be_bytes([self.data[2], self.data[3]]);
1618 self.set_short_at(2, flags | FLAGS_TC);
1619 }
1620
1621 fn write_header(&mut self, id: u16, flags: u16) {
1644 self.set_short_at(0, id);
1645 self.set_short_at(2, flags);
1646 self.set_short_at(4, self.question_count);
1647 self.set_short_at(6, self.answer_count);
1648 self.set_short_at(8, self.auth_count);
1649 self.set_short_at(10, self.addi_count);
1650 }
1651}
1652
1653struct PacketBuilder<'a> {
1656 out: &'a DnsOutgoing,
1657
1658 max_size: usize,
1660
1661 is_ipv4: bool,
1664
1665 finished: Vec<DnsOutPacket>,
1666 current: DnsOutPacket,
1667}
1668
1669impl<'a> PacketBuilder<'a> {
1670 fn new(out: &'a DnsOutgoing, max_size: usize, is_ipv4: bool) -> Self {
1671 Self {
1672 out,
1673 max_size,
1674 is_ipv4,
1675 finished: Vec::new(),
1676 current: DnsOutPacket::new(max_size),
1677 }
1678 }
1679
1680 fn add<F>(&mut self, section: Section, write: F)
1687 where
1688 F: Fn(&mut DnsOutPacket) -> WriteResult,
1689 {
1690 match write(&mut self.current) {
1691 Ok(()) => {
1692 self.current.bump(section);
1693 return;
1694 }
1695 Err(WriteError::NameTooLong) => return,
1697 Err(WriteError::PacketFull) => {}
1698 }
1699
1700 if !self.current.is_empty() {
1702 self.flush();
1703
1704 match write(&mut self.current) {
1705 Ok(()) => {
1706 self.current.bump(section);
1707 return;
1708 }
1709 Err(WriteError::NameTooLong) => return,
1710 Err(WriteError::PacketFull) => {}
1711 }
1712 }
1713
1714 if matches!(section, Section::Question) {
1716 return;
1717 }
1718
1719 self.current.max_size = max_pkt_absolute(self.is_ipv4);
1725
1726 if write(&mut self.current).is_ok() {
1727 self.current.bump(section);
1728 self.flush();
1729 } else {
1730 self.current.max_size = self.max_size;
1732 debug!(
1733 "Record too big for absolute max size, skipping: {:?}",
1734 section
1735 );
1736 }
1737 }
1738
1739 fn flush(&mut self) {
1741 self.current
1742 .write_header(self.out.wire_id(), self.out.flags);
1743
1744 let next = DnsOutPacket::new(self.max_size);
1745 self.finished
1746 .push(std::mem::replace(&mut self.current, next));
1747 }
1748
1749 fn finish(mut self) -> Vec<DnsOutPacket> {
1750 if !self.current.is_empty() || self.finished.is_empty() {
1753 self.flush();
1754 }
1755
1756 let mut packets = self.finished;
1757
1758 if self.out.is_query() {
1766 if let Some((_last, rest)) = packets.split_last_mut() {
1767 for packet in rest {
1768 packet.set_truncated();
1769 }
1770 }
1771 }
1772
1773 packets
1774 }
1775}
1776
1777#[derive(Debug)]
1779pub struct DnsOutgoing {
1780 flags: u16,
1781 id: u16,
1782 multicast: bool,
1783 questions: Vec<DnsQuestion>,
1784 answers: Vec<(DnsRecordBox, u64)>,
1785 authorities: Vec<DnsRecordBox>,
1786 additionals: Vec<DnsRecordBox>,
1787 known_answer_count: i64, }
1789
1790impl DnsOutgoing {
1791 pub fn new(flags: u16) -> Self {
1792 Self {
1793 flags,
1794 id: 0,
1795 multicast: true,
1796 questions: Vec::new(),
1797 answers: Vec::new(),
1798 authorities: Vec::new(),
1799 additionals: Vec::new(),
1800 known_answer_count: 0,
1801 }
1802 }
1803
1804 pub fn questions(&self) -> &[DnsQuestion] {
1805 &self.questions
1806 }
1807
1808 pub(crate) fn _answers(&self) -> &[(DnsRecordBox, u64)] {
1810 &self.answers
1811 }
1812
1813 pub fn answers_count(&self) -> usize {
1814 self.answers.len()
1815 }
1816
1817 pub fn authorities(&self) -> &[DnsRecordBox] {
1818 &self.authorities
1819 }
1820
1821 pub fn additionals(&self) -> &[DnsRecordBox] {
1822 &self.additionals
1823 }
1824
1825 pub fn known_answer_count(&self) -> i64 {
1826 self.known_answer_count
1827 }
1828
1829 pub fn set_id(&mut self, id: u16) {
1830 self.id = id;
1831 }
1832
1833 const fn wire_id(&self) -> u16 {
1835 if self.multicast {
1836 0
1837 } else {
1838 self.id
1839 }
1840 }
1841
1842 pub const fn is_query(&self) -> bool {
1843 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
1844 }
1845
1846 pub fn add_additional_answer(&mut self, answer: impl DnsRecordExt + 'static) {
1880 trace!("add_additional_answer: {:?}", &answer);
1881 self.additionals.push(answer.boxed());
1882 }
1883
1884 pub fn add_answer_box(&mut self, answer_box: DnsRecordBox) {
1886 self.answers.push((answer_box, 0));
1887 }
1888
1889 pub fn add_authority(&mut self, record: DnsRecordBox) {
1890 self.authorities.push(record);
1891 }
1892
1893 pub(crate) fn retain_answers<F>(&mut self, mut keep: F)
1895 where
1896 F: FnMut(&DnsRecordBox) -> bool,
1897 {
1898 self.answers.retain(|(record, _)| keep(record));
1899 }
1900
1901 pub(crate) fn retain_additionals<F>(&mut self, mut keep: F)
1903 where
1904 F: FnMut(&DnsRecordBox) -> bool,
1905 {
1906 self.additionals.retain(|record| keep(record));
1907 }
1908
1909 pub fn add_answer(
1912 &mut self,
1913 msg: &DnsIncoming,
1914 answer: impl DnsRecordExt + Send + 'static,
1915 ) -> bool {
1916 trace!("Check for add_answer");
1917 if answer.suppressed_by(msg) {
1918 trace!("my answer is suppressed by incoming msg");
1919 self.known_answer_count += 1;
1920 return false;
1921 }
1922
1923 self.add_answer_at_time(answer, 0)
1924 }
1925
1926 pub fn add_answer_at_time(
1930 &mut self,
1931 answer: impl DnsRecordExt + Send + 'static,
1932 now: u64,
1933 ) -> bool {
1934 if now == 0 || !answer.get_record().is_expired(now) {
1935 trace!("add_answer push: {:?}", &answer);
1936 self.answers.push((answer.boxed(), now));
1937 return true;
1938 }
1939 false
1940 }
1941
1942 pub(crate) fn add_answer_with_additionals(
1951 &mut self,
1952 msg: &DnsIncoming,
1953 service: &ServiceInfo,
1954 intf: &MyIntf,
1955 dns_registry: &DnsRegistry,
1956 is_ipv4: bool,
1957 ) {
1958 let intf_addrs = if is_ipv4 {
1959 service.get_addrs_on_my_intf_v4(intf)
1960 } else {
1961 service.get_addrs_on_my_intf_v6(intf)
1962 };
1963 if intf_addrs.is_empty() {
1964 trace!("No addrs on LAN of intf {:?}", intf);
1965 return;
1966 }
1967
1968 let service_fullname = dns_registry.resolve_name(service.get_fullname());
1970 let hostname = dns_registry.resolve_name(service.get_hostname());
1971
1972 let ptr_added = self.add_answer(
1973 msg,
1974 DnsPointer::new(
1975 service.get_type(),
1976 RRType::PTR,
1977 CLASS_IN,
1978 service.get_other_ttl(),
1979 service_fullname.to_string(),
1980 ),
1981 );
1982
1983 if !ptr_added {
1984 trace!("answer was not added for msg {:?}", msg);
1985 return;
1986 }
1987
1988 if let Some(sub) = service.get_subtype() {
1989 trace!("Adding subdomain {}", sub);
1990 self.add_additional_answer(DnsPointer::new(
1991 sub,
1992 RRType::PTR,
1993 CLASS_IN,
1994 service.get_other_ttl(),
1995 service_fullname.to_string(),
1996 ));
1997 }
1998
1999 self.add_additional_answer(DnsSrv::new(
2002 service_fullname,
2003 CLASS_IN | CLASS_CACHE_FLUSH,
2004 service.get_host_ttl(),
2005 service.get_priority(),
2006 service.get_weight(),
2007 service.get_port(),
2008 hostname.to_string(),
2009 ));
2010
2011 self.add_additional_answer(DnsTxt::new(
2012 service_fullname,
2013 CLASS_IN | CLASS_CACHE_FLUSH,
2014 service.get_other_ttl(),
2015 service.generate_txt(),
2016 ));
2017
2018 for address in intf_addrs {
2019 self.add_additional_answer(DnsAddress::new(
2020 hostname,
2021 ip_address_rr_type(&address),
2022 CLASS_IN | CLASS_CACHE_FLUSH,
2023 service.get_host_ttl(),
2024 address,
2025 intf.into(),
2026 ));
2027 }
2028 }
2029
2030 pub fn add_question(&mut self, name: &str, qtype: RRType) {
2031 let q = DnsQuestion {
2032 entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN),
2033 };
2034 self.questions.push(q);
2035 }
2036
2037 pub fn clear_cache_flush_bits(&mut self) {
2042 for (rec, _) in &mut self.answers {
2043 rec.get_record_mut().entry.cache_flush = false;
2044 }
2045 for rec in &mut self.additionals {
2046 rec.get_record_mut().entry.cache_flush = false;
2047 }
2048 for rec in &mut self.authorities {
2049 rec.get_record_mut().entry.cache_flush = false;
2050 }
2051 }
2052
2053 pub fn to_data_on_wire(&self, max_size: usize, is_ipv4: bool) -> Vec<Vec<u8>> {
2058 let packet_list = self.to_packets(max_size, is_ipv4);
2059 packet_list.into_iter().map(|p| p.data).collect()
2060 }
2061
2062 pub fn to_packets(&self, max_size: usize, is_ipv4: bool) -> Vec<DnsOutPacket> {
2079 debug_assert!(
2080 max_size <= MAX_PKT_ABSOLUTE_IPV6,
2081 "max_size {} exceeds the RFC 6762 section 17 ceiling",
2082 max_size
2083 );
2084 let mut builder = PacketBuilder::new(self, max_size, is_ipv4);
2085
2086 for question in self.questions.iter() {
2087 builder.add(Section::Question, |packet| packet.write_question(question));
2088 }
2089
2090 for (answer, time) in self.answers.iter() {
2091 builder.add(Section::Answer, |packet| {
2092 packet.write_record(answer.as_ref(), *time)
2093 });
2094 }
2095
2096 for auth in self.authorities.iter() {
2097 builder.add(Section::Authority, |packet| {
2098 packet.write_record(auth.as_ref(), 0)
2099 });
2100 }
2101
2102 for addi in self.additionals.iter() {
2103 builder.add(Section::Additional, |packet| {
2104 packet.write_record(addi.as_ref(), 0)
2105 });
2106 }
2107
2108 builder.finish()
2109 }
2110}
2111
2112pub struct DnsIncoming {
2114 offset: usize,
2115 data: Vec<u8>,
2116 questions: Vec<DnsQuestion>,
2117 answers: Vec<DnsRecordBox>,
2118 authorities: Vec<DnsRecordBox>,
2119 additional: Vec<DnsRecordBox>,
2120 id: u16,
2121 flags: u16,
2122 num_questions: u16,
2123 num_answers: u16,
2124 num_authorities: u16,
2125 num_additionals: u16,
2126 interface_id: InterfaceId,
2127}
2128
2129impl fmt::Debug for DnsIncoming {
2131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2132 f.debug_struct("DnsIncoming")
2133 .field("offset", &self.offset)
2134 .field("questions", &self.questions)
2135 .field("answers", &self.answers)
2136 .field("authorities", &self.authorities)
2137 .field("additional", &self.additional)
2138 .field("id", &self.id)
2139 .field("flags", &self.flags)
2140 .field("num_questions", &self.num_questions)
2141 .field("num_answers", &self.num_answers)
2142 .field("num_authorities", &self.num_authorities)
2143 .field("num_additionals", &self.num_additionals)
2144 .field("interface_id", &self.interface_id)
2145 .finish()
2146 }
2147}
2148
2149impl DnsIncoming {
2150 pub fn new(data: Vec<u8>, interface_id: InterfaceId) -> Result<Self> {
2151 let mut incoming = Self {
2152 offset: 0,
2153 data,
2154 questions: Vec::new(),
2155 answers: Vec::new(),
2156 authorities: Vec::new(),
2157 additional: Vec::new(),
2158 id: 0,
2159 flags: 0,
2160 num_questions: 0,
2161 num_answers: 0,
2162 num_authorities: 0,
2163 num_additionals: 0,
2164 interface_id,
2165 };
2166
2167 if let Err(e) = incoming.read_sections() {
2187 return Err(Error::Msg(format!(
2188 "{e}; raw packet length: {}",
2189 incoming.data.len(),
2190 )));
2191 }
2192
2193 Ok(incoming)
2194 }
2195
2196 fn read_sections(&mut self) -> Result<()> {
2199 self.read_header()?;
2200 self.read_questions()?;
2201 self.read_answers()?;
2202 self.read_authorities()?;
2203 self.read_additional()?;
2204 Ok(())
2205 }
2206
2207 pub fn id(&self) -> u16 {
2208 self.id
2209 }
2210
2211 pub fn questions(&self) -> &[DnsQuestion] {
2212 &self.questions
2213 }
2214
2215 pub fn answers(&self) -> &[DnsRecordBox] {
2216 &self.answers
2217 }
2218
2219 pub fn authorities(&self) -> &[DnsRecordBox] {
2220 &self.authorities
2221 }
2222
2223 pub fn additionals(&self) -> &[DnsRecordBox] {
2224 &self.additional
2225 }
2226
2227 pub fn answers_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2228 &mut self.answers
2229 }
2230
2231 pub fn authorities_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2232 &mut self.authorities
2233 }
2234
2235 pub fn additionals_mut(&mut self) -> &mut Vec<DnsRecordBox> {
2236 &mut self.additional
2237 }
2238
2239 pub fn all_records(self) -> impl Iterator<Item = DnsRecordBox> {
2240 self.answers
2241 .into_iter()
2242 .chain(self.authorities)
2243 .chain(self.additional)
2244 }
2245
2246 pub fn num_additionals(&self) -> u16 {
2247 self.num_additionals
2248 }
2249
2250 pub fn num_authorities(&self) -> u16 {
2251 self.num_authorities
2252 }
2253
2254 pub fn num_questions(&self) -> u16 {
2255 self.num_questions
2256 }
2257
2258 pub const fn is_query(&self) -> bool {
2259 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_QUERY
2260 }
2261
2262 pub const fn is_response(&self) -> bool {
2263 (self.flags & FLAGS_QR_MASK) == FLAGS_QR_RESPONSE
2264 }
2265
2266 fn read_header(&mut self) -> Result<()> {
2267 if self.data.len() < MSG_HEADER_LEN {
2268 return Err(e_fmt!(
2269 "DNS incoming: header is too short: {} bytes",
2270 self.data.len()
2271 ));
2272 }
2273
2274 let data = &self.data[0..];
2275 self.id = u16_from_be_slice(&data[..2]);
2276 self.flags = u16_from_be_slice(&data[2..4]);
2277 self.num_questions = u16_from_be_slice(&data[4..6]);
2278 self.num_answers = u16_from_be_slice(&data[6..8]);
2279 self.num_authorities = u16_from_be_slice(&data[8..10]);
2280 self.num_additionals = u16_from_be_slice(&data[10..12]);
2281
2282 self.offset = MSG_HEADER_LEN;
2283
2284 trace!(
2285 "read_header: id {}, {} questions {} answers {} authorities {} additionals",
2286 self.id,
2287 self.num_questions,
2288 self.num_answers,
2289 self.num_authorities,
2290 self.num_additionals
2291 );
2292 Ok(())
2293 }
2294
2295 fn read_questions(&mut self) -> Result<()> {
2296 trace!("read_questions: {}", &self.num_questions);
2297 for i in 0..self.num_questions {
2298 let name = self.read_name()?;
2299
2300 let data = &self.data[self.offset..];
2301 if data.len() < 4 {
2302 return Err(Error::Msg(format!(
2303 "DNS incoming: question idx {} too short: {}",
2304 i,
2305 data.len()
2306 )));
2307 }
2308 let ty = u16_from_be_slice(&data[..2]);
2309 let class = u16_from_be_slice(&data[2..4]);
2310 self.offset += 4;
2311
2312 let Some(rr_type) = RRType::from_u16(ty) else {
2313 return Err(Error::Msg(format!(
2314 "DNS incoming: question idx {i} qtype unknown: {ty}",
2315 )));
2316 };
2317
2318 self.questions.push(DnsQuestion {
2319 entry: DnsEntry::new(name, rr_type, class),
2320 });
2321 }
2322 Ok(())
2323 }
2324
2325 fn read_answers(&mut self) -> Result<()> {
2326 self.answers = self.read_rr_records(self.num_answers)?;
2327 Ok(())
2328 }
2329
2330 fn read_authorities(&mut self) -> Result<()> {
2331 self.authorities = self.read_rr_records(self.num_authorities)?;
2332 Ok(())
2333 }
2334
2335 fn read_additional(&mut self) -> Result<()> {
2336 self.additional = self.read_rr_records(self.num_additionals)?;
2337 Ok(())
2338 }
2339
2340 fn read_rr_records(&mut self, count: u16) -> Result<Vec<DnsRecordBox>> {
2342 trace!("read_rr_records: {}", count);
2343 let mut rr_records = Vec::new();
2344
2345 const RR_HEADER_REMAIN: usize = 10;
2371
2372 for _ in 0..count {
2373 let name = self.read_name()?;
2374 let slice = &self.data[self.offset..];
2375
2376 if slice.len() < RR_HEADER_REMAIN {
2377 return Err(Error::Msg(format!(
2378 "read_others: RR '{}' is too short after name: {} bytes",
2379 &name,
2380 slice.len()
2381 )));
2382 }
2383
2384 let ty = u16_from_be_slice(&slice[..2]);
2385 let class = u16_from_be_slice(&slice[2..4]);
2386 let mut ttl = u32_from_be_slice(&slice[4..8]);
2387 if ttl == 0 && self.is_response() {
2388 ttl = 1;
2395 }
2396 let rdata_len = u16_from_be_slice(&slice[8..10]) as usize;
2397 self.offset += RR_HEADER_REMAIN;
2398 let next_offset = self.offset + rdata_len;
2399
2400 if next_offset > self.data.len() {
2402 return Err(Error::Msg(format!(
2403 "RR {name} RDATA length {rdata_len} is invalid: remain data len: {}",
2404 self.data.len() - self.offset
2405 )));
2406 }
2407
2408 match self.read_rdata(ty, class, ttl, rdata_len, &name) {
2412 Ok(Some(record)) => {
2413 if self.offset == next_offset {
2414 trace!("read_rr_records: {:?}", &record);
2415 rr_records.push(record);
2416 } else {
2417 debug!(
2418 "skipping record '{}' (type {}): RDATA ended at {}, expected {}",
2419 &name, ty, self.offset, next_offset
2420 );
2421 }
2422 }
2423 Ok(None) => {
2424 trace!("Unsupported DNS record type: {} name: {}", ty, &name);
2425 }
2426 Err(e) => {
2427 debug!(
2428 "skipping record '{}' (type {}) with invalid RDATA: {}",
2429 &name, ty, e,
2430 );
2431 }
2432 }
2433
2434 self.offset = next_offset;
2438 }
2439
2440 Ok(rr_records)
2441 }
2442
2443 fn read_rdata(
2450 &mut self,
2451 ty: u16,
2452 class: u16,
2453 ttl: u32,
2454 rdata_len: usize,
2455 name: &str,
2456 ) -> Result<Option<DnsRecordBox>> {
2457 let rec: Option<DnsRecordBox> = match RRType::from_u16(ty) {
2458 None => None,
2459
2460 Some(rr_type) => match rr_type {
2461 RRType::CNAME | RRType::PTR => {
2462 Some(DnsPointer::new(name, rr_type, class, ttl, self.read_name()?).boxed())
2463 }
2464 RRType::TXT => {
2465 Some(DnsTxt::new(name, class, ttl, self.read_vec(rdata_len)?).boxed())
2466 }
2467 RRType::SRV => Some(
2468 DnsSrv::new(
2469 name,
2470 class,
2471 ttl,
2472 self.read_u16()?,
2473 self.read_u16()?,
2474 self.read_u16()?,
2475 self.read_name()?,
2476 )
2477 .boxed(),
2478 ),
2479 RRType::HINFO => Some(
2480 DnsHostInfo::new(
2481 name,
2482 rr_type,
2483 class,
2484 ttl,
2485 self.read_char_string()?,
2486 self.read_char_string()?,
2487 )
2488 .boxed(),
2489 ),
2490 RRType::A => Some(
2491 DnsAddress::new(
2492 name,
2493 rr_type,
2494 class,
2495 ttl,
2496 self.read_ipv4()?.into(),
2497 self.interface_id.clone(),
2498 )
2499 .boxed(),
2500 ),
2501 RRType::AAAA => Some(
2502 DnsAddress::new(
2503 name,
2504 rr_type,
2505 class,
2506 ttl,
2507 self.read_ipv6()?.into(),
2508 self.interface_id.clone(),
2509 )
2510 .boxed(),
2511 ),
2512 RRType::NSEC => Some(
2513 DnsNSec::new(
2514 name,
2515 class,
2516 ttl,
2517 self.read_name()?,
2518 self.read_type_bitmap()?,
2519 )
2520 .boxed(),
2521 ),
2522 _ => None,
2523 },
2524 };
2525
2526 Ok(rec)
2527 }
2528
2529 fn read_char_string(&mut self) -> Result<String> {
2530 let Some(&length) = self.data.get(self.offset) else {
2531 return Err(e_fmt!(
2532 "read_char_string: no length byte at offset {}, data len {}",
2533 self.offset,
2534 self.data.len()
2535 ));
2536 };
2537 self.offset += 1;
2538 self.read_string(length as usize)
2539 }
2540
2541 fn read_u16(&mut self) -> Result<u16> {
2542 let slice = &self.data[self.offset..];
2543 if slice.len() < U16_SIZE {
2544 return Err(Error::Msg(format!(
2545 "read_u16: slice len is only {}",
2546 slice.len()
2547 )));
2548 }
2549 let num = u16_from_be_slice(&slice[..U16_SIZE]);
2550 self.offset += U16_SIZE;
2551 Ok(num)
2552 }
2553
2554 fn read_type_bitmap(&mut self) -> Result<Vec<u8>> {
2556 if self.data.len() < self.offset + 2 {
2565 return Err(Error::Msg(format!(
2566 "DnsIncoming is too short: {} at NSEC Type Bit Map offset {}",
2567 self.data.len(),
2568 self.offset
2569 )));
2570 }
2571
2572 let block_num = self.data[self.offset];
2573 self.offset += 1;
2574 if block_num != 0 {
2575 return Err(Error::Msg(format!(
2576 "NSEC block number is not 0: {block_num}"
2577 )));
2578 }
2579
2580 let block_len = self.data[self.offset] as usize;
2581 if !(1..=32).contains(&block_len) {
2582 return Err(Error::Msg(format!(
2583 "NSEC block length must be in the range 1-32: {block_len}"
2584 )));
2585 }
2586 self.offset += 1;
2587
2588 let end = self.offset + block_len;
2589 if end > self.data.len() {
2590 return Err(Error::Msg(format!(
2591 "NSEC block overflow: {} over RData len {}",
2592 end,
2593 self.data.len()
2594 )));
2595 }
2596 let bitmap = self.data[self.offset..end].to_vec();
2597 self.offset += block_len;
2598
2599 Ok(bitmap)
2600 }
2601
2602 fn read_vec(&mut self, length: usize) -> Result<Vec<u8>> {
2603 if self.data.len() < self.offset + length {
2604 return Err(e_fmt!(
2605 "DNS Incoming: not enough data to read a chunk of data"
2606 ));
2607 }
2608
2609 let v = self.data[self.offset..self.offset + length].to_vec();
2610 self.offset += length;
2611 Ok(v)
2612 }
2613
2614 fn read_ipv4(&mut self) -> Result<Ipv4Addr> {
2615 if self.data.len() < self.offset + 4 {
2616 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV4"));
2617 }
2618
2619 let bytes: [u8; 4] = self.data[self.offset..self.offset + 4]
2620 .try_into()
2621 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV4"))?;
2622 self.offset += bytes.len();
2623 Ok(Ipv4Addr::from(bytes))
2624 }
2625
2626 fn read_ipv6(&mut self) -> Result<Ipv6Addr> {
2627 if self.data.len() < self.offset + 16 {
2628 return Err(e_fmt!("DNS Incoming: not enough data to read an IPV6"));
2629 }
2630
2631 let bytes: [u8; 16] = self.data[self.offset..self.offset + 16]
2632 .try_into()
2633 .map_err(|_| e_fmt!("DNS incoming: Not enough bytes for reading an IPV6"))?;
2634 self.offset += bytes.len();
2635 Ok(Ipv6Addr::from(bytes))
2636 }
2637
2638 fn read_string(&mut self, length: usize) -> Result<String> {
2639 if self.data.len() < self.offset + length {
2640 return Err(e_fmt!("DNS Incoming: not enough data to read a string"));
2641 }
2642
2643 let s = str::from_utf8(&self.data[self.offset..self.offset + length])
2644 .map_err(|e| Error::Msg(e.to_string()))?;
2645 self.offset += length;
2646 Ok(s.to_string())
2647 }
2648
2649 fn read_name(&mut self) -> Result<String> {
2654 let mut name = String::new();
2655 self.offset = self.read_labels(self.offset, &mut name)?;
2656 Ok(name)
2657 }
2658
2659 fn read_labels(&self, mut offset: usize, name: &mut String) -> Result<usize> {
2688 let data = &self.data[..];
2689
2690 loop {
2701 if offset >= data.len() {
2702 return Err(Error::Msg(format!(
2703 "read_labels: offset: {} data len {}",
2704 offset,
2705 data.len(),
2706 )));
2707 }
2708 let length = data[offset];
2709
2710 if length == 0 {
2713 return Ok(offset + 1); }
2715
2716 match length & 0xC0 {
2718 0x00 => {
2719 offset += 1;
2721 let ending = offset + length as usize;
2722
2723 if ending > data.len() {
2725 return Err(Error::Msg(format!(
2726 "read_labels: ending {} exceeds data length {}",
2727 ending,
2728 data.len()
2729 )));
2730 }
2731
2732 let label = str::from_utf8(&data[offset..ending])
2733 .map_err(|e| Error::Msg(format!("read_labels: from_utf8: {e}")))?;
2734
2735 if name.len() + label.len() + 1 > MAX_NAME_BYTES {
2744 return Err(Error::Msg(format!(
2745 "read_labels: name exceeds {MAX_NAME_BYTES} bytes: {name}"
2746 )));
2747 }
2748
2749 *name += label;
2750 *name += ".";
2751 offset = ending;
2752 }
2753 0xC0 => {
2754 self.follow_pointer(offset, name)?;
2756 return Ok(offset + U16_SIZE);
2757 }
2758 _ => {
2759 return Err(Error::Msg(format!(
2760 "Bad name with invalid length: 0x{:x} offset {}, data (so far): {:x?}",
2761 length,
2762 offset,
2763 &data[..offset]
2764 )));
2765 }
2766 };
2767 }
2768 }
2769
2770 fn follow_pointer(&self, at: usize, name: &mut String) -> Result<()> {
2776 let data = &self.data[..];
2777 let mut pointer_at = at;
2778
2779 let target = loop {
2782 let slice = &data[pointer_at..];
2783 if slice.len() < U16_SIZE {
2784 return Err(Error::Msg(format!(
2785 "follow_pointer: u16 slice len is only {}",
2786 slice.len()
2787 )));
2788 }
2789 let target = (u16_from_be_slice(slice) ^ 0xC000) as usize;
2790
2791 if target >= pointer_at {
2794 return Err(Error::Msg(format!(
2795 "Invalid name compression: pointer {target} at offset {pointer_at} must point backwards"
2796 )));
2797 }
2798
2799 if data[target] & 0xC0 != 0xC0 {
2800 break target;
2801 }
2802
2803 pointer_at = target;
2805 };
2806
2807 self.read_labels(target, name)?;
2808 Ok(())
2809 }
2810}
2811
2812const fn u16_from_be_slice(bytes: &[u8]) -> u16 {
2813 let u8_array: [u8; 2] = [bytes[0], bytes[1]];
2814 u16::from_be_bytes(u8_array)
2815}
2816
2817const fn u32_from_be_slice(s: &[u8]) -> u32 {
2818 let u8_array: [u8; 4] = [s[0], s[1], s[2], s[3]];
2819 u32::from_be_bytes(u8_array)
2820}
2821
2822const fn get_expiration_time(created: u64, ttl: u32, percent: u32) -> u64 {
2825 created + (ttl as u64 * percent as u64 * 10)
2828}
2829
2830#[cfg(test)]
2831mod tests {
2832 use super::{
2833 u16_from_be_slice, DnsAddress, DnsHostInfo, DnsIncoming, DnsOutPacket, DnsOutgoing,
2834 DnsPointer, DnsTxt, RRType, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE,
2835 FLAGS_TC, MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT, MSG_HEADER_LEN,
2836 };
2837 use crate::InterfaceId;
2838 use std::collections::HashMap;
2839 use std::net::{IpAddr, Ipv4Addr};
2840
2841 const IPV6: bool = false;
2844
2845 #[test]
2851 fn test_hinfo_char_string_at_end_of_packet() {
2852 let mut data = Vec::new();
2853
2854 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());
2864 data.extend_from_slice(&CLASS_IN.to_be_bytes());
2865 data.extend_from_slice(&0u32.to_be_bytes()); data.extend_from_slice(&0u16.to_be_bytes()); assert_eq!(data.len(), 23);
2872
2873 let parsed = DnsIncoming::new(data, test_interface_id())
2874 .expect("a truncated HINFO must be skipped, not fail the packet");
2875
2876 assert_eq!(parsed.authorities().len(), 0);
2878 }
2879
2880 #[test]
2881 fn test_dns_outgoing_serialization_empty() {
2882 let out = DnsOutgoing::new(0);
2883 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2884 assert_eq!(packets.len(), 1);
2885 assert_eq!(packets[0].as_bytes(), &[0; 12]);
2886 let expected_names = HashMap::new();
2887 assert_eq!(&packets[0].names, &expected_names);
2888 }
2889
2890 #[test]
2891 fn test_dns_outgoing_serialization_question() {
2892 let mut out = DnsOutgoing::new(0);
2893 out.add_question("123.test", RRType::A);
2894 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2895 assert_eq!(packets.len(), 1);
2896 assert_eq!(
2897 packets[0].as_bytes(),
2898 &[
2899 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,
2902 ]
2903 );
2904 let mut expected_names = HashMap::new();
2905 expected_names.insert("123.test".to_string(), 12);
2906 expected_names.insert("test".to_string(), 16);
2907 assert_eq!(&packets[0].names, &expected_names);
2908 }
2909
2910 #[test]
2911 fn test_dns_outgoing_serialization_question_with_authority() {
2912 let mut out = DnsOutgoing::new(0);
2913 out.add_question("123.test", RRType::ANY);
2914 out.add_authority(Box::new(DnsTxt::new(
2915 "124.test",
2916 CLASS_IN,
2917 0x00112233,
2918 b"help".to_vec(),
2919 )));
2920 out.add_authority(Box::new(DnsHostInfo::new(
2921 "124.test",
2922 RRType::CNAME,
2923 CLASS_IN,
2924 0x00112233,
2925 "arm".to_string(),
2926 "linux".to_string(),
2927 )));
2928 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2929 assert_eq!(packets.len(), 1);
2930 assert_eq!(
2931 packets[0].as_bytes(),
2932 &[
2933 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,
2936 16, 0, 1, 0, 17, 34, 51, 0, 4, 104, 101, 108, 112, 192, 26, 0, 5, 0, 1, 0, 17, 34,
2937 51, 0, 8, 97, 114, 109, 108, 105, 110, 117, 120,
2938 ]
2939 );
2940 let mut expected_names = HashMap::new();
2941 expected_names.insert("123.test".to_string(), 12);
2942 expected_names.insert("test".to_string(), 16);
2943 expected_names.insert("124.test".to_string(), 26);
2944 assert_eq!(&packets[0].names, &expected_names);
2945 }
2946
2947 #[test]
2948 fn test_dns_outgoing_serialization_additional_answer() {
2949 let mut out = DnsOutgoing::new(0);
2950 out.add_additional_answer(DnsAddress::new(
2951 "test.local",
2952 RRType::A,
2953 CLASS_IN | CLASS_CACHE_FLUSH,
2954 0xdead_beef,
2955 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
2956 InterfaceId::default(),
2957 ));
2958 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2959 assert_eq!(packets.len(), 1);
2960 assert_eq!(
2961 packets[0].as_bytes(),
2962 &[
2963 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,
2966 239, 0, 4, 127, 0, 0, 1,
2967 ]
2968 );
2969 let mut expected_names = HashMap::new();
2970 expected_names.insert("test.local".to_string(), 12);
2971 expected_names.insert("local".to_string(), 17);
2972 assert_eq!(&packets[0].names, &expected_names);
2973 }
2974
2975 #[test]
2976 fn test_dns_outgoing_serialization_answer_at_time() {
2977 let mut out = DnsOutgoing::new(0);
2978 out.add_answer_at_time(
2979 DnsPointer::new(
2980 "test",
2981 RRType::PTR,
2982 CLASS_IN,
2983 0xaaaa5555,
2984 "test-service".to_string(),
2985 ),
2986 0,
2987 );
2988 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
2989 assert_eq!(packets.len(), 1);
2990 assert_eq!(
2991 packets[0].as_bytes(),
2992 &[
2993 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,
2996 116, 45, 115, 101, 114, 118, 105, 99, 101, 0,
2997 ]
2998 );
2999
3000 let mut out = DnsOutgoing::new(0);
3001 out.add_answer_at_time(
3002 DnsPointer::new(
3003 "test",
3004 RRType::CNAME,
3005 CLASS_IN,
3006 0xaaaa5555,
3007 "test-service.local".to_string(),
3008 ),
3009 0,
3010 );
3011 out.add_answer_at_time(
3012 DnsPointer::new(
3013 "test",
3014 RRType::AAAA,
3015 CLASS_IN,
3016 0xffffffff,
3017 "test-service.local".to_string(),
3018 ),
3019 0,
3020 );
3021 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3022 assert_eq!(packets.len(), 1);
3023 assert_eq!(
3024 packets[0].as_bytes(),
3025 &[
3026 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,
3029 116, 45, 115, 101, 114, 118, 105, 99, 101, 5, 108, 111, 99, 97, 108, 0, 192, 12, 0,
3030 28, 0, 1, 255, 255, 255, 255, 0, 2, 192, 28,
3031 ]
3032 );
3033 let mut expected_names = HashMap::new();
3034 expected_names.insert("test".to_string(), 12);
3035 expected_names.insert("test-service.local".to_string(), 28);
3036 expected_names.insert("local".to_string(), 41);
3037 assert_eq!(&packets[0].names, &expected_names);
3038 }
3039
3040 #[test]
3044 fn test_dns_outgoing_question_label_too_long() {
3045 let long_label = "a".repeat(64);
3046 let mut out = DnsOutgoing::new(0);
3047 out.add_question(&format!("{long_label}.local"), RRType::PTR);
3048 out.add_question("123.test", RRType::A);
3049
3050 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3051 assert_eq!(packets.len(), 1);
3052 assert_eq!(
3053 packets[0].as_bytes(),
3054 &[
3055 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,
3058 ]
3059 );
3060
3061 let mut expected_names = HashMap::new();
3063 expected_names.insert("123.test".to_string(), 12);
3064 expected_names.insert("test".to_string(), 16);
3065 assert_eq!(&packets[0].names, &expected_names);
3066 }
3067
3068 #[test]
3071 fn test_dns_outgoing_record_label_too_long() {
3072 let long_label = "a".repeat(64);
3073 let mut out = DnsOutgoing::new(0);
3074 out.add_answer_at_time(
3075 DnsPointer::new(
3076 "_test._tcp.local.",
3077 RRType::PTR,
3078 CLASS_IN,
3079 0,
3080 format!("{long_label}._test._tcp.local."),
3081 ),
3082 0,
3083 );
3084 out.add_answer_at_time(
3085 DnsPointer::new(
3086 "_test._tcp.local.",
3087 RRType::PTR,
3088 CLASS_IN,
3089 0,
3090 "ok._test._tcp.local.".to_string(),
3091 ),
3092 0,
3093 );
3094
3095 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3096 assert_eq!(packets.len(), 1);
3097
3098 assert_eq!(&packets[0].as_bytes()[6..8], &[0, 1]);
3100
3101 let incoming = DnsIncoming::new(
3103 packets[0].as_bytes().to_vec(),
3104 InterfaceId {
3105 name: "test".to_string(),
3106 index: 1,
3107 },
3108 )
3109 .unwrap();
3110 assert_eq!(incoming.answers().len(), 1);
3111 }
3112
3113 #[test]
3118 fn test_incoming_name_with_merged_labels_does_not_panic() {
3119 let mut data: Vec<u8> = vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
3121 data.push(63);
3122 data.extend(vec![b'a'; 62]);
3123 data.push(b'\\');
3124 data.push(63);
3125 data.extend(vec![b'b'; 63]);
3126 data.push(0);
3127 data.extend([0, 12, 0, 1]); let incoming = DnsIncoming::new(
3130 data,
3131 InterfaceId {
3132 name: "test".to_string(),
3133 index: 1,
3134 },
3135 )
3136 .unwrap();
3137 let name = incoming.questions()[0].entry.name.clone();
3138
3139 assert!(name.starts_with("aaa"));
3141 assert!(name.contains("\\.bbb"));
3142
3143 let mut out = DnsOutgoing::new(0);
3145 out.add_question(&name, RRType::PTR);
3146 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3147 assert_eq!(packets.len(), 1);
3148 assert_eq!(packets[0].as_bytes(), &[0; MSG_HEADER_LEN]);
3149 }
3150
3151 #[test]
3155 fn test_read_name_pointer_loop_is_rejected() {
3156 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 1, 0, 0, 0, 0];
3160 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());
3169 }
3170
3171 #[test]
3179 fn test_read_name_pointer_after_backward_jump() {
3180 fn push_question(data: &mut Vec<u8>, label_len: usize) {
3182 data.push(label_len as u8);
3183 data.extend(vec![b'a'; label_len]);
3184 data.push(0); data.extend_from_slice(&[0, 12]); data.extend_from_slice(&[0, 1]); }
3188
3189 let mut data: Vec<u8> = vec![
3190 0, 0, 0, 0, 0, 11, 0, 1, 0, 0, 0, 0, ];
3196
3197 for _ in 0..10 {
3199 push_question(&mut data, 60);
3200 }
3201 assert_eq!(data.len(), 672);
3202
3203 push_question(&mut data, 22);
3205 assert_eq!(data.len(), 700);
3206
3207 data[640] = 62;
3209
3210 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);
3219 assert_eq!(u16_from_be_slice(&data[703..705]) ^ 0xC000, 702);
3220
3221 let incoming = DnsIncoming::new(data, test_interface_id())
3222 .expect("a name whose pointers all point backwards must parse");
3223 assert_eq!(incoming.questions().len(), 11);
3224
3225 assert_eq!(incoming.answers().len(), 0);
3227 }
3228
3229 #[test]
3236 fn test_read_name_mutual_pointers_are_rejected() {
3237 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 2, 0, 0, 0, 0];
3238
3239 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);
3248
3249 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);
3257 assert_eq!(u16_from_be_slice(&data[23..25]) ^ 0xC000, 25);
3258 assert_eq!(u16_from_be_slice(&data[25..27]) ^ 0xC000, 23);
3259
3260 assert!(DnsIncoming::new(data, test_interface_id()).is_err());
3261 }
3262
3263 #[test]
3268 fn test_read_name_label_cycle_is_rejected() {
3269 let mut data: Vec<u8> = vec![0, 0, 0x84, 0, 0, 0, 0, 2, 0, 0, 0, 0];
3270
3271 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);
3281
3282 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);
3291 assert_eq!(u16_from_be_slice(&data[30..32]) ^ 0xC000, 23);
3292
3293 assert!(DnsIncoming::new(data, test_interface_id()).is_err());
3294 }
3295
3296 #[test]
3306 fn test_malformed_nsec_record_is_skipped() {
3307 let data: Vec<u8> = vec![
3308 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x5f,
3309 0x6d, 0x69, 0x69, 0x6f, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61,
3310 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x24, 0x21, 0x64,
3311 0x72, 0x65, 0x61, 0x6d, 0x65, 0x2d, 0x76, 0x61, 0x63, 0x75, 0x75, 0x6d, 0x2d, 0x70,
3312 0x32, 0x30, 0x32, 0x39, 0x5f, 0x6d, 0x69, 0x69, 0x6f, 0x34, 0x34, 0x37, 0x33, 0x30,
3313 0x35, 0x32, 0x34, 0x37, 0xc0, 0x0c, 0x21, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x2d,
3314 0x76, 0x61, 0x63, 0x75, 0x75, 0x6d, 0x2d, 0x70, 0x32, 0x30, 0x32, 0x39, 0x5f, 0x6d,
3315 0x69, 0x69, 0x6f, 0x34, 0x34, 0x37, 0x33, 0x30, 0x35, 0x32, 0x34, 0x37, 0x00, 0x00,
3316 0x2f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x09, 0xc0, 0x79, 0x00, 0x05, 0x40,
3317 0x00, 0x00, 0x00, 0x00, 0xc0, 0x4c, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78,
3318 0x00, 0x04, 0x0a, 0x2a, 0x02, 0x32, 0xc0, 0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00,
3319 0x00, 0x78, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31, 0xc0, 0x4c, 0xc0, 0x28,
3320 0x00, 0x10, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x0e, 0x70, 0x61, 0x74,
3321 0x68, 0x3d, 0x2f, 0x6d, 0x79, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
3322 ];
3323
3324 assert_eq!(u16_from_be_slice(&data[121..123]) ^ 0xC000, 121);
3327
3328 let incoming = DnsIncoming::new(data, test_interface_id())
3329 .expect("one malformed record must not fail the whole packet");
3330
3331 assert_eq!(incoming.answers().len(), 4);
3333 assert!(
3334 !incoming
3335 .answers()
3336 .iter()
3337 .any(|r| r.get_type() == RRType::NSEC),
3338 "the malformed NSEC record must be skipped"
3339 );
3340 }
3341
3342 fn test_interface_id() -> InterfaceId {
3343 InterfaceId {
3344 name: "test".to_string(),
3345 index: 1,
3346 }
3347 }
3348
3349 fn packet_flags(packet: &DnsOutPacket) -> u16 {
3351 let bytes = packet.as_bytes();
3352 u16::from_be_bytes([bytes[2], bytes[3]])
3353 }
3354
3355 fn ptr_answer(index: usize) -> DnsPointer {
3356 DnsPointer::new(
3357 "_spill._tcp.local.",
3358 RRType::PTR,
3359 CLASS_IN,
3360 4500,
3361 format!("instance-{index:04}._spill._tcp.local."),
3362 )
3363 }
3364
3365 fn parsed_answer_count(packets: &[DnsOutPacket]) -> usize {
3368 packets
3369 .iter()
3370 .map(|packet: &DnsOutPacket| {
3371 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id())
3372 .expect("each packet must parse on its own");
3373 assert!(
3374 !parsed.answers().is_empty(),
3375 "a spilled packet must not be empty"
3376 );
3377 parsed.answers().len()
3378 })
3379 .sum()
3380 }
3381
3382 #[test]
3385 fn test_dns_outgoing_response_spills_into_packets() {
3386 const ANSWER_COUNT: usize = 100;
3387
3388 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3389 for i in 0..ANSWER_COUNT {
3390 out.add_answer_at_time(ptr_answer(i), 0);
3391 }
3392
3393 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3394 assert!(
3395 packets.len() > 1,
3396 "{} answers should not fit in one packet",
3397 ANSWER_COUNT
3398 );
3399
3400 for packet in &packets {
3401 assert!(
3402 packet.size() <= MAX_PKT_DEFAULT,
3403 "packet of {} bytes exceeds the limit",
3404 packet.size()
3405 );
3406
3407 assert_eq!(packet_flags(packet) & FLAGS_TC, 0);
3410 }
3411
3412 assert_eq!(parsed_answer_count(&packets), ANSWER_COUNT);
3413 }
3414
3415 #[test]
3418 fn test_dns_outgoing_query_truncation_bit() {
3419 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
3420 out.add_question("_spill._tcp.local.", RRType::PTR);
3421 for i in 0..100 {
3422 out.add_answer_box(Box::new(ptr_answer(i)));
3423 }
3424
3425 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3426 assert!(
3427 packets.len() > 1,
3428 "known answers should not fit in one packet"
3429 );
3430
3431 let (last, rest) = packets.split_last().expect("at least one packet");
3432 for packet in rest {
3433 assert_ne!(
3434 packet_flags(packet) & FLAGS_TC,
3435 0,
3436 "a packet with more known answers to follow must set TC"
3437 );
3438 }
3439 assert_eq!(
3440 packet_flags(last) & FLAGS_TC,
3441 0,
3442 "the last packet must not set TC"
3443 );
3444
3445 assert_eq!(packets[0].as_bytes()[4..6], 1u16.to_be_bytes());
3447 for packet in rest.iter().skip(1) {
3448 assert_eq!(packet.as_bytes()[4..6], [0, 0]);
3449 }
3450 assert_eq!(parsed_answer_count(&packets), 100);
3451 }
3452
3453 #[test]
3457 fn test_dns_outgoing_oversized_record_sent_alone() {
3458 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3459 out.add_answer_at_time(ptr_answer(0), 0);
3460 out.add_answer_at_time(
3461 DnsTxt::new("big._spill._tcp.local.", CLASS_IN, 4500, vec![b'x'; 2000]),
3462 0,
3463 );
3464 out.add_answer_at_time(ptr_answer(1), 0);
3465
3466 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3467 assert_eq!(packets.len(), 3, "the big record needs a packet to itself");
3468
3469 assert!(packets[0].size() <= MAX_PKT_DEFAULT);
3470 assert!(
3471 packets[1].size() > MAX_PKT_DEFAULT,
3472 "the oversized record must not be dropped"
3473 );
3474 assert!(packets[1].size() <= MAX_PKT_ABSOLUTE_IPV6);
3476 assert!(packets[2].size() <= MAX_PKT_DEFAULT);
3477
3478 let parsed = DnsIncoming::new(packets[1].as_bytes().to_vec(), test_interface_id()).unwrap();
3480 assert_eq!(parsed.answers().len(), 1);
3481 assert_eq!(parsed.answers()[0].get_name(), "big._spill._tcp.local.");
3482 assert_eq!(parsed_answer_count(&packets), 3);
3483 }
3484
3485 #[test]
3488 fn test_dns_outgoing_record_over_absolute_ceiling_dropped() {
3489 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3490 out.add_answer_at_time(ptr_answer(0), 0);
3491 out.add_answer_at_time(
3492 DnsTxt::new(
3493 "huge._spill._tcp.local.",
3494 CLASS_IN,
3495 4500,
3496 vec![b'x'; MAX_PKT_ABSOLUTE_IPV6],
3497 ),
3498 0,
3499 );
3500 out.add_answer_at_time(ptr_answer(1), 0);
3501
3502 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3503 for packet in &packets {
3504 assert!(
3505 packet.size() <= MAX_PKT_ABSOLUTE_IPV6,
3506 "an unsendable packet must never be generated"
3507 );
3508 }
3509 assert_eq!(
3510 parsed_answer_count(&packets),
3511 2,
3512 "only the huge record is dropped"
3513 );
3514 }
3515
3516 #[test]
3518 fn test_dns_outgoing_all_sections_spill() {
3519 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE);
3520 for i in 0..40 {
3521 out.add_answer_at_time(ptr_answer(i), 0);
3522 }
3523 for i in 40..80 {
3524 out.add_authority(Box::new(ptr_answer(i)));
3525 }
3526 for i in 80..120 {
3527 out.add_additional_answer(ptr_answer(i));
3528 }
3529
3530 let packets = out.to_packets(MAX_PKT_DEFAULT, IPV6);
3531 assert!(packets.len() > 1);
3532
3533 let mut answers = 0;
3534 let mut authorities = 0;
3535 let mut additionals = 0;
3536 for packet in &packets {
3537 assert!(packet.size() <= MAX_PKT_DEFAULT);
3538 let parsed = DnsIncoming::new(packet.as_bytes().to_vec(), test_interface_id()).unwrap();
3539 answers += parsed.answers().len();
3540 authorities += parsed.authorities().len();
3541 additionals += parsed.additionals().len();
3542 }
3543
3544 assert_eq!(answers, 40);
3545 assert_eq!(authorities, 40);
3546 assert_eq!(additionals, 40);
3547 }
3548}