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