// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! IPv4 and IPv6 sockets.

use core::cmp::Ordering;
use core::convert::Infallible;
use core::num::{NonZeroU32, NonZeroU8};

use net_types::{
    ip::{Ip, Ipv6Addr, Ipv6SourceAddr, Mtu},
    MulticastAddress, SpecifiedAddr,
};
use packet::{BufferMut, SerializeError};
use thiserror::Error;

use crate::{
    context::{CounterContext, InstantContext, NonTestCtxMarker, TracingContext},
    device::{self, AnyDevice, DeviceIdContext, WeakId as _},
    filter::{
        FilterBindingsTypes, FilterHandler as _, FilterHandlerProvider, TransportPacketSerializer,
    },
    ip::{
        device::{state::IpDeviceStateIpExt, IpDeviceAddr},
        types::{ResolvedRoute, RoutableIpAddr},
        EitherDeviceId, IpCounters, IpDeviceContext, IpExt, IpLayerIpExt, IpLayerPacketMetadata,
        ResolveRouteError, SendIpPacketMeta,
    },
    socket::address::SocketIpAddr,
    trace_duration,
};

/// An execution context defining a type of IP socket.
pub trait IpSocketHandler<I: IpExt, BC>: DeviceIdContext<AnyDevice> {
    /// Constructs a new [`IpSock`].
    ///
    /// `new_ip_socket` constructs a new `IpSock` to the given remote IP
    /// address from the given local IP address with the given IP protocol. If
    /// no local IP address is given, one will be chosen automatically. If
    /// `device` is `Some`, the socket will be bound to the given device - only
    /// routes which egress over the device will be used. If no route is
    /// available which egresses over the device - even if routes are available
    /// which egress over other devices - the socket will be considered
    /// unroutable.
    ///
    /// `new_ip_socket` returns an error if no route to the remote was found in
    /// the forwarding table or if the given local IP address is not valid for
    /// the found route.
    fn new_ip_socket(
        &mut self,
        bindings_ctx: &mut BC,
        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
        local_ip: Option<SocketIpAddr<I::Addr>>,
        remote_ip: SocketIpAddr<I::Addr>,
        proto: I::Proto,
    ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError>;

    /// Sends an IP packet on a socket.
    ///
    /// The generated packet has its metadata initialized from `socket`,
    /// including the source and destination addresses, the Time To Live/Hop
    /// Limit, and the Protocol/Next Header. The outbound device is also chosen
    /// based on information stored in the socket.
    ///
    /// `mtu` may be used to optionally impose an MTU on the outgoing packet.
    /// Note that the device's MTU will still be imposed on the packet. That is,
    /// the smaller of `mtu` and the device's MTU will be imposed on the packet.
    ///
    /// If the socket is currently unroutable, an error is returned.
    fn send_ip_packet<S, O>(
        &mut self,
        bindings_ctx: &mut BC,
        socket: &IpSock<I, Self::WeakDeviceId>,
        body: S,
        mtu: Option<u32>,
        options: &O,
    ) -> Result<(), (S, IpSockSendError)>
    where
        S: TransportPacketSerializer,
        S::Buffer: BufferMut,
        O: SendOptions<I, Self::WeakDeviceId>;

    /// Creates a temporary IP socket and sends a single packet on it.
    ///
    /// `local_ip`, `remote_ip`, `proto`, and `options` are passed directly to
    /// [`IpSocketHandler::new_ip_socket`]. `get_body_from_src_ip` is given the
    /// source IP address for the packet - which may have been chosen
    /// automatically if `local_ip` is `None` - and returns the body to be
    /// encapsulated. This is provided in case the body's contents depend on the
    /// chosen source IP address.
    ///
    /// If `device` is specified, the available routes are limited to those that
    /// egress over the device.
    ///
    /// `mtu` may be used to optionally impose an MTU on the outgoing packet.
    /// Note that the device's MTU will still be imposed on the packet. That is,
    /// the smaller of `mtu` and the device's MTU will be imposed on the packet.
    ///
    /// # Errors
    ///
    /// If an error is encountered while constructing the temporary IP socket
    /// or sending the packet, `options` will be returned along with the
    /// error. `get_body_from_src_ip` is fallible, and if there's an error,
    /// it will be returned as well.
    fn send_oneshot_ip_packet_with_fallible_serializer<S, E, F, O>(
        &mut self,
        bindings_ctx: &mut BC,
        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
        local_ip: Option<IpDeviceAddr<I::Addr>>,
        remote_ip: RoutableIpAddr<I::Addr>,
        proto: I::Proto,
        options: &O,
        get_body_from_src_ip: F,
        mtu: Option<u32>,
    ) -> Result<(), SendOneShotIpPacketError<E>>
    where
        S: TransportPacketSerializer,
        S::Buffer: BufferMut,
        F: FnOnce(SocketIpAddr<I::Addr>) -> Result<S, E>,
        O: SendOptions<I, Self::WeakDeviceId>,
    {
        let tmp = self
            .new_ip_socket(bindings_ctx, device, local_ip, remote_ip, proto)
            .map_err(|err| SendOneShotIpPacketError::CreateAndSendError { err: err.into() })?;
        let packet = get_body_from_src_ip(*tmp.local_ip())
            .map_err(SendOneShotIpPacketError::SerializeError)?;
        self.send_ip_packet(bindings_ctx, &tmp, packet, mtu, options).map_err(|(_body, err)| {
            SendOneShotIpPacketError::CreateAndSendError { err: err.into() }
        })
    }

    /// Sends a one-shot IP packet but with a non-fallible serializer.
    fn send_oneshot_ip_packet<S, F, O>(
        &mut self,
        bindings_ctx: &mut BC,
        device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
        local_ip: Option<SocketIpAddr<I::Addr>>,
        remote_ip: SocketIpAddr<I::Addr>,
        proto: I::Proto,
        options: &O,
        get_body_from_src_ip: F,
        mtu: Option<u32>,
    ) -> Result<(), IpSockCreateAndSendError>
    where
        S: TransportPacketSerializer,
        S::Buffer: BufferMut,
        F: FnOnce(SocketIpAddr<I::Addr>) -> S,
        O: SendOptions<I, Self::WeakDeviceId>,
    {
        self.send_oneshot_ip_packet_with_fallible_serializer(
            bindings_ctx,
            device,
            local_ip,
            remote_ip,
            proto,
            options,
            |ip| Ok::<_, Infallible>(get_body_from_src_ip(ip)),
            mtu,
        )
        .map_err(|err| match err {
            SendOneShotIpPacketError::CreateAndSendError { err } => err,
            SendOneShotIpPacketError::SerializeError(infallible) => match infallible {},
        })
    }
}

/// An error in sending a packet on an IP socket.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub enum IpSockSendError {
    /// An MTU was exceeded.
    ///
    /// This could be caused by an MTU at any layer of the stack, including both
    /// device MTUs and packet format body size limits.
    #[error("a maximum transmission unit (MTU) was exceeded")]
    Mtu,
    /// The socket is currently unroutable.
    #[error("the socket is currently unroutable: {}", _0)]
    Unroutable(#[from] ResolveRouteError),
}

impl From<SerializeError<Infallible>> for IpSockSendError {
    fn from(err: SerializeError<Infallible>) -> IpSockSendError {
        match err {
            SerializeError::Alloc(err) => match err {},
            SerializeError::SizeLimitExceeded => IpSockSendError::Mtu,
        }
    }
}

/// An error in sending a packet on a temporary IP socket.
#[derive(Error, Copy, Clone, Debug)]
pub enum IpSockCreateAndSendError {
    /// Cannot send via temporary socket.
    #[error("cannot send via temporary socket: {}", _0)]
    Send(#[from] IpSockSendError),
    /// The temporary socket could not be created.
    #[error("the temporary socket could not be created: {}", _0)]
    Create(#[from] IpSockCreationError),
}

#[derive(Debug)]
pub enum SendOneShotIpPacketError<E> {
    CreateAndSendError { err: IpSockCreateAndSendError },
    SerializeError(E),
}

/// Extension trait for `Ip` providing socket-specific functionality.
pub(crate) trait SocketIpExt: Ip + IpExt {
    /// `Self::LOOPBACK_ADDRESS`, but wrapped in the `SocketIpAddr` type.
    const LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR: SocketIpAddr<Self::Addr> = unsafe {
        // SAFETY: The loopback address is a valid SocketIpAddr, as verified
        // in the `loopback_addr_is_valid_socket_addr` test.
        SocketIpAddr::new_from_specified_unchecked(Self::LOOPBACK_ADDRESS)
    };
}

impl<I: Ip + IpExt> SocketIpExt for I {}

#[cfg(test)]
mod socket_ip_ext_test {
    use super::*;
    use ip_test_macro::ip_test;
    use net_types::ip::{Ipv4, Ipv6};

    #[ip_test]
    fn loopback_addr_is_valid_socket_addr<I: Ip + SocketIpExt>() {
        // `LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR is defined with the "unchecked"
        // constructor (which supports const construction). Verify here that the
        // addr actually satisfies all the requirements (protecting against far
        // away changes)
        let _addr = SocketIpAddr::new(I::LOOPBACK_ADDRESS_AS_SOCKET_IP_ADDR.addr())
            .expect("loopback address should be a valid SocketIpAddr");
    }
}

/// Maximum packet size, that is the maximum IP payload one packet can carry.
///
/// More details from https://www.rfc-editor.org/rfc/rfc1122#section-3.3.2.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct Mms(NonZeroU32);

impl Mms {
    pub(crate) fn from_mtu<I: IpExt>(mtu: Mtu, options_size: u32) -> Option<Self> {
        NonZeroU32::new(mtu.get().saturating_sub(I::IP_HEADER_LENGTH.get() + options_size))
            .map(|mms| Self(mms.min(I::IP_MAX_PAYLOAD_LENGTH)))
    }

    pub(crate) fn get(&self) -> NonZeroU32 {
        let Self(mms) = *self;
        mms
    }
}

/// Possible errors when retrieving the maximum transport message size.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum MmsError {
    /// Cannot find the device that is used for the ip socket, possibly because
    /// there is no route.
    #[error("cannot find the device: {}", _0)]
    NoDevice(#[from] ResolveRouteError),
    /// The MTU provided by the device is too small such that there is no room
    /// for a transport message at all.
    #[error("invalid MTU: {:?}", _0)]
    MTUTooSmall(Mtu),
}

/// Gets device related information of an IP socket.
pub trait DeviceIpSocketHandler<I, BC>: DeviceIdContext<AnyDevice>
where
    I: IpLayerIpExt,
{
    /// Gets the maximum message size for the transport layer, it equals the
    /// device MTU minus the IP header size.
    ///
    /// This corresponds to the GET_MAXSIZES call described in:
    /// https://www.rfc-editor.org/rfc/rfc1122#section-3.4
    fn get_mms(
        &mut self,
        bindings_ctx: &mut BC,
        ip_sock: &IpSock<I, Self::WeakDeviceId>,
    ) -> Result<Mms, MmsError>;
}

/// An error encountered when creating an IP socket.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub enum IpSockCreationError {
    /// An error occurred while looking up a route.
    #[error("a route cannot be determined: {}", _0)]
    Route(#[from] ResolveRouteError),
}

/// An IP socket.
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub struct IpSock<I: IpExt, D> {
    /// The definition of the socket.
    ///
    /// This does not change for the lifetime of the socket.
    definition: IpSockDefinition<I, D>,
}

/// The definition of an IP socket.
///
/// These values are part of the socket's definition, and never change.
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub(crate) struct IpSockDefinition<I: IpExt, D> {
    remote_ip: SocketIpAddr<I::Addr>,
    // Guaranteed to be unicast in its subnet since it's always equal to an
    // address assigned to the local device. We can't use the `UnicastAddr`
    // witness type since `Ipv4Addr` doesn't implement `UnicastAddress`.
    //
    // TODO(joshlf): Support unnumbered interfaces. Once we do that, a few
    // issues arise: A) Does the unicast restriction still apply, and is that
    // even well-defined for IPv4 in the absence of a subnet? B) Presumably we
    // have to always bind to a particular interface?
    local_ip: SocketIpAddr<I::Addr>,
    device: Option<D>,
    proto: I::Proto,
}

impl<I: IpExt, D> IpSock<I, D> {
    pub(crate) fn local_ip(&self) -> &SocketIpAddr<I::Addr> {
        &self.definition.local_ip
    }

    pub(crate) fn remote_ip(&self) -> &SocketIpAddr<I::Addr> {
        &self.definition.remote_ip
    }

    pub(crate) fn device(&self) -> Option<&D> {
        self.definition.device.as_ref()
    }

    pub(crate) fn proto(&self) -> I::Proto {
        self.definition.proto
    }
}

// TODO(joshlf): Once we support configuring transport-layer protocols using
// type parameters, use that to ensure that `proto` is the right protocol for
// the caller. We will still need to have a separate enforcement mechanism for
// raw IP sockets once we support those.

/// The bindings execution context for IP sockets.
pub trait IpSocketBindingsContext: InstantContext + TracingContext + FilterBindingsTypes {}
impl<BC: InstantContext + TracingContext + FilterBindingsTypes> IpSocketBindingsContext for BC {}

/// The context required in order to implement [`IpSocketHandler`].
///
/// Blanket impls of `IpSocketHandler` are provided in terms of
/// `IpSocketContext`.
pub trait IpSocketContext<I, BC: IpSocketBindingsContext>:
    DeviceIdContext<AnyDevice> + FilterHandlerProvider<I, BC>
where
    I: IpDeviceStateIpExt + IpExt,
{
    /// Returns a route for a socket.
    ///
    /// If `device` is specified, the available routes are limited to those that
    /// egress over the device.
    fn lookup_route(
        &mut self,
        bindings_ctx: &mut BC,
        device: Option<&Self::DeviceId>,
        src_ip: Option<IpDeviceAddr<I::Addr>>,
        dst_ip: RoutableIpAddr<I::Addr>,
    ) -> Result<ResolvedRoute<I, Self::DeviceId>, ResolveRouteError>;

    /// Send an IP packet to the next-hop node.
    fn send_ip_packet<S>(
        &mut self,
        bindings_ctx: &mut BC,
        meta: SendIpPacketMeta<I, &Self::DeviceId, SpecifiedAddr<I::Addr>>,
        body: S,
        packet_metadata: IpLayerPacketMetadata<I, BC>,
    ) -> Result<(), S>
    where
        S: TransportPacketSerializer,
        S::Buffer: BufferMut;
}

impl<I, BC, CC> IpSocketHandler<I, BC> for CC
where
    I: IpLayerIpExt + IpDeviceStateIpExt,
    BC: IpSocketBindingsContext,
    CC: IpSocketContext<I, BC> + CounterContext<IpCounters<I>> + NonTestCtxMarker,
    CC::DeviceId: crate::filter::InterfaceProperties<BC::DeviceClass>,
{
    fn new_ip_socket(
        &mut self,
        bindings_ctx: &mut BC,
        device: Option<EitherDeviceId<&CC::DeviceId, &CC::WeakDeviceId>>,
        local_ip: Option<SocketIpAddr<I::Addr>>,
        remote_ip: SocketIpAddr<I::Addr>,
        proto: I::Proto,
    ) -> Result<IpSock<I, CC::WeakDeviceId>, IpSockCreationError> {
        let device = device
            .as_ref()
            .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
            .transpose()?;
        let device = device.as_ref().map(|d| d.as_ref());

        // Make sure the remote is routable with a local address before creating
        // the socket. We do not care about the actual destination here because
        // we will recalculate it when we send a packet so that the best route
        // available at the time is used for each outgoing packet.
        let resolved_route = self.lookup_route(bindings_ctx, device, local_ip, remote_ip)?;
        Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
    }

    fn send_ip_packet<S, O>(
        &mut self,
        bindings_ctx: &mut BC,
        ip_sock: &IpSock<I, CC::WeakDeviceId>,
        body: S,
        mtu: Option<u32>,
        options: &O,
    ) -> Result<(), (S, IpSockSendError)>
    where
        S: TransportPacketSerializer,
        S::Buffer: BufferMut,
        O: SendOptions<I, Self::WeakDeviceId>,
    {
        // TODO(joshlf): Call `trace!` with relevant fields from the socket.
        self.increment(|counters| &counters.send_ip_packet);

        send_ip_packet(self, bindings_ctx, ip_sock, body, mtu, options)
    }
}

/// Provides hooks for altering sending behavior of [`IpSock`].
///
/// Must be implemented by the socket option type of an `IpSock` when using it
/// to call [`IpSocketHandler::send_ip_packet`]. This is implemented as a trait
/// instead of an inherent impl on a type so that users of sockets that don't
/// need certain option types, like TCP for anything multicast-related, can
/// avoid allocating space for those options.
pub trait SendOptions<I: Ip, D> {
    /// Returns the hop limit to set on a packet going to the given destination.
    ///
    /// If `Some(u)`, `u` will be used as the hop limit (IPv6) or TTL (IPv4) for
    /// a packet going to the given destination. Otherwise the default value
    /// will be used.
    fn hop_limit(&self, destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8>;

    /// Returns the interface selected for outgoing multicast packets.`
    fn multicast_interface(&self) -> Option<&D>;
}

/// Empty send options that never overrides default values.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub(crate) struct DefaultSendOptions;

impl<I: Ip, D> SendOptions<I, D> for DefaultSendOptions {
    fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
        None
    }

    fn multicast_interface(&self) -> Option<&D> {
        None
    }
}

fn new_ip_socket<I, D>(
    requested_device: Option<&D>,
    route: ResolvedRoute<I, D>,
    remote_ip: SocketIpAddr<I::Addr>,
    proto: I::Proto,
) -> IpSock<I, D::Weak>
where
    I: IpLayerIpExt,
    D: device::StrongId,
{
    // TODO(https://fxbug.dev/323389672): Cache a reference to the route to
    // avoid the route lookup on send as long as the routing table hasn't
    // changed in between these operations.
    let ResolvedRoute { src_addr, device: route_device, local_delivery_device, next_hop: _ } =
        route;

    // If the source or destination address require a device, make sure to
    // set that in the socket definition. Otherwise defer to what was provided.
    let socket_device = (crate::socket::must_have_zone(src_addr.as_ref())
        || crate::socket::must_have_zone(remote_ip.as_ref()))
    .then(|| {
        // NB: The route device might be loopback, and in such cases
        // we want to bind the socket to the device the source IP is
        // assigned to instead.
        local_delivery_device.unwrap_or(route_device)
    })
    .as_ref()
    .or(requested_device)
    .map(|d| d.downgrade());

    let definition =
        IpSockDefinition { local_ip: src_addr, remote_ip, device: socket_device, proto };
    IpSock { definition }
}

fn send_ip_packet<I, S, BC, CC, O>(
    core_ctx: &mut CC,
    bindings_ctx: &mut BC,
    socket: &IpSock<I, CC::WeakDeviceId>,
    body: S,
    mtu: Option<u32>,
    options: &O,
) -> Result<(), (S, IpSockSendError)>
where
    I: IpExt + IpDeviceStateIpExt + packet_formats::ip::IpExt,
    S: TransportPacketSerializer,
    S::Buffer: BufferMut,
    BC: IpSocketBindingsContext,
    CC: IpSocketContext<I, BC>,
    CC::DeviceId: crate::filter::InterfaceProperties<BC::DeviceClass>,
    O: SendOptions<I, CC::WeakDeviceId> + ?Sized,
{
    trace_duration!(bindings_ctx, c"ip::send_packet");

    let IpSock { definition: IpSockDefinition { remote_ip, local_ip, device, proto } } = socket;

    let device = device.as_ref().or_else(|| {
        remote_ip.addr().is_multicast().then(|| options.multicast_interface()).flatten()
    });

    let device = match device.map(|d| d.upgrade()) {
        Some(Some(device)) => Some(device),
        Some(None) => return Err((body, ResolveRouteError::Unreachable.into())),
        None => None,
    };

    let ResolvedRoute { src_addr: got_local_ip, local_delivery_device: _, device, next_hop } =
        match core_ctx.lookup_route(bindings_ctx, device.as_ref(), Some(*local_ip), *remote_ip) {
            Ok(o) => o,
            Err(e) => return Err((body, IpSockSendError::Unroutable(e))),
        };
    assert_eq!(local_ip, &got_local_ip);

    // TODO(https://fxbug.dev/318717702): when we implement NAT, perform re-routing
    // after the LOCAL_EGRESS hook since the packet may have been changed.
    let mut packet = crate::filter::TxPacket::new(local_ip.addr(), remote_ip.addr(), *proto, &body);

    let mut packet_metadata = IpLayerPacketMetadata::default();
    match core_ctx.filter_handler().local_egress_hook(&mut packet, &device, &mut packet_metadata) {
        crate::filter::Verdict::Drop => {
            packet_metadata.acknowledge_drop();
            return Ok(());
        }
        crate::filter::Verdict::Accept => {}
    }

    let remote_ip: SpecifiedAddr<_> = (*remote_ip).into();
    let local_ip: SpecifiedAddr<_> = (*local_ip).into();

    let (next_hop, broadcast) = next_hop.into_next_hop_and_broadcast_marker(remote_ip);

    IpSocketContext::send_ip_packet(
        core_ctx,
        bindings_ctx,
        SendIpPacketMeta {
            device: &device,
            src_ip: local_ip,
            dst_ip: remote_ip,
            broadcast,
            next_hop,
            ttl: options.hop_limit(&remote_ip),
            proto: *proto,
            mtu,
        },
        body,
        packet_metadata,
    )
    .map_err(|s| (s, IpSockSendError::Mtu))
}

impl<
        I: IpLayerIpExt + IpDeviceStateIpExt,
        BC: IpSocketBindingsContext,
        CC: IpDeviceContext<I, BC> + IpSocketContext<I, BC> + NonTestCtxMarker,
    > DeviceIpSocketHandler<I, BC> for CC
{
    fn get_mms(
        &mut self,
        bindings_ctx: &mut BC,
        ip_sock: &IpSock<I, Self::WeakDeviceId>,
    ) -> Result<Mms, MmsError> {
        let IpSockDefinition { remote_ip, local_ip, device, proto: _ } = &ip_sock.definition;
        let device = device
            .as_ref()
            .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
            .transpose()?;

        let ResolvedRoute { src_addr: _, local_delivery_device: _, device, next_hop: _ } = self
            .lookup_route(bindings_ctx, device.as_ref(), Some(*local_ip), *remote_ip)
            .map_err(MmsError::NoDevice)?;
        let mtu = IpDeviceContext::<I, BC>::get_mtu(self, &device);
        // TODO(https://fxbug.dev/42072935): Calculate the options size when they
        // are supported.
        Mms::from_mtu::<I>(mtu, 0 /* no ip options used */).ok_or(MmsError::MTUTooSmall(mtu))
    }
}

/// IPv6 source address selection as defined in [RFC 6724 Section 5].
pub(crate) mod ipv6_source_address_selection {
    use net_types::ip::{AddrSubnet, IpAddress as _};

    use super::*;

    use crate::ip::device::{state::Ipv6AddressFlags, Ipv6DeviceAddr};

    pub(crate) struct SasCandidate<D> {
        pub(crate) addr_sub: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
        pub(crate) flags: Ipv6AddressFlags,
        pub(crate) device: D,
    }

    /// Selects the source address for an IPv6 socket using the algorithm
    /// defined in [RFC 6724 Section 5].
    ///
    /// This algorithm is only applicable when the user has not explicitly
    /// specified a source address.
    ///
    /// `remote_ip` is the remote IP address of the socket, `outbound_device` is
    /// the device over which outbound traffic to `remote_ip` is sent (according
    /// to the forwarding table), and `addresses` is an iterator of all
    /// addresses on all devices. The algorithm works by iterating over
    /// `addresses` and selecting the address which is most preferred according
    /// to a set of selection criteria.
    pub(crate) fn select_ipv6_source_address<
        'a,
        D: PartialEq,
        I: Iterator<Item = SasCandidate<D>>,
    >(
        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
        outbound_device: &D,
        addresses: I,
    ) -> Ipv6SourceAddr {
        // Source address selection as defined in RFC 6724 Section 5.
        //
        // The algorithm operates by defining a partial ordering on available
        // source addresses, and choosing one of the best address as defined by
        // that ordering (given multiple best addresses, the choice from among
        // those is implementation-defined). The partial order is defined in
        // terms of a sequence of rules. If a given rule defines an order
        // between two addresses, then that is their order. Otherwise, the next
        // rule must be consulted, and so on until all of the rules are
        // exhausted.

        let addr = addresses
            // Tentative addresses are not considered available to the source
            // selection algorithm.
            .filter(|SasCandidate { addr_sub: _, flags, device: _ }| flags.assigned)
            .max_by(|a, b| select_ipv6_source_address_cmp(remote_ip, outbound_device, a, b))
            .map(|SasCandidate { addr_sub, flags: _, device: _ }| addr_sub.addr());
        match addr {
            Some(addr) => Ipv6SourceAddr::Unicast(addr),
            None => Ipv6SourceAddr::Unspecified,
        }
    }

    /// Comparison operator used by `select_ipv6_source_address`.
    fn select_ipv6_source_address_cmp<D: PartialEq>(
        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
        outbound_device: &D,
        a: &SasCandidate<D>,
        b: &SasCandidate<D>,
    ) -> Ordering {
        // TODO(https://fxbug.dev/42123500): Implement rules 2, 4, 5.5, 6, and 7.

        let a_addr = a.addr_sub.addr().into_specified();
        let b_addr = b.addr_sub.addr().into_specified();

        // Assertions required in order for this implementation to be valid.

        // Required by the implementation of Rule 1.
        if let Some(remote_ip) = remote_ip {
            debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));
        }

        // Addresses that are not considered assigned are not valid source
        // addresses.
        debug_assert!(a.flags.assigned);
        debug_assert!(b.flags.assigned);

        rule_1(remote_ip, a_addr, b_addr)
            .then_with(|| rule_3(a.flags.deprecated, b.flags.deprecated))
            .then_with(|| rule_5(outbound_device, &a.device, &b.device))
            .then_with(|| rule_8(remote_ip, a.addr_sub, b.addr_sub))
    }

    // Assumes that `a` and `b` are not both equal to `remote_ip`.
    fn rule_1(
        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
        a: SpecifiedAddr<Ipv6Addr>,
        b: SpecifiedAddr<Ipv6Addr>,
    ) -> Ordering {
        let remote_ip = match remote_ip {
            Some(remote_ip) => remote_ip,
            None => return Ordering::Equal,
        };
        if (a == remote_ip) != (b == remote_ip) {
            // Rule 1: Prefer same address.
            //
            // Note that both `a` and `b` cannot be equal to `remote_ip` since
            // that would imply that we had added the same address twice to the
            // same device.
            //
            // If `(a == remote_ip) != (b == remote_ip)`, then exactly one of
            // them is equal. If this inequality does not hold, then they must
            // both be unequal to `remote_ip`. In the first case, we have a tie,
            // and in the second case, the rule doesn't apply. In either case,
            // we move onto the next rule.
            if a == remote_ip {
                Ordering::Greater
            } else {
                Ordering::Less
            }
        } else {
            Ordering::Equal
        }
    }

    fn rule_3(a_deprecated: bool, b_deprecated: bool) -> Ordering {
        match (a_deprecated, b_deprecated) {
            (true, false) => Ordering::Less,
            (true, true) | (false, false) => Ordering::Equal,
            (false, true) => Ordering::Greater,
        }
    }

    fn rule_5<D: PartialEq>(outbound_device: &D, a_device: &D, b_device: &D) -> Ordering {
        if (a_device == outbound_device) != (b_device == outbound_device) {
            // Rule 5: Prefer outgoing interface.
            if a_device == outbound_device {
                Ordering::Greater
            } else {
                Ordering::Less
            }
        } else {
            Ordering::Equal
        }
    }

    fn rule_8(
        remote_ip: Option<SpecifiedAddr<Ipv6Addr>>,
        a: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
        b: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
    ) -> Ordering {
        let remote_ip = match remote_ip {
            Some(remote_ip) => remote_ip,
            None => return Ordering::Equal,
        };
        // Per RFC 6724 Section 2.2:
        //
        //   We define the common prefix length CommonPrefixLen(S, D) of a
        //   source address S and a destination address D as the length of the
        //   longest prefix (looking at the most significant, or leftmost, bits)
        //   that the two addresses have in common, up to the length of S's
        //   prefix (i.e., the portion of the address not including the
        //   interface ID).  For example, CommonPrefixLen(fe80::1, fe80::2) is
        //   64.
        fn common_prefix_len(
            src: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
            dst: SpecifiedAddr<Ipv6Addr>,
        ) -> u8 {
            core::cmp::min(src.addr().common_prefix_len(&dst), src.subnet().prefix())
        }

        // Rule 8: Use longest matching prefix.
        //
        // Note that, per RFC 6724 Section 5:
        //
        //   Rule 8 MAY be superseded if the implementation has other means of
        //   choosing among source addresses.  For example, if the
        //   implementation somehow knows which source address will result in
        //   the "best" communications performance.
        //
        // We don't currently make use of this option, but it's an option for
        // the future.
        common_prefix_len(a, remote_ip).cmp(&common_prefix_len(b, remote_ip))
    }

    #[cfg(test)]
    mod tests {
        use net_declare::net_ip_v6;

        use super::*;

        #[test]
        fn test_select_ipv6_source_address() {
            // Test the comparison operator used by `select_ipv6_source_address`
            // by separately testing each comparison condition.

            let remote = SpecifiedAddr::new(net_ip_v6!("2001:0db8:1::")).unwrap();
            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();
            let dev0 = &0;
            let dev1 = &1;
            let dev2 = &2;

            // Rule 1: Prefer same address
            assert_eq!(rule_1(Some(remote), remote, local0), Ordering::Greater);
            assert_eq!(rule_1(Some(remote), local0, remote), Ordering::Less);
            assert_eq!(rule_1(Some(remote), local0, local1), Ordering::Equal);
            assert_eq!(rule_1(None, local0, local1), Ordering::Equal);

            // Rule 3: Avoid deprecated states
            assert_eq!(rule_3(false, true), Ordering::Greater);
            assert_eq!(rule_3(true, false), Ordering::Less);
            assert_eq!(rule_3(true, true), Ordering::Equal);
            assert_eq!(rule_3(false, false), Ordering::Equal);

            // Rule 5: Prefer outgoing interface
            assert_eq!(rule_5(dev0, dev0, dev2), Ordering::Greater);
            assert_eq!(rule_5(dev0, dev2, dev0), Ordering::Less);
            assert_eq!(rule_5(dev0, dev0, dev0), Ordering::Equal);
            assert_eq!(rule_5(dev0, dev2, dev2), Ordering::Equal);

            // Rule 8: Use longest matching prefix.
            {
                let new_addr_entry = |addr, prefix_len| AddrSubnet::new(addr, prefix_len).unwrap();

                // First, test that the longest prefix match is preferred when
                // using addresses whose common prefix length is shorter than
                // the subnet prefix length.

                // 4 leading 0x01 bytes.
                let remote = SpecifiedAddr::new(net_ip_v6!("1111::")).unwrap();
                // 3 leading 0x01 bytes.
                let local0 = new_addr_entry(net_ip_v6!("1110::"), 64);
                // 2 leading 0x01 bytes.
                let local1 = new_addr_entry(net_ip_v6!("1100::"), 64);

                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Greater);
                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Less);
                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);

                // Second, test that the common prefix length is capped at the
                // subnet prefix length.

                // 3 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
                let local0 = new_addr_entry(net_ip_v6!("1110::"), 8);
                // 2 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
                let local1 = new_addr_entry(net_ip_v6!("1100::"), 8);

                assert_eq!(rule_8(Some(remote), local0, local1), Ordering::Equal);
                assert_eq!(rule_8(Some(remote), local1, local0), Ordering::Equal);
                assert_eq!(rule_8(Some(remote), local0, local0), Ordering::Equal);
                assert_eq!(rule_8(Some(remote), local1, local1), Ordering::Equal);
                assert_eq!(rule_8(None, local0, local1), Ordering::Equal);
            }

            {
                let new_addr_entry = |addr, device| SasCandidate {
                    addr_sub: AddrSubnet::new(addr, 128).unwrap(),
                    flags: Ipv6AddressFlags { deprecated: false, assigned: true },
                    device,
                };

                // If no rules apply, then the two address entries are equal.
                assert_eq!(
                    select_ipv6_source_address_cmp(
                        Some(remote),
                        dev0,
                        &new_addr_entry(*local0, *dev1),
                        &new_addr_entry(*local1, *dev2),
                    ),
                    Ordering::Equal
                );
            }
        }

        #[test]
        fn test_select_ipv6_source_address_no_remote() {
            // Verify that source address selection correctly applies all
            // applicable rules when the remote is `None`.
            let dev0 = &0;
            let dev1 = &1;
            let dev2 = &2;

            let local0 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:2::")).unwrap();
            let local1 = SpecifiedAddr::new(net_ip_v6!("2001:0db8:3::")).unwrap();

            let new_addr_entry = |addr, deprecated, device| SasCandidate {
                addr_sub: AddrSubnet::new(addr, 128).unwrap(),
                flags: Ipv6AddressFlags { deprecated, assigned: true },
                device,
            };

            // Verify that Rule 3 still applies (avoid deprecated states).
            assert_eq!(
                select_ipv6_source_address_cmp(
                    None,
                    dev0,
                    &new_addr_entry(*local0, false, *dev1),
                    &new_addr_entry(*local1, true, *dev2),
                ),
                Ordering::Greater
            );

            // Verify that Rule 5 still applies (Prefer outgoing interface).
            assert_eq!(
                select_ipv6_source_address_cmp(
                    None,
                    dev0,
                    &new_addr_entry(*local0, false, *dev0),
                    &new_addr_entry(*local1, false, *dev1),
                ),
                Ordering::Greater
            );
        }
    }
}

/// Test fake implementations of the traits defined in the `socket` module.
#[cfg(test)]
pub(crate) mod testutil {
    use alloc::{boxed::Box, collections::HashMap, vec::Vec};
    use core::num::NonZeroUsize;

    use derivative::Derivative;
    use net_types::{
        ip::{GenericOverIp, IpAddr, IpInvariant, Ipv4, Ipv4Addr, Ipv6},
        MulticastAddr, Witness as _,
    };

    use super::*;
    use crate::{
        context::{testutil::FakeCoreCtx, SendFrameContext},
        device::testutil::{FakeStrongDeviceId, FakeWeakDeviceId},
        ip::{
            forwarding::{testutil::FakeIpForwardingCtx, ForwardingTable},
            testutil::FakeIpDeviceIdCtx,
            types::Destination,
            HopLimits, MulticastMembershipHandler, TransportIpContext, DEFAULT_HOP_LIMITS,
        },
    };

    /// A fake implementation of [`IpSocketContext`].
    ///
    /// `IpSocketContext` is implemented for `FakeIpSocketCtx` and any
    /// `FakeCtx<S>` where `S` implements `AsRef` and `AsMut` for
    /// `FakeIpSocketCtx`.
    #[derive(Derivative, GenericOverIp)]
    #[generic_over_ip(I, Ip)]
    #[derivative(Default(bound = ""))]
    pub(crate) struct FakeIpSocketCtx<I: IpLayerIpExt, D> {
        pub(crate) table: ForwardingTable<I, D>,
        forwarding: FakeIpForwardingCtx<D>,
        devices: HashMap<D, FakeDeviceState<I>>,
    }

    impl<I: IpLayerIpExt, D> AsRef<Self> for FakeIpSocketCtx<I, D> {
        fn as_ref(&self) -> &Self {
            self
        }
    }

    impl<I: IpLayerIpExt, D> AsMut<Self> for FakeIpSocketCtx<I, D> {
        fn as_mut(&mut self) -> &mut Self {
            self
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId, BC> TransportIpContext<I, BC>
        for FakeIpSocketCtx<I, D>
    {
        fn get_default_hop_limits(&mut self, device: Option<&D>) -> HopLimits {
            device.map_or(DEFAULT_HOP_LIMITS, |device| {
                let hop_limit = self.get_device_state(device).default_hop_limit;
                HopLimits { unicast: hop_limit, multicast: DEFAULT_HOP_LIMITS.multicast }
            })
        }

        type DevicesWithAddrIter<'a> = Box<dyn Iterator<Item = D> + 'a>;

        fn get_devices_with_assigned_addr(
            &mut self,
            addr: SpecifiedAddr<<I>::Addr>,
        ) -> Self::DevicesWithAddrIter<'_> {
            Box::new(self.devices.iter().filter_map(move |(device, state)| {
                state.addresses.contains(&addr).then(|| device.clone())
            }))
        }

        fn confirm_reachable_with_destination(
            &mut self,
            _bindings_ctx: &mut BC,
            _dst: SpecifiedAddr<<I>::Addr>,
            _device: Option<&D>,
        ) {
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeIpSocketCtx<I, D> {
        type DeviceId = <FakeIpDeviceIdCtx<D> as DeviceIdContext<AnyDevice>>::DeviceId;
        type WeakDeviceId = <FakeIpDeviceIdCtx<D> as DeviceIdContext<AnyDevice>>::WeakDeviceId;
    }

    impl<I, D, BC> IpSocketHandler<I, BC> for FakeIpSocketCtx<I, D>
    where
        I: IpLayerIpExt,
        D: FakeStrongDeviceId,
    {
        fn new_ip_socket(
            &mut self,
            _bindings_ctx: &mut BC,
            device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
            local_ip: Option<SocketIpAddr<I::Addr>>,
            remote_ip: SocketIpAddr<I::Addr>,
            proto: I::Proto,
        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError> {
            let device = device
                .as_ref()
                .map(|d| d.as_strong_ref().ok_or(ResolveRouteError::Unreachable))
                .transpose()?;
            let device = device.as_ref().map(|d| d.as_ref());
            let resolved_route = self.lookup_route(device, local_ip, remote_ip)?;
            Ok(new_ip_socket(device, resolved_route, remote_ip, proto))
        }

        fn send_ip_packet<S, O>(
            &mut self,
            _bindings_ctx: &mut BC,
            _socket: &IpSock<I, Self::WeakDeviceId>,
            _body: S,
            _mtu: Option<u32>,
            _options: &O,
        ) -> Result<(), (S, IpSockSendError)>
        where
            S: TransportPacketSerializer,
            S::Buffer: BufferMut,
            O: SendOptions<I, Self::WeakDeviceId>,
        {
            panic!("FakeIpSocketCtx can't send packets, wrap it in a FakeCoreCtx instead");
        }
    }

    impl<
            I: IpLayerIpExt + IpDeviceStateIpExt,
            State: AsRef<FakeIpSocketCtx<I, DeviceId>>
                + AsMut<FakeIpSocketCtx<I, DeviceId>>
                + AsRef<FakeIpDeviceIdCtx<DeviceId>>,
            Meta,
            DeviceId: FakeStrongDeviceId,
            BC,
        > IpSocketHandler<I, BC> for FakeCoreCtx<State, Meta, DeviceId>
    where
        FakeCoreCtx<State, Meta, DeviceId>:
            SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
    {
        fn new_ip_socket(
            &mut self,
            bindings_ctx: &mut BC,
            device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
            local_ip: Option<SocketIpAddr<I::Addr>>,
            remote_ip: SocketIpAddr<I::Addr>,
            proto: I::Proto,
        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError> {
            self.get_mut().as_mut().new_ip_socket(bindings_ctx, device, local_ip, remote_ip, proto)
        }

        fn send_ip_packet<S, O>(
            &mut self,
            bindings_ctx: &mut BC,
            socket: &IpSock<I, Self::WeakDeviceId>,
            body: S,
            mtu: Option<u32>,
            options: &O,
        ) -> Result<(), (S, IpSockSendError)>
        where
            S: TransportPacketSerializer,
            S::Buffer: BufferMut,
            O: SendOptions<I, Self::WeakDeviceId>,
        {
            let meta = match self.state.as_mut().resolve_send_meta(socket, mtu, options) {
                Ok(meta) => meta,
                Err(e) => {
                    return Err((body, e));
                }
            };
            self.send_frame(bindings_ctx, meta, body).map_err(|s| (s, IpSockSendError::Mtu))
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
        for FakeIpSocketCtx<I, D>
    {
        fn join_multicast_group(
            &mut self,
            _bindings_ctx: &mut BC,
            device: &Self::DeviceId,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) {
            let value = self.get_device_state_mut(device).multicast_groups.entry(addr).or_insert(0);
            *value = value.checked_add(1).unwrap();
        }

        fn leave_multicast_group(
            &mut self,
            _bindings_ctx: &mut BC,
            device: &Self::DeviceId,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) {
            let value = self
                .get_device_state_mut(device)
                .multicast_groups
                .get_mut(&addr)
                .unwrap_or_else(|| panic!("no entry for {addr} on {device:?}"));
            *value = value.checked_sub(1).unwrap();
        }

        fn select_device_for_multicast_group(
            &mut self,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) -> Result<Self::DeviceId, ResolveRouteError> {
            let remote_ip = SocketIpAddr::new_from_multicast(addr);
            self.lookup_route(None, None, remote_ip).map(|ResolvedRoute { device, .. }| device)
        }
    }

    impl<
            I: IpLayerIpExt,
            BC: InstantContext + TracingContext + FilterBindingsTypes,
            D: FakeStrongDeviceId,
            State: TransportIpContext<I, BC, DeviceId = D>,
            Meta,
        > TransportIpContext<I, BC> for FakeCoreCtx<State, Meta, D>
    where
        Self: IpSocketHandler<I, BC, DeviceId = D, WeakDeviceId = FakeWeakDeviceId<D>>,
    {
        type DevicesWithAddrIter<'a> = State::DevicesWithAddrIter<'a>
            where Self: 'a;

        fn get_devices_with_assigned_addr(
            &mut self,
            addr: SpecifiedAddr<I::Addr>,
        ) -> Self::DevicesWithAddrIter<'_> {
            TransportIpContext::<I, BC>::get_devices_with_assigned_addr(self.get_mut(), addr)
        }

        fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
            TransportIpContext::<I, BC>::get_default_hop_limits(self.get_mut(), device)
        }

        fn confirm_reachable_with_destination(
            &mut self,
            bindings_ctx: &mut BC,
            dst: SpecifiedAddr<I::Addr>,
            device: Option<&Self::DeviceId>,
        ) {
            TransportIpContext::<I, BC>::confirm_reachable_with_destination(
                self.get_mut(),
                bindings_ctx,
                dst,
                device,
            )
        }
    }

    #[derive(Derivative)]
    #[derivative(Default(bound = ""))]
    pub(crate) struct FakeDualStackIpSocketCtx<D> {
        v4: FakeIpSocketCtx<Ipv4, D>,
        v6: FakeIpSocketCtx<Ipv6, D>,
    }

    impl<D: FakeStrongDeviceId> FakeDualStackIpSocketCtx<D> {
        pub(crate) fn new<A: Into<SpecifiedAddr<IpAddr>>>(
            devices: impl IntoIterator<Item = FakeDeviceConfig<D, A>>,
        ) -> Self {
            let partition =
                |v: Vec<A>| -> (Vec<SpecifiedAddr<Ipv4Addr>>, Vec<SpecifiedAddr<Ipv6Addr>>) {
                    v.into_iter().fold((Vec::new(), Vec::new()), |(mut v4, mut v6), i| {
                        match IpAddr::from(i.into()) {
                            IpAddr::V4(a) => v4.push(a),
                            IpAddr::V6(a) => v6.push(a),
                        }
                        (v4, v6)
                    })
                };

            let (v4, v6): (Vec<_>, Vec<_>) = devices
                .into_iter()
                .map(|FakeDeviceConfig { device, local_ips, remote_ips }| {
                    let (local_v4, local_v6) = partition(local_ips);
                    let (remote_v4, remote_v6) = partition(remote_ips);
                    (
                        FakeDeviceConfig {
                            device: device.clone(),
                            local_ips: local_v4,
                            remote_ips: remote_v4,
                        },
                        FakeDeviceConfig { device, local_ips: local_v6, remote_ips: remote_v6 },
                    )
                })
                .unzip();
            Self { v4: FakeIpSocketCtx::new(v4), v6: FakeIpSocketCtx::new(v6) }
        }

        fn inner_mut<I: IpLayerIpExt>(&mut self) -> &mut FakeIpSocketCtx<I, D> {
            I::map_ip(IpInvariant(self), |IpInvariant(s)| &mut s.v4, |IpInvariant(s)| &mut s.v6)
        }

        fn inner<I: IpLayerIpExt>(&self) -> &FakeIpSocketCtx<I, D> {
            I::map_ip(IpInvariant(self), |IpInvariant(s)| &s.v4, |IpInvariant(s)| &s.v6)
        }

        pub(crate) fn add_route(&mut self, device: D, ip: SpecifiedAddr<IpAddr>) {
            match IpAddr::from(ip) {
                IpAddr::V4(ip) => crate::ip::forwarding::testutil::add_on_link_forwarding_entry(
                    &mut self.v4.table,
                    ip,
                    device,
                ),
                IpAddr::V6(ip) => crate::ip::forwarding::testutil::add_on_link_forwarding_entry(
                    &mut self.v6.table,
                    ip,
                    device,
                ),
            }
        }

        pub(crate) fn get_device_state_mut<I: IpLayerIpExt>(
            &mut self,
            device: &D,
        ) -> &mut FakeDeviceState<I> {
            self.inner_mut::<I>().get_device_state_mut(device)
        }

        pub(crate) fn multicast_memberships<I: IpLayerIpExt>(
            &self,
        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
            self.inner::<I>().multicast_memberships()
        }
    }

    impl<D: FakeStrongDeviceId> AsRef<Self> for FakeDualStackIpSocketCtx<D> {
        fn as_ref(&self) -> &Self {
            self
        }
    }

    impl<D: FakeStrongDeviceId> DeviceIdContext<AnyDevice> for FakeDualStackIpSocketCtx<D> {
        type DeviceId = D;
        type WeakDeviceId = D::Weak;
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId, BC> IpSocketHandler<I, BC>
        for FakeDualStackIpSocketCtx<D>
    {
        fn new_ip_socket(
            &mut self,
            bindings_ctx: &mut BC,
            device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
            local_ip: Option<SocketIpAddr<I::Addr>>,
            remote_ip: SocketIpAddr<I::Addr>,
            proto: I::Proto,
        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError> {
            IpSocketHandler::<I, BC>::new_ip_socket(
                self.inner_mut::<I>(),
                bindings_ctx,
                device,
                local_ip,
                remote_ip,
                proto,
            )
        }

        fn send_ip_packet<S, O>(
            &mut self,
            bindings_ctx: &mut BC,
            socket: &IpSock<I, Self::WeakDeviceId>,
            body: S,
            mtu: Option<u32>,
            options: &O,
        ) -> Result<(), (S, IpSockSendError)>
        where
            S: TransportPacketSerializer,
            S::Buffer: BufferMut,
            O: SendOptions<I, Self::WeakDeviceId>,
        {
            IpSocketHandler::<I, BC>::send_ip_packet(
                self.inner_mut::<I>(),
                bindings_ctx,
                socket,
                body,
                mtu,
                options,
            )
        }
    }

    impl<I: IpLayerIpExt, Meta, DeviceId: FakeStrongDeviceId, BC> IpSocketHandler<I, BC>
        for FakeCoreCtx<FakeDualStackIpSocketCtx<DeviceId>, Meta, DeviceId>
    where
        FakeCoreCtx<FakeDualStackIpSocketCtx<DeviceId>, Meta, DeviceId>:
            SendFrameContext<BC, SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>>,
    {
        fn new_ip_socket(
            &mut self,
            bindings_ctx: &mut BC,
            device: Option<EitherDeviceId<&Self::DeviceId, &Self::WeakDeviceId>>,
            local_ip: Option<SocketIpAddr<I::Addr>>,
            remote_ip: SocketIpAddr<I::Addr>,
            proto: I::Proto,
        ) -> Result<IpSock<I, Self::WeakDeviceId>, IpSockCreationError> {
            self.get_mut().new_ip_socket(bindings_ctx, device, local_ip, remote_ip, proto)
        }

        fn send_ip_packet<S, O>(
            &mut self,
            bindings_ctx: &mut BC,
            socket: &IpSock<I, Self::WeakDeviceId>,
            body: S,
            mtu: Option<u32>,
            options: &O,
        ) -> Result<(), (S, IpSockSendError)>
        where
            S: TransportPacketSerializer,
            S::Buffer: BufferMut,
            O: SendOptions<I, Self::WeakDeviceId>,
        {
            let meta = match self.state.inner_mut::<I>().resolve_send_meta(socket, mtu, options) {
                Ok(meta) => meta,
                Err(e) => {
                    return Err((body, e));
                }
            };
            self.send_frame(bindings_ctx, meta, body).map_err(|s| (s, IpSockSendError::Mtu))
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId, BC> MulticastMembershipHandler<I, BC>
        for FakeDualStackIpSocketCtx<D>
    {
        fn join_multicast_group(
            &mut self,
            bindings_ctx: &mut BC,
            device: &Self::DeviceId,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) {
            MulticastMembershipHandler::<I, BC>::join_multicast_group(
                self.inner_mut::<I>(),
                bindings_ctx,
                device,
                addr,
            )
        }

        fn leave_multicast_group(
            &mut self,
            bindings_ctx: &mut BC,
            device: &Self::DeviceId,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) {
            MulticastMembershipHandler::<I, BC>::leave_multicast_group(
                self.inner_mut::<I>(),
                bindings_ctx,
                device,
                addr,
            )
        }

        fn select_device_for_multicast_group(
            &mut self,
            addr: MulticastAddr<<I as Ip>::Addr>,
        ) -> Result<Self::DeviceId, ResolveRouteError> {
            MulticastMembershipHandler::<I, BC>::select_device_for_multicast_group(
                self.inner_mut::<I>(),
                addr,
            )
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId, BC> TransportIpContext<I, BC>
        for FakeDualStackIpSocketCtx<D>
    {
        fn get_default_hop_limits(&mut self, device: Option<&Self::DeviceId>) -> HopLimits {
            TransportIpContext::<I, BC>::get_default_hop_limits(self.inner_mut::<I>(), device)
        }

        type DevicesWithAddrIter<'a> = alloc::boxed::Box<dyn Iterator<Item = D> + 'a>;

        fn get_devices_with_assigned_addr(
            &mut self,
            addr: SpecifiedAddr<<I>::Addr>,
        ) -> Self::DevicesWithAddrIter<'_> {
            TransportIpContext::<I, BC>::get_devices_with_assigned_addr(self.inner_mut::<I>(), addr)
        }

        fn confirm_reachable_with_destination(
            &mut self,
            bindings_ctx: &mut BC,
            dst: SpecifiedAddr<<I>::Addr>,
            device: Option<&Self::DeviceId>,
        ) {
            TransportIpContext::<I, BC>::confirm_reachable_with_destination(
                self.inner_mut::<I>(),
                bindings_ctx,
                dst,
                device,
            )
        }
    }

    #[derive(Clone, GenericOverIp)]
    #[generic_over_ip()]
    pub(crate) struct FakeDeviceConfig<D, A> {
        pub(crate) device: D,
        pub(crate) local_ips: Vec<A>,
        pub(crate) remote_ips: Vec<A>,
    }

    pub(crate) struct FakeDeviceState<I: Ip> {
        pub default_hop_limit: NonZeroU8,
        pub addresses: Vec<SpecifiedAddr<I::Addr>>,
        pub multicast_groups: HashMap<MulticastAddr<I::Addr>, usize>,
    }

    impl<I: Ip> FakeDeviceState<I> {
        pub fn is_in_multicast_group(&self, addr: &MulticastAddr<I::Addr>) -> bool {
            self.multicast_groups.get(addr).is_some_and(|v| *v != 0)
        }
    }

    impl<I: IpLayerIpExt, D: FakeStrongDeviceId> FakeIpSocketCtx<I, D> {
        /// Creates a new `FakeIpSocketCtx` with the given device
        /// configs.
        pub(crate) fn new(
            device_configs: impl IntoIterator<Item = FakeDeviceConfig<D, SpecifiedAddr<I::Addr>>>,
        ) -> Self {
            let mut table = ForwardingTable::default();
            let mut devices = HashMap::default();
            for FakeDeviceConfig { device, local_ips, remote_ips } in device_configs {
                for addr in remote_ips {
                    crate::ip::forwarding::testutil::add_on_link_forwarding_entry(
                        &mut table,
                        addr,
                        device.clone(),
                    )
                }
                let state = FakeDeviceState {
                    default_hop_limit: crate::ip::DEFAULT_HOP_LIMITS.unicast,
                    addresses: local_ips,
                    multicast_groups: Default::default(),
                };
                assert!(
                    devices.insert(device.clone(), state).is_none(),
                    "duplicate entries for {device:?}",
                );
            }

            Self { table, devices, forwarding: Default::default() }
        }

        pub(crate) fn get_device_state(&self, device: &D) -> &FakeDeviceState<I> {
            self.devices.get(device).unwrap_or_else(|| panic!("no device {device:?}"))
        }

        pub(crate) fn get_device_state_mut(&mut self, device: &D) -> &mut FakeDeviceState<I> {
            self.devices.get_mut(device).unwrap_or_else(|| panic!("no device {device:?}"))
        }

        pub(crate) fn multicast_memberships(
            &self,
        ) -> HashMap<(D, MulticastAddr<I::Addr>), NonZeroUsize> {
            self.devices
                .iter()
                .map(|(device, state)| {
                    state.multicast_groups.iter().filter_map(|(group, count)| {
                        NonZeroUsize::new(*count).map(|count| ((device.clone(), *group), count))
                    })
                })
                .flatten()
                .collect()
        }

        fn lookup_route(
            &mut self,
            device: Option<&D>,
            local_ip: Option<IpDeviceAddr<I::Addr>>,
            addr: RoutableIpAddr<I::Addr>,
        ) -> Result<ResolvedRoute<I, D>, ResolveRouteError> {
            let Self { table, devices, forwarding } = self;
            let (destination, ()) = table
                .lookup_filter_map(forwarding, device, addr.addr(), |_, d| match &local_ip {
                    None => Some(()),
                    Some(local_ip) => devices.get(d).and_then(|state| {
                        state.addresses.contains(local_ip.as_ref()).then_some(())
                    }),
                })
                .next()
                .ok_or(ResolveRouteError::Unreachable)?;

            let Destination { device, next_hop } = destination;
            let mut addrs = devices.get(device).unwrap().addresses.iter();
            let local_ip = match local_ip {
                None => {
                    let addr = addrs.next().ok_or(ResolveRouteError::NoSrcAddr)?;
                    SocketIpAddr::new(addr.get()).expect("not valid socket addr")
                }
                Some(local_ip) => {
                    // We already constrained the set of devices so this
                    // should be a given.
                    assert!(
                        addrs.any(|a| a.get() == local_ip.addr()),
                        "didn't find IP {:?} in {:?}",
                        local_ip,
                        addrs.collect::<Vec<_>>()
                    );
                    local_ip
                }
            };

            Ok(ResolvedRoute {
                src_addr: local_ip,
                device: device.clone(),
                local_delivery_device: None,
                next_hop,
            })
        }

        fn resolve_send_meta<O>(
            &mut self,
            socket: &IpSock<I, D::Weak>,
            mtu: Option<u32>,
            options: &O,
        ) -> Result<SendIpPacketMeta<I, D, SpecifiedAddr<I::Addr>>, IpSockSendError>
        where
            O: SendOptions<I, D::Weak>,
        {
            let IpSockDefinition { remote_ip, local_ip, device, proto } = &socket.definition;
            let device = device
                .as_ref()
                .map(|d| d.upgrade().ok_or(ResolveRouteError::Unreachable))
                .transpose()?;
            let ResolvedRoute { src_addr, device, next_hop, local_delivery_device: _ } =
                self.lookup_route(device.as_ref(), Some(*local_ip), *remote_ip)?;

            let remote_ip: &SpecifiedAddr<_> = remote_ip.as_ref();
            let (next_hop, broadcast) = next_hop.into_next_hop_and_broadcast_marker(*remote_ip);
            Ok(SendIpPacketMeta {
                device,
                src_ip: src_addr.into(),
                dst_ip: *remote_ip,
                broadcast,
                next_hop,
                proto: *proto,
                ttl: options.hop_limit(remote_ip),
                mtu,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use alloc::vec::Vec;

    use assert_matches::assert_matches;
    use const_unwrap::const_unwrap_option;
    use ip_test_macro::ip_test;

    use net_types::{
        ip::{AddrSubnet, GenericOverIp, IpAddr, IpAddress, IpInvariant, Ipv4, Ipv4Addr, Ipv6},
        Witness,
    };
    use packet::{Buf, InnerPacketBuilder, ParseBuffer, Serializer as _};
    use packet_formats::{
        ethernet::EthernetFrameLengthCheck,
        icmp::{IcmpIpExt, IcmpUnusedCode},
        ip::{IpExt, IpPacket},
        ipv4::{Ipv4OnlyMeta, Ipv4Packet},
        testutil::{parse_ethernet_frame, parse_ip_packet_in_ethernet_frame},
    };
    use test_case::test_case;

    use super::*;
    use crate::{
        context::EventContext,
        device::{
            loopback::{LoopbackCreationProperties, LoopbackDevice},
            DeviceId, EthernetLinkDevice,
        },
        ip::{
            device::IpDeviceConfigurationContext as DeviceIpDeviceConfigurationContext,
            types::{AddableEntryEither, AddableMetric, RawMetric},
            IpLayerEvent, IpStateContext,
        },
        testutil::*,
        UnlockedCoreCtx,
    };

    enum AddressType {
        LocallyOwned,
        Remote,
        Unspecified {
            // Indicates whether or not it should be possible for the stack to
            // select an address when the client fails to specify one.
            can_select: bool,
        },
        Unroutable,
    }

    enum DeviceType {
        Unspecified,
        OtherDevice,
        LocalDevice,
    }

    struct NewSocketTestCase {
        local_ip_type: AddressType,
        remote_ip_type: AddressType,
        device_type: DeviceType,
        expected_result: Result<(), IpSockCreationError>,
    }

    trait IpSocketIpExt: Ip + TestIpExt + IcmpIpExt + IpExt + crate::ip::IpExt {
        fn multicast_addr(host: u8) -> SpecifiedAddr<Self::Addr>;
    }

    impl IpSocketIpExt for Ipv4 {
        fn multicast_addr(host: u8) -> SpecifiedAddr<Self::Addr> {
            let [a, b, c, _] = Ipv4::MULTICAST_SUBNET.network().ipv4_bytes();
            SpecifiedAddr::new(Ipv4Addr::new([a, b, c, host])).unwrap()
        }
    }
    impl IpSocketIpExt for Ipv6 {
        fn multicast_addr(host: u8) -> SpecifiedAddr<Self::Addr> {
            let mut bytes = Ipv6::MULTICAST_SUBNET.network().ipv6_bytes();
            bytes[15] = host;
            SpecifiedAddr::new(Ipv6Addr::from_bytes(bytes)).unwrap()
        }
    }

    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    struct WithHopLimit(Option<NonZeroU8>);

    impl<I: Ip, D> SendOptions<I, D> for WithHopLimit {
        fn hop_limit(&self, _destination: &SpecifiedAddr<I::Addr>) -> Option<NonZeroU8> {
            let Self(hop_limit) = self;
            *hop_limit
        }

        fn multicast_interface(&self) -> Option<&D> {
            None
        }
    }

    #[netstack3_macros::context_ip_bounds(I, FakeBindingsCtx, crate)]
    fn remove_all_local_addrs<I: crate::IpExt>(ctx: &mut FakeCtx) {
        let devices = DeviceIpDeviceConfigurationContext::<I, _>::with_devices_and_state(
            &mut ctx.core_ctx(),
            |devices, _ctx| devices.collect::<Vec<_>>(),
        );
        for device in devices {
            #[derive(GenericOverIp)]
            #[generic_over_ip(I, Ip)]
            struct WrapVecAddrSubnet<I: Ip>(Vec<AddrSubnet<I::Addr>>);

            let WrapVecAddrSubnet(subnets) = I::map_ip(
                IpInvariant((&mut ctx.core_ctx(), &device)),
                |IpInvariant((core_ctx, device))| {
                    crate::ip::device::with_assigned_ipv4_addr_subnets(core_ctx, device, |addrs| {
                        WrapVecAddrSubnet(addrs.collect::<Vec<_>>())
                    })
                },
                |IpInvariant((core_ctx, device))| {
                    crate::ip::device::testutil::with_assigned_ipv6_addr_subnets(
                        core_ctx,
                        device,
                        |addrs| WrapVecAddrSubnet(addrs.collect::<Vec<_>>()),
                    )
                },
            );

            for subnet in subnets {
                assert_eq!(
                    ctx.core_api()
                        .device_ip::<I>()
                        .del_ip_addr(&device, subnet.addr())
                        .expect("failed to remove addr from device")
                        .into_removed(),
                    subnet
                );
            }
        }
    }

    #[ip_test]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unroutable,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(ResolveRouteError::NoSrcAddr.into()),
        }; "unroutable local to remote")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::Unroutable,
            device_type: DeviceType::Unspecified,
            expected_result: Err(ResolveRouteError::Unreachable.into()),
        }; "local to unroutable remote")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        }; "local to remote")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        }; "unspecified to remote")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::LocalDevice,
            expected_result: Ok(()),
        }; "unspecified to remote through local device")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::OtherDevice,
            expected_result: Err(ResolveRouteError::Unreachable.into()),
        }; "unspecified to remote through other device")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: false },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(ResolveRouteError::NoSrcAddr.into()),
        }; "new unspcified to remote can't select")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Remote,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(ResolveRouteError::NoSrcAddr.into()),
        }; "new remote to remote")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        }; "new local to local")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        }; "new unspecified to local")]
    #[test_case(NewSocketTestCase {
            local_ip_type: AddressType::Remote,
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Err(ResolveRouteError::NoSrcAddr.into()),
        }; "new remote to local")]
    #[netstack3_macros::context_ip_bounds(I, FakeBindingsCtx, crate)]
    fn test_new<I: Ip + IpSocketIpExt + crate::IpExt>(test_case: NewSocketTestCase) {
        let cfg = I::FAKE_CONFIG;
        let proto = I::ICMP_IP_PROTO;

        let FakeEventDispatcherConfig { local_ip, remote_ip, subnet, local_mac: _, remote_mac: _ } =
            cfg;
        let (mut ctx, device_ids) = FakeEventDispatcherBuilder::from_config(cfg).build();
        let loopback_device_id = ctx
            .core_api()
            .device::<LoopbackDevice>()
            .add_device_with_default_state(
                LoopbackCreationProperties { mtu: Mtu::new(u16::MAX as u32) },
                DEFAULT_INTERFACE_METRIC,
            )
            .into();

        crate::device::testutil::enable_device(&mut ctx, &loopback_device_id);

        let NewSocketTestCase { local_ip_type, remote_ip_type, expected_result, device_type } =
            test_case;

        let local_device = match device_type {
            DeviceType::Unspecified => None,
            DeviceType::LocalDevice => Some(device_ids[0].clone().into()),
            DeviceType::OtherDevice => Some(loopback_device_id.clone()),
        };

        let (expected_from_ip, from_ip) = match local_ip_type {
            AddressType::LocallyOwned => (local_ip, Some(local_ip)),
            AddressType::Remote => (remote_ip, Some(remote_ip)),
            AddressType::Unspecified { can_select } => {
                if !can_select {
                    remove_all_local_addrs::<I>(&mut ctx);
                }
                (local_ip, None)
            }
            AddressType::Unroutable => {
                remove_all_local_addrs::<I>(&mut ctx);
                (local_ip, Some(local_ip))
            }
        };
        let to_ip = match remote_ip_type {
            AddressType::LocallyOwned => local_ip,
            AddressType::Remote => remote_ip,
            AddressType::Unspecified { can_select: _ } => {
                panic!("remote_ip_type cannot be unspecified")
            }
            AddressType::Unroutable => {
                ctx.test_api().del_routes_to_subnet(subnet.into()).unwrap();
                remote_ip
            }
        };
        let Ctx { core_ctx, bindings_ctx } = &mut ctx;

        let get_expected_result = |template| expected_result.map(|()| template);
        let weak_local_device = local_device.as_ref().map(|d| d.downgrade());
        let template = IpSock {
            definition: IpSockDefinition {
                remote_ip: SocketIpAddr::try_from(to_ip).unwrap(),
                local_ip: SocketIpAddr::try_from(expected_from_ip).unwrap(),
                device: weak_local_device.clone(),
                proto,
            },
        };

        let res = IpSocketHandler::<I, _>::new_ip_socket(
            &mut core_ctx.context(),
            bindings_ctx,
            weak_local_device.as_ref().map(EitherDeviceId::Weak),
            from_ip.map(|a| SocketIpAddr::try_from(a).unwrap()),
            SocketIpAddr::try_from(to_ip).unwrap(),
            proto,
        );
        assert_eq!(res, get_expected_result(template));
    }

    #[ip_test]
    #[test_case(AddressType::LocallyOwned, AddressType::LocallyOwned; "local to local")]
    #[test_case(AddressType::Unspecified { can_select: true },
            AddressType::LocallyOwned; "unspecified to local")]
    #[test_case(AddressType::LocallyOwned, AddressType::Remote; "local to remote")]
    #[netstack3_macros::context_ip_bounds(I, FakeBindingsCtx, crate)]
    fn test_send_local<I: Ip + IpSocketIpExt + crate::IpExt>(
        from_addr_type: AddressType,
        to_addr_type: AddressType,
    ) where
        for<'a> UnlockedCoreCtx<'a, FakeBindingsCtx>: IpSocketHandler<I, FakeBindingsCtx>
            + DeviceIdContext<AnyDevice, DeviceId = DeviceId<FakeBindingsCtx>>,
    {
        set_logger_for_test();

        use packet_formats::icmp::{IcmpEchoRequest, IcmpPacketBuilder};

        let FakeEventDispatcherConfig::<I::Addr> {
            subnet,
            local_ip,
            remote_ip,
            local_mac,
            remote_mac: _,
        } = I::FAKE_CONFIG;

        let mut builder = FakeEventDispatcherBuilder::default();
        let device_idx = builder.add_device(local_mac);
        let (mut ctx, device_ids) = builder.build();
        let device_id: DeviceId<_> = device_ids[device_idx].clone().into();

        ctx.core_api()
            .device_ip::<I>()
            .add_ip_addr_subnet(&device_id, AddrSubnet::new(local_ip.get(), 16).unwrap())
            .unwrap();
        ctx.core_api()
            .device_ip::<I>()
            .add_ip_addr_subnet(&device_id, AddrSubnet::new(remote_ip.get(), 16).unwrap())
            .unwrap();
        ctx.test_api()
            .add_route(AddableEntryEither::without_gateway(
                subnet.into(),
                device_id,
                AddableMetric::ExplicitMetric(RawMetric(0)),
            ))
            .unwrap();

        let loopback_device_id = ctx
            .core_api()
            .device::<LoopbackDevice>()
            .add_device_with_default_state(
                LoopbackCreationProperties { mtu: Mtu::new(u16::MAX as u32) },
                DEFAULT_INTERFACE_METRIC,
            )
            .into();
        crate::device::testutil::enable_device(&mut ctx, &loopback_device_id);
        let Ctx { core_ctx, bindings_ctx } = &mut ctx;

        let (expected_from_ip, from_ip) = match from_addr_type {
            AddressType::LocallyOwned => (local_ip, Some(local_ip)),
            AddressType::Remote => panic!("from_addr_type cannot be remote"),
            AddressType::Unspecified { can_select: _ } => (local_ip, None),
            AddressType::Unroutable => panic!("from_addr_type cannot be unroutable"),
        };

        let to_ip = match to_addr_type {
            AddressType::LocallyOwned => local_ip,
            AddressType::Remote => remote_ip,
            AddressType::Unspecified { can_select: _ } => {
                panic!("to_addr_type cannot be unspecified")
            }
            AddressType::Unroutable => panic!("to_addr_type cannot be unroutable"),
        };

        let sock = IpSocketHandler::<I, _>::new_ip_socket(
            &mut core_ctx.context(),
            bindings_ctx,
            None,
            from_ip.map(|a| SocketIpAddr::try_from(a).unwrap()),
            SocketIpAddr::try_from(to_ip).unwrap(),
            I::ICMP_IP_PROTO,
        )
        .unwrap();

        let reply = IcmpEchoRequest::new(0, 0).reply();
        let body = &[1, 2, 3, 4];
        let buffer = Buf::new(body.to_vec(), ..)
            .encapsulate(IcmpPacketBuilder::<I, _>::new(
                expected_from_ip.get(),
                to_ip.get(),
                IcmpUnusedCode,
                reply,
            ))
            .serialize_vec_outer()
            .unwrap();

        // Send an echo packet on the socket and validate that the packet is
        // delivered locally.
        IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            bindings_ctx,
            &sock,
            buffer.into_inner().buffer_view().as_ref().into_serializer(),
            None,
            &DefaultSendOptions,
        )
        .unwrap();

        assert!(handle_queued_rx_packets(&mut ctx));

        assert_matches!(ctx.bindings_ctx.take_ethernet_frames()[..], []);

        assert_eq!(ctx.core_ctx.ip_counters::<I>().dispatch_receive_ip_packet.get(), 1);
    }

    #[ip_test]
    fn test_send<I: Ip + IpSocketIpExt + IpLayerIpExt>()
    where
        for<'a> UnlockedCoreCtx<'a, FakeBindingsCtx>: IpSocketHandler<I, FakeBindingsCtx>
            + IpDeviceContext<I, FakeBindingsCtx, DeviceId = DeviceId<FakeBindingsCtx>>
            + IpStateContext<I, FakeBindingsCtx>,
        FakeBindingsCtx: EventContext<IpLayerEvent<DeviceId<FakeBindingsCtx>, I>>,
    {
        // Test various edge cases of the
        // IpSocketContext::send_ip_packet` method.

        let cfg = I::FAKE_CONFIG;
        let proto = I::ICMP_IP_PROTO;
        let socket_options = WithHopLimit(Some(const_unwrap_option(NonZeroU8::new(1))));

        let FakeEventDispatcherConfig::<_> { local_mac, remote_mac, local_ip, remote_ip, subnet } =
            cfg;

        let (Ctx { core_ctx, mut bindings_ctx }, device_ids) =
            FakeEventDispatcherBuilder::from_config(cfg).build();
        // Create a normal, routable socket.
        let sock = IpSocketHandler::<I, _>::new_ip_socket(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            None,
            None,
            SocketIpAddr::try_from(remote_ip).unwrap(),
            proto,
        )
        .unwrap();

        let curr_id = crate::ip::gen_ip_packet_id::<Ipv4, _, _>(&mut core_ctx.context());

        let check_frame =
            move |frame: &[u8], packet_count| match [local_ip.get(), remote_ip.get()].into() {
                IpAddr::V4([local_ip, remote_ip]) => {
                    let (mut body, src_mac, dst_mac, _ethertype) =
                        parse_ethernet_frame(frame, EthernetFrameLengthCheck::NoCheck).unwrap();
                    let packet = (&mut body).parse::<Ipv4Packet<&[u8]>>().unwrap();
                    assert_eq!(src_mac, local_mac.get());
                    assert_eq!(dst_mac, remote_mac.get());
                    assert_eq!(packet.src_ip(), local_ip);
                    assert_eq!(packet.dst_ip(), remote_ip);
                    assert_eq!(packet.proto(), Ipv4::ICMP_IP_PROTO);
                    assert_eq!(packet.ttl(), 1);
                    let Ipv4OnlyMeta { id } = packet.version_specific_meta();
                    assert_eq!(usize::from(id), usize::from(curr_id) + packet_count);
                    assert_eq!(body, [0]);
                }
                IpAddr::V6([local_ip, remote_ip]) => {
                    let (body, src_mac, dst_mac, src_ip, dst_ip, ip_proto, ttl) =
                        parse_ip_packet_in_ethernet_frame::<Ipv6>(
                            frame,
                            EthernetFrameLengthCheck::NoCheck,
                        )
                        .unwrap();
                    assert_eq!(body, [0]);
                    assert_eq!(src_mac, local_mac.get());
                    assert_eq!(dst_mac, remote_mac.get());
                    assert_eq!(src_ip, local_ip);
                    assert_eq!(dst_ip, remote_ip);
                    assert_eq!(ip_proto, Ipv6::ICMP_IP_PROTO);
                    assert_eq!(ttl, 1);
                }
            };
        let mut packet_count = 0;
        assert_matches!(bindings_ctx.take_ethernet_frames()[..], []);

        // Send a packet on the socket and make sure that the right contents
        // are sent.
        IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            &sock,
            (&[0u8][..]).into_serializer(),
            None,
            &socket_options,
        )
        .unwrap();
        let mut check_sent_frame = |bindings_ctx: &mut crate::testutil::FakeBindingsCtx| {
            packet_count += 1;
            let frames = bindings_ctx.take_ethernet_frames();
            let (dev, frame) = assert_matches!(&frames[..], [frame] => frame);
            assert_eq!(dev, &device_ids[0]);
            check_frame(&frame, packet_count);
        };
        check_sent_frame(&mut bindings_ctx);

        // Send a packet while imposing an MTU that is large enough to fit the
        // packet.
        let small_body = [0; 1];
        let small_body_serializer = (&small_body).into_serializer();
        let res = IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            &sock,
            small_body_serializer,
            Some(Ipv6::MINIMUM_LINK_MTU.into()),
            &socket_options,
        );
        assert_matches!(res, Ok(()));
        check_sent_frame(&mut bindings_ctx);

        // Send a packet on the socket while imposing an MTU which will not
        // allow a packet to be sent.
        let res = IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            &sock,
            small_body_serializer,
            Some(1), // mtu
            &socket_options,
        );
        assert_matches!(res, Err((_, IpSockSendError::Mtu)));

        assert_matches!(bindings_ctx.take_ethernet_frames()[..], []);
        // Try sending a packet which will be larger than the device's MTU,
        // and make sure it fails.
        let res = IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            &sock,
            (&[0; Ipv6::MINIMUM_LINK_MTU.get() as usize][..]).into_serializer(),
            None,
            &socket_options,
        );
        assert_matches!(res, Err((_, IpSockSendError::Mtu)));

        // Make sure that sending on an unroutable socket fails.
        crate::ip::forwarding::testutil::del_routes_to_subnet::<I, _, _>(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            subnet,
        )
        .unwrap();
        let res = IpSocketHandler::<I, _>::send_ip_packet(
            &mut core_ctx.context(),
            &mut bindings_ctx,
            &sock,
            small_body_serializer,
            None,
            &socket_options,
        );
        assert_matches!(res, Err((_, IpSockSendError::Unroutable(ResolveRouteError::Unreachable))));
    }

    #[ip_test]
    #[netstack3_macros::context_ip_bounds(I, FakeBindingsCtx, crate)]
    fn test_send_hop_limits<I: Ip + IpSocketIpExt + crate::IpExt>() {
        set_logger_for_test();

        #[derive(Copy, Clone, Debug)]
        struct SetHopLimitFor<A>(SpecifiedAddr<A>);

        const SET_HOP_LIMIT: NonZeroU8 = const_unwrap_option(NonZeroU8::new(42));

        impl<A: IpAddress, D> SendOptions<A::Version, D> for SetHopLimitFor<A> {
            fn hop_limit(&self, destination: &SpecifiedAddr<A>) -> Option<NonZeroU8> {
                let Self(expected_destination) = self;
                (destination == expected_destination).then_some(SET_HOP_LIMIT)
            }

            fn multicast_interface(&self) -> Option<&D> {
                None
            }
        }

        let FakeEventDispatcherConfig::<I::Addr> {
            local_ip,
            remote_ip: _,
            local_mac,
            subnet: _,
            remote_mac: _,
        } = I::FAKE_CONFIG;

        let mut builder = FakeEventDispatcherBuilder::default();
        let device_idx = builder.add_device(local_mac);
        let (mut ctx, device_ids) = builder.build();
        let device_id: DeviceId<_> = device_ids[device_idx].clone().into();

        ctx.core_api()
            .device_ip::<I>()
            .add_ip_addr_subnet(&device_id, AddrSubnet::new(local_ip.get(), 16).unwrap())
            .unwrap();

        // Use multicast remote addresses since unicast addresses would trigger
        // ARP/NDP requests.
        ctx.test_api()
            .add_route(AddableEntryEither::without_gateway(
                I::MULTICAST_SUBNET.into(),
                device_id,
                AddableMetric::ExplicitMetric(RawMetric(0)),
            ))
            .expect("add device route");
        let remote_ip = I::multicast_addr(0);
        let options = SetHopLimitFor(remote_ip);
        let other_remote_ip = I::multicast_addr(1);

        let (mut core_ctx, bindings_ctx) = ctx.contexts();
        let mut send_to = |destination_ip| {
            let sock = IpSocketHandler::<I, _>::new_ip_socket(
                &mut core_ctx,
                bindings_ctx,
                None,
                None,
                destination_ip,
                I::ICMP_IP_PROTO,
            )
            .unwrap();

            IpSocketHandler::<I, _>::send_ip_packet(
                &mut core_ctx,
                bindings_ctx,
                &sock,
                (&[0u8][..]).into_serializer(),
                None,
                &options,
            )
            .unwrap();
        };

        // Send to two remote addresses: `remote_ip` and `other_remote_ip` and
        // check that the frames were sent with the correct hop limits.
        send_to(SocketIpAddr::try_from(remote_ip).unwrap());
        send_to(SocketIpAddr::try_from(other_remote_ip).unwrap());

        let frames = bindings_ctx.take_ethernet_frames();
        let [df_remote, df_other_remote] = assert_matches!(&frames[..], [df1, df2] => [df1, df2]);
        {
            let (_dev, frame) = df_remote;
            let (_body, _src_mac, _dst_mac, _src_ip, dst_ip, _ip_proto, hop_limit) =
                parse_ip_packet_in_ethernet_frame::<I>(&frame, EthernetFrameLengthCheck::NoCheck)
                    .unwrap();
            assert_eq!(dst_ip, remote_ip.get());
            // The `SetHopLimit`-returned value should take precedence.
            assert_eq!(hop_limit, SET_HOP_LIMIT.get());
        }

        {
            let (_dev, frame) = df_other_remote;
            let (_body, _src_mac, _dst_mac, _src_ip, dst_ip, _ip_proto, hop_limit) =
                parse_ip_packet_in_ethernet_frame::<I>(&frame, EthernetFrameLengthCheck::NoCheck)
                    .unwrap();
            assert_eq!(dst_ip, other_remote_ip.get());
            // When the options object does not provide a hop limit the default
            // is used.
            assert_eq!(hop_limit, crate::ip::DEFAULT_HOP_LIMITS.unicast.get());
        }
    }

    #[ip_test]
    #[test_case(true; "remove device")]
    #[test_case(false; "dont remove device")]
    #[netstack3_macros::context_ip_bounds(I, FakeBindingsCtx, crate)]
    fn get_mms_device_removed<I: Ip + IpSocketIpExt + crate::IpExt>(remove_device: bool)
    where
        for<'a> UnlockedCoreCtx<'a, FakeBindingsCtx>:
            IpSocketHandler<I, FakeBindingsCtx> + DeviceIpSocketHandler<I, FakeBindingsCtx>,
    {
        set_logger_for_test();

        let FakeEventDispatcherConfig::<I::Addr> {
            local_ip,
            remote_ip: _,
            local_mac,
            subnet: _,
            remote_mac: _,
        } = I::FAKE_CONFIG;

        let mut builder = FakeEventDispatcherBuilder::default();
        let device_idx = builder.add_device(local_mac);
        let (mut ctx, device_ids) = builder.build();
        let eth_device_id = device_ids[device_idx].clone();
        core::mem::drop(device_ids);
        let device_id: DeviceId<_> = eth_device_id.clone().into();

        ctx.core_api()
            .device_ip::<I>()
            .add_ip_addr_subnet(&device_id, AddrSubnet::new(local_ip.get(), 16).unwrap())
            .unwrap();
        ctx.test_api()
            .add_route(AddableEntryEither::without_gateway(
                I::MULTICAST_SUBNET.into(),
                device_id.clone(),
                AddableMetric::ExplicitMetric(RawMetric(0)),
            ))
            .unwrap();

        let (mut core_ctx, bindings_ctx) = ctx.contexts();
        let ip_sock = IpSocketHandler::<I, _>::new_ip_socket(
            &mut core_ctx,
            bindings_ctx,
            None,
            None,
            SocketIpAddr::try_from(I::multicast_addr(1)).unwrap(),
            I::ICMP_IP_PROTO,
        )
        .unwrap();

        let expected = if remove_device {
            // Clear routes on the device before removing it.
            ctx.test_api().del_device_routes(&device_id);

            // Don't keep any strong device IDs to the device before removing.
            core::mem::drop(device_id);
            ctx.core_api()
                .device::<EthernetLinkDevice>()
                .remove_device(eth_device_id)
                .into_removed();
            Err(MmsError::NoDevice(ResolveRouteError::Unreachable))
        } else {
            Ok(Mms::from_mtu::<I>(
                IpDeviceContext::<I, _>::get_mtu(&mut ctx.core_ctx(), &device_id),
                0, /* no ip options/ext hdrs used */
            )
            .unwrap())
        };
        let (mut core_ctx, bindings_ctx) = ctx.contexts();
        assert_eq!(DeviceIpSocketHandler::get_mms(&mut core_ctx, bindings_ctx, &ip_sock), expected,);
    }
}
