netstack3_ip/
socket.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! IPv4 and IPv6 sockets.
6
7use core::cmp::Ordering;
8use core::convert::Infallible;
9use core::num::NonZeroU8;
10
11use log::error;
12use net_types::ip::{Ip, IpVersionMarker, Ipv6Addr, Mtu};
13use net_types::{MulticastAddress, ScopeableAddress, SpecifiedAddr};
14use netstack3_base::socket::{SocketIpAddr, SocketIpAddrExt as _};
15use netstack3_base::{
16    AnyDevice, CounterContext, DeviceIdContext, DeviceIdentifier, EitherDeviceId, InstantContext,
17    IpDeviceAddr, IpExt, Marks, Mms, SendFrameErrorReason, StrongDeviceIdentifier,
18    TxMetadataBindingsTypes, WeakDeviceIdentifier,
19};
20use netstack3_filter::{
21    self as filter, FilterBindingsContext, FilterHandler as _, InterfaceProperties, RawIpBody,
22    TransportPacketSerializer,
23};
24use netstack3_trace::trace_duration;
25use packet::{BufferMut, PacketConstraints, SerializeError};
26use packet_formats::ip::DscpAndEcn;
27use thiserror::Error;
28
29use crate::internal::base::{
30    FilterHandlerProvider, IpCounters, IpDeviceMtuContext, IpLayerIpExt, IpLayerPacketMetadata,
31    IpPacketDestination, IpSendFrameError, IpSendFrameErrorReason, ResolveRouteError,
32    SendIpPacketMeta,
33};
34use crate::internal::device::state::IpDeviceStateIpExt;
35use crate::internal::routing::rules::RuleInput;
36use crate::internal::routing::PacketOrigin;
37use crate::internal::types::{InternalForwarding, ResolvedRoute, RoutableIpAddr};
38use crate::{HopLimits, NextHop};
39
40/// An execution context defining a type of IP socket.
41pub trait IpSocketHandler<I: IpExt, BC: TxMetadataBindingsTypes>:
42    DeviceIdContext<AnyDevice>
43{
44    /// Constructs a new [`IpSock`].
45    ///
46    /// `new_ip_socket` constructs a new `IpSock` to the given remote IP
47    /// address from the given local IP address with the given IP protocol. If
48    /// no local IP address is given, one will be chosen automatically. If
49    /// `device` is `Some`, the socket will be bound to the given device - only
50    /// routes which egress over the device will be used. If no route is
51    /// available which egresses over the device - even if routes are available
52    /// which egress over other devices - the socket will be considered
53    /// unroutable.
54    ///
55    /// `new_ip_socket` returns an error if no route to the remote was found in
56    /// the forwarding table or if the given local IP address is not valid for
57    /// the found route.
58    fn new_ip_socket<O>(
59        &mut self,
60        bindings_ctx: &mut BC,
61        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
62        local_ip: Option<IpDeviceAddr<I::Addr>>,
63        remote_ip: SocketIpAddr<I::Addr>,
64        proto: I::Proto,
65        options: &O,
66    ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
67    where
68        O: RouteResolutionOptions<I>;
69
70    /// Sends an IP packet on a socket.
71    ///
72    /// The generated packet has its metadata initialized from `socket`,
73    /// including the source and destination addresses, the Time To Live/Hop
74    /// Limit, and the Protocol/Next Header. The outbound device is also chosen
75    /// based on information stored in the socket.
76    ///
77    /// `mtu` may be used to optionally impose an MTU on the outgoing packet.
78    /// Note that the device's MTU will still be imposed on the packet. That is,
79    /// the smaller of `mtu` and the device's MTU will be imposed on the packet.
80    ///
81    /// If the socket is currently unroutable, an error is returned.
82    fn send_ip_packet<S, O>(
83        &mut self,
84        bindings_ctx: &mut BC,
85        socket: &IpSock<I, Self::WeakDeviceId>,
86        body: S,
87        options: &O,
88        tx_metadata: BC::TxMetadata,
89    ) -> Result<(), IpSockSendError>
90    where
91        S: TransportPacketSerializer<I>,
92        S::Buffer: BufferMut,
93        O: SendOptions<I> + RouteResolutionOptions<I>;
94
95    /// Confirms the provided IP socket destination is reachable.
96    ///
97    /// Implementations must retrieve the next hop given the provided
98    /// IP socket and confirm neighbor reachability for the resolved target
99    /// device.
100    fn confirm_reachable<O>(
101        &mut self,
102        bindings_ctx: &mut BC,
103        socket: &IpSock<I, Self::WeakDeviceId>,
104        options: &O,
105    ) where
106        O: RouteResolutionOptions<I>;
107
108    /// Creates a temporary IP socket and sends a single packet on it.
109    ///
110    /// `local_ip`, `remote_ip`, `proto`, and `options` are passed directly to
111    /// [`IpSocketHandler::new_ip_socket`]. `get_body_from_src_ip` is given the
112    /// source IP address for the packet - which may have been chosen
113    /// automatically if `local_ip` is `None` - and returns the body to be
114    /// encapsulated. This is provided in case the body's contents depend on the
115    /// chosen source IP address.
116    ///
117    /// If `device` is specified, the available routes are limited to those that
118    /// egress over the device.
119    ///
120    /// `mtu` may be used to optionally impose an MTU on the outgoing packet.
121    /// Note that the device's MTU will still be imposed on the packet. That is,
122    /// the smaller of `mtu` and the device's MTU will be imposed on the packet.
123    ///
124    /// # Errors
125    ///
126    /// If an error is encountered while constructing the temporary IP socket
127    /// or sending the packet, `options` will be returned along with the
128    /// error. `get_body_from_src_ip` is fallible, and if there's an error,
129    /// it will be returned as well.
130    fn send_oneshot_ip_packet_with_fallible_serializer<S, E, F, O>(
131        &mut self,
132        bindings_ctx: &mut BC,
133        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
134        local_ip: Option<IpDeviceAddr<I::Addr>>,
135        remote_ip: RoutableIpAddr<I::Addr>,
136        proto: I::Proto,
137        options: &O,
138        tx_metadata: BC::TxMetadata,
139        get_body_from_src_ip: F,
140    ) -> Result<(), SendOneShotIpPacketError<E>>
141    where
142        S: TransportPacketSerializer<I>,
143        S::Buffer: BufferMut,
144        F: FnOnce(IpDeviceAddr<I::Addr>) -> Result<S, E>,
145        O: SendOptions<I> + RouteResolutionOptions<I>,
146    {
147        let tmp = self
148            .new_ip_socket(bindings_ctx, device, local_ip, remote_ip, proto, options)
149            .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })?;
150        let packet = get_body_from_src_ip(*tmp.local_ip())
151            .map_err(SendOneShotIpPacketError::SerializeError)?;
152        self.send_ip_packet(bindings_ctx, &tmp, packet, options, tx_metadata)
153            .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })
154    }
155
156    /// Sends a one-shot IP packet but with a non-fallible serializer.
157    fn send_oneshot_ip_packet<S, F, O>(
158        &mut self,
159        bindings_ctx: &mut BC,
160        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
161        local_ip: Option<IpDeviceAddr<I::Addr>>,
162        remote_ip: SocketIpAddr<I::Addr>,
163        proto: I::Proto,
164        options: &O,
165        tx_metadata: BC::TxMetadata,
166        get_body_from_src_ip: F,
167    ) -> Result<(), IpSockCreateAndSendError>
168    where
169        S: TransportPacketSerializer<I>,
170        S::Buffer: BufferMut,
171        F: FnOnce(IpDeviceAddr<I::Addr>) -> S,
172        O: SendOptions<I> + RouteResolutionOptions<I>,
173    {
174        self.send_oneshot_ip_packet_with_fallible_serializer(
175            bindings_ctx,
176            device,
177            local_ip,
178            remote_ip,
179            proto,
180            options,
181            tx_metadata,
182            |ip| Ok::<_, Infallible>(get_body_from_src_ip(ip)),
183        )
184        .map_err(|err| match err {
185            SendOneShotIpPacketError::CreateAndSendError { err } => err,
186        })
187    }
188}
189
190/// An error in sending a packet on an IP socket.
191#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
192pub enum IpSockSendError {
193    /// An MTU was exceeded.
194    ///
195    /// This could be caused by an MTU at any layer of the stack, including both
196    /// device MTUs and packet format body size limits.
197    #[error("a maximum transmission unit (MTU) was exceeded")]
198    Mtu,
199    /// The socket is currently unroutable.
200    #[error("the socket is currently unroutable: {0}")]
201    Unroutable(#[from] ResolveRouteError),
202    /// The socket operation would've resulted in illegal loopback addresses on
203    /// a non-loopback device.
204    #[error("illegal loopback address")]
205    IllegalLoopbackAddress,
206    /// Broadcast send is not allowed.
207    #[error("Broadcast send is not enabled for the socket")]
208    BroadcastNotAllowed,
209}
210
211impl From<SerializeError<Infallible>> for IpSockSendError {
212    fn from(err: SerializeError<Infallible>) -> IpSockSendError {
213        match err {
214            SerializeError::SizeLimitExceeded => IpSockSendError::Mtu,
215        }
216    }
217}
218
219impl IpSockSendError {
220    /// Constructs a `Result` from an [`IpSendFrameErrorReason`] with
221    /// application-visible [`IpSockSendError`]s in the `Err` variant.
222    ///
223    /// Errors that are not bubbled up to applications are dropped.
224    fn from_ip_send_frame(e: IpSendFrameErrorReason) -> Result<(), Self> {
225        match e {
226            IpSendFrameErrorReason::Device(d) => Self::from_send_frame(d),
227            IpSendFrameErrorReason::IllegalLoopbackAddress => Err(Self::IllegalLoopbackAddress),
228        }
229    }
230
231    /// Constructs a `Result` from a [`SendFrameErrorReason`] with
232    /// application-visible [`IpSockSendError`]s in the `Err` variant.
233    ///
234    /// Errors that are not bubbled up to applications are dropped.
235    fn from_send_frame(e: SendFrameErrorReason) -> Result<(), Self> {
236        match e {
237            SendFrameErrorReason::Alloc | SendFrameErrorReason::QueueFull => Ok(()),
238            SendFrameErrorReason::SizeConstraintsViolation => Err(Self::Mtu),
239        }
240    }
241}
242
243/// An error in sending a packet on a temporary IP socket.
244#[derive(Error, Copy, Clone, Debug)]
245pub enum IpSockCreateAndSendError {
246    /// Cannot send via temporary socket.
247    #[error("cannot send via temporary socket: {0}")]
248    Send(#[from] IpSockSendError),
249    /// The temporary socket could not be created.
250    #[error("the temporary socket could not be created: {0}")]
251    Create(#[from] IpSockCreationError),
252}
253
254/// The error returned by
255/// [`IpSocketHandler::send_oneshot_ip_packet_with_fallible_serializer`].
256#[derive(Debug)]
257#[allow(missing_docs)]
258pub enum SendOneShotIpPacketError<E> {
259    CreateAndSendError { err: IpSockCreateAndSendError },
260    SerializeError(E),
261}
262
263/// Possible errors when retrieving the maximum transport message size.
264#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
265pub enum MmsError {
266    /// Cannot find the device that is used for the ip socket, possibly because
267    /// there is no route.
268    #[error("cannot find the device: {0}")]
269    NoDevice(#[from] ResolveRouteError),
270    /// The MTU provided by the device is too small such that there is no room
271    /// for a transport message at all.
272    #[error("invalid MTU: {0:?}")]
273    MTUTooSmall(Mtu),
274}
275
276/// Gets device related information of an IP socket.
277pub trait DeviceIpSocketHandler<I: IpExt, BC>: DeviceIdContext<AnyDevice> {
278    /// Gets the maximum message size for the transport layer, it equals the
279    /// device MTU minus the IP header size.
280    ///
281    /// This corresponds to the GET_MAXSIZES call described in:
282    /// https://www.rfc-editor.org/rfc/rfc1122#section-3.4
283    fn get_mms<O: RouteResolutionOptions<I>>(
284        &mut self,
285        bindings_ctx: &mut BC,
286        ip_sock: &IpSock<I, Self::WeakDeviceId>,
287        options: &O,
288    ) -> Result<Mms, MmsError>;
289}
290
291/// An error encountered when creating an IP socket.
292#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
293pub enum IpSockCreationError {
294    /// An error occurred while looking up a route.
295    #[error("a route cannot be determined: {0}")]
296    Route(#[from] ResolveRouteError),
297}
298
299/// An IP socket.
300#[derive(Clone, Debug)]
301#[cfg_attr(test, derive(PartialEq))]
302pub struct IpSock<I: IpExt, D> {
303    /// The definition of the socket.
304    ///
305    /// This does not change for the lifetime of the socket.
306    definition: IpSockDefinition<I, D>,
307}
308
309impl<I: IpExt, D> IpSock<I, D> {
310    /// Returns the socket's definition.
311    #[cfg(any(test, feature = "testutils"))]
312    pub fn definition(&self) -> &IpSockDefinition<I, D> {
313        &self.definition
314    }
315}
316
317/// The definition of an IP socket.
318///
319/// These values are part of the socket's definition, and never change.
320#[derive(Clone, Debug, PartialEq)]
321pub struct IpSockDefinition<I: IpExt, D> {
322    /// The socket's remote address.
323    pub remote_ip: SocketIpAddr<I::Addr>,
324    /// The socket's local address.
325    ///
326    /// Guaranteed to be unicast in its subnet since it's always equal to an
327    /// address assigned to the local device. We can't use the `UnicastAddr`
328    /// witness type since `Ipv4Addr` doesn't implement `UnicastAddress`.
329    //
330    // TODO(joshlf): Support unnumbered interfaces. Once we do that, a few
331    // issues arise: A) Does the unicast restriction still apply, and is that
332    // even well-defined for IPv4 in the absence of a subnet? B) Presumably we
333    // have to always bind to a particular interface?
334    pub local_ip: IpDeviceAddr<I::Addr>,
335    /// The socket's bound output device.
336    pub device: Option<D>,
337    /// The IP protocol the socket is bound to.
338    pub proto: I::Proto,
339}
340
341impl<I: IpExt, D> IpSock<I, D> {
342    /// Returns the socket's local IP address.
343    pub fn local_ip(&self) -> &IpDeviceAddr<I::Addr> {
344        &self.definition.local_ip
345    }
346    /// Returns the socket's remote IP address.
347    pub fn remote_ip(&self) -> &SocketIpAddr<I::Addr> {
348        &self.definition.remote_ip
349    }
350    /// Returns the selected output interface for the socket, if any.
351    pub fn device(&self) -> Option<&D> {
352        self.definition.device.as_ref()
353    }
354    /// Returns the socket's protocol.
355    pub fn proto(&self) -> I::Proto {
356        self.definition.proto
357    }
358}
359
360// TODO(joshlf): Once we support configuring transport-layer protocols using
361// type parameters, use that to ensure that `proto` is the right protocol for
362// the caller. We will still need to have a separate enforcement mechanism for
363// raw IP sockets once we support those.
364
365/// The bindings execution context for IP sockets.
366pub trait IpSocketBindingsContext:
367    InstantContext + FilterBindingsContext + TxMetadataBindingsTypes
368{
369}
370impl<BC: InstantContext + FilterBindingsContext + TxMetadataBindingsTypes> IpSocketBindingsContext
371    for BC
372{
373}
374
375/// The context required in order to implement [`IpSocketHandler`].
376///
377/// Blanket impls of `IpSocketHandler` are provided in terms of
378/// `IpSocketContext`.
379pub trait IpSocketContext<I, BC: IpSocketBindingsContext>:
380    DeviceIdContext<AnyDevice, DeviceId: InterfaceProperties<BC::DeviceClass>>
381    + FilterHandlerProvider<I, BC>
382where
383    I: IpDeviceStateIpExt + IpExt,
384{
385    /// Returns a route for a socket.
386    ///
387    /// If `device` is specified, the available routes are limited to those that
388    /// egress over the device.
389    fn lookup_route(
390        &mut self,
391        bindings_ctx: &mut BC,
392        device: Option<&Self::DeviceId>,
393        src_ip: Option<IpDeviceAddr<I::Addr>>,
394        dst_ip: RoutableIpAddr<I::Addr>,
395        transparent: bool,
396        marks: &Marks,
397    ) -> Result<ResolvedRoute<I, Self::DeviceId>, ResolveRouteError>;
398
399    /// Send an IP packet to the next-hop node.
400    fn send_ip_packet<S>(
401        &mut self,
402        bindings_ctx: &mut BC,
403        meta: SendIpPacketMeta<I, &Self::DeviceId, SpecifiedAddr<I::Addr>>,
404        body: S,
405        packet_metadata: IpLayerPacketMetadata<I, Self::WeakAddressId, BC>,
406    ) -> Result<(), IpSendFrameError<S>>
407    where
408        S: TransportPacketSerializer<I>,
409        S::Buffer: BufferMut;
410
411    /// Returns `DeviceId` for the loopback device.
412    fn get_loopback_device(&mut self) -> Option<Self::DeviceId>;
413
414    /// Confirms the provided IP socket destination is reachable.
415    ///
416    /// Implementations must retrieve the next hop given the provided
417    /// IP socket and confirm neighbor reachability for the resolved target
418    /// device.
419    fn confirm_reachable(
420        &mut self,
421        bindings_ctx: &mut BC,
422        dst: SpecifiedAddr<I::Addr>,
423        input: RuleInput<'_, I, Self::DeviceId>,
424    );
425}
426
427/// Enables a blanket implementation of [`IpSocketHandler`].
428///
429/// Implementing this marker trait for a type enables a blanket implementation
430/// of `IpSocketHandler` given the other requirements are met.
431pub trait UseIpSocketHandlerBlanket {}
432
433impl<I, BC, CC> IpSocketHandler<I, BC> for CC
434where
435    I: IpLayerIpExt + IpDeviceStateIpExt,
436    BC: IpSocketBindingsContext,
437    CC: IpSocketContext<I, BC> + CounterContext<IpCounters<I>> + UseIpSocketHandlerBlanket,
438    CC::DeviceId: filter::InterfaceProperties<BC::DeviceClass>,
439{
440    fn new_ip_socket<O>(
441        &mut self,
442        bindings_ctx: &mut BC,
443        device: Option<EitherDeviceId<&CC::DeviceId, &CC::WeakDeviceId>>,
444        local_ip: Option<IpDeviceAddr<I::Addr>>,
445        remote_ip: SocketIpAddr<I::Addr>,
446        proto: I::Proto,
447        options: &O,
448    ) -> Result<IpSock<I, CC::WeakDeviceId>, IpSockCreationError>
449    where
450        O: RouteResolutionOptions<I>,
451    {
452        let device = device
453            .as_ref()
454            .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
455            .transpose()?;
456        let device = device.as_ref().map(|d| d.as_ref());
457
458        // Make sure the remote is routable with a local address before creating
459        // the socket. We do not care about the actual destination here because
460        // we will recalculate it when we send a packet so that the best route
461        // available at the time is used for each outgoing packet.
462        let resolved_route = self.lookup_route(
463            bindings_ctx,
464            device,
465            local_ip,
466            remote_ip,
467            options.transparent(),
468            options.marks(),
469        )?;
470        Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
471    }
472
473    fn send_ip_packet<S, O>(
474        &mut self,
475        bindings_ctx: &mut BC,
476        ip_sock: &IpSock<I, CC::WeakDeviceId>,
477        body: S,
478        options: &O,
479        tx_metadata: BC::TxMetadata,
480    ) -> Result<(), IpSockSendError>
481    where
482        S: TransportPacketSerializer<I>,
483        S::Buffer: BufferMut,
484        O: SendOptions<I> + RouteResolutionOptions<I>,
485    {
486        // TODO(joshlf): Call `trace!` with relevant fields from the socket.
487        self.counters().send_ip_packet.increment();
488
489        send_ip_packet(self, bindings_ctx, ip_sock, body, options, tx_metadata)
490    }
491
492    fn confirm_reachable<O>(
493        &mut self,
494        bindings_ctx: &mut BC,
495        socket: &IpSock<I, CC::WeakDeviceId>,
496        options: &O,
497    ) where
498        O: RouteResolutionOptions<I>,
499    {
500        let bound_device = socket.device().and_then(|weak| weak.upgrade());
501        let bound_device = bound_device.as_ref();
502        let bound_address = Some((*socket.local_ip()).into());
503        let destination = (*socket.remote_ip()).into();
504        IpSocketContext::confirm_reachable(
505            self,
506            bindings_ctx,
507            destination,
508            RuleInput {
509                packet_origin: PacketOrigin::Local { bound_address, bound_device },
510                marks: options.marks(),
511            },
512        )
513    }
514}
515
516/// Provides hooks for altering route resolution behavior of [`IpSock`].
517///
518/// Must be implemented by the socket option type of an `IpSock` when using it
519/// to call [`IpSocketHandler::new_ip_socket`] or
520/// [`IpSocketHandler::send_ip_packet`]. This is implemented as a trait instead
521/// of an inherent impl on a type so that users of sockets that don't need
522/// certain option types can avoid allocating space for those options.
523// TODO(https://fxbug.dev/323389672): We need a mechanism to inform `IpSock` of
524// changes in the route resolution options when it starts caching previously
525// calculated routes. Any changes to the options here *MUST* cause the route to
526// be re-calculated.
527pub trait RouteResolutionOptions<I: Ip> {
528    /// Whether the socket is transparent.
529    ///
530    /// This allows transparently proxying traffic to the socket, and allows the
531    /// socket to be bound to a non-local address.
532    fn transparent(&self) -> bool;
533
534    /// Returns the marks carried by packets created on the socket.
535    fn marks(&self) -> &Marks;
536}
537
538/// Provides hooks for altering sending behavior of [`IpSock`].
539///
540/// Must be implemented by the socket option type of an `IpSock` when using it
541/// to call [`IpSocketHandler::send_ip_packet`]. This is implemented as a trait
542/// instead of an inherent impl on a type so that users of sockets that don't
543/// need certain option types, like TCP for anything multicast-related, can
544/// avoid allocating space for those options.
545pub trait SendOptions<I: IpExt> {
546    /// Returns the hop limit to set on a packet going to the given destination.
547    ///
548    /// If `Some(u)`, `u` will be used as the hop limit (IPv6) or TTL (IPv4) for
549    /// a packet going to the given destination. Otherwise the default value
550    /// will be used.
551    fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8>;
552
553    /// Returns true if outgoing multicast packets should be looped back and
554    /// delivered to local receivers who joined the multicast group.
555    fn multicast_loop(&self) -> bool;
556
557    /// `Some` if the socket can be used to send broadcast packets.
558    fn allow_broadcast(&self) -> Option<I::BroadcastMarker>;
559
560    /// Returns TCLASS/TOS field value that should be set in IP headers.
561    fn dscp_and_ecn(&self) -> DscpAndEcn;
562
563    /// The IP MTU to use for this transmission.
564    ///
565    /// Note that the minimum overall MTU is used considering the device and
566    /// path. This option can be used to restrict an MTU to an upper bound.
567    fn mtu(&self) -> Mtu;
568}
569
570/// Empty send and creation options that never overrides default values.
571#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
572pub struct DefaultIpSocketOptions;
573
574impl<I: IpExt> SendOptions<I> for DefaultIpSocketOptions {
575    fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
576        None
577    }
578
579    fn multicast_loop(&self) -> bool {
580        false
581    }
582
583    fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
584        None
585    }
586
587    fn dscp_and_ecn(&self) -> DscpAndEcn {
588        DscpAndEcn::default()
589    }
590
591    fn mtu(&self) -> Mtu {
592        Mtu::no_limit()
593    }
594}
595
596impl<I: Ip> RouteResolutionOptions<I> for DefaultIpSocketOptions {
597    fn transparent(&self) -> bool {
598        false
599    }
600
601    fn marks(&self) -> &Marks {
602        &Marks::UNMARKED
603    }
604}
605
606/// A trait providing send options delegation to an inner type.
607///
608/// A blanket impl of [`SendOptions`] is provided to all implementers. This
609/// trait has the same shape as `SendOptions` but all the methods provide
610/// default implementations that delegate to the value returned by
611/// `DelegatedSendOptions::Delegate`. For brevity, the default `delegate` is
612/// [`DefaultIpSocketOptions`].
613#[allow(missing_docs)]
614pub trait DelegatedSendOptions<I: IpExt>: OptionDelegationMarker {
615    /// Returns the delegate providing the impl for all default methods.
616    fn delegate(&self) -> &impl SendOptions<I> {
617        &DefaultIpSocketOptions
618    }
619
620    fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
621        self.delegate().hop_limit(destination)
622    }
623
624    fn multicast_loop(&self) -> bool {
625        self.delegate().multicast_loop()
626    }
627
628    fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
629        self.delegate().allow_broadcast()
630    }
631
632    fn dscp_and_ecn(&self) -> DscpAndEcn {
633        self.delegate().dscp_and_ecn()
634    }
635
636    fn mtu(&self) -> Mtu {
637        self.delegate().mtu()
638    }
639}
640
641impl<O: DelegatedSendOptions<I> + OptionDelegationMarker, I: IpExt> SendOptions<I> for O {
642    fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
643        self.hop_limit(destination)
644    }
645
646    fn multicast_loop(&self) -> bool {
647        self.multicast_loop()
648    }
649
650    fn allow_broadcast(&self) -> Option<I::BroadcastMarker> {
651        self.allow_broadcast()
652    }
653
654    fn dscp_and_ecn(&self) -> DscpAndEcn {
655        self.dscp_and_ecn()
656    }
657
658    fn mtu(&self) -> Mtu {
659        self.mtu()
660    }
661}
662
663/// A trait providing route resolution options delegation to an inner type.
664///
665/// A blanket impl of [`RouteResolutionOptions`] is provided to all
666/// implementers. This trait has the same shape as `RouteResolutionOptions` but
667/// all the methods provide default implementations that delegate to the value
668/// returned by `DelegatedRouteResolutionOptions::Delegate`. For brevity, the
669/// default `delegate` is [`DefaultIpSocketOptions`].
670#[allow(missing_docs)]
671pub trait DelegatedRouteResolutionOptions<I: Ip>: OptionDelegationMarker {
672    /// Returns the delegate providing the impl for all default methods.
673    fn delegate(&self) -> &impl RouteResolutionOptions<I> {
674        &DefaultIpSocketOptions
675    }
676
677    fn transparent(&self) -> bool {
678        self.delegate().transparent()
679    }
680
681    fn marks(&self) -> &Marks {
682        self.delegate().marks()
683    }
684}
685
686impl<O: DelegatedRouteResolutionOptions<I> + OptionDelegationMarker, I: IpExt>
687    RouteResolutionOptions<I> for O
688{
689    fn transparent(&self) -> bool {
690        self.transparent()
691    }
692
693    fn marks(&self) -> &Marks {
694        self.marks()
695    }
696}
697
698/// A marker trait to allow option delegation traits.
699///
700/// This trait sidesteps trait resolution rules around the delegation traits
701/// because of the `Ip` parameter in them.
702pub trait OptionDelegationMarker {}
703
704/// The configurable hop limits for a socket.
705#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
706pub struct SocketHopLimits<I: Ip> {
707    /// Unicast hop limit.
708    pub unicast: Option<NonZeroU8>,
709    /// Multicast hop limit.
710    // TODO(https://fxbug.dev/42059735): Make this an Option<u8> to allow sending
711    // multicast packets destined only for the local machine.
712    pub multicast: Option<NonZeroU8>,
713    /// An unused marker type signifying the IP version for which these hop
714    /// limits are valid. Including this helps prevent using the wrong hop limits
715    /// when operating on dualstack sockets.
716    pub version: IpVersionMarker<I>,
717}
718
719impl<I: Ip> SocketHopLimits<I> {
720    /// Returns a function that updates the unicast hop limit.
721    pub fn set_unicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
722        move |limits| limits.unicast = value
723    }
724
725    /// Returns a function that updates the multicast hop limit.
726    pub fn set_multicast(value: Option<NonZeroU8>) -> impl FnOnce(&mut Self) {
727        move |limits| limits.multicast = value
728    }
729
730    /// Returns the hop limits, or the provided defaults if unset.
731    pub fn get_limits_with_defaults(&self, defaults: &HopLimits) -> HopLimits {
732        let Self { unicast, multicast, version: _ } = self;
733        HopLimits {
734            unicast: unicast.unwrap_or(defaults.unicast),
735            multicast: multicast.unwrap_or(defaults.multicast),
736        }
737    }
738
739    /// Returns the appropriate hop limit to use for the given destination addr.
740    pub fn hop_limit_for_dst(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
741        let Self { unicast, multicast, version: _ } = self;
742        if destination.is_multicast() {
743            *multicast
744        } else {
745            *unicast
746        }
747    }
748}
749
750fn new_ip_socket<I, D>(
751    requested_device: Option<&D>,
752    route: ResolvedRoute<I, D>,
753    remote_ip: SocketIpAddr<I::Addr>,
754    proto: I::Proto,
755) -> IpSock<I, D::Weak>
756where
757    I: IpExt,
758    D: StrongDeviceIdentifier,
759{
760    // TODO(https://fxbug.dev/323389672): Cache a reference to the route to
761    // avoid the route lookup on send as long as the routing table hasn't
762    // changed in between these operations.
763    let ResolvedRoute {
764        src_addr,
765        device: route_device,
766        local_delivery_device,
767        next_hop: _,
768        internal_forwarding: _,
769    } = route;
770
771    // If the source or destination address require a device, make sure to
772    // set that in the socket definition. Otherwise defer to what was provided.
773    let socket_device = (src_addr.as_ref().must_have_zone() || remote_ip.as_ref().must_have_zone())
774        .then(|| {
775            // NB: The route device might be loopback, and in such cases
776            // we want to bind the socket to the device the source IP is
777            // assigned to instead.
778            local_delivery_device.unwrap_or(route_device)
779        })
780        .as_ref()
781        .or(requested_device)
782        .map(|d| d.downgrade());
783
784    let definition =
785        IpSockDefinition { local_ip: src_addr, remote_ip, device: socket_device, proto };
786    IpSock { definition }
787}
788
789fn send_ip_packet<I, S, BC, CC, O>(
790    core_ctx: &mut CC,
791    bindings_ctx: &mut BC,
792    socket: &IpSock<I, CC::WeakDeviceId>,
793    mut body: S,
794    options: &O,
795    tx_metadata: BC::TxMetadata,
796) -> Result<(), IpSockSendError>
797where
798    I: IpExt + IpDeviceStateIpExt,
799    S: TransportPacketSerializer<I>,
800    S::Buffer: BufferMut,
801    BC: IpSocketBindingsContext,
802    CC: IpSocketContext<I, BC>,
803    CC::DeviceId: filter::InterfaceProperties<BC::DeviceClass>,
804    O: SendOptions<I> + RouteResolutionOptions<I>,
805{
806    trace_duration!(c"ip::send_packet");
807
808    // Extracted to a function without the serializer parameter to ease code
809    // generation.
810    fn resolve<
811        I: IpExt + IpDeviceStateIpExt,
812        CC: IpSocketContext<I, BC>,
813        BC: IpSocketBindingsContext,
814    >(
815        core_ctx: &mut CC,
816        bindings_ctx: &mut BC,
817        device: &Option<CC::WeakDeviceId>,
818        local_ip: IpDeviceAddr<I::Addr>,
819        remote_ip: RoutableIpAddr<I::Addr>,
820        transparent: bool,
821        marks: &Marks,
822    ) -> Result<ResolvedRoute<I, CC::DeviceId>, IpSockSendError> {
823        let device = match device.as_ref().map(|d| d.upgrade()) {
824            Some(Some(device)) => Some(device),
825            Some(None) => return Err(ResolveRouteError::Unreachable.into()),
826            None => None,
827        };
828        let route = core_ctx
829            .lookup_route(
830                bindings_ctx,
831                device.as_ref(),
832                Some(local_ip),
833                remote_ip,
834                transparent,
835                marks,
836            )
837            .map_err(|e| IpSockSendError::Unroutable(e))?;
838        assert_eq!(local_ip, route.src_addr);
839        Ok(route)
840    }
841
842    let IpSock {
843        definition: IpSockDefinition { remote_ip, local_ip, device: socket_device, proto },
844    } = socket;
845    let ResolvedRoute {
846        src_addr: local_ip,
847        device: mut egress_device,
848        mut next_hop,
849        mut local_delivery_device,
850        mut internal_forwarding,
851    } = resolve(
852        core_ctx,
853        bindings_ctx,
854        socket_device,
855        *local_ip,
856        *remote_ip,
857        options.transparent(),
858        options.marks(),
859    )?;
860
861    if matches!(next_hop, NextHop::Broadcast(_)) && options.allow_broadcast().is_none() {
862        return Err(IpSockSendError::BroadcastNotAllowed);
863    }
864
865    let previous_dst = remote_ip.addr();
866    let mut packet = filter::TxPacket::new(local_ip.addr(), remote_ip.addr(), *proto, &mut body);
867    let mut packet_metadata =
868        IpLayerPacketMetadata::from_tx_metadata_and_marks(tx_metadata, *options.marks());
869
870    match core_ctx.filter_handler().local_egress_hook(
871        bindings_ctx,
872        &mut packet,
873        &egress_device,
874        &mut packet_metadata,
875    ) {
876        filter::Verdict::Drop => {
877            packet_metadata.acknowledge_drop();
878            return Ok(());
879        }
880        filter::Verdict::Accept(()) => {}
881    }
882
883    let Some(mut local_ip) = IpDeviceAddr::new(packet.src_addr()) else {
884        packet_metadata.acknowledge_drop();
885        return Err(IpSockSendError::Unroutable(ResolveRouteError::NoSrcAddr));
886    };
887    let Some(remote_ip) = RoutableIpAddr::new(packet.dst_addr()) else {
888        packet_metadata.acknowledge_drop();
889        return Err(IpSockSendError::Unroutable(ResolveRouteError::Unreachable));
890    };
891
892    // If the LOCAL_EGRESS hook ended up rewriting the packet's destination, perform
893    // re-routing based on the new destination.
894    if remote_ip.addr() != previous_dst {
895        let ResolvedRoute {
896            src_addr: new_local_ip,
897            device: new_device,
898            next_hop: new_next_hop,
899            local_delivery_device: new_local_delivery_device,
900            internal_forwarding: new_internal_forwarding,
901        } = match resolve(
902            core_ctx,
903            bindings_ctx,
904            socket_device,
905            local_ip,
906            remote_ip,
907            options.transparent(),
908            options.marks(),
909        ) {
910            Ok(r) => r,
911            Err(err) => {
912                packet_metadata.acknowledge_drop();
913                return Err(err);
914            }
915        };
916        local_ip = new_local_ip;
917        egress_device = new_device;
918        next_hop = new_next_hop;
919        local_delivery_device = new_local_delivery_device;
920        internal_forwarding = new_internal_forwarding;
921    }
922
923    // NB: Hit the forwarding hook if the route leverages internal forwarding.
924    match internal_forwarding {
925        InternalForwarding::Used(ingress_device) => {
926            match core_ctx.filter_handler().forwarding_hook(
927                &mut packet,
928                &ingress_device,
929                &egress_device,
930                &mut packet_metadata,
931            ) {
932                filter::Verdict::Drop => {
933                    packet_metadata.acknowledge_drop();
934                    return Ok(());
935                }
936                filter::Verdict::Accept(()) => {}
937            }
938        }
939        InternalForwarding::NotUsed => {}
940    }
941
942    // The packet needs to be delivered locally if it's sent to a broadcast
943    // or multicast address. For multicast packets this feature can be disabled
944    // with IP_MULTICAST_LOOP.
945
946    let loopback_packet = (!egress_device.is_loopback()
947        && ((options.multicast_loop() && remote_ip.addr().is_multicast())
948            || next_hop.is_broadcast()))
949    .then(|| body.serialize_new_buf(PacketConstraints::UNCONSTRAINED, packet::new_buf_vec))
950    .transpose()?
951    .map(|buf| RawIpBody::new(*proto, local_ip.addr(), remote_ip.addr(), buf));
952
953    let destination = match &local_delivery_device {
954        Some(d) => IpPacketDestination::Loopback(d),
955        None => IpPacketDestination::from_next_hop(next_hop, remote_ip.into()),
956    };
957    let ttl = options.hop_limit(&remote_ip.into());
958    let meta = SendIpPacketMeta {
959        device: &egress_device,
960        src_ip: local_ip.into(),
961        dst_ip: remote_ip.into(),
962        destination,
963        ttl,
964        proto: *proto,
965        mtu: options.mtu(),
966        dscp_and_ecn: options.dscp_and_ecn(),
967    };
968    IpSocketContext::send_ip_packet(core_ctx, bindings_ctx, meta, body, packet_metadata).or_else(
969        |IpSendFrameError { serializer: _, error }| IpSockSendError::from_ip_send_frame(error),
970    )?;
971
972    match (loopback_packet, core_ctx.get_loopback_device()) {
973        (Some(loopback_packet), Some(loopback_device)) => {
974            let meta = SendIpPacketMeta {
975                device: &loopback_device,
976                src_ip: local_ip.into(),
977                dst_ip: remote_ip.into(),
978                destination: IpPacketDestination::Loopback(&egress_device),
979                ttl,
980                proto: *proto,
981                mtu: options.mtu(),
982                dscp_and_ecn: options.dscp_and_ecn(),
983            };
984            let packet_metadata = IpLayerPacketMetadata::default();
985
986            // The loopback packet will hit the egress hook. LOCAL_EGRESS hook
987            // is not called again.
988            IpSocketContext::send_ip_packet(
989                core_ctx,
990                bindings_ctx,
991                meta,
992                loopback_packet,
993                packet_metadata,
994            )
995            .unwrap_or_else(|IpSendFrameError { serializer: _, error }| {
996                error!("failed to send loopback packet: {error:?}")
997            });
998        }
999        (Some(_loopback_packet), None) => {
1000            error!("can't send a loopback packet without the loopback device")
1001        }
1002        _ => (),
1003    }
1004
1005    Ok(())
1006}
1007
1008/// Enables a blanket implementation of [`DeviceIpSocketHandler`].
1009///
1010/// Implementing this marker trait for a type enables a blanket implementation
1011/// of `DeviceIpSocketHandler` given the other requirements are met.
1012pub trait UseDeviceIpSocketHandlerBlanket {}
1013
1014impl<I, BC, CC> DeviceIpSocketHandler<I, BC> for CC
1015where
1016    I: IpLayerIpExt + IpDeviceStateIpExt,
1017    BC: IpSocketBindingsContext,
1018    CC: IpDeviceMtuContext<I> + IpSocketContext<I, BC> + UseDeviceIpSocketHandlerBlanket,
1019{
1020    fn get_mms<O: RouteResolutionOptions<I>>(
1021        &mut self,
1022        bindings_ctx: &mut BC,
1023        ip_sock: &IpSock<I, Self::WeakDeviceId>,
1024        options: &O,
1025    ) -> Result<Mms, MmsError> {
1026        let IpSockDefinition { remote_ip, local_ip, device, proto: _ } = &ip_sock.definition;
1027        let device = device
1028            .as_ref()
1029            .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1030            .transpose()?;
1031
1032        let ResolvedRoute {
1033            src_addr: _,
1034            local_delivery_device: _,
1035            device,
1036            next_hop: _,
1037            internal_forwarding: _,
1038        } = self
1039            .lookup_route(
1040                bindings_ctx,
1041                device.as_ref(),
1042                Some(*local_ip),
1043                *remote_ip,
1044                options.transparent(),
1045                options.marks(),
1046            )
1047            .map_err(MmsError::NoDevice)?;
1048        let mtu = self.get_mtu(&device);
1049        // TODO(https://fxbug.dev/42072935): Calculate the options size when they
1050        // are supported.
1051        Mms::from_mtu::<I>(mtu, 0 /* no ip options used */).ok_or(MmsError::MTUTooSmall(mtu))
1052    }
1053}
1054
1055/// IPv6 source address selection as defined in [RFC 6724 Section 5].
1056pub(crate) mod ipv6_source_address_selection {
1057    use net_types::ip::{AddrSubnet, IpAddress as _};
1058
1059    use super::*;
1060
1061    use netstack3_base::Ipv6DeviceAddr;
1062
1063    /// A source address selection candidate.
1064    pub struct SasCandidate<D> {
1065        /// The candidate address and subnet.
1066        pub addr_sub: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1067        /// True if the address is assigned (i.e. non tentative).
1068        pub assigned: bool,
1069        /// True if the address is deprecated (i.e. not preferred).
1070        pub deprecated: bool,
1071        /// True if the address is temporary (i.e. not permanent).
1072        pub temporary: bool,
1073        /// The device this address belongs to.
1074        pub device: D,
1075    }
1076
1077    /// Selects the source address for an IPv6 socket using the algorithm
1078    /// defined in [RFC 6724 Section 5].
1079    ///
1080    /// This algorithm is only applicable when the user has not explicitly
1081    /// specified a source address.
1082    ///
1083    /// `remote_ip` is the remote IP address of the socket, `outbound_device` is
1084    /// the device over which outbound traffic to `remote_ip` is sent (according
1085    /// to the forwarding table), and `addresses` is an iterator of all
1086    /// addresses on all devices. The algorithm works by iterating over
1087    /// `addresses` and selecting the address which is most preferred according
1088    /// to a set of selection criteria.
1089    pub fn select_ipv6_source_address<
1090        'a,
1091        D: PartialEq,
1092        A,
1093        I: Iterator<Item = A>,
1094        F: FnMut(&A) -> SasCandidate<D>,
1095    >(
1096        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1097        outbound_device: &D,
1098        addresses: I,
1099        mut get_candidate: F,
1100    ) -> Option<A> {
1101        // Source address selection as defined in RFC 6724 Section 5.
1102        //
1103        // The algorithm operates by defining a partial ordering on available
1104        // source addresses, and choosing one of the best address as defined by
1105        // that ordering (given multiple best addresses, the choice from among
1106        // those is implementation-defined). The partial order is defined in
1107        // terms of a sequence of rules. If a given rule defines an order
1108        // between two addresses, then that is their order. Otherwise, the next
1109        // rule must be consulted, and so on until all of the rules are
1110        // exhausted.
1111
1112        addresses
1113            .map(|item| {
1114                let candidate = get_candidate(&item);
1115                (item, candidate)
1116            })
1117            // Tentative addresses are not considered available to the source
1118            // selection algorithm.
1119            .filter(|(_, candidate)| candidate.assigned)
1120            .max_by(|(_, a), (_, b)| {
1121                select_ipv6_source_address_cmp(remote_ip, outbound_device, a, b)
1122            })
1123            .map(|(item, _candidate)| item)
1124    }
1125
1126    /// Comparison operator used by `select_ipv6_source_address`.
1127    fn select_ipv6_source_address_cmp<D: PartialEq>(
1128        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1129        outbound_device: &D,
1130        a: &SasCandidate<D>,
1131        b: &SasCandidate<D>,
1132    ) -> Ordering {
1133        // TODO(https://fxbug.dev/42123500): Implement rules 4, 5.5, and 6.
1134        let SasCandidate {
1135            addr_sub: a_addr_sub,
1136            assigned: a_assigned,
1137            deprecated: a_deprecated,
1138            temporary: a_temporary,
1139            device: a_device,
1140        } = a;
1141        let SasCandidate {
1142            addr_sub: b_addr_sub,
1143            assigned: b_assigned,
1144            deprecated: b_deprecated,
1145            temporary: b_temporary,
1146            device: b_device,
1147        } = b;
1148
1149        let a_addr = a_addr_sub.addr().into_specified();
1150        let b_addr = b_addr_sub.addr().into_specified();
1151
1152        // Assertions required in order for this implementation to be valid.
1153
1154        // Required by the implementation of Rule 1.
1155        if let Some(remote_ip) = remote_ip {
1156            debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));
1157        }
1158
1159        // Addresses that are not considered assigned are not valid source
1160        // addresses.
1161        debug_assert!(a_assigned);
1162        debug_assert!(b_assigned);
1163
1164        rule_1(remote_ip, a_addr, b_addr)
1165            .then_with(|| rule_2(remote_ip, a_addr, b_addr))
1166            .then_with(|| rule_3(*a_deprecated, *b_deprecated))
1167            .then_with(|| rule_5(outbound_device, a_device, b_device))
1168            .then_with(|| rule_7(*a_temporary, *b_temporary))
1169            .then_with(|| rule_8(remote_ip, *a_addr_sub, *b_addr_sub))
1170    }
1171
1172    // Assumes that `a` and `b` are not both equal to `remote_ip`.
1173    fn rule_1(
1174        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1175        a: SpecifiedAddr<Ipv6Addr>,
1176        b: SpecifiedAddr<Ipv6Addr>,
1177    ) -> Ordering {
1178        let remote_ip = match remote_ip {
1179            Some(remote_ip) => remote_ip,
1180            None => return Ordering::Equal,
1181        };
1182        if (a == remote_ip) != (b == remote_ip) {
1183            // Rule 1: Prefer same address.
1184            //
1185            // Note that both `a` and `b` cannot be equal to `remote_ip` since
1186            // that would imply that we had added the same address twice to the
1187            // same device.
1188            //
1189            // If `(a == remote_ip) != (b == remote_ip)`, then exactly one of
1190            // them is equal. If this inequality does not hold, then they must
1191            // both be unequal to `remote_ip`. In the first case, we have a tie,
1192            // and in the second case, the rule doesn't apply. In either case,
1193            // we move onto the next rule.
1194            if a == remote_ip {
1195                Ordering::Greater
1196            } else {
1197                Ordering::Less
1198            }
1199        } else {
1200            Ordering::Equal
1201        }
1202    }
1203
1204    fn rule_2(
1205        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1206        a: SpecifiedAddr<Ipv6Addr>,
1207        b: SpecifiedAddr<Ipv6Addr>,
1208    ) -> Ordering {
1209        // Scope ordering is defined by the Multicast Scope ID, see
1210        // https://datatracker.ietf.org/doc/html/rfc6724#section-3.1 .
1211        let remote_scope = match remote_ip {
1212            Some(remote_ip) => remote_ip.scope().multicast_scope_id(),
1213            None => return Ordering::Equal,
1214        };
1215        let a_scope = a.scope().multicast_scope_id();
1216        let b_scope = b.scope().multicast_scope_id();
1217        if a_scope < b_scope {
1218            if a_scope < remote_scope {
1219                Ordering::Less
1220            } else {
1221                Ordering::Greater
1222            }
1223        } else if a_scope > b_scope {
1224            if b_scope < remote_scope {
1225                Ordering::Greater
1226            } else {
1227                Ordering::Less
1228            }
1229        } else {
1230            Ordering::Equal
1231        }
1232    }
1233
1234    fn rule_3(a_deprecated: bool, b_deprecated: bool) -> Ordering {
1235        match (a_deprecated, b_deprecated) {
1236            (true, false) => Ordering::Less,
1237            (true, true) | (false, false) => Ordering::Equal,
1238            (false, true) => Ordering::Greater,
1239        }
1240    }
1241
1242    fn rule_5<D: PartialEq>(outbound_device: &D, a_device: &D, b_device: &D) -> Ordering {
1243        if (a_device == outbound_device) != (b_device == outbound_device) {
1244            // Rule 5: Prefer outgoing interface.
1245            if a_device == outbound_device {
1246                Ordering::Greater
1247            } else {
1248                Ordering::Less
1249            }
1250        } else {
1251            Ordering::Equal
1252        }
1253    }
1254
1255    // Prefer temporary addresses following rule 7.
1256    fn rule_7(a_temporary: bool, b_temporary: bool) -> Ordering {
1257        match (a_temporary, b_temporary) {
1258            (true, false) => Ordering::Greater,
1259            (true, true) | (false, false) => Ordering::Equal,
1260            (false, true) => Ordering::Less,
1261        }
1262    }
1263
1264    fn rule_8(
1265        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1266        a: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1267        b: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1268    ) -> Ordering {
1269        let remote_ip = match remote_ip {
1270            Some(remote_ip) => remote_ip,
1271            None => return Ordering::Equal,
1272        };
1273        // Per RFC 6724 Section 2.2:
1274        //
1275        //   We define the common prefix length CommonPrefixLen(S, D) of a
1276        //   source address S and a destination address D as the length of the
1277        //   longest prefix (looking at the most significant, or leftmost, bits)
1278        //   that the two addresses have in common, up to the length of S's
1279        //   prefix (i.e., the portion of the address not including the
1280        //   interface ID).  For example, CommonPrefixLen(fe80::1, fe80::2) is
1281        //   64.
1282        fn common_prefix_len(
1283            src: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1284            dst: SpecifiedAddr<Ipv6Addr>,
1285        ) -> u8 {
1286            core::cmp::min(src.addr().common_prefix_len(&dst), src.subnet().prefix())
1287        }
1288
1289        // Rule 8: Use longest matching prefix.
1290        //
1291        // Note that, per RFC 6724 Section 5:
1292        //
1293        //   Rule 8 MAY be superseded if the implementation has other means of
1294        //   choosing among source addresses.  For example, if the
1295        //   implementation somehow knows which source address will result in
1296        //   the "best" communications performance.
1297        //
1298        // We don't currently make use of this option, but it's an option for
1299        // the future.
1300        common_prefix_len(a, remote_ip).cmp(&common_prefix_len(b, remote_ip))
1301    }
1302
1303    #[cfg(test)]
1304    mod tests {
1305        use net_declare::net_ip_v6;
1306
1307        use super::*;
1308
1309        #[test]
1310        fn test_select_ipv6_source_address() {
1311            // Test the comparison operator used by `select_ipv6_source_address`
1312            // by separately testing each comparison condition.
1313
1314            let remote = SpecifiedAddr::new(net_ip_v6!("2001:0db8:1::")).unwrap();
1315            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1316            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1317            let link_local_remote = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:42")).unwrap();
1318            let link_local = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:4")).unwrap();
1319            let dev0 = &0;
1320            let dev1 = &1;
1321            let dev2 = &2;
1322
1323            // Rule 1: Prefer same address
1324            assert_eq!(rule_1(Some(remote), remote, local0), Ordering::Greater);
1325            assert_eq!(rule_1(Some(remote), local0, remote), Ordering::Less);
1326            assert_eq!(rule_1(Some(remote), local0, local1), Ordering::Equal);
1327            assert_eq!(rule_1(None, local0, local1), Ordering::Equal);
1328
1329            // Rule 2: Prefer appropriate scope
1330            assert_eq!(rule_2(Some(remote), local0, local1), Ordering::Equal);
1331            assert_eq!(rule_2(Some(remote), local1, local0), Ordering::Equal);
1332            assert_eq!(rule_2(Some(remote), local0, link_local), Ordering::Greater);
1333            assert_eq!(rule_2(Some(remote), link_local, local0), Ordering::Less);
1334            assert_eq!(rule_2(Some(link_local_remote), local0, link_local), Ordering::Less);
1335            assert_eq!(rule_2(Some(link_local_remote), link_local, local0), Ordering::Greater);
1336            assert_eq!(rule_1(None, local0, link_local), Ordering::Equal);
1337
1338            // Rule 3: Avoid deprecated states
1339            assert_eq!(rule_3(false, true), Ordering::Greater);
1340            assert_eq!(rule_3(true, false), Ordering::Less);
1341            assert_eq!(rule_3(true, true), Ordering::Equal);
1342            assert_eq!(rule_3(false, false), Ordering::Equal);
1343
1344            // Rule 5: Prefer outgoing interface
1345            assert_eq!(rule_5(dev0, dev0, dev2), Ordering::Greater);
1346            assert_eq!(rule_5(dev0, dev2, dev0), Ordering::Less);
1347            assert_eq!(rule_5(dev0, dev0, dev0), Ordering::Equal);
1348            assert_eq!(rule_5(dev0, dev2, dev2), Ordering::Equal);
1349
1350            // Rule 7: Prefer temporary address.
1351            assert_eq!(rule_7(true, false), Ordering::Greater);
1352            assert_eq!(rule_7(false, true), Ordering::Less);
1353            assert_eq!(rule_7(true, true), Ordering::Equal);
1354            assert_eq!(rule_7(false, false), Ordering::Equal);
1355
1356            // Rule 8: Use longest matching prefix.
1357            {
1358                let new_addr_entry = |addr, prefix_len| AddrSubnet::new(addr, prefix_len).unwrap();
1359
1360                // First, test that the longest prefix match is preferred when
1361                // using addresses whose common prefix length is shorter than
1362                // the subnet prefix length.
1363
1364                // 4 leading 0x01 bytes.
1365                let remote = SpecifiedAddr::new(net_ip_v6!("1111::")).unwrap();
1366                // 3 leading 0x01 bytes.
1367                let local0 = new_addr_entry(net_ip_v6!("1110::"), 64);
1368                // 2 leading 0x01 bytes.
1369                let local1 = new_addr_entry(net_ip_v6!("1100::"), 64);
1370
1371                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Greater);
1372                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Less);
1373                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1374                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1375                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1376
1377                // Second, test that the common prefix length is capped at the
1378                // subnet prefix length.
1379
1380                // 3 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
1381                let local0 = new_addr_entry(net_ip_v6!("1110::"), 8);
1382                // 2 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
1383                let local1 = new_addr_entry(net_ip_v6!("1100::"), 8);
1384
1385                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Equal);
1386                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Equal);
1387                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1388                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1389                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1390            }
1391
1392            {
1393                let new_addr_entry = |addr, device| SasCandidate {
1394                    addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1395                    deprecated: false,
1396                    assigned: true,
1397                    temporary: false,
1398                    device,
1399                };
1400
1401                // If no rules apply, then the two address entries are equal.
1402                assert_eq!(
1403                    select_ipv6_source_address_cmp(
1404                        Some(remote),
1405                        dev0,
1406                        &new_addr_entry(*local0, *dev1),
1407                        &new_addr_entry(*local1, *dev2),
1408                    ),
1409                    Ordering::Equal
1410                );
1411            }
1412        }
1413
1414        #[test]
1415        fn test_select_ipv6_source_address_no_remote() {
1416            // Verify that source address selection correctly applies all
1417            // applicable rules when the remote is `None`.
1418            let dev0 = &0;
1419            let dev1 = &1;
1420            let dev2 = &2;
1421
1422            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1423            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1424
1425            let new_addr_entry = |addr, deprecated, device| SasCandidate {
1426                addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1427                deprecated,
1428                assigned: true,
1429                temporary: false,
1430                device,
1431            };
1432
1433            // Verify that Rule 3 still applies (avoid deprecated states).
1434            assert_eq!(
1435                select_ipv6_source_address_cmp(
1436                    None,
1437                    dev0,
1438                    &new_addr_entry(*local0, false, *dev1),
1439                    &new_addr_entry(*local1, true, *dev2),
1440                ),
1441                Ordering::Greater
1442            );
1443
1444            // Verify that Rule 5 still applies (Prefer outgoing interface).
1445            assert_eq!(
1446                select_ipv6_source_address_cmp(
1447                    None,
1448                    dev0,
1449                    &new_addr_entry(*local0, false, *dev0),
1450                    &new_addr_entry(*local1, false, *dev1),
1451                ),
1452                Ordering::Greater
1453            );
1454        }
1455    }
1456}
1457
1458/// Test fake implementations of the traits defined in the `socket` module.
1459#[cfg(any(test, feature = "testutils"))]
1460pub(crate) mod testutil {
1461    use alloc::boxed::Box;
1462    use alloc::collections::HashMap;
1463    use alloc::vec::Vec;
1464    use core::num::NonZeroUsize;
1465
1466    use derivative::Derivative;
1467    use net_types::ip::{GenericOverIp, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Subnet};
1468    use net_types::{MulticastAddr, Witness as _};
1469    use netstack3_base::testutil::{FakeCoreCtx, FakeStrongDeviceId, FakeWeakDeviceId};
1470    use netstack3_base::{SendFrameContext, SendFrameError};
1471    use netstack3_filter::Tuple;
1472
1473    use super::*;
1474    use crate::internal::base::{
1475        BaseTransportIpContext, HopLimits, MulticastMembershipHandler, DEFAULT_HOP_LIMITS,
1476    };
1477    use crate::internal::routing::testutil::FakeIpRoutingCtx;
1478    use crate::internal::routing::{self, RoutingTable};
1479    use crate::internal::types::{Destination, Entry, Metric, RawMetric};
1480
1481    /// A fake implementation of the traits required by the transport layer from
1482    /// the IP layer.
1483    #[derive(Derivative, GenericOverIp)]
1484    #[generic_over_ip(I, Ip)]
1485    #[derivative(Default(bound = ""))]
1486    pub struct FakeIpSocketCtx<I: Ip, D> {
1487        pub(crate) table: RoutingTable<I, D>,
1488        forwarding: FakeIpRoutingCtx<D>,
1489        devices: HashMap<D, FakeDeviceState<I>>,
1490    }
1491
1492    /// A trait enabling [`FakeIpSockeCtx`]'s implementations for
1493    /// [`FakeCoreCtx`] with types that hold a [`FakeIpSocketCtx`] internally,
1494    pub trait InnerFakeIpSocketCtx<I: Ip, D> {
1495        /// Gets a mutable reference to the inner fake context.
1496        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D>;
1497    }
1498
1499    impl<I: Ip, D> InnerFakeIpSocketCtx<I, D> for FakeIpSocketCtx<I, D> {
1500        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1501            self
1502        }
1503    }
1504
1505    impl<I: IpExt, D: FakeStrongDeviceId, BC> BaseTransportIpContext<I, BC> for FakeIpSocketCtx<I, D> {
1506        fn get_default_hop_limits(&mut self, device: Option<&D>) -> HopLimits {
1507            device.map_or(DEFAULT_HOP_LIMITS, |device| {
1508                let hop_limit = self.get_device_state(device).default_hop_limit;
1509                HopLimits { unicast: hop_limit, multicast: DEFAULT_HOP_LIMITS.multicast }
1510            })
1511        }
1512
1513        type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1514
1515        fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1516            &mut self,
1517            addr: SpecifiedAddr<I::Addr>,
1518            cb: F,
1519        ) -> O {
1520            cb(Box::new(self.devices.iter().filter_map(move |(device, state)| {
1521                state.addresses.contains(&addr).then(|| device.clone())
1522            })))
1523        }
1524
1525        fn get_original_destination(&mut self, _tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1526            unimplemented!()
1527        }
1528    }
1529
1530    impl<I: IpExt, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeIpSocketCtx<I, D> {
1531        type DeviceId = D;
1532        type WeakDeviceId = D::Weak;
1533    }
1534
1535    impl<I, State, D, Meta, BC> IpSocketHandler<I, BC> for FakeCoreCtx<State, Meta, D>
1536    where
1537        I: IpExt,
1538        State: InnerFakeIpSocketCtx<I, D>,
1539        D: FakeStrongDeviceId,
1540        BC: TxMetadataBindingsTypes,
1541        FakeCoreCtx<State, Meta, D>:
1542            SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
1543    {
1544        fn new_ip_socket<O>(
1545            &mut self,
1546            _bindings_ctx: &mut BC,
1547            device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
1548            local_ip: Option<IpDeviceAddr<I::Addr>>,
1549            remote_ip: SocketIpAddr<I::Addr>,
1550            proto: I::Proto,
1551            options: &O,
1552        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
1553        where
1554            O: RouteResolutionOptions<I>,
1555        {
1556            self.state.fake_ip_socket_ctx_mut().new_ip_socket(
1557                device,
1558                local_ip,
1559                remote_ip,
1560                proto,
1561                options.transparent(),
1562            )
1563        }
1564
1565        fn send_ip_packet<S, O>(
1566            &mut self,
1567            bindings_ctx: &mut BC,
1568            socket: &IpSock<I, Self::WeakDeviceId>,
1569            body: S,
1570            options: &O,
1571            // NB: Tx metadata plumbing is not supported for fake socket
1572            // contexts. Drop at the end of the scope.
1573            _tx_meta: BC::TxMetadata,
1574        ) -> Result<(), IpSockSendError>
1575        where
1576            S: TransportPacketSerializer<I>,
1577            S::Buffer: BufferMut,
1578            O: SendOptions<I> + RouteResolutionOptions<I>,
1579        {
1580            let meta = self.state.fake_ip_socket_ctx_mut().resolve_send_meta(socket, options)?;
1581            self.send_frame(bindings_ctx, meta, body).or_else(
1582                |SendFrameError { serializer: _, error }| IpSockSendError::from_send_frame(error),
1583            )
1584        }
1585
1586        fn confirm_reachable<O>(
1587            &mut self,
1588            _bindings_ctx: &mut BC,
1589            _socket: &IpSock<I, Self::WeakDeviceId>,
1590            _options: &O,
1591        ) {
1592        }
1593    }
1594
1595    impl<I: IpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
1596        for FakeIpSocketCtx<I, D>
1597    {
1598        fn join_multicast_group(
1599            &mut self,
1600            _bindings_ctx: &mut BC,
1601            device: &Self::DeviceId,
1602            addr: MulticastAddr<<I as Ip>::Addr>,
1603        ) {
1604            let value = self.get_device_state_mut(device).multicast_groups.entry(addr).or_insert(0);
1605            *value = value.checked_add(1).unwrap();
1606        }
1607
1608        fn leave_multicast_group(
1609            &mut self,
1610            _bindings_ctx: &mut BC,
1611            device: &Self::DeviceId,
1612            addr: MulticastAddr<<I as Ip>::Addr>,
1613        ) {
1614            let value = self
1615                .get_device_state_mut(device)
1616                .multicast_groups
1617                .get_mut(&addr)
1618                .unwrap_or_else(|| panic!("no entry for {addr} on {device:?}"));
1619            *value = value.checked_sub(1).unwrap();
1620        }
1621
1622        fn select_device_for_multicast_group(
1623            &mut self,
1624            addr: MulticastAddr<<I as Ip>::Addr>,
1625            _marks: &Marks,
1626        ) -> Result<Self::DeviceId, ResolveRouteError> {
1627            let remote_ip = SocketIpAddr::new_from_multicast(addr);
1628            self.lookup_route(None, None, remote_ip, /* transparent */ false)
1629                .map(|ResolvedRoute { device, .. }| device)
1630        }
1631    }
1632
1633    impl<I, BC, D, State, Meta> BaseTransportIpContext<I, BC> for FakeCoreCtx<State, Meta, D>
1634    where
1635        I: IpExt,
1636        D: FakeStrongDeviceId,
1637        State: InnerFakeIpSocketCtx<I, D>,
1638        BC: TxMetadataBindingsTypes,
1639        Self: IpSocketHandler<I, BC, DeviceId = D, WeakDeviceId = FakeWeakDeviceId<D>>,
1640    {
1641        type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1642
1643        fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1644            &mut self,
1645            addr: SpecifiedAddr<I::Addr>,
1646            cb: F,
1647        ) -> O {
1648            BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
1649                self.state.fake_ip_socket_ctx_mut(),
1650                addr,
1651                cb,
1652            )
1653        }
1654
1655        fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
1656            BaseTransportIpContext::<I, BC>::get_default_hop_limits(
1657                self.state.fake_ip_socket_ctx_mut(),
1658                device,
1659            )
1660        }
1661
1662        fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1663            BaseTransportIpContext::<I, BC>::get_original_destination(
1664                self.state.fake_ip_socket_ctx_mut(),
1665                tuple,
1666            )
1667        }
1668    }
1669
1670    /// A fake context providing [`IpSocketHandler`] for tests.
1671    #[derive(Derivative)]
1672    #[derivative(Default(bound = ""))]
1673    pub struct FakeDualStackIpSocketCtx<D> {
1674        v4: FakeIpSocketCtx<Ipv4, D>,
1675        v6: FakeIpSocketCtx<Ipv6, D>,
1676    }
1677
1678    impl<D: FakeStrongDeviceId> FakeDualStackIpSocketCtx<D> {
1679        /// Creates a new [`FakeDualStackIpSocketCtx`] with `devices`.
1680        pub fn new<A: Into<SpecifiedAddr<IpAddr>>>(
1681            devices: impl IntoIterator<Item = FakeDeviceConfig<D, A>>,
1682        ) -> Self {
1683            let partition =
1684                |v: Vec<A>| -> (Vec<SpecifiedAddr<Ipv4Addr>>, Vec<SpecifiedAddr<Ipv6Addr>>) {
1685                    v.into_iter().fold((Vec::new(), Vec::new()), |(mut v4, mut v6), i| {
1686                        match IpAddr::from(i.into()) {
1687                            IpAddr::V4(a) => v4.push(a),
1688                            IpAddr::V6(a) => v6.push(a),
1689                        }
1690                        (v4, v6)
1691                    })
1692                };
1693
1694            let (v4, v6): (Vec<_>, Vec<_>) = devices
1695                .into_iter()
1696                .map(|FakeDeviceConfig { device, local_ips, remote_ips }| {
1697                    let (local_v4, local_v6) = partition(local_ips);
1698                    let (remote_v4, remote_v6) = partition(remote_ips);
1699                    (
1700                        FakeDeviceConfig {
1701                            device: device.clone(),
1702                            local_ips: local_v4,
1703                            remote_ips: remote_v4,
1704                        },
1705                        FakeDeviceConfig { device, local_ips: local_v6, remote_ips: remote_v6 },
1706                    )
1707                })
1708                .unzip();
1709            Self { v4: FakeIpSocketCtx::new(v4), v6: FakeIpSocketCtx::new(v6) }
1710        }
1711
1712        /// Returns the [`FakeIpSocketCtx`] for IP version `I`.
1713        pub fn inner_mut<I: Ip>(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1714            I::map_ip_out(self, |s| &mut s.v4, |s| &mut s.v6)
1715        }
1716
1717        fn inner<I: Ip>(&self) -> &FakeIpSocketCtx<I, D> {
1718            I::map_ip_out(self, |s| &s.v4, |s| &s.v6)
1719        }
1720
1721        /// Adds a fake direct route to `ip` through `device`.
1722        pub fn add_route(&mut self, device: D, ip: SpecifiedAddr<IpAddr>) {
1723            match IpAddr::from(ip) {
1724                IpAddr::V4(ip) => {
1725                    routing::testutil::add_on_link_routing_entry(&mut self.v4.table, ip, device)
1726                }
1727                IpAddr::V6(ip) => {
1728                    routing::testutil::add_on_link_routing_entry(&mut self.v6.table, ip, device)
1729                }
1730            }
1731        }
1732
1733        /// Adds a fake route to `subnet` through `device`.
1734        pub fn add_subnet_route<A: IpAddress>(&mut self, device: D, subnet: Subnet<A>) {
1735            let entry = Entry {
1736                subnet,
1737                device,
1738                gateway: None,
1739                metric: Metric::ExplicitMetric(RawMetric(0)),
1740            };
1741            A::Version::map_ip::<_, ()>(
1742                entry,
1743                |entry_v4| {
1744                    let _ = routing::testutil::add_entry(&mut self.v4.table, entry_v4)
1745                        .expect("Failed to add route");
1746                },
1747                |entry_v6| {
1748                    let _ = routing::testutil::add_entry(&mut self.v6.table, entry_v6)
1749                        .expect("Failed to add route");
1750                },
1751            );
1752        }
1753
1754        /// Returns a mutable reference to fake device state.
1755        pub fn get_device_state_mut<I: IpExt>(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1756            self.inner_mut::<I>().get_device_state_mut(device)
1757        }
1758
1759        /// Returns the fake multicast memberships.
1760        pub fn multicast_memberships<I: IpExt>(
1761            &self,
1762        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1763            self.inner::<I>().multicast_memberships()
1764        }
1765    }
1766
1767    impl<I: IpExt, S: InnerFakeIpSocketCtx<I, D>, Meta, D: FakeStrongDeviceId, BC>
1768        MulticastMembershipHandler<I, BC> for FakeCoreCtx<S, Meta, D>
1769    {
1770        fn join_multicast_group(
1771            &mut self,
1772            bindings_ctx: &mut BC,
1773            device: &Self::DeviceId,
1774            addr: MulticastAddr<<I as Ip>::Addr>,
1775        ) {
1776            MulticastMembershipHandler::<I, BC>::join_multicast_group(
1777                self.state.fake_ip_socket_ctx_mut(),
1778                bindings_ctx,
1779                device,
1780                addr,
1781            )
1782        }
1783
1784        fn leave_multicast_group(
1785            &mut self,
1786            bindings_ctx: &mut BC,
1787            device: &Self::DeviceId,
1788            addr: MulticastAddr<<I as Ip>::Addr>,
1789        ) {
1790            MulticastMembershipHandler::<I, BC>::leave_multicast_group(
1791                self.state.fake_ip_socket_ctx_mut(),
1792                bindings_ctx,
1793                device,
1794                addr,
1795            )
1796        }
1797
1798        fn select_device_for_multicast_group(
1799            &mut self,
1800            addr: MulticastAddr<<I as Ip>::Addr>,
1801            marks: &Marks,
1802        ) -> Result<Self::DeviceId, ResolveRouteError> {
1803            MulticastMembershipHandler::<I, BC>::select_device_for_multicast_group(
1804                self.state.fake_ip_socket_ctx_mut(),
1805                addr,
1806                marks,
1807            )
1808        }
1809    }
1810
1811    impl<I: Ip, D, State: InnerFakeIpSocketCtx<I, D>, Meta> InnerFakeIpSocketCtx<I, D>
1812        for FakeCoreCtx<State, Meta, D>
1813    {
1814        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1815            self.state.fake_ip_socket_ctx_mut()
1816        }
1817    }
1818
1819    impl<I: Ip, D: FakeStrongDeviceId> InnerFakeIpSocketCtx<I, D> for FakeDualStackIpSocketCtx<D> {
1820        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1821            self.inner_mut::<I>()
1822        }
1823    }
1824
1825    /// A device configuration for fake socket contexts.
1826    #[derive(Clone, GenericOverIp)]
1827    #[generic_over_ip()]
1828    pub struct FakeDeviceConfig<D, A> {
1829        /// The device.
1830        pub device: D,
1831        /// The device's local IPs.
1832        pub local_ips: Vec<A>,
1833        /// The remote IPs reachable from this device.
1834        pub remote_ips: Vec<A>,
1835    }
1836
1837    /// State associated with a fake device in [`FakeIpSocketCtx`].
1838    pub struct FakeDeviceState<I: Ip> {
1839        /// The default hop limit used by the device.
1840        pub default_hop_limit: NonZeroU8,
1841        /// The assigned device addresses.
1842        pub addresses: Vec<SpecifiedAddr<I::Addr>>,
1843        /// The joined multicast groups.
1844        pub multicast_groups: HashMap<MulticastAddr<I::Addr>, usize>,
1845    }
1846
1847    impl<I: Ip> FakeDeviceState<I> {
1848        /// Returns whether this fake device has joined multicast group `addr`.
1849        pub fn is_in_multicast_group(&self, addr: &MulticastAddr<I::Addr>) -> bool {
1850            self.multicast_groups.get(addr).is_some_and(|v| *v != 0)
1851        }
1852    }
1853
1854    impl<I: IpExt, D: FakeStrongDeviceId> FakeIpSocketCtx<I, D> {
1855        /// Creates a new `FakeIpSocketCtx` with the given device
1856        /// configs.
1857        pub fn new(
1858            device_configs: impl IntoIterator<Item = FakeDeviceConfig<D, SpecifiedAddr<I::Addr>>>,
1859        ) -> Self {
1860            let mut table = RoutingTable::default();
1861            let mut devices = HashMap::default();
1862            for FakeDeviceConfig { device, local_ips, remote_ips } in device_configs {
1863                for addr in remote_ips {
1864                    routing::testutil::add_on_link_routing_entry(&mut table, addr, device.clone())
1865                }
1866                let state = FakeDeviceState {
1867                    default_hop_limit: DEFAULT_HOP_LIMITS.unicast,
1868                    addresses: local_ips,
1869                    multicast_groups: Default::default(),
1870                };
1871                assert!(
1872                    devices.insert(device.clone(), state).is_none(),
1873                    "duplicate entries for {device:?}",
1874                );
1875            }
1876
1877            Self { table, devices, forwarding: Default::default() }
1878        }
1879
1880        /// Returns an immutable reference to the fake device state.
1881        pub fn get_device_state(&self, device: &D) -> &FakeDeviceState<I> {
1882            self.devices.get(device).unwrap_or_else(|| panic!("no device {device:?}"))
1883        }
1884
1885        /// Returns a mutable reference to the fake device state.
1886        pub fn get_device_state_mut(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1887            self.devices.get_mut(device).unwrap_or_else(|| panic!("no device {device:?}"))
1888        }
1889
1890        pub(crate) fn multicast_memberships(
1891            &self,
1892        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1893            self.devices
1894                .iter()
1895                .map(|(device, state)| {
1896                    state.multicast_groups.iter().filter_map(|(group, count)| {
1897                        NonZeroUsize::new(*count).map(|count| ((device.clone(), *group), count))
1898                    })
1899                })
1900                .flatten()
1901                .collect()
1902        }
1903
1904        fn new_ip_socket(
1905            &mut self,
1906            device: Option<EitherDeviceId<&D, &D::Weak>>,
1907            local_ip: Option<IpDeviceAddr<I::Addr>>,
1908            remote_ip: SocketIpAddr<I::Addr>,
1909            proto: I::Proto,
1910            transparent: bool,
1911        ) -> Result<IpSock<I, D::Weak>, IpSockCreationError> {
1912            let device = device
1913                .as_ref()
1914                .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
1915                .transpose()?;
1916            let device = device.as_ref().map(|d| d.as_ref());
1917            let resolved_route = self.lookup_route(device, local_ip, remote_ip, transparent)?;
1918            Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
1919        }
1920
1921        fn lookup_route(
1922            &mut self,
1923            device: Option<&D>,
1924            local_ip: Option<IpDeviceAddr<I::Addr>>,
1925            addr: RoutableIpAddr<I::Addr>,
1926            transparent: bool,
1927        ) -> Result<ResolvedRoute<I, D>, ResolveRouteError> {
1928            let Self { table, devices, forwarding } = self;
1929            let (destination, ()) = table
1930                .lookup_filter_map(forwarding, device, addr.addr(), |_, d| match &local_ip {
1931                    None => Some(()),
1932                    Some(local_ip) => {
1933                        if transparent {
1934                            return Some(());
1935                        }
1936                        devices.get(d).and_then(|state| {
1937                            state.addresses.contains(local_ip.as_ref()).then_some(())
1938                        })
1939                    }
1940                })
1941                .next()
1942                .ok_or(ResolveRouteError::Unreachable)?;
1943
1944            let Destination { device, next_hop } = destination;
1945            let mut addrs = devices.get(device).unwrap().addresses.iter();
1946            let local_ip = match local_ip {
1947                None => {
1948                    let addr = addrs.next().ok_or(ResolveRouteError::NoSrcAddr)?;
1949                    IpDeviceAddr::new(addr.get()).expect("not valid device addr")
1950                }
1951                Some(local_ip) => {
1952                    if !transparent {
1953                        // We already constrained the set of devices so this
1954                        // should be a given.
1955                        assert!(
1956                            addrs.any(|a| a.get() == local_ip.addr()),
1957                            "didn't find IP {:?} in {:?}",
1958                            local_ip,
1959                            addrs.collect::<Vec<_>>()
1960                        );
1961                    }
1962                    local_ip
1963                }
1964            };
1965
1966            Ok(ResolvedRoute {
1967                src_addr: local_ip,
1968                device: device.clone(),
1969                local_delivery_device: None,
1970                next_hop,
1971                // NB: Keep unit tests simple and skip internal forwarding
1972                // logic. Instead, this is verified by integration tests.
1973                internal_forwarding: InternalForwarding::NotUsed,
1974            })
1975        }
1976
1977        fn resolve_send_meta<O>(
1978            &mut self,
1979            socket: &IpSock<I, D::Weak>,
1980            options: &O,
1981        ) -> Result<SendIpPacketMeta<I, D, SpecifiedAddr<I::Addr>>, IpSockSendError>
1982        where
1983            O: SendOptions<I> + RouteResolutionOptions<I>,
1984        {
1985            let IpSockDefinition { remote_ip, local_ip, device, proto } = &socket.definition;
1986            let device = device
1987                .as_ref()
1988                .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1989                .transpose()?;
1990            let ResolvedRoute {
1991                src_addr,
1992                device,
1993                next_hop,
1994                local_delivery_device: _,
1995                internal_forwarding: _,
1996            } = self.lookup_route(
1997                device.as_ref(),
1998                Some(*local_ip),
1999                *remote_ip,
2000                options.transparent(),
2001            )?;
2002
2003            let remote_ip: &SpecifiedAddr<_> = remote_ip.as_ref();
2004
2005            let destination = IpPacketDestination::from_next_hop(next_hop, *remote_ip);
2006            Ok(SendIpPacketMeta {
2007                device,
2008                src_ip: src_addr.into(),
2009                dst_ip: *remote_ip,
2010                destination,
2011                proto: *proto,
2012                ttl: options.hop_limit(remote_ip),
2013                mtu: options.mtu(),
2014                dscp_and_ecn: DscpAndEcn::default(),
2015            })
2016        }
2017    }
2018}