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