From 1514e6567b64d3f8165d63bfcd11988a8c08e1ac Mon Sep 17 00:00:00 2001 From: Lucas Villa Real Date: Wed, 17 Apr 2024 15:18:19 -0300 Subject: [PATCH 1/5] mDNS: always set the "cache flush" bit Always broadcast mDNS messages with the "cache flush" bit set for TXT, SRV, A, and AAAA records. This is useful when the Matter device reboots and gets assigned a different IP address, for example. In such a case, hosts with an outdated cache may need to wait until the original TTL expires (up to 60 seconds, per the TTL definitions on mdns/builtin.rs). --- rs-matter/src/mdns/proto.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/rs-matter/src/mdns/proto.rs b/rs-matter/src/mdns/proto.rs index af90d163..82cb6e41 100644 --- a/rs-matter/src/mdns/proto.rs +++ b/rs-matter/src/mdns/proto.rs @@ -20,6 +20,11 @@ use crate::error::{Error, ErrorCode}; use super::Service; +/// Internet DNS class with the "Cache Flush" bit set. +fn dns_class_with_flush(dns_class: Class) -> Class { + Class::Int(u16::from(dns_class) | 0x8000) +} + impl From for Error { fn from(_: ShortBuf) -> Self { Self::new(ErrorCode::NoSpace) @@ -304,7 +309,7 @@ impl<'a> Host<'a> { ) -> Result<(), PushError> { answer.push(( Self::host_fqdn(self.hostname, false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, A::from_octets(self.ip[0], self.ip[1], self.ip[2], self.ip[3]), )) @@ -318,7 +323,7 @@ impl<'a> Host<'a> { if let Some(ip) = &self.ipv6 { answer.push(( Self::host_fqdn(self.hostname, false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, Aaaa::new((*ip).into()), )) @@ -346,7 +351,7 @@ impl<'a> Service<'a> { ) -> Result<(), PushError> { answer.push(( self.service_fqdn(false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, Srv::new(0, 0, self.port, Host::host_fqdn(hostname, false).unwrap()), )) @@ -359,14 +364,14 @@ impl<'a> Service<'a> { ) -> Result<(), PushError> { answer.push(( Self::dns_sd_fqdn(false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, Ptr::new(self.service_type_fqdn(false).unwrap()), ))?; answer.push(( self.service_type_fqdn(false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, Ptr::new(self.service_fqdn(false).unwrap()), )) @@ -392,14 +397,14 @@ impl<'a> Service<'a> { ) -> Result<(), PushError> { answer.push(( Self::dns_sd_fqdn(false).unwrap(), - Class::In, - ttl_sec, + dns_class_with_flush(Class::In), + dns_class_with_flush(ttl_sec), Ptr::new(self.service_subtype_fqdn(service_subtype, false).unwrap()), ))?; answer.push(( self.service_subtype_fqdn(service_subtype, false).unwrap(), - Class::In, + dns_class_with_flush(Class::In), ttl_sec, Ptr::new(self.service_fqdn(false).unwrap()), )) @@ -425,7 +430,12 @@ impl<'a> Service<'a> { let txt = Txt::from_octets(&mut octets).unwrap(); - answer.push((self.service_fqdn(false).unwrap(), Class::In, ttl_sec, txt)) + answer.push(( + self.service_fqdn(false).unwrap(), + dns_class_with_flush(Class::In), + ttl_sec, + txt, + )) } fn service_fqdn(&self, suffix: bool) -> Result { From 73298d26851b8acca0bfd3c53682a0100c021728 Mon Sep 17 00:00:00 2001 From: Lucas Villa Real Date: Wed, 17 Apr 2024 15:40:35 -0300 Subject: [PATCH 2/5] Remove misplaced call to dns_class_with_flush() --- rs-matter/src/mdns/proto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rs-matter/src/mdns/proto.rs b/rs-matter/src/mdns/proto.rs index 82cb6e41..7bb6ee84 100644 --- a/rs-matter/src/mdns/proto.rs +++ b/rs-matter/src/mdns/proto.rs @@ -398,7 +398,7 @@ impl<'a> Service<'a> { answer.push(( Self::dns_sd_fqdn(false).unwrap(), dns_class_with_flush(Class::In), - dns_class_with_flush(ttl_sec), + ttl_sec, Ptr::new(self.service_subtype_fqdn(service_subtype, false).unwrap()), ))?; From 924c1fdc7ead22f08eb99dba0bf2d2bcc18241d2 Mon Sep 17 00:00:00 2001 From: Lucas Villa Real Date: Wed, 19 Jun 2024 10:39:03 -0300 Subject: [PATCH 3/5] Don't set the flush-bit on dns_sd_fqdn records --- rs-matter/src/mdns/proto.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rs-matter/src/mdns/proto.rs b/rs-matter/src/mdns/proto.rs index 7bb6ee84..b25b8599 100644 --- a/rs-matter/src/mdns/proto.rs +++ b/rs-matter/src/mdns/proto.rs @@ -21,8 +21,10 @@ use crate::error::{Error, ErrorCode}; use super::Service; /// Internet DNS class with the "Cache Flush" bit set. +/// See https://datatracker.ietf.org/doc/html/rfc6762#section-10.2 for details. fn dns_class_with_flush(dns_class: Class) -> Class { - Class::Int(u16::from(dns_class) | 0x8000) + const RESOURCE_RECORD_CACHE_FLUSH_BIT: u16 = 0x8000; + Class::Int(u16::from(dns_class) | RESOURCE_RECORD_CACHE_FLUSH_BIT) } impl From for Error { @@ -362,9 +364,12 @@ impl<'a> Service<'a> { answer: &mut AnswerBuilder, ttl_sec: u32, ) -> Result<(), PushError> { + // Don't set the flush-bit when sending this PTR record, as we're not the + // authority of dns_sd_fqdn: there may be answers from other devices on + // the network as well. answer.push(( Self::dns_sd_fqdn(false).unwrap(), - dns_class_with_flush(Class::In), + Class::In, ttl_sec, Ptr::new(self.service_type_fqdn(false).unwrap()), ))?; @@ -395,9 +400,12 @@ impl<'a> Service<'a> { service_subtype: &str, ttl_sec: u32, ) -> Result<(), PushError> { + // Don't set the flush-bit when sending this PTR record, as we're not the + // authority of dns_sd_fqdn: there may be answers from other devices on + // the network as well. answer.push(( Self::dns_sd_fqdn(false).unwrap(), - dns_class_with_flush(Class::In), + Class::In, ttl_sec, Ptr::new(self.service_subtype_fqdn(service_subtype, false).unwrap()), ))?; From eedf6978c75f793ff9a0661e2c27f383fda0eada Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 26 Jul 2024 10:06:11 -0400 Subject: [PATCH 4/5] Remove trailing whitespace in proto.rs Fixes previous merge to make fmt happy. --- rs-matter/src/mdns/proto.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rs-matter/src/mdns/proto.rs b/rs-matter/src/mdns/proto.rs index 4b08ba36..7ddcbe7b 100644 --- a/rs-matter/src/mdns/proto.rs +++ b/rs-matter/src/mdns/proto.rs @@ -593,9 +593,9 @@ impl<'a> Service<'a> { let txt = Txt::from_octets(&octets).unwrap(); answer.push(( - self.service_fqdn(false).unwrap(), - dns_class_with_flush(Class::IN), - ttl_sec, + self.service_fqdn(false).unwrap(), + dns_class_with_flush(Class::IN), + ttl_sec, txt, )) } From 6fc803c5b5cb077cf1713d5d65901a11e2fb33ba Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 26 Jul 2024 10:23:23 -0400 Subject: [PATCH 5/5] Use from_int to generate a custom class --- rs-matter/src/mdns/proto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rs-matter/src/mdns/proto.rs b/rs-matter/src/mdns/proto.rs index 7ddcbe7b..bd2ed06b 100644 --- a/rs-matter/src/mdns/proto.rs +++ b/rs-matter/src/mdns/proto.rs @@ -23,7 +23,7 @@ use super::Service; /// See https://datatracker.ietf.org/doc/html/rfc6762#section-10.2 for details. fn dns_class_with_flush(dns_class: Class) -> Class { const RESOURCE_RECORD_CACHE_FLUSH_BIT: u16 = 0x8000; - Class::Int(u16::from(dns_class) | RESOURCE_RECORD_CACHE_FLUSH_BIT) + Class::from_int(u16::from(dns_class) | RESOURCE_RECORD_CACHE_FLUSH_BIT) } impl From for Error {