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