1use crate::ot::WrongSize;
6use crate::prelude_internal::*;
7use core::pin::Pin;
8use core::task::{Context, Poll};
9use fuchsia_sync::Mutex;
10use std::sync::Arc;
11use std::task::Waker;
12
13#[allow(missing_debug_implementations)]
15pub struct LocalExternalRouteIterator<'a, T: ?Sized> {
16 ot_instance: &'a T,
17 ot_iter: otNetworkDataIterator,
18}
19
20impl<T: ?Sized + BorderRouter> Iterator for LocalExternalRouteIterator<'_, T> {
21 type Item = ExternalRouteConfig;
22 fn next(&mut self) -> Option<Self::Item> {
23 self.ot_instance.iter_next_local_external_route(&mut self.ot_iter)
24 }
25}
26
27#[allow(missing_debug_implementations)]
29pub struct LocalOnMeshPrefixIterator<'a, T: ?Sized> {
30 ot_instance: &'a T,
31 ot_iter: otNetworkDataIterator,
32}
33
34impl<T: ?Sized + BorderRouter> Iterator for LocalOnMeshPrefixIterator<'_, T> {
35 type Item = BorderRouterConfig;
36 fn next(&mut self) -> Option<Self::Item> {
37 self.ot_instance.iter_next_local_on_mesh_prefix(&mut self.ot_iter)
38 }
39}
40
41pub trait BorderRouter {
45 fn add_external_route(&self, route: &ExternalRouteConfig) -> Result;
48
49 fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result;
52
53 fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result;
56
57 fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result;
60
61 fn border_router_register(&self) -> Result;
64
65 fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result;
68
69 fn border_routing_set_enabled(&self, enabled: bool) -> Result;
72
73 fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool);
76
77 fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState;
80
81 fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
84 where
85 F: FnMut(BorderRoutingDhcp6PdState) + 'a;
86
87 fn border_routing_dhcp6_pd_state_change_stream(&self)
89 -> BorderRoutingDhcp6PdStateChangedStream;
90
91 fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry>;
94
95 fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix>;
98
99 fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix>;
102
103 fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize>;
106
107 fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo;
110
111 fn border_routing_is_multi_ail_detected(&self) -> bool;
114
115 fn iter_next_local_external_route(
123 &self,
124 ot_iter: &mut otNetworkDataIterator,
125 ) -> Option<ExternalRouteConfig>;
126
127 fn iter_next_local_on_mesh_prefix(
135 &self,
136 ot_iter: &mut otNetworkDataIterator,
137 ) -> Option<BorderRouterConfig>;
138
139 fn iter_local_external_routes(&self) -> LocalExternalRouteIterator<'_, Self> {
141 LocalExternalRouteIterator { ot_instance: self, ot_iter: OT_NETWORK_DATA_ITERATOR_INIT }
142 }
143
144 fn iter_local_on_mesh_prefixes(&self) -> LocalOnMeshPrefixIterator<'_, Self> {
146 LocalOnMeshPrefixIterator { ot_instance: self, ot_iter: OT_NETWORK_DATA_ITERATOR_INIT }
147 }
148}
149
150impl<T: BorderRouter + Boxable> BorderRouter for ot::Box<T> {
151 fn add_external_route(&self, route: &ExternalRouteConfig) -> Result {
152 self.as_ref().add_external_route(route)
153 }
154
155 fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result {
156 self.as_ref().add_on_mesh_prefix(route)
157 }
158
159 fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result {
160 self.as_ref().remove_external_route(prefix)
161 }
162
163 fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result {
164 self.as_ref().remove_on_mesh_prefix(prefix)
165 }
166
167 fn border_router_register(&self) -> Result {
168 self.as_ref().border_router_register()
169 }
170
171 fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result {
172 self.as_ref().border_routing_init(infra_if, infra_is_running)
173 }
174
175 fn border_routing_set_enabled(&self, enabled: bool) -> Result {
176 self.as_ref().border_routing_set_enabled(enabled)
177 }
178
179 fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool) {
180 self.as_ref().border_routing_dhcp6_pd_set_enabled(enabled)
181 }
182
183 fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState {
184 self.as_ref().border_routing_dhcp6_pd_get_state()
185 }
186
187 fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
188 where
189 F: FnMut(BorderRoutingDhcp6PdState) + 'a,
190 {
191 self.as_ref().border_routing_dhcp6_pd_set_request_fn(f)
192 }
193
194 fn border_routing_dhcp6_pd_state_change_stream(
195 &self,
196 ) -> BorderRoutingDhcp6PdStateChangedStream {
197 self.as_ref().border_routing_dhcp6_pd_state_change_stream()
198 }
199
200 fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry> {
201 self.as_ref().border_routing_get_pd_omr_prefix()
202 }
203
204 fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix> {
205 self.as_ref().border_routing_get_omr_prefix()
206 }
207
208 fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix> {
209 self.as_ref().border_routing_get_on_link_prefix()
210 }
211
212 fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize> {
213 self.as_ref().border_routing_process_icmp6_ra(message)
214 }
215
216 fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo {
217 self.as_ref().border_routing_get_pd_processed_ra_info()
218 }
219
220 fn border_routing_is_multi_ail_detected(&self) -> bool {
221 self.as_ref().border_routing_is_multi_ail_detected()
222 }
223
224 fn iter_next_local_external_route(
225 &self,
226 ot_iter: &mut otNetworkDataIterator,
227 ) -> Option<ExternalRouteConfig> {
228 self.as_ref().iter_next_local_external_route(ot_iter)
229 }
230
231 fn iter_next_local_on_mesh_prefix(
232 &self,
233 ot_iter: &mut otNetworkDataIterator,
234 ) -> Option<BorderRouterConfig> {
235 self.as_ref().iter_next_local_on_mesh_prefix(ot_iter)
236 }
237}
238
239impl BorderRouter for Instance {
240 fn add_external_route(&self, route: &ExternalRouteConfig) -> Result {
241 Error::from(unsafe { otBorderRouterAddRoute(self.as_ot_ptr(), route.as_ot_ptr()) }).into()
242 }
243
244 fn add_on_mesh_prefix(&self, route: &BorderRouterConfig) -> Result {
245 Error::from(unsafe { otBorderRouterAddOnMeshPrefix(self.as_ot_ptr(), route.as_ot_ptr()) })
246 .into()
247 }
248
249 fn remove_external_route(&self, prefix: &Ip6Prefix) -> Result {
250 Error::from(unsafe { otBorderRouterRemoveRoute(self.as_ot_ptr(), prefix.as_ot_ptr()) })
251 .into()
252 }
253
254 fn remove_on_mesh_prefix(&self, prefix: &Ip6Prefix) -> Result {
255 Error::from(unsafe {
256 otBorderRouterRemoveOnMeshPrefix(self.as_ot_ptr(), prefix.as_ot_ptr())
257 })
258 .into()
259 }
260
261 fn border_router_register(&self) -> Result {
262 Error::from(unsafe { otBorderRouterRegister(self.as_ot_ptr()) }).into()
263 }
264
265 fn border_routing_init(&self, infra_if: u32, infra_is_running: bool) -> Result {
266 Error::from(unsafe { otBorderRoutingInit(self.as_ot_ptr(), infra_if, infra_is_running) })
267 .into()
268 }
269
270 fn border_routing_set_enabled(&self, enabled: bool) -> Result {
271 Error::from(unsafe { otBorderRoutingSetEnabled(self.as_ot_ptr(), enabled) }).into()
272 }
273
274 fn border_routing_dhcp6_pd_set_enabled(&self, enabled: bool) {
275 unsafe { otBorderRoutingDhcp6PdSetEnabled(self.as_ot_ptr(), enabled) }
276 }
277
278 fn border_routing_dhcp6_pd_get_state(&self) -> BorderRoutingDhcp6PdState {
279 BorderRoutingDhcp6PdState::from_isize(unsafe {
280 otBorderRoutingDhcp6PdGetState(self.as_ot_ptr())
281 } as isize)
282 .unwrap_or(BorderRoutingDhcp6PdState::Disabled)
283 }
284
285 fn border_routing_dhcp6_pd_set_request_fn<'a, F>(&'a self, f: Option<F>)
286 where
287 F: FnMut(BorderRoutingDhcp6PdState) + 'a,
288 {
289 unsafe extern "C" fn _ot_border_routing_dhcp6_pd_state_change_callback<
290 'a,
291 F: FnMut(BorderRoutingDhcp6PdState) + 'a,
292 >(
293 state: otBorderRoutingDhcp6PdState,
294 context: *mut ::std::os::raw::c_void,
295 ) {
296 trace!("_ot_border_routing_dhcp6_pd_state_change_callback");
297
298 let state = BorderRoutingDhcp6PdState::from(state);
300
301 let sender = &mut *(context as *mut F);
303
304 sender(state)
305 }
306
307 let (fn_ptr, fn_box, cb): (_, _, otBorderRoutingRequestDhcp6PdCallback) = if let Some(f) = f
308 {
309 let mut x = Box::new(f);
310
311 (
312 x.as_mut() as *mut F as *mut ::std::os::raw::c_void,
313 Some(x as Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'a>),
314 Some(_ot_border_routing_dhcp6_pd_state_change_callback::<F>),
315 )
316 } else {
317 (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
318 };
319
320 unsafe {
321 otBorderRoutingDhcp6PdSetRequestCallback(self.as_ot_ptr(), cb, fn_ptr);
322
323 self.borrow_backing().dhcp6pd_state_change_callback_fn.set(std::mem::transmute::<
329 Option<Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'a>>,
330 Option<Box<dyn FnMut(BorderRoutingDhcp6PdState) + 'static>>,
331 >(fn_box));
332 }
333 }
334
335 fn border_routing_dhcp6_pd_state_change_stream(
336 &self,
337 ) -> BorderRoutingDhcp6PdStateChangedStream {
338 let state = Arc::new(Mutex::new((None, futures::task::noop_waker())));
339
340 let state_copy = state.clone();
341
342 self.border_routing_dhcp6_pd_set_request_fn(Some(
343 move |pd_state: BorderRoutingDhcp6PdState| {
344 let mut borrowed = state_copy.lock();
345 borrowed.0 = Some(pd_state);
346 borrowed.1.wake_by_ref();
347 },
348 ));
349
350 BorderRoutingDhcp6PdStateChangedStream(state)
351 }
352
353 fn border_routing_get_pd_omr_prefix(&self) -> Result<ot::BorderRoutingPrefixTableEntry> {
354 let mut ret: BorderRoutingPrefixTableEntry = Default::default();
355 Error::from(unsafe {
356 otBorderRoutingGetPdOmrPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr())
357 })
358 .into_result()?;
359 Ok(ret)
360 }
361
362 fn border_routing_get_omr_prefix(&self) -> Result<ot::Ip6Prefix> {
363 let mut ret: Ip6Prefix = Default::default();
364 Error::from(unsafe { otBorderRoutingGetOmrPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr()) })
365 .into_result()?;
366 Ok(ret)
367 }
368
369 fn border_routing_get_on_link_prefix(&self) -> Result<ot::Ip6Prefix> {
370 let mut ret: Ip6Prefix = Default::default();
371 Error::from(unsafe {
372 otBorderRoutingGetOnLinkPrefix(self.as_ot_ptr(), ret.as_ot_mut_ptr())
373 })
374 .into_result()?;
375 Ok(ret)
376 }
377
378 fn border_routing_process_icmp6_ra(&self, message: &[u8]) -> Result<(), WrongSize> {
379 unsafe {
380 otPlatBorderRoutingProcessIcmp6Ra(
381 self.as_ot_ptr(),
382 message.as_ptr(),
383 message.len().try_into().map_err(|_| WrongSize)?,
384 )
385 }
386 Ok(())
387 }
388
389 fn border_routing_get_pd_processed_ra_info(&self) -> PdProcessedRaInfo {
390 let mut info = PdProcessedRaInfo::default();
391 unsafe {
392 otBorderRoutingGetPdProcessedRaInfo(self.as_ot_ptr(), info.as_ot_mut_ptr());
393 }
394 info
395 }
396
397 fn border_routing_is_multi_ail_detected(&self) -> bool {
398 unsafe { otBorderRoutingIsMultiAilDetected(self.as_ot_ptr()) }
399 }
400
401 fn iter_next_local_external_route(
402 &self,
403 ot_iter: &mut otNetworkDataIterator,
404 ) -> Option<ExternalRouteConfig> {
405 unsafe {
406 let mut ret = ExternalRouteConfig::default();
407 match Error::from(otBorderRouterGetNextRoute(
408 self.as_ot_ptr(),
409 ot_iter as *mut otNetworkDataIterator,
410 ret.as_ot_mut_ptr(),
411 )) {
412 Error::NotFound => None,
413 Error::None => Some(ret),
414 err => panic!("Unexpected error from otBorderRouterGetNextRoute: {err:?}"),
415 }
416 }
417 }
418
419 fn iter_next_local_on_mesh_prefix(
420 &self,
421 ot_iter: &mut otNetworkDataIterator,
422 ) -> Option<BorderRouterConfig> {
423 unsafe {
424 let mut ret = BorderRouterConfig::default();
425 match Error::from(otBorderRouterGetNextOnMeshPrefix(
426 self.as_ot_ptr(),
427 ot_iter as *mut otNetworkDataIterator,
428 ret.as_ot_mut_ptr(),
429 )) {
430 Error::NotFound => None,
431 Error::None => Some(ret),
432 err => panic!("Unexpected error from otBorderRouterGetNextOnMeshPrefix: {err:?}"),
433 }
434 }
435 }
436}
437
438#[derive(Debug, Clone)]
440pub struct BorderRoutingDhcp6PdStateChangedStream(
441 Arc<Mutex<(Option<BorderRoutingDhcp6PdState>, Waker)>>,
442);
443
444impl Stream for BorderRoutingDhcp6PdStateChangedStream {
445 type Item = BorderRoutingDhcp6PdState;
446
447 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
448 let mut state = self.0.lock();
449
450 state.1 = cx.waker().clone();
451
452 if let Some(pd_state) = state.0.take() {
453 Poll::Ready(Some(pd_state))
454 } else {
455 Poll::Pending
456 }
457 }
458}