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