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