Skip to main content

openthread/ot/
nat64.rs

1// Copyright 2023 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#[allow(missing_debug_implementations)]
8/// NAT64 Address Mapping iterator
9pub struct Nat64AddressMappingIterator<'a, T: ?Sized> {
10    /// NAT64 mapping iter
11    pub ot_nat64_address_mapping_iter: otNat64AddressMappingIterator,
12
13    /// OpenThread instance
14    pub ot_instance: &'a T,
15}
16
17impl<T: ?Sized + Nat64> Iterator for Nat64AddressMappingIterator<'_, T> {
18    type Item = Nat64AddressMapping;
19    fn next(&mut self) -> Option<Self::Item> {
20        let mut mapping = Nat64AddressMapping::default();
21        self.ot_instance
22            .nat64_get_next_address_mapping(&mut self.ot_nat64_address_mapping_iter, &mut mapping)
23            .ok()
24            .map(|()| mapping)
25    }
26}
27
28/// Methods from the [OpenThread "NAT64" Module](https://openthread.io/reference/group/api-nat64).
29pub trait Nat64 {
30    /// Enable or disable NAT64 functions.
31    fn nat64_set_enabled(&self, enabled: bool);
32
33    /// Sets the CIDR used when setting the source address of the outgoing translated IPv4 packets.
34    fn nat64_set_ip4_cidr(&self, ip4_cidr: Ip4Cidr) -> Result;
35
36    /// Get CIDR from OpenThread
37    fn nat64_get_cidr(&self) -> Result<Ip4Cidr>;
38
39    /// Registers a callback to provide received IPv4 datagrams.
40    fn nat64_set_receive_fn<'a, F>(&'a self, f: Option<F>)
41    where
42        F: FnMut(OtMessageBox<'_>) + 'a;
43
44    /// Send a message to NAT64 handler in OpenThread
45    ///
46    /// Returns [`Error::InvalidArgs`] if the message origin is
47    /// [`Origin::ThreadNetif`](ot::message::Origin::ThreadNetif).
48    fn nat64_send(&self, message: OtMessageBox<'_>) -> Result;
49
50    /// Send data to NAT64 handler in OpenThread
51    ///
52    /// The message is tagged with `origin`. Traffic from the host network
53    /// stack that may have been forwarded from an untrusted network must use
54    /// [`Origin::HostUntrusted`](ot::message::Origin::HostUntrusted).
55    /// Returns [`Error::InvalidArgs`] for
56    /// [`Origin::ThreadNetif`](ot::message::Origin::ThreadNetif).
57    fn nat64_send_data_slice(&self, data_slice: &[u8], origin: ot::message::Origin) -> Result;
58
59    /// Return AIL prefix to OpenThread
60    fn nat64_infra_if_prefix_discover_done(
61        &self,
62        infra_if_idx: ot::NetifIndex,
63        ip6_prefix: openthread_sys::otIp6Prefix,
64    );
65
66    /// Get the NAT64 address mapping iterator instance
67    fn nat64_get_address_mapping_iterator(&self) -> Nat64AddressMappingIterator<'_, Self> {
68        let mut iter = otNat64AddressMappingIterator::default();
69        self.nat64_init_address_mapping_iterator(&mut iter);
70        Nat64AddressMappingIterator { ot_nat64_address_mapping_iter: iter, ot_instance: self }
71    }
72
73    ///  Init the NAT64 address mapping iterator
74    fn nat64_init_address_mapping_iterator(&self, iter: &mut otNat64AddressMappingIterator);
75
76    /// Get next NAT64 address mapping
77    fn nat64_get_next_address_mapping(
78        &self,
79        iter: &mut otNat64AddressMappingIterator,
80        mapping: &mut Nat64AddressMapping,
81    ) -> Result;
82
83    /// Get NAT64 translator state
84    fn nat64_get_translator_state(&self) -> Nat64State;
85
86    /// Get NAT64 prefix manager state
87    fn nat64_get_prefix_manager_state(&self) -> Nat64State;
88
89    /// Get NAT64 error counters
90    fn nat64_get_error_counters(&self) -> Nat64ErrorCounters;
91
92    /// Get NAT64 protocol counters
93    fn nat64_get_counters(&self) -> Nat64ProtocolCounters;
94}
95
96impl<T: Nat64 + ot::Boxable> Nat64 for ot::Box<T> {
97    fn nat64_set_enabled(&self, enabled: bool) {
98        self.as_ref().nat64_set_enabled(enabled)
99    }
100    fn nat64_set_ip4_cidr(&self, ip4_cidr: Ip4Cidr) -> Result {
101        self.as_ref().nat64_set_ip4_cidr(ip4_cidr)
102    }
103    fn nat64_get_cidr(&self) -> Result<Ip4Cidr> {
104        self.as_ref().nat64_get_cidr()
105    }
106    fn nat64_set_receive_fn<'a, F>(&'a self, f: Option<F>)
107    where
108        F: FnMut(OtMessageBox<'_>) + 'a,
109    {
110        self.as_ref().nat64_set_receive_fn(f)
111    }
112    fn nat64_send(&self, message: OtMessageBox<'_>) -> Result {
113        self.as_ref().nat64_send(message)
114    }
115    fn nat64_send_data_slice(&self, data_slice: &[u8], origin: ot::message::Origin) -> Result {
116        self.as_ref().nat64_send_data_slice(data_slice, origin)
117    }
118    fn nat64_infra_if_prefix_discover_done(
119        &self,
120        infra_if_idx: ot::NetifIndex,
121        ip6_prefix: openthread_sys::otIp6Prefix,
122    ) {
123        self.as_ref().nat64_infra_if_prefix_discover_done(infra_if_idx, ip6_prefix);
124    }
125    fn nat64_init_address_mapping_iterator(&self, iter: &mut otNat64AddressMappingIterator) {
126        self.as_ref().nat64_init_address_mapping_iterator(iter)
127    }
128    fn nat64_get_next_address_mapping(
129        &self,
130        iter: &mut otNat64AddressMappingIterator,
131        mapping: &mut Nat64AddressMapping,
132    ) -> Result {
133        self.as_ref().nat64_get_next_address_mapping(iter, mapping)
134    }
135    fn nat64_get_translator_state(&self) -> Nat64State {
136        self.as_ref().nat64_get_translator_state()
137    }
138    fn nat64_get_prefix_manager_state(&self) -> Nat64State {
139        self.as_ref().nat64_get_prefix_manager_state()
140    }
141    fn nat64_get_error_counters(&self) -> Nat64ErrorCounters {
142        self.as_ref().nat64_get_error_counters()
143    }
144    fn nat64_get_counters(&self) -> Nat64ProtocolCounters {
145        self.as_ref().nat64_get_counters()
146    }
147}
148
149impl Nat64 for Instance {
150    fn nat64_set_enabled(&self, enabled: bool) {
151        unsafe { otNat64SetEnabled(self.as_ot_ptr(), enabled) }
152    }
153    fn nat64_set_ip4_cidr(&self, ip4_cidr: Ip4Cidr) -> Result {
154        Error::from(unsafe { otNat64SetIp4Cidr(self.as_ot_ptr(), ip4_cidr.as_ot_ptr()) }).into()
155    }
156    fn nat64_get_cidr(&self) -> Result<Ip4Cidr> {
157        let mut ip4_cidr: Ip4Cidr = Default::default();
158
159        let res: Result<(), Error> =
160            Error::from(unsafe { otNat64GetCidr(self.as_ot_ptr(), ip4_cidr.as_ot_mut_ptr()) })
161                .into();
162
163        res.map(|_: ()| ip4_cidr)
164    }
165    fn nat64_set_receive_fn<'a, F>(&'a self, f: Option<F>)
166    where
167        F: FnMut(OtMessageBox<'_>) + 'a,
168    {
169        unsafe extern "C" fn _ot_nat64_receive_callback<'a, F: FnMut(OtMessageBox<'_>) + 'a>(
170            message: *mut otMessage,
171            context: *mut ::std::os::raw::c_void,
172        ) {
173            trace!("_ot_nat64_receive_callback");
174
175            // Convert the `*otMessage` into an `ot::Box<ot::Message>`.
176            let message = unsafe { OtMessageBox::from_ot_ptr(message) }
177                .expect("_ot_nat64_receive_callback: Got NULL otMessage");
178
179            // Reconstitute a reference to our closure.
180            let sender = unsafe { &mut *(context as *mut F) };
181
182            sender(message)
183        }
184
185        let (fn_ptr, fn_box, cb): (_, _, otNat64ReceiveIp4Callback) = if let Some(f) = f {
186            let mut x = Box::new(f);
187
188            (
189                x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
190                Some(x as Box<dyn FnMut(OtMessageBox<'_>) + 'a>),
191                Some(_ot_nat64_receive_callback::<F>),
192            )
193        } else {
194            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
195        };
196
197        unsafe {
198            otNat64SetReceiveIp4Callback(self.as_ot_ptr(), cb, fn_ptr);
199
200            // Make sure our object eventually gets cleaned up.
201            // Here we must also transmute our closure to have a 'static lifetime.
202            // We need to do this because the borrow checker cannot infer the
203            // proper lifetime for the singleton instance backing, but
204            // this is guaranteed by the API.
205            self.borrow_backing().nat64_receive_fn.set(std::mem::transmute::<
206                Option<Box<dyn FnMut(OtMessageBox<'_>) + 'a>>,
207                Option<Box<dyn FnMut(OtMessageBox<'_>) + 'static>>,
208            >(fn_box));
209        }
210    }
211
212    fn nat64_send(&self, message: OtMessageBox<'_>) -> Result {
213        // Unlike `otIp6Send()`, `otNat64Send()` does not validate the message
214        // origin. Reject messages claiming to come from the Thread netif so
215        // that host traffic can never be treated as if it came from the radio.
216        if message.origin() == ot::message::Origin::ThreadNetif {
217            return Err(Error::InvalidArgs);
218        }
219        Error::from(unsafe { otNat64Send(self.as_ot_ptr(), message.take_ot_ptr()) }).into()
220    }
221
222    fn nat64_send_data_slice(&self, data_slice: &[u8], origin: ot::message::Origin) -> Result {
223        if origin == ot::message::Origin::ThreadNetif {
224            return Err(Error::InvalidArgs);
225        }
226        if let Ok(mut msg) = Message::ip4_new(self, None) {
227            msg.append(data_slice)?;
228            msg.set_origin(origin);
229            self.nat64_send(msg)?;
230            Ok(())
231        } else if self.get_buffer_info().0.mFreeBuffers == 0 {
232            Err(ot::Error::NoBufs)
233        } else {
234            Err(ot::Error::Failed)
235        }
236    }
237
238    fn nat64_infra_if_prefix_discover_done(
239        &self,
240        infra_if_idx: ot::NetifIndex,
241        ip6_prefix: openthread_sys::otIp6Prefix,
242    ) {
243        unsafe {
244            openthread_sys::otPlatInfraIfDiscoverNat64PrefixDone(
245                self.as_ot_ptr(),
246                infra_if_idx,
247                &ip6_prefix,
248            )
249        }
250    }
251
252    fn nat64_init_address_mapping_iterator(&self, iter: &mut otNat64AddressMappingIterator) {
253        unsafe {
254            otNat64InitAddressMappingIterator(self.as_ot_ptr(), iter);
255        }
256    }
257
258    fn nat64_get_next_address_mapping(
259        &self,
260        iter: &mut otNat64AddressMappingIterator,
261        mapping: &mut Nat64AddressMapping,
262    ) -> Result {
263        Error::from(unsafe {
264            otNat64GetNextAddressMapping(self.as_ot_ptr(), iter, mapping.as_ot_mut_ptr())
265        })
266        .into()
267    }
268
269    fn nat64_get_translator_state(&self) -> Nat64State {
270        unsafe { otNat64GetTranslatorState(self.as_ot_ptr()).into() }
271    }
272
273    fn nat64_get_prefix_manager_state(&self) -> Nat64State {
274        unsafe { otNat64GetPrefixManagerState(self.as_ot_ptr()).into() }
275    }
276
277    fn nat64_get_error_counters(&self) -> Nat64ErrorCounters {
278        unsafe {
279            let mut error_counters: otNat64ErrorCounters = Default::default();
280            otNat64GetErrorCounters(
281                self.as_ot_ptr(),
282                (&mut error_counters) as *mut otNat64ErrorCounters,
283            );
284            error_counters.into()
285        }
286    }
287
288    fn nat64_get_counters(&self) -> Nat64ProtocolCounters {
289        unsafe {
290            let mut protocol_counters: otNat64ProtocolCounters = Default::default();
291            otNat64GetCounters(
292                self.as_ot_ptr(),
293                (&mut protocol_counters) as *mut otNat64ProtocolCounters,
294            );
295            protocol_counters.into()
296        }
297    }
298}