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_unicast_hops_v6(DEFAULT_HOP_LIMIT.into()).map_err(move |err| {
263 error!(tag = "udp"; "Error: {:?}", err);
264 ot::Error::Failed
265 })?;
266 socket.as_ref().set_multicast_hops_v6(DEFAULT_HOP_LIMIT.into()).map_err(move |err| {
267 error!(tag = "udp"; "Error: {:?}", err);
268 ot::Error::Failed
269 })?;
270
271 Ok(())
272 }
273
274 fn bind_to_netif(&mut self, net_if_id: ot::NetifIdentifier) -> ot::Result {
275 if self.get_handle().is_none() {
276 warn!(
277 tag = "udp";
278 "otPlatUdp:{:?}: Cannot bind_to_netif, socket is closed.",
279 self.as_ot_ptr()
280 );
281 return Err(ot::Error::InvalidState);
282 }
283
284 debug!(tag = "udp"; "otPlatUdp:{:?}: Bind to netif={:?}", self.as_ot_ptr(), net_if_id);
285
286 self.set_netif_id(net_if_id);
287
288 Ok(())
289 }
290
291 fn connect(&mut self) -> ot::Result {
292 if self.get_handle().is_none() {
293 warn!(
294 tag = "udp";
295 "otPlatUdp:{:?}: Cannot connect, socket is closed.",
296 self.as_ot_ptr()
297 );
298 return Err(ot::Error::InvalidState);
299 }
300
301 debug!(tag = "udp"; "otPlatUdp:{:?}: Connect to {:?}", self.as_ot_ptr(), self.peer_name());
302
303 Ok(())
308 }
309
310 fn send(&mut self, message: &ot::Message<'_>, info: &'_ ot::message::Info) -> ot::Result {
311 if self.get_handle().is_none() {
312 warn!(tag = "udp"; "otPlatUdp:{:?}: Cannot send, socket is closed.", self.as_ot_ptr());
313 return Err(ot::Error::InvalidState);
314 }
315
316 let data = message.to_vec();
317
318 debug!(
319 tag = "udp";
320 "otPlatUdp:{:?}: Sending {} byte packet to {:?}. {:?}",
321 self.as_ot_ptr(),
322 data.len(),
323 info.peer_name(),
324 info
325 );
326
327 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
328
329 if info.multicast_loop() {
331 socket.as_ref().set_multicast_loop_v6(true).map_err(move |err| {
332 error!(tag = "udp"; "Error: {:?}", err);
333 ot::Error::Failed
334 })?;
335 }
336
337 let should_set_hop_limit = info.hop_limit() > 0 || info.allow_zero_hop_limit();
338
339 if should_set_hop_limit {
340 socket.as_ref().set_unicast_hops_v6(info.hop_limit().into()).map_err(move |err| {
341 error!(tag = "udp"; "Error: {:?}", err);
342 ot::Error::Failed
343 })?;
344 socket.as_ref().set_multicast_hops_v6(info.hop_limit().into()).map_err(move |err| {
345 error!(tag = "udp"; "Error: {:?}", err);
346 ot::Error::Failed
347 })?;
348 }
349
350 let mut sockaddr: std::net::SocketAddrV6 = info.peer_name().into();
351
352 if self.get_netif_id() == ot::NetifIdentifier::Unspecified && dest_needs_scope(&sockaddr) {
353 let netif_id = if info.is_host_interface() {
354 ot::NetifIdentifier::Backbone
355 } else {
356 ot::NetifIdentifier::Thread
357 };
358
359 let platform_backing = unsafe { PlatformBacking::as_ref() };
362
363 let netif: ot::NetifIndex = platform_backing
364 .lookup_netif_index(netif_id)
365 .unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
366 sockaddr.set_scope_id(netif);
367 }
368
369 let ret = match socket.as_ref().send_to(&data, &sockaddr.into()) {
370 Ok(sent) if data.len() == sent => Ok(()),
371 Ok(sent) => {
372 warn!(
373 tag = "udp";
374 "otPlatUdpSend:{:?}: send_to did not send whole packet, only sent {} bytes",
375 self.as_ot_ptr(),
376 sent
377 );
378 Err(ot::Error::Failed)
379 }
380 Err(err) => {
381 warn!(
382 tag = "udp";
383 "otPlatUdpSend:{:?}: send_to({:?}) failed: {:?}",
384 self.as_ot_ptr(),
385 sockaddr,
386 err
387 );
388 Err(ot::Error::Failed)
389 }
390 };
391
392 if should_set_hop_limit {
394 socket.as_ref().set_unicast_hops_v6(DEFAULT_HOP_LIMIT.into()).map_err(move |err| {
395 error!(tag = "udp"; "Error: {:?}", err);
396 ot::Error::Failed
397 })?;
398 socket.as_ref().set_multicast_hops_v6(DEFAULT_HOP_LIMIT.into()).map_err(
399 move |err| {
400 error!(tag = "udp"; "Error: {:?}", err);
401 ot::Error::Failed
402 },
403 )?;
404 }
405
406 if info.multicast_loop() {
408 socket.as_ref().set_multicast_loop_v6(false).map_err(move |err| {
409 error!(tag = "udp"; "Error: {:?}", err);
410 ot::Error::Failed
411 })?;
412 }
413
414 ret
415 }
416
417 fn join_mcast_group(
418 &mut self,
419 netif: ot::NetifIdentifier,
420 addr: &ot::Ip6Address,
421 ) -> ot::Result {
422 if self.get_handle().is_none() {
423 warn!(
424 tag = "udp";
425 "otPlatUdp:{:?}: Cannot join_mcast_group, socket is closed.",
426 self.as_ot_ptr()
427 );
428 return Err(ot::Error::InvalidState);
429 }
430
431 debug!(
432 tag = "udp";
433 "otPlatUdp:{:?}: JoinMulticastGroup {:?} on netif {:?}",
434 self.as_ot_ptr(),
435 addr,
436 netif
437 );
438
439 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
440
441 let platform_backing = unsafe { PlatformBacking::as_ref() };
444 let netif: ot::NetifIndex =
445 platform_backing.lookup_netif_index(netif).unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
446
447 match socket.as_ref().join_multicast_v6(addr, netif) {
448 Ok(()) => Ok(()),
449 Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => Ok(()),
450 Err(err) => {
451 error!(
452 tag = "udp";
453 "otPlatUdp:{:?}: Error joining multicast group {addr}%{netif}: {err:?}",
454 self.as_ot_ptr()
455 );
456 Err(ot::Error::Failed)
457 }
458 }
459 }
460
461 fn leave_mcast_group(
462 &mut self,
463 netif: ot::NetifIdentifier,
464 addr: &ot::Ip6Address,
465 ) -> ot::Result {
466 if self.get_handle().is_none() {
467 warn!(
468 tag = "udp";
469 "otPlatUdp:{:?}: Cannot leave_mcast_group, socket is closed.",
470 self.as_ot_ptr()
471 );
472 return Err(ot::Error::InvalidState);
473 }
474
475 debug!(
476 tag = "udp";
477 "otPlatUdp:{:?}: LeaveMulticastGroup {:?} on netif {:?}",
478 self.as_ot_ptr(),
479 addr,
480 netif
481 );
482 let socket = self.get_async_udp_socket().ok_or(ot::Error::Failed)?;
483
484 let platform_backing = unsafe { PlatformBacking::as_ref() };
487 let netif: ot::NetifIndex =
488 platform_backing.lookup_netif_index(netif).unwrap_or(ot::NETIF_INDEX_UNSPECIFIED);
489
490 match socket.as_ref().leave_multicast_v6(addr, netif) {
491 Ok(()) => Ok(()),
492 Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => Ok(()),
493 Err(err) => {
494 error!(
495 tag = "udp";
496 "otPlatUdp:{:?}: Error leaving multicast group {addr}%{netif}: {err:?}",
497 self.as_ot_ptr()
498 );
499 Err(ot::Error::Failed)
500 }
501 }
502 }
503}
504
505#[unsafe(no_mangle)]
506unsafe extern "C" fn otPlatUdpSocket(ot_socket_ptr: *mut otUdpSocket) -> otError {
507 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }.unwrap().open().into_ot_error()
508}
509
510#[unsafe(no_mangle)]
511unsafe extern "C" fn otPlatUdpClose(ot_socket_ptr: *mut otUdpSocket) -> otError {
512 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }.unwrap().close().into_ot_error()
513}
514
515#[unsafe(no_mangle)]
516unsafe extern "C" fn otPlatUdpBind(ot_socket_ptr: *mut otUdpSocket) -> otError {
517 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }.unwrap().bind().into_ot_error()
518}
519
520#[unsafe(no_mangle)]
521unsafe extern "C" fn otPlatUdpBindToNetif(
522 ot_socket_ptr: *mut otUdpSocket,
523 net_if_id: otNetifIdentifier,
524) -> otError {
525 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }
526 .unwrap()
527 .bind_to_netif(ot::NetifIdentifier::from(net_if_id))
528 .into_ot_error()
529}
530
531#[unsafe(no_mangle)]
532unsafe extern "C" fn otPlatUdpConnect(ot_socket_ptr: *mut otUdpSocket) -> otError {
533 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }.unwrap().connect().into_ot_error()
534}
535
536#[unsafe(no_mangle)]
537unsafe extern "C" fn otPlatUdpSend(
538 ot_socket_ptr: *mut otUdpSocket,
539 message: *mut otMessage,
540 message_info: *const otMessageInfo,
541) -> otError {
542 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }
543 .unwrap()
544 .send(
545 unsafe { ot::Message::ref_from_ot_ptr(message) }.unwrap(),
546 unsafe { ot::message::Info::ref_from_ot_ptr(message_info) }.unwrap(),
547 )
548 .map(move |_| unsafe { otMessageFree(message) }) .into_ot_error()
550}
551
552#[unsafe(no_mangle)]
553unsafe extern "C" fn otPlatUdpJoinMulticastGroup(
554 ot_socket_ptr: *mut otUdpSocket,
555 net_if_id: otNetifIdentifier,
556 addr: *const otIp6Address,
557) -> otError {
558 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }
559 .unwrap()
560 .join_mcast_group(
561 net_if_id.into(),
562 unsafe { ot::Ip6Address::ref_from_ot_ptr(addr) }.unwrap(),
563 )
564 .into_ot_error()
565}
566
567#[unsafe(no_mangle)]
568unsafe extern "C" fn otPlatUdpLeaveMulticastGroup(
569 ot_socket_ptr: *mut otUdpSocket,
570 net_if_id: otNetifIdentifier,
571 addr: *const otIp6Address,
572) -> otError {
573 unsafe { ot::UdpSocket::mut_from_ot_mut_ptr(ot_socket_ptr) }
574 .unwrap()
575 .leave_mcast_group(
576 net_if_id.into(),
577 unsafe { ot::Ip6Address::ref_from_ot_ptr(addr) }.unwrap(),
578 )
579 .into_ot_error()
580}
581
582#[cfg(test)]
583mod test {
584 use super::*;
585 use std::net::{Ipv6Addr, SocketAddrV6};
586
587 #[test]
588 fn test_dest_needs_scope() {
589 assert!(!dest_needs_scope(&SocketAddrV6::new(
590 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
591 8080,
592 0,
593 0
594 )));
595 assert!(!dest_needs_scope(&SocketAddrV6::new(
596 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
597 8080,
598 0,
599 1
600 )));
601
602 assert!(dest_needs_scope(&SocketAddrV6::new(
603 Ipv6Addr::new(0xfe80, 0xdb8, 0, 0, 0, 0, 0, 1),
604 8080,
605 0,
606 0
607 )));
608 assert!(!dest_needs_scope(&SocketAddrV6::new(
609 Ipv6Addr::new(0xfe80, 0xdb8, 0, 0, 0, 0, 0, 1),
610 8080,
611 0,
612 1
613 )));
614
615 assert!(!dest_needs_scope(&SocketAddrV6::new(
616 Ipv6Addr::new(0xff05, 0xdb8, 0, 0, 0, 0, 0, 1),
617 8080,
618 0,
619 0
620 )));
621 assert!(!dest_needs_scope(&SocketAddrV6::new(
622 Ipv6Addr::new(0xff05, 0xdb8, 0, 0, 0, 0, 0, 1),
623 8080,
624 0,
625 1
626 )));
627
628 assert!(dest_needs_scope(&SocketAddrV6::new(
629 Ipv6Addr::new(0xff03, 0xdb8, 0, 0, 0, 0, 0, 1),
630 8080,
631 0,
632 0
633 )));
634 assert!(!dest_needs_scope(&SocketAddrV6::new(
635 Ipv6Addr::new(0xff03, 0xdb8, 0, 0, 0, 0, 0, 1),
636 8080,
637 0,
638 1
639 )));
640
641 assert!(dest_needs_scope(&SocketAddrV6::new(
642 Ipv6Addr::new(0xff02, 0xdb8, 0, 0, 0, 0, 0, 1),
643 8080,
644 0,
645 0
646 )));
647 assert!(!dest_needs_scope(&SocketAddrV6::new(
648 Ipv6Addr::new(0xff02, 0xdb8, 0, 0, 0, 0, 0, 1),
649 8080,
650 0,
651 1
652 )));
653
654 assert!(!dest_needs_scope(&SocketAddrV6::new(
655 Ipv6Addr::new(0xff01, 0xdb8, 0, 0, 0, 0, 0, 1),
656 8080,
657 0,
658 0
659 )));
660 assert!(!dest_needs_scope(&SocketAddrV6::new(
661 Ipv6Addr::new(0xff01, 0xdb8, 0, 0, 0, 0, 0, 1),
662 8080,
663 0,
664 1
665 )));
666 }
667}