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