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,
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::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::<_, !>(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::<_, !>(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<!>> for IpSockSendError {
278    fn from(err: SerializeError<!>) -> 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    // TODO(https://fxbug.dev/565891068): Support TCP GSO by populating GSO
936    // metadata when segment offloading is enabled for the socket.
937    let gso_info = None;
938    let mut packet_metadata =
939        IpLayerPacketMetadata::new_local_tx(tx_metadata, *options.marks(), gso_info);
940
941    let filter_result = core_ctx.filter_handler().local_egress_hook(
942        bindings_ctx,
943        &mut packet,
944        &egress_device,
945        &mut packet_metadata,
946    );
947    match filter_result {
948        filter::Verdict::Stop(filter::DropOrReject::Drop) => {
949            packet_metadata.acknowledge_drop();
950            return Ok(());
951        }
952        filter::Verdict::Stop(filter::DropOrReject::Reject(reject_type)) => {
953            packet_metadata.acknowledge_drop();
954
955            let Some(icmp_error): Option<I::IcmpError> = I::map_ip_out(
956                reject_type,
957                |reject_type| reject_type_to_icmpv4_error(reject_type),
958                |reject_type| reject_type_to_icmpv6_error(reject_type),
959            ) else {
960                debug!("Unsupported reject type: {:?}", reject_type);
961                return Ok(());
962            };
963
964            let src_ip = SocketIpAddr::new_from_witness(local_ip.into_inner().get());
965            let dst_ip = *remote_ip;
966            let ttl = options.hop_limit(&dst_ip.into()).map(|v| v.into()).unwrap_or(1);
967            let packet_builder = I::PacketBuilder::new(
968                src_ip.into_inner().get(),
969                dst_ip.into_inner().get(),
970                ttl,
971                *proto,
972            );
973            let header_len = packet_builder.constraints().header_len();
974            let ip_frame = packet_builder.wrap_body(body);
975            let packet = match ip_frame.serialize_outer(
976                &mut NetworkSerializationContext::default(),
977                packet::NoReuseBufferProvider(packet::new_buf_vec),
978            ) {
979                Ok(packet) => packet,
980                Err((error, _frame)) => {
981                    debug!("Failed to serialize packet {:?}", error);
982                    return Ok(());
983                }
984            };
985
986            // Invoke `send_icmp_error_message` with the `local_ip` as the
987            // `original_source_ip`, which will result in the ICMP error
988            // message getting sent back to the `socket`.
989            core_ctx.send_icmp_error_message(
990                bindings_ctx,
991                /*device=*/ None,
992                /*frame_dst=*/ None,
993                src_ip,
994                dst_ip,
995                packet,
996                icmp_error,
997                header_len,
998                *proto,
999                &options.marks(),
1000            );
1001
1002            return Ok(());
1003        }
1004        filter::Verdict::Proceed(filter::Accept) => {}
1005    }
1006
1007    let Some(mut local_ip) = IpDeviceAddr::new(packet.src_addr()) else {
1008        packet_metadata.acknowledge_drop();
1009        return Err(IpSockSendError::Unroutable(ResolveRouteError::NoSrcAddr));
1010    };
1011    let Some(remote_ip) = RoutableIpAddr::new(packet.dst_addr()) else {
1012        packet_metadata.acknowledge_drop();
1013        return Err(IpSockSendError::Unroutable(ResolveRouteError::Unreachable));
1014    };
1015
1016    // If the LOCAL_EGRESS hook ended up rewriting the packet's destination, perform
1017    // re-routing based on the new destination.
1018    if remote_ip.addr() != previous_dst {
1019        let ResolvedRoute {
1020            src_addr: new_local_ip,
1021            device: new_device,
1022            next_hop: new_next_hop,
1023            local_delivery_device: new_local_delivery_device,
1024            internal_forwarding: new_internal_forwarding,
1025        } = match resolve(
1026            core_ctx,
1027            bindings_ctx,
1028            socket_device,
1029            local_ip,
1030            remote_ip,
1031            options.transparent(),
1032            options.marks(),
1033        ) {
1034            Ok(r) => r,
1035            Err(err) => {
1036                packet_metadata.acknowledge_drop();
1037                return Err(err);
1038            }
1039        };
1040        local_ip = new_local_ip;
1041        egress_device = new_device;
1042        next_hop = new_next_hop;
1043        local_delivery_device = new_local_delivery_device;
1044        internal_forwarding = new_internal_forwarding;
1045    }
1046
1047    // NB: Hit the forwarding hook if the route leverages internal forwarding.
1048    match internal_forwarding {
1049        InternalForwarding::Used(ingress_device) => {
1050            match core_ctx.filter_handler().forwarding_hook(
1051                &mut packet,
1052                &ingress_device,
1053                &egress_device,
1054                &mut packet_metadata,
1055            ) {
1056                filter::Verdict::Stop(filter::DropOrReject::Drop) => {
1057                    packet_metadata.acknowledge_drop();
1058                    return Ok(());
1059                }
1060                filter::Verdict::Stop(filter::DropOrReject::Reject(_reject_type)) => {
1061                    // TODO(https://fxbug.dev/466098884): Send reject packet.
1062                    packet_metadata.acknowledge_drop();
1063                    return Ok(());
1064                }
1065                filter::Verdict::Proceed(filter::Accept) => {}
1066            }
1067        }
1068        InternalForwarding::NotUsed => {}
1069    }
1070
1071    if let Some(socket_info) = packet_metadata.tx_metadata().socket_info() {
1072        let egress_filter_result = bindings_ctx.socket_ops_filter().on_egress(
1073            &packet,
1074            &egress_device,
1075            socket_info,
1076            packet_metadata.marks(),
1077        );
1078
1079        // TODO(https://fxbug.dev/412426836): Implement congestion signal handling.
1080        match egress_filter_result {
1081            SocketEgressFilterResult::Pass { congestion: _ } => (),
1082            SocketEgressFilterResult::Drop { congestion: _ } => {
1083                core_ctx.counters().socket_egress_filter_dropped.increment();
1084                packet_metadata.acknowledge_drop();
1085                return Ok(());
1086            }
1087        }
1088    }
1089
1090    // The packet needs to be delivered locally if it's sent to a broadcast
1091    // or multicast address. For multicast packets this feature can be disabled
1092    // with IP_MULTICAST_LOOP.
1093
1094    let loopback_packet_and_meta = if !egress_device.is_loopback()
1095        && ((options.multicast_loop() && remote_ip.addr().is_multicast())
1096            || next_hop.is_broadcast())
1097    {
1098        let body_copy = body.serialize_new_buf(
1099            &mut NetworkSerializationContext::default(),
1100            PacketConstraints::UNCONSTRAINED,
1101            packet::new_buf_vec,
1102        )?;
1103        let loopback_metadata;
1104        SplitMulticastPacketMetadata { primary: packet_metadata, secondary: loopback_metadata } =
1105            packet_metadata.split_for_multicast();
1106        Some((
1107            RawIpBody::new(*proto, local_ip.addr(), remote_ip.addr(), body_copy),
1108            loopback_metadata,
1109        ))
1110    } else {
1111        None
1112    };
1113
1114    let destination = match &local_delivery_device {
1115        Some(d) => IpPacketDestination::Loopback(d),
1116        None => IpPacketDestination::from_next_hop(next_hop, remote_ip.into()),
1117    };
1118    let ttl = options.hop_limit(&remote_ip.into());
1119    let meta = SendIpPacketMeta {
1120        device: &egress_device,
1121        src_ip: local_ip.into(),
1122        dst_ip: remote_ip.into(),
1123        destination,
1124        ttl,
1125        proto: *proto,
1126        mtu: options.mtu(),
1127        dscp_and_ecn: options.dscp_and_ecn(),
1128    };
1129    let result =
1130        IpSocketContext::send_ip_packet(core_ctx, bindings_ctx, meta, body, packet_metadata)
1131            .or_else(|IpSendFrameError { serializer: _, error }| {
1132                IpSockSendError::from_ip_send_frame(error)
1133            });
1134
1135    match (result, loopback_packet_and_meta, core_ctx.get_loopback_device()) {
1136        (Ok(()), Some((loopback_packet, packet_metadata)), Some(loopback_device)) => {
1137            let meta = SendIpPacketMeta {
1138                device: &loopback_device,
1139                src_ip: local_ip.into(),
1140                dst_ip: remote_ip.into(),
1141                destination: IpPacketDestination::Loopback(&egress_device),
1142                ttl,
1143                proto: *proto,
1144                mtu: options.mtu(),
1145                dscp_and_ecn: options.dscp_and_ecn(),
1146            };
1147
1148            // The loopback packet will hit the egress hook. LOCAL_EGRESS hook
1149            // is not called again.
1150            IpSocketContext::send_ip_packet(
1151                core_ctx,
1152                bindings_ctx,
1153                meta,
1154                loopback_packet,
1155                packet_metadata,
1156            )
1157            .unwrap_or_else(|IpSendFrameError { serializer: _, error }| {
1158                error!("failed to send loopback packet: {error:?}")
1159            });
1160        }
1161        (Ok(()), Some((_loopback_packet, packet_metadata)), None) => {
1162            error!("can't send a loopback packet without the loopback device");
1163            packet_metadata.acknowledge_drop();
1164        }
1165        (Err(_), Some((_loopback_packet, packet_metadata)), _) => {
1166            // Don't send the loopback packet in case the original one wasn't sent.
1167            packet_metadata.acknowledge_drop();
1168        }
1169        (_, None, _) => (),
1170    }
1171
1172    result
1173}
1174
1175/// Enables a blanket implementation of [`DeviceIpSocketHandler`].
1176///
1177/// Implementing this marker trait for a type enables a blanket implementation
1178/// of `DeviceIpSocketHandler` given the other requirements are met.
1179pub trait UseDeviceIpSocketHandlerBlanket {}
1180
1181impl<I, BC, CC> DeviceIpSocketHandler<I, BC> for CC
1182where
1183    I: IpLayerIpExt + IpDeviceStateIpExt,
1184    BC: IpSocketBindingsContext<CC::DeviceId>,
1185    CC: IpDeviceMtuContext<I> + IpSocketContext<I, BC> + UseDeviceIpSocketHandlerBlanket,
1186{
1187    fn get_mms<O: RouteResolutionOptions<I>>(
1188        &mut self,
1189        bindings_ctx: &mut BC,
1190        ip_sock: &IpSock<I, Self::WeakDeviceId>,
1191        options: &O,
1192    ) -> Result<Mms, MmsError> {
1193        let IpSockDefinition { remote_ip, local_ip, device, proto: _ } = &ip_sock.definition;
1194        let device = device
1195            .as_ref()
1196            .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
1197            .transpose()?;
1198
1199        let ResolvedRoute {
1200            src_addr: _,
1201            local_delivery_device: _,
1202            device,
1203            next_hop: _,
1204            internal_forwarding: _,
1205        } = self
1206            .lookup_route(
1207                bindings_ctx,
1208                device.as_ref(),
1209                Some(*local_ip),
1210                *remote_ip,
1211                options.transparent(),
1212                options.marks(),
1213            )
1214            .map_err(MmsError::NoDevice)?;
1215        let mtu = self.get_mtu(&device);
1216        // TODO(https://fxbug.dev/42072935): Calculate the options size when they
1217        // are supported.
1218        Mms::from_mtu::<I>(mtu, 0 /* no ip options used */).ok_or(MmsError::MTUTooSmall(mtu))
1219    }
1220}
1221
1222/// IPv6 source address selection as defined in [RFC 6724 Section 5].
1223pub(crate) mod ipv6_source_address_selection {
1224    use net_types::ip::{AddrSubnet, IpAddress as _};
1225
1226    use super::*;
1227
1228    use netstack3_base::Ipv6DeviceAddr;
1229
1230    /// A source address selection candidate.
1231    pub struct SasCandidate<D> {
1232        /// The candidate address and subnet.
1233        pub addr_sub: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1234        /// True if the address is assigned (i.e. non tentative).
1235        pub assigned: bool,
1236        /// True if the address is deprecated (i.e. not preferred).
1237        pub deprecated: bool,
1238        /// True if the address is temporary (i.e. not permanent).
1239        pub temporary: bool,
1240        /// The device this address belongs to.
1241        pub device: D,
1242    }
1243
1244    /// Selects the source address for an IPv6 socket using the algorithm
1245    /// defined in [RFC 6724 Section 5].
1246    ///
1247    /// This algorithm is only applicable when the user has not explicitly
1248    /// specified a source address.
1249    ///
1250    /// `remote_ip` is the remote IP address of the socket, `outbound_device` is
1251    /// the device over which outbound traffic to `remote_ip` is sent (according
1252    /// to the forwarding table), and `addresses` is an iterator of all
1253    /// addresses on all devices. The algorithm works by iterating over
1254    /// `addresses` and selecting the address which is most preferred according
1255    /// to a set of selection criteria.
1256    pub fn select_ipv6_source_address<
1257        'a,
1258        D: PartialEq,
1259        A,
1260        I: Iterator<Item = A>,
1261        F: FnMut(&A) -> SasCandidate<D>,
1262    >(
1263        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1264        outbound_device: &D,
1265        addresses: I,
1266        mut get_candidate: F,
1267    ) -> Option<A> {
1268        // Source address selection as defined in RFC 6724 Section 5.
1269        //
1270        // The algorithm operates by defining a partial ordering on available
1271        // source addresses, and choosing one of the best address as defined by
1272        // that ordering (given multiple best addresses, the choice from among
1273        // those is implementation-defined). The partial order is defined in
1274        // terms of a sequence of rules. If a given rule defines an order
1275        // between two addresses, then that is their order. Otherwise, the next
1276        // rule must be consulted, and so on until all of the rules are
1277        // exhausted.
1278
1279        addresses
1280            .map(|item| {
1281                let candidate = get_candidate(&item);
1282                (item, candidate)
1283            })
1284            // Tentative addresses are not considered available to the source
1285            // selection algorithm.
1286            .filter(|(_, candidate)| candidate.assigned)
1287            .max_by(|(_, a), (_, b)| {
1288                select_ipv6_source_address_cmp(remote_ip, outbound_device, a, b)
1289            })
1290            .map(|(item, _candidate)| item)
1291    }
1292
1293    /// Comparison operator used by `select_ipv6_source_address`.
1294    fn select_ipv6_source_address_cmp<D: PartialEq>(
1295        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1296        outbound_device: &D,
1297        a: &SasCandidate<D>,
1298        b: &SasCandidate<D>,
1299    ) -> Ordering {
1300        // TODO(https://fxbug.dev/42123500): Implement rules 4, 5.5, and 6.
1301        let SasCandidate {
1302            addr_sub: a_addr_sub,
1303            assigned: a_assigned,
1304            deprecated: a_deprecated,
1305            temporary: a_temporary,
1306            device: a_device,
1307        } = a;
1308        let SasCandidate {
1309            addr_sub: b_addr_sub,
1310            assigned: b_assigned,
1311            deprecated: b_deprecated,
1312            temporary: b_temporary,
1313            device: b_device,
1314        } = b;
1315
1316        let a_addr = a_addr_sub.addr().into_specified();
1317        let b_addr = b_addr_sub.addr().into_specified();
1318
1319        // Assertions required in order for this implementation to be valid.
1320
1321        // Required by the implementation of Rule 1.
1322        if let Some(remote_ip) = remote_ip {
1323            debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));
1324        }
1325
1326        // Addresses that are not considered assigned are not valid source
1327        // addresses.
1328        debug_assert!(a_assigned);
1329        debug_assert!(b_assigned);
1330
1331        rule_1(remote_ip, a_addr, b_addr)
1332            .then_with(|| rule_2(remote_ip, a_addr, b_addr))
1333            .then_with(|| rule_3(*a_deprecated, *b_deprecated))
1334            .then_with(|| rule_5(outbound_device, a_device, b_device))
1335            .then_with(|| rule_7(*a_temporary, *b_temporary))
1336            .then_with(|| rule_8(remote_ip, *a_addr_sub, *b_addr_sub))
1337    }
1338
1339    // Assumes that `a` and `b` are not both equal to `remote_ip`.
1340    fn rule_1(
1341        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1342        a: SpecifiedAddr<Ipv6Addr>,
1343        b: SpecifiedAddr<Ipv6Addr>,
1344    ) -> Ordering {
1345        let remote_ip = match remote_ip {
1346            Some(remote_ip) => remote_ip,
1347            None => return Ordering::Equal,
1348        };
1349        if (a == remote_ip) != (b == remote_ip) {
1350            // Rule 1: Prefer same address.
1351            //
1352            // Note that both `a` and `b` cannot be equal to `remote_ip` since
1353            // that would imply that we had added the same address twice to the
1354            // same device.
1355            //
1356            // If `(a == remote_ip) != (b == remote_ip)`, then exactly one of
1357            // them is equal. If this inequality does not hold, then they must
1358            // both be unequal to `remote_ip`. In the first case, we have a tie,
1359            // and in the second case, the rule doesn't apply. In either case,
1360            // we move onto the next rule.
1361            if a == remote_ip { Ordering::Greater } else { Ordering::Less }
1362        } else {
1363            Ordering::Equal
1364        }
1365    }
1366
1367    fn rule_2(
1368        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1369        a: SpecifiedAddr<Ipv6Addr>,
1370        b: SpecifiedAddr<Ipv6Addr>,
1371    ) -> Ordering {
1372        // Scope ordering is defined by the Multicast Scope ID, see
1373        // https://datatracker.ietf.org/doc/html/rfc6724#section-3.1 .
1374        let remote_scope = match remote_ip {
1375            Some(remote_ip) => remote_ip.scope().multicast_scope_id(),
1376            None => return Ordering::Equal,
1377        };
1378        let a_scope = a.scope().multicast_scope_id();
1379        let b_scope = b.scope().multicast_scope_id();
1380        if a_scope < b_scope {
1381            if a_scope < remote_scope { Ordering::Less } else { Ordering::Greater }
1382        } else if a_scope > b_scope {
1383            if b_scope < remote_scope { Ordering::Greater } else { Ordering::Less }
1384        } else {
1385            Ordering::Equal
1386        }
1387    }
1388
1389    fn rule_3(a_deprecated: bool, b_deprecated: bool) -> Ordering {
1390        match (a_deprecated, b_deprecated) {
1391            (true, false) => Ordering::Less,
1392            (true, true) | (false, false) => Ordering::Equal,
1393            (false, true) => Ordering::Greater,
1394        }
1395    }
1396
1397    fn rule_5<D: PartialEq>(outbound_device: &D, a_device: &D, b_device: &D) -> Ordering {
1398        if (a_device == outbound_device) != (b_device == outbound_device) {
1399            // Rule 5: Prefer outgoing interface.
1400            if a_device == outbound_device { Ordering::Greater } else { Ordering::Less }
1401        } else {
1402            Ordering::Equal
1403        }
1404    }
1405
1406    // Prefer temporary addresses following rule 7.
1407    fn rule_7(a_temporary: bool, b_temporary: bool) -> Ordering {
1408        match (a_temporary, b_temporary) {
1409            (true, false) => Ordering::Greater,
1410            (true, true) | (false, false) => Ordering::Equal,
1411            (false, true) => Ordering::Less,
1412        }
1413    }
1414
1415    fn rule_8(
1416        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
1417        a: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1418        b: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1419    ) -> Ordering {
1420        let remote_ip = match remote_ip {
1421            Some(remote_ip) => remote_ip,
1422            None => return Ordering::Equal,
1423        };
1424        // Per RFC 6724 Section 2.2:
1425        //
1426        //   We define the common prefix length CommonPrefixLen(S, D) of a
1427        //   source address S and a destination address D as the length of the
1428        //   longest prefix (looking at the most significant, or leftmost, bits)
1429        //   that the two addresses have in common, up to the length of S's
1430        //   prefix (i.e., the portion of the address not including the
1431        //   interface ID).  For example, CommonPrefixLen(fe80::1, fe80::2) is
1432        //   64.
1433        fn common_prefix_len(
1434            src: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
1435            dst: SpecifiedAddr<Ipv6Addr>,
1436        ) -> u8 {
1437            core::cmp::min(src.addr().common_prefix_len(&dst), src.subnet().prefix())
1438        }
1439
1440        // Rule 8: Use longest matching prefix.
1441        //
1442        // Note that, per RFC 6724 Section 5:
1443        //
1444        //   Rule 8 MAY be superseded if the implementation has other means of
1445        //   choosing among source addresses.  For example, if the
1446        //   implementation somehow knows which source address will result in
1447        //   the "best" communications performance.
1448        //
1449        // We don't currently make use of this option, but it's an option for
1450        // the future.
1451        common_prefix_len(a, remote_ip).cmp(&common_prefix_len(b, remote_ip))
1452    }
1453
1454    #[cfg(test)]
1455    mod tests {
1456        use net_declare::net_ip_v6;
1457
1458        use super::*;
1459
1460        #[test]
1461        fn test_select_ipv6_source_address() {
1462            // Test the comparison operator used by `select_ipv6_source_address`
1463            // by separately testing each comparison condition.
1464
1465            let remote = SpecifiedAddr::new(net_ip_v6!("2001:0db8:1::")).unwrap();
1466            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1467            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1468            let link_local_remote = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:42")).unwrap();
1469            let link_local = SpecifiedAddr::new(net_ip_v6!("fe80::1:2:4")).unwrap();
1470            let dev0 = &0;
1471            let dev1 = &1;
1472            let dev2 = &2;
1473
1474            // Rule 1: Prefer same address
1475            assert_eq!(rule_1(Some(remote), remote, local0), Ordering::Greater);
1476            assert_eq!(rule_1(Some(remote), local0, remote), Ordering::Less);
1477            assert_eq!(rule_1(Some(remote), local0, local1), Ordering::Equal);
1478            assert_eq!(rule_1(None, local0, local1), Ordering::Equal);
1479
1480            // Rule 2: Prefer appropriate scope
1481            assert_eq!(rule_2(Some(remote), local0, local1), Ordering::Equal);
1482            assert_eq!(rule_2(Some(remote), local1, local0), Ordering::Equal);
1483            assert_eq!(rule_2(Some(remote), local0, link_local), Ordering::Greater);
1484            assert_eq!(rule_2(Some(remote), link_local, local0), Ordering::Less);
1485            assert_eq!(rule_2(Some(link_local_remote), local0, link_local), Ordering::Less);
1486            assert_eq!(rule_2(Some(link_local_remote), link_local, local0), Ordering::Greater);
1487            assert_eq!(rule_1(None, local0, link_local), Ordering::Equal);
1488
1489            // Rule 3: Avoid deprecated states
1490            assert_eq!(rule_3(false, true), Ordering::Greater);
1491            assert_eq!(rule_3(true, false), Ordering::Less);
1492            assert_eq!(rule_3(true, true), Ordering::Equal);
1493            assert_eq!(rule_3(false, false), Ordering::Equal);
1494
1495            // Rule 5: Prefer outgoing interface
1496            assert_eq!(rule_5(dev0, dev0, dev2), Ordering::Greater);
1497            assert_eq!(rule_5(dev0, dev2, dev0), Ordering::Less);
1498            assert_eq!(rule_5(dev0, dev0, dev0), Ordering::Equal);
1499            assert_eq!(rule_5(dev0, dev2, dev2), Ordering::Equal);
1500
1501            // Rule 7: Prefer temporary address.
1502            assert_eq!(rule_7(true, false), Ordering::Greater);
1503            assert_eq!(rule_7(false, true), Ordering::Less);
1504            assert_eq!(rule_7(true, true), Ordering::Equal);
1505            assert_eq!(rule_7(false, false), Ordering::Equal);
1506
1507            // Rule 8: Use longest matching prefix.
1508            {
1509                let new_addr_entry = |addr, prefix_len| AddrSubnet::new(addr, prefix_len).unwrap();
1510
1511                // First, test that the longest prefix match is preferred when
1512                // using addresses whose common prefix length is shorter than
1513                // the subnet prefix length.
1514
1515                // 4 leading 0x01 bytes.
1516                let remote = SpecifiedAddr::new(net_ip_v6!("1111::")).unwrap();
1517                // 3 leading 0x01 bytes.
1518                let local0 = new_addr_entry(net_ip_v6!("1110::"), 64);
1519                // 2 leading 0x01 bytes.
1520                let local1 = new_addr_entry(net_ip_v6!("1100::"), 64);
1521
1522                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Greater);
1523                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Less);
1524                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1525                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1526                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1527
1528                // Second, test that the common prefix length is capped at the
1529                // subnet prefix length.
1530
1531                // 3 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
1532                let local0 = new_addr_entry(net_ip_v6!("1110::"), 8);
1533                // 2 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
1534                let local1 = new_addr_entry(net_ip_v6!("1100::"), 8);
1535
1536                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Equal);
1537                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Equal);
1538                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
1539                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
1540                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
1541            }
1542
1543            {
1544                let new_addr_entry = |addr, device| SasCandidate {
1545                    addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1546                    deprecated: false,
1547                    assigned: true,
1548                    temporary: false,
1549                    device,
1550                };
1551
1552                // If no rules apply, then the two address entries are equal.
1553                assert_eq!(
1554                    select_ipv6_source_address_cmp(
1555                        Some(remote),
1556                        dev0,
1557                        &new_addr_entry(*local0, *dev1),
1558                        &new_addr_entry(*local1, *dev2),
1559                    ),
1560                    Ordering::Equal
1561                );
1562            }
1563        }
1564
1565        #[test]
1566        fn test_select_ipv6_source_address_no_remote() {
1567            // Verify that source address selection correctly applies all
1568            // applicable rules when the remote is `None`.
1569            let dev0 = &0;
1570            let dev1 = &1;
1571            let dev2 = &2;
1572
1573            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
1574            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
1575
1576            let new_addr_entry = |addr, deprecated, device| SasCandidate {
1577                addr_sub: AddrSubnet::new(addr, 128).unwrap(),
1578                deprecated,
1579                assigned: true,
1580                temporary: false,
1581                device,
1582            };
1583
1584            // Verify that Rule 3 still applies (avoid deprecated states).
1585            assert_eq!(
1586                select_ipv6_source_address_cmp(
1587                    None,
1588                    dev0,
1589                    &new_addr_entry(*local0, false, *dev1),
1590                    &new_addr_entry(*local1, true, *dev2),
1591                ),
1592                Ordering::Greater
1593            );
1594
1595            // Verify that Rule 5 still applies (Prefer outgoing interface).
1596            assert_eq!(
1597                select_ipv6_source_address_cmp(
1598                    None,
1599                    dev0,
1600                    &new_addr_entry(*local0, false, *dev0),
1601                    &new_addr_entry(*local1, false, *dev1),
1602                ),
1603                Ordering::Greater
1604            );
1605        }
1606    }
1607}
1608
1609/// Test fake implementations of the traits defined in the `socket` module.
1610#[cfg(any(test, feature = "testutils"))]
1611pub(crate) mod testutil {
1612    use alloc::boxed::Box;
1613    use alloc::vec::Vec;
1614    use core::num::NonZeroUsize;
1615
1616    use crate::internal::types::RoutePreference;
1617    use derivative::Derivative;
1618    use net_types::MulticastAddr;
1619    use net_types::ip::{GenericOverIp, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Subnet};
1620    use netstack3_base::testutil::{FakeCoreCtx, FakeStrongDeviceId, FakeWeakDeviceId};
1621    use netstack3_base::{SendFrameContext, SendFrameError};
1622    use netstack3_filter::Tuple;
1623    use netstack3_hashmap::HashMap;
1624
1625    use super::*;
1626    use crate::internal::base::{
1627        BaseTransportIpContext, DEFAULT_HOP_LIMITS, HopLimits, MulticastMembershipHandler,
1628    };
1629    use crate::internal::routing::testutil::FakeIpRoutingCtx;
1630    use crate::internal::routing::{self, RoutingTable};
1631    use crate::internal::types::{Destination, Entry, Metric, RawMetric};
1632
1633    /// A fake implementation of the traits required by the transport layer from
1634    /// the IP layer.
1635    #[derive(Derivative, GenericOverIp)]
1636    #[generic_over_ip(I, Ip)]
1637    #[derivative(Default(bound = ""))]
1638    pub struct FakeIpSocketCtx<I: Ip, D> {
1639        pub(crate) table: RoutingTable<I, D>,
1640        forwarding: FakeIpRoutingCtx<D>,
1641        devices: HashMap<D, FakeDeviceState<I>>,
1642    }
1643
1644    /// A trait enabling [`FakeIpSockeCtx`]'s implementations for
1645    /// [`FakeCoreCtx`] with types that hold a [`FakeIpSocketCtx`] internally,
1646    pub trait InnerFakeIpSocketCtx<I: Ip, D> {
1647        /// Gets a mutable reference to the inner fake context.
1648        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D>;
1649    }
1650
1651    impl<I: Ip, D> InnerFakeIpSocketCtx<I, D> for FakeIpSocketCtx<I, D> {
1652        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1653            self
1654        }
1655    }
1656
1657    impl<I: IpExt, D: FakeStrongDeviceId, BC> BaseTransportIpContext<I, BC> for FakeIpSocketCtx<I, D> {
1658        fn get_default_hop_limits(&mut self, device: Option<&D>) -> HopLimits {
1659            device.map_or(DEFAULT_HOP_LIMITS, |device| {
1660                let hop_limit = self.get_device_state(device).default_hop_limit;
1661                HopLimits { unicast: hop_limit, multicast: DEFAULT_HOP_LIMITS.multicast }
1662            })
1663        }
1664
1665        type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1666
1667        fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1668            &mut self,
1669            addr: SpecifiedAddr<I::Addr>,
1670            cb: F,
1671        ) -> O {
1672            cb(Box::new(self.devices.iter().filter_map(move |(device, state)| {
1673                state.addresses.contains(&addr).then(|| device.clone())
1674            })))
1675        }
1676
1677        fn get_original_destination(&mut self, _tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1678            unimplemented!()
1679        }
1680    }
1681
1682    impl<I: IpExt, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeIpSocketCtx<I, D> {
1683        type DeviceId = D;
1684        type WeakDeviceId = D::Weak;
1685    }
1686
1687    impl<I, State, D, Meta, BC> IpSocketHandler<I, BC> for FakeCoreCtx<State, Meta, D>
1688    where
1689        I: IpExt + FilterIpExt,
1690        State: InnerFakeIpSocketCtx<I, D>,
1691        D: FakeStrongDeviceId,
1692        BC: TxMetadataBindingsTypes,
1693        FakeCoreCtx<State, Meta, D>:
1694            SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
1695    {
1696        fn new_ip_socket<O>(
1697            &mut self,
1698            _bindings_ctx: &mut BC,
1699            args: IpSocketArgs<'_, Self::DeviceId, I, O>,
1700        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>
1701        where
1702            O: RouteResolutionOptions<I>,
1703        {
1704            self.state.fake_ip_socket_ctx_mut().new_ip_socket(args)
1705        }
1706
1707        fn send_ip_packet<S, O>(
1708            &mut self,
1709            bindings_ctx: &mut BC,
1710            socket: &IpSock<I, Self::WeakDeviceId>,
1711            body: S,
1712            options: &O,
1713            // NB: Tx metadata plumbing is not supported for fake socket
1714            // contexts. Drop at the end of the scope.
1715            _tx_meta: BC::TxMetadata,
1716        ) -> Result<(), IpSockSendError>
1717        where
1718            S: TransportPacketSerializer<I>,
1719            S::Buffer: BufferMut,
1720            O: SendOptions<I> + RouteResolutionOptions<I>,
1721        {
1722            let meta = self.state.fake_ip_socket_ctx_mut().resolve_send_meta(socket, options)?;
1723            self.send_frame(bindings_ctx, meta, body).or_else(
1724                |SendFrameError { serializer: _, error }| IpSockSendError::from_send_frame(error),
1725            )
1726        }
1727
1728        fn confirm_reachable<O>(
1729            &mut self,
1730            _bindings_ctx: &mut BC,
1731            _socket: &IpSock<I, Self::WeakDeviceId>,
1732            _options: &O,
1733        ) {
1734        }
1735    }
1736
1737    impl<I: IpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
1738        for FakeIpSocketCtx<I, D>
1739    {
1740        fn join_multicast_group(
1741            &mut self,
1742            _bindings_ctx: &mut BC,
1743            device: &Self::DeviceId,
1744            addr: MulticastAddr<<I as Ip>::Addr>,
1745        ) {
1746            let value = self.get_device_state_mut(device).multicast_groups.entry(addr).or_insert(0);
1747            *value = value.checked_add(1).unwrap();
1748        }
1749
1750        fn leave_multicast_group(
1751            &mut self,
1752            _bindings_ctx: &mut BC,
1753            device: &Self::DeviceId,
1754            addr: MulticastAddr<<I as Ip>::Addr>,
1755        ) {
1756            let value = self
1757                .get_device_state_mut(device)
1758                .multicast_groups
1759                .get_mut(&addr)
1760                .unwrap_or_else(|| panic!("no entry for {addr} on {device:?}"));
1761            *value = value.checked_sub(1).unwrap();
1762        }
1763
1764        fn select_device_for_multicast_group(
1765            &mut self,
1766            addr: MulticastAddr<<I as Ip>::Addr>,
1767            _marks: &Marks,
1768        ) -> Result<Self::DeviceId, ResolveRouteError> {
1769            let remote_ip = SocketIpAddr::new_from_multicast(addr);
1770            self.lookup_route(None, None, remote_ip, /* transparent */ false)
1771                .map(|ResolvedRoute { device, .. }| device)
1772        }
1773    }
1774
1775    impl<I, BC, D, State, Meta> BaseTransportIpContext<I, BC> for FakeCoreCtx<State, Meta, D>
1776    where
1777        I: IpExt + FilterIpExt,
1778        D: FakeStrongDeviceId,
1779        State: InnerFakeIpSocketCtx<I, D>,
1780        BC: TxMetadataBindingsTypes,
1781        Self: IpSocketHandler<I, BC, DeviceId = D, WeakDeviceId = FakeWeakDeviceId<D>>,
1782    {
1783        type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;
1784
1785        fn with_devices_with_assigned_addr<O, F: FnOnce(Self::DevicesWithAddrIter<'_>) -> O>(
1786            &mut self,
1787            addr: SpecifiedAddr<I::Addr>,
1788            cb: F,
1789        ) -> O {
1790            BaseTransportIpContext::<I, BC>::with_devices_with_assigned_addr(
1791                self.state.fake_ip_socket_ctx_mut(),
1792                addr,
1793                cb,
1794            )
1795        }
1796
1797        fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
1798            BaseTransportIpContext::<I, BC>::get_default_hop_limits(
1799                self.state.fake_ip_socket_ctx_mut(),
1800                device,
1801            )
1802        }
1803
1804        fn get_original_destination(&mut self, tuple: &Tuple<I>) -> Option<(I::Addr, u16)> {
1805            BaseTransportIpContext::<I, BC>::get_original_destination(
1806                self.state.fake_ip_socket_ctx_mut(),
1807                tuple,
1808            )
1809        }
1810    }
1811
1812    /// A fake context providing [`IpSocketHandler`] for tests.
1813    #[derive(Derivative)]
1814    #[derivative(Default(bound = ""))]
1815    pub struct FakeDualStackIpSocketCtx<D> {
1816        v4: FakeIpSocketCtx<Ipv4, D>,
1817        v6: FakeIpSocketCtx<Ipv6, D>,
1818    }
1819
1820    impl<D: FakeStrongDeviceId> FakeDualStackIpSocketCtx<D> {
1821        /// Creates a new [`FakeDualStackIpSocketCtx`] with `devices`.
1822        pub fn new<A: Into<SpecifiedAddr<IpAddr>>>(
1823            devices: impl IntoIterator<Item = FakeDeviceConfig<D, A>>,
1824        ) -> Self {
1825            let partition =
1826                |v: Vec<A>| -> (Vec<SpecifiedAddr<Ipv4Addr>>, Vec<SpecifiedAddr<Ipv6Addr>>) {
1827                    v.into_iter().fold((Vec::new(), Vec::new()), |(mut v4, mut v6), i| {
1828                        match IpAddr::from(i.into()) {
1829                            IpAddr::V4(a) => v4.push(a),
1830                            IpAddr::V6(a) => v6.push(a),
1831                        }
1832                        (v4, v6)
1833                    })
1834                };
1835
1836            let (v4, v6): (Vec<_>, Vec<_>) = devices
1837                .into_iter()
1838                .map(|FakeDeviceConfig { device, local_ips, remote_ips }| {
1839                    let (local_v4, local_v6) = partition(local_ips);
1840                    let (remote_v4, remote_v6) = partition(remote_ips);
1841                    (
1842                        FakeDeviceConfig {
1843                            device: device.clone(),
1844                            local_ips: local_v4,
1845                            remote_ips: remote_v4,
1846                        },
1847                        FakeDeviceConfig { device, local_ips: local_v6, remote_ips: remote_v6 },
1848                    )
1849                })
1850                .unzip();
1851            Self { v4: FakeIpSocketCtx::new(v4), v6: FakeIpSocketCtx::new(v6) }
1852        }
1853
1854        /// Returns the [`FakeIpSocketCtx`] for IP version `I`.
1855        pub fn inner_mut<I: Ip>(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1856            I::map_ip_out(self, |s| &mut s.v4, |s| &mut s.v6)
1857        }
1858
1859        fn inner<I: Ip>(&self) -> &FakeIpSocketCtx<I, D> {
1860            I::map_ip_out(self, |s| &s.v4, |s| &s.v6)
1861        }
1862
1863        /// Adds a fake direct route to `ip` through `device`.
1864        pub fn add_route(&mut self, device: D, ip: SpecifiedAddr<IpAddr>) {
1865            match IpAddr::from(ip) {
1866                IpAddr::V4(ip) => {
1867                    routing::testutil::add_on_link_routing_entry(&mut self.v4.table, ip, device)
1868                }
1869                IpAddr::V6(ip) => {
1870                    routing::testutil::add_on_link_routing_entry(&mut self.v6.table, ip, device)
1871                }
1872            }
1873        }
1874
1875        /// Adds a fake route to `subnet` through `device`.
1876        pub fn add_subnet_route<A: IpAddress>(&mut self, device: D, subnet: Subnet<A>) {
1877            let entry = Entry {
1878                subnet,
1879                device,
1880                gateway: None,
1881                metric: Metric::ExplicitMetric(RawMetric(0)),
1882                route_preference: RoutePreference::Medium,
1883            };
1884            A::Version::map_ip::<_, ()>(
1885                entry,
1886                |entry_v4| {
1887                    let _ = routing::testutil::add_entry(&mut self.v4.table, entry_v4)
1888                        .expect("Failed to add route");
1889                },
1890                |entry_v6| {
1891                    let _ = routing::testutil::add_entry(&mut self.v6.table, entry_v6)
1892                        .expect("Failed to add route");
1893                },
1894            );
1895        }
1896
1897        /// Returns a mutable reference to fake device state.
1898        pub fn get_device_state_mut<I: IpExt>(&mut self, device: &D) -> &mut FakeDeviceState<I> {
1899            self.inner_mut::<I>().get_device_state_mut(device)
1900        }
1901
1902        /// Returns the fake multicast memberships.
1903        pub fn multicast_memberships<I: IpExt>(
1904            &self,
1905        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
1906            self.inner::<I>().multicast_memberships()
1907        }
1908    }
1909
1910    impl<I: IpExt, S: InnerFakeIpSocketCtx<I, D>, Meta, D: FakeStrongDeviceId, BC>
1911        MulticastMembershipHandler<I, BC> for FakeCoreCtx<S, Meta, D>
1912    {
1913        fn join_multicast_group(
1914            &mut self,
1915            bindings_ctx: &mut BC,
1916            device: &Self::DeviceId,
1917            addr: MulticastAddr<<I as Ip>::Addr>,
1918        ) {
1919            MulticastMembershipHandler::<I, BC>::join_multicast_group(
1920                self.state.fake_ip_socket_ctx_mut(),
1921                bindings_ctx,
1922                device,
1923                addr,
1924            )
1925        }
1926
1927        fn leave_multicast_group(
1928            &mut self,
1929            bindings_ctx: &mut BC,
1930            device: &Self::DeviceId,
1931            addr: MulticastAddr<<I as Ip>::Addr>,
1932        ) {
1933            MulticastMembershipHandler::<I, BC>::leave_multicast_group(
1934                self.state.fake_ip_socket_ctx_mut(),
1935                bindings_ctx,
1936                device,
1937                addr,
1938            )
1939        }
1940
1941        fn select_device_for_multicast_group(
1942            &mut self,
1943            addr: MulticastAddr<<I as Ip>::Addr>,
1944            marks: &Marks,
1945        ) -> Result<Self::DeviceId, ResolveRouteError> {
1946            MulticastMembershipHandler::<I, BC>::select_device_for_multicast_group(
1947                self.state.fake_ip_socket_ctx_mut(),
1948                addr,
1949                marks,
1950            )
1951        }
1952    }
1953
1954    impl<I: Ip, D, State: InnerFakeIpSocketCtx<I, D>, Meta> InnerFakeIpSocketCtx<I, D>
1955        for FakeCoreCtx<State, Meta, D>
1956    {
1957        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1958            self.state.fake_ip_socket_ctx_mut()
1959        }
1960    }
1961
1962    impl<I: Ip, D: FakeStrongDeviceId> InnerFakeIpSocketCtx<I, D> for FakeDualStackIpSocketCtx<D> {
1963        fn fake_ip_socket_ctx_mut(&mut self) -> &mut FakeIpSocketCtx<I, D> {
1964            self.inner_mut::<I>()
1965        }
1966    }
1967
1968    /// A device configuration for fake socket contexts.
1969    #[derive(Clone, GenericOverIp)]
1970    #[generic_over_ip()]
1971    pub struct FakeDeviceConfig<D, A> {
1972        /// The device.
1973        pub device: D,
1974        /// The device's local IPs.
1975        pub local_ips: Vec<A>,
1976        /// The remote IPs reachable from this device.
1977        pub remote_ips: Vec<A>,
1978    }
1979
1980    /// State associated with a fake device in [`FakeIpSocketCtx`].
1981    pub struct FakeDeviceState<I: Ip> {
1982        /// The default hop limit used by the device.
1983        pub default_hop_limit: NonZeroU8,
1984        /// The assigned device addresses.
1985        pub addresses: Vec<SpecifiedAddr<I::Addr>>,
1986        /// The joined multicast groups.
1987        pub multicast_groups: HashMap<MulticastAddr<I::Addr>, usize>,
1988    }
1989
1990    impl<I: Ip> FakeDeviceState<I> {
1991        /// Returns whether this fake device has joined multicast group `addr`.
1992        pub fn is_in_multicast_group(&self, addr: &MulticastAddr<I::Addr>) -> bool {
1993            self.multicast_groups.get(addr).is_some_and(|v| *v != 0)
1994        }
1995    }
1996
1997    impl<I: IpExt, D: FakeStrongDeviceId> FakeIpSocketCtx<I, D> {
1998        /// Creates a new `FakeIpSocketCtx` with the given device
1999        /// configs.
2000        pub fn new(
2001            device_configs: impl IntoIterator<Item = FakeDeviceConfig<D, SpecifiedAddr<I::Addr>>>,
2002        ) -> Self {
2003            let mut table = RoutingTable::default();
2004            let mut devices = HashMap::default();
2005            for FakeDeviceConfig { device, local_ips, remote_ips } in device_configs {
2006                for addr in remote_ips {
2007                    routing::testutil::add_on_link_routing_entry(&mut table, addr, device.clone())
2008                }
2009                let state = FakeDeviceState {
2010                    default_hop_limit: DEFAULT_HOP_LIMITS.unicast,
2011                    addresses: local_ips,
2012                    multicast_groups: Default::default(),
2013                };
2014                assert!(
2015                    devices.insert(device.clone(), state).is_none(),
2016                    "duplicate entries for {device:?}",
2017                );
2018            }
2019
2020            Self { table, devices, forwarding: Default::default() }
2021        }
2022
2023        /// Returns an immutable reference to the fake device state.
2024        pub fn get_device_state(&self, device: &D) -> &FakeDeviceState<I> {
2025            self.devices.get(device).unwrap_or_else(|| panic!("no device {device:?}"))
2026        }
2027
2028        /// Returns a mutable reference to the fake device state.
2029        pub fn get_device_state_mut(&mut self, device: &D) -> &mut FakeDeviceState<I> {
2030            self.devices.get_mut(device).unwrap_or_else(|| panic!("no device {device:?}"))
2031        }
2032
2033        pub(crate) fn multicast_memberships(
2034            &self,
2035        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
2036            self.devices
2037                .iter()
2038                .map(|(device, state)| {
2039                    state.multicast_groups.iter().filter_map(|(group, count)| {
2040                        NonZeroUsize::new(*count).map(|count| ((device.clone(), *group), count))
2041                    })
2042                })
2043                .flatten()
2044                .collect()
2045        }
2046
2047        fn new_ip_socket<O>(
2048            &mut self,
2049            args: IpSocketArgs<'_, D, I, O>,
2050        ) -> Result<IpSock<I, D::Weak>, IpSockCreationError>
2051        where
2052            O: RouteResolutionOptions<I>,
2053        {
2054            let IpSocketArgs { device, local_ip, remote_ip, proto, options } = args;
2055            let device = device
2056                .as_ref()
2057                .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
2058                .transpose()?;
2059            let device = device.as_ref().map(|d| d.as_ref());
2060            let resolved_route =
2061                self.lookup_route(device, local_ip, remote_ip, options.transparent())?;
2062            Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
2063        }
2064
2065        fn lookup_route(
2066            &mut self,
2067            device: Option<&D>,
2068            local_ip: Option<IpDeviceAddr<I::Addr>>,
2069            addr: RoutableIpAddr<I::Addr>,
2070            transparent: bool,
2071        ) -> Result<ResolvedRoute<I, D>, ResolveRouteError> {
2072            let Self { table, devices, forwarding } = self;
2073            let (destination, ()) = table
2074                .lookup_filter_map(forwarding, device, addr.addr(), |_, d| match &local_ip {
2075                    None => Some(()),
2076                    Some(local_ip) => {
2077                        if transparent {
2078                            return Some(());
2079                        }
2080                        devices.get(d).and_then(|state| {
2081                            state.addresses.contains(local_ip.as_ref()).then_some(())
2082                        })
2083                    }
2084                })
2085                .next()
2086                .ok_or(ResolveRouteError::Unreachable)?;
2087
2088            let Destination { device, next_hop } = destination;
2089            let mut addrs = devices.get(device).unwrap().addresses.iter();
2090            let local_ip = match local_ip {
2091                None => {
2092                    let addr = addrs.next().ok_or(ResolveRouteError::NoSrcAddr)?;
2093                    IpDeviceAddr::new(addr.get()).expect("not valid device addr")
2094                }
2095                Some(local_ip) => {
2096                    if !transparent {
2097                        // We already constrained the set of devices so this
2098                        // should be a given.
2099                        assert!(
2100                            addrs.any(|a| a.get() == local_ip.addr()),
2101                            "didn't find IP {:?} in {:?}",
2102                            local_ip,
2103                            addrs.collect::<Vec<_>>()
2104                        );
2105                    }
2106                    local_ip
2107                }
2108            };
2109
2110            Ok(ResolvedRoute {
2111                src_addr: local_ip,
2112                device: device.clone(),
2113                local_delivery_device: None,
2114                next_hop,
2115                // NB: Keep unit tests simple and skip internal forwarding
2116                // logic. Instead, this is verified by integration tests.
2117                internal_forwarding: InternalForwarding::NotUsed,
2118            })
2119        }
2120
2121        fn resolve_send_meta<O>(
2122            &mut self,
2123            socket: &IpSock<I, D::Weak>,
2124            options: &O,
2125        ) -> Result<SendIpPacketMeta<I, D, SpecifiedAddr<I::Addr>>, IpSockSendError>
2126        where
2127            O: SendOptions<I> + RouteResolutionOptions<I>,
2128        {
2129            let IpSockDefinition { remote_ip, local_ip, device, proto } = &socket.definition;
2130            let device = device
2131                .as_ref()
2132                .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
2133                .transpose()?;
2134            let ResolvedRoute {
2135                src_addr,
2136                device,
2137                next_hop,
2138                local_delivery_device: _,
2139                internal_forwarding: _,
2140            } = self.lookup_route(
2141                device.as_ref(),
2142                Some(*local_ip),
2143                *remote_ip,
2144                options.transparent(),
2145            )?;
2146
2147            let remote_ip: &SpecifiedAddr<_> = remote_ip.as_ref();
2148
2149            let destination = IpPacketDestination::from_next_hop(next_hop, *remote_ip);
2150            Ok(SendIpPacketMeta {
2151                device,
2152                src_ip: src_addr.into(),
2153                dst_ip: *remote_ip,
2154                destination,
2155                proto: *proto,
2156                ttl: options.hop_limit(remote_ip),
2157                mtu: options.mtu(),
2158                dscp_and_ecn: DscpAndEcn::default(),
2159            })
2160        }
2161    }
2162}