Skip to main content

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