Skip to main content

fidl_fuchsia_net_routes_ext/
admin.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
5//! Extensions for fuchsia.net.routes.admin.
6
7use std::fmt::Debug;
8
9use fidl::endpoints::{DiscoverableProtocolMarker, ProtocolMarker};
10use fidl_fuchsia_net_resources as fnet_resources;
11use fidl_fuchsia_net_root as fnet_root;
12use fidl_fuchsia_net_routes_admin as fnet_routes_admin;
13use futures::future::Either;
14use net_types::ip::{GenericOverIp, Ip, IpInvariant, Ipv4, Ipv6};
15use thiserror::Error;
16
17use crate::{FidlRouteIpExt, Responder, TableId, impl_responder};
18
19/// Route set creation errors.
20#[derive(Clone, Debug, Error)]
21pub enum RouteSetCreationError {
22    /// Proxy creation failed.
23    #[error("failed to create proxy: {0}")]
24    CreateProxy(fidl::Error),
25    /// Route set creation failed.
26    #[error("failed to create route set: {0}")]
27    RouteSet(fidl::Error),
28}
29
30/// Route table creation errors.
31#[derive(Clone, Debug, Error)]
32pub enum RouteTableCreationError {
33    /// Proxy creation failed.
34    #[error("failed to create proxy: {0}")]
35    CreateProxy(fidl::Error),
36    /// Route table creation failed.
37    #[error("failed to create route set: {0}")]
38    RouteTable(fidl::Error),
39}
40
41/// Admin extension for the `fuchsia.net.routes.admin` FIDL API.
42pub trait FidlRouteAdminIpExt: Ip {
43    /// The "route table" protocol to use for this IP version.
44    type RouteTableMarker: DiscoverableProtocolMarker<
45            RequestStream = Self::RouteTableRequestStream,
46            Proxy: Clone + Debug,
47        > + Unpin;
48    /// The "root set" protocol to use for this IP version.
49    type GlobalRouteTableMarker: DiscoverableProtocolMarker;
50    /// The "route set" protocol to use for this IP version.
51    type RouteSetMarker: ProtocolMarker<RequestStream = Self::RouteSetRequestStream>;
52    /// The "route table provider" protocol to use for this IP version.
53    type RouteTableProviderMarker: DiscoverableProtocolMarker<Proxy: Clone>;
54    /// The request stream for the route set protocol.
55    type RouteSetRequestStream: fidl::endpoints::RequestStream<Ok: Send, ControlHandle: Send>;
56    /// The request stream for the route table protocol.
57    type RouteTableRequestStream: fidl::endpoints::RequestStream<Ok: Send, ControlHandle: Send>;
58    /// The responder for AddRoute requests.
59    type AddRouteResponder: Responder<Payload = Result<bool, fnet_routes_admin::RouteSetError>>;
60    /// The responder for RemoveRoute requests.
61    type RemoveRouteResponder: Responder<Payload = Result<bool, fnet_routes_admin::RouteSetError>>;
62    /// The responder for AuthenticateForInterface requests.
63    type RouteSetAuthenticateForInterfaceResponder: Responder<
64        Payload = Result<(), fnet_routes_admin::AuthenticateForInterfaceError>,
65    >;
66    /// The responder for GetTableId requests.
67    type RouteTableGetTableIdResponder: Responder<Payload = u32>;
68    /// The responder for RemoveRequests.
69    type RouteTableRemoveResponder: Responder<
70        Payload = Result<(), fnet_routes_admin::BaseRouteTableRemoveError>,
71    >;
72    /// The responder for GetAuthorizationForRouteTable requests.
73    type RouteTableGetAuthorizationResponder: Responder<
74        Payload = fnet_routes_admin::GrantForRouteTableAuthorization,
75    >;
76    /// The control handle for RouteTable protocols.
77    type RouteTableControlHandle: fidl::endpoints::ControlHandle + Debug;
78
79    /// The control handle for RouteTableProvider protocols.
80    type RouteTableProviderControlHandle: fidl::endpoints::ControlHandle + Debug;
81
82    /// The responder for the GetInterfaceLocalTable method.
83    type GetInterfaceLocalTableResponder: Responder<
84        Payload = Result<
85            fidl::endpoints::ClientEnd<Self::RouteTableMarker>,
86            fnet_routes_admin::GetInterfaceLocalTableError,
87        >,
88    >;
89
90    /// Turns a FIDL route table provider request into the extension type.
91    fn into_route_table_provider_request(
92        request: fidl::endpoints::Request<Self::RouteTableProviderMarker>,
93    ) -> RouteTableProviderRequest<Self>;
94
95    /// Turns a FIDL route set request into the extension type.
96    fn into_route_set_request(
97        request: fidl::endpoints::Request<Self::RouteSetMarker>,
98    ) -> RouteSetRequest<Self>;
99
100    /// Turns a FIDL route table request into the extension type.
101    fn into_route_table_request(
102        request: fidl::endpoints::Request<Self::RouteTableMarker>,
103    ) -> RouteTableRequest<Self>;
104
105    /// Turns a FIDL route set request stream item into a Result of the extension type.
106    fn into_route_set_request_result(
107        request: <Self::RouteSetRequestStream as futures::Stream>::Item,
108    ) -> Result<RouteSetRequest<Self>, fidl::Error>;
109
110    /// Turns a FIDL route table request stream item into a Result of the extension type.
111    fn into_route_table_request_result(
112        request: <Self::RouteTableRequestStream as futures::Stream>::Item,
113    ) -> Result<RouteTableRequest<Self>, fidl::Error>;
114}
115
116impl FidlRouteAdminIpExt for Ipv4 {
117    type RouteTableMarker = fnet_routes_admin::RouteTableV4Marker;
118    type GlobalRouteTableMarker = fnet_root::RoutesV4Marker;
119    type RouteSetMarker = fnet_routes_admin::RouteSetV4Marker;
120    type RouteTableProviderMarker = fnet_routes_admin::RouteTableProviderV4Marker;
121    type RouteSetRequestStream = fnet_routes_admin::RouteSetV4RequestStream;
122    type RouteTableRequestStream = fnet_routes_admin::RouteTableV4RequestStream;
123    type AddRouteResponder = fnet_routes_admin::RouteSetV4AddRouteResponder;
124    type RemoveRouteResponder = fnet_routes_admin::RouteSetV4RemoveRouteResponder;
125    type RouteSetAuthenticateForInterfaceResponder =
126        fnet_routes_admin::RouteSetV4AuthenticateForInterfaceResponder;
127    type RouteTableGetTableIdResponder = fnet_routes_admin::RouteTableV4GetTableIdResponder;
128    type RouteTableRemoveResponder = fnet_routes_admin::RouteTableV4RemoveResponder;
129    type RouteTableGetAuthorizationResponder =
130        fnet_routes_admin::RouteTableV4GetAuthorizationForRouteTableResponder;
131    type RouteTableControlHandle = fnet_routes_admin::RouteTableV4ControlHandle;
132    type RouteTableProviderControlHandle = fnet_routes_admin::RouteTableProviderV4ControlHandle;
133    type GetInterfaceLocalTableResponder =
134        fnet_routes_admin::RouteTableProviderV4GetInterfaceLocalTableResponder;
135
136    fn into_route_table_provider_request(
137        request: fidl::endpoints::Request<Self::RouteTableProviderMarker>,
138    ) -> RouteTableProviderRequest<Ipv4> {
139        RouteTableProviderRequest::from(request)
140    }
141
142    fn into_route_set_request(
143        request: fidl::endpoints::Request<Self::RouteSetMarker>,
144    ) -> RouteSetRequest<Self> {
145        RouteSetRequest::from(request)
146    }
147
148    fn into_route_table_request(
149        request: fidl::endpoints::Request<Self::RouteTableMarker>,
150    ) -> RouteTableRequest<Self> {
151        RouteTableRequest::from(request)
152    }
153
154    fn into_route_set_request_result(
155        request: <Self::RouteSetRequestStream as futures::Stream>::Item,
156    ) -> Result<RouteSetRequest<Self>, fidl::Error> {
157        request.map(RouteSetRequest::from)
158    }
159
160    fn into_route_table_request_result(
161        request: <Self::RouteTableRequestStream as futures::Stream>::Item,
162    ) -> Result<RouteTableRequest<Self>, fidl::Error> {
163        request.map(RouteTableRequest::from)
164    }
165}
166
167impl FidlRouteAdminIpExt for Ipv6 {
168    type RouteTableMarker = fnet_routes_admin::RouteTableV6Marker;
169    type GlobalRouteTableMarker = fnet_root::RoutesV6Marker;
170    type RouteSetMarker = fnet_routes_admin::RouteSetV6Marker;
171    type RouteTableProviderMarker = fnet_routes_admin::RouteTableProviderV6Marker;
172    type RouteSetRequestStream = fnet_routes_admin::RouteSetV6RequestStream;
173    type RouteTableRequestStream = fnet_routes_admin::RouteTableV6RequestStream;
174    type AddRouteResponder = fnet_routes_admin::RouteSetV6AddRouteResponder;
175    type RemoveRouteResponder = fnet_routes_admin::RouteSetV6RemoveRouteResponder;
176    type RouteSetAuthenticateForInterfaceResponder =
177        fnet_routes_admin::RouteSetV6AuthenticateForInterfaceResponder;
178    type RouteTableGetTableIdResponder = fnet_routes_admin::RouteTableV6GetTableIdResponder;
179    type RouteTableRemoveResponder = fnet_routes_admin::RouteTableV6RemoveResponder;
180    type RouteTableGetAuthorizationResponder =
181        fnet_routes_admin::RouteTableV6GetAuthorizationForRouteTableResponder;
182    type RouteTableControlHandle = fnet_routes_admin::RouteTableV6ControlHandle;
183    type RouteTableProviderControlHandle = fnet_routes_admin::RouteTableProviderV6ControlHandle;
184    type GetInterfaceLocalTableResponder =
185        fnet_routes_admin::RouteTableProviderV6GetInterfaceLocalTableResponder;
186
187    fn into_route_table_provider_request(
188        request: fidl::endpoints::Request<Self::RouteTableProviderMarker>,
189    ) -> RouteTableProviderRequest<Ipv6> {
190        RouteTableProviderRequest::from(request)
191    }
192
193    fn into_route_set_request(
194        request: fidl::endpoints::Request<Self::RouteSetMarker>,
195    ) -> RouteSetRequest<Self> {
196        RouteSetRequest::from(request)
197    }
198
199    fn into_route_table_request(
200        request: fidl::endpoints::Request<Self::RouteTableMarker>,
201    ) -> RouteTableRequest<Self> {
202        RouteTableRequest::from(request)
203    }
204
205    fn into_route_set_request_result(
206        request: <Self::RouteSetRequestStream as futures::Stream>::Item,
207    ) -> Result<RouteSetRequest<Self>, fidl::Error> {
208        request.map(RouteSetRequest::from)
209    }
210
211    fn into_route_table_request_result(
212        request: <Self::RouteTableRequestStream as futures::Stream>::Item,
213    ) -> Result<RouteTableRequest<Self>, fidl::Error> {
214        request.map(RouteTableRequest::from)
215    }
216}
217
218impl_responder!(
219    fnet_routes_admin::RouteSetV4AddRouteResponder,
220    Result<bool, fnet_routes_admin::RouteSetError>,
221);
222impl_responder!(
223    fnet_routes_admin::RouteSetV4RemoveRouteResponder,
224    Result<bool, fnet_routes_admin::RouteSetError>,
225);
226impl_responder!(
227    fnet_routes_admin::RouteSetV6AddRouteResponder,
228    Result<bool, fnet_routes_admin::RouteSetError>,
229);
230impl_responder!(
231    fnet_routes_admin::RouteSetV6RemoveRouteResponder,
232    Result<bool, fnet_routes_admin::RouteSetError>,
233);
234impl_responder!(
235    fnet_routes_admin::RouteSetV4AuthenticateForInterfaceResponder,
236    Result<(), fnet_routes_admin::AuthenticateForInterfaceError>,
237);
238impl_responder!(
239    fnet_routes_admin::RouteSetV6AuthenticateForInterfaceResponder,
240    Result<(), fnet_routes_admin::AuthenticateForInterfaceError>,
241);
242impl_responder!(fnet_routes_admin::RouteTableV4GetTableIdResponder, u32,);
243impl_responder!(fnet_routes_admin::RouteTableV6GetTableIdResponder, u32,);
244impl_responder!(
245    fnet_routes_admin::RouteTableV4RemoveResponder,
246    Result<(), fnet_routes_admin::BaseRouteTableRemoveError>,
247);
248impl_responder!(
249    fnet_routes_admin::RouteTableV6RemoveResponder,
250    Result<(), fnet_routes_admin::BaseRouteTableRemoveError>,
251);
252impl_responder!(
253    fnet_routes_admin::RouteTableV4GetAuthorizationForRouteTableResponder,
254    fnet_routes_admin::GrantForRouteTableAuthorization,
255);
256impl_responder!(
257    fnet_routes_admin::RouteTableV6GetAuthorizationForRouteTableResponder,
258    fnet_routes_admin::GrantForRouteTableAuthorization,
259);
260impl_responder!(
261    fnet_routes_admin::RouteTableProviderV4GetInterfaceLocalTableResponder,
262    Result<
263        fidl::endpoints::ClientEnd<fnet_routes_admin::RouteTableV4Marker>,
264        fnet_routes_admin::GetInterfaceLocalTableError,
265    >,
266);
267impl_responder!(
268    fnet_routes_admin::RouteTableProviderV6GetInterfaceLocalTableResponder,
269    Result<
270        fidl::endpoints::ClientEnd<fnet_routes_admin::RouteTableV6Marker>,
271        fnet_routes_admin::GetInterfaceLocalTableError,
272    >,
273);
274
275/// Options for creating route tables.
276#[derive(Clone, Debug, GenericOverIp)]
277#[generic_over_ip(I, Ip)]
278pub struct RouteTableOptions<I: Ip> {
279    /// Optional name for the table.
280    pub name: Option<String>,
281    /// Marker for the IP version.
282    pub _marker: std::marker::PhantomData<I>,
283}
284
285impl From<RouteTableOptions<Ipv4>> for fnet_routes_admin::RouteTableOptionsV4 {
286    fn from(val: RouteTableOptions<Ipv4>) -> Self {
287        let RouteTableOptions { name, _marker } = val;
288        Self { name, __source_breaking: fidl::marker::SourceBreaking }
289    }
290}
291
292impl From<RouteTableOptions<Ipv6>> for fnet_routes_admin::RouteTableOptionsV6 {
293    fn from(val: RouteTableOptions<Ipv6>) -> Self {
294        let RouteTableOptions { name, _marker } = val;
295        Self { name, __source_breaking: fidl::marker::SourceBreaking }
296    }
297}
298
299impl From<fnet_routes_admin::RouteTableOptionsV4> for RouteTableOptions<Ipv4> {
300    fn from(val: fnet_routes_admin::RouteTableOptionsV4) -> Self {
301        let fnet_routes_admin::RouteTableOptionsV4 { name, __source_breaking: _ } = val;
302        Self { name, _marker: std::marker::PhantomData }
303    }
304}
305
306impl From<fnet_routes_admin::RouteTableOptionsV6> for RouteTableOptions<Ipv6> {
307    fn from(val: fnet_routes_admin::RouteTableOptionsV6) -> Self {
308        let fnet_routes_admin::RouteTableOptionsV6 { name, __source_breaking: _ } = val;
309        Self { name, _marker: std::marker::PhantomData }
310    }
311}
312
313/// GenericOverIp version of RouteTableProviderV{4, 6}Request.
314#[derive(derivative::Derivative, GenericOverIp)]
315#[derivative(Debug(bound = ""))]
316#[generic_over_ip(I, Ip)]
317pub enum RouteTableProviderRequest<I: Ip + FidlRouteAdminIpExt> {
318    /// Request to create a new route table.
319    NewRouteTable {
320        /// The server end of the RouteTable request
321        provider: fidl::endpoints::ServerEnd<I::RouteTableMarker>,
322        /// The creation options.
323        options: RouteTableOptions<I>,
324        /// The control handle for the protocol.
325        control_handle: I::RouteTableProviderControlHandle,
326    },
327    /// Request to get the interface-local route table.
328    GetInterfaceLocalTable {
329        /// The credentials for the interface.
330        credential: fnet_resources::ProofOfInterfaceAuthorization,
331        /// Responder to return the local table.
332        responder: I::GetInterfaceLocalTableResponder,
333    },
334}
335
336impl From<fnet_routes_admin::RouteTableProviderV4Request> for RouteTableProviderRequest<Ipv4> {
337    fn from(val: fnet_routes_admin::RouteTableProviderV4Request) -> Self {
338        match val {
339            fnet_routes_admin::RouteTableProviderV4Request::NewRouteTable {
340                provider,
341                options,
342                control_handle,
343            } => Self::NewRouteTable { provider, options: options.into(), control_handle },
344            fnet_routes_admin::RouteTableProviderV4Request::GetInterfaceLocalTable {
345                credential,
346                responder,
347            } => Self::GetInterfaceLocalTable { credential, responder },
348        }
349    }
350}
351
352impl From<fnet_routes_admin::RouteTableProviderV6Request> for RouteTableProviderRequest<Ipv6> {
353    fn from(val: fnet_routes_admin::RouteTableProviderV6Request) -> Self {
354        match val {
355            fnet_routes_admin::RouteTableProviderV6Request::NewRouteTable {
356                provider,
357                options,
358                control_handle,
359            } => Self::NewRouteTable { provider, options: options.into(), control_handle },
360            fnet_routes_admin::RouteTableProviderV6Request::GetInterfaceLocalTable {
361                credential,
362                responder,
363            } => Self::GetInterfaceLocalTable { credential, responder },
364        }
365    }
366}
367
368/// Dispatches `new_route_table` on either the `RouteTableProviderV4`
369/// or `RouteTableProviderV6` proxy.
370pub fn new_route_table<I: Ip + FidlRouteAdminIpExt>(
371    route_table_provider_proxy: &<I::RouteTableProviderMarker as ProtocolMarker>::Proxy,
372    name: Option<String>,
373) -> Result<<I::RouteTableMarker as ProtocolMarker>::Proxy, RouteTableCreationError> {
374    let (route_table_proxy, route_table_server_end) =
375        fidl::endpoints::create_proxy::<I::RouteTableMarker>();
376
377    #[derive(GenericOverIp)]
378    #[generic_over_ip(I, Ip)]
379    struct NewRouteTableInput<'a, I: FidlRouteAdminIpExt> {
380        route_table_server_end: fidl::endpoints::ServerEnd<I::RouteTableMarker>,
381        route_table_provider_proxy: &'a <I::RouteTableProviderMarker as ProtocolMarker>::Proxy,
382        name: Option<String>,
383    }
384
385    let result = I::map_ip_in(
386        NewRouteTableInput::<'_, I> { route_table_server_end, route_table_provider_proxy, name },
387        |NewRouteTableInput { route_table_server_end, route_table_provider_proxy, name }| {
388            route_table_provider_proxy.new_route_table(
389                route_table_server_end,
390                &fnet_routes_admin::RouteTableOptionsV4 {
391                    name,
392                    ..fnet_routes_admin::RouteTableOptionsV4::default()
393                },
394            )
395        },
396        |NewRouteTableInput { route_table_server_end, route_table_provider_proxy, name }| {
397            route_table_provider_proxy.new_route_table(
398                route_table_server_end,
399                &fnet_routes_admin::RouteTableOptionsV6 {
400                    name,
401                    ..fnet_routes_admin::RouteTableOptionsV6::default()
402                },
403            )
404        },
405    );
406
407    result.map_err(RouteTableCreationError::RouteTable)?;
408    Ok(route_table_proxy)
409}
410
411/// Dispatches `get_interface_local_table` on either the `RouteTableProviderV4`
412/// or `RouteTableProviderV6` proxy.
413pub async fn get_interface_local_table<I: Ip + FidlRouteAdminIpExt>(
414    route_table_provider_proxy: &<I::RouteTableProviderMarker as ProtocolMarker>::Proxy,
415    credential: fnet_resources::ProofOfInterfaceAuthorization,
416) -> Result<
417    Result<
418        <I::RouteTableMarker as ProtocolMarker>::Proxy,
419        fnet_routes_admin::GetInterfaceLocalTableError,
420    >,
421    fidl::Error,
422> {
423    #[derive(GenericOverIp)]
424    #[generic_over_ip(I, Ip)]
425    struct Input<'a, I: FidlRouteAdminIpExt> {
426        route_table_provider_proxy: &'a <I::RouteTableProviderMarker as ProtocolMarker>::Proxy,
427        credential: fnet_resources::ProofOfInterfaceAuthorization,
428    }
429
430    #[derive(GenericOverIp)]
431    #[generic_over_ip(I, Ip)]
432    struct Output<I: FidlRouteAdminIpExt>(
433        fidl::client::QueryResponseFut<
434            Result<
435                fidl::endpoints::ClientEnd<I::RouteTableMarker>,
436                fnet_routes_admin::GetInterfaceLocalTableError,
437            >,
438        >,
439    );
440
441    let Output(fut) = I::map_ip(
442        Input::<'_, I> { route_table_provider_proxy, credential },
443        |Input { route_table_provider_proxy, credential }| {
444            Output::<Ipv4>(route_table_provider_proxy.get_interface_local_table(credential))
445        },
446        |Input { route_table_provider_proxy, credential }| {
447            Output::<Ipv6>(route_table_provider_proxy.get_interface_local_table(credential))
448        },
449    );
450
451    fut.await.map(|r| r.map(fidl::endpoints::ClientEnd::into_proxy))
452}
453
454/// Dispatches `new_route_set` on either the `RouteTableV4`
455/// or `RouteTableV6` proxy.
456pub fn new_route_set<I: Ip + FidlRouteAdminIpExt>(
457    route_table_proxy: &<I::RouteTableMarker as ProtocolMarker>::Proxy,
458) -> Result<<I::RouteSetMarker as ProtocolMarker>::Proxy, RouteSetCreationError> {
459    let (route_set_proxy, route_set_server_end) =
460        fidl::endpoints::create_proxy::<I::RouteSetMarker>();
461
462    #[derive(GenericOverIp)]
463    #[generic_over_ip(I, Ip)]
464    struct NewRouteSetInput<'a, I: FidlRouteAdminIpExt> {
465        route_set_server_end: fidl::endpoints::ServerEnd<I::RouteSetMarker>,
466        route_table_proxy: &'a <I::RouteTableMarker as ProtocolMarker>::Proxy,
467    }
468    let result = I::map_ip_in(
469        NewRouteSetInput::<'_, I> { route_set_server_end, route_table_proxy },
470        |NewRouteSetInput { route_set_server_end, route_table_proxy }| {
471            route_table_proxy.new_route_set(route_set_server_end)
472        },
473        |NewRouteSetInput { route_set_server_end, route_table_proxy }| {
474            route_table_proxy.new_route_set(route_set_server_end)
475        },
476    );
477
478    result.map_err(RouteSetCreationError::RouteSet)?;
479    Ok(route_set_proxy)
480}
481
482/// Dispatches `global_route_set` on either the `RoutesV4` or `RoutesV6` in
483/// fuchsia.net.root.
484pub fn new_global_route_set<I: Ip + FidlRouteAdminIpExt>(
485    route_table_proxy: &<I::GlobalRouteTableMarker as ProtocolMarker>::Proxy,
486) -> Result<<I::RouteSetMarker as ProtocolMarker>::Proxy, RouteSetCreationError> {
487    let (route_set_proxy, route_set_server_end) =
488        fidl::endpoints::create_proxy::<I::RouteSetMarker>();
489
490    #[derive(GenericOverIp)]
491    #[generic_over_ip(I, Ip)]
492    struct NewRouteSetInput<'a, I: FidlRouteAdminIpExt> {
493        route_set_server_end: fidl::endpoints::ServerEnd<I::RouteSetMarker>,
494        route_table_proxy: &'a <I::GlobalRouteTableMarker as ProtocolMarker>::Proxy,
495    }
496    let result = I::map_ip_in(
497        NewRouteSetInput::<'_, I> { route_set_server_end, route_table_proxy },
498        |NewRouteSetInput { route_set_server_end, route_table_proxy }| {
499            route_table_proxy.global_route_set(route_set_server_end)
500        },
501        |NewRouteSetInput { route_set_server_end, route_table_proxy }| {
502            route_table_proxy.global_route_set(route_set_server_end)
503        },
504    );
505
506    result.map_err(RouteSetCreationError::RouteSet)?;
507    Ok(route_set_proxy)
508}
509
510/// Dispatches `add_route` on either the `RouteSetV4` or `RouteSetV6` proxy.
511pub async fn add_route<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
512    route_set: &<I::RouteSetMarker as ProtocolMarker>::Proxy,
513    route: &I::Route,
514) -> Result<Result<bool, fnet_routes_admin::RouteSetError>, fidl::Error> {
515    #[derive(GenericOverIp)]
516    #[generic_over_ip(I, Ip)]
517    struct AddRouteInput<'a, I: FidlRouteAdminIpExt + FidlRouteIpExt> {
518        route_set: &'a <I::RouteSetMarker as ProtocolMarker>::Proxy,
519        route: &'a I::Route,
520    }
521
522    I::map_ip_in(
523        AddRouteInput { route_set, route },
524        |AddRouteInput { route_set, route }| Either::Left(route_set.add_route(route)),
525        |AddRouteInput { route_set, route }| Either::Right(route_set.add_route(route)),
526    )
527    .await
528}
529
530/// Dispatches `remove_route` on either the `RouteSetV4` or `RouteSetV6` proxy.
531pub async fn remove_route<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
532    route_set: &<I::RouteSetMarker as ProtocolMarker>::Proxy,
533    route: &I::Route,
534) -> Result<Result<bool, fnet_routes_admin::RouteSetError>, fidl::Error> {
535    #[derive(GenericOverIp)]
536    #[generic_over_ip(I, Ip)]
537    struct RemoveRouteInput<'a, I: FidlRouteAdminIpExt + FidlRouteIpExt> {
538        route_set: &'a <I::RouteSetMarker as ProtocolMarker>::Proxy,
539        route: &'a I::Route,
540    }
541
542    I::map_ip_in(
543        RemoveRouteInput { route_set, route },
544        |RemoveRouteInput { route_set, route }| Either::Left(route_set.remove_route(route)),
545        |RemoveRouteInput { route_set, route }| Either::Right(route_set.remove_route(route)),
546    )
547    .await
548}
549
550/// Dispatches `authenticate_for_interface` on either the `RouteSetV4` or
551/// `RouteSetV6` proxy.
552pub async fn authenticate_for_interface<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
553    route_set: &<I::RouteSetMarker as ProtocolMarker>::Proxy,
554    credential: fnet_resources::ProofOfInterfaceAuthorization,
555) -> Result<Result<(), fnet_routes_admin::AuthenticateForInterfaceError>, fidl::Error> {
556    #[derive(GenericOverIp)]
557    #[generic_over_ip(I, Ip)]
558    struct AuthenticateForInterfaceInput<'a, I: FidlRouteAdminIpExt + FidlRouteIpExt> {
559        route_set: &'a <I::RouteSetMarker as ProtocolMarker>::Proxy,
560        credential: fnet_resources::ProofOfInterfaceAuthorization,
561    }
562
563    I::map_ip_in(
564        AuthenticateForInterfaceInput { route_set, credential },
565        |AuthenticateForInterfaceInput { route_set, credential }| {
566            Either::Left(route_set.authenticate_for_interface(credential))
567        },
568        |AuthenticateForInterfaceInput { route_set, credential }| {
569            Either::Right(route_set.authenticate_for_interface(credential))
570        },
571    )
572    .await
573}
574
575#[derive(GenericOverIp)]
576#[generic_over_ip(I, Ip)]
577struct RouteTableProxy<'a, I: FidlRouteAdminIpExt + FidlRouteIpExt> {
578    route_table: &'a <I::RouteTableMarker as ProtocolMarker>::Proxy,
579}
580
581/// Dispatches `detach` on either the `RouteTableV4` or `RouteTableV6` proxy.
582pub async fn detach_route_table<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
583    route_table: &<I::RouteTableMarker as ProtocolMarker>::Proxy,
584) -> Result<(), fidl::Error> {
585    let IpInvariant(result) = net_types::map_ip_twice!(
586        I,
587        RouteTableProxy { route_table },
588        |RouteTableProxy { route_table }| { IpInvariant(route_table.detach()) }
589    );
590
591    result
592}
593
594/// Dispatches `remove` on either the `RouteTableV4` or `RouteTableV6` proxy.
595pub async fn remove_route_table<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
596    route_table: &<I::RouteTableMarker as ProtocolMarker>::Proxy,
597) -> Result<Result<(), fnet_routes_admin::BaseRouteTableRemoveError>, fidl::Error> {
598    let IpInvariant(result_fut) = net_types::map_ip_twice!(
599        I,
600        RouteTableProxy { route_table },
601        |RouteTableProxy { route_table }| { IpInvariant(route_table.remove()) }
602    );
603
604    result_fut.await
605}
606
607/// Dispatches `get_table_id` on either the `RouteTableV4` or `RouteTableV6`
608/// proxy.
609pub async fn get_table_id<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
610    route_table: &<I::RouteTableMarker as ProtocolMarker>::Proxy,
611) -> Result<TableId, fidl::Error> {
612    let IpInvariant(result_fut) = net_types::map_ip_twice!(
613        I,
614        RouteTableProxy { route_table },
615        |RouteTableProxy { route_table }| IpInvariant(route_table.get_table_id()),
616    );
617
618    result_fut.await.map(TableId::new)
619}
620
621/// Dispatches `get_authorization_for_route_table` on either the `RouteTableV4`
622/// or `RouteTableV6` proxy.
623pub async fn get_authorization_for_route_table<I: Ip + FidlRouteAdminIpExt + FidlRouteIpExt>(
624    route_table: &<I::RouteTableMarker as ProtocolMarker>::Proxy,
625) -> Result<fnet_routes_admin::GrantForRouteTableAuthorization, fidl::Error> {
626    let IpInvariant(result_fut) = net_types::map_ip_twice!(
627        I,
628        RouteTableProxy { route_table },
629        |RouteTableProxy { route_table }| IpInvariant(
630            route_table.get_authorization_for_route_table()
631        ),
632    );
633
634    result_fut.await
635}
636
637/// GenericOverIp version of RouteSetV{4, 6}Request.
638#[derive(GenericOverIp, Debug)]
639#[generic_over_ip(I, Ip)]
640pub enum RouteSetRequest<I: FidlRouteAdminIpExt> {
641    /// Adds a route to the route set.
642    AddRoute {
643        /// The route to add.
644        route: Result<
645            crate::Route<I>,
646            crate::FidlConversionError<crate::RoutePropertiesRequiredFields>,
647        >,
648        /// The responder for this request.
649        responder: I::AddRouteResponder,
650    },
651    /// Removes a route from the route set.
652    RemoveRoute {
653        /// The route to add.
654        route: Result<
655            crate::Route<I>,
656            crate::FidlConversionError<crate::RoutePropertiesRequiredFields>,
657        >,
658        /// The responder for this request.
659        responder: I::RemoveRouteResponder,
660    },
661    /// Authenticates the route set for managing routes on an interface.
662    AuthenticateForInterface {
663        /// The credential proving authorization for this interface.
664        credential: fnet_resources::ProofOfInterfaceAuthorization,
665        /// The responder for this request.
666        responder: I::RouteSetAuthenticateForInterfaceResponder,
667    },
668}
669
670impl From<fnet_routes_admin::RouteSetV4Request> for RouteSetRequest<Ipv4> {
671    fn from(value: fnet_routes_admin::RouteSetV4Request) -> Self {
672        match value {
673            fnet_routes_admin::RouteSetV4Request::AddRoute { route, responder } => {
674                RouteSetRequest::AddRoute { route: route.try_into(), responder }
675            }
676            fnet_routes_admin::RouteSetV4Request::RemoveRoute { route, responder } => {
677                RouteSetRequest::RemoveRoute { route: route.try_into(), responder }
678            }
679            fnet_routes_admin::RouteSetV4Request::AuthenticateForInterface {
680                credential,
681                responder,
682            } => RouteSetRequest::AuthenticateForInterface { credential, responder },
683        }
684    }
685}
686
687impl From<fnet_routes_admin::RouteSetV6Request> for RouteSetRequest<Ipv6> {
688    fn from(value: fnet_routes_admin::RouteSetV6Request) -> Self {
689        match value {
690            fnet_routes_admin::RouteSetV6Request::AddRoute { route, responder } => {
691                RouteSetRequest::AddRoute { route: route.try_into(), responder }
692            }
693            fnet_routes_admin::RouteSetV6Request::RemoveRoute { route, responder } => {
694                RouteSetRequest::RemoveRoute { route: route.try_into(), responder }
695            }
696            fnet_routes_admin::RouteSetV6Request::AuthenticateForInterface {
697                credential,
698                responder,
699            } => RouteSetRequest::AuthenticateForInterface { credential, responder },
700        }
701    }
702}
703
704/// GenericOverIp version of RouteTableV{4, 6}Request.
705#[derive(GenericOverIp, derivative::Derivative)]
706#[derivative(Debug(bound = ""))]
707#[generic_over_ip(I, Ip)]
708pub enum RouteTableRequest<I: FidlRouteAdminIpExt> {
709    /// Gets the table ID for the table
710    GetTableId {
711        /// Responder for the request.
712        responder: I::RouteTableGetTableIdResponder,
713    },
714    /// Detaches the table lifetime from the channel.
715    Detach {
716        /// Control handle to the protocol.
717        control_handle: I::RouteTableControlHandle,
718    },
719    /// Removes the table.
720    Remove {
721        /// Responder to the request.
722        responder: I::RouteTableRemoveResponder,
723    },
724    /// Gets the authorization for the route table.
725    GetAuthorizationForRouteTable {
726        /// Responder to the request.
727        responder: I::RouteTableGetAuthorizationResponder,
728    },
729    /// Creates a new route set for the table.
730    NewRouteSet {
731        /// The server end of the route set protocol.
732        route_set: fidl::endpoints::ServerEnd<I::RouteSetMarker>,
733        /// Control handle to the protocol.
734        control_handle: I::RouteTableControlHandle,
735    },
736}
737
738impl From<fnet_routes_admin::RouteTableV4Request> for RouteTableRequest<Ipv4> {
739    fn from(value: fnet_routes_admin::RouteTableV4Request) -> Self {
740        match value {
741            fnet_routes_admin::RouteTableV4Request::NewRouteSet { route_set, control_handle } => {
742                RouteTableRequest::NewRouteSet { route_set, control_handle }
743            }
744            fnet_routes_admin::RouteTableV4Request::GetTableId { responder } => {
745                RouteTableRequest::GetTableId { responder }
746            }
747
748            fnet_routes_admin::RouteTableV4Request::Detach { control_handle } => {
749                RouteTableRequest::Detach { control_handle }
750            }
751
752            fnet_routes_admin::RouteTableV4Request::Remove { responder } => {
753                RouteTableRequest::Remove { responder }
754            }
755            fnet_routes_admin::RouteTableV4Request::GetAuthorizationForRouteTable { responder } => {
756                RouteTableRequest::GetAuthorizationForRouteTable { responder }
757            }
758        }
759    }
760}
761
762impl From<fnet_routes_admin::RouteTableV6Request> for RouteTableRequest<Ipv6> {
763    fn from(value: fnet_routes_admin::RouteTableV6Request) -> Self {
764        match value {
765            fnet_routes_admin::RouteTableV6Request::NewRouteSet { route_set, control_handle } => {
766                RouteTableRequest::NewRouteSet { route_set, control_handle }
767            }
768            fnet_routes_admin::RouteTableV6Request::GetTableId { responder } => {
769                RouteTableRequest::GetTableId { responder }
770            }
771
772            fnet_routes_admin::RouteTableV6Request::Detach { control_handle } => {
773                RouteTableRequest::Detach { control_handle }
774            }
775
776            fnet_routes_admin::RouteTableV6Request::Remove { responder } => {
777                RouteTableRequest::Remove { responder }
778            }
779            fnet_routes_admin::RouteTableV6Request::GetAuthorizationForRouteTable { responder } => {
780                RouteTableRequest::GetAuthorizationForRouteTable { responder }
781            }
782        }
783    }
784}