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