1#[cfg(feature = "logging")]
32use crate::log::{debug, error, trace};
33use crate::{
34 current_time_millis,
35 dns_cache::{DnsCache, IpType},
36 dns_parser::{
37 ip_address_rr_type, max_pkt_absolute, DnsAddress, DnsEntryExt, DnsIncoming, DnsNSec,
38 DnsOutgoing, DnsPointer, DnsQuestion, DnsRecordBox, DnsRecordExt, DnsSrv, DnsTxt,
39 InterfaceId, RRType, ScopedIp, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_AA, FLAGS_QR_QUERY,
40 FLAGS_QR_RESPONSE, MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT,
41 },
42 error::{e_fmt, Error, Result},
43 service_info::{
44 valid_ip_on_intf, DnsRegistry, MyIntf, Probe, ServiceInfo, ServiceStatus,
45 MULTICAST_RATE_LIMIT_MILLIS,
46 },
47 Receiver, ResolvedService, TxtProperties,
48};
49use flume::{bounded, Sender, TrySendError};
50use if_addrs::{IfAddr, Interface};
51use mio::{event::Source, net::UdpSocket as MioUdpSocket, Interest, Poll, Registry, Token};
52use socket2::Domain;
53use socket_pktinfo::PktInfoUdpSocket;
54use std::{
55 cmp::{self, Reverse},
56 collections::{hash_map::Entry, BinaryHeap, HashMap, HashSet},
57 fmt, io,
58 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, UdpSocket},
59 str, thread,
60 time::Duration,
61 vec,
62};
63
64pub const SERVICE_NAME_LEN_MAX_DEFAULT: u8 = 15;
68
69pub const IP_CHECK_INTERVAL_IN_SECS_DEFAULT: u32 = 5;
71
72pub const VERIFY_TIMEOUT_DEFAULT: Duration = Duration::from_secs(10);
75
76pub(crate) const MIN_MAX_PACKET_SIZE: usize = 512;
78
79pub const MDNS_PORT: u16 = 5353;
81
82const GROUP_ADDR_V4: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251);
83const GROUP_ADDR_V6: Ipv6Addr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0xfb);
84const LOOPBACK_V4: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
85
86const RESOLVE_RETRY_BASE_MILLIS: u64 = 200;
90
91const RESOLVE_MAX_TRY: u16 = 4;
94
95const ANNOUNCE_SECOND_DELAY_MILLIS: u64 = MULTICAST_RATE_LIMIT_MILLIS + 100;
103
104const ANNOUNCE_SECOND_JITTER_MILLIS: u64 = 50;
107
108#[allow(clippy::assertions_on_constants)]
112const _: () = assert!(ANNOUNCE_SECOND_DELAY_MILLIS > MULTICAST_RATE_LIMIT_MILLIS);
113
114const SHARED_RESPONSE_DELAY_MIN_MILLIS: u64 = 10;
122
123const SHARED_RESPONSE_DELAY_MAX_MILLIS: u64 = 50;
125
126const INITIAL_QUERY_DELAY_MIN_MILLIS: u64 = 10;
134const INITIAL_QUERY_DELAY_MAX_MILLIS: u64 = 50;
135
136#[derive(Debug)]
138pub enum UnregisterStatus {
139 OK,
141 NotFound,
143}
144
145#[derive(Debug, PartialEq, Clone, Eq)]
147#[non_exhaustive]
148pub enum DaemonStatus {
149 Running,
151
152 Shutdown,
154}
155
156#[derive(Hash, Eq, PartialEq)]
159enum Counter {
160 Register,
161 RegisterResend,
162 Unregister,
163 UnregisterResend,
164 Browse,
165 ResolveHostname,
166 Respond,
167 CacheRefreshPTR,
168 CacheRefreshSrvTxt,
169 CacheRefreshAddr,
170 KnownAnswerSuppression,
171 CachedPTR,
172 CachedSRV,
173 CachedAddr,
174 CachedTxt,
175 CachedNSec,
176 CachedSubtype,
177 DnsRegistryProbe,
178 DnsRegistryActive,
179 DnsRegistryTimer,
180 DnsRegistryNameChange,
181 Timer,
182}
183
184impl fmt::Display for Counter {
185 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 match self {
187 Self::Register => write!(f, "register"),
188 Self::RegisterResend => write!(f, "register-resend"),
189 Self::Unregister => write!(f, "unregister"),
190 Self::UnregisterResend => write!(f, "unregister-resend"),
191 Self::Browse => write!(f, "browse"),
192 Self::ResolveHostname => write!(f, "resolve-hostname"),
193 Self::Respond => write!(f, "respond"),
194 Self::CacheRefreshPTR => write!(f, "cache-refresh-ptr"),
195 Self::CacheRefreshSrvTxt => write!(f, "cache-refresh-srv-txt"),
196 Self::CacheRefreshAddr => write!(f, "cache-refresh-addr"),
197 Self::KnownAnswerSuppression => write!(f, "known-answer-suppression"),
198 Self::CachedPTR => write!(f, "cached-ptr"),
199 Self::CachedSRV => write!(f, "cached-srv"),
200 Self::CachedAddr => write!(f, "cached-addr"),
201 Self::CachedTxt => write!(f, "cached-txt"),
202 Self::CachedNSec => write!(f, "cached-nsec"),
203 Self::CachedSubtype => write!(f, "cached-subtype"),
204 Self::DnsRegistryProbe => write!(f, "dns-registry-probe"),
205 Self::DnsRegistryActive => write!(f, "dns-registry-active"),
206 Self::DnsRegistryTimer => write!(f, "dns-registry-timer"),
207 Self::DnsRegistryNameChange => write!(f, "dns-registry-name-change"),
208 Self::Timer => write!(f, "timer"),
209 }
210 }
211}
212
213#[derive(Debug)]
214enum InternalError {
215 IntfAddrInvalid(Interface),
216}
217
218impl fmt::Display for InternalError {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 match self {
221 InternalError::IntfAddrInvalid(iface) => write!(f, "interface addr invalid: {iface:?}"),
222 }
223 }
224}
225
226type MyResult<T> = core::result::Result<T, InternalError>;
227
228struct MyUdpSocket {
233 pktinfo: PktInfoUdpSocket,
236
237 mio: MioUdpSocket,
240}
241
242impl MyUdpSocket {
243 pub fn new(pktinfo: PktInfoUdpSocket) -> io::Result<Self> {
244 let std_sock = pktinfo.try_clone_std()?;
245 let mio = MioUdpSocket::from_std(std_sock);
246
247 Ok(Self { pktinfo, mio })
248 }
249}
250
251impl Source for MyUdpSocket {
253 fn register(
254 &mut self,
255 registry: &Registry,
256 token: Token,
257 interests: Interest,
258 ) -> io::Result<()> {
259 self.mio.register(registry, token, interests)
260 }
261
262 fn reregister(
263 &mut self,
264 registry: &Registry,
265 token: Token,
266 interests: Interest,
267 ) -> io::Result<()> {
268 self.mio.reregister(registry, token, interests)
269 }
270
271 fn deregister(&mut self, registry: &Registry) -> std::io::Result<()> {
272 self.mio.deregister(registry)
273 }
274}
275
276pub type Metrics = HashMap<String, i64>;
279
280const IPV4_SOCK_EVENT_KEY: usize = 4; const IPV6_SOCK_EVENT_KEY: usize = 6; const SIGNAL_SOCK_EVENT_KEY: usize = usize::MAX - 1; #[derive(Clone)]
288pub struct ServiceDaemon {
289 sender: Sender<Command>,
291
292 signal_addr: SocketAddr,
298}
299
300impl ServiceDaemon {
301 pub fn new() -> Result<Self> {
317 Self::new_with_port(MDNS_PORT)
318 }
319
320 pub fn new_with_port(port: u16) -> Result<Self> {
352 let signal_addr = SocketAddrV4::new(LOOPBACK_V4, 0);
355
356 let signal_sock = UdpSocket::bind(signal_addr)
357 .map_err(|e| e_fmt!("failed to create signal_sock for daemon: {}", e))?;
358
359 let signal_addr = signal_sock
361 .local_addr()
362 .map_err(|e| e_fmt!("failed to get signal sock addr: {}", e))?;
363
364 signal_sock
366 .set_nonblocking(true)
367 .map_err(|e| e_fmt!("failed to set nonblocking for signal socket: {}", e))?;
368
369 let poller = Poll::new().map_err(|e| e_fmt!("failed to create mio Poll: {e}"))?;
370
371 let (sender, receiver) = bounded(100);
372
373 let mio_sock = MioUdpSocket::from_std(signal_sock);
375 let cmd_sender = sender.clone();
376 thread::Builder::new()
377 .name("mDNS_daemon".to_string())
378 .spawn(move || {
379 Self::daemon_thread(mio_sock, poller, receiver, port, cmd_sender, signal_addr)
380 })
381 .map_err(|e| e_fmt!("thread builder failed to spawn: {}", e))?;
382
383 Ok(Self {
384 sender,
385 signal_addr,
386 })
387 }
388
389 fn send_cmd(&self, cmd: Command) -> Result<()> {
392 let cmd_name = cmd.to_string();
393
394 self.sender.try_send(cmd).map_err(|e| match e {
396 TrySendError::Full(_) => Error::Again,
397 TrySendError::Disconnected(_) => Error::DaemonShutdown,
398 })?;
399
400 let addr = SocketAddrV4::new(LOOPBACK_V4, 0);
402 let socket = UdpSocket::bind(addr)
403 .map_err(|e| e_fmt!("Failed to create socket to send signal: {}", e))?;
404 socket
405 .send_to(cmd_name.as_bytes(), self.signal_addr)
406 .map_err(|e| {
407 e_fmt!(
408 "signal socket send_to {} ({}) failed: {}",
409 self.signal_addr,
410 cmd_name,
411 e
412 )
413 })?;
414
415 Ok(())
416 }
417
418 pub fn browse(&self, service_type: &str) -> Result<Receiver<ServiceEvent>> {
438 check_domain_suffix(service_type)?;
439
440 let (resp_s, resp_r) = bounded(10);
441 self.send_cmd(Command::Browse(service_type.to_string(), 1, false, resp_s))?;
442 Ok(resp_r)
443 }
444
445 pub fn browse_cache(&self, service_type: &str) -> Result<Receiver<ServiceEvent>> {
458 check_domain_suffix(service_type)?;
459
460 let (resp_s, resp_r) = bounded(10);
461 self.send_cmd(Command::Browse(service_type.to_string(), 1, true, resp_s))?;
462 Ok(resp_r)
463 }
464
465 pub fn stop_browse(&self, ty_domain: &str) -> Result<()> {
473 self.send_cmd(Command::StopBrowse(ty_domain.to_string()))
474 }
475
476 pub fn resolve_hostname(
496 &self,
497 hostname: &str,
498 timeout: Option<u64>,
499 ) -> Result<Receiver<HostnameResolutionEvent>> {
500 check_hostname(hostname)?;
501 let (resp_s, resp_r) = bounded(10);
502 self.send_cmd(Command::ResolveHostname(
503 hostname.to_string(),
504 1,
505 resp_s,
506 timeout,
507 ))?;
508 Ok(resp_r)
509 }
510
511 pub fn stop_resolve_hostname(&self, hostname: &str) -> Result<()> {
517 self.send_cmd(Command::StopResolveHostname(hostname.to_string()))
518 }
519
520 pub fn register(&self, service_info: ServiceInfo) -> Result<()> {
540 check_service_name(service_info.get_fullname())?;
541 check_hostname(service_info.get_hostname())?;
542
543 self.send_cmd(Command::Register(service_info.into()))
544 }
545
546 pub fn unregister(&self, fullname: &str) -> Result<Receiver<UnregisterStatus>> {
557 let (resp_s, resp_r) = bounded(1);
558 self.send_cmd(Command::Unregister(fullname.to_lowercase(), resp_s))?;
559 Ok(resp_r)
560 }
561
562 pub fn monitor(&self) -> Result<Receiver<DaemonEvent>> {
572 let (resp_s, resp_r) = bounded(100);
573 self.send_cmd(Command::Monitor(resp_s))?;
574 Ok(resp_r)
575 }
576
577 pub fn shutdown(&self) -> Result<Receiver<DaemonStatus>> {
585 let (resp_s, resp_r) = bounded(1);
586 self.send_cmd(Command::Exit(resp_s))?;
587 Ok(resp_r)
588 }
589
590 pub fn status(&self) -> Result<Receiver<DaemonStatus>> {
598 let (resp_s, resp_r) = bounded(1);
599
600 if self.sender.is_disconnected() {
601 resp_s
602 .send(DaemonStatus::Shutdown)
603 .map_err(|e| e_fmt!("failed to send daemon status to the client: {}", e))?;
604 } else {
605 self.send_cmd(Command::GetStatus(resp_s))?;
606 }
607
608 Ok(resp_r)
609 }
610
611 pub fn get_metrics(&self) -> Result<Receiver<Metrics>> {
622 let (resp_s, resp_r) = bounded(1);
623 self.send_cmd(Command::GetMetrics(resp_s))?;
624 Ok(resp_r)
625 }
626
627 pub fn set_service_name_len_max(&self, len_max: u8) -> Result<()> {
642 const SERVICE_NAME_LEN_MAX_LIMIT: u8 = 30; if len_max > SERVICE_NAME_LEN_MAX_LIMIT {
645 return Err(Error::Msg(format!(
646 "service name length max {len_max} is too large"
647 )));
648 }
649
650 self.send_cmd(Command::SetOption(DaemonOption::ServiceNameLenMax(len_max)))
651 }
652
653 pub fn set_max_packet_size(&self, if_kind: impl IntoIfKindVec, size: usize) -> Result<()> {
668 if size < MIN_MAX_PACKET_SIZE {
669 return Err(Error::Msg(format!(
670 "max packet size {size} is too small, must be at least {MIN_MAX_PACKET_SIZE}"
671 )));
672 }
673
674 if size > MAX_PKT_ABSOLUTE_IPV6 {
675 return Err(Error::Msg(format!(
676 "max packet size {size} is too big, must be at most {MAX_PKT_ABSOLUTE_IPV6}"
677 )));
678 }
679
680 let if_kind_vec = if_kind.into_vec();
681 self.send_cmd(Command::SetOption(DaemonOption::MaxPacketSize(
682 if_kind_vec.kinds,
683 size,
684 )))
685 }
686
687 pub fn set_ip_check_interval(&self, interval_in_secs: u32) -> Result<()> {
693 let interval_in_millis = interval_in_secs as u64 * 1000;
694 self.send_cmd(Command::SetOption(DaemonOption::IpCheckInterval(
695 interval_in_millis,
696 )))
697 }
698
699 pub fn get_ip_check_interval(&self) -> Result<u32> {
701 let (resp_s, resp_r) = bounded(1);
702 self.send_cmd(Command::GetOption(resp_s))?;
703
704 let option = resp_r
705 .recv_timeout(Duration::from_secs(10))
706 .map_err(|e| e_fmt!("failed to receive ip check interval: {}", e))?;
707 let ip_check_interval_in_secs = option.ip_check_interval / 1000;
708 Ok(ip_check_interval_in_secs as u32)
709 }
710
711 pub fn enable_interface(&self, if_kind: impl IntoIfKindVec) -> Result<()> {
718 let if_kind_vec = if_kind.into_vec();
719 self.send_cmd(Command::SetOption(DaemonOption::EnableInterface(
720 if_kind_vec.kinds,
721 )))
722 }
723
724 pub fn disable_interface(&self, if_kind: impl IntoIfKindVec) -> Result<()> {
731 let if_kind_vec = if_kind.into_vec();
732 self.send_cmd(Command::SetOption(DaemonOption::DisableInterface(
733 if_kind_vec.kinds,
734 )))
735 }
736
737 pub fn accept_unsolicited(&self, accept: bool) -> Result<()> {
748 self.send_cmd(Command::SetOption(DaemonOption::AcceptUnsolicited(accept)))
749 }
750
751 pub fn include_apple_p2p(&self, include: bool) -> Result<()> {
754 self.send_cmd(Command::SetOption(DaemonOption::IncludeAppleP2P(include)))
755 }
756
757 #[cfg(test)]
758 pub fn test_down_interface(&self, ifname: &str) -> Result<()> {
759 self.send_cmd(Command::SetOption(DaemonOption::TestDownInterface(
760 ifname.to_string(),
761 )))
762 }
763
764 #[cfg(test)]
765 pub fn test_up_interface(&self, ifname: &str) -> Result<()> {
766 self.send_cmd(Command::SetOption(DaemonOption::TestUpInterface(
767 ifname.to_string(),
768 )))
769 }
770
771 pub fn set_multicast_loop_v4(&self, on: bool) -> Result<()> {
787 self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV4(on)))
788 }
789
790 pub fn set_multicast_loop_v6(&self, on: bool) -> Result<()> {
806 self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV6(on)))
807 }
808
809 pub fn verify(&self, instance_fullname: String, timeout: Duration) -> Result<()> {
828 self.send_cmd(Command::Verify(instance_fullname, timeout))
829 }
830
831 fn daemon_thread(
832 signal_sock: MioUdpSocket,
833 poller: Poll,
834 receiver: Receiver<Command>,
835 port: u16,
836 cmd_sender: Sender<Command>,
837 signal_addr: SocketAddr,
838 ) {
839 let mut zc = Zeroconf::new(signal_sock, poller, port, cmd_sender, signal_addr);
840
841 if let Some(cmd) = zc.run(receiver) {
842 match cmd {
843 Command::Exit(resp_s) => {
844 if let Err(e) = resp_s.send(DaemonStatus::Shutdown) {
847 debug!("exit: failed to send response of shutdown: {}", e);
848 }
849 }
850 _ => {
851 debug!("Unexpected command: {:?}", cmd);
852 }
853 }
854 }
855 }
856}
857
858fn _new_socket_bind(intf: &Interface, should_loop: bool) -> Result<MyUdpSocket> {
860 let intf_ip = &intf.ip();
863 match intf_ip {
864 IpAddr::V4(ip) => {
865 let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), MDNS_PORT);
866 let sock = new_socket(addr.into(), true)?;
867
868 sock.join_multicast_v4(&GROUP_ADDR_V4, ip)
870 .map_err(|e| e_fmt!("join multicast group on addr {}: {}", intf_ip, e))?;
871
872 sock.set_multicast_if_v4(ip)
874 .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
875
876 sock.set_multicast_ttl_v4(255)
881 .map_err(|e| e_fmt!("set set_multicast_ttl_v4 on addr {}: {}", ip, e))?;
882
883 if !should_loop {
884 sock.set_multicast_loop_v4(false)
885 .map_err(|e| e_fmt!("failed to set multicast loop v4 for {ip}: {e}"))?;
886 }
887
888 let multicast_addr = SocketAddrV4::new(GROUP_ADDR_V4, MDNS_PORT).into();
890 let test_packets = DnsOutgoing::new(0).to_data_on_wire(MAX_PKT_DEFAULT, true);
891 for packet in test_packets {
892 sock.send_to(&packet, &multicast_addr)
893 .map_err(|e| e_fmt!("send multicast packet on addr {}: {}", ip, e))?;
894 }
895 MyUdpSocket::new(sock)
896 .map_err(|e| e_fmt!("failed to create MySocket for interface {}: {e}", intf.name))
897 }
898 IpAddr::V6(ip) => {
899 let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), MDNS_PORT, 0, 0);
900 let sock = new_socket(addr.into(), true)?;
901
902 let if_index = intf.index.unwrap_or(0);
903
904 sock.join_multicast_v6(&GROUP_ADDR_V6, if_index)
906 .map_err(|e| e_fmt!("join multicast group on addr {}: {}", ip, e))?;
907
908 sock.set_multicast_if_v6(if_index)
910 .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
911
912 MyUdpSocket::new(sock)
917 .map_err(|e| e_fmt!("failed to create MySocket for interface {}: {e}", intf.name))
918 }
919 }
920}
921
922fn new_socket(addr: SocketAddr, non_block: bool) -> Result<PktInfoUdpSocket> {
925 let domain = match addr {
926 SocketAddr::V4(_) => socket2::Domain::IPV4,
927 SocketAddr::V6(_) => socket2::Domain::IPV6,
928 };
929
930 let fd = PktInfoUdpSocket::new(domain).map_err(|e| e_fmt!("create socket failed: {}", e))?;
931
932 fd.set_reuse_address(true)
933 .map_err(|e| e_fmt!("set ReuseAddr failed: {}", e))?;
934 #[cfg(unix)]
935 if let Err(e) = fd.set_reuse_port(true) {
936 debug!(
937 "SO_REUSEPORT is not supported, continuing without it: {}",
938 e
939 );
940 }
941
942 if non_block {
943 fd.set_nonblocking(true)
944 .map_err(|e| e_fmt!("set O_NONBLOCK: {}", e))?;
945 }
946
947 fd.bind(&addr.into())
948 .map_err(|e| e_fmt!("socket bind to {} failed: {}", &addr, e))?;
949
950 trace!("new socket bind to {}", &addr);
951 Ok(fd)
952}
953
954struct ReRun {
956 next_time: u64,
958 command: Command,
959}
960
961struct DelayedResponse {
963 next_time: u64,
965 out: DnsOutgoing,
966 if_index: u32,
967 is_ipv4: bool,
968}
969
970#[derive(Debug, Clone)]
974#[non_exhaustive]
975pub enum IfKind {
976 All,
978
979 IPv4,
981
982 IPv6,
984
985 Name(String),
987
988 Addr(IpAddr),
992
993 LoopbackV4,
997
998 LoopbackV6,
1000
1001 IndexV4(u32),
1003
1004 IndexV6(u32),
1006
1007 Predicate(IfPredicate),
1009}
1010
1011impl IfKind {
1012 pub(crate) fn matches(&self, intf: &Interface) -> bool {
1014 match self {
1015 Self::All => true,
1016 Self::IPv4 => intf.ip().is_ipv4(),
1017 Self::IPv6 => intf.ip().is_ipv6(),
1018 Self::Name(ifname) => ifname == &intf.name,
1019 Self::Addr(addr) => addr == &intf.ip(),
1020 Self::LoopbackV4 => intf.is_loopback() && intf.ip().is_ipv4(),
1021 Self::LoopbackV6 => intf.is_loopback() && intf.ip().is_ipv6(),
1022 Self::IndexV4(idx) => intf.index == Some(*idx) && intf.ip().is_ipv4(),
1023 Self::IndexV6(idx) => intf.index == Some(*idx) && intf.ip().is_ipv6(),
1024 Self::Predicate(p) => p.matches(intf),
1025 }
1026 }
1027}
1028
1029impl From<&str> for IfKind {
1032 fn from(val: &str) -> Self {
1033 Self::Name(val.to_string())
1034 }
1035}
1036
1037impl From<&String> for IfKind {
1038 fn from(val: &String) -> Self {
1039 Self::Name(val.to_string())
1040 }
1041}
1042
1043impl From<IpAddr> for IfKind {
1045 fn from(val: IpAddr) -> Self {
1046 Self::Addr(val)
1047 }
1048}
1049
1050pub struct IfKindVec {
1052 kinds: Vec<IfKind>,
1053}
1054
1055pub trait IntoIfKindVec {
1057 fn into_vec(self) -> IfKindVec;
1058}
1059
1060impl<T: Into<IfKind>> IntoIfKindVec for T {
1061 fn into_vec(self) -> IfKindVec {
1062 let if_kind: IfKind = self.into();
1063 IfKindVec {
1064 kinds: vec![if_kind],
1065 }
1066 }
1067}
1068
1069impl<T: Into<IfKind>> IntoIfKindVec for Vec<T> {
1070 fn into_vec(self) -> IfKindVec {
1071 let kinds: Vec<IfKind> = self.into_iter().map(|x| x.into()).collect();
1072 IfKindVec { kinds }
1073 }
1074}
1075
1076#[derive(Clone)]
1078pub struct IfPredicate(std::sync::Arc<dyn Fn(&Interface) -> bool + Send + Sync>);
1079
1080impl IfPredicate {
1081 pub fn new(predicate: impl Fn(&Interface) -> bool + Send + Sync + 'static) -> Self {
1092 Self(std::sync::Arc::new(predicate))
1093 }
1094
1095 pub(crate) fn matches(&self, intf: &Interface) -> bool {
1096 self.0(intf)
1097 }
1098}
1099
1100impl std::fmt::Debug for IfPredicate {
1101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102 write!(f, "IfPredicate(...)")
1103 }
1104}
1105
1106struct IfSelection {
1108 if_kind: IfKind,
1110
1111 selected: bool,
1113}
1114
1115struct MaxPacketSizeSelection {
1117 if_kind: IfKind,
1119
1120 max_packet_size: usize,
1122}
1123
1124struct Zeroconf {
1126 port: u16,
1129
1130 my_intfs: HashMap<u32, MyIntf>,
1132
1133 ipv4_sock: Option<MyUdpSocket>,
1135
1136 ipv6_sock: Option<MyUdpSocket>,
1138
1139 my_services: HashMap<String, ServiceInfo>,
1141
1142 cache: DnsCache,
1144
1145 dns_registry_map: HashMap<u32, DnsRegistry>,
1147
1148 service_queriers: HashMap<String, Sender<ServiceEvent>>, hostname_resolvers: HashMap<String, (Sender<HostnameResolutionEvent>, Option<u64>)>, retransmissions: Vec<ReRun>,
1159
1160 delayed_responses: Vec<DelayedResponse>,
1162
1163 counters: Metrics,
1164
1165 poller: Poll,
1167
1168 monitors: Vec<Sender<DaemonEvent>>,
1170
1171 service_name_len_max: u8,
1173
1174 ip_check_interval: u64,
1176
1177 max_packet_sizes: Vec<MaxPacketSizeSelection>,
1180
1181 if_selections: Vec<IfSelection>,
1183
1184 signal_sock: MioUdpSocket,
1186
1187 timers: BinaryHeap<Reverse<u64>>,
1193
1194 status: DaemonStatus,
1195
1196 pending_resolves: HashSet<String>,
1198
1199 resolved: HashSet<String>,
1201
1202 multicast_loop_v4: bool,
1203
1204 multicast_loop_v6: bool,
1205
1206 accept_unsolicited: bool,
1207
1208 include_apple_p2p: bool,
1209
1210 cmd_sender: Sender<Command>,
1211
1212 signal_addr: SocketAddr,
1213
1214 #[cfg(test)]
1215 test_down_interfaces: HashSet<String>,
1216}
1217
1218fn join_multicast_group(my_sock: &PktInfoUdpSocket, intf: &Interface) -> Result<()> {
1220 let intf_ip = &intf.ip();
1221 match intf_ip {
1222 IpAddr::V4(ip) => {
1223 debug!("join multicast group V4 on {} addr {ip}", intf.name);
1225 my_sock
1226 .join_multicast_v4(&GROUP_ADDR_V4, ip)
1227 .map_err(|e| e_fmt!("PKT join multicast group on addr {}: {}", intf_ip, e))?;
1228 }
1229 IpAddr::V6(ip) => {
1230 let if_index = intf.index.unwrap_or(0);
1231 debug!(
1233 "join multicast group V6 on {} addr {ip} with index {if_index}",
1234 intf.name
1235 );
1236 my_sock
1237 .join_multicast_v6(&GROUP_ADDR_V6, if_index)
1238 .map_err(|e| e_fmt!("PKT join multicast group on addr {}: {}", ip, e))?;
1239 }
1240 }
1241 Ok(())
1242}
1243
1244impl Zeroconf {
1245 fn new(
1246 signal_sock: MioUdpSocket,
1247 poller: Poll,
1248 port: u16,
1249 cmd_sender: Sender<Command>,
1250 signal_addr: SocketAddr,
1251 ) -> Self {
1252 let my_ifaddrs = my_ip_interfaces(true);
1254
1255 let mut my_intfs = HashMap::new();
1259 let mut dns_registry_map = HashMap::new();
1260
1261 let mut ipv4_sock = None;
1264 let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port);
1265 match new_socket(addr.into(), true) {
1266 Ok(sock) => {
1267 sock.set_multicast_ttl_v4(255)
1272 .map_err(|e| e_fmt!("set set_multicast_ttl_v4 on addr: {}", e))
1273 .ok();
1274
1275 ipv4_sock = match MyUdpSocket::new(sock) {
1277 Ok(s) => Some(s),
1278 Err(e) => {
1279 debug!("failed to create IPv4 MyUdpSocket: {e}");
1280 None
1281 }
1282 };
1283 }
1284 Err(e) => debug!("failed to create IPv4 socket: {e}"),
1286 }
1287
1288 let mut ipv6_sock = None;
1289 let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), port, 0, 0);
1290 match new_socket(addr.into(), true) {
1291 Ok(sock) => {
1292 sock.set_multicast_hops_v6(255)
1296 .map_err(|e| e_fmt!("set set_multicast_hops_v6: {}", e))
1297 .ok();
1298
1299 ipv6_sock = match MyUdpSocket::new(sock) {
1301 Ok(s) => Some(s),
1302 Err(e) => {
1303 debug!("failed to create IPv6 MyUdpSocket: {e}");
1304 None
1305 }
1306 };
1307 }
1308 Err(e) => debug!("failed to create IPv6 socket: {e}"),
1309 }
1310
1311 for intf in my_ifaddrs {
1313 let sock_opt = if intf.ip().is_ipv4() {
1314 &ipv4_sock
1315 } else {
1316 &ipv6_sock
1317 };
1318 let Some(sock) = sock_opt else {
1319 debug!(
1320 "no socket available for interface {} with addr {}. Skipped.",
1321 intf.name,
1322 intf.ip()
1323 );
1324 continue;
1325 };
1326
1327 if let Err(e) = join_multicast_group(&sock.pktinfo, &intf) {
1328 debug!("failed to join multicast: {}: {e}. Skipped.", &intf.ip());
1329 }
1330
1331 let if_index = intf.index.unwrap_or(0);
1332
1333 dns_registry_map
1335 .entry(if_index)
1336 .or_insert_with(DnsRegistry::new);
1337
1338 my_intfs
1339 .entry(if_index)
1340 .and_modify(|v: &mut MyIntf| {
1341 v.addrs.insert(intf.addr.clone());
1342 })
1343 .or_insert(MyIntf {
1344 name: intf.name.clone(),
1345 index: if_index,
1346 addrs: HashSet::from([intf.addr]),
1347 max_packet_size_v4: MAX_PKT_DEFAULT,
1348 max_packet_size_v6: MAX_PKT_DEFAULT,
1349 });
1350 }
1351
1352 let monitors = Vec::new();
1353 let service_name_len_max = SERVICE_NAME_LEN_MAX_DEFAULT;
1354 let ip_check_interval = IP_CHECK_INTERVAL_IN_SECS_DEFAULT as u64 * 1000;
1355
1356 let timers = BinaryHeap::new();
1357
1358 let if_selections = vec![];
1360
1361 let status = DaemonStatus::Running;
1362
1363 Self {
1364 port,
1365 my_intfs,
1366 ipv4_sock,
1367 ipv6_sock,
1368 my_services: HashMap::new(),
1369 cache: DnsCache::new(),
1370 dns_registry_map,
1371 hostname_resolvers: HashMap::new(),
1372 service_queriers: HashMap::new(),
1373 retransmissions: Vec::new(),
1374 delayed_responses: Vec::new(),
1375 counters: HashMap::new(),
1376 poller,
1377 monitors,
1378 service_name_len_max,
1379 ip_check_interval,
1380 max_packet_sizes: Vec::new(),
1381 if_selections,
1382 signal_sock,
1383 timers,
1384 status,
1385 pending_resolves: HashSet::new(),
1386 resolved: HashSet::new(),
1387 multicast_loop_v4: true,
1388 multicast_loop_v6: true,
1389 accept_unsolicited: false,
1390 include_apple_p2p: false,
1391 cmd_sender,
1392 signal_addr,
1393
1394 #[cfg(test)]
1395 test_down_interfaces: HashSet::new(),
1396 }
1397 }
1398
1399 fn send_cmd_to_self(&self, cmd: Command) -> Result<()> {
1401 let cmd_name = cmd.to_string();
1402
1403 self.cmd_sender.try_send(cmd).map_err(|e| match e {
1404 TrySendError::Full(_) => Error::Again,
1405 TrySendError::Disconnected(_) => Error::DaemonShutdown,
1406 })?;
1407
1408 let addr = SocketAddrV4::new(LOOPBACK_V4, 0);
1409 let socket = UdpSocket::bind(addr)
1410 .map_err(|e| e_fmt!("Failed to create socket to send signal: {}", e))?;
1411 socket
1412 .send_to(cmd_name.as_bytes(), self.signal_addr)
1413 .map_err(|e| {
1414 e_fmt!(
1415 "signal socket send_to {} ({}) failed: {}",
1416 self.signal_addr,
1417 cmd_name,
1418 e
1419 )
1420 })?;
1421
1422 Ok(())
1423 }
1424
1425 fn cleanup(&mut self) {
1434 debug!("Starting cleanup for shutdown");
1435
1436 let service_names: Vec<String> = self.my_services.keys().cloned().collect();
1438 for fullname in service_names {
1439 if let Some(info) = self.my_services.get(&fullname) {
1440 debug!("Unregistering service during shutdown: {}", &fullname);
1441
1442 for intf in self.my_intfs.values() {
1443 if let Some(sock) = self.ipv4_sock.as_ref() {
1444 self.unregister_service(info, intf, &sock.pktinfo);
1445 }
1446
1447 if let Some(sock) = self.ipv6_sock.as_ref() {
1448 self.unregister_service(info, intf, &sock.pktinfo);
1449 }
1450 }
1451 }
1452 }
1453 self.my_services.clear();
1454
1455 let browse_types: Vec<String> = self.service_queriers.keys().cloned().collect();
1457 for ty_domain in browse_types {
1458 debug!("Stopping browse during shutdown: {}", &ty_domain);
1459 if let Some(sender) = self.service_queriers.remove(&ty_domain) {
1460 if let Err(e) = sender.send(ServiceEvent::SearchStopped(ty_domain.clone())) {
1462 debug!("Failed to send SearchStopped during shutdown: {}", e);
1463 }
1464 }
1465 }
1466
1467 let hostnames: Vec<String> = self.hostname_resolvers.keys().cloned().collect();
1469 for hostname in hostnames {
1470 debug!(
1471 "Stopping hostname resolution during shutdown: {}",
1472 &hostname
1473 );
1474 if let Some((sender, _timeout)) = self.hostname_resolvers.remove(&hostname) {
1475 if let Err(e) =
1477 sender.send(HostnameResolutionEvent::SearchStopped(hostname.clone()))
1478 {
1479 debug!(
1480 "Failed to send HostnameResolutionEvent::SearchStopped during shutdown: {}",
1481 e
1482 );
1483 }
1484 }
1485 }
1486
1487 self.retransmissions.clear();
1489
1490 self.delayed_responses.clear();
1492
1493 debug!("Cleanup completed");
1494 }
1495
1496 fn run(&mut self, receiver: Receiver<Command>) -> Option<Command> {
1505 if let Err(e) = self.poller.registry().register(
1507 &mut self.signal_sock,
1508 mio::Token(SIGNAL_SOCK_EVENT_KEY),
1509 mio::Interest::READABLE,
1510 ) {
1511 debug!("failed to add signal socket to the poller: {}", e);
1512 return None;
1513 }
1514
1515 if let Some(sock) = self.ipv4_sock.as_mut() {
1516 if let Err(e) = self.poller.registry().register(
1517 sock,
1518 mio::Token(IPV4_SOCK_EVENT_KEY),
1519 mio::Interest::READABLE,
1520 ) {
1521 debug!("failed to register ipv4 socket: {}", e);
1522 return None;
1523 }
1524 }
1525
1526 if let Some(sock) = self.ipv6_sock.as_mut() {
1527 if let Err(e) = self.poller.registry().register(
1528 sock,
1529 mio::Token(IPV6_SOCK_EVENT_KEY),
1530 mio::Interest::READABLE,
1531 ) {
1532 debug!("failed to register ipv6 socket: {}", e);
1533 return None;
1534 }
1535 }
1536
1537 let mut next_ip_check = if self.ip_check_interval > 0 {
1539 current_time_millis() + self.ip_check_interval
1540 } else {
1541 0
1542 };
1543
1544 if next_ip_check > 0 {
1545 self.add_timer(next_ip_check);
1546 }
1547
1548 let mut events = mio::Events::with_capacity(1024);
1551 loop {
1552 let now = current_time_millis();
1553
1554 let earliest_timer = self.peek_earliest_timer();
1555 let timeout = earliest_timer.map(|timer| {
1556 let millis = if timer > now { timer - now } else { 1 };
1558 Duration::from_millis(millis)
1559 });
1560
1561 events.clear();
1563 match self.poller.poll(&mut events, timeout) {
1564 Ok(_) => self.handle_poller_events(&events),
1565 Err(e) => debug!("failed to select from sockets: {}", e),
1566 }
1567
1568 let now = current_time_millis();
1569
1570 self.pop_timers_till(now);
1572
1573 for hostname in self
1575 .hostname_resolvers
1576 .clone()
1577 .into_iter()
1578 .filter(|(_, (_, timeout))| timeout.map(|t| now >= t).unwrap_or(false))
1579 .map(|(hostname, _)| hostname)
1580 {
1581 trace!("hostname resolver timeout for {}", &hostname);
1582 call_hostname_resolution_listener(
1583 &self.hostname_resolvers,
1584 &hostname,
1585 HostnameResolutionEvent::SearchTimeout(hostname.to_owned()),
1586 );
1587 call_hostname_resolution_listener(
1588 &self.hostname_resolvers,
1589 &hostname,
1590 HostnameResolutionEvent::SearchStopped(hostname.to_owned()),
1591 );
1592 self.hostname_resolvers.remove(&hostname);
1593 }
1594
1595 while let Ok(command) = receiver.try_recv() {
1597 if matches!(command, Command::Exit(_)) {
1598 debug!("Exit command received, performing cleanup");
1599 self.cleanup();
1600 self.status = DaemonStatus::Shutdown;
1601 return Some(command);
1602 }
1603 self.exec_command(command, false);
1604 }
1605
1606 let mut i = 0;
1608 while i < self.retransmissions.len() {
1609 if now >= self.retransmissions[i].next_time {
1610 let rerun = self.retransmissions.remove(i);
1611 self.exec_command(rerun.command, true);
1612 } else {
1613 i += 1;
1614 }
1615 }
1616
1617 let mut i = 0;
1619 while i < self.delayed_responses.len() {
1620 if now >= self.delayed_responses[i].next_time {
1621 let resp = self.delayed_responses.remove(i);
1622 self.send_delayed_response(resp);
1623 } else {
1624 i += 1;
1625 }
1626 }
1627
1628 self.refresh_active_services();
1630
1631 let mut query_count = 0;
1633 for (hostname, _sender) in self.hostname_resolvers.iter() {
1634 for (hostname, ip_addr) in
1635 self.cache.refresh_due_hostname_resolutions(hostname).iter()
1636 {
1637 self.send_query(hostname, ip_address_rr_type(&ip_addr.to_ip_addr()));
1638 query_count += 1;
1639 }
1640 }
1641
1642 self.increase_counter(Counter::CacheRefreshAddr, query_count);
1643
1644 let now = current_time_millis();
1646
1647 let expired_services = self.cache.evict_expired_services(now);
1649 if !expired_services.is_empty() {
1650 debug!(
1651 "run: send {} service removal to listeners",
1652 expired_services.len()
1653 );
1654 self.notify_service_removal(expired_services);
1655 }
1656
1657 let expired_addrs = self.cache.evict_expired_addr(now);
1659 for (hostname, addrs) in expired_addrs {
1660 call_hostname_resolution_listener(
1661 &self.hostname_resolvers,
1662 &hostname,
1663 HostnameResolutionEvent::AddressesRemoved(hostname.clone(), addrs),
1664 );
1665 let instances = self.cache.get_instances_on_host(&hostname);
1666 let instance_set: HashSet<String> = instances.into_iter().collect();
1667 self.resolve_updated_instances(&instance_set);
1668 }
1669
1670 self.probing_handler();
1672
1673 if now >= next_ip_check && next_ip_check > 0 {
1675 next_ip_check = now + self.ip_check_interval;
1676 self.add_timer(next_ip_check);
1677
1678 self.check_ip_changes();
1679 }
1680 }
1681 }
1682
1683 fn process_set_option(&mut self, daemon_opt: DaemonOption) {
1684 match daemon_opt {
1685 DaemonOption::ServiceNameLenMax(length) => self.service_name_len_max = length,
1686 DaemonOption::IpCheckInterval(interval) => self.ip_check_interval = interval,
1687 DaemonOption::MaxPacketSize(if_kind, size) => self.set_max_packet_size(if_kind, size),
1688 DaemonOption::EnableInterface(if_kind) => self.enable_interface(if_kind),
1689 DaemonOption::DisableInterface(if_kind) => self.disable_interface(if_kind),
1690 DaemonOption::MulticastLoopV4(on) => self.set_multicast_loop_v4(on),
1691 DaemonOption::MulticastLoopV6(on) => self.set_multicast_loop_v6(on),
1692 DaemonOption::AcceptUnsolicited(accept) => self.set_accept_unsolicited(accept),
1693 DaemonOption::IncludeAppleP2P(enable) => self.set_apple_p2p(enable),
1694 #[cfg(test)]
1695 DaemonOption::TestDownInterface(ifname) => {
1696 self.test_down_interfaces.insert(ifname);
1697 }
1698 #[cfg(test)]
1699 DaemonOption::TestUpInterface(ifname) => {
1700 self.test_down_interfaces.remove(&ifname);
1701 }
1702 }
1703 }
1704
1705 fn enable_interface(&mut self, kinds: Vec<IfKind>) {
1706 debug!("enable_interface: {:?}", kinds);
1707 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1708
1709 for if_kind in kinds {
1710 self.if_selections.push(IfSelection {
1711 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1712 selected: true,
1713 });
1714 }
1715
1716 self.apply_intf_selections(interfaces);
1717 }
1718
1719 fn disable_interface(&mut self, kinds: Vec<IfKind>) {
1720 debug!("disable_interface: {:?}", kinds);
1721 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1722
1723 for if_kind in kinds {
1724 self.if_selections.push(IfSelection {
1725 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1726 selected: false,
1727 });
1728 }
1729
1730 self.apply_intf_selections(interfaces);
1731 }
1732
1733 fn set_max_packet_size(&mut self, kinds: Vec<IfKind>, size: usize) {
1734 debug!("set_max_packet_size: {:?} {}", kinds, size);
1735 let interfaces = my_ip_interfaces_inner(true, self.include_apple_p2p);
1736
1737 for if_kind in kinds {
1738 self.max_packet_sizes.push(MaxPacketSizeSelection {
1739 if_kind: resolve_addr_to_index(if_kind, &interfaces),
1740 max_packet_size: size,
1741 });
1742 }
1743
1744 self.apply_max_packet_sizes(&interfaces);
1745 }
1746
1747 fn apply_max_packet_sizes(&mut self, interfaces: &[Interface]) {
1750 for (if_index, my_intf) in self.my_intfs.iter_mut() {
1751 let v4 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, *if_index, true);
1752 let v6 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, *if_index, false);
1753
1754 if my_intf.max_packet_size_v4 != v4 || my_intf.max_packet_size_v6 != v6 {
1755 debug!(
1756 "interface {}: max packet size v4 {} -> {v4}, v6 {} -> {v6}",
1757 my_intf.name, my_intf.max_packet_size_v4, my_intf.max_packet_size_v6
1758 );
1759 my_intf.max_packet_size_v4 = v4;
1760 my_intf.max_packet_size_v6 = v6;
1761 }
1762 }
1763 }
1764
1765 fn set_multicast_loop_v4(&mut self, on: bool) {
1766 let Some(sock) = self.ipv4_sock.as_mut() else {
1767 return;
1768 };
1769 self.multicast_loop_v4 = on;
1770 sock.pktinfo
1771 .set_multicast_loop_v4(on)
1772 .map_err(|e| e_fmt!("failed to set multicast loop v4: {}", e))
1773 .unwrap();
1774 }
1775
1776 fn set_multicast_loop_v6(&mut self, on: bool) {
1777 let Some(sock) = self.ipv6_sock.as_mut() else {
1778 return;
1779 };
1780 self.multicast_loop_v6 = on;
1781 sock.pktinfo
1782 .set_multicast_loop_v6(on)
1783 .map_err(|e| e_fmt!("failed to set multicast loop v6: {}", e))
1784 .unwrap();
1785 }
1786
1787 fn set_accept_unsolicited(&mut self, accept: bool) {
1788 self.accept_unsolicited = accept;
1789 }
1790
1791 fn set_apple_p2p(&mut self, include: bool) {
1792 if self.include_apple_p2p != include {
1793 self.include_apple_p2p = include;
1794 self.apply_intf_selections(my_ip_interfaces_inner(true, self.include_apple_p2p));
1795 }
1796 }
1797
1798 fn notify_monitors(&mut self, event: DaemonEvent) {
1799 self.monitors.retain(|sender| {
1801 if let Err(e) = sender.try_send(event.clone()) {
1802 debug!("notify_monitors: try_send: {}", &e);
1803 if matches!(e, TrySendError::Disconnected(_)) {
1804 return false; }
1806 }
1807 true
1808 });
1809 }
1810
1811 fn del_addr_in_my_services(&mut self, addr: &IpAddr) {
1813 for (_, service_info) in self.my_services.iter_mut() {
1814 if service_info.is_addr_auto() {
1815 service_info.remove_ipaddr(addr);
1816 }
1817 }
1818 }
1819
1820 fn add_timer(&mut self, next_time: u64) {
1821 self.timers.push(Reverse(next_time));
1822 }
1823
1824 fn peek_earliest_timer(&self) -> Option<u64> {
1825 self.timers.peek().map(|Reverse(v)| *v)
1826 }
1827
1828 fn _pop_earliest_timer(&mut self) -> Option<u64> {
1829 self.timers.pop().map(|Reverse(v)| v)
1830 }
1831
1832 fn pop_timers_till(&mut self, now: u64) {
1834 while let Some(Reverse(v)) = self.timers.peek() {
1835 if *v > now {
1836 break;
1837 }
1838 self.timers.pop();
1839 }
1840 }
1841
1842 fn selected_intfs(&self, interfaces: Vec<Interface>) -> HashSet<Interface> {
1844 let intf_count = interfaces.len();
1845 let mut intf_selections = vec![true; intf_count];
1846
1847 for selection in self.if_selections.iter() {
1849 for i in 0..intf_count {
1851 if selection.if_kind.matches(&interfaces[i]) {
1852 intf_selections[i] = selection.selected;
1853 }
1854 }
1855 }
1856
1857 let mut selected_addrs = HashSet::new();
1858 for i in 0..intf_count {
1859 if intf_selections[i] {
1860 selected_addrs.insert(interfaces[i].clone());
1861 }
1862 }
1863
1864 selected_addrs
1865 }
1866
1867 fn apply_intf_selections(&mut self, interfaces: Vec<Interface>) {
1872 let intf_count = interfaces.len();
1874 let mut intf_selections = vec![true; intf_count];
1875
1876 for selection in self.if_selections.iter() {
1878 for i in 0..intf_count {
1880 if selection.if_kind.matches(&interfaces[i]) {
1881 intf_selections[i] = selection.selected;
1882 }
1883 }
1884 }
1885
1886 for (idx, intf) in interfaces.iter().enumerate() {
1888 if intf_selections[idx] {
1889 self.add_interface(intf, &interfaces);
1891 } else {
1892 self.del_interface_addr(intf);
1894 }
1895 }
1896
1897 self.apply_max_packet_sizes(&interfaces);
1900 }
1901
1902 fn del_ip(&mut self, ip: IpAddr) {
1903 self.del_addr_in_my_services(&ip);
1904 self.notify_monitors(DaemonEvent::IpDel(ip));
1905 }
1906
1907 fn check_ip_changes(&mut self) {
1909 let my_ifaddrs = my_ip_interfaces_inner(true, self.include_apple_p2p);
1911
1912 #[cfg(test)]
1913 let my_ifaddrs: Vec<_> = my_ifaddrs
1914 .into_iter()
1915 .filter(|intf| !self.test_down_interfaces.contains(&intf.name))
1916 .collect();
1917
1918 let ifaddrs_map: HashMap<u32, Vec<&IfAddr>> =
1919 my_ifaddrs.iter().fold(HashMap::new(), |mut acc, intf| {
1920 let if_index = intf.index.unwrap_or(0);
1921 acc.entry(if_index).or_default().push(&intf.addr);
1922 acc
1923 });
1924
1925 let mut deleted_intfs = Vec::new();
1926 let mut deleted_ips = Vec::new();
1927
1928 for (if_index, my_intf) in self.my_intfs.iter_mut() {
1929 let mut last_ipv4 = None;
1930 let mut last_ipv6 = None;
1931
1932 if let Some(current_addrs) = ifaddrs_map.get(if_index) {
1933 my_intf.addrs.retain(|addr| {
1934 if current_addrs.contains(&addr) {
1935 true
1936 } else {
1937 match addr.ip() {
1938 IpAddr::V4(ipv4) => last_ipv4 = Some(ipv4),
1939 IpAddr::V6(ipv6) => last_ipv6 = Some(ipv6),
1940 }
1941 deleted_ips.push(addr.ip());
1942 false
1943 }
1944 });
1945 if my_intf.addrs.is_empty() {
1946 deleted_intfs.push((*if_index, last_ipv4, last_ipv6))
1947 }
1948 } else {
1949 debug!(
1951 "check_ip_changes: interface {} ({}) no longer exists, removing",
1952 my_intf.name, if_index
1953 );
1954 for addr in my_intf.addrs.iter() {
1955 match addr.ip() {
1956 IpAddr::V4(ipv4) => last_ipv4 = Some(ipv4),
1957 IpAddr::V6(ipv6) => last_ipv6 = Some(ipv6),
1958 }
1959 deleted_ips.push(addr.ip())
1960 }
1961 deleted_intfs.push((*if_index, last_ipv4, last_ipv6));
1962 }
1963 }
1964
1965 if !deleted_ips.is_empty() || !deleted_intfs.is_empty() {
1966 debug!(
1967 "check_ip_changes: {} deleted ips {} deleted intfs",
1968 deleted_ips.len(),
1969 deleted_intfs.len()
1970 );
1971 }
1972
1973 for ip in deleted_ips {
1974 self.del_ip(ip);
1975 }
1976
1977 for (if_index, last_ipv4, last_ipv6) in deleted_intfs {
1978 let Some(my_intf) = self.my_intfs.remove(&if_index) else {
1979 continue;
1980 };
1981
1982 if let Some(ipv4) = last_ipv4 {
1983 debug!("leave multicast for {ipv4}");
1984 if let Some(sock) = self.ipv4_sock.as_mut() {
1985 if let Err(e) = sock.pktinfo.leave_multicast_v4(&GROUP_ADDR_V4, &ipv4) {
1986 debug!("leave multicast group for addr {ipv4}: {e}");
1987 }
1988 }
1989 }
1990
1991 if let Some(ipv6) = last_ipv6 {
1992 debug!("leave multicast for {ipv6}");
1993 if let Some(sock) = self.ipv6_sock.as_mut() {
1994 if let Err(e) = sock
1995 .pktinfo
1996 .leave_multicast_v6(&GROUP_ADDR_V6, my_intf.index)
1997 {
1998 debug!("leave multicast group for IPv6: {ipv6}: {e}");
1999 }
2000 }
2001 }
2002
2003 let intf_id = InterfaceId {
2005 name: my_intf.name.to_string(),
2006 index: my_intf.index,
2007 };
2008 let result = self.cache.remove_records_on_intf(intf_id);
2009 self.notify_service_removal(result.removed_instances);
2010 self.resolve_updated_instances(&result.modified_instances);
2011 }
2012
2013 self.apply_intf_selections(my_ifaddrs);
2015 }
2016
2017 fn del_interface_addr(&mut self, intf: &Interface) {
2020 let if_index = intf.index.unwrap_or(0);
2021 debug!(
2022 "del_interface_addr: {} ({if_index}) addr {}",
2023 intf.name,
2024 intf.ip()
2025 );
2026
2027 let Some(my_intf) = self.my_intfs.get_mut(&if_index) else {
2028 debug!("del_interface_addr: interface {} not found", intf.name);
2029 return;
2030 };
2031
2032 let mut ip_removed = false;
2033
2034 if my_intf.addrs.remove(&intf.addr) {
2035 ip_removed = true;
2036
2037 match intf.addr.ip() {
2038 IpAddr::V4(ipv4) => {
2039 if my_intf.next_ifaddr_v4().is_none() {
2040 if let Some(sock) = self.ipv4_sock.as_mut() {
2041 if let Err(e) = sock.pktinfo.leave_multicast_v4(&GROUP_ADDR_V4, &ipv4) {
2042 debug!("leave multicast group for addr {ipv4}: {e}");
2043 } else {
2044 debug!("leave multicast for {ipv4}");
2045 }
2046 }
2047 }
2048 }
2049
2050 IpAddr::V6(ipv6) => {
2051 if my_intf.next_ifaddr_v6().is_none() {
2052 if let Some(sock) = self.ipv6_sock.as_mut() {
2053 if let Err(e) =
2054 sock.pktinfo.leave_multicast_v6(&GROUP_ADDR_V6, if_index)
2055 {
2056 debug!("leave multicast group for addr {ipv6}: {e}");
2057 }
2058 }
2059 }
2060 }
2061 }
2062
2063 if my_intf.addrs.is_empty() {
2064 debug!("del_interface_addr: removing interface {}", intf.name);
2066 self.my_intfs.remove(&if_index);
2067 self.dns_registry_map.remove(&if_index);
2068 self.cache
2069 .remove_addrs_on_disabled_intf(if_index, IpType::BOTH);
2070 } else {
2071 let is_v4 = intf.addr.ip().is_ipv4();
2075 let version_gone = if is_v4 {
2076 my_intf.next_ifaddr_v4().is_none()
2077 } else {
2078 my_intf.next_ifaddr_v6().is_none()
2079 };
2080 if version_gone {
2081 let ip_type = if is_v4 { IpType::V4 } else { IpType::V6 };
2082 self.cache.remove_addrs_on_disabled_intf(if_index, ip_type);
2083 }
2084 }
2085 }
2086
2087 if ip_removed {
2088 self.notify_monitors(DaemonEvent::IpDel(intf.ip()));
2090 self.del_addr_in_my_services(&intf.ip());
2092 }
2093 }
2094
2095 fn add_interface(&mut self, intf: &Interface, interfaces: &[Interface]) {
2109 let sock_opt = if intf.ip().is_ipv4() {
2110 &self.ipv4_sock
2111 } else {
2112 &self.ipv6_sock
2113 };
2114
2115 let Some(sock) = sock_opt else {
2116 debug!(
2117 "add_interface: no socket available for interface {} with addr {}. Skipped.",
2118 intf.name,
2119 intf.ip()
2120 );
2121 return;
2122 };
2123
2124 let if_index = intf.index.unwrap_or(0);
2125 let mut new_addr = false;
2126
2127 match self.my_intfs.entry(if_index) {
2128 Entry::Occupied(mut entry) => {
2129 let my_intf = entry.get_mut();
2131 if !my_intf.addrs.contains(&intf.addr) {
2132 if let Err(e) = join_multicast_group(&sock.pktinfo, intf) {
2133 debug!("add_interface: socket_config {}: {e}", &intf.name);
2134 }
2135 my_intf.addrs.insert(intf.addr.clone());
2136 new_addr = true;
2137 }
2138 }
2139 Entry::Vacant(entry) => {
2140 if let Err(e) = join_multicast_group(&sock.pktinfo, intf) {
2141 debug!("add_interface: socket_config {}: {e}. Skipped.", &intf.name);
2142 return;
2143 }
2144
2145 new_addr = true;
2146 let new_intf = MyIntf {
2147 name: intf.name.clone(),
2148 index: if_index,
2149 addrs: HashSet::from([intf.addr.clone()]),
2150 max_packet_size_v4: MAX_PKT_DEFAULT,
2151 max_packet_size_v6: MAX_PKT_DEFAULT,
2152 };
2153 entry.insert(new_intf);
2154 }
2155 }
2156
2157 if !new_addr {
2158 trace!("add_interface: interface {} already exists", &intf.name);
2159 return;
2160 }
2161
2162 debug!("add new interface {}: {}", intf.name, intf.ip());
2163
2164 let v4 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, if_index, true);
2166 let v6 = resolve_max_packet_size(&self.max_packet_sizes, interfaces, if_index, false);
2167 if let Some(my_intf) = self.my_intfs.get_mut(&if_index) {
2168 my_intf.max_packet_size_v4 = v4;
2169 my_intf.max_packet_size_v6 = v6;
2170 }
2171
2172 let Some(my_intf) = self.my_intfs.get(&if_index) else {
2173 debug!("add_interface: cannot find if_index {if_index}");
2174 return;
2175 };
2176
2177 let dns_registry = match self.dns_registry_map.get_mut(&if_index) {
2178 Some(registry) => registry,
2179 None => self
2180 .dns_registry_map
2181 .entry(if_index)
2182 .or_insert_with(DnsRegistry::new),
2183 };
2184
2185 for (_, service_info) in self.my_services.iter_mut() {
2186 if service_info.is_addr_auto() {
2187 if !service_info.insert_ipaddr(intf) {
2188 continue;
2191 }
2192
2193 if let Ok(true) = announce_service_on_intf(
2194 dns_registry,
2195 service_info,
2196 my_intf,
2197 &sock.pktinfo,
2198 self.port,
2199 ) {
2200 debug!(
2201 "Announce service {} on {}",
2202 service_info.get_fullname(),
2203 intf.ip()
2204 );
2205 service_info.set_status(if_index, ServiceStatus::Announced);
2206 } else {
2207 for timer in dns_registry.new_timers.drain(..) {
2208 self.timers.push(Reverse(timer));
2209 }
2210 service_info.set_status(if_index, ServiceStatus::Probing);
2211 }
2212 }
2213 }
2214
2215 if let Some(my_intf) = self.my_intfs.get(&if_index) {
2220 for ty in self.service_queriers.keys() {
2221 self.send_query_on_intf(ty, RRType::PTR, my_intf);
2222 }
2223 }
2224
2225 self.notify_monitors(DaemonEvent::IpAdd(intf.ip()));
2227 }
2228
2229 fn register_service(&mut self, mut info: ServiceInfo) {
2238 if let Err(e) = check_service_name_length(info.get_type(), self.service_name_len_max) {
2240 error!("check_service_name_length: {}", &e);
2241 self.notify_monitors(DaemonEvent::Error(e));
2242 return;
2243 }
2244
2245 if info.is_addr_auto() {
2246 let selected_intfs =
2247 self.selected_intfs(my_ip_interfaces_inner(true, self.include_apple_p2p));
2248 for intf in selected_intfs {
2249 info.insert_ipaddr(&intf);
2250 }
2251 }
2252
2253 debug!("register service {:?}", &info);
2254
2255 let outgoing_addrs = self.send_unsolicited_response(&mut info);
2256 if !outgoing_addrs.is_empty() {
2257 self.notify_monitors(DaemonEvent::Announce(
2258 info.get_fullname().to_string(),
2259 format!("{:?}", &outgoing_addrs),
2260 ));
2261 }
2262
2263 let service_fullname = info.get_fullname().to_lowercase();
2266 self.my_services.insert(service_fullname, info);
2267 }
2268
2269 fn send_unsolicited_response(&mut self, info: &mut ServiceInfo) -> Vec<IpAddr> {
2272 let mut outgoing_addrs = Vec::new();
2273 let mut outgoing_intfs = HashSet::new();
2274
2275 let mut invalid_intf_addrs = HashSet::new();
2276
2277 for (if_index, intf) in self.my_intfs.iter() {
2278 let dns_registry = match self.dns_registry_map.get_mut(if_index) {
2279 Some(registry) => registry,
2280 None => self
2281 .dns_registry_map
2282 .entry(*if_index)
2283 .or_insert_with(DnsRegistry::new),
2284 };
2285
2286 let mut announced = false;
2287
2288 if let Some(sock) = self.ipv4_sock.as_mut() {
2290 match announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port) {
2291 Ok(true) => {
2292 for addr in intf.addrs.iter().filter(|a| a.ip().is_ipv4()) {
2293 outgoing_addrs.push(addr.ip());
2294 }
2295 outgoing_intfs.insert(intf.index);
2296
2297 debug!(
2298 "Announce service IPv4 {} on {}",
2299 info.get_fullname(),
2300 intf.name
2301 );
2302 announced = true;
2303 }
2304 Ok(false) => {}
2305 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2306 invalid_intf_addrs.insert(intf_addr);
2307 }
2308 }
2309 }
2310
2311 if let Some(sock) = self.ipv6_sock.as_mut() {
2312 match announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port) {
2313 Ok(true) => {
2314 for addr in intf.addrs.iter().filter(|a| a.ip().is_ipv6()) {
2315 outgoing_addrs.push(addr.ip());
2316 }
2317 outgoing_intfs.insert(intf.index);
2318
2319 debug!(
2320 "Announce service IPv6 {} on {}",
2321 info.get_fullname(),
2322 intf.name
2323 );
2324 announced = true;
2325 }
2326 Ok(false) => {}
2327 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2328 invalid_intf_addrs.insert(intf_addr);
2329 }
2330 }
2331 }
2332
2333 if announced {
2334 info.set_status(intf.index, ServiceStatus::Announced);
2335 } else {
2336 for timer in dns_registry.new_timers.drain(..) {
2337 self.timers.push(Reverse(timer));
2338 }
2339 info.set_status(*if_index, ServiceStatus::Probing);
2340 }
2341 }
2342
2343 if !invalid_intf_addrs.is_empty() {
2344 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2345 }
2346
2347 let next_time = current_time_millis()
2351 + ANNOUNCE_SECOND_DELAY_MILLIS
2352 + fastrand::u64(0..ANNOUNCE_SECOND_JITTER_MILLIS);
2353 for if_index in outgoing_intfs {
2354 self.add_retransmission(
2355 next_time,
2356 Command::RegisterResend(info.get_fullname().to_string(), if_index),
2357 );
2358 }
2359
2360 outgoing_addrs
2361 }
2362
2363 fn probing_handler(&mut self) {
2365 let now = current_time_millis();
2366 let mut invalid_intf_addrs = HashSet::new();
2367
2368 for (if_index, intf) in self.my_intfs.iter() {
2369 let Some(dns_registry) = self.dns_registry_map.get_mut(if_index) else {
2370 continue;
2371 };
2372
2373 let (out, expired_probes) = check_probing(dns_registry, &mut self.timers, now);
2374
2375 if !out.questions().is_empty() {
2377 trace!("sending out probing of questions: {:?}", out.questions());
2378 if let Some(sock) = self.ipv4_sock.as_mut() {
2379 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2380 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2381 {
2382 invalid_intf_addrs.insert(intf_addr);
2383 }
2384 }
2385 if let Some(sock) = self.ipv6_sock.as_mut() {
2386 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2387 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2388 {
2389 invalid_intf_addrs.insert(intf_addr);
2390 }
2391 }
2392 }
2393
2394 let waiting_services =
2396 handle_expired_probes(expired_probes, &intf.name, dns_registry, &mut self.monitors);
2397
2398 for service_name in waiting_services {
2399 if let Some(info) = self.my_services.get_mut(&service_name.to_lowercase()) {
2401 if info.get_status(*if_index) == ServiceStatus::Announced {
2402 debug!("service {} already announced", info.get_fullname());
2403 continue;
2404 }
2405
2406 let announced_v4 = if let Some(sock) = self.ipv4_sock.as_mut() {
2407 match announce_service_on_intf(
2408 dns_registry,
2409 info,
2410 intf,
2411 &sock.pktinfo,
2412 self.port,
2413 ) {
2414 Ok(announced) => announced,
2415 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2416 invalid_intf_addrs.insert(intf_addr);
2417 false
2418 }
2419 }
2420 } else {
2421 false
2422 };
2423 let announced_v6 = if let Some(sock) = self.ipv6_sock.as_mut() {
2424 match announce_service_on_intf(
2425 dns_registry,
2426 info,
2427 intf,
2428 &sock.pktinfo,
2429 self.port,
2430 ) {
2431 Ok(announced) => announced,
2432 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2433 invalid_intf_addrs.insert(intf_addr);
2434 false
2435 }
2436 }
2437 } else {
2438 false
2439 };
2440
2441 if announced_v4 || announced_v6 {
2442 let next_time = now
2443 + ANNOUNCE_SECOND_DELAY_MILLIS
2444 + fastrand::u64(0..ANNOUNCE_SECOND_JITTER_MILLIS);
2445 let command =
2446 Command::RegisterResend(info.get_fullname().to_string(), *if_index);
2447 self.retransmissions.push(ReRun { next_time, command });
2448 self.timers.push(Reverse(next_time));
2449
2450 let fullname = dns_registry.resolve_name(&service_name).to_string();
2451
2452 let hostname = dns_registry.resolve_name(info.get_hostname());
2453
2454 debug!("wake up: announce service {} on {}", fullname, intf.name);
2455 notify_monitors(
2456 &mut self.monitors,
2457 DaemonEvent::Announce(fullname, format!("{}:{}", hostname, &intf.name)),
2458 );
2459
2460 info.set_status(*if_index, ServiceStatus::Announced);
2461 }
2462 }
2463 }
2464 }
2465
2466 if !invalid_intf_addrs.is_empty() {
2467 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2468 }
2469 }
2470
2471 fn unregister_service(
2472 &self,
2473 info: &ServiceInfo,
2474 intf: &MyIntf,
2475 sock: &PktInfoUdpSocket,
2476 ) -> Vec<u8> {
2477 let is_ipv4 = sock.domain() == Domain::IPV4;
2478
2479 let (fullname, hostname) = match self.dns_registry_map.get(&intf.index) {
2483 Some(dns_registry) => (
2484 dns_registry.resolve_name(info.get_fullname()),
2485 dns_registry.resolve_name(info.get_hostname()),
2486 ),
2487 None => (info.get_fullname(), info.get_hostname()),
2488 };
2489
2490 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
2491 out.add_answer_at_time(
2492 DnsPointer::new(
2493 info.get_type(),
2494 RRType::PTR,
2495 CLASS_IN,
2496 0,
2497 fullname.to_string(),
2498 ),
2499 0,
2500 );
2501
2502 if let Some(sub) = info.get_subtype() {
2503 trace!("Adding subdomain {}", sub);
2504 out.add_answer_at_time(
2505 DnsPointer::new(sub, RRType::PTR, CLASS_IN, 0, fullname.to_string()),
2506 0,
2507 );
2508 }
2509
2510 out.add_answer_at_time(
2511 DnsSrv::new(
2512 fullname,
2513 CLASS_IN | CLASS_CACHE_FLUSH,
2514 0,
2515 info.get_priority(),
2516 info.get_weight(),
2517 info.get_port(),
2518 hostname.to_string(),
2519 ),
2520 0,
2521 );
2522 out.add_answer_at_time(
2523 DnsTxt::new(
2524 fullname,
2525 CLASS_IN | CLASS_CACHE_FLUSH,
2526 0,
2527 info.generate_txt(),
2528 ),
2529 0,
2530 );
2531
2532 let if_addrs = if is_ipv4 {
2533 info.get_addrs_on_my_intf_v4(intf)
2534 } else {
2535 info.get_addrs_on_my_intf_v6(intf)
2536 };
2537
2538 if if_addrs.is_empty() {
2539 return vec![];
2540 }
2541
2542 for address in if_addrs {
2543 out.add_answer_at_time(
2544 DnsAddress::new(
2545 hostname,
2546 ip_address_rr_type(&address),
2547 CLASS_IN | CLASS_CACHE_FLUSH,
2548 0,
2549 address,
2550 intf.into(),
2551 ),
2552 0,
2553 );
2554 }
2555
2556 let sent_vec = match send_dns_outgoing(&out, intf, sock, self.port, None, None) {
2558 Ok(sent_vec) => sent_vec,
2559 Err(InternalError::IntfAddrInvalid(intf_addr)) => {
2560 let invalid_intf_addrs = HashSet::from([intf_addr]);
2561 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2562 vec![]
2563 }
2564 };
2565 sent_vec.into_iter().next().unwrap_or_default()
2566 }
2567
2568 fn add_hostname_resolver(
2572 &mut self,
2573 hostname: String,
2574 listener: Sender<HostnameResolutionEvent>,
2575 timeout: Option<u64>,
2576 ) {
2577 let real_timeout = timeout.map(|t| current_time_millis() + t);
2578 self.hostname_resolvers
2579 .insert(hostname.to_lowercase(), (listener, real_timeout));
2580 if let Some(t) = real_timeout {
2581 self.add_timer(t);
2582 }
2583 }
2584
2585 fn send_query(&self, name: &str, qtype: RRType) {
2587 self.send_query_vec(&[(name, qtype)]);
2588 }
2589
2590 fn send_query_on_intf(&self, name: &str, qtype: RRType, intf: &MyIntf) {
2595 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
2596 out.add_question(name, qtype);
2597
2598 let mut invalid_intf_addrs = HashSet::new();
2599 if let Some(sock) = self.ipv4_sock.as_ref() {
2600 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2601 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2602 {
2603 invalid_intf_addrs.insert(intf_addr);
2604 }
2605 }
2606 if let Some(sock) = self.ipv6_sock.as_ref() {
2607 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2608 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2609 {
2610 invalid_intf_addrs.insert(intf_addr);
2611 }
2612 }
2613 if !invalid_intf_addrs.is_empty() {
2614 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2615 }
2616 }
2617
2618 fn send_query_vec(&self, questions: &[(&str, RRType)]) {
2620 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
2621 let now = current_time_millis();
2622
2623 for (name, qtype) in questions {
2624 out.add_question(name, *qtype);
2625
2626 for record in self.cache.get_known_answers(name, *qtype, now) {
2627 trace!("add known answer: {:?}", record.record);
2635 let mut new_record = record.record.clone();
2636 new_record.get_record_mut().update_ttl(now);
2637 out.add_answer_box(new_record);
2638 }
2639 }
2640
2641 let mut invalid_intf_addrs = HashSet::new();
2642 for (_, intf) in self.my_intfs.iter() {
2643 if let Some(sock) = self.ipv4_sock.as_ref() {
2644 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2645 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2646 {
2647 invalid_intf_addrs.insert(intf_addr);
2648 }
2649 }
2650 if let Some(sock) = self.ipv6_sock.as_ref() {
2651 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
2652 send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None)
2653 {
2654 invalid_intf_addrs.insert(intf_addr);
2655 }
2656 }
2657 }
2658
2659 if !invalid_intf_addrs.is_empty() {
2660 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addrs));
2661 }
2662 }
2663
2664 fn handle_read(&mut self, event_key: usize) -> bool {
2669 let is_ipv4 = event_key == IPV4_SOCK_EVENT_KEY;
2670 let sock_opt = match event_key {
2671 IPV4_SOCK_EVENT_KEY => &mut self.ipv4_sock,
2672 IPV6_SOCK_EVENT_KEY => &mut self.ipv6_sock,
2673 _ => {
2674 debug!("handle_read: unknown token {}", event_key);
2675 return false;
2676 }
2677 };
2678 let Some(sock) = sock_opt.as_mut() else {
2679 debug!("handle_read: socket not available for token {}", event_key);
2680 return false;
2681 };
2682 let max_size = max_pkt_absolute(is_ipv4);
2686 let mut buf = vec![0u8; max_size + 1];
2687
2688 let (sz, pktinfo) = match sock.pktinfo.recv(&mut buf) {
2690 Ok(sz) => sz,
2691 Err(e) => {
2692 if e.kind() != std::io::ErrorKind::WouldBlock {
2693 debug!("listening socket read failed: {}", e);
2694 }
2695 return false;
2696 }
2697 };
2698
2699 if sz > max_size {
2708 debug!(
2709 "handle_read: dropping over-sized datagram of at least {} bytes (max {})",
2710 sz, max_size
2711 );
2712 return true; }
2714
2715 let pkt_if_index = pktinfo.if_index as u32;
2717 let Some(my_intf) = self.my_intfs.get(&pkt_if_index) else {
2718 debug!(
2719 "handle_read: no interface found for pktinfo if_index: {}",
2720 pktinfo.if_index
2721 );
2722 return true; };
2724
2725 let is_ipv4 = event_key == IPV4_SOCK_EVENT_KEY;
2730 if (is_ipv4 && my_intf.next_ifaddr_v4().is_none())
2731 || (!is_ipv4 && my_intf.next_ifaddr_v6().is_none())
2732 {
2733 debug!(
2734 "handle_read: dropping {} packet on intf {} (disabled)",
2735 if is_ipv4 { "IPv4" } else { "IPv6" },
2736 my_intf.name
2737 );
2738 return true;
2739 }
2740
2741 buf.truncate(sz); match DnsIncoming::new(buf, my_intf.into()) {
2744 Ok(msg) => {
2745 debug!(
2746 "handle_read: {} bytes from {} on if_index {}: {} ({} questions {} answers {} authorities {} additionals)",
2747 sz,
2748 pktinfo.addr_src,
2749 pkt_if_index,
2750 if msg.is_query() { "query" } else { "response" },
2751 msg.questions().len(),
2752 msg.answers().len(),
2753 msg.authorities().len(),
2754 msg.additionals().len(),
2755 );
2756 if msg.is_query() {
2757 let querier_addr = pktinfo.addr_src;
2758 self.handle_query(msg, pkt_if_index, querier_addr);
2759 } else if msg.is_response() {
2760 self.handle_response(msg, pkt_if_index);
2761 } else {
2762 debug!("Invalid message: not query and not response");
2763 }
2764 }
2765 Err(e) => debug!("Invalid incoming DNS message: {}", e),
2766 }
2767
2768 true
2769 }
2770
2771 fn query_unresolved(&mut self, instance: &str) -> bool {
2773 if !valid_instance_name(instance) {
2774 trace!("instance name {} not valid", instance);
2775 return false;
2776 }
2777
2778 if let Some(records) = self.cache.get_srv(instance) {
2779 for record in records {
2780 if let Some(srv) = record.record.any().downcast_ref::<DnsSrv>() {
2781 if self.cache.get_addr(srv.host()).is_none() {
2782 debug!(
2783 "query_unresolved: SRV record found for instance: {}, host: {}, sending address query",
2784 instance,
2785 srv.host()
2786 );
2787 self.send_query_vec(&[(srv.host(), RRType::A), (srv.host(), RRType::AAAA)]);
2788 return true;
2789 }
2790 }
2791 }
2792 } else {
2793 debug!(
2794 "query_unresolved: SRV record not found for instance: {}, sending SRV+TXT query",
2795 instance
2796 );
2797 self.send_query_vec(&[(instance, RRType::SRV), (instance, RRType::TXT)]);
2802 return true;
2803 }
2804
2805 false
2806 }
2807
2808 fn query_unresolved_instances(&mut self, ty_domain: &str) {
2815 let now = current_time_millis();
2816 let mut instances = Vec::new();
2817 if let Some(records) = self.cache.get_ptr(ty_domain) {
2818 for record in records.iter().filter(|r| !r.record.expires_soon(now)) {
2819 if let Some(ptr) = record.record.any().downcast_ref::<DnsPointer>() {
2820 instances.push(ptr.alias().to_string());
2821 }
2822 }
2823 }
2824
2825 for instance in instances {
2826 if !self.resolved.contains(&instance) {
2827 self.query_unresolved(&instance);
2828 }
2829 }
2830 }
2831
2832 fn query_cache_for_service(
2835 &mut self,
2836 ty_domain: &str,
2837 sender: &Sender<ServiceEvent>,
2838 now: u64,
2839 ) {
2840 let mut resolved: HashSet<String> = HashSet::new();
2841 let mut unresolved: HashSet<String> = HashSet::new();
2842
2843 if let Some(records) = self.cache.get_ptr(ty_domain) {
2844 for record in records.iter().filter(|r| !r.record.expires_soon(now)) {
2845 if let Some(ptr) = record.record.any().downcast_ref::<DnsPointer>() {
2846 let mut new_event = None;
2847 match self.resolve_service_from_cache(ty_domain, ptr.alias()) {
2848 Ok(resolved_service) => {
2849 if resolved_service.is_valid() {
2850 debug!("Resolved service from cache: {}", ptr.alias());
2851 new_event =
2852 Some(ServiceEvent::ServiceResolved(Box::new(resolved_service)));
2853 } else {
2854 debug!(
2855 "query_cache_for_service: not valid: {} (host_empty={}, addrs_empty={})",
2856 ptr.alias(),
2857 resolved_service.get_hostname().is_empty(),
2858 resolved_service.get_addresses().is_empty(),
2859 );
2860 }
2861 }
2862 Err(err) => {
2863 debug!("Error while resolving service from cache: {}", err);
2864 continue;
2865 }
2866 }
2867
2868 match sender.send(ServiceEvent::ServiceFound(
2869 ty_domain.to_string(),
2870 ptr.alias().to_string(),
2871 )) {
2872 Ok(()) => debug!("sent service found {}", ptr.alias()),
2873 Err(e) => {
2874 debug!("failed to send service found: {}", e);
2875 continue;
2876 }
2877 }
2878
2879 if let Some(event) = new_event {
2880 resolved.insert(ptr.alias().to_string());
2881 match sender.send(event) {
2882 Ok(()) => debug!("sent service resolved: {}", ptr.alias()),
2883 Err(e) => debug!("failed to send service resolved: {}", e),
2884 }
2885 } else {
2886 unresolved.insert(ptr.alias().to_string());
2887 }
2888 }
2889 }
2890 }
2891
2892 for instance in resolved.drain() {
2893 self.pending_resolves.remove(&instance);
2894 self.resolved.insert(instance);
2895 }
2896
2897 for instance in unresolved.drain() {
2898 self.add_pending_resolve(instance);
2899 }
2900 }
2901
2902 fn query_cache_for_hostname(
2905 &mut self,
2906 hostname: &str,
2907 sender: Sender<HostnameResolutionEvent>,
2908 ) {
2909 let addresses_map = self.cache.get_addresses_for_host(hostname);
2910 for (name, addresses) in addresses_map {
2911 match sender.send(HostnameResolutionEvent::AddressesFound(name, addresses)) {
2912 Ok(()) => trace!("sent hostname addresses found"),
2913 Err(e) => debug!("failed to send hostname addresses found: {}", e),
2914 }
2915 }
2916 }
2917
2918 fn add_pending_resolve(&mut self, instance: String) {
2919 if !self.pending_resolves.contains(&instance) {
2920 let next_time = current_time_millis() + RESOLVE_RETRY_BASE_MILLIS;
2921 self.add_retransmission(next_time, Command::Resolve(instance.clone(), 1));
2922 self.pending_resolves.insert(instance);
2923 }
2924 }
2925
2926 fn resolve_service_from_cache(
2928 &self,
2929 ty_domain: &str,
2930 fullname: &str,
2931 ) -> Result<ResolvedService> {
2932 let now = current_time_millis();
2933 let mut resolved_service = ResolvedService {
2934 ty_domain: ty_domain.to_string(),
2935 sub_ty_domain: None,
2936 fullname: fullname.to_string(),
2937 host: String::new(),
2938 port: 0,
2939 addresses: HashSet::new(),
2940 txt_properties: TxtProperties::new(),
2941 };
2942
2943 if let Some(subtype) = self.cache.get_subtype(fullname) {
2945 trace!(
2946 "ty_domain: {} found subtype {} for instance: {}",
2947 ty_domain,
2948 subtype,
2949 fullname
2950 );
2951 if resolved_service.sub_ty_domain.is_none() {
2952 resolved_service.sub_ty_domain = Some(subtype.to_string());
2953 }
2954 }
2955
2956 if let Some(records) = self.cache.get_srv(fullname) {
2958 if let Some(answer) = records.iter().find(|r| !r.record.expires_soon(now)) {
2959 if let Some(dns_srv) = answer.record.any().downcast_ref::<DnsSrv>() {
2960 resolved_service.host = dns_srv.host().to_string();
2961 resolved_service.port = dns_srv.port();
2962 }
2963 }
2964 }
2965
2966 if let Some(records) = self.cache.get_txt(fullname) {
2968 if let Some(record) = records.iter().find(|r| !r.record.expires_soon(now)) {
2969 if let Some(dns_txt) = record.record.any().downcast_ref::<DnsTxt>() {
2970 resolved_service.txt_properties = dns_txt.text().into();
2971 }
2972 }
2973 }
2974
2975 if let Some(records) = self.cache.get_addr(&resolved_service.host) {
2977 for answer in records.iter() {
2978 if let Some(dns_a) = answer.record.any().downcast_ref::<DnsAddress>() {
2979 if dns_a.expires_soon(now) {
2980 trace!(
2981 "Addr expired or expires soon: {}",
2982 dns_a.address().to_ip_addr()
2983 );
2984 } else {
2985 let scoped = dns_a.address();
2986 if let ScopedIp::V4(v4) = &scoped {
2987 let existing = resolved_service
2990 .addresses
2991 .iter()
2992 .find(|a| a.to_ip_addr() == IpAddr::V4(*v4.addr()))
2993 .cloned();
2994 if let Some(mut existing) = existing {
2995 resolved_service.addresses.remove(&existing);
2996 if let ScopedIp::V4(existing_v4) = &mut existing {
2997 for id in v4.interface_ids() {
2998 existing_v4.add_interface_id(id.clone());
2999 }
3000 }
3001 resolved_service.addresses.insert(existing);
3002 } else {
3003 resolved_service.addresses.insert(scoped);
3004 }
3005 } else {
3006 resolved_service.addresses.insert(scoped);
3007 }
3008 }
3009 }
3010 }
3011 }
3012
3013 Ok(resolved_service)
3014 }
3015
3016 fn handle_poller_events(&mut self, events: &mio::Events) {
3017 for ev in events.iter() {
3018 trace!("event received with key {:?}", ev.token());
3019 if ev.token().0 == SIGNAL_SOCK_EVENT_KEY {
3020 self.signal_sock_drain();
3022
3023 if let Err(e) = self.poller.registry().reregister(
3024 &mut self.signal_sock,
3025 ev.token(),
3026 mio::Interest::READABLE,
3027 ) {
3028 debug!("failed to modify poller for signal socket: {}", e);
3029 }
3030 continue; }
3032
3033 while self.handle_read(ev.token().0) {}
3035
3036 if ev.token().0 == IPV4_SOCK_EVENT_KEY {
3038 if let Some(sock) = self.ipv4_sock.as_mut() {
3040 if let Err(e) =
3041 self.poller
3042 .registry()
3043 .reregister(sock, ev.token(), mio::Interest::READABLE)
3044 {
3045 debug!("modify poller for IPv4 socket: {}", e);
3046 }
3047 }
3048 } else if ev.token().0 == IPV6_SOCK_EVENT_KEY {
3049 if let Some(sock) = self.ipv6_sock.as_mut() {
3051 if let Err(e) =
3052 self.poller
3053 .registry()
3054 .reregister(sock, ev.token(), mio::Interest::READABLE)
3055 {
3056 debug!("modify poller for IPv6 socket: {}", e);
3057 }
3058 }
3059 }
3060 }
3061 }
3062
3063 fn handle_response(&mut self, mut msg: DnsIncoming, if_index: u32) {
3066 let now = current_time_millis();
3067
3068 let mut record_predicate = |record: &DnsRecordBox| {
3070 if !record.get_record().is_expired(now) {
3071 return true;
3072 }
3073
3074 debug!("record is expired, removing it from cache.");
3075 if self.cache.remove(record) {
3076 if let Some(dns_ptr) = record.any().downcast_ref::<DnsPointer>() {
3078 call_service_listener(
3079 &self.service_queriers,
3080 dns_ptr.get_name(),
3081 ServiceEvent::ServiceRemoved(
3082 dns_ptr.get_name().to_string(),
3083 dns_ptr.alias().to_string(),
3084 ),
3085 );
3086 }
3087 }
3088 false
3089 };
3090 msg.answers_mut().retain(&mut record_predicate);
3091 msg.authorities_mut().retain(&mut record_predicate);
3092 msg.additionals_mut().retain(&mut record_predicate);
3093
3094 self.conflict_handler(&msg, if_index);
3096
3097 let mut is_for_us = true; for answer in msg.answers() {
3104 if answer.get_type() == RRType::PTR {
3105 if self.service_queriers.contains_key(answer.get_name()) {
3106 is_for_us = true;
3107 break; } else {
3109 is_for_us = false;
3110 }
3111 } else if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA {
3112 let answer_lowercase = answer.get_name().to_lowercase();
3114 if self.hostname_resolvers.contains_key(&answer_lowercase) {
3115 is_for_us = true;
3116 break; }
3118 }
3119 }
3120
3121 if self.accept_unsolicited {
3123 is_for_us = true;
3124 }
3125
3126 struct InstanceChange {
3128 ty: RRType, name: String, }
3131
3132 let mut changes = Vec::new();
3140 let mut timers = Vec::new();
3141 let Some(my_intf) = self.my_intfs.get(&if_index) else {
3142 return;
3143 };
3144 for record in msg.all_records() {
3145 match self
3146 .cache
3147 .add_or_update(my_intf, record, &mut timers, is_for_us)
3148 {
3149 Some((dns_record, true)) => {
3150 timers.push(dns_record.record.get_record().get_expire_time());
3151 timers.push(dns_record.record.get_record().get_refresh_time());
3152
3153 let ty = dns_record.record.get_type();
3154 let name = dns_record.record.get_name();
3155
3156 debug!("cache: new record: {:?}", &dns_record.record);
3159
3160 if ty == RRType::PTR && dns_record.record.get_record().get_ttl() > 1 {
3162 if self.service_queriers.contains_key(name) {
3163 timers.push(dns_record.record.get_record().get_refresh_time());
3164 }
3165
3166 if let Some(dns_ptr) = dns_record.record.any().downcast_ref::<DnsPointer>()
3168 {
3169 debug!("calling listener with service found: {name}");
3170 call_service_listener(
3171 &self.service_queriers,
3172 name,
3173 ServiceEvent::ServiceFound(
3174 name.to_string(),
3175 dns_ptr.alias().to_string(),
3176 ),
3177 );
3178 changes.push(InstanceChange {
3179 ty,
3180 name: dns_ptr.alias().to_string(),
3181 });
3182 }
3183 } else {
3184 changes.push(InstanceChange {
3185 ty,
3186 name: name.to_string(),
3187 });
3188 }
3189 }
3190 Some((dns_record, false)) => {
3191 timers.push(dns_record.record.get_record().get_expire_time());
3192 timers.push(dns_record.record.get_record().get_refresh_time());
3193 }
3194 _ => {}
3195 }
3196 }
3197
3198 for t in timers {
3200 self.add_timer(t);
3201 }
3202
3203 for change in changes
3205 .iter()
3206 .filter(|change| change.ty == RRType::A || change.ty == RRType::AAAA)
3207 {
3208 let addr_map = self.cache.get_addresses_for_host(&change.name);
3209 for (name, addresses) in addr_map {
3210 call_hostname_resolution_listener(
3211 &self.hostname_resolvers,
3212 &change.name,
3213 HostnameResolutionEvent::AddressesFound(name, addresses),
3214 )
3215 }
3216 }
3217
3218 let mut updated_instances = HashSet::new();
3220 for update in changes {
3221 match update.ty {
3222 RRType::PTR | RRType::SRV | RRType::TXT => {
3223 updated_instances.insert(update.name);
3224 }
3225 RRType::A | RRType::AAAA => {
3226 let instances = self.cache.get_instances_on_host(&update.name);
3227 updated_instances.extend(instances);
3228 }
3229 _ => {}
3230 }
3231 }
3232
3233 self.resolve_updated_instances(&updated_instances);
3234 }
3235
3236 fn conflict_handler(&mut self, msg: &DnsIncoming, if_index: u32) {
3237 let Some(my_intf) = self.my_intfs.get(&if_index) else {
3238 debug!("handle_response: no intf found for index {if_index}");
3239 return;
3240 };
3241
3242 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
3243 return;
3244 };
3245
3246 for answer in msg.answers().iter() {
3247 let mut new_records = Vec::new();
3248
3249 let name = answer.get_name();
3250 let Some(probe) = dns_registry.probing.get_mut(name) else {
3251 continue;
3252 };
3253
3254 if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA {
3256 if let Some(answer_addr) = answer.any().downcast_ref::<DnsAddress>() {
3257 if answer_addr.interface_id.index != if_index {
3258 debug!(
3259 "conflict handler: answer addr {:?} not in the subnet of intf {}",
3260 answer_addr, my_intf.name
3261 );
3262 continue;
3263 }
3264 }
3265
3266 let any_match = probe.records.iter().any(|r| {
3269 r.get_type() == answer.get_type()
3270 && r.get_class() == answer.get_class()
3271 && r.rrdata_match(answer.as_ref())
3272 });
3273 if any_match {
3274 continue; }
3276 }
3277
3278 probe.records.retain(|record| {
3279 if record.get_type() == answer.get_type()
3280 && record.get_class() == answer.get_class()
3281 && !record.rrdata_match(answer.as_ref())
3282 {
3283 debug!(
3284 "found conflict name: '{name}' record: {}: {} PEER: {}",
3285 record.get_type(),
3286 record.rdata_print(),
3287 answer.rdata_print()
3288 );
3289
3290 let mut new_record = record.clone();
3293 let new_name = match record.get_type() {
3294 RRType::A => hostname_change(name),
3295 RRType::AAAA => hostname_change(name),
3296 _ => name_change(name),
3297 };
3298 new_record.get_record_mut().set_new_name(new_name);
3299 new_records.push(new_record);
3300 return false; }
3302
3303 true
3304 });
3305
3306 let create_time = current_time_millis() + fastrand::u64(0..250);
3313
3314 let waiting_services = probe.waiting_services.clone();
3315
3316 for record in new_records {
3317 if dns_registry.update_hostname(name, record.get_name(), create_time) {
3318 self.timers.push(Reverse(create_time));
3319 }
3320
3321 dns_registry.name_changes.insert(
3323 record.get_record().get_original_name().to_string(),
3324 record.get_name().to_string(),
3325 );
3326
3327 let new_probe = match dns_registry.probing.get_mut(record.get_name()) {
3328 Some(p) => p,
3329 None => {
3330 let new_probe = dns_registry
3331 .probing
3332 .entry(record.get_name().to_string())
3333 .or_insert_with(|| {
3334 debug!("conflict handler: new probe of {}", record.get_name());
3335 Probe::new(create_time)
3336 });
3337 self.timers.push(Reverse(new_probe.next_send));
3338 new_probe
3339 }
3340 };
3341
3342 debug!(
3343 "insert record with new name '{}' {} into probe",
3344 record.get_name(),
3345 record.get_type()
3346 );
3347 new_probe.insert_record(record);
3348
3349 new_probe.waiting_services.extend(waiting_services.clone());
3350 }
3351 }
3352 }
3353
3354 fn resolve_updated_instances(&mut self, updated_instances: &HashSet<String>) {
3361 if updated_instances.is_empty() {
3362 return;
3363 }
3364
3365 let mut resolved: HashSet<String> = HashSet::new();
3366 let mut unresolved: HashSet<String> = HashSet::new();
3367 let mut removed_instances = HashMap::new();
3368
3369 let now = current_time_millis();
3370
3371 for (ty_domain, records) in self.cache.all_ptr().iter() {
3372 if !self.service_queriers.contains_key(ty_domain) {
3373 continue;
3375 }
3376
3377 for ptr in records.iter().filter(|r| !r.record.expires_soon(now)) {
3378 let Some(dns_ptr) = ptr.record.any().downcast_ref::<DnsPointer>() else {
3379 continue;
3380 };
3381
3382 let instance = dns_ptr.alias();
3383 if !updated_instances.contains(instance) {
3384 continue;
3385 }
3386
3387 let Ok(resolved_service) = self.resolve_service_from_cache(ty_domain, instance)
3388 else {
3389 continue;
3390 };
3391
3392 debug!("resolve_updated_instances: from cache: {instance}");
3393 if resolved_service.is_valid() {
3394 debug!(
3395 "resolved '{}' -> host '{}' port {} addrs {:?}",
3396 instance,
3397 resolved_service.host,
3398 resolved_service.port,
3399 resolved_service.addresses,
3400 );
3401 resolved.insert(instance.to_string());
3402 let event = ServiceEvent::ServiceResolved(Box::new(resolved_service));
3403 call_service_listener(&self.service_queriers, ty_domain, event);
3404 } else {
3405 debug!(
3406 "resolve_updated_instances: not valid: {instance} (host_empty={}, addrs_empty={})",
3407 resolved_service.get_hostname().is_empty(),
3408 resolved_service.get_addresses().is_empty(),
3409 );
3410 if self.resolved.remove(dns_ptr.alias()) {
3411 removed_instances
3412 .entry(ty_domain.to_string())
3413 .or_insert_with(HashSet::new)
3414 .insert(instance.to_string());
3415 }
3416 unresolved.insert(instance.to_string());
3417 }
3418 }
3419 }
3420
3421 for instance in resolved.drain() {
3422 self.pending_resolves.remove(&instance);
3423 self.resolved.insert(instance);
3424 }
3425
3426 for instance in unresolved.drain() {
3427 self.add_pending_resolve(instance);
3428 }
3429
3430 if !removed_instances.is_empty() {
3431 debug!(
3432 "resolve_updated_instances: removed {}",
3433 &removed_instances.len()
3434 );
3435 self.notify_service_removal(removed_instances);
3436 }
3437 }
3438
3439 fn handle_query(&mut self, msg: DnsIncoming, if_index: u32, querier_addr: SocketAddr) {
3441 let querier_ip = querier_addr.ip();
3442 let is_ipv4 = querier_ip.is_ipv4();
3443
3444 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
3445 let mut delayed = false;
3446
3447 const META_QUERY: &str = "_services._dns-sd._udp.local.";
3450
3451 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
3452 debug!("missing dns registry for intf {}", if_index);
3453 return;
3454 };
3455
3456 let Some(intf) = self.my_intfs.get(&if_index) else {
3457 debug!("handle_query: no intf found for index {if_index}");
3458 return;
3459 };
3460
3461 for question in msg.questions().iter() {
3462 let qtype = question.entry_type();
3463 let q_name = question.entry_name();
3464
3465 if qtype == RRType::PTR {
3466 if querier_addr.port() == MDNS_PORT && msg.num_authorities() == 0 {
3470 delayed = true;
3471 }
3472 for service in self.my_services.values() {
3473 if service.get_status(if_index) != ServiceStatus::Announced {
3474 continue;
3475 }
3476
3477 if service.matches_type_or_subtype(q_name) {
3478 out.add_answer_with_additionals(&msg, service, intf, dns_registry, is_ipv4);
3479 } else if q_name == META_QUERY {
3480 let ttl = service.get_other_ttl();
3481 let alias = service.get_type().to_string();
3482 let ptr = DnsPointer::new(q_name, RRType::PTR, CLASS_IN, ttl, alias);
3483 if !out.add_answer(&msg, ptr) {
3484 trace!("answer was not added for meta-query {:?}", &question);
3485 }
3486 }
3487 }
3488 } else {
3489 if qtype == RRType::ANY && msg.num_authorities() > 0 {
3491 if let Some(probe) = dns_registry.probing.get_mut(q_name) {
3492 probe.tiebreaking(&msg, q_name);
3493 }
3494 }
3495
3496 if matches!(
3497 qtype,
3498 RRType::A | RRType::AAAA | RRType::ANY | RRType::SVCB | RRType::HTTPS
3499 ) {
3500 answer_hostname_question(
3501 &self.my_services,
3502 intf,
3503 question,
3504 dns_registry,
3505 &mut out,
3506 &msg,
3507 );
3508 }
3509
3510 let query_name = q_name.to_lowercase();
3511 let service_opt = self
3512 .my_services
3513 .iter()
3514 .find(|(k, _v)| dns_registry.resolve_name(k.as_str()) == query_name)
3515 .map(|(_, v)| v);
3516
3517 let Some(service) = service_opt else {
3518 continue;
3519 };
3520
3521 if service.get_status(if_index) != ServiceStatus::Announced {
3522 continue;
3523 }
3524
3525 let intf_addrs = if is_ipv4 {
3526 service.get_addrs_on_my_intf_v4(intf)
3527 } else {
3528 service.get_addrs_on_my_intf_v6(intf)
3529 };
3530 if intf_addrs.is_empty() {
3531 debug!(
3532 "Cannot find valid addrs for TYPE_SRV response on intf {:?}",
3533 &intf
3534 );
3535 continue;
3536 }
3537
3538 add_answer_of_service(
3539 &mut out,
3540 &msg,
3541 question.entry_name(),
3542 service,
3543 qtype,
3544 intf_addrs,
3545 );
3546 }
3547 }
3548
3549 if delayed && out.answers_count() > 0 {
3551 out.set_id(msg.id());
3552 self.increase_counter(Counter::KnownAnswerSuppression, out.known_answer_count());
3553 let delay =
3554 fastrand::u64(SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS);
3555 let next_time = current_time_millis() + delay;
3556 self.delayed_responses.push(DelayedResponse {
3557 next_time,
3558 out,
3559 if_index,
3560 is_ipv4,
3561 });
3562 self.add_timer(next_time);
3563 return;
3564 }
3565
3566 if out.answers_count() > 0 {
3567 self.send_response(&mut out, &msg, if_index, querier_addr);
3568 }
3569
3570 self.increase_counter(Counter::KnownAnswerSuppression, out.known_answer_count());
3571 }
3572
3573 fn send_response(
3574 &mut self,
3575 out: &mut DnsOutgoing,
3576 msg: &DnsIncoming,
3577 if_index: u32,
3578 querier_addr: SocketAddr,
3579 ) {
3580 let querier_ip = querier_addr.ip();
3581 let is_ipv4 = querier_ip.is_ipv4();
3582 let sock_opt = if is_ipv4 {
3583 &self.ipv4_sock
3584 } else {
3585 &self.ipv6_sock
3586 };
3587 let Some(sock) = sock_opt.as_ref() else {
3588 debug!("send_response: socket not available for intf {if_index}");
3589 return;
3590 };
3591 let Some(intf) = self.my_intfs.get(&if_index) else {
3592 debug!("send_response: no intf found for index {if_index}");
3593 return;
3594 };
3595
3596 out.set_id(msg.id());
3597
3598 let matched_source = intf
3601 .addrs
3602 .iter()
3603 .find(|if_addr| valid_ip_on_intf(&querier_ip, if_addr));
3604
3605 let unicast_dest = if querier_addr.port() != MDNS_PORT {
3614 Some(querier_addr)
3615 } else {
3616 None
3617 };
3618
3619 if unicast_dest.is_some() {
3620 for q in msg.questions() {
3621 out.add_question(q.entry_name(), q.entry_type());
3622 }
3623 out.update_records_for_legacy_unicast();
3624 out.set_multicast(false);
3625 } else if msg.num_authorities() == 0 {
3626 if let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) {
3633 dns_registry.apply_multicast_rate_limit(out, current_time_millis(), is_ipv4);
3634 }
3635 }
3636
3637 if out.answers_count() > 0 {
3638 debug!("sending response on intf {}", &intf.name);
3639 if let Err(InternalError::IntfAddrInvalid(intf_addr)) = send_dns_outgoing(
3640 out,
3641 intf,
3642 &sock.pktinfo,
3643 self.port,
3644 matched_source,
3645 unicast_dest,
3646 ) {
3647 let invalid_intf_addr = HashSet::from([intf_addr]);
3648 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3649 }
3650
3651 let if_name = intf.name.clone();
3652
3653 self.increase_counter(Counter::Respond, 1);
3654 self.notify_monitors(DaemonEvent::Respond(if_name));
3655 }
3656 }
3657
3658 fn send_delayed_response(&mut self, resp: DelayedResponse) {
3667 let DelayedResponse {
3668 mut out,
3669 if_index,
3670 is_ipv4,
3671 ..
3672 } = resp;
3673
3674 let sock_opt = if is_ipv4 {
3675 &self.ipv4_sock
3676 } else {
3677 &self.ipv6_sock
3678 };
3679 let Some(sock) = sock_opt.as_ref() else {
3680 debug!("send_delayed_response: socket not available for intf {if_index}");
3681 return;
3682 };
3683
3684 if let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) {
3685 dns_registry.apply_multicast_rate_limit(&mut out, current_time_millis(), is_ipv4);
3686 }
3687 if out.answers_count() == 0 {
3688 return;
3689 }
3690
3691 let Some(intf) = self.my_intfs.get(&if_index) else {
3692 debug!("send_delayed_response: no intf found for index {if_index}");
3693 return;
3694 };
3695
3696 let if_name = intf.name.clone();
3697 debug!("sending delayed response on intf {}", &if_name);
3698 let send_result = send_dns_outgoing(&out, intf, &sock.pktinfo, self.port, None, None);
3699
3700 if let Err(InternalError::IntfAddrInvalid(intf_addr)) = send_result {
3701 let invalid_intf_addr = HashSet::from([intf_addr]);
3702 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3703 }
3704
3705 self.increase_counter(Counter::Respond, 1);
3706 self.notify_monitors(DaemonEvent::Respond(if_name));
3707 }
3708
3709 fn increase_counter(&mut self, counter: Counter, count: i64) {
3711 let key = counter.to_string();
3712 match self.counters.get_mut(&key) {
3713 Some(v) => *v += count,
3714 None => {
3715 self.counters.insert(key, count);
3716 }
3717 }
3718 }
3719
3720 fn set_counter(&mut self, counter: Counter, count: i64) {
3722 let key = counter.to_string();
3723 self.counters.insert(key, count);
3724 }
3725
3726 fn signal_sock_drain(&self) {
3727 let mut signal_buf = [0; 1024];
3728
3729 while let Ok(sz) = self.signal_sock.recv(&mut signal_buf) {
3731 trace!(
3732 "signal socket recvd: {}",
3733 String::from_utf8_lossy(&signal_buf[0..sz])
3734 );
3735 }
3736 }
3737
3738 fn add_retransmission(&mut self, next_time: u64, command: Command) {
3739 self.retransmissions.push(ReRun { next_time, command });
3740 self.add_timer(next_time);
3741 }
3742
3743 fn notify_service_removal(&self, expired: HashMap<String, HashSet<String>>) {
3746 for (ty_domain, sender) in self.service_queriers.iter() {
3747 if let Some(instances) = expired.get(ty_domain) {
3748 for instance_name in instances {
3749 let event = ServiceEvent::ServiceRemoved(
3750 ty_domain.to_string(),
3751 instance_name.to_string(),
3752 );
3753 match sender.send(event) {
3754 Ok(()) => debug!("notify_service_removal: sent ServiceRemoved to listener of {ty_domain}: {instance_name}"),
3755 Err(e) => debug!("Failed to send event: {}", e),
3756 }
3757 }
3758 }
3759 }
3760 }
3761
3762 fn exec_command(&mut self, command: Command, repeating: bool) {
3766 trace!("exec_command: {:?} repeating: {}", &command, repeating);
3767 match command {
3768 Command::Browse(ty, next_delay, cache_only, listener) => {
3769 self.exec_command_browse(repeating, ty, next_delay, cache_only, listener);
3770 }
3771
3772 Command::ResolveHostname(hostname, next_delay, listener, timeout) => {
3773 self.exec_command_resolve_hostname(
3774 repeating, hostname, next_delay, listener, timeout,
3775 );
3776 }
3777
3778 Command::Register(service_info) => {
3779 self.register_service(*service_info);
3780 self.increase_counter(Counter::Register, 1);
3781 }
3782
3783 Command::RegisterResend(fullname, intf) => {
3784 trace!("register-resend service: {fullname} on {}", &intf);
3785 if let Err(InternalError::IntfAddrInvalid(intf_addr)) =
3786 self.exec_command_register_resend(fullname, intf)
3787 {
3788 let invalid_intf_addr = HashSet::from([intf_addr]);
3789 let _ = self.send_cmd_to_self(Command::InvalidIntfAddrs(invalid_intf_addr));
3790 }
3791 }
3792
3793 Command::Unregister(fullname, resp_s) => {
3794 trace!("unregister service {} repeat {}", &fullname, &repeating);
3795 self.exec_command_unregister(repeating, fullname, resp_s);
3796 }
3797
3798 Command::UnregisterResend(packet, if_index, is_ipv4) => {
3799 self.exec_command_unregister_resend(packet, if_index, is_ipv4);
3800 }
3801
3802 Command::StopBrowse(ty_domain) => self.exec_command_stop_browse(ty_domain),
3803
3804 Command::StopResolveHostname(hostname) => {
3805 self.exec_command_stop_resolve_hostname(hostname.to_lowercase())
3806 }
3807
3808 Command::Resolve(instance, try_count) => self.exec_command_resolve(instance, try_count),
3809
3810 Command::GetMetrics(resp_s) => self.exec_command_get_metrics(resp_s),
3811
3812 Command::GetStatus(resp_s) => match resp_s.send(self.status.clone()) {
3813 Ok(()) => trace!("Sent status to the client"),
3814 Err(e) => debug!("Failed to send status: {}", e),
3815 },
3816
3817 Command::Monitor(resp_s) => {
3818 self.monitors.push(resp_s);
3819 }
3820
3821 Command::SetOption(daemon_opt) => {
3822 self.process_set_option(daemon_opt);
3823 }
3824
3825 Command::GetOption(resp_s) => {
3826 let val = DaemonOptionVal {
3827 _service_name_len_max: self.service_name_len_max,
3828 ip_check_interval: self.ip_check_interval,
3829 };
3830 if let Err(e) = resp_s.send(val) {
3831 debug!("Failed to send options: {}", e);
3832 }
3833 }
3834
3835 Command::Verify(instance_fullname, timeout) => {
3836 self.exec_command_verify(instance_fullname, timeout, repeating);
3837 }
3838
3839 Command::InvalidIntfAddrs(invalid_intf_addrs) => {
3840 for intf_addr in invalid_intf_addrs {
3841 self.del_interface_addr(&intf_addr);
3842 }
3843
3844 self.check_ip_changes();
3845 }
3846
3847 _ => {
3848 debug!("unexpected command: {:?}", &command);
3849 }
3850 }
3851 }
3852
3853 fn exec_command_get_metrics(&mut self, resp_s: Sender<HashMap<String, i64>>) {
3854 self.set_counter(Counter::CachedPTR, self.cache.ptr_count() as i64);
3855 self.set_counter(Counter::CachedSRV, self.cache.srv_count() as i64);
3856 self.set_counter(Counter::CachedAddr, self.cache.addr_count() as i64);
3857 self.set_counter(Counter::CachedTxt, self.cache.txt_count() as i64);
3858 self.set_counter(Counter::CachedNSec, self.cache.nsec_count() as i64);
3859 self.set_counter(Counter::CachedSubtype, self.cache.subtype_count() as i64);
3860 self.set_counter(Counter::Timer, self.timers.len() as i64);
3861
3862 let dns_registry_probe_count: usize = self
3863 .dns_registry_map
3864 .values()
3865 .map(|r| r.probing.len())
3866 .sum();
3867 self.set_counter(Counter::DnsRegistryProbe, dns_registry_probe_count as i64);
3868
3869 let dns_registry_active_count: usize = self
3870 .dns_registry_map
3871 .values()
3872 .map(|r| r.active.values().map(|a| a.len()).sum::<usize>())
3873 .sum();
3874 self.set_counter(Counter::DnsRegistryActive, dns_registry_active_count as i64);
3875
3876 let dns_registry_timer_count: usize = self
3877 .dns_registry_map
3878 .values()
3879 .map(|r| r.new_timers.len())
3880 .sum();
3881 self.set_counter(Counter::DnsRegistryTimer, dns_registry_timer_count as i64);
3882
3883 let dns_registry_name_change_count: usize = self
3884 .dns_registry_map
3885 .values()
3886 .map(|r| r.name_changes.len())
3887 .sum();
3888 self.set_counter(
3889 Counter::DnsRegistryNameChange,
3890 dns_registry_name_change_count as i64,
3891 );
3892
3893 if let Err(e) = resp_s.send(self.counters.clone()) {
3895 debug!("Failed to send metrics: {}", e);
3896 }
3897 }
3898
3899 fn exec_command_browse(
3900 &mut self,
3901 repeating: bool,
3902 ty: String,
3903 next_delay: u32,
3904 cache_only: bool,
3905 listener: Sender<ServiceEvent>,
3906 ) {
3907 let pretty_addrs: Vec<String> = self
3908 .my_intfs
3909 .iter()
3910 .map(|(if_index, itf)| format!("{} ({if_index})", itf.name))
3911 .collect();
3912
3913 if let Err(e) = listener.send(ServiceEvent::SearchStarted(format!(
3914 "{ty} on {} interfaces [{}]",
3915 pretty_addrs.len(),
3916 pretty_addrs.join(", ")
3917 ))) {
3918 debug!(
3919 "Failed to send SearchStarted({})(repeating:{}): {}",
3920 &ty, repeating, e
3921 );
3922 return;
3923 }
3924
3925 let now = current_time_millis();
3926 if !repeating {
3927 self.service_queriers.insert(ty.clone(), listener.clone());
3931
3932 self.query_cache_for_service(&ty, &listener, now);
3934 }
3935
3936 if cache_only {
3937 match listener.send(ServiceEvent::SearchStopped(ty.clone())) {
3939 Ok(()) => debug!("SearchStopped sent for {}", &ty),
3940 Err(e) => debug!("Failed to send SearchStopped: {}", e),
3941 }
3942 return;
3943 }
3944
3945 if !repeating {
3946 let jitter =
3948 fastrand::u64(INITIAL_QUERY_DELAY_MIN_MILLIS..INITIAL_QUERY_DELAY_MAX_MILLIS);
3949 self.add_retransmission(now + jitter, Command::Browse(ty, 1, cache_only, listener));
3950 return;
3951 }
3952
3953 self.send_query(&ty, RRType::PTR);
3954
3955 self.query_unresolved_instances(&ty);
3956
3957 self.increase_counter(Counter::Browse, 1);
3958
3959 let next_time = now + (next_delay * 1000) as u64;
3960 let max_delay = 60 * 60;
3961 let delay = cmp::min(next_delay * 2, max_delay);
3962 self.add_retransmission(next_time, Command::Browse(ty, delay, cache_only, listener));
3963 }
3964
3965 fn exec_command_resolve_hostname(
3966 &mut self,
3967 repeating: bool,
3968 hostname: String,
3969 next_delay: u32,
3970 listener: Sender<HostnameResolutionEvent>,
3971 timeout: Option<u64>,
3972 ) {
3973 let addr_list: Vec<_> = self.my_intfs.iter().collect();
3974 if let Err(e) = listener.send(HostnameResolutionEvent::SearchStarted(format!(
3975 "{} on addrs {:?}",
3976 &hostname, &addr_list
3977 ))) {
3978 debug!(
3979 "Failed to send ResolveStarted({})(repeating:{}): {}",
3980 &hostname, repeating, e
3981 );
3982 return;
3983 }
3984 let now = current_time_millis();
3985 if !repeating {
3986 self.add_hostname_resolver(hostname.to_owned(), listener.clone(), timeout);
3987 self.query_cache_for_hostname(&hostname, listener.clone());
3989
3990 let jitter =
3992 fastrand::u64(INITIAL_QUERY_DELAY_MIN_MILLIS..INITIAL_QUERY_DELAY_MAX_MILLIS);
3993 self.add_retransmission(
3994 now + jitter,
3995 Command::ResolveHostname(hostname, 1, listener, None),
3996 );
3997 return;
3998 }
3999
4000 self.send_query_vec(&[(&hostname, RRType::A), (&hostname, RRType::AAAA)]);
4001 self.increase_counter(Counter::ResolveHostname, 1);
4002
4003 let next_time = now + u64::from(next_delay) * 1000;
4004 let max_delay = 60 * 60;
4005 let delay = cmp::min(next_delay * 2, max_delay);
4006
4007 if self
4009 .hostname_resolvers
4010 .get(&hostname)
4011 .and_then(|(_sender, timeout)| *timeout)
4012 .map(|timeout| next_time < timeout)
4013 .unwrap_or(true)
4014 {
4015 self.add_retransmission(
4016 next_time,
4017 Command::ResolveHostname(hostname, delay, listener, None),
4018 );
4019 }
4020 }
4021
4022 fn exec_command_resolve(&mut self, instance: String, try_count: u16) {
4023 let pending_query = self.query_unresolved(&instance);
4024 if pending_query && try_count < RESOLVE_MAX_TRY {
4025 let next_delay = RESOLVE_RETRY_BASE_MILLIS << try_count;
4030 let next_time = current_time_millis() + next_delay;
4031 self.add_retransmission(next_time, Command::Resolve(instance, try_count + 1));
4032 } else {
4033 self.pending_resolves.remove(&instance);
4035 }
4036 }
4037
4038 fn exec_command_unregister(
4039 &mut self,
4040 repeating: bool,
4041 fullname: String,
4042 resp_s: Sender<UnregisterStatus>,
4043 ) {
4044 let response = match self.my_services.remove_entry(&fullname) {
4045 None => {
4046 debug!("unregister: cannot find such service {}", &fullname);
4047 UnregisterStatus::NotFound
4048 }
4049 Some((_k, info)) => {
4050 let mut timers = Vec::new();
4051
4052 for (if_index, intf) in self.my_intfs.iter() {
4053 if let Some(sock) = self.ipv4_sock.as_ref() {
4054 let packet = self.unregister_service(&info, intf, &sock.pktinfo);
4055 if !repeating && !packet.is_empty() {
4057 let next_time = current_time_millis() + 120;
4058 self.retransmissions.push(ReRun {
4059 next_time,
4060 command: Command::UnregisterResend(packet, *if_index, true),
4061 });
4062 timers.push(next_time);
4063 }
4064 }
4065
4066 if let Some(sock) = self.ipv6_sock.as_ref() {
4068 let packet = self.unregister_service(&info, intf, &sock.pktinfo);
4069 if !repeating && !packet.is_empty() {
4070 let next_time = current_time_millis() + 120;
4071 self.retransmissions.push(ReRun {
4072 next_time,
4073 command: Command::UnregisterResend(packet, *if_index, false),
4074 });
4075 timers.push(next_time);
4076 }
4077 }
4078 }
4079
4080 for t in timers {
4081 self.add_timer(t);
4082 }
4083
4084 self.increase_counter(Counter::Unregister, 1);
4085 UnregisterStatus::OK
4086 }
4087 };
4088 if let Err(e) = resp_s.send(response) {
4089 debug!("unregister: failed to send response: {}", e);
4090 }
4091 }
4092
4093 fn exec_command_unregister_resend(&mut self, packet: Vec<u8>, if_index: u32, is_ipv4: bool) {
4094 let Some(intf) = self.my_intfs.get(&if_index) else {
4095 return;
4096 };
4097 let sock_opt = if is_ipv4 {
4098 &self.ipv4_sock
4099 } else {
4100 &self.ipv6_sock
4101 };
4102 let Some(sock) = sock_opt else {
4103 return;
4104 };
4105
4106 let if_addr = if is_ipv4 {
4107 match intf.next_ifaddr_v4() {
4108 Some(addr) => addr,
4109 None => return,
4110 }
4111 } else {
4112 match intf.next_ifaddr_v6() {
4113 Some(addr) => addr,
4114 None => return,
4115 }
4116 };
4117
4118 debug!("UnregisterResend from {:?}", if_addr);
4119 multicast_on_intf(
4120 &packet[..],
4121 &intf.name,
4122 intf.index,
4123 if_addr,
4124 &sock.pktinfo,
4125 self.port,
4126 );
4127
4128 self.increase_counter(Counter::UnregisterResend, 1);
4129 }
4130
4131 fn exec_command_stop_browse(&mut self, ty_domain: String) {
4132 match self.service_queriers.remove_entry(&ty_domain) {
4133 None => debug!("StopBrowse: cannot find querier for {}", &ty_domain),
4134 Some((ty, sender)) => {
4135 trace!("StopBrowse: removed queryer for {}", &ty);
4137 let mut i = 0;
4138 while i < self.retransmissions.len() {
4139 if let Command::Browse(t, _, _, _) = &self.retransmissions[i].command {
4140 if t == &ty {
4141 self.retransmissions.remove(i);
4142 trace!("StopBrowse: removed retransmission for {}", &ty);
4143 continue;
4144 }
4145 }
4146 i += 1;
4147 }
4148
4149 self.cache.remove_service_type(&ty_domain);
4151
4152 match sender.send(ServiceEvent::SearchStopped(ty_domain)) {
4154 Ok(()) => trace!("Sent SearchStopped to the listener"),
4155 Err(e) => debug!("Failed to send SearchStopped: {}", e),
4156 }
4157 }
4158 }
4159 }
4160
4161 fn exec_command_stop_resolve_hostname(&mut self, hostname: String) {
4162 if let Some((host, (sender, _timeout))) = self.hostname_resolvers.remove_entry(&hostname) {
4163 trace!("StopResolve: removed queryer for {}", &host);
4165 let mut i = 0;
4166 while i < self.retransmissions.len() {
4167 if let Command::Resolve(t, _) = &self.retransmissions[i].command {
4168 if t == &host {
4169 self.retransmissions.remove(i);
4170 trace!("StopResolve: removed retransmission for {}", &host);
4171 continue;
4172 }
4173 }
4174 i += 1;
4175 }
4176
4177 match sender.send(HostnameResolutionEvent::SearchStopped(hostname)) {
4179 Ok(()) => trace!("Sent SearchStopped to the listener"),
4180 Err(e) => debug!("Failed to send SearchStopped: {}", e),
4181 }
4182 }
4183 }
4184
4185 fn exec_command_register_resend(&mut self, fullname: String, if_index: u32) -> MyResult<()> {
4186 let Some(info) = self.my_services.get_mut(&fullname) else {
4187 trace!("announce: cannot find such service {}", &fullname);
4188 return Ok(());
4189 };
4190
4191 let Some(dns_registry) = self.dns_registry_map.get_mut(&if_index) else {
4192 return Ok(());
4193 };
4194
4195 let Some(intf) = self.my_intfs.get(&if_index) else {
4196 return Ok(());
4197 };
4198
4199 let announced_v4 = if let Some(sock) = self.ipv4_sock.as_ref() {
4200 announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port)?
4201 } else {
4202 false
4203 };
4204 let announced_v6 = if let Some(sock) = self.ipv6_sock.as_ref() {
4205 announce_service_on_intf(dns_registry, info, intf, &sock.pktinfo, self.port)?
4206 } else {
4207 false
4208 };
4209
4210 if announced_v4 || announced_v6 {
4211 let hostname = dns_registry.resolve_name(info.get_hostname());
4212 let service_name = dns_registry.resolve_name(&fullname).to_string();
4213
4214 debug!("resend: announce service {service_name} on {}", intf.name);
4215
4216 notify_monitors(
4217 &mut self.monitors,
4218 DaemonEvent::Announce(service_name, format!("{}:{}", hostname, &intf.name)),
4219 );
4220 info.set_status(if_index, ServiceStatus::Announced);
4221 } else {
4222 debug!("register-resend should not fail");
4223 }
4224
4225 self.increase_counter(Counter::RegisterResend, 1);
4226 Ok(())
4227 }
4228
4229 fn exec_command_verify(&mut self, instance: String, timeout: Duration, repeating: bool) {
4230 let now = current_time_millis();
4240 let expire_at = if repeating {
4241 None
4242 } else {
4243 Some(now + timeout.as_millis() as u64)
4244 };
4245
4246 let record_vec = self.cache.service_verify_queries(&instance, expire_at);
4248
4249 if !record_vec.is_empty() {
4250 let query_vec: Vec<(&str, RRType)> = record_vec
4251 .iter()
4252 .map(|(record, rr_type)| (record.as_str(), *rr_type))
4253 .collect();
4254 self.send_query_vec(&query_vec);
4255
4256 if let Some(new_expire) = expire_at {
4257 self.add_timer(new_expire); self.add_retransmission(now + 1000, Command::Verify(instance, timeout));
4261 }
4262 }
4263 }
4264
4265 fn refresh_active_services(&mut self) {
4267 let mut query_ptr_count = 0;
4268 let mut query_srv_count = 0;
4269 let mut new_timers = HashSet::new();
4270 let mut query_addr_count = 0;
4271
4272 for (ty_domain, _sender) in self.service_queriers.iter() {
4273 let refreshed_timers = self.cache.refresh_due_ptr(ty_domain);
4274 if !refreshed_timers.is_empty() {
4275 trace!("sending refresh query for PTR: {}", ty_domain);
4276 self.send_query(ty_domain, RRType::PTR);
4277 query_ptr_count += 1;
4278 new_timers.extend(refreshed_timers);
4279 }
4280
4281 let (instances, timers) = self.cache.refresh_due_srv_txt(ty_domain);
4282 for (instance, types) in instances {
4283 trace!("sending refresh query for: {}", &instance);
4284 let query_vec = types
4285 .into_iter()
4286 .map(|ty| (instance.as_str(), ty))
4287 .collect::<Vec<_>>();
4288 self.send_query_vec(&query_vec);
4289 query_srv_count += 1;
4290 }
4291 new_timers.extend(timers);
4292 let (hostnames, timers) = self.cache.refresh_due_hosts(ty_domain);
4293 for hostname in hostnames.iter() {
4294 trace!("sending refresh queries for A and AAAA: {}", hostname);
4295 self.send_query_vec(&[(hostname, RRType::A), (hostname, RRType::AAAA)]);
4296 query_addr_count += 2;
4297 }
4298 new_timers.extend(timers);
4299 }
4300
4301 for timer in new_timers {
4302 self.add_timer(timer);
4303 }
4304
4305 self.increase_counter(Counter::CacheRefreshPTR, query_ptr_count);
4306 self.increase_counter(Counter::CacheRefreshSrvTxt, query_srv_count);
4307 self.increase_counter(Counter::CacheRefreshAddr, query_addr_count);
4308 }
4309}
4310
4311fn add_answer_of_service(
4313 out: &mut DnsOutgoing,
4314 msg: &DnsIncoming,
4315 entry_name: &str,
4316 service: &ServiceInfo,
4317 qtype: RRType,
4318 intf_addrs: Vec<IpAddr>,
4319) {
4320 if qtype == RRType::SRV || qtype == RRType::ANY {
4321 out.add_answer(
4322 msg,
4323 DnsSrv::new(
4324 entry_name,
4325 CLASS_IN | CLASS_CACHE_FLUSH,
4326 service.get_host_ttl(),
4327 service.get_priority(),
4328 service.get_weight(),
4329 service.get_port(),
4330 service.get_hostname().to_string(),
4331 ),
4332 );
4333 }
4334
4335 if qtype == RRType::TXT || qtype == RRType::ANY {
4336 out.add_answer(
4337 msg,
4338 DnsTxt::new(
4339 entry_name,
4340 CLASS_IN | CLASS_CACHE_FLUSH,
4341 service.get_other_ttl(),
4342 service.generate_txt(),
4343 ),
4344 );
4345 }
4346
4347 if qtype == RRType::SRV {
4348 for address in intf_addrs {
4349 out.add_additional_answer(DnsAddress::new(
4350 service.get_hostname(),
4351 ip_address_rr_type(&address),
4352 CLASS_IN | CLASS_CACHE_FLUSH,
4353 service.get_host_ttl(),
4354 address,
4355 InterfaceId::default(),
4356 ));
4357 }
4358 }
4359}
4360
4361fn answer_hostname_question(
4368 services: &HashMap<String, ServiceInfo>,
4369 intf: &MyIntf,
4370 question: &DnsQuestion,
4371 dns_registry: &DnsRegistry,
4372 out: &mut DnsOutgoing,
4373 msg: &DnsIncoming,
4374) {
4375 let if_index = intf.index;
4376 let qtype = question.entry_type();
4377 let mut hostname = None;
4378 let mut host_ttl = u32::MAX;
4379 let mut has_ipv4 = false;
4380 let mut has_ipv6 = false;
4381 for service in services.values() {
4382 if service.get_status(if_index) != ServiceStatus::Announced {
4383 continue;
4384 }
4385
4386 let service_hostname = dns_registry.resolve_name(service.get_hostname());
4387
4388 if service_hostname.to_lowercase() == question.entry_name().to_lowercase() {
4389 let ipv4 = service.get_addrs_on_my_intf_v4(intf);
4390 let ipv6 = service.get_addrs_on_my_intf_v6(intf);
4391 if ipv4.is_empty() && ipv6.is_empty() {
4392 continue;
4393 }
4394 hostname = Some(service_hostname);
4395 host_ttl = host_ttl.min(service.get_host_ttl());
4396 has_ipv4 |= !ipv4.is_empty();
4397 has_ipv6 |= !ipv6.is_empty();
4398 let mut intf_addrs: Vec<IpAddr> = Vec::new();
4405 if qtype == RRType::A || qtype == RRType::ANY {
4406 intf_addrs.extend(ipv4);
4407 }
4408 if qtype == RRType::AAAA || qtype == RRType::ANY {
4409 intf_addrs.extend(ipv6);
4410 }
4411 for address in intf_addrs {
4412 out.add_answer(
4413 msg,
4414 DnsAddress::new(
4415 service_hostname,
4416 ip_address_rr_type(&address),
4417 CLASS_IN | CLASS_CACHE_FLUSH,
4418 service.get_host_ttl(),
4419 address,
4420 intf.into(),
4421 ),
4422 );
4423 }
4424 }
4425 }
4426 let missing = match qtype {
4427 RRType::A => !has_ipv4,
4428 RRType::AAAA => !has_ipv6,
4429 RRType::SVCB | RRType::HTTPS => true,
4430 _ => false,
4431 };
4432 if let Some(hostname) = hostname.filter(|_| missing) {
4433 let bitmap = if has_ipv6 {
4438 vec![if has_ipv4 { 0x40 } else { 0 }, 0, 0, 0x08]
4439 } else {
4440 vec![0x40]
4441 };
4442 out.add_answer(
4443 msg,
4444 DnsNSec::new(
4445 hostname,
4446 CLASS_IN | CLASS_CACHE_FLUSH,
4447 host_ttl,
4448 hostname.to_string(),
4449 bitmap,
4450 ),
4451 );
4452 }
4453}
4454
4455#[derive(Clone, Debug)]
4458#[non_exhaustive]
4459pub enum ServiceEvent {
4460 SearchStarted(String),
4462
4463 ServiceFound(String, String),
4465
4466 ServiceResolved(Box<ResolvedService>),
4468
4469 ServiceRemoved(String, String),
4471
4472 SearchStopped(String),
4474}
4475
4476#[derive(Clone, Debug)]
4479#[non_exhaustive]
4480pub enum HostnameResolutionEvent {
4481 SearchStarted(String),
4483 AddressesFound(String, HashSet<ScopedIp>),
4485 AddressesRemoved(String, HashSet<ScopedIp>),
4487 SearchTimeout(String),
4489 SearchStopped(String),
4491}
4492
4493#[derive(Clone, Debug)]
4496#[non_exhaustive]
4497pub enum DaemonEvent {
4498 Announce(String, String),
4500
4501 Error(Error),
4503
4504 IpAdd(IpAddr),
4506
4507 IpDel(IpAddr),
4509
4510 NameChange(DnsNameChange),
4513
4514 Respond(String),
4516}
4517
4518#[derive(Clone, Debug)]
4521pub struct DnsNameChange {
4522 pub original: String,
4524
4525 pub new_name: String,
4535
4536 pub rr_type: RRType,
4538
4539 pub intf_name: String,
4541}
4542
4543#[derive(Debug)]
4545enum Command {
4546 Browse(String, u32, bool, Sender<ServiceEvent>),
4548
4549 ResolveHostname(String, u32, Sender<HostnameResolutionEvent>, Option<u64>), Register(Box<ServiceInfo>),
4554
4555 Unregister(String, Sender<UnregisterStatus>), RegisterResend(String, u32), UnregisterResend(Vec<u8>, u32, bool), StopBrowse(String), StopResolveHostname(String), Resolve(String, u16), GetMetrics(Sender<Metrics>),
4576
4577 GetStatus(Sender<DaemonStatus>),
4579
4580 Monitor(Sender<DaemonEvent>),
4582
4583 SetOption(DaemonOption),
4584
4585 GetOption(Sender<DaemonOptionVal>),
4586
4587 Verify(String, Duration),
4592
4593 InvalidIntfAddrs(HashSet<Interface>),
4595
4596 Exit(Sender<DaemonStatus>),
4597}
4598
4599impl fmt::Display for Command {
4600 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4601 match self {
4602 Self::Browse(_, _, _, _) => write!(f, "Command Browse"),
4603 Self::ResolveHostname(_, _, _, _) => write!(f, "Command ResolveHostname"),
4604 Self::Exit(_) => write!(f, "Command Exit"),
4605 Self::GetStatus(_) => write!(f, "Command GetStatus"),
4606 Self::GetMetrics(_) => write!(f, "Command GetMetrics"),
4607 Self::Monitor(_) => write!(f, "Command Monitor"),
4608 Self::Register(_) => write!(f, "Command Register"),
4609 Self::RegisterResend(_, _) => write!(f, "Command RegisterResend"),
4610 Self::SetOption(_) => write!(f, "Command SetOption"),
4611 Self::GetOption(_) => write!(f, "Command GetOption"),
4612 Self::StopBrowse(_) => write!(f, "Command StopBrowse"),
4613 Self::StopResolveHostname(_) => write!(f, "Command StopResolveHostname"),
4614 Self::Unregister(_, _) => write!(f, "Command Unregister"),
4615 Self::UnregisterResend(_, _, _) => write!(f, "Command UnregisterResend"),
4616 Self::Resolve(_, _) => write!(f, "Command Resolve"),
4617 Self::Verify(_, _) => write!(f, "Command VerifyResource"),
4618 Self::InvalidIntfAddrs(_) => write!(f, "Command InvalidIntfAddrs"),
4619 }
4620 }
4621}
4622
4623struct DaemonOptionVal {
4624 _service_name_len_max: u8,
4625 ip_check_interval: u64,
4626}
4627
4628#[derive(Debug)]
4629enum DaemonOption {
4630 ServiceNameLenMax(u8),
4631 IpCheckInterval(u64),
4632 MaxPacketSize(Vec<IfKind>, usize),
4633 EnableInterface(Vec<IfKind>),
4634 DisableInterface(Vec<IfKind>),
4635 MulticastLoopV4(bool),
4636 MulticastLoopV6(bool),
4637 AcceptUnsolicited(bool),
4638 IncludeAppleP2P(bool),
4639 #[cfg(test)]
4640 TestDownInterface(String),
4641 #[cfg(test)]
4642 TestUpInterface(String),
4643}
4644
4645const DOMAIN_LEN: usize = "._tcp.local.".len();
4647
4648fn check_service_name_length(ty_domain: &str, limit: u8) -> Result<()> {
4650 if ty_domain.len() <= DOMAIN_LEN + 1 {
4651 return Err(e_fmt!("Service type name cannot be empty: {}", ty_domain));
4653 }
4654
4655 let service_name_len = ty_domain.len() - DOMAIN_LEN - 1; if service_name_len > limit as usize {
4657 return Err(e_fmt!("Service name length must be <= {} bytes", limit));
4658 }
4659 Ok(())
4660}
4661
4662fn check_domain_suffix(name: &str) -> Result<()> {
4664 if !(name.ends_with("._tcp.local.") || name.ends_with("._udp.local.")) {
4665 return Err(e_fmt!(
4666 "mDNS service {} must end with '._tcp.local.' or '._udp.local.'",
4667 name
4668 ));
4669 }
4670
4671 Ok(())
4672}
4673
4674fn check_service_name(fullname: &str) -> Result<()> {
4682 check_domain_suffix(fullname)?;
4683
4684 let remaining: Vec<&str> = fullname[..fullname.len() - DOMAIN_LEN].split('.').collect();
4685 let name = remaining.last().ok_or_else(|| e_fmt!("No service name"))?;
4686
4687 if &name[0..1] != "_" {
4688 return Err(e_fmt!("Service name must start with '_'"));
4689 }
4690
4691 let name = &name[1..];
4692
4693 if name.contains("--") {
4694 return Err(e_fmt!("Service name must not contain '--'"));
4695 }
4696
4697 if name.starts_with('-') || name.ends_with('-') {
4698 return Err(e_fmt!("Service name (%s) may not start or end with '-'"));
4699 }
4700
4701 let ascii_count = name.chars().filter(|c| c.is_ascii_alphabetic()).count();
4702 if ascii_count < 1 {
4703 return Err(e_fmt!(
4704 "Service name must contain at least one letter (eg: 'A-Za-z')"
4705 ));
4706 }
4707
4708 Ok(())
4709}
4710
4711fn check_hostname(hostname: &str) -> Result<()> {
4713 if !hostname.ends_with(".local.") {
4714 return Err(e_fmt!("Hostname must end with '.local.': {hostname}"));
4715 }
4716
4717 if hostname == ".local." {
4718 return Err(e_fmt!(
4719 "The part of the hostname before '.local.' cannot be empty"
4720 ));
4721 }
4722
4723 if hostname.len() > 255 {
4724 return Err(e_fmt!("Hostname length must be <= 255 bytes"));
4725 }
4726
4727 Ok(())
4728}
4729
4730fn call_service_listener(
4731 listeners_map: &HashMap<String, Sender<ServiceEvent>>,
4732 ty_domain: &str,
4733 event: ServiceEvent,
4734) {
4735 if let Some(listener) = listeners_map.get(ty_domain) {
4736 match listener.send(event) {
4737 Ok(()) => trace!("Sent event to listener successfully"),
4738 Err(e) => debug!("Failed to send event: {}", e),
4739 }
4740 }
4741}
4742
4743fn call_hostname_resolution_listener(
4744 listeners_map: &HashMap<String, (Sender<HostnameResolutionEvent>, Option<u64>)>,
4745 hostname: &str,
4746 event: HostnameResolutionEvent,
4747) {
4748 let hostname_lower = hostname.to_lowercase();
4749 if let Some(listener) = listeners_map.get(&hostname_lower).map(|(l, _)| l) {
4750 match listener.send(event) {
4751 Ok(()) => trace!("Sent event to listener successfully"),
4752 Err(e) => debug!("Failed to send event: {}", e),
4753 }
4754 }
4755}
4756
4757fn my_ip_interfaces(with_loopback: bool) -> Vec<Interface> {
4761 my_ip_interfaces_inner(with_loopback, false)
4762}
4763
4764fn my_ip_interfaces_inner(with_loopback: bool, with_apple_p2p: bool) -> Vec<Interface> {
4765 if_addrs::get_if_addrs()
4766 .unwrap_or_default()
4767 .into_iter()
4768 .filter(|i| {
4769 i.is_oper_up()
4770 && !i.is_p2p()
4771 && (!i.is_loopback() || with_loopback)
4772 && (with_apple_p2p || !is_apple_p2p_by_name(&i.name))
4773 })
4774 .collect()
4775}
4776
4777fn is_apple_p2p_by_name(name: &str) -> bool {
4780 let p2p_prefixes = ["awdl", "llw"];
4781 p2p_prefixes.iter().any(|prefix| name.starts_with(prefix))
4782}
4783
4784#[derive(Clone, Copy, Debug)]
4786struct SendConfig {
4787 port: u16,
4789
4790 max_packet_size: usize,
4793
4794 is_ipv4: bool,
4797}
4798
4799fn send_dns_outgoing(
4802 out: &DnsOutgoing,
4803 my_intf: &MyIntf,
4804 sock: &PktInfoUdpSocket,
4805 port: u16,
4806 source: Option<&IfAddr>,
4807 unicast_dest: Option<SocketAddr>,
4808) -> MyResult<Vec<Vec<u8>>> {
4809 let if_name = &my_intf.name;
4810
4811 let if_addr = match source {
4812 Some(addr) => addr,
4813 None => {
4814 if sock.domain() == Domain::IPV4 {
4815 match my_intf.next_ifaddr_v4() {
4816 Some(addr) => addr,
4817 None => return Ok(vec![]),
4818 }
4819 } else {
4820 match my_intf.next_ifaddr_v6() {
4821 Some(addr) => addr,
4822 None => return Ok(vec![]),
4823 }
4824 }
4825 }
4826 };
4827
4828 let is_ipv4 = if_addr.ip().is_ipv4();
4830 let config = SendConfig {
4831 port,
4832 max_packet_size: my_intf.max_packet_size(is_ipv4),
4833 is_ipv4,
4834 };
4835
4836 send_dns_outgoing_impl(
4837 out,
4838 if_name,
4839 my_intf.index,
4840 if_addr,
4841 sock,
4842 config,
4843 unicast_dest,
4844 )
4845}
4846
4847fn send_dns_outgoing_impl(
4849 out: &DnsOutgoing,
4850 if_name: &str,
4851 if_index: u32,
4852 if_addr: &IfAddr,
4853 sock: &PktInfoUdpSocket,
4854 config: SendConfig,
4855 unicast_dest: Option<SocketAddr>,
4856) -> MyResult<Vec<Vec<u8>>> {
4857 let qtype = if out.is_query() {
4858 "query"
4859 } else {
4860 if out.answers_count() == 0 && out.additionals().is_empty() {
4861 return Ok(vec![]); }
4863 "response"
4864 };
4865 trace!(
4866 "send {}: {} questions {} answers {} authorities {} additional",
4867 qtype,
4868 out.questions().len(),
4869 out.answers_count(),
4870 out.authorities().len(),
4871 out.additionals().len()
4872 );
4873
4874 match if_addr.ip() {
4875 IpAddr::V4(ipv4) => {
4876 if let Err(e) = sock.set_multicast_if_v4(&ipv4) {
4877 debug!(
4878 "send_dns_outgoing: failed to set multicast interface for IPv4 {}: {}",
4879 ipv4, e
4880 );
4881 if e.kind() == std::io::ErrorKind::AddrNotAvailable {
4883 let intf_addr = Interface {
4884 name: if_name.to_string(),
4885 addr: if_addr.clone(),
4886 index: Some(if_index),
4887 oper_status: if_addrs::IfOperStatus::Down,
4888 is_p2p: false,
4889 #[cfg(windows)]
4890 adapter_name: String::new(),
4891 };
4892 return Err(InternalError::IntfAddrInvalid(intf_addr));
4893 }
4894 return Ok(vec![]); }
4896 }
4897 IpAddr::V6(ipv6) => {
4898 if let Err(e) = sock.set_multicast_if_v6(if_index) {
4899 debug!(
4900 "send_dns_outgoing: failed to set multicast interface for IPv6 {}: {}",
4901 ipv6, e
4902 );
4903 if e.kind() == std::io::ErrorKind::AddrNotAvailable {
4905 let intf_addr = Interface {
4906 name: if_name.to_string(),
4907 addr: if_addr.clone(),
4908 index: Some(if_index),
4909 oper_status: if_addrs::IfOperStatus::Down,
4910 is_p2p: false,
4911 #[cfg(windows)]
4912 adapter_name: String::new(),
4913 };
4914 return Err(InternalError::IntfAddrInvalid(intf_addr));
4915 }
4916 return Ok(vec![]); }
4918 }
4919 }
4920
4921 let packet_list = out.to_data_on_wire(config.max_packet_size, config.is_ipv4);
4922 for packet in packet_list.iter() {
4923 match unicast_dest {
4924 Some(dest) => unicast_on_intf(packet, if_name, dest, sock),
4925 None => multicast_on_intf(packet, if_name, if_index, if_addr, sock, config.port),
4926 }
4927 }
4928 Ok(packet_list)
4929}
4930
4931fn unicast_on_intf(packet: &[u8], if_name: &str, dest: SocketAddr, socket: &PktInfoUdpSocket) {
4934 let max_size = max_pkt_absolute(dest.is_ipv4());
4935 if packet.len() > max_size {
4936 debug!("Drop over-sized packet ({} > {max_size})", packet.len());
4937 return;
4938 }
4939
4940 let sock_addr = dest.into();
4941 match socket.send_to(packet, &sock_addr) {
4942 Ok(sz) => trace!(
4943 "sent unicast {} bytes on interface {} to {}",
4944 sz,
4945 if_name,
4946 dest
4947 ),
4948 Err(e) => trace!(
4949 "Failed to send unicast to {} via {:?}: {}",
4950 dest,
4951 &if_name,
4952 e
4953 ),
4954 }
4955}
4956
4957fn multicast_on_intf(
4959 packet: &[u8],
4960 if_name: &str,
4961 if_index: u32,
4962 if_addr: &IfAddr,
4963 socket: &PktInfoUdpSocket,
4964 port: u16,
4965) {
4966 let max_size = max_pkt_absolute(if_addr.ip().is_ipv4());
4967 if packet.len() > max_size {
4968 debug!("Drop over-sized packet ({} > {max_size})", packet.len());
4969 return;
4970 }
4971
4972 let addr: SocketAddr = match if_addr {
4973 if_addrs::IfAddr::V4(_) => SocketAddrV4::new(GROUP_ADDR_V4, port).into(),
4974 if_addrs::IfAddr::V6(_) => {
4975 let mut sock = SocketAddrV6::new(GROUP_ADDR_V6, port, 0, 0);
4976 sock.set_scope_id(if_index); sock.into()
4978 }
4979 };
4980
4981 let sock_addr = addr.into();
4983 match socket.send_to(packet, &sock_addr) {
4984 Ok(sz) => trace!(
4985 "sent out {} bytes on interface {} (idx {}) addr {}",
4986 sz,
4987 if_name,
4988 if_index,
4989 if_addr.ip()
4990 ),
4991 Err(e) => trace!("Failed to send to {} via {:?}: {}", addr, &if_name, e),
4992 }
4993}
4994
4995fn valid_instance_name(name: &str) -> bool {
4999 name.split('.').count() >= 5
5000}
5001
5002fn notify_monitors(monitors: &mut Vec<Sender<DaemonEvent>>, event: DaemonEvent) {
5003 monitors.retain(|sender| {
5004 if let Err(e) = sender.try_send(event.clone()) {
5005 debug!("notify_monitors: try_send: {}", &e);
5006 if matches!(e, TrySendError::Disconnected(_)) {
5007 return false; }
5009 }
5010 true
5011 });
5012}
5013
5014fn prepare_announce(
5017 info: &ServiceInfo,
5018 intf: &MyIntf,
5019 dns_registry: &mut DnsRegistry,
5020 is_ipv4: bool,
5021) -> Option<DnsOutgoing> {
5022 let intf_addrs = if is_ipv4 {
5023 info.get_addrs_on_my_intf_v4(intf)
5024 } else {
5025 info.get_addrs_on_my_intf_v6(intf)
5026 };
5027
5028 if intf_addrs.is_empty() {
5029 debug!(
5030 "prepare_announce (ipv4: {is_ipv4}): no valid addrs on interface {}",
5031 &intf.name
5032 );
5033 return None;
5034 }
5035
5036 let service_fullname = dns_registry.resolve_name(info.get_fullname());
5038
5039 debug!(
5040 "prepare to announce service {service_fullname} on {:?}",
5041 &intf_addrs
5042 );
5043
5044 let mut probing_count = 0;
5045 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
5046 let create_time = current_time_millis() + fastrand::u64(0..250);
5047
5048 out.add_answer_at_time(
5049 DnsPointer::new(
5050 info.get_type(),
5051 RRType::PTR,
5052 CLASS_IN,
5053 info.get_other_ttl(),
5054 service_fullname.to_string(),
5055 ),
5056 0,
5057 );
5058
5059 if let Some(sub) = info.get_subtype() {
5060 trace!("Adding subdomain {}", sub);
5061 out.add_answer_at_time(
5062 DnsPointer::new(
5063 sub,
5064 RRType::PTR,
5065 CLASS_IN,
5066 info.get_other_ttl(),
5067 service_fullname.to_string(),
5068 ),
5069 0,
5070 );
5071 }
5072
5073 let hostname = dns_registry.resolve_name(info.get_hostname()).to_string();
5075
5076 let mut srv = DnsSrv::new(
5077 info.get_fullname(),
5078 CLASS_IN | CLASS_CACHE_FLUSH,
5079 info.get_host_ttl(),
5080 info.get_priority(),
5081 info.get_weight(),
5082 info.get_port(),
5083 hostname,
5084 );
5085
5086 if let Some(new_name) = dns_registry.name_changes.get(info.get_fullname()) {
5087 srv.get_record_mut().set_new_name(new_name.to_string());
5088 }
5089
5090 if !info.requires_probe()
5091 || dns_registry.is_probing_done(&srv, info.get_fullname(), create_time)
5092 {
5093 out.add_answer_at_time(srv, 0);
5094 } else {
5095 probing_count += 1;
5096 }
5097
5098 let mut txt = DnsTxt::new(
5101 info.get_fullname(),
5102 CLASS_IN | CLASS_CACHE_FLUSH,
5103 info.get_other_ttl(),
5104 info.generate_txt(),
5105 );
5106
5107 if let Some(new_name) = dns_registry.name_changes.get(info.get_fullname()) {
5108 txt.get_record_mut().set_new_name(new_name.to_string());
5109 }
5110
5111 if !info.requires_probe()
5112 || dns_registry.is_probing_done(&txt, info.get_fullname(), create_time)
5113 {
5114 out.add_answer_at_time(txt, 0);
5115 } else {
5116 probing_count += 1;
5117 }
5118
5119 let hostname = info.get_hostname();
5122 for address in intf_addrs {
5123 let mut dns_addr = DnsAddress::new(
5124 hostname,
5125 ip_address_rr_type(&address),
5126 CLASS_IN | CLASS_CACHE_FLUSH,
5127 info.get_host_ttl(),
5128 address,
5129 intf.into(),
5130 );
5131
5132 if let Some(new_name) = dns_registry.name_changes.get(hostname) {
5133 dns_addr.get_record_mut().set_new_name(new_name.to_string());
5134 }
5135
5136 if !info.requires_probe()
5137 || dns_registry.is_probing_done(&dns_addr, info.get_fullname(), create_time)
5138 {
5139 out.add_answer_at_time(dns_addr, 0);
5140 } else {
5141 probing_count += 1;
5142 }
5143 }
5144
5145 if probing_count > 0 {
5146 return None;
5147 }
5148
5149 Some(out)
5150}
5151
5152fn announce_service_on_intf(
5155 dns_registry: &mut DnsRegistry,
5156 info: &ServiceInfo,
5157 intf: &MyIntf,
5158 sock: &PktInfoUdpSocket,
5159 port: u16,
5160) -> MyResult<bool> {
5161 let is_ipv4 = sock.domain() == Domain::IPV4;
5162 if let Some(mut out) = prepare_announce(info, intf, dns_registry, is_ipv4) {
5163 dns_registry.apply_multicast_rate_limit(&mut out, current_time_millis(), is_ipv4);
5166 if out.answers_count() > 0 {
5167 let _ = send_dns_outgoing(&out, intf, sock, port, None, None)?;
5168 }
5169 return Ok(true);
5170 }
5171
5172 Ok(false)
5173}
5174
5175fn name_change(original: &str) -> String {
5183 let mut parts: Vec<_> = original.split('.').collect();
5184 let Some(first_part) = parts.get_mut(0) else {
5185 return format!("{original} (2)");
5186 };
5187
5188 let mut new_name = format!("{first_part} (2)");
5189
5190 if let Some(paren_pos) = first_part.rfind(" (") {
5192 if let Some(end_paren) = first_part[paren_pos..].find(')') {
5194 let absolute_end_pos = paren_pos + end_paren;
5195 if absolute_end_pos == first_part.len() - 1 {
5197 let num_start = paren_pos + 2; if let Ok(number) = first_part[num_start..absolute_end_pos].parse::<u32>() {
5200 let base_name = &first_part[..paren_pos];
5201 new_name = format!("{} ({})", base_name, number + 1)
5202 }
5203 }
5204 }
5205 }
5206
5207 *first_part = &new_name;
5208 parts.join(".")
5209}
5210
5211fn hostname_change(original: &str) -> String {
5219 let mut parts: Vec<_> = original.split('.').collect();
5220 let Some(first_part) = parts.get_mut(0) else {
5221 return format!("{original}-2");
5222 };
5223
5224 let mut new_name = format!("{first_part}-2");
5225
5226 if let Some(hyphen_pos) = first_part.rfind('-') {
5228 if let Ok(number) = first_part[hyphen_pos + 1..].parse::<u32>() {
5230 let base_name = &first_part[..hyphen_pos];
5231 new_name = format!("{}-{}", base_name, number + 1);
5232 }
5233 }
5234
5235 *first_part = &new_name;
5236 parts.join(".")
5237}
5238
5239fn check_probing(
5242 dns_registry: &mut DnsRegistry,
5243 timers: &mut BinaryHeap<Reverse<u64>>,
5244 now: u64,
5245) -> (DnsOutgoing, Vec<String>) {
5246 let mut expired_probes = Vec::new();
5247 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
5248
5249 for (name, probe) in dns_registry.probing.iter_mut() {
5250 if now >= probe.next_send {
5251 if probe.expired(now) {
5252 expired_probes.push(name.clone());
5254 } else {
5255 out.add_question(name, RRType::ANY);
5256
5257 for record in probe.records.iter() {
5265 out.add_authority(record.clone());
5266 }
5267
5268 probe.update_next_send(now);
5269
5270 timers.push(Reverse(probe.next_send));
5272 }
5273 }
5274 }
5275
5276 (out, expired_probes)
5277}
5278
5279fn handle_expired_probes(
5284 expired_probes: Vec<String>,
5285 intf_name: &str,
5286 dns_registry: &mut DnsRegistry,
5287 monitors: &mut Vec<Sender<DaemonEvent>>,
5288) -> HashSet<String> {
5289 let mut waiting_services = HashSet::new();
5290
5291 for name in expired_probes {
5292 let Some(probe) = dns_registry.probing.remove(&name) else {
5293 continue;
5294 };
5295
5296 for record in probe.records.iter() {
5298 if let Some(new_name) = record.get_record().get_new_name() {
5299 dns_registry
5300 .name_changes
5301 .insert(name.clone(), new_name.to_string());
5302
5303 let event = DnsNameChange {
5304 original: record.get_record().get_original_name().to_string(),
5305 new_name: new_name.to_string(),
5306 rr_type: record.get_type(),
5307 intf_name: intf_name.to_string(),
5308 };
5309 debug!("Name change event: {:?}", &event);
5310 notify_monitors(monitors, DaemonEvent::NameChange(event));
5311 }
5312 }
5313
5314 debug!(
5316 "probe of '{name}' finished: move {} records to active. ({} waiting services)",
5317 probe.records.len(),
5318 probe.waiting_services.len(),
5319 );
5320
5321 if !probe.records.is_empty() {
5323 match dns_registry.active.get_mut(&name) {
5324 Some(records) => {
5325 records.extend(probe.records);
5326 }
5327 None => {
5328 dns_registry.active.insert(name, probe.records);
5329 }
5330 }
5331
5332 waiting_services.extend(probe.waiting_services);
5333 }
5334 }
5335
5336 waiting_services
5337}
5338
5339fn resolve_max_packet_size(
5347 selections: &[MaxPacketSizeSelection],
5348 interfaces: &[Interface],
5349 if_index: u32,
5350 is_ipv4: bool,
5351) -> usize {
5352 let mut size = MAX_PKT_DEFAULT;
5353
5354 for selection in selections {
5355 let matched = interfaces.iter().any(|intf| {
5356 intf.index.unwrap_or(0) == if_index
5357 && intf.ip().is_ipv4() == is_ipv4
5358 && selection.if_kind.matches(intf)
5359 });
5360 if matched {
5361 size = selection.max_packet_size;
5362 }
5363 }
5364
5365 size
5366}
5367
5368fn resolve_addr_to_index(if_kind: IfKind, interfaces: &[Interface]) -> IfKind {
5370 if let IfKind::Addr(addr) = &if_kind {
5371 if let Some(intf) = interfaces.iter().find(|intf| &intf.ip() == addr) {
5372 let if_index = intf.index.unwrap_or(0);
5373 return if addr.is_ipv4() {
5374 IfKind::IndexV4(if_index)
5375 } else {
5376 IfKind::IndexV6(if_index)
5377 };
5378 }
5379 }
5380 if_kind
5381}
5382
5383#[cfg(test)]
5384mod tests {
5385 use super::{
5386 _new_socket_bind, check_domain_suffix, check_service_name_length, hostname_change,
5387 my_ip_interfaces, name_change, resolve_max_packet_size, send_dns_outgoing_impl,
5388 valid_instance_name, valid_ip_on_intf, DaemonEvent, HostnameResolutionEvent, IfKind,
5389 MaxPacketSizeSelection, MyIntf, SendConfig, ServiceDaemon, ServiceEvent, ServiceInfo,
5390 GROUP_ADDR_V4, INITIAL_QUERY_DELAY_MAX_MILLIS, INITIAL_QUERY_DELAY_MIN_MILLIS,
5391 MAX_PKT_ABSOLUTE_IPV6, MAX_PKT_DEFAULT, MDNS_PORT, MIN_MAX_PACKET_SIZE, RESOLVE_MAX_TRY,
5392 SHARED_RESPONSE_DELAY_MAX_MILLIS, SHARED_RESPONSE_DELAY_MIN_MILLIS,
5393 };
5394 use crate::{
5395 dns_parser::{
5396 DnsAddress, DnsEntryExt, DnsIncoming, DnsOutgoing, DnsPointer, DnsSrv, InterfaceId,
5397 RRType, ScopedIp, CLASS_IN, FLAGS_AA, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE,
5398 LEGACY_UNICAST_MAX_TTL,
5399 },
5400 service_daemon::{add_answer_of_service, check_hostname},
5401 };
5402 use if_addrs::{IfAddr, Ifv4Addr, Ifv6Addr, Interface};
5403 use std::{
5404 collections::HashSet,
5405 net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket},
5406 time::{Duration, Instant, SystemTime},
5407 };
5408 use test_log::test;
5409
5410 fn test_interface(name: &str, index: u32, addr: IfAddr) -> Interface {
5412 Interface {
5413 name: name.to_string(),
5414 addr,
5415 index: Some(index),
5416 oper_status: if_addrs::IfOperStatus::Up,
5417 is_p2p: false,
5418 #[cfg(windows)]
5419 adapter_name: String::new(),
5420 }
5421 }
5422
5423 fn test_ifaddr_v4(ip: Ipv4Addr) -> IfAddr {
5424 IfAddr::V4(Ifv4Addr {
5425 ip,
5426 netmask: Ipv4Addr::new(255, 255, 255, 0),
5427 broadcast: None,
5428 prefixlen: 24,
5429 })
5430 }
5431
5432 fn test_ifaddr_v6(ip: Ipv6Addr) -> IfAddr {
5433 IfAddr::V6(Ifv6Addr {
5434 ip,
5435 netmask: Ipv6Addr::from(u128::MAX << 64),
5436 broadcast: None,
5437 prefixlen: 64,
5438 })
5439 }
5440
5441 #[test]
5442 fn test_excluded_address_preserves_announced_service() {
5443 use crate::service_info::ServiceStatus;
5444
5445 for ipv4_service in [true, false] {
5446 let signal = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
5447 let signal_addr = signal.local_addr().unwrap();
5448 signal.set_nonblocking(true).unwrap();
5449 let port = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))
5450 .unwrap()
5451 .local_addr()
5452 .unwrap()
5453 .port();
5454 let (sender, _receiver) = flume::bounded(100);
5455 let mut daemon = super::Zeroconf::new(
5456 mio::net::UdpSocket::from_std(signal),
5457 mio::Poll::new().unwrap(),
5458 port,
5459 sender,
5460 signal_addr,
5461 );
5462 let loopback = my_ip_interfaces(true)
5463 .into_iter()
5464 .find(|intf| intf.ip() == IpAddr::V4(Ipv4Addr::LOCALHOST))
5465 .unwrap();
5466 let index = loopback.index.unwrap();
5467 daemon.my_intfs.retain(|key, _| *key == index);
5470 daemon.dns_registry_map.retain(|key, _| *key == index);
5471 let mut service = ServiceInfo::new(
5472 "_address-change._tcp.local.",
5473 "address-change",
5474 "address-change.local.",
5475 "",
5476 8080,
5477 None,
5478 )
5479 .unwrap()
5480 .enable_addr_auto();
5481 service.set_interfaces(vec![if ipv4_service {
5482 IfKind::IPv4
5483 } else {
5484 IfKind::IPv6
5485 }]);
5486 let fullname = service.get_fullname().to_lowercase();
5487 daemon.register_service(service);
5488 assert_eq!(
5489 daemon.my_services[&fullname].get_status(index),
5490 ServiceStatus::Probing
5491 );
5492 assert!(!daemon.dns_registry_map[&index].probing.is_empty());
5493 for probe in daemon
5495 .dns_registry_map
5496 .get_mut(&index)
5497 .unwrap()
5498 .probing
5499 .values_mut()
5500 {
5501 probe.start_time = crate::current_time_millis() - 1000;
5502 probe.next_send = 0;
5503 }
5504 daemon.probing_handler();
5505 assert_eq!(
5506 daemon.my_services[&fullname].get_status(index),
5507 ServiceStatus::Announced
5508 );
5509 assert!(!daemon.dns_registry_map[&index].active.is_empty());
5510 let addresses = daemon.my_services[&fullname].get_addresses().clone();
5511
5512 let new_addr = test_interface(
5513 &loopback.name,
5514 index,
5515 if ipv4_service {
5516 test_ifaddr_v6("2001:db8::1234".parse().unwrap())
5517 } else {
5518 test_ifaddr_v4(Ipv4Addr::new(192, 0, 2, 123))
5519 },
5520 );
5521 daemon.add_interface(&new_addr, std::slice::from_ref(&new_addr));
5522 assert!(daemon.my_intfs[&index].addrs.contains(&new_addr.addr));
5523 assert_eq!(daemon.my_services[&fullname].get_addresses(), &addresses);
5524 assert!(daemon.dns_registry_map[&index].probing.is_empty());
5525 assert_eq!(
5526 daemon.my_services[&fullname].get_status(index),
5527 ServiceStatus::Announced,
5528 "an excluded address must not leave the service waiting for nonexistent probes"
5529 );
5530 }
5531 }
5532
5533 #[test]
5534 fn test_resolve_max_packet_size() {
5535 let interfaces = vec![
5537 test_interface("en0", 1, test_ifaddr_v4(Ipv4Addr::new(192, 168, 1, 2))),
5538 test_interface(
5539 "en0",
5540 1,
5541 test_ifaddr_v6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)),
5542 ),
5543 test_interface("en1", 2, test_ifaddr_v4(Ipv4Addr::new(10, 0, 0, 2))),
5544 ];
5545
5546 let resolve = |selections: &[MaxPacketSizeSelection], if_index, is_ipv4| {
5547 resolve_max_packet_size(selections, &interfaces, if_index, is_ipv4)
5548 };
5549
5550 assert_eq!(resolve(&[], 1, true), MAX_PKT_DEFAULT);
5552 assert_eq!(resolve(&[], 1, false), MAX_PKT_DEFAULT);
5553
5554 let by_name = vec![MaxPacketSizeSelection {
5556 if_kind: IfKind::Name("en0".to_string()),
5557 max_packet_size: 8000,
5558 }];
5559 assert_eq!(resolve(&by_name, 1, true), 8000);
5560 assert_eq!(resolve(&by_name, 1, false), 8000);
5561 assert_eq!(resolve(&by_name, 2, true), MAX_PKT_DEFAULT);
5562
5563 let overlapping = vec![
5565 MaxPacketSizeSelection {
5566 if_kind: IfKind::All,
5567 max_packet_size: 8000,
5568 },
5569 MaxPacketSizeSelection {
5570 if_kind: IfKind::Name("en1".to_string()),
5571 max_packet_size: 4000,
5572 },
5573 ];
5574 assert_eq!(resolve(&overlapping, 1, true), 8000);
5575 assert_eq!(resolve(&overlapping, 1, false), 8000);
5576 assert_eq!(resolve(&overlapping, 2, true), 4000);
5577
5578 let v4_only = vec![MaxPacketSizeSelection {
5580 if_kind: IfKind::IPv4,
5581 max_packet_size: 8000,
5582 }];
5583 assert_eq!(resolve(&v4_only, 1, true), 8000);
5584 assert_eq!(resolve(&v4_only, 1, false), MAX_PKT_DEFAULT);
5585
5586 let v6_only = vec![MaxPacketSizeSelection {
5587 if_kind: IfKind::IPv6,
5588 max_packet_size: 8000,
5589 }];
5590 assert_eq!(resolve(&v6_only, 1, false), 8000);
5591 assert_eq!(resolve(&v6_only, 1, true), MAX_PKT_DEFAULT);
5592 assert_eq!(resolve(&v6_only, 2, true), MAX_PKT_DEFAULT);
5594 assert_eq!(resolve(&v6_only, 2, false), MAX_PKT_DEFAULT);
5595
5596 let by_index_v4 = vec![MaxPacketSizeSelection {
5598 if_kind: IfKind::IndexV4(1),
5599 max_packet_size: 8000,
5600 }];
5601 assert_eq!(resolve(&by_index_v4, 1, true), 8000);
5602 assert_eq!(resolve(&by_index_v4, 1, false), MAX_PKT_DEFAULT);
5603 }
5604
5605 #[test]
5608 fn test_set_max_packet_size_range() {
5609 let daemon = ServiceDaemon::new().unwrap();
5610
5611 assert!(daemon
5612 .set_max_packet_size(IfKind::All, MIN_MAX_PACKET_SIZE - 1)
5613 .is_err());
5614 assert!(daemon
5615 .set_max_packet_size(IfKind::All, MAX_PKT_ABSOLUTE_IPV6 + 1)
5616 .is_err());
5617
5618 assert!(daemon
5620 .set_max_packet_size(IfKind::All, MIN_MAX_PACKET_SIZE)
5621 .is_ok());
5622 assert!(daemon
5623 .set_max_packet_size(IfKind::All, MAX_PKT_ABSOLUTE_IPV6)
5624 .is_ok());
5625
5626 daemon.shutdown().unwrap();
5627 }
5628
5629 #[test]
5630 fn test_response_source_ifaddr_match() {
5631 let ifaddr_a = IfAddr::V4(Ifv4Addr {
5635 ip: Ipv4Addr::new(192, 168, 1, 148),
5636 netmask: Ipv4Addr::new(255, 255, 255, 0),
5637 broadcast: None,
5638 prefixlen: 24,
5639 });
5640 let ifaddr_b = IfAddr::V4(Ifv4Addr {
5641 ip: Ipv4Addr::new(10, 238, 0, 51),
5642 netmask: Ipv4Addr::new(255, 255, 255, 0),
5643 broadcast: None,
5644 prefixlen: 24,
5645 });
5646
5647 let intf = MyIntf {
5648 name: "dummy0".to_string(),
5649 index: 1,
5650 addrs: HashSet::from([ifaddr_a.clone(), ifaddr_b.clone()]),
5651 max_packet_size_v4: MAX_PKT_DEFAULT,
5652 max_packet_size_v6: MAX_PKT_DEFAULT,
5653 };
5654
5655 let pick = |querier: IpAddr| -> Option<IfAddr> {
5656 intf.addrs
5657 .iter()
5658 .find(|a| valid_ip_on_intf(&querier, a))
5659 .cloned()
5660 };
5661
5662 assert_eq!(
5663 pick(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2))),
5664 Some(ifaddr_a)
5665 );
5666 assert_eq!(
5667 pick(IpAddr::V4(Ipv4Addr::new(10, 238, 0, 99))),
5668 Some(ifaddr_b)
5669 );
5670 assert_eq!(pick(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1))), None);
5672 }
5673
5674 #[test]
5675 fn test_instance_name() {
5676 assert!(valid_instance_name("my-laser._printer._tcp.local."));
5677 assert!(valid_instance_name("my-laser.._printer._tcp.local."));
5678 assert!(!valid_instance_name("_printer._tcp.local."));
5679 }
5680
5681 #[test]
5682 fn test_legacy_unicast_response() {
5683 let intf_ip = match my_ip_interfaces(false)
5694 .into_iter()
5695 .find_map(|intf| match intf.ip() {
5696 IpAddr::V4(ip) => Some(ip),
5697 IpAddr::V6(_) => None,
5698 }) {
5699 Some(ip) => ip,
5700 None => {
5701 println!("No IPv4 interface available; skipping test.");
5702 return;
5703 }
5704 };
5705
5706 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
5708 let unique = SystemTime::now()
5709 .duration_since(SystemTime::UNIX_EPOCH)
5710 .unwrap()
5711 .as_micros();
5712 let hostname = format!("legacy-unicast-test-{unique}.local.");
5713 let service_info = ServiceInfo::new(
5714 "_legacy-uni._udp.local.",
5715 "test_instance",
5716 &hostname,
5717 &[IpAddr::V4(intf_ip)] as &[IpAddr],
5718 5353, None,
5720 )
5721 .expect("invalid service info");
5722 daemon.register(service_info).expect("register service");
5723
5724 let querier = UdpSocket::bind((intf_ip, 0)).expect("bind querier socket");
5728 querier
5729 .set_multicast_loop_v4(true)
5730 .expect("enable multicast loopback");
5731 querier
5732 .set_read_timeout(Some(Duration::from_millis(500)))
5733 .expect("set read timeout");
5734 assert_ne!(
5735 querier.local_addr().unwrap().port(),
5736 MDNS_PORT,
5737 "querier must use an ephemeral (non-5353) source port"
5738 );
5739
5740 const QUERY_ID: u16 = 0x4a17;
5745 let mut query = DnsOutgoing::new(FLAGS_QR_QUERY);
5746 query.set_id(QUERY_ID);
5747 query.set_multicast(false);
5748 query.add_question(&hostname, RRType::A);
5749 let query_packet = query
5750 .to_data_on_wire(MAX_PKT_DEFAULT, true)
5751 .pop()
5752 .expect("query serialized to one packet");
5753
5754 let if_id = InterfaceId {
5755 name: "test".to_string(),
5756 index: 0,
5757 };
5758
5759 let deadline = Instant::now() + Duration::from_secs(8);
5762 let mut response = None;
5763 'outer: while Instant::now() < deadline {
5764 querier
5765 .send_to(&query_packet, (GROUP_ADDR_V4, MDNS_PORT))
5766 .expect("send query");
5767
5768 let mut buf = [0u8; 1500];
5771 while let Ok((len, from)) = querier.recv_from(&mut buf) {
5772 let Ok(msg) = DnsIncoming::new(buf[..len].to_vec(), if_id.clone()) else {
5773 continue;
5774 };
5775 if msg.is_response()
5776 && msg
5777 .answers()
5778 .iter()
5779 .any(|a| a.get_name().eq_ignore_ascii_case(&hostname))
5780 {
5781 response = Some((msg, from));
5782 break 'outer;
5783 }
5784 }
5785 }
5786
5787 let (msg, from) = response.expect(
5788 "expected a unicast response to the legacy query; \
5789 a multicast-only reply would never reach this un-joined socket",
5790 );
5791
5792 assert_eq!(
5794 from.port(),
5795 MDNS_PORT,
5796 "response should originate from the mDNS port"
5797 );
5798
5799 assert_eq!(
5801 msg.id(),
5802 QUERY_ID,
5803 "legacy unicast response must echo the query id"
5804 );
5805
5806 assert!(
5808 msg.questions()
5809 .iter()
5810 .any(|q| q.entry_name().eq_ignore_ascii_case(&hostname)),
5811 "legacy unicast response must echo the question section"
5812 );
5813
5814 let answer = msg
5817 .answers()
5818 .iter()
5819 .find(|a| a.get_name().eq_ignore_ascii_case(&hostname))
5820 .expect("response contains an answer for our hostname");
5821 assert_eq!(
5822 answer.get_type(),
5823 RRType::A,
5824 "an A query should be answered with an A record"
5825 );
5826 assert!(
5827 !answer.get_cache_flush(),
5828 "legacy unicast responses must clear the cache-flush bit"
5829 );
5830
5831 assert!(
5832 answer.get_record().get_ttl() <= LEGACY_UNICAST_MAX_TTL,
5833 "legacy unicast response TTL {} exceeds the {}s cap",
5834 answer.get_record().get_ttl(),
5835 LEGACY_UNICAST_MAX_TTL
5836 );
5837
5838 daemon.shutdown().unwrap();
5839 }
5840
5841 #[test]
5842 fn test_shared_response_delay_bounds() {
5843 assert_eq!(SHARED_RESPONSE_DELAY_MIN_MILLIS, 10);
5848 assert_eq!(SHARED_RESPONSE_DELAY_MAX_MILLIS, 50);
5849 for _ in 0..10_000 {
5850 let d =
5851 fastrand::u64(SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS);
5852 assert!(
5853 (SHARED_RESPONSE_DELAY_MIN_MILLIS..SHARED_RESPONSE_DELAY_MAX_MILLIS).contains(&d),
5854 "delay {} ms is outside the configured {}-{} ms range",
5855 d,
5856 SHARED_RESPONSE_DELAY_MIN_MILLIS,
5857 SHARED_RESPONSE_DELAY_MAX_MILLIS
5858 );
5859 }
5860 }
5861
5862 #[test]
5863 fn test_initial_query_delayed() {
5864 use socket2::{Domain, Protocol, Socket, Type};
5871
5872 let (intf, intf_ip) = match my_ip_interfaces(false)
5873 .into_iter()
5874 .find_map(|intf| match intf.ip() {
5875 IpAddr::V4(ip) if !ip.is_loopback() => Some((intf, ip)),
5876 _ => None,
5877 }) {
5878 Some(pair) => pair,
5879 None => {
5880 println!("No IPv4 interface available; skipping test.");
5881 return;
5882 }
5883 };
5884 let interface_id = InterfaceId::from(&intf);
5885
5886 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
5890 sock.set_reuse_address(true).unwrap();
5891 #[cfg(unix)]
5892 sock.set_reuse_port(true).unwrap();
5893 sock.bind(&std::net::SocketAddr::from((Ipv4Addr::UNSPECIFIED, MDNS_PORT)).into())
5894 .unwrap();
5895 sock.join_multicast_v4(&GROUP_ADDR_V4, &intf_ip).unwrap();
5896 sock.set_read_timeout(Some(Duration::from_millis(200)))
5897 .unwrap();
5898 let sock: UdpSocket = sock.into();
5899
5900 let unique = SystemTime::now()
5902 .duration_since(SystemTime::UNIX_EPOCH)
5903 .unwrap()
5904 .as_micros()
5905 % 1_000_000_000;
5906 let service_type = format!("_qd{unique}._udp.local.");
5907
5908 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
5909
5910 let sent_at = Instant::now();
5911 let _browse = daemon.browse(&service_type).expect("browse");
5912
5913 let deadline = Instant::now() + Duration::from_secs(2);
5916 let mut buf = [0u8; 2048];
5917 let mut measured = None;
5918 while Instant::now() < deadline {
5919 let n = match sock.recv_from(&mut buf) {
5920 Ok((n, _)) => n,
5921 Err(_) => continue, };
5923 let Ok(msg) = DnsIncoming::new(buf[..n].to_vec(), interface_id.clone()) else {
5924 continue;
5925 };
5926 if msg.is_query()
5927 && msg
5928 .questions()
5929 .iter()
5930 .any(|q| q.entry_name() == service_type)
5931 {
5932 measured = Some(sent_at.elapsed());
5933 break;
5934 }
5935 }
5936
5937 daemon.shutdown().unwrap();
5938
5939 let elapsed = measured.expect("expected the daemon to send a PTR query for our browse");
5940 let tolerance = Duration::from_millis(2);
5941 assert!(
5942 elapsed + tolerance >= Duration::from_millis(INITIAL_QUERY_DELAY_MIN_MILLIS),
5943 "first browse query was sent after only {:?}; the first query of a series must be \
5944 delayed (10-50 ms window), not sent immediately",
5945 elapsed
5946 );
5947
5948 let scheduling_slack = Duration::from_millis(50);
5953 assert!(
5954 elapsed <= Duration::from_millis(INITIAL_QUERY_DELAY_MAX_MILLIS) + scheduling_slack,
5955 "first browse query was sent after {:?}, beyond the {}-{} ms jitter window (plus slack)",
5956 elapsed,
5957 INITIAL_QUERY_DELAY_MIN_MILLIS,
5958 INITIAL_QUERY_DELAY_MAX_MILLIS
5959 );
5960 }
5961
5962 #[test]
5963 fn test_shared_ptr_response_delayed() {
5964 use socket2::{Domain, Protocol, Socket, Type};
5971
5972 let intf_ip = match my_ip_interfaces(false)
5973 .into_iter()
5974 .find_map(|intf| match intf.ip() {
5975 IpAddr::V4(ip) if !ip.is_loopback() => Some(ip),
5976 _ => None,
5977 }) {
5978 Some(ip) => ip,
5979 None => {
5980 println!("No IPv4 interface available; skipping test.");
5981 return;
5982 }
5983 };
5984
5985 let daemon = ServiceDaemon::new().expect("Failed to create daemon");
5986 let monitor = daemon.monitor().expect("monitor daemon events");
5987
5988 let unique = SystemTime::now()
5991 .duration_since(SystemTime::UNIX_EPOCH)
5992 .unwrap()
5993 .as_micros()
5994 % 1_000_000_000;
5995 let service_type = format!("_sd{unique}._udp.local.");
5996 let hostname = format!("sd{unique}.local.");
5997 let service_info = ServiceInfo::new(
5998 &service_type,
5999 "test_instance",
6000 &hostname,
6001 &[IpAddr::V4(intf_ip)] as &[IpAddr],
6002 5353,
6003 None,
6004 )
6005 .expect("invalid service info");
6006 daemon.register(service_info).expect("register service");
6007
6008 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap();
6012 sock.set_reuse_address(true).unwrap();
6013 #[cfg(unix)]
6014 sock.set_reuse_port(true).unwrap();
6015 sock.bind(&std::net::SocketAddr::from((Ipv4Addr::UNSPECIFIED, MDNS_PORT)).into())
6016 .unwrap();
6017 sock.set_multicast_if_v4(&intf_ip).unwrap();
6018 sock.set_multicast_loop_v4(true).unwrap();
6020 let sock: UdpSocket = sock.into();
6021
6022 let mut query = DnsOutgoing::new(FLAGS_QR_QUERY);
6024 query.add_question(&service_type, RRType::PTR);
6025 let query_packet = query
6026 .to_data_on_wire(MAX_PKT_DEFAULT, true)
6027 .pop()
6028 .expect("one packet");
6029
6030 std::thread::sleep(Duration::from_secs(3));
6034
6035 let deadline = Instant::now() + Duration::from_secs(8);
6039 let mut measured = None;
6040 while Instant::now() < deadline {
6041 while monitor.try_recv().is_ok() {}
6044
6045 let sent_at = Instant::now();
6046 sock.send_to(&query_packet, (GROUP_ADDR_V4, MDNS_PORT))
6047 .expect("send query");
6048
6049 let attempt_deadline = sent_at + Duration::from_millis(700);
6052 loop {
6053 let remaining = attempt_deadline.saturating_duration_since(Instant::now());
6054 if remaining.is_zero() {
6055 break;
6056 }
6057 match monitor.recv_timeout(remaining) {
6058 Ok(DaemonEvent::Respond(_)) => {
6059 measured = Some(sent_at.elapsed());
6060 break;
6061 }
6062 Ok(_) => continue, Err(_) => break, }
6065 }
6066 if measured.is_some() {
6067 break;
6068 }
6069 }
6070
6071 let elapsed =
6072 measured.expect("expected the daemon to respond to our PTR query within the deadline");
6073 assert!(
6074 elapsed >= Duration::from_millis(8),
6075 "PTR response was sent after only {:?}; a shared-record response must be \
6076 delayed (10-50 ms window), not sent immediately",
6077 elapsed
6078 );
6079 assert!(
6080 elapsed <= Duration::from_millis(600),
6081 "PTR response was sent after {:?}; expected within the 10-50 ms delay window",
6082 elapsed
6083 );
6084
6085 daemon.shutdown().unwrap();
6086 }
6087
6088 #[test]
6089 fn test_check_service_name_length() {
6090 let result = check_service_name_length("_tcp", 100);
6091 assert!(result.is_err());
6092 if let Err(e) = result {
6093 println!("{}", e);
6094 }
6095 }
6096
6097 #[test]
6098 fn test_check_hostname() {
6099 for hostname in &[
6101 "my_host.local.",
6102 &("A".repeat(255 - ".local.".len()) + ".local."),
6103 ] {
6104 let result = check_hostname(hostname);
6105 assert!(result.is_ok());
6106 }
6107
6108 for hostname in &[
6110 "my_host.local",
6111 ".local.",
6112 &("A".repeat(256 - ".local.".len()) + ".local."),
6113 ] {
6114 let result = check_hostname(hostname);
6115 assert!(result.is_err());
6116 if let Err(e) = result {
6117 println!("{}", e);
6118 }
6119 }
6120 }
6121
6122 #[test]
6123 fn test_check_domain_suffix() {
6124 assert!(check_domain_suffix("_missing_dot._tcp.local").is_err());
6125 assert!(check_domain_suffix("_missing_bar.tcp.local.").is_err());
6126 assert!(check_domain_suffix("_mis_spell._tpp.local.").is_err());
6127 assert!(check_domain_suffix("_mis_spell._upp.local.").is_err());
6128 assert!(check_domain_suffix("_has_dot._tcp.local.").is_ok());
6129 assert!(check_domain_suffix("_goodname._udp.local.").is_ok());
6130 }
6131
6132 #[test]
6133 fn test_service_with_temporarily_invalidated_ptr() {
6134 let d = ServiceDaemon::new().expect("Failed to create daemon");
6136
6137 let service = "_test_inval_ptr._udp.local.";
6138 let host_name = "my_host_tmp_invalidated_ptr.local.";
6139 let intfs: Vec<_> = my_ip_interfaces(false);
6140 let intf_ips: Vec<_> = intfs.iter().map(|intf| intf.ip()).collect();
6141 let port = 5201;
6142 let my_service =
6143 ServiceInfo::new(service, "my_instance", host_name, &intf_ips[..], port, None)
6144 .expect("invalid service info")
6145 .enable_addr_auto();
6146 let result = d.register(my_service.clone());
6147 assert!(result.is_ok());
6148
6149 let browse_chan = d.browse(service).unwrap();
6151 let timeout = Duration::from_secs(2);
6152 let mut resolved = false;
6153
6154 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6155 match event {
6156 ServiceEvent::ServiceResolved(info) => {
6157 resolved = true;
6158 println!("Resolved a service of {}", &info.fullname);
6159 break;
6160 }
6161 e => {
6162 println!("Received event {:?}", e);
6163 }
6164 }
6165 }
6166
6167 assert!(resolved);
6168
6169 println!("Stopping browse of {}", service);
6170 d.stop_browse(service).unwrap();
6173
6174 let mut stopped = false;
6179 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6180 match event {
6181 ServiceEvent::SearchStopped(_) => {
6182 stopped = true;
6183 println!("Stopped browsing service");
6184 break;
6185 }
6186 e => {
6190 println!("Received event {:?}", e);
6191 }
6192 }
6193 }
6194
6195 assert!(stopped);
6196
6197 let invalidate_ptr_packet = DnsPointer::new(
6199 my_service.get_type(),
6200 RRType::PTR,
6201 CLASS_IN,
6202 0,
6203 my_service.get_fullname().to_string(),
6204 );
6205
6206 let mut packet_buffer = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6207 packet_buffer.add_additional_answer(invalidate_ptr_packet);
6208
6209 for intf in intfs {
6210 let sock = _new_socket_bind(&intf, true).unwrap();
6211 send_dns_outgoing_impl(
6212 &packet_buffer,
6213 &intf.name,
6214 intf.index.unwrap_or(0),
6215 &intf.addr,
6216 &sock.pktinfo,
6217 SendConfig {
6218 port: MDNS_PORT,
6219 max_packet_size: MAX_PKT_DEFAULT,
6220 is_ipv4: intf.addr.ip().is_ipv4(),
6221 },
6222 None,
6223 )
6224 .unwrap();
6225 }
6226
6227 println!(
6228 "Sent PTR record invalidation. Starting second browse for {}",
6229 service
6230 );
6231
6232 let browse_chan = d.browse(service).unwrap();
6234
6235 resolved = false;
6236 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6237 match event {
6238 ServiceEvent::ServiceResolved(info) => {
6239 resolved = true;
6240 println!("Resolved a service of {}", &info.fullname);
6241 break;
6242 }
6243 e => {
6244 println!("Received event {:?}", e);
6245 }
6246 }
6247 }
6248
6249 assert!(resolved);
6250 d.shutdown().unwrap();
6251 }
6252
6253 #[test]
6254 fn test_expired_srv() {
6255 let service_type = "_expired-srv._udp.local.";
6257 let instance = "test_instance";
6258 let host_name = "expired_srv_host.local.";
6259 let mut my_service = ServiceInfo::new(service_type, instance, host_name, "", 5023, None)
6260 .unwrap()
6261 .enable_addr_auto();
6262 let new_ttl = 3; my_service._set_host_ttl(new_ttl);
6267
6268 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6270 let result = mdns_server.register(my_service);
6271 assert!(result.is_ok());
6272
6273 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6274 let browse_chan = mdns_client.browse(service_type).unwrap();
6275 let timeout = Duration::from_secs(2);
6276 let mut resolved = false;
6277
6278 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6279 if let ServiceEvent::ServiceResolved(info) = event {
6280 resolved = true;
6281 println!("Resolved a service of {}", &info.fullname);
6282 break;
6283 }
6284 }
6285
6286 assert!(resolved);
6287
6288 mdns_server.shutdown().unwrap();
6290
6291 let expire_timeout = Duration::from_secs(new_ttl as u64);
6293 while let Ok(event) = browse_chan.recv_timeout(expire_timeout) {
6294 if let ServiceEvent::ServiceRemoved(service_type, full_name) = event {
6295 println!("Service removed: {}: {}", &service_type, &full_name);
6296 break;
6297 }
6298 }
6299 }
6300
6301 #[test]
6302 fn test_hostname_resolution_address_removed() {
6303 let server = ServiceDaemon::new().expect("Failed to create server");
6305 let hostname = "addr_remove_host._tcp.local.";
6306 let service_ip_addr: ScopedIp = my_ip_interfaces(false)
6307 .iter()
6308 .find(|iface| iface.ip().is_ipv4())
6309 .map(|iface| iface.into())
6310 .unwrap();
6311
6312 let mut my_service = ServiceInfo::new(
6313 "_host_res_test._tcp.local.",
6314 "my_instance",
6315 hostname,
6316 service_ip_addr.to_ip_addr(),
6317 1234,
6318 None,
6319 )
6320 .expect("invalid service info");
6321
6322 let addr_ttl = 2;
6324 my_service._set_host_ttl(addr_ttl); server.register(my_service).unwrap();
6327
6328 let client = ServiceDaemon::new().expect("Failed to create client");
6330 let event_receiver = client.resolve_hostname(hostname, None).unwrap();
6331 let resolved = loop {
6332 match event_receiver.recv() {
6333 Ok(HostnameResolutionEvent::AddressesFound(found_hostname, addresses)) => {
6334 assert_eq!(found_hostname, hostname);
6335 assert!(addresses.contains(&service_ip_addr));
6336 println!("address found: {:?}", &addresses);
6337 break true;
6338 }
6339 Ok(HostnameResolutionEvent::SearchStopped(_)) => break false,
6340 Ok(_event) => {}
6341 Err(_) => break false,
6342 }
6343 };
6344
6345 assert!(resolved);
6346
6347 server.shutdown().unwrap();
6349
6350 let timeout = Duration::from_secs(addr_ttl as u64 + 1);
6352 let removed = loop {
6353 match event_receiver.recv_timeout(timeout) {
6354 Ok(HostnameResolutionEvent::AddressesRemoved(removed_host, addresses)) => {
6355 assert_eq!(removed_host, hostname);
6356 assert!(addresses.contains(&service_ip_addr));
6357
6358 println!(
6359 "address removed: hostname: {} addresses: {:?}",
6360 &hostname, &addresses
6361 );
6362 break true;
6363 }
6364 Ok(_event) => {}
6365 Err(_) => {
6366 break false;
6367 }
6368 }
6369 };
6370
6371 assert!(removed);
6372
6373 client.shutdown().unwrap();
6374 }
6375
6376 #[test]
6377 fn test_refresh_ptr() {
6378 let service_type = "_refresh-ptr._udp.local.";
6380 let instance = "test_instance";
6381 let host_name = "refresh_ptr_host.local.";
6382 let service_ip_addr = my_ip_interfaces(false)
6383 .iter()
6384 .find(|iface| iface.ip().is_ipv4())
6385 .map(|iface| iface.ip())
6386 .unwrap();
6387
6388 let mut my_service = ServiceInfo::new(
6389 service_type,
6390 instance,
6391 host_name,
6392 service_ip_addr,
6393 5023,
6394 None,
6395 )
6396 .unwrap();
6397
6398 let new_ttl = 3; my_service._set_other_ttl(new_ttl);
6400
6401 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6403 let result = mdns_server.register(my_service);
6404 assert!(result.is_ok());
6405
6406 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6407 let browse_chan = mdns_client.browse(service_type).unwrap();
6408 let timeout = Duration::from_millis(1500); let mut resolved = false;
6410
6411 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6413 if let ServiceEvent::ServiceResolved(info) = event {
6414 resolved = true;
6415 println!("Resolved a service of {}", &info.fullname);
6416 break;
6417 }
6418 }
6419
6420 assert!(resolved);
6421
6422 let timeout = Duration::from_millis(new_ttl as u64 * 1000 * 90 / 100);
6424 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6425 println!("event: {:?}", &event);
6426 }
6427
6428 let metrics_chan = mdns_client.get_metrics().unwrap();
6430 let metrics = metrics_chan.recv_timeout(timeout).unwrap();
6431 let ptr_refresh_counter = metrics["cache-refresh-ptr"];
6432 assert_eq!(ptr_refresh_counter, 1);
6433 let srvtxt_refresh_counter = metrics["cache-refresh-srv-txt"];
6434 assert_eq!(srvtxt_refresh_counter, 1);
6435
6436 mdns_server.shutdown().unwrap();
6438 mdns_client.shutdown().unwrap();
6439 }
6440
6441 #[test]
6442 fn test_name_change() {
6443 assert_eq!(name_change("foo.local."), "foo (2).local.");
6444 assert_eq!(name_change("foo (2).local."), "foo (3).local.");
6445 assert_eq!(name_change("foo (9).local."), "foo (10).local.");
6446 assert_eq!(name_change("foo"), "foo (2)");
6447 assert_eq!(name_change("foo (2)"), "foo (3)");
6448 assert_eq!(name_change(""), " (2)");
6449
6450 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)"); }
6455
6456 #[test]
6457 fn test_hostname_change() {
6458 assert_eq!(hostname_change("foo.local."), "foo-2.local.");
6459 assert_eq!(hostname_change("foo"), "foo-2");
6460 assert_eq!(hostname_change("foo-2.local."), "foo-3.local.");
6461 assert_eq!(hostname_change("foo-9"), "foo-10");
6462 assert_eq!(hostname_change("test-42.domain."), "test-43.domain.");
6463 }
6464
6465 #[test]
6466 fn test_add_answer_txt_ttl() {
6467 let service_type = "_test_add_answer._udp.local.";
6469 let instance = "test_instance";
6470 let host_name = "add_answer_host.local.";
6471 let service_intf = my_ip_interfaces(false)
6472 .into_iter()
6473 .find(|iface| iface.ip().is_ipv4())
6474 .unwrap();
6475 let service_ip_addr = service_intf.ip();
6476 let my_service = ServiceInfo::new(
6477 service_type,
6478 instance,
6479 host_name,
6480 service_ip_addr,
6481 5023,
6482 None,
6483 )
6484 .unwrap();
6485
6486 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6488
6489 let mut dummy_data = out.to_data_on_wire(MAX_PKT_DEFAULT, true);
6491 let interface_id = InterfaceId::from(&service_intf);
6492 let incoming = DnsIncoming::new(dummy_data.pop().unwrap(), interface_id).unwrap();
6493
6494 let if_addrs = vec![service_intf.ip()];
6496 add_answer_of_service(
6497 &mut out,
6498 &incoming,
6499 instance,
6500 &my_service,
6501 RRType::TXT,
6502 if_addrs,
6503 );
6504
6505 assert!(
6507 out.answers_count() > 0,
6508 "No answers added to the outgoing message"
6509 );
6510
6511 let answer = out._answers().first().unwrap();
6513 assert_eq!(answer.0.get_type(), RRType::TXT);
6514
6515 assert_eq!(answer.0.get_record().get_ttl(), my_service.get_other_ttl());
6517 }
6518
6519 #[test]
6520 fn test_interface_flip() {
6521 let ty_domain = "_intf-flip._udp.local.";
6523 let host_name = "intf_flip.local.";
6524 let now = SystemTime::now()
6525 .duration_since(SystemTime::UNIX_EPOCH)
6526 .unwrap();
6527 let instance_name = now.as_micros().to_string(); let port = 5200;
6529
6530 let (ip_addr1, intf_name) = my_ip_interfaces(false)
6532 .iter()
6533 .find(|iface| iface.ip().is_ipv4())
6534 .map(|iface| (iface.ip(), iface.name.clone()))
6535 .unwrap();
6536
6537 println!("Using interface {} with IP {}", intf_name, ip_addr1);
6538
6539 let service1 = ServiceInfo::new(ty_domain, &instance_name, host_name, ip_addr1, port, None)
6541 .expect("valid service info");
6542 let server1 = ServiceDaemon::new().expect("failed to start server");
6543 server1
6544 .register(service1)
6545 .expect("Failed to register service1");
6546
6547 std::thread::sleep(Duration::from_secs(2));
6549
6550 let client = ServiceDaemon::new().expect("failed to start client");
6552
6553 let receiver = client.browse(ty_domain).unwrap();
6554
6555 let timeout = Duration::from_secs(3);
6556 let mut got_data = false;
6557
6558 while let Ok(event) = receiver.recv_timeout(timeout) {
6559 if let ServiceEvent::ServiceResolved(_) = event {
6560 println!("Received ServiceResolved event");
6561 got_data = true;
6562 break;
6563 }
6564 }
6565
6566 assert!(got_data, "Should receive ServiceResolved event");
6567
6568 client.set_ip_check_interval(1).unwrap();
6570
6571 println!("Shutting down interface {}", &intf_name);
6573 client.test_down_interface(&intf_name).unwrap();
6574
6575 let mut got_removed = false;
6576
6577 while let Ok(event) = receiver.recv_timeout(timeout) {
6578 if let ServiceEvent::ServiceRemoved(ty_domain, instance) = event {
6579 got_removed = true;
6580 println!("removed: {ty_domain} : {instance}");
6581 break;
6582 }
6583 }
6584 assert!(got_removed, "Should receive ServiceRemoved event");
6585
6586 println!("Bringing up interface {}", &intf_name);
6587 client.test_up_interface(&intf_name).unwrap();
6588 let mut got_data = false;
6589 while let Ok(event) = receiver.recv_timeout(timeout) {
6590 if let ServiceEvent::ServiceResolved(resolved) = event {
6591 got_data = true;
6592 println!("Received ServiceResolved: {:?}", resolved);
6593 break;
6594 }
6595 }
6596 assert!(
6597 got_data,
6598 "Should receive ServiceResolved event after interface is back up"
6599 );
6600
6601 server1.shutdown().unwrap();
6602 client.shutdown().unwrap();
6603 }
6604
6605 #[test]
6606 fn test_cache_only() {
6607 let service_type = "_cache_only._udp.local.";
6609 let instance = "test_instance";
6610 let host_name = "cache_only_host.local.";
6611 let service_ip_addr = my_ip_interfaces(false)
6612 .iter()
6613 .find(|iface| iface.ip().is_ipv4())
6614 .map(|iface| iface.ip())
6615 .unwrap();
6616
6617 let mut my_service = ServiceInfo::new(
6618 service_type,
6619 instance,
6620 host_name,
6621 service_ip_addr,
6622 5023,
6623 None,
6624 )
6625 .unwrap();
6626
6627 let new_ttl = 3; my_service._set_other_ttl(new_ttl);
6629
6630 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6631
6632 let browse_chan = mdns_client.browse_cache(service_type).unwrap();
6635 std::thread::sleep(Duration::from_secs(2));
6636
6637 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6639 let result = mdns_server.register(my_service);
6640 assert!(result.is_ok());
6641
6642 let timeout = Duration::from_millis(1500); let mut resolved = false;
6644
6645 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6647 if let ServiceEvent::ServiceResolved(info) = event {
6648 resolved = true;
6649 println!("Resolved a service of {}", &info.get_fullname());
6650 break;
6651 }
6652 }
6653
6654 assert!(resolved);
6655
6656 mdns_server.shutdown().unwrap();
6658 mdns_client.shutdown().unwrap();
6659 }
6660
6661 #[test]
6662 fn test_cache_only_unsolicited() {
6663 let service_type = "_c_unsolicit._udp.local.";
6664 let instance = "test_instance";
6665 let host_name = "c_unsolicit_host.local.";
6666 let service_ip_addr = my_ip_interfaces(false)
6667 .iter()
6668 .find(|iface| iface.ip().is_ipv4())
6669 .map(|iface| iface.ip())
6670 .unwrap();
6671
6672 let my_service = ServiceInfo::new(
6673 service_type,
6674 instance,
6675 host_name,
6676 service_ip_addr,
6677 5023,
6678 None,
6679 )
6680 .unwrap();
6681
6682 let mdns_server = ServiceDaemon::new().expect("Failed to create mdns server");
6684 let result = mdns_server.register(my_service);
6685 assert!(result.is_ok());
6686
6687 let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6688 mdns_client.accept_unsolicited(true).unwrap();
6689
6690 std::thread::sleep(Duration::from_secs(2));
6693 let browse_chan = mdns_client.browse_cache(service_type).unwrap();
6694 let timeout = Duration::from_millis(1500); let mut resolved = false;
6696
6697 while let Ok(event) = browse_chan.recv_timeout(timeout) {
6699 if let ServiceEvent::ServiceResolved(info) = event {
6700 resolved = true;
6701 println!("Resolved a service of {}", &info.get_fullname());
6702 break;
6703 }
6704 }
6705
6706 assert!(resolved);
6707
6708 mdns_server.shutdown().unwrap();
6710 mdns_client.shutdown().unwrap();
6711 }
6712
6713 #[test]
6714 fn test_custom_port_isolation() {
6715 let service_type = "_custom_port._udp.local.";
6720 let instance_custom = "custom_port_instance";
6721 let instance_default = "default_port_instance";
6722 let host_name = "custom_port_host.local.";
6723
6724 let service_ip_addr = my_ip_interfaces(false)
6725 .iter()
6726 .find(|iface| iface.ip().is_ipv4())
6727 .map(|iface| iface.ip())
6728 .expect("Test requires an IPv4 interface");
6729
6730 let service_custom = ServiceInfo::new(
6732 service_type,
6733 instance_custom,
6734 host_name,
6735 service_ip_addr,
6736 8080,
6737 None,
6738 )
6739 .unwrap();
6740
6741 let service_default = ServiceInfo::new(
6743 service_type,
6744 instance_default,
6745 host_name,
6746 service_ip_addr,
6747 8081,
6748 None,
6749 )
6750 .unwrap();
6751
6752 let custom_port = 5454u16;
6754 let server_custom =
6755 ServiceDaemon::new_with_port(custom_port).expect("Failed to create custom port server");
6756 let client_custom =
6757 ServiceDaemon::new_with_port(custom_port).expect("Failed to create custom port client");
6758
6759 let server_default = ServiceDaemon::new().expect("Failed to create default port server");
6761
6762 server_custom
6764 .register(service_custom.clone())
6765 .expect("Failed to register custom port service");
6766
6767 server_default
6769 .register(service_default.clone())
6770 .expect("Failed to register default port service");
6771
6772 let browse_custom = client_custom
6774 .browse(service_type)
6775 .expect("Failed to browse on custom port");
6776
6777 let timeout = Duration::from_secs(3);
6778 let mut found_custom = false;
6779 let mut found_default_on_custom = false;
6780
6781 while let Ok(event) = browse_custom.recv_timeout(timeout) {
6783 if let ServiceEvent::ServiceResolved(info) = event {
6784 println!(
6785 "Custom port client resolved: {} on port {}",
6786 info.get_fullname(),
6787 info.get_port()
6788 );
6789 if info.get_fullname().starts_with(instance_custom) {
6790 found_custom = true;
6791 assert_eq!(info.get_port(), 8080);
6792 }
6793 if info.get_fullname().starts_with(instance_default) {
6794 found_default_on_custom = true;
6795 }
6796 }
6797 }
6798
6799 assert!(
6800 found_custom,
6801 "Custom port client should find service on custom port"
6802 );
6803 assert!(
6804 !found_default_on_custom,
6805 "Custom port client should NOT find service on default port"
6806 );
6807
6808 let client_default = ServiceDaemon::new().expect("Failed to create default port client");
6811 let browse_default = client_default
6812 .browse(service_type)
6813 .expect("Failed to browse on default port");
6814
6815 let mut found_default = false;
6816 let mut found_custom_on_default = false;
6817
6818 while let Ok(event) = browse_default.recv_timeout(timeout) {
6819 if let ServiceEvent::ServiceResolved(info) = event {
6820 println!(
6821 "Default port client resolved: {} on port {}",
6822 info.get_fullname(),
6823 info.get_port()
6824 );
6825 if info.get_fullname().starts_with(instance_default) {
6826 found_default = true;
6827 assert_eq!(info.get_port(), 8081);
6828 }
6829 if info.get_fullname().starts_with(instance_custom) {
6830 found_custom_on_default = true;
6831 }
6832 }
6833 }
6834
6835 assert!(
6836 found_default,
6837 "Default port client should find service on default port"
6838 );
6839 assert!(
6840 !found_custom_on_default,
6841 "Default port client should NOT find service on custom port"
6842 );
6843
6844 server_custom.shutdown().unwrap();
6846 client_custom.shutdown().unwrap();
6847 server_default.shutdown().unwrap();
6848 client_default.shutdown().unwrap();
6849 }
6850
6851 #[test]
6856 fn test_unresolved_instance_not_stranded() {
6857 use socket2::{Domain, Protocol, Socket, Type};
6858 use std::net::SocketAddrV4;
6859
6860 let intf_ip = match my_ip_interfaces(false)
6862 .into_iter()
6863 .find_map(|intf| match intf.ip() {
6864 IpAddr::V4(ip) if !ip.is_loopback() => Some(ip),
6865 _ => None,
6866 }) {
6867 Some(ip) => ip,
6868 None => {
6869 println!("No non-loopback IPv4 interface available; skipping test.");
6870 return;
6871 }
6872 };
6873
6874 let unique = SystemTime::now()
6875 .duration_since(SystemTime::UNIX_EPOCH)
6876 .unwrap()
6877 .as_micros();
6878 let ty_domain = format!("_strandtest{unique}._udp.local.");
6879 let instance = format!("inst.{ty_domain}");
6880 let host = format!("strandhost{unique}.local.");
6883 let port = 1234u16;
6884 let ttl = 4500u32;
6885
6886 let if_id = InterfaceId {
6887 name: "test".to_string(),
6888 index: 0,
6889 };
6890
6891 let sock = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))
6895 .expect("create responder socket");
6896 sock.set_reuse_address(true).expect("set reuse_address");
6897 #[cfg(unix)]
6898 let _ = sock.set_reuse_port(true);
6899 sock.bind(&SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, MDNS_PORT).into())
6900 .expect("bind responder socket");
6901 sock.join_multicast_v4(&GROUP_ADDR_V4, &intf_ip)
6902 .expect("join multicast group");
6903 sock.set_multicast_if_v4(&intf_ip)
6904 .expect("set multicast_if");
6905 sock.set_multicast_loop_v4(true).expect("enable loopback");
6906 sock.set_read_timeout(Some(Duration::from_millis(100)))
6907 .expect("set read timeout");
6908 let responder: UdpSocket = sock.into();
6909
6910 let announce_packets = || {
6912 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6913 out.add_answer_at_time(
6914 DnsPointer::new(&ty_domain, RRType::PTR, CLASS_IN, ttl, instance.clone()),
6915 0,
6916 );
6917 out.add_answer_at_time(
6918 DnsSrv::new(&instance, CLASS_IN, ttl, 0, 0, port, host.clone()),
6919 0,
6920 );
6921 out.to_data_on_wire(MAX_PKT_DEFAULT, true)
6922 };
6923
6924 let addr_packets = || {
6926 let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6927 out.add_answer_at_time(
6928 DnsAddress::new(
6929 &host,
6930 RRType::A,
6931 CLASS_IN,
6932 ttl,
6933 IpAddr::V4(intf_ip),
6934 if_id.clone(),
6935 ),
6936 0,
6937 );
6938 out.to_data_on_wire(MAX_PKT_DEFAULT, true)
6939 };
6940
6941 let send_all = |packets: Vec<Vec<u8>>| {
6942 for packet in packets {
6943 let _ = responder.send_to(&packet, (GROUP_ADDR_V4, MDNS_PORT));
6944 }
6945 };
6946
6947 let daemon = ServiceDaemon::new().expect("create daemon");
6949 let browse_rx = daemon.browse(&ty_domain).expect("start browse");
6950 send_all(announce_packets());
6951
6952 let answer_after = RESOLVE_MAX_TRY as i32;
6958 let mut addr_query_count = 0;
6959 let mut resolved = false;
6960 let mut buf = [0u8; 2048];
6961 let deadline = Instant::now() + Duration::from_secs(20);
6962
6963 while Instant::now() < deadline {
6964 while let Ok((len, from)) = responder.recv_from(&mut buf) {
6966 if from.ip() != IpAddr::V4(intf_ip) {
6971 continue;
6972 }
6973 let Ok(msg) = DnsIncoming::new(buf[..len].to_vec(), if_id.clone()) else {
6974 continue;
6975 };
6976 if msg.is_response() {
6977 continue;
6978 }
6979
6980 let mut saw_addr_query = false;
6981 let mut saw_service_query = false;
6982 for q in msg.questions() {
6983 let qname = q.entry_name();
6984 if qname.eq_ignore_ascii_case(&host)
6985 && matches!(q.entry_type(), RRType::A | RRType::AAAA)
6986 {
6987 saw_addr_query = true;
6988 } else if qname.eq_ignore_ascii_case(&ty_domain)
6989 || qname.eq_ignore_ascii_case(&instance)
6990 {
6991 saw_service_query = true;
6992 }
6993 }
6994
6995 if saw_service_query {
6997 send_all(announce_packets());
6998 }
6999
7000 if saw_addr_query {
7004 addr_query_count += 1;
7005 if addr_query_count > answer_after {
7006 send_all(addr_packets());
7007 }
7008 }
7009 }
7010
7011 while let Ok(event) = browse_rx.try_recv() {
7013 if let ServiceEvent::ServiceResolved(info) = event {
7014 if info.get_fullname().eq_ignore_ascii_case(&instance) {
7015 resolved = true;
7016 }
7017 }
7018 }
7019
7020 if resolved {
7021 break;
7022 }
7023 }
7024
7025 daemon.shutdown().unwrap();
7026
7027 assert!(
7028 addr_query_count > answer_after,
7029 "daemon stopped querying for the address after {} tries; \
7030 an unresolved instance must keep being queried while the browse is active",
7031 addr_query_count
7032 );
7033 assert!(
7034 resolved,
7035 "instance was found but never resolved even though its address was \
7036 eventually answered"
7037 );
7038 }
7039 fn negative_answer_test_daemon() -> (super::Zeroconf, u32) {
7040 let signal = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
7041 let signal_addr = signal.local_addr().unwrap();
7042 signal.set_nonblocking(true).unwrap();
7043 let port = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0))
7044 .unwrap()
7045 .local_addr()
7046 .unwrap()
7047 .port();
7048 let (sender, _receiver) = flume::bounded(100);
7049 let mut daemon = super::Zeroconf::new(
7050 mio::net::UdpSocket::from_std(signal),
7051 mio::Poll::new().unwrap(),
7052 port,
7053 sender,
7054 signal_addr,
7055 );
7056 let index = my_ip_interfaces(true)
7057 .iter()
7058 .find(|intf| intf.ip() == IpAddr::V4(Ipv4Addr::LOCALHOST))
7059 .unwrap()
7060 .index
7061 .unwrap();
7062 daemon.my_intfs.retain(|key, _| *key == index);
7064 daemon.dns_registry_map.retain(|key, _| *key == index);
7065 (daemon, index)
7066 }
7067
7068 fn register_negative_answer_test_service(
7069 daemon: &mut super::Zeroconf,
7070 index: u32,
7071 instance: &str,
7072 address: IpAddr,
7073 ) -> String {
7074 let service = ServiceInfo::new(
7075 "_negative-test._tcp.local.",
7076 instance,
7077 "negative.local.",
7078 address,
7079 8080,
7080 None,
7081 )
7082 .unwrap();
7083 let fullname = service.get_fullname().to_lowercase();
7084 daemon.register_service(service);
7085 for probe in daemon
7087 .dns_registry_map
7088 .get_mut(&index)
7089 .unwrap()
7090 .probing
7091 .values_mut()
7092 {
7093 probe.start_time = crate::current_time_millis() - 1000;
7094 probe.next_send = 0;
7095 }
7096 daemon.probing_handler();
7097 assert_eq!(
7098 daemon.my_services[&fullname].get_status(index),
7099 crate::service_info::ServiceStatus::Announced
7100 );
7101 fullname
7102 }
7103
7104 fn query_negative_answer_test_daemon(
7105 daemon: &mut super::Zeroconf,
7106 index: u32,
7107 name: &str,
7108 types: &[RRType],
7109 ) -> Option<DnsIncoming> {
7110 let querier = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap();
7111 querier
7112 .set_read_timeout(Some(Duration::from_millis(100)))
7113 .unwrap();
7114 let mut out = DnsOutgoing::new(FLAGS_QR_QUERY);
7115 for ty in types {
7116 out.add_question(name, *ty);
7117 }
7118 let interface = InterfaceId {
7119 name: "loopback-test".to_string(),
7120 index,
7121 };
7122 let packets = out.to_data_on_wire(MAX_PKT_DEFAULT, true);
7123 let incoming = DnsIncoming::new(packets[0].clone(), interface.clone()).unwrap();
7124 daemon.handle_query(incoming, index, querier.local_addr().unwrap());
7125 let mut data = [0; 4096];
7126 match querier.recv_from(&mut data) {
7127 Ok((length, _)) => Some(DnsIncoming::new(data[..length].to_vec(), interface).unwrap()),
7128 Err(error)
7129 if matches!(
7130 error.kind(),
7131 std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut
7132 ) =>
7133 {
7134 None
7135 }
7136 Err(error) => panic!("receiving test response: {}", error),
7137 }
7138 }
7139
7140 #[test]
7141 fn test_negative_hostname_answers() {
7142 use super::DnsNSec;
7143 use crate::dns_parser::DnsRecordExt;
7144
7145 for (address, present, absent) in [
7146 (IpAddr::V4(Ipv4Addr::LOCALHOST), RRType::A, RRType::AAAA),
7147 (IpAddr::V6(Ipv6Addr::LOCALHOST), RRType::AAAA, RRType::A),
7148 ] {
7149 let (mut daemon, index) = negative_answer_test_daemon();
7150 let fullname =
7151 register_negative_answer_test_service(&mut daemon, index, "single", address);
7152 for ty in [absent, RRType::SVCB, RRType::HTTPS] {
7153 let reply =
7154 query_negative_answer_test_daemon(&mut daemon, index, "NEGATIVE.local.", &[ty])
7155 .unwrap();
7156 assert_eq!(reply.answers().len(), 1);
7157 let nsec = reply.answers()[0].any().downcast_ref::<DnsNSec>().unwrap();
7158 assert_eq!(nsec._types(), vec![present as u16]);
7159 assert_eq!(nsec.get_name(), "negative.local.");
7160 assert!(nsec.get_record().get_ttl() <= LEGACY_UNICAST_MAX_TTL);
7161 }
7162 for ty in [present, RRType::ANY] {
7163 let reply =
7164 query_negative_answer_test_daemon(&mut daemon, index, "negative.local.", &[ty])
7165 .unwrap();
7166 assert!(reply
7167 .answers()
7168 .iter()
7169 .any(|record| record.get_type() == present));
7170 assert!(reply
7171 .answers()
7172 .iter()
7173 .all(|record| record.get_type() != RRType::NSEC));
7174 }
7175 let mixed = query_negative_answer_test_daemon(
7176 &mut daemon,
7177 index,
7178 "negative.local.",
7179 &[RRType::HTTPS, RRType::AAAA, RRType::A],
7180 )
7181 .unwrap();
7182 assert!(mixed
7183 .answers()
7184 .iter()
7185 .any(|record| record.get_type() == present));
7186 assert!(mixed
7187 .answers()
7188 .iter()
7189 .any(|record| record.get_type() == RRType::NSEC));
7190 assert!(query_negative_answer_test_daemon(
7191 &mut daemon,
7192 index,
7193 "unowned.local.",
7194 &[absent]
7195 )
7196 .is_none());
7197 daemon
7198 .my_services
7199 .get_mut(&fullname)
7200 .unwrap()
7201 .set_status(index, crate::service_info::ServiceStatus::Probing);
7202 assert!(query_negative_answer_test_daemon(
7203 &mut daemon,
7204 index,
7205 "negative.local.",
7206 &[absent]
7207 )
7208 .is_none());
7209 }
7210 }
7211
7212 #[test]
7213 fn test_negative_hostname_answers_combine_registrations_on_one_interface() {
7214 let (mut daemon, index) = negative_answer_test_daemon();
7215 register_negative_answer_test_service(
7216 &mut daemon,
7217 index,
7218 "ipv4",
7219 IpAddr::V4(Ipv4Addr::LOCALHOST),
7220 );
7221 let ipv6 = register_negative_answer_test_service(
7222 &mut daemon,
7223 index,
7224 "ipv6",
7225 IpAddr::V6(Ipv6Addr::LOCALHOST),
7226 );
7227 for ty in [RRType::A, RRType::AAAA] {
7228 let reply =
7229 query_negative_answer_test_daemon(&mut daemon, index, "negative.local.", &[ty])
7230 .unwrap();
7231 assert!(reply.answers().iter().any(|record| record.get_type() == ty));
7232 assert!(reply
7233 .answers()
7234 .iter()
7235 .all(|record| record.get_type() != RRType::NSEC));
7236 }
7237 let reply = query_negative_answer_test_daemon(
7238 &mut daemon,
7239 index,
7240 "negative.local.",
7241 &[RRType::HTTPS],
7242 )
7243 .unwrap();
7244 assert_eq!(reply.answers().len(), 1);
7245 assert_eq!(
7246 reply.answers()[0]
7247 .any()
7248 .downcast_ref::<super::DnsNSec>()
7249 .unwrap()
7250 ._types(),
7251 [1, 28]
7252 );
7253 daemon
7255 .my_services
7256 .get_mut(&ipv6)
7257 .unwrap()
7258 .remove_ipaddr(&IpAddr::V6(Ipv6Addr::LOCALHOST));
7259 daemon
7260 .my_services
7261 .get_mut(&ipv6)
7262 .unwrap()
7263 .insert_ipaddr(&test_interface(
7264 "other",
7265 index + 1,
7266 test_ifaddr_v6("2001:db8::1".parse().unwrap()),
7267 ));
7268 let reply = query_negative_answer_test_daemon(
7269 &mut daemon,
7270 index,
7271 "negative.local.",
7272 &[RRType::AAAA],
7273 )
7274 .unwrap();
7275 assert_eq!(
7276 reply.answers()[0]
7277 .any()
7278 .downcast_ref::<super::DnsNSec>()
7279 .unwrap()
7280 ._types(),
7281 [1]
7282 );
7283 }
7284}