1pub mod sock_diag;
8
9use netlink_packet_core::{
10 NetlinkDeserializable, NetlinkMessage, NetlinkPayload, NetlinkSerializable,
11};
12use netlink_packet_utils::DecodeError;
13
14use std::fmt::Debug;
15use std::hash::Hash;
16use std::num::NonZeroU32;
17
18use async_trait::async_trait;
22
23use crate::client::{AsyncWorkCompletionWaiter, ExternalClient, InternalClient};
24use crate::logging::{log_debug, log_warn};
25use crate::messaging::{MessageWithPermission, Sender};
26use crate::multicast_groups::{
27 InvalidLegacyGroupsError, InvalidModernGroupError, LegacyGroups, ModernGroup,
28 MulticastCapableNetlinkFamily,
29};
30use crate::route_tables::{NetlinkRouteTableIndex, NonZeroNetlinkRouteTableIndex};
31
32pub(crate) trait ProtocolFamily: MulticastCapableNetlinkFamily + Send + Sized {
34 type Request: Clone
36 + Debug
37 + NetlinkDeserializable<Error: Into<DecodeError>>
38 + MessageWithPermission
39 + Send;
40
41 type Response: Clone + Debug + NetlinkSerializable + Send;
43
44 type RequestHandler<S: Sender<Self::Response>>: NetlinkFamilyRequestHandler<Self, S>;
46
47 const NAME: &'static str;
48
49 type NotifiedMulticastGroup: PartialEq + Eq + Hash + Clone + Copy + Debug + Send;
50
51 type AsyncWorkItem: Debug;
54
55 fn should_notify_on_group_membership_change(
58 group: ModernGroup,
59 ) -> Option<Self::NotifiedMulticastGroup>;
60}
61
62#[async_trait]
63pub(crate) trait NetlinkFamilyRequestHandler<F: ProtocolFamily, S: Sender<F::Response>>:
65 Clone + Send
66{
67 async fn handle_request(
69 &mut self,
70 req: NetlinkMessage<F::Request>,
71 client: &mut InternalClient<F, S>,
72 );
73}
74
75pub trait NetlinkClient: Send + Sync {
77 type Request: Clone
79 + Debug
80 + NetlinkDeserializable<Error: Into<DecodeError>>
81 + MessageWithPermission
82 + Send;
83
84 fn set_pid(&self, pid: NonZeroU32);
86
87 fn add_membership(
89 &self,
90 group: ModernGroup,
91 ) -> Result<AsyncWorkCompletionWaiter, InvalidModernGroupError>;
92
93 fn del_membership(&self, group: ModernGroup) -> Result<(), InvalidModernGroupError>;
95
96 fn set_legacy_memberships(
98 &self,
99 legacy_memberships: LegacyGroups,
100 ) -> Result<AsyncWorkCompletionWaiter, InvalidLegacyGroupsError>;
101}
102
103pub mod route {
104 use super::*;
107
108 use std::fmt::Display;
109 use std::num::NonZeroU64;
110
111 use fidl_fuchsia_net_routes_ext as fnet_routes_ext;
112
113 use either::Either;
114 use futures::channel::{mpsc, oneshot};
115 use futures::sink::SinkExt as _;
116 use linux_uapi::{
117 IFA_F_NOPREFIXROUTE, rt_class_t_RT_TABLE_COMPAT, rt_class_t_RT_TABLE_MAIN,
118 rtnetlink_groups_RTNLGRP_DCB, rtnetlink_groups_RTNLGRP_DECnet_IFADDR,
119 rtnetlink_groups_RTNLGRP_DECnet_ROUTE, rtnetlink_groups_RTNLGRP_DECnet_RULE,
120 rtnetlink_groups_RTNLGRP_IPV4_IFADDR, rtnetlink_groups_RTNLGRP_IPV4_MROUTE,
121 rtnetlink_groups_RTNLGRP_IPV4_MROUTE_R, rtnetlink_groups_RTNLGRP_IPV4_NETCONF,
122 rtnetlink_groups_RTNLGRP_IPV4_ROUTE, rtnetlink_groups_RTNLGRP_IPV4_RULE,
123 rtnetlink_groups_RTNLGRP_IPV6_IFADDR, rtnetlink_groups_RTNLGRP_IPV6_IFINFO,
124 rtnetlink_groups_RTNLGRP_IPV6_MROUTE, rtnetlink_groups_RTNLGRP_IPV6_MROUTE_R,
125 rtnetlink_groups_RTNLGRP_IPV6_NETCONF, rtnetlink_groups_RTNLGRP_IPV6_PREFIX,
126 rtnetlink_groups_RTNLGRP_IPV6_ROUTE, rtnetlink_groups_RTNLGRP_IPV6_RULE,
127 rtnetlink_groups_RTNLGRP_LINK, rtnetlink_groups_RTNLGRP_MDB,
128 rtnetlink_groups_RTNLGRP_MPLS_NETCONF, rtnetlink_groups_RTNLGRP_MPLS_ROUTE,
129 rtnetlink_groups_RTNLGRP_ND_USEROPT, rtnetlink_groups_RTNLGRP_NEIGH,
130 rtnetlink_groups_RTNLGRP_NONE, rtnetlink_groups_RTNLGRP_NOP2,
131 rtnetlink_groups_RTNLGRP_NOP4, rtnetlink_groups_RTNLGRP_NOTIFY,
132 rtnetlink_groups_RTNLGRP_NSID, rtnetlink_groups_RTNLGRP_PHONET_IFADDR,
133 rtnetlink_groups_RTNLGRP_PHONET_ROUTE, rtnetlink_groups_RTNLGRP_TC,
134 };
135 use net_types::SpecifiedAddr;
136 use net_types::ip::{
137 AddrSubnetEither, AddrSubnetError, Ip, IpAddr, IpInvariant, IpVersion, Ipv4, Ipv4Addr,
138 Ipv6, Ipv6Addr, Subnet,
139 };
140 use netlink_packet_route::address::{AddressAttribute, AddressMessage};
141 use netlink_packet_route::link::{LinkAttribute, LinkFlags, LinkMessage};
142 use netlink_packet_route::route::{RouteAttribute, RouteMessage, RouteType};
143 use netlink_packet_route::{AddressFamily, RouteNetlinkMessage};
144
145 use crate::client::AsyncWorkCompletionWaiter;
146 use crate::interfaces::AcceptRaRtTable;
147 use crate::messaging::{MessageWithPermission, Permission};
148 use crate::netlink_packet::errno::Errno;
149 use crate::netlink_packet::{self};
150 use crate::route_eventloop::UnifiedRequest;
151 use crate::rules::{RuleRequest, RuleRequestArgs};
152 use crate::{SysctlError, SysctlInterfaceSelector, interfaces, routes};
153
154 use netlink_packet_core::{NLM_F_ACK, NLM_F_DUMP, NLM_F_REPLACE, NetlinkHeader};
155
156 pub(crate) enum NetlinkRoute {}
158
159 impl MulticastCapableNetlinkFamily for NetlinkRoute {
160 #[allow(non_upper_case_globals)]
161 fn is_valid_group(ModernGroup(group): &ModernGroup) -> bool {
162 match *group {
163 rtnetlink_groups_RTNLGRP_DCB
164 | rtnetlink_groups_RTNLGRP_DECnet_IFADDR
165 | rtnetlink_groups_RTNLGRP_DECnet_ROUTE
166 | rtnetlink_groups_RTNLGRP_DECnet_RULE
167 | rtnetlink_groups_RTNLGRP_IPV4_IFADDR
168 | rtnetlink_groups_RTNLGRP_IPV4_MROUTE
169 | rtnetlink_groups_RTNLGRP_IPV4_MROUTE_R
170 | rtnetlink_groups_RTNLGRP_IPV4_NETCONF
171 | rtnetlink_groups_RTNLGRP_IPV4_ROUTE
172 | rtnetlink_groups_RTNLGRP_IPV4_RULE
173 | rtnetlink_groups_RTNLGRP_IPV6_IFADDR
174 | rtnetlink_groups_RTNLGRP_IPV6_IFINFO
175 | rtnetlink_groups_RTNLGRP_IPV6_MROUTE
176 | rtnetlink_groups_RTNLGRP_IPV6_MROUTE_R
177 | rtnetlink_groups_RTNLGRP_IPV6_NETCONF
178 | rtnetlink_groups_RTNLGRP_IPV6_PREFIX
179 | rtnetlink_groups_RTNLGRP_IPV6_ROUTE
180 | rtnetlink_groups_RTNLGRP_IPV6_RULE
181 | rtnetlink_groups_RTNLGRP_LINK
182 | rtnetlink_groups_RTNLGRP_MDB
183 | rtnetlink_groups_RTNLGRP_MPLS_NETCONF
184 | rtnetlink_groups_RTNLGRP_MPLS_ROUTE
185 | rtnetlink_groups_RTNLGRP_ND_USEROPT
186 | rtnetlink_groups_RTNLGRP_NEIGH
187 | rtnetlink_groups_RTNLGRP_NONE
188 | rtnetlink_groups_RTNLGRP_NOP2
189 | rtnetlink_groups_RTNLGRP_NOP4
190 | rtnetlink_groups_RTNLGRP_NOTIFY
191 | rtnetlink_groups_RTNLGRP_NSID
192 | rtnetlink_groups_RTNLGRP_PHONET_IFADDR
193 | rtnetlink_groups_RTNLGRP_PHONET_ROUTE
194 | rtnetlink_groups_RTNLGRP_TC => true,
195 _ => false,
196 }
197 }
198 }
199
200 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
201 pub(crate) enum NetlinkRouteNotifiedGroup {
202 Nduseropt,
203 }
204
205 impl MessageWithPermission for RouteNetlinkMessage {
206 fn permission(&self) -> Permission {
207 match self {
208 Self::GetLink(_)
209 | Self::GetAddress(_)
210 | Self::GetNeighbour(_)
211 | Self::GetNeighbourTable(_)
212 | Self::GetRoute(_)
213 | Self::GetQueueDiscipline(_)
214 | Self::GetTrafficClass(_)
215 | Self::GetTrafficFilter(_)
216 | Self::GetTrafficChain(_)
217 | Self::GetNsId(_)
218 | Self::GetRule(_) => Permission::NetlinkRouteRead,
219
220 Self::NewLink(_)
221 | Self::DelLink(_)
222 | Self::SetLink(_)
223 | Self::NewLinkProp(_)
224 | Self::DelLinkProp(_)
225 | Self::NewAddress(_)
226 | Self::DelAddress(_)
227 | Self::NewNeighbour(_)
228 | Self::DelNeighbour(_)
229 | Self::NewNeighbourTable(_)
230 | Self::SetNeighbourTable(_)
231 | Self::NewNeighbourDiscoveryUserOption(_)
232 | Self::NewRoute(_)
233 | Self::DelRoute(_)
234 | Self::NewPrefix(_)
235 | Self::NewQueueDiscipline(_)
236 | Self::DelQueueDiscipline(_)
237 | Self::NewTrafficClass(_)
238 | Self::DelTrafficClass(_)
239 | Self::NewTrafficFilter(_)
240 | Self::DelTrafficFilter(_)
241 | Self::NewTrafficChain(_)
242 | Self::DelTrafficChain(_)
243 | Self::NewNsId(_)
244 | Self::DelNsId(_)
245 | Self::NewRule(_)
246 | Self::DelRule(_) => Permission::NetlinkRouteWrite,
247 }
248 }
249 }
250
251 impl ProtocolFamily for NetlinkRoute {
252 type Request = RouteNetlinkMessage;
253 type Response = RouteNetlinkMessage;
254 type RequestHandler<S: Sender<Self::Response>> = NetlinkRouteRequestHandler<S>;
255 type NotifiedMulticastGroup = NetlinkRouteNotifiedGroup;
256 type AsyncWorkItem = RouteAsyncWork;
257
258 const NAME: &'static str = "NETLINK_ROUTE";
259 fn should_notify_on_group_membership_change(
260 group: ModernGroup,
261 ) -> Option<Self::NotifiedMulticastGroup> {
262 (group == ModernGroup(rtnetlink_groups_RTNLGRP_ND_USEROPT))
263 .then_some(NetlinkRouteNotifiedGroup::Nduseropt)
264 }
265 }
266
267 #[derive(Debug)]
268 pub(crate) enum RouteAsyncWork {
269 SetAcceptRaRtTable {
270 interface: SysctlInterfaceSelector,
271 value: AcceptRaRtTable,
272 responder: oneshot_sync::Sender<Result<(), SysctlError>>,
273 },
274 GetAcceptRaRtTable {
275 interface: SysctlInterfaceSelector,
276 responder: oneshot_sync::Sender<Result<AcceptRaRtTable, SysctlError>>,
277 },
278 }
279
280 #[derive(Clone)]
281 pub(crate) struct NetlinkRouteRequestHandler<S: Sender<RouteNetlinkMessage>> {
282 pub(crate) unified_request_sink: mpsc::Sender<UnifiedRequest<S>>,
283 }
284
285 struct ExtractedAddressRequest {
286 address_and_interface_id: interfaces::AddressAndInterfaceArgs,
287 addr_flags: u32,
288 }
289
290 fn extract_if_id_and_addr_from_addr_message(
291 message: &AddressMessage,
292 client: &impl Display,
293 req: &RouteNetlinkMessage,
294 is_new: bool,
296 ) -> Result<Option<ExtractedAddressRequest>, Errno> {
297 let kind = if is_new { "new" } else { "del" };
298
299 let interface_id = match NonZeroU32::new(message.header.index.into()) {
300 Some(interface_id) => interface_id,
301 None => {
302 log_debug!(
303 "unspecified interface ID in address {} request from {}: {:?}",
304 kind,
305 client,
306 req,
307 );
308 return Err(Errno::EINVAL);
309 }
310 };
311
312 let mut address = None;
313 let mut local = None;
314 let mut addr_flags = None;
315 message.attributes.iter().for_each(|nla| match nla {
316 AddressAttribute::Address(a) => address = Some(a),
317 AddressAttribute::Local(l) => local = Some(l),
318 AddressAttribute::Flags(flags) => addr_flags = Some(*flags),
319 nla => {
320 log_warn!(
321 "unexpected Address NLA in {} request from {}: {:?}; req = {:?}",
322 kind,
323 client,
324 nla,
325 req,
326 );
327 }
328 });
329
330 let addr = match (local, address) {
368 (Some(local), Some(address)) => {
369 if local == address {
370 address
371 } else {
372 log_debug!(
373 "got different `IFA_ADDRESS` and `IFA_LOCAL` values for {} address request from {}: {:?}",
374 kind,
375 client,
376 req,
377 );
378 return Err(Errno::ENOTSUP);
379 }
380 }
381 (Some(addr), None) | (None, Some(addr)) => addr,
382 (None, None) => {
383 log_debug!(
384 "missing `IFA_ADDRESS` and `IFA_LOCAL` in address {} request from {}: {:?}",
385 kind,
386 client,
387 req,
388 );
389 return Err(Errno::EINVAL);
390 }
391 };
392
393 let addr = match message.header.family() {
394 AddressFamily::Inet => {
395 if addr.is_unspecified() {
396 return Ok(None);
399 }
400 match addr {
401 std::net::IpAddr::V4(v4) => IpAddr::V4(Ipv4Addr::new(v4.octets())),
402 std::net::IpAddr::V6(_) => {
403 log_debug!(
404 "expected IPv4 address in new address request from {}: {:?}",
405 client,
406 req
407 );
408 return Err(Errno::EINVAL);
409 }
410 }
411 }
412 AddressFamily::Inet6 => {
413 if addr.is_unspecified() {
414 return Err(Errno::EADDRNOTAVAIL);
417 }
418 match addr {
419 std::net::IpAddr::V4(_) => {
420 log_debug!(
421 "expected IPv6 address in new address request from {}: {:?}",
422 client,
423 req
424 );
425 return Err(Errno::EINVAL);
426 }
427 std::net::IpAddr::V6(v6) => IpAddr::V6(Ipv6Addr::new(v6.segments())),
428 }
429 }
430 family => {
431 log_debug!(
432 "invalid address family ({:?}) in new address \
433 request from {}: {:?}",
434 family,
435 client,
436 req
437 );
438 return Err(Errno::EINVAL);
439 }
440 };
441
442 let address = match AddrSubnetEither::new(addr, message.header.prefix_len) {
443 Ok(address) => address,
444 Err(
445 AddrSubnetError::PrefixTooLong
446 | AddrSubnetError::NotUnicastInSubnet
447 | AddrSubnetError::InvalidWitness,
448 ) => {
449 log_debug!(
450 "invalid address in address {} request from {}: {:?}",
451 kind,
452 client,
453 req
454 );
455 return Err(Errno::EINVAL);
456 }
457 };
458
459 Ok(Some(ExtractedAddressRequest {
460 address_and_interface_id: interfaces::AddressAndInterfaceArgs { address, interface_id },
461 addr_flags: addr_flags
462 .map(|value| value.bits())
463 .unwrap_or_else(|| message.header.flags.into()),
464 }))
465 }
466
467 fn to_get_link_args(
469 link_msg: LinkMessage,
470 is_dump: bool,
471 ) -> Result<interfaces::GetLinkArgs, Errno> {
472 if is_dump {
476 return Ok(interfaces::GetLinkArgs::Dump);
477 }
478 if let Ok(link_id) = <u32 as TryInto<NonZeroU32>>::try_into(link_msg.header.index) {
479 return Ok(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(link_id)));
480 }
481 if let Some(name) = link_msg.attributes.into_iter().find_map(|nla| match nla {
482 LinkAttribute::IfName(name) => Some(name),
483 nla => {
484 log_debug!("ignoring unexpected NLA in GetLink request: {:?}", nla);
485 None
486 }
487 }) {
488 return Ok(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(name)));
489 }
490 return Err(Errno::EINVAL);
491 }
492
493 fn to_set_link_args(link_msg: LinkMessage) -> Result<interfaces::SetLinkArgs, Errno> {
495 let link_id = NonZeroU32::new(link_msg.header.index);
496 let link_name = link_msg.attributes.into_iter().find_map(|nla| match nla {
497 LinkAttribute::IfName(name) => Some(name),
498 nla => {
499 log_debug!("ignoring unexpected NLA in SetLink request: {:?}", nla);
500 None
501 }
502 });
503 let link = match (link_id, link_name) {
504 (Some(id), None) => interfaces::LinkSpecifier::Index(id),
505 (None, Some(name)) => interfaces::LinkSpecifier::Name(name),
506 (None, None) => return Err(Errno::EINVAL),
507 (Some(_id), Some(_name)) => return Err(Errno::EBUSY),
510 };
511 let enable: Option<bool> = ((link_msg.header.change_mask & LinkFlags::Up) == LinkFlags::Up)
514 .then_some((link_msg.header.flags & LinkFlags::Up) != LinkFlags::empty());
515
516 let unsupported_changes = link_msg.header.change_mask & !LinkFlags::Up;
517 if unsupported_changes != LinkFlags::empty() {
518 log_warn!(
519 "ignoring unsupported changes in SetLink request: {:#X}",
520 unsupported_changes
521 );
522 }
523
524 Ok(interfaces::SetLinkArgs { link, enable })
525 }
526
527 #[derive(Debug)]
528 enum ExtractedRouteRequest<I: Ip> {
529 Unicast(ExtractedUnicastRouteRequest<I>),
531 }
532 #[derive(Debug)]
536 struct ExtractedUnicastRouteRequest<I: Ip> {
537 subnet: Subnet<I::Addr>,
538 outbound_interface: Option<NonZeroU64>,
539 next_hop: Option<SpecifiedAddr<I::Addr>>,
540 priority: Option<NonZeroU32>,
541 table: NonZeroNetlinkRouteTableIndex,
542 }
543
544 fn extract_data_from_unicast_route_message<I: Ip>(
548 message: &RouteMessage,
549 client: &impl Display,
550 req: &RouteNetlinkMessage,
551 kind: &str,
552 ) -> Result<ExtractedRouteRequest<I>, Errno> {
553 let destination_prefix_len = message.header.destination_prefix_length;
554 let mut table: NetlinkRouteTableIndex =
555 NetlinkRouteTableIndex::new(message.header.table.into());
556
557 let mut destination_addr = None;
558 let mut outbound_interface = None;
559 let mut next_hop_addr = None;
560 let mut priority = None;
561 message.attributes.iter().for_each(|nla| match nla {
562 RouteAttribute::Destination(addr) => destination_addr = Some(addr),
563 RouteAttribute::Oif(id) => outbound_interface = Some(id),
564 RouteAttribute::Gateway(addr) => next_hop_addr = Some(addr),
565 RouteAttribute::Priority(num) => priority = Some(*num),
566 RouteAttribute::Table(num) => {
567 if message.header.table != rt_class_t_RT_TABLE_COMPAT as u8 {
574 log_debug!(
575 "`RTA_TABLE` is expected only when table in header is `RT_TABLE_COMPAT`, \
576 but it was {}. Using provided value of {} in the NLA",
577 message.header.table,
578 num
579 );
580 }
581 table = NetlinkRouteTableIndex::new(*num)
582 }
583 nla => {
584 log_warn!(
585 "ignoring unexpected Route NLA in {} request from {}: {:?}; req = {:?}",
586 kind,
587 client,
588 nla,
589 req,
590 );
591 }
592 });
593
594 let outbound_interface =
595 outbound_interface.map(|id| NonZeroU64::new((*id).into())).flatten();
596 let priority = priority.map(NonZeroU32::new).flatten();
597 let table = NonZeroNetlinkRouteTableIndex::new(table).unwrap_or_else(|| {
598 NonZeroNetlinkRouteTableIndex::new_non_zero(
599 NonZeroU32::new(rt_class_t_RT_TABLE_MAIN.into()).unwrap(),
600 )
601 });
602 let destination_addr = match destination_addr {
603 Some(addr) => crate::netlink_packet::ip_addr_from_route::<I>(addr)?,
604 None => {
605 if destination_prefix_len != 0 {
608 log_warn!(
609 "rejecting route {} request with prefix length {} and missing `RTA_DST` \
610 from {}: {:?}",
611 kind,
612 destination_prefix_len,
613 client,
614 req
615 );
616 return Err(Errno::EINVAL);
617 }
618 I::UNSPECIFIED_ADDRESS
619 }
620 };
621
622 let next_hop = match next_hop_addr {
623 Some(addr) => {
624 crate::netlink_packet::ip_addr_from_route::<I>(addr).map(SpecifiedAddr::new)?
628 }
629 None => None,
630 };
631
632 let extracted_route_request = match Subnet::new(destination_addr, destination_prefix_len) {
633 Ok(subnet) => ExtractedRouteRequest::Unicast(ExtractedUnicastRouteRequest {
634 subnet,
635 outbound_interface,
636 next_hop,
637 priority,
638 table,
639 }),
640 Err(e) => {
641 log_warn!(
642 "{:?} subnet ({}) in route {} request from {}: {:?}",
643 e,
644 destination_addr,
645 kind,
646 client,
647 req,
648 );
649 return Err(Errno::EINVAL);
650 }
651 };
652
653 Ok(extracted_route_request)
654 }
655
656 fn to_new_route_args<I: Ip>(
662 message: &RouteMessage,
663 client: &impl Display,
664 req: &RouteNetlinkMessage,
665 ) -> Result<routes::RouteRequestArgs<I>, Errno> {
666 let extracted_request =
667 extract_data_from_unicast_route_message::<I>(message, client, req, "new")?;
668
669 let ExtractedRouteRequest::Unicast(ExtractedUnicastRouteRequest {
670 subnet,
671 outbound_interface,
672 next_hop,
673 priority,
674 table,
675 }) = extracted_request;
676
677 let outbound_interface = outbound_interface.map(NonZeroU64::get).ok_or_else(|| {
678 log_warn!(
681 "unsupported request: missing `RTA_OIF` in new route request from {}: {:?}",
682 client,
683 req
684 );
685 Errno::ENOTSUP
686 })?;
687
688 Ok(routes::RouteRequestArgs::New(routes::NewRouteArgs::Unicast(
689 routes::UnicastNewRouteArgs {
690 subnet,
691 target: fnet_routes_ext::RouteTarget { outbound_interface, next_hop },
692 priority,
693 table: table.into(),
694 },
695 )))
696 }
697
698 fn to_del_route_args<I: Ip>(
700 message: &RouteMessage,
701 client: &impl Display,
702 req: &RouteNetlinkMessage,
703 ) -> Result<routes::RouteRequestArgs<I>, Errno> {
704 let extracted_request =
705 extract_data_from_unicast_route_message::<I>(message, client, req, "del")?;
706
707 let ExtractedRouteRequest::Unicast(ExtractedUnicastRouteRequest {
708 subnet,
709 outbound_interface,
710 next_hop,
711 priority,
712 table,
713 }) = extracted_request;
714
715 Ok(routes::RouteRequestArgs::Del(routes::DelRouteArgs::Unicast(
716 routes::UnicastDelRouteArgs { subnet, outbound_interface, next_hop, priority, table },
717 )))
718 }
719
720 #[async_trait]
721 impl<S: Sender<RouteNetlinkMessage>> NetlinkFamilyRequestHandler<NetlinkRoute, S>
722 for NetlinkRouteRequestHandler<S>
723 {
724 async fn handle_request(
725 &mut self,
726 req: NetlinkMessage<RouteNetlinkMessage>,
727 client: &mut InternalClient<NetlinkRoute, S>,
728 ) {
729 let Self { unified_request_sink } = self;
730
731 let (req_header, payload) = req.into_parts();
732 let req = match payload {
733 NetlinkPayload::InnerMessage(p) => p,
734 p => {
735 log_warn!(
736 "Ignoring request from client {} with unexpected payload: {:?}",
737 client,
738 p
739 );
740 return;
741 }
742 };
743
744 let is_dump = req_header.flags & NLM_F_DUMP == NLM_F_DUMP;
745 let is_replace = req_header.flags & NLM_F_REPLACE == NLM_F_REPLACE;
746 let expects_ack = req_header.flags & NLM_F_ACK == NLM_F_ACK;
747
748 use RouteNetlinkMessage::*;
749 match req {
750 GetLink(link_msg) => {
751 let (completer, waiter) = oneshot::channel();
752 let args = match to_get_link_args(link_msg, is_dump) {
753 Ok(args) => args,
754 Err(e) => {
755 log_debug!("received invalid `GetLink` request from {}", client);
756 client.send_unicast(netlink_packet::new_error(Err(e), req_header));
757 return;
758 }
759 };
760 unified_request_sink.send(
761 UnifiedRequest::InterfacesRequest(
762 interfaces::Request{
763 args: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Get(args)),
764 sequence_number: req_header.sequence_number,
765 client: client.clone(),
766 completer,
767 })).await.expect("interface event loop should never terminate");
768 match waiter
769 .await
770 .expect("interfaces event loop should have handled the request") {
771 Ok(()) => if is_dump {
772 client.send_unicast(netlink_packet::new_done(req_header))
773 } else if expects_ack {
774 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
775 }
776 Err(e) => client.send_unicast(
777 netlink_packet::new_error(Err(e.into_errno()), req_header)),
778 }
779 }
780 SetLink(link_msg) => {
781 let args = match to_set_link_args(link_msg) {
782 Ok(args) => args,
783 Err(e) => {
784 log_debug!("received invalid `SetLink` request from {}", client);
785 client.send_unicast(netlink_packet::new_error(Err(e), req_header));
786 return;
787 }
788 };
789 let (completer, waiter) = oneshot::channel();
790 unified_request_sink.send(
791 UnifiedRequest::InterfacesRequest(
792 interfaces::Request{
793 args: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Set(args)),
794 sequence_number: req_header.sequence_number,
795 client: client.clone(),
796 completer,
797 })).await.expect("interface event loop should never terminate");
798 match waiter
799 .await
800 .expect("interfaces event loop should have handled the request") {
801 Ok(()) => if expects_ack {
802 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
803 }
804 Err(e) => client.send_unicast(
805 netlink_packet::new_error(Err(e.into_errno()), req_header)),
806 }
807 }
808 GetAddress(ref message) if is_dump => {
809 let ip_version_filter = match message.header.family() {
810 AddressFamily::Unspec => None,
811 AddressFamily::Inet => Some(IpVersion::V4),
812 AddressFamily::Inet6 => Some(IpVersion::V6),
813 family => {
814 log_debug!(
815 "invalid address family ({:?}) in address dump request from {}: {:?}",
816 family, client, req,
817 );
818 client.send_unicast(
819 netlink_packet::new_error(Err(Errno::EINVAL), req_header));
820 return;
821 }
822 };
823
824 let (completer, waiter) = oneshot::channel();
825 unified_request_sink.send(
826 UnifiedRequest::InterfacesRequest(
827 interfaces::Request {
828 args: interfaces::RequestArgs::Address(
829 interfaces::AddressRequestArgs::Get(
830 interfaces::GetAddressArgs::Dump {
831 ip_version_filter,
832 },
833 ),
834 ),
835 sequence_number: req_header.sequence_number,
836 client: client.clone(),
837 completer,
838 }
839 )).await.expect("interface event loop should never terminate");
840 waiter
841 .await
842 .expect("interfaces event loop should have handled the request")
843 .expect("addr dump requests are infallible");
844 client.send_unicast(netlink_packet::new_done(req_header))
845 }
846 NewAddress(ref message) => {
847 let extracted_request = match extract_if_id_and_addr_from_addr_message(
848 message,
849 client,
850 &req,
851 true,
852 ) {
853 Ok(o) => o,
854 Err(e) => {
855 return client.send_unicast(netlink_packet::new_error(Err(e), req_header));
856 }
857 };
858 let result = if let Some(ExtractedAddressRequest {
859 address_and_interface_id,
860 addr_flags,
861 }) = extracted_request {
862 let (completer, waiter) = oneshot::channel();
863 let requested_subnet_route =
864 addr_flags & IFA_F_NOPREFIXROUTE != IFA_F_NOPREFIXROUTE;
865 let can_add_subnet_route = match address_and_interface_id.address {
867 AddrSubnetEither::V4(addr_subnet) => {
868 let prefix = addr_subnet.subnet().prefix();
869 prefix != 0 && prefix != 32
870 }
871 AddrSubnetEither::V6(_addr_subnet) => true,
872 };
873 let add_subnet_route = requested_subnet_route && can_add_subnet_route;
874 unified_request_sink.send(UnifiedRequest::InterfacesRequest(
875 interfaces::Request {
876 args: interfaces::RequestArgs::Address(
877 interfaces::AddressRequestArgs::New(
878 interfaces::NewAddressArgs {
879 address_and_interface_id,
880 add_subnet_route,
881 },
882 ),
883 ),
884 sequence_number: req_header.sequence_number,
885 client: client.clone(),
886 completer,
887 })).await.expect("interface event loop should never terminate");
888 waiter
889 .await
890 .expect("interfaces event loop should have handled the request")
891 } else {
892 Ok(())
893 };
894
895 match result {
896 Ok(()) => if expects_ack {
897 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
898 },
899 Err(e) => client.send_unicast(
900 netlink_packet::new_error(Err(e.into_errno()), req_header)),
901 }
902 }
903 DelAddress(ref message) => {
904 let extracted_request = match extract_if_id_and_addr_from_addr_message(
905 message,
906 client,
907 &req,
908 false,
909 ) {
910 Ok(o) => o,
911 Err(e) => {
912 return client.send_unicast(netlink_packet::new_error(Err(e), req_header));
913 }
914 };
915
916 let result = if let Some(ExtractedAddressRequest {
917 address_and_interface_id,
918 addr_flags: _,
919 }) = extracted_request {
920 let (completer, waiter) = oneshot::channel();
921 unified_request_sink.send(UnifiedRequest::InterfacesRequest(
922 interfaces::Request {
923 args: interfaces::RequestArgs::Address(
924 interfaces::AddressRequestArgs::Del(
925 interfaces::DelAddressArgs {
926 address_and_interface_id,
927 },
928 ),
929 ),
930 sequence_number: req_header.sequence_number,
931 client: client.clone(),
932 completer,
933 })).await.expect("interface event loop should never terminate");
934 waiter
935 .await
936 .expect("interfaces event loop should have handled the request")
937 } else {
938 Ok(())
939 };
940 match result {
941 Ok(()) => if expects_ack {
942 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
943 },
944 Err(e) => client.send_unicast(
945 netlink_packet::new_error(Err(e.into_errno()), req_header))
946 }
947 }
948 GetRoute(ref message) if is_dump => {
949 match message.header.address_family {
950 AddressFamily::Unspec => {
951 process_routes_worker_request::<_, Ipv4>(
954 unified_request_sink,
955 client,
956 req_header,
957 routes::RouteRequestArgs::Get(
958 routes::GetRouteArgs::Dump,
959 ),
960 ).await
961 .expect("route dump requests are infallible");
962 process_routes_worker_request::<_, Ipv6>(
963 unified_request_sink,
964 client,
965 req_header,
966 routes::RouteRequestArgs::Get(
967 routes::GetRouteArgs::Dump,
968 ),
969 ).await
970 .expect("route dump requests are infallible");
971 },
972 AddressFamily::Inet => {
973 process_routes_worker_request::<_, Ipv4>(
974 unified_request_sink,
975 client,
976 req_header,
977 routes::RouteRequestArgs::Get(
978 routes::GetRouteArgs::Dump,
979 ),
980 ).await
981 .expect("route dump requests are infallible");
982 },
983 AddressFamily::Inet6 => {
984 process_routes_worker_request::<_, Ipv6>(
985 unified_request_sink,
986 client,
987 req_header,
988 routes::RouteRequestArgs::Get(
989 routes::GetRouteArgs::Dump,
990 ),
991 ).await
992 .expect("route dump requests are infallible");
993 },
994 family => {
995 log_debug!(
996 "invalid address family ({:?}) in route dump request from {}: {:?}",
997 family,
998 client,
999 req
1000 );
1001 client.send_unicast(
1002 netlink_packet::new_error(Err(Errno::EINVAL), req_header));
1003 return;
1004 }
1005 };
1006
1007 client.send_unicast(netlink_packet::new_done(req_header))
1008 }
1009 GetRule(msg) => {
1010 if !is_dump {
1011 client.send_unicast(
1012 netlink_packet::new_error(Err(Errno::ENOTSUP), req_header)
1013 );
1014 return;
1015 }
1016 let ip_versions = match msg.header.family {
1017 AddressFamily::Inet => Either::Left(std::iter::once(IpVersion::V4)),
1018 AddressFamily::Inet6 => Either::Left(std::iter::once(IpVersion::V6)),
1019 AddressFamily::Unspec => Either::Right([IpVersion::V4, IpVersion::V6].into_iter()),
1020 family => {
1021 client.send_unicast(
1022 netlink_packet::new_error(Err(Errno::EAFNOSUPPORT), req_header)
1023 );
1024 log_debug!("received RTM_GETRULE req from {} with invalid address \
1025 family ({:?}): {:?}", client, family, msg);
1026 return;
1027 }
1028 };
1029 for ip_version in ip_versions.into_iter() {
1030 let (completer, receiver) = oneshot::channel();
1031 net_types::for_any_ip_version!(ip_version, I, {
1032 unified_request_sink.send(
1033 UnifiedRequest::rule_request::<I>(RuleRequest {
1034 args: RuleRequestArgs::DumpRules,
1035 _ip_version_marker: <I as Ip>::VERSION_MARKER,
1036 sequence_number: req_header.sequence_number,
1037 client: client.clone(),
1038 },
1039 completer,
1040 )).await.expect("event loop should never terminate");
1041 });
1042
1043 match receiver.await.expect("completer should not be dropped") {
1044 Ok(()) => {},
1045 Err(e) => {
1046 client.send_unicast(netlink_packet::new_error(Err(e), req_header));
1047 return;
1048 }
1049 }
1050 }
1051 client.send_unicast(netlink_packet::new_done(req_header))
1052 }
1053 NewRule(msg) => {
1054 if is_replace {
1055 log_warn!("unimplemented: RTM_NEWRULE requests with NLM_F_REPLACE set.");
1056 client.send_unicast(
1057 netlink_packet::new_error(Err(Errno::ENOTSUP), req_header)
1058 );
1059 return;
1060 }
1061 let ip_version = match msg.header.family {
1062 AddressFamily::Inet => IpVersion::V4,
1063 AddressFamily::Inet6 => IpVersion::V6,
1064 family => {
1065 log_debug!("received RTM_NEWRULE req from {} with invalid address \
1066 family ({:?}): {:?}", client, family, msg);
1067 client.send_unicast(
1068 netlink_packet::new_error(Err(Errno::EAFNOSUPPORT), req_header)
1069 );
1070 return;
1071 }
1072 };
1073 let (completer, receiver) = oneshot::channel();
1074 net_types::for_any_ip_version!(ip_version, I, {
1075 let request = RuleRequest {
1076 args: RuleRequestArgs::New(msg),
1077 _ip_version_marker: <I as Ip>::VERSION_MARKER,
1078 sequence_number: req_header.sequence_number,
1079 client: client.clone(),
1080 };
1081 unified_request_sink.send(
1082 UnifiedRequest::rule_request::<I>(request, completer)
1083 ).await.expect("event loop should never terminate");
1084 });
1085 match receiver.await.expect("completer should not be dropped") {
1086 Ok(()) => if expects_ack {
1087 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1088 },
1089 Err(e) => {
1090 client.send_unicast(netlink_packet::new_error(Err(e), req_header));
1091 }
1092 }
1093 }
1094 DelRule(msg) => {
1095 let ip_version = match msg.header.family {
1096 AddressFamily::Inet => IpVersion::V4,
1097 AddressFamily::Inet6 => IpVersion::V6,
1098 family => {
1099 log_debug!("received RTM_DELRULE req from {} with invalid address \
1100 family ({:?}): {:?}", client, family, msg);
1101 client.send_unicast(
1102 netlink_packet::new_error(Err(Errno::EAFNOSUPPORT), req_header)
1103 );
1104 return;
1105 }
1106 };
1107 let (completer, receiver) = oneshot::channel();
1108 net_types::for_any_ip_version!(ip_version, I, {
1109 let request = RuleRequest {
1110 args: RuleRequestArgs::Del(msg),
1111 _ip_version_marker: <I as Ip>::VERSION_MARKER,
1112 sequence_number: req_header.sequence_number,
1113 client: client.clone(),
1114 };
1115 unified_request_sink.send(
1116 UnifiedRequest::rule_request::<I>(request, completer)
1117 ).await.expect("event loop should never terminate");
1118 });
1119 match receiver.await.expect("completer should not be dropped") {
1120 Ok(()) => if expects_ack {
1121 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1122 },
1123 Err(e) => {
1124 client.send_unicast(netlink_packet::new_error(Err(e), req_header));
1125 }
1126 }
1127 }
1128 NewRoute(ref message) => {
1129 let is_replace = req_header.flags & NLM_F_REPLACE == NLM_F_REPLACE;
1132 if is_replace {
1133 log_warn!("unsupported request type: NLM_F_REPLACE flag present in new \
1134 route request from {}: {:?}", client, req);
1135 client.send_unicast(
1136 netlink_packet::new_error(Err(Errno::ENOTSUP), req_header));
1137 return;
1138 }
1139
1140 if message.header.kind != RouteType::Unicast {
1141 log_warn!("unsupported request type: {:?} route present in new route \
1142 request from {}: {:?}, only `RTN_UNICAST` is supported",
1143 message.header.kind, client, req);
1144 client.send_unicast(
1145 netlink_packet::new_error(Err(Errno::ENOTSUP), req_header));
1146 return;
1147 }
1148
1149 let result = match message.header.address_family {
1150 AddressFamily::Inet => {
1151 match to_new_route_args::<Ipv4>(message, client, &req) {
1152 Ok(req) => {
1153 process_routes_worker_request::<_, Ipv4>(
1154 unified_request_sink,
1155 client,
1156 req_header,
1157 req,
1158 ).await
1159 },
1160 Err(e) => {
1161 return client.send_unicast(
1162 netlink_packet::new_error(Err(e), req_header)
1163 );
1164 }
1165 }
1166 },
1167 AddressFamily::Inet6 => {
1168 match to_new_route_args::<Ipv6>(message, client, &req) {
1169 Ok(req) => {
1170 process_routes_worker_request::<_, Ipv6>(
1171 unified_request_sink,
1172 client,
1173 req_header,
1174 req,
1175 ).await
1176 },
1177 Err(e) => {
1178 return client.send_unicast(
1179 netlink_packet::new_error(Err(e), req_header)
1180 );
1181 }
1182 }
1183 },
1184 family => {
1185 log_debug!("invalid address family ({:?}) in new route \
1186 request from {}: {:?}", family, client, req);
1187 return client.send_unicast(
1188 netlink_packet::new_error(Err(Errno::EINVAL), req_header)
1189 );
1190 }
1191 };
1192
1193 match result {
1194 Ok(()) => if expects_ack {
1195 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1196 },
1197 Err(e) => client.send_unicast(
1198 netlink_packet::new_error(Err(e.into_errno()), req_header)),
1199 }
1200 }
1201 DelRoute(ref message) => {
1202 if message.header.kind != RouteType::Unicast {
1203 log_warn!("unsupported request type: {:?} route present in new route \
1204 request from {}: {:?}, only `RTN_UNICAST` is supported",
1205 message.header.kind, client, req);
1206 client.send_unicast(
1207 netlink_packet::new_error(Err(Errno::ENOTSUP), req_header));
1208 return;
1209 }
1210
1211 let result = match message.header.address_family {
1212 AddressFamily::Inet => match to_del_route_args::<Ipv4>(message, client, &req) {
1213 Ok(req) => {
1214 process_routes_worker_request::<_, Ipv4>(
1215 unified_request_sink,
1216 client,
1217 req_header,
1218 req,
1219 ).await
1220 },
1221 Err(e) => {
1222 return client.send_unicast(
1223 netlink_packet::new_error(Err(e), req_header)
1224 );
1225 }
1226 },
1227 AddressFamily::Inet6 => match to_del_route_args::<Ipv6>(message, client, &req) {
1228 Ok(req) => {
1229 process_routes_worker_request::<_, Ipv6>(
1230 unified_request_sink,
1231 client,
1232 req_header,
1233 req,
1234 ).await
1235 },
1236 Err(e) => {
1237 return client.send_unicast(
1238 netlink_packet::new_error(Err(e), req_header)
1239 );
1240 }
1241 },
1242 family => {
1243 log_debug!("invalid address family ({:?}) in new route \
1244 request from {}: {:?}", family, client, req);
1245 return client.send_unicast(
1246 netlink_packet::new_error(Err(Errno::EINVAL), req_header)
1247 );
1248 }
1249 };
1250
1251 match result {
1252 Ok(()) => if expects_ack {
1253 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1254 },
1255 Err(e) => client.send_unicast(
1256 netlink_packet::new_error(Err(e.into_errno()), req_header)
1257 ),
1258 }
1259 }
1260 NewLink(_)
1261 | DelLink(_)
1262 | NewLinkProp(_)
1263 | DelLinkProp(_)
1264 | NewNeighbourTable(_)
1265 | SetNeighbourTable(_)
1266 | NewTrafficClass(_)
1267 | DelTrafficClass(_)
1268 | NewTrafficFilter(_)
1269 | DelTrafficFilter(_)
1270 | NewTrafficChain(_)
1271 | DelTrafficChain(_)
1272 | NewNsId(_)
1273 | DelNsId(_)
1274 | NewNeighbourDiscoveryUserOption(_)
1275 | NewPrefix(_)
1276 | NewNeighbour(_)
1278 | DelNeighbour(_)
1280 | NewQueueDiscipline(_)
1282 | DelQueueDiscipline(_) => {
1284 if expects_ack {
1285 log_warn!(
1286 "Received unsupported NETLINK_ROUTE request; responding with an Ack: {:?}",
1287 req,
1288 );
1289 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1290 } else {
1291 log_warn!(
1292 "Received unsupported NETLINK_ROUTE request that does not expect an Ack: {:?}",
1293 req,
1294 )
1295 }
1296 }
1297 GetNeighbourTable(_)
1298 | GetTrafficClass(_)
1299 | GetTrafficFilter(_)
1300 | GetTrafficChain(_)
1301 | GetNsId(_)
1302 | GetNeighbour(_)
1304 | GetAddress(_)
1306 | GetRoute(_)
1308 | GetQueueDiscipline(_) => {
1310 if is_dump {
1311 log_warn!(
1312 "Received unsupported NETLINK_ROUTE DUMP request; responding with Done: {:?}",
1313 req
1314 );
1315 client.send_unicast(netlink_packet::new_done(req_header))
1316 } else if expects_ack {
1317 log_warn!(
1318 "Received unsupported NETLINK_ROUTE GET request: responding with Ack {:?}",
1319 req
1320 );
1321 client.send_unicast(netlink_packet::new_error(Ok(()), req_header))
1322 } else {
1323 log_warn!(
1324 "Received unsupported NETLINK_ROUTE GET request that does not expect an Ack {:?}",
1325 req
1326 )
1327 }
1328 },
1329 }
1330 }
1331 }
1332
1333 async fn process_routes_worker_request<S: Sender<RouteNetlinkMessage>, I: Ip>(
1335 sink: &mut mpsc::Sender<UnifiedRequest<S>>,
1336 client: &mut InternalClient<NetlinkRoute, S>,
1337 req_header: NetlinkHeader,
1338 route_request: routes::RouteRequestArgs<I>,
1339 ) -> Result<(), routes::RequestError> {
1340 let (completer, waiter) = oneshot::channel();
1341 let request = routes::Request {
1342 args: routes::RequestArgs::Route(route_request),
1343 sequence_number: req_header.sequence_number,
1344 client: client.clone(),
1345 completer,
1346 };
1347 let fut = I::map_ip_in(
1348 (request, IpInvariant(sink)),
1349 |(request, IpInvariant(sink))| sink.send(UnifiedRequest::RoutesV4Request(request)),
1350 |(request, IpInvariant(sink))| sink.send(UnifiedRequest::RoutesV6Request(request)),
1351 );
1352 fut.await.expect("route event loop should never terminate");
1353 waiter.await.expect("routes event loop should have handled the request")
1354 }
1355
1356 pub struct NetlinkRouteClient(pub(crate) ExternalClient<NetlinkRoute>);
1358
1359 impl NetlinkClient for NetlinkRouteClient {
1360 type Request = RouteNetlinkMessage;
1361
1362 fn set_pid(&self, pid: NonZeroU32) {
1363 let NetlinkRouteClient(client) = self;
1364 client.set_port_number(pid)
1365 }
1366
1367 fn add_membership(
1368 &self,
1369 group: ModernGroup,
1370 ) -> Result<AsyncWorkCompletionWaiter, InvalidModernGroupError> {
1371 let NetlinkRouteClient(client) = self;
1372 client.add_membership(group)
1373 }
1374
1375 fn del_membership(&self, group: ModernGroup) -> Result<(), InvalidModernGroupError> {
1376 let NetlinkRouteClient(client) = self;
1377 client.del_membership(group)
1378 }
1379
1380 fn set_legacy_memberships(
1381 &self,
1382 legacy_memberships: LegacyGroups,
1383 ) -> Result<AsyncWorkCompletionWaiter, InvalidLegacyGroupsError> {
1384 let NetlinkRouteClient(client) = self;
1385 client.set_legacy_memberships(legacy_memberships)
1386 }
1387 }
1388}
1389
1390#[cfg(test)]
1391pub(crate) mod testutil {
1392 use super::*;
1393
1394 use std::convert::Infallible as Never;
1395
1396 use crate::messaging::testutil::FakeCreds;
1397 use crate::messaging::{NetlinkMessageWithCreds, Permission};
1398 use netlink_packet_core::NetlinkHeader;
1399
1400 pub(crate) const LEGACY_GROUP1: u32 = 0x00000001;
1401 pub(crate) const LEGACY_GROUP2: u32 = 0x00000002;
1402 pub(crate) const LEGACY_GROUP3: u32 = 0x00000004;
1403 pub(crate) const INVALID_LEGACY_GROUP: u32 = 0x00000008;
1404 pub(crate) const MODERN_GROUP1: ModernGroup = ModernGroup(1);
1405 pub(crate) const MODERN_GROUP2: ModernGroup = ModernGroup(2);
1406 pub(crate) const MODERN_GROUP3: ModernGroup = ModernGroup(3);
1407 pub(crate) const INVALID_MODERN_GROUP: ModernGroup = ModernGroup(4);
1408 pub(crate) const MODERN_GROUP_NEEDS_BLOCKING: ModernGroup = ModernGroup(5);
1409 pub(crate) const AF_PACKET: u16 = 17;
1411
1412 #[derive(Debug)]
1413 pub(crate) enum FakeProtocolFamily {}
1414
1415 impl MulticastCapableNetlinkFamily for FakeProtocolFamily {
1416 fn is_valid_group(group: &ModernGroup) -> bool {
1417 match *group {
1418 MODERN_GROUP1 | MODERN_GROUP2 | MODERN_GROUP3 | MODERN_GROUP_NEEDS_BLOCKING => true,
1419 _ => false,
1420 }
1421 }
1422 }
1423
1424 pub(crate) fn new_fake_netlink_message() -> NetlinkMessage<FakeNetlinkInnerMessage> {
1425 NetlinkMessage::new(
1426 NetlinkHeader::default(),
1427 NetlinkPayload::InnerMessage(FakeNetlinkInnerMessage),
1428 )
1429 }
1430
1431 pub(crate) fn new_fake_netlink_message_with_creds()
1432 -> NetlinkMessageWithCreds<NetlinkMessage<FakeNetlinkInnerMessage>, FakeCreds> {
1433 NetlinkMessageWithCreds::new(new_fake_netlink_message(), FakeCreds::default())
1434 }
1435
1436 #[derive(Clone, Debug, Default, PartialEq)]
1437 pub(crate) struct FakeNetlinkInnerMessage;
1438
1439 impl MessageWithPermission for FakeNetlinkInnerMessage {
1440 fn permission(&self) -> Permission {
1441 Permission::NetlinkRouteWrite
1442 }
1443 }
1444
1445 impl NetlinkSerializable for FakeNetlinkInnerMessage {
1446 fn message_type(&self) -> u16 {
1447 u16::MAX
1448 }
1449
1450 fn buffer_len(&self) -> usize {
1451 0
1452 }
1453
1454 fn serialize(&self, _buffer: &mut [u8]) {}
1455 }
1456
1457 impl NetlinkDeserializable for FakeNetlinkInnerMessage {
1458 type Error = DecodeError;
1459
1460 fn deserialize(_header: &NetlinkHeader, _payload: &[u8]) -> Result<Self, Self::Error> {
1461 unimplemented!()
1462 }
1463 }
1464
1465 #[derive(Clone)]
1469 pub(crate) struct FakeNetlinkRequestHandler;
1470
1471 #[async_trait]
1472 impl<S: Sender<FakeNetlinkInnerMessage>> NetlinkFamilyRequestHandler<FakeProtocolFamily, S>
1473 for FakeNetlinkRequestHandler
1474 {
1475 async fn handle_request(
1476 &mut self,
1477 req: NetlinkMessage<FakeNetlinkInnerMessage>,
1478 client: &mut InternalClient<FakeProtocolFamily, S>,
1479 ) {
1480 client.send_unicast(req)
1481 }
1482 }
1483
1484 impl ProtocolFamily for FakeProtocolFamily {
1485 type Request = FakeNetlinkInnerMessage;
1486 type Response = FakeNetlinkInnerMessage;
1487 type RequestHandler<S: Sender<Self::Response>> = FakeNetlinkRequestHandler;
1488 type NotifiedMulticastGroup = ();
1489 type AsyncWorkItem = Never;
1490
1491 const NAME: &'static str = "FAKE_PROTOCOL_FAMILY";
1492 fn should_notify_on_group_membership_change(
1493 group: ModernGroup,
1494 ) -> Option<Self::NotifiedMulticastGroup> {
1495 (group == MODERN_GROUP_NEEDS_BLOCKING).then_some(())
1496 }
1497 }
1498}
1499
1500#[cfg(test)]
1501mod test {
1502 use super::*;
1503
1504 use fuchsia_sync::Mutex;
1505 use std::collections::VecDeque;
1506 use std::net::IpAddr;
1507 use std::num::{NonZeroU32, NonZeroU64};
1508 use std::pin::pin;
1509 use std::sync::Arc;
1510
1511 use fidl_fuchsia_net_routes_ext as fnet_routes_ext;
1512
1513 use assert_matches::assert_matches;
1514 use fuchsia_async as fasync;
1515 use futures::SinkExt;
1516 use futures::channel::mpsc;
1517 use futures::future::FutureExt as _;
1518 use futures::stream::StreamExt as _;
1519 use linux_uapi::{
1520 AF_INET, AF_INET6, AF_UNSPEC, IFA_F_NOPREFIXROUTE, RTN_MULTICAST, RTN_UNICAST,
1521 net_device_flags_IFF_UP, rt_class_t_RT_TABLE_COMPAT, rt_class_t_RT_TABLE_MAIN,
1522 };
1523 use net_declare::{net_addr_subnet, net_ip_v4, net_ip_v6, net_subnet_v4, net_subnet_v6};
1524 use net_types::ip::{
1525 AddrSubnetEither, GenericOverIp, Ip, IpVersion, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Subnet,
1526 };
1527 use net_types::{SpecifiedAddr, Witness as _};
1528 use netlink_packet_core::{NLM_F_ACK, NLM_F_DUMP, NLM_F_REPLACE, NetlinkHeader};
1529 use netlink_packet_route::address::{AddressAttribute, AddressFlags, AddressMessage};
1530 use netlink_packet_route::link::{LinkAttribute, LinkFlags, LinkMessage};
1531 use netlink_packet_route::neighbour_discovery_user_option::{
1532 NeighbourDiscoveryIcmpType, NeighbourDiscoveryIcmpV6Type,
1533 NeighbourDiscoveryUserOptionHeader, NeighbourDiscoveryUserOptionMessage,
1534 };
1535 use netlink_packet_route::route::{RouteAddress, RouteAttribute, RouteMessage, RouteType};
1536 use netlink_packet_route::rule::RuleMessage;
1537 use netlink_packet_route::{AddressFamily, RouteNetlinkMessage};
1538 use test::testutil::AF_PACKET;
1539 use test_case::test_case;
1540
1541 use crate::messaging::testutil::{FakeSender, SentMessage};
1542 use crate::netlink_packet::errno::Errno;
1543 use crate::netlink_packet::{self};
1544 use crate::protocol_family::route::{NetlinkRoute, NetlinkRouteRequestHandler};
1545 use crate::route_eventloop::UnifiedRequest;
1546 use crate::rules::{RuleRequest, RuleRequestArgs};
1547 use crate::{interfaces, routes};
1548
1549 enum ExpectedResponse {
1550 Ack,
1551 Error(Errno),
1552 Done,
1553 }
1554
1555 fn header_with_flags(flags: u16) -> NetlinkHeader {
1556 let mut header = NetlinkHeader::default();
1557 header.flags = flags;
1558 header
1559 }
1560
1561 fn neighbour_discovery_user_option_msg() -> NeighbourDiscoveryUserOptionMessage {
1562 NeighbourDiscoveryUserOptionMessage::new(
1563 NeighbourDiscoveryUserOptionHeader::new(
1564 0,
1565 NeighbourDiscoveryIcmpType::Inet6(
1566 NeighbourDiscoveryIcmpV6Type::NeighbourAdvertisement,
1567 ),
1568 ),
1569 Default::default(),
1570 Default::default(),
1571 )
1572 }
1573
1574 #[test_case(
1581 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1582 0,
1583 None; "get_tc__with_no_flags")]
1584 #[test_case(
1585 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1586 NLM_F_ACK,
1587 Some(ExpectedResponse::Ack); "get_tc_with_ack_flag")]
1588 #[test_case(
1589 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1590 NLM_F_DUMP,
1591 Some(ExpectedResponse::Done); "get_tc_with_dump_flag")]
1592 #[test_case(
1593 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1594 NLM_F_ACK | NLM_F_DUMP,
1595 Some(ExpectedResponse::Done); "get_tc_with_ack_and_dump_flag")]
1596 #[test_case(
1597 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1598 0,
1599 None; "new_tc_with_no_flags")]
1600 #[test_case(
1601 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1602 NLM_F_DUMP,
1603 None; "new_tc_with_dump_flag")]
1604 #[test_case(
1605 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1606 NLM_F_ACK,
1607 Some(ExpectedResponse::Ack); "new_tc_with_ack_flag")]
1608 #[test_case(
1609 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1610 NLM_F_ACK | NLM_F_DUMP,
1611 Some(ExpectedResponse::Ack); "new_tc_with_ack_and_dump_flags")]
1612 #[test_case(
1613 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1614 0,
1615 None; "deltc_with_no_flags")]
1616 #[test_case(
1617 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1618 NLM_F_DUMP,
1619 None; "del_tc_with_dump_flag")]
1620 #[test_case(
1621 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1622 NLM_F_ACK,
1623 Some(ExpectedResponse::Ack); "del_tc_with_ack_flag")]
1624 #[test_case(
1625 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1626 NLM_F_ACK | NLM_F_DUMP,
1627 Some(ExpectedResponse::Ack); "del_tc_with_ack_and_dump_flags")]
1628 #[test_case(
1629 RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(neighbour_discovery_user_option_msg()),
1630 NLM_F_ACK,
1631 Some(ExpectedResponse::Ack); "new_neighbour_user_option_with_ack_flag")]
1632 #[test_case(
1633 RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(neighbour_discovery_user_option_msg()),
1634 0,
1635 None; "new_neighbour_user_option_no_flags")]
1636 #[test_case(
1637 RouteNetlinkMessage::NewPrefix(Default::default()),
1638 NLM_F_ACK,
1639 Some(ExpectedResponse::Ack); "new_prefix_with_ack_flag")]
1640 #[test_case(
1641 RouteNetlinkMessage::NewPrefix(Default::default()),
1642 0,
1643 None; "new_prefix_no_flags")]
1644 #[fuchsia::test]
1645 async fn test_handle_unsupported_request_response(
1646 inner_message: RouteNetlinkMessage,
1647 flags: u16,
1648 expected_response: Option<ExpectedResponse>,
1649 ) {
1650 let (unified_request_sink, _unified_request_stream) = mpsc::channel(0);
1651
1652 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
1653
1654 let (mut client_sink, mut client, async_work_drain_task) =
1655 crate::client::testutil::new_fake_client::<NetlinkRoute>(
1656 crate::client::testutil::CLIENT_ID_1,
1657 std::iter::empty(),
1658 );
1659 let join_handle = fasync::Task::spawn(async_work_drain_task);
1660
1661 let header = header_with_flags(flags);
1662
1663 handler
1664 .handle_request(
1665 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(inner_message)),
1666 &mut client,
1667 )
1668 .await;
1669
1670 match expected_response {
1671 Some(ExpectedResponse::Ack) => {
1672 assert_eq!(
1673 client_sink.take_messages(),
1674 [SentMessage::unicast(netlink_packet::new_error(Ok(()), header))]
1675 )
1676 }
1677 Some(ExpectedResponse::Error(e)) => {
1678 assert_eq!(
1679 client_sink.take_messages(),
1680 [SentMessage::unicast(netlink_packet::new_error(Err(e), header))]
1681 )
1682 }
1683 Some(ExpectedResponse::Done) => {
1684 assert_eq!(
1685 client_sink.take_messages(),
1686 [SentMessage::unicast(netlink_packet::new_done(header))]
1687 )
1688 }
1689 None => {
1690 assert_eq!(client_sink.take_messages(), [])
1691 }
1692 }
1693 drop(client);
1694 join_handle.await;
1695 }
1696
1697 struct RequestAndResponse<R> {
1698 request: R,
1699 response: Result<(), interfaces::RequestError>,
1700 }
1701
1702 async fn test_request(
1703 request: NetlinkMessage<RouteNetlinkMessage>,
1704 req_and_resp: Option<RequestAndResponse<interfaces::RequestArgs>>,
1705 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
1706 let (mut client_sink, mut client, async_work_drain_task) =
1707 crate::client::testutil::new_fake_client::<NetlinkRoute>(
1708 crate::client::testutil::CLIENT_ID_1,
1709 std::iter::empty(),
1710 );
1711 let join_handle = fasync::Task::spawn(async_work_drain_task);
1712
1713 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
1714 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
1715
1716 let mut interfaces_request_stream = unified_request_stream.filter_map(|req| {
1717 futures::future::ready(match req {
1718 UnifiedRequest::InterfacesRequest(req) => Some(req),
1719 _ => None,
1720 })
1721 });
1722
1723 let ((), ()) = futures::future::join(handler.handle_request(request, &mut client), async {
1724 let next = interfaces_request_stream.next();
1725 match req_and_resp {
1726 Some(RequestAndResponse { request, response }) => {
1727 let interfaces::Request { args, sequence_number: _, client: _, completer } =
1728 next.await.expect("handler should send request");
1729 assert_eq!(args, request);
1730 completer.send(response).expect("handler should be alive");
1731 }
1732 None => assert_matches!(next.now_or_never(), None),
1733 }
1734 })
1735 .await;
1736
1737 drop(client);
1738 join_handle.await;
1739 client_sink.take_messages()
1740 }
1741
1742 const FAKE_INTERFACE_ID: u32 = 1;
1743 const FAKE_INTERFACE_NAME: &str = "interface";
1744
1745 #[test_case(
1747 0,
1748 0,
1749 None,
1750 None,
1751 Ok(()),
1752 Some(ExpectedResponse::Error(Errno::EINVAL)); "no_specifiers")]
1753 #[test_case(
1754 NLM_F_DUMP,
1755 0,
1756 None,
1757 Some(interfaces::GetLinkArgs::Dump),
1758 Ok(()),
1759 Some(ExpectedResponse::Done); "dump")]
1760 #[test_case(
1761 NLM_F_DUMP | NLM_F_ACK,
1762 0,
1763 None,
1764 Some(interfaces::GetLinkArgs::Dump),
1765 Ok(()),
1766 Some(ExpectedResponse::Done); "dump_with_ack")]
1767 #[test_case(
1768 NLM_F_DUMP,
1769 FAKE_INTERFACE_ID,
1770 None,
1771 Some(interfaces::GetLinkArgs::Dump),
1772 Ok(()),
1773 Some(ExpectedResponse::Done); "dump_with_id")]
1774 #[test_case(
1775 NLM_F_DUMP,
1776 FAKE_INTERFACE_ID,
1777 Some(FAKE_INTERFACE_NAME),
1778 Some(interfaces::GetLinkArgs::Dump),
1779 Ok(()),
1780 Some(ExpectedResponse::Done); "dump_with_id_and_name")]
1781 #[test_case(
1782 0,
1783 FAKE_INTERFACE_ID,
1784 None,
1785 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
1786 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
1787 Ok(()),
1788 None; "id")]
1789 #[test_case(
1790 NLM_F_ACK,
1791 FAKE_INTERFACE_ID,
1792 None,
1793 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
1794 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
1795 Ok(()),
1796 Some(ExpectedResponse::Ack); "id_with_ack")]
1797 #[test_case(
1798 0,
1799 FAKE_INTERFACE_ID,
1800 Some(FAKE_INTERFACE_NAME),
1801 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
1802 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
1803 Ok(()),
1804 None; "id_with_name")]
1805 #[test_case(
1806 0,
1807 0,
1808 Some(FAKE_INTERFACE_NAME),
1809 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
1810 FAKE_INTERFACE_NAME.to_string()))),
1811 Ok(()),
1812 None; "name")]
1813 #[test_case(
1814 NLM_F_ACK,
1815 0,
1816 Some(FAKE_INTERFACE_NAME),
1817 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
1818 FAKE_INTERFACE_NAME.to_string()))),
1819 Ok(()),
1820 Some(ExpectedResponse::Ack); "name_with_ack")]
1821 #[test_case(
1822 0,
1823 FAKE_INTERFACE_ID,
1824 None,
1825 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
1826 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
1827 Err(interfaces::RequestError::UnrecognizedInterface),
1828 Some(ExpectedResponse::Error(Errno::ENODEV)); "id_not_found")]
1829 #[test_case(
1830 0,
1831 0,
1832 Some(FAKE_INTERFACE_NAME),
1833 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
1834 FAKE_INTERFACE_NAME.to_string()))),
1835 Err(interfaces::RequestError::UnrecognizedInterface),
1836 Some(ExpectedResponse::Error(Errno::ENODEV)); "name_not_found")]
1837 #[fuchsia::test]
1838 async fn test_get_link(
1839 flags: u16,
1840 link_id: u32,
1841 link_name: Option<&str>,
1842 expected_request_args: Option<interfaces::GetLinkArgs>,
1843 interfaces_worker_result: Result<(), interfaces::RequestError>,
1844 expected_response: Option<ExpectedResponse>,
1845 ) {
1846 let header = header_with_flags(flags);
1847 let mut link_message = LinkMessage::default();
1848 link_message.header.index = link_id;
1849 link_message.attributes =
1850 link_name.map(|n| LinkAttribute::IfName(n.to_string())).into_iter().collect();
1851
1852 pretty_assertions::assert_eq!(
1853 test_request(
1854 NetlinkMessage::new(
1855 header,
1856 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetLink(link_message)),
1857 ),
1858 expected_request_args.map(|a| RequestAndResponse {
1859 request: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Get(a)),
1860 response: interfaces_worker_result,
1861 }),
1862 )
1863 .await,
1864 expected_response
1865 .into_iter()
1866 .map(|expected_response| {
1867 SentMessage::unicast(match expected_response {
1868 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
1869 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
1870 ExpectedResponse::Done => netlink_packet::new_done(header),
1871 })
1872 })
1873 .collect::<Vec<_>>(),
1874 )
1875 }
1876
1877 #[test_case(
1878 0,
1879 0,
1880 None,
1881 0,
1882 0,
1883 None,
1884 Ok(()),
1885 Some(ExpectedResponse::Error(Errno::EINVAL)); "interface_not_specified")]
1886 #[test_case(
1887 0,
1888 FAKE_INTERFACE_ID,
1889 Some(FAKE_INTERFACE_NAME),
1890 0,
1891 0,
1892 None,
1893 Ok(()),
1894 Some(ExpectedResponse::Error(Errno::EBUSY)); "name_and_id")]
1895 #[test_case(
1896 0,
1897 FAKE_INTERFACE_ID,
1898 None,
1899 0,
1900 0,
1901 Some(interfaces::SetLinkArgs{
1902 link: interfaces::LinkSpecifier::Index(NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()),
1903 enable: None,
1904 }),
1905 Ok(()),
1906 None; "no_change_by_id")]
1907 #[test_case(
1908 0,
1909 0,
1910 Some(FAKE_INTERFACE_NAME),
1911 0,
1912 0,
1913 Some(interfaces::SetLinkArgs{
1914 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1915 enable: None,
1916 }),
1917 Ok(()),
1918 None; "no_change_by_name")]
1919 #[test_case(
1920 NLM_F_ACK,
1921 0,
1922 Some(FAKE_INTERFACE_NAME),
1923 0,
1924 0,
1925 Some(interfaces::SetLinkArgs{
1926 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1927 enable: None,
1928 }),
1929 Ok(()),
1930 Some(ExpectedResponse::Ack); "no_change_ack")]
1931 #[test_case(
1932 0,
1933 0,
1934 Some(FAKE_INTERFACE_NAME),
1935 net_device_flags_IFF_UP,
1936 net_device_flags_IFF_UP,
1937 Some(interfaces::SetLinkArgs{
1938 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1939 enable: Some(true),
1940 }),
1941 Ok(()),
1942 None; "enable")]
1943 #[test_case(
1944 NLM_F_ACK,
1945 0,
1946 Some(FAKE_INTERFACE_NAME),
1947 net_device_flags_IFF_UP,
1948 net_device_flags_IFF_UP,
1949 Some(interfaces::SetLinkArgs{
1950 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1951 enable: Some(true),
1952 }),
1953 Ok(()),
1954 Some(ExpectedResponse::Ack); "enable_ack")]
1955 #[test_case(
1956 NLM_F_ACK,
1957 0,
1958 Some(FAKE_INTERFACE_NAME),
1959 net_device_flags_IFF_UP,
1960 net_device_flags_IFF_UP,
1961 Some(interfaces::SetLinkArgs{
1962 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1963 enable: Some(true),
1964 }),
1965 Err(interfaces::RequestError::UnrecognizedInterface),
1966 Some(ExpectedResponse::Error(Errno::ENODEV)); "enable_error")]
1967 #[test_case(
1968 0,
1969 0,
1970 Some(FAKE_INTERFACE_NAME),
1971 0,
1972 net_device_flags_IFF_UP,
1973 Some(interfaces::SetLinkArgs{
1974 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1975 enable: Some(false),
1976 }),
1977 Ok(()),
1978 None; "disable")]
1979 #[test_case(
1980 NLM_F_ACK,
1981 0,
1982 Some(FAKE_INTERFACE_NAME),
1983 0,
1984 net_device_flags_IFF_UP,
1985 Some(interfaces::SetLinkArgs{
1986 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1987 enable: Some(false),
1988 }),
1989 Ok(()),
1990 Some(ExpectedResponse::Ack); "disable_ack")]
1991 #[test_case(
1992 NLM_F_ACK,
1993 0,
1994 Some(FAKE_INTERFACE_NAME),
1995 0,
1996 net_device_flags_IFF_UP,
1997 Some(interfaces::SetLinkArgs{
1998 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
1999 enable: Some(false),
2000 }),
2001 Err(interfaces::RequestError::UnrecognizedInterface),
2002 Some(ExpectedResponse::Error(Errno::ENODEV)); "disable_error")]
2003 #[fuchsia::test]
2004 async fn test_set_link(
2005 flags: u16,
2006 link_id: u32,
2007 link_name: Option<&str>,
2008 link_flags: u32,
2009 change_mask: u32,
2010 expected_request_args: Option<interfaces::SetLinkArgs>,
2011 interfaces_worker_result: Result<(), interfaces::RequestError>,
2012 expected_response: Option<ExpectedResponse>,
2013 ) {
2014 let header = header_with_flags(flags);
2015 let mut link_message = LinkMessage::default();
2016 link_message.header.index = link_id;
2017 link_message.header.flags = LinkFlags::from_bits(link_flags).unwrap();
2018 link_message.header.change_mask = LinkFlags::from_bits(change_mask).unwrap();
2019 link_message.attributes =
2020 link_name.map(|n| LinkAttribute::IfName(n.to_string())).into_iter().collect();
2021
2022 pretty_assertions::assert_eq!(
2023 test_request(
2024 NetlinkMessage::new(
2025 header,
2026 NetlinkPayload::InnerMessage(RouteNetlinkMessage::SetLink(link_message)),
2027 ),
2028 expected_request_args.map(|a| RequestAndResponse {
2029 request: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Set(a)),
2030 response: interfaces_worker_result,
2031 }),
2032 )
2033 .await,
2034 expected_response
2035 .into_iter()
2036 .map(|expected_response| {
2037 SentMessage::unicast(match expected_response {
2038 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
2039 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
2040 ExpectedResponse::Done => netlink_packet::new_done(header),
2041 })
2042 })
2043 .collect::<Vec<_>>(),
2044 )
2045 }
2046
2047 #[test_case(
2050 0,
2051 AF_UNSPEC,
2052 None,
2053 None; "af_unspec_no_flags")]
2054 #[test_case(
2055 NLM_F_ACK,
2056 AF_UNSPEC,
2057 None,
2058 Some(ExpectedResponse::Ack); "af_unspec_ack_flag")]
2059 #[test_case(
2060 NLM_F_DUMP,
2061 AF_UNSPEC,
2062 Some(interfaces::GetAddressArgs::Dump {
2063 ip_version_filter: None,
2064 }),
2065 Some(ExpectedResponse::Done); "af_unspec_dump_flag")]
2066 #[test_case(
2067 NLM_F_DUMP | NLM_F_ACK,
2068 AF_UNSPEC,
2069 Some(interfaces::GetAddressArgs::Dump {
2070 ip_version_filter: None,
2071 }),
2072 Some(ExpectedResponse::Done); "af_unspec_dump_and_ack_flags")]
2073 #[test_case(
2074 0,
2075 AF_INET,
2076 None,
2077 None; "af_inet_no_flags")]
2078 #[test_case(
2079 NLM_F_ACK,
2080 AF_INET,
2081 None,
2082 Some(ExpectedResponse::Ack); "af_inet_ack_flag")]
2083 #[test_case(
2084 NLM_F_DUMP,
2085 AF_INET,
2086 Some(interfaces::GetAddressArgs::Dump {
2087 ip_version_filter: Some(IpVersion::V4),
2088 }),
2089 Some(ExpectedResponse::Done); "af_inet_dump_flag")]
2090 #[test_case(
2091 NLM_F_DUMP | NLM_F_ACK,
2092 AF_INET,
2093 Some(interfaces::GetAddressArgs::Dump {
2094 ip_version_filter: Some(IpVersion::V4),
2095 }),
2096 Some(ExpectedResponse::Done); "af_inet_dump_and_ack_flags")]
2097 #[test_case(
2098 0,
2099 AF_INET6,
2100 None,
2101 None; "af_inet6_no_flags")]
2102 #[test_case(
2103 NLM_F_ACK,
2104 AF_INET6,
2105 None,
2106 Some(ExpectedResponse::Ack); "af_inet6_ack_flag")]
2107 #[test_case(
2108 NLM_F_DUMP,
2109 AF_INET6,
2110 Some(interfaces::GetAddressArgs::Dump {
2111 ip_version_filter: Some(IpVersion::V6),
2112 }),
2113 Some(ExpectedResponse::Done); "af_inet6_dump_flag")]
2114 #[test_case(
2115 NLM_F_DUMP | NLM_F_ACK,
2116 AF_INET6,
2117 Some(interfaces::GetAddressArgs::Dump {
2118 ip_version_filter: Some(IpVersion::V6),
2119 }),
2120 Some(ExpectedResponse::Done); "af_inet6_dump_and_ack_flags")]
2121 #[test_case(
2122 0,
2123 AF_PACKET.into(),
2124 None,
2125 None; "af_other_no_flags")]
2126 #[test_case(
2127 NLM_F_ACK,
2128 AF_PACKET.into(),
2129 None,
2130 Some(ExpectedResponse::Ack); "af_other_ack_flag")]
2131 #[test_case(
2132 NLM_F_DUMP,
2133 AF_PACKET.into(),
2134 None,
2135 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_flag")]
2136 #[test_case(
2137 NLM_F_DUMP | NLM_F_ACK,
2138 AF_PACKET.into(),
2139 None,
2140 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_and_ack_flags")]
2141 #[fuchsia::test]
2142 async fn test_get_addr(
2143 flags: u16,
2144 family: u32,
2145 expected_request_args: Option<interfaces::GetAddressArgs>,
2146 expected_response: Option<ExpectedResponse>,
2147 ) {
2148 let family = family as u16;
2150 let header = header_with_flags(flags);
2151 let address_message = {
2152 let mut message = AddressMessage::default();
2153 message.header.family = AddressFamily::from(family as u8).into();
2155 message
2156 };
2157
2158 pretty_assertions::assert_eq!(
2159 test_request(
2160 NetlinkMessage::new(
2161 header,
2162 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetAddress(address_message)),
2163 ),
2164 expected_request_args.map(|a| RequestAndResponse {
2165 request: interfaces::RequestArgs::Address(interfaces::AddressRequestArgs::Get(
2166 a
2167 )),
2168 response: Ok(()),
2169 }),
2170 )
2171 .await,
2172 expected_response
2173 .into_iter()
2174 .map(|expected_response| SentMessage::unicast(match expected_response {
2175 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
2176 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
2177 ExpectedResponse::Done => netlink_packet::new_done(header),
2178 }))
2179 .collect::<Vec<_>>(),
2180 )
2181 }
2182
2183 enum AddressRequestKind {
2184 New { add_subnet_route: bool },
2185 Del,
2186 }
2187
2188 struct TestAddrCase {
2189 kind: AddressRequestKind,
2190 flags: u16,
2191 family: u16,
2192 nlas: Vec<AddressAttribute>,
2193 prefix_len: u8,
2194 interface_id: u32,
2195 expected_request_args: Option<RequestAndResponse<interfaces::AddressAndInterfaceArgs>>,
2196 expected_response: Option<ExpectedResponse>,
2197 }
2198
2199 fn ip_from_addr(a: AddrSubnetEither) -> IpAddr {
2200 match a {
2201 AddrSubnetEither::V4(a) => IpAddr::V4(a.addr().get().ipv4_bytes().into()),
2202 AddrSubnetEither::V6(a) => IpAddr::V6(a.addr().get().ipv6_bytes().into()),
2203 }
2204 }
2205
2206 fn prefix_from_addr(a: AddrSubnetEither) -> u8 {
2207 let (_addr, prefix) = a.addr_prefix();
2208 prefix
2209 }
2210
2211 fn interface_id_as_u32(id: u64) -> u32 {
2212 id.try_into().unwrap()
2213 }
2214
2215 fn valid_new_del_addr_request(
2216 kind: AddressRequestKind,
2217 ack: bool,
2218 addr: AddrSubnetEither,
2219 extra_nlas: impl IntoIterator<Item = AddressAttribute>,
2220 interface_id: u64,
2221 response: Result<(), interfaces::RequestError>,
2222 ) -> TestAddrCase {
2223 TestAddrCase {
2224 kind,
2225 flags: if ack { NLM_F_ACK } else { 0 },
2226 family: match addr {
2227 AddrSubnetEither::V4(_) => AF_INET as u16,
2230 AddrSubnetEither::V6(_) => AF_INET6 as u16,
2231 },
2232 nlas: [AddressAttribute::Local(ip_from_addr(addr))]
2233 .into_iter()
2234 .chain(extra_nlas)
2235 .collect(),
2236 prefix_len: prefix_from_addr(addr),
2237 interface_id: interface_id_as_u32(interface_id),
2238 expected_request_args: Some(RequestAndResponse {
2239 request: interfaces::AddressAndInterfaceArgs {
2240 address: addr,
2241 interface_id: NonZeroU32::new(interface_id_as_u32(interface_id)).unwrap(),
2242 },
2243 response,
2244 }),
2245 expected_response: ack.then_some(ExpectedResponse::Ack),
2246 }
2247 }
2248
2249 fn valid_new_addr_request_with_extra_nlas(
2250 ack: bool,
2251 addr: AddrSubnetEither,
2252 extra_nlas: impl IntoIterator<Item = AddressAttribute>,
2253 interface_id: u64,
2254 response: Result<(), interfaces::RequestError>,
2255 ) -> TestAddrCase {
2256 valid_new_del_addr_request(
2257 AddressRequestKind::New { add_subnet_route: true },
2258 ack,
2259 addr,
2260 extra_nlas,
2261 interface_id,
2262 response,
2263 )
2264 }
2265
2266 fn valid_new_addr_request(
2267 ack: bool,
2268 addr: AddrSubnetEither,
2269 interface_id: u64,
2270 response: Result<(), interfaces::RequestError>,
2271 ) -> TestAddrCase {
2272 valid_new_addr_request_with_extra_nlas(ack, addr, None, interface_id, response)
2273 }
2274
2275 fn invalid_new_addr_request(
2276 ack: bool,
2277 addr: AddrSubnetEither,
2278 interface_id: u64,
2279 errno: Errno,
2280 ) -> TestAddrCase {
2281 TestAddrCase {
2282 expected_request_args: None,
2283 expected_response: Some(ExpectedResponse::Error(errno)),
2284 ..valid_new_addr_request(ack, addr, interface_id, Ok(()))
2285 }
2286 }
2287
2288 fn valid_del_addr_request(
2289 ack: bool,
2290 addr: AddrSubnetEither,
2291 interface_id: u64,
2292 response: Result<(), interfaces::RequestError>,
2293 ) -> TestAddrCase {
2294 valid_new_del_addr_request(AddressRequestKind::Del, ack, addr, None, interface_id, response)
2295 }
2296
2297 fn invalid_del_addr_request(
2298 ack: bool,
2299 addr: AddrSubnetEither,
2300 interface_id: u64,
2301 errno: Errno,
2302 ) -> TestAddrCase {
2303 TestAddrCase {
2304 expected_request_args: None,
2305 expected_response: Some(ExpectedResponse::Error(errno)),
2306 ..valid_del_addr_request(ack, addr, interface_id, Ok(()))
2307 }
2308 }
2309
2310 #[test_case(
2313 TestAddrCase {
2314 expected_request_args: None,
2315 ..valid_new_addr_request(
2316 true,
2317 net_addr_subnet!("0.0.0.0/0"),
2318 interfaces::testutil::PPP_INTERFACE_ID,
2319 Ok(()))
2320 }; "new_v4_unspecified_address_zero_prefix_ok_ack")]
2321 #[test_case(
2322 TestAddrCase {
2323 expected_request_args: None,
2324 ..valid_new_addr_request(
2325 false,
2326 net_addr_subnet!("0.0.0.0/24"),
2327 interfaces::testutil::PPP_INTERFACE_ID,
2328 Ok(()))
2329 }; "new_v4_unspecified_address_non_zero_prefix_ok_no_ack")]
2330 #[test_case(
2331 invalid_new_addr_request(
2332 true,
2333 net_addr_subnet!("::/0"),
2334 interfaces::testutil::ETH_INTERFACE_ID,
2335 Errno::EADDRNOTAVAIL); "new_v6_unspecified_address_zero_prefix_ack")]
2336 #[test_case(
2337 invalid_new_addr_request(
2338 false,
2339 net_addr_subnet!("::/64"),
2340 interfaces::testutil::ETH_INTERFACE_ID,
2341 Errno::EADDRNOTAVAIL); "new_v6_unspecified_address_non_zero_prefix_no_ack")]
2342 #[test_case(
2343 valid_new_addr_request(
2344 true,
2345 interfaces::testutil::test_addr_subnet_v4(),
2346 interfaces::testutil::LO_INTERFACE_ID,
2347 Ok(())); "new_v4_ok_ack")]
2348 #[test_case(
2349 valid_new_addr_request(
2350 true,
2351 interfaces::testutil::test_addr_subnet_v6(),
2352 interfaces::testutil::LO_INTERFACE_ID,
2353 Ok(())); "new_v6_ok_ack")]
2354 #[test_case(
2355 valid_new_addr_request(
2356 false,
2357 interfaces::testutil::test_addr_subnet_v4(),
2358 interfaces::testutil::ETH_INTERFACE_ID,
2359 Ok(())); "new_v4_ok_no_ack")]
2360 #[test_case(
2361 valid_new_addr_request(
2362 false,
2363 interfaces::testutil::test_addr_subnet_v6(),
2364 interfaces::testutil::ETH_INTERFACE_ID,
2365 Ok(())); "new_v6_ok_no_ack")]
2366 #[test_case(
2367 TestAddrCase {
2368 nlas: vec![
2369 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2370 ],
2371 ..valid_new_addr_request(
2372 false,
2373 interfaces::testutil::test_addr_subnet_v4(),
2374 interfaces::testutil::ETH_INTERFACE_ID,
2375 Ok(()),
2376 )
2377 }; "new_v4_local_nla_ok_no_ack")]
2378 #[test_case(
2379 TestAddrCase {
2380 nlas: vec![
2381 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2382 ],
2383 ..valid_new_addr_request(
2384 true,
2385 interfaces::testutil::test_addr_subnet_v6(),
2386 interfaces::testutil::PPP_INTERFACE_ID,
2387 Ok(()),
2388 )
2389 }; "new_v6_address_nla_ok_ack")]
2390 #[test_case(
2391 TestAddrCase {
2392 nlas: vec![
2393 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2394 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2395 ],
2396 ..valid_new_addr_request(
2397 false,
2398 interfaces::testutil::test_addr_subnet_v6(),
2399 interfaces::testutil::PPP_INTERFACE_ID,
2400 Ok(()),
2401 )
2402 }; "new_v6_same_local_and_address_nla_ok_no_ack")]
2403 #[test_case(
2404 TestAddrCase {
2405 kind: AddressRequestKind::New { add_subnet_route: true },
2406 ..valid_new_addr_request_with_extra_nlas(
2407 false,
2408 interfaces::testutil::test_addr_subnet_v4(),
2409 [AddressAttribute::Flags(AddressFlags::empty())],
2410 interfaces::testutil::ETH_INTERFACE_ID,
2411 Ok(()),
2412 )
2413 }; "new_v4_with_route_ok_no_ack")]
2414 #[test_case(
2415 TestAddrCase {
2416 kind: AddressRequestKind::New { add_subnet_route: false },
2417 ..valid_new_addr_request_with_extra_nlas(
2418 true,
2419 interfaces::testutil::test_addr_subnet_v6(),
2420 [AddressAttribute::Flags(AddressFlags::from_bits(IFA_F_NOPREFIXROUTE).unwrap())],
2421 interfaces::testutil::LO_INTERFACE_ID,
2422 Ok(()),
2423 )
2424 }; "new_v6_without_route_ok_ack")]
2425 #[test_case(
2426 TestAddrCase {
2427 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
2428 ..valid_new_addr_request(
2429 true,
2430 interfaces::testutil::test_addr_subnet_v4(),
2431 interfaces::testutil::LO_INTERFACE_ID,
2432 Err(interfaces::RequestError::InvalidRequest),
2433 )
2434 }; "new_v4_invalid_response_ack")]
2435 #[test_case(
2436 TestAddrCase {
2437 expected_response: Some(ExpectedResponse::Error(Errno::EEXIST)),
2438 ..valid_new_addr_request(
2439 false,
2440 interfaces::testutil::test_addr_subnet_v6(),
2441 interfaces::testutil::LO_INTERFACE_ID,
2442 Err(interfaces::RequestError::AlreadyExists),
2443 )
2444 }; "new_v6_exist_response_no_ack")]
2445 #[test_case(
2446 TestAddrCase {
2447 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
2448 ..valid_new_addr_request(
2449 false,
2450 interfaces::testutil::test_addr_subnet_v6(),
2451 interfaces::testutil::WLAN_INTERFACE_ID,
2452 Err(interfaces::RequestError::UnrecognizedInterface),
2453 )
2454 }; "new_v6_unrecognized_interface_response_no_ack")]
2455 #[test_case(
2456 TestAddrCase {
2457 expected_response: Some(ExpectedResponse::Error(Errno::EADDRNOTAVAIL)),
2458 ..valid_new_addr_request(
2459 true,
2460 interfaces::testutil::test_addr_subnet_v4(),
2461 interfaces::testutil::ETH_INTERFACE_ID,
2462 Err(interfaces::RequestError::AddressNotFound),
2463 )
2464 }; "new_v4_not_found_response_ck")]
2465 #[test_case(
2466 TestAddrCase {
2467 interface_id: 0,
2468 ..invalid_new_addr_request(
2469 true,
2470 interfaces::testutil::test_addr_subnet_v6(),
2471 interfaces::testutil::LO_INTERFACE_ID,
2472 Errno::EINVAL,
2473 )
2474 }; "new_zero_interface_id_ack")]
2475 #[test_case(
2476 TestAddrCase {
2477 interface_id: 0,
2478 ..invalid_new_addr_request(
2479 false,
2480 interfaces::testutil::test_addr_subnet_v4(),
2481 interfaces::testutil::WLAN_INTERFACE_ID,
2482 Errno::EINVAL,
2483 )
2484 }; "new_zero_interface_id_no_ack")]
2485 #[test_case(
2486 TestAddrCase {
2487 nlas: Vec::new(),
2488 ..invalid_new_addr_request(
2489 true,
2490 interfaces::testutil::test_addr_subnet_v4(),
2491 interfaces::testutil::WLAN_INTERFACE_ID,
2492 Errno::EINVAL,
2493 )
2494 }; "new_no_nlas_ack")]
2495 #[test_case(
2496 TestAddrCase {
2497 nlas: Vec::new(),
2498 ..invalid_new_addr_request(
2499 false,
2500 interfaces::testutil::test_addr_subnet_v6(),
2501 interfaces::testutil::WLAN_INTERFACE_ID,
2502 Errno::EINVAL,
2503 )
2504 }; "new_no_nlas_no_ack")]
2505 #[test_case(
2506 TestAddrCase {
2507 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2508 ..invalid_new_addr_request(
2509 true,
2510 interfaces::testutil::test_addr_subnet_v4(),
2511 interfaces::testutil::WLAN_INTERFACE_ID,
2512 Errno::EINVAL,
2513 )
2514 }; "new_missing_address_and_local_nla_ack")]
2515 #[test_case(
2516 TestAddrCase {
2517 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2518 ..invalid_new_addr_request(
2519 false,
2520 interfaces::testutil::test_addr_subnet_v6(),
2521 interfaces::testutil::WLAN_INTERFACE_ID,
2522 Errno::EINVAL,
2523 )
2524 }; "new_missing_address_and_local_nla_no_ack")]
2525 #[test_case(
2526 TestAddrCase {
2527 prefix_len: 0,
2528 kind: AddressRequestKind::New { add_subnet_route: false },
2529 ..valid_new_addr_request(
2530 true,
2531 net_addr_subnet!("192.0.2.123/0"),
2532 interfaces::testutil::WLAN_INTERFACE_ID,
2533 Ok(()),
2534 )
2535 }; "new_zero_prefix_len_ack")]
2536 #[test_case(
2537 TestAddrCase {
2538 prefix_len: 0,
2539 ..valid_new_addr_request(
2540 false,
2541 net_addr_subnet!("2001:db8::1324/0"),
2542 interfaces::testutil::WLAN_INTERFACE_ID,
2543 Ok(()),
2544 )
2545 }; "new_zero_prefix_len_no_ack")]
2546 #[test_case(
2547 TestAddrCase {
2548 prefix_len: u8::MAX,
2549 ..invalid_new_addr_request(
2550 true,
2551 interfaces::testutil::test_addr_subnet_v4(),
2552 interfaces::testutil::WLAN_INTERFACE_ID,
2553 Errno::EINVAL,
2554 )
2555 }; "new_invalid_prefix_len_ack")]
2556 #[test_case(
2557 TestAddrCase {
2558 prefix_len: u8::MAX,
2559 ..invalid_new_addr_request(
2560 false,
2561 interfaces::testutil::test_addr_subnet_v6(),
2562 interfaces::testutil::WLAN_INTERFACE_ID,
2563 Errno::EINVAL,
2564 )
2565 }; "new_invalid_prefix_len_no_ack")]
2566 #[test_case(
2567 TestAddrCase {
2568 family: AF_UNSPEC as u16,
2569 ..invalid_new_addr_request(
2570 true,
2571 interfaces::testutil::test_addr_subnet_v4(),
2572 interfaces::testutil::LO_INTERFACE_ID,
2573 Errno::EINVAL,
2574 )
2575 }; "new_invalid_family_ack")]
2576 #[test_case(
2577 TestAddrCase {
2578 family: AF_UNSPEC as u16,
2579 ..invalid_new_addr_request(
2580 false,
2581 interfaces::testutil::test_addr_subnet_v6(),
2582 interfaces::testutil::PPP_INTERFACE_ID,
2583 Errno::EINVAL,
2584 )
2585 }; "new_invalid_family_no_ack")]
2586 #[test_case(
2588 valid_del_addr_request(
2589 true,
2590 interfaces::testutil::test_addr_subnet_v4(),
2591 interfaces::testutil::LO_INTERFACE_ID,
2592 Ok(())); "del_v4_ok_ack")]
2593 #[test_case(
2594 valid_del_addr_request(
2595 true,
2596 interfaces::testutil::test_addr_subnet_v6(),
2597 interfaces::testutil::LO_INTERFACE_ID,
2598 Ok(())); "del_v6_ok_ack")]
2599 #[test_case(
2600 valid_del_addr_request(
2601 false,
2602 interfaces::testutil::test_addr_subnet_v4(),
2603 interfaces::testutil::ETH_INTERFACE_ID,
2604 Ok(())); "del_v4_ok_no_ack")]
2605 #[test_case(
2606 valid_del_addr_request(
2607 false,
2608 interfaces::testutil::test_addr_subnet_v6(),
2609 interfaces::testutil::ETH_INTERFACE_ID,
2610 Ok(())); "del_v6_ok_no_ack")]
2611 #[test_case(
2612 TestAddrCase {
2613 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
2614 ..valid_del_addr_request(
2615 true,
2616 interfaces::testutil::test_addr_subnet_v4(),
2617 interfaces::testutil::LO_INTERFACE_ID,
2618 Err(interfaces::RequestError::InvalidRequest),
2619 )
2620 }; "del_v4_invalid_response_ack")]
2621 #[test_case(
2622 TestAddrCase {
2623 nlas: vec![
2624 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2625 ],
2626 ..valid_del_addr_request(
2627 false,
2628 interfaces::testutil::test_addr_subnet_v4(),
2629 interfaces::testutil::ETH_INTERFACE_ID,
2630 Ok(()),
2631 )
2632 }; "del_v4_local_nla_ok_no_ack")]
2633 #[test_case(
2634 TestAddrCase {
2635 nlas: vec![
2636 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2637 ],
2638 ..valid_del_addr_request(
2639 true,
2640 interfaces::testutil::test_addr_subnet_v6(),
2641 interfaces::testutil::PPP_INTERFACE_ID,
2642 Ok(()),
2643 )
2644 }; "del_v6_address_nla_ok_ack")]
2645 #[test_case(
2646 TestAddrCase {
2647 nlas: vec![
2648 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2649 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2650 ],
2651 ..valid_del_addr_request(
2652 true,
2653 interfaces::testutil::test_addr_subnet_v4(),
2654 interfaces::testutil::ETH_INTERFACE_ID,
2655 Ok(()),
2656 )
2657 }; "del_v4_same_local_and_address_nla_ok_ack")]
2658 #[test_case(
2659 TestAddrCase {
2660 expected_response: Some(ExpectedResponse::Error(Errno::EEXIST)),
2661 ..valid_del_addr_request(
2662 false,
2663 interfaces::testutil::test_addr_subnet_v6(),
2664 interfaces::testutil::LO_INTERFACE_ID,
2665 Err(interfaces::RequestError::AlreadyExists),
2666 )
2667 }; "del_v6_exist_response_no_ack")]
2668 #[test_case(
2669 TestAddrCase {
2670 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
2671 ..valid_del_addr_request(
2672 false,
2673 interfaces::testutil::test_addr_subnet_v6(),
2674 interfaces::testutil::WLAN_INTERFACE_ID,
2675 Err(interfaces::RequestError::UnrecognizedInterface),
2676 )
2677 }; "del_v6_unrecognized_interface_response_no_ack")]
2678 #[test_case(
2679 TestAddrCase {
2680 expected_response: Some(ExpectedResponse::Error(Errno::EADDRNOTAVAIL)),
2681 ..valid_del_addr_request(
2682 true,
2683 interfaces::testutil::test_addr_subnet_v4(),
2684 interfaces::testutil::ETH_INTERFACE_ID,
2685 Err(interfaces::RequestError::AddressNotFound),
2686 )
2687 }; "del_v4_not_found_response_ck")]
2688 #[test_case(
2689 TestAddrCase {
2690 interface_id: 0,
2691 ..invalid_del_addr_request(
2692 true,
2693 interfaces::testutil::test_addr_subnet_v6(),
2694 interfaces::testutil::LO_INTERFACE_ID,
2695 Errno::EINVAL,
2696 )
2697 }; "del_zero_interface_id_ack")]
2698 #[test_case(
2699 TestAddrCase {
2700 interface_id: 0,
2701 ..invalid_del_addr_request(
2702 false,
2703 interfaces::testutil::test_addr_subnet_v4(),
2704 interfaces::testutil::WLAN_INTERFACE_ID,
2705 Errno::EINVAL,
2706 )
2707 }; "del_zero_interface_id_no_ack")]
2708 #[test_case(
2709 TestAddrCase {
2710 nlas: Vec::new(),
2711 ..invalid_del_addr_request(
2712 true,
2713 interfaces::testutil::test_addr_subnet_v4(),
2714 interfaces::testutil::WLAN_INTERFACE_ID,
2715 Errno::EINVAL,
2716 )
2717 }; "del_no_nlas_ack")]
2718 #[test_case(
2719 TestAddrCase {
2720 nlas: Vec::new(),
2721 ..invalid_del_addr_request(
2722 false,
2723 interfaces::testutil::test_addr_subnet_v6(),
2724 interfaces::testutil::WLAN_INTERFACE_ID,
2725 Errno::EINVAL,
2726 )
2727 }; "del_no_nlas_no_ack")]
2728 #[test_case(
2729 TestAddrCase {
2730 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2731 ..invalid_del_addr_request(
2732 true,
2733 interfaces::testutil::test_addr_subnet_v4(),
2734 interfaces::testutil::WLAN_INTERFACE_ID,
2735 Errno::EINVAL,
2736 )
2737 }; "del_missing_address_and_local_nla_ack")]
2738 #[test_case(
2739 TestAddrCase {
2740 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2741 ..invalid_del_addr_request(
2742 false,
2743 interfaces::testutil::test_addr_subnet_v6(),
2744 interfaces::testutil::WLAN_INTERFACE_ID,
2745 Errno::EINVAL,
2746 )
2747 }; "del_missing_address_and_local_nla_no_ack")]
2748 #[test_case(
2749 TestAddrCase {
2750 prefix_len: 0,
2751 ..valid_del_addr_request(
2752 true,
2753 net_addr_subnet!("192.0.2.123/0"),
2754 interfaces::testutil::WLAN_INTERFACE_ID,
2755 Ok(()),
2756 )
2757 }; "del_zero_prefix_len_ack")]
2758 #[test_case(
2759 TestAddrCase {
2760 prefix_len: 0,
2761 ..valid_del_addr_request(
2762 false,
2763 net_addr_subnet!("2001:db8::1324/0"),
2764 interfaces::testutil::WLAN_INTERFACE_ID,
2765 Ok(()),
2766 )
2767 }; "del_zero_prefix_len_no_ack")]
2768 #[test_case(
2769 TestAddrCase {
2770 prefix_len: u8::MAX,
2771 ..invalid_del_addr_request(
2772 true,
2773 interfaces::testutil::test_addr_subnet_v4(),
2774 interfaces::testutil::WLAN_INTERFACE_ID,
2775 Errno::EINVAL,
2776 )
2777 }; "del_invalid_prefix_len_ack")]
2778 #[test_case(
2779 TestAddrCase {
2780 prefix_len: u8::MAX,
2781 ..invalid_del_addr_request(
2782 false,
2783 interfaces::testutil::test_addr_subnet_v6(),
2784 interfaces::testutil::WLAN_INTERFACE_ID,
2785 Errno::EINVAL,
2786 )
2787 }; "del_invalid_prefix_len_no_ack")]
2788 #[test_case(
2789 TestAddrCase {
2790 family: AF_UNSPEC as u16,
2791 ..invalid_del_addr_request(
2792 true,
2793 interfaces::testutil::test_addr_subnet_v4(),
2794 interfaces::testutil::LO_INTERFACE_ID,
2795 Errno::EINVAL,
2796 )
2797 }; "del_invalid_family_ack")]
2798 #[test_case(
2799 TestAddrCase {
2800 family: AF_UNSPEC as u16,
2801 ..invalid_del_addr_request(
2802 false,
2803 interfaces::testutil::test_addr_subnet_v6(),
2804 interfaces::testutil::PPP_INTERFACE_ID,
2805 Errno::EINVAL,
2806 )
2807 }; "del_invalid_family_no_ack")]
2808 #[fuchsia::test]
2809 async fn test_new_del_addr(test_case: TestAddrCase) {
2810 let TestAddrCase {
2811 kind,
2812 flags,
2813 family,
2814 nlas,
2815 prefix_len,
2816 interface_id,
2817 expected_request_args,
2818 expected_response,
2819 } = test_case;
2820
2821 let header = header_with_flags(flags);
2822 let address_message = {
2823 let mut message = AddressMessage::default();
2824 message.header.family = AddressFamily::from(family as u8).into();
2826 message.header.index = interface_id.into();
2827 message.header.prefix_len = prefix_len;
2828 message.attributes = nlas;
2829 message
2830 };
2831
2832 let (message, request) = match kind {
2833 AddressRequestKind::New { add_subnet_route } => (
2834 RouteNetlinkMessage::NewAddress(address_message),
2835 expected_request_args.map(|RequestAndResponse { request, response }| {
2836 RequestAndResponse {
2837 request: interfaces::RequestArgs::Address(
2838 interfaces::AddressRequestArgs::New(interfaces::NewAddressArgs {
2839 address_and_interface_id: request,
2840 add_subnet_route,
2841 }),
2842 ),
2843 response,
2844 }
2845 }),
2846 ),
2847 AddressRequestKind::Del => (
2848 RouteNetlinkMessage::DelAddress(address_message),
2849 expected_request_args.map(|RequestAndResponse { request, response }| {
2850 RequestAndResponse {
2851 request: interfaces::RequestArgs::Address(
2852 interfaces::AddressRequestArgs::Del(interfaces::DelAddressArgs {
2853 address_and_interface_id: request,
2854 }),
2855 ),
2856 response,
2857 }
2858 }),
2859 ),
2860 };
2861
2862 pretty_assertions::assert_eq!(
2863 test_request(
2864 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(message),),
2865 request,
2866 )
2867 .await,
2868 expected_response
2869 .into_iter()
2870 .map(|response| SentMessage::unicast(match response {
2871 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
2872 ExpectedResponse::Done => netlink_packet::new_done(header),
2873 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
2874 }))
2875 .collect::<Vec<_>>(),
2876 )
2877 }
2878
2879 async fn split_route_requests(
2883 unified_request_stream: mpsc::Receiver<UnifiedRequest<FakeSender<RouteNetlinkMessage>>>,
2884 v4_routes_request_sink: mpsc::Sender<
2885 crate::routes::Request<FakeSender<RouteNetlinkMessage>, Ipv4>,
2886 >,
2887 v6_routes_request_sink: mpsc::Sender<
2888 crate::routes::Request<FakeSender<RouteNetlinkMessage>, Ipv6>,
2889 >,
2890 ) {
2891 unified_request_stream
2892 .fold(
2893 (v4_routes_request_sink, v6_routes_request_sink),
2894 |(mut v4_routes_request_sink, mut v6_routes_request_sink), req| async move {
2895 match req {
2896 UnifiedRequest::RoutesV4Request(req) => {
2897 v4_routes_request_sink
2898 .send(req)
2899 .map(|res| res.expect("send should succeed"))
2900 .await
2901 }
2902 UnifiedRequest::RoutesV6Request(req) => {
2903 v6_routes_request_sink
2904 .send(req)
2905 .map(|res| res.expect("send should succeed"))
2906 .await
2907 }
2908 _ => (),
2909 };
2910 (v4_routes_request_sink, v6_routes_request_sink)
2911 },
2912 )
2913 .map(|(_v4_sink, _v6_sink)| ())
2914 .await
2915 }
2916
2917 async fn test_get_route_request(
2921 family: u16,
2922 request: NetlinkMessage<RouteNetlinkMessage>,
2923 expected_request: Option<routes::GetRouteArgs>,
2924 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
2925 let (mut client_sink, mut client, async_work_drain_task) =
2926 crate::client::testutil::new_fake_client::<NetlinkRoute>(
2927 crate::client::testutil::CLIENT_ID_1,
2928 std::iter::empty(),
2929 );
2930 let join_handle = fasync::Task::spawn(async_work_drain_task);
2931
2932 {
2933 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
2934
2935 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
2936
2937 let (v4_routes_request_sink, mut v4_routes_request_stream) = mpsc::channel(0);
2938 let (v6_routes_request_sink, mut v6_routes_request_stream) = mpsc::channel(0);
2939
2940 let mut split_route_requests_background_work = pin!(
2941 split_route_requests(
2942 unified_request_stream,
2943 v4_routes_request_sink,
2944 v6_routes_request_sink,
2945 )
2946 .fuse()
2947 );
2948
2949 let mut handler_fut = pin!(
2950 futures::future::join(handler.handle_request(request, &mut client), async {
2951 if family == AF_UNSPEC as u16 || family == AF_INET as u16 {
2953 let next = v4_routes_request_stream.next();
2954 match expected_request.map(|a| {
2955 routes::RequestArgs::<Ipv4>::Route(routes::RouteRequestArgs::Get(a))
2956 }) {
2957 Some(expected_request) => {
2958 let routes::Request {
2959 args,
2960 sequence_number: _,
2961 client: _,
2962 completer,
2963 } = next.await.expect("handler should send request");
2964 assert_eq!(args, expected_request);
2965 completer.send(Ok(())).expect("handler should be alive");
2966 }
2967 None => assert_matches!(next.now_or_never(), None),
2968 };
2969 }
2970 if family == AF_UNSPEC as u16 || family == AF_INET6 as u16 {
2971 let next = v6_routes_request_stream.next();
2972 match expected_request.map(|a| {
2973 routes::RequestArgs::<Ipv6>::Route(routes::RouteRequestArgs::Get(a))
2974 }) {
2975 Some(expected_request) => {
2976 let routes::Request {
2977 args,
2978 sequence_number: _,
2979 client: _,
2980 completer,
2981 } = next.await.expect("handler should send request");
2982 assert_eq!(args, expected_request);
2983 completer.send(Ok(())).expect("handler should be alive");
2984 }
2985 None => assert_matches!(next.now_or_never(), None),
2986 };
2987 }
2988 })
2989 .fuse()
2990 );
2991
2992 futures::select! {
2993 ((), ()) = handler_fut => (),
2994 () = split_route_requests_background_work => unreachable!(),
2995 };
2996 }
2997 drop(client);
2998 join_handle.await;
2999 client_sink.take_messages()
3000 }
3001
3002 #[test_case(
3005 0,
3006 AF_UNSPEC as u16,
3007 None,
3008 None; "af_unspec_no_flags")]
3009 #[test_case(
3010 NLM_F_ACK,
3011 AF_UNSPEC as u16,
3012 None,
3013 Some(ExpectedResponse::Ack); "af_unspec_ack_flag")]
3014 #[test_case(
3015 NLM_F_DUMP,
3016 AF_UNSPEC as u16,
3017 Some(routes::GetRouteArgs::Dump),
3018 Some(ExpectedResponse::Done); "af_unspec_dump_flag")]
3019 #[test_case(
3020 NLM_F_DUMP | NLM_F_ACK,
3021 AF_UNSPEC as u16,
3022 Some(routes::GetRouteArgs::Dump),
3023 Some(ExpectedResponse::Done); "af_unspec_dump_and_ack_flags")]
3024 #[test_case(
3025 0,
3026 AF_INET as u16,
3027 None,
3028 None; "af_inet_no_flags")]
3029 #[test_case(
3030 NLM_F_ACK,
3031 AF_INET as u16,
3032 None,
3033 Some(ExpectedResponse::Ack); "af_inet_ack_flag")]
3034 #[test_case(
3035 NLM_F_DUMP,
3036 AF_INET as u16,
3037 Some(routes::GetRouteArgs::Dump),
3038 Some(ExpectedResponse::Done); "af_inet_dump_flag")]
3039 #[test_case(
3040 NLM_F_DUMP | NLM_F_ACK,
3041 AF_INET as u16,
3042 Some(routes::GetRouteArgs::Dump),
3043 Some(ExpectedResponse::Done); "af_inet_dump_and_ack_flags")]
3044 #[test_case(
3045 0,
3046 AF_INET6 as u16,
3047 None,
3048 None; "af_inet6_no_flags")]
3049 #[test_case(
3050 NLM_F_ACK,
3051 AF_INET6 as u16,
3052 None,
3053 Some(ExpectedResponse::Ack); "af_inet6_ack_flag")]
3054 #[test_case(
3055 NLM_F_DUMP,
3056 AF_INET6 as u16,
3057 Some(routes::GetRouteArgs::Dump),
3058 Some(ExpectedResponse::Done); "af_inet6_dump_flag")]
3059 #[test_case(
3060 NLM_F_DUMP | NLM_F_ACK,
3061 AF_INET6 as u16,
3062 Some(routes::GetRouteArgs::Dump),
3063 Some(ExpectedResponse::Done); "af_inet6_dump_and_ack_flags")]
3064 #[test_case(
3065 0,
3066 AF_PACKET,
3067 None,
3068 None; "af_other_no_flags")]
3069 #[test_case(
3070 NLM_F_ACK,
3071 AF_PACKET,
3072 None,
3073 Some(ExpectedResponse::Ack); "af_other_ack_flag")]
3074 #[test_case(
3075 NLM_F_DUMP,
3076 AF_PACKET,
3077 None,
3078 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_flag")]
3079 #[test_case(
3080 NLM_F_DUMP | NLM_F_ACK,
3081 AF_PACKET,
3082 None,
3083 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_and_ack_flags")]
3084 #[fuchsia::test]
3085 async fn test_get_route(
3086 flags: u16,
3087 family: u16,
3088 expected_request_args: Option<routes::GetRouteArgs>,
3089 expected_response: Option<ExpectedResponse>,
3090 ) {
3091 let header = header_with_flags(flags);
3092 let route_message = {
3093 let mut message = RouteMessage::default();
3094 message.header.address_family = AddressFamily::from(family as u8);
3095 message
3096 };
3097
3098 pretty_assertions::assert_eq!(
3099 test_get_route_request(
3100 family,
3101 NetlinkMessage::new(
3102 header,
3103 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetRoute(route_message)),
3104 ),
3105 expected_request_args,
3106 )
3107 .await,
3108 expected_response
3109 .into_iter()
3110 .map(|expected_response| SentMessage::unicast(match expected_response {
3111 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
3112 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
3113 ExpectedResponse::Done => netlink_packet::new_done(header),
3114 }))
3115 .collect::<Vec<_>>(),
3116 )
3117 }
3118
3119 #[derive(Debug)]
3121 pub(crate) struct FakeRuleRequestResponse {
3122 pub(crate) expected_request_args: RuleRequestArgs,
3123 pub(crate) expected_ip_version: IpVersion,
3124 pub(crate) response: Result<(), Errno>,
3125 }
3126
3127 #[derive(Clone, Debug)]
3132 pub(crate) struct FakeRuleRequestHandler {
3133 pub(crate) requests_and_responses: Arc<Mutex<VecDeque<FakeRuleRequestResponse>>>,
3134 }
3135
3136 impl FakeRuleRequestHandler {
3137 fn new(requests_and_responses: impl IntoIterator<Item = FakeRuleRequestResponse>) -> Self {
3138 FakeRuleRequestHandler {
3139 requests_and_responses: Arc::new(Mutex::new(VecDeque::from_iter(
3140 requests_and_responses,
3141 ))),
3142 }
3143 }
3144
3145 fn handle_request<S: Sender<RouteNetlinkMessage>, I: Ip>(
3146 &mut self,
3147 actual_request: RuleRequest<S, I>,
3148 ) -> Result<(), Errno> {
3149 let Self { requests_and_responses } = self;
3150 let FakeRuleRequestResponse { expected_request_args, expected_ip_version, response } =
3151 requests_and_responses.lock().pop_front().expect(
3152 "FakeRuleRequest handler should have a fake request/response pre-configured",
3153 );
3154 let RuleRequest { args, _ip_version_marker, sequence_number: _, client: _ } =
3155 actual_request;
3156 assert_eq!(args, expected_request_args);
3157 assert_eq!(I::VERSION, expected_ip_version);
3158 response
3159 }
3160 }
3161
3162 fn default_rule_for_family(family: u16) -> RuleMessage {
3163 let mut rule = RuleMessage::default();
3164 rule.header.family = AddressFamily::from(family as u8);
3166 rule
3167 }
3168
3169 const AF_INVALID: u16 = 255;
3170 #[test_case(
3172 RouteNetlinkMessage::GetRule,
3173 0,
3174 AF_UNSPEC as u16,
3175 vec![],
3176 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_no_dump")]
3177 #[test_case(
3178 RouteNetlinkMessage::GetRule,
3179 NLM_F_DUMP,
3180 AF_INVALID,
3181 vec![],
3182 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "get_rule_dump_invalid_address_family")]
3183 #[test_case(
3184 RouteNetlinkMessage::GetRule,
3185 NLM_F_DUMP,
3186 AF_INET as u16,
3187 vec![FakeRuleRequestResponse{
3188 expected_request_args: RuleRequestArgs::DumpRules,
3189 expected_ip_version: IpVersion::V4,
3190 response: Ok(()),
3191 }],
3192 Some(ExpectedResponse::Done); "get_rule_dump_v4")]
3193 #[test_case(
3194 RouteNetlinkMessage::GetRule,
3195 NLM_F_DUMP,
3196 AF_INET6 as u16,
3197 vec![FakeRuleRequestResponse{
3198 expected_request_args: RuleRequestArgs::DumpRules,
3199 expected_ip_version: IpVersion::V6,
3200 response: Ok(()),
3201 }],
3202 Some(ExpectedResponse::Done); "get_rule_dump_v6")]
3203 #[test_case(
3204 RouteNetlinkMessage::GetRule,
3205 NLM_F_DUMP,
3206 AF_UNSPEC as u16,
3207 vec![FakeRuleRequestResponse{
3208 expected_request_args: RuleRequestArgs::DumpRules,
3209 expected_ip_version: IpVersion::V4,
3210 response: Ok(()),
3211 },
3212 FakeRuleRequestResponse{
3213 expected_request_args: RuleRequestArgs::DumpRules,
3214 expected_ip_version: IpVersion::V6,
3215 response: Ok(()),
3216 }],
3217 Some(ExpectedResponse::Done); "get_rule_dump_af_unspec")]
3218 #[test_case(
3219 RouteNetlinkMessage::GetRule,
3220 NLM_F_DUMP,
3221 AF_INET as u16,
3222 vec![FakeRuleRequestResponse{
3223 expected_request_args: RuleRequestArgs::DumpRules,
3224 expected_ip_version: IpVersion::V4,
3225 response: Err(Errno::ENOTSUP),
3226 }],
3227 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_v4_fails")]
3228 #[test_case(
3229 RouteNetlinkMessage::GetRule,
3230 NLM_F_DUMP,
3231 AF_INET6 as u16,
3232 vec![FakeRuleRequestResponse{
3233 expected_request_args: RuleRequestArgs::DumpRules,
3234 expected_ip_version: IpVersion::V6,
3235 response: Err(Errno::ENOTSUP),
3236 }],
3237 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_v6_fails")]
3238 #[test_case(
3239 RouteNetlinkMessage::GetRule,
3240 NLM_F_DUMP,
3241 AF_UNSPEC as u16,
3242 vec![FakeRuleRequestResponse{
3243 expected_request_args: RuleRequestArgs::DumpRules,
3244 expected_ip_version: IpVersion::V4,
3245 response: Err(Errno::ENOTSUP),
3246 }],
3247 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_af_unspec_v4_fails")]
3248 #[test_case(
3249 RouteNetlinkMessage::GetRule,
3250 NLM_F_DUMP,
3251 AF_UNSPEC as u16,
3252 vec![FakeRuleRequestResponse{
3253 expected_request_args: RuleRequestArgs::DumpRules,
3254 expected_ip_version: IpVersion::V4,
3255 response: Ok(()),
3256 },
3257 FakeRuleRequestResponse{
3258 expected_request_args: RuleRequestArgs::DumpRules,
3259 expected_ip_version: IpVersion::V6,
3260 response: Err(Errno::ENOTSUP),
3261 }],
3262 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_af_unspec_v6_fails")]
3263 #[test_case(
3264 RouteNetlinkMessage::NewRule,
3265 0,
3266 AF_INET as u16,
3267 vec![FakeRuleRequestResponse{
3268 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3269 expected_ip_version: IpVersion::V4,
3270 response: Ok(()),
3271 }],
3272 None; "new_rule_succeeds_v4")]
3273 #[test_case(
3274 RouteNetlinkMessage::NewRule,
3275 0,
3276 AF_INET6 as u16,
3277 vec![FakeRuleRequestResponse{
3278 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3279 expected_ip_version: IpVersion::V6,
3280 response: Ok(()),
3281 }],
3282 None; "new_rule_succeeds_v6")]
3283 #[test_case(
3284 RouteNetlinkMessage::NewRule,
3285 0,
3286 AF_UNSPEC as u16,
3287 vec![],
3288 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "new_rule_af_unspec_fails")]
3289 #[test_case(
3290 RouteNetlinkMessage::NewRule,
3291 NLM_F_ACK,
3292 AF_INET as u16,
3293 vec![FakeRuleRequestResponse{
3294 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3295 expected_ip_version: IpVersion::V4,
3296 response: Ok(()),
3297 }],
3298 Some(ExpectedResponse::Ack); "new_rule_v4_succeeds_with_ack")]
3299 #[test_case(
3300 RouteNetlinkMessage::NewRule,
3301 NLM_F_ACK,
3302 AF_INET6 as u16,
3303 vec![FakeRuleRequestResponse{
3304 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3305 expected_ip_version: IpVersion::V6,
3306 response: Ok(()),
3307 }],
3308 Some(ExpectedResponse::Ack); "new_rule_v6_succeeds_with_ack")]
3309 #[test_case(
3310 RouteNetlinkMessage::NewRule,
3311 0,
3312 AF_INET as u16,
3313 vec![FakeRuleRequestResponse{
3314 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3315 expected_ip_version: IpVersion::V4,
3316 response: Err(Errno::ENOTSUP),
3317 }],
3318 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v4_fails")]
3319 #[test_case(
3320 RouteNetlinkMessage::NewRule,
3321 0,
3322 AF_INET6 as u16,
3323 vec![FakeRuleRequestResponse{
3324 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3325 expected_ip_version: IpVersion::V6,
3326 response: Err(Errno::ENOTSUP),
3327 }],
3328 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v6_fails")]
3329 #[test_case(
3330 RouteNetlinkMessage::NewRule,
3331 NLM_F_REPLACE,
3332 AF_INET as u16,
3333 vec![],
3334 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v4_replace_unimplemented")]
3335 #[test_case(
3336 RouteNetlinkMessage::NewRule,
3337 NLM_F_REPLACE,
3338 AF_INET6 as u16,
3339 vec![],
3340 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v6_replace_unimplemented")]
3341 #[test_case(
3342 RouteNetlinkMessage::DelRule,
3343 0,
3344 AF_INET as u16,
3345 vec![FakeRuleRequestResponse{
3346 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3347 expected_ip_version: IpVersion::V4,
3348 response: Ok(()),
3349 }],
3350 None; "del_rule_succeeds_v4")]
3351 #[test_case(
3352 RouteNetlinkMessage::DelRule,
3353 0,
3354 AF_INET6 as u16,
3355 vec![FakeRuleRequestResponse{
3356 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3357 expected_ip_version: IpVersion::V6,
3358 response: Ok(()),
3359 }],
3360 None; "del_rule_succeeds_v6")]
3361 #[test_case(
3362 RouteNetlinkMessage::DelRule,
3363 0,
3364 AF_UNSPEC as u16,
3365 vec![],
3366 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "del_rule_af_unspec_fails")]
3367 #[test_case(
3368 RouteNetlinkMessage::DelRule,
3369 NLM_F_ACK,
3370 AF_INET as u16,
3371 vec![FakeRuleRequestResponse{
3372 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3373 expected_ip_version: IpVersion::V4,
3374 response: Ok(()),
3375 }],
3376 Some(ExpectedResponse::Ack); "del_rule_v4_succeeds_with_ack")]
3377 #[test_case(
3378 RouteNetlinkMessage::DelRule,
3379 NLM_F_ACK,
3380 AF_INET6 as u16,
3381 vec![FakeRuleRequestResponse{
3382 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3383 expected_ip_version: IpVersion::V6,
3384 response: Ok(()),
3385 }],
3386 Some(ExpectedResponse::Ack); "del_rule_v6_succeeds_with_ack")]
3387 #[test_case(
3388 RouteNetlinkMessage::DelRule,
3389 0,
3390 AF_INET as u16,
3391 vec![FakeRuleRequestResponse{
3392 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3393 expected_ip_version: IpVersion::V4,
3394 response: Err(Errno::ENOTSUP),
3395 }],
3396 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "del_rule_v4_fails")]
3397 #[test_case(
3398 RouteNetlinkMessage::DelRule,
3399 0,
3400 AF_INET6 as u16,
3401 vec![FakeRuleRequestResponse{
3402 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3403 expected_ip_version: IpVersion::V6,
3404 response: Err(Errno::ENOTSUP),
3405 }],
3406 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "del_rule_v6_fails")]
3407 #[fuchsia::test]
3408 async fn test_rule_request(
3409 rule_fn: fn(RuleMessage) -> RouteNetlinkMessage,
3410 flags: u16,
3411 address_family: u16,
3412 requests_and_responses: Vec<FakeRuleRequestResponse>,
3413 expected_response: Option<ExpectedResponse>,
3414 ) {
3415 let rules_request_handler = FakeRuleRequestHandler::new(requests_and_responses);
3416 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
3417 let unified_request_stream = pin!(unified_request_stream);
3418 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
3419
3420 let (mut client_sink, mut client, async_work_drain_task) = {
3421 crate::client::testutil::new_fake_client::<NetlinkRoute>(
3422 crate::client::testutil::CLIENT_ID_1,
3423 std::iter::empty(),
3424 )
3425 };
3426 let join_handle = fasync::Task::spawn(async_work_drain_task);
3427
3428 let header = header_with_flags(flags);
3429
3430 futures::select! {
3431 () = handler.handle_request(
3432 NetlinkMessage::new(
3433 header,
3434 NetlinkPayload::InnerMessage(rule_fn(default_rule_for_family(address_family))),
3435 ),
3436 &mut client,
3437 ).fuse() => {},
3438 _rules_request_handler = unified_request_stream.fold(
3439 rules_request_handler,
3440 |mut rules_request_handler, req| async move {
3441 match req {
3442 UnifiedRequest::RuleV4Request(request, completer) => {
3443 completer
3444 .send(rules_request_handler.handle_request(request))
3445 .expect("send should succeed");
3446 rules_request_handler
3447 }
3448 UnifiedRequest::RuleV6Request(request, completer) => {
3449 completer
3450 .send(rules_request_handler.handle_request(request))
3451 .expect("send should succeed");
3452 rules_request_handler
3453 }
3454 _ => panic!("not RuleRequest"),
3455 }
3456 }
3457 ).fuse() => {},
3458 }
3459
3460 match expected_response {
3461 Some(ExpectedResponse::Ack) => {
3462 assert_eq!(
3463 client_sink.take_messages(),
3464 [SentMessage::unicast(netlink_packet::new_error(Ok(()), header))]
3465 )
3466 }
3467 Some(ExpectedResponse::Error(e)) => {
3468 assert_eq!(
3469 client_sink.take_messages(),
3470 [SentMessage::unicast(netlink_packet::new_error(Err(e), header))]
3471 )
3472 }
3473 Some(ExpectedResponse::Done) => {
3474 assert_eq!(
3475 client_sink.take_messages(),
3476 [SentMessage::unicast(netlink_packet::new_done(header))]
3477 )
3478 }
3479 None => {
3480 assert_eq!(client_sink.take_messages(), [])
3481 }
3482 }
3483 drop(client);
3484 join_handle.await;
3485 }
3486
3487 const TEST_V4_SUBNET: Subnet<Ipv4Addr> = net_subnet_v4!("192.0.2.0/24");
3488 const TEST_V4_NEXTHOP: Ipv4Addr = net_ip_v4!("192.0.2.1");
3489 const TEST_V6_SUBNET: Subnet<Ipv6Addr> = net_subnet_v6!("2001:db8::0/32");
3490 const TEST_V6_NEXTHOP: Ipv6Addr = net_ip_v6!("2001:db8::1");
3491
3492 fn test_nexthop_spec_addr<I: Ip>() -> SpecifiedAddr<I::Addr> {
3493 I::map_ip(
3494 (),
3495 |()| SpecifiedAddr::new(TEST_V4_NEXTHOP).unwrap(),
3496 |()| SpecifiedAddr::new(TEST_V6_NEXTHOP).unwrap(),
3497 )
3498 }
3499
3500 #[derive(Clone)]
3501 struct RouteRequestAndResponse<R> {
3502 request: R,
3503 response: Result<(), routes::RequestError>,
3504 }
3505
3506 #[derive(Clone, Copy)]
3507 enum RouteRequestKind {
3508 New,
3509 Del,
3510 }
3511
3512 struct TestRouteCase<I: Ip> {
3513 kind: RouteRequestKind,
3514 flags: u16,
3515 family: u16,
3516 nlas: Vec<RouteAttribute>,
3517 destination_prefix_len: u8,
3518 table: u8,
3519 rtm_type: u8,
3520 expected_request_args: Option<RouteRequestAndResponse<routes::RouteRequestArgs<I>>>,
3521 expected_response: Option<ExpectedResponse>,
3522 }
3523
3524 fn route_addr_from_spec_addr<I: Ip>(a: &SpecifiedAddr<I::Addr>) -> RouteAddress {
3525 let bytes = I::map_ip_in(a, |a| a.ipv4_bytes().to_vec(), |a| a.ipv6_bytes().to_vec());
3526 match I::VERSION {
3527 IpVersion::V4 => RouteAddress::parse(AddressFamily::Inet, &bytes).unwrap(),
3528 IpVersion::V6 => RouteAddress::parse(AddressFamily::Inet6, &bytes).unwrap(),
3529 }
3530 }
3531
3532 fn route_addr_from_subnet<I: Ip>(a: &Subnet<I::Addr>) -> RouteAddress {
3533 let bytes = I::map_ip_in(
3534 a,
3535 |a| a.network().ipv4_bytes().to_vec(),
3536 |a| a.network().ipv6_bytes().to_vec(),
3537 );
3538 match I::VERSION {
3539 IpVersion::V4 => RouteAddress::parse(AddressFamily::Inet, &bytes).unwrap(),
3540 IpVersion::V6 => RouteAddress::parse(AddressFamily::Inet6, &bytes).unwrap(),
3541 }
3542 }
3543
3544 fn build_route_test_case<I: Ip>(
3545 kind: RouteRequestKind,
3546 flags: u16,
3547 dst: Subnet<I::Addr>,
3548 next_hop: Option<SpecifiedAddr<I::Addr>>,
3549 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3550 interface_id: Option<NonZeroU64>,
3551 table: u8,
3552 rtm_type: u8,
3553 response: Result<(), routes::RequestError>,
3554 ) -> TestRouteCase<I> {
3555 let extra_nlas = extra_nlas.into_iter().collect::<Vec<_>>();
3556 let table_from_nla = extra_nlas.clone().into_iter().find_map(|nla| match nla {
3557 RouteAttribute::Table(table) => Some(NetlinkRouteTableIndex::new(table)),
3558 _ => None,
3559 });
3560 let priority_from_nla = extra_nlas.clone().into_iter().find_map(|nla| match nla {
3561 RouteAttribute::Priority(priority) => Some(priority),
3562 _ => None,
3563 });
3564
3565 TestRouteCase::<I> {
3566 kind,
3567 flags,
3568 family: {
3569 let family = match I::VERSION {
3570 IpVersion::V4 => AF_INET,
3571 IpVersion::V6 => AF_INET6,
3572 };
3573 family as u16
3575 },
3576 nlas: [RouteAttribute::Destination(route_addr_from_subnet::<I>(&dst))]
3577 .into_iter()
3578 .chain(interface_id.map(|id| RouteAttribute::Oif(interface_id_as_u32(id.get()))))
3579 .chain(extra_nlas.into_iter())
3580 .collect(),
3581 destination_prefix_len: {
3582 let prefix_len = I::map_ip_in(dst, |dst| dst.prefix(), |dst| dst.prefix());
3583 prefix_len
3584 },
3585 table,
3586 rtm_type,
3587 expected_request_args: Some(RouteRequestAndResponse {
3588 request: {
3589 match kind {
3590 RouteRequestKind::New => {
3591 let interface_id =
3592 interface_id.expect("new requests must have interface id");
3593
3594 routes::RouteRequestArgs::New::<I>(routes::NewRouteArgs::Unicast(
3595 routes::UnicastNewRouteArgs {
3596 subnet: dst,
3597 target: fnet_routes_ext::RouteTarget {
3598 outbound_interface: interface_id.get(),
3599 next_hop,
3600 },
3601 priority: priority_from_nla.and_then(NonZeroU32::new),
3602 table: table_from_nla.unwrap_or_else(|| {
3604 NetlinkRouteTableIndex::new(table as u32)
3605 }),
3606 },
3607 ))
3608 }
3609 RouteRequestKind::Del => {
3610 routes::RouteRequestArgs::Del::<I>(routes::DelRouteArgs::Unicast(
3611 routes::UnicastDelRouteArgs {
3612 subnet: dst,
3613 outbound_interface: interface_id,
3614 next_hop,
3615 priority: priority_from_nla
3616 .map(|priority| NonZeroU32::new(priority))
3617 .flatten(),
3618 table: table_from_nla
3622 .map(|table_nla| {
3623 NonZeroNetlinkRouteTableIndex::new(table_nla)
3624 })
3625 .flatten()
3626 .unwrap_or_else(|| {
3627 NonZeroNetlinkRouteTableIndex::new_non_zero(
3628 NonZeroU32::new(table as u32).unwrap_or(
3629 NonZeroU32::new(
3630 rt_class_t_RT_TABLE_MAIN as u32,
3631 )
3632 .unwrap(),
3633 ),
3634 )
3635 }),
3636 },
3637 ))
3638 }
3639 }
3640 },
3641 response,
3642 }),
3643 expected_response: (flags & NLM_F_ACK == NLM_F_ACK).then_some(ExpectedResponse::Ack),
3644 }
3645 }
3646
3647 fn build_valid_route_test_case_with_extra_nlas<I: Ip>(
3648 kind: RouteRequestKind,
3649 flags: u16,
3650 addr: Subnet<I::Addr>,
3651 next_hop: Option<SpecifiedAddr<I::Addr>>,
3652 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3653 interface_id: Option<u64>,
3654 table: u8,
3655 rtm_type: u8,
3656 response: Result<(), routes::RequestError>,
3657 ) -> TestRouteCase<I> {
3658 build_route_test_case::<I>(
3659 kind,
3660 flags,
3661 addr,
3662 next_hop,
3663 extra_nlas,
3664 interface_id.map(|id| NonZeroU64::new(id)).flatten(),
3665 table,
3666 rtm_type,
3667 response,
3668 )
3669 }
3670
3671 fn build_valid_route_test_case<I: Ip>(
3672 kind: RouteRequestKind,
3673 flags: u16,
3674 addr: Subnet<I::Addr>,
3675 interface_id: Option<u64>,
3676 table: u8,
3677 rtm_type: u8,
3678 response: Result<(), routes::RequestError>,
3679 ) -> TestRouteCase<I> {
3680 build_valid_route_test_case_with_extra_nlas::<I>(
3681 kind,
3682 flags,
3683 addr,
3684 None,
3685 None,
3686 interface_id,
3687 table,
3688 rtm_type,
3689 response,
3690 )
3691 }
3692
3693 fn build_invalid_route_test_case<I: Ip>(
3694 kind: RouteRequestKind,
3695 flags: u16,
3696 addr: Subnet<I::Addr>,
3697 interface_id: Option<u64>,
3698 table: u8,
3699 rtm_type: u8,
3700 errno: Errno,
3701 ) -> TestRouteCase<I> {
3702 build_invalid_route_test_case_with_extra_nlas::<I>(
3703 kind,
3704 flags,
3705 addr,
3706 None,
3707 None,
3708 interface_id,
3709 table,
3710 rtm_type,
3711 errno,
3712 )
3713 }
3714
3715 fn build_invalid_route_test_case_with_extra_nlas<I: Ip>(
3716 kind: RouteRequestKind,
3717 flags: u16,
3718 addr: Subnet<I::Addr>,
3719 next_hop: Option<SpecifiedAddr<I::Addr>>,
3720 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3721 interface_id: Option<u64>,
3722 table: u8,
3723 rtm_type: u8,
3724 errno: Errno,
3725 ) -> TestRouteCase<I> {
3726 TestRouteCase {
3727 expected_request_args: None,
3728 expected_response: Some(ExpectedResponse::Error(errno)),
3729 ..build_valid_route_test_case_with_extra_nlas::<I>(
3730 kind,
3731 flags,
3732 addr,
3733 next_hop,
3734 extra_nlas,
3735 interface_id,
3736 table,
3737 rtm_type,
3738 Ok(()),
3739 )
3740 }
3741 }
3742
3743 #[derive(Clone, Debug, PartialEq)]
3744 enum RouteRequestArgsEither {
3745 V4(routes::RequestArgs<Ipv4>),
3746 V6(routes::RequestArgs<Ipv6>),
3747 }
3748
3749 async fn test_route_request<I: Ip>(
3750 request: NetlinkMessage<RouteNetlinkMessage>,
3751 req_and_resp: Option<RouteRequestAndResponse<routes::RouteRequestArgs<I>>>,
3752 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
3753 let (mut client_sink, mut client, async_work_drain_task) = {
3754 crate::client::testutil::new_fake_client::<NetlinkRoute>(
3755 crate::client::testutil::CLIENT_ID_1,
3756 std::iter::empty(),
3757 )
3758 };
3759 let join_handle = fasync::Task::spawn(async_work_drain_task);
3760
3761 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
3762 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
3763
3764 let mut unified_request_stream = pin!(unified_request_stream);
3765
3766 match req_and_resp {
3767 None => {
3768 handler.handle_request(request, &mut client).await;
3769 assert_matches!(unified_request_stream.next().now_or_never(), None);
3770 }
3771 Some(RouteRequestAndResponse { request: expected_request, response }) => {
3772 let ((), ()) =
3773 futures::join!(handler.handle_request(request, &mut client), async {
3774 let args = match I::VERSION {
3775 IpVersion::V4 => {
3776 let next = unified_request_stream.next();
3777 let routes::Request {
3778 args,
3779 sequence_number: _,
3780 client: _,
3781 completer,
3782 } = match next.await.expect("handler should send request") {
3783 UnifiedRequest::RoutesV4Request(request) => request,
3784 UnifiedRequest::InterfacesRequest(_)
3785 | UnifiedRequest::RoutesV6Request(_)
3786 | UnifiedRequest::RuleV4Request(_, _)
3787 | UnifiedRequest::RuleV6Request(_, _) => {
3788 panic!("not RoutesV4Request")
3789 }
3790 };
3791 completer.send(response).expect("handler should be alive");
3792 RouteRequestArgsEither::V4(args)
3793 }
3794 IpVersion::V6 => {
3795 let next = unified_request_stream.next();
3796 let routes::Request {
3797 args,
3798 sequence_number: _,
3799 client: _,
3800 completer,
3801 } = match next.await.expect("handler should send request") {
3802 UnifiedRequest::RoutesV6Request(request) => request,
3803 UnifiedRequest::InterfacesRequest(_)
3804 | UnifiedRequest::RoutesV4Request(_)
3805 | UnifiedRequest::RuleV4Request(_, _)
3806 | UnifiedRequest::RuleV6Request(_, _) => {
3807 panic!("not RoutesV6Request")
3808 }
3809 };
3810 completer.send(response).expect("handler should be alive");
3811 RouteRequestArgsEither::V6(args)
3812 }
3813 };
3814
3815 #[derive(GenericOverIp)]
3816 #[generic_over_ip(I, Ip)]
3817 struct EqualityInputs<I: Ip> {
3818 args: RouteRequestArgsEither,
3819 expected_request: routes::RequestArgs<I>,
3820 }
3821
3822 I::map_ip_in(
3823 EqualityInputs {
3824 args: args,
3825 expected_request: routes::RequestArgs::Route(expected_request),
3826 },
3827 |EqualityInputs { args, expected_request }| {
3828 let args = assert_matches!(
3829 args,
3830 RouteRequestArgsEither::V4(request) => request
3831 );
3832 assert_eq!(args, expected_request);
3833 },
3834 |EqualityInputs { args, expected_request }| {
3835 let args = assert_matches!(
3836 args,
3837 RouteRequestArgsEither::V6(request) => request
3838 );
3839 assert_eq!(args, expected_request);
3840 },
3841 );
3842 });
3843 }
3844 }
3845
3846 drop(client);
3847 join_handle.await;
3848 client_sink.take_messages()
3849 }
3850
3851 #[test_case(
3855 TestRouteCase::<Ipv4> {
3856 family: AF_UNSPEC as u16,
3857 ..build_invalid_route_test_case(
3858 RouteRequestKind::New,
3859 NLM_F_ACK,
3860 TEST_V4_SUBNET,
3861 Some(interfaces::testutil::LO_INTERFACE_ID),
3862 rt_class_t_RT_TABLE_MAIN as u8,
3863 RTN_UNICAST as u8,
3864 Errno::EINVAL,
3865 )
3866 }; "new_v4_invalid_family_ack")]
3867 #[test_case(
3868 TestRouteCase::<Ipv6> {
3869 family: AF_UNSPEC as u16,
3870 ..build_invalid_route_test_case(
3871 RouteRequestKind::New,
3872 0,
3873 TEST_V6_SUBNET,
3874 Some(interfaces::testutil::LO_INTERFACE_ID),
3875 rt_class_t_RT_TABLE_MAIN as u8,
3876 RTN_UNICAST as u8,
3877 Errno::EINVAL,
3878 )
3879 })]
3880 #[test_case(
3881 TestRouteCase::<Ipv4> {
3882 flags: NLM_F_ACK | NLM_F_REPLACE,
3883 ..build_invalid_route_test_case::<Ipv4>(
3884 RouteRequestKind::New,
3885 NLM_F_ACK,
3886 TEST_V4_SUBNET,
3887 Some(interfaces::testutil::LO_INTERFACE_ID),
3888 rt_class_t_RT_TABLE_MAIN as u8,
3889 RTN_UNICAST as u8,
3890 Errno::ENOTSUP,
3891 )
3892 }; "new_v4_replace_flag_ack")]
3893 #[test_case(
3894 build_invalid_route_test_case::<Ipv6>(
3895 RouteRequestKind::New,
3896 NLM_F_REPLACE,
3897 TEST_V6_SUBNET,
3898 Some(interfaces::testutil::LO_INTERFACE_ID),
3899 rt_class_t_RT_TABLE_MAIN as u8,
3900 RTN_UNICAST as u8,
3901 Errno::ENOTSUP,
3902 ); "new_v6_replace_flag_no_ack")]
3903 #[test_case(
3904 build_invalid_route_test_case::<Ipv4>(
3905 RouteRequestKind::New,
3906 NLM_F_ACK,
3907 TEST_V4_SUBNET,
3908 Some(interfaces::testutil::LO_INTERFACE_ID),
3909 rt_class_t_RT_TABLE_MAIN as u8,
3910 RTN_MULTICAST as u8,
3911 Errno::ENOTSUP); "new_v4_non_unicast_type_ack")]
3912 #[test_case(
3913 build_invalid_route_test_case::<Ipv6>(
3914 RouteRequestKind::New,
3915 0,
3916 TEST_V6_SUBNET,
3917 Some(interfaces::testutil::LO_INTERFACE_ID),
3918 rt_class_t_RT_TABLE_MAIN as u8,
3919 RTN_MULTICAST as u8,
3920 Errno::ENOTSUP); "new_v6_non_unicast_type_no_ack")]
3921 #[test_case(
3922 build_valid_route_test_case::<Ipv4>(
3923 RouteRequestKind::New,
3924 NLM_F_ACK,
3925 net_subnet_v4!("0.0.0.0/0"),
3926 Some(interfaces::testutil::LO_INTERFACE_ID),
3927 rt_class_t_RT_TABLE_MAIN as u8,
3928 RTN_UNICAST as u8,
3929 Ok(())); "new_v4_default_route_ok_ack")]
3930 #[test_case(
3931 build_valid_route_test_case::<Ipv4>(
3932 RouteRequestKind::New,
3933 0,
3934 net_subnet_v4!("0.0.0.0/24"),
3935 Some(interfaces::testutil::LO_INTERFACE_ID),
3936 rt_class_t_RT_TABLE_MAIN as u8,
3937 RTN_UNICAST as u8,
3938 Ok(())); "new_v4_unspecified_route_non_zero_prefix_ok_no_ack")]
3939 #[test_case(
3940 build_valid_route_test_case::<Ipv6>(
3941 RouteRequestKind::New,
3942 NLM_F_ACK,
3943 net_subnet_v6!("::/0"),
3944 Some(interfaces::testutil::LO_INTERFACE_ID),
3945 rt_class_t_RT_TABLE_MAIN as u8,
3946 RTN_UNICAST as u8,
3947 Ok(())); "new_v6_default_route_prefix_ack")]
3948 #[test_case(
3949 build_valid_route_test_case::<Ipv6>(
3950 RouteRequestKind::New,
3951 0,
3952 net_subnet_v6!("::/64"),
3953 Some(interfaces::testutil::LO_INTERFACE_ID),
3954 rt_class_t_RT_TABLE_MAIN as u8,
3955 RTN_UNICAST as u8,
3956 Ok(())); "new_v6_unspecified_route_non_zero_prefix_no_ack")]
3957 #[test_case(
3958 build_valid_route_test_case::<Ipv4>(
3959 RouteRequestKind::New,
3960 NLM_F_ACK,
3961 TEST_V4_SUBNET,
3962 Some(interfaces::testutil::LO_INTERFACE_ID),
3963 rt_class_t_RT_TABLE_MAIN as u8,
3964 RTN_UNICAST as u8,
3965 Ok(())); "new_v4_ok_ack")]
3966 #[test_case(
3967 build_valid_route_test_case::<Ipv6>(
3968 RouteRequestKind::New,
3969 NLM_F_ACK,
3970 TEST_V6_SUBNET,
3971 Some(interfaces::testutil::LO_INTERFACE_ID),
3972 rt_class_t_RT_TABLE_MAIN as u8,
3973 RTN_UNICAST as u8,
3974 Ok(())); "new_v6_ok_ack")]
3975 #[test_case(
3976 build_valid_route_test_case::<Ipv4>(
3977 RouteRequestKind::New,
3978 0,
3979 TEST_V4_SUBNET,
3980 Some(interfaces::testutil::LO_INTERFACE_ID),
3981 rt_class_t_RT_TABLE_MAIN as u8,
3982 RTN_UNICAST as u8,
3983 Ok(())); "new_v4_ok_no_ack")]
3984 #[test_case(
3985 build_valid_route_test_case::<Ipv6>(
3986 RouteRequestKind::New,
3987 0,
3988 TEST_V6_SUBNET,
3989 Some(interfaces::testutil::LO_INTERFACE_ID),
3990 rt_class_t_RT_TABLE_MAIN as u8,
3991 RTN_UNICAST as u8,
3992 Ok(())); "new_v6_ok_no_ack")]
3993 #[test_case(
3994 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
3995 RouteRequestKind::New,
3996 NLM_F_ACK,
3997 TEST_V4_SUBNET,
3998 Some(test_nexthop_spec_addr::<Ipv4>()),
3999 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv4>(
4000 &test_nexthop_spec_addr::<Ipv4>()
4001 ))],
4002 Some(interfaces::testutil::LO_INTERFACE_ID),
4003 rt_class_t_RT_TABLE_MAIN as u8,
4004 RTN_UNICAST as u8,
4005 Ok(())); "new_v4_with_nexthop_ok_ack")]
4006 #[test_case(
4007 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4008 RouteRequestKind::New,
4009 0,
4010 TEST_V6_SUBNET,
4011 Some(test_nexthop_spec_addr::<Ipv6>()),
4012 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv6>(
4013 &test_nexthop_spec_addr::<Ipv6>()
4014 ))],
4015 Some(interfaces::testutil::LO_INTERFACE_ID),
4016 rt_class_t_RT_TABLE_MAIN as u8,
4017 RTN_UNICAST as u8,
4018 Ok(())); "new_v6_with_nexthop_ok_no_ack")]
4019 #[test_case(
4020 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4021 RouteRequestKind::New,
4022 NLM_F_ACK,
4023 TEST_V4_SUBNET,
4024 None,
4025 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet, &net_ip_v4!("0.0.0.0").ipv4_bytes().to_vec()).unwrap())],
4026 Some(interfaces::testutil::LO_INTERFACE_ID),
4027 rt_class_t_RT_TABLE_MAIN as u8,
4028 RTN_UNICAST as u8,
4029 Ok(())); "new_v4_unspecified_nexthop_ok_ack")]
4030 #[test_case(
4031 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4032 RouteRequestKind::New,
4033 0,
4034 TEST_V6_SUBNET,
4035 None,
4036 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet6, &net_ip_v6!("::").ipv6_bytes().to_vec()).unwrap())],
4037 Some(interfaces::testutil::LO_INTERFACE_ID),
4038 rt_class_t_RT_TABLE_MAIN as u8,
4039 RTN_UNICAST as u8,
4040 Ok(())); "new_v6_unspecified_nexthop_no_ack")]
4041 #[test_case(
4042 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4043 RouteRequestKind::New,
4044 NLM_F_ACK,
4045 TEST_V4_SUBNET,
4046 None,
4047 [RouteAttribute::Priority(100)],
4048 Some(interfaces::testutil::LO_INTERFACE_ID),
4049 rt_class_t_RT_TABLE_MAIN as u8,
4050 RTN_UNICAST as u8,
4051 Ok(())); "new_v4_priority_nla_ok_ack")]
4052 #[test_case(
4053 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4054 RouteRequestKind::New,
4055 0,
4056 TEST_V6_SUBNET,
4057 None,
4058 [RouteAttribute::Priority(100)],
4059 Some(interfaces::testutil::LO_INTERFACE_ID),
4060 rt_class_t_RT_TABLE_MAIN as u8,
4061 RTN_UNICAST as u8,
4062 Ok(())); "new_v6_priority_nla_ok_no_ack")]
4063 #[test_case(
4064 TestRouteCase::<Ipv4> {
4065 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4066 ..build_valid_route_test_case(
4067 RouteRequestKind::New,
4068 NLM_F_ACK,
4069 TEST_V4_SUBNET,
4070 Some(interfaces::testutil::LO_INTERFACE_ID),
4071 rt_class_t_RT_TABLE_MAIN as u8,
4072 RTN_UNICAST as u8,
4073 Err(routes::RequestError::InvalidRequest),
4074 )
4075 }; "new_v4_invalid_request_response_ack")]
4076 #[test_case(
4077 TestRouteCase::<Ipv6> {
4078 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4079 ..build_valid_route_test_case(
4080 RouteRequestKind::New,
4081 NLM_F_ACK,
4082 TEST_V6_SUBNET,
4083 Some(interfaces::testutil::LO_INTERFACE_ID),
4084 rt_class_t_RT_TABLE_MAIN as u8,
4085 RTN_UNICAST as u8,
4086 Err(routes::RequestError::InvalidRequest),
4087 )
4088 }; "new_v6_invalid_request_response_no_ack")]
4089 #[test_case(
4090 TestRouteCase::<Ipv6> {
4091 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
4092 ..build_valid_route_test_case(
4093 RouteRequestKind::New,
4094 0,
4095 TEST_V6_SUBNET,
4096 Some(interfaces::testutil::LO_INTERFACE_ID),
4097 rt_class_t_RT_TABLE_MAIN as u8,
4098 RTN_UNICAST as u8,
4099 Err(routes::RequestError::UnrecognizedInterface),
4100 )
4101 }; "new_v6_unrecognized_interface_response_no_ack")]
4102 #[test_case(
4103 TestRouteCase::<Ipv6> {
4104 expected_response: Some(ExpectedResponse::Error(Errno::ENOTSUP)),
4105 ..build_valid_route_test_case(
4106 RouteRequestKind::New,
4107 0,
4108 TEST_V6_SUBNET,
4109 Some(interfaces::testutil::LO_INTERFACE_ID),
4110 rt_class_t_RT_TABLE_MAIN as u8,
4111 RTN_UNICAST as u8,
4112 Err(routes::RequestError::Unknown),
4113 )
4114 }; "new_v6_unknown_response_no_ack")]
4115 #[test_case(
4116 TestRouteCase::<Ipv4> {
4117 nlas: vec![
4118 RouteAttribute::Destination(route_addr_from_subnet::<Ipv4>(
4119 &TEST_V4_SUBNET
4120 )),
4121 ],
4122 ..build_invalid_route_test_case(
4123 RouteRequestKind::New,
4124 0,
4125 TEST_V4_SUBNET,
4126 Some(interfaces::testutil::LO_INTERFACE_ID),
4127 rt_class_t_RT_TABLE_MAIN as u8,
4128 RTN_UNICAST as u8,
4129 Errno::ENOTSUP,
4130 )
4131 }; "new_v4_missing_oif_nla_ack")]
4132 #[test_case(
4133 TestRouteCase::<Ipv6> {
4134 nlas: vec![
4135 RouteAttribute::Destination(route_addr_from_subnet::<Ipv6>(
4136 &TEST_V6_SUBNET
4137 )),
4138 ],
4139 ..build_invalid_route_test_case(
4140 RouteRequestKind::New,
4141 0,
4142 TEST_V6_SUBNET,
4143 Some(interfaces::testutil::LO_INTERFACE_ID),
4144 rt_class_t_RT_TABLE_MAIN as u8,
4145 RTN_UNICAST as u8,
4146 Errno::ENOTSUP,
4147 )
4148 }; "new_v6_missing_oif_nla_ack")]
4149 #[test_case(
4150 TestRouteCase::<Ipv4> {
4151 nlas: vec![
4152 RouteAttribute::Destination(route_addr_from_subnet::<Ipv4>(
4153 &TEST_V4_SUBNET
4154 )),
4155 ],
4156 ..build_invalid_route_test_case(
4157 RouteRequestKind::New,
4158 0,
4159 TEST_V4_SUBNET,
4160 Some(interfaces::testutil::LO_INTERFACE_ID),
4161 rt_class_t_RT_TABLE_MAIN as u8,
4162 RTN_UNICAST as u8,
4163 Errno::ENOTSUP,
4164 )
4165 }; "new_v4_missing_oif_nla_no_ack")]
4166 #[test_case(
4167 TestRouteCase::<Ipv6> {
4168 nlas: vec![
4169 RouteAttribute::Destination(route_addr_from_subnet::<Ipv6>(
4170 &TEST_V6_SUBNET
4171 )),
4172 ],
4173 ..build_invalid_route_test_case(
4174 RouteRequestKind::New,
4175 0,
4176 TEST_V6_SUBNET,
4177 Some(interfaces::testutil::LO_INTERFACE_ID),
4178 rt_class_t_RT_TABLE_MAIN as u8,
4179 RTN_UNICAST as u8,
4180 Errno::ENOTSUP,
4181 )
4182 }; "new_v6_missing_oif_nla_no_ack")]
4183 #[test_case(
4184 TestRouteCase::<Ipv4> {
4185 nlas: vec![
4186 RouteAttribute::Oif(interfaces::testutil::ETH_INTERFACE_ID.try_into().unwrap()),
4187 ],
4188 destination_prefix_len: 1,
4189 ..build_invalid_route_test_case(
4190 RouteRequestKind::New,
4191 NLM_F_ACK,
4192 TEST_V4_SUBNET,
4193 Some(interfaces::testutil::LO_INTERFACE_ID),
4194 rt_class_t_RT_TABLE_MAIN as u8,
4195 RTN_UNICAST as u8,
4196 Errno::EINVAL,
4197 )
4198 }; "new_v4_missing_destination_nla_nonzero_prefix_ack")]
4199 #[test_case(
4200 TestRouteCase::<Ipv6> {
4201 nlas: vec![
4202 RouteAttribute::Oif(interfaces::testutil::ETH_INTERFACE_ID.try_into().unwrap()),
4203 ],
4204 destination_prefix_len: 1,
4205 ..build_invalid_route_test_case(
4206 RouteRequestKind::New,
4207 0,
4208 TEST_V6_SUBNET,
4209 Some(interfaces::testutil::LO_INTERFACE_ID),
4210 rt_class_t_RT_TABLE_MAIN as u8,
4211 RTN_UNICAST as u8,
4212 Errno::EINVAL,
4213 )
4214 }; "new_v6_missing_destination_nla_nonzero_prefix_no_ack")]
4215 #[test_case(
4216 TestRouteCase::<Ipv4> {
4217 nlas: vec![
4218 RouteAttribute::Oif(interfaces::testutil::LO_INTERFACE_ID.try_into().unwrap()),
4219 ],
4220 ..build_valid_route_test_case(
4221 RouteRequestKind::New,
4222 NLM_F_ACK,
4223 net_subnet_v4!("0.0.0.0/0"),
4224 Some(interfaces::testutil::LO_INTERFACE_ID),
4225 rt_class_t_RT_TABLE_MAIN as u8,
4226 RTN_UNICAST as u8,
4227 Ok(()))}; "new_v4_missing_destination_nla_zero_prefix_ack")]
4228 #[test_case(
4229 TestRouteCase::<Ipv6> {
4230 nlas: vec![
4231 RouteAttribute::Oif(interfaces::testutil::LO_INTERFACE_ID.try_into().unwrap()),
4232 ],
4233 ..build_valid_route_test_case(
4234 RouteRequestKind::New,
4235 0,
4236 net_subnet_v6!("::/0"),
4237 Some(interfaces::testutil::LO_INTERFACE_ID),
4238 rt_class_t_RT_TABLE_MAIN as u8,
4239 RTN_UNICAST as u8,
4240 Ok(()))}; "new_v6_missing_destination_nla_zero_prefix_no_ack")]
4241 #[test_case(
4242 TestRouteCase::<Ipv4> {
4243 nlas: Vec::new(),
4244 ..build_invalid_route_test_case(
4245 RouteRequestKind::New,
4246 NLM_F_ACK,
4247 TEST_V4_SUBNET,
4248 Some(interfaces::testutil::LO_INTERFACE_ID),
4249 rt_class_t_RT_TABLE_MAIN as u8,
4250 RTN_UNICAST as u8,
4251 Errno::EINVAL,
4252 )
4253 }; "new_v4_no_nlas_ack")]
4254 #[test_case(
4255 TestRouteCase::<Ipv6> {
4256 nlas: Vec::new(),
4257 ..build_invalid_route_test_case(
4258 RouteRequestKind::New,
4259 0,
4260 TEST_V6_SUBNET,
4261 Some(interfaces::testutil::LO_INTERFACE_ID),
4262 rt_class_t_RT_TABLE_MAIN as u8,
4263 RTN_UNICAST as u8,
4264 Errno::EINVAL,
4265 )
4266 }; "new_v6_no_nlas_no_ack")]
4267 #[test_case(
4268 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4269 RouteRequestKind::New,
4270 NLM_F_ACK,
4271 TEST_V4_SUBNET,
4272 None,
4273 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4275 Some(interfaces::testutil::LO_INTERFACE_ID),
4276 rt_class_t_RT_TABLE_COMPAT as u8,
4277 RTN_UNICAST as u8,
4278 Ok(())); "new_v4_with_table_nla_rt_table_compat_ack")]
4279 #[test_case(
4280 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4281 RouteRequestKind::New,
4282 0,
4283 TEST_V6_SUBNET,
4284 None,
4285 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4287 Some(interfaces::testutil::LO_INTERFACE_ID),
4288 rt_class_t_RT_TABLE_COMPAT as u8,
4289 RTN_UNICAST as u8,
4290 Ok(())); "new_v6_with_table_nla_rt_table_compat_no_ack")]
4291 #[test_case(
4292 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4293 RouteRequestKind::New,
4294 NLM_F_ACK,
4295 TEST_V4_SUBNET,
4296 None,
4297 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4298 Some(interfaces::testutil::LO_INTERFACE_ID),
4299 rt_class_t_RT_TABLE_MAIN as u8,
4300 RTN_UNICAST as u8,
4301 Ok(())); "new_v4_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_ack")]
4302 #[test_case(
4303 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4304 RouteRequestKind::New,
4305 0,
4306 TEST_V6_SUBNET,
4307 None,
4308 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4309 Some(interfaces::testutil::LO_INTERFACE_ID),
4310 rt_class_t_RT_TABLE_MAIN as u8,
4311 RTN_UNICAST as u8,
4312 Ok(())); "new_v6_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_no_ack")]
4313 #[test_case(
4314 TestRouteCase::<Ipv4> {
4315 destination_prefix_len: u8::MAX,
4316 ..build_invalid_route_test_case(
4317 RouteRequestKind::New,
4318 NLM_F_ACK,
4319 TEST_V4_SUBNET,
4320 Some(interfaces::testutil::LO_INTERFACE_ID),
4321 rt_class_t_RT_TABLE_MAIN as u8,
4322 RTN_UNICAST as u8,
4323 Errno::EINVAL,
4324 )
4325 }; "new_v4_invalid_prefix_len_ack")]
4326 #[test_case(
4327 TestRouteCase::<Ipv6> {
4328 destination_prefix_len: u8::MAX,
4329 ..build_invalid_route_test_case(
4330 RouteRequestKind::New,
4331 0,
4332 TEST_V6_SUBNET,
4333 Some(interfaces::testutil::LO_INTERFACE_ID),
4334 rt_class_t_RT_TABLE_MAIN as u8,
4335 RTN_UNICAST as u8,
4336 Errno::EINVAL,
4337 )
4338 }; "new_v6_invalid_prefix_len_no_ack")]
4339 #[test_case(
4340 TestRouteCase::<Ipv4> {
4341 destination_prefix_len: 0,
4342 ..build_invalid_route_test_case(
4343 RouteRequestKind::New,
4344 NLM_F_ACK,
4345 TEST_V4_SUBNET,
4346 Some(interfaces::testutil::LO_INTERFACE_ID),
4347 rt_class_t_RT_TABLE_MAIN as u8,
4348 RTN_UNICAST as u8,
4349 Errno::EINVAL,
4350 )
4351 }; "new_v4_zero_prefix_len_ack")]
4352 #[test_case(
4353 TestRouteCase::<Ipv6> {
4354 destination_prefix_len: 0,
4355 ..build_invalid_route_test_case(
4356 RouteRequestKind::New,
4357 0,
4358 TEST_V6_SUBNET,
4359 Some(interfaces::testutil::LO_INTERFACE_ID),
4360 rt_class_t_RT_TABLE_MAIN as u8,
4361 RTN_UNICAST as u8,
4362 Errno::EINVAL,
4363 )
4364 }; "new_v6_zero_prefix_len_no_ack")]
4365 #[test_case(
4367 TestRouteCase::<Ipv4> {
4368 family: AF_UNSPEC as u16,
4369 ..build_invalid_route_test_case(
4370 RouteRequestKind::Del,
4371 NLM_F_ACK,
4372 TEST_V4_SUBNET,
4373 Some(interfaces::testutil::LO_INTERFACE_ID),
4374 rt_class_t_RT_TABLE_MAIN as u8,
4375 RTN_UNICAST as u8,
4376 Errno::EINVAL,
4377 )
4378 }; "del_v4_invalid_family_ack")]
4379 #[test_case(
4380 TestRouteCase::<Ipv6> {
4381 family: AF_UNSPEC as u16,
4382 ..build_invalid_route_test_case(
4383 RouteRequestKind::Del,
4384 0,
4385 TEST_V6_SUBNET,
4386 Some(interfaces::testutil::LO_INTERFACE_ID),
4387 rt_class_t_RT_TABLE_MAIN as u8,
4388 RTN_UNICAST as u8,
4389 Errno::EINVAL,
4390 )
4391 }; "del_v6_invalid_family_no_ack")]
4392 #[test_case(
4393 build_invalid_route_test_case::<Ipv4>(
4394 RouteRequestKind::Del,
4395 NLM_F_ACK,
4396 TEST_V4_SUBNET,
4397 Some(interfaces::testutil::LO_INTERFACE_ID),
4398 rt_class_t_RT_TABLE_MAIN as u8,
4399 RTN_MULTICAST as u8,
4400 Errno::ENOTSUP); "del_v4_non_unicast_type_ack")]
4401 #[test_case(
4402 build_invalid_route_test_case::<Ipv6>(
4403 RouteRequestKind::Del,
4404 0,
4405 TEST_V6_SUBNET,
4406 Some(interfaces::testutil::LO_INTERFACE_ID),
4407 rt_class_t_RT_TABLE_MAIN as u8,
4408 RTN_MULTICAST as u8,
4409 Errno::ENOTSUP); "del_v6_non_unicast_type_no_ack")]
4410 #[test_case(
4411 build_valid_route_test_case::<Ipv4>(
4412 RouteRequestKind::Del,
4413 NLM_F_ACK,
4414 net_subnet_v4!("0.0.0.0/0"),
4415 Some(interfaces::testutil::LO_INTERFACE_ID),
4416 rt_class_t_RT_TABLE_MAIN as u8,
4417 RTN_UNICAST as u8,
4418 Ok(())); "del_v4_default_route_ok_ack")]
4419 #[test_case(
4420 build_valid_route_test_case::<Ipv4>(
4421 RouteRequestKind::Del,
4422 0,
4423 net_subnet_v4!("0.0.0.0/24"),
4424 Some(interfaces::testutil::LO_INTERFACE_ID),
4425 rt_class_t_RT_TABLE_MAIN as u8,
4426 RTN_UNICAST as u8,
4427 Ok(())); "del_v4_unspecified_route_non_zero_prefix_ok_no_ack")]
4428 #[test_case(
4429 build_valid_route_test_case::<Ipv6>(
4430 RouteRequestKind::Del,
4431 NLM_F_ACK,
4432 net_subnet_v6!("::/0"),
4433 Some(interfaces::testutil::LO_INTERFACE_ID),
4434 rt_class_t_RT_TABLE_MAIN as u8,
4435 RTN_UNICAST as u8,
4436 Ok(())); "del_v6_default_route_prefix_ack")]
4437 #[test_case(
4438 build_valid_route_test_case::<Ipv6>(
4439 RouteRequestKind::Del,
4440 0,
4441 net_subnet_v6!("::/64"),
4442 Some(interfaces::testutil::LO_INTERFACE_ID),
4443 rt_class_t_RT_TABLE_MAIN as u8,
4444 RTN_UNICAST as u8,
4445 Ok(())); "del_v6_unspecified_route_non_zero_prefix_no_ack")]
4446 #[test_case(
4447 build_valid_route_test_case::<Ipv4>(
4448 RouteRequestKind::Del,
4449 NLM_F_ACK,
4450 TEST_V4_SUBNET,
4451 None,
4452 rt_class_t_RT_TABLE_MAIN as u8,
4453 RTN_UNICAST as u8,
4454 Ok(())); "del_v4_only_dest_nla_ack")]
4455 #[test_case(
4456 build_valid_route_test_case::<Ipv6>(
4457 RouteRequestKind::Del,
4458 NLM_F_ACK,
4459 TEST_V6_SUBNET,
4460 None,
4461 rt_class_t_RT_TABLE_MAIN as u8,
4462 RTN_UNICAST as u8,
4463 Ok(())); "del_v6_only_dest_nla_ack")]
4464 #[test_case(
4465 build_valid_route_test_case::<Ipv4>(
4466 RouteRequestKind::Del,
4467 0,
4468 TEST_V4_SUBNET,
4469 None,
4470 rt_class_t_RT_TABLE_MAIN as u8,
4471 RTN_UNICAST as u8,
4472 Ok(())); "del_v4_only_dest_nla_no_ack")]
4473 #[test_case(
4474 build_valid_route_test_case::<Ipv6>(
4475 RouteRequestKind::Del,
4476 0,
4477 TEST_V6_SUBNET,
4478 None,
4479 rt_class_t_RT_TABLE_MAIN as u8,
4480 RTN_UNICAST as u8,
4481 Ok(())); "del_v6_only_dest_nla_no_ack")]
4482 #[test_case(
4483 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4484 RouteRequestKind::Del,
4485 NLM_F_ACK,
4486 TEST_V4_SUBNET,
4487 Some(test_nexthop_spec_addr::<Ipv4>()),
4488 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv4>(
4489 &test_nexthop_spec_addr::<Ipv4>()
4490 ))],
4491 Some(interfaces::testutil::LO_INTERFACE_ID),
4492 rt_class_t_RT_TABLE_MAIN as u8,
4493 RTN_UNICAST as u8,
4494 Ok(())); "del_v4_with_nexthop_ok_ack")]
4495 #[test_case(
4496 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4497 RouteRequestKind::Del,
4498 0,
4499 TEST_V6_SUBNET,
4500 Some(test_nexthop_spec_addr::<Ipv6>()),
4501 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv6>(
4502 &test_nexthop_spec_addr::<Ipv6>()
4503 ))],
4504 Some(interfaces::testutil::LO_INTERFACE_ID),
4505 rt_class_t_RT_TABLE_MAIN as u8,
4506 RTN_UNICAST as u8,
4507 Ok(())); "del_v6_with_nexthop_ok_no_ack")]
4508 #[test_case(
4509 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4510 RouteRequestKind::Del,
4511 NLM_F_ACK,
4512 TEST_V4_SUBNET,
4513 None,
4514 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet, &net_ip_v4!("0.0.0.0").ipv4_bytes().to_vec()).unwrap())],
4515 Some(interfaces::testutil::LO_INTERFACE_ID),
4516 rt_class_t_RT_TABLE_MAIN as u8,
4517 RTN_UNICAST as u8,
4518 Ok(())); "del_v4_unspecified_nexthop_ok_ack")]
4519 #[test_case(
4520 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4521 RouteRequestKind::Del,
4522 0,
4523 TEST_V6_SUBNET,
4524 None,
4525 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet6, &net_ip_v6!("::").ipv6_bytes().to_vec()).unwrap())],
4526 Some(interfaces::testutil::LO_INTERFACE_ID),
4527 rt_class_t_RT_TABLE_MAIN as u8,
4528 RTN_UNICAST as u8,
4529 Ok(())); "del_v6_unspecified_nexthop_no_ack")]
4530 #[test_case(
4531 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4532 RouteRequestKind::Del,
4533 NLM_F_ACK,
4534 TEST_V4_SUBNET,
4535 None,
4536 [RouteAttribute::Priority(100)],
4537 Some(interfaces::testutil::LO_INTERFACE_ID),
4538 rt_class_t_RT_TABLE_MAIN as u8,
4539 RTN_UNICAST as u8,
4540 Ok(())); "del_v4_priority_nla_ok_ack")]
4541 #[test_case(
4542 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4543 RouteRequestKind::Del,
4544 0,
4545 TEST_V6_SUBNET,
4546 None,
4547 [RouteAttribute::Priority(100)],
4548 Some(interfaces::testutil::LO_INTERFACE_ID),
4549 rt_class_t_RT_TABLE_MAIN as u8,
4550 RTN_UNICAST as u8,
4551 Ok(())); "del_v6_priority_nla_ok_no_ack")]
4552 #[test_case(
4553 TestRouteCase::<Ipv4> {
4554 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4555 ..build_valid_route_test_case(
4556 RouteRequestKind::Del,
4557 NLM_F_ACK,
4558 TEST_V4_SUBNET,
4559 Some(interfaces::testutil::LO_INTERFACE_ID),
4560 rt_class_t_RT_TABLE_MAIN as u8,
4561 RTN_UNICAST as u8,
4562 Err(routes::RequestError::InvalidRequest),
4563 )
4564 }; "del_v4_invalid_request_response_ack")]
4565 #[test_case(
4566 TestRouteCase::<Ipv6> {
4567 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4568 ..build_valid_route_test_case(
4569 RouteRequestKind::Del,
4570 NLM_F_ACK,
4571 TEST_V6_SUBNET,
4572 Some(interfaces::testutil::LO_INTERFACE_ID),
4573 rt_class_t_RT_TABLE_MAIN as u8,
4574 RTN_UNICAST as u8,
4575 Err(routes::RequestError::InvalidRequest),
4576 )
4577 }; "del_v6_invalid_request_response_no_ack")]
4578 #[test_case(
4579 TestRouteCase::<Ipv6> {
4580 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
4581 ..build_valid_route_test_case(
4582 RouteRequestKind::Del,
4583 0,
4584 TEST_V6_SUBNET,
4585 Some(interfaces::testutil::LO_INTERFACE_ID),
4586 rt_class_t_RT_TABLE_MAIN as u8,
4587 RTN_UNICAST as u8,
4588 Err(routes::RequestError::UnrecognizedInterface),
4589 )
4590 }; "del_v6_unrecognized_interface_response_no_ack")]
4591 #[test_case(
4592 TestRouteCase::<Ipv6> {
4593 expected_response: Some(ExpectedResponse::Error(Errno::ENOTSUP)),
4594 ..build_valid_route_test_case(
4595 RouteRequestKind::Del,
4596 0,
4597 TEST_V6_SUBNET,
4598 Some(interfaces::testutil::LO_INTERFACE_ID),
4599 rt_class_t_RT_TABLE_MAIN as u8,
4600 RTN_UNICAST as u8,
4601 Err(routes::RequestError::Unknown),
4602 )
4603 }; "del_v6_unknown_response_no_ack")]
4604 #[test_case(
4605 build_valid_route_test_case::<Ipv4>(
4606 RouteRequestKind::Del,
4607 NLM_F_ACK,
4608 TEST_V4_SUBNET,
4609 Some(interfaces::testutil::LO_INTERFACE_ID),
4610 rt_class_t_RT_TABLE_MAIN as u8,
4611 RTN_UNICAST as u8,
4612 Ok(()),
4613 ); "del_v4_dest_oif_nlas_ack")]
4614 #[test_case(
4615 build_valid_route_test_case::<Ipv6>(
4616 RouteRequestKind::Del,
4617 NLM_F_ACK,
4618 TEST_V6_SUBNET,
4619 Some(interfaces::testutil::LO_INTERFACE_ID),
4620 rt_class_t_RT_TABLE_MAIN as u8,
4621 RTN_UNICAST as u8,
4622 Ok(()),
4623 ); "del_v6_dest_oif_nlas_ack")]
4624 #[test_case(
4625 build_valid_route_test_case::<Ipv4>(
4626 RouteRequestKind::Del,
4627 0,
4628 TEST_V4_SUBNET,
4629 Some(interfaces::testutil::LO_INTERFACE_ID),
4630 rt_class_t_RT_TABLE_MAIN as u8,
4631 RTN_UNICAST as u8,
4632 Ok(()),
4633 ); "del_v4_dest_oif_nlas_no_ack")]
4634 #[test_case(
4635 build_valid_route_test_case::<Ipv6>(
4636 RouteRequestKind::Del,
4637 0,
4638 TEST_V6_SUBNET,
4639 Some(interfaces::testutil::LO_INTERFACE_ID),
4640 rt_class_t_RT_TABLE_MAIN as u8,
4641 RTN_UNICAST as u8,
4642 Ok(()),
4643 ); "del_v6_dest_oif_nlas_no_ack")]
4644 #[test_case(
4645 TestRouteCase::<Ipv4> {
4646 nlas: Vec::new(),
4647 destination_prefix_len: 1,
4648 ..build_invalid_route_test_case(
4649 RouteRequestKind::Del,
4650 NLM_F_ACK,
4651 TEST_V4_SUBNET,
4652 Some(interfaces::testutil::LO_INTERFACE_ID),
4653 rt_class_t_RT_TABLE_MAIN as u8,
4654 RTN_UNICAST as u8,
4655 Errno::EINVAL,
4656 )
4657 }; "del_v4_missing_destination_nla_nonzero_prefix_ack")]
4658 #[test_case(
4659 TestRouteCase::<Ipv6> {
4660 nlas: Vec::new(),
4661 destination_prefix_len: 1,
4662 ..build_invalid_route_test_case(
4663 RouteRequestKind::Del,
4664 0,
4665 TEST_V6_SUBNET,
4666 Some(interfaces::testutil::LO_INTERFACE_ID),
4667 rt_class_t_RT_TABLE_MAIN as u8,
4668 RTN_UNICAST as u8,
4669 Errno::EINVAL,
4670 )
4671 }; "del_v6_missing_destination_nla_nonzero_prefix_no_ack")]
4672 #[test_case(
4673 TestRouteCase::<Ipv4> {
4674 nlas: Vec::new(),
4675 destination_prefix_len: 0,
4676 ..build_valid_route_test_case(
4677 RouteRequestKind::Del,
4678 NLM_F_ACK,
4679 net_subnet_v4!("0.0.0.0/0"),
4680 None,
4681 rt_class_t_RT_TABLE_MAIN as u8,
4682 RTN_UNICAST as u8,
4683 Ok(()),
4684 )
4685 }; "del_v4_no_nlas_zero_prefix_len_ack")]
4686 #[test_case(
4687 TestRouteCase::<Ipv6> {
4688 nlas: Vec::new(),
4689 destination_prefix_len: 0,
4690 ..build_valid_route_test_case(
4691 RouteRequestKind::Del,
4692 0,
4693 net_subnet_v6!("::/0"),
4694 None,
4695 rt_class_t_RT_TABLE_MAIN as u8,
4696 RTN_UNICAST as u8,
4697 Ok(()),
4698 )
4699 }; "del_v6_no_nlas_zero_prefix_len_no_ack")]
4700 #[test_case(
4701 build_valid_route_test_case::<Ipv4>(
4702 RouteRequestKind::Del,
4703 NLM_F_ACK,
4704 net_subnet_v4!("0.0.0.0/0"),
4705 Some(interfaces::testutil::LO_INTERFACE_ID),
4706 rt_class_t_RT_TABLE_MAIN as u8,
4707 RTN_UNICAST as u8,
4708 Ok(()),
4709 ); "del_v4_missing_destination_nla_zero_prefix_ack")]
4710 #[test_case(
4711 build_valid_route_test_case::<Ipv6>(
4712 RouteRequestKind::Del,
4713 0,
4714 net_subnet_v6!("::/0"),
4715 Some(interfaces::testutil::LO_INTERFACE_ID),
4716 rt_class_t_RT_TABLE_MAIN as u8,
4717 RTN_UNICAST as u8,
4718 Ok(()),
4719 ); "del_v6_missing_destination_nla_zero_prefix_no_ack")]
4720 #[test_case(
4721 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4722 RouteRequestKind::Del,
4723 NLM_F_ACK,
4724 TEST_V4_SUBNET,
4725 None,
4726 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4728 Some(interfaces::testutil::LO_INTERFACE_ID),
4729 rt_class_t_RT_TABLE_COMPAT as u8,
4730 RTN_UNICAST as u8,
4731 Ok(())); "del_v4_with_table_nla_rt_table_compat_ack")]
4732 #[test_case(
4733 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4734 RouteRequestKind::Del,
4735 0,
4736 TEST_V6_SUBNET,
4737 None,
4738 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4740 Some(interfaces::testutil::LO_INTERFACE_ID),
4741 rt_class_t_RT_TABLE_COMPAT as u8,
4742 RTN_UNICAST as u8,
4743 Ok(())); "del_v6_with_table_nla_rt_table_compat_no_ack")]
4744 #[test_case(
4745 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4746 RouteRequestKind::Del,
4747 NLM_F_ACK,
4748 TEST_V4_SUBNET,
4749 None,
4750 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4751 Some(interfaces::testutil::LO_INTERFACE_ID),
4752 rt_class_t_RT_TABLE_MAIN as u8,
4753 RTN_UNICAST as u8,
4754 Ok(())); "del_v4_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_ack")]
4755 #[test_case(
4756 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4757 RouteRequestKind::Del,
4758 0,
4759 TEST_V6_SUBNET,
4760 None,
4761 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4762 Some(interfaces::testutil::LO_INTERFACE_ID),
4763 rt_class_t_RT_TABLE_MAIN as u8,
4764 RTN_UNICAST as u8,
4765 Ok(())); "del_v6_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_no_ack")]
4766 #[test_case(
4767 TestRouteCase::<Ipv4> {
4768 destination_prefix_len: u8::MAX,
4769 ..build_invalid_route_test_case(
4770 RouteRequestKind::Del,
4771 NLM_F_ACK,
4772 TEST_V4_SUBNET,
4773 Some(interfaces::testutil::LO_INTERFACE_ID),
4774 rt_class_t_RT_TABLE_MAIN as u8,
4775 RTN_UNICAST as u8,
4776 Errno::EINVAL,
4777 )
4778 }; "del_v4_invalid_prefix_len_ack")]
4779 #[test_case(
4780 TestRouteCase::<Ipv6> {
4781 destination_prefix_len: u8::MAX,
4782 ..build_invalid_route_test_case(
4783 RouteRequestKind::Del,
4784 0,
4785 TEST_V6_SUBNET,
4786 Some(interfaces::testutil::LO_INTERFACE_ID),
4787 rt_class_t_RT_TABLE_MAIN as u8,
4788 RTN_UNICAST as u8,
4789 Errno::EINVAL,
4790 )
4791 }; "del_v6_invalid_prefix_len_no_ack")]
4792 #[test_case(
4793 TestRouteCase::<Ipv4> {
4794 destination_prefix_len: 0,
4795 ..build_invalid_route_test_case(
4796 RouteRequestKind::Del,
4797 NLM_F_ACK,
4798 TEST_V4_SUBNET,
4799 Some(interfaces::testutil::LO_INTERFACE_ID),
4800 rt_class_t_RT_TABLE_MAIN as u8,
4801 RTN_UNICAST as u8,
4802 Errno::EINVAL,
4803 )
4804 }; "del_v4_zero_prefix_len_ack")]
4805 #[test_case(
4806 TestRouteCase::<Ipv6> {
4807 destination_prefix_len: 0,
4808 ..build_invalid_route_test_case(
4809 RouteRequestKind::Del,
4810 0,
4811 TEST_V6_SUBNET,
4812 Some(interfaces::testutil::LO_INTERFACE_ID),
4813 rt_class_t_RT_TABLE_MAIN as u8,
4814 RTN_UNICAST as u8,
4815 Errno::EINVAL,
4816 )
4817 }; "del_v6_zero_prefix_len_no_ack")]
4818 #[test_case(
4819 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4820 RouteRequestKind::Del,
4821 NLM_F_ACK,
4822 TEST_V4_SUBNET,
4823 None,
4824 [RouteAttribute::Oif(0)],
4825 None,
4826 rt_class_t_RT_TABLE_MAIN as u8,
4827 RTN_UNICAST as u8,
4828 Ok(()),
4829 ); "del_v4_zero_interface_id_ack")]
4830 #[test_case(
4831 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4832 RouteRequestKind::Del,
4833 NLM_F_ACK,
4834 TEST_V6_SUBNET,
4835 None,
4836 [RouteAttribute::Oif(0)],
4837 None,
4838 rt_class_t_RT_TABLE_MAIN as u8,
4839 RTN_UNICAST as u8,
4840 Ok(()),
4841 ); "del_v6_zero_interface_id_no_ack")]
4842 #[fuchsia::test]
4843 async fn test_new_del_route<I: Ip>(test_case: TestRouteCase<I>) {
4844 let TestRouteCase {
4845 kind,
4846 flags,
4847 family,
4848 nlas,
4849 destination_prefix_len,
4850 table,
4851 rtm_type,
4852 expected_request_args,
4853 expected_response,
4854 }: TestRouteCase<I> = test_case;
4855
4856 let header = header_with_flags(flags);
4857 let route_message = {
4858 let mut message = RouteMessage::default();
4859 message.header.address_family = AddressFamily::from(family as u8);
4860 message.header.destination_prefix_length = destination_prefix_len;
4861 message.header.table = table;
4862 message.header.kind = RouteType::from(rtm_type);
4863 message.attributes = nlas;
4864 message
4865 };
4866
4867 let (message, request) = match kind {
4868 RouteRequestKind::New => {
4869 (RouteNetlinkMessage::NewRoute(route_message), expected_request_args)
4870 }
4871 RouteRequestKind::Del => {
4872 (RouteNetlinkMessage::DelRoute(route_message), expected_request_args)
4873 }
4874 };
4875
4876 pretty_assertions::assert_eq!(
4877 test_route_request(
4878 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(message)),
4879 request,
4880 )
4881 .await,
4882 expected_response
4883 .into_iter()
4884 .map(|response| SentMessage::unicast(match response {
4885 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), header),
4886 ExpectedResponse::Done => netlink_packet::new_done(header),
4887 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), header),
4888 }))
4889 .collect::<Vec<_>>(),
4890 )
4891 }
4892}