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