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 fidl_fuchsia_net as fnet;
1784 use fuchsia_async as fasync;
1785 use futures::SinkExt;
1786 use futures::channel::mpsc;
1787 use futures::future::FutureExt as _;
1788 use futures::stream::StreamExt as _;
1789 use linux_uapi::{
1790 AF_INET, AF_INET6, AF_UNSPEC, IFA_F_NOPREFIXROUTE, RTN_MULTICAST, RTN_UNICAST,
1791 net_device_flags_IFF_UP, rt_class_t_RT_TABLE_COMPAT, rt_class_t_RT_TABLE_MAIN,
1792 };
1793 use net_declare::{
1794 fidl_ip, net_addr_subnet, net_ip_v4, net_ip_v6, net_subnet_v4, net_subnet_v6, std_ip_v4,
1795 std_ip_v6,
1796 };
1797 use net_types::ip::{
1798 AddrSubnetEither, GenericOverIp, Ip, IpVersion, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Subnet,
1799 };
1800 use net_types::{SpecifiedAddr, Witness as _};
1801 use netlink_packet_core::{NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_REPLACE, NetlinkHeader};
1802
1803 use netlink_packet_route::address::{AddressAttribute, AddressFlags, AddressMessage};
1804 use netlink_packet_route::link::{InfoKind, LinkAttribute, LinkFlags, LinkInfo, LinkMessage};
1805 use netlink_packet_route::neighbour::{
1806 NeighbourAttribute, NeighbourHeader, NeighbourMessage, NeighbourState,
1807 };
1808 use netlink_packet_route::neighbour_discovery_user_option::{
1809 NeighbourDiscoveryIcmpType, NeighbourDiscoveryIcmpV6Type,
1810 NeighbourDiscoveryUserOptionHeader, NeighbourDiscoveryUserOptionMessage,
1811 };
1812 use netlink_packet_route::route::{RouteAddress, RouteAttribute, RouteMessage, RouteType};
1813 use netlink_packet_route::rule::RuleMessage;
1814 use netlink_packet_route::{AddressFamily, RouteNetlinkMessage};
1815 use test::testutil::AF_PACKET;
1816 use test_case::test_case;
1817
1818 use crate::messaging::testutil::{FakeSender, SentMessage};
1819 use crate::netlink_packet::errno::Errno;
1820 use crate::netlink_packet::{self};
1821 use crate::protocol_family::route::{NetlinkRoute, NetlinkRouteRequestHandler};
1822 use crate::route_eventloop::UnifiedRequest;
1823 use crate::rules::{RuleRequest, RuleRequestArgs};
1824 use crate::{interfaces, neighbors, routes};
1825
1826 enum ExpectedResponse {
1827 Ack,
1828 Error(Errno),
1829 Done,
1830 }
1831
1832 fn expected_sent_messages(
1833 expected_response: Option<ExpectedResponse>,
1834 nl_header: NetlinkHeader,
1835 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
1836 expected_response
1837 .into_iter()
1838 .map(|expected_response| {
1839 SentMessage::unicast(match expected_response {
1840 ExpectedResponse::Ack => netlink_packet::new_error(Ok(()), nl_header),
1841 ExpectedResponse::Error(e) => netlink_packet::new_error(Err(e), nl_header),
1842 ExpectedResponse::Done => netlink_packet::new_done(nl_header),
1843 })
1844 })
1845 .collect::<Vec<_>>()
1846 }
1847
1848 fn header_with_flags(flags: u16) -> NetlinkHeader {
1849 let mut header = NetlinkHeader::default();
1850 header.flags = flags;
1851 header
1852 }
1853
1854 fn neighbour_discovery_user_option_msg() -> NeighbourDiscoveryUserOptionMessage {
1855 NeighbourDiscoveryUserOptionMessage::new(
1856 NeighbourDiscoveryUserOptionHeader::new(
1857 0,
1858 NeighbourDiscoveryIcmpType::Inet6(
1859 NeighbourDiscoveryIcmpV6Type::NeighbourAdvertisement,
1860 ),
1861 ),
1862 Default::default(),
1863 Default::default(),
1864 )
1865 }
1866
1867 #[test_case(
1874 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1875 0,
1876 None; "get_tc__with_no_flags")]
1877 #[test_case(
1878 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1879 NLM_F_ACK,
1880 Some(ExpectedResponse::Ack); "get_tc_with_ack_flag")]
1881 #[test_case(
1882 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1883 NLM_F_DUMP,
1884 Some(ExpectedResponse::Done); "get_tc_with_dump_flag")]
1885 #[test_case(
1886 RouteNetlinkMessage::GetTrafficChain(Default::default()),
1887 NLM_F_ACK | NLM_F_DUMP,
1888 Some(ExpectedResponse::Done); "get_tc_with_ack_and_dump_flag")]
1889 #[test_case(
1890 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1891 0,
1892 None; "new_tc_with_no_flags")]
1893 #[test_case(
1894 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1895 NLM_F_DUMP,
1896 None; "new_tc_with_dump_flag")]
1897 #[test_case(
1898 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1899 NLM_F_ACK,
1900 Some(ExpectedResponse::Ack); "new_tc_with_ack_flag")]
1901 #[test_case(
1902 RouteNetlinkMessage::NewTrafficChain(Default::default()),
1903 NLM_F_ACK | NLM_F_DUMP,
1904 Some(ExpectedResponse::Ack); "new_tc_with_ack_and_dump_flags")]
1905 #[test_case(
1906 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1907 0,
1908 None; "deltc_with_no_flags")]
1909 #[test_case(
1910 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1911 NLM_F_DUMP,
1912 None; "del_tc_with_dump_flag")]
1913 #[test_case(
1914 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1915 NLM_F_ACK,
1916 Some(ExpectedResponse::Ack); "del_tc_with_ack_flag")]
1917 #[test_case(
1918 RouteNetlinkMessage::DelTrafficChain(Default::default()),
1919 NLM_F_ACK | NLM_F_DUMP,
1920 Some(ExpectedResponse::Ack); "del_tc_with_ack_and_dump_flags")]
1921 #[test_case(
1922 RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(neighbour_discovery_user_option_msg()),
1923 NLM_F_ACK,
1924 Some(ExpectedResponse::Ack); "new_neighbour_user_option_with_ack_flag")]
1925 #[test_case(
1926 RouteNetlinkMessage::NewNeighbourDiscoveryUserOption(neighbour_discovery_user_option_msg()),
1927 0,
1928 None; "new_neighbour_user_option_no_flags")]
1929 #[test_case(
1930 RouteNetlinkMessage::NewPrefix(Default::default()),
1931 NLM_F_ACK,
1932 Some(ExpectedResponse::Ack); "new_prefix_with_ack_flag")]
1933 #[test_case(
1934 RouteNetlinkMessage::NewPrefix(Default::default()),
1935 0,
1936 None; "new_prefix_no_flags")]
1937 #[fuchsia::test]
1938 async fn test_handle_unsupported_request_response(
1939 inner_message: RouteNetlinkMessage,
1940 flags: u16,
1941 expected_response: Option<ExpectedResponse>,
1942 ) {
1943 let (unified_request_sink, _unified_request_stream) = mpsc::channel(0);
1944
1945 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
1946
1947 let (mut client_sink, mut client, async_work_drain_task) =
1948 crate::client::testutil::new_fake_client::<NetlinkRoute>(
1949 crate::client::testutil::CLIENT_ID_1,
1950 std::iter::empty(),
1951 );
1952 let join_handle = fasync::Task::spawn(async_work_drain_task);
1953
1954 let header = header_with_flags(flags);
1955
1956 handler
1957 .handle_request(
1958 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(inner_message)),
1959 &mut client,
1960 )
1961 .await;
1962
1963 assert_eq!(client_sink.take_messages(), expected_sent_messages(expected_response, header));
1964
1965 drop(client);
1966 join_handle.await;
1967 }
1968
1969 struct RequestAndResponse<R> {
1970 request: R,
1971 response: Result<(), interfaces::RequestError>,
1972 }
1973
1974 async fn test_request(
1975 request: NetlinkMessage<RouteNetlinkMessage>,
1976 req_and_resp: Option<RequestAndResponse<interfaces::RequestArgs>>,
1977 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
1978 let (mut client_sink, mut client, async_work_drain_task) =
1979 crate::client::testutil::new_fake_client::<NetlinkRoute>(
1980 crate::client::testutil::CLIENT_ID_1,
1981 std::iter::empty(),
1982 );
1983 let join_handle = fasync::Task::spawn(async_work_drain_task);
1984
1985 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
1986 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
1987
1988 let mut interfaces_request_stream = unified_request_stream.filter_map(|req| {
1989 futures::future::ready(match req {
1990 UnifiedRequest::InterfacesRequest(req) => Some(req),
1991 _ => None,
1992 })
1993 });
1994
1995 let ((), ()) = futures::future::join(handler.handle_request(request, &mut client), async {
1996 let next = interfaces_request_stream.next();
1997 match req_and_resp {
1998 Some(RequestAndResponse { request, response }) => {
1999 let interfaces::Request { args, sequence_number: _, client: _, completer } =
2000 next.await.expect("handler should send request");
2001 assert_eq!(args, request);
2002 completer.send(response).expect("handler should be alive");
2003 }
2004 None => assert_matches!(next.now_or_never(), None),
2005 }
2006 })
2007 .await;
2008
2009 drop(client);
2010 join_handle.await;
2011 client_sink.take_messages()
2012 }
2013
2014 const FAKE_INTERFACE_ID: u32 = 1;
2015 const FAKE_INTERFACE_NAME: &str = "interface";
2016
2017 #[test_case(
2019 0,
2020 0,
2021 None,
2022 None,
2023 Ok(()),
2024 Some(ExpectedResponse::Error(Errno::EINVAL)); "no_specifiers")]
2025 #[test_case(
2026 NLM_F_DUMP,
2027 0,
2028 None,
2029 Some(interfaces::GetLinkArgs::Dump),
2030 Ok(()),
2031 Some(ExpectedResponse::Done); "dump")]
2032 #[test_case(
2033 NLM_F_DUMP | NLM_F_ACK,
2034 0,
2035 None,
2036 Some(interfaces::GetLinkArgs::Dump),
2037 Ok(()),
2038 Some(ExpectedResponse::Done); "dump_with_ack")]
2039 #[test_case(
2040 NLM_F_DUMP,
2041 FAKE_INTERFACE_ID,
2042 None,
2043 Some(interfaces::GetLinkArgs::Dump),
2044 Ok(()),
2045 Some(ExpectedResponse::Done); "dump_with_id")]
2046 #[test_case(
2047 NLM_F_DUMP,
2048 FAKE_INTERFACE_ID,
2049 Some(FAKE_INTERFACE_NAME),
2050 Some(interfaces::GetLinkArgs::Dump),
2051 Ok(()),
2052 Some(ExpectedResponse::Done); "dump_with_id_and_name")]
2053 #[test_case(
2054 0,
2055 FAKE_INTERFACE_ID,
2056 None,
2057 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
2058 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
2059 Ok(()),
2060 None; "id")]
2061 #[test_case(
2062 NLM_F_ACK,
2063 FAKE_INTERFACE_ID,
2064 None,
2065 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
2066 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
2067 Ok(()),
2068 Some(ExpectedResponse::Ack); "id_with_ack")]
2069 #[test_case(
2070 0,
2071 FAKE_INTERFACE_ID,
2072 Some(FAKE_INTERFACE_NAME),
2073 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
2074 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
2075 Ok(()),
2076 None; "id_with_name")]
2077 #[test_case(
2078 0,
2079 0,
2080 Some(FAKE_INTERFACE_NAME),
2081 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
2082 FAKE_INTERFACE_NAME.to_string()))),
2083 Ok(()),
2084 None; "name")]
2085 #[test_case(
2086 NLM_F_ACK,
2087 0,
2088 Some(FAKE_INTERFACE_NAME),
2089 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
2090 FAKE_INTERFACE_NAME.to_string()))),
2091 Ok(()),
2092 Some(ExpectedResponse::Ack); "name_with_ack")]
2093 #[test_case(
2094 0,
2095 FAKE_INTERFACE_ID,
2096 None,
2097 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Index(
2098 NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()))),
2099 Err(interfaces::RequestError::UnrecognizedInterface),
2100 Some(ExpectedResponse::Error(Errno::ENODEV)); "id_not_found")]
2101 #[test_case(
2102 0,
2103 0,
2104 Some(FAKE_INTERFACE_NAME),
2105 Some(interfaces::GetLinkArgs::Get(interfaces::LinkSpecifier::Name(
2106 FAKE_INTERFACE_NAME.to_string()))),
2107 Err(interfaces::RequestError::UnrecognizedInterface),
2108 Some(ExpectedResponse::Error(Errno::ENODEV)); "name_not_found")]
2109 #[fuchsia::test]
2110 async fn test_get_link(
2111 flags: u16,
2112 link_id: u32,
2113 link_name: Option<&str>,
2114 expected_request_args: Option<interfaces::GetLinkArgs>,
2115 interfaces_worker_result: Result<(), interfaces::RequestError>,
2116 expected_response: Option<ExpectedResponse>,
2117 ) {
2118 let header = header_with_flags(flags);
2119 let mut link_message = LinkMessage::default();
2120 link_message.header.index = link_id;
2121 link_message.attributes =
2122 link_name.map(|n| LinkAttribute::IfName(n.to_string())).into_iter().collect();
2123
2124 pretty_assertions::assert_eq!(
2125 test_request(
2126 NetlinkMessage::new(
2127 header,
2128 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetLink(link_message)),
2129 ),
2130 expected_request_args.map(|a| RequestAndResponse {
2131 request: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Get(a)),
2132 response: interfaces_worker_result,
2133 }),
2134 )
2135 .await,
2136 expected_sent_messages(expected_response, header),
2137 )
2138 }
2139
2140 #[test_case(
2141 0,
2142 0,
2143 None,
2144 0,
2145 0,
2146 None,
2147 Ok(()),
2148 Some(ExpectedResponse::Error(Errno::EINVAL)); "interface_not_specified")]
2149 #[test_case(
2150 0,
2151 FAKE_INTERFACE_ID,
2152 Some(FAKE_INTERFACE_NAME),
2153 0,
2154 0,
2155 None,
2156 Ok(()),
2157 Some(ExpectedResponse::Error(Errno::EBUSY)); "name_and_id")]
2158 #[test_case(
2159 0,
2160 FAKE_INTERFACE_ID,
2161 None,
2162 0,
2163 0,
2164 Some(interfaces::SetLinkArgs{
2165 link: interfaces::LinkSpecifier::Index(NonZeroU32::new(FAKE_INTERFACE_ID).unwrap()),
2166 enable: None,
2167 }),
2168 Ok(()),
2169 None; "no_change_by_id")]
2170 #[test_case(
2171 0,
2172 0,
2173 Some(FAKE_INTERFACE_NAME),
2174 0,
2175 0,
2176 Some(interfaces::SetLinkArgs{
2177 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2178 enable: None,
2179 }),
2180 Ok(()),
2181 None; "no_change_by_name")]
2182 #[test_case(
2183 NLM_F_ACK,
2184 0,
2185 Some(FAKE_INTERFACE_NAME),
2186 0,
2187 0,
2188 Some(interfaces::SetLinkArgs{
2189 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2190 enable: None,
2191 }),
2192 Ok(()),
2193 Some(ExpectedResponse::Ack); "no_change_ack")]
2194 #[test_case(
2195 0,
2196 0,
2197 Some(FAKE_INTERFACE_NAME),
2198 net_device_flags_IFF_UP,
2199 net_device_flags_IFF_UP,
2200 Some(interfaces::SetLinkArgs{
2201 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2202 enable: Some(true),
2203 }),
2204 Ok(()),
2205 None; "enable")]
2206 #[test_case(
2207 NLM_F_ACK,
2208 0,
2209 Some(FAKE_INTERFACE_NAME),
2210 net_device_flags_IFF_UP,
2211 net_device_flags_IFF_UP,
2212 Some(interfaces::SetLinkArgs{
2213 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2214 enable: Some(true),
2215 }),
2216 Ok(()),
2217 Some(ExpectedResponse::Ack); "enable_ack")]
2218 #[test_case(
2219 NLM_F_ACK,
2220 0,
2221 Some(FAKE_INTERFACE_NAME),
2222 net_device_flags_IFF_UP,
2223 net_device_flags_IFF_UP,
2224 Some(interfaces::SetLinkArgs{
2225 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2226 enable: Some(true),
2227 }),
2228 Err(interfaces::RequestError::UnrecognizedInterface),
2229 Some(ExpectedResponse::Error(Errno::ENODEV)); "enable_error")]
2230 #[test_case(
2231 0,
2232 0,
2233 Some(FAKE_INTERFACE_NAME),
2234 0,
2235 net_device_flags_IFF_UP,
2236 Some(interfaces::SetLinkArgs{
2237 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2238 enable: Some(false),
2239 }),
2240 Ok(()),
2241 None; "disable")]
2242 #[test_case(
2243 NLM_F_ACK,
2244 0,
2245 Some(FAKE_INTERFACE_NAME),
2246 0,
2247 net_device_flags_IFF_UP,
2248 Some(interfaces::SetLinkArgs{
2249 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2250 enable: Some(false),
2251 }),
2252 Ok(()),
2253 Some(ExpectedResponse::Ack); "disable_ack")]
2254 #[test_case(
2255 NLM_F_ACK,
2256 0,
2257 Some(FAKE_INTERFACE_NAME),
2258 0,
2259 net_device_flags_IFF_UP,
2260 Some(interfaces::SetLinkArgs{
2261 link: interfaces::LinkSpecifier::Name(FAKE_INTERFACE_NAME.to_string()),
2262 enable: Some(false),
2263 }),
2264 Err(interfaces::RequestError::UnrecognizedInterface),
2265 Some(ExpectedResponse::Error(Errno::ENODEV)); "disable_error")]
2266 #[fuchsia::test]
2267 async fn test_set_link(
2268 flags: u16,
2269 link_id: u32,
2270 link_name: Option<&str>,
2271 link_flags: u32,
2272 change_mask: u32,
2273 expected_request_args: Option<interfaces::SetLinkArgs>,
2274 interfaces_worker_result: Result<(), interfaces::RequestError>,
2275 expected_response: Option<ExpectedResponse>,
2276 ) {
2277 let header = header_with_flags(flags);
2278 let mut link_message = LinkMessage::default();
2279 link_message.header.index = link_id;
2280 link_message.header.flags = LinkFlags::from_bits(link_flags).unwrap();
2281 link_message.header.change_mask = LinkFlags::from_bits(change_mask).unwrap();
2282 link_message.attributes =
2283 link_name.map(|n| LinkAttribute::IfName(n.to_string())).into_iter().collect();
2284
2285 pretty_assertions::assert_eq!(
2286 test_request(
2287 NetlinkMessage::new(
2288 header,
2289 NetlinkPayload::InnerMessage(RouteNetlinkMessage::SetLink(link_message)),
2290 ),
2291 expected_request_args.map(|a| RequestAndResponse {
2292 request: interfaces::RequestArgs::Link(interfaces::LinkRequestArgs::Set(a)),
2293 response: interfaces_worker_result,
2294 }),
2295 )
2296 .await,
2297 expected_sent_messages(expected_response, header),
2298 )
2299 }
2300
2301 #[fuchsia::test]
2302 async fn test_new_link() {
2303 let header = header_with_flags(0);
2304 let mut link_message = LinkMessage::default();
2305 link_message.header.index = 1;
2306 link_message.attributes = vec![
2307 LinkAttribute::IfName("interface".to_string()),
2308 LinkAttribute::LinkInfo(vec![LinkInfo::Kind(InfoKind::Xfrm)]),
2309 ];
2310
2311 pretty_assertions::assert_eq!(
2312 test_request(
2313 NetlinkMessage::new(
2314 header,
2315 NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewLink(link_message)),
2316 ),
2317 None,
2318 )
2319 .await,
2320 expected_sent_messages(Some(ExpectedResponse::Error(Errno::ENOTSUP)), header)
2321 );
2322 }
2323
2324 #[fuchsia::test]
2325 async fn test_del_link() {
2326 let header = header_with_flags(0);
2327 let mut link_message = LinkMessage::default();
2328 link_message.header.index = 1;
2329 link_message.attributes = vec![LinkAttribute::IfName("interface".to_string())];
2330
2331 pretty_assertions::assert_eq!(
2332 test_request(
2333 NetlinkMessage::new(
2334 header,
2335 NetlinkPayload::InnerMessage(RouteNetlinkMessage::DelLink(link_message)),
2336 ),
2337 None,
2338 )
2339 .await,
2340 expected_sent_messages(Some(ExpectedResponse::Error(Errno::ENOTSUP)), header)
2341 );
2342 }
2343
2344 #[test_case(
2347 0,
2348 AF_UNSPEC,
2349 None,
2350 None; "af_unspec_no_flags")]
2351 #[test_case(
2352 NLM_F_ACK,
2353 AF_UNSPEC,
2354 None,
2355 Some(ExpectedResponse::Ack); "af_unspec_ack_flag")]
2356 #[test_case(
2357 NLM_F_DUMP,
2358 AF_UNSPEC,
2359 Some(interfaces::GetAddressArgs::Dump {
2360 ip_version_filter: None,
2361 }),
2362 Some(ExpectedResponse::Done); "af_unspec_dump_flag")]
2363 #[test_case(
2364 NLM_F_DUMP | NLM_F_ACK,
2365 AF_UNSPEC,
2366 Some(interfaces::GetAddressArgs::Dump {
2367 ip_version_filter: None,
2368 }),
2369 Some(ExpectedResponse::Done); "af_unspec_dump_and_ack_flags")]
2370 #[test_case(
2371 0,
2372 AF_INET,
2373 None,
2374 None; "af_inet_no_flags")]
2375 #[test_case(
2376 NLM_F_ACK,
2377 AF_INET,
2378 None,
2379 Some(ExpectedResponse::Ack); "af_inet_ack_flag")]
2380 #[test_case(
2381 NLM_F_DUMP,
2382 AF_INET,
2383 Some(interfaces::GetAddressArgs::Dump {
2384 ip_version_filter: Some(IpVersion::V4),
2385 }),
2386 Some(ExpectedResponse::Done); "af_inet_dump_flag")]
2387 #[test_case(
2388 NLM_F_DUMP | NLM_F_ACK,
2389 AF_INET,
2390 Some(interfaces::GetAddressArgs::Dump {
2391 ip_version_filter: Some(IpVersion::V4),
2392 }),
2393 Some(ExpectedResponse::Done); "af_inet_dump_and_ack_flags")]
2394 #[test_case(
2395 0,
2396 AF_INET6,
2397 None,
2398 None; "af_inet6_no_flags")]
2399 #[test_case(
2400 NLM_F_ACK,
2401 AF_INET6,
2402 None,
2403 Some(ExpectedResponse::Ack); "af_inet6_ack_flag")]
2404 #[test_case(
2405 NLM_F_DUMP,
2406 AF_INET6,
2407 Some(interfaces::GetAddressArgs::Dump {
2408 ip_version_filter: Some(IpVersion::V6),
2409 }),
2410 Some(ExpectedResponse::Done); "af_inet6_dump_flag")]
2411 #[test_case(
2412 NLM_F_DUMP | NLM_F_ACK,
2413 AF_INET6,
2414 Some(interfaces::GetAddressArgs::Dump {
2415 ip_version_filter: Some(IpVersion::V6),
2416 }),
2417 Some(ExpectedResponse::Done); "af_inet6_dump_and_ack_flags")]
2418 #[test_case(
2419 0,
2420 AF_PACKET.into(),
2421 None,
2422 None; "af_other_no_flags")]
2423 #[test_case(
2424 NLM_F_ACK,
2425 AF_PACKET.into(),
2426 None,
2427 Some(ExpectedResponse::Ack); "af_other_ack_flag")]
2428 #[test_case(
2429 NLM_F_DUMP,
2430 AF_PACKET.into(),
2431 None,
2432 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_flag")]
2433 #[test_case(
2434 NLM_F_DUMP | NLM_F_ACK,
2435 AF_PACKET.into(),
2436 None,
2437 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_and_ack_flags")]
2438 #[fuchsia::test]
2439 async fn test_get_addr(
2440 flags: u16,
2441 family: u32,
2442 expected_request_args: Option<interfaces::GetAddressArgs>,
2443 expected_response: Option<ExpectedResponse>,
2444 ) {
2445 let family = family as u16;
2447 let header = header_with_flags(flags);
2448 let address_message = {
2449 let mut message = AddressMessage::default();
2450 message.header.family = AddressFamily::from(family as u8).into();
2452 message
2453 };
2454
2455 pretty_assertions::assert_eq!(
2456 test_request(
2457 NetlinkMessage::new(
2458 header,
2459 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetAddress(address_message)),
2460 ),
2461 expected_request_args.map(|a| RequestAndResponse {
2462 request: interfaces::RequestArgs::Address(interfaces::AddressRequestArgs::Get(
2463 a
2464 )),
2465 response: Ok(()),
2466 }),
2467 )
2468 .await,
2469 expected_sent_messages(expected_response, header)
2470 )
2471 }
2472
2473 enum AddressRequestKind {
2474 New { add_subnet_route: bool },
2475 Del,
2476 }
2477
2478 struct TestAddrCase {
2479 kind: AddressRequestKind,
2480 flags: u16,
2481 family: u16,
2482 nlas: Vec<AddressAttribute>,
2483 prefix_len: u8,
2484 interface_id: u32,
2485 expected_request_args: Option<RequestAndResponse<interfaces::AddressAndInterfaceArgs>>,
2486 expected_response: Option<ExpectedResponse>,
2487 }
2488
2489 fn ip_from_addr(a: AddrSubnetEither) -> IpAddr {
2490 match a {
2491 AddrSubnetEither::V4(a) => IpAddr::V4(a.addr().get().ipv4_bytes().into()),
2492 AddrSubnetEither::V6(a) => IpAddr::V6(a.addr().get().ipv6_bytes().into()),
2493 }
2494 }
2495
2496 fn prefix_from_addr(a: AddrSubnetEither) -> u8 {
2497 let (_addr, prefix) = a.addr_prefix();
2498 prefix
2499 }
2500
2501 fn interface_id_as_u32(id: u64) -> u32 {
2502 id.try_into().unwrap()
2503 }
2504
2505 fn valid_new_del_addr_request(
2506 kind: AddressRequestKind,
2507 ack: bool,
2508 addr: AddrSubnetEither,
2509 extra_nlas: impl IntoIterator<Item = AddressAttribute>,
2510 interface_id: u64,
2511 response: Result<(), interfaces::RequestError>,
2512 ) -> TestAddrCase {
2513 TestAddrCase {
2514 kind,
2515 flags: if ack { NLM_F_ACK } else { 0 },
2516 family: match addr {
2517 AddrSubnetEither::V4(_) => AF_INET as u16,
2520 AddrSubnetEither::V6(_) => AF_INET6 as u16,
2521 },
2522 nlas: [AddressAttribute::Local(ip_from_addr(addr))]
2523 .into_iter()
2524 .chain(extra_nlas)
2525 .collect(),
2526 prefix_len: prefix_from_addr(addr),
2527 interface_id: interface_id_as_u32(interface_id),
2528 expected_request_args: Some(RequestAndResponse {
2529 request: interfaces::AddressAndInterfaceArgs {
2530 address: addr,
2531 interface_id: NonZeroU32::new(interface_id_as_u32(interface_id)).unwrap(),
2532 },
2533 response,
2534 }),
2535 expected_response: ack.then_some(ExpectedResponse::Ack),
2536 }
2537 }
2538
2539 fn valid_new_addr_request_with_extra_nlas(
2540 ack: bool,
2541 addr: AddrSubnetEither,
2542 extra_nlas: impl IntoIterator<Item = AddressAttribute>,
2543 interface_id: u64,
2544 response: Result<(), interfaces::RequestError>,
2545 ) -> TestAddrCase {
2546 valid_new_del_addr_request(
2547 AddressRequestKind::New { add_subnet_route: true },
2548 ack,
2549 addr,
2550 extra_nlas,
2551 interface_id,
2552 response,
2553 )
2554 }
2555
2556 fn valid_new_addr_request(
2557 ack: bool,
2558 addr: AddrSubnetEither,
2559 interface_id: u64,
2560 response: Result<(), interfaces::RequestError>,
2561 ) -> TestAddrCase {
2562 valid_new_addr_request_with_extra_nlas(ack, addr, None, interface_id, response)
2563 }
2564
2565 fn invalid_new_addr_request(
2566 ack: bool,
2567 addr: AddrSubnetEither,
2568 interface_id: u64,
2569 errno: Errno,
2570 ) -> TestAddrCase {
2571 TestAddrCase {
2572 expected_request_args: None,
2573 expected_response: Some(ExpectedResponse::Error(errno)),
2574 ..valid_new_addr_request(ack, addr, interface_id, Ok(()))
2575 }
2576 }
2577
2578 fn valid_del_addr_request(
2579 ack: bool,
2580 addr: AddrSubnetEither,
2581 interface_id: u64,
2582 response: Result<(), interfaces::RequestError>,
2583 ) -> TestAddrCase {
2584 valid_new_del_addr_request(AddressRequestKind::Del, ack, addr, None, interface_id, response)
2585 }
2586
2587 fn invalid_del_addr_request(
2588 ack: bool,
2589 addr: AddrSubnetEither,
2590 interface_id: u64,
2591 errno: Errno,
2592 ) -> TestAddrCase {
2593 TestAddrCase {
2594 expected_request_args: None,
2595 expected_response: Some(ExpectedResponse::Error(errno)),
2596 ..valid_del_addr_request(ack, addr, interface_id, Ok(()))
2597 }
2598 }
2599
2600 #[test_case(
2603 TestAddrCase {
2604 expected_request_args: None,
2605 ..valid_new_addr_request(
2606 true,
2607 net_addr_subnet!("0.0.0.0/0"),
2608 interfaces::testutil::PPP_INTERFACE_ID,
2609 Ok(()))
2610 }; "new_v4_unspecified_address_zero_prefix_ok_ack")]
2611 #[test_case(
2612 TestAddrCase {
2613 expected_request_args: None,
2614 ..valid_new_addr_request(
2615 false,
2616 net_addr_subnet!("0.0.0.0/24"),
2617 interfaces::testutil::PPP_INTERFACE_ID,
2618 Ok(()))
2619 }; "new_v4_unspecified_address_non_zero_prefix_ok_no_ack")]
2620 #[test_case(
2621 invalid_new_addr_request(
2622 true,
2623 net_addr_subnet!("::/0"),
2624 interfaces::testutil::ETH_INTERFACE_ID,
2625 Errno::EADDRNOTAVAIL); "new_v6_unspecified_address_zero_prefix_ack")]
2626 #[test_case(
2627 invalid_new_addr_request(
2628 false,
2629 net_addr_subnet!("::/64"),
2630 interfaces::testutil::ETH_INTERFACE_ID,
2631 Errno::EADDRNOTAVAIL); "new_v6_unspecified_address_non_zero_prefix_no_ack")]
2632 #[test_case(
2633 valid_new_addr_request(
2634 true,
2635 interfaces::testutil::test_addr_subnet_v4(),
2636 interfaces::testutil::LO_INTERFACE_ID,
2637 Ok(())); "new_v4_ok_ack")]
2638 #[test_case(
2639 valid_new_addr_request(
2640 true,
2641 interfaces::testutil::test_addr_subnet_v6(),
2642 interfaces::testutil::LO_INTERFACE_ID,
2643 Ok(())); "new_v6_ok_ack")]
2644 #[test_case(
2645 valid_new_addr_request(
2646 false,
2647 interfaces::testutil::test_addr_subnet_v4(),
2648 interfaces::testutil::ETH_INTERFACE_ID,
2649 Ok(())); "new_v4_ok_no_ack")]
2650 #[test_case(
2651 valid_new_addr_request(
2652 false,
2653 interfaces::testutil::test_addr_subnet_v6(),
2654 interfaces::testutil::ETH_INTERFACE_ID,
2655 Ok(())); "new_v6_ok_no_ack")]
2656 #[test_case(
2657 TestAddrCase {
2658 nlas: vec![
2659 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2660 ],
2661 ..valid_new_addr_request(
2662 false,
2663 interfaces::testutil::test_addr_subnet_v4(),
2664 interfaces::testutil::ETH_INTERFACE_ID,
2665 Ok(()),
2666 )
2667 }; "new_v4_local_nla_ok_no_ack")]
2668 #[test_case(
2669 TestAddrCase {
2670 nlas: vec![
2671 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2672 ],
2673 ..valid_new_addr_request(
2674 true,
2675 interfaces::testutil::test_addr_subnet_v6(),
2676 interfaces::testutil::PPP_INTERFACE_ID,
2677 Ok(()),
2678 )
2679 }; "new_v6_address_nla_ok_ack")]
2680 #[test_case(
2681 TestAddrCase {
2682 nlas: vec![
2683 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2684 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2685 ],
2686 ..valid_new_addr_request(
2687 false,
2688 interfaces::testutil::test_addr_subnet_v6(),
2689 interfaces::testutil::PPP_INTERFACE_ID,
2690 Ok(()),
2691 )
2692 }; "new_v6_same_local_and_address_nla_ok_no_ack")]
2693 #[test_case(
2694 TestAddrCase {
2695 kind: AddressRequestKind::New { add_subnet_route: true },
2696 ..valid_new_addr_request_with_extra_nlas(
2697 false,
2698 interfaces::testutil::test_addr_subnet_v4(),
2699 [AddressAttribute::Flags(AddressFlags::empty())],
2700 interfaces::testutil::ETH_INTERFACE_ID,
2701 Ok(()),
2702 )
2703 }; "new_v4_with_route_ok_no_ack")]
2704 #[test_case(
2705 TestAddrCase {
2706 kind: AddressRequestKind::New { add_subnet_route: false },
2707 ..valid_new_addr_request_with_extra_nlas(
2708 true,
2709 interfaces::testutil::test_addr_subnet_v6(),
2710 [AddressAttribute::Flags(AddressFlags::from_bits(IFA_F_NOPREFIXROUTE).unwrap())],
2711 interfaces::testutil::LO_INTERFACE_ID,
2712 Ok(()),
2713 )
2714 }; "new_v6_without_route_ok_ack")]
2715 #[test_case(
2716 TestAddrCase {
2717 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
2718 ..valid_new_addr_request(
2719 true,
2720 interfaces::testutil::test_addr_subnet_v4(),
2721 interfaces::testutil::LO_INTERFACE_ID,
2722 Err(interfaces::RequestError::InvalidRequest),
2723 )
2724 }; "new_v4_invalid_response_ack")]
2725 #[test_case(
2726 TestAddrCase {
2727 expected_response: Some(ExpectedResponse::Error(Errno::EEXIST)),
2728 ..valid_new_addr_request(
2729 false,
2730 interfaces::testutil::test_addr_subnet_v6(),
2731 interfaces::testutil::LO_INTERFACE_ID,
2732 Err(interfaces::RequestError::AlreadyExists),
2733 )
2734 }; "new_v6_exist_response_no_ack")]
2735 #[test_case(
2736 TestAddrCase {
2737 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
2738 ..valid_new_addr_request(
2739 false,
2740 interfaces::testutil::test_addr_subnet_v6(),
2741 interfaces::testutil::WLAN_INTERFACE_ID,
2742 Err(interfaces::RequestError::UnrecognizedInterface),
2743 )
2744 }; "new_v6_unrecognized_interface_response_no_ack")]
2745 #[test_case(
2746 TestAddrCase {
2747 expected_response: Some(ExpectedResponse::Error(Errno::EADDRNOTAVAIL)),
2748 ..valid_new_addr_request(
2749 true,
2750 interfaces::testutil::test_addr_subnet_v4(),
2751 interfaces::testutil::ETH_INTERFACE_ID,
2752 Err(interfaces::RequestError::AddressNotFound),
2753 )
2754 }; "new_v4_not_found_response_ck")]
2755 #[test_case(
2756 TestAddrCase {
2757 interface_id: 0,
2758 ..invalid_new_addr_request(
2759 true,
2760 interfaces::testutil::test_addr_subnet_v6(),
2761 interfaces::testutil::LO_INTERFACE_ID,
2762 Errno::EINVAL,
2763 )
2764 }; "new_zero_interface_id_ack")]
2765 #[test_case(
2766 TestAddrCase {
2767 interface_id: 0,
2768 ..invalid_new_addr_request(
2769 false,
2770 interfaces::testutil::test_addr_subnet_v4(),
2771 interfaces::testutil::WLAN_INTERFACE_ID,
2772 Errno::EINVAL,
2773 )
2774 }; "new_zero_interface_id_no_ack")]
2775 #[test_case(
2776 TestAddrCase {
2777 nlas: Vec::new(),
2778 ..invalid_new_addr_request(
2779 true,
2780 interfaces::testutil::test_addr_subnet_v4(),
2781 interfaces::testutil::WLAN_INTERFACE_ID,
2782 Errno::EINVAL,
2783 )
2784 }; "new_no_nlas_ack")]
2785 #[test_case(
2786 TestAddrCase {
2787 nlas: Vec::new(),
2788 ..invalid_new_addr_request(
2789 false,
2790 interfaces::testutil::test_addr_subnet_v6(),
2791 interfaces::testutil::WLAN_INTERFACE_ID,
2792 Errno::EINVAL,
2793 )
2794 }; "new_no_nlas_no_ack")]
2795 #[test_case(
2796 TestAddrCase {
2797 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2798 ..invalid_new_addr_request(
2799 true,
2800 interfaces::testutil::test_addr_subnet_v4(),
2801 interfaces::testutil::WLAN_INTERFACE_ID,
2802 Errno::EINVAL,
2803 )
2804 }; "new_missing_address_and_local_nla_ack")]
2805 #[test_case(
2806 TestAddrCase {
2807 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
2808 ..invalid_new_addr_request(
2809 false,
2810 interfaces::testutil::test_addr_subnet_v6(),
2811 interfaces::testutil::WLAN_INTERFACE_ID,
2812 Errno::EINVAL,
2813 )
2814 }; "new_missing_address_and_local_nla_no_ack")]
2815 #[test_case(
2816 TestAddrCase {
2817 prefix_len: 0,
2818 kind: AddressRequestKind::New { add_subnet_route: false },
2819 ..valid_new_addr_request(
2820 true,
2821 net_addr_subnet!("192.0.2.123/0"),
2822 interfaces::testutil::WLAN_INTERFACE_ID,
2823 Ok(()),
2824 )
2825 }; "new_zero_prefix_len_ack")]
2826 #[test_case(
2827 TestAddrCase {
2828 prefix_len: 0,
2829 ..valid_new_addr_request(
2830 false,
2831 net_addr_subnet!("2001:db8::1324/0"),
2832 interfaces::testutil::WLAN_INTERFACE_ID,
2833 Ok(()),
2834 )
2835 }; "new_zero_prefix_len_no_ack")]
2836 #[test_case(
2837 TestAddrCase {
2838 prefix_len: u8::MAX,
2839 ..invalid_new_addr_request(
2840 true,
2841 interfaces::testutil::test_addr_subnet_v4(),
2842 interfaces::testutil::WLAN_INTERFACE_ID,
2843 Errno::EINVAL,
2844 )
2845 }; "new_invalid_prefix_len_ack")]
2846 #[test_case(
2847 TestAddrCase {
2848 prefix_len: u8::MAX,
2849 ..invalid_new_addr_request(
2850 false,
2851 interfaces::testutil::test_addr_subnet_v6(),
2852 interfaces::testutil::WLAN_INTERFACE_ID,
2853 Errno::EINVAL,
2854 )
2855 }; "new_invalid_prefix_len_no_ack")]
2856 #[test_case(
2857 TestAddrCase {
2858 family: AF_UNSPEC as u16,
2859 ..invalid_new_addr_request(
2860 true,
2861 interfaces::testutil::test_addr_subnet_v4(),
2862 interfaces::testutil::LO_INTERFACE_ID,
2863 Errno::EINVAL,
2864 )
2865 }; "new_invalid_family_ack")]
2866 #[test_case(
2867 TestAddrCase {
2868 family: AF_UNSPEC as u16,
2869 ..invalid_new_addr_request(
2870 false,
2871 interfaces::testutil::test_addr_subnet_v6(),
2872 interfaces::testutil::PPP_INTERFACE_ID,
2873 Errno::EINVAL,
2874 )
2875 }; "new_invalid_family_no_ack")]
2876 #[test_case(
2878 valid_del_addr_request(
2879 true,
2880 interfaces::testutil::test_addr_subnet_v4(),
2881 interfaces::testutil::LO_INTERFACE_ID,
2882 Ok(())); "del_v4_ok_ack")]
2883 #[test_case(
2884 valid_del_addr_request(
2885 true,
2886 interfaces::testutil::test_addr_subnet_v6(),
2887 interfaces::testutil::LO_INTERFACE_ID,
2888 Ok(())); "del_v6_ok_ack")]
2889 #[test_case(
2890 valid_del_addr_request(
2891 false,
2892 interfaces::testutil::test_addr_subnet_v4(),
2893 interfaces::testutil::ETH_INTERFACE_ID,
2894 Ok(())); "del_v4_ok_no_ack")]
2895 #[test_case(
2896 valid_del_addr_request(
2897 false,
2898 interfaces::testutil::test_addr_subnet_v6(),
2899 interfaces::testutil::ETH_INTERFACE_ID,
2900 Ok(())); "del_v6_ok_no_ack")]
2901 #[test_case(
2902 TestAddrCase {
2903 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
2904 ..valid_del_addr_request(
2905 true,
2906 interfaces::testutil::test_addr_subnet_v4(),
2907 interfaces::testutil::LO_INTERFACE_ID,
2908 Err(interfaces::RequestError::InvalidRequest),
2909 )
2910 }; "del_v4_invalid_response_ack")]
2911 #[test_case(
2912 TestAddrCase {
2913 nlas: vec![
2914 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2915 ],
2916 ..valid_del_addr_request(
2917 false,
2918 interfaces::testutil::test_addr_subnet_v4(),
2919 interfaces::testutil::ETH_INTERFACE_ID,
2920 Ok(()),
2921 )
2922 }; "del_v4_local_nla_ok_no_ack")]
2923 #[test_case(
2924 TestAddrCase {
2925 nlas: vec![
2926 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v6())),
2927 ],
2928 ..valid_del_addr_request(
2929 true,
2930 interfaces::testutil::test_addr_subnet_v6(),
2931 interfaces::testutil::PPP_INTERFACE_ID,
2932 Ok(()),
2933 )
2934 }; "del_v6_address_nla_ok_ack")]
2935 #[test_case(
2936 TestAddrCase {
2937 nlas: vec![
2938 AddressAttribute::Address(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2939 AddressAttribute::Local(ip_from_addr(interfaces::testutil::test_addr_subnet_v4())),
2940 ],
2941 ..valid_del_addr_request(
2942 true,
2943 interfaces::testutil::test_addr_subnet_v4(),
2944 interfaces::testutil::ETH_INTERFACE_ID,
2945 Ok(()),
2946 )
2947 }; "del_v4_same_local_and_address_nla_ok_ack")]
2948 #[test_case(
2949 TestAddrCase {
2950 expected_response: Some(ExpectedResponse::Error(Errno::EEXIST)),
2951 ..valid_del_addr_request(
2952 false,
2953 interfaces::testutil::test_addr_subnet_v6(),
2954 interfaces::testutil::LO_INTERFACE_ID,
2955 Err(interfaces::RequestError::AlreadyExists),
2956 )
2957 }; "del_v6_exist_response_no_ack")]
2958 #[test_case(
2959 TestAddrCase {
2960 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
2961 ..valid_del_addr_request(
2962 false,
2963 interfaces::testutil::test_addr_subnet_v6(),
2964 interfaces::testutil::WLAN_INTERFACE_ID,
2965 Err(interfaces::RequestError::UnrecognizedInterface),
2966 )
2967 }; "del_v6_unrecognized_interface_response_no_ack")]
2968 #[test_case(
2969 TestAddrCase {
2970 expected_response: Some(ExpectedResponse::Error(Errno::EADDRNOTAVAIL)),
2971 ..valid_del_addr_request(
2972 true,
2973 interfaces::testutil::test_addr_subnet_v4(),
2974 interfaces::testutil::ETH_INTERFACE_ID,
2975 Err(interfaces::RequestError::AddressNotFound),
2976 )
2977 }; "del_v4_not_found_response_ck")]
2978 #[test_case(
2979 TestAddrCase {
2980 interface_id: 0,
2981 ..invalid_del_addr_request(
2982 true,
2983 interfaces::testutil::test_addr_subnet_v6(),
2984 interfaces::testutil::LO_INTERFACE_ID,
2985 Errno::EINVAL,
2986 )
2987 }; "del_zero_interface_id_ack")]
2988 #[test_case(
2989 TestAddrCase {
2990 interface_id: 0,
2991 ..invalid_del_addr_request(
2992 false,
2993 interfaces::testutil::test_addr_subnet_v4(),
2994 interfaces::testutil::WLAN_INTERFACE_ID,
2995 Errno::EINVAL,
2996 )
2997 }; "del_zero_interface_id_no_ack")]
2998 #[test_case(
2999 TestAddrCase {
3000 nlas: Vec::new(),
3001 ..invalid_del_addr_request(
3002 true,
3003 interfaces::testutil::test_addr_subnet_v4(),
3004 interfaces::testutil::WLAN_INTERFACE_ID,
3005 Errno::EINVAL,
3006 )
3007 }; "del_no_nlas_ack")]
3008 #[test_case(
3009 TestAddrCase {
3010 nlas: Vec::new(),
3011 ..invalid_del_addr_request(
3012 false,
3013 interfaces::testutil::test_addr_subnet_v6(),
3014 interfaces::testutil::WLAN_INTERFACE_ID,
3015 Errno::EINVAL,
3016 )
3017 }; "del_no_nlas_no_ack")]
3018 #[test_case(
3019 TestAddrCase {
3020 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
3021 ..invalid_del_addr_request(
3022 true,
3023 interfaces::testutil::test_addr_subnet_v4(),
3024 interfaces::testutil::WLAN_INTERFACE_ID,
3025 Errno::EINVAL,
3026 )
3027 }; "del_missing_address_and_local_nla_ack")]
3028 #[test_case(
3029 TestAddrCase {
3030 nlas: vec![AddressAttribute::Flags(AddressFlags::empty())],
3031 ..invalid_del_addr_request(
3032 false,
3033 interfaces::testutil::test_addr_subnet_v6(),
3034 interfaces::testutil::WLAN_INTERFACE_ID,
3035 Errno::EINVAL,
3036 )
3037 }; "del_missing_address_and_local_nla_no_ack")]
3038 #[test_case(
3039 TestAddrCase {
3040 prefix_len: 0,
3041 ..valid_del_addr_request(
3042 true,
3043 net_addr_subnet!("192.0.2.123/0"),
3044 interfaces::testutil::WLAN_INTERFACE_ID,
3045 Ok(()),
3046 )
3047 }; "del_zero_prefix_len_ack")]
3048 #[test_case(
3049 TestAddrCase {
3050 prefix_len: 0,
3051 ..valid_del_addr_request(
3052 false,
3053 net_addr_subnet!("2001:db8::1324/0"),
3054 interfaces::testutil::WLAN_INTERFACE_ID,
3055 Ok(()),
3056 )
3057 }; "del_zero_prefix_len_no_ack")]
3058 #[test_case(
3059 TestAddrCase {
3060 prefix_len: u8::MAX,
3061 ..invalid_del_addr_request(
3062 true,
3063 interfaces::testutil::test_addr_subnet_v4(),
3064 interfaces::testutil::WLAN_INTERFACE_ID,
3065 Errno::EINVAL,
3066 )
3067 }; "del_invalid_prefix_len_ack")]
3068 #[test_case(
3069 TestAddrCase {
3070 prefix_len: u8::MAX,
3071 ..invalid_del_addr_request(
3072 false,
3073 interfaces::testutil::test_addr_subnet_v6(),
3074 interfaces::testutil::WLAN_INTERFACE_ID,
3075 Errno::EINVAL,
3076 )
3077 }; "del_invalid_prefix_len_no_ack")]
3078 #[test_case(
3079 TestAddrCase {
3080 family: AF_UNSPEC as u16,
3081 ..invalid_del_addr_request(
3082 true,
3083 interfaces::testutil::test_addr_subnet_v4(),
3084 interfaces::testutil::LO_INTERFACE_ID,
3085 Errno::EINVAL,
3086 )
3087 }; "del_invalid_family_ack")]
3088 #[test_case(
3089 TestAddrCase {
3090 family: AF_UNSPEC as u16,
3091 ..invalid_del_addr_request(
3092 false,
3093 interfaces::testutil::test_addr_subnet_v6(),
3094 interfaces::testutil::PPP_INTERFACE_ID,
3095 Errno::EINVAL,
3096 )
3097 }; "del_invalid_family_no_ack")]
3098 #[fuchsia::test]
3099 async fn test_new_del_addr(test_case: TestAddrCase) {
3100 let TestAddrCase {
3101 kind,
3102 flags,
3103 family,
3104 nlas,
3105 prefix_len,
3106 interface_id,
3107 expected_request_args,
3108 expected_response,
3109 } = test_case;
3110
3111 let header = header_with_flags(flags);
3112 let address_message = {
3113 let mut message = AddressMessage::default();
3114 message.header.family = AddressFamily::from(family as u8).into();
3116 message.header.index = interface_id.into();
3117 message.header.prefix_len = prefix_len;
3118 message.attributes = nlas;
3119 message
3120 };
3121
3122 let (message, request) = match kind {
3123 AddressRequestKind::New { add_subnet_route } => (
3124 RouteNetlinkMessage::NewAddress(address_message),
3125 expected_request_args.map(|RequestAndResponse { request, response }| {
3126 RequestAndResponse {
3127 request: interfaces::RequestArgs::Address(
3128 interfaces::AddressRequestArgs::New(interfaces::NewAddressArgs {
3129 address_and_interface_id: request,
3130 add_subnet_route,
3131 }),
3132 ),
3133 response,
3134 }
3135 }),
3136 ),
3137 AddressRequestKind::Del => (
3138 RouteNetlinkMessage::DelAddress(address_message),
3139 expected_request_args.map(|RequestAndResponse { request, response }| {
3140 RequestAndResponse {
3141 request: interfaces::RequestArgs::Address(
3142 interfaces::AddressRequestArgs::Del(interfaces::DelAddressArgs {
3143 address_and_interface_id: request,
3144 }),
3145 ),
3146 response,
3147 }
3148 }),
3149 ),
3150 };
3151
3152 pretty_assertions::assert_eq!(
3153 test_request(
3154 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(message),),
3155 request,
3156 )
3157 .await,
3158 expected_sent_messages(expected_response, header),
3159 )
3160 }
3161
3162 async fn split_route_requests(
3166 unified_request_stream: mpsc::Receiver<UnifiedRequest<FakeSender<RouteNetlinkMessage>>>,
3167 v4_routes_request_sink: mpsc::Sender<
3168 crate::routes::Request<FakeSender<RouteNetlinkMessage>, Ipv4>,
3169 >,
3170 v6_routes_request_sink: mpsc::Sender<
3171 crate::routes::Request<FakeSender<RouteNetlinkMessage>, Ipv6>,
3172 >,
3173 ) {
3174 unified_request_stream
3175 .fold(
3176 (v4_routes_request_sink, v6_routes_request_sink),
3177 |(mut v4_routes_request_sink, mut v6_routes_request_sink), req| async move {
3178 match req {
3179 UnifiedRequest::RoutesV4Request(req) => {
3180 v4_routes_request_sink
3181 .send(req)
3182 .map(|res| res.expect("send should succeed"))
3183 .await
3184 }
3185 UnifiedRequest::RoutesV6Request(req) => {
3186 v6_routes_request_sink
3187 .send(req)
3188 .map(|res| res.expect("send should succeed"))
3189 .await
3190 }
3191 _ => (),
3192 };
3193 (v4_routes_request_sink, v6_routes_request_sink)
3194 },
3195 )
3196 .map(|(_v4_sink, _v6_sink)| ())
3197 .await
3198 }
3199
3200 async fn test_get_route_request(
3204 family: u16,
3205 request: NetlinkMessage<RouteNetlinkMessage>,
3206 expected_request: Option<routes::GetRouteArgs>,
3207 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
3208 let (mut client_sink, mut client, async_work_drain_task) =
3209 crate::client::testutil::new_fake_client::<NetlinkRoute>(
3210 crate::client::testutil::CLIENT_ID_1,
3211 std::iter::empty(),
3212 );
3213 let join_handle = fasync::Task::spawn(async_work_drain_task);
3214
3215 {
3216 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
3217
3218 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
3219
3220 let (v4_routes_request_sink, mut v4_routes_request_stream) = mpsc::channel(0);
3221 let (v6_routes_request_sink, mut v6_routes_request_stream) = mpsc::channel(0);
3222
3223 let mut split_route_requests_background_work = pin!(
3224 split_route_requests(
3225 unified_request_stream,
3226 v4_routes_request_sink,
3227 v6_routes_request_sink,
3228 )
3229 .fuse()
3230 );
3231
3232 let mut handler_fut = pin!(
3233 futures::future::join(handler.handle_request(request, &mut client), async {
3234 if family == AF_UNSPEC as u16 || family == AF_INET as u16 {
3236 let next = v4_routes_request_stream.next();
3237 match expected_request.map(|a| {
3238 routes::RequestArgs::<Ipv4>::Route(routes::RouteRequestArgs::Get(a))
3239 }) {
3240 Some(expected_request) => {
3241 let routes::Request {
3242 args,
3243 sequence_number: _,
3244 client: _,
3245 completer,
3246 } = next.await.expect("handler should send request");
3247 assert_eq!(args, expected_request);
3248 completer.send(Ok(())).expect("handler should be alive");
3249 }
3250 None => assert_matches!(next.now_or_never(), None),
3251 };
3252 }
3253 if family == AF_UNSPEC as u16 || family == AF_INET6 as u16 {
3254 let next = v6_routes_request_stream.next();
3255 match expected_request.map(|a| {
3256 routes::RequestArgs::<Ipv6>::Route(routes::RouteRequestArgs::Get(a))
3257 }) {
3258 Some(expected_request) => {
3259 let routes::Request {
3260 args,
3261 sequence_number: _,
3262 client: _,
3263 completer,
3264 } = next.await.expect("handler should send request");
3265 assert_eq!(args, expected_request);
3266 completer.send(Ok(())).expect("handler should be alive");
3267 }
3268 None => assert_matches!(next.now_or_never(), None),
3269 };
3270 }
3271 })
3272 .fuse()
3273 );
3274
3275 futures::select! {
3276 ((), ()) = handler_fut => (),
3277 () = split_route_requests_background_work => unreachable!(),
3278 };
3279 }
3280 drop(client);
3281 join_handle.await;
3282 client_sink.take_messages()
3283 }
3284
3285 #[test_case(
3288 0,
3289 AF_UNSPEC as u16,
3290 None,
3291 None; "af_unspec_no_flags")]
3292 #[test_case(
3293 NLM_F_ACK,
3294 AF_UNSPEC as u16,
3295 None,
3296 Some(ExpectedResponse::Ack); "af_unspec_ack_flag")]
3297 #[test_case(
3298 NLM_F_DUMP,
3299 AF_UNSPEC as u16,
3300 Some(routes::GetRouteArgs::Dump),
3301 Some(ExpectedResponse::Done); "af_unspec_dump_flag")]
3302 #[test_case(
3303 NLM_F_DUMP | NLM_F_ACK,
3304 AF_UNSPEC as u16,
3305 Some(routes::GetRouteArgs::Dump),
3306 Some(ExpectedResponse::Done); "af_unspec_dump_and_ack_flags")]
3307 #[test_case(
3308 0,
3309 AF_INET as u16,
3310 None,
3311 None; "af_inet_no_flags")]
3312 #[test_case(
3313 NLM_F_ACK,
3314 AF_INET as u16,
3315 None,
3316 Some(ExpectedResponse::Ack); "af_inet_ack_flag")]
3317 #[test_case(
3318 NLM_F_DUMP,
3319 AF_INET as u16,
3320 Some(routes::GetRouteArgs::Dump),
3321 Some(ExpectedResponse::Done); "af_inet_dump_flag")]
3322 #[test_case(
3323 NLM_F_DUMP | NLM_F_ACK,
3324 AF_INET as u16,
3325 Some(routes::GetRouteArgs::Dump),
3326 Some(ExpectedResponse::Done); "af_inet_dump_and_ack_flags")]
3327 #[test_case(
3328 0,
3329 AF_INET6 as u16,
3330 None,
3331 None; "af_inet6_no_flags")]
3332 #[test_case(
3333 NLM_F_ACK,
3334 AF_INET6 as u16,
3335 None,
3336 Some(ExpectedResponse::Ack); "af_inet6_ack_flag")]
3337 #[test_case(
3338 NLM_F_DUMP,
3339 AF_INET6 as u16,
3340 Some(routes::GetRouteArgs::Dump),
3341 Some(ExpectedResponse::Done); "af_inet6_dump_flag")]
3342 #[test_case(
3343 NLM_F_DUMP | NLM_F_ACK,
3344 AF_INET6 as u16,
3345 Some(routes::GetRouteArgs::Dump),
3346 Some(ExpectedResponse::Done); "af_inet6_dump_and_ack_flags")]
3347 #[test_case(
3348 0,
3349 AF_PACKET,
3350 None,
3351 None; "af_other_no_flags")]
3352 #[test_case(
3353 NLM_F_ACK,
3354 AF_PACKET,
3355 None,
3356 Some(ExpectedResponse::Ack); "af_other_ack_flag")]
3357 #[test_case(
3358 NLM_F_DUMP,
3359 AF_PACKET,
3360 None,
3361 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_flag")]
3362 #[test_case(
3363 NLM_F_DUMP | NLM_F_ACK,
3364 AF_PACKET,
3365 None,
3366 Some(ExpectedResponse::Error(Errno::EINVAL)); "af_other_dump_and_ack_flags")]
3367 #[fuchsia::test]
3368 async fn test_get_route(
3369 flags: u16,
3370 family: u16,
3371 expected_request_args: Option<routes::GetRouteArgs>,
3372 expected_response: Option<ExpectedResponse>,
3373 ) {
3374 let header = header_with_flags(flags);
3375 let route_message = {
3376 let mut message = RouteMessage::default();
3377 message.header.address_family = AddressFamily::from(family as u8);
3378 message
3379 };
3380
3381 pretty_assertions::assert_eq!(
3382 test_get_route_request(
3383 family,
3384 NetlinkMessage::new(
3385 header,
3386 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetRoute(route_message)),
3387 ),
3388 expected_request_args,
3389 )
3390 .await,
3391 expected_sent_messages(expected_response, header)
3392 )
3393 }
3394
3395 #[derive(Debug)]
3397 pub(crate) struct FakeRuleRequestResponse {
3398 pub(crate) expected_request_args: RuleRequestArgs,
3399 pub(crate) expected_ip_version: IpVersion,
3400 pub(crate) response: Result<(), Errno>,
3401 }
3402
3403 #[derive(Clone, Debug)]
3408 pub(crate) struct FakeRuleRequestHandler {
3409 pub(crate) requests_and_responses: Arc<Mutex<VecDeque<FakeRuleRequestResponse>>>,
3410 }
3411
3412 impl FakeRuleRequestHandler {
3413 fn new(requests_and_responses: impl IntoIterator<Item = FakeRuleRequestResponse>) -> Self {
3414 FakeRuleRequestHandler {
3415 requests_and_responses: Arc::new(Mutex::new(VecDeque::from_iter(
3416 requests_and_responses,
3417 ))),
3418 }
3419 }
3420
3421 fn handle_request<S: Sender<RouteNetlinkMessage>, I: Ip>(
3422 &mut self,
3423 actual_request: RuleRequest<S, I>,
3424 ) -> Result<(), Errno> {
3425 let Self { requests_and_responses } = self;
3426 let FakeRuleRequestResponse { expected_request_args, expected_ip_version, response } =
3427 requests_and_responses.lock().pop_front().expect(
3428 "FakeRuleRequest handler should have a fake request/response pre-configured",
3429 );
3430 let RuleRequest { args, _ip_version_marker, sequence_number: _, client: _ } =
3431 actual_request;
3432 assert_eq!(args, expected_request_args);
3433 assert_eq!(I::VERSION, expected_ip_version);
3434 response
3435 }
3436 }
3437
3438 fn default_rule_for_family(family: u16) -> RuleMessage {
3439 let mut rule = RuleMessage::default();
3440 rule.header.family = AddressFamily::from(family as u8);
3442 rule
3443 }
3444
3445 const AF_INVALID: u16 = 255;
3446 #[test_case(
3448 RouteNetlinkMessage::GetRule,
3449 0,
3450 AF_UNSPEC as u16,
3451 vec![],
3452 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_no_dump")]
3453 #[test_case(
3454 RouteNetlinkMessage::GetRule,
3455 NLM_F_DUMP,
3456 AF_INVALID,
3457 vec![],
3458 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "get_rule_dump_invalid_address_family")]
3459 #[test_case(
3460 RouteNetlinkMessage::GetRule,
3461 NLM_F_DUMP,
3462 AF_INET as u16,
3463 vec![FakeRuleRequestResponse{
3464 expected_request_args: RuleRequestArgs::DumpRules,
3465 expected_ip_version: IpVersion::V4,
3466 response: Ok(()),
3467 }],
3468 Some(ExpectedResponse::Done); "get_rule_dump_v4")]
3469 #[test_case(
3470 RouteNetlinkMessage::GetRule,
3471 NLM_F_DUMP,
3472 AF_INET6 as u16,
3473 vec![FakeRuleRequestResponse{
3474 expected_request_args: RuleRequestArgs::DumpRules,
3475 expected_ip_version: IpVersion::V6,
3476 response: Ok(()),
3477 }],
3478 Some(ExpectedResponse::Done); "get_rule_dump_v6")]
3479 #[test_case(
3480 RouteNetlinkMessage::GetRule,
3481 NLM_F_DUMP,
3482 AF_UNSPEC as u16,
3483 vec![FakeRuleRequestResponse{
3484 expected_request_args: RuleRequestArgs::DumpRules,
3485 expected_ip_version: IpVersion::V4,
3486 response: Ok(()),
3487 },
3488 FakeRuleRequestResponse{
3489 expected_request_args: RuleRequestArgs::DumpRules,
3490 expected_ip_version: IpVersion::V6,
3491 response: Ok(()),
3492 }],
3493 Some(ExpectedResponse::Done); "get_rule_dump_af_unspec")]
3494 #[test_case(
3495 RouteNetlinkMessage::GetRule,
3496 NLM_F_DUMP,
3497 AF_INET as u16,
3498 vec![FakeRuleRequestResponse{
3499 expected_request_args: RuleRequestArgs::DumpRules,
3500 expected_ip_version: IpVersion::V4,
3501 response: Err(Errno::ENOTSUP),
3502 }],
3503 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_v4_fails")]
3504 #[test_case(
3505 RouteNetlinkMessage::GetRule,
3506 NLM_F_DUMP,
3507 AF_INET6 as u16,
3508 vec![FakeRuleRequestResponse{
3509 expected_request_args: RuleRequestArgs::DumpRules,
3510 expected_ip_version: IpVersion::V6,
3511 response: Err(Errno::ENOTSUP),
3512 }],
3513 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_v6_fails")]
3514 #[test_case(
3515 RouteNetlinkMessage::GetRule,
3516 NLM_F_DUMP,
3517 AF_UNSPEC as u16,
3518 vec![FakeRuleRequestResponse{
3519 expected_request_args: RuleRequestArgs::DumpRules,
3520 expected_ip_version: IpVersion::V4,
3521 response: Err(Errno::ENOTSUP),
3522 }],
3523 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_af_unspec_v4_fails")]
3524 #[test_case(
3525 RouteNetlinkMessage::GetRule,
3526 NLM_F_DUMP,
3527 AF_UNSPEC as u16,
3528 vec![FakeRuleRequestResponse{
3529 expected_request_args: RuleRequestArgs::DumpRules,
3530 expected_ip_version: IpVersion::V4,
3531 response: Ok(()),
3532 },
3533 FakeRuleRequestResponse{
3534 expected_request_args: RuleRequestArgs::DumpRules,
3535 expected_ip_version: IpVersion::V6,
3536 response: Err(Errno::ENOTSUP),
3537 }],
3538 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "get_rule_dump_af_unspec_v6_fails")]
3539 #[test_case(
3540 RouteNetlinkMessage::NewRule,
3541 0,
3542 AF_INET as u16,
3543 vec![FakeRuleRequestResponse{
3544 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3545 expected_ip_version: IpVersion::V4,
3546 response: Ok(()),
3547 }],
3548 None; "new_rule_succeeds_v4")]
3549 #[test_case(
3550 RouteNetlinkMessage::NewRule,
3551 0,
3552 AF_INET6 as u16,
3553 vec![FakeRuleRequestResponse{
3554 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3555 expected_ip_version: IpVersion::V6,
3556 response: Ok(()),
3557 }],
3558 None; "new_rule_succeeds_v6")]
3559 #[test_case(
3560 RouteNetlinkMessage::NewRule,
3561 0,
3562 AF_UNSPEC as u16,
3563 vec![],
3564 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "new_rule_af_unspec_fails")]
3565 #[test_case(
3566 RouteNetlinkMessage::NewRule,
3567 NLM_F_ACK,
3568 AF_INET as u16,
3569 vec![FakeRuleRequestResponse{
3570 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3571 expected_ip_version: IpVersion::V4,
3572 response: Ok(()),
3573 }],
3574 Some(ExpectedResponse::Ack); "new_rule_v4_succeeds_with_ack")]
3575 #[test_case(
3576 RouteNetlinkMessage::NewRule,
3577 NLM_F_ACK,
3578 AF_INET6 as u16,
3579 vec![FakeRuleRequestResponse{
3580 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3581 expected_ip_version: IpVersion::V6,
3582 response: Ok(()),
3583 }],
3584 Some(ExpectedResponse::Ack); "new_rule_v6_succeeds_with_ack")]
3585 #[test_case(
3586 RouteNetlinkMessage::NewRule,
3587 0,
3588 AF_INET as u16,
3589 vec![FakeRuleRequestResponse{
3590 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET as u16)),
3591 expected_ip_version: IpVersion::V4,
3592 response: Err(Errno::ENOTSUP),
3593 }],
3594 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v4_fails")]
3595 #[test_case(
3596 RouteNetlinkMessage::NewRule,
3597 0,
3598 AF_INET6 as u16,
3599 vec![FakeRuleRequestResponse{
3600 expected_request_args: RuleRequestArgs::New(default_rule_for_family(AF_INET6 as u16)),
3601 expected_ip_version: IpVersion::V6,
3602 response: Err(Errno::ENOTSUP),
3603 }],
3604 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v6_fails")]
3605 #[test_case(
3606 RouteNetlinkMessage::NewRule,
3607 NLM_F_REPLACE,
3608 AF_INET as u16,
3609 vec![],
3610 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v4_replace_unimplemented")]
3611 #[test_case(
3612 RouteNetlinkMessage::NewRule,
3613 NLM_F_REPLACE,
3614 AF_INET6 as u16,
3615 vec![],
3616 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "new_rule_v6_replace_unimplemented")]
3617 #[test_case(
3618 RouteNetlinkMessage::DelRule,
3619 0,
3620 AF_INET as u16,
3621 vec![FakeRuleRequestResponse{
3622 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3623 expected_ip_version: IpVersion::V4,
3624 response: Ok(()),
3625 }],
3626 None; "del_rule_succeeds_v4")]
3627 #[test_case(
3628 RouteNetlinkMessage::DelRule,
3629 0,
3630 AF_INET6 as u16,
3631 vec![FakeRuleRequestResponse{
3632 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3633 expected_ip_version: IpVersion::V6,
3634 response: Ok(()),
3635 }],
3636 None; "del_rule_succeeds_v6")]
3637 #[test_case(
3638 RouteNetlinkMessage::DelRule,
3639 0,
3640 AF_UNSPEC as u16,
3641 vec![],
3642 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "del_rule_af_unspec_fails")]
3643 #[test_case(
3644 RouteNetlinkMessage::DelRule,
3645 NLM_F_ACK,
3646 AF_INET as u16,
3647 vec![FakeRuleRequestResponse{
3648 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3649 expected_ip_version: IpVersion::V4,
3650 response: Ok(()),
3651 }],
3652 Some(ExpectedResponse::Ack); "del_rule_v4_succeeds_with_ack")]
3653 #[test_case(
3654 RouteNetlinkMessage::DelRule,
3655 NLM_F_ACK,
3656 AF_INET6 as u16,
3657 vec![FakeRuleRequestResponse{
3658 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3659 expected_ip_version: IpVersion::V6,
3660 response: Ok(()),
3661 }],
3662 Some(ExpectedResponse::Ack); "del_rule_v6_succeeds_with_ack")]
3663 #[test_case(
3664 RouteNetlinkMessage::DelRule,
3665 0,
3666 AF_INET as u16,
3667 vec![FakeRuleRequestResponse{
3668 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET as u16)),
3669 expected_ip_version: IpVersion::V4,
3670 response: Err(Errno::ENOTSUP),
3671 }],
3672 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "del_rule_v4_fails")]
3673 #[test_case(
3674 RouteNetlinkMessage::DelRule,
3675 0,
3676 AF_INET6 as u16,
3677 vec![FakeRuleRequestResponse{
3678 expected_request_args: RuleRequestArgs::Del(default_rule_for_family(AF_INET6 as u16)),
3679 expected_ip_version: IpVersion::V6,
3680 response: Err(Errno::ENOTSUP),
3681 }],
3682 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "del_rule_v6_fails")]
3683 #[fuchsia::test]
3684 async fn test_rule_request(
3685 rule_fn: fn(RuleMessage) -> RouteNetlinkMessage,
3686 flags: u16,
3687 address_family: u16,
3688 requests_and_responses: Vec<FakeRuleRequestResponse>,
3689 expected_response: Option<ExpectedResponse>,
3690 ) {
3691 let rules_request_handler = FakeRuleRequestHandler::new(requests_and_responses);
3692 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
3693 let unified_request_stream = pin!(unified_request_stream);
3694 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
3695
3696 let (mut client_sink, mut client, async_work_drain_task) = {
3697 crate::client::testutil::new_fake_client::<NetlinkRoute>(
3698 crate::client::testutil::CLIENT_ID_1,
3699 std::iter::empty(),
3700 )
3701 };
3702 let join_handle = fasync::Task::spawn(async_work_drain_task);
3703
3704 let header = header_with_flags(flags);
3705
3706 let handle_request_fut = handler
3707 .handle_request(
3708 NetlinkMessage::new(
3709 header,
3710 NetlinkPayload::InnerMessage(rule_fn(default_rule_for_family(address_family))),
3711 ),
3712 &mut client,
3713 )
3714 .fuse();
3715
3716 futures::select! {
3717 () = pin!(handle_request_fut) => {},
3718 _rules_request_handler = unified_request_stream.fold(
3719 rules_request_handler,
3720 |mut rules_request_handler, req| async move {
3721 match req {
3722 UnifiedRequest::RuleV4Request(request, completer) => {
3723 completer
3724 .send(rules_request_handler.handle_request(request))
3725 .expect("send should succeed");
3726 rules_request_handler
3727 }
3728 UnifiedRequest::RuleV6Request(request, completer) => {
3729 completer
3730 .send(rules_request_handler.handle_request(request))
3731 .expect("send should succeed");
3732 rules_request_handler
3733 }
3734 _ => panic!("not RuleRequest"),
3735 }
3736 }
3737 ).fuse() => {},
3738 }
3739 assert_eq!(client_sink.take_messages(), expected_sent_messages(expected_response, header));
3740
3741 drop(client);
3742 join_handle.await;
3743 }
3744
3745 const TEST_V4_SUBNET: Subnet<Ipv4Addr> = net_subnet_v4!("192.0.2.0/24");
3746 const TEST_V4_NEXTHOP: Ipv4Addr = net_ip_v4!("192.0.2.1");
3747 const TEST_V6_SUBNET: Subnet<Ipv6Addr> = net_subnet_v6!("2001:db8::0/32");
3748 const TEST_V6_NEXTHOP: Ipv6Addr = net_ip_v6!("2001:db8::1");
3749
3750 fn test_nexthop_spec_addr<I: Ip>() -> SpecifiedAddr<I::Addr> {
3751 I::map_ip(
3752 (),
3753 |()| SpecifiedAddr::new(TEST_V4_NEXTHOP).unwrap(),
3754 |()| SpecifiedAddr::new(TEST_V6_NEXTHOP).unwrap(),
3755 )
3756 }
3757
3758 #[derive(Clone)]
3759 struct RouteRequestAndResponse<R> {
3760 request: R,
3761 response: Result<(), routes::RequestError>,
3762 }
3763
3764 #[derive(Clone, Copy)]
3765 enum RouteRequestKind {
3766 New,
3767 Del,
3768 }
3769
3770 struct TestRouteCase<I: Ip> {
3771 kind: RouteRequestKind,
3772 flags: u16,
3773 family: u16,
3774 nlas: Vec<RouteAttribute>,
3775 destination_prefix_len: u8,
3776 table: u8,
3777 rtm_type: u8,
3778 expected_request_args: Option<RouteRequestAndResponse<routes::RouteRequestArgs<I>>>,
3779 expected_response: Option<ExpectedResponse>,
3780 }
3781
3782 fn route_addr_from_spec_addr<I: Ip>(a: &SpecifiedAddr<I::Addr>) -> RouteAddress {
3783 let bytes = I::map_ip_in(a, |a| a.ipv4_bytes().to_vec(), |a| a.ipv6_bytes().to_vec());
3784 match I::VERSION {
3785 IpVersion::V4 => RouteAddress::parse(AddressFamily::Inet, &bytes).unwrap(),
3786 IpVersion::V6 => RouteAddress::parse(AddressFamily::Inet6, &bytes).unwrap(),
3787 }
3788 }
3789
3790 fn route_addr_from_subnet<I: Ip>(a: &Subnet<I::Addr>) -> RouteAddress {
3791 let bytes = I::map_ip_in(
3792 a,
3793 |a| a.network().ipv4_bytes().to_vec(),
3794 |a| a.network().ipv6_bytes().to_vec(),
3795 );
3796 match I::VERSION {
3797 IpVersion::V4 => RouteAddress::parse(AddressFamily::Inet, &bytes).unwrap(),
3798 IpVersion::V6 => RouteAddress::parse(AddressFamily::Inet6, &bytes).unwrap(),
3799 }
3800 }
3801
3802 fn build_route_test_case<I: Ip>(
3803 kind: RouteRequestKind,
3804 flags: u16,
3805 dst: Subnet<I::Addr>,
3806 next_hop: Option<SpecifiedAddr<I::Addr>>,
3807 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3808 interface_id: Option<NonZeroU64>,
3809 table: u8,
3810 rtm_type: u8,
3811 response: Result<(), routes::RequestError>,
3812 ) -> TestRouteCase<I> {
3813 let extra_nlas = extra_nlas.into_iter().collect::<Vec<_>>();
3814 let table_from_nla = extra_nlas.clone().into_iter().find_map(|nla| match nla {
3815 RouteAttribute::Table(table) => Some(NetlinkRouteTableIndex::new(table)),
3816 _ => None,
3817 });
3818 let priority_from_nla = extra_nlas.clone().into_iter().find_map(|nla| match nla {
3819 RouteAttribute::Priority(priority) => Some(priority),
3820 _ => None,
3821 });
3822
3823 TestRouteCase::<I> {
3824 kind,
3825 flags,
3826 family: {
3827 let family = match I::VERSION {
3828 IpVersion::V4 => AF_INET,
3829 IpVersion::V6 => AF_INET6,
3830 };
3831 family as u16
3833 },
3834 nlas: [RouteAttribute::Destination(route_addr_from_subnet::<I>(&dst))]
3835 .into_iter()
3836 .chain(interface_id.map(|id| RouteAttribute::Oif(interface_id_as_u32(id.get()))))
3837 .chain(extra_nlas.into_iter())
3838 .collect(),
3839 destination_prefix_len: {
3840 let prefix_len = I::map_ip_in(dst, |dst| dst.prefix(), |dst| dst.prefix());
3841 prefix_len
3842 },
3843 table,
3844 rtm_type,
3845 expected_request_args: Some(RouteRequestAndResponse {
3846 request: {
3847 match kind {
3848 RouteRequestKind::New => {
3849 let interface_id =
3850 interface_id.expect("new requests must have interface id");
3851
3852 routes::RouteRequestArgs::New::<I>(routes::NewRouteArgs::Unicast(
3853 routes::UnicastNewRouteArgs {
3854 subnet: dst,
3855 target: fnet_routes_ext::RouteTarget {
3856 outbound_interface: interface_id.get(),
3857 next_hop,
3858 },
3859 priority: priority_from_nla.and_then(NonZeroU32::new),
3860 table: table_from_nla.unwrap_or_else(|| {
3862 NetlinkRouteTableIndex::new(table as u32)
3863 }),
3864 },
3865 ))
3866 }
3867 RouteRequestKind::Del => {
3868 routes::RouteRequestArgs::Del::<I>(routes::DelRouteArgs::Unicast(
3869 routes::UnicastDelRouteArgs {
3870 subnet: dst,
3871 outbound_interface: interface_id,
3872 next_hop,
3873 priority: priority_from_nla
3874 .map(|priority| NonZeroU32::new(priority))
3875 .flatten(),
3876 table: table_from_nla
3880 .map(|table_nla| {
3881 NonZeroNetlinkRouteTableIndex::new(table_nla)
3882 })
3883 .flatten()
3884 .unwrap_or_else(|| {
3885 NonZeroNetlinkRouteTableIndex::new_non_zero(
3886 NonZeroU32::new(table as u32).unwrap_or(
3887 NonZeroU32::new(
3888 rt_class_t_RT_TABLE_MAIN as u32,
3889 )
3890 .unwrap(),
3891 ),
3892 )
3893 }),
3894 },
3895 ))
3896 }
3897 }
3898 },
3899 response,
3900 }),
3901 expected_response: (flags & NLM_F_ACK == NLM_F_ACK).then_some(ExpectedResponse::Ack),
3902 }
3903 }
3904
3905 fn build_valid_route_test_case_with_extra_nlas<I: Ip>(
3906 kind: RouteRequestKind,
3907 flags: u16,
3908 addr: Subnet<I::Addr>,
3909 next_hop: Option<SpecifiedAddr<I::Addr>>,
3910 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3911 interface_id: Option<u64>,
3912 table: u8,
3913 rtm_type: u8,
3914 response: Result<(), routes::RequestError>,
3915 ) -> TestRouteCase<I> {
3916 build_route_test_case::<I>(
3917 kind,
3918 flags,
3919 addr,
3920 next_hop,
3921 extra_nlas,
3922 interface_id.map(|id| NonZeroU64::new(id)).flatten(),
3923 table,
3924 rtm_type,
3925 response,
3926 )
3927 }
3928
3929 fn build_valid_route_test_case<I: Ip>(
3930 kind: RouteRequestKind,
3931 flags: u16,
3932 addr: Subnet<I::Addr>,
3933 interface_id: Option<u64>,
3934 table: u8,
3935 rtm_type: u8,
3936 response: Result<(), routes::RequestError>,
3937 ) -> TestRouteCase<I> {
3938 build_valid_route_test_case_with_extra_nlas::<I>(
3939 kind,
3940 flags,
3941 addr,
3942 None,
3943 None,
3944 interface_id,
3945 table,
3946 rtm_type,
3947 response,
3948 )
3949 }
3950
3951 fn build_invalid_route_test_case<I: Ip>(
3952 kind: RouteRequestKind,
3953 flags: u16,
3954 addr: Subnet<I::Addr>,
3955 interface_id: Option<u64>,
3956 table: u8,
3957 rtm_type: u8,
3958 errno: Errno,
3959 ) -> TestRouteCase<I> {
3960 build_invalid_route_test_case_with_extra_nlas::<I>(
3961 kind,
3962 flags,
3963 addr,
3964 None,
3965 None,
3966 interface_id,
3967 table,
3968 rtm_type,
3969 errno,
3970 )
3971 }
3972
3973 fn build_invalid_route_test_case_with_extra_nlas<I: Ip>(
3974 kind: RouteRequestKind,
3975 flags: u16,
3976 addr: Subnet<I::Addr>,
3977 next_hop: Option<SpecifiedAddr<I::Addr>>,
3978 extra_nlas: impl IntoIterator<Item = RouteAttribute>,
3979 interface_id: Option<u64>,
3980 table: u8,
3981 rtm_type: u8,
3982 errno: Errno,
3983 ) -> TestRouteCase<I> {
3984 TestRouteCase {
3985 expected_request_args: None,
3986 expected_response: Some(ExpectedResponse::Error(errno)),
3987 ..build_valid_route_test_case_with_extra_nlas::<I>(
3988 kind,
3989 flags,
3990 addr,
3991 next_hop,
3992 extra_nlas,
3993 interface_id,
3994 table,
3995 rtm_type,
3996 Ok(()),
3997 )
3998 }
3999 }
4000
4001 #[derive(Clone, Debug, PartialEq)]
4002 enum RouteRequestArgsEither {
4003 V4(routes::RequestArgs<Ipv4>),
4004 V6(routes::RequestArgs<Ipv6>),
4005 }
4006
4007 async fn test_route_request<I: Ip>(
4008 request: NetlinkMessage<RouteNetlinkMessage>,
4009 req_and_resp: Option<RouteRequestAndResponse<routes::RouteRequestArgs<I>>>,
4010 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
4011 let (mut client_sink, mut client, async_work_drain_task) = {
4012 crate::client::testutil::new_fake_client::<NetlinkRoute>(
4013 crate::client::testutil::CLIENT_ID_1,
4014 std::iter::empty(),
4015 )
4016 };
4017 let join_handle = fasync::Task::spawn(async_work_drain_task);
4018
4019 let (unified_request_sink, unified_request_stream) = mpsc::channel(0);
4020 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
4021
4022 let mut unified_request_stream = pin!(unified_request_stream);
4023
4024 match req_and_resp {
4025 None => {
4026 handler.handle_request(request, &mut client).await;
4027 assert_matches!(unified_request_stream.next().now_or_never(), None);
4028 }
4029 Some(RouteRequestAndResponse { request: expected_request, response }) => {
4030 let ((), ()) =
4031 futures::join!(handler.handle_request(request, &mut client), async {
4032 let args = match I::VERSION {
4033 IpVersion::V4 => {
4034 let next = unified_request_stream.next();
4035 let routes::Request {
4036 args,
4037 sequence_number: _,
4038 client: _,
4039 completer,
4040 } = match next.await.expect("handler should send request") {
4041 UnifiedRequest::RoutesV4Request(request) => request,
4042 UnifiedRequest::InterfacesRequest(_)
4043 | UnifiedRequest::RoutesV6Request(_)
4044 | UnifiedRequest::RuleV4Request(_, _)
4045 | UnifiedRequest::RuleV6Request(_, _)
4046 | UnifiedRequest::NeighborsRequest(_) => {
4047 panic!("not RoutesV4Request")
4048 }
4049 };
4050 completer.send(response).expect("handler should be alive");
4051 RouteRequestArgsEither::V4(args)
4052 }
4053 IpVersion::V6 => {
4054 let next = unified_request_stream.next();
4055 let routes::Request {
4056 args,
4057 sequence_number: _,
4058 client: _,
4059 completer,
4060 } = match next.await.expect("handler should send request") {
4061 UnifiedRequest::RoutesV6Request(request) => request,
4062 UnifiedRequest::InterfacesRequest(_)
4063 | UnifiedRequest::RoutesV4Request(_)
4064 | UnifiedRequest::RuleV4Request(_, _)
4065 | UnifiedRequest::RuleV6Request(_, _)
4066 | UnifiedRequest::NeighborsRequest(_) => {
4067 panic!("not RoutesV6Request")
4068 }
4069 };
4070 completer.send(response).expect("handler should be alive");
4071 RouteRequestArgsEither::V6(args)
4072 }
4073 };
4074
4075 #[derive(GenericOverIp)]
4076 #[generic_over_ip(I, Ip)]
4077 struct EqualityInputs<I: Ip> {
4078 args: RouteRequestArgsEither,
4079 expected_request: routes::RequestArgs<I>,
4080 }
4081
4082 I::map_ip_in(
4083 EqualityInputs {
4084 args: args,
4085 expected_request: routes::RequestArgs::Route(expected_request),
4086 },
4087 |EqualityInputs { args, expected_request }| {
4088 let args = assert_matches!(
4089 args,
4090 RouteRequestArgsEither::V4(request) => request
4091 );
4092 assert_eq!(args, expected_request);
4093 },
4094 |EqualityInputs { args, expected_request }| {
4095 let args = assert_matches!(
4096 args,
4097 RouteRequestArgsEither::V6(request) => request
4098 );
4099 assert_eq!(args, expected_request);
4100 },
4101 );
4102 });
4103 }
4104 }
4105
4106 drop(client);
4107 join_handle.await;
4108 client_sink.take_messages()
4109 }
4110
4111 #[test_case(
4115 TestRouteCase::<Ipv4> {
4116 family: AF_UNSPEC as u16,
4117 ..build_invalid_route_test_case(
4118 RouteRequestKind::New,
4119 NLM_F_ACK,
4120 TEST_V4_SUBNET,
4121 Some(interfaces::testutil::LO_INTERFACE_ID),
4122 rt_class_t_RT_TABLE_MAIN as u8,
4123 RTN_UNICAST as u8,
4124 Errno::EINVAL,
4125 )
4126 }; "new_v4_invalid_family_ack")]
4127 #[test_case(
4128 TestRouteCase::<Ipv6> {
4129 family: AF_UNSPEC as u16,
4130 ..build_invalid_route_test_case(
4131 RouteRequestKind::New,
4132 0,
4133 TEST_V6_SUBNET,
4134 Some(interfaces::testutil::LO_INTERFACE_ID),
4135 rt_class_t_RT_TABLE_MAIN as u8,
4136 RTN_UNICAST as u8,
4137 Errno::EINVAL,
4138 )
4139 })]
4140 #[test_case(
4141 TestRouteCase::<Ipv4> {
4142 flags: NLM_F_ACK | NLM_F_REPLACE,
4143 ..build_invalid_route_test_case::<Ipv4>(
4144 RouteRequestKind::New,
4145 NLM_F_ACK,
4146 TEST_V4_SUBNET,
4147 Some(interfaces::testutil::LO_INTERFACE_ID),
4148 rt_class_t_RT_TABLE_MAIN as u8,
4149 RTN_UNICAST as u8,
4150 Errno::ENOTSUP,
4151 )
4152 }; "new_v4_replace_flag_ack")]
4153 #[test_case(
4154 build_invalid_route_test_case::<Ipv6>(
4155 RouteRequestKind::New,
4156 NLM_F_REPLACE,
4157 TEST_V6_SUBNET,
4158 Some(interfaces::testutil::LO_INTERFACE_ID),
4159 rt_class_t_RT_TABLE_MAIN as u8,
4160 RTN_UNICAST as u8,
4161 Errno::ENOTSUP,
4162 ); "new_v6_replace_flag_no_ack")]
4163 #[test_case(
4164 build_invalid_route_test_case::<Ipv4>(
4165 RouteRequestKind::New,
4166 NLM_F_ACK,
4167 TEST_V4_SUBNET,
4168 Some(interfaces::testutil::LO_INTERFACE_ID),
4169 rt_class_t_RT_TABLE_MAIN as u8,
4170 RTN_MULTICAST as u8,
4171 Errno::ENOTSUP); "new_v4_non_unicast_type_ack")]
4172 #[test_case(
4173 build_invalid_route_test_case::<Ipv6>(
4174 RouteRequestKind::New,
4175 0,
4176 TEST_V6_SUBNET,
4177 Some(interfaces::testutil::LO_INTERFACE_ID),
4178 rt_class_t_RT_TABLE_MAIN as u8,
4179 RTN_MULTICAST as u8,
4180 Errno::ENOTSUP); "new_v6_non_unicast_type_no_ack")]
4181 #[test_case(
4182 build_valid_route_test_case::<Ipv4>(
4183 RouteRequestKind::New,
4184 NLM_F_ACK,
4185 net_subnet_v4!("0.0.0.0/0"),
4186 Some(interfaces::testutil::LO_INTERFACE_ID),
4187 rt_class_t_RT_TABLE_MAIN as u8,
4188 RTN_UNICAST as u8,
4189 Ok(())); "new_v4_default_route_ok_ack")]
4190 #[test_case(
4191 build_valid_route_test_case::<Ipv4>(
4192 RouteRequestKind::New,
4193 0,
4194 net_subnet_v4!("0.0.0.0/24"),
4195 Some(interfaces::testutil::LO_INTERFACE_ID),
4196 rt_class_t_RT_TABLE_MAIN as u8,
4197 RTN_UNICAST as u8,
4198 Ok(())); "new_v4_unspecified_route_non_zero_prefix_ok_no_ack")]
4199 #[test_case(
4200 build_valid_route_test_case::<Ipv6>(
4201 RouteRequestKind::New,
4202 NLM_F_ACK,
4203 net_subnet_v6!("::/0"),
4204 Some(interfaces::testutil::LO_INTERFACE_ID),
4205 rt_class_t_RT_TABLE_MAIN as u8,
4206 RTN_UNICAST as u8,
4207 Ok(())); "new_v6_default_route_prefix_ack")]
4208 #[test_case(
4209 build_valid_route_test_case::<Ipv6>(
4210 RouteRequestKind::New,
4211 0,
4212 net_subnet_v6!("::/64"),
4213 Some(interfaces::testutil::LO_INTERFACE_ID),
4214 rt_class_t_RT_TABLE_MAIN as u8,
4215 RTN_UNICAST as u8,
4216 Ok(())); "new_v6_unspecified_route_non_zero_prefix_no_ack")]
4217 #[test_case(
4218 build_valid_route_test_case::<Ipv4>(
4219 RouteRequestKind::New,
4220 NLM_F_ACK,
4221 TEST_V4_SUBNET,
4222 Some(interfaces::testutil::LO_INTERFACE_ID),
4223 rt_class_t_RT_TABLE_MAIN as u8,
4224 RTN_UNICAST as u8,
4225 Ok(())); "new_v4_ok_ack")]
4226 #[test_case(
4227 build_valid_route_test_case::<Ipv6>(
4228 RouteRequestKind::New,
4229 NLM_F_ACK,
4230 TEST_V6_SUBNET,
4231 Some(interfaces::testutil::LO_INTERFACE_ID),
4232 rt_class_t_RT_TABLE_MAIN as u8,
4233 RTN_UNICAST as u8,
4234 Ok(())); "new_v6_ok_ack")]
4235 #[test_case(
4236 build_valid_route_test_case::<Ipv4>(
4237 RouteRequestKind::New,
4238 0,
4239 TEST_V4_SUBNET,
4240 Some(interfaces::testutil::LO_INTERFACE_ID),
4241 rt_class_t_RT_TABLE_MAIN as u8,
4242 RTN_UNICAST as u8,
4243 Ok(())); "new_v4_ok_no_ack")]
4244 #[test_case(
4245 build_valid_route_test_case::<Ipv6>(
4246 RouteRequestKind::New,
4247 0,
4248 TEST_V6_SUBNET,
4249 Some(interfaces::testutil::LO_INTERFACE_ID),
4250 rt_class_t_RT_TABLE_MAIN as u8,
4251 RTN_UNICAST as u8,
4252 Ok(())); "new_v6_ok_no_ack")]
4253 #[test_case(
4254 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4255 RouteRequestKind::New,
4256 NLM_F_ACK,
4257 TEST_V4_SUBNET,
4258 Some(test_nexthop_spec_addr::<Ipv4>()),
4259 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv4>(
4260 &test_nexthop_spec_addr::<Ipv4>()
4261 ))],
4262 Some(interfaces::testutil::LO_INTERFACE_ID),
4263 rt_class_t_RT_TABLE_MAIN as u8,
4264 RTN_UNICAST as u8,
4265 Ok(())); "new_v4_with_nexthop_ok_ack")]
4266 #[test_case(
4267 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4268 RouteRequestKind::New,
4269 0,
4270 TEST_V6_SUBNET,
4271 Some(test_nexthop_spec_addr::<Ipv6>()),
4272 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv6>(
4273 &test_nexthop_spec_addr::<Ipv6>()
4274 ))],
4275 Some(interfaces::testutil::LO_INTERFACE_ID),
4276 rt_class_t_RT_TABLE_MAIN as u8,
4277 RTN_UNICAST as u8,
4278 Ok(())); "new_v6_with_nexthop_ok_no_ack")]
4279 #[test_case(
4280 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4281 RouteRequestKind::New,
4282 NLM_F_ACK,
4283 TEST_V4_SUBNET,
4284 None,
4285 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet, &net_ip_v4!("0.0.0.0").ipv4_bytes().to_vec()).unwrap())],
4286 Some(interfaces::testutil::LO_INTERFACE_ID),
4287 rt_class_t_RT_TABLE_MAIN as u8,
4288 RTN_UNICAST as u8,
4289 Ok(())); "new_v4_unspecified_nexthop_ok_ack")]
4290 #[test_case(
4291 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4292 RouteRequestKind::New,
4293 0,
4294 TEST_V6_SUBNET,
4295 None,
4296 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet6, &net_ip_v6!("::").ipv6_bytes().to_vec()).unwrap())],
4297 Some(interfaces::testutil::LO_INTERFACE_ID),
4298 rt_class_t_RT_TABLE_MAIN as u8,
4299 RTN_UNICAST as u8,
4300 Ok(())); "new_v6_unspecified_nexthop_no_ack")]
4301 #[test_case(
4302 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4303 RouteRequestKind::New,
4304 NLM_F_ACK,
4305 TEST_V4_SUBNET,
4306 None,
4307 [RouteAttribute::Priority(100)],
4308 Some(interfaces::testutil::LO_INTERFACE_ID),
4309 rt_class_t_RT_TABLE_MAIN as u8,
4310 RTN_UNICAST as u8,
4311 Ok(())); "new_v4_priority_nla_ok_ack")]
4312 #[test_case(
4313 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4314 RouteRequestKind::New,
4315 0,
4316 TEST_V6_SUBNET,
4317 None,
4318 [RouteAttribute::Priority(100)],
4319 Some(interfaces::testutil::LO_INTERFACE_ID),
4320 rt_class_t_RT_TABLE_MAIN as u8,
4321 RTN_UNICAST as u8,
4322 Ok(())); "new_v6_priority_nla_ok_no_ack")]
4323 #[test_case(
4324 TestRouteCase::<Ipv4> {
4325 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4326 ..build_valid_route_test_case(
4327 RouteRequestKind::New,
4328 NLM_F_ACK,
4329 TEST_V4_SUBNET,
4330 Some(interfaces::testutil::LO_INTERFACE_ID),
4331 rt_class_t_RT_TABLE_MAIN as u8,
4332 RTN_UNICAST as u8,
4333 Err(routes::RequestError::InvalidRequest),
4334 )
4335 }; "new_v4_invalid_request_response_ack")]
4336 #[test_case(
4337 TestRouteCase::<Ipv6> {
4338 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4339 ..build_valid_route_test_case(
4340 RouteRequestKind::New,
4341 NLM_F_ACK,
4342 TEST_V6_SUBNET,
4343 Some(interfaces::testutil::LO_INTERFACE_ID),
4344 rt_class_t_RT_TABLE_MAIN as u8,
4345 RTN_UNICAST as u8,
4346 Err(routes::RequestError::InvalidRequest),
4347 )
4348 }; "new_v6_invalid_request_response_no_ack")]
4349 #[test_case(
4350 TestRouteCase::<Ipv6> {
4351 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
4352 ..build_valid_route_test_case(
4353 RouteRequestKind::New,
4354 0,
4355 TEST_V6_SUBNET,
4356 Some(interfaces::testutil::LO_INTERFACE_ID),
4357 rt_class_t_RT_TABLE_MAIN as u8,
4358 RTN_UNICAST as u8,
4359 Err(routes::RequestError::UnrecognizedInterface),
4360 )
4361 }; "new_v6_unrecognized_interface_response_no_ack")]
4362 #[test_case(
4363 TestRouteCase::<Ipv6> {
4364 expected_response: Some(ExpectedResponse::Error(Errno::ENOTSUP)),
4365 ..build_valid_route_test_case(
4366 RouteRequestKind::New,
4367 0,
4368 TEST_V6_SUBNET,
4369 Some(interfaces::testutil::LO_INTERFACE_ID),
4370 rt_class_t_RT_TABLE_MAIN as u8,
4371 RTN_UNICAST as u8,
4372 Err(routes::RequestError::Unknown),
4373 )
4374 }; "new_v6_unknown_response_no_ack")]
4375 #[test_case(
4376 TestRouteCase::<Ipv4> {
4377 nlas: vec![
4378 RouteAttribute::Destination(route_addr_from_subnet::<Ipv4>(
4379 &TEST_V4_SUBNET
4380 )),
4381 ],
4382 ..build_invalid_route_test_case(
4383 RouteRequestKind::New,
4384 0,
4385 TEST_V4_SUBNET,
4386 Some(interfaces::testutil::LO_INTERFACE_ID),
4387 rt_class_t_RT_TABLE_MAIN as u8,
4388 RTN_UNICAST as u8,
4389 Errno::ENOTSUP,
4390 )
4391 }; "new_v4_missing_oif_nla_ack")]
4392 #[test_case(
4393 TestRouteCase::<Ipv6> {
4394 nlas: vec![
4395 RouteAttribute::Destination(route_addr_from_subnet::<Ipv6>(
4396 &TEST_V6_SUBNET
4397 )),
4398 ],
4399 ..build_invalid_route_test_case(
4400 RouteRequestKind::New,
4401 0,
4402 TEST_V6_SUBNET,
4403 Some(interfaces::testutil::LO_INTERFACE_ID),
4404 rt_class_t_RT_TABLE_MAIN as u8,
4405 RTN_UNICAST as u8,
4406 Errno::ENOTSUP,
4407 )
4408 }; "new_v6_missing_oif_nla_ack")]
4409 #[test_case(
4410 TestRouteCase::<Ipv4> {
4411 nlas: vec![
4412 RouteAttribute::Destination(route_addr_from_subnet::<Ipv4>(
4413 &TEST_V4_SUBNET
4414 )),
4415 ],
4416 ..build_invalid_route_test_case(
4417 RouteRequestKind::New,
4418 0,
4419 TEST_V4_SUBNET,
4420 Some(interfaces::testutil::LO_INTERFACE_ID),
4421 rt_class_t_RT_TABLE_MAIN as u8,
4422 RTN_UNICAST as u8,
4423 Errno::ENOTSUP,
4424 )
4425 }; "new_v4_missing_oif_nla_no_ack")]
4426 #[test_case(
4427 TestRouteCase::<Ipv6> {
4428 nlas: vec![
4429 RouteAttribute::Destination(route_addr_from_subnet::<Ipv6>(
4430 &TEST_V6_SUBNET
4431 )),
4432 ],
4433 ..build_invalid_route_test_case(
4434 RouteRequestKind::New,
4435 0,
4436 TEST_V6_SUBNET,
4437 Some(interfaces::testutil::LO_INTERFACE_ID),
4438 rt_class_t_RT_TABLE_MAIN as u8,
4439 RTN_UNICAST as u8,
4440 Errno::ENOTSUP,
4441 )
4442 }; "new_v6_missing_oif_nla_no_ack")]
4443 #[test_case(
4444 TestRouteCase::<Ipv4> {
4445 nlas: vec![
4446 RouteAttribute::Oif(interfaces::testutil::ETH_INTERFACE_ID.try_into().unwrap()),
4447 ],
4448 destination_prefix_len: 1,
4449 ..build_invalid_route_test_case(
4450 RouteRequestKind::New,
4451 NLM_F_ACK,
4452 TEST_V4_SUBNET,
4453 Some(interfaces::testutil::LO_INTERFACE_ID),
4454 rt_class_t_RT_TABLE_MAIN as u8,
4455 RTN_UNICAST as u8,
4456 Errno::EINVAL,
4457 )
4458 }; "new_v4_missing_destination_nla_nonzero_prefix_ack")]
4459 #[test_case(
4460 TestRouteCase::<Ipv6> {
4461 nlas: vec![
4462 RouteAttribute::Oif(interfaces::testutil::ETH_INTERFACE_ID.try_into().unwrap()),
4463 ],
4464 destination_prefix_len: 1,
4465 ..build_invalid_route_test_case(
4466 RouteRequestKind::New,
4467 0,
4468 TEST_V6_SUBNET,
4469 Some(interfaces::testutil::LO_INTERFACE_ID),
4470 rt_class_t_RT_TABLE_MAIN as u8,
4471 RTN_UNICAST as u8,
4472 Errno::EINVAL,
4473 )
4474 }; "new_v6_missing_destination_nla_nonzero_prefix_no_ack")]
4475 #[test_case(
4476 TestRouteCase::<Ipv4> {
4477 nlas: vec![
4478 RouteAttribute::Oif(interfaces::testutil::LO_INTERFACE_ID.try_into().unwrap()),
4479 ],
4480 ..build_valid_route_test_case(
4481 RouteRequestKind::New,
4482 NLM_F_ACK,
4483 net_subnet_v4!("0.0.0.0/0"),
4484 Some(interfaces::testutil::LO_INTERFACE_ID),
4485 rt_class_t_RT_TABLE_MAIN as u8,
4486 RTN_UNICAST as u8,
4487 Ok(()))}; "new_v4_missing_destination_nla_zero_prefix_ack")]
4488 #[test_case(
4489 TestRouteCase::<Ipv6> {
4490 nlas: vec![
4491 RouteAttribute::Oif(interfaces::testutil::LO_INTERFACE_ID.try_into().unwrap()),
4492 ],
4493 ..build_valid_route_test_case(
4494 RouteRequestKind::New,
4495 0,
4496 net_subnet_v6!("::/0"),
4497 Some(interfaces::testutil::LO_INTERFACE_ID),
4498 rt_class_t_RT_TABLE_MAIN as u8,
4499 RTN_UNICAST as u8,
4500 Ok(()))}; "new_v6_missing_destination_nla_zero_prefix_no_ack")]
4501 #[test_case(
4502 TestRouteCase::<Ipv4> {
4503 nlas: Vec::new(),
4504 ..build_invalid_route_test_case(
4505 RouteRequestKind::New,
4506 NLM_F_ACK,
4507 TEST_V4_SUBNET,
4508 Some(interfaces::testutil::LO_INTERFACE_ID),
4509 rt_class_t_RT_TABLE_MAIN as u8,
4510 RTN_UNICAST as u8,
4511 Errno::EINVAL,
4512 )
4513 }; "new_v4_no_nlas_ack")]
4514 #[test_case(
4515 TestRouteCase::<Ipv6> {
4516 nlas: Vec::new(),
4517 ..build_invalid_route_test_case(
4518 RouteRequestKind::New,
4519 0,
4520 TEST_V6_SUBNET,
4521 Some(interfaces::testutil::LO_INTERFACE_ID),
4522 rt_class_t_RT_TABLE_MAIN as u8,
4523 RTN_UNICAST as u8,
4524 Errno::EINVAL,
4525 )
4526 }; "new_v6_no_nlas_no_ack")]
4527 #[test_case(
4528 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4529 RouteRequestKind::New,
4530 NLM_F_ACK,
4531 TEST_V4_SUBNET,
4532 None,
4533 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4535 Some(interfaces::testutil::LO_INTERFACE_ID),
4536 rt_class_t_RT_TABLE_COMPAT as u8,
4537 RTN_UNICAST as u8,
4538 Ok(())); "new_v4_with_table_nla_rt_table_compat_ack")]
4539 #[test_case(
4540 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4541 RouteRequestKind::New,
4542 0,
4543 TEST_V6_SUBNET,
4544 None,
4545 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4547 Some(interfaces::testutil::LO_INTERFACE_ID),
4548 rt_class_t_RT_TABLE_COMPAT as u8,
4549 RTN_UNICAST as u8,
4550 Ok(())); "new_v6_with_table_nla_rt_table_compat_no_ack")]
4551 #[test_case(
4552 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4553 RouteRequestKind::New,
4554 NLM_F_ACK,
4555 TEST_V4_SUBNET,
4556 None,
4557 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4558 Some(interfaces::testutil::LO_INTERFACE_ID),
4559 rt_class_t_RT_TABLE_MAIN as u8,
4560 RTN_UNICAST as u8,
4561 Ok(())); "new_v4_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_ack")]
4562 #[test_case(
4563 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4564 RouteRequestKind::New,
4565 0,
4566 TEST_V6_SUBNET,
4567 None,
4568 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4569 Some(interfaces::testutil::LO_INTERFACE_ID),
4570 rt_class_t_RT_TABLE_MAIN as u8,
4571 RTN_UNICAST as u8,
4572 Ok(())); "new_v6_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_no_ack")]
4573 #[test_case(
4574 TestRouteCase::<Ipv4> {
4575 destination_prefix_len: u8::MAX,
4576 ..build_invalid_route_test_case(
4577 RouteRequestKind::New,
4578 NLM_F_ACK,
4579 TEST_V4_SUBNET,
4580 Some(interfaces::testutil::LO_INTERFACE_ID),
4581 rt_class_t_RT_TABLE_MAIN as u8,
4582 RTN_UNICAST as u8,
4583 Errno::EINVAL,
4584 )
4585 }; "new_v4_invalid_prefix_len_ack")]
4586 #[test_case(
4587 TestRouteCase::<Ipv6> {
4588 destination_prefix_len: u8::MAX,
4589 ..build_invalid_route_test_case(
4590 RouteRequestKind::New,
4591 0,
4592 TEST_V6_SUBNET,
4593 Some(interfaces::testutil::LO_INTERFACE_ID),
4594 rt_class_t_RT_TABLE_MAIN as u8,
4595 RTN_UNICAST as u8,
4596 Errno::EINVAL,
4597 )
4598 }; "new_v6_invalid_prefix_len_no_ack")]
4599 #[test_case(
4600 TestRouteCase::<Ipv4> {
4601 destination_prefix_len: 0,
4602 ..build_invalid_route_test_case(
4603 RouteRequestKind::New,
4604 NLM_F_ACK,
4605 TEST_V4_SUBNET,
4606 Some(interfaces::testutil::LO_INTERFACE_ID),
4607 rt_class_t_RT_TABLE_MAIN as u8,
4608 RTN_UNICAST as u8,
4609 Errno::EINVAL,
4610 )
4611 }; "new_v4_zero_prefix_len_ack")]
4612 #[test_case(
4613 TestRouteCase::<Ipv6> {
4614 destination_prefix_len: 0,
4615 ..build_invalid_route_test_case(
4616 RouteRequestKind::New,
4617 0,
4618 TEST_V6_SUBNET,
4619 Some(interfaces::testutil::LO_INTERFACE_ID),
4620 rt_class_t_RT_TABLE_MAIN as u8,
4621 RTN_UNICAST as u8,
4622 Errno::EINVAL,
4623 )
4624 }; "new_v6_zero_prefix_len_no_ack")]
4625 #[test_case(
4627 TestRouteCase::<Ipv4> {
4628 family: AF_UNSPEC as u16,
4629 ..build_invalid_route_test_case(
4630 RouteRequestKind::Del,
4631 NLM_F_ACK,
4632 TEST_V4_SUBNET,
4633 Some(interfaces::testutil::LO_INTERFACE_ID),
4634 rt_class_t_RT_TABLE_MAIN as u8,
4635 RTN_UNICAST as u8,
4636 Errno::EINVAL,
4637 )
4638 }; "del_v4_invalid_family_ack")]
4639 #[test_case(
4640 TestRouteCase::<Ipv6> {
4641 family: AF_UNSPEC as u16,
4642 ..build_invalid_route_test_case(
4643 RouteRequestKind::Del,
4644 0,
4645 TEST_V6_SUBNET,
4646 Some(interfaces::testutil::LO_INTERFACE_ID),
4647 rt_class_t_RT_TABLE_MAIN as u8,
4648 RTN_UNICAST as u8,
4649 Errno::EINVAL,
4650 )
4651 }; "del_v6_invalid_family_no_ack")]
4652 #[test_case(
4653 build_invalid_route_test_case::<Ipv4>(
4654 RouteRequestKind::Del,
4655 NLM_F_ACK,
4656 TEST_V4_SUBNET,
4657 Some(interfaces::testutil::LO_INTERFACE_ID),
4658 rt_class_t_RT_TABLE_MAIN as u8,
4659 RTN_MULTICAST as u8,
4660 Errno::ENOTSUP); "del_v4_non_unicast_type_ack")]
4661 #[test_case(
4662 build_invalid_route_test_case::<Ipv6>(
4663 RouteRequestKind::Del,
4664 0,
4665 TEST_V6_SUBNET,
4666 Some(interfaces::testutil::LO_INTERFACE_ID),
4667 rt_class_t_RT_TABLE_MAIN as u8,
4668 RTN_MULTICAST as u8,
4669 Errno::ENOTSUP); "del_v6_non_unicast_type_no_ack")]
4670 #[test_case(
4671 build_valid_route_test_case::<Ipv4>(
4672 RouteRequestKind::Del,
4673 NLM_F_ACK,
4674 net_subnet_v4!("0.0.0.0/0"),
4675 Some(interfaces::testutil::LO_INTERFACE_ID),
4676 rt_class_t_RT_TABLE_MAIN as u8,
4677 RTN_UNICAST as u8,
4678 Ok(())); "del_v4_default_route_ok_ack")]
4679 #[test_case(
4680 build_valid_route_test_case::<Ipv4>(
4681 RouteRequestKind::Del,
4682 0,
4683 net_subnet_v4!("0.0.0.0/24"),
4684 Some(interfaces::testutil::LO_INTERFACE_ID),
4685 rt_class_t_RT_TABLE_MAIN as u8,
4686 RTN_UNICAST as u8,
4687 Ok(())); "del_v4_unspecified_route_non_zero_prefix_ok_no_ack")]
4688 #[test_case(
4689 build_valid_route_test_case::<Ipv6>(
4690 RouteRequestKind::Del,
4691 NLM_F_ACK,
4692 net_subnet_v6!("::/0"),
4693 Some(interfaces::testutil::LO_INTERFACE_ID),
4694 rt_class_t_RT_TABLE_MAIN as u8,
4695 RTN_UNICAST as u8,
4696 Ok(())); "del_v6_default_route_prefix_ack")]
4697 #[test_case(
4698 build_valid_route_test_case::<Ipv6>(
4699 RouteRequestKind::Del,
4700 0,
4701 net_subnet_v6!("::/64"),
4702 Some(interfaces::testutil::LO_INTERFACE_ID),
4703 rt_class_t_RT_TABLE_MAIN as u8,
4704 RTN_UNICAST as u8,
4705 Ok(())); "del_v6_unspecified_route_non_zero_prefix_no_ack")]
4706 #[test_case(
4707 build_valid_route_test_case::<Ipv4>(
4708 RouteRequestKind::Del,
4709 NLM_F_ACK,
4710 TEST_V4_SUBNET,
4711 None,
4712 rt_class_t_RT_TABLE_MAIN as u8,
4713 RTN_UNICAST as u8,
4714 Ok(())); "del_v4_only_dest_nla_ack")]
4715 #[test_case(
4716 build_valid_route_test_case::<Ipv6>(
4717 RouteRequestKind::Del,
4718 NLM_F_ACK,
4719 TEST_V6_SUBNET,
4720 None,
4721 rt_class_t_RT_TABLE_MAIN as u8,
4722 RTN_UNICAST as u8,
4723 Ok(())); "del_v6_only_dest_nla_ack")]
4724 #[test_case(
4725 build_valid_route_test_case::<Ipv4>(
4726 RouteRequestKind::Del,
4727 0,
4728 TEST_V4_SUBNET,
4729 None,
4730 rt_class_t_RT_TABLE_MAIN as u8,
4731 RTN_UNICAST as u8,
4732 Ok(())); "del_v4_only_dest_nla_no_ack")]
4733 #[test_case(
4734 build_valid_route_test_case::<Ipv6>(
4735 RouteRequestKind::Del,
4736 0,
4737 TEST_V6_SUBNET,
4738 None,
4739 rt_class_t_RT_TABLE_MAIN as u8,
4740 RTN_UNICAST as u8,
4741 Ok(())); "del_v6_only_dest_nla_no_ack")]
4742 #[test_case(
4743 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4744 RouteRequestKind::Del,
4745 NLM_F_ACK,
4746 TEST_V4_SUBNET,
4747 Some(test_nexthop_spec_addr::<Ipv4>()),
4748 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv4>(
4749 &test_nexthop_spec_addr::<Ipv4>()
4750 ))],
4751 Some(interfaces::testutil::LO_INTERFACE_ID),
4752 rt_class_t_RT_TABLE_MAIN as u8,
4753 RTN_UNICAST as u8,
4754 Ok(())); "del_v4_with_nexthop_ok_ack")]
4755 #[test_case(
4756 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4757 RouteRequestKind::Del,
4758 0,
4759 TEST_V6_SUBNET,
4760 Some(test_nexthop_spec_addr::<Ipv6>()),
4761 [RouteAttribute::Gateway(route_addr_from_spec_addr::<Ipv6>(
4762 &test_nexthop_spec_addr::<Ipv6>()
4763 ))],
4764 Some(interfaces::testutil::LO_INTERFACE_ID),
4765 rt_class_t_RT_TABLE_MAIN as u8,
4766 RTN_UNICAST as u8,
4767 Ok(())); "del_v6_with_nexthop_ok_no_ack")]
4768 #[test_case(
4769 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4770 RouteRequestKind::Del,
4771 NLM_F_ACK,
4772 TEST_V4_SUBNET,
4773 None,
4774 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet, &net_ip_v4!("0.0.0.0").ipv4_bytes().to_vec()).unwrap())],
4775 Some(interfaces::testutil::LO_INTERFACE_ID),
4776 rt_class_t_RT_TABLE_MAIN as u8,
4777 RTN_UNICAST as u8,
4778 Ok(())); "del_v4_unspecified_nexthop_ok_ack")]
4779 #[test_case(
4780 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4781 RouteRequestKind::Del,
4782 0,
4783 TEST_V6_SUBNET,
4784 None,
4785 [RouteAttribute::Gateway(RouteAddress::parse(AddressFamily::Inet6, &net_ip_v6!("::").ipv6_bytes().to_vec()).unwrap())],
4786 Some(interfaces::testutil::LO_INTERFACE_ID),
4787 rt_class_t_RT_TABLE_MAIN as u8,
4788 RTN_UNICAST as u8,
4789 Ok(())); "del_v6_unspecified_nexthop_no_ack")]
4790 #[test_case(
4791 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4792 RouteRequestKind::Del,
4793 NLM_F_ACK,
4794 TEST_V4_SUBNET,
4795 None,
4796 [RouteAttribute::Priority(100)],
4797 Some(interfaces::testutil::LO_INTERFACE_ID),
4798 rt_class_t_RT_TABLE_MAIN as u8,
4799 RTN_UNICAST as u8,
4800 Ok(())); "del_v4_priority_nla_ok_ack")]
4801 #[test_case(
4802 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4803 RouteRequestKind::Del,
4804 0,
4805 TEST_V6_SUBNET,
4806 None,
4807 [RouteAttribute::Priority(100)],
4808 Some(interfaces::testutil::LO_INTERFACE_ID),
4809 rt_class_t_RT_TABLE_MAIN as u8,
4810 RTN_UNICAST as u8,
4811 Ok(())); "del_v6_priority_nla_ok_no_ack")]
4812 #[test_case(
4813 TestRouteCase::<Ipv4> {
4814 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4815 ..build_valid_route_test_case(
4816 RouteRequestKind::Del,
4817 NLM_F_ACK,
4818 TEST_V4_SUBNET,
4819 Some(interfaces::testutil::LO_INTERFACE_ID),
4820 rt_class_t_RT_TABLE_MAIN as u8,
4821 RTN_UNICAST as u8,
4822 Err(routes::RequestError::InvalidRequest),
4823 )
4824 }; "del_v4_invalid_request_response_ack")]
4825 #[test_case(
4826 TestRouteCase::<Ipv6> {
4827 expected_response: Some(ExpectedResponse::Error(Errno::EINVAL)),
4828 ..build_valid_route_test_case(
4829 RouteRequestKind::Del,
4830 NLM_F_ACK,
4831 TEST_V6_SUBNET,
4832 Some(interfaces::testutil::LO_INTERFACE_ID),
4833 rt_class_t_RT_TABLE_MAIN as u8,
4834 RTN_UNICAST as u8,
4835 Err(routes::RequestError::InvalidRequest),
4836 )
4837 }; "del_v6_invalid_request_response_no_ack")]
4838 #[test_case(
4839 TestRouteCase::<Ipv6> {
4840 expected_response: Some(ExpectedResponse::Error(Errno::ENODEV)),
4841 ..build_valid_route_test_case(
4842 RouteRequestKind::Del,
4843 0,
4844 TEST_V6_SUBNET,
4845 Some(interfaces::testutil::LO_INTERFACE_ID),
4846 rt_class_t_RT_TABLE_MAIN as u8,
4847 RTN_UNICAST as u8,
4848 Err(routes::RequestError::UnrecognizedInterface),
4849 )
4850 }; "del_v6_unrecognized_interface_response_no_ack")]
4851 #[test_case(
4852 TestRouteCase::<Ipv6> {
4853 expected_response: Some(ExpectedResponse::Error(Errno::ENOTSUP)),
4854 ..build_valid_route_test_case(
4855 RouteRequestKind::Del,
4856 0,
4857 TEST_V6_SUBNET,
4858 Some(interfaces::testutil::LO_INTERFACE_ID),
4859 rt_class_t_RT_TABLE_MAIN as u8,
4860 RTN_UNICAST as u8,
4861 Err(routes::RequestError::Unknown),
4862 )
4863 }; "del_v6_unknown_response_no_ack")]
4864 #[test_case(
4865 build_valid_route_test_case::<Ipv4>(
4866 RouteRequestKind::Del,
4867 NLM_F_ACK,
4868 TEST_V4_SUBNET,
4869 Some(interfaces::testutil::LO_INTERFACE_ID),
4870 rt_class_t_RT_TABLE_MAIN as u8,
4871 RTN_UNICAST as u8,
4872 Ok(()),
4873 ); "del_v4_dest_oif_nlas_ack")]
4874 #[test_case(
4875 build_valid_route_test_case::<Ipv6>(
4876 RouteRequestKind::Del,
4877 NLM_F_ACK,
4878 TEST_V6_SUBNET,
4879 Some(interfaces::testutil::LO_INTERFACE_ID),
4880 rt_class_t_RT_TABLE_MAIN as u8,
4881 RTN_UNICAST as u8,
4882 Ok(()),
4883 ); "del_v6_dest_oif_nlas_ack")]
4884 #[test_case(
4885 build_valid_route_test_case::<Ipv4>(
4886 RouteRequestKind::Del,
4887 0,
4888 TEST_V4_SUBNET,
4889 Some(interfaces::testutil::LO_INTERFACE_ID),
4890 rt_class_t_RT_TABLE_MAIN as u8,
4891 RTN_UNICAST as u8,
4892 Ok(()),
4893 ); "del_v4_dest_oif_nlas_no_ack")]
4894 #[test_case(
4895 build_valid_route_test_case::<Ipv6>(
4896 RouteRequestKind::Del,
4897 0,
4898 TEST_V6_SUBNET,
4899 Some(interfaces::testutil::LO_INTERFACE_ID),
4900 rt_class_t_RT_TABLE_MAIN as u8,
4901 RTN_UNICAST as u8,
4902 Ok(()),
4903 ); "del_v6_dest_oif_nlas_no_ack")]
4904 #[test_case(
4905 TestRouteCase::<Ipv4> {
4906 nlas: Vec::new(),
4907 destination_prefix_len: 1,
4908 ..build_invalid_route_test_case(
4909 RouteRequestKind::Del,
4910 NLM_F_ACK,
4911 TEST_V4_SUBNET,
4912 Some(interfaces::testutil::LO_INTERFACE_ID),
4913 rt_class_t_RT_TABLE_MAIN as u8,
4914 RTN_UNICAST as u8,
4915 Errno::EINVAL,
4916 )
4917 }; "del_v4_missing_destination_nla_nonzero_prefix_ack")]
4918 #[test_case(
4919 TestRouteCase::<Ipv6> {
4920 nlas: Vec::new(),
4921 destination_prefix_len: 1,
4922 ..build_invalid_route_test_case(
4923 RouteRequestKind::Del,
4924 0,
4925 TEST_V6_SUBNET,
4926 Some(interfaces::testutil::LO_INTERFACE_ID),
4927 rt_class_t_RT_TABLE_MAIN as u8,
4928 RTN_UNICAST as u8,
4929 Errno::EINVAL,
4930 )
4931 }; "del_v6_missing_destination_nla_nonzero_prefix_no_ack")]
4932 #[test_case(
4933 TestRouteCase::<Ipv4> {
4934 nlas: Vec::new(),
4935 destination_prefix_len: 0,
4936 ..build_valid_route_test_case(
4937 RouteRequestKind::Del,
4938 NLM_F_ACK,
4939 net_subnet_v4!("0.0.0.0/0"),
4940 None,
4941 rt_class_t_RT_TABLE_MAIN as u8,
4942 RTN_UNICAST as u8,
4943 Ok(()),
4944 )
4945 }; "del_v4_no_nlas_zero_prefix_len_ack")]
4946 #[test_case(
4947 TestRouteCase::<Ipv6> {
4948 nlas: Vec::new(),
4949 destination_prefix_len: 0,
4950 ..build_valid_route_test_case(
4951 RouteRequestKind::Del,
4952 0,
4953 net_subnet_v6!("::/0"),
4954 None,
4955 rt_class_t_RT_TABLE_MAIN as u8,
4956 RTN_UNICAST as u8,
4957 Ok(()),
4958 )
4959 }; "del_v6_no_nlas_zero_prefix_len_no_ack")]
4960 #[test_case(
4961 build_valid_route_test_case::<Ipv4>(
4962 RouteRequestKind::Del,
4963 NLM_F_ACK,
4964 net_subnet_v4!("0.0.0.0/0"),
4965 Some(interfaces::testutil::LO_INTERFACE_ID),
4966 rt_class_t_RT_TABLE_MAIN as u8,
4967 RTN_UNICAST as u8,
4968 Ok(()),
4969 ); "del_v4_missing_destination_nla_zero_prefix_ack")]
4970 #[test_case(
4971 build_valid_route_test_case::<Ipv6>(
4972 RouteRequestKind::Del,
4973 0,
4974 net_subnet_v6!("::/0"),
4975 Some(interfaces::testutil::LO_INTERFACE_ID),
4976 rt_class_t_RT_TABLE_MAIN as u8,
4977 RTN_UNICAST as u8,
4978 Ok(()),
4979 ); "del_v6_missing_destination_nla_zero_prefix_no_ack")]
4980 #[test_case(
4981 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
4982 RouteRequestKind::Del,
4983 NLM_F_ACK,
4984 TEST_V4_SUBNET,
4985 None,
4986 [RouteAttribute::Table(u8::MAX as u32 + 1)],
4988 Some(interfaces::testutil::LO_INTERFACE_ID),
4989 rt_class_t_RT_TABLE_COMPAT as u8,
4990 RTN_UNICAST as u8,
4991 Ok(())); "del_v4_with_table_nla_rt_table_compat_ack")]
4992 #[test_case(
4993 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
4994 RouteRequestKind::Del,
4995 0,
4996 TEST_V6_SUBNET,
4997 None,
4998 [RouteAttribute::Table(u8::MAX as u32 + 1)],
5000 Some(interfaces::testutil::LO_INTERFACE_ID),
5001 rt_class_t_RT_TABLE_COMPAT as u8,
5002 RTN_UNICAST as u8,
5003 Ok(())); "del_v6_with_table_nla_rt_table_compat_no_ack")]
5004 #[test_case(
5005 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
5006 RouteRequestKind::Del,
5007 NLM_F_ACK,
5008 TEST_V4_SUBNET,
5009 None,
5010 [RouteAttribute::Table(u8::MAX as u32 + 1)],
5011 Some(interfaces::testutil::LO_INTERFACE_ID),
5012 rt_class_t_RT_TABLE_MAIN as u8,
5013 RTN_UNICAST as u8,
5014 Ok(())); "del_v4_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_ack")]
5015 #[test_case(
5016 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
5017 RouteRequestKind::Del,
5018 0,
5019 TEST_V6_SUBNET,
5020 None,
5021 [RouteAttribute::Table(u8::MAX as u32 + 1)],
5022 Some(interfaces::testutil::LO_INTERFACE_ID),
5023 rt_class_t_RT_TABLE_MAIN as u8,
5024 RTN_UNICAST as u8,
5025 Ok(())); "del_v6_with_table_nla_rt_class_t_RT_TABLE_MAIN as u8_no_ack")]
5026 #[test_case(
5027 TestRouteCase::<Ipv4> {
5028 destination_prefix_len: u8::MAX,
5029 ..build_invalid_route_test_case(
5030 RouteRequestKind::Del,
5031 NLM_F_ACK,
5032 TEST_V4_SUBNET,
5033 Some(interfaces::testutil::LO_INTERFACE_ID),
5034 rt_class_t_RT_TABLE_MAIN as u8,
5035 RTN_UNICAST as u8,
5036 Errno::EINVAL,
5037 )
5038 }; "del_v4_invalid_prefix_len_ack")]
5039 #[test_case(
5040 TestRouteCase::<Ipv6> {
5041 destination_prefix_len: u8::MAX,
5042 ..build_invalid_route_test_case(
5043 RouteRequestKind::Del,
5044 0,
5045 TEST_V6_SUBNET,
5046 Some(interfaces::testutil::LO_INTERFACE_ID),
5047 rt_class_t_RT_TABLE_MAIN as u8,
5048 RTN_UNICAST as u8,
5049 Errno::EINVAL,
5050 )
5051 }; "del_v6_invalid_prefix_len_no_ack")]
5052 #[test_case(
5053 TestRouteCase::<Ipv4> {
5054 destination_prefix_len: 0,
5055 ..build_invalid_route_test_case(
5056 RouteRequestKind::Del,
5057 NLM_F_ACK,
5058 TEST_V4_SUBNET,
5059 Some(interfaces::testutil::LO_INTERFACE_ID),
5060 rt_class_t_RT_TABLE_MAIN as u8,
5061 RTN_UNICAST as u8,
5062 Errno::EINVAL,
5063 )
5064 }; "del_v4_zero_prefix_len_ack")]
5065 #[test_case(
5066 TestRouteCase::<Ipv6> {
5067 destination_prefix_len: 0,
5068 ..build_invalid_route_test_case(
5069 RouteRequestKind::Del,
5070 0,
5071 TEST_V6_SUBNET,
5072 Some(interfaces::testutil::LO_INTERFACE_ID),
5073 rt_class_t_RT_TABLE_MAIN as u8,
5074 RTN_UNICAST as u8,
5075 Errno::EINVAL,
5076 )
5077 }; "del_v6_zero_prefix_len_no_ack")]
5078 #[test_case(
5079 build_valid_route_test_case_with_extra_nlas::<Ipv4>(
5080 RouteRequestKind::Del,
5081 NLM_F_ACK,
5082 TEST_V4_SUBNET,
5083 None,
5084 [RouteAttribute::Oif(0)],
5085 None,
5086 rt_class_t_RT_TABLE_MAIN as u8,
5087 RTN_UNICAST as u8,
5088 Ok(()),
5089 ); "del_v4_zero_interface_id_ack")]
5090 #[test_case(
5091 build_valid_route_test_case_with_extra_nlas::<Ipv6>(
5092 RouteRequestKind::Del,
5093 NLM_F_ACK,
5094 TEST_V6_SUBNET,
5095 None,
5096 [RouteAttribute::Oif(0)],
5097 None,
5098 rt_class_t_RT_TABLE_MAIN as u8,
5099 RTN_UNICAST as u8,
5100 Ok(()),
5101 ); "del_v6_zero_interface_id_no_ack")]
5102 #[fuchsia::test]
5103 async fn test_new_del_route<I: Ip>(test_case: TestRouteCase<I>) {
5104 let TestRouteCase {
5105 kind,
5106 flags,
5107 family,
5108 nlas,
5109 destination_prefix_len,
5110 table,
5111 rtm_type,
5112 expected_request_args,
5113 expected_response,
5114 }: TestRouteCase<I> = test_case;
5115
5116 let header = header_with_flags(flags);
5117 let route_message = {
5118 let mut message = RouteMessage::default();
5119 message.header.address_family = AddressFamily::from(family as u8);
5120 message.header.destination_prefix_length = destination_prefix_len;
5121 message.header.table = table;
5122 message.header.kind = RouteType::from(rtm_type);
5123 message.attributes = nlas;
5124 message
5125 };
5126
5127 let (message, request) = match kind {
5128 RouteRequestKind::New => {
5129 (RouteNetlinkMessage::NewRoute(route_message), expected_request_args)
5130 }
5131 RouteRequestKind::Del => {
5132 (RouteNetlinkMessage::DelRoute(route_message), expected_request_args)
5133 }
5134 };
5135
5136 pretty_assertions::assert_eq!(
5137 test_route_request(
5138 NetlinkMessage::new(header, NetlinkPayload::InnerMessage(message)),
5139 request,
5140 )
5141 .await,
5142 expected_sent_messages(expected_response, header),
5143 )
5144 }
5145
5146 async fn test_neighbor_request(
5147 request: NetlinkMessage<RouteNetlinkMessage>,
5148 expected_request: Option<neighbors::NeighborRequestArgs>,
5149 ) -> Vec<SentMessage<RouteNetlinkMessage>> {
5150 let (mut client_sink, mut client, async_work_drain_task) =
5151 crate::client::testutil::new_fake_client::<NetlinkRoute>(
5152 crate::client::testutil::CLIENT_ID_1,
5153 std::iter::empty(),
5154 );
5155 let join_handle = fasync::Task::spawn(async_work_drain_task);
5156 {
5157 let (unified_request_sink, mut unified_request_stream) = mpsc::channel(0);
5158
5159 let mut handler = NetlinkRouteRequestHandler::<FakeSender<_>> { unified_request_sink };
5160
5161 let handle_request_fut = handler.handle_request(request, &mut client).fuse();
5162 let mut handle_request_fut = pin!(handle_request_fut);
5163 let mut request_fut = unified_request_stream.next().fuse();
5164
5165 futures::select! {
5166 _ = handle_request_fut => assert_eq!(expected_request, None),
5167 request = request_fut => match request.expect("request channel should be open") {
5168 UnifiedRequest::NeighborsRequest(neigh_req) => {
5169 let neighbors::Request { args, sequence_number: _, client: _, completer } =
5170 neigh_req;
5171 assert_eq!(expected_request, Some(args));
5172 completer.send(Ok(())).expect("handler should be alive");
5173 handle_request_fut.await;
5174 },
5175 _ => panic!("received unexpected request"),
5176 }
5177 }
5178 }
5179 drop(client);
5180 join_handle.await;
5181 client_sink.take_messages()
5182 }
5183
5184 #[test_case(
5185 NLM_F_DUMP,
5186 NeighbourHeader::default(),
5187 vec![],
5188 Some(neighbors::GetNeighborArgs::Dump { ip_version: None, interface: None }),
5189 Some(ExpectedResponse::Done); "dump all")]
5190 #[test_case(
5191 NLM_F_DUMP,
5192 NeighbourHeader { family: AddressFamily::Inet, ..Default::default() },
5193 vec![NeighbourAttribute::IfIndex(1)],
5194 Some(neighbors::GetNeighborArgs::Dump {
5195 ip_version: Some(IpVersion::V4),
5196 interface: Some(NonZeroU64::new(1).unwrap()),
5197 }),
5198 Some(ExpectedResponse::Done); "dump ipv4 on interface 1")]
5199 #[test_case(
5200 NLM_F_DUMP | NLM_F_ACK,
5201 NeighbourHeader::default(),
5202 vec![],
5203 Some(neighbors::GetNeighborArgs::Dump { ip_version: None, interface: None }),
5204 Some(ExpectedResponse::Done); "dump all with ack")]
5205 #[test_case(
5206 NLM_F_DUMP,
5207 NeighbourHeader { family: AddressFamily::Local, ..Default::default() },
5208 vec![],
5209 None,
5210 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "dump invalid request")]
5211 #[test_case(
5212 0,
5213 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5214 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5215 Some(neighbors::GetNeighborArgs::Get {
5216 ip: fidl_ip!("192.168.0.1"),
5217 interface: NonZeroU64::new(1).unwrap(),
5218 }),
5219 None; "get")]
5220 #[test_case(
5221 NLM_F_ACK,
5222 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5223 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5224 Some(neighbors::GetNeighborArgs::Get {
5225 ip: fidl_ip!("192.168.0.1"),
5226 interface: NonZeroU64::new(1).unwrap(),
5227 }),
5228 Some(ExpectedResponse::Ack); "get with ack")]
5229 #[test_case(
5230 0,
5231 NeighbourHeader::default(),
5232 vec![],
5233 None,
5234 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "get invalid request")]
5235 #[fuchsia::test]
5236 async fn get_neighbor_with_faked_response(
5237 flags: u16,
5238 header: NeighbourHeader,
5239 attrs: Vec<NeighbourAttribute>,
5240 expected_request_args: Option<neighbors::GetNeighborArgs>,
5241 expected_response: Option<ExpectedResponse>,
5242 ) {
5243 let nl_header = header_with_flags(flags);
5244 let neighbor_message = {
5245 let mut message = NeighbourMessage::default();
5246 message.header = header;
5247 message.attributes = attrs;
5248 message
5249 };
5250
5251 pretty_assertions::assert_eq!(
5252 test_neighbor_request(
5253 NetlinkMessage::new(
5254 nl_header,
5255 NetlinkPayload::InnerMessage(RouteNetlinkMessage::GetNeighbour(
5256 neighbor_message
5257 )),
5258 ),
5259 expected_request_args.map(neighbors::NeighborRequestArgs::Get),
5260 )
5261 .await,
5262 expected_sent_messages(expected_response, nl_header),
5263 )
5264 }
5265
5266 #[test_case(
5267 0,
5268 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5269 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5270 Some(neighbors::DelNeighborArgs {
5271 ip: fidl_ip!("192.168.0.1"),
5272 interface: NonZeroU64::new(1).unwrap(),
5273 }),
5274 None; "del ipv4")]
5275 #[test_case(
5276 0,
5277 NeighbourHeader { family: AddressFamily::Inet6, ifindex: 1, ..Default::default() },
5278 vec![NeighbourAttribute::Destination(std_ip_v6!("fe80::1").into())],
5279 Some(neighbors::DelNeighborArgs {
5280 ip: fidl_ip!("fe80::1"),
5281 interface: NonZeroU64::new(1).unwrap(),
5282 }),
5283 None; "del ipv6")]
5284 #[test_case(
5285 NLM_F_ACK,
5286 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5287 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5288 Some(neighbors::DelNeighborArgs {
5289 ip: fidl_ip!("192.168.0.1"),
5290 interface: NonZeroU64::new(1).unwrap(),
5291 }),
5292 Some(ExpectedResponse::Ack); "del with ack")]
5293 #[test_case(
5294 0,
5295 NeighbourHeader { family: AddressFamily::Local, ifindex: 1, ..Default::default() },
5296 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5297 None,
5298 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "del invalid family")]
5299 #[test_case(
5300 0,
5301 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5302 vec![],
5303 None,
5304 Some(ExpectedResponse::Error(Errno::EINVAL)); "del missing destination")]
5305 #[test_case(
5306 0,
5307 NeighbourHeader { family: AddressFamily::Inet, ifindex: 0, ..Default::default() },
5308 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5309 None,
5310 Some(ExpectedResponse::Error(Errno::EINVAL)); "del missing interface")]
5311 #[fuchsia::test]
5312 async fn del_neighbor_with_faked_response(
5313 flags: u16,
5314 header: NeighbourHeader,
5315 attrs: Vec<NeighbourAttribute>,
5316 expected_request_args: Option<neighbors::DelNeighborArgs>,
5317 expected_response: Option<ExpectedResponse>,
5318 ) {
5319 let nl_header = header_with_flags(flags);
5320 let neighbor_message = {
5321 let mut message = NeighbourMessage::default();
5322 message.header = header;
5323 message.attributes = attrs;
5324 message
5325 };
5326
5327 pretty_assertions::assert_eq!(
5328 test_neighbor_request(
5329 NetlinkMessage::new(
5330 nl_header,
5331 NetlinkPayload::InnerMessage(RouteNetlinkMessage::DelNeighbour(
5332 neighbor_message
5333 )),
5334 ),
5335 expected_request_args.map(neighbors::NeighborRequestArgs::Del),
5336 )
5337 .await,
5338 expected_sent_messages(expected_response, nl_header),
5339 )
5340 }
5341
5342 #[test_case(
5343 0,
5344 NeighbourHeader { family: AddressFamily::Inet, ifindex: 1, ..Default::default() },
5345 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5346 None,
5347 Some(ExpectedResponse::Error(Errno::ENOTSUP)); "missing flags")]
5348 #[test_case(
5349 NLM_F_CREATE | NLM_F_REPLACE,
5350 NeighbourHeader {
5351 family: AddressFamily::Inet,
5352 ifindex: 1,
5353 state: NeighbourState::Permanent,
5354 ..Default::default()
5355 },
5356 vec![
5357 NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into()),
5358 NeighbourAttribute::LinkLocalAddress(vec![0, 1, 2, 3, 4, 5]),
5359 ],
5360 Some(neighbors::NeighborRequestArgs::New(neighbors::NewNeighborArgs::CreateStatic {
5361 ip: fidl_ip!("192.168.0.1"),
5362 interface: NonZeroU64::new(1).unwrap(),
5363 mac: fnet::MacAddress { octets: [0, 1, 2, 3, 4, 5] },
5364 })),
5365 None; "create static ipv4")]
5366 #[test_case(
5367 NLM_F_CREATE | NLM_F_REPLACE,
5368 NeighbourHeader {
5369 family: AddressFamily::Inet6,
5370 ifindex: 1,
5371 state: NeighbourState::Permanent,
5372 ..Default::default()
5373 },
5374 vec![
5375 NeighbourAttribute::Destination(std_ip_v6!("fe80::1").into()),
5376 NeighbourAttribute::LinkLocalAddress(vec![0, 1, 2, 3, 4, 5]),
5377 ],
5378 Some(neighbors::NeighborRequestArgs::New(neighbors::NewNeighborArgs::CreateStatic {
5379 ip: fidl_ip!("fe80::1"),
5380 interface: NonZeroU64::new(1).unwrap(),
5381 mac: fnet::MacAddress { octets: [0, 1, 2, 3, 4, 5] },
5382 })),
5383 None; "create static ipv6")]
5384 #[test_case(
5385 NLM_F_REPLACE,
5386 NeighbourHeader {
5387 family: AddressFamily::Inet,
5388 ifindex: 1,
5389 state: NeighbourState::Probe,
5390 ..Default::default()
5391 },
5392 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5393 Some(neighbors::NeighborRequestArgs::New(neighbors::NewNeighborArgs::ProbeExisting {
5394 ip: fidl_ip!("192.168.0.1"),
5395 interface: NonZeroU64::new(1).unwrap(),
5396 })),
5397 None; "probe existing")]
5398 #[test_case(
5399 NLM_F_REPLACE,
5400 NeighbourHeader { family: AddressFamily::Local, ifindex: 1, ..Default::default() },
5401 vec![
5402 NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into()),
5403 ],
5404 None,
5405 Some(ExpectedResponse::Error(Errno::EAFNOSUPPORT)); "invalid family")]
5406 #[test_case(
5407 NLM_F_CREATE | NLM_F_REPLACE,
5408 NeighbourHeader {
5409 family: AddressFamily::Inet,
5410 ifindex: 1,
5411 state: NeighbourState::Probe,
5412 ..Default::default()
5413 },
5414 vec![
5415 NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into()),
5416 NeighbourAttribute::LinkLocalAddress(vec![0, 1, 2, 3, 4, 5]),
5417 ],
5418 None,
5419 Some(ExpectedResponse::Error(Errno::EINVAL)); "invalid state for create static")]
5420 #[test_case(
5421 NLM_F_CREATE | NLM_F_REPLACE,
5422 NeighbourHeader {
5423 family: AddressFamily::Inet,
5424 ifindex: 1,
5425 state: NeighbourState::Permanent,
5426 ..Default::default()
5427 },
5428 vec![
5429 NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into()),
5430 ],
5431 None,
5432 Some(ExpectedResponse::Error(Errno::EINVAL)); "invalid state for probe")]
5433 #[test_case(
5434 NLM_F_CREATE | NLM_F_REPLACE,
5435 NeighbourHeader {
5436 family: AddressFamily::Inet,
5437 ifindex: 1,
5438 state: NeighbourState::Permanent,
5439 ..Default::default()
5440 },
5441 vec![NeighbourAttribute::Destination(std_ip_v4!("192.168.0.1").into())],
5442 None,
5443 Some(ExpectedResponse::Error(Errno::EINVAL)); "create static missing mac")]
5444 #[fuchsia::test]
5445 async fn new_neighbor_with_faked_response(
5446 flags: u16,
5447 header: NeighbourHeader,
5448 attrs: Vec<NeighbourAttribute>,
5449 expected_request_args: Option<neighbors::NeighborRequestArgs>,
5450 expected_response: Option<ExpectedResponse>,
5451 ) {
5452 let nl_header = header_with_flags(flags);
5453 let neighbor_message = {
5454 let mut message = NeighbourMessage::default();
5455 message.header = header;
5456 message.attributes = attrs;
5457 message
5458 };
5459
5460 pretty_assertions::assert_eq!(
5461 test_neighbor_request(
5462 NetlinkMessage::new(
5463 nl_header,
5464 NetlinkPayload::InnerMessage(RouteNetlinkMessage::NewNeighbour(
5465 neighbor_message
5466 )),
5467 ),
5468 expected_request_args,
5469 )
5470 .await,
5471 expected_sent_messages(expected_response, nl_header),
5472 )
5473 }
5474}