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