@@ -16,11 +16,20 @@ pub const MAX_ADDRESS_COUNT: usize = 4;
16
16
pub const MAX_SERVER_COUNT : usize = 4 ;
17
17
18
18
const DNS_PORT : u16 = 53 ;
19
+ const MDNS_DNS_PORT : u16 = 5353 ;
19
20
const MAX_NAME_LEN : usize = 255 ;
20
21
const RETRANSMIT_DELAY : Duration = Duration :: from_millis ( 1_000 ) ;
21
22
const MAX_RETRANSMIT_DELAY : Duration = Duration :: from_millis ( 10_000 ) ;
22
23
const RETRANSMIT_TIMEOUT : Duration = Duration :: from_millis ( 10_000 ) ; // Should generally be 2-10 secs
23
24
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
+
24
33
/// Error returned by [`Socket::start_query`]
25
34
#[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
26
35
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -81,6 +90,7 @@ struct PendingQuery {
81
90
delay : Duration ,
82
91
83
92
server_idx : usize ,
93
+ mdns : bool ,
84
94
}
85
95
86
96
#[ derive( Debug ) ]
@@ -185,6 +195,7 @@ impl<'a> Socket<'a> {
185
195
& mut self ,
186
196
cx : & mut Context ,
187
197
name : & str ,
198
+ query_type : Type ,
188
199
) -> Result < QueryHandle , StartQueryError > {
189
200
let mut name = name. as_bytes ( ) ;
190
201
@@ -200,6 +211,12 @@ impl<'a> Socket<'a> {
200
211
201
212
let mut raw_name: Vec < u8 , MAX_NAME_LEN > = Vec :: new ( ) ;
202
213
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
+
203
220
for s in name. split ( |& c| c == b'.' ) {
204
221
if s. len ( ) > 63 {
205
222
net_trace ! ( "invalid name: too long label" ) ;
@@ -224,7 +241,7 @@ impl<'a> Socket<'a> {
224
241
. push ( 0x00 )
225
242
. map_err ( |_| StartQueryError :: NameTooLong ) ?;
226
243
227
- self . start_query_raw ( cx, & raw_name)
244
+ self . start_query_raw ( cx, & raw_name, query_type , mdns )
228
245
}
229
246
230
247
/// Start a query with a raw (wire-format) DNS name.
@@ -235,19 +252,33 @@ impl<'a> Socket<'a> {
235
252
& mut self ,
236
253
cx : & mut Context ,
237
254
raw_name : & [ u8 ] ,
255
+ query_type : Type ,
256
+ mdns : bool ,
238
257
) -> Result < QueryHandle , StartQueryError > {
239
258
let handle = self . find_free_query ( ) . ok_or ( StartQueryError :: NoFreeSlot ) ?;
240
259
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
+
241
271
self . queries [ handle. 0 ] = Some ( DnsQuery {
242
272
state : State :: Pending ( PendingQuery {
243
273
name : Vec :: from_slice ( raw_name) . map_err ( |_| StartQueryError :: NameTooLong ) ?,
244
- type_ : Type :: A ,
274
+ type_ : query_type ,
245
275
txid : cx. rand ( ) . rand_u16 ( ) ,
246
276
port : cx. rand ( ) . rand_source_port ( ) ,
247
277
delay : RETRANSMIT_DELAY ,
248
278
timeout_at : None ,
249
279
retransmit_at : Instant :: ZERO ,
250
280
server_idx : 0 ,
281
+ mdns,
251
282
} ) ,
252
283
#[ cfg( feature = "async" ) ]
253
284
waker : WakerRegistration :: new ( ) ,
@@ -313,11 +344,12 @@ impl<'a> Socket<'a> {
313
344
}
314
345
315
346
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
317
348
&& self
318
349
. servers
319
350
. 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 )
321
353
}
322
354
323
355
pub ( crate ) fn process (
@@ -500,7 +532,6 @@ impl<'a> Socket<'a> {
500
532
// Try next server. We check below whether we've tried all servers.
501
533
pq. server_idx += 1 ;
502
534
}
503
-
504
535
// Check if we've run out of servers to try.
505
536
if pq. server_idx >= self . servers . len ( ) {
506
537
net_trace ! ( "already tried all servers." ) ;
@@ -526,17 +557,19 @@ impl<'a> Socket<'a> {
526
557
opcode : Opcode :: Query ,
527
558
question : Question {
528
559
name : & pq. name ,
529
- type_ : Type :: A ,
560
+ type_ : pq . type_ ,
530
561
} ,
531
562
} ;
532
563
533
564
let mut payload = [ 0u8 ; 512 ] ;
534
565
let payload = & mut payload[ ..repr. buffer_len ( ) ] ;
535
566
repr. emit ( & mut Packet :: new_unchecked ( payload) ) ;
536
567
568
+ let dst_port = if pq. mdns { MDNS_DNS_PORT } else { DNS_PORT } ;
569
+
537
570
let udp_repr = UdpRepr {
538
571
src_port : pq. port ,
539
- dst_port : 53 ,
572
+ dst_port,
540
573
} ;
541
574
542
575
let dst_addr = self . servers [ pq. server_idx ] ;
@@ -550,7 +583,7 @@ impl<'a> Socket<'a> {
550
583
) ;
551
584
552
585
net_trace ! (
553
- "sending {} octets to {:?}: {}" ,
586
+ "sending {} octets to {} from port {}" ,
554
587
payload. len( ) ,
555
588
ip_repr. dst_addr( ) ,
556
589
udp_repr. src_port
0 commit comments