Skip to main content

mdns_sd/
service_daemon.rs

1//! Service daemon for mDNS Service Discovery.
2
3// How DNS-based Service Discovery works in a nutshell:
4//
5// (excerpt from RFC 6763)
6// .... that a particular service instance can be
7//    described using a DNS SRV [RFC2782] and DNS TXT [RFC1035] record.
8//    The SRV record has a name of the form "<Instance>.<Service>.<Domain>"
9//    and gives the target host and port where the service instance can be
10//    reached.  The DNS TXT record of the same name gives additional
11//    information about this instance, in a structured form using key/value
12//    pairs, described in Section 6.  A client discovers the list of
13//    available instances of a given service type using a query for a DNS
14//    PTR [RFC1035] record with a name of the form "<Service>.<Domain>",
15//    which returns a set of zero or more names, which are the names of the
16//    aforementioned DNS SRV/TXT record pairs.
17//
18// Some naming conventions in this source code:
19//
20// `ty_domain` refers to service type together with domain name, i.e. <service>.<domain>.
21// Every <service> consists of two labels: service itself and "_udp." or "_tcp".
22// See RFC 6763 section 7 Service Names.
23//     for example: `_my-service._udp.local.`
24//
25// `fullname` refers to a full Service Instance Name, i.e. <instance>.<service>.<domain>
26//     for example: `my_home._my-service._udp.local.`
27//
28// In mDNS and DNS, the basic data structure is "Resource Record" (RR), where
29// in Service Discovery, the basic data structure is "Service Info". One Service Info
30// corresponds to a set of DNS Resource Records.
31#[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
64/// The default max length of the service name without domain, not including the
65/// leading underscore (`_`). It is set to 15 per
66/// [RFC 6763 section 7.2](https://www.rfc-editor.org/rfc/rfc6763#section-7.2).
67pub const SERVICE_NAME_LEN_MAX_DEFAULT: u8 = 15;
68
69/// The default interval for checking IP changes automatically.
70pub const IP_CHECK_INTERVAL_IN_SECS_DEFAULT: u32 = 5;
71
72/// The default time out for [ServiceDaemon::verify] is 10 seconds, per
73/// [RFC 6762 section 10.4](https://datatracker.ietf.org/doc/html/rfc6762#section-10.4)
74pub const VERIFY_TIMEOUT_DEFAULT: Duration = Duration::from_secs(10);
75
76/// The smallest value accepted by [`ServiceDaemon::set_max_packet_size`].
77pub(crate) const MIN_MAX_PACKET_SIZE: usize = 512;
78
79/// The mDNS port number per RFC 6762.
80pub 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
86/// The first fast-path follow-up resolve query fires this soon after an
87/// instance is found via PTR. Subsequent tries back off exponentially
88/// (200ms, 400ms, 800ms, 1600ms), see `exec_command_resolve`.
89const RESOLVE_RETRY_BASE_MILLIS: u64 = 200;
90
91/// Max number of fast-path resolve tries before the browse retransmission
92/// cycle takes over re-querying (see `query_unresolved_instances`).
93const RESOLVE_MAX_TRY: u16 = 4;
94
95/// RFC 6762 §8.3: the two unsolicited announcements are sent "one second apart".
96/// We schedule the second one strictly wider than the §6 multicast rate-limit
97/// window ([`MULTICAST_RATE_LIMIT_MILLIS`]) so that scheduling skew — the few
98/// millis between capturing this base time and actually stamping the records as
99/// multicast — can never make the rate limit throttle the second announcement
100/// away. A small random jitter is added on top (see `ANNOUNCE_SECOND_JITTER_MILLIS`)
101/// to de-synchronize announcements across hosts and services.
102const ANNOUNCE_SECOND_DELAY_MILLIS: u64 = MULTICAST_RATE_LIMIT_MILLIS + 100;
103
104/// Upper bound (exclusive) of the random jitter added to the second announcement
105/// delay. Kept small so the spacing stays close to the RFC's "one second".
106const ANNOUNCE_SECOND_JITTER_MILLIS: u64 = 50;
107
108// The §8.3 announcement spacing MUST stay strictly wider than the §6 rate-limit
109// window, or the rate limit throttles the second announcement away (leaving only
110// one unsolicited response). Enforced at compile time so the two can't drift.
111#[allow(clippy::assertions_on_constants)]
112const _: () = assert!(ANNOUNCE_SECOND_DELAY_MILLIS > MULTICAST_RATE_LIMIT_MILLIS);
113
114/// RFC 6762 §6:
115/// In any case where there may be multiple responses, such as queries
116/// where the answer is a member of a shared resource record set, each
117/// responder SHOULD delay its response by a random amount of time
118/// selected with uniform random distribution in the range 20-120 ms.
119///
120/// 20ms suggested in the RFC is a bit too long for min. Use 10ms instead.
121const SHARED_RESPONSE_DELAY_MIN_MILLIS: u64 = 10;
122
123/// 120ms suggested in the RFC is too long for max, use 50ms instead.
124const SHARED_RESPONSE_DELAY_MAX_MILLIS: u64 = 50;
125
126/// RFC 6762 §5.2: to avoid accidental synchronization when multiple clients
127/// begin querying at exactly the same moment (e.g. because of some common
128/// external trigger event), a querier SHOULD delay the first query of a
129/// continuous-monitoring series by a randomly chosen amount in the range
130/// 20-120 ms.
131///
132/// Like the responder delay above, we use a shorter 10-50 ms window.
133const INITIAL_QUERY_DELAY_MIN_MILLIS: u64 = 10;
134const INITIAL_QUERY_DELAY_MAX_MILLIS: u64 = 50;
135
136/// Response status code for the service `unregister` call.
137#[derive(Debug)]
138pub enum UnregisterStatus {
139    /// Unregister was successful.
140    OK,
141    /// The service was not found in the registration.
142    NotFound,
143}
144
145/// Status code for the service daemon.
146#[derive(Debug, PartialEq, Clone, Eq)]
147#[non_exhaustive]
148pub enum DaemonStatus {
149    /// The daemon is running as normal.
150    Running,
151
152    /// The daemon has been shutdown.
153    Shutdown,
154}
155
156/// Different counters included in the metrics.
157/// Currently all counters are for outgoing packets.
158#[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
228/// A wrapper around UDP socket used by the mDNS daemon.
229///
230/// We do this because `mio` does not support PKTINFO and
231/// does not provide a way to implement `Source` trait directly and safely.
232struct MyUdpSocket {
233    /// The underlying socket that supports control messages like
234    /// `IP_PKTINFO` for IPv4 and `IPV6_PKTINFO` for IPv6.
235    pktinfo: PktInfoUdpSocket,
236
237    /// The mio UDP socket that is a clone of `pktinfo` and
238    /// is used for event polling.
239    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
251/// Implements the mio `Source` trait so that we can use `MyUdpSocket` with `Poll`.
252impl 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
276/// The metrics is a HashMap of (name_key, i64_value).
277/// The main purpose is to help monitoring the mDNS packet traffic.
278pub type Metrics = HashMap<String, i64>;
279
280const IPV4_SOCK_EVENT_KEY: usize = 4; // Pick a key just to indicate IPv4.
281const IPV6_SOCK_EVENT_KEY: usize = 6; // Pick a key just to indicate IPv6.
282const SIGNAL_SOCK_EVENT_KEY: usize = usize::MAX - 1; // avoid to overlap with zc.poll_ids
283
284/// A daemon thread for mDNS
285///
286/// This struct provides a handle and an API to the daemon. It is cloneable.
287#[derive(Clone)]
288pub struct ServiceDaemon {
289    /// Sender handle of the channel to the daemon.
290    sender: Sender<Command>,
291
292    /// Send to this addr to signal that a `Command` is coming.
293    ///
294    /// The daemon listens on this addr together with other mDNS sockets,
295    /// to avoid busy polling the flume channel. If there is a way to poll
296    /// the channel and mDNS sockets together, then this can be removed.
297    signal_addr: SocketAddr,
298}
299
300impl ServiceDaemon {
301    /// Creates a new daemon and spawns a thread to run the daemon.
302    ///
303    /// Creates a new mDNS service daemon using the default port (5353).
304    ///
305    /// For development/testing with custom ports, use [`ServiceDaemon::new_with_port`].
306    ///
307    /// # Errors
308    ///
309    /// Returns [`Error::Msg`] if the daemon cannot be initialized. This wraps an
310    /// underlying OS-level failure.
311    ///
312    /// Note that this constructor does not open the mDNS multicast sockets — those
313    /// are opened lazily by the daemon thread once it starts, so platform issues
314    /// such as "multicast not permitted" are surfaced later via [`DaemonEvent`] from
315    /// [`monitor`](Self::monitor) rather than here.
316    pub fn new() -> Result<Self> {
317        Self::new_with_port(MDNS_PORT)
318    }
319
320    /// Creates a new mDNS service daemon using a custom port.
321    ///
322    /// # Arguments
323    ///
324    /// * `port` - The UDP port to bind for mDNS communication.
325    ///   - In production, this should be `MDNS_PORT` (5353) per RFC 6762.
326    ///   - For development/testing, you can use a non-standard port (e.g., 5454)
327    ///     to avoid conflicts with system mDNS services.
328    ///   - Both publisher and browser must use the same port to communicate.
329    ///
330    /// # Example
331    ///
332    /// ```no_run
333    /// use mdns_sd::ServiceDaemon;
334    ///
335    /// // Use standard mDNS port (production)
336    /// let daemon = ServiceDaemon::new_with_port(5353)?;
337    ///
338    /// // Use custom port for development (avoids macOS Bonjour conflict)
339    /// let daemon_dev = ServiceDaemon::new_with_port(5454)?;
340    /// # Ok::<(), mdns_sd::Error>(())
341    /// ```
342    ///
343    /// # Errors
344    ///
345    /// See [`new`](Self::new) for the set of OS-level failures that may surface
346    /// here. Note that `port` is *not* validated against the kernel until the
347    /// daemon thread tries to bind the mDNS sockets, so an unusable `port`
348    /// (e.g., already in use, requires elevated privileges) will not be
349    /// reported by this constructor — listen for such failures via
350    /// [`monitor`](Self::monitor).
351    pub fn new_with_port(port: u16) -> Result<Self> {
352        // Use port 0 to allow the system assign a random available port,
353        // no need for a pre-defined port number.
354        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        // Get the socket with the OS chosen port
360        let signal_addr = signal_sock
361            .local_addr()
362            .map_err(|e| e_fmt!("failed to get signal sock addr: {}", e))?;
363
364        // Must be nonblocking so we can listen to it together with mDNS sockets.
365        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        // Spawn the daemon thread
374        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    /// Sends `cmd` to the daemon via its channel, and sends a signal
390    /// to its sock addr to notify.
391    fn send_cmd(&self, cmd: Command) -> Result<()> {
392        let cmd_name = cmd.to_string();
393
394        // First, send to the flume channel.
395        self.sender.try_send(cmd).map_err(|e| match e {
396            TrySendError::Full(_) => Error::Again,
397            TrySendError::Disconnected(_) => Error::DaemonShutdown,
398        })?;
399
400        // Second, send a signal to notify the daemon.
401        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    /// Starts browsing for a specific service type.
419    ///
420    /// `service_type` must end with a valid mDNS domain: '._tcp.local.' or '._udp.local.'
421    ///
422    /// Returns a channel `Receiver` to receive events about the service. The caller
423    /// can call `.recv_async().await` on this receiver to handle events in an
424    /// async environment or call `.recv()` in a sync environment.
425    ///
426    /// When a new instance is found, the daemon automatically tries to resolve, i.e.
427    /// finding more details, i.e. SRV records and TXT records.
428    ///
429    /// # Errors
430    ///
431    /// Returns [`Error::Msg`] if `service_type` does not end with
432    /// `._tcp.local.` or `._udp.local.`.
433    ///
434    /// Returns [`Error::Again`] if the daemon's command queue is full.
435    ///
436    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
437    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    /// Preforms a "cache-only" browse.
446    ///
447    /// `service_type` must end with a valid mDNS domain: '._tcp.local.' or '._udp.local.'
448    ///
449    /// The functionality is identical to 'browse', but the service events are based solely on the contents
450    /// of the daemon's cache. No actual mDNS query is sent to the network.
451    ///
452    /// See [accept_unsolicited](Self::accept_unsolicited) if you want to do cache-only browsing.
453    ///
454    /// # Errors
455    ///
456    /// Same error conditions as [`browse`](Self::browse).
457    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    /// Stops searching for a specific service type.
466    ///
467    /// # Errors
468    ///
469    /// Returns [`Error::Again`] if the daemon's command queue is full.
470    ///
471    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
472    pub fn stop_browse(&self, ty_domain: &str) -> Result<()> {
473        self.send_cmd(Command::StopBrowse(ty_domain.to_string()))
474    }
475
476    /// Starts querying for the ip addresses of a hostname.
477    ///
478    /// Returns a channel `Receiver` to receive events about the hostname.
479    /// The caller can call `.recv_async().await` on this receiver to handle events in an
480    /// async environment or call `.recv()` in a sync environment.
481    ///
482    /// The `timeout` is specified in milliseconds.
483    ///
484    /// # Errors
485    ///
486    /// Returns [`Error::Msg`] if:
487    ///
488    /// - `hostname` does not end with `.local.`;
489    /// - `hostname` is exactly `.local.` (the label before `.local.` is empty);
490    /// - `hostname` is longer than 255 bytes.
491    ///
492    /// Returns [`Error::Again`] if the daemon's command queue is full.
493    ///
494    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
495    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    /// Stops querying for the ip addresses of a hostname.
512    ///
513    /// # Errors
514    ///
515    /// Same error conditions as [`stop_browse`](Self::stop_browse).
516    pub fn stop_resolve_hostname(&self, hostname: &str) -> Result<()> {
517        self.send_cmd(Command::StopResolveHostname(hostname.to_string()))
518    }
519
520    /// Registers a service provided by this host.
521    ///
522    /// If `service_info` has no addresses yet and its `addr_auto` is enabled,
523    /// this method will automatically fill in addresses from the host.
524    ///
525    /// To re-announce a service with an updated `service_info`, just call
526    /// this `register` function again. No need to call `unregister` first.
527    ///
528    /// # Errors
529    ///
530    /// Returns [`Error::Msg`] if the [`ServiceInfo`] is malformed, for example:
531    ///
532    /// - the fullname does not end with `._tcp.local.` or `._udp.local.`;
533    /// - the hostname does not end with `.local.`, is exactly `.local.`, or
534    ///   is longer than 255 bytes.
535    ///
536    /// Returns [`Error::Again`] if the daemon's command queue is full.
537    ///
538    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
539    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    /// Unregisters a service. This is a graceful shutdown of a service.
547    ///
548    /// Returns a channel receiver that is used to receive the status code
549    /// of the unregister.
550    ///
551    /// # Errors
552    ///
553    /// Returns [`Error::Again`] if the daemon's command queue is full.
554    ///
555    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
556    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    /// Starts to monitor events from the daemon.
563    ///
564    /// Returns a channel [`Receiver`] of [`DaemonEvent`].
565    ///
566    /// # Errors
567    ///
568    /// Returns [`Error::Again`] if the daemon's command queue is full.
569    ///
570    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
571    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    /// Shuts down the daemon thread and returns a channel to receive the status.
578    ///
579    /// # Errors
580    ///
581    /// Returns [`Error::Again`] if the daemon's command queue is full.
582    ///
583    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
584    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    /// Returns the status of the daemon.
591    ///
592    /// # Errors
593    ///
594    /// Returns [`Error::Again`] if the daemon's command queue is full.
595    ///
596    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
597    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    /// Returns a channel receiver for the metrics, e.g. input/output counters.
612    ///
613    /// The metrics returned is a snapshot. Hence the caller should call
614    /// this method repeatedly if they want to monitor the metrics continuously.
615    ///
616    /// # Errors
617    ///
618    /// Returns [`Error::Again`] if the daemon's command queue is full.
619    ///
620    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
621    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    /// Change the max length allowed for a service name.
628    ///
629    /// As RFC 6763 defines a length max for a service name, a user should not call
630    /// this method unless they have to. See [`SERVICE_NAME_LEN_MAX_DEFAULT`].
631    ///
632    /// `len_max` is capped at an internal limit, which is currently 30.
633    ///
634    /// # Errors
635    ///
636    /// Returns [`Error::Msg`] if `len_max` exceeds the internal cap (30).
637    ///
638    /// Returns [`Error::Again`] if the daemon's command queue is full.
639    ///
640    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
641    pub fn set_service_name_len_max(&self, len_max: u8) -> Result<()> {
642        const SERVICE_NAME_LEN_MAX_LIMIT: u8 = 30; // Double the default length max.
643
644        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    /// Change the max byte size of a packet this daemon generates on the interfaces
654    /// matching `if_kind`. Use `IfKind::All` to change it on every interface. Messages
655    /// that don't fit are split across multiple packets. A single record that doesn't
656    /// fit in a packet is sent alone in a packet of up to 8952 bytes over IPv6 or 8972
657    /// bytes over IPv4, per RFC 6762 section 17.
658    ///
659    /// The default is `MAX_PKT_DEFAULT` (1452 bytes), small enough to fit in one
660    /// Ethernet frame over either IPv4 or IPv6.
661    ///
662    /// `size` must be in the range `512..=8952`. The minimum of 512 bytes is the classic
663    /// UDP DNS message size of RFC 1035. The maximum of 8952 bytes follows from RFC 6762
664    /// section 17, which caps an mDNS packet at 9000 bytes: we subtract the
665    /// bigger of the two IP headers so that a generated packet is legal over either
666    /// IP version.
667    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    /// Change the interval for checking IP changes automatically.
688    ///
689    /// Setting the interval to 0 disables the IP check.
690    ///
691    /// See [`IP_CHECK_INTERVAL_IN_SECS_DEFAULT`] for the default interval.
692    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    /// Get the current interval in seconds for checking IP changes automatically.
700    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    /// Include interfaces that match `if_kind` for this service daemon.
712    ///
713    /// For example:
714    /// ```ignore
715    ///     daemon.enable_interface("en0")?;
716    /// ```
717    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    /// Ignore/exclude interfaces that match `if_kind` for this daemon.
725    ///
726    /// For example:
727    /// ```ignore
728    ///     daemon.disable_interface(IfKind::IPv6)?;
729    /// ```
730    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    /// If `accept` is true, accept and cache all responses, even if there is no active querier
738    /// for a given service type. This is useful / necessary when doing cache-only browsing. See
739    /// [browse_cache](Self::browse_cache).
740    ///
741    /// If `accept` is false (default), accept only responses matching queries that we have initiated.
742    ///
743    /// For example:
744    /// ```ignore
745    ///     daemon.accept_unsolicited(true)?;
746    /// ```
747    pub fn accept_unsolicited(&self, accept: bool) -> Result<()> {
748        self.send_cmd(Command::SetOption(DaemonOption::AcceptUnsolicited(accept)))
749    }
750
751    /// Include or exclude Apple P2P interfaces, e.g. "awdl0", "llw0".
752    /// By default, they are excluded.
753    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    /// Enable or disable the loopback for locally sent multicast packets in IPv4.
772    ///
773    /// By default, multicast loop is enabled for IPv4. When disabled, a querier will not
774    /// receive announcements from a responder on the same host.
775    ///
776    /// Reference: <https://learn.microsoft.com/en-us/windows/win32/winsock/ip-multicast-2>
777    ///
778    /// "The Winsock version of the IP_MULTICAST_LOOP option is semantically different than
779    /// the UNIX version of the IP_MULTICAST_LOOP option:
780    ///
781    /// In Winsock, the IP_MULTICAST_LOOP option applies only to the receive path.
782    /// In the UNIX version, the IP_MULTICAST_LOOP option applies to the send path."
783    ///
784    /// Which means, in order NOT to receive localhost announcements, you want to call
785    /// this API on the querier side on Windows, but on the responder side on Unix.
786    pub fn set_multicast_loop_v4(&self, on: bool) -> Result<()> {
787        self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV4(on)))
788    }
789
790    /// Enable or disable the loopback for locally sent multicast packets in IPv6.
791    ///
792    /// By default, multicast loop is enabled for IPv6. When disabled, a querier will not
793    /// receive announcements from a responder on the same host.
794    ///
795    /// Reference: <https://learn.microsoft.com/en-us/windows/win32/winsock/ip-multicast-2>
796    ///
797    /// "The Winsock version of the IP_MULTICAST_LOOP option is semantically different than
798    /// the UNIX version of the IP_MULTICAST_LOOP option:
799    ///
800    /// In Winsock, the IP_MULTICAST_LOOP option applies only to the receive path.
801    /// In the UNIX version, the IP_MULTICAST_LOOP option applies to the send path."
802    ///
803    /// Which means, in order NOT to receive localhost announcements, you want to call
804    /// this API on the querier side on Windows, but on the responder side on Unix.
805    pub fn set_multicast_loop_v6(&self, on: bool) -> Result<()> {
806        self.send_cmd(Command::SetOption(DaemonOption::MulticastLoopV6(on)))
807    }
808
809    /// Proactively confirms whether a service instance still valid.
810    ///
811    /// This call will issue queries for a service instance's SRV record and Address records.
812    ///
813    /// For `timeout`, most users should use [VERIFY_TIMEOUT_DEFAULT]
814    /// unless there is a reason not to follow RFC.
815    ///
816    /// If no response is received within `timeout`, the current resource
817    /// records will be flushed, and if needed, `ServiceRemoved` event will be
818    /// sent to active queriers.
819    ///
820    /// Reference: [RFC 6762](https://datatracker.ietf.org/doc/html/rfc6762#section-10.4)
821    ///
822    /// # Errors
823    ///
824    /// Returns [`Error::Again`] if the daemon's command queue is full.
825    ///
826    /// Returns [`Error::DaemonShutdown`] if the daemon thread has already exited.
827    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                    // It is guaranteed that the receiver already dropped,
845                    // i.e. the daemon command channel closed.
846                    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
858/// Creates a new UDP socket that uses `intf` to send and recv multicast.
859fn _new_socket_bind(intf: &Interface, should_loop: bool) -> Result<MyUdpSocket> {
860    // Use the same socket for receiving and sending multicast packets.
861    // Such socket has to bind to INADDR_ANY or IN6ADDR_ANY.
862    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            // Join mDNS group to receive packets.
869            sock.join_multicast_v4(&GROUP_ADDR_V4, ip)
870                .map_err(|e| e_fmt!("join multicast group on addr {}: {}", intf_ip, e))?;
871
872            // Set IP_MULTICAST_IF to send packets.
873            sock.set_multicast_if_v4(ip)
874                .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
875
876            // Per RFC 6762 section 11:
877            // "All Multicast DNS responses (including responses sent via unicast) SHOULD
878            // be sent with IP TTL set to 255."
879            // Here we set the TTL to 255 for multicast as we don't support unicast yet.
880            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            // Test if we can send packets successfully.
889            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            // Join mDNS group to receive packets.
905            sock.join_multicast_v6(&GROUP_ADDR_V6, if_index)
906                .map_err(|e| e_fmt!("join multicast group on addr {}: {}", ip, e))?;
907
908            // Set IPV6_MULTICAST_IF to send packets.
909            sock.set_multicast_if_v6(if_index)
910                .map_err(|e| e_fmt!("set multicast_if on addr {}: {}", ip, e))?;
911
912            // We are not sending multicast packets to test this socket as there might
913            // be many IPv6 interfaces on a host and could cause such send error:
914            // "No buffer space available (os error 55)".
915
916            MyUdpSocket::new(sock)
917                .map_err(|e| e_fmt!("failed to create MySocket for interface {}: {e}", intf.name))
918        }
919    }
920}
921
922/// Creates a new UDP socket to bind to `port` with REUSEPORT option.
923/// `non_block` indicates whether to set O_NONBLOCK for the socket.
924fn 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
954/// Specify a UNIX timestamp in millis to run `command` for the next time.
955struct ReRun {
956    /// UNIX timestamp in millis.
957    next_time: u64,
958    command: Command,
959}
960
961/// A query response deferred per RFC 6762 §6 (shared response).
962struct DelayedResponse {
963    /// UNIX timestamp in millis at which to send `out`.
964    next_time: u64,
965    out: DnsOutgoing,
966    if_index: u32,
967    is_ipv4: bool,
968}
969
970/// Specify kinds of interfaces. It is used to enable or to disable interfaces in the daemon.
971///
972/// Note that for ergonomic reasons, `From<&str>` and `From<IpAddr>` are implemented.
973#[derive(Debug, Clone)]
974#[non_exhaustive]
975pub enum IfKind {
976    /// All interfaces.
977    All,
978
979    /// All IPv4 interfaces.
980    IPv4,
981
982    /// All IPv6 interfaces.
983    IPv6,
984
985    /// By the interface name, for example "en0"
986    Name(String),
987
988    /// By an IPv4 or IPv6 address.
989    /// This is used to look up the interface. The semantics is to identify an interface of
990    /// IPv4 or IPv6, not a specific address on the interface.
991    Addr(IpAddr),
992
993    /// 127.0.0.1 (or anything in 127.0.0.0/8), enabled by default.
994    ///
995    /// Loopback interfaces are required by some use cases (e.g., OSCQuery) for publishing.
996    LoopbackV4,
997
998    /// ::1/128, enabled by default.
999    LoopbackV6,
1000
1001    /// By interface index, IPv4 only.
1002    IndexV4(u32),
1003
1004    /// By interface index, IPv6 only.
1005    IndexV6(u32),
1006
1007    /// By a user-supplied predicate function.
1008    Predicate(IfPredicate),
1009}
1010
1011impl IfKind {
1012    /// Checks if `intf` matches with this interface kind.
1013    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
1029/// The first use case of specifying an interface was to
1030/// use an interface name. Hence adding this for ergonomic reasons.
1031impl 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
1043/// Still for ergonomic reasons.
1044impl From<IpAddr> for IfKind {
1045    fn from(val: IpAddr) -> Self {
1046        Self::Addr(val)
1047    }
1048}
1049
1050/// A list of `IfKind` that can be used to match interfaces.
1051pub struct IfKindVec {
1052    kinds: Vec<IfKind>,
1053}
1054
1055/// A trait that converts a type into a Vec of `IfKind`.
1056pub 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/// A predicate function for matching against interfaces.
1077#[derive(Clone)]
1078pub struct IfPredicate(std::sync::Arc<dyn Fn(&Interface) -> bool + Send + Sync>);
1079
1080impl IfPredicate {
1081    /// Creates a predicate from a closure that decides whether an interface
1082    /// matches.
1083    ///
1084    /// # Example
1085    ///
1086    /// ```no_run
1087    /// # use mdns_sd::IfPredicate;
1088    /// // Match any interface that doesn't look like a virtual bridge
1089    /// IfPredicate::new(|intf| !intf.name.starts_with("virbr"));
1090    /// ```
1091    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
1106/// Selection of interfaces.
1107struct IfSelection {
1108    /// The interfaces to be selected.
1109    if_kind: IfKind,
1110
1111    /// Whether the `if_kind` should be enabled or not.
1112    selected: bool,
1113}
1114
1115/// Selection of the max packet size of interfaces.
1116struct MaxPacketSizeSelection {
1117    /// The interfaces to be selected.
1118    if_kind: IfKind,
1119
1120    /// Max byte size of a packet generated for the selected interfaces.
1121    max_packet_size: usize,
1122}
1123
1124/// A struct holding the state. It was inspired by `zeroconf` package in Python.
1125struct Zeroconf {
1126    /// The mDNS port number to use for socket binding.
1127    /// Typically MDNS_PORT (5353), but can be customized for development/testing.
1128    port: u16,
1129
1130    /// Local interfaces keyed by interface index.
1131    my_intfs: HashMap<u32, MyIntf>,
1132
1133    /// A common socket for IPv4 interfaces. It's None if IPv4 is disabled in OS kernel.
1134    ipv4_sock: Option<MyUdpSocket>,
1135
1136    /// A common socket for IPv6 interfaces. It's None if IPv6 is disabled in OS kernel.
1137    ipv6_sock: Option<MyUdpSocket>,
1138
1139    /// Local registered services, keyed by service full names.
1140    my_services: HashMap<String, ServiceInfo>,
1141
1142    /// Received DNS records.
1143    cache: DnsCache,
1144
1145    /// Registered service records, keyed by interface index.
1146    dns_registry_map: HashMap<u32, DnsRegistry>,
1147
1148    /// Active "Browse" commands.
1149    service_queriers: HashMap<String, Sender<ServiceEvent>>, // <ty_domain, channel::sender>
1150
1151    /// Active "ResolveHostname" commands.
1152    ///
1153    /// The timestamps are set at the future timestamp when the command should timeout.
1154    /// `hostname` is case-insensitive and stored in lowercase.
1155    hostname_resolvers: HashMap<String, (Sender<HostnameResolutionEvent>, Option<u64>)>, // <hostname, (channel::sender, UNIX timestamp in millis)>
1156
1157    /// All repeating transmissions.
1158    retransmissions: Vec<ReRun>,
1159
1160    /// Query responses deferred per RFC 6762 §6.
1161    delayed_responses: Vec<DelayedResponse>,
1162
1163    counters: Metrics,
1164
1165    /// Waits for incoming packets.
1166    poller: Poll,
1167
1168    /// Channels to notify events.
1169    monitors: Vec<Sender<DaemonEvent>>,
1170
1171    /// Options
1172    service_name_len_max: u8,
1173
1174    /// Interval in millis to check IP address changes.
1175    ip_check_interval: u64,
1176
1177    /// All max packet size selections called to the daemon, in call order.
1178    /// For an interface matched by more than one, the last one wins.
1179    max_packet_sizes: Vec<MaxPacketSizeSelection>,
1180
1181    /// All interface selections called to the daemon.
1182    if_selections: Vec<IfSelection>,
1183
1184    /// Socket for signaling.
1185    signal_sock: MioUdpSocket,
1186
1187    /// Timestamps marking where we need another iteration of the run loop,
1188    /// to react to events like retransmissions, cache refreshes, interface IP address changes, etc.
1189    ///
1190    /// When the run loop goes through a single iteration, it will
1191    /// set its timeout to the earliest timer in this list.
1192    timers: BinaryHeap<Reverse<u64>>,
1193
1194    status: DaemonStatus,
1195
1196    /// Service instances that are pending for resolving SRV and TXT.
1197    pending_resolves: HashSet<String>,
1198
1199    /// Service instances that are already resolved.
1200    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
1218/// Join the multicast group for the given interface.
1219fn join_multicast_group(my_sock: &PktInfoUdpSocket, intf: &Interface) -> Result<()> {
1220    let intf_ip = &intf.ip();
1221    match intf_ip {
1222        IpAddr::V4(ip) => {
1223            // Join mDNS group to receive packets.
1224            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            // Join mDNS group to receive packets.
1232            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        // Get interfaces.
1253        let my_ifaddrs = my_ip_interfaces(true);
1254
1255        // Create a socket for every IP addr.
1256        // Note: it is possible that `my_ifaddrs` contains the same IP addr with different interface names,
1257        // or the same interface name with different IP addrs.
1258        let mut my_intfs = HashMap::new();
1259        let mut dns_registry_map = HashMap::new();
1260
1261        // Use the same socket for receiving and sending multicast packets.
1262        // Such socket has to bind to INADDR_ANY or IN6ADDR_ANY.
1263        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                // Per RFC 6762 section 11:
1268                // "All Multicast DNS responses (including responses sent via unicast) SHOULD
1269                // be sent with IP TTL set to 255."
1270                // Here we set the TTL to 255 for multicast as we don't support unicast yet.
1271                sock.set_multicast_ttl_v4(255)
1272                    .map_err(|e| e_fmt!("set set_multicast_ttl_v4 on addr: {}", e))
1273                    .ok();
1274
1275                // This clones a socket.
1276                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            // Per RFC 6762 section 11:}
1285            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                // Per RFC 6762 section 11:
1293                // "All Multicast DNS responses (including responses sent via unicast) SHOULD
1294                // be sent with IP TTL set to 255."
1295                sock.set_multicast_hops_v6(255)
1296                    .map_err(|e| e_fmt!("set set_multicast_hops_v6: {}", e))
1297                    .ok();
1298
1299                // This clones the ipv6 socket.
1300                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        // Configure sockets to join multicast groups.
1312        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            // Add this interface address if not already present.
1334            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        // Enable everything, including loopback interfaces.
1359        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    /// Send a Command into the daemon channel and poke the signal socket to wake the poll loop.
1400    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    /// Clean up all resources before shutdown.
1426    ///
1427    /// This method:
1428    /// 1. Unregisters all registered services (sends goodbye packets)
1429    /// 2. Stops all active browse operations
1430    /// 3. Stops all active hostname resolution operations
1431    /// 4. Clears all retransmissions
1432    /// 5. Drops all pending delayed responses
1433    fn cleanup(&mut self) {
1434        debug!("Starting cleanup for shutdown");
1435
1436        // 1. Unregister all services - send goodbye packets
1437        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        // 2. Stop all browse operations
1456        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                // Notify the client
1461                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        // 3. Stop all hostname resolution operations
1468        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                // Notify the client
1476                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        // 4. Clear all retransmissions
1488        self.retransmissions.clear();
1489
1490        // 5. Drop any pending delayed responses
1491        self.delayed_responses.clear();
1492
1493        debug!("Cleanup completed");
1494    }
1495
1496    /// The main event loop of the daemon thread
1497    ///
1498    /// In each round, it will:
1499    /// 1. select the listening sockets with a timeout.
1500    /// 2. process the incoming packets if any.
1501    /// 3. try_recv on its channel and execute commands.
1502    /// 4. announce its registered services.
1503    /// 5. process retransmissions if any.
1504    fn run(&mut self, receiver: Receiver<Command>) -> Option<Command> {
1505        // Add the daemon's signal socket to the poller.
1506        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        // Setup timer for IP checks.
1538        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        // Start the run loop.
1549
1550        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                // If `timer` already passed, set `timeout` to be 1ms.
1557                let millis = if timer > now { timer - now } else { 1 };
1558                Duration::from_millis(millis)
1559            });
1560
1561            // Process incoming packets, command events and optional timeout.
1562            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            // Remove the timers if already passed.
1571            self.pop_timers_till(now);
1572
1573            // Remove hostname resolvers with expired timeouts.
1574            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            // process commands from the command channel
1596            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            // check for repeated commands and run them if their time is up.
1607            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            // Send delayed responses whose time is up (RFC 6762 §6).
1618            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            // Refresh cached service records with active queriers
1629            self.refresh_active_services();
1630
1631            // Refresh cached A/AAAA records with active queriers
1632            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            // check and evict expired records in our cache
1645            let now = current_time_millis();
1646
1647            // Notify service listeners about the expired records.
1648            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            // Notify hostname listeners about the expired records.
1658            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            // Send out probing queries.
1671            self.probing_handler();
1672
1673            // check IP changes if next_ip_check is reached.
1674            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    /// Resolve all max packet size selections against `interfaces` and store the
1748    /// outcome in every interface in `my_intfs`.
1749    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        // Only retain the monitors that are still connected.
1800        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; // This monitor is dropped.
1805                }
1806            }
1807            true
1808        });
1809    }
1810
1811    /// Remove `addr` in my services that enabled `addr_auto`.
1812    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    /// Pop all timers that are already passed till `now`.
1833    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    /// Apply all selections to `interfaces` and return the selected addresses.
1843    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        // apply if_selections
1848        for selection in self.if_selections.iter() {
1849            // Mark the interfaces for this selection.
1850            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    /// Apply all selections to `interfaces`.
1868    ///
1869    /// For any interface, add it if selected but not bound yet,
1870    /// delete it if not selected but still bound.
1871    fn apply_intf_selections(&mut self, interfaces: Vec<Interface>) {
1872        // By default, we enable all interfaces.
1873        let intf_count = interfaces.len();
1874        let mut intf_selections = vec![true; intf_count];
1875
1876        // apply if_selections
1877        for selection in self.if_selections.iter() {
1878            // Mark the interfaces for this selection.
1879            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        // Update `my_intfs` based on the selections.
1887        for (idx, intf) in interfaces.iter().enumerate() {
1888            if intf_selections[idx] {
1889                // Add the interface
1890                self.add_interface(intf, &interfaces);
1891            } else {
1892                // Remove the interface
1893                self.del_interface_addr(intf);
1894            }
1895        }
1896
1897        // An interface that lost an address may now match a different selection.
1898        // (`add_interface` already resolved the ones that gained one.)
1899        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    /// Check for IP changes and update [my_intfs] as needed.
1908    fn check_ip_changes(&mut self) {
1909        // Get the current interfaces.
1910        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                // If it does not exist, remove the interface.
1950                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            // Remove cache records for this interface.
2004            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        // Add newly found interfaces only if in our selections.
2014        self.apply_intf_selections(my_ifaddrs);
2015    }
2016
2017    /// Remove an interface address when it was down, disabled or removed from the system.
2018    /// If no more addresses on the interface, remove the interface as well.
2019    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                // If no more addresses, remove the interface.
2065                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                // Interface still has addresses of the other IP version.
2072                // Remove cached address records for the disabled IP version
2073                // only if no more addresses of that version remain.
2074                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            // Notify the monitors.
2089            self.notify_monitors(DaemonEvent::IpDel(intf.ip()));
2090            // Remove the interface from my services that enabled `addr_auto`.
2091            self.del_addr_in_my_services(&intf.ip());
2092        }
2093    }
2094
2095    /// Adds the address of `intf` and brings our services up on it.
2096    ///
2097    /// Note: this `interface` type only contains one address.
2098    ///
2099    /// Does nothing if the address is already known. Otherwise it joins the
2100    /// multicast group on the interface and, for each `addr_auto` service, adds
2101    /// the address (when supported) and announces the service, marking it as
2102    /// probing when it cannot be announced yet. It then re-sends the active
2103    /// browse queries on the new interface and notifies monitors with
2104    /// `DaemonEvent::IpAdd`.
2105    ///
2106    /// `interfaces` is the full list the caller is applying, needed to resolve the
2107    /// max packet size of the interface before we send anything on it.
2108    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                // If intf has a new address, add it to the existing interface.
2130                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        // Resolve before announcing, so the first packet out already honors it.
2165        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                    // Skip an unsupported address. Should not try to announce it.
2189                    // Otherwise could demote an already announced service into probing.
2190                    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        // Send browse queries on the new interface without known answers.
2216        // This avoids known-answer suppression (RFC 6762 Section 7.1) that
2217        // would cause the responder to suppress its response, preventing
2218        // address records from being attributed to the new interface.
2219        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        // Notify the monitors.
2226        self.notify_monitors(DaemonEvent::IpAdd(intf.ip()));
2227    }
2228
2229    /// Registers a service.
2230    ///
2231    /// RFC 6762 section 8.3.
2232    /// ...the Multicast DNS responder MUST send
2233    ///    an unsolicited Multicast DNS response containing, in the Answer
2234    ///    Section, all of its newly registered resource records
2235    ///
2236    /// Zeroconf will then respond to requests for information about this service.
2237    fn register_service(&mut self, mut info: ServiceInfo) {
2238        // Check the service name length.
2239        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        // The key has to be lower case letter as DNS record name is case insensitive.
2264        // The info will have the original name.
2265        let service_fullname = info.get_fullname().to_lowercase();
2266        self.my_services.insert(service_fullname, info);
2267    }
2268
2269    /// Sends out announcement of `info` on every valid interface.
2270    /// Returns the list of interface IPs that sent out the announcement.
2271    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            // IPv4
2289            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        // RFC 6762 section 8.3.
2348        // ..The Multicast DNS responder MUST send at least two unsolicited
2349        //    responses, one second apart.
2350        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    /// Send probings or finish them if expired. Notify waiting services.
2364    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            // send probing.
2376            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            // For finished probes, wake up services that are waiting for the probes.
2395            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                // service names are lowercase
2400                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        // Goodbye records must carry the names peers actually cached: if
2480        // probing renamed a record on this interface, withdraw the renamed
2481        // name, not the original one from `ServiceInfo`.
2482        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        // Only (at most) one packet is expected to be sent out.
2557        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    /// Binds a channel `listener` to querying mDNS hostnames.
2569    ///
2570    /// If there is already a `listener`, it will be updated, i.e. overwritten.
2571    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    /// Sends a multicast query for `name` with `qtype`.
2586    fn send_query(&self, name: &str, qtype: RRType) {
2587        self.send_query_vec(&[(name, qtype)]);
2588    }
2589
2590    /// Sends a query on a specific interface without known answers.
2591    ///
2592    /// Used when a new interface is added so the responder won't suppress
2593    /// its response due to known-answer suppression (RFC 6762 Section 7.1).
2594    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    /// Sends out a list of `questions` (i.e. DNS questions) via multicast.
2619    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                /*
2628                RFC 6762 section 7.1: https://datatracker.ietf.org/doc/html/rfc6762#section-7.1
2629                ...
2630                    When a Multicast DNS querier sends a query to which it already knows
2631                    some answers, it populates the Answer Section of the DNS query
2632                    message with those answers.
2633                 */
2634                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    /// Reads one UDP datagram from the socket of `intf`.
2665    ///
2666    /// Returns false if failed to receive a packet,
2667    /// otherwise returns true.
2668    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        // The buffer is one byte bigger than the biggest legal message, so that an
2683        // over-sized datagram can be told apart from a legal one that happens to be
2684        // exactly at the limit.
2685        let max_size = max_pkt_absolute(is_ipv4);
2686        let mut buf = vec![0u8; max_size + 1];
2687
2688        // Read the next mDNS UDP datagram.
2689        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        // RFC 6762 section 17 caps an mDNS packet at 9000 bytes including the IP and
2700        // UDP headers. A datagram over that arrives truncated, and decoding a
2701        // truncated message does not fail cleanly: names run into whatever bytes
2702        // follow, yielding bogus records or confusing parse errors. Drop it instead.
2703        //
2704        // On Windows, `recv` fails with WSAEMSGSIZE for such a datagram instead of
2705        // truncating it, so it is dropped by the error branch above. Either way it
2706        // is never decoded.
2707        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; // We still read something.
2713        }
2714
2715        // Find the interface that received the packet.
2716        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; // We still return true to indicate that we read something.
2723        };
2724
2725        // Drop packets for an IP version that has been disabled on this interface.
2726        // This is needed because some times the socket layer may still receive packets
2727        // for an IP version even after we left the multicast group for that IP version.
2728        // We want to drop such packets to avoid unnecessary processing.
2729        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); // reduce potential processing errors
2742
2743        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    /// Returns true, if sent query. Returns false if SRV already exists.
2772    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            // Query SRV and TXT explicitly rather than RRType::ANY. RFC 6762 §6.5 makes
2798            // ANY legal, but SRV+TXT is what Bonjour's DNSServiceResolve and Avahi send,
2799            // so it is the path every responder is actually exercised on; it also lets
2800            // known-answer suppression apply (`get_known_answers` has no ANY case).
2801            self.send_query_vec(&[(instance, RRType::SRV), (instance, RRType::TXT)]);
2802            return true;
2803        }
2804
2805        false
2806    }
2807
2808    /// Re-issues follow-up queries (SRV / address) for every instance of
2809    /// `ty_domain` that has been found via PTR but is not yet resolved.
2810    ///
2811    /// This is meant to be driven by the browse retransmission cycle so a
2812    /// pending instance keeps being queried for as long as the browse is
2813    /// active.
2814    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    /// Checks if `ty_domain` has records in the cache. If yes, sends the
2833    /// cached records via `sender`.
2834    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    /// Checks if `hostname` has records in the cache. If yes, sends the
2903    /// cached records via `sender`.
2904    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    /// Creates a `ResolvedService` from the cache.
2927    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        // Be sure setting `subtype` if available even when querying for the parent domain.
2944        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        // resolve SRV record
2957        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        // resolve TXT record
2967        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        // resolve A and AAAA records
2976        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                            // Merge interface_ids if this V4 addr already exists.
2988                            // Linear scan by IP since Eq/Hash include interface_ids.
2989                            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                // Drain signals as we will drain commands as well.
3021                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; // Next event.
3031            }
3032
3033            // Read until no more packets available.
3034            while self.handle_read(ev.token().0) {}
3035
3036            // we continue to monitor this socket.
3037            if ev.token().0 == IPV4_SOCK_EVENT_KEY {
3038                // Re-register the IPv4 socket for reading.
3039                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                // Re-register the IPv6 socket for reading.
3050                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    /// Deal with incoming response packets.  All answers
3064    /// are held in the cache, and listeners are notified.
3065    fn handle_response(&mut self, mut msg: DnsIncoming, if_index: u32) {
3066        let now = current_time_millis();
3067
3068        // remove records that are expired.
3069        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                // for PTR records, send event to listeners
3077                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        // check possible conflicts and handle them.
3095        self.conflict_handler(&msg, if_index);
3096
3097        // check if the message is for us.
3098        let mut is_for_us = true; // assume it is for us.
3099
3100        // If there are any PTR records in the answers, there should be
3101        // at least one PTR for us. Otherwise, the message is not for us.
3102        // If there are no PTR records at all, assume this message is for us.
3103        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; // OK to break: at least one PTR for us.
3108                } else {
3109                    is_for_us = false;
3110                }
3111            } else if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA {
3112                // If there is a hostname querier for this address, then it is for us.
3113                let answer_lowercase = answer.get_name().to_lowercase();
3114                if self.hostname_resolvers.contains_key(&answer_lowercase) {
3115                    is_for_us = true;
3116                    break; // OK to break: at least one hostname for us.
3117                }
3118            }
3119        }
3120
3121        // if we explicitily want to accept unsolicited responses, we should consider all messages as for us.
3122        if self.accept_unsolicited {
3123            is_for_us = true;
3124        }
3125
3126        /// Represents a DNS record change that involves one service instance.
3127        struct InstanceChange {
3128            ty: RRType,   // The type of DNS record for the instance.
3129            name: String, // The name of the record.
3130        }
3131
3132        // Go through all answers to get the new and updated records.
3133        // For new PTR records, send out ServiceFound immediately. For others,
3134        // collect them into `changes`.
3135        //
3136        // Note: we don't try to identify the update instances based on
3137        // each record immediately as the answers are likely related to each
3138        // other.
3139        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                    // Positive dump: a new record was accepted into the cache.
3157                    // Counterpart to the "skipping record" debug line in the parser.
3158                    debug!("cache: new record: {:?}", &dns_record.record);
3159
3160                    // Only process PTR that does not expire soon (i.e. TTL > 1).
3161                    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                        // send ServiceFound
3167                        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        // Add timers for the new records.
3199        for t in timers {
3200            self.add_timer(t);
3201        }
3202
3203        // Go through remaining changes to see if any hostname resolutions were found or updated.
3204        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        // Identify the instances that need to be "resolved".
3219        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            // check against possible multicast forwarding
3255            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                // double check if any other address record matches rrdata,
3267                // as there could be multiple addresses for the same name.
3268                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; // no conflict for this answer.
3275                }
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                    // create a new name for this record
3291                    // then remove the old record in probing.
3292                    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; // old record is dropped from the probe.
3301                }
3302
3303                true
3304            });
3305
3306            // ?????
3307            // if probe.records.is_empty() {
3308            //     dns_registry.probing.remove(name);
3309            // }
3310
3311            // Probing again with the new names.
3312            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                // remember the name changes (note: `name` might not be the original, it could be already changed once.)
3322                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    /// Resolve the updated (including new) instances.
3355    ///
3356    /// Note: it is possible that more than 1 PTR pointing to the same
3357    /// instance. For example, a regular service type PTR and a sub-type
3358    /// service type PTR can both point to the same service instance.
3359    /// This loop automatically handles the sub-type PTRs.
3360    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                // No need to resolve if not in our queries.
3374                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    /// Handle incoming query packets, figure out whether and what to respond.
3440    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        // Special meta-query "_services._dns-sd._udp.<Domain>".
3448        // See https://datatracker.ietf.org/doc/html/rfc6763#section-9
3449        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                // PTR answers are shared records: defer the response unless this
3467                // is a legacy-unicast (source port != 5353) or probe-defense
3468                // (records in the Authority Section) query.
3469                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                // Simultaneous Probe Tiebreaking (RFC 6762 section 8.2)
3490                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        // Defer PTR responses (RFC 6762 §6).
3550        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        // Pick a source IfAddr on `intf` whose subnet contains the querier's IP.
3599        // It's OK if it's None, `send_dns_outgoing` will then pick one address.
3600        let matched_source = intf
3601            .addrs
3602            .iter()
3603            .find(|if_addr| valid_ip_on_intf(&querier_ip, if_addr));
3604
3605        // RFC 6762 §6.7 (Legacy Unicast Responses): if the querier's source
3606        // port is not 5353, it's a one-shot legacy querier (e.g. Android's
3607        // getaddrinfo, iOS resolver fallback). The response MUST be unicast
3608        // back to the querier's source IP and port; multicast replies will
3609        // never reach the querier's ephemeral socket. Legacy unicast
3610        // responses must also echo the question section, clear the
3611        // cache-flush bit (legacy resolvers don't understand it), and cap
3612        // record TTLs to 10 seconds (see update_records_for_legacy_unicast).
3613        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            // RFC 6762 §6: a record MUST NOT be multicast on an interface
3627            // more than once per second. Two exceptions skip the limit here:
3628            //   - Unicast responses (handled above).
3629            //   - Answering probe queries: a probe carries the proposed
3630            //     records in its Authority Section, and we MUST defend our
3631            //     records immediately so the prober detects the conflict.
3632            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    /// Multicasts a PTR query response that was deferred per RFC 6762 §6.
3659    ///
3660    /// Re-resolves the socket and interface from `if_index`, so it is safe to
3661    /// call from the timer loop after the borrows taken while building the
3662    /// response are gone. The original querier is no longer known, so the
3663    /// response is always a plain multicast (no unicast destination, no
3664    /// source-address preference); the §6 once-per-second multicast rate limit
3665    /// still applies.
3666    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    /// Increases the value of `counter` by `count`.
3710    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    /// Sets the value of `counter` to `count`.
3721    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        // This recv is non-blocking as the socket is non-blocking.
3730        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    /// Sends service removal event to listeners for expired service records.
3744    /// `expired`: map of service type domain to set of instance names.
3745    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    /// The entry point that executes all commands received by the daemon.
3763    ///
3764    /// `repeating`: whether this is a retransmission.
3765    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        // Send the metrics to the client.
3894        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            // Binds a `listener` to querying mDNS domain type `ty`.
3928            //
3929            // If there is already a `listener`, it will be updated, i.e. overwritten.
3930            self.service_queriers.insert(ty.clone(), listener.clone());
3931
3932            // if we already have the records in our cache, just send them
3933            self.query_cache_for_service(&ty, &listener, now);
3934        }
3935
3936        if cache_only {
3937            // If cache_only is true, we do not send a query.
3938            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            // RFC 6762 §5.2: delay the first query by a random jitter.
3947            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            // if we already have the records in our cache, just send them
3988            self.query_cache_for_hostname(&hostname, listener.clone());
3989
3990            // RFC 6762 §5.2: delay the first query by a random jitter.
3991            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        // Only add retransmission if it does not exceed the hostname resolver timeout, if any.
4008        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            // Note that if the current try already succeeds, the next retransmission
4026            // will be no-op as the cache has been updated.
4027            //
4028            // Back off exponentially
4029            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            // This fast-path retry chain is ending.
4034            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                        // repeat for one time just in case some peers miss the message
4056                        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                    // ipv6
4067                    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                // Remove pending browse commands in the reruns.
4136                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                // Remove cache entries.
4150                self.cache.remove_service_type(&ty_domain);
4151
4152                // Notify the client.
4153                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            // Remove pending resolve commands in the reruns.
4164            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            // Notify the client.
4178            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        /*
4231        RFC 6762 section 10.4:
4232        ...
4233        When the cache receives this hint that it should reconfirm some
4234        record, it MUST issue two or more queries for the resource record in
4235        dispute.  If no response is received within ten seconds, then, even
4236        though its TTL may indicate that it is not yet due to expire, that
4237        record SHOULD be promptly flushed from the cache.
4238        */
4239        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        // send query for the resource records.
4247        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); // ensure a check for the new expire time.
4258
4259                // schedule a resend 1 second later
4260                self.add_retransmission(now + 1000, Command::Verify(instance, timeout));
4261            }
4262        }
4263    }
4264
4265    /// Refresh cached service records with active queriers
4266    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
4311/// Adds one or more answers of a service for incoming msg and RR entry name.
4312fn 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
4361/// Answers a query for a hostname we own: A/AAAA (address records), SVCB/HTTPS
4362/// (service-binding records), or ANY.
4363///
4364/// Adds the A/AAAA records held on `intf` for every announced service whose
4365/// hostname matches the question. If the queried address family is absent, adds
4366/// NSEC (negative) answer instead. SVCB/HTTPS always get the NSEC answer.
4367fn 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            // Pick addresses based on the question type, not the
4399            // socket family. RFC 6762 doesn't require A queries
4400            // to come over IPv4 transport — Android's getaddrinfo
4401            // routinely sends both A and AAAA queries over its
4402            // preferred IPv6 mDNS socket and expects A records
4403            // to be answered with v4 addresses.
4404            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        // RFC 6762 section 6.1: explicitly deny absent records
4434        // only for a hostname we own on this interface. Combine
4435        // all announced services sharing the hostname, so one
4436        // registration cannot deny another's address family.
4437        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/// All possible events sent to the client from the daemon
4456/// regarding service discovery.
4457#[derive(Clone, Debug)]
4458#[non_exhaustive]
4459pub enum ServiceEvent {
4460    /// Started searching for a service type.
4461    SearchStarted(String),
4462
4463    /// Found a specific (service_type, fullname).
4464    ServiceFound(String, String),
4465
4466    /// Resolved a service instance in a ResolvedService struct.
4467    ServiceResolved(Box<ResolvedService>),
4468
4469    /// A service instance (service_type, fullname) was removed.
4470    ServiceRemoved(String, String),
4471
4472    /// Stopped searching for a service type.
4473    SearchStopped(String),
4474}
4475
4476/// All possible events sent to the client from the daemon
4477/// regarding host resolution.
4478#[derive(Clone, Debug)]
4479#[non_exhaustive]
4480pub enum HostnameResolutionEvent {
4481    /// Started searching for the ip address of a hostname.
4482    SearchStarted(String),
4483    /// One or more addresses for a hostname has been found.
4484    AddressesFound(String, HashSet<ScopedIp>),
4485    /// One or more addresses for a hostname has been removed.
4486    AddressesRemoved(String, HashSet<ScopedIp>),
4487    /// The search for the ip address of a hostname has timed out.
4488    SearchTimeout(String),
4489    /// Stopped searching for the ip address of a hostname.
4490    SearchStopped(String),
4491}
4492
4493/// Some notable events from the daemon besides [`ServiceEvent`].
4494/// These events are expected to happen infrequently.
4495#[derive(Clone, Debug)]
4496#[non_exhaustive]
4497pub enum DaemonEvent {
4498    /// Daemon unsolicitly announced a service from an interface.
4499    Announce(String, String),
4500
4501    /// Daemon encountered an error.
4502    Error(Error),
4503
4504    /// Daemon detected a new IP address from the host.
4505    IpAdd(IpAddr),
4506
4507    /// Daemon detected a IP address removed from the host.
4508    IpDel(IpAddr),
4509
4510    /// Daemon resolved a name conflict by changing one of its names.
4511    /// see [DnsNameChange] for more details.
4512    NameChange(DnsNameChange),
4513
4514    /// Send out a multicast response via an interface.
4515    Respond(String),
4516}
4517
4518/// Represents a name change due to a name conflict resolution.
4519/// See [RFC 6762 section 9](https://datatracker.ietf.org/doc/html/rfc6762#section-9)
4520#[derive(Clone, Debug)]
4521pub struct DnsNameChange {
4522    /// The original name set in `ServiceInfo` by the user.
4523    pub original: String,
4524
4525    /// A new name is created by appending a suffix after the original name.
4526    ///
4527    /// - for a service instance name, the suffix is `(N)`, where N starts at 2.
4528    /// - for a host name, the suffix is `-N`, where N starts at 2.
4529    ///
4530    /// For example:
4531    ///
4532    /// - Service name `foo._service-type._udp` becomes `foo (2)._service-type._udp`
4533    /// - Host name `foo.local.` becomes `foo-2.local.`
4534    pub new_name: String,
4535
4536    /// The resource record type
4537    pub rr_type: RRType,
4538
4539    /// The interface where the name conflict and its change happened.
4540    pub intf_name: String,
4541}
4542
4543/// Commands supported by the daemon
4544#[derive(Debug)]
4545enum Command {
4546    /// Browsing for a service type (ty_domain, next_time_delay_in_seconds, channel::sender)
4547    Browse(String, u32, bool, Sender<ServiceEvent>),
4548
4549    /// Resolve a hostname to IP addresses.
4550    ResolveHostname(String, u32, Sender<HostnameResolutionEvent>, Option<u64>), // (hostname, next_time_delay_in_seconds, sender, timeout_in_milliseconds)
4551
4552    /// Register a service
4553    Register(Box<ServiceInfo>),
4554
4555    /// Unregister a service
4556    Unregister(String, Sender<UnregisterStatus>), // (fullname)
4557
4558    /// Announce again a service to local network
4559    RegisterResend(String, u32), // (fullname)
4560
4561    /// Resend unregister packet.
4562    UnregisterResend(Vec<u8>, u32, bool), // (packet content, if_index, is_ipv4)
4563
4564    /// Stop browsing a service type
4565    StopBrowse(String), // (ty_domain)
4566
4567    /// Stop resolving a hostname
4568    StopResolveHostname(String), // (hostname)
4569
4570    /// Send query to resolve a service instance.
4571    /// This is used when a PTR record exists but SRV & TXT records are missing.
4572    Resolve(String, u16), // (service_instance_fullname, try_count)
4573
4574    /// Read the current values of the counters
4575    GetMetrics(Sender<Metrics>),
4576
4577    /// Get the current status of the daemon.
4578    GetStatus(Sender<DaemonStatus>),
4579
4580    /// Monitor noticeable events in the daemon.
4581    Monitor(Sender<DaemonEvent>),
4582
4583    SetOption(DaemonOption),
4584
4585    GetOption(Sender<DaemonOptionVal>),
4586
4587    /// Proactively confirm a DNS resource record.
4588    ///
4589    /// The intention is to check if a service name or IP address still valid
4590    /// before its TTL expires.
4591    Verify(String, Duration),
4592
4593    /// Invalidate some interface addresses.
4594    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
4645/// The length of Service Domain name supported in this lib.
4646const DOMAIN_LEN: usize = "._tcp.local.".len();
4647
4648/// Validate the length of "service_name" in a "_<service_name>.<domain_name>." string.
4649fn check_service_name_length(ty_domain: &str, limit: u8) -> Result<()> {
4650    if ty_domain.len() <= DOMAIN_LEN + 1 {
4651        // service name cannot be empty or only '_'.
4652        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; // exclude the leading `_`
4656    if service_name_len > limit as usize {
4657        return Err(e_fmt!("Service name length must be <= {} bytes", limit));
4658    }
4659    Ok(())
4660}
4661
4662/// Checks if `name` ends with a valid domain: '._tcp.local.' or '._udp.local.'
4663fn 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
4674/// Validate the service name in a fully qualified name.
4675///
4676/// A Full Name = <Instance>.<Service>.<Domain>
4677/// The only `<Domain>` supported are "._tcp.local." and "._udp.local.".
4678///
4679/// Note: this function does not check for the length of the service name.
4680/// Instead, `register_service` method will check the length.
4681fn 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
4711/// Validate a hostname.
4712fn 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
4757/// Returns valid network interfaces in the host system.
4758/// Operational down interfaces are excluded.
4759/// Loopback interfaces are excluded if `with_loopback` is false.
4760fn 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
4777/// Checks if the interface name indicates it's an Apple peer-to-peer interface,
4778/// which should be ignored by default.
4779fn 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/// How to encode and where to send outgoing messages on one interface.
4785#[derive(Clone, Copy, Debug)]
4786struct SendConfig {
4787    /// The mDNS port to send to.
4788    port: u16,
4789
4790    /// Max byte size of a generated packet.
4791    /// See [`ServiceDaemon::set_max_packet_size`].
4792    max_packet_size: usize,
4793
4794    /// Whether the packets go out over IPv4, which decides their absolute
4795    /// ceiling: see [`max_pkt_absolute`].
4796    is_ipv4: bool,
4797}
4798
4799/// Send an outgoing mDNS query or response, and returns the packet bytes.
4800/// Returns empty vec if no valid interface address is found.
4801fn 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    // The limits are per address family, so read them off the address we send from.
4829    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
4847/// Send an outgoing mDNS query or response, and returns the packet bytes.
4848fn 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![]); // no need to send empty response
4862        }
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                // cannot send without a valid interface
4882                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![]); // non-fatal other failure
4895            }
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                // cannot send without a valid interface
4904                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![]); // non-fatal other failure
4917            }
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
4931/// Sends a unicast packet directly to `dest` (used for RFC 6762 §6.7
4932/// legacy unicast responses).
4933fn 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
4957/// Sends a multicast packet, and returns the packet bytes.
4958fn 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); // Choose iface for multicast
4977            sock.into()
4978        }
4979    };
4980
4981    // Sends out `packet` to `addr` on the socket.
4982    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
4995/// Returns true if `name` is a valid instance name of format:
4996/// <instance>.<service_type>.<_udp|_tcp>.local.
4997/// Note: <instance> could contain '.' as well.
4998fn 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; // This monitor is dropped.
5008            }
5009        }
5010        true
5011    });
5012}
5013
5014/// Check if all unique records passed "probing", and if yes, create a packet
5015/// to announce the service.
5016fn 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    // check if we changed our name due to conflicts.
5037    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    // SRV records.
5074    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    // TXT records.
5099
5100    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    // Address records. (A and AAAA)
5120
5121    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
5152/// Send an unsolicited response for owned service via `intf` and `sock`.
5153/// Returns true if sent out successfully for IPv4 or IPv6.
5154fn 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        // RFC 6762 §6: a record MUST NOT be multicast on an interface more than
5164        // once per second. Announcements are unsolicited multicast responses.
5165        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
5175/// Returns a new name based on the `original` to avoid conflicts.
5176/// If the name already contains a number in parentheses, increments that number.
5177///
5178/// Examples:
5179/// - `foo.local.` becomes `foo (2).local.`
5180/// - `foo (2).local.` becomes `foo (3).local.`
5181/// - `foo (9)` becomes `foo (10)`
5182fn 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    // check if there is already has `(<num>)` suffix.
5191    if let Some(paren_pos) = first_part.rfind(" (") {
5192        // Check if there's a closing parenthesis
5193        if let Some(end_paren) = first_part[paren_pos..].find(')') {
5194            let absolute_end_pos = paren_pos + end_paren;
5195            // Only process if the closing parenthesis is the last character
5196            if absolute_end_pos == first_part.len() - 1 {
5197                let num_start = paren_pos + 2; // Skip " ("
5198                                               // Try to parse the number between parentheses
5199                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
5211/// Returns a new name based on the `original` to avoid conflicts.
5212/// If the name already contains a hyphenated number, increments that number.
5213///
5214/// Examples:
5215/// - `foo.local.` becomes `foo-2.local.`
5216/// - `foo-2.local.` becomes `foo-3.local.`
5217/// - `foo` becomes `foo-2`
5218fn 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    // check if there is already a `-<num>` suffix
5227    if let Some(hyphen_pos) = first_part.rfind('-') {
5228        // Try to parse everything after the hyphen as a number
5229        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
5239/// Check probes in a registry and returns: a probing packet to send out, and a list of probe names
5240/// that are finished.
5241fn 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                // move the record to active
5253                expired_probes.push(name.clone());
5254            } else {
5255                out.add_question(name, RRType::ANY);
5256
5257                /*
5258                RFC 6762 section 8.2: https://datatracker.ietf.org/doc/html/rfc6762#section-8.2
5259                ...
5260                for tiebreaking to work correctly in all
5261                cases, the Authority Section must contain *all* the records and
5262                proposed rdata being probed for uniqueness.
5263                    */
5264                for record in probe.records.iter() {
5265                    out.add_authority(record.clone());
5266                }
5267
5268                probe.update_next_send(now);
5269
5270                // add timer
5271                timers.push(Reverse(probe.next_send));
5272            }
5273        }
5274    }
5275
5276    (out, expired_probes)
5277}
5278
5279/// Process expired probes on an interface and return a list of services
5280/// that are waiting for the probe to finish.
5281///
5282/// `DnsNameChange` events are sent to the monitors.
5283fn 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        // send notifications about name changes
5297        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        // move RR from probe to active.
5315        debug!(
5316            "probe of '{name}' finished: move {} records to active. ({} waiting services)",
5317            probe.records.len(),
5318            probe.waiting_services.len(),
5319        );
5320
5321        // Move records to active and plan to wake up services if records are not empty.
5322        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
5339/// Returns the max packet size to use on the interface `if_index` for the given
5340/// address family, i.e. the size of the last selection matching it, or
5341/// [`MAX_PKT_DEFAULT`] if none does.
5342///
5343/// A selection matches an address, so it applies as soon as any address of the
5344/// interface in that family matches. That keeps the two families independent:
5345/// e.g. [`IfKind::IPv4`] leaves the IPv6 side of the interface alone.
5346fn 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
5368/// Resolves `IfKind::Addr(ip)` to `IndexV4(if_index)` or `IndexV6(if_index)`.
5369fn 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    /// Builds an interface address for the max packet size tests below.
5411    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            // Registration and announcements use only loopback and a private
5468            // port. Injected addresses below never change host configuration.
5469            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            // Finish real registration probes without waiting for wall-clock timers.
5494            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        // en0 is dual-stack, en1 is IPv4 only.
5536        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        // No selection: every interface keeps the default.
5551        assert_eq!(resolve(&[], 1, true), MAX_PKT_DEFAULT);
5552        assert_eq!(resolve(&[], 1, false), MAX_PKT_DEFAULT);
5553
5554        // A selection by name applies to the interface it matches, both families.
5555        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        // For an interface matched more than once, the last selection wins.
5564        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        // A selection of one address family leaves the other one alone.
5579        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        // en1 has no IPv6 address, so the IPv6 selection cannot reach it.
5593        assert_eq!(resolve(&v6_only, 2, true), MAX_PKT_DEFAULT);
5594        assert_eq!(resolve(&v6_only, 2, false), MAX_PKT_DEFAULT);
5595
5596        // Same for an index selection, which names a family too.
5597        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    /// A size outside [`MIN_MAX_PACKET_SIZE`]..=[`MAX_PKT_ABSOLUTE_IPV6`] is rejected
5606    /// rather than clamped, so what reaches the encoder is always legal.
5607    #[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        // Both ends of the range are accepted.
5619        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        // When an interface has multiple IPs on unrelated subnets,
5632        // handle_query should pick the IfAddr whose subnet contains the querier,
5633        // and fall back to None if none match.
5634        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        // Querier not on any local subnet: fall back to None.
5671        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        // RFC 6762 §6.7: a query whose UDP source port is not 5353 (a
5684        // "legacy" / "one-shot" querier, e.g. Android's getaddrinfo) must
5685        // get its response via unicast, sent back to the querier's source
5686        // address, with the question echoed and the cache-flush bit cleared.
5687        //
5688        // This test sends such a query from an ephemeral port and asserts
5689        // the response arrives on that same socket. The socket is not joined
5690        // to the mDNS multicast group, so a multicast-only reply would never
5691        // reach it — simply receiving the response proves it was unicast.
5692
5693        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        // Register a service with a unique hostname on this host.
5707        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, // arbitrary; the test only resolves the hostname
5719            None,
5720        )
5721        .expect("invalid service info");
5722        daemon.register(service_info).expect("register service");
5723
5724        // A one-shot querier: ephemeral source port, not 5353. Binding to
5725        // `intf_ip` directs the multicast query out that interface, which is
5726        // one the daemon is listening on.
5727        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        // Build a one-question A-record query for our hostname, carrying a
5741        // distinctive non-zero id that the legacy unicast response must echo.
5742        // `set_multicast(false)` makes the query serialize with that id on the
5743        // wire rather than 0.
5744        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        // The service is announced asynchronously after register(), so retry
5760        // the query until our answer comes back or the deadline passes.
5761        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            // Drain whatever has arrived; on read timeout the loop ends and
5769            // we re-send the query.
5770            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        // The reply came back to our ephemeral socket, from the mDNS port.
5793        assert_eq!(
5794            from.port(),
5795            MDNS_PORT,
5796            "response should originate from the mDNS port"
5797        );
5798
5799        // RFC 6762 §6.7: the response header must echo the querier's id.
5800        assert_eq!(
5801            msg.id(),
5802            QUERY_ID,
5803            "legacy unicast response must echo the query id"
5804        );
5805
5806        // RFC 6762 §6.7: the original question must be echoed.
5807        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        // RFC 6762 §6.7 / §10.2: the answer must be the A record we asked
5815        // for, with the cache-flush bit cleared.
5816        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        // A shared-record (PTR) response is delayed by a uniform-random amount.
5844        // We deviate from the RFC 6762 §6 suggested 20-120 ms window and use a
5845        // shorter 10-50 ms delay (`MAX` is the exclusive upper bound, so the
5846        // actual delay is 10..=49 ms).
5847        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        // RFC 6762 §5.2: a querier delays the first query of a continuous
5865        // monitoring series by a random amount (we use a 10-50 ms window).
5866        // Start a browse and observe, on a socket joined to the mDNS group, the
5867        // daemon's first PTR query for our (unique) service type. Assert it
5868        // arrives no sooner than ~10 ms after `browse()` — i.e. it is not sent
5869        // immediately.
5870        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        // A receiver socket joined to the mDNS group on this interface. The
5887        // daemon loops back its multicast by default, so its outgoing query is
5888        // delivered here on the same host.
5889        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        // Unique service type, kept within the RFC 6763 §7.2 15-byte label limit.
5901        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        // Read packets until we see our own PTR query or time out. The 10-50 ms
5914        // jitter plus command/scheduling latency comfortably fits in 2 s.
5915        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, // read timeout; keep polling until the deadline
5922            };
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        // Upper bound: the query must fall within the jitter window. Allow
5949        // generous slack above INITIAL_QUERY_DELAY_MAX_MILLIS for command
5950        // handoff, event-loop wakeup, and loopback latency, while still catching
5951        // a regression to a much larger delay (e.g. the RFC's 120 ms window).
5952        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        // RFC 6762 §6: a PTR (shared record set) response sent by multicast is
5965        // delayed by a uniform-random amount (we use a 10-50 ms window). Register
5966        // a service, then as a proper multicast querier (source port 5353) send a
5967        // PTR query and assert the daemon emits its response no sooner than ~10 ms
5968        // after the query. (A legacy unicast querier gets an *immediate* response
5969        // instead; see `test_legacy_unicast_response`.)
5970        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        // Keep the service name (the `_sd…` label) within the 15-byte limit
5989        // that RFC 6763 §7.2 imposes, while staying unique per run.
5990        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        // A proper multicast querier: source port 5353 so the daemon takes the
6009        // shared-record (delayed) path rather than the legacy-unicast one. We only
6010        // *send* on this socket; the response is observed through the monitor.
6011        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        // Loop the query back to the daemon's socket on this same host.
6019        sock.set_multicast_loop_v4(true).unwrap();
6020        let sock: UdpSocket = sock.into();
6021
6022        // Build the PTR query for our service type.
6023        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        // Wait for the initial announcements and the §6 rate-limit window (1s) to
6031        // pass, so our query elicits a fresh (delayed) response instead of being
6032        // suppressed by the rate limiter.
6033        std::thread::sleep(Duration::from_secs(3));
6034
6035        // Retry until the daemon emits a Respond for our query. A query landing
6036        // inside the 1 s multicast rate-limit window is rate-limited to an empty
6037        // response (no send, no event), so we simply re-query on the next pass.
6038        let deadline = Instant::now() + Duration::from_secs(8);
6039        let mut measured = None;
6040        while Instant::now() < deadline {
6041            // Drop any Respond events queued earlier so we time only the response
6042            // to the query we are about to send.
6043            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            // The delay window is 10-50 ms; 700 ms comfortably covers it plus any
6050            // scheduling slack. Ignore unrelated events; on timeout, re-query.
6051            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, // some other daemon event; keep waiting
6063                    Err(_) => break,   // timed out; re-query
6064                }
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        // valid hostnames
6100        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        // erroneous hostnames
6109        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        // Create a daemon
6135        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        // Browse for a service
6150        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        // Pause browsing so restarting will cause a new immediate query.
6171        // Unregistering will not work here, it will invalidate all the records.
6172        d.stop_browse(service).unwrap();
6173
6174        // Ensure the search is stopped.
6175        // Reduces the chance of receiving an answer adding the ptr back to the
6176        // cache causing the later browse to return directly from the cache.
6177        // (which invalidates what this test is trying to test for.)
6178        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                // Other `ServiceResolved` messages may be received
6187                // here as they come from different interfaces.
6188                // That's fine for this test.
6189                e => {
6190                    println!("Received event {:?}", e);
6191                }
6192            }
6193        }
6194
6195        assert!(stopped);
6196
6197        // Invalidate the ptr from the service to the host.
6198        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        // Restart the browse to force the sender to re-send the announcements.
6233        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        // construct service info
6256        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 fullname = my_service.get_fullname().to_string();
6263
6264        // set SRV to expire soon.
6265        let new_ttl = 3; // for testing only.
6266        my_service._set_host_ttl(new_ttl);
6267
6268        // register my service
6269        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        // Exit the server so that no more responses.
6289        mdns_server.shutdown().unwrap();
6290
6291        // SRV record in the client cache will expire.
6292        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        // Create a mDNS server
6304        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        // Set a short TTL for addresses for testing.
6323        let addr_ttl = 2;
6324        my_service._set_host_ttl(addr_ttl); // Expire soon
6325
6326        server.register(my_service).unwrap();
6327
6328        // Create a mDNS client for resolving the hostname.
6329        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        // Shutdown the server so no more responses / refreshes for addresses.
6348        server.shutdown().unwrap();
6349
6350        // Wait till hostname address record expires, with 1 second grace period.
6351        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        // construct service info
6379        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; // for testing only.
6399        my_service._set_other_ttl(new_ttl);
6400
6401        // register my service
6402        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); // Give at least 1 second for the service probing.
6409        let mut resolved = false;
6410
6411        // resolve the service first.
6412        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        // wait over 80% of TTL, and refresh PTR should be sent out.
6423        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        // verify refresh counter.
6429        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        // Exit the server so that no more responses.
6437        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        // Additional edge cases
6451        assert_eq!(name_change("foo (abc)"), "foo (abc) (2)"); // Invalid number
6452        assert_eq!(name_change("foo (2"), "foo (2 (2)"); // Missing closing parenthesis
6453        assert_eq!(name_change("foo (2) extra"), "foo (2) extra (2)"); // Extra text after number
6454    }
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        // construct a simple service info
6468        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        // construct a DnsOutgoing message
6487        let mut out = DnsOutgoing::new(FLAGS_QR_RESPONSE | FLAGS_AA);
6488
6489        // Construct a dummy DnsIncoming message
6490        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        // Add an answer of TXT type for the service.
6495        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        // Check if the answer was added correctly
6506        assert!(
6507            out.answers_count() > 0,
6508            "No answers added to the outgoing message"
6509        );
6510
6511        // Check if the first answer is of type TXT
6512        let answer = out._answers().first().unwrap();
6513        assert_eq!(answer.0.get_type(), RRType::TXT);
6514
6515        // Check TTL is set properly for the TXT record
6516        assert_eq!(answer.0.get_record().get_ttl(), my_service.get_other_ttl());
6517    }
6518
6519    #[test]
6520    fn test_interface_flip() {
6521        // start a server
6522        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(); // Create a unique name.
6528        let port = 5200;
6529
6530        // Get a single IPv4 address
6531        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        // Register the service.
6540        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        // wait for the service announced.
6548        std::thread::sleep(Duration::from_secs(2));
6549
6550        // start a client
6551        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        // Set a short IP check interval to detect interface changes quickly.
6569        client.set_ip_check_interval(1).unwrap();
6570
6571        // Now shutdown the interface and expect the client to lose the service.
6572        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        // construct service info
6608        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; // for testing only.
6628        my_service._set_other_ttl(new_ttl);
6629
6630        let mdns_client = ServiceDaemon::new().expect("Failed to create mdns client");
6631
6632        // make a single browse request to record that we are interested in the service.  This ensures that
6633        // subsequent announcements are cached.
6634        let browse_chan = mdns_client.browse_cache(service_type).unwrap();
6635        std::thread::sleep(Duration::from_secs(2));
6636
6637        // register my service
6638        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); // Give at least 1 second for the service probing.
6643        let mut resolved = false;
6644
6645        // resolve the service.
6646        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        // Exit the server so that no more responses.
6657        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        // register my service
6683        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        // Wait a bit for the service announcements to go out, before calling browse_cache.  This ensures
6691        // that the announcements are treated as unsolicited
6692        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); // Give at least 1 second for the service probing.
6695        let mut resolved = false;
6696
6697        // resolve the service.
6698        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        // Exit the server so that no more responses.
6709        mdns_server.shutdown().unwrap();
6710        mdns_client.shutdown().unwrap();
6711    }
6712
6713    #[test]
6714    fn test_custom_port_isolation() {
6715        // This test verifies:
6716        // 1. Daemons on a custom port can communicate with each other
6717        // 2. Daemons on different ports are isolated (no cross-talk)
6718
6719        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        // Create service info for custom port (5454)
6731        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        // Create service info for default port (5353)
6742        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        // Create two daemons on custom port 5454
6753        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        // Create daemon on default port (5353)
6760        let server_default = ServiceDaemon::new().expect("Failed to create default port server");
6761
6762        // Register service on custom port
6763        server_custom
6764            .register(service_custom.clone())
6765            .expect("Failed to register custom port service");
6766
6767        // Register service on default port
6768        server_default
6769            .register(service_default.clone())
6770            .expect("Failed to register default port service");
6771
6772        // Browse from custom port client
6773        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        // Custom port client should find the custom port service
6782        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        // Now verify the default port daemon can find its own services
6809        // but not the custom port services
6810        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        // Cleanup
6845        server_custom.shutdown().unwrap();
6846        client_custom.shutdown().unwrap();
6847        server_default.shutdown().unwrap();
6848        client_default.shutdown().unwrap();
6849    }
6850
6851    /// Regression test for such issue: an instance that is found (via PTR) but
6852    /// whose SRV/address answers are lost during the initial resolve attempts
6853    /// must not be stranded. As long as the browse is active, the daemon must
6854    /// keep re-querying for it.
6855    #[test]
6856    fn test_unresolved_instance_not_stranded() {
6857        use socket2::{Domain, Protocol, Socket, Type};
6858        use std::net::SocketAddrV4;
6859
6860        // Pick the first IPv4 interface, like the other multicast tests.
6861        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        // The SRV target is a distinct hostname, which is the case that needs a
6881        // separate address query.
6882        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        // Build our hand-rolled responder socket: bound to the mDNS port,
6892        // joined to the group, with loopback on so it exchanges packets with
6893        // the in-process daemon.
6894        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        // A response carrying PTR + SRV, but deliberately no address record.
6911        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        // A response carrying just the withheld address record.
6925        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        // Start the browse, then announce (unsolicited) to seed the cache.
6948        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        // The number of address-query packets we must see before we start
6953        // answering. We withhold past the fast-path budget (`RESOLVE_MAX_TRY`
6954        // tries in `exec_command_resolve`) so that resolution can only come
6955        // from the browse retransmission cycle. The buggy code went silent
6956        // once the fast path was exhausted and never resolved the instance.
6957        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            // Drive the responder: react to whatever queries have arrived.
6965            while let Ok((len, from)) = responder.recv_from(&mut buf) {
6966                // The daemon sends each query on every interface (loopback
6967                // included) and on Linux this socket receives all copies. Count
6968                // only the copy sent on the interface we joined, so one daemon
6969                // query counts exactly once.
6970                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                // Keep the PTR/SRV fresh if the daemon asks for them.
6996                if saw_service_query {
6997                    send_all(announce_packets());
6998                }
6999
7000                // Count address queries as one per packet (the daemon batches
7001                // A and AAAA into a single query). Only answer once the buggy
7002                // give-up window is behind us.
7003                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            // Has the daemon resolved the instance yet?
7012            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        // Only loopback and a private port are used for test announcements.
7063        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        // Complete actual registration probes deterministically.
7086        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        // An address on another interface cannot prevent a negative answer here.
7254        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}