@@ -16,11 +16,20 @@ pub const MAX_ADDRESS_COUNT: usize = 4;
1616pub const MAX_SERVER_COUNT : usize = 4 ;
1717
1818const DNS_PORT : u16 = 53 ;
19+ const MDNS_DNS_PORT : u16 = 5353 ;
1920const MAX_NAME_LEN : usize = 255 ;
2021const RETRANSMIT_DELAY : Duration = Duration :: from_millis ( 1_000 ) ;
2122const MAX_RETRANSMIT_DELAY : Duration = Duration :: from_millis ( 10_000 ) ;
2223const RETRANSMIT_TIMEOUT : Duration = Duration :: from_millis ( 10_000 ) ; // Should generally be 2-10 secs
2324
25+ #[ cfg( feature = "proto-ipv6" ) ]
26+ const MDNS_IPV6_ADDR : IpAddress = IpAddress :: Ipv6 ( crate :: wire:: Ipv6Address ( [
27+ 0xff , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xfb ,
28+ ] ) ) ;
29+
30+ #[ cfg( feature = "proto-ipv4" ) ]
31+ const MDNS_IPV4_ADDR : IpAddress = IpAddress :: Ipv4 ( crate :: wire:: Ipv4Address ( [ 224 , 0 , 0 , 251 ] ) ) ;
32+
2433/// Error returned by [`Socket::start_query`]
2534#[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
2635#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -81,6 +90,7 @@ struct PendingQuery {
8190 delay : Duration ,
8291
8392 server_idx : usize ,
93+ mdns : bool ,
8494}
8595
8696#[ derive( Debug ) ]
@@ -185,6 +195,7 @@ impl<'a> Socket<'a> {
185195 & mut self ,
186196 cx : & mut Context ,
187197 name : & str ,
198+ query_type : Type ,
188199 ) -> Result < QueryHandle , StartQueryError > {
189200 let mut name = name. as_bytes ( ) ;
190201
@@ -200,6 +211,12 @@ impl<'a> Socket<'a> {
200211
201212 let mut raw_name: Vec < u8 , MAX_NAME_LEN > = Vec :: new ( ) ;
202213
214+ let mut mdns = false ;
215+ if name. split ( |& c| c == b'.' ) . last ( ) . unwrap ( ) == b"local" {
216+ net_trace ! ( "Starting a mDNS query" ) ;
217+ mdns = true ;
218+ }
219+
203220 for s in name. split ( |& c| c == b'.' ) {
204221 if s. len ( ) > 63 {
205222 net_trace ! ( "invalid name: too long label" ) ;
@@ -224,7 +241,7 @@ impl<'a> Socket<'a> {
224241 . push ( 0x00 )
225242 . map_err ( |_| StartQueryError :: NameTooLong ) ?;
226243
227- self . start_query_raw ( cx, & raw_name)
244+ self . start_query_raw ( cx, & raw_name, query_type , mdns )
228245 }
229246
230247 /// Start a query with a raw (wire-format) DNS name.
@@ -235,19 +252,33 @@ impl<'a> Socket<'a> {
235252 & mut self ,
236253 cx : & mut Context ,
237254 raw_name : & [ u8 ] ,
255+ query_type : Type ,
256+ mdns : bool ,
238257 ) -> Result < QueryHandle , StartQueryError > {
239258 let handle = self . find_free_query ( ) . ok_or ( StartQueryError :: NoFreeSlot ) ?;
240259
260+ if mdns {
261+ // as per RFC 6762 any DNS query ending in .local. MUST be sent as mdns
262+ // so we internally overwrite the servers for any of those queries
263+ self . update_servers ( & [
264+ #[ cfg( feature = "proto-ipv6" ) ]
265+ MDNS_IPV6_ADDR ,
266+ #[ cfg( feature = "proto-ipv4" ) ]
267+ MDNS_IPV4_ADDR ,
268+ ] ) ;
269+ }
270+
241271 self . queries [ handle. 0 ] = Some ( DnsQuery {
242272 state : State :: Pending ( PendingQuery {
243273 name : Vec :: from_slice ( raw_name) . map_err ( |_| StartQueryError :: NameTooLong ) ?,
244- type_ : Type :: A ,
274+ type_ : query_type ,
245275 txid : cx. rand ( ) . rand_u16 ( ) ,
246276 port : cx. rand ( ) . rand_source_port ( ) ,
247277 delay : RETRANSMIT_DELAY ,
248278 timeout_at : None ,
249279 retransmit_at : Instant :: ZERO ,
250280 server_idx : 0 ,
281+ mdns,
251282 } ) ,
252283 #[ cfg( feature = "async" ) ]
253284 waker : WakerRegistration :: new ( ) ,
@@ -313,11 +344,12 @@ impl<'a> Socket<'a> {
313344 }
314345
315346 pub ( crate ) fn accepts ( & self , ip_repr : & IpRepr , udp_repr : & UdpRepr ) -> bool {
316- udp_repr. src_port == DNS_PORT
347+ ( udp_repr. src_port == DNS_PORT
317348 && self
318349 . servers
319350 . iter ( )
320- . any ( |server| * server == ip_repr. src_addr ( ) )
351+ . any ( |server| * server == ip_repr. src_addr ( ) ) )
352+ || ( udp_repr. src_port == MDNS_DNS_PORT )
321353 }
322354
323355 pub ( crate ) fn process (
@@ -500,7 +532,6 @@ impl<'a> Socket<'a> {
500532 // Try next server. We check below whether we've tried all servers.
501533 pq. server_idx += 1 ;
502534 }
503-
504535 // Check if we've run out of servers to try.
505536 if pq. server_idx >= self . servers . len ( ) {
506537 net_trace ! ( "already tried all servers." ) ;
@@ -526,17 +557,19 @@ impl<'a> Socket<'a> {
526557 opcode : Opcode :: Query ,
527558 question : Question {
528559 name : & pq. name ,
529- type_ : Type :: A ,
560+ type_ : pq . type_ ,
530561 } ,
531562 } ;
532563
533564 let mut payload = [ 0u8 ; 512 ] ;
534565 let payload = & mut payload[ ..repr. buffer_len ( ) ] ;
535566 repr. emit ( & mut Packet :: new_unchecked ( payload) ) ;
536567
568+ let dst_port = if pq. mdns { MDNS_DNS_PORT } else { DNS_PORT } ;
569+
537570 let udp_repr = UdpRepr {
538571 src_port : pq. port ,
539- dst_port : 53 ,
572+ dst_port,
540573 } ;
541574
542575 let dst_addr = self . servers [ pq. server_idx ] ;
@@ -550,7 +583,7 @@ impl<'a> Socket<'a> {
550583 ) ;
551584
552585 net_trace ! (
553- "sending {} octets to {:?}: {}" ,
586+ "sending {} octets to {} from port {}" ,
554587 payload. len( ) ,
555588 ip_repr. dst_addr( ) ,
556589 udp_repr. src_port
0 commit comments