1use super::*;
6use fuchsia_async::net as fasync_net;
7use futures::never::Never;
8use openthread::ot::OtCastable;
9use openthread_sys::*;
10use std::ffi::c_void;
11use std::ptr::NonNull;
12use std::task::Poll;
13
14const DEFAULT_HOP_LIMIT: u8 = 64;
16
17pub(crate) fn poll_ot_udp_socket(
18 ot_udp_socket: &ot::UdpSocket<'_>,
19 instance: &ot::Instance,
20 cx: &mut std::task::Context<'_>,
21) -> Poll<Result<Never, anyhow::Error>> {
22 let socket = ot_udp_socket.get_async_udp_socket();
23 if let Some(socket) = socket {
24 let mut buffer = [0u8; crate::UDP_PACKET_MAX_LENGTH];
25 match socket.async_recv_from(&mut buffer, cx) {
26 Poll::Ready(Ok((len, sock_addr))) => {
27 let sock_addr = sock_addr.as_socket_ipv6().ok_or_else(|| {
28 anyhow::format_err!("Expected IPv6 sockaddr, got something else")
29 })?;
30 let ot_sockaddr: ot::SockAddr = sock_addr.into();
31
32 debug!(
33 tag = "udp";
34 "otPlatUdp:{:?}: Incoming {} byte packet from {:?}",
35 ot_udp_socket.as_ot_ptr(),
36 len,
37 ot_sockaddr
38 );
39
40 let mut message = ot::Message::udp_new(instance, None)?;
41 message.append(&buffer[..len])?;
42 let mut info = ot::message::Info::new(ot_udp_socket.sock_name(), ot_sockaddr);
43
44 if ot_udp_socket.get_netif_id() == ot::NetifIdentifier::Backbone {
45 info.set_host_interface(true);
46 } else if ot_udp_socket.get_netif_id() == ot::NetifIdentifier::Thread {
47 info.set_host_interface(false);
48 } else if let Some(host_iface) = unsafe {
49 PlatformBacking::as_ref().lookup_netif_index(ot::NetifIdentifier::Backbone)
54 } {
55 let scope_id = sock_addr.scope_id();
56 debug!(
57 tag = "udp";
58 "inbound scope_id = {}, host_iface = {}", scope_id, host_iface
59 );
60 info.set_host_interface(scope_id == host_iface);
61 }
62
63 ot_udp_socket.handle_receive(&message, &info);
66 }
67 Poll::Ready(Err(err)) => {
68 return Poll::Ready(Err(err.into()));
69 }
70 Poll::Pending => {}
71 }
72 }
73 Poll::Pending
74}
75
76struct UdpSocketBacking {
77 socket: fasync_net::UdpSocket,
78 netif_id: ot::NetifIdentifier,
79}
80
81fn dest_needs_scope(sockaddr: &std::net::SocketAddrV6) -> bool {
83 let dest_is_unicast_link_local = (sockaddr.ip().segments()[0] & 0xffc0) == 0xfe80;
84 let dest_is_multicast_link_local = sockaddr.ip().segments()[0] == 0xff02;
85 let dest_is_multicast_realm_local = sockaddr.ip().segments()[0] == 0xff03;
86
87 sockaddr.scope_id() == 0
88 && (dest_is_unicast_link_local
89 | dest_is_multicast_link_local
90 | dest_is_multicast_realm_local)
91}
92
93trait UdpSocketHelpers {
94 fn get_async_udp_socket_backing(&self) -> Option<&UdpSocketBacking>;
96
97 fn get_async_udp_socket(&self) -> Option<&fasync_net::UdpSocket>;
99
100 fn set_async_udp_socket(&mut self, socket: fasync_net::UdpSocket);
102
103 fn drop_async_udp_socket(&mut self);
105
106 fn get_netif_id(&self) -> ot::NetifIdentifier;
107 fn set_netif_id(&mut self, netif_id: ot::NetifIdentifier);
108
109 fn open(&mut self) -> ot::Result;
110 fn close(&mut self) -> ot::Result;
111 fn bind(&mut self) -> ot::Result;
112 fn bind_to_netif(&mut self, netif: ot::NetifIdentifier) -> ot::Result;
113 fn connect(&mut self) -> ot::Result;
114 fn send(
115 &mut self,
116 message: &'_ ot::Message<'_>,
117 message_info: &'_ ot::message::Info,
118 ) -> ot::Result;
119 fn join_mcast_group(&mut self, netif: ot::NetifIdentifier, addr: &ot::Ip6Address)
120 -> ot::Result;
121 fn leave_mcast_group(
122 &mut self,
123 netif: ot::NetifIdentifier,
124 addr: &ot::Ip6Address,
125 ) -> ot::Result;
126}
127
128impl UdpSocketHelpers for ot::UdpSocket<'_> {
129 fn get_async_udp_socket_backing(&self) -> Option<&UdpSocketBacking> {
130 self.get_handle().map(|handle| {
131 unsafe { &*(handle.as_ptr() as *mut UdpSocketBacking) }
134 })
135 }
136
137 fn get_netif_id(&self) -> ot::NetifIdentifier {
138 self.get_async_udp_socket_backing()
139 .map(|x| x.netif_id)
140 .unwrap_or(ot::NetifIdentifier::Unspecified)
141 }
142
143 fn set_netif_id(&mut self, netif_id: ot::NetifIdentifier) {
144 self.get_handle()
145 .map(|handle| {
146 unsafe { &mut *(handle.as_ptr() as *mut UdpSocketBacking) }
149 })
150 .unwrap()
151 .netif_id = netif_id;
152 }
153
154 fn get_async_udp_socket(&self) -> Option<&fasync_net::UdpSocket> {
155 self.get_async_udp_socket_backing().map(|x| &x.socket)
156 }
157
158 fn set_async_udp_socket(&mut self, socket: fasync_net::UdpSocket) {
159 assert!(self.get_handle().is_none());
160
161 let socket_backing =
162 UdpSocketBacking { socket, netif_id: ot::NetifIdentifier::Unspecified };
163
164 let boxed = Box::new(socket_backing);
165
166 let socket_ptr = Box::leak(boxed) as *mut UdpSocketBacking;
170
171 self.set_handle(Some(NonNull::new(socket_ptr as *mut c_void).unwrap()));
172 }
173
174 fn drop_async_udp_socket(&mut self) {
175 if let Some(handle) = self.get_handle() {
176 let boxed = unsafe {
179 Box::<UdpSocketBacking>::from_raw(handle.as_ptr() as *mut UdpSocketBacking)
180 };
181
182 std::mem::drop(boxed);
184
185 self.set_handle(None);
186 }
187 }
188
189 fn open(&mut self) -> ot::Result {
190 debug!(tag = "udp"; "otPlatUdp:{:?}: Opening", self.as_ot_ptr());
191
192 if self.get_handle().is_some() {
193 warn!(
194 tag = "udp";
195 "otPlatUdp:{:?}: Tried to open already open socket",
196 self.as_ot_ptr()
197 );
198 return Err(ot::Error::Already);
199 }
200
201 let socket = socket2::Socket::new(
202 socket2::Domain::IPV6,
203 socket2::Type::DGRAM,
204 Some(socket2::Protocol::UDP),
205 )
206 .map_err(|err| {
207 error!(tag = "udp"; "Error: {:?}", err);
208 Err(ot::Error::Failed)
209 })?;
210
211 let socket = fasync_net::UdpSocket::from_socket(socket.into()).map_err(|err| {
212 error!(tag = "udp"; "Error: {:?}", err);
213 Err(ot::Error::Failed)
214 })?;
215
216 self.set_async_udp_socket(socket);
217
218 Ok(())
219 }
220
221 fn close(&mut self) -> ot::Result {
222 debug!(tag = "udp"; "otPlatUdp:{:?}: Closing", self.as_ot_ptr());
223
224 if self.get_handle().is_none() {
225 warn!(
226 tag = "udp";
227 "otPlatUdp:{:?}: Tried to close already closed socket",
228 self.as_ot_ptr()
229 );
230 return Err(ot::Error::Already);
231 }
232
233 self.drop_async_udp_socket();
234
235 Ok(())
236 }
237
238 fn bind(&mut self) -> ot::Result {
239 if self.get_handle().is_none() {
240 warn!(tag = "udp"; "otPlatUdp:{:?}: Cannot bind, socket is closed.", self.as_ot_ptr());
241 return Err(ot::Error::InvalidState);
242 }
243
244 let mut sockaddr: std::net::SocketAddrV6 = self.sock_name().into();
245
246 let platform_backing = unsafe { PlatformBacking::as_ref() };
249
250 if let Some(netif) = platform_backing.lookup_netif_index(self.get_netif_id()) {
251 sockaddr.set_scope_id(netif);
252 }
253
254 debug!(tag = "udp"; "otPlatUdp:{:?}: Bind to {}", self.as_ot_ptr(), sockaddr);
255
256 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
257 socket.as_ref().bind(&sockaddr.into()).map_err(move |err| {
258 error!(tag = "udp"; "Error: {:?}", err);
259 ot::Error::Failed
260 })?;
261
262 socket.as_ref().set_ttl(DEFAULT_HOP_LIMIT.into()).map_err(move |err| {
263 error!(tag = "udp"; "Error: {:?}", err);
264 ot::Error::Failed
265 })?;
266
267 Ok(())
268 }
269
270 fn bind_to_netif(&mut self, net_if_id: ot::NetifIdentifier) -> ot::Result {
271 if self.get_handle().is_none() {
272 warn!(
273 tag = "udp";
274 "otPlatUdp:{:?}: Cannot bind_to_netif, socket is closed.",
275 self.as_ot_ptr()
276 );
277 return Err(ot::Error::InvalidState);
278 }
279
280 debug!(tag = "udp"; "otPlatUdp:{:?}: Bind to netif={:?}", self.as_ot_ptr(), net_if_id);
281
282 self.set_netif_id(net_if_id);
283
284 Ok(())
285 }
286
287 fn connect(&mut self) -> ot::Result {
288 if self.get_handle().is_none() {
289 warn!(
290 tag = "udp";
291 "otPlatUdp:{:?}: Cannot connect, socket is closed.",
292 self.as_ot_ptr()
293 );
294 return Err(ot::Error::InvalidState);
295 }
296
297 debug!(tag = "udp"; "otPlatUdp:{:?}: Connect to {:?}", self.as_ot_ptr(), self.peer_name());
298
299 Ok(())
304 }
305
306 fn send(&mut self, message: &ot::Message<'_>, info: &'_ ot::message::Info) -> ot::Result {
307 if self.get_handle().is_none() {
308 warn!(tag = "udp"; "otPlatUdp:{:?}: Cannot send, socket is closed.", self.as_ot_ptr());
309 return Err(ot::Error::InvalidState);
310 }
311
312 let data = message.to_vec();
313
314 debug!(
315 tag = "udp";
316 "otPlatUdp:{:?}: Sending {} byte packet to {:?}. {:?}",
317 self.as_ot_ptr(),
318 data.len(),
319 info.peer_name(),
320 info
321 );
322
323 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
324
325 if info.multicast_loop() {
327 socket.as_ref().set_multicast_loop_v6(true).map_err(move |err| {
328 error!(tag = "udp"; "Error: {:?}", err);
329 ot::Error::Failed
330 })?;
331 }
332
333 let should_set_hop_limit = info.hop_limit() > 0 || info.allow_zero_hop_limit();
334
335 if should_set_hop_limit {
336 socket.as_ref().set_ttl(info.hop_limit().into()).map_err(move |err| {
337 error!(tag = "udp"; "Error: {:?}", err);
338 ot::Error::Failed
339 })?;
340 }
341
342 let mut sockaddr: std::net::SocketAddrV6 = info.peer_name().into();
343
344 if self.get_netif_id() == ot::NetifIdentifier::Unspecified && dest_needs_scope(&sockaddr) {
345 let netif_id = if info.is_host_interface() {
346 ot::NetifIdentifier::Backbone
347 } else {
348 ot::NetifIdentifier::Thread
349 };
350
351 let platform_backing = unsafe { PlatformBacking::as_ref() };
354
355 let netif: ot::NetifIndex = platform_backing
356 .lookup_netif_index(netif_id)
357 .unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
358 sockaddr.set_scope_id(netif);
359 }
360
361 let ret = match socket.as_ref().send_to(&data, &sockaddr.into()) {
362 Ok(sent) if data.len() == sent => Ok(()),
363 Ok(sent) => {
364 warn!(
365 tag = "udp";
366 "otPlatUdpSend:{:?}: send_to did not send whole packet, only sent {} bytes",
367 self.as_ot_ptr(),
368 sent
369 );
370 Err(ot::Error::Failed)
371 }
372 Err(err) => {
373 warn!(
374 tag = "udp";
375 "otPlatUdpSend:{:?}: send_to({:?}) failed: {:?}",
376 self.as_ot_ptr(),
377 sockaddr,
378 err
379 );
380 Err(ot::Error::Failed)
381 }
382 };
383
384 if should_set_hop_limit {
386 socket.as_ref().set_ttl(DEFAULT_HOP_LIMIT.into()).map_err(move |err| {
387 error!(tag = "udp"; "Error: {:?}", err);
388 ot::Error::Failed
389 })?;
390 }
391
392 if info.multicast_loop() {
394 socket.as_ref().set_multicast_loop_v6(false).map_err(move |err| {
395 error!(tag = "udp"; "Error: {:?}", err);
396 ot::Error::Failed
397 })?;
398 }
399
400 ret
401 }
402
403 fn join_mcast_group(
404 &mut self,
405 netif: ot::NetifIdentifier,
406 addr: &ot::Ip6Address,
407 ) -> ot::Result {
408 if self.get_handle().is_none() {
409 warn!(
410 tag = "udp";
411 "otPlatUdp:{:?}: Cannot join_mcast_group, socket is closed.",
412 self.as_ot_ptr()
413 );
414 return Err(ot::Error::InvalidState);
415 }
416
417 debug!(
418 tag = "udp";
419 "otPlatUdp:{:?}: JoinMulticastGroup {:?} on netif {:?}",
420 self.as_ot_ptr(),
421 addr,
422 netif
423 );
424
425 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
426
427 let platform_backing = unsafe { PlatformBacking::as_ref() };
430 let netif: ot::NetifIndex =
431 platform_backing.lookup_netif_index(netif).unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
432
433 match socket.as_ref().join_multicast_v6(addr, netif) {
434 Ok(()) => Ok(()),
435 Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => Ok(()),
436 Err(err) => {
437 error!(
438 tag = "udp";
439 "otPlatUdp:{:?}: Error joining multicast group {addr}%{netif}: {err:?}",
440 self.as_ot_ptr()
441 );
442 Err(ot::Error::Failed)
443 }
444 }
445 }
446
447 fn leave_mcast_group(
448 &mut self,
449 netif: ot::NetifIdentifier,
450 addr: &ot::Ip6Address,
451 ) -> ot::Result {
452 if self.get_handle().is_none() {
453 warn!(
454 tag = "udp";
455 "otPlatUdp:{:?}: Cannot leave_mcast_group, socket is closed.",
456 self.as_ot_ptr()
457 );
458 return Err(ot::Error::InvalidState);
459 }
460
461 debug!(
462 tag = "udp";
463 "otPlatUdp:{:?}: LeaveMulticastGroup {:?} on netif {:?}",
464 self.as_ot_ptr(),
465 addr,
466 netif
467 );
468 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
469
470 let platform_backing = unsafe { PlatformBacking::as_ref() };
473 let netif: ot::NetifIndex =
474 platform_backing.lookup_netif_index(netif).unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
475
476 match socket.as_ref().leave_multicast_v6(addr, netif) {
477 Ok(()) => Ok(()),
478 Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => Ok(()),
479 Err(err) => {
480 error!(
481 tag = "udp";
482 "otPlatUdp:{:?}: Error leaving multicast group {addr}%{netif}: {err:?}",
483 self.as_ot_ptr()
484 );
485 Err(ot::Error::Failed)
486 }
487 }
488 }
489}
490
491#[no_mangle]
492unsafe extern "C" fn otPlatUdpSocket(ot_socket_ptr: *mut otUdpSocket) -> otError {
493 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr).unwrap().open().into_ot_error()
494}
495
496#[no_mangle]
497unsafe extern "C" fn otPlatUdpClose(ot_socket_ptr: *mut otUdpSocket) -> otError {
498 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr).unwrap().close().into_ot_error()
499}
500
501#[no_mangle]
502unsafe extern "C" fn otPlatUdpBind(ot_socket_ptr: *mut otUdpSocket) -> otError {
503 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr).unwrap().bind().into_ot_error()
504}
505
506#[no_mangle]
507unsafe extern "C" fn otPlatUdpBindToNetif(
508 ot_socket_ptr: *mut otUdpSocket,
509 net_if_id: otNetifIdentifier,
510) -> otError {
511 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr)
512 .unwrap()
513 .bind_to_netif(ot::NetifIdentifier::from(net_if_id))
514 .into_ot_error()
515}
516
517#[no_mangle]
518unsafe extern "C" fn otPlatUdpConnect(ot_socket_ptr: *mut otUdpSocket) -> otError {
519 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr).unwrap().connect().into_ot_error()
520}
521
522#[no_mangle]
523unsafe extern "C" fn otPlatUdpSend(
524 ot_socket_ptr: *mut otUdpSocket,
525 message: *mut otMessage,
526 message_info: *const otMessageInfo,
527) -> otError {
528 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr)
529 .unwrap()
530 .send(
531 ot::Message::ref_from_ot_ptr(message).unwrap(),
532 ot::message::Info::ref_from_ot_ptr(message_info).unwrap(),
533 )
534 .map(move |_| otMessageFree(message)) .into_ot_error()
536}
537
538#[no_mangle]
539unsafe extern "C" fn otPlatUdpJoinMulticastGroup(
540 ot_socket_ptr: *mut otUdpSocket,
541 net_if_id: otNetifIdentifier,
542 addr: *const otIp6Address,
543) -> otError {
544 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr)
545 .unwrap()
546 .join_mcast_group(net_if_id.into(), ot::Ip6Address::ref_from_ot_ptr(addr).unwrap())
547 .into_ot_error()
548}
549
550#[no_mangle]
551unsafe extern "C" fn otPlatUdpLeaveMulticastGroup(
552 ot_socket_ptr: *mut otUdpSocket,
553 net_if_id: otNetifIdentifier,
554 addr: *const otIp6Address,
555) -> otError {
556 ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr)
557 .unwrap()
558 .leave_mcast_group(net_if_id.into(), ot::Ip6Address::ref_from_ot_ptr(addr).unwrap())
559 .into_ot_error()
560}
561
562#[cfg(test)]
563mod test {
564 use super::*;
565 use std::net::{Ipv6Addr, SocketAddrV6};
566
567 #[test]
568 fn test_dest_needs_scope() {
569 assert!(!dest_needs_scope(&SocketAddrV6::new(
570 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
571 8080,
572 0,
573 0
574 )));
575 assert!(!dest_needs_scope(&SocketAddrV6::new(
576 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
577 8080,
578 0,
579 1
580 )));
581
582 assert!(dest_needs_scope(&SocketAddrV6::new(
583 Ipv6Addr::new(0xfe80, 0xdb8, 0, 0, 0, 0, 0, 1),
584 8080,
585 0,
586 0
587 )));
588 assert!(!dest_needs_scope(&SocketAddrV6::new(
589 Ipv6Addr::new(0xfe80, 0xdb8, 0, 0, 0, 0, 0, 1),
590 8080,
591 0,
592 1
593 )));
594
595 assert!(!dest_needs_scope(&SocketAddrV6::new(
596 Ipv6Addr::new(0xff05, 0xdb8, 0, 0, 0, 0, 0, 1),
597 8080,
598 0,
599 0
600 )));
601 assert!(!dest_needs_scope(&SocketAddrV6::new(
602 Ipv6Addr::new(0xff05, 0xdb8, 0, 0, 0, 0, 0, 1),
603 8080,
604 0,
605 1
606 )));
607
608 assert!(dest_needs_scope(&SocketAddrV6::new(
609 Ipv6Addr::new(0xff03, 0xdb8, 0, 0, 0, 0, 0, 1),
610 8080,
611 0,
612 0
613 )));
614 assert!(!dest_needs_scope(&SocketAddrV6::new(
615 Ipv6Addr::new(0xff03, 0xdb8, 0, 0, 0, 0, 0, 1),
616 8080,
617 0,
618 1
619 )));
620
621 assert!(dest_needs_scope(&SocketAddrV6::new(
622 Ipv6Addr::new(0xff02, 0xdb8, 0, 0, 0, 0, 0, 1),
623 8080,
624 0,
625 0
626 )));
627 assert!(!dest_needs_scope(&SocketAddrV6::new(
628 Ipv6Addr::new(0xff02, 0xdb8, 0, 0, 0, 0, 0, 1),
629 8080,
630 0,
631 1
632 )));
633
634 assert!(!dest_needs_scope(&SocketAddrV6::new(
635 Ipv6Addr::new(0xff01, 0xdb8, 0, 0, 0, 0, 0, 1),
636 8080,
637 0,
638 0
639 )));
640 assert!(!dest_needs_scope(&SocketAddrV6::new(
641 Ipv6Addr::new(0xff01, 0xdb8, 0, 0, 0, 0, 0, 1),
642 8080,
643 0,
644 1
645 )));
646 }
647}