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