1#[cfg(feature = "logging")]
32use crate::log::{debug, error, trace};
33use crate::{
34 dns_cache::{DnsCache, IpType},
35 dns_parser::{
36 ip_address_rr_type, max_pkt_absolute, DnsAddress, DnsEntryExt, DnsIncoming, DnsNSec,
37 DnsOutgoing, DnsPointer, DnsQuestion, DnsRecordBox, DnsRecordExt, DnsSrv, DnsTxt,
38 InterfaceId, RRType, ScopedIp, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_AA, FLAGS_QR_QUERY,
39 FLAGS_QR_RESPONSE, MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT,
40 },
41 error::{e_fmt, Error, Result},
42 service_info::{
43 valid_ip_on_intf, DnsRegistry, MyIntf, Probe, ServiceInfo, ServiceStatus,
44 MULTICAST_RATE_LIMIT_MILLIS,
45 },
46 Receiver, ResolvedService, TxtProperties,
47};
48use flume::{bounded, Sender, TrySendError};
49use if_addrs::{IfAddr, Interface};
50use mio::{event::Source, net::UdpSocket as MioUdpSocket, Interest, Poll, Registry, Token};
51use socket2::Domain;
52use socket_pktinfo::PktInfoUdpSocket;
53use std::{
54 cmp::{self, Reverse},
55 collections::{hash_map::Entry, BinaryHeap, HashMap, HashSet},
56 fmt, io,
57 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, UdpSocket},
58 str, thread,
59 time::{Duration, Instant, SystemTime},
60 vec,
61};
62
63pub const SERVICE_NAME_LEN_MAX_DEFAULT: u8 = 15;
67
68pub const IP_CHECK_INTERVAL_IN_SECS_DEFAULT: u32 = 5;
70
71pub const VERIFY_TIMEOUT_DEFAULT: Duration = Duration::from_secs(10);
74
75pub(crate) const MIN_MAX_PACKET_SIZE: usize = 512;
77
78pub const MDNS_PORT: u16 = 5353;
80
81const GROUP_ADDR_V4: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
82const GROUP_ADDR_V6: Ipv6Addr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0xfb);
83const LOOPBACK_V4: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
84
85const RESOLVE_RETRY_BASE_MILLIS: u64 = 200;
89
90const RESOLVE_MAX_TRY: u16 = 4;
93
94const ANNOUNCE_SECOND_DELAY_MILLIS: u64 = MULTICAST_RATE_LIMIT_MILLIS + 100;
102
103const ANNOUNCE_SECOND_JITTER_MILLIS: u64 = 50;
106
107#[allow(clippy::assertions_on_constants)]
111const _: () = assert!(ANNOUNCE_SECOND_DELAY_MILLIS > MULTICAST_RATE_LIMIT_MILLIS);
112
113const SHARED_RESPONSE_DELAY_MIN_MILLIS: u64 = 10;
121
122const SHARED_RESPONSE_DELAY_MAX_MILLIS: u64 = 50;
124
125const INITIAL_QUERY_DELAY_MIN_MILLIS: u64 = 10;
133const INITIAL_QUERY_DELAY_MAX_MILLIS: u64 = 50;
134
135const SLEEP_DETECTION_THRESHOLD: Duration = Duration::from_secs(2);
139
140#[derive(Debug)]
142pub enum UnregisterStatus {
143 OK,
145 NotFound,
147}
148
149#[derive(Debug, PartialEq, Clone, Eq)]
151#[non_exhaustive]
152pub enum DaemonStatus {
153 Running,
155
156 Shutdown,
158}
159
160#[derive(Hash, Eq, PartialEq)]
163enum Counter {
164 Register,
165 RegisterResend,
166 Unregister,
167 UnregisterResend,
168 Browse,
169 ResolveHostname,
170 Respond,
171 CacheRefreshPTR,
172 CacheRefreshSrvTxt,
173 CacheRefreshAddr,
174 KnownAnswerSuppression,
175 CachedPTR,
176 CachedSRV,
177 CachedAddr,
178 CachedTxt,
179 CachedNSec,
180 CachedSubtype,
181 DnsRegistryProbe,
182 DnsRegistryActive,
183 DnsRegistryTimer,
184 DnsRegistryNameChange,
185 Timer,
186}
187
188impl fmt::Display for Counter {
189 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190 match self {
191 Self::Register => write!(f, "register"),
192 Self::RegisterResend => write!(f, "register-resend"),
193 Self::Unregister => write!(f, "unregister"),
194 Self::UnregisterResend => write!(f, "unregister-resend"),
195 Self::Browse => write!(f, "browse"),
196 Self::ResolveHostname => write!(f, "resolve-hostname"),
197 Self::Respond => write!(f, "respond"),
198 Self::CacheRefreshPTR => write!(f, "cache-refresh-ptr"),
199 Self::CacheRefreshSrvTxt => write!(f, "cache-refresh-srv-txt"),
200 Self::CacheRefreshAddr => write!(f, "cache-refresh-addr"),
201 Self::KnownAnswerSuppression => write!(f, "known-answer-suppression"),
202 Self::CachedPTR => write!(f, "cached-ptr"),
203 Self::CachedSRV => write!(f, "cached-srv"),
204 Self::CachedAddr => write!(f, "cached-addr"),
205 Self::CachedTxt => write!(f, "cached-txt"),
206 Self::CachedNSec => write!(f, "cached-nsec"),
207 Self::CachedSubtype => write!(f, "cached-subtype"),
208 Self::DnsRegistryProbe => write!(f, "dns-registry-probe"),
209 Self::DnsRegistryActive => write!(f, "dns-registry-active"),
210 Self::DnsRegistryTimer => write!(f, "dns-registry-timer"),
211 Self::DnsRegistryNameChange => write!(f, "dns-registry-name-change"),
212 Self::Timer => write!(f, "timer"),
213 }
214 }
215}
216
217#[derive(Debug)]
218enum InternalError {
219 IntfAddrInvalid(Interface),
220}
221
222impl fmt::Display for InternalError {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 match self {
225 InternalError::IntfAddrInvalid(iface) => write!(f, "interface addr invalid: {iface:?}"),
226 }
227 }
228}
229
230type MyResult<T> = core::result::Result<T, InternalError>;
231
232struct MyUdpSocket {
237 pktinfo: PktInfoUdpSocket,
240
241 mio: MioUdpSocket,
244}
245
246impl MyUdpSocket {
247 pub fn new(pktinfo: PktInfoUdpSocket) -> io::Result<Self> {
248 let std_sock = pktinfo.try_clone_std()?;
249 let mio = MioUdpSocket::from_std(std_sock);
250
251 Ok(Self { pktinfo, mio })
252 }
253}
254
255impl Source for MyUdpSocket {
257 fn register(
258 &mut self,
259 registry: &Registry,
260 token: Token,
261 interests: Interest,
262 ) -> io::Result<()> {
263 self.mio.register(registry, token, interests)
264 }
265
266 fn reregister(
267 &mut self,
268 registry: &Registry,
269 token: Token,
270 interests: Interest,
271 ) -> io::Result<()> {
272 self.mio.reregister(registry, token, interests)
273 }
274
275 fn deregister(&mut self, registry: &Registry) -> std::io::Result<()> {
276 self.mio.deregister(registry)
277 }
278}
279
280pub type Metrics = HashMap<String, i64>;
283
284const IPV4_SOCK_EVENT_KEY: usize = 4; const IPV6_SOCK_EVENT_KEY: usize = 6; const SIGNAL_SOCK_EVENT_KEY: usize = usize::MAX - 1; #[derive(Clone)]
292pub struct ServiceDaemon {
293 sender: Sender<Command>,
295
296 signal_addr: SocketAddr,
302}
303
304impl ServiceDaemon {
305 pub fn new() -> Result<Self> {
321 Self::new_with_port(MDNS_PORT)
322 }
323
324 pub fn new_with_port(port: u16) -> Result<Self> {
356 let signal_addr = SocketAddrV4::new(LOOPBACK_V4, 0);
359
360 let signal_sock = UdpSocket::bind(signal_addr)
361 .map_err(|e| e_fmt!("failed to create signal_sock for daemon: {}", e))?;
362
363 let signal_addr = signal_sock
365 .local_addr()
366 .map_err(|e| e_fmt!("failed to get signal sock addr: {}", e))?;
367
368 signal_sock
370 .set_nonblocking(true)
371 .map_err(|e| e_fmt!("failed to set nonblocking for signal socket: {}", e))?;
372
373 let poller = Poll::new().map_err(|e| e_fmt!("failed to create mio Poll: {e}"))?;
374
375 let (sender, receiver) = bounded(100);
376
377 let mio_sock = MioUdpSocket::from_std(signal_sock);
379 let cmd_sender = sender.clone();
380 thread::Builder::new()
381 .name("mDNS_daemon".to_string())
382 .spawn(move || {
383 Self::daemon_thread(mio_sock, poller, receiver, port, cmd_sender, signal_addr)
384 })
385 .map_err(|e| e_fmt!("thread builder failed to spawn: {}", e))?;
386
387 Ok(Self {
388 sender,
389 signal_addr,
390 })
391 }
392
393 fn send_cmd(&self, cmd: Command) -> Result<()> {
396 let cmd_name = cmd.to_string();
397
398 self.sender.try_send(cmd).map_err(|e| match e {
400 TrySendError::Full(_) => Error::Again,
401 TrySendError::Disconnected(_) => Error::DaemonShutdown,
402 })?;
403
404 let addr = SocketAddrV4::new(LOOPBACK_V4, 0);
406 let socket = UdpSocket::bind(addr)
407 .map_err(|e| e_fmt!("Failed to create socket to send signal: {}", e))?;
408 socket
409 .send_to(cmd_name.as_bytes(), self.signal_addr)
410 .map_err(|e| {
411 e_fmt!(
412 "signal socket send_to {} ({}) failed: {}",
413 self.signal_addr,
414 cmd_name,
415 e
416 )
417 })?;
418
419 Ok(())
420 }
421
422 pub fn browse(&self, service_type: &str) -> Result<Receiver<ServiceEvent>> {
442 check_domain_suffix(service_type)?;
443
444 let (resp_s, resp_r) = bounded(10);
445 self.send_cmd(Command::Browse(service_type.to_string(), 1, false, resp_s))?;
446 Ok(resp_r)
447 }
448
449 pub fn browse_cache(&self, service_type: &str) -> Result<Receiver<ServiceEvent>> {
462 check_domain_suffix(service_type)?;
463
464 let (resp_s, resp_r) = bounded(10);
465 self.send_cmd(Command::Browse(service_type.to_string(), 1, true, resp_s))?;
466 Ok(resp_r)
467 }
468
469 pub fn stop_browse(&self, ty_domain: &str) -> Result<()> {
477 self.send_cmd(Command::StopBrowse(ty_domain.to_string()))
478 }
479
480 pub fn resolve_hostname(
500 &self,
501 hostname: &str,
502 timeout: Option<u64>,
503 ) -> Result<Receiver<HostnameResolutionEvent>> {
504 check_hostname(hostname)?;
505 let (resp_s, resp_r) = bounded(10);
506 self.send_cmd(Command::ResolveHostname(
507 hostname.to_string(),
508 1,
509 resp_s,
510 timeout,
511 ))?;
512 Ok(resp_r)
513 }
514
515 pub fn stop_resolve_hostname(&self, hostname: &str) -> Result<()> {
521 self.send_cmd(Command::StopResolveHostname(hostname.to_string()))
522 }
523
524 pub fn register(&self, service_info: ServiceInfo) -> Result<()> {
544 check_service_name(service_info.get_fullname())?;
545 check_hostname(service_info.get_hostname())?;
546
547 self.send_cmd(Command::Register(service_info.into()))
548 }
549
550 pub fn unregister(&self, fullname: &str) -> Result<Receiver<UnregisterStatus>> {
561 let (resp_s, resp_r) = bounded(1);
562 self.send_cmd(Command::Unregister(fullname.to_lowercase(), resp_s))?;
563 Ok(resp_r)
564 }
565
566 pub fn monitor(&self) -> Result<Receiver<DaemonEvent>> {
576 let (resp_s, resp_r) = bounded(100);
577 self.send_cmd(Command::Monitor(resp_s))?;
578 Ok(resp_r)
579 }
580
581 pub fn shutdown(&self) -> Result<Receiver<DaemonStatus>> {
589 let (resp_s, resp_r) = bounded(1);
590 self.send_cmd(Command::Exit(resp_s))?;
591 Ok(resp_r)
592 }
593
594 pub fn status(&self) -> Result<Receiver<DaemonStatus>> {
602 let (resp_s, resp_r) = bounded(1);
603
604 if self.sender.is_disconnected() {
605 resp_s
606 .send(DaemonStatus::Shutdown)
607 .map_err(|e| e_fmt!("failed to send daemon status to the client: {}", e))?;
608 } else {
609 self.send_cmd(Command::GetStatus(resp_s))?;
610 }
611
612 Ok(resp_r)
613 }
614
615 pub fn get_metrics(&self) -> Result<Receiver<Metrics>> {
626 let (resp_s, resp_r) = bounded(1);
627 self.send_cmd(Command::GetMetrics(resp_s))?;
628 Ok(resp_r)
629 }
630
631 pub fn set_service_name_len_max(&self, len_max: u8) -> Result<()> {
646 const SERVICE_NAME_LEN_MAX_LIMIT: u8 = 30; if len_max > SERVICE_NAME_LEN_MAX_LIMIT {
649 return Err(Error::Msg(format!(
650 "service name length max {len_max} is too large"
651 )));
652 }
653
654 self.send_cmd(Command::SetOption(DaemonOption::ServiceNameLenMax(len_max)))
655 }
656
657 pub fn set_max_packet_size(&self, if_kind: impl IntoIfKindVec, size: usize) -> Result<()> {
672 if size < MIN_MAX_PACKET_SIZE {
673 return Err(Error::Msg(format!(
674 "max packet size {size} is too small, must be at least {MIN_MAX_PACKET_SIZE}"
675 )));
676 }
677
678 if size > MAX_PKT_ABSOLUTE_IPV6 {
679 return Err(Error::Msg(format!(
680 "max packet size {size} is too big, must be at most {MAX_PKT_ABSOLUTE_IPV6}"
681 )));
682 }
683
684 let if_kind_vec = if_kind.into_vec();
685 self.send_cmd(Command::SetOption(DaemonOption::MaxPacketSize(
686 if_kind_vec.kinds,
687 size,
688 )))
689 }
690
691 pub fn set_ip_check_interval(&self, interval_in_secs: u32) -> Result<()> {
697 let interval_in_millis = interval_in_secs as u64 * 1000;
698 self.send_cmd(Command::SetOption(DaemonOption::IpCheckInterval(
699 interval_in_millis,
700 )))
701 }
702
703 pub fn get_ip_check_interval(&self) -> Result<u32> {
705 let (resp_s, resp_r) = bounded(1);
706 self.send_cmd(Command::GetOption(resp_s))?;
707
708 let option = resp_r
709 .recv_timeout(Duration::from_secs(10))
710 .map_err(|e| e_fmt!("failed to receive ip check interval: {}", e))?;
711 let ip_check_interval_in_secs = option.ip_check_interval / 1000;
712 Ok(ip_check_interval_in_secs as u32)
713 }
714
715 pub fn enable_interface(&self, if_kind: impl IntoIfKindVec) -> Result<()> {
722 let if_kind_vec = if_kind.into_vec();
723 self.send_cmd(Command::SetOption(DaemonOption::EnableInterface(
724 if_kind_vec.kinds,
725 )))
726 }
727
728 pub fn disable_interface(&self, if_kind: impl IntoIfKindVec) -> Result<()> {
735 let if_kind_vec = if_kind.into_vec();
736 self.send_cmd(Command::SetOption(DaemonOption::DisableInterface(
737 if_kind_vec.kinds,
738 )))
739 }
740
741 pub fn accept_unsolicited(&self, accept: bool) -> Result<()> {
752 self.send_cmd(Command::SetOption(DaemonOption::AcceptUnsolicited(accept)))
753 }
754
755 pub fn include_apple_p2p(&self, include: bool) -> Result<()> {
758 self.send_cmd(Command::SetOption(DaemonOption::IncludeAppleP2P(include)))
759 }
760
761 #[cfg(test)]
762 pub fn test_down_interface(&self, ifname: &str) -> Result<()> {
763 self.send_cmd(Command::SetOption(DaemonOption::TestDownInterface(
764 ifname.to_string(),
765 )))
766 }
767
768 #[cfg(test)]
769 pub fn test_up_interface(&self, ifname: &str) -> Result<()> {
770 self.send_cmd(Command::SetOption(DaemonOption::TestUpInterface(
771 ifname.to_string(),
772 )))
773 }
774
775 pub fn set_multicast_loop_v4(&self, on: bool) -> Result<()> {
791 self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV4(on)))
792 }
793
794 pub fn set_multicast_loop_v6(&self, on: bool) -> Result<()> {
810 self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV6(on)))
811 }
812
813 pub fn verify(&self, instance_fullname: String, timeout: Duration) -> Result<()> {
832 self.send_cmd(Command::Verify(instance_fullname, timeout))
833 }
834
835 fn daemon_thread(
836 signal_sock: MioUdpSocket,
837 poller: Poll,
838 receiver: Receiver<Command>,
839 port: u16,
840 cmd_sender: Sender<Command>,
841 signal_addr: SocketAddr,
842 ) {
843 let mut zc = Zeroconf::new(signal_sock, poller, port, cmd_sender, signal_addr);
844
845 if let Some(cmd) = zc.run(receiver) {
846 match cmd {
847 Command::Exit(resp_s) => {
848 if let Err(e) = resp_s.send(DaemonStatus::Shutdown) {
851 debug!("exit: failed to send response of shutdown: {}", e);
852 }
853 }
854 _ => {
855 debug!("Unexpected command: {:?}", cmd);
856 }
857 }
858 }
859 }
860}
861
862fn _new_socket_bind(intf: &Interface, should_loop: bool) -> Result<MyUdpSocket> {
864 let intf_ip = &intf.ip();
867 match intf_ip {
868 IpAddr::V4(ip) => {
869 let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), MDNS_PORT);
870 let sock = new_socket(addr.into(), true)?;
871
872 sock.join_multicast_v4(&GROUP_ADDR_V4, ip)
874 .map_err(|e| e_fmt!("join multicast group on addr {}: {}", intf_ip, e))?;
875
876 sock.set_multicast_if_v4(ip)
878 .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
879
880 sock.set_multicast_ttl_v4(255)
885 .map_err(|e| e_fmt!("set set_multicast_ttl_v4 on addr {}: {}", ip, e))?;
886
887 if !should_loop {
888 sock.set_multicast_loop_v4(false)
889 .map_err(|e| e_fmt!("failed to set multicast loop v4 for {ip}: {e}"))?;
890 }
891
892 let multicast_addr = SocketAddrV4::new(GROUP_ADDR_V4, MDNS_PORT).into();
894 let test_packets = DnsOutgoing::new(0).to_data_on_wire(MAX_PKT_DEFAULT, true);
895 for packet in test_packets {
896 sock.send_to(&packet, &multicast_addr)
897 .map_err(|e| e_fmt!("send multicast packet on addr {}: {}", ip, e))?;
898 }
899 MyUdpSocket::new(sock)
900 .map_err(|e| e_fmt!("failed to create MySocket for interface {}: {e}", intf.name))
901 }
902 IpAddr::V6(ip) => {
903 let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), MDNS_PORT, 0, 0);
904 let sock = new_socket(addr.into(), true)?;
905
906 let if_index = intf.index.unwrap_or(0);
907
908 sock.join_multicast_v6(&GROUP_ADDR_V6, if_index)
910 .map_err(|e| e_fmt!("join multicast group on addr {}: {}", ip, e))?;
911
912 sock.set_multicast_if_v6(if_index)
914 .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
915
916 MyUdpSocket::new(sock)
921 .map_err(|e| e_fmt!("failed to create MySocket for interface {}: {e}", intf.name))
922 }
923 }
924}
925
926fn new_socket(addr: SocketAddr, non_block: bool) -> Result<PktInfoUdpSocket> {
929 let domain = match addr {
930 SocketAddr::V4(_) => socket2::Domain::IPV4,
931 SocketAddr::V6(_) => socket2::Domain::IPV6,
932 };
933
934 let fd = PktInfoUdpSocket::new(domain).map_err(|e| e_fmt!("create socket failed: {}", e))?;
935
936 fd.set_reuse_address(true)
937 .map_err(|e| e_fmt!("set ReuseAddr failed: {}", e))?;
938 #[cfg(unix)]
939 if let Err(e) = fd.set_reuse_port(true) {
940 debug!(
941 "SO_REUSEPORT is not supported, continuing without it: {}",
942 e
943 );
944 }
945
946 if non_block {
947 fd.set_nonblocking(true)
948 .map_err(|e| e_fmt!("set O_NONBLOCK: {}", e))?;
949 }
950
951 fd.bind(&addr.into())
952 .map_err(|e| e_fmt!("socket bind to {} failed: {}", &addr, e))?;
953
954 trace!("new socket bind to {}", &addr);
955 Ok(fd)
956}
957
958struct ReRun {
960 next_time: Instant,
961 command: Command,
962}
963
964struct DelayedResponse {
966 next_time: Instant,
968 out: DnsOutgoing,
969 if_index: u32,
970 is_ipv4: bool,
971}
972
973#[derive(Debug, Clone)]
977#[non_exhaustive]
978pub enum IfKind {
979 All,
981
982 IPv4,
984
985 IPv6,
987
988 Name(String),
990
991 Addr(IpAddr),
995
996 LoopbackV4,
1000
1001 LoopbackV6,
1003
1004 IndexV4(u32),
1006
1007 IndexV6(u32),
1009
1010 Predicate(IfPredicate),
1012}
1013
1014impl IfKind {
1015 pub(crate) fn matches(&self, intf: &Interface) -> bool {
1017 match self {
1018 Self::All => true,
1019 Self::IPv4 => intf.ip().is_ipv4(),
1020 Self::IPv6 => intf.ip().is_ipv6(),
1021 Self::Name(ifname) => ifname == &intf.name,
1022 Self::Addr(addr) => addr == &intf.ip(),
1023 Self::LoopbackV4 => intf.is_loopback() && intf.ip().is_ipv4(),
1024 Self::LoopbackV6 => intf.is_loopback() && intf.ip().is_ipv6(),
1025 Self::IndexV4(idx) => intf.index == Some(*idx) && intf.ip().is_ipv4(),
1026 Self::IndexV6(idx) => intf.index == Some(*idx) && intf.ip().is_ipv6(),
1027 Self::Predicate(p) => p.matches(intf),
1028 }
1029 }
1030}
1031
1032impl From<&str> for IfKind {
1035 fn from(val: &str) -> Self {
1036 Self::Name(val.to_string())
1037 }
1038}
1039
1040impl From<&String> for IfKind {
1041 fn from(val: &String) -> Self {
1042 Self::Name(val.to_string())
1043 }
1044}
1045
1046impl From<IpAddr> for IfKind {
1048 fn from(val: IpAddr) -> Self {
1049 Self::Addr(val)
1050 }
1051}
1052
1053pub struct IfKindVec {
1055 kinds: Vec<IfKind>,
1056}
1057
1058pub trait IntoIfKindVec {
1060 fn into_vec(self) -> IfKindVec;
1061}
1062
1063impl<T: Into<IfKind>> IntoIfKindVec for T {
1064 fn into_vec(self) -> IfKindVec {
1065 let if_kind: IfKind = self.into();
1066 IfKindVec {
1067 kinds: vec![if_kind],
1068 }
1069 }
1070}
1071
1072impl<T: Into<IfKind>> IntoIfKindVec for Vec<T> {
1073 fn into_vec(self) -> IfKindVec {
1074 let kinds: Vec<IfKind> = self.into_iter().map(|x| x.into()).collect();
1075 IfKindVec { kinds }
1076 }
1077}
1078
1079#[derive(Clone)]
1081pub struct IfPredicate(std::sync::Arc<dyn Fn(&Interface) -> bool + Send + Sync>);
1082
1083impl IfPredicate {
1084 pub fn new(predicate: impl Fn(&Interface) -> bool + Send + Sync + 'static) -> Self {
1095 Self(std::sync::Arc::new(predicate))
1096 }
1097
1098 pub(crate) fn matches(&self, intf: &Interface) -> bool {
1099 self.0(intf)
1100 }
1101}
1102
1103impl std::fmt::Debug for IfPredicate {
1104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1105 write!(f, "IfPredicate(...)")
1106 }
1107}
1108
1109struct IfSelection {
1111 if_kind: IfKind,
1113
1114 selected: bool,
1116}
1117
1118struct MaxPacketSizeSelection {
1120 if_kind: IfKind,
1122
1123 max_packet_size: usize,
1125}
1126
1127struct Zeroconf {
1129 port: u16,
1132
1133 my_intfs: HashMap<u32, MyIntf>,
1135
1136 ipv4_sock: Option<MyUdpSocket>,
1138
1139 ipv6_sock: Option<MyUdpSocket>,
1141
1142 my_services: HashMap<String, ServiceInfo>,
1144
1145 cache: DnsCache,
1147
1148 dns_registry_map: HashMap<u32, DnsRegistry>,
1150
1151 service_queriers: HashMap<String, Sender<ServiceEvent>>, hostname_resolvers: HashMap<String, (Sender<HostnameResolutionEvent>, Option<Instant>)>, retransmissions: Vec<ReRun>,
1162
1163 delayed_responses: Vec<DelayedResponse>,
1165
1166 counters: Metrics,
1167
1168 poller: Poll,
1170
1171 monitors: Vec<Sender<DaemonEvent>>,
1173
1174 service_name_len_max: u8,
1176
1177 ip_check_interval: u64,
1179
1180 next_ip_check: Option<Instant>,
1182
1183 max_packet_sizes: Vec<MaxPacketSizeSelection>,
1186
1187 if_selections: Vec<IfSelection>,
1189
1190 signal_sock: MioUdpSocket,
1192
1193 timers: BinaryHeap<Reverse<Instant>>,
1199
1200 status: DaemonStatus,
1201
1202 pending_resolves: HashSet<String>,
1204
1205 resolved: HashSet<String>,
1207
1208 multicast_loop_v4: bool,
1209
1210 multicast_loop_v6: bool,
1211
1212 accept_unsolicited: bool,
1213
1214 include_apple_p2p: bool,
1215
1216 cmd_sender: Sender<Command>,
1217
1218 signal_addr: SocketAddr,
1219
1220 #[cfg(test)]
1221 test_down_interfaces: HashSet<String>,
1222}
1223
1224fn join_multicast_v4(my_sock: &PktInfoUdpSocket, ip: &Ipv4Addr) -> io::Result<()> {
1231 match my_sock.join_multicast_v4(&GROUP_ADDR_V4, ip) {
1232 Err(e) if e.kind() == io::ErrorKind::AddrInUse => {
1233 debug!("multicast group V4 already joined on addr {ip}");
1234 Ok(())
1235 }
1236 result => result,
1237 }
1238}
1239
1240fn join_multicast_group(my_sock: &PktInfoUdpSocket, intf: &Interface) -> Result<()> {
1242 let intf_ip = &intf.ip();
1243 match intf_ip {
1244 IpAddr::V4(ip) => {
1245 debug!("join multicast group V4 on {} addr {ip}", intf.name);
1247 join_multicast_v4(my_sock, ip)
1248 .map_err(|e| e_fmt!("PKT join multicast group on addr {}: {}", intf_ip, e))?;
1249 }
1250 IpAddr::V6(ip) => {
1251 let if_index = intf.index.unwrap_or(0);
1252 debug!(
1254 "join multicast group V6 on {} addr {ip} with index {if_index}",
1255 intf.name
1256 );
1257 my_sock
1258 .join_multicast_v6(&GROUP_ADDR_V6, if_index)
1259 .map_err(|e| e_fmt!("PKT join multicast group on addr {}: {}", ip, e))?;
1260 }
1261 }
1262 Ok(())
1263}
1264
1265fn new_multicast_socket(addr: SocketAddr) -> Result<MyUdpSocket> {
1271 let sock = new_socket(addr, true)?;
1272
1273 let ttl_result = match addr {
1278 SocketAddr::V4(_) => sock.set_multicast_ttl_v4(255),
1279 SocketAddr::V6(_) => sock.set_multicast_hops_v6(255),
1280 };
1281 if let Err(e) = ttl_result {
1282 debug!("failed to set multicast TTL on {addr}: {e}");
1283 }
1284
1285 MyUdpSocket::new(sock).map_err(|e| e_fmt!("create MyUdpSocket for {}: {}", addr, e))
1287}
1288
1289impl Zeroconf {
1290 fn new(
1291 signal_sock: MioUdpSocket,
1292 poller: Poll,
1293 port: u16,
1294 cmd_sender: Sender<Command>,
1295 signal_addr: SocketAddr,
1296 ) -> Self {
1297 let my_ifaddrs = my_ip_interfaces(true);
1299
1300 let mut my_intfs = HashMap::new();
1304 let mut dns_registry_map = HashMap::new();
1305
1306 let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port);
1309 let ipv4_sock = new_multicast_socket(addr.into());
1310 if let Err(e) = &ipv4_sock {
1311 debug!("failed to set up IPv4 socket: {e}");
1312 }
1313 let ipv4_sock = ipv4_sock.ok();
1314
1315 let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), port, 0, 0);
1316 let ipv6_sock = new_multicast_socket(addr.into());
1317 if let Err(e) = &ipv6_sock {
1318 debug!("failed to set up IPv6 socket: {e}");
1319 }
1320 let ipv6_sock = ipv6_sock.ok();
1321
1322 for intf in my_ifaddrs {
1324 let sock_opt = if intf.ip().is_ipv4() {
1325 &ipv4_sock
1326 } else {
1327 &ipv6_sock
1328 };
1329 let Some(sock) = sock_opt else {
1330 debug!(
1331 "no socket available for interface {} with addr {}. Skipped.",
1332 intf.name,
1333 intf.ip()
1334 );
1335 continue;
1336 };
1337
1338 if let Err(e) = join_multicast_group(&sock.pktinfo, &intf) {
1339 debug!("failed to join multicast: {}: {e}. Skipped.", &intf.ip());
1340 }
1341
1342 let if_index = intf.index.unwrap_or(0);
1343
1344 dns_registry_map
1346 .entry(if_index)
1347 .or_insert_with(DnsRegistry::new);
1348
1349 my_intfs
1350 .entry(if_index)
1351 .and_modify(|v: &mut MyIntf| {
1352 v.addrs.insert(intf.addr.clone());
1353 })
1354 .or_insert(MyIntf {
1355 name: intf.name.clone(),
1356 index: if_index,
1357 addrs: HashSet::from([intf.addr]),
1358 max_packet_size_v4: MAX_PKT_DEFAULT,
1359 max_packet_size_v6: MAX_PKT_DEFAULT,
1360 });
1361 }
1362
1363 let monitors = Vec::new();
1364 let service_name_len_max = SERVICE_NAME_LEN_MAX_DEFAULT;
1365 let ip_check_interval = IP_CHECK_INTERVAL_IN_SECS_DEFAULT as u64 * 1000;
1366
1367 let timers = BinaryHeap::new();
1368
1369 let if_selections = vec![];
1371
1372 let status = DaemonStatus::Running;
1373
1374 Self {
1375 port,
1376 my_intfs,
1377 ipv4_sock,
1378 ipv6_sock,
1379 my_services: HashMap::new(),
1380 cache: DnsCache::new(),
1381 dns_registry_map,
1382 hostname_resolvers: HashMap::new(),
1383 service_queriers: HashMap::new(),
1384 retransmissions: Vec::new(),
1385 delayed_responses: Vec::new(),
1386 counters: HashMap::new(),
1387 poller,
1388 monitors,
1389 service_name_len_max,
1390 ip_check_interval,
1391 next_ip_check: None,
1392 max_packet_sizes: Vec::new(),
1393 if_selections,
1394 signal_sock,
1395 timers,
1396 status,
1397 pending_resolves: HashSet::new(),
1398 resolved: HashSet::new(),
1399 multicast_loop_v4: true,
1400 multicast_loop_v6: true,
1401 accept_unsolicited: false,
1402 include_apple_p2p: false,
1403 cmd_sender,
1404 signal_addr,
1405
1406 #[cfg(test)]
1407 test_down_interfaces: HashSet::new(),
1408 }
1409 }
1410
1411 fn send_cmd_to_self(&self, cmd: Command) -> Result<()> {
1413 let cmd_name = cmd.to_string();
1414
1415 self.cmd_sender.try_send(cmd).map_err(|e| match e {
1416 TrySendError::Full(_) => Error::Again,
1417 TrySendError::Disconnected(_) => Error::DaemonShutdown,
1418 })?;
1419
1420 let addr = SocketAddrV4::new(LOOPBACK_V4, 0);
1421 let socket = UdpSocket::bind(addr)
1422 .map_err(|e| e_fmt!("Failed to create socket to send signal: {}", e))?;
1423 socket
1424 .send_to(cmd_name.as_bytes(), self.signal_addr)
1425 .map_err(|e| {
1426 e_fmt!(
1427 "signal socket send_to {} ({}) failed: {}",
1428 self.signal_addr,
1429 cmd_name,
1430 e
1431 )
1432 })?;
1433
1434 Ok(())
1435 }
1436
1437 fn cleanup(&mut self) {
1446 debug!("Starting cleanup for shutdown");
1447
1448 let service_names: Vec<String> = self.my_services.keys().cloned().collect();
1450 for fullname in service_names {
1451 if let Some(info) = self.my_services.get(&fullname) {
1452 debug!("Unregistering service during shutdown: {}", &fullname);
1453
1454 for intf in self.my_intfs.values() {
1455 if let Some(sock) = self.ipv4_sock.as_ref() {
1456 self.unregister_service(info, intf, &sock.pktinfo);
1457 }
1458
1459 if let Some(sock) = self.ipv6_sock.as_ref() {
1460 self.unregister_service(info, intf, &sock.pktinfo);
1461 }
1462 }
1463 }
1464 }
1465 self.my_services.clear();
1466
1467 let browse_types: Vec<String> = self.service_queriers.keys().cloned().collect();
1469 for ty_domain in browse_types {
1470 debug!("Stopping browse during shutdown: {}", &ty_domain);
1471 if let Some(sender) = self.service_queriers.remove(&ty_domain) {
1472 if let Err(e) = sender.send(ServiceEvent::SearchStopped(ty_domain.clone())) {
1474 debug!("Failed to send SearchStopped during shutdown: {}", e);
1475 }
1476 }
1477 }
1478
1479 let hostnames: Vec<String> = self.hostname_resolvers.keys().cloned().collect();
1481 for hostname in hostnames {
1482 debug!(
1483 "Stopping hostname resolution during shutdown: {}",
1484 &hostname
1485 );
1486 if let Some((sender, _timeout)) = self.hostname_resolvers.remove(&hostname) {
1487 if let Err(e) =
1489 sender.send(HostnameResolutionEvent::SearchStopped(hostname.clone()))
1490 {
1491 debug!(
1492 "Failed to send HostnameResolutionEvent::SearchStopped during shutdown: {}",
1493 e
1494 );
1495 }
1496 }
1497 }
1498
1499 self.retransmissions.clear();
1501
1502 self.delayed_responses.clear();
1504
1505 debug!("Cleanup completed");
1506 }
1507
1508 fn run(&mut self, receiver: Receiver<Command>) -> Option<Command> {
1517 if let Err(e) = self.poller.registry().register(
1519 &mut self.signal_sock,
1520 mio::Token(SIGNAL_SOCK_EVENT_KEY),
1521 mio::Interest::READABLE,
1522 ) {
1523 debug!("failed to add signal socket to the poller: {}", e);
1524 return None;
1525 }
1526
1527 if let Some(sock) = self.ipv4_sock.as_mut() {
1528 if let Err(e) = self.poller.registry().register(
1529 sock,
1530 mio::Token(IPV4_SOCK_EVENT_KEY),
1531 mio::Interest::READABLE,
1532 ) {
1533 debug!("failed to register ipv4 socket: {}", e);
1534 return None;
1535 }
1536 }
1537
1538 if let Some(sock) = self.ipv6_sock.as_mut() {
1539 if let Err(e) = self.poller.registry().register(
1540 sock,
1541 mio::Token(IPV6_SOCK_EVENT_KEY),
1542 mio::Interest::READABLE,
1543 ) {
1544 debug!("failed to register ipv6 socket: {}", e);
1545 return None;
1546 }
1547 }
1548
1549 self.schedule_ip_check(Instant::now());
1551
1552 let mut last_now = Instant::now();
1554 let mut last_wall_now = SystemTime::now();
1555
1556 let mut events = mio::Events::with_capacity(1024);
1559 loop {
1560 let now = Instant::now();
1561
1562 let earliest_timer = self.peek_earliest_timer();
1563 let timeout = earliest_timer.map(|timer| {
1564 timer
1566 .saturating_duration_since(now)
1567 .max(Duration::from_millis(1))
1568 });
1569
1570 events.clear();
1572 match self.poller.poll(&mut events, timeout) {
1573 Ok(_) => self.handle_poller_events(&events),
1574 Err(e) => debug!("failed to select from sockets: {}", e),
1575 }
1576
1577 let now = Instant::now();
1578
1579 let wall_now = SystemTime::now();
1581 if let Some(slept) = slept_duration(
1582 now.saturating_duration_since(last_now),
1583 wall_now.duration_since(last_wall_now).ok(),
1584 ) {
1585 debug!("system slept for about {:?}: aging cached records", slept);
1586 self.cache.age_records(slept);
1587 }
1588 last_now = now;
1589 last_wall_now = wall_now;
1590
1591 self.pop_timers_till(now);
1593
1594 for hostname in self
1596 .hostname_resolvers
1597 .clone()
1598 .into_iter()
1599 .filter(|(_, (_, timeout))| timeout.map(|t| now >= t).unwrap_or(false))
1600 .map(|(hostname, _)| hostname)
1601 {
1602 trace!("hostname resolver timeout for {}", &hostname);
1603 call_hostname_resolution_listener(
1604 &self.hostname_resolvers,
1605 &hostname,
1606 HostnameResolutionEvent::SearchTimeout(hostname.to_owned()),
1607 );
1608 call_hostname_resolution_listener(
1609 &self.hostname_resolvers,
1610 &hostname,
1611 HostnameResolutionEvent::SearchStopped(hostname.to_owned()),
1612 );
1613 self.hostname_resolvers.remove(&hostname);
1614 }
1615
1616 while let Ok(command) = receiver.try_recv() {
1618 if matches!(command, Command::Exit(_)) {
1619 debug!("Exit command received, performing cleanup");
1620 self.cleanup();
1621 self.status = DaemonStatus::Shutdown;
1622 return Some(command);
1623 }
1624 self.exec_command(command, false);
1625 }
1626
1627 let mut i = 0;
1629 while i < self.retransmissions.len() {
1630 if now >= self.retransmissions[i].next_time {
1631 let rerun = self.retransmissions.remove(i);
1632 self.exec_command(rerun.command, true);
1633 } else {
1634 i += 1;
1635 }
1636 }
1637
1638 let mut i = 0;
1640 while i < self.delayed_responses.len() {
1641 if now >= self.delayed_responses[i].next_time {
1642 let resp = self.delayed_responses.remove(i);
1643 self.send_delayed_response(resp);
1644 } else {
1645 i += 1;
1646 }
1647 }
1648
1649 self.refresh_active_services();
1651
1652 let mut query_count = 0;
1654 for (hostname, _sender) in self.hostname_resolvers.iter() {
1655 for (hostname, ip_addr) in
1656 self.cache.refresh_due_hostname_resolutions(hostname).iter()
1657 {
1658 self.send_query(hostname, ip_address_rr_type(&ip_addr.to_ip_addr()));
1659 query_count += 1;
1660 }
1661 }
1662
1663 self.increase_counter(Counter::CacheRefreshAddr, query_count);
1664
1665 let now = Instant::now();
1667
1668 let expired_services = self.cache.evict_expired_services(now);
1670 if !expired_services.is_empty() {
1671 debug!(
1672 "run: send {} service removal to listeners",
1673 expired_services.len()
1674 );
1675 self.notify_service_removal(expired_services);
1676 }
1677
1678 let expired_addrs = self.cache.evict_expired_addr(now);
1680 for (hostname, addrs) in expired_addrs {
1681 call_hostname_resolution_listener(
1682 &self.hostname_resolvers,
1683 &hostname,
1684 HostnameResolutionEvent::AddressesRemoved(hostname.clone(), addrs),
1685 );
1686 let instances = self.cache.get_instances_on_host(&hostname);
1687 let instance_set: HashSet<String> = instances.into_iter().collect();
1688 self.resolve_updated_instances(&instance_set);
1689 }
1690
1691 self.probing_handler();
1693
1694 if self.next_ip_check.is_some_and(|t| now >= t) {
1696 self.schedule_ip_check(now);
1697 self.check_ip_changes();
1698 }
1699 }
1700 }
1701
1702 fn process_set_option(&mut self, daemon_opt: DaemonOption) {
1703 match daemon_opt {
1704 DaemonOption::ServiceNameLenMax(length) => self.service_name_len_max = length,
1705 DaemonOption::IpCheckInterval(interval) => {
1706 self.ip_check_interval = interval;
1707 self.schedule_ip_check(Instant::now());
1708 }
1709 DaemonOption::MaxPacketSize(if_kind, size) => self.set_max_packet_size(if_kind, size),
1710 DaemonOption::EnableInterface(if_kind) => self.enable_interface(if_kind),
1711 DaemonOption::DisableInterface(if_kind) => self.disable_interface(if_kind),
1712 DaemonOption::MulticastLoopV4(on) => self.set_multicast_loop_v4(on),
1713 DaemonOption::MulticastLoopV6(on) => self.set_multicast_loop_v6(on),
1714 DaemonOption::AcceptUnsolicited(accept) => self.set_accept_unsolicited(accept),
1715 DaemonOption::IncludeAppleP2P(enable) => self.set_apple_p2p(enable),
1716 #[cfg(test)]
1717 DaemonOption::TestDownInterface(ifname) => {
1718 self.test_down_interfaces.insert(ifname);
1719 }
1720 #[cfg(test)]
1721 DaemonOption::TestUpInterface(ifname) => {
1722 self.test_down_interfaces.remove(&ifname);
1723 }
1724 }
1725 }
1726
1727 fn enable_interface(&mut self, kinds: Vec<IfKind>) {
1728 debug!("enable_interface: {:?}", kinds);
1729 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1730
1731 for if_kind in kinds {
1732 self.if_selections.push(IfSelection {
1733 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1734 selected: true,
1735 });
1736 }
1737
1738 self.apply_intf_selections(interfaces);
1739 }
1740
1741 fn disable_interface(&mut self, kinds: Vec<IfKind>) {
1742 debug!("disable_interface: {:?}", kinds);
1743 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1744
1745 for if_kind in kinds {
1746 self.if_selections.push(IfSelection {
1747 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1748 selected: false,
1749 });
1750 }
1751
1752 self.apply_intf_selections(interfaces);
1753 }
1754
1755 fn set_max_packet_size(&mut self, kinds: Vec<IfKind>, size: usize) {
1756 debug!("set_max_packet_size: {:?} {}", kinds, size);
1757 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1758
1759 for if_kind in kinds {
1760 self.max_packet_sizes.push(MaxPacketSizeSelection {
1761 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1762 max_packet_size: size,
1763 });
1764 }
1765
1766 self.apply_max_packet_sizes(&interfaces);
1767 }
1768
1769 fn apply_max_packet_sizes(&mut self, interfaces: &[Interface]) {
1772 for (if_index, my_intf) in self.my_intfs.iter_mut() {
1773 let v4 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, *if_index, true);
1774 let v6 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, *if_index, false);
1775
1776 if my_intf.max_packet_size_v4 != v4 || my_intf.max_packet_size_v6 != v6 {
1777 debug!(
1778 "interface {}: max packet size v4 {} -> {v4}, v6 {} -> {v6}",
1779 my_intf.name, my_intf.max_packet_size_v4, my_intf.max_packet_size_v6
1780 );
1781 my_intf.max_packet_size_v4 = v4;
1782 my_intf.max_packet_size_v6 = v6;
1783 }
1784 }
1785 }
1786
1787 fn set_multicast_loop_v4(&mut self, on: bool) {
1788 let Some(sock) = self.ipv4_sock.as_mut() else {
1789 return;
1790 };
1791 self.multicast_loop_v4 = on;
1792 sock.pktinfo
1793 .set_multicast_loop_v4(on)
1794 .map_err(|e| e_fmt!("failed to set multicast loop v4: {}", e))
1795 .unwrap();
1796 }
1797
1798 fn set_multicast_loop_v6(&mut self, on: bool) {
1799 let Some(sock) = self.ipv6_sock.as_mut() else {
1800 return;
1801 };
1802 self.multicast_loop_v6 = on;
1803 sock.pktinfo
1804 .set_multicast_loop_v6(on)
1805 .map_err(|e| e_fmt!("failed to set multicast loop v6: {}", e))
1806 .unwrap();
1807 }
1808
1809 fn set_accept_unsolicited(&mut self, accept: bool) {
1810 self.accept_unsolicited = accept;
1811 }
1812
1813 fn set_apple_p2p(&mut self, include: bool) {
1814 if self.include_apple_p2p != include {
1815 self.include_apple_p2p = include;
1816 self.apply_intf_selections(my_ip_interfaces_inner(true, self.include_apple_p2p));
1817 }
1818 }
1819
1820 fn notify_monitors(&mut self, event: DaemonEvent) {
1821 self.monitors.retain(|sender| {
1823 if let Err(e) = sender.try_send(event.clone()) {
1824 debug!("notify_monitors: try_send: {}", &e);
1825 if matches!(e, TrySendError::Disconnected(_)) {
1826 return false; }
1828 }
1829 true
1830 });
1831 }
1832
1833 fn del_addr_in_my_services(&mut self, addr: &IpAddr) {
1835 for (_, service_info) in self.my_services.iter_mut() {
1836 if service_info.is_addr_auto() {
1837 service_info.remove_ipaddr(addr);
1838 }
1839 }
1840 }
1841
1842 fn schedule_ip_check(&mut self, now: Instant) {
1845 self.next_ip_check = (self.ip_check_interval > 0)
1846 .then(|| now + Duration::from_millis(self.ip_check_interval));
1847 if let Some(t) = self.next_ip_check {
1848 self.add_timer(t);
1849 }
1850 }
1851
1852 fn add_timer(&mut self, next_time: Instant) {
1853 self.timers.push(Reverse(next_time));
1854 }
1855
1856 fn peek_earliest_timer(&self) -> Option<Instant> {
1857 self.timers.peek().map(|Reverse(v)| *v)
1858 }
1859
1860 fn _pop_earliest_timer(&mut self) -> Option<Instant> {
1861 self.timers.pop().map(|Reverse(v)| v)
1862 }
1863
1864 fn pop_timers_till(&mut self, now: Instant) {
1866 while let Some(Reverse(v)) = self.timers.peek() {
1867 if *v > now {
1868 break;
1869 }
1870 self.timers.pop();
1871 }
1872 }
1873
1874 fn selected_intfs(&self, interfaces: Vec<Interface>) -> HashSet<Interface> {
1876 let intf_count = interfaces.len();
1877 let mut intf_selections = vec![true; intf_count];
1878
1879 for selection in self.if_selections.iter() {
1881 for i in 0..intf_count {
1883 if selection.if_kind.matches(&interfaces[i]) {
1884 intf_selections[i] = selection.selected;
1885 }
1886 }
1887 }
1888
1889 let mut selected_addrs = HashSet::new();
1890 for i in 0..intf_count {
1891 if intf_selections[i] {
1892 selected_addrs.insert(interfaces[i].clone());
1893 }
1894 }
1895
1896 selected_addrs
1897 }
1898
1899 fn apply_intf_selections(&mut self, interfaces: Vec<Interface>) {
1904 let intf_count = interfaces.len();
1906 let mut intf_selections = vec![true; intf_count];
1907
1908 for selection in self.if_selections.iter() {
1910 for i in 0..intf_count {
1912 if selection.if_kind.matches(&interfaces[i]) {
1913 intf_selections[i] = selection.selected;
1914 }
1915 }
1916 }
1917
1918 for (idx, intf) in interfaces.iter().enumerate() {
1920 if intf_selections[idx] {
1921 self.add_interface(intf, &interfaces);
1923 } else {
1924 self.del_interface_addr(intf);
1926 }
1927 }
1928
1929 self.apply_max_packet_sizes(&interfaces);
1932 }
1933
1934 fn del_ip(&mut self, ip: IpAddr) {
1935 self.del_addr_in_my_services(&ip);
1936 self.notify_monitors(DaemonEvent::IpDel(ip));
1937 }
1938
1939 fn check_ip_changes(&mut self) {
1941 let my_ifaddrs = my_ip_interfaces_inner(true, self.include_apple_p2p);
1943
1944 #[cfg(test)]
1945 let my_ifaddrs: Vec<_> = my_ifaddrs
1946 .into_iter()
1947 .filter(|intf| !self.test_down_interfaces.contains(&intf.name))
1948 .collect();
1949
1950 let ifaddrs_map: HashMap<u32, Vec<&IfAddr>> =
1951 my_ifaddrs.iter().fold(HashMap::new(), |mut acc, intf| {
1952 let if_index = intf.index.unwrap_or(0);
1953 acc.entry(if_index).or_default().push(&intf.addr);
1954 acc
1955 });
1956
1957 let mut deleted_intfs = Vec::new();
1958 let mut deleted_ips = Vec::new();
1959
1960 for (if_index, my_intf) in self.my_intfs.iter_mut() {
1961 let mut last_ipv4 = None;
1962 let mut last_ipv6 = None;
1963
1964 if let Some(current_addrs) = ifaddrs_map.get(if_index) {
1965 my_intf.addrs.retain(|addr| {
1966 if current_addrs.contains(&addr) {
1967 true
1968 } else {
1969 match addr.ip() {
1970 IpAddr::V4(ipv4) => last_ipv4 = Some(ipv4),
1971 IpAddr::V6(ipv6) => last_ipv6 = Some(ipv6),
1972 }
1973 deleted_ips.push(addr.ip());
1974 false
1975 }
1976 });
1977 if my_intf.addrs.is_empty() {
1978 deleted_intfs.push((*if_index, last_ipv4, last_ipv6))
1979 }
1980 } else {
1981 debug!(
1983 "check_ip_changes: interface {} ({}) no longer exists, removing",
1984 my_intf.name, if_index
1985 );
1986 for addr in my_intf.addrs.iter() {
1987 match addr.ip() {
1988 IpAddr::V4(ipv4) => last_ipv4 = Some(ipv4),
1989 IpAddr::V6(ipv6) => last_ipv6 = Some(ipv6),
1990 }
1991 deleted_ips.push(addr.ip())
1992 }
1993 deleted_intfs.push((*if_index, last_ipv4, last_ipv6));
1994 }
1995 }
1996
1997 if !deleted_ips.is_empty() || !deleted_intfs.is_empty() {
1998 debug!(
1999 "check_ip_changes: {} deleted ips {} deleted intfs",
2000 deleted_ips.len(),
2001 deleted_intfs.len()
2002 );
2003 }
2004
2005 for (if_index, last_ipv4, last_ipv6) in deleted_intfs {
2006 let Some(my_intf) = self.my_intfs.remove(&if_index) else {
2007 continue;
2008 };
2009
2010 if let Some(ipv4) = last_ipv4 {
2011 if self.intfs_with_ip(&IpAddr::V4(ipv4)).next().is_some() {
2012 debug!("keep multicast for {ipv4}: still used by another interface");
2014 } else if let Some(sock) = self.ipv4_sock.as_mut() {
2015 debug!("leave multicast for {ipv4}");
2016 if let Err(e) = sock.pktinfo.leave_multicast_v4(&GROUP_ADDR_V4, &ipv4) {
2017 debug!("leave multicast group for addr {ipv4}: {e}");
2018 }
2019 }
2020 }
2021
2022 if let Some(ipv6) = last_ipv6 {
2023 debug!("leave multicast for {ipv6}");
2024 if let Some(sock) = self.ipv6_sock.as_mut() {
2025 if let Err(e) = sock
2026 .pktinfo
2027 .leave_multicast_v6(&GROUP_ADDR_V6, my_intf.index)
2028 {
2029 debug!("leave multicast group for IPv6: {ipv6}: {e}");
2030 }
2031 }
2032 }
2033
2034 let intf_id = InterfaceId {
2036 name: my_intf.name.to_string(),
2037 index: my_intf.index,
2038 };
2039 let result = self.cache.remove_records_on_intf(intf_id);
2040 self.notify_service_removal(result.removed_instances);
2041 self.resolve_updated_instances(&result.modified_instances);
2042 }
2043
2044 deleted_ips.sort();
2047 deleted_ips.dedup();
2048 for ip in deleted_ips {
2049 if self.intfs_with_ip(&ip).next().is_none() {
2050 self.del_ip(ip);
2051 continue;
2052 }
2053
2054 if let (IpAddr::V4(ipv4), Some(sock)) = (ip, self.ipv4_sock.as_ref()) {
2058 if let Err(e) = join_multicast_v4(&sock.pktinfo, &ipv4) {
2059 debug!("check_ip_changes: rejoin multicast group on addr {ipv4}: {e}");
2060 }
2061 }
2062 }
2063
2064 self.apply_intf_selections(my_ifaddrs);
2066 }
2067
2068 fn del_interface_addr(&mut self, intf: &Interface) {
2071 let if_index = intf.index.unwrap_or(0);
2072 debug!(
2073 "del_interface_addr: {} ({if_index}) addr {}",
2074 intf.name,
2075 intf.ip()
2076 );
2077
2078 let shared = self.intfs_with_ip(&intf.ip()).any(|i| i != if_index);
2081
2082 let Some(my_intf) = self.my_intfs.get_mut(&if_index) else {
2083 debug!("del_interface_addr: interface {} not found", intf.name);
2084 return;
2085 };
2086
2087 let mut ip_removed = false;
2088
2089 if my_intf.addrs.remove(&intf.addr) {
2090 ip_removed = true;
2091
2092 match intf.addr.ip() {
2093 IpAddr::V4(ipv4) => {
2094 if shared {
2095 debug!("keep multicast for {ipv4}: still used by another interface");
2096 } else if my_intf.next_ifaddr_v4().is_none() {
2097 if let Some(sock) = self.ipv4_sock.as_mut() {
2098 if let Err(e) = sock.pktinfo.leave_multicast_v4(&GROUP_ADDR_V4, &ipv4) {
2099 debug!("leave multicast group for addr {ipv4}: {e}");
2100 } else {
2101 debug!("leave multicast for {ipv4}");
2102 }
2103 }
2104 }
2105 }
2106
2107 IpAddr::V6(ipv6) => {
2108 if my_intf.next_ifaddr_v6().is_none() {
2109 if let Some(sock) = self.ipv6_sock.as_mut() {
2110 if let Err(e) =
2111 sock.pktinfo.leave_multicast_v6(&GROUP_ADDR_V6, if_index)
2112 {
2113 debug!("leave multicast group for addr {ipv6}: {e}");
2114 }
2115 }
2116 }
2117 }
2118 }
2119
2120 if my_intf.addrs.is_empty() {
2121 debug!("del_interface_addr: removing interface {}", intf.name);
2123 self.my_intfs.remove(&if_index);
2124 self.dns_registry_map.remove(&if_index);
2125 self.cache
2126 .remove_addrs_on_disabled_intf(if_index, IpType::BOTH);
2127 } else {
2128 let is_v4 = intf.addr.ip().is_ipv4();
2132 let version_gone = if is_v4 {
2133 my_intf.next_ifaddr_v4().is_none()
2134 } else {
2135 my_intf.next_ifaddr_v6().is_none()
2136 };
2137 if version_gone {
2138 let ip_type = if is_v4 { IpType::V4 } else { IpType::V6 };
2139 self.cache.remove_addrs_on_disabled_intf(if_index, ip_type);
2140 }
2141 }
2142 }
2143
2144 if ip_removed && !shared {
2145 self.notify_monitors(DaemonEvent::IpDel(intf.ip()));
2147 self.del_addr_in_my_services(&intf.ip());
2149 }
2150 }
2151
2152 fn intfs_with_ip<'a>(&'a self, ip: &'a IpAddr) -> impl Iterator<Item = u32> + 'a {
2154 self.my_intfs
2155 .values()
2156 .filter(move |my_intf| my_intf.addrs.iter().any(|addr| addr.ip() == *ip))
2157 .map(|my_intf| my_intf.index)
2158 }
2159
2160 fn add_interface(&mut self, intf: &Interface, interfaces: &[Interface]) {
2174 let sock_opt = if intf.ip().is_ipv4() {
2175 &self.ipv4_sock
2176 } else {
2177 &self.ipv6_sock
2178 };
2179
2180 let Some(sock) = sock_opt else {
2181 debug!(
2182 "add_interface: no socket available for interface {} with addr {}. Skipped.",
2183 intf.name,
2184 intf.ip()
2185 );
2186 return;
2187 };
2188
2189 let if_index = intf.index.unwrap_or(0);
2190 let mut new_addr = false;
2191
2192 match self.my_intfs.entry(if_index) {
2193 Entry::Occupied(mut entry) => {
2194 let my_intf = entry.get_mut();
2196 if !my_intf.addrs.contains(&intf.addr) {
2197 if let Err(e) = join_multicast_group(&sock.pktinfo, intf) {
2198 debug!("add_interface: socket_config {}: {e}", &intf.name);
2199 }
2200 my_intf.addrs.insert(intf.addr.clone());
2201 new_addr = true;
2202 }
2203 }
2204 Entry::Vacant(entry) => {
2205 if let Err(e) = join_multicast_group(&sock.pktinfo, intf) {
2206 debug!("add_interface: socket_config {}: {e}. Skipped.", &intf.name);
2207 return;
2208 }
2209
2210 new_addr = true;
2211 let new_intf = MyIntf {
2212 name: intf.name.clone(),
2213 index: if_index,
2214 addrs: HashSet::from([intf.addr.clone()]),
2215 max_packet_size_v4: MAX_PKT_DEFAULT,
2216 max_packet_size_v6: MAX_PKT_DEFAULT,
2217 };
2218 entry.insert(new_intf);
2219 }
2220 }
2221
2222 if !new_addr {
2223 trace!("add_interface: interface {} already exists", &intf.name);
2224 return;
2225 }
2226
2227 debug!("add new interface {}: {}", intf.name, intf.ip());
2228
2229 let v4 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, if_index, true);
2231 let v6 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, if_index, false);
2232 if let Some(my_intf) = self.my_intfs.get_mut(&if_index) {
2233 my_intf.max_packet_size_v4 = v4;
2234 my_intf.max_packet_size_v6 = v6;
2235 }
2236
2237 let Some(my_intf) = self.my_intfs.get(&if_index) else {
2238 debug!("add_interface: cannot find if_index {if_index}");
2239 return;
2240 };
2241
2242 let dns_registry = match self.dns_registry_map.get_mut(&if_index) {
2243 Some(registry) => registry,
2244 None => self
2245 .dns_registry_map
2246 .entry(if_index)
2247 .or_insert_with(DnsRegistry::new),
2248 };
2249
2250 for (_, service_info) in self.my_services.iter_mut() {
2251 if service_info.is_addr_auto() {
2252 if !service_info.insert_ipaddr(intf) {
2253 continue;
2256 }
2257
2258 if let Ok(true) = announce_service_on_intf(
2259 dns_registry,
2260 service_info,
2261 my_intf,
2262 &sock.pktinfo,
2263 self.port,
2264 ) {
2265 debug!(
2266 "Announce service {} on {}",
2267 service_info.get_fullname(),
2268 intf.ip()
2269 );
2270 service_info.set_status(if_index, ServiceStatus::Announced);
2271 } else {
2272 for timer in dns_registry.new_timers.drain(..) {
2273 self.timers.push(Reverse(timer));
2274 }
2275 service_info.set_status(if_index, ServiceStatus::Probing);
2276 }
2277 }
2278 }
2279
2280 if let Some(my_intf) = self.my_intfs.get(&if_index) {
2285 for ty in self.service_queriers.keys() {
2286 self.send_query_on_intf(ty, RRType::PTR, my_intf);
2287 }
2288 }
2289
2290 self.notify_monitors(DaemonEvent::IpAdd(intf.ip()));
2292 }
2293
2294 fn register_service(&mut self, mut info: ServiceInfo) {
2303 if let Err(e) = check_service_name_length(info.get_type(), self.service_name_len_max) {
2305 error!("check_service_name_length: {}", &e);
2306 self.notify_monitors(DaemonEvent::Error(e));
2307 return;
2308 }
2309
2310 if info.is_addr_auto() {
2311 let selected_intfs =
2312 self.selected_intfs(my_ip_interfaces_inner(true, self.include_apple_p2p));
2313 for intf in selected_intfs {
2314 info.insert_ipaddr(&intf);
2315 }
2316 }
2317
2318 debug!("register service {:?}", &info);
2319
2320 let outgoing_addrs = self.send_unsolicited_response(&mut info);
2321 if !outgoing_addrs.is_empty() {
2322 self.notify_monitors(DaemonEvent::Announce(
2323 info.get_fullname().to_string(),
2324 format!("{:?}", &outgoing_addrs),
2325 ));
2326 }
2327
2328 let service_fullname = info.get_fullname().to_lowercase();
2331 self.my_services.insert(service_fullname, info);
2332 }
2333
2334 fn send_unsolicited_response(&mut self, info: &mut ServiceInfo) -> Vec<IpAddr> {
2337 let mut outgoing_addrs = Vec::new();
2338 let mut outgoing_intfs = HashSet::new();
2339
2340 let mut invalid_intf_addrs = HashSet::new();
2341
2342 for (if_index, intf) in self.my_intfs.iter() {
2343 let dns_registry = match self.dns_registry_map.get_mut(if_index) {
2344 Some(registry) => registry,
2345 None => self
2346 .dns_registry_map
2347 .entry(*if_index)
2348 .or_insert_with(DnsRegistry::new),
2349 };
2350
2351 let mut announced = false;
2352
2353 if let Some(sock) = self.ipv4_sock.as_mut() {
2355 match announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port) {
2356 Ok(true) => {
2357 for addr in intf.addrs.iter().filter(|a| a.ip().is_ipv4()) {
2358 outgoing_addrs.push(addr.ip());
2359 }
2360 outgoing_intfs.insert(intf.index);
2361
2362 debug!(
2363 "Announce service IPv4 {} on {}",
2364 info.get_fullname(),
2365 intf.name
2366 );
2367 announced = true;
2368 }
2369 Ok(false) => {}
2370 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2371 invalid_intf_addrs.insert(intf_addr);
2372 }
2373 }
2374 }
2375
2376 if let Some(sock) = self.ipv6_sock.as_mut() {
2377 match announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port) {
2378 Ok(true) => {
2379 for addr in intf.addrs.iter().filter(|a| a.ip().is_ipv6()) {
2380 outgoing_addrs.push(addr.ip());
2381 }
2382 outgoing_intfs.insert(intf.index);
2383
2384 debug!(
2385 "Announce service IPv6 {} on {}",
2386 info.get_fullname(),
2387 intf.name
2388 );
2389 announced = true;
2390 }
2391 Ok(false) => {}
2392 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2393 invalid_intf_addrs.insert(intf_addr);
2394 }
2395 }
2396 }
2397
2398 if announced {
2399 info.set_status(intf.index, ServiceStatus::Announced);
2400 } else {
2401 for timer in dns_registry.new_timers.drain(..) {
2402 self.timers.push(Reverse(timer));
2403 }
2404 info.set_status(*if_index, ServiceStatus::Probing);
2405 }
2406 }
2407
2408 if !invalid_intf_addrs.is_empty() {
2409 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2410 }
2411
2412 let next_time = Instant::now()
2416 + Duration::from_millis(
2417 ANNOUNCE_SECOND_DELAY_MILLIS + fastrand::u64(0..ANNOUNCE_SECOND_JITTER_MILLIS),
2418 );
2419 for if_index in outgoing_intfs {
2420 self.add_retransmission(
2421 next_time,
2422 Command::RegisterResend(info.get_fullname().to_string(), if_index),
2423 );
2424 }
2425
2426 outgoing_addrs
2427 }
2428
2429 fn probing_handler(&mut self) {
2431 let now = Instant::now();
2432 let mut invalid_intf_addrs = HashSet::new();
2433
2434 for (if_index, intf) in self.my_intfs.iter() {
2435 let Some(dns_registry) = self.dns_registry_map.get_mut(if_index) else {
2436 continue;
2437 };
2438
2439 let (out, expired_probes) = check_probing(dns_registry, &mut self.timers, now);
2440
2441 if !out.questions().is_empty() {
2443 trace!("sending out probing of questions: {:?}", out.questions());
2444 if let Some(sock) = self.ipv4_sock.as_mut() {
2445 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2446 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2447 {
2448 invalid_intf_addrs.insert(intf_addr);
2449 }
2450 }
2451 if let Some(sock) = self.ipv6_sock.as_mut() {
2452 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2453 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2454 {
2455 invalid_intf_addrs.insert(intf_addr);
2456 }
2457 }
2458 }
2459
2460 let waiting_services =
2462 handle_expired_probes(expired_probes, &intf.name, dns_registry, &mut self.monitors);
2463
2464 for service_name in waiting_services {
2465 if let Some(info) = self.my_services.get_mut(&service_name.to_lowercase()) {
2467 if info.get_status(*if_index) == ServiceStatus::Announced {
2468 debug!("service {} already announced", info.get_fullname());
2469 continue;
2470 }
2471
2472 let announced_v4 = if let Some(sock) = self.ipv4_sock.as_mut() {
2473 match announce_service_on_intf(
2474 dns_registry,
2475 info,
2476 intf,
2477 &sock.pktinfo,
2478 self.port,
2479 ) {
2480 Ok(announced) => announced,
2481 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2482 invalid_intf_addrs.insert(intf_addr);
2483 false
2484 }
2485 }
2486 } else {
2487 false
2488 };
2489 let announced_v6 = if let Some(sock) = self.ipv6_sock.as_mut() {
2490 match announce_service_on_intf(
2491 dns_registry,
2492 info,
2493 intf,
2494 &sock.pktinfo,
2495 self.port,
2496 ) {
2497 Ok(announced) => announced,
2498 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2499 invalid_intf_addrs.insert(intf_addr);
2500 false
2501 }
2502 }
2503 } else {
2504 false
2505 };
2506
2507 if announced_v4 || announced_v6 {
2508 let next_time = now
2509 + Duration::from_millis(
2510 ANNOUNCE_SECOND_DELAY_MILLIS
2511 + fastrand::u64(0..ANNOUNCE_SECOND_JITTER_MILLIS),
2512 );
2513 let command =
2514 Command::RegisterResend(info.get_fullname().to_string(), *if_index);
2515 self.retransmissions.push(ReRun { next_time, command });
2516 self.timers.push(Reverse(next_time));
2517
2518 let fullname = dns_registry.resolve_name(&service_name).to_string();
2519
2520 let hostname = dns_registry.resolve_name(info.get_hostname());
2521
2522 debug!("wake up: announce service {} on {}", fullname, intf.name);
2523 notify_monitors(
2524 &mut self.monitors,
2525 DaemonEvent::Announce(fullname, format!("{}:{}", hostname, &intf.name)),
2526 );
2527
2528 info.set_status(*if_index, ServiceStatus::Announced);
2529 }
2530 }
2531 }
2532 }
2533
2534 if !invalid_intf_addrs.is_empty() {
2535 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2536 }
2537 }
2538
2539 fn unregister_service(
2540 &self,
2541 info: &ServiceInfo,
2542 intf: &MyIntf,
2543 sock: &PktInfoUdpSocket,
2544 ) -> Vec<u8> {
2545 let is_ipv4 = sock.domain() == Domain::IPV4;
2546
2547 let (fullname, hostname) = match self.dns_registry_map.get(&intf.index) {
2551 Some(dns_registry) => (
2552 dns_registry.resolve_name(info.get_fullname()),
2553 dns_registry.resolve_name(info.get_hostname()),
2554 ),
2555 None => (info.get_fullname(), info.get_hostname()),
2556 };
2557
2558 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
2559 out.add_answer_record(DnsPointer::new(
2560 info.get_type(),
2561 RRType::PTR,
2562 CLASS_IN,
2563 0,
2564 fullname.to_string(),
2565 ));
2566
2567 if let Some(sub) = info.get_subtype() {
2568 trace!("Adding subdomain {}", sub);
2569 out.add_answer_record(DnsPointer::new(
2570 sub,
2571 RRType::PTR,
2572 CLASS_IN,
2573 0,
2574 fullname.to_string(),
2575 ));
2576 }
2577
2578 out.add_answer_record(DnsSrv::new(
2579 fullname,
2580 CLASS_IN | CLASS_CACHE_FLUSH,
2581 0,
2582 info.get_priority(),
2583 info.get_weight(),
2584 info.get_port(),
2585 hostname.to_string(),
2586 ));
2587 out.add_answer_record(DnsTxt::new(
2588 fullname,
2589 CLASS_IN | CLASS_CACHE_FLUSH,
2590 0,
2591 info.generate_txt(),
2592 ));
2593
2594 let if_addrs = if is_ipv4 {
2595 info.get_addrs_on_my_intf_v4(intf)
2596 } else {
2597 info.get_addrs_on_my_intf_v6(intf)
2598 };
2599
2600 if if_addrs.is_empty() {
2601 return vec![];
2602 }
2603
2604 for address in if_addrs {
2605 out.add_answer_record(DnsAddress::new(
2606 hostname,
2607 ip_address_rr_type(&address),
2608 CLASS_IN | CLASS_CACHE_FLUSH,
2609 0,
2610 address,
2611 intf.into(),
2612 ));
2613 }
2614
2615 let sent_vec = match send_dns_outgoing(&out, intf, sock, self.port, None, None) {
2617 Ok(sent_vec) => sent_vec,
2618 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2619 let invalid_intf_addrs = HashSet::from([intf_addr]);
2620 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2621 vec![]
2622 }
2623 };
2624 sent_vec.into_iter().next().unwrap_or_default()
2625 }
2626
2627 fn add_hostname_resolver(
2631 &mut self,
2632 hostname: String,
2633 listener: Sender<HostnameResolutionEvent>,
2634 timeout: Option<u64>,
2635 ) {
2636 let real_timeout = timeout.map(|t| Instant::now() + Duration::from_millis(t));
2637 self.hostname_resolvers
2638 .insert(hostname.to_lowercase(), (listener, real_timeout));
2639 if let Some(t) = real_timeout {
2640 self.add_timer(t);
2641 }
2642 }
2643
2644 fn send_query(&self, name: &str, qtype: RRType) {
2646 self.send_query_vec(&[(name, qtype)]);
2647 }
2648
2649 fn send_query_on_intf(&self, name: &str, qtype: RRType, intf: &MyIntf) {
2654 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
2655 out.add_question(name, qtype);
2656
2657 let mut invalid_intf_addrs = HashSet::new();
2658 if let Some(sock) = self.ipv4_sock.as_ref() {
2659 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2660 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2661 {
2662 invalid_intf_addrs.insert(intf_addr);
2663 }
2664 }
2665 if let Some(sock) = self.ipv6_sock.as_ref() {
2666 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2667 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2668 {
2669 invalid_intf_addrs.insert(intf_addr);
2670 }
2671 }
2672 if !invalid_intf_addrs.is_empty() {
2673 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2674 }
2675 }
2676
2677 fn send_query_vec(&self, questions: &[(&str, RRType)]) {
2679 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
2680 let now = Instant::now();
2681
2682 for (name, qtype) in questions {
2683 out.add_question(name, *qtype);
2684
2685 for record in self.cache.get_known_answers(name, *qtype, now) {
2686 trace!("add known answer: {:?}", record.record);
2694 let mut new_record = record.record.clone();
2695 new_record.get_record_mut().update_ttl(now);
2696 out.add_answer_box(new_record);
2697 }
2698 }
2699
2700 let mut invalid_intf_addrs = HashSet::new();
2701 for (_, intf) in self.my_intfs.iter() {
2702 if let Some(sock) = self.ipv4_sock.as_ref() {
2703 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2704 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2705 {
2706 invalid_intf_addrs.insert(intf_addr);
2707 }
2708 }
2709 if let Some(sock) = self.ipv6_sock.as_ref() {
2710 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2711 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2712 {
2713 invalid_intf_addrs.insert(intf_addr);
2714 }
2715 }
2716 }
2717
2718 if !invalid_intf_addrs.is_empty() {
2719 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2720 }
2721 }
2722
2723 fn handle_read(&mut self, event_key: usize) -> bool {
2728 let is_ipv4 = event_key == IPV4_SOCK_EVENT_KEY;
2729 let sock_opt = match event_key {
2730 IPV4_SOCK_EVENT_KEY => &mut self.ipv4_sock,
2731 IPV6_SOCK_EVENT_KEY => &mut self.ipv6_sock,
2732 _ => {
2733 debug!("handle_read: unknown token {}", event_key);
2734 return false;
2735 }
2736 };
2737 let Some(sock) = sock_opt.as_mut() else {
2738 debug!("handle_read: socket not available for token {}", event_key);
2739 return false;
2740 };
2741 let max_size = max_pkt_absolute(is_ipv4);
2745 let mut buf = vec![0u8; max_size + 1];
2746
2747 let (sz, pktinfo) = match sock.pktinfo.recv(&mut buf) {
2749 Ok(sz) => sz,
2750 Err(e) => {
2751 if e.kind() != std::io::ErrorKind::WouldBlock {
2752 debug!("listening socket read failed: {}", e);
2753 }
2754 return false;
2755 }
2756 };
2757
2758 if sz > max_size {
2767 debug!(
2768 "handle_read: dropping over-sized datagram of at least {} bytes (max {})",
2769 sz, max_size
2770 );
2771 return true; }
2773
2774 let pkt_if_index = pktinfo.if_index as u32;
2776 let Some(my_intf) = self.my_intfs.get(&pkt_if_index) else {
2777 debug!(
2778 "handle_read: no interface found for pktinfo if_index: {}",
2779 pktinfo.if_index
2780 );
2781 return true; };
2783
2784 let is_ipv4 = event_key == IPV4_SOCK_EVENT_KEY;
2789 if (is_ipv4 && my_intf.next_ifaddr_v4().is_none())
2790 || (!is_ipv4 && my_intf.next_ifaddr_v6().is_none())
2791 {
2792 debug!(
2793 "handle_read: dropping {} packet on intf {} (disabled)",
2794 if is_ipv4 { "IPv4" } else { "IPv6" },
2795 my_intf.name
2796 );
2797 return true;
2798 }
2799
2800 buf.truncate(sz); match DnsIncoming::new(buf, my_intf.into()) {
2803 Ok(msg) => {
2804 debug!(
2805 "handle_read: {} bytes from {} on if_index {}: {} ({} questions {} answers {} authorities {} additionals)",
2806 sz,
2807 pktinfo.addr_src,
2808 pkt_if_index,
2809 if msg.is_query() { "query" } else { "response" },
2810 msg.questions().len(),
2811 msg.answers().len(),
2812 msg.authorities().len(),
2813 msg.additionals().len(),
2814 );
2815 if msg.is_query() {
2816 let querier_addr = pktinfo.addr_src;
2817 self.handle_query(msg, pkt_if_index, querier_addr);
2818 } else if msg.is_response() {
2819 self.handle_response(msg, pkt_if_index);
2820 } else {
2821 debug!("Invalid message: not query and not response");
2822 }
2823 }
2824 Err(e) => debug!("Invalid incoming DNS message: {}", e),
2825 }
2826
2827 true
2828 }
2829
2830 fn query_unresolved(&mut self, instance: &str) -> bool {
2832 if !valid_instance_name(instance) {
2833 trace!("instance name {} not valid", instance);
2834 return false;
2835 }
2836
2837 if let Some(records) = self.cache.get_srv(instance) {
2838 for record in records {
2839 if let Some(srv) = record.record.any().downcast_ref::<DnsSrv>() {
2840 if self.cache.get_addr(srv.host()).is_none() {
2841 debug!(
2842 "query_unresolved: SRV record found for instance: {}, host: {}, sending address query",
2843 instance,
2844 srv.host()
2845 );
2846 self.send_query_vec(&[(srv.host(), RRType::A), (srv.host(), RRType::AAAA)]);
2847 return true;
2848 }
2849 }
2850 }
2851 } else {
2852 debug!(
2853 "query_unresolved: SRV record not found for instance: {}, sending SRV+TXT query",
2854 instance
2855 );
2856 self.send_query_vec(&[(instance, RRType::SRV), (instance, RRType::TXT)]);
2861 return true;
2862 }
2863
2864 false
2865 }
2866
2867 fn query_unresolved_instances(&mut self, ty_domain: &str) {
2874 let now = Instant::now();
2875 let mut instances = Vec::new();
2876 if let Some(records) = self.cache.get_ptr(ty_domain) {
2877 for record in records.iter().filter(|r| !r.record.expires_soon(now)) {
2878 if let Some(ptr) = record.record.any().downcast_ref::<DnsPointer>() {
2879 instances.push(ptr.alias().to_string());
2880 }
2881 }
2882 }
2883
2884 for instance in instances {
2885 if !self.resolved.contains(&instance) {
2886 self.query_unresolved(&instance);
2887 }
2888 }
2889 }
2890
2891 fn query_cache_for_service(
2894 &mut self,
2895 ty_domain: &str,
2896 sender: &Sender<ServiceEvent>,
2897 now: Instant,
2898 ) {
2899 let mut resolved: HashSet<String> = HashSet::new();
2900 let mut unresolved: HashSet<String> = HashSet::new();
2901
2902 if let Some(records) = self.cache.get_ptr(ty_domain) {
2903 for record in records.iter().filter(|r| !r.record.expires_soon(now)) {
2904 if let Some(ptr) = record.record.any().downcast_ref::<DnsPointer>() {
2905 let mut new_event = None;
2906 match self.resolve_service_from_cache(ty_domain, ptr.alias()) {
2907 Ok(resolved_service) => {
2908 if resolved_service.is_valid() {
2909 debug!("Resolved service from cache: {}", ptr.alias());
2910 new_event =
2911 Some(ServiceEvent::ServiceResolved(Box::new(resolved_service)));
2912 } else {
2913 debug!(
2914 "query_cache_for_service: not valid: {} (host_empty={}, addrs_empty={})",
2915 ptr.alias(),
2916 resolved_service.get_hostname().is_empty(),
2917 resolved_service.get_addresses().is_empty(),
2918 );
2919 }
2920 }
2921 Err(err) => {
2922 debug!("Error while resolving service from cache: {}", err);
2923 continue;
2924 }
2925 }
2926
2927 match sender.send(ServiceEvent::ServiceFound(
2928 ty_domain.to_string(),
2929 ptr.alias().to_string(),
2930 )) {
2931 Ok(()) => debug!("sent service found {}", ptr.alias()),
2932 Err(e) => {
2933 debug!("failed to send service found: {}", e);
2934 continue;
2935 }
2936 }
2937
2938 if let Some(event) = new_event {
2939 resolved.insert(ptr.alias().to_string());
2940 match sender.send(event) {
2941 Ok(()) => debug!("sent service resolved: {}", ptr.alias()),
2942 Err(e) => debug!("failed to send service resolved: {}", e),
2943 }
2944 } else {
2945 unresolved.insert(ptr.alias().to_string());
2946 }
2947 }
2948 }
2949 }
2950
2951 for instance in resolved.drain() {
2952 self.pending_resolves.remove(&instance);
2953 self.resolved.insert(instance);
2954 }
2955
2956 for instance in unresolved.drain() {
2957 self.add_pending_resolve(instance);
2958 }
2959 }
2960
2961 fn query_cache_for_hostname(
2964 &mut self,
2965 hostname: &str,
2966 sender: Sender<HostnameResolutionEvent>,
2967 ) {
2968 let addresses_map = self.cache.get_addresses_for_host(hostname);
2969 for (name, addresses) in addresses_map {
2970 match sender.send(HostnameResolutionEvent::AddressesFound(name, addresses)) {
2971 Ok(()) => trace!("sent hostname addresses found"),
2972 Err(e) => debug!("failed to send hostname addresses found: {}", e),
2973 }
2974 }
2975 }
2976
2977 fn add_pending_resolve(&mut self, instance: String) {
2978 if !self.pending_resolves.contains(&instance) {
2979 let next_time = Instant::now() + Duration::from_millis(RESOLVE_RETRY_BASE_MILLIS);
2980 self.add_retransmission(next_time, Command::Resolve(instance.clone(), 1));
2981 self.pending_resolves.insert(instance);
2982 }
2983 }
2984
2985 fn resolve_service_from_cache(
2987 &self,
2988 ty_domain: &str,
2989 fullname: &str,
2990 ) -> Result<ResolvedService> {
2991 let now = Instant::now();
2992 let mut resolved_service = ResolvedService {
2993 ty_domain: ty_domain.to_string(),
2994 sub_ty_domain: None,
2995 fullname: fullname.to_string(),
2996 host: String::new(),
2997 port: 0,
2998 addresses: HashSet::new(),
2999 txt_properties: TxtProperties::new(),
3000 };
3001
3002 if let Some(subtype) = self.cache.get_subtype(fullname) {
3004 trace!(
3005 "ty_domain: {} found subtype {} for instance: {}",
3006 ty_domain,
3007 subtype,
3008 fullname
3009 );
3010 if resolved_service.sub_ty_domain.is_none() {
3011 resolved_service.sub_ty_domain = Some(subtype.to_string());
3012 }
3013 }
3014
3015 if let Some(records) = self.cache.get_srv(fullname) {
3017 if let Some(answer) = records.iter().find(|r| !r.record.expires_soon(now)) {
3018 if let Some(dns_srv) = answer.record.any().downcast_ref::<DnsSrv>() {
3019 resolved_service.host = dns_srv.host().to_string();
3020 resolved_service.port = dns_srv.port();
3021 }
3022 }
3023 }
3024
3025 if let Some(records) = self.cache.get_txt(fullname) {
3027 if let Some(record) = records.iter().find(|r| !r.record.expires_soon(now)) {
3028 if let Some(dns_txt) = record.record.any().downcast_ref::<DnsTxt>() {
3029 resolved_service.txt_properties = dns_txt.text().into();
3030 }
3031 }
3032 }
3033
3034 if let Some(records) = self.cache.get_addr(&resolved_service.host) {
3036 for answer in records.iter() {
3037 if let Some(dns_a) = answer.record.any().downcast_ref::<DnsAddress>() {
3038 if dns_a.expires_soon(now) {
3039 trace!(
3040 "Addr expired or expires soon: {}",
3041 dns_a.address().to_ip_addr()
3042 );
3043 } else {
3044 let scoped = dns_a.address();
3045 if let ScopedIp::V4(v4) = &scoped {
3046 let existing = resolved_service
3049 .addresses
3050 .iter()
3051 .find(|a| a.to_ip_addr() == IpAddr::V4(*v4.addr()))
3052 .cloned();
3053 if let Some(mut existing) = existing {
3054 resolved_service.addresses.remove(&existing);
3055 if let ScopedIp::V4(existing_v4) = &mut existing {
3056 for id in v4.interface_ids() {
3057 existing_v4.add_interface_id(id.clone());
3058 }
3059 }
3060 resolved_service.addresses.insert(existing);
3061 } else {
3062 resolved_service.addresses.insert(scoped);
3063 }
3064 } else {
3065 resolved_service.addresses.insert(scoped);
3066 }
3067 }
3068 }
3069 }
3070 }
3071
3072 Ok(resolved_service)
3073 }
3074
3075 fn handle_poller_events(&mut self, events: &mio::Events) {
3076 for ev in events.iter() {
3077 trace!("event received with key {:?}", ev.token());
3078 if ev.token().0 == SIGNAL_SOCK_EVENT_KEY {
3079 self.signal_sock_drain();
3081
3082 if let Err(e) = self.poller.registry().reregister(
3083 &mut self.signal_sock,
3084 ev.token(),
3085 mio::Interest::READABLE,
3086 ) {
3087 debug!("failed to modify poller for signal socket: {}", e);
3088 }
3089 continue; }
3091
3092 while self.handle_read(ev.token().0) {}
3094
3095 if ev.token().0 == IPV4_SOCK_EVENT_KEY {
3097 if let Some(sock) = self.ipv4_sock.as_mut() {
3099 if let Err(e) =
3100 self.poller
3101 .registry()
3102 .reregister(sock, ev.token(), mio::Interest::READABLE)
3103 {
3104 debug!("modify poller for IPv4 socket: {}", e);
3105 }
3106 }
3107 } else if ev.token().0 == IPV6_SOCK_EVENT_KEY {
3108 if let Some(sock) = self.ipv6_sock.as_mut() {
3110 if let Err(e) =
3111 self.poller
3112 .registry()
3113 .reregister(sock, ev.token(), mio::Interest::READABLE)
3114 {
3115 debug!("modify poller for IPv6 socket: {}", e);
3116 }
3117 }
3118 }
3119 }
3120 }
3121
3122 fn handle_response(&mut self, mut msg: DnsIncoming, if_index: u32) {
3125 let now = Instant::now();
3126
3127 let mut record_predicate = |record: &DnsRecordBox| {
3129 if !record.get_record().is_expired(now) {
3130 return true;
3131 }
3132
3133 debug!("record is expired, removing it from cache.");
3134 if self.cache.remove(record) {
3135 if let Some(dns_ptr) = record.any().downcast_ref::<DnsPointer>() {
3137 call_service_listener(
3138 &self.service_queriers,
3139 dns_ptr.get_name(),
3140 ServiceEvent::ServiceRemoved(
3141 dns_ptr.get_name().to_string(),
3142 dns_ptr.alias().to_string(),
3143 ),
3144 );
3145 }
3146 }
3147 false
3148 };
3149 msg.answers_mut().retain(&mut record_predicate);
3150 msg.authorities_mut().retain(&mut record_predicate);
3151 msg.additionals_mut().retain(&mut record_predicate);
3152
3153 self.conflict_handler(&msg, if_index);
3155
3156 let mut is_for_us = true; for answer in msg.answers() {
3163 if answer.get_type() == RRType::PTR {
3164 if self.service_queriers.contains_key(answer.get_name()) {
3165 is_for_us = true;
3166 break; } else {
3168 is_for_us = false;
3169 }
3170 } else if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA {
3171 let answer_lowercase = answer.get_name().to_lowercase();
3173 if self.hostname_resolvers.contains_key(&answer_lowercase) {
3174 is_for_us = true;
3175 break; }
3177 }
3178 }
3179
3180 if self.accept_unsolicited {
3182 is_for_us = true;
3183 }
3184
3185 struct InstanceChange {
3187 ty: RRType, name: String, }
3190
3191 let mut changes = Vec::new();
3199 let mut timers = Vec::new();
3200 let Some(my_intf) = self.my_intfs.get(&if_index) else {
3201 return;
3202 };
3203 for record in msg.all_records() {
3204 match self
3205 .cache
3206 .add_or_update(my_intf, record, &mut timers, is_for_us)
3207 {
3208 Some((dns_record, true)) => {
3209 timers.push(dns_record.record.get_record().get_expire_time());
3210 timers.push(dns_record.record.get_record().get_refresh_time());
3211
3212 let ty = dns_record.record.get_type();
3213 let name = dns_record.record.get_name();
3214
3215 debug!("cache: new record: {:?}", &dns_record.record);
3218
3219 if ty == RRType::PTR && dns_record.record.get_record().get_ttl() > 1 {
3221 if self.service_queriers.contains_key(name) {
3222 timers.push(dns_record.record.get_record().get_refresh_time());
3223 }
3224
3225 if let Some(dns_ptr) = dns_record.record.any().downcast_ref::<DnsPointer>()
3227 {
3228 debug!("calling listener with service found: {name}");
3229 call_service_listener(
3230 &self.service_queriers,
3231 name,
3232 ServiceEvent::ServiceFound(
3233 name.to_string(),
3234 dns_ptr.alias().to_string(),
3235 ),
3236 );
3237 changes.push(InstanceChange {
3238 ty,
3239 name: dns_ptr.alias().to_string(),
3240 });
3241 }
3242 } else {
3243 changes.push(InstanceChange {
3244 ty,
3245 name: name.to_string(),
3246 });
3247 }
3248 }
3249 Some((dns_record, false)) => {
3250 timers.push(dns_record.record.get_record().get_expire_time());
3251 timers.push(dns_record.record.get_record().get_refresh_time());
3252 }
3253 _ => {}
3254 }
3255 }
3256
3257 for t in timers {
3259 self.add_timer(t);
3260 }
3261
3262 for change in changes
3264 .iter()
3265 .filter(|change| change.ty == RRType::A || change.ty == RRType::AAAA)
3266 {
3267 let addr_map = self.cache.get_addresses_for_host(&change.name);
3268 for (name, addresses) in addr_map {
3269 call_hostname_resolution_listener(
3270 &self.hostname_resolvers,
3271 &change.name,
3272 HostnameResolutionEvent::AddressesFound(name, addresses),
3273 )
3274 }
3275 }
3276
3277 let mut updated_instances = HashSet::new();
3279 for update in changes {
3280 match update.ty {
3281 RRType::PTR | RRType::SRV | RRType::TXT => {
3282 updated_instances.insert(update.name);
3283 }
3284 RRType::A | RRType::AAAA => {
3285 let instances = self.cache.get_instances_on_host(&update.name);
3286 updated_instances.extend(instances);
3287 }
3288 _ => {}
3289 }
3290 }
3291
3292 self.resolve_updated_instances(&updated_instances);
3293 }
3294
3295 fn conflict_handler(&mut self, msg: &DnsIncoming, if_index: u32) {
3296 let Some(my_intf) = self.my_intfs.get(&if_index) else {
3297 debug!("handle_response: no intf found for index {if_index}");
3298 return;
3299 };
3300
3301 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
3302 return;
3303 };
3304
3305 for answer in msg.answers().iter() {
3306 let mut new_records = Vec::new();
3307
3308 let name = answer.get_name();
3309 let Some(probe) = dns_registry.probing.get_mut(name) else {
3310 continue;
3311 };
3312
3313 if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA {
3315 if let Some(answer_addr) = answer.any().downcast_ref::<DnsAddress>() {
3316 if answer_addr.interface_id.index != if_index {
3317 debug!(
3318 "conflict handler: answer addr {:?} not in the subnet of intf {}",
3319 answer_addr, my_intf.name
3320 );
3321 continue;
3322 }
3323 }
3324
3325 let any_match = probe.records.iter().any(|r| {
3328 r.get_type() == answer.get_type()
3329 && r.get_class() == answer.get_class()
3330 && r.rrdata_match(answer.as_ref())
3331 });
3332 if any_match {
3333 continue; }
3335 }
3336
3337 probe.records.retain(|record| {
3338 if record.get_type() == answer.get_type()
3339 && record.get_class() == answer.get_class()
3340 && !record.rrdata_match(answer.as_ref())
3341 {
3342 debug!(
3343 "found conflict name: '{name}' record: {}: {} PEER: {}",
3344 record.get_type(),
3345 record.rdata_print(),
3346 answer.rdata_print()
3347 );
3348
3349 let mut new_record = record.clone();
3352 let new_name = match record.get_type() {
3353 RRType::A => hostname_change(name),
3354 RRType::AAAA => hostname_change(name),
3355 _ => name_change(name),
3356 };
3357 new_record.get_record_mut().set_new_name(new_name);
3358 new_records.push(new_record);
3359 return false; }
3361
3362 true
3363 });
3364
3365 let create_time = Instant::now() + Duration::from_millis(fastrand::u64(0..250));
3372
3373 let waiting_services = probe.waiting_services.clone();
3374
3375 for record in new_records {
3376 if dns_registry.update_hostname(name, record.get_name(), create_time) {
3377 self.timers.push(Reverse(create_time));
3378 }
3379
3380 dns_registry.name_changes.insert(
3382 record.get_record().get_original_name().to_string(),
3383 record.get_name().to_string(),
3384 );
3385
3386 let new_probe = match dns_registry.probing.get_mut(record.get_name()) {
3387 Some(p) => p,
3388 None => {
3389 let new_probe = dns_registry
3390 .probing
3391 .entry(record.get_name().to_string())
3392 .or_insert_with(|| {
3393 debug!("conflict handler: new probe of {}", record.get_name());
3394 Probe::new(create_time)
3395 });
3396 self.timers.push(Reverse(new_probe.next_send));
3397 new_probe
3398 }
3399 };
3400
3401 debug!(
3402 "insert record with new name '{}' {} into probe",
3403 record.get_name(),
3404 record.get_type()
3405 );
3406 new_probe.insert_record(record);
3407
3408 new_probe.waiting_services.extend(waiting_services.clone());
3409 }
3410 }
3411 }
3412
3413 fn resolve_updated_instances(&mut self, updated_instances: &HashSet<String>) {
3420 if updated_instances.is_empty() {
3421 return;
3422 }
3423
3424 let mut resolved: HashSet<String> = HashSet::new();
3425 let mut unresolved: HashSet<String> = HashSet::new();
3426 let mut removed_instances = HashMap::new();
3427
3428 let now = Instant::now();
3429
3430 for (ty_domain, records) in self.cache.all_ptr().iter() {
3431 if !self.service_queriers.contains_key(ty_domain) {
3432 continue;
3434 }
3435
3436 for ptr in records.iter().filter(|r| !r.record.expires_soon(now)) {
3437 let Some(dns_ptr) = ptr.record.any().downcast_ref::<DnsPointer>() else {
3438 continue;
3439 };
3440
3441 let instance = dns_ptr.alias();
3442 if !updated_instances.contains(instance) {
3443 continue;
3444 }
3445
3446 let Ok(resolved_service) = self.resolve_service_from_cache(ty_domain, instance)
3447 else {
3448 continue;
3449 };
3450
3451 debug!("resolve_updated_instances: from cache: {instance}");
3452 if resolved_service.is_valid() {
3453 debug!(
3454 "resolved '{}' -> host '{}' port {} addrs {:?}",
3455 instance,
3456 resolved_service.host,
3457 resolved_service.port,
3458 resolved_service.addresses,
3459 );
3460 resolved.insert(instance.to_string());
3461 let event = ServiceEvent::ServiceResolved(Box::new(resolved_service));
3462 call_service_listener(&self.service_queriers, ty_domain, event);
3463 } else {
3464 debug!(
3465 "resolve_updated_instances: not valid: {instance} (host_empty={}, addrs_empty={})",
3466 resolved_service.get_hostname().is_empty(),
3467 resolved_service.get_addresses().is_empty(),
3468 );
3469 if self.resolved.remove(dns_ptr.alias()) {
3470 removed_instances
3471 .entry(ty_domain.to_string())
3472 .or_insert_with(HashSet::new)
3473 .insert(instance.to_string());
3474 }
3475 unresolved.insert(instance.to_string());
3476 }
3477 }
3478 }
3479
3480 for instance in resolved.drain() {
3481 self.pending_resolves.remove(&instance);
3482 self.resolved.insert(instance);
3483 }
3484
3485 for instance in unresolved.drain() {
3486 self.add_pending_resolve(instance);
3487 }
3488
3489 if !removed_instances.is_empty() {
3490 debug!(
3491 "resolve_updated_instances: removed {}",
3492 &removed_instances.len()
3493 );
3494 self.notify_service_removal(removed_instances);
3495 }
3496 }
3497
3498 fn handle_query(&mut self, msg: DnsIncoming, if_index: u32, querier_addr: SocketAddr) {
3500 let querier_ip = querier_addr.ip();
3501 let is_ipv4 = querier_ip.is_ipv4();
3502
3503 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
3504 let mut delayed = false;
3505
3506 const META_QUERY: &str = "_services._dns-sd._udp.local.";
3509
3510 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
3511 debug!("missing dns registry for intf {}", if_index);
3512 return;
3513 };
3514
3515 let Some(intf) = self.my_intfs.get(&if_index) else {
3516 debug!("handle_query: no intf found for index {if_index}");
3517 return;
3518 };
3519
3520 for question in msg.questions().iter() {
3521 let qtype = question.entry_type();
3522 let q_name = question.entry_name();
3523
3524 if qtype == RRType::PTR {
3525 if querier_addr.port() == MDNS_PORT && msg.num_authorities() == 0 {
3529 delayed = true;
3530 }
3531 for service in self.my_services.values() {
3532 if service.get_status(if_index) != ServiceStatus::Announced {
3533 continue;
3534 }
3535
3536 if service.matches_type_or_subtype(q_name) {
3537 out.add_answer_with_additionals(&msg, service, intf, dns_registry, is_ipv4);
3538 } else if q_name == META_QUERY {
3539 let ttl = service.get_other_ttl();
3540 let alias = service.get_type().to_string();
3541 let ptr = DnsPointer::new(q_name, RRType::PTR, CLASS_IN, ttl, alias);
3542 if !out.add_answer(&msg, ptr) {
3543 trace!("answer was not added for meta-query {:?}", &question);
3544 }
3545 }
3546 }
3547 } else {
3548 if qtype == RRType::ANY && msg.num_authorities() > 0 {
3550 if let Some(probe) = dns_registry.probing.get_mut(q_name) {
3551 probe.tiebreaking(&msg, q_name);
3552 }
3553 }
3554
3555 if matches!(
3556 qtype,
3557 RRType::A | RRType::AAAA | RRType::ANY | RRType::SVCB | RRType::HTTPS
3558 ) {
3559 answer_hostname_question(
3560 &self.my_services,
3561 intf,
3562 question,
3563 dns_registry,
3564 &mut out,
3565 &msg,
3566 );
3567 }
3568
3569 let query_name = q_name.to_lowercase();
3570 let service_opt = self
3571 .my_services
3572 .iter()
3573 .find(|(k, _v)| dns_registry.resolve_name(k.as_str()) == query_name)
3574 .map(|(_, v)| v);
3575
3576 let Some(service) = service_opt else {
3577 continue;
3578 };
3579
3580 if service.get_status(if_index) != ServiceStatus::Announced {
3581 continue;
3582 }
3583
3584 let intf_addrs = if is_ipv4 {
3585 service.get_addrs_on_my_intf_v4(intf)
3586 } else {
3587 service.get_addrs_on_my_intf_v6(intf)
3588 };
3589 if intf_addrs.is_empty() {
3590 debug!(
3591 "Cannot find valid addrs for TYPE_SRV response on intf {:?}",
3592 &intf
3593 );
3594 continue;
3595 }
3596
3597 add_answer_of_service(
3598 &mut out,
3599 &msg,
3600 question.entry_name(),
3601 service,
3602 qtype,
3603 intf_addrs,
3604 );
3605 }
3606 }
3607
3608 if delayed && out.answers_count() > 0 {
3610 out.set_id(msg.id());
3611 self.increase_counter(Counter::KnownAnswerSuppression, out.known_answer_count());
3612 let delay =
3613 fastrand::u64(SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS);
3614 let next_time = Instant::now() + Duration::from_millis(delay);
3615 self.delayed_responses.push(DelayedResponse {
3616 next_time,
3617 out,
3618 if_index,
3619 is_ipv4,
3620 });
3621 self.add_timer(next_time);
3622 return;
3623 }
3624
3625 if out.answers_count() > 0 {
3626 self.send_response(&mut out, &msg, if_index, querier_addr);
3627 }
3628
3629 self.increase_counter(Counter::KnownAnswerSuppression, out.known_answer_count());
3630 }
3631
3632 fn send_response(
3633 &mut self,
3634 out: &mut DnsOutgoing,
3635 msg: &DnsIncoming,
3636 if_index: u32,
3637 querier_addr: SocketAddr,
3638 ) {
3639 let querier_ip = querier_addr.ip();
3640 let is_ipv4 = querier_ip.is_ipv4();
3641 let sock_opt = if is_ipv4 {
3642 &self.ipv4_sock
3643 } else {
3644 &self.ipv6_sock
3645 };
3646 let Some(sock) = sock_opt.as_ref() else {
3647 debug!("send_response: socket not available for intf {if_index}");
3648 return;
3649 };
3650 let Some(intf) = self.my_intfs.get(&if_index) else {
3651 debug!("send_response: no intf found for index {if_index}");
3652 return;
3653 };
3654
3655 out.set_id(msg.id());
3656
3657 let matched_source = intf
3660 .addrs
3661 .iter()
3662 .find(|if_addr| valid_ip_on_intf(&querier_ip, if_addr));
3663
3664 let unicast_dest = if querier_addr.port() != MDNS_PORT {
3673 Some(querier_addr)
3674 } else {
3675 None
3676 };
3677
3678 if unicast_dest.is_some() {
3679 for q in msg.questions() {
3680 out.add_question(q.entry_name(), q.entry_type());
3681 }
3682 out.update_records_for_legacy_unicast();
3683 out.set_multicast(false);
3684 } else if msg.num_authorities() == 0 {
3685 if let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) {
3692 dns_registry.apply_multicast_rate_limit(out, Instant::now(), is_ipv4);
3693 }
3694 }
3695
3696 if out.answers_count() > 0 {
3697 debug!("sending response on intf {}", &intf.name);
3698 if let Err(InternalError::IntfAddrInvalid(intf_addr)) = send_dns_outgoing(
3699 out,
3700 intf,
3701 &sock.pktinfo,
3702 self.port,
3703 matched_source,
3704 unicast_dest,
3705 ) {
3706 let invalid_intf_addr = HashSet::from([intf_addr]);
3707 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3708 }
3709
3710 let if_name = intf.name.clone();
3711
3712 self.increase_counter(Counter::Respond, 1);
3713 self.notify_monitors(DaemonEvent::Respond(if_name));
3714 }
3715 }
3716
3717 fn send_delayed_response(&mut self, resp: DelayedResponse) {
3726 let DelayedResponse {
3727 mut out,
3728 if_index,
3729 is_ipv4,
3730 ..
3731 } = resp;
3732
3733 let sock_opt = if is_ipv4 {
3734 &self.ipv4_sock
3735 } else {
3736 &self.ipv6_sock
3737 };
3738 let Some(sock) = sock_opt.as_ref() else {
3739 debug!("send_delayed_response: socket not available for intf {if_index}");
3740 return;
3741 };
3742
3743 if let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) {
3744 dns_registry.apply_multicast_rate_limit(&mut out, Instant::now(), is_ipv4);
3745 }
3746 if out.answers_count() == 0 {
3747 return;
3748 }
3749
3750 let Some(intf) = self.my_intfs.get(&if_index) else {
3751 debug!("send_delayed_response: no intf found for index {if_index}");
3752 return;
3753 };
3754
3755 let if_name = intf.name.clone();
3756 debug!("sending delayed response on intf {}", &if_name);
3757 let send_result = send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None);
3758
3759 if let Err(InternalError::IntfAddrInvalid(intf_addr)) = send_result {
3760 let invalid_intf_addr = HashSet::from([intf_addr]);
3761 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3762 }
3763
3764 self.increase_counter(Counter::Respond, 1);
3765 self.notify_monitors(DaemonEvent::Respond(if_name));
3766 }
3767
3768 fn increase_counter(&mut self, counter: Counter, count: i64) {
3770 let key = counter.to_string();
3771 match self.counters.get_mut(&key) {
3772 Some(v) => *v += count,
3773 None => {
3774 self.counters.insert(key, count);
3775 }
3776 }
3777 }
3778
3779 fn set_counter(&mut self, counter: Counter, count: i64) {
3781 let key = counter.to_string();
3782 self.counters.insert(key, count);
3783 }
3784
3785 fn signal_sock_drain(&self) {
3786 let mut signal_buf = [0; 1024];
3787
3788 while let Ok(sz) = self.signal_sock.recv(&mut signal_buf) {
3790 trace!(
3791 "signal socket recvd: {}",
3792 String::from_utf8_lossy(&signal_buf[0..sz])
3793 );
3794 }
3795 }
3796
3797 fn add_retransmission(&mut self, next_time: Instant, command: Command) {
3798 self.retransmissions.push(ReRun { next_time, command });
3799 self.add_timer(next_time);
3800 }
3801
3802 fn notify_service_removal(&self, expired: HashMap<String, HashSet<String>>) {
3805 for (ty_domain, sender) in self.service_queriers.iter() {
3806 if let Some(instances) = expired.get(ty_domain) {
3807 for instance_name in instances {
3808 let event = ServiceEvent::ServiceRemoved(
3809 ty_domain.to_string(),
3810 instance_name.to_string(),
3811 );
3812 match sender.send(event) {
3813 Ok(()) => debug!("notify_service_removal: sent ServiceRemoved to listener of {ty_domain}: {instance_name}"),
3814 Err(e) => debug!("Failed to send event: {}", e),
3815 }
3816 }
3817 }
3818 }
3819 }
3820
3821 fn exec_command(&mut self, command: Command, repeating: bool) {
3825 trace!("exec_command: {:?} repeating: {}", &command, repeating);
3826 match command {
3827 Command::Browse(ty, next_delay, cache_only, listener) => {
3828 self.exec_command_browse(repeating, ty, next_delay, cache_only, listener);
3829 }
3830
3831 Command::ResolveHostname(hostname, next_delay, listener, timeout) => {
3832 self.exec_command_resolve_hostname(
3833 repeating, hostname, next_delay, listener, timeout,
3834 );
3835 }
3836
3837 Command::Register(service_info) => {
3838 self.register_service(*service_info);
3839 self.increase_counter(Counter::Register, 1);
3840 }
3841
3842 Command::RegisterResend(fullname, intf) => {
3843 trace!("register-resend service: {fullname} on {}", &intf);
3844 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
3845 self.exec_command_register_resend(fullname, intf)
3846 {
3847 let invalid_intf_addr = HashSet::from([intf_addr]);
3848 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3849 }
3850 }
3851
3852 Command::Unregister(fullname, resp_s) => {
3853 trace!("unregister service {} repeat {}", &fullname, &repeating);
3854 self.exec_command_unregister(repeating, fullname, resp_s);
3855 }
3856
3857 Command::UnregisterResend(packet, if_index, is_ipv4) => {
3858 self.exec_command_unregister_resend(packet, if_index, is_ipv4);
3859 }
3860
3861 Command::StopBrowse(ty_domain) => self.exec_command_stop_browse(ty_domain),
3862
3863 Command::StopResolveHostname(hostname) => {
3864 self.exec_command_stop_resolve_hostname(hostname.to_lowercase())
3865 }
3866
3867 Command::Resolve(instance, try_count) => self.exec_command_resolve(instance, try_count),
3868
3869 Command::GetMetrics(resp_s) => self.exec_command_get_metrics(resp_s),
3870
3871 Command::GetStatus(resp_s) => match resp_s.send(self.status.clone()) {
3872 Ok(()) => trace!("Sent status to the client"),
3873 Err(e) => debug!("Failed to send status: {}", e),
3874 },
3875
3876 Command::Monitor(resp_s) => {
3877 self.monitors.push(resp_s);
3878 }
3879
3880 Command::SetOption(daemon_opt) => {
3881 self.process_set_option(daemon_opt);
3882 }
3883
3884 Command::GetOption(resp_s) => {
3885 let val = DaemonOptionVal {
3886 _service_name_len_max: self.service_name_len_max,
3887 ip_check_interval: self.ip_check_interval,
3888 };
3889 if let Err(e) = resp_s.send(val) {
3890 debug!("Failed to send options: {}", e);
3891 }
3892 }
3893
3894 Command::Verify(instance_fullname, timeout) => {
3895 self.exec_command_verify(instance_fullname, timeout, repeating);
3896 }
3897
3898 Command::InvalidIntfAddrs(invalid_intf_addrs) => {
3899 for intf_addr in invalid_intf_addrs {
3900 self.del_interface_addr(&intf_addr);
3901 }
3902
3903 self.check_ip_changes();
3904 }
3905
3906 _ => {
3907 debug!("unexpected command: {:?}", &command);
3908 }
3909 }
3910 }
3911
3912 fn exec_command_get_metrics(&mut self, resp_s: Sender<HashMap<String, i64>>) {
3913 self.set_counter(Counter::CachedPTR, self.cache.ptr_count() as i64);
3914 self.set_counter(Counter::CachedSRV, self.cache.srv_count() as i64);
3915 self.set_counter(Counter::CachedAddr, self.cache.addr_count() as i64);
3916 self.set_counter(Counter::CachedTxt, self.cache.txt_count() as i64);
3917 self.set_counter(Counter::CachedNSec, self.cache.nsec_count() as i64);
3918 self.set_counter(Counter::CachedSubtype, self.cache.subtype_count() as i64);
3919 self.set_counter(Counter::Timer, self.timers.len() as i64);
3920
3921 let dns_registry_probe_count: usize = self
3922 .dns_registry_map
3923 .values()
3924 .map(|r| r.probing.len())
3925 .sum();
3926 self.set_counter(Counter::DnsRegistryProbe, dns_registry_probe_count as i64);
3927
3928 let dns_registry_active_count: usize = self
3929 .dns_registry_map
3930 .values()
3931 .map(|r| r.active.values().map(|a| a.len()).sum::<usize>())
3932 .sum();
3933 self.set_counter(Counter::DnsRegistryActive, dns_registry_active_count as i64);
3934
3935 let dns_registry_timer_count: usize = self
3936 .dns_registry_map
3937 .values()
3938 .map(|r| r.new_timers.len())
3939 .sum();
3940 self.set_counter(Counter::DnsRegistryTimer, dns_registry_timer_count as i64);
3941
3942 let dns_registry_name_change_count: usize = self
3943 .dns_registry_map
3944 .values()
3945 .map(|r| r.name_changes.len())
3946 .sum();
3947 self.set_counter(
3948 Counter::DnsRegistryNameChange,
3949 dns_registry_name_change_count as i64,
3950 );
3951
3952 if let Err(e) = resp_s.send(self.counters.clone()) {
3954 debug!("Failed to send metrics: {}", e);
3955 }
3956 }
3957
3958 fn exec_command_browse(
3959 &mut self,
3960 repeating: bool,
3961 ty: String,
3962 next_delay: u32,
3963 cache_only: bool,
3964 listener: Sender<ServiceEvent>,
3965 ) {
3966 let pretty_addrs: Vec<String> = self
3967 .my_intfs
3968 .iter()
3969 .map(|(if_index, itf)| format!("{} ({if_index})", itf.name))
3970 .collect();
3971
3972 if let Err(e) = listener.send(ServiceEvent::SearchStarted(format!(
3973 "{ty} on {} interfaces [{}]",
3974 pretty_addrs.len(),
3975 pretty_addrs.join(", ")
3976 ))) {
3977 debug!(
3978 "Failed to send SearchStarted({})(repeating:{}): {}",
3979 &ty, repeating, e
3980 );
3981 return;
3982 }
3983
3984 let now = Instant::now();
3985 if !repeating {
3986 self.service_queriers.insert(ty.clone(), listener.clone());
3990
3991 self.query_cache_for_service(&ty, &listener, now);
3993 }
3994
3995 if cache_only {
3996 match listener.send(ServiceEvent::SearchStopped(ty.clone())) {
3998 Ok(()) => debug!("SearchStopped sent for {}", &ty),
3999 Err(e) => debug!("Failed to send SearchStopped: {}", e),
4000 }
4001 return;
4002 }
4003
4004 if !repeating {
4005 let jitter =
4007 fastrand::u64(INITIAL_QUERY_DELAY_MIN_MILLIS..INITIAL_QUERY_DELAY_MAX_MILLIS);
4008 self.add_retransmission(
4009 now + Duration::from_millis(jitter),
4010 Command::Browse(ty, 1, cache_only, listener),
4011 );
4012 return;
4013 }
4014
4015 self.send_query(&ty, RRType::PTR);
4016
4017 self.query_unresolved_instances(&ty);
4018
4019 self.increase_counter(Counter::Browse, 1);
4020
4021 let next_time = now + Duration::from_millis((next_delay * 1000) as u64);
4022 let max_delay = 60 * 60;
4023 let delay = cmp::min(next_delay * 2, max_delay);
4024 self.add_retransmission(next_time, Command::Browse(ty, delay, cache_only, listener));
4025 }
4026
4027 fn exec_command_resolve_hostname(
4028 &mut self,
4029 repeating: bool,
4030 hostname: String,
4031 next_delay: u32,
4032 listener: Sender<HostnameResolutionEvent>,
4033 timeout: Option<u64>,
4034 ) {
4035 let addr_list: Vec<_> = self.my_intfs.iter().collect();
4036 if let Err(e) = listener.send(HostnameResolutionEvent::SearchStarted(format!(
4037 "{} on addrs {:?}",
4038 &hostname, &addr_list
4039 ))) {
4040 debug!(
4041 "Failed to send ResolveStarted({})(repeating:{}): {}",
4042 &hostname, repeating, e
4043 );
4044 return;
4045 }
4046 let now = Instant::now();
4047 if !repeating {
4048 self.add_hostname_resolver(hostname.to_owned(), listener.clone(), timeout);
4049 self.query_cache_for_hostname(&hostname, listener.clone());
4051
4052 let jitter =
4054 fastrand::u64(INITIAL_QUERY_DELAY_MIN_MILLIS..INITIAL_QUERY_DELAY_MAX_MILLIS);
4055 self.add_retransmission(
4056 now + Duration::from_millis(jitter),
4057 Command::ResolveHostname(hostname, 1, listener, None),
4058 );
4059 return;
4060 }
4061
4062 self.send_query_vec(&[(&hostname, RRType::A), (&hostname, RRType::AAAA)]);
4063 self.increase_counter(Counter::ResolveHostname, 1);
4064
4065 let next_time = now + Duration::from_millis(u64::from(next_delay) * 1000);
4066 let max_delay = 60 * 60;
4067 let delay = cmp::min(next_delay * 2, max_delay);
4068
4069 if self
4071 .hostname_resolvers
4072 .get(&hostname)
4073 .and_then(|(_sender, timeout)| *timeout)
4074 .map(|timeout| next_time < timeout)
4075 .unwrap_or(true)
4076 {
4077 self.add_retransmission(
4078 next_time,
4079 Command::ResolveHostname(hostname, delay, listener, None),
4080 );
4081 }
4082 }
4083
4084 fn exec_command_resolve(&mut self, instance: String, try_count: u16) {
4085 let pending_query = self.query_unresolved(&instance);
4086 if pending_query && try_count < RESOLVE_MAX_TRY {
4087 let next_delay = RESOLVE_RETRY_BASE_MILLIS << try_count;
4092 let next_time = Instant::now() + Duration::from_millis(next_delay);
4093 self.add_retransmission(next_time, Command::Resolve(instance, try_count + 1));
4094 } else {
4095 self.pending_resolves.remove(&instance);
4097 }
4098 }
4099
4100 fn exec_command_unregister(
4101 &mut self,
4102 repeating: bool,
4103 fullname: String,
4104 resp_s: Sender<UnregisterStatus>,
4105 ) {
4106 let response = match self.my_services.remove_entry(&fullname) {
4107 None => {
4108 debug!("unregister: cannot find such service {}", &fullname);
4109 UnregisterStatus::NotFound
4110 }
4111 Some((_k, info)) => {
4112 let mut timers = Vec::new();
4113
4114 for (if_index, intf) in self.my_intfs.iter() {
4115 if let Some(sock) = self.ipv4_sock.as_ref() {
4116 let packet = self.unregister_service(&info, intf, &sock.pktinfo);
4117 if !repeating && !packet.is_empty() {
4119 let next_time = Instant::now() + Duration::from_millis(120);
4120 self.retransmissions.push(ReRun {
4121 next_time,
4122 command: Command::UnregisterResend(packet, *if_index, true),
4123 });
4124 timers.push(next_time);
4125 }
4126 }
4127
4128 if let Some(sock) = self.ipv6_sock.as_ref() {
4130 let packet = self.unregister_service(&info, intf, &sock.pktinfo);
4131 if !repeating && !packet.is_empty() {
4132 let next_time = Instant::now() + Duration::from_millis(120);
4133 self.retransmissions.push(ReRun {
4134 next_time,
4135 command: Command::UnregisterResend(packet, *if_index, false),
4136 });
4137 timers.push(next_time);
4138 }
4139 }
4140 }
4141
4142 for t in timers {
4143 self.add_timer(t);
4144 }
4145
4146 self.increase_counter(Counter::Unregister, 1);
4147 UnregisterStatus::OK
4148 }
4149 };
4150 if let Err(e) = resp_s.send(response) {
4151 debug!("unregister: failed to send response: {}", e);
4152 }
4153 }
4154
4155 fn exec_command_unregister_resend(&mut self, packet: Vec<u8>, if_index: u32, is_ipv4: bool) {
4156 let Some(intf) = self.my_intfs.get(&if_index) else {
4157 return;
4158 };
4159 let sock_opt = if is_ipv4 {
4160 &self.ipv4_sock
4161 } else {
4162 &self.ipv6_sock
4163 };
4164 let Some(sock) = sock_opt else {
4165 return;
4166 };
4167
4168 let if_addr = if is_ipv4 {
4169 match intf.next_ifaddr_v4() {
4170 Some(addr) => addr,
4171 None => return,
4172 }
4173 } else {
4174 match intf.next_ifaddr_v6() {
4175 Some(addr) => addr,
4176 None => return,
4177 }
4178 };
4179
4180 debug!("UnregisterResend from {:?}", if_addr);
4181 multicast_on_intf(
4182 &packet[..],
4183 &intf.name,
4184 intf.index,
4185 if_addr,
4186 &sock.pktinfo,
4187 self.port,
4188 );
4189
4190 self.increase_counter(Counter::UnregisterResend, 1);
4191 }
4192
4193 fn exec_command_stop_browse(&mut self, ty_domain: String) {
4194 match self.service_queriers.remove_entry(&ty_domain) {
4195 None => debug!("StopBrowse: cannot find querier for {}", &ty_domain),
4196 Some((ty, sender)) => {
4197 trace!("StopBrowse: removed queryer for {}", &ty);
4199 let mut i = 0;
4200 while i < self.retransmissions.len() {
4201 if let Command::Browse(t, _, _, _) = &self.retransmissions[i].command {
4202 if t == &ty {
4203 self.retransmissions.remove(i);
4204 trace!("StopBrowse: removed retransmission for {}", &ty);
4205 continue;
4206 }
4207 }
4208 i += 1;
4209 }
4210
4211 self.cache.remove_service_type(&ty_domain);
4213
4214 match sender.send(ServiceEvent::SearchStopped(ty_domain)) {
4216 Ok(()) => trace!("Sent SearchStopped to the listener"),
4217 Err(e) => debug!("Failed to send SearchStopped: {}", e),
4218 }
4219 }
4220 }
4221 }
4222
4223 fn exec_command_stop_resolve_hostname(&mut self, hostname: String) {
4224 if let Some((host, (sender, _timeout))) = self.hostname_resolvers.remove_entry(&hostname) {
4225 trace!("StopResolve: removed queryer for {}", &host);
4227 let mut i = 0;
4228 while i < self.retransmissions.len() {
4229 if let Command::Resolve(t, _) = &self.retransmissions[i].command {
4230 if t == &host {
4231 self.retransmissions.remove(i);
4232 trace!("StopResolve: removed retransmission for {}", &host);
4233 continue;
4234 }
4235 }
4236 i += 1;
4237 }
4238
4239 match sender.send(HostnameResolutionEvent::SearchStopped(hostname)) {
4241 Ok(()) => trace!("Sent SearchStopped to the listener"),
4242 Err(e) => debug!("Failed to send SearchStopped: {}", e),
4243 }
4244 }
4245 }
4246
4247 fn exec_command_register_resend(&mut self, fullname: String, if_index: u32) -> MyResult<()> {
4248 let Some(info) = self.my_services.get_mut(&fullname) else {
4249 trace!("announce: cannot find such service {}", &fullname);
4250 return Ok(());
4251 };
4252
4253 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
4254 return Ok(());
4255 };
4256
4257 let Some(intf) = self.my_intfs.get(&if_index) else {
4258 return Ok(());
4259 };
4260
4261 let announced_v4 = if let Some(sock) = self.ipv4_sock.as_ref() {
4262 announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port)?
4263 } else {
4264 false
4265 };
4266 let announced_v6 = if let Some(sock) = self.ipv6_sock.as_ref() {
4267 announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port)?
4268 } else {
4269 false
4270 };
4271
4272 if announced_v4 || announced_v6 {
4273 let hostname = dns_registry.resolve_name(info.get_hostname());
4274 let service_name = dns_registry.resolve_name(&fullname).to_string();
4275
4276 debug!("resend: announce service {service_name} on {}", intf.name);
4277
4278 notify_monitors(
4279 &mut self.monitors,
4280 DaemonEvent::Announce(service_name, format!("{}:{}", hostname, &intf.name)),
4281 );
4282 info.set_status(if_index, ServiceStatus::Announced);
4283 } else {
4284 debug!("register-resend should not fail");
4285 }
4286
4287 self.increase_counter(Counter::RegisterResend, 1);
4288 Ok(())
4289 }
4290
4291 fn exec_command_verify(&mut self, instance: String, timeout: Duration, repeating: bool) {
4292 let now = Instant::now();
4302 let expire_at = if repeating {
4303 None
4304 } else {
4305 Some(now + Duration::from_millis(timeout.as_millis() as u64))
4306 };
4307
4308 let record_vec = self.cache.service_verify_queries(&instance, expire_at);
4310
4311 if !record_vec.is_empty() {
4312 let query_vec: Vec<(&str, RRType)> = record_vec
4313 .iter()
4314 .map(|(record, rr_type)| (record.as_str(), *rr_type))
4315 .collect();
4316 self.send_query_vec(&query_vec);
4317
4318 if let Some(new_expire) = expire_at {
4319 self.add_timer(new_expire); self.add_retransmission(
4323 now + Duration::from_millis(1000),
4324 Command::Verify(instance, timeout),
4325 );
4326 }
4327 }
4328 }
4329
4330 fn refresh_active_services(&mut self) {
4332 let mut query_ptr_count = 0;
4333 let mut query_srv_count = 0;
4334 let mut new_timers = HashSet::new();
4335 let mut query_addr_count = 0;
4336
4337 for (ty_domain, _sender) in self.service_queriers.iter() {
4338 let refreshed_timers = self.cache.refresh_due_ptr(ty_domain);
4339 if !refreshed_timers.is_empty() {
4340 trace!("sending refresh query for PTR: {}", ty_domain);
4341 self.send_query(ty_domain, RRType::PTR);
4342 query_ptr_count += 1;
4343 new_timers.extend(refreshed_timers);
4344 }
4345
4346 let (instances, timers) = self.cache.refresh_due_srv_txt(ty_domain);
4347 for (instance, types) in instances {
4348 trace!("sending refresh query for: {}", &instance);
4349 let query_vec = types
4350 .into_iter()
4351 .map(|ty| (instance.as_str(), ty))
4352 .collect::<Vec<_>>();
4353 self.send_query_vec(&query_vec);
4354 query_srv_count += 1;
4355 }
4356 new_timers.extend(timers);
4357 let (hostnames, timers) = self.cache.refresh_due_hosts(ty_domain);
4358 for hostname in hostnames.iter() {
4359 trace!("sending refresh queries for A and AAAA: {}", hostname);
4360 self.send_query_vec(&[(hostname, RRType::A), (hostname, RRType::AAAA)]);
4361 query_addr_count += 2;
4362 }
4363 new_timers.extend(timers);
4364 }
4365
4366 for timer in new_timers {
4367 self.add_timer(timer);
4368 }
4369
4370 self.increase_counter(Counter::CacheRefreshPTR, query_ptr_count);
4371 self.increase_counter(Counter::CacheRefreshSrvTxt, query_srv_count);
4372 self.increase_counter(Counter::CacheRefreshAddr, query_addr_count);
4373 }
4374}
4375
4376fn add_answer_of_service(
4378 out: &mut DnsOutgoing,
4379 msg: &DnsIncoming,
4380 entry_name: &str,
4381 service: &ServiceInfo,
4382 qtype: RRType,
4383 intf_addrs: Vec<IpAddr>,
4384) {
4385 if qtype == RRType::SRV || qtype == RRType::ANY {
4386 out.add_answer(
4387 msg,
4388 DnsSrv::new(
4389 entry_name,
4390 CLASS_IN | CLASS_CACHE_FLUSH,
4391 service.get_host_ttl(),
4392 service.get_priority(),
4393 service.get_weight(),
4394 service.get_port(),
4395 service.get_hostname().to_string(),
4396 ),
4397 );
4398 }
4399
4400 if qtype == RRType::TXT || qtype == RRType::ANY {
4401 out.add_answer(
4402 msg,
4403 DnsTxt::new(
4404 entry_name,
4405 CLASS_IN | CLASS_CACHE_FLUSH,
4406 service.get_other_ttl(),
4407 service.generate_txt(),
4408 ),
4409 );
4410 }
4411
4412 if qtype == RRType::SRV {
4413 for address in intf_addrs {
4414 out.add_additional_answer(DnsAddress::new(
4415 service.get_hostname(),
4416 ip_address_rr_type(&address),
4417 CLASS_IN | CLASS_CACHE_FLUSH,
4418 service.get_host_ttl(),
4419 address,
4420 InterfaceId::default(),
4421 ));
4422 }
4423 }
4424}
4425
4426fn answer_hostname_question(
4433 services: &HashMap<String, ServiceInfo>,
4434 intf: &MyIntf,
4435 question: &DnsQuestion,
4436 dns_registry: &DnsRegistry,
4437 out: &mut DnsOutgoing,
4438 msg: &DnsIncoming,
4439) {
4440 let if_index = intf.index;
4441 let qtype = question.entry_type();
4442 let mut hostname = None;
4443 let mut host_ttl = u32::MAX;
4444 let mut has_ipv4 = false;
4445 let mut has_ipv6 = false;
4446 for service in services.values() {
4447 if service.get_status(if_index) != ServiceStatus::Announced {
4448 continue;
4449 }
4450
4451 let service_hostname = dns_registry.resolve_name(service.get_hostname());
4452
4453 if service_hostname.to_lowercase() == question.entry_name().to_lowercase() {
4454 let ipv4 = service.get_addrs_on_my_intf_v4(intf);
4455 let ipv6 = service.get_addrs_on_my_intf_v6(intf);
4456 if ipv4.is_empty() && ipv6.is_empty() {
4457 continue;
4458 }
4459 hostname = Some(service_hostname);
4460 host_ttl = host_ttl.min(service.get_host_ttl());
4461 has_ipv4 |= !ipv4.is_empty();
4462 has_ipv6 |= !ipv6.is_empty();
4463 let mut intf_addrs: Vec<IpAddr> = Vec::new();
4470 if qtype == RRType::A || qtype == RRType::ANY {
4471 intf_addrs.extend(ipv4);
4472 }
4473 if qtype == RRType::AAAA || qtype == RRType::ANY {
4474 intf_addrs.extend(ipv6);
4475 }
4476 for address in intf_addrs {
4477 out.add_answer(
4478 msg,
4479 DnsAddress::new(
4480 service_hostname,
4481 ip_address_rr_type(&address),
4482 CLASS_IN | CLASS_CACHE_FLUSH,
4483 service.get_host_ttl(),
4484 address,
4485 intf.into(),
4486 ),
4487 );
4488 }
4489 }
4490 }
4491 let missing = match qtype {
4492 RRType::A => !has_ipv4,
4493 RRType::AAAA => !has_ipv6,
4494 RRType::SVCB | RRType::HTTPS => true,
4495 _ => false,
4496 };
4497 if let Some(hostname) = hostname.filter(|_| missing) {
4498 let bitmap = if has_ipv6 {
4503 vec![if has_ipv4 { 0x40 } else { 0 }, 0, 0, 0x08]
4504 } else {
4505 vec![0x40]
4506 };
4507 out.add_answer(
4508 msg,
4509 DnsNSec::new(
4510 hostname,
4511 CLASS_IN | CLASS_CACHE_FLUSH,
4512 host_ttl,
4513 hostname.to_string(),
4514 bitmap,
4515 ),
4516 );
4517 }
4518}
4519
4520#[derive(Clone, Debug)]
4523#[non_exhaustive]
4524pub enum ServiceEvent {
4525 SearchStarted(String),
4527
4528 ServiceFound(String, String),
4530
4531 ServiceResolved(Box<ResolvedService>),
4533
4534 ServiceRemoved(String, String),
4536
4537 SearchStopped(String),
4539}
4540
4541#[derive(Clone, Debug)]
4544#[non_exhaustive]
4545pub enum HostnameResolutionEvent {
4546 SearchStarted(String),
4548 AddressesFound(String, HashSet<ScopedIp>),
4550 AddressesRemoved(String, HashSet<ScopedIp>),
4552 SearchTimeout(String),
4554 SearchStopped(String),
4556}
4557
4558#[derive(Clone, Debug)]
4561#[non_exhaustive]
4562pub enum DaemonEvent {
4563 Announce(String, String),
4565
4566 Error(Error),
4568
4569 IpAdd(IpAddr),
4571
4572 IpDel(IpAddr),
4574
4575 NameChange(DnsNameChange),
4578
4579 Respond(String),
4581}
4582
4583#[derive(Clone, Debug)]
4586pub struct DnsNameChange {
4587 pub original: String,
4589
4590 pub new_name: String,
4600
4601 pub rr_type: RRType,
4603
4604 pub intf_name: String,
4606}
4607
4608#[derive(Debug)]
4610enum Command {
4611 Browse(String, u32, bool, Sender<ServiceEvent>),
4613
4614 ResolveHostname(String, u32, Sender<HostnameResolutionEvent>, Option<u64>), Register(Box<ServiceInfo>),
4619
4620 Unregister(String, Sender<UnregisterStatus>), RegisterResend(String, u32), UnregisterResend(Vec<u8>, u32, bool), StopBrowse(String), StopResolveHostname(String), Resolve(String, u16), GetMetrics(Sender<Metrics>),
4641
4642 GetStatus(Sender<DaemonStatus>),
4644
4645 Monitor(Sender<DaemonEvent>),
4647
4648 SetOption(DaemonOption),
4649
4650 GetOption(Sender<DaemonOptionVal>),
4651
4652 Verify(String, Duration),
4657
4658 InvalidIntfAddrs(HashSet<Interface>),
4660
4661 Exit(Sender<DaemonStatus>),
4662}
4663
4664impl fmt::Display for Command {
4665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4666 match self {
4667 Self::Browse(_, _, _, _) => write!(f, "Command Browse"),
4668 Self::ResolveHostname(_, _, _, _) => write!(f, "Command ResolveHostname"),
4669 Self::Exit(_) => write!(f, "Command Exit"),
4670 Self::GetStatus(_) => write!(f, "Command GetStatus"),
4671 Self::GetMetrics(_) => write!(f, "Command GetMetrics"),
4672 Self::Monitor(_) => write!(f, "Command Monitor"),
4673 Self::Register(_) => write!(f, "Command Register"),
4674 Self::RegisterResend(_, _) => write!(f, "Command RegisterResend"),
4675 Self::SetOption(_) => write!(f, "Command SetOption"),
4676 Self::GetOption(_) => write!(f, "Command GetOption"),
4677 Self::StopBrowse(_) => write!(f, "Command StopBrowse"),
4678 Self::StopResolveHostname(_) => write!(f, "Command StopResolveHostname"),
4679 Self::Unregister(_, _) => write!(f, "Command Unregister"),
4680 Self::UnregisterResend(_, _, _) => write!(f, "Command UnregisterResend"),
4681 Self::Resolve(_, _) => write!(f, "Command Resolve"),
4682 Self::Verify(_, _) => write!(f, "Command VerifyResource"),
4683 Self::InvalidIntfAddrs(_) => write!(f, "Command InvalidIntfAddrs"),
4684 }
4685 }
4686}
4687
4688struct DaemonOptionVal {
4689 _service_name_len_max: u8,
4690 ip_check_interval: u64,
4691}
4692
4693#[derive(Debug)]
4694enum DaemonOption {
4695 ServiceNameLenMax(u8),
4696 IpCheckInterval(u64),
4697 MaxPacketSize(Vec<IfKind>, usize),
4698 EnableInterface(Vec<IfKind>),
4699 DisableInterface(Vec<IfKind>),
4700 MulticastLoopV4(bool),
4701 MulticastLoopV6(bool),
4702 AcceptUnsolicited(bool),
4703 IncludeAppleP2P(bool),
4704 #[cfg(test)]
4705 TestDownInterface(String),
4706 #[cfg(test)]
4707 TestUpInterface(String),
4708}
4709
4710const DOMAIN_LEN: usize = "._tcp.local.".len();
4712
4713fn slept_duration(instant_elapsed: Duration, wall_elapsed: Option<Duration>) -> Option<Duration> {
4716 let gap = wall_elapsed?.checked_sub(instant_elapsed)?;
4717 (gap > SLEEP_DETECTION_THRESHOLD).then_some(gap)
4718}
4719
4720fn check_service_name_length(ty_domain: &str, limit: u8) -> Result<()> {
4722 if ty_domain.len() <= DOMAIN_LEN + 1 {
4723 return Err(e_fmt!("Service type name cannot be empty: {}", ty_domain));
4725 }
4726
4727 let service_name_len = ty_domain.len() - DOMAIN_LEN - 1; if service_name_len > limit as usize {
4729 return Err(e_fmt!("Service name length must be <= {} bytes", limit));
4730 }
4731 Ok(())
4732}
4733
4734fn check_domain_suffix(name: &str) -> Result<()> {
4736 if !(name.ends_with("._tcp.local.") || name.ends_with("._udp.local.")) {
4737 return Err(e_fmt!(
4738 "mDNS service {} must end with '._tcp.local.' or '._udp.local.'",
4739 name
4740 ));
4741 }
4742
4743 Ok(())
4744}
4745
4746fn check_service_name(fullname: &str) -> Result<()> {
4754 check_domain_suffix(fullname)?;
4755
4756 let remaining: Vec<&str> = fullname[..fullname.len() - DOMAIN_LEN].split('.').collect();
4757 let name = remaining.last().ok_or_else(|| e_fmt!("No service name"))?;
4758
4759 if &name[0..1] != "_" {
4760 return Err(e_fmt!("Service name must start with '_'"));
4761 }
4762
4763 let name = &name[1..];
4764
4765 if name.contains("--") {
4766 return Err(e_fmt!("Service name must not contain '--'"));
4767 }
4768
4769 if name.starts_with('-') || name.ends_with('-') {
4770 return Err(e_fmt!("Service name (%s) may not start or end with '-'"));
4771 }
4772
4773 let ascii_count = name.chars().filter(|c| c.is_ascii_alphabetic()).count();
4774 if ascii_count < 1 {
4775 return Err(e_fmt!(
4776 "Service name must contain at least one letter (eg: 'A-Za-z')"
4777 ));
4778 }
4779
4780 Ok(())
4781}
4782
4783fn check_hostname(hostname: &str) -> Result<()> {
4785 if !hostname.ends_with(".local.") {
4786 return Err(e_fmt!("Hostname must end with '.local.': {hostname}"));
4787 }
4788
4789 if hostname == ".local." {
4790 return Err(e_fmt!(
4791 "The part of the hostname before '.local.' cannot be empty"
4792 ));
4793 }
4794
4795 if hostname.len() > 255 {
4796 return Err(e_fmt!("Hostname length must be <= 255 bytes"));
4797 }
4798
4799 Ok(())
4800}
4801
4802fn call_service_listener(
4803 listeners_map: &HashMap<String, Sender<ServiceEvent>>,
4804 ty_domain: &str,
4805 event: ServiceEvent,
4806) {
4807 if let Some(listener) = listeners_map.get(ty_domain) {
4808 match listener.send(event) {
4809 Ok(()) => trace!("Sent event to listener successfully"),
4810 Err(e) => debug!("Failed to send event: {}", e),
4811 }
4812 }
4813}
4814
4815fn call_hostname_resolution_listener(
4816 listeners_map: &HashMap<String, (Sender<HostnameResolutionEvent>, Option<Instant>)>,
4817 hostname: &str,
4818 event: HostnameResolutionEvent,
4819) {
4820 let hostname_lower = hostname.to_lowercase();
4821 if let Some(listener) = listeners_map.get(&hostname_lower).map(|(l, _)| l) {
4822 match listener.send(event) {
4823 Ok(()) => trace!("Sent event to listener successfully"),
4824 Err(e) => debug!("Failed to send event: {}", e),
4825 }
4826 }
4827}
4828
4829fn my_ip_interfaces(with_loopback: bool) -> Vec<Interface> {
4833 my_ip_interfaces_inner(with_loopback, false)
4834}
4835
4836fn my_ip_interfaces_inner(with_loopback: bool, with_apple_p2p: bool) -> Vec<Interface> {
4837 if_addrs::get_if_addrs()
4838 .unwrap_or_default()
4839 .into_iter()
4840 .filter(|i| {
4841 i.is_oper_up()
4842 && !i.is_p2p()
4843 && (!i.is_loopback() || with_loopback)
4844 && (with_apple_p2p || !is_apple_p2p_by_name(&i.name))
4845 })
4846 .collect()
4847}
4848
4849fn is_apple_p2p_by_name(name: &str) -> bool {
4852 let p2p_prefixes = ["awdl", "llw"];
4853 p2p_prefixes.iter().any(|prefix| name.starts_with(prefix))
4854}
4855
4856#[derive(Clone, Copy, Debug)]
4858struct SendConfig {
4859 port: u16,
4861
4862 max_packet_size: usize,
4865
4866 is_ipv4: bool,
4869}
4870
4871fn send_dns_outgoing(
4874 out: &DnsOutgoing,
4875 my_intf: &MyIntf,
4876 sock: &PktInfoUdpSocket,
4877 port: u16,
4878 source: Option<&IfAddr>,
4879 unicast_dest: Option<SocketAddr>,
4880) -> MyResult<Vec<Vec<u8>>> {
4881 let if_name = &my_intf.name;
4882
4883 let if_addr = match source {
4884 Some(addr) => addr,
4885 None => {
4886 if sock.domain() == Domain::IPV4 {
4887 match my_intf.next_ifaddr_v4() {
4888 Some(addr) => addr,
4889 None => return Ok(vec![]),
4890 }
4891 } else {
4892 match my_intf.next_ifaddr_v6() {
4893 Some(addr) => addr,
4894 None => return Ok(vec![]),
4895 }
4896 }
4897 }
4898 };
4899
4900 let is_ipv4 = if_addr.ip().is_ipv4();
4902 let config = SendConfig {
4903 port,
4904 max_packet_size: my_intf.max_packet_size(is_ipv4),
4905 is_ipv4,
4906 };
4907
4908 send_dns_outgoing_impl(
4909 out,
4910 if_name,
4911 my_intf.index,
4912 if_addr,
4913 sock,
4914 config,
4915 unicast_dest,
4916 )
4917}
4918
4919fn send_dns_outgoing_impl(
4921 out: &DnsOutgoing,
4922 if_name: &str,
4923 if_index: u32,
4924 if_addr: &IfAddr,
4925 sock: &PktInfoUdpSocket,
4926 config: SendConfig,
4927 unicast_dest: Option<SocketAddr>,
4928) -> MyResult<Vec<Vec<u8>>> {
4929 let qtype = if out.is_query() {
4930 "query"
4931 } else {
4932 if out.answers_count() == 0 && out.additionals().is_empty() {
4933 return Ok(vec![]); }
4935 "response"
4936 };
4937 trace!(
4938 "send {}: {} questions {} answers {} authorities {} additional",
4939 qtype,
4940 out.questions().len(),
4941 out.answers_count(),
4942 out.authorities().len(),
4943 out.additionals().len()
4944 );
4945
4946 match if_addr.ip() {
4947 IpAddr::V4(ipv4) => {
4948 if let Err(e) = sock.set_multicast_if_v4(&ipv4) {
4949 debug!(
4950 "send_dns_outgoing: failed to set multicast interface for IPv4 {}: {}",
4951 ipv4, e
4952 );
4953 if e.kind() == std::io::ErrorKind::AddrNotAvailable {
4955 let intf_addr = Interface {
4956 name: if_name.to_string(),
4957 addr: if_addr.clone(),
4958 index: Some(if_index),
4959 oper_status: if_addrs::IfOperStatus::Down,
4960 is_p2p: false,
4961 #[cfg(windows)]
4962 adapter_name: String::new(),
4963 };
4964 return Err(InternalError::IntfAddrInvalid(intf_addr));
4965 }
4966 return Ok(vec![]); }
4968 }
4969 IpAddr::V6(ipv6) => {
4970 if let Err(e) = sock.set_multicast_if_v6(if_index) {
4971 debug!(
4972 "send_dns_outgoing: failed to set multicast interface for IPv6 {}: {}",
4973 ipv6, e
4974 );
4975 if e.kind() == std::io::ErrorKind::AddrNotAvailable {
4977 let intf_addr = Interface {
4978 name: if_name.to_string(),
4979 addr: if_addr.clone(),
4980 index: Some(if_index),
4981 oper_status: if_addrs::IfOperStatus::Down,
4982 is_p2p: false,
4983 #[cfg(windows)]
4984 adapter_name: String::new(),
4985 };
4986 return Err(InternalError::IntfAddrInvalid(intf_addr));
4987 }
4988 return Ok(vec![]); }
4990 }
4991 }
4992
4993 let packet_list = out.to_data_on_wire(config.max_packet_size, config.is_ipv4);
4994 for packet in packet_list.iter() {
4995 match unicast_dest {
4996 Some(dest) => unicast_on_intf(packet, if_name, dest, sock),
4997 None => multicast_on_intf(packet, if_name, if_index, if_addr, sock, config.port),
4998 }
4999 }
5000 Ok(packet_list)
5001}
5002
5003fn unicast_on_intf(packet: &[u8], if_name: &str, dest: SocketAddr, socket: &PktInfoUdpSocket) {
5006 let max_size = max_pkt_absolute(dest.is_ipv4());
5007 if packet.len() > max_size {
5008 debug!("Drop over-sized packet ({} > {max_size})", packet.len());
5009 return;
5010 }
5011
5012 let sock_addr = dest.into();
5013 match socket.send_to(packet, &sock_addr) {
5014 Ok(sz) => trace!(
5015 "sent unicast {} bytes on interface {} to {}",
5016 sz,
5017 if_name,
5018 dest
5019 ),
5020 Err(e) => trace!(
5021 "Failed to send unicast to {} via {:?}: {}",
5022 dest,
5023 &if_name,
5024 e
5025 ),
5026 }
5027}
5028
5029fn multicast_on_intf(
5031 packet: &[u8],
5032 if_name: &str,
5033 if_index: u32,
5034 if_addr: &IfAddr,
5035 socket: &PktInfoUdpSocket,
5036 port: u16,
5037) {
5038 let max_size = max_pkt_absolute(if_addr.ip().is_ipv4());
5039 if packet.len() > max_size {
5040 debug!("Drop over-sized packet ({} > {max_size})", packet.len());
5041 return;
5042 }
5043
5044 let addr: SocketAddr = match if_addr {
5045 if_addrs::IfAddr::V4(_) => SocketAddrV4::new(GROUP_ADDR_V4, port).into(),
5046 if_addrs::IfAddr::V6(_) => {
5047 let mut sock = SocketAddrV6::new(GROUP_ADDR_V6, port, 0, 0);
5048 sock.set_scope_id(if_index); sock.into()
5050 }
5051 };
5052
5053 let sock_addr = addr.into();
5055 match socket.send_to(packet, &sock_addr) {
5056 Ok(sz) => trace!(
5057 "sent out {} bytes on interface {} (idx {}) addr {}",
5058 sz,
5059 if_name,
5060 if_index,
5061 if_addr.ip()
5062 ),
5063 Err(e) => trace!("Failed to send to {} via {:?}: {}", addr, &if_name, e),
5064 }
5065}
5066
5067fn valid_instance_name(name: &str) -> bool {
5071 name.split('.').count() >= 5
5072}
5073
5074fn notify_monitors(monitors: &mut Vec<Sender<DaemonEvent>>, event: DaemonEvent) {
5075 monitors.retain(|sender| {
5076 if let Err(e) = sender.try_send(event.clone()) {
5077 debug!("notify_monitors: try_send: {}", &e);
5078 if matches!(e, TrySendError::Disconnected(_)) {
5079 return false; }
5081 }
5082 true
5083 });
5084}
5085
5086fn prepare_announce(
5089 info: &ServiceInfo,
5090 intf: &MyIntf,
5091 dns_registry: &mut DnsRegistry,
5092 is_ipv4: bool,
5093) -> Option<DnsOutgoing> {
5094 let intf_addrs = if is_ipv4 {
5095 info.get_addrs_on_my_intf_v4(intf)
5096 } else {
5097 info.get_addrs_on_my_intf_v6(intf)
5098 };
5099
5100 if intf_addrs.is_empty() {
5101 debug!(
5102 "prepare_announce (ipv4: {is_ipv4}): no valid addrs on interface {}",
5103 &intf.name
5104 );
5105 return None;
5106 }
5107
5108 let service_fullname = dns_registry.resolve_name(info.get_fullname());
5110
5111 debug!(
5112 "prepare to announce service {service_fullname} on {:?}",
5113 &intf_addrs
5114 );
5115
5116 let mut probing_count = 0;
5117 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
5118 let create_time = Instant::now() + Duration::from_millis(fastrand::u64(0..250));
5119
5120 out.add_answer_record(DnsPointer::new(
5121 info.get_type(),
5122 RRType::PTR,
5123 CLASS_IN,
5124 info.get_other_ttl(),
5125 service_fullname.to_string(),
5126 ));
5127
5128 if let Some(sub) = info.get_subtype() {
5129 trace!("Adding subdomain {}", sub);
5130 out.add_answer_record(DnsPointer::new(
5131 sub,
5132 RRType::PTR,
5133 CLASS_IN,
5134 info.get_other_ttl(),
5135 service_fullname.to_string(),
5136 ));
5137 }
5138
5139 let hostname = dns_registry.resolve_name(info.get_hostname()).to_string();
5141
5142 let mut srv = DnsSrv::new(
5143 info.get_fullname(),
5144 CLASS_IN | CLASS_CACHE_FLUSH,
5145 info.get_host_ttl(),
5146 info.get_priority(),
5147 info.get_weight(),
5148 info.get_port(),
5149 hostname,
5150 );
5151
5152 if let Some(new_name) = dns_registry.name_changes.get(info.get_fullname()) {
5153 srv.get_record_mut().set_new_name(new_name.to_string());
5154 }
5155
5156 if !info.requires_probe()
5157 || dns_registry.is_probing_done(&srv, info.get_fullname(), create_time)
5158 {
5159 out.add_answer_record(srv);
5160 } else {
5161 probing_count += 1;
5162 }
5163
5164 let mut txt = DnsTxt::new(
5167 info.get_fullname(),
5168 CLASS_IN | CLASS_CACHE_FLUSH,
5169 info.get_other_ttl(),
5170 info.generate_txt(),
5171 );
5172
5173 if let Some(new_name) = dns_registry.name_changes.get(info.get_fullname()) {
5174 txt.get_record_mut().set_new_name(new_name.to_string());
5175 }
5176
5177 if !info.requires_probe()
5178 || dns_registry.is_probing_done(&txt, info.get_fullname(), create_time)
5179 {
5180 out.add_answer_record(txt);
5181 } else {
5182 probing_count += 1;
5183 }
5184
5185 let hostname = info.get_hostname();
5188 for address in intf_addrs {
5189 let mut dns_addr = DnsAddress::new(
5190 hostname,
5191 ip_address_rr_type(&address),
5192 CLASS_IN | CLASS_CACHE_FLUSH,
5193 info.get_host_ttl(),
5194 address,
5195 intf.into(),
5196 );
5197
5198 if let Some(new_name) = dns_registry.name_changes.get(hostname) {
5199 dns_addr.get_record_mut().set_new_name(new_name.to_string());
5200 }
5201
5202 if !info.requires_probe()
5203 || dns_registry.is_probing_done(&dns_addr, info.get_fullname(), create_time)
5204 {
5205 out.add_answer_record(dns_addr);
5206 } else {
5207 probing_count += 1;
5208 }
5209 }
5210
5211 if probing_count > 0 {
5212 return None;
5213 }
5214
5215 Some(out)
5216}
5217
5218fn announce_service_on_intf(
5221 dns_registry: &mut DnsRegistry,
5222 info: &ServiceInfo,
5223 intf: &MyIntf,
5224 sock: &PktInfoUdpSocket,
5225 port: u16,
5226) -> MyResult<bool> {
5227 let is_ipv4 = sock.domain() == Domain::IPV4;
5228 if let Some(mut out) = prepare_announce(info, intf, dns_registry, is_ipv4) {
5229 dns_registry.apply_multicast_rate_limit(&mut out, Instant::now(), is_ipv4);
5232 if out.answers_count() > 0 {
5233 let _ = send_dns_outgoing(&out, intf, sock, port, None, None)?;
5234 }
5235 return Ok(true);
5236 }
5237
5238 Ok(false)
5239}
5240
5241fn name_change(original: &str) -> String {
5249 let mut parts: Vec<_> = original.split('.').collect();
5250 let Some(first_part) = parts.get_mut(0) else {
5251 return format!("{original} (2)");
5252 };
5253
5254 let mut new_name = format!("{first_part} (2)");
5255
5256 if let Some(paren_pos) = first_part.rfind(" (") {
5258 if let Some(end_paren) = first_part[paren_pos..].find(')') {
5260 let absolute_end_pos = paren_pos + end_paren;
5261 if absolute_end_pos == first_part.len() - 1 {
5263 let num_start = paren_pos + 2; if let Ok(number) = first_part[num_start..absolute_end_pos].parse::<u32>() {
5266 let base_name = &first_part[..paren_pos];
5267 new_name = format!("{} ({})", base_name, number + 1)
5268 }
5269 }
5270 }
5271 }
5272
5273 *first_part = &new_name;
5274 parts.join(".")
5275}
5276
5277fn hostname_change(original: &str) -> String {
5285 let mut parts: Vec<_> = original.split('.').collect();
5286 let Some(first_part) = parts.get_mut(0) else {
5287 return format!("{original}-2");
5288 };
5289
5290 let mut new_name = format!("{first_part}-2");
5291
5292 if let Some(hyphen_pos) = first_part.rfind('-') {
5294 if let Ok(number) = first_part[hyphen_pos + 1..].parse::<u32>() {
5296 let base_name = &first_part[..hyphen_pos];
5297 new_name = format!("{}-{}", base_name, number + 1);
5298 }
5299 }
5300
5301 *first_part = &new_name;
5302 parts.join(".")
5303}
5304
5305fn check_probing(
5308 dns_registry: &mut DnsRegistry,
5309 timers: &mut BinaryHeap<Reverse<Instant>>,
5310 now: Instant,
5311) -> (DnsOutgoing, Vec<String>) {
5312 let mut expired_probes = Vec::new();
5313 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
5314
5315 for (name, probe) in dns_registry.probing.iter_mut() {
5316 if now >= probe.next_send {
5317 if probe.expired(now) {
5318 expired_probes.push(name.clone());
5320 } else {
5321 out.add_question(name, RRType::ANY);
5322
5323 for record in probe.records.iter() {
5331 out.add_authority(record.clone());
5332 }
5333
5334 probe.update_next_send(now);
5335
5336 timers.push(Reverse(probe.next_send));
5338 }
5339 }
5340 }
5341
5342 (out, expired_probes)
5343}
5344
5345fn handle_expired_probes(
5350 expired_probes: Vec<String>,
5351 intf_name: &str,
5352 dns_registry: &mut DnsRegistry,
5353 monitors: &mut Vec<Sender<DaemonEvent>>,
5354) -> HashSet<String> {
5355 let mut waiting_services = HashSet::new();
5356
5357 for name in expired_probes {
5358 let Some(probe) = dns_registry.probing.remove(&name) else {
5359 continue;
5360 };
5361
5362 for record in probe.records.iter() {
5364 if let Some(new_name) = record.get_record().get_new_name() {
5365 dns_registry
5366 .name_changes
5367 .insert(name.clone(), new_name.to_string());
5368
5369 let event = DnsNameChange {
5370 original: record.get_record().get_original_name().to_string(),
5371 new_name: new_name.to_string(),
5372 rr_type: record.get_type(),
5373 intf_name: intf_name.to_string(),
5374 };
5375 debug!("Name change event: {:?}", &event);
5376 notify_monitors(monitors, DaemonEvent::NameChange(event));
5377 }
5378 }
5379
5380 debug!(
5382 "probe of '{name}' finished: move {} records to active. ({} waiting services)",
5383 probe.records.len(),
5384 probe.waiting_services.len(),
5385 );
5386
5387 if !probe.records.is_empty() {
5389 match dns_registry.active.get_mut(&name) {
5390 Some(records) => {
5391 records.extend(probe.records);
5392 }
5393 None => {
5394 dns_registry.active.insert(name, probe.records);
5395 }
5396 }
5397
5398 waiting_services.extend(probe.waiting_services);
5399 }
5400 }
5401
5402 waiting_services
5403}
5404
5405fn resolve_max_packet_size(
5413 selections: &[MaxPacketSizeSelection],
5414 interfaces: &[Interface],
5415 if_index: u32,
5416 is_ipv4: bool,
5417) -> usize {
5418 let mut size = MAX_PKT_DEFAULT;
5419
5420 for selection in selections {
5421 let matched = interfaces.iter().any(|intf| {
5422 intf.index.unwrap_or(0) == if_index
5423 && intf.ip().is_ipv4() == is_ipv4
5424 && selection.if_kind.matches(intf)
5425 });
5426 if matched {
5427 size = selection.max_packet_size;
5428 }
5429 }
5430
5431 size
5432}
5433
5434fn resolve_addr_to_index(if_kind: IfKind, interfaces: &[Interface]) -> IfKind {
5436 if let IfKind::Addr(addr) = &if_kind {
5437 if let Some(intf) = interfaces.iter().find(|intf| &intf.ip() == addr) {
5438 let if_index = intf.index.unwrap_or(0);
5439 return if addr.is_ipv4() {
5440 IfKind::IndexV4(if_index)
5441 } else {
5442 IfKind::IndexV6(if_index)
5443 };
5444 }
5445 }
5446 if_kind
5447}
5448
5449#[cfg(test)]
5450mod tests {
5451 use super::{
5452 _new_socket_bind, check_domain_suffix, check_service_name_length, hostname_change,
5453 my_ip_interfaces, name_change, resolve_max_packet_size, send_dns_outgoing_impl,
5454 valid_instance_name, valid_ip_on_intf, DaemonEvent, HostnameResolutionEvent, IfKind,
5455 MaxPacketSizeSelection, MyIntf, SendConfig, ServiceDaemon, ServiceEvent, ServiceInfo,
5456 GROUP_ADDR_V4, INITIAL_QUERY_DELAY_MAX_MILLIS, INITIAL_QUERY_DELAY_MIN_MILLIS,
5457 MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT, MDNS_PORT, MIN_MAX_PACKET_SIZE, RESOLVE_MAX_TRY,
5458 SHARED_RESPONSE_DELAY_MAX_MILLIS, SHARED_RESPONSE_DELAY_MIN_MILLIS,
5459 };
5460 use crate::{
5461 dns_parser::{
5462 DnsAddress, DnsEntryExt, DnsIncoming, DnsOutgoing, DnsPointer, DnsSrv, InterfaceId,
5463 RRType, ScopedIp, CLASS_IN, FLAGS_AA, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE,
5464 LEGACY_UNICAST_MAX_TTL,
5465 },
5466 service_daemon::{add_answer_of_service, check_hostname},
5467 };
5468 use if_addrs::{IfAddr, Ifv4Addr, Ifv6Addr, Interface};
5469 use std::{
5470 collections::HashSet,
5471 net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket},
5472 time::{Duration, Instant, SystemTime},
5473 };
5474 use test_log::test;
5475
5476 fn test_interface(name: &str, index: u32, addr: IfAddr) -> Interface {
5478 Interface {
5479 name: name.to_string(),
5480 addr,
5481 index: Some(index),
5482 oper_status: if_addrs::IfOperStatus::Up,
5483 is_p2p: false,
5484 #[cfg(windows)]
5485 adapter_name: String::new(),
5486 }
5487 }
5488
5489 fn test_ifaddr_v4(ip: Ipv4Addr) -> IfAddr {
5490 IfAddr::V4(Ifv4Addr {
5491 ip,
5492 netmask: Ipv4Addr::new(255, 255, 255, 0),
5493 broadcast: None,
5494 prefixlen: 24,
5495 })
5496 }
5497
5498 fn test_ifaddr_v6(ip: Ipv6Addr) -> IfAddr {
5499 IfAddr::V6(Ifv6Addr {
5500 ip,
5501 netmask: Ipv6Addr::from(u128::MAX << 64),
5502 broadcast: None,
5503 prefixlen: 64,
5504 })
5505 }
5506
5507 fn new_test_zeroconf() -> super::Zeroconf {
5510 let signal = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
5511 let signal_addr = signal.local_addr().unwrap();
5512 signal.set_nonblocking(true).unwrap();
5513 let port = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))
5514 .unwrap()
5515 .local_addr()
5516 .unwrap()
5517 .port();
5518 let (sender, _receiver) = flume::bounded(100);
5519 super::Zeroconf::new(
5520 mio::net::UdpSocket::from_std(signal),
5521 mio::Poll::new().unwrap(),
5522 port,
5523 sender,
5524 signal_addr,
5525 )
5526 }
5527
5528 #[cfg(not(windows))]
5536 fn holds_ipv4_membership(daemon: &super::Zeroconf, ip: &Ipv4Addr) -> bool {
5537 let sock = daemon.ipv4_sock.as_ref().expect("no IPv4 socket");
5538 match sock.pktinfo.join_multicast_v4(&super::GROUP_ADDR_V4, ip) {
5539 Ok(()) => {
5540 let _ = sock.pktinfo.leave_multicast_v4(&super::GROUP_ADDR_V4, ip);
5542 false
5543 }
5544 Err(e) if e.kind() == std::io::ErrorKind::AddrInUse => true,
5545 Err(e) => panic!("unexpected join error on {}: {}", ip, e),
5546 }
5547 }
5548
5549 #[cfg(not(windows))]
5552 fn loopback_alias() -> Interface {
5553 test_interface("mdns-sd-alias", 65_535, test_ifaddr_v4(Ipv4Addr::LOCALHOST))
5554 }
5555
5556 #[test]
5557 #[cfg(not(windows))]
5558 fn test_interface_sharing_an_ipv4_address_is_recorded() {
5559 let mut daemon = new_test_zeroconf();
5560 assert!(
5561 holds_ipv4_membership(&daemon, &Ipv4Addr::LOCALHOST),
5562 "precondition: the daemon joined the group on loopback at startup"
5563 );
5564
5565 let alias = loopback_alias();
5566 daemon.add_interface(&alias, std::slice::from_ref(&alias));
5567
5568 assert!(
5571 daemon.my_intfs.contains_key(&65_535),
5572 "an interface sharing an already-joined IPv4 address must be recorded"
5573 );
5574 }
5575
5576 #[test]
5577 fn test_slept_duration() {
5578 use super::{slept_duration, SLEEP_DETECTION_THRESHOLD};
5579 let secs = Duration::from_secs;
5580
5581 assert_eq!(slept_duration(secs(60), Some(secs(60))), None);
5583
5584 let drift = secs(60) + SLEEP_DETECTION_THRESHOLD;
5586 assert_eq!(slept_duration(secs(60), Some(drift)), None);
5587
5588 assert_eq!(slept_duration(secs(5), Some(secs(3605))), Some(secs(3600)));
5590
5591 assert_eq!(slept_duration(secs(60), Some(secs(10))), None);
5593 assert_eq!(slept_duration(secs(60), None), None);
5594 }
5595
5596 #[test]
5600 fn test_set_ip_check_interval_reschedules_the_check() {
5601 let mut daemon = new_test_zeroconf();
5602 daemon.schedule_ip_check(Instant::now());
5603 assert!(
5604 daemon.next_ip_check.is_some(),
5605 "precondition: the default interval schedules a check"
5606 );
5607
5608 daemon.process_set_option(super::DaemonOption::IpCheckInterval(0));
5611 assert_eq!(daemon.next_ip_check, None);
5612
5613 let before = Instant::now();
5614 daemon.process_set_option(super::DaemonOption::IpCheckInterval(30_000));
5615 let next = daemon
5616 .next_ip_check
5617 .expect("a nonzero interval must re-enable the check");
5618 assert!(next >= before + Duration::from_secs(30));
5619 assert!(next <= Instant::now() + Duration::from_secs(30));
5620 }
5621
5622 #[test]
5623 #[cfg(not(windows))]
5624 fn test_removing_one_of_two_interfaces_sharing_an_ipv4_address_keeps_the_membership() {
5625 let mut daemon = new_test_zeroconf();
5626 let alias = loopback_alias();
5627 daemon.my_intfs.insert(
5629 65_535,
5630 super::MyIntf {
5631 name: alias.name.clone(),
5632 index: 65_535,
5633 addrs: HashSet::from([alias.addr.clone()]),
5634 max_packet_size_v4: super::MAX_PKT_DEFAULT,
5635 max_packet_size_v6: super::MAX_PKT_DEFAULT,
5636 },
5637 );
5638
5639 daemon.del_interface_addr(&alias);
5640
5641 assert!(
5642 holds_ipv4_membership(&daemon, &Ipv4Addr::LOCALHOST),
5643 "leaving by address would drop the membership the other interface still uses"
5644 );
5645 }
5646
5647 #[test]
5648 fn test_excluded_address_preserves_announced_service() {
5649 use crate::service_info::ServiceStatus;
5650
5651 for ipv4_service in [true, false] {
5652 let signal = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
5653 let signal_addr = signal.local_addr().unwrap();
5654 signal.set_nonblocking(true).unwrap();
5655 let port = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))
5656 .unwrap()
5657 .local_addr()
5658 .unwrap()
5659 .port();
5660 let (sender, _receiver) = flume::bounded(100);
5661 let mut daemon = super::Zeroconf::new(
5662 mio::net::UdpSocket::from_std(signal),
5663 mio::Poll::new().unwrap(),
5664 port,
5665 sender,
5666 signal_addr,
5667 );
5668 let loopback = my_ip_interfaces(true)
5669 .into_iter()
5670 .find(|intf| intf.ip() == IpAddr::V4(Ipv4Addr::LOCALHOST))
5671 .unwrap();
5672 let index = loopback.index.unwrap();
5673 daemon.my_intfs.retain(|key, _| *key == index);
5676 daemon.dns_registry_map.retain(|key, _| *key == index);
5677 let mut service = ServiceInfo::new(
5678 "_address-change._tcp.local.",
5679 "address-change",
5680 "address-change.local.",
5681 "",
5682 8080,
5683 None,
5684 )
5685 .unwrap()
5686 .enable_addr_auto();
5687 service.set_interfaces(vec![if ipv4_service {
5688 IfKind::IPv4
5689 } else {
5690 IfKind::IPv6
5691 }]);
5692 let fullname = service.get_fullname().to_lowercase();
5693 daemon.register_service(service);
5694 assert_eq!(
5695 daemon.my_services[&fullname].get_status(index),
5696 ServiceStatus::Probing
5697 );
5698 assert!(!daemon.dns_registry_map[&index].probing.is_empty());
5699 for probe in daemon
5701 .dns_registry_map
5702 .get_mut(&index)
5703 .unwrap()
5704 .probing
5705 .values_mut()
5706 {
5707 probe.start_time = Instant::now() - Duration::from_millis(1000);
5708 probe.next_send = probe.start_time;
5709 }
5710 daemon.probing_handler();
5711 assert_eq!(
5712 daemon.my_services[&fullname].get_status(index),
5713 ServiceStatus::Announced
5714 );
5715 assert!(!daemon.dns_registry_map[&index].active.is_empty());
5716 let addresses = daemon.my_services[&fullname].get_addresses().clone();
5717
5718 let new_addr = test_interface(
5719 &loopback.name,
5720 index,
5721 if ipv4_service {
5722 test_ifaddr_v6("2001:db8::1234".parse().unwrap())
5723 } else {
5724 test_ifaddr_v4(Ipv4Addr::new(192, 0, 2, 123))
5725 },
5726 );
5727 daemon.add_interface(&new_addr, std::slice::from_ref(&new_addr));
5728 assert!(daemon.my_intfs[&index].addrs.contains(&new_addr.addr));
5729 assert_eq!(daemon.my_services[&fullname].get_addresses(), &addresses);
5730 assert!(daemon.dns_registry_map[&index].probing.is_empty());
5731 assert_eq!(
5732 daemon.my_services[&fullname].get_status(index),
5733 ServiceStatus::Announced,
5734 "an excluded address must not leave the service waiting for nonexistent probes"
5735 );
5736 }
5737 }
5738
5739 #[test]
5740 fn test_resolve_max_packet_size() {
5741 let interfaces = vec![
5743 test_interface("en0", 1, test_ifaddr_v4(Ipv4Addr::new(192, 168, 1, 2))),
5744 test_interface(
5745 "en0",
5746 1,
5747 test_ifaddr_v6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)),
5748 ),
5749 test_interface("en1", 2, test_ifaddr_v4(Ipv4Addr::new(10, 0, 0, 2))),
5750 ];
5751
5752 let resolve = |selections: &[MaxPacketSizeSelection], if_index, is_ipv4| {
5753 resolve_max_packet_size(selections, &interfaces, if_index, is_ipv4)
5754 };
5755
5756 assert_eq!(resolve(&[], 1, true), MAX_PKT_DEFAULT);
5758 assert_eq!(resolve(&[], 1, false), MAX_PKT_DEFAULT);
5759
5760 let by_name = vec![MaxPacketSizeSelection {
5762 if_kind: IfKind::Name("en0".to_string()),
5763 max_packet_size: 8000,
5764 }];
5765 assert_eq!(resolve(&by_name, 1, true), 8000);
5766 assert_eq!(resolve(&by_name, 1, false), 8000);
5767 assert_eq!(resolve(&by_name, 2, true), MAX_PKT_DEFAULT);
5768
5769 let overlapping = vec![
5771 MaxPacketSizeSelection {
5772 if_kind: IfKind::All,
5773 max_packet_size: 8000,
5774 },
5775 MaxPacketSizeSelection {
5776 if_kind: IfKind::Name("en1".to_string()),
5777 max_packet_size: 4000,
5778 },
5779 ];
5780 assert_eq!(resolve(&overlapping, 1, true), 8000);
5781 assert_eq!(resolve(&overlapping, 1, false), 8000);
5782 assert_eq!(resolve(&overlapping, 2, true), 4000);
5783
5784 let v4_only = vec![MaxPacketSizeSelection {
5786 if_kind: IfKind::IPv4,
5787 max_packet_size: 8000,
5788 }];
5789 assert_eq!(resolve(&v4_only, 1, true), 8000);
5790 assert_eq!(resolve(&v4_only, 1, false), MAX_PKT_DEFAULT);
5791
5792 let v6_only = vec![MaxPacketSizeSelection {
5793 if_kind: IfKind::IPv6,
5794 max_packet_size: 8000,
5795 }];
5796 assert_eq!(resolve(&v6_only, 1, false), 8000);
5797 assert_eq!(resolve(&v6_only, 1, true), MAX_PKT_DEFAULT);
5798 assert_eq!(resolve(&v6_only, 2, true), MAX_PKT_DEFAULT);
5800 assert_eq!(resolve(&v6_only, 2, false), MAX_PKT_DEFAULT);
5801
5802 let by_index_v4 = vec![MaxPacketSizeSelection {
5804 if_kind: IfKind::IndexV4(1),
5805 max_packet_size: 8000,
5806 }];
5807 assert_eq!(resolve(&by_index_v4, 1, true), 8000);
5808 assert_eq!(resolve(&by_index_v4, 1, false), MAX_PKT_DEFAULT);
5809 }
5810
5811 #[test]
5814 fn test_set_max_packet_size_range() {
5815 let daemon = ServiceDaemon::new().unwrap();
5816
5817 assert!(daemon
5818 .set_max_packet_size(IfKind::All, MIN_MAX_PACKET_SIZE - 1)
5819 .is_err());
5820 assert!(daemon
5821 .set_max_packet_size(IfKind::All, MAX_PKT_ABSOLUTE_IPV6 + 1)
5822 .is_err());
5823
5824 assert!(daemon
5826 .set_max_packet_size(IfKind::All, MIN_MAX_PACKET_SIZE)
5827 .is_ok());
5828 assert!(daemon
5829 .set_max_packet_size(IfKind::All, MAX_PKT_ABSOLUTE_IPV6)
5830 .is_ok());
5831
5832 daemon.shutdown().unwrap();
5833 }
5834
5835 #[test]
5836 fn test_response_source_ifaddr_match() {
5837 let ifaddr_a = IfAddr::V4(Ifv4Addr {
5841 ip: Ipv4Addr::new(192, 168, 1, 148),
5842 netmask: Ipv4Addr::new(255, 255, 255, 0),
5843 broadcast: None,
5844 prefixlen: 24,
5845 });
5846 let ifaddr_b = IfAddr::V4(Ifv4Addr {
5847 ip: Ipv4Addr::new(10, 238, 0, 51),
5848 netmask: Ipv4Addr::new(255, 255, 255, 0),
5849 broadcast: None,
5850 prefixlen: 24,
5851 });
5852
5853 let intf = MyIntf {
5854 name: "dummy0".to_string(),
5855 index: 1,
5856 addrs: HashSet::from([ifaddr_a.clone(), ifaddr_b.clone()]),
5857 max_packet_size_v4: MAX_PKT_DEFAULT,
5858 max_packet_size_v6: MAX_PKT_DEFAULT,
5859 };
5860
5861 let pick = |querier: IpAddr| -> Option<IfAddr> {
5862 intf.addrs
5863 .iter()
5864 .find(|a| valid_ip_on_intf(&querier, a))
5865 .cloned()
5866 };
5867
5868 assert_eq!(
5869 pick(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2))),
5870 Some(ifaddr_a)
5871 );
5872 assert_eq!(
5873 pick(IpAddr::V4(Ipv4Addr::new(10, 238, 0, 99))),
5874 Some(ifaddr_b)
5875 );
5876 assert_eq!(pick(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))), None);
5878 }
5879
5880 #[test]
5881 fn test_instance_name() {
5882 assert!(valid_instance_name("my-laser._printer._tcp.local."));
5883 assert!(valid_instance_name("my-laser.._printer._tcp.local."));
5884 assert!(!valid_instance_name("_printer._tcp.local."));
5885 }
5886
5887 #[test]
5888 fn test_legacy_unicast_response() {
5889 let intf_ip = match my_ip_interfaces(false)
5900 .into_iter()
5901 .find_map(|intf| match intf.ip() {
5902 IpAddr::V4(ip) => Some(ip),
5903 IpAddr::V6(_) => None,
5904 }) {
5905 Some(ip) => ip,
5906 None => {
5907 println!("No IPv4 interface available; skipping test.");
5908 return;
5909 }
5910 };
5911
5912 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
5914 let unique = SystemTime::now()
5915 .duration_since(SystemTime::UNIX_EPOCH)
5916 .unwrap()
5917 .as_micros();
5918 let hostname = format!("legacy-unicast-test-{unique}.local.");
5919 let service_info = ServiceInfo::new(
5920 "_legacy-uni._udp.local.",
5921 "test_instance",
5922 &hostname,
5923 &[IpAddr::V4(intf_ip)] as &[IpAddr],
5924 5353, None,
5926 )
5927 .expect("invalid service info");
5928 daemon.register(service_info).expect("register service");
5929
5930 let querier = UdpSocket::bind((intf_ip, 0)).expect("bind querier socket");
5934 querier
5935 .set_multicast_loop_v4(true)
5936 .expect("enable multicast loopback");
5937 querier
5938 .set_read_timeout(Some(Duration::from_millis(500)))
5939 .expect("set read timeout");
5940 assert_ne!(
5941 querier.local_addr().unwrap().port(),
5942 MDNS_PORT,
5943 "querier must use an ephemeral (non-5353) source port"
5944 );
5945
5946 const QUERY_ID: u16 = 0x4a17;
5951 let mut query = DnsOutgoing::new(FLAGS_QR_QUERY);
5952 query.set_id(QUERY_ID);
5953 query.set_multicast(false);
5954 query.add_question(&hostname, RRType::A);
5955 let query_packet = query
5956 .to_data_on_wire(MAX_PKT_DEFAULT, true)
5957 .pop()
5958 .expect("query serialized to one packet");
5959
5960 let if_id = InterfaceId {
5961 name: "test".to_string(),
5962 index: 0,
5963 };
5964
5965 let deadline = Instant::now() + Duration::from_secs(8);
5968 let mut response = None;
5969 'outer: while Instant::now() < deadline {
5970 querier
5971 .send_to(&query_packet, (GROUP_ADDR_V4, MDNS_PORT))
5972 .expect("send query");
5973
5974 let mut buf = [0u8; 1500];
5977 while let Ok((len, from)) = querier.recv_from(&mut buf) {
5978 let Ok(msg) = DnsIncoming::new(buf[..len].to_vec(), if_id.clone()) else {
5979 continue;
5980 };
5981 if msg.is_response()
5982 && msg
5983 .answers()
5984 .iter()
5985 .any(|a| a.get_name().eq_ignore_ascii_case(&hostname))
5986 {
5987 response = Some((msg, from));
5988 break 'outer;
5989 }
5990 }
5991 }
5992
5993 let (msg, from) = response.expect(
5994 "expected a unicast response to the legacy query; \
5995 a multicast-only reply would never reach this un-joined socket",
5996 );
5997
5998 assert_eq!(
6000 from.port(),
6001 MDNS_PORT,
6002 "response should originate from the mDNS port"
6003 );
6004
6005 assert_eq!(
6007 msg.id(),
6008 QUERY_ID,
6009 "legacy unicast response must echo the query id"
6010 );
6011
6012 assert!(
6014 msg.questions()
6015 .iter()
6016 .any(|q| q.entry_name().eq_ignore_ascii_case(&hostname)),
6017 "legacy unicast response must echo the question section"
6018 );
6019
6020 let answer = msg
6023 .answers()
6024 .iter()
6025 .find(|a| a.get_name().eq_ignore_ascii_case(&hostname))
6026 .expect("response contains an answer for our hostname");
6027 assert_eq!(
6028 answer.get_type(),
6029 RRType::A,
6030 "an A query should be answered with an A record"
6031 );
6032 assert!(
6033 !answer.get_cache_flush(),
6034 "legacy unicast responses must clear the cache-flush bit"
6035 );
6036
6037 assert!(
6038 answer.get_record().get_ttl() <= LEGACY_UNICAST_MAX_TTL,
6039 "legacy unicast response TTL {} exceeds the {}s cap",
6040 answer.get_record().get_ttl(),
6041 LEGACY_UNICAST_MAX_TTL
6042 );
6043
6044 daemon.shutdown().unwrap();
6045 }
6046
6047 #[test]
6048 fn test_shared_response_delay_bounds() {
6049 assert_eq!(SHARED_RESPONSE_DELAY_MIN_MILLIS, 10);
6054 assert_eq!(SHARED_RESPONSE_DELAY_MAX_MILLIS, 50);
6055 for _ in 0..10_000 {
6056 let d =
6057 fastrand::u64(SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS);
6058 assert!(
6059 (SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS).contains(&d),
6060 "delay {} ms is outside the configured {}-{} ms range",
6061 d,
6062 SHARED_RESPONSE_DELAY_MIN_MILLIS,
6063 SHARED_RESPONSE_DELAY_MAX_MILLIS
6064 );
6065 }
6066 }
6067
6068 #[test]
6069 fn test_initial_query_delayed() {
6070 use socket2::{Domain, Protocol, Socket, Type};
6077
6078 let (intf, intf_ip) = match my_ip_interfaces(false)
6079 .into_iter()
6080 .find_map(|intf| match intf.ip() {
6081 IpAddr::V4(ip) if !ip.is_loopback() => Some((intf, ip)),
6082 _ => None,
6083 }) {
6084 Some(pair) => pair,
6085 None => {
6086 println!("No IPv4 interface available; skipping test.");
6087 return;
6088 }
6089 };
6090 let interface_id = InterfaceId::from(&intf);
6091
6092 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
6096 sock.set_reuse_address(true).unwrap();
6097 #[cfg(unix)]
6098 sock.set_reuse_port(true).unwrap();
6099 sock.bind(&std::net::SocketAddr::from((Ipv4Addr::UNSPECIFIED, MDNS_PORT)).into())
6100 .unwrap();
6101 sock.join_multicast_v4(&GROUP_ADDR_V4, &intf_ip).unwrap();
6102 sock.set_read_timeout(Some(Duration::from_millis(200)))
6103 .unwrap();
6104 let sock: UdpSocket = sock.into();
6105
6106 let unique = SystemTime::now()
6108 .duration_since(SystemTime::UNIX_EPOCH)
6109 .unwrap()
6110 .as_micros()
6111 % 1_000_000_000;
6112 let service_type = format!("_qd{unique}._udp.local.");
6113
6114 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
6115
6116 let sent_at = Instant::now();
6117 let _browse = daemon.browse(&service_type).expect("browse");
6118
6119 let deadline = Instant::now() + Duration::from_secs(2);
6122 let mut buf = [0u8; 2048];
6123 let mut measured = None;
6124 while Instant::now() < deadline {
6125 let n = match sock.recv_from(&mut buf) {
6126 Ok((n, _)) => n,
6127 Err(_) => continue, };
6129 let Ok(msg) = DnsIncoming::new(buf[..n].to_vec(), interface_id.clone()) else {
6130 continue;
6131 };
6132 if msg.is_query()
6133 && msg
6134 .questions()
6135 .iter()
6136 .any(|q| q.entry_name() == service_type)
6137 {
6138 measured = Some(sent_at.elapsed());
6139 break;
6140 }
6141 }
6142
6143 daemon.shutdown().unwrap();
6144
6145 let elapsed = measured.expect("expected the daemon to send a PTR query for our browse");
6146 let tolerance = Duration::from_millis(2);
6147 assert!(
6148 elapsed + tolerance >= Duration::from_millis(INITIAL_QUERY_DELAY_MIN_MILLIS),
6149 "first browse query was sent after only {:?}; the first query of a series must be \
6150 delayed (10-50 ms window), not sent immediately",
6151 elapsed
6152 );
6153
6154 let scheduling_slack = Duration::from_millis(50);
6159 assert!(
6160 elapsed <= Duration::from_millis(INITIAL_QUERY_DELAY_MAX_MILLIS) + scheduling_slack,
6161 "first browse query was sent after {:?}, beyond the {}-{} ms jitter window (plus slack)",
6162 elapsed,
6163 INITIAL_QUERY_DELAY_MIN_MILLIS,
6164 INITIAL_QUERY_DELAY_MAX_MILLIS
6165 );
6166 }
6167
6168 #[test]
6169 fn test_shared_ptr_response_delayed() {
6170 use socket2::{Domain, Protocol, Socket, Type};
6177
6178 let intf_ip = match my_ip_interfaces(false)
6179 .into_iter()
6180 .find_map(|intf| match intf.ip() {
6181 IpAddr::V4(ip) if !ip.is_loopback() => Some(ip),
6182 _ => None,
6183 }) {
6184 Some(ip) => ip,
6185 None => {
6186 println!("No IPv4 interface available; skipping test.");
6187 return;
6188 }
6189 };
6190
6191 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
6192 let monitor = daemon.monitor().expect("monitor daemon events");
6193
6194 let unique = SystemTime::now()
6197 .duration_since(SystemTime::UNIX_EPOCH)
6198 .unwrap()
6199 .as_micros()
6200 % 1_000_000_000;
6201 let service_type = format!("_sd{unique}._udp.local.");
6202 let hostname = format!("sd{unique}.local.");
6203 let service_info = ServiceInfo::new(
6204 &service_type,
6205 "test_instance",
6206 &hostname,
6207 &[IpAddr::V4(intf_ip)] as &[IpAddr],
6208 5353,
6209 None,
6210 )
6211 .expect("invalid service info");
6212 daemon.register(service_info).expect("register service");
6213
6214 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
6218 sock.set_reuse_address(true).unwrap();
6219 #[cfg(unix)]
6220 sock.set_reuse_port(true).unwrap();
6221 sock.bind(&std::net::SocketAddr::from((Ipv4Addr::UNSPECIFIED, MDNS_PORT)).into())
6222 .unwrap();
6223 sock.set_multicast_if_v4(&intf_ip).unwrap();
6224 sock.set_multicast_loop_v4(true).unwrap();
6226 let sock: UdpSocket = sock.into();
6227
6228 let mut query = DnsOutgoing::new(FLAGS_QR_QUERY);
6230 query.add_question(&service_type, RRType::PTR);
6231 let query_packet = query
6232 .to_data_on_wire(MAX_PKT_DEFAULT, true)
6233 .pop()
6234 .expect("one packet");
6235
6236 std::thread::sleep(Duration::from_secs(3));
6240
6241 let deadline = Instant::now() + Duration::from_secs(8);
6245 let mut measured = None;
6246 while Instant::now() < deadline {
6247 while monitor.try_recv().is_ok() {}
6250
6251 let sent_at = Instant::now();
6252 sock.send_to(&query_packet, (GROUP_ADDR_V4, MDNS_PORT))
6253 .expect("send query");
6254
6255 let attempt_deadline = sent_at + Duration::from_millis(700);
6258 loop {
6259 let remaining = attempt_deadline.saturating_duration_since(Instant::now());
6260 if remaining.is_zero() {
6261 break;
6262 }
6263 match monitor.recv_timeout(remaining) {
6264 Ok(DaemonEvent::Respond(_)) => {
6265 measured = Some(sent_at.elapsed());
6266 break;
6267 }
6268 Ok(_) => continue, Err(_) => break, }
6271 }
6272 if measured.is_some() {
6273 break;
6274 }
6275 }
6276
6277 let elapsed =
6278 measured.expect("expected the daemon to respond to our PTR query within the deadline");
6279 assert!(
6280 elapsed >= Duration::from_millis(8),
6281 "PTR response was sent after only {:?}; a shared-record response must be \
6282 delayed (10-50 ms window), not sent immediately",
6283 elapsed
6284 );
6285 assert!(
6286 elapsed <= Duration::from_millis(600),
6287 "PTR response was sent after {:?}; expected within the 10-50 ms delay window",
6288 elapsed
6289 );
6290
6291 daemon.shutdown().unwrap();
6292 }
6293
6294 #[test]
6295 fn test_check_service_name_length() {
6296 let result = check_service_name_length("_tcp", 100);
6297 assert!(result.is_err());
6298 if let Err(e) = result {
6299 println!("{}", e);
6300 }
6301 }
6302
6303 #[test]
6304 fn test_check_hostname() {
6305 for hostname in &[
6307 "my_host.local.",
6308 &("A".repeat(255 - ".local.".len()) + ".local."),
6309 ] {
6310 let result = check_hostname(hostname);
6311 assert!(result.is_ok());
6312 }
6313
6314 for hostname in &[
6316 "my_host.local",
6317 ".local.",
6318 &("A".repeat(256 - ".local.".len()) + ".local."),
6319 ] {
6320 let result = check_hostname(hostname);
6321 assert!(result.is_err());
6322 if let Err(e) = result {
6323 println!("{}", e);
6324 }
6325 }
6326 }
6327
6328 #[test]
6329 fn test_check_domain_suffix() {
6330 assert!(check_domain_suffix("_missing_dot._tcp.local").is_err());
6331 assert!(check_domain_suffix("_missing_bar.tcp.local.").is_err());
6332 assert!(check_domain_suffix("_mis_spell._tpp.local.").is_err());
6333 assert!(check_domain_suffix("_mis_spell._upp.local.").is_err());
6334 assert!(check_domain_suffix("_has_dot._tcp.local.").is_ok());
6335 assert!(check_domain_suffix("_goodname._udp.local.").is_ok());
6336 }
6337
6338 #[test]
6339 fn test_service_with_temporarily_invalidated_ptr() {
6340 let d = ServiceDaemon::new().expect("Failed to create daemon");
6342
6343 let service = "_test_inval_ptr._udp.local.";
6344 let host_name = "my_host_tmp_invalidated_ptr.local.";
6345 let intfs: Vec<_> = my_ip_interfaces(false);
6346 let intf_ips: Vec<_> = intfs.iter().map(|intf| intf.ip()).collect();
6347 let port = 5201;
6348 let my_service =
6349 ServiceInfo::new(service, "my_instance", host_name, &intf_ips[..], port, None)
6350 .expect("invalid service info")
6351 .enable_addr_auto();
6352 let result = d.register(my_service.clone());
6353 assert!(result.is_ok());
6354
6355 let browse_chan = d.browse(service).unwrap();
6357 let timeout = Duration::from_secs(2);
6358 let mut resolved = false;
6359
6360 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6361 match event {
6362 ServiceEvent::ServiceResolved(info) => {
6363 resolved = true;
6364 println!("Resolved a service of {}", &info.fullname);
6365 break;
6366 }
6367 e => {
6368 println!("Received event {:?}", e);
6369 }
6370 }
6371 }
6372
6373 assert!(resolved);
6374
6375 println!("Stopping browse of {}", service);
6376 d.stop_browse(service).unwrap();
6379
6380 let mut stopped = false;
6385 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6386 match event {
6387 ServiceEvent::SearchStopped(_) => {
6388 stopped = true;
6389 println!("Stopped browsing service");
6390 break;
6391 }
6392 e => {
6396 println!("Received event {:?}", e);
6397 }
6398 }
6399 }
6400
6401 assert!(stopped);
6402
6403 let invalidate_ptr_packet = DnsPointer::new(
6405 my_service.get_type(),
6406 RRType::PTR,
6407 CLASS_IN,
6408 0,
6409 my_service.get_fullname().to_string(),
6410 );
6411
6412 let mut packet_buffer = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6413 packet_buffer.add_additional_answer(invalidate_ptr_packet);
6414
6415 for intf in intfs {
6416 let sock = _new_socket_bind(&intf, true).unwrap();
6417 send_dns_outgoing_impl(
6418 &packet_buffer,
6419 &intf.name,
6420 intf.index.unwrap_or(0),
6421 &intf.addr,
6422 &sock.pktinfo,
6423 SendConfig {
6424 port: MDNS_PORT,
6425 max_packet_size: MAX_PKT_DEFAULT,
6426 is_ipv4: intf.addr.ip().is_ipv4(),
6427 },
6428 None,
6429 )
6430 .unwrap();
6431 }
6432
6433 println!(
6434 "Sent PTR record invalidation. Starting second browse for {}",
6435 service
6436 );
6437
6438 let browse_chan = d.browse(service).unwrap();
6440
6441 resolved = false;
6442 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6443 match event {
6444 ServiceEvent::ServiceResolved(info) => {
6445 resolved = true;
6446 println!("Resolved a service of {}", &info.fullname);
6447 break;
6448 }
6449 e => {
6450 println!("Received event {:?}", e);
6451 }
6452 }
6453 }
6454
6455 assert!(resolved);
6456 d.shutdown().unwrap();
6457 }
6458
6459 #[test]
6460 fn test_expired_srv() {
6461 let service_type = "_expired-srv._udp.local.";
6463 let instance = "test_instance";
6464 let host_name = "expired_srv_host.local.";
6465 let mut my_service = ServiceInfo::new(service_type, instance, host_name, "", 5023, None)
6466 .unwrap()
6467 .enable_addr_auto();
6468 let new_ttl = 3; my_service._set_host_ttl(new_ttl);
6473
6474 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6476 let result = mdns_server.register(my_service);
6477 assert!(result.is_ok());
6478
6479 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6480 let browse_chan = mdns_client.browse(service_type).unwrap();
6481 let timeout = Duration::from_secs(2);
6482 let mut resolved = false;
6483
6484 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6485 if let ServiceEvent::ServiceResolved(info) = event {
6486 resolved = true;
6487 println!("Resolved a service of {}", &info.fullname);
6488 break;
6489 }
6490 }
6491
6492 assert!(resolved);
6493
6494 mdns_server.shutdown().unwrap();
6496
6497 let expire_timeout = Duration::from_secs(new_ttl as u64);
6499 while let Ok(event) = browse_chan.recv_timeout(expire_timeout) {
6500 if let ServiceEvent::ServiceRemoved(service_type, full_name) = event {
6501 println!("Service removed: {}: {}", &service_type, &full_name);
6502 break;
6503 }
6504 }
6505 }
6506
6507 #[test]
6508 fn test_hostname_resolution_address_removed() {
6509 let server = ServiceDaemon::new().expect("Failed to create server");
6511 let hostname = "addr_remove_host._tcp.local.";
6512 let service_ip_addr: ScopedIp = my_ip_interfaces(false)
6513 .iter()
6514 .find(|iface| iface.ip().is_ipv4())
6515 .map(|iface| iface.into())
6516 .unwrap();
6517
6518 let mut my_service = ServiceInfo::new(
6519 "_host_res_test._tcp.local.",
6520 "my_instance",
6521 hostname,
6522 service_ip_addr.to_ip_addr(),
6523 1234,
6524 None,
6525 )
6526 .expect("invalid service info");
6527
6528 let addr_ttl = 2;
6530 my_service._set_host_ttl(addr_ttl); server.register(my_service).unwrap();
6533
6534 let client = ServiceDaemon::new().expect("Failed to create client");
6536 let event_receiver = client.resolve_hostname(hostname, None).unwrap();
6537 let resolved = loop {
6538 match event_receiver.recv() {
6539 Ok(HostnameResolutionEvent::AddressesFound(found_hostname, addresses)) => {
6540 assert_eq!(found_hostname, hostname);
6541 assert!(addresses.contains(&service_ip_addr));
6542 println!("address found: {:?}", &addresses);
6543 break true;
6544 }
6545 Ok(HostnameResolutionEvent::SearchStopped(_)) => break false,
6546 Ok(_event) => {}
6547 Err(_) => break false,
6548 }
6549 };
6550
6551 assert!(resolved);
6552
6553 server.shutdown().unwrap();
6555
6556 let timeout = Duration::from_secs(addr_ttl as u64 + 1);
6558 let removed = loop {
6559 match event_receiver.recv_timeout(timeout) {
6560 Ok(HostnameResolutionEvent::AddressesRemoved(removed_host, addresses)) => {
6561 assert_eq!(removed_host, hostname);
6562 assert!(addresses.contains(&service_ip_addr));
6563
6564 println!(
6565 "address removed: hostname: {} addresses: {:?}",
6566 &hostname, &addresses
6567 );
6568 break true;
6569 }
6570 Ok(_event) => {}
6571 Err(_) => {
6572 break false;
6573 }
6574 }
6575 };
6576
6577 assert!(removed);
6578
6579 client.shutdown().unwrap();
6580 }
6581
6582 #[test]
6583 fn test_refresh_ptr() {
6584 let service_type = "_refresh-ptr._udp.local.";
6586 let instance = "test_instance";
6587 let host_name = "refresh_ptr_host.local.";
6588 let service_ip_addr = my_ip_interfaces(false)
6589 .iter()
6590 .find(|iface| iface.ip().is_ipv4())
6591 .map(|iface| iface.ip())
6592 .unwrap();
6593
6594 let mut my_service = ServiceInfo::new(
6595 service_type,
6596 instance,
6597 host_name,
6598 service_ip_addr,
6599 5023,
6600 None,
6601 )
6602 .unwrap();
6603
6604 let new_ttl = 3; my_service._set_other_ttl(new_ttl);
6606
6607 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6609 let result = mdns_server.register(my_service);
6610 assert!(result.is_ok());
6611
6612 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6613 let browse_chan = mdns_client.browse(service_type).unwrap();
6614 let timeout = Duration::from_millis(1500); let mut resolved = false;
6616
6617 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6619 if let ServiceEvent::ServiceResolved(info) = event {
6620 resolved = true;
6621 println!("Resolved a service of {}", &info.fullname);
6622 break;
6623 }
6624 }
6625
6626 assert!(resolved);
6627
6628 let timeout = Duration::from_millis(new_ttl as u64 * 1000 * 90 / 100);
6630 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6631 println!("event: {:?}", &event);
6632 }
6633
6634 let metrics_chan = mdns_client.get_metrics().unwrap();
6636 let metrics = metrics_chan.recv_timeout(timeout).unwrap();
6637 let ptr_refresh_counter = metrics["cache-refresh-ptr"];
6638 assert_eq!(ptr_refresh_counter, 1);
6639 let srvtxt_refresh_counter = metrics["cache-refresh-srv-txt"];
6640 assert_eq!(srvtxt_refresh_counter, 1);
6641
6642 mdns_server.shutdown().unwrap();
6644 mdns_client.shutdown().unwrap();
6645 }
6646
6647 #[test]
6648 fn test_name_change() {
6649 assert_eq!(name_change("foo.local."), "foo (2).local.");
6650 assert_eq!(name_change("foo (2).local."), "foo (3).local.");
6651 assert_eq!(name_change("foo (9).local."), "foo (10).local.");
6652 assert_eq!(name_change("foo"), "foo (2)");
6653 assert_eq!(name_change("foo (2)"), "foo (3)");
6654 assert_eq!(name_change(""), " (2)");
6655
6656 assert_eq!(name_change("foo (abc)"), "foo (abc) (2)"); assert_eq!(name_change("foo (2"), "foo (2 (2)"); assert_eq!(name_change("foo (2) extra"), "foo (2) extra (2)"); }
6661
6662 #[test]
6663 fn test_hostname_change() {
6664 assert_eq!(hostname_change("foo.local."), "foo-2.local.");
6665 assert_eq!(hostname_change("foo"), "foo-2");
6666 assert_eq!(hostname_change("foo-2.local."), "foo-3.local.");
6667 assert_eq!(hostname_change("foo-9"), "foo-10");
6668 assert_eq!(hostname_change("test-42.domain."), "test-43.domain.");
6669 }
6670
6671 #[test]
6672 fn test_add_answer_txt_ttl() {
6673 let service_type = "_test_add_answer._udp.local.";
6675 let instance = "test_instance";
6676 let host_name = "add_answer_host.local.";
6677 let service_intf = my_ip_interfaces(false)
6678 .into_iter()
6679 .find(|iface| iface.ip().is_ipv4())
6680 .unwrap();
6681 let service_ip_addr = service_intf.ip();
6682 let my_service = ServiceInfo::new(
6683 service_type,
6684 instance,
6685 host_name,
6686 service_ip_addr,
6687 5023,
6688 None,
6689 )
6690 .unwrap();
6691
6692 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6694
6695 let mut dummy_data = out.to_data_on_wire(MAX_PKT_DEFAULT, true);
6697 let interface_id = InterfaceId::from(&service_intf);
6698 let incoming = DnsIncoming::new(dummy_data.pop().unwrap(), interface_id).unwrap();
6699
6700 let if_addrs = vec![service_intf.ip()];
6702 add_answer_of_service(
6703 &mut out,
6704 &incoming,
6705 instance,
6706 &my_service,
6707 RRType::TXT,
6708 if_addrs,
6709 );
6710
6711 assert!(
6713 out.answers_count() > 0,
6714 "No answers added to the outgoing message"
6715 );
6716
6717 let answer = out._answers().first().unwrap();
6719 assert_eq!(answer.get_type(), RRType::TXT);
6720
6721 assert_eq!(answer.get_record().get_ttl(), my_service.get_other_ttl());
6723 }
6724
6725 #[test]
6726 fn test_interface_flip() {
6727 let ty_domain = "_intf-flip._udp.local.";
6729 let host_name = "intf_flip.local.";
6730 let now = SystemTime::now()
6731 .duration_since(SystemTime::UNIX_EPOCH)
6732 .unwrap();
6733 let instance_name = now.as_micros().to_string(); let port = 5200;
6735
6736 let (ip_addr1, intf_name) = my_ip_interfaces(false)
6738 .iter()
6739 .find(|iface| iface.ip().is_ipv4())
6740 .map(|iface| (iface.ip(), iface.name.clone()))
6741 .unwrap();
6742
6743 println!("Using interface {} with IP {}", intf_name, ip_addr1);
6744
6745 let service1 = ServiceInfo::new(ty_domain, &instance_name, host_name, ip_addr1, port, None)
6747 .expect("valid service info");
6748 let server1 = ServiceDaemon::new().expect("failed to start server");
6749 server1
6750 .register(service1)
6751 .expect("Failed to register service1");
6752
6753 std::thread::sleep(Duration::from_secs(2));
6755
6756 let client = ServiceDaemon::new().expect("failed to start client");
6758
6759 let receiver = client.browse(ty_domain).unwrap();
6760
6761 let timeout = Duration::from_secs(3);
6762 let mut got_data = false;
6763
6764 while let Ok(event) = receiver.recv_timeout(timeout) {
6765 if let ServiceEvent::ServiceResolved(_) = event {
6766 println!("Received ServiceResolved event");
6767 got_data = true;
6768 break;
6769 }
6770 }
6771
6772 assert!(got_data, "Should receive ServiceResolved event");
6773
6774 client.set_ip_check_interval(1).unwrap();
6776
6777 println!("Shutting down interface {}", &intf_name);
6779 client.test_down_interface(&intf_name).unwrap();
6780
6781 let mut got_removed = false;
6782
6783 while let Ok(event) = receiver.recv_timeout(timeout) {
6784 if let ServiceEvent::ServiceRemoved(ty_domain, instance) = event {
6785 got_removed = true;
6786 println!("removed: {ty_domain} : {instance}");
6787 break;
6788 }
6789 }
6790 assert!(got_removed, "Should receive ServiceRemoved event");
6791
6792 println!("Bringing up interface {}", &intf_name);
6793 client.test_up_interface(&intf_name).unwrap();
6794 let mut got_data = false;
6795 while let Ok(event) = receiver.recv_timeout(timeout) {
6796 if let ServiceEvent::ServiceResolved(resolved) = event {
6797 got_data = true;
6798 println!("Received ServiceResolved: {:?}", resolved);
6799 break;
6800 }
6801 }
6802 assert!(
6803 got_data,
6804 "Should receive ServiceResolved event after interface is back up"
6805 );
6806
6807 server1.shutdown().unwrap();
6808 client.shutdown().unwrap();
6809 }
6810
6811 #[test]
6812 fn test_cache_only() {
6813 let service_type = "_cache_only._udp.local.";
6815 let instance = "test_instance";
6816 let host_name = "cache_only_host.local.";
6817 let service_ip_addr = my_ip_interfaces(false)
6818 .iter()
6819 .find(|iface| iface.ip().is_ipv4())
6820 .map(|iface| iface.ip())
6821 .unwrap();
6822
6823 let mut my_service = ServiceInfo::new(
6824 service_type,
6825 instance,
6826 host_name,
6827 service_ip_addr,
6828 5023,
6829 None,
6830 )
6831 .unwrap();
6832
6833 let new_ttl = 3; my_service._set_other_ttl(new_ttl);
6835
6836 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6837
6838 let browse_chan = mdns_client.browse_cache(service_type).unwrap();
6841 std::thread::sleep(Duration::from_secs(2));
6842
6843 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6845 let result = mdns_server.register(my_service);
6846 assert!(result.is_ok());
6847
6848 let timeout = Duration::from_millis(1500); let mut resolved = false;
6850
6851 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6853 if let ServiceEvent::ServiceResolved(info) = event {
6854 resolved = true;
6855 println!("Resolved a service of {}", &info.get_fullname());
6856 break;
6857 }
6858 }
6859
6860 assert!(resolved);
6861
6862 mdns_server.shutdown().unwrap();
6864 mdns_client.shutdown().unwrap();
6865 }
6866
6867 #[test]
6868 fn test_cache_only_unsolicited() {
6869 let service_type = "_c_unsolicit._udp.local.";
6870 let instance = "test_instance";
6871 let host_name = "c_unsolicit_host.local.";
6872 let service_ip_addr = my_ip_interfaces(false)
6873 .iter()
6874 .find(|iface| iface.ip().is_ipv4())
6875 .map(|iface| iface.ip())
6876 .unwrap();
6877
6878 let my_service = ServiceInfo::new(
6879 service_type,
6880 instance,
6881 host_name,
6882 service_ip_addr,
6883 5023,
6884 None,
6885 )
6886 .unwrap();
6887
6888 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6890 let result = mdns_server.register(my_service);
6891 assert!(result.is_ok());
6892
6893 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6894 mdns_client.accept_unsolicited(true).unwrap();
6895
6896 std::thread::sleep(Duration::from_secs(2));
6899 let browse_chan = mdns_client.browse_cache(service_type).unwrap();
6900 let timeout = Duration::from_millis(1500); let mut resolved = false;
6902
6903 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6905 if let ServiceEvent::ServiceResolved(info) = event {
6906 resolved = true;
6907 println!("Resolved a service of {}", &info.get_fullname());
6908 break;
6909 }
6910 }
6911
6912 assert!(resolved);
6913
6914 mdns_server.shutdown().unwrap();
6916 mdns_client.shutdown().unwrap();
6917 }
6918
6919 #[test]
6920 fn test_custom_port_isolation() {
6921 let service_type = "_custom_port._udp.local.";
6926 let instance_custom = "custom_port_instance";
6927 let instance_default = "default_port_instance";
6928 let host_name = "custom_port_host.local.";
6929
6930 let service_ip_addr = my_ip_interfaces(false)
6931 .iter()
6932 .find(|iface| iface.ip().is_ipv4())
6933 .map(|iface| iface.ip())
6934 .expect("Test requires an IPv4 interface");
6935
6936 let service_custom = ServiceInfo::new(
6938 service_type,
6939 instance_custom,
6940 host_name,
6941 service_ip_addr,
6942 8080,
6943 None,
6944 )
6945 .unwrap();
6946
6947 let service_default = ServiceInfo::new(
6949 service_type,
6950 instance_default,
6951 host_name,
6952 service_ip_addr,
6953 8081,
6954 None,
6955 )
6956 .unwrap();
6957
6958 let custom_port = 5454u16;
6960 let server_custom =
6961 ServiceDaemon::new_with_port(custom_port).expect("Failed to create custom port server");
6962 let client_custom =
6963 ServiceDaemon::new_with_port(custom_port).expect("Failed to create custom port client");
6964
6965 let server_default = ServiceDaemon::new().expect("Failed to create default port server");
6967
6968 server_custom
6970 .register(service_custom.clone())
6971 .expect("Failed to register custom port service");
6972
6973 server_default
6975 .register(service_default.clone())
6976 .expect("Failed to register default port service");
6977
6978 let browse_custom = client_custom
6980 .browse(service_type)
6981 .expect("Failed to browse on custom port");
6982
6983 let timeout = Duration::from_secs(3);
6984 let mut found_custom = false;
6985 let mut found_default_on_custom = false;
6986
6987 while let Ok(event) = browse_custom.recv_timeout(timeout) {
6989 if let ServiceEvent::ServiceResolved(info) = event {
6990 println!(
6991 "Custom port client resolved: {} on port {}",
6992 info.get_fullname(),
6993 info.get_port()
6994 );
6995 if info.get_fullname().starts_with(instance_custom) {
6996 found_custom = true;
6997 assert_eq!(info.get_port(), 8080);
6998 }
6999 if info.get_fullname().starts_with(instance_default) {
7000 found_default_on_custom = true;
7001 }
7002 }
7003 }
7004
7005 assert!(
7006 found_custom,
7007 "Custom port client should find service on custom port"
7008 );
7009 assert!(
7010 !found_default_on_custom,
7011 "Custom port client should NOT find service on default port"
7012 );
7013
7014 let client_default = ServiceDaemon::new().expect("Failed to create default port client");
7017 let browse_default = client_default
7018 .browse(service_type)
7019 .expect("Failed to browse on default port");
7020
7021 let mut found_default = false;
7022 let mut found_custom_on_default = false;
7023
7024 while let Ok(event) = browse_default.recv_timeout(timeout) {
7025 if let ServiceEvent::ServiceResolved(info) = event {
7026 println!(
7027 "Default port client resolved: {} on port {}",
7028 info.get_fullname(),
7029 info.get_port()
7030 );
7031 if info.get_fullname().starts_with(instance_default) {
7032 found_default = true;
7033 assert_eq!(info.get_port(), 8081);
7034 }
7035 if info.get_fullname().starts_with(instance_custom) {
7036 found_custom_on_default = true;
7037 }
7038 }
7039 }
7040
7041 assert!(
7042 found_default,
7043 "Default port client should find service on default port"
7044 );
7045 assert!(
7046 !found_custom_on_default,
7047 "Default port client should NOT find service on custom port"
7048 );
7049
7050 server_custom.shutdown().unwrap();
7052 client_custom.shutdown().unwrap();
7053 server_default.shutdown().unwrap();
7054 client_default.shutdown().unwrap();
7055 }
7056
7057 #[test]
7062 fn test_unresolved_instance_not_stranded() {
7063 use socket2::{Domain, Protocol, Socket, Type};
7064 use std::net::SocketAddrV4;
7065
7066 let intf_ip = match my_ip_interfaces(false)
7068 .into_iter()
7069 .find_map(|intf| match intf.ip() {
7070 IpAddr::V4(ip) if !ip.is_loopback() => Some(ip),
7071 _ => None,
7072 }) {
7073 Some(ip) => ip,
7074 None => {
7075 println!("No non-loopback IPv4 interface available; skipping test.");
7076 return;
7077 }
7078 };
7079
7080 let unique = SystemTime::now()
7081 .duration_since(SystemTime::UNIX_EPOCH)
7082 .unwrap()
7083 .as_micros();
7084 let ty_domain = format!("_strandtest{unique}._udp.local.");
7085 let instance = format!("inst.{ty_domain}");
7086 let host = format!("strandhost{unique}.local.");
7089 let port = 1234u16;
7090 let ttl = 4500u32;
7091
7092 let if_id = InterfaceId {
7093 name: "test".to_string(),
7094 index: 0,
7095 };
7096
7097 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))
7101 .expect("create responder socket");
7102 sock.set_reuse_address(true).expect("set reuse_address");
7103 #[cfg(unix)]
7104 let _ = sock.set_reuse_port(true);
7105 sock.bind(&SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, MDNS_PORT).into())
7106 .expect("bind responder socket");
7107 sock.join_multicast_v4(&GROUP_ADDR_V4, &intf_ip)
7108 .expect("join multicast group");
7109 sock.set_multicast_if_v4(&intf_ip)
7110 .expect("set multicast_if");
7111 sock.set_multicast_loop_v4(true).expect("enable loopback");
7112 sock.set_read_timeout(Some(Duration::from_millis(100)))
7113 .expect("set read timeout");
7114 let responder: UdpSocket = sock.into();
7115
7116 let announce_packets = || {
7118 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
7119 out.add_answer_record(DnsPointer::new(
7120 &ty_domain,
7121 RRType::PTR,
7122 CLASS_IN,
7123 ttl,
7124 instance.clone(),
7125 ));
7126 out.add_answer_record(DnsSrv::new(
7127 &instance,
7128 CLASS_IN,
7129 ttl,
7130 0,
7131 0,
7132 port,
7133 host.clone(),
7134 ));
7135 out.to_data_on_wire(MAX_PKT_DEFAULT, true)
7136 };
7137
7138 let addr_packets = || {
7140 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
7141 out.add_answer_record(DnsAddress::new(
7142 &host,
7143 RRType::A,
7144 CLASS_IN,
7145 ttl,
7146 IpAddr::V4(intf_ip),
7147 if_id.clone(),
7148 ));
7149 out.to_data_on_wire(MAX_PKT_DEFAULT, true)
7150 };
7151
7152 let send_all = |packets: Vec<Vec<u8>>| {
7153 for packet in packets {
7154 let _ = responder.send_to(&packet, (GROUP_ADDR_V4, MDNS_PORT));
7155 }
7156 };
7157
7158 let daemon = ServiceDaemon::new().expect("create daemon");
7160 let browse_rx = daemon.browse(&ty_domain).expect("start browse");
7161 send_all(announce_packets());
7162
7163 let answer_after = RESOLVE_MAX_TRY as i32;
7169 let mut addr_query_count = 0;
7170 let mut resolved = false;
7171 let mut buf = [0u8; 2048];
7172 let deadline = Instant::now() + Duration::from_secs(20);
7173
7174 while Instant::now() < deadline {
7175 while let Ok((len, from)) = responder.recv_from(&mut buf) {
7177 if from.ip() != IpAddr::V4(intf_ip) {
7182 continue;
7183 }
7184 let Ok(msg) = DnsIncoming::new(buf[..len].to_vec(), if_id.clone()) else {
7185 continue;
7186 };
7187 if msg.is_response() {
7188 continue;
7189 }
7190
7191 let mut saw_addr_query = false;
7192 let mut saw_service_query = false;
7193 for q in msg.questions() {
7194 let qname = q.entry_name();
7195 if qname.eq_ignore_ascii_case(&host)
7196 && matches!(q.entry_type(), RRType::A | RRType::AAAA)
7197 {
7198 saw_addr_query = true;
7199 } else if qname.eq_ignore_ascii_case(&ty_domain)
7200 || qname.eq_ignore_ascii_case(&instance)
7201 {
7202 saw_service_query = true;
7203 }
7204 }
7205
7206 if saw_service_query {
7208 send_all(announce_packets());
7209 }
7210
7211 if saw_addr_query {
7215 addr_query_count += 1;
7216 if addr_query_count > answer_after {
7217 send_all(addr_packets());
7218 }
7219 }
7220 }
7221
7222 while let Ok(event) = browse_rx.try_recv() {
7224 if let ServiceEvent::ServiceResolved(info) = event {
7225 if info.get_fullname().eq_ignore_ascii_case(&instance) {
7226 resolved = true;
7227 }
7228 }
7229 }
7230
7231 if resolved {
7232 break;
7233 }
7234 }
7235
7236 daemon.shutdown().unwrap();
7237
7238 assert!(
7239 addr_query_count > answer_after,
7240 "daemon stopped querying for the address after {} tries; \
7241 an unresolved instance must keep being queried while the browse is active",
7242 addr_query_count
7243 );
7244 assert!(
7245 resolved,
7246 "instance was found but never resolved even though its address was \
7247 eventually answered"
7248 );
7249 }
7250 fn negative_answer_test_daemon() -> (super::Zeroconf, u32) {
7251 let signal = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
7252 let signal_addr = signal.local_addr().unwrap();
7253 signal.set_nonblocking(true).unwrap();
7254 let port = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))
7255 .unwrap()
7256 .local_addr()
7257 .unwrap()
7258 .port();
7259 let (sender, _receiver) = flume::bounded(100);
7260 let mut daemon = super::Zeroconf::new(
7261 mio::net::UdpSocket::from_std(signal),
7262 mio::Poll::new().unwrap(),
7263 port,
7264 sender,
7265 signal_addr,
7266 );
7267 let index = my_ip_interfaces(true)
7268 .iter()
7269 .find(|intf| intf.ip() == IpAddr::V4(Ipv4Addr::LOCALHOST))
7270 .unwrap()
7271 .index
7272 .unwrap();
7273 daemon.my_intfs.retain(|key, _| *key == index);
7275 daemon.dns_registry_map.retain(|key, _| *key == index);
7276 (daemon, index)
7277 }
7278
7279 fn register_negative_answer_test_service(
7280 daemon: &mut super::Zeroconf,
7281 index: u32,
7282 instance: &str,
7283 address: IpAddr,
7284 ) -> String {
7285 let service = ServiceInfo::new(
7286 "_negative-test._tcp.local.",
7287 instance,
7288 "negative.local.",
7289 address,
7290 8080,
7291 None,
7292 )
7293 .unwrap();
7294 let fullname = service.get_fullname().to_lowercase();
7295 daemon.register_service(service);
7296 for probe in daemon
7298 .dns_registry_map
7299 .get_mut(&index)
7300 .unwrap()
7301 .probing
7302 .values_mut()
7303 {
7304 probe.start_time = Instant::now() - Duration::from_millis(1000);
7305 probe.next_send = probe.start_time;
7306 }
7307 daemon.probing_handler();
7308 assert_eq!(
7309 daemon.my_services[&fullname].get_status(index),
7310 crate::service_info::ServiceStatus::Announced
7311 );
7312 fullname
7313 }
7314
7315 fn query_negative_answer_test_daemon(
7316 daemon: &mut super::Zeroconf,
7317 index: u32,
7318 name: &str,
7319 types: &[RRType],
7320 ) -> Option<DnsIncoming> {
7321 let querier = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
7322 querier
7323 .set_read_timeout(Some(Duration::from_millis(100)))
7324 .unwrap();
7325 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
7326 for ty in types {
7327 out.add_question(name, *ty);
7328 }
7329 let interface = InterfaceId {
7330 name: "loopback-test".to_string(),
7331 index,
7332 };
7333 let packets = out.to_data_on_wire(MAX_PKT_DEFAULT, true);
7334 let incoming = DnsIncoming::new(packets[0].clone(), interface.clone()).unwrap();
7335 daemon.handle_query(incoming, index, querier.local_addr().unwrap());
7336 let mut data = [0; 4096];
7337 match querier.recv_from(&mut data) {
7338 Ok((length, _)) => Some(DnsIncoming::new(data[..length].to_vec(), interface).unwrap()),
7339 Err(error)
7340 if matches!(
7341 error.kind(),
7342 std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut
7343 ) =>
7344 {
7345 None
7346 }
7347 Err(error) => panic!("receiving test response: {}", error),
7348 }
7349 }
7350
7351 #[test]
7352 fn test_negative_hostname_answers() {
7353 use super::DnsNSec;
7354 use crate::dns_parser::DnsRecordExt;
7355
7356 for (address, present, absent) in [
7357 (IpAddr::V4(Ipv4Addr::LOCALHOST), RRType::A, RRType::AAAA),
7358 (IpAddr::V6(Ipv6Addr::LOCALHOST), RRType::AAAA, RRType::A),
7359 ] {
7360 let (mut daemon, index) = negative_answer_test_daemon();
7361 let fullname =
7362 register_negative_answer_test_service(&mut daemon, index, "single", address);
7363 for ty in [absent, RRType::SVCB, RRType::HTTPS] {
7364 let reply =
7365 query_negative_answer_test_daemon(&mut daemon, index, "NEGATIVE.local.", &[ty])
7366 .unwrap();
7367 assert_eq!(reply.answers().len(), 1);
7368 let nsec = reply.answers()[0].any().downcast_ref::<DnsNSec>().unwrap();
7369 assert_eq!(nsec._types(), vec![present as u16]);
7370 assert_eq!(nsec.get_name(), "negative.local.");
7371 assert!(nsec.get_record().get_ttl() <= LEGACY_UNICAST_MAX_TTL);
7372 }
7373 for ty in [present, RRType::ANY] {
7374 let reply =
7375 query_negative_answer_test_daemon(&mut daemon, index, "negative.local.", &[ty])
7376 .unwrap();
7377 assert!(reply
7378 .answers()
7379 .iter()
7380 .any(|record| record.get_type() == present));
7381 assert!(reply
7382 .answers()
7383 .iter()
7384 .all(|record| record.get_type() != RRType::NSEC));
7385 }
7386 let mixed = query_negative_answer_test_daemon(
7387 &mut daemon,
7388 index,
7389 "negative.local.",
7390 &[RRType::HTTPS, RRType::AAAA, RRType::A],
7391 )
7392 .unwrap();
7393 assert!(mixed
7394 .answers()
7395 .iter()
7396 .any(|record| record.get_type() == present));
7397 assert!(mixed
7398 .answers()
7399 .iter()
7400 .any(|record| record.get_type() == RRType::NSEC));
7401 assert!(query_negative_answer_test_daemon(
7402 &mut daemon,
7403 index,
7404 "unowned.local.",
7405 &[absent]
7406 )
7407 .is_none());
7408 daemon
7409 .my_services
7410 .get_mut(&fullname)
7411 .unwrap()
7412 .set_status(index, crate::service_info::ServiceStatus::Probing);
7413 assert!(query_negative_answer_test_daemon(
7414 &mut daemon,
7415 index,
7416 "negative.local.",
7417 &[absent]
7418 )
7419 .is_none());
7420 }
7421 }
7422
7423 #[test]
7424 fn test_negative_hostname_answers_combine_registrations_on_one_interface() {
7425 let (mut daemon, index) = negative_answer_test_daemon();
7426 register_negative_answer_test_service(
7427 &mut daemon,
7428 index,
7429 "ipv4",
7430 IpAddr::V4(Ipv4Addr::LOCALHOST),
7431 );
7432 let ipv6 = register_negative_answer_test_service(
7433 &mut daemon,
7434 index,
7435 "ipv6",
7436 IpAddr::V6(Ipv6Addr::LOCALHOST),
7437 );
7438 for ty in [RRType::A, RRType::AAAA] {
7439 let reply =
7440 query_negative_answer_test_daemon(&mut daemon, index, "negative.local.", &[ty])
7441 .unwrap();
7442 assert!(reply.answers().iter().any(|record| record.get_type() == ty));
7443 assert!(reply
7444 .answers()
7445 .iter()
7446 .all(|record| record.get_type() != RRType::NSEC));
7447 }
7448 let reply = query_negative_answer_test_daemon(
7449 &mut daemon,
7450 index,
7451 "negative.local.",
7452 &[RRType::HTTPS],
7453 )
7454 .unwrap();
7455 assert_eq!(reply.answers().len(), 1);
7456 assert_eq!(
7457 reply.answers()[0]
7458 .any()
7459 .downcast_ref::<super::DnsNSec>()
7460 .unwrap()
7461 ._types(),
7462 [1, 28]
7463 );
7464 daemon
7466 .my_services
7467 .get_mut(&ipv6)
7468 .unwrap()
7469 .remove_ipaddr(&IpAddr::V6(Ipv6Addr::LOCALHOST));
7470 daemon
7471 .my_services
7472 .get_mut(&ipv6)
7473 .unwrap()
7474 .insert_ipaddr(&test_interface(
7475 "other",
7476 index + 1,
7477 test_ifaddr_v6("2001:db8::1".parse().unwrap()),
7478 ));
7479 let reply = query_negative_answer_test_daemon(
7480 &mut daemon,
7481 index,
7482 "negative.local.",
7483 &[RRType::AAAA],
7484 )
7485 .unwrap();
7486 assert_eq!(
7487 reply.answers()[0]
7488 .any()
7489 .downcast_ref::<super::DnsNSec>()
7490 .unwrap()
7491 ._types(),
7492 [1]
7493 );
7494 }
7495}