Skip to main content

openthread/ot/
ip6.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::prelude_internal::*;
6
7/// Functional equivalent of [`otsys::otIcmp6EchoMode`](crate::otsys::otIcmp6EchoMode).
8#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
9pub enum Icmp6EchoMode {
10    /// ICMPv6 Echo processing enabled for unicast and multicast requests.
11    HandleAll = OT_ICMP6_ECHO_HANDLER_ALL as isize,
12
13    /// ICMPv6 Echo processing disabled.
14    HandleDisabled = OT_ICMP6_ECHO_HANDLER_DISABLED as isize,
15
16    /// ICMPv6 Echo processing enabled only for multicast requests only.
17    HandleMulticastOnly = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY as isize,
18
19    /// ICMPv6 Echo processing enabled only for unicast requests only.
20    HandleUnicastOnly = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY as isize,
21
22    /// ICMPv6 Echo processing enabled for RLOC/ALOC destinations only
23    HandleRlocAlocOnly = OT_ICMP6_ECHO_HANDLER_RLOC_ALOC_ONLY as isize,
24}
25
26impl From<otIcmp6EchoMode> for Icmp6EchoMode {
27    fn from(x: otIcmp6EchoMode) -> Self {
28        use num::FromPrimitive;
29        Self::from_u32(x).unwrap_or_else(|| panic!("Unknown otIcmp6EchoMode value: {x}"))
30    }
31}
32
33impl From<Icmp6EchoMode> for otIcmp6EchoMode {
34    fn from(x: Icmp6EchoMode) -> Self {
35        x as otIcmp6EchoMode
36    }
37}
38
39/// Iterates over the [`NetifAddress`] structs from [`Ip6::ip6_get_unicast_addresses()`].
40#[derive(Default, Debug, Clone)]
41pub struct NetifAddressIterator<'a>(Option<&'a NetifAddress>);
42
43impl<'a> Iterator for NetifAddressIterator<'a> {
44    type Item = &'a NetifAddress;
45
46    fn next(&mut self) -> Option<Self::Item> {
47        if let Some(addr_ref) = self.0 {
48            // SAFETY: The `otNetifAddress` pointer used here comes
49            //         from `otIp6GetUnicastAddresses`, which is guaranteed
50            //         to have valid values for `mNext`.
51            self.0 = unsafe { NetifAddress::ref_from_ot_ptr(addr_ref.0.mNext) };
52            Some(addr_ref)
53        } else {
54            None
55        }
56    }
57}
58
59/// Iterates over the [`NetifMulticastAddress`] structs from [`Ip6::ip6_get_multicast_addresses()`].
60#[derive(Default, Debug, Clone)]
61pub struct NetifMulticastAddressIterator<'a>(Option<&'a NetifMulticastAddress>);
62
63impl<'a> Iterator for NetifMulticastAddressIterator<'a> {
64    type Item = &'a NetifMulticastAddress;
65
66    fn next(&mut self) -> Option<Self::Item> {
67        if let Some(addr_ref) = self.0 {
68            // SAFETY: The `otNetifMulticastAddress` pointer used here comes
69            //         from `otIp6GetMulticastAddresses`, which is guaranteed
70            //         to have valid values for `mNext`.
71            self.0 = unsafe { NetifMulticastAddress::ref_from_ot_ptr(addr_ref.0.mNext) };
72            Some(addr_ref)
73        } else {
74            None
75        }
76    }
77}
78
79/// Methods from the [OpenThread "IPv6" Module](https://openthread.io/reference/group/api-ip6).
80pub trait Ip6 {
81    /// Functional equivalent of [`otsys::otIp6Send`](crate::otsys::otIp6Send).
82    fn ip6_send(&self, message: OtMessageBox<'_>) -> Result;
83
84    /// Similar to [`ip6_send()`], but takes a byte slice instead
85    /// of an [`OtMessageBox`](crate::OtMessageBox).
86    fn ip6_send_data(&self, data: &[u8]) -> Result;
87
88    /// Similar to [`ip6_send_data()`], but sends the packet without layer-2 security.
89    fn ip6_send_data_direct(&self, data: &[u8]) -> Result;
90
91    /// Functional equivalent of [`otsys::otIp6IsEnabled`](crate::otsys::otIp6IsEnabled).
92    fn ip6_is_enabled(&self) -> bool;
93
94    /// Functional equivalent of [`otsys::otIp6SetEnabled`](crate::otsys::otIp6SetEnabled).
95    fn ip6_set_enabled(&self, enabled: bool) -> Result;
96
97    /// Functional equivalent of
98    /// [`otsys::otIp6AddUnicastAddress`](crate::otsys::otIp6AddUnicastAddress).
99    fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result;
100
101    /// Functional equivalent of
102    /// [`otsys::otIp6RemoveUnicastAddress`](crate::otsys::otIp6RemoveUnicastAddress).
103    fn ip6_remove_unicast_address(&self, addr: &Ip6Address) -> Result;
104
105    /// Functional equivalent of
106    /// [`otsys::otIp6SubscribeMulticastAddress`](crate::otsys::otIp6SubscribeMulticastAddress).
107    fn ip6_join_multicast_group(&self, addr: &Ip6Address) -> Result;
108
109    /// Functional equivalent of
110    /// [`otsys::otIp6UnsubscribeMulticastAddress`](crate::otsys::otIp6UnsubscribeMulticastAddress).
111    fn ip6_leave_multicast_group(&self, addr: &Ip6Address) -> Result;
112
113    /// Sets the IPv6 receive callback closure. Functional equivalent of
114    /// [`otsys::otIp6SetReceiveCallback`](crate::otsys::otIp6SetReceiveCallback).
115    ///
116    /// The closure will ultimately be executed via
117    /// [`ot::Tasklets::process`](crate::ot::Tasklets::process).
118    fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
119    where
120        F: FnMut(OtMessageBox<'_>) + 'a;
121
122    /// Sets the IPv6 address callback closure. Functional equivalent of
123    /// [`otsys::otIp6SetAddressCallback`](crate::otsys::otIp6SetAddressCallback).
124    ///
125    /// The closure takes two arguments:
126    ///
127    ///  * An instance of [`ot::Ip6AddressInfo`](crate::ot::Ip6AddressInfo).
128    ///  * A `bool` indicating if the address is being added (`true`) or removed (`false`).
129    ///
130    /// The closure will ultimately be executed via
131    /// [`ot::Tasklets::process`](crate::ot::Tasklets::process).
132    fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
133    where
134        F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a;
135
136    /// Functional equivalent of [`otsys::otIp6IsSlaacEnabled`](crate::otsys::otIp6IsSlaacEnabled).
137    fn ip6_is_slaac_enabled(&self) -> bool;
138
139    /// Functional equivalent of
140    /// [`otsys::otIp6SetSlaacEnabled`](crate::otsys::otIp6SetSlaacEnabled).
141    fn ip6_set_slaac_enabled(&self, enabled: bool);
142
143    /// Functional equivalent of
144    /// [`otsys::otIcmp6GetEchoMode`](crate::otsys::otIcmp6GetEchoMode).
145    fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode;
146
147    /// Functional equivalent of
148    /// [`otsys::otIcmp6SetEchoMode`](crate::otsys::otIcmp6SetEchoMode).
149    fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode);
150
151    /// Functional equivalent of
152    /// [`otsys::otIp6SetReceiveFilterEnabled`](crate::otsys::otIp6SetReceiveFilterEnabled).
153    fn ip6_set_receive_filter_enabled(&self, enabled: bool);
154
155    /// Functional equivalent of
156    /// [`otsys::otIp6IsReceiveFilterEnabled`](crate::otsys::otIp6IsReceiveFilterEnabled).
157    fn ip6_is_receive_filter_enabled(&self) -> bool;
158
159    /// Functional equivalent of
160    /// [`otsys::otIp6GetBorderRoutingCounters`](crate::otsys::otIp6GetBorderRoutingCounters).
161    fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters;
162
163    /// Functional equivalent of
164    /// [`otsys::otIp6GetUnicastAddresses`](crate::otsys::otIp6GetUnicastAddresses).
165    fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_>;
166
167    /// Functional equivalent of
168    /// [`otsys::otIp6GetMulticastAddresses`](crate::otsys::otIp6GetMulticastAddresses).
169    fn ip6_get_multicast_addresses(&self) -> NetifMulticastAddressIterator<'_>;
170}
171
172impl<T: Ip6 + ot::Boxable> Ip6 for ot::Box<T> {
173    fn ip6_send(&self, message: OtMessageBox<'_>) -> Result<()> {
174        self.as_ref().ip6_send(message)
175    }
176
177    fn ip6_send_data(&self, data: &[u8]) -> Result {
178        self.as_ref().ip6_send_data(data)
179    }
180
181    fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
182        self.as_ref().ip6_send_data_direct(data)
183    }
184
185    fn ip6_is_enabled(&self) -> bool {
186        self.as_ref().ip6_is_enabled()
187    }
188
189    fn ip6_set_enabled(&self, enabled: bool) -> Result {
190        self.as_ref().ip6_set_enabled(enabled)
191    }
192
193    fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
194        self.as_ref().ip6_add_unicast_address(addr)
195    }
196
197    fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
198        self.as_ref().ip6_remove_unicast_address(addr)
199    }
200
201    fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
202        self.as_ref().ip6_join_multicast_group(addr)
203    }
204
205    fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
206        self.as_ref().ip6_join_multicast_group(addr)
207    }
208
209    fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
210    where
211        F: FnMut(OtMessageBox<'_>) + 'a,
212    {
213        self.as_ref().ip6_set_receive_fn(f)
214    }
215
216    fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
217    where
218        F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
219    {
220        self.as_ref().ip6_set_address_fn(f)
221    }
222
223    fn ip6_is_slaac_enabled(&self) -> bool {
224        self.as_ref().ip6_is_slaac_enabled()
225    }
226
227    fn ip6_set_slaac_enabled(&self, enabled: bool) {
228        self.as_ref().ip6_set_slaac_enabled(enabled);
229    }
230
231    fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
232        self.as_ref().icmp6_get_echo_mode()
233    }
234
235    fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
236        self.as_ref().icmp6_set_echo_mode(mode)
237    }
238
239    fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
240        self.as_ref().ip6_set_receive_filter_enabled(enabled);
241    }
242
243    fn ip6_is_receive_filter_enabled(&self) -> bool {
244        self.as_ref().ip6_is_receive_filter_enabled()
245    }
246
247    fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
248        self.as_ref().ip6_get_border_routing_counters()
249    }
250
251    fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
252        self.as_ref().ip6_get_unicast_addresses()
253    }
254
255    fn ip6_get_multicast_addresses(&self) -> NetifMulticastAddressIterator<'_> {
256        self.as_ref().ip6_get_multicast_addresses()
257    }
258}
259
260impl Ip6 for Instance {
261    fn ip6_send(&self, message: OtMessageBox<'_>) -> Result {
262        Error::from(unsafe { otIp6Send(self.as_ot_ptr(), message.take_ot_ptr()) }).into()
263    }
264
265    fn ip6_send_data(&self, data: &[u8]) -> Result {
266        if let Ok(msg) = Message::ip6_new_from_bytes(self, data, None) {
267            self.ip6_send(msg)
268        } else if self.get_buffer_info().0.mFreeBuffers == 0 {
269            Err(ot::Error::NoBufs)
270        } else {
271            Err(ot::Error::Failed)
272        }
273    }
274
275    fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
276        if let Ok(mut msg) = Message::ip6_new_from_bytes(self, data, None) {
277            msg.set_direct_transmission(true);
278            self.ip6_send(msg)
279        } else if self.get_buffer_info().0.mFreeBuffers == 0 {
280            Err(ot::Error::NoBufs)
281        } else {
282            Err(ot::Error::Failed)
283        }
284    }
285
286    fn ip6_is_enabled(&self) -> bool {
287        unsafe { otIp6IsEnabled(self.as_ot_ptr()) }
288    }
289
290    fn ip6_set_enabled(&self, enabled: bool) -> Result {
291        Error::from(unsafe { otIp6SetEnabled(self.as_ot_ptr(), enabled) }).into()
292    }
293
294    fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
295        Error::from(unsafe { otIp6AddUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
296    }
297
298    fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
299        Error::from(unsafe { otIp6RemoveUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
300    }
301
302    fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
303        Error::from(unsafe { otIp6SubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
304            .into()
305    }
306
307    fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
308        Error::from(unsafe { otIp6UnsubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
309            .into()
310    }
311
312    fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
313    where
314        F: FnMut(OtMessageBox<'_>) + 'a,
315    {
316        unsafe extern "C" fn _ot_ip6_receive_callback<'a, F: FnMut(OtMessageBox<'_>) + 'a>(
317            message: *mut otMessage,
318            context: *mut ::std::os::raw::c_void,
319        ) {
320            trace!("_ot_ip6_receive_callback");
321
322            // Convert the `*otMessage` into an `ot::Box<ot::Message>`.
323            let message = unsafe { OtMessageBox::from_ot_ptr(message) }
324                .expect("_ot_ip6_receive_callback: Got NULL otMessage");
325
326            // Reconstitute a reference to our closure.
327            let sender = unsafe { &mut *(context as *mut F) };
328
329            sender(message)
330        }
331
332        let (fn_ptr, fn_box, cb): (_, _, otIp6ReceiveCallback) = if let Some(f) = f {
333            let mut x = Box::new(f);
334
335            (
336                x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
337                Some(x as Box<dyn FnMut(OtMessageBox<'_>) + 'a>),
338                Some(_ot_ip6_receive_callback::<F>),
339            )
340        } else {
341            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
342        };
343
344        unsafe {
345            otIp6SetReceiveCallback(self.as_ot_ptr(), cb, fn_ptr);
346
347            // Make sure our object eventually gets cleaned up.
348            // Here we must also transmute our closure to have a 'static lifetime.
349            // We need to do this because the borrow checker cannot infer the
350            // proper lifetime for the singleton instance backing, but
351            // this is guaranteed by the API.
352            self.borrow_backing().ip6_receive_fn.set(std::mem::transmute::<
353                Option<Box<dyn FnMut(OtMessageBox<'_>) + 'a>>,
354                Option<Box<dyn FnMut(OtMessageBox<'_>) + 'static>>,
355            >(fn_box));
356        }
357    }
358
359    fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
360    where
361        F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
362    {
363        unsafe extern "C" fn _ot_ip6_address_callback<
364            'a,
365            F: FnMut(Ip6AddressInfo<'_>, bool) + 'a,
366        >(
367            info: *const otIp6AddressInfo,
368            is_added: bool,
369            context: *mut ::std::os::raw::c_void,
370        ) {
371            trace!("_ot_ip6_address_callback");
372
373            // Convert the `*otIp6AddressInfo` into an `&ot::Ip6AddressInfo`.
374            let info = unsafe { *Ip6AddressInfo::ref_from_ot_ptr(info).unwrap() };
375
376            // Reconstitute a reference to our closure.
377            let sender = unsafe { &mut *(context as *mut F) };
378
379            sender(info, is_added)
380        }
381
382        let (fn_ptr, fn_box, cb): (_, _, otIp6AddressCallback) = if let Some(f) = f {
383            let mut x = Box::new(f);
384
385            (
386                x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
387                Some(x as Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>),
388                Some(_ot_ip6_address_callback::<F>),
389            )
390        } else {
391            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
392        };
393
394        unsafe {
395            otIp6SetAddressCallback(self.as_ot_ptr(), cb, fn_ptr);
396
397            // Make sure our object eventually gets cleaned up.
398            // Here we must also transmute our closure to have a 'static lifetime.
399            // We need to do this because the borrow checker cannot infer the
400            // proper lifetime for the singleton instance backing, but
401            // this is guaranteed by the API.
402            self.borrow_backing().ip6_address_fn.set(std::mem::transmute::<
403                Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>>,
404                Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'static>>,
405            >(fn_box));
406        }
407    }
408
409    fn ip6_is_slaac_enabled(&self) -> bool {
410        unsafe { otIp6IsSlaacEnabled(self.as_ot_ptr()) }
411    }
412
413    fn ip6_set_slaac_enabled(&self, enabled: bool) {
414        unsafe { otIp6SetSlaacEnabled(self.as_ot_ptr(), enabled) }
415    }
416
417    fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
418        unsafe { otIcmp6GetEchoMode(self.as_ot_ptr()) }.into()
419    }
420
421    fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
422        unsafe { otIcmp6SetEchoMode(self.as_ot_ptr(), mode.into()) }
423    }
424
425    fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
426        unsafe { otIp6SetReceiveFilterEnabled(self.as_ot_ptr(), enabled) }
427    }
428
429    fn ip6_is_receive_filter_enabled(&self) -> bool {
430        unsafe { otIp6IsReceiveFilterEnabled(self.as_ot_ptr()) }
431    }
432
433    fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
434        unsafe {
435            BorderRoutingCounters::ref_from_ot_ptr(otIp6GetBorderRoutingCounters(self.as_ot_ptr()))
436                .unwrap()
437        }
438    }
439
440    fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
441        NetifAddressIterator(unsafe {
442            NetifAddress::ref_from_ot_ptr(otIp6GetUnicastAddresses(self.as_ot_ptr()))
443        })
444    }
445
446    fn ip6_get_multicast_addresses(&self) -> NetifMulticastAddressIterator<'_> {
447        NetifMulticastAddressIterator(unsafe {
448            NetifMulticastAddress::ref_from_ot_ptr(otIp6GetMulticastAddresses(self.as_ot_ptr()))
449        })
450    }
451}