1use crate::prelude_internal::*;
6
7#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
9pub enum Icmp6EchoMode {
10 HandleAll = OT_ICMP6_ECHO_HANDLER_ALL as isize,
12
13 HandleDisabled = OT_ICMP6_ECHO_HANDLER_DISABLED as isize,
15
16 HandleMulticastOnly = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY as isize,
18
19 HandleUnicastOnly = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY as isize,
21
22 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#[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 self.0 = unsafe { NetifAddress::ref_from_ot_ptr(addr_ref.0.mNext) };
52 Some(addr_ref)
53 } else {
54 None
55 }
56 }
57}
58
59pub trait Ip6 {
61 fn ip6_send(&self, message: OtMessageBox<'_>) -> Result;
63
64 fn ip6_send_data(&self, data: &[u8]) -> Result;
67
68 fn ip6_send_data_direct(&self, data: &[u8]) -> Result;
70
71 fn ip6_is_enabled(&self) -> bool;
73
74 fn ip6_set_enabled(&self, enabled: bool) -> Result;
76
77 fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result;
80
81 fn ip6_remove_unicast_address(&self, addr: &Ip6Address) -> Result;
84
85 fn ip6_join_multicast_group(&self, addr: &Ip6Address) -> Result;
88
89 fn ip6_leave_multicast_group(&self, addr: &Ip6Address) -> Result;
92
93 fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
99 where
100 F: FnMut(OtMessageBox<'_>) + 'a;
101
102 fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
113 where
114 F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a;
115
116 fn ip6_is_slaac_enabled(&self) -> bool;
118
119 fn ip6_set_slaac_enabled(&self, enabled: bool);
122
123 fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode;
126
127 fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode);
130
131 fn ip6_set_receive_filter_enabled(&self, enabled: bool);
134
135 fn ip6_is_receive_filter_enabled(&self) -> bool;
138
139 fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters;
142
143 fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_>;
146}
147
148impl<T: Ip6 + ot::Boxable> Ip6 for ot::Box<T> {
149 fn ip6_send(&self, message: OtMessageBox<'_>) -> Result<()> {
150 self.as_ref().ip6_send(message)
151 }
152
153 fn ip6_send_data(&self, data: &[u8]) -> Result {
154 self.as_ref().ip6_send_data(data)
155 }
156
157 fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
158 self.as_ref().ip6_send_data_direct(data)
159 }
160
161 fn ip6_is_enabled(&self) -> bool {
162 self.as_ref().ip6_is_enabled()
163 }
164
165 fn ip6_set_enabled(&self, enabled: bool) -> Result {
166 self.as_ref().ip6_set_enabled(enabled)
167 }
168
169 fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
170 self.as_ref().ip6_add_unicast_address(addr)
171 }
172
173 fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
174 self.as_ref().ip6_remove_unicast_address(addr)
175 }
176
177 fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
178 self.as_ref().ip6_join_multicast_group(addr)
179 }
180
181 fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
182 self.as_ref().ip6_join_multicast_group(addr)
183 }
184
185 fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
186 where
187 F: FnMut(OtMessageBox<'_>) + 'a,
188 {
189 self.as_ref().ip6_set_receive_fn(f)
190 }
191
192 fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
193 where
194 F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
195 {
196 self.as_ref().ip6_set_address_fn(f)
197 }
198
199 fn ip6_is_slaac_enabled(&self) -> bool {
200 self.as_ref().ip6_is_slaac_enabled()
201 }
202
203 fn ip6_set_slaac_enabled(&self, enabled: bool) {
204 self.as_ref().ip6_set_slaac_enabled(enabled);
205 }
206
207 fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
208 self.as_ref().icmp6_get_echo_mode()
209 }
210
211 fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
212 self.as_ref().icmp6_set_echo_mode(mode)
213 }
214
215 fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
216 self.as_ref().ip6_set_receive_filter_enabled(enabled);
217 }
218
219 fn ip6_is_receive_filter_enabled(&self) -> bool {
220 self.as_ref().ip6_is_receive_filter_enabled()
221 }
222
223 fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
224 self.as_ref().ip6_get_border_routing_counters()
225 }
226
227 fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
228 self.as_ref().ip6_get_unicast_addresses()
229 }
230}
231
232impl Ip6 for Instance {
233 fn ip6_send(&self, message: OtMessageBox<'_>) -> Result {
234 Error::from(unsafe { otIp6Send(self.as_ot_ptr(), message.take_ot_ptr()) }).into()
235 }
236
237 fn ip6_send_data(&self, data: &[u8]) -> Result {
238 if let Ok(msg) = Message::ip6_new_from_bytes(self, data, None) {
239 self.ip6_send(msg)
240 } else if self.get_buffer_info().0.mFreeBuffers == 0 {
241 Err(ot::Error::NoBufs)
242 } else {
243 Err(ot::Error::Failed)
244 }
245 }
246
247 fn ip6_send_data_direct(&self, data: &[u8]) -> Result {
248 if let Ok(mut msg) = Message::ip6_new_from_bytes(self, data, None) {
249 msg.set_direct_transmission(true);
250 self.ip6_send(msg)
251 } else if self.get_buffer_info().0.mFreeBuffers == 0 {
252 Err(ot::Error::NoBufs)
253 } else {
254 Err(ot::Error::Failed)
255 }
256 }
257
258 fn ip6_is_enabled(&self) -> bool {
259 unsafe { otIp6IsEnabled(self.as_ot_ptr()) }
260 }
261
262 fn ip6_set_enabled(&self, enabled: bool) -> Result {
263 Error::from(unsafe { otIp6SetEnabled(self.as_ot_ptr(), enabled) }).into()
264 }
265
266 fn ip6_add_unicast_address(&self, addr: &NetifAddress) -> Result {
267 Error::from(unsafe { otIp6AddUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
268 }
269
270 fn ip6_remove_unicast_address(&self, addr: &std::net::Ipv6Addr) -> Result {
271 Error::from(unsafe { otIp6RemoveUnicastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) }).into()
272 }
273
274 fn ip6_join_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
275 Error::from(unsafe { otIp6SubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
276 .into()
277 }
278
279 fn ip6_leave_multicast_group(&self, addr: &std::net::Ipv6Addr) -> Result {
280 Error::from(unsafe { otIp6UnsubscribeMulticastAddress(self.as_ot_ptr(), addr.as_ot_ptr()) })
281 .into()
282 }
283
284 fn ip6_set_receive_fn<'a, F>(&'a self, f: Option<F>)
285 where
286 F: FnMut(OtMessageBox<'_>) + 'a,
287 {
288 unsafe extern "C" fn _ot_ip6_receive_callback<'a, F: FnMut(OtMessageBox<'_>) + 'a>(
289 message: *mut otMessage,
290 context: *mut ::std::os::raw::c_void,
291 ) {
292 trace!("_ot_ip6_receive_callback");
293
294 let message = OtMessageBox::from_ot_ptr(message)
296 .expect("_ot_ip6_receive_callback: Got NULL otMessage");
297
298 let sender = &mut *(context as *mut F);
300
301 sender(message)
302 }
303
304 let (fn_ptr, fn_box, cb): (_, _, otIp6ReceiveCallback) = if let Some(f) = f {
305 let mut x = Box::new(f);
306
307 (
308 x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
309 Some(x as Box<dyn FnMut(OtMessageBox<'_>) + 'a>),
310 Some(_ot_ip6_receive_callback::<F>),
311 )
312 } else {
313 (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
314 };
315
316 unsafe {
317 otIp6SetReceiveCallback(self.as_ot_ptr(), cb, fn_ptr);
318
319 self.borrow_backing().ip6_receive_fn.set(std::mem::transmute::<
325 Option<Box<dyn FnMut(OtMessageBox<'_>) + 'a>>,
326 Option<Box<dyn FnMut(OtMessageBox<'_>) + 'static>>,
327 >(fn_box));
328 }
329 }
330
331 fn ip6_set_address_fn<'a, F>(&'a self, f: Option<F>)
332 where
333 F: for<'r> FnMut(Ip6AddressInfo<'r>, bool) + 'a,
334 {
335 unsafe extern "C" fn _ot_ip6_address_callback<
336 'a,
337 F: FnMut(Ip6AddressInfo<'_>, bool) + 'a,
338 >(
339 info: *const otIp6AddressInfo,
340 is_added: bool,
341 context: *mut ::std::os::raw::c_void,
342 ) {
343 trace!("_ot_ip6_address_callback");
344
345 let info = *Ip6AddressInfo::ref_from_ot_ptr(info).unwrap();
347
348 let sender = &mut *(context as *mut F);
350
351 sender(info, is_added)
352 }
353
354 let (fn_ptr, fn_box, cb): (_, _, otIp6AddressCallback) = if let Some(f) = f {
355 let mut x = Box::new(f);
356
357 (
358 x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
359 Some(x as Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>),
360 Some(_ot_ip6_address_callback::<F>),
361 )
362 } else {
363 (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
364 };
365
366 unsafe {
367 otIp6SetAddressCallback(self.as_ot_ptr(), cb, fn_ptr);
368
369 self.borrow_backing().ip6_address_fn.set(std::mem::transmute::<
375 Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'a>>,
376 Option<Box<dyn FnMut(Ip6AddressInfo<'_>, bool) + 'static>>,
377 >(fn_box));
378 }
379 }
380
381 fn ip6_is_slaac_enabled(&self) -> bool {
382 unsafe { otIp6IsSlaacEnabled(self.as_ot_ptr()) }
383 }
384
385 fn ip6_set_slaac_enabled(&self, enabled: bool) {
386 unsafe { otIp6SetSlaacEnabled(self.as_ot_ptr(), enabled) }
387 }
388
389 fn icmp6_get_echo_mode(&self) -> Icmp6EchoMode {
390 unsafe { otIcmp6GetEchoMode(self.as_ot_ptr()) }.into()
391 }
392
393 fn icmp6_set_echo_mode(&self, mode: Icmp6EchoMode) {
394 unsafe { otIcmp6SetEchoMode(self.as_ot_ptr(), mode.into()) }
395 }
396
397 fn ip6_set_receive_filter_enabled(&self, enabled: bool) {
398 unsafe { otIp6SetReceiveFilterEnabled(self.as_ot_ptr(), enabled) }
399 }
400
401 fn ip6_is_receive_filter_enabled(&self) -> bool {
402 unsafe { otIp6IsReceiveFilterEnabled(self.as_ot_ptr()) }
403 }
404
405 fn ip6_get_border_routing_counters(&self) -> &BorderRoutingCounters {
406 unsafe {
407 BorderRoutingCounters::ref_from_ot_ptr(otIp6GetBorderRoutingCounters(self.as_ot_ptr()))
408 .unwrap()
409 }
410 }
411
412 fn ip6_get_unicast_addresses(&self) -> NetifAddressIterator<'_> {
413 NetifAddressIterator(unsafe {
414 NetifAddress::ref_from_ot_ptr(otIp6GetUnicastAddresses(self.as_ot_ptr()))
415 })
416 }
417}