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