// 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 alloc::vec::Vec;
use core::cmp::Ordering;
use core::convert::Infallible;
use core::num::NonZeroU8;

use net_types::ip::{Ip, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
use net_types::{SpecifiedAddr, UnicastAddr};
use packet::{Buf, BufferMut, SerializeError, Serializer};
use packet_formats::ip::{Ipv4Proto, Ipv6Proto};
use thiserror::Error;

use crate::{
    context::{CounterContext, InstantContext},
    ip::{
        device::state::{IpDeviceStateIpExt, Ipv6AddressEntry},
        forwarding::Destination,
        IpDeviceIdContext, IpExt, SendIpPacketMeta,
    },
};

/// A socket identifying a connection between a local and remote IP host.
pub(crate) trait IpSocket<I: Ip> {
    /// Get the local IP address.
    fn local_ip(&self) -> &SpecifiedAddr<I::Addr>;

    /// Get the remote IP address.
    fn remote_ip(&self) -> &SpecifiedAddr<I::Addr>;
}

/// An execution context defining a type of IP socket.
pub trait IpSocketHandler<I: IpExt, C>: IpDeviceIdContext<I> {
    /// A builder carrying optional parameters passed to [`new_ip_socket`].
    ///
    /// [`new_ip_socket`]: crate::ip::socket::IpSocketHandler::new_ip_socket
    type Builder: Default;

    /// Constructs a new [`Self::IpSocket`].
    ///
    /// `new_ip_socket` constructs a new `Self::IpSocket` 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.
    ///
    /// The builder may be used to override certain default parameters. Passing
    /// `None` for the `builder` parameter is equivalent to passing
    /// `Some(Default::default())`.
    fn new_ip_socket(
        &mut self,
        ctx: &mut C,
        device: Option<Self::DeviceId>,
        local_ip: Option<SpecifiedAddr<I::Addr>>,
        remote_ip: SpecifiedAddr<I::Addr>,
        proto: I::Proto,
        builder: Option<Self::Builder>,
    ) -> Result<IpSock<I, Self::DeviceId>, IpSockCreationError>;
}

/// 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] IpSockUnroutableError),
}

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

/// An error in sending a packet on a temporary IP socket.
#[derive(Error, Copy, Clone, Debug)]
pub enum IpSockCreateAndSendError {
    /// 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 temporary socket could not be created.
    #[error("the temporary socket could not be created: {}", _0)]
    Create(#[from] IpSockCreationError),
}

/// An extension of [`IpSocketHandler`] adding the ability to send packets on an
/// IP socket.
pub trait BufferIpSocketHandler<I: IpExt, C, B: BufferMut>: IpSocketHandler<I, C> {
    /// 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: Serializer<Buffer = B>>(
        &mut self,
        ctx: &mut C,
        socket: &IpSock<I, Self::DeviceId>,
        body: S,
        mtu: Option<u32>,
    ) -> Result<(), (S, IpSockSendError)>;

    /// Creates a temporary IP socket and sends a single packet on it.
    ///
    /// `local_ip`, `remote_ip`, `proto`, and `builder` 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 sending the packet, the body returned
    /// from `get_body_from_src_ip` will be returned along with the error. If an
    /// error is encountered while constructing the temporary IP socket,
    /// `get_body_from_src_ip` will be called on an arbitrary IP address in
    /// order to obtain a body to return. In the case where a buffer was passed
    /// by ownership to `get_body_from_src_ip`, this allows the caller to
    /// recover that buffer.
    fn send_oneshot_ip_packet<S: Serializer<Buffer = B>, F: FnOnce(SpecifiedAddr<I::Addr>) -> S>(
        &mut self,
        ctx: &mut C,
        device: Option<Self::DeviceId>,
        local_ip: Option<SpecifiedAddr<I::Addr>>,
        remote_ip: SpecifiedAddr<I::Addr>,
        proto: I::Proto,
        builder: Option<Self::Builder>,
        get_body_from_src_ip: F,
        mtu: Option<u32>,
    ) -> Result<(), (S, IpSockCreateAndSendError)> {
        // We use a `match` instead of `map_err` because `map_err` would require passing a closure
        // which takes ownership of `get_body_from_src_ip`, which we also use in the success case.
        match self.new_ip_socket(ctx, device, local_ip, remote_ip, proto, builder) {
            Err(err) => Err((get_body_from_src_ip(I::LOOPBACK_ADDRESS), err.into())),
            Ok(tmp) => self
                .send_ip_packet(ctx, &tmp, get_body_from_src_ip(*tmp.local_ip()), mtu)
                .map_err(|(body, err)| match err {
                    IpSockSendError::Mtu => (body, IpSockCreateAndSendError::Mtu),
                    IpSockSendError::Unroutable(_) => {
                        unreachable!("socket which was just created should still be routable")
                    }
                }),
        }
    }
}

/// An error encountered when creating an IP socket.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub enum IpSockCreationError {
    /// The specified local IP address is not a unicast address in its subnet.
    ///
    /// For IPv4, this means that the address is a member of a subnet to which
    /// we are attached, but in that subnet, it is not a unicast address. For
    /// IPv6, whether or not an address is unicast is a property of the address
    /// and does not depend on what subnets we're attached to.
    #[error("the specified local IP address is not a unicast address in its subnet")]
    LocalAddrNotUnicast,
    /// An error occurred while looking up a route.
    #[error("a route cannot be determined: {}", _0)]
    Route(#[from] IpSockRouteError),
}

/// An error encountered when looking up a route for an IP socket.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub enum IpSockRouteError {
    /// No local IP address was specified, and one could not be automatically
    /// selected.
    #[error("a local IP address could not be automatically selected")]
    NoLocalAddrAvailable,
    /// The socket is unroutable.
    #[error("the socket is unroutable: {}", _0)]
    Unroutable(#[from] IpSockUnroutableError),
}

/// An error encountered when attempting to compute the routing information on
/// an IP socket.
///
/// An `IpSockUnroutableError` can occur when creating a socket or when updating
/// an existing socket in response to changes to the forwarding table or to the
/// set of IP addresses assigned to devices.
#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
pub enum IpSockUnroutableError {
    /// The specified local IP address is not one of our assigned addresses.
    ///
    /// For IPv6, this error will also be returned if the specified local IP
    /// address exists on one of our devices, but it is in the "temporary"
    /// state.
    #[error("the specified local IP address is not one of our assigned addresses")]
    LocalAddrNotAssigned,
    /// No route exists to the specified remote IP address.
    #[error("no route exists to the remote IP address")]
    NoRouteToRemoteAddr,
}

/// A builder for IPv4 sockets.
///
/// [`IpSocketContext::new_ip_socket`] accepts optional configuration in the
/// form of a `SocketBuilder`. All configurations have default values that are
/// used if a custom value is not provided.
#[derive(Default)]
pub struct Ipv4SocketBuilder {
    // NOTE(joshlf): These fields are `Option`s rather than being set to a
    // default value in `Default::default` because global defaults may be set
    // per-stack at runtime, meaning that default values cannot be known at
    // compile time.
    ttl: Option<NonZeroU8>,
}

impl Ipv4SocketBuilder {
    /// Set the Time to Live (TTL) field that will be set on outbound IPv4
    /// packets.
    ///
    /// The TTL must be non-zero. Per [RFC 1122 Section 3.2.1.7] and [RFC 1812
    /// Section 4.2.2.9], hosts and routers (respectively) must not originate
    /// IPv4 packets with a TTL of zero.
    ///
    /// [RFC 1122 Section 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7
    /// [RFC 1812 Section 4.2.2.9]: https://tools.ietf.org/html/rfc1812#section-4.2.2.9
    #[allow(dead_code)] // TODO(joshlf): Remove once this is used
    pub(crate) fn ttl(&mut self, ttl: NonZeroU8) -> &mut Ipv4SocketBuilder {
        self.ttl = Some(ttl);
        self
    }
}

/// A builder for IPv6 sockets.
///
/// [`IpSocketContext::new_ip_socket`] accepts optional configuration in the
/// form of a `SocketBuilder`. All configurations have default values that are
/// used if a custom value is not provided.
#[derive(Default)]
pub struct Ipv6SocketBuilder {
    // NOTE(joshlf): These fields are `Option`s rather than being set to a
    // default value in `Default::default` because global defaults may be set
    // per-stack at runtime, meaning that default values cannot be known at
    // compile time.
    hop_limit: Option<NonZeroU8>,
}

impl Ipv6SocketBuilder {
    /// Sets the Hop Limit field that will be set on outbound IPv6 packets.
    #[allow(dead_code)] // TODO(joshlf): Remove once this is used
    pub(crate) fn hop_limit(&mut self, hop_limit: NonZeroU8) -> &mut Ipv6SocketBuilder {
        self.hop_limit = Some(hop_limit);
        self
    }
}

/// The production implementation of the [`IpSocket`] trait.
#[derive(Clone)]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct IpSock<I: IpExt, D> {
    defn: IpSockDefinition<I, D>,
}

/// The definition of an IP socket.
///
/// These values are part of the socket's definition, and never change.
#[derive(Clone)]
#[cfg_attr(test, derive(Debug, PartialEq))]
struct IpSockDefinition<I: IpExt, D> {
    remote_ip: SpecifiedAddr<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: SpecifiedAddr<I::Addr>,
    #[cfg_attr(not(test), allow(unused))]
    device: Option<D>,
    hop_limit: Option<NonZeroU8>,
    proto: I::Proto,
}

impl<I: IpExt, D> IpSocket<I> for IpSock<I, D> {
    fn local_ip(&self) -> &SpecifiedAddr<I::Addr> {
        &self.defn.local_ip
    }

    fn remote_ip(&self) -> &SpecifiedAddr<I::Addr> {
        &self.defn.remote_ip
    }
}

// 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 route for a socket.
pub(super) struct IpSockRoute<I: Ip, D> {
    /// The local IP to use for the socket.
    pub(super) local_ip: SpecifiedAddr<I::Addr>,

    /// The destination for packets originating from the socket.
    pub(super) destination: Destination<I::Addr, D>,
}

/// The non-synchronized execution context for IP sockets.
pub(super) trait IpSocketNonSyncContext: InstantContext + CounterContext {}
impl<C: InstantContext + CounterContext> IpSocketNonSyncContext for C {}

/// The context required in order to implement [`IpSocketHandler`].
///
/// Blanket impls of `IpSocketHandler` are provided in terms of
/// `IpSocketContext`.
pub(super) trait IpSocketContext<I, C: IpSocketNonSyncContext>:
    IpDeviceIdContext<I>
where
    I: IpDeviceStateIpExt<C::Instant>,
{
    /// 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(
        &self,
        ctx: &mut C,
        device: Option<Self::DeviceId>,
        src_ip: Option<SpecifiedAddr<I::Addr>>,
        dst_ip: SpecifiedAddr<I::Addr>,
    ) -> Result<IpSockRoute<I, Self::DeviceId>, IpSockRouteError>;
}

/// The context required in order to implement [`BufferIpSocketHandler`].
///
/// Blanket impls of `BufferIpSocketHandler` are provided in terms of
/// `BufferIpSocketContext`.
pub(super) trait BufferIpSocketContext<I, C: IpSocketNonSyncContext, B: BufferMut>:
    IpSocketContext<I, C>
where
    I: IpDeviceStateIpExt<C::Instant> + packet_formats::ip::IpExt,
{
    /// Send an IP packet to the next-hop node.
    fn send_ip_packet<S: Serializer<Buffer = B>>(
        &mut self,
        ctx: &mut C,
        meta: SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>,
        body: S,
    ) -> Result<(), S>;
}

impl<C: IpSocketNonSyncContext, SC: IpSocketContext<Ipv4, C>> IpSocketHandler<Ipv4, C> for SC {
    type Builder = Ipv4SocketBuilder;

    fn new_ip_socket(
        &mut self,
        ctx: &mut C,
        device: Option<SC::DeviceId>,
        local_ip: Option<SpecifiedAddr<Ipv4Addr>>,
        remote_ip: SpecifiedAddr<Ipv4Addr>,
        proto: Ipv4Proto,
        builder: Option<Ipv4SocketBuilder>,
    ) -> Result<IpSock<Ipv4, SC::DeviceId>, IpSockCreationError> {
        // 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 IpSockRoute { local_ip, destination: _ } =
            self.lookup_route(ctx, device, local_ip, remote_ip)?;

        let Ipv4SocketBuilder { ttl } = builder.unwrap_or_default();

        let defn = IpSockDefinition { local_ip, remote_ip, device, proto, hop_limit: ttl };
        Ok(IpSock { defn })
    }
}

impl<C: IpSocketNonSyncContext, SC: IpSocketContext<Ipv6, C>> IpSocketHandler<Ipv6, C> for SC {
    type Builder = Ipv6SocketBuilder;

    fn new_ip_socket(
        &mut self,
        ctx: &mut C,
        device: Option<SC::DeviceId>,
        local_ip: Option<SpecifiedAddr<Ipv6Addr>>,
        remote_ip: SpecifiedAddr<Ipv6Addr>,
        proto: Ipv6Proto,
        builder: Option<Ipv6SocketBuilder>,
    ) -> Result<IpSock<Ipv6, SC::DeviceId>, IpSockCreationError> {
        // 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 IpSockRoute { local_ip, destination: _ } =
            self.lookup_route(ctx, device, local_ip, remote_ip)?;

        let Ipv6SocketBuilder { hop_limit } = builder.unwrap_or_default();

        let defn = IpSockDefinition { local_ip, remote_ip, device, proto, hop_limit };
        Ok(IpSock { defn })
    }
}

fn send_ip_packet<
    I: IpExt + IpDeviceStateIpExt<C::Instant> + packet_formats::ip::IpExt,
    B: BufferMut,
    S: Serializer<Buffer = B>,
    C: IpSocketNonSyncContext,
    SC: BufferIpSocketContext<I, C, B>
        + BufferIpSocketContext<I, C, Buf<Vec<u8>>>
        + IpSocketContext<I, C>,
>(
    sync_ctx: &mut SC,
    ctx: &mut C,
    IpSock { defn: IpSockDefinition { remote_ip, local_ip, device, hop_limit, proto } }: &IpSock<
        I,
        SC::DeviceId,
    >,
    body: S,
    mtu: Option<u32>,
) -> Result<(), (S, IpSockSendError)> {
    let IpSockRoute { local_ip: got_local_ip, destination: Destination { device, next_hop } } =
        match sync_ctx.lookup_route(ctx, *device, Some(*local_ip), *remote_ip) {
            Ok(o) => o,
            Err(IpSockRouteError::NoLocalAddrAvailable) => {
                unreachable!("local IP {} was specified", local_ip)
            }
            Err(IpSockRouteError::Unroutable(e)) => {
                return Err((body, IpSockSendError::Unroutable(e)))
            }
        };

    assert_eq!(*local_ip, got_local_ip);

    BufferIpSocketContext::send_ip_packet(
        sync_ctx,
        ctx,
        SendIpPacketMeta {
            device,
            src_ip: *local_ip,
            dst_ip: *remote_ip,
            next_hop,
            ttl: *hop_limit,
            proto: *proto,
            mtu,
        },
        body,
    )
    .map_err(|s| (s, IpSockSendError::Mtu))
}

impl<
        B: BufferMut,
        C: IpSocketNonSyncContext,
        SC: BufferIpSocketContext<Ipv4, C, B>
            + BufferIpSocketContext<Ipv4, C, Buf<Vec<u8>>>
            + IpSocketContext<Ipv4, C>,
    > BufferIpSocketHandler<Ipv4, C, B> for SC
{
    fn send_ip_packet<S: Serializer<Buffer = B>>(
        &mut self,
        ctx: &mut C,
        ip_sock: &IpSock<Ipv4, SC::DeviceId>,
        body: S,
        mtu: Option<u32>,
    ) -> Result<(), (S, IpSockSendError)> {
        // TODO(joshlf): Call `trace!` with relevant fields from the socket.
        ctx.increment_counter("send_ipv4_packet");

        send_ip_packet(self, ctx, ip_sock, body, mtu)
    }
}

impl<
        B: BufferMut,
        C: IpSocketNonSyncContext,
        SC: BufferIpSocketContext<Ipv6, C, B> + BufferIpSocketContext<Ipv6, C, Buf<Vec<u8>>>,
    > BufferIpSocketHandler<Ipv6, C, B> for SC
{
    fn send_ip_packet<S: Serializer<Buffer = B>>(
        &mut self,
        ctx: &mut C,
        ip_sock: &IpSock<Ipv6, SC::DeviceId>,
        body: S,
        mtu: Option<u32>,
    ) -> Result<(), (S, IpSockSendError)> {
        // TODO(joshlf): Call `trace!` with relevant fields from the socket.
        ctx.increment_counter("send_ipv6_packet");

        send_ip_packet(self, ctx, ip_sock, body, mtu)
    }
}

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

    use super::*;

    /// 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: Copy + PartialEq,
        Instant: 'a,
        I: Iterator<Item = (&'a Ipv6AddressEntry<Instant>, D)>,
    >(
        remote_ip: SpecifiedAddr<Ipv6Addr>,
        outbound_device: D,
        addresses: I,
    ) -> Option<UnicastAddr<Ipv6Addr>> {
        // 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.

        addresses
            // Tentative addresses are not considered available to the source
            // selection algorithm.
            .filter(|(a, _)| !a.state.is_tentative())
            .max_by(|(a, a_device), (b, b_device)| {
                select_ipv6_source_address_cmp(
                    remote_ip,
                    outbound_device,
                    a,
                    *a_device,
                    b,
                    *b_device,
                )
            })
            .map(|(addr, _device)| addr.addr_sub().addr())
    }

    /// Comparison operator used by `select_ipv6_source_address`.
    fn select_ipv6_source_address_cmp<Instant, D: Copy + PartialEq>(
        remote_ip: SpecifiedAddr<Ipv6Addr>,
        outbound_device: D,
        a: &Ipv6AddressEntry<Instant>,
        a_device: D,
        b: &Ipv6AddressEntry<Instant>,
        b_device: D,
    ) -> Ordering {
        // TODO(fxbug.dev/46822): 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.
        debug_assert!(!(a_addr == remote_ip && b_addr == remote_ip));

        // Tentative addresses are not valid source addresses since they are
        // not considered assigned.
        debug_assert!(!a.state.is_tentative());
        debug_assert!(!b.state.is_tentative());

        rule_1(remote_ip, a_addr, b_addr)
            .then_with(|| rule_3(a.deprecated, b.deprecated))
            .then_with(|| rule_5(outbound_device, a_device, b_device))
            .then_with(|| rule_8(remote_ip, a, b))
    }

    // Assumes that `a` and `b` are not both equal to `remote_ip`.
    fn rule_1(
        remote_ip: SpecifiedAddr<Ipv6Addr>,
        a: SpecifiedAddr<Ipv6Addr>,
        b: SpecifiedAddr<Ipv6Addr>,
    ) -> Ordering {
        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<Instant>(
        remote_ip: SpecifiedAddr<Ipv6Addr>,
        a: &Ipv6AddressEntry<Instant>,
        b: &Ipv6AddressEntry<Instant>,
    ) -> Ordering {
        // 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<Instant>(
            src: &Ipv6AddressEntry<Instant>,
            dst: SpecifiedAddr<Ipv6Addr>,
        ) -> u8 {
            core::cmp::min(
                src.addr_sub().addr().common_prefix_len(&dst),
                src.addr_sub().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_types::ip::AddrSubnet;

        use super::*;
        use crate::{
            device::DeviceId,
            ip::device::state::{AddrConfig, AddressState},
        };

        #[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(Ipv6Addr::from_bytes([
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 1,
            ]))
            .unwrap();
            let local0 = SpecifiedAddr::new(Ipv6Addr::from_bytes([
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 2,
            ]))
            .unwrap();
            let local1 = SpecifiedAddr::new(Ipv6Addr::from_bytes([
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 3,
            ]))
            .unwrap();
            let dev0 = DeviceId::new_ethernet(0);
            let dev1 = DeviceId::new_ethernet(1);
            let dev2 = DeviceId::new_ethernet(2);

            // Rule 1: Prefer same address
            assert_eq!(rule_1(remote, remote, local0), Ordering::Greater);
            assert_eq!(rule_1(remote, local0, remote), Ordering::Less);
            assert_eq!(rule_1(remote, 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 = |bytes, prefix_len| {
                    Ipv6AddressEntry::<()>::new(
                        AddrSubnet::new(Ipv6Addr::from_bytes(bytes), prefix_len).unwrap(),
                        AddressState::Assigned,
                        AddrConfig::Manual,
                    )
                };

                // 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(Ipv6Addr::from_bytes([
                    1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                ]))
                .unwrap();
                // 3 leading 0x01 bytes.
                let local0 = new_addr_entry([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 64);
                // 2 leading 0x01 bytes.
                let local1 = new_addr_entry([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 64);

                assert_eq!(rule_8(remote, &local0, &local1), Ordering::Greater);
                assert_eq!(rule_8(remote, &local1, &local0), Ordering::Less);
                assert_eq!(rule_8(remote, &local0, &local0), Ordering::Equal);
                assert_eq!(rule_8(remote, &local1, &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([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 8);
                // 2 leading 0x01 bytes, but a subnet prefix length of 8 (1 byte).
                let local1 = new_addr_entry([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 8);

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

            {
                let new_addr_entry = |addr| {
                    Ipv6AddressEntry::<()>::new(
                        AddrSubnet::new(addr, 128).unwrap(),
                        AddressState::Assigned,
                        AddrConfig::Manual,
                    )
                };

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

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

    use net_types::{
        ip::{AddrSubnet, IpAddress, Subnet},
        Witness,
    };

    use super::*;
    use crate::{
        context::{
            testutil::{DummyInstant, DummyNonSyncCtx, DummySyncCtx},
            FrameContext,
        },
        ip::{
            device::state::{AddrConfig, AddressState, AssignedAddress as _, IpDeviceState},
            forwarding::ForwardingTable,
            DummyDeviceId, IpDeviceId, SendIpPacketMeta,
        },
    };

    /// A dummy implementation of [`IpSocketContext`].
    ///
    /// `IpSocketContext` is implemented for any `DummyCtx<S>` where `S`
    /// implements `AsRef` and `AsMut` for `DummyIpSocketCtx`.
    pub(crate) struct DummyIpSocketCtx<I: IpDeviceStateIpExt<DummyInstant>, D> {
        pub(crate) table: ForwardingTable<I, D>,
        device_state: HashMap<D, IpDeviceState<DummyInstant, I>>,
    }

    impl<
            I: IpDeviceStateIpExt<DummyInstant>,
            S: AsRef<DummyIpSocketCtx<I, DeviceId>> + AsMut<DummyIpSocketCtx<I, DeviceId>>,
            Id,
            Meta,
            Event: Debug,
            DeviceId: IpDeviceId + 'static,
            NonSyncCtxState,
        > IpSocketContext<I, DummyNonSyncCtx<Id, Event, NonSyncCtxState>>
        for DummySyncCtx<S, Meta, DeviceId>
    {
        fn lookup_route(
            &self,
            _ctx: &mut DummyNonSyncCtx<Id, Event, NonSyncCtxState>,
            device: Option<Self::DeviceId>,
            local_ip: Option<SpecifiedAddr<I::Addr>>,
            addr: SpecifiedAddr<I::Addr>,
        ) -> Result<IpSockRoute<I, Self::DeviceId>, IpSockRouteError> {
            let destination = self
                .get_ref()
                .as_ref()
                .table
                .lookup(device, addr)
                .ok_or(IpSockUnroutableError::NoRouteToRemoteAddr)?;

            let Destination { device, next_hop: _ } = &destination;
            local_ip
                .map_or_else(
                    || {
                        self.get_ref()
                            .as_ref()
                            .device_state
                            .get(&device)
                            .unwrap()
                            .iter_addrs()
                            .map(|e| e.addr())
                            .next()
                            .ok_or(IpSockRouteError::NoLocalAddrAvailable)
                    },
                    |local_ip| {
                        self.get_ref()
                            .as_ref()
                            .device_state
                            .get(&device)
                            .unwrap()
                            .iter_addrs()
                            .any(|e| e.addr() == local_ip)
                            .then(|| local_ip)
                            .ok_or(IpSockUnroutableError::LocalAddrNotAssigned.into())
                    },
                )
                .map(|local_ip| IpSockRoute { local_ip, destination })
        }
    }

    impl<
            I: IpDeviceStateIpExt<DummyInstant> + packet_formats::ip::IpExt,
            B: BufferMut,
            S: AsRef<DummyIpSocketCtx<I, DeviceId>> + AsMut<DummyIpSocketCtx<I, DeviceId>>,
            Id,
            Meta,
            Event: Debug,
            DeviceId,
            NonSyncCtxState,
        > BufferIpSocketContext<I, DummyNonSyncCtx<Id, Event, NonSyncCtxState>, B>
        for DummySyncCtx<S, Meta, DeviceId>
    where
        DummySyncCtx<S, Meta, DeviceId>: FrameContext<
                DummyNonSyncCtx<Id, Event, NonSyncCtxState>,
                B,
                SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>,
            > + IpSocketContext<I, DummyNonSyncCtx<Id, Event, NonSyncCtxState>>,
    {
        fn send_ip_packet<SS: Serializer<Buffer = B>>(
            &mut self,
            ctx: &mut DummyNonSyncCtx<Id, Event, NonSyncCtxState>,
            meta: SendIpPacketMeta<I, Self::DeviceId, SpecifiedAddr<I::Addr>>,
            body: SS,
        ) -> Result<(), SS> {
            self.send_frame(ctx, meta, body)
        }
    }

    impl<I: IpDeviceStateIpExt<DummyInstant>, D: IpDeviceId> DummyIpSocketCtx<I, D> {
        pub(crate) fn with_devices_state(
            devices: impl IntoIterator<
                Item = (D, IpDeviceState<DummyInstant, I>, Vec<SpecifiedAddr<I::Addr>>),
            >,
        ) -> Self {
            let mut table = ForwardingTable::default();
            let mut device_state = HashMap::default();
            for (device, state, addrs) in devices {
                for ip in addrs {
                    assert_eq!(
                        table.add_device_route(
                            Subnet::new(ip.get(), <I::Addr as IpAddress>::BYTES * 8).unwrap(),
                            device,
                        ),
                        Ok(())
                    );
                }
                assert!(
                    device_state.insert(device, state).is_none(),
                    "duplicate entries for {}",
                    device
                );
            }

            DummyIpSocketCtx { table, device_state }
        }

        pub(crate) fn find_device_with_addr(&self, addr: SpecifiedAddr<I::Addr>) -> Option<D> {
            let Self { table: _, device_state } = self;
            device_state.iter().find_map(|(device, state)| {
                state.find_addr(&addr).map(|_: &I::AssignedAddress| *device)
            })
        }
    }

    pub(crate) struct DummyDeviceConfig<D, A: IpAddress> {
        pub(crate) device: D,
        pub(crate) local_ips: Vec<SpecifiedAddr<A>>,
        pub(crate) remote_ips: Vec<SpecifiedAddr<A>>,
    }

    impl<D: IpDeviceId> DummyIpSocketCtx<Ipv4, D> {
        /// Creates a new `DummyIpSocketCtx<Ipv4>` with the given device
        /// configs.
        pub(crate) fn new_ipv4(
            devices: impl IntoIterator<Item = DummyDeviceConfig<D, Ipv4Addr>>,
        ) -> Self {
            DummyIpSocketCtx::with_devices_state(devices.into_iter().map(
                |DummyDeviceConfig { device, local_ips, remote_ips }| {
                    let mut device_state = IpDeviceState::default();
                    for ip in local_ips {
                        // Users of this utility don't care about subnet prefix length,
                        // so just pick a reasonable one.
                        device_state
                            .add_addr(AddrSubnet::new(ip.get(), 32).unwrap())
                            .expect("add address");
                    }
                    (device, device_state, remote_ips)
                },
            ))
        }
    }

    impl DummyIpSocketCtx<Ipv4, DummyDeviceId> {
        /// Creates a new `DummyIpSocketCtx<Ipv4>`.
        pub(crate) fn new_dummy_ipv4(
            local_ips: Vec<SpecifiedAddr<Ipv4Addr>>,
            remote_ips: Vec<SpecifiedAddr<Ipv4Addr>>,
        ) -> Self {
            Self::new_ipv4([DummyDeviceConfig { device: DummyDeviceId, local_ips, remote_ips }])
        }
    }

    impl<D: IpDeviceId> DummyIpSocketCtx<Ipv6, D> {
        /// Creates a new `DummyIpSocketCtx<Ipv6>` with the given device
        /// configs.
        pub(crate) fn new_ipv6(
            devices: impl IntoIterator<Item = DummyDeviceConfig<D, Ipv6Addr>>,
        ) -> Self {
            DummyIpSocketCtx::with_devices_state(devices.into_iter().map(
                |DummyDeviceConfig { device, local_ips, remote_ips }| {
                    let mut device_state = IpDeviceState::default();
                    for ip in local_ips {
                        // Users of this utility don't care about subnet prefix length,
                        // so just pick a reasonable one.
                        device_state
                            .add_addr(Ipv6AddressEntry::new(
                                // Users of this utility don't care about subnet prefix
                                // length, so just pick a reasonable one.
                                AddrSubnet::new(ip.get(), 128).unwrap(),
                                AddressState::Assigned,
                                AddrConfig::Manual,
                            ))
                            .expect("add address");
                    }
                    (device, device_state, remote_ips)
                },
            ))
        }
    }

    impl DummyIpSocketCtx<Ipv6, DummyDeviceId> {
        /// Creates a new `DummyIpSocketCtx<Ipv6>`.
        pub(crate) fn new_dummy_ipv6(
            local_ips: Vec<SpecifiedAddr<Ipv6Addr>>,
            remote_ips: Vec<SpecifiedAddr<Ipv6Addr>>,
        ) -> Self {
            Self::new_ipv6([DummyDeviceConfig { device: DummyDeviceId, local_ips, remote_ips }])
        }
    }
}

#[cfg(test)]
mod tests {
    use net_types::{
        ip::{AddrSubnet, SubnetEither},
        Witness,
    };
    use packet::{Buf, InnerPacketBuilder, ParseBuffer};
    use packet_formats::{
        ip::IpPacket,
        ipv4::{Ipv4OnlyMeta, Ipv4Packet, Ipv4PacketBuilder},
        ipv6::Ipv6PacketBuilder,
        testutil::{parse_ethernet_frame, parse_ip_packet_in_ethernet_frame},
    };
    use specialize_ip_macro::{ip_test, specialize_ip};

    use super::*;
    use crate::{device::DeviceId, testutil::*, Ctx};

    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>,
    }

    #[specialize_ip]
    fn test_new<I: Ip>(test_case: NewSocketTestCase) {
        #[ipv4]
        let (cfg, proto) = (DUMMY_CONFIG_V4, Ipv4Proto::Icmp);

        #[ipv6]
        let (cfg, proto) = (DUMMY_CONFIG_V6, Ipv6Proto::Icmpv6);

        let DummyEventDispatcherConfig { local_ip, remote_ip, subnet, local_mac: _, remote_mac: _ } =
            cfg;
        let Ctx { mut sync_ctx, mut non_sync_ctx } =
            DummyEventDispatcherBuilder::from_config(cfg).build();
        let loopback_device_id = crate::add_loopback_device(&mut sync_ctx, u16::MAX.into())
            .expect("create the loopback interface");
        crate::device::testutil::enable_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            loopback_device_id,
        );

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

        #[ipv4]
        let remove_all_local_addrs =
            |sync_ctx: &mut crate::testutil::DummySyncCtx,
             ctx: &mut crate::testutil::DummyNonSyncCtx| {
                let devices = crate::ip::device::iter_ipv4_devices(sync_ctx)
                    .map(|(device, _state)| device)
                    .collect::<Vec<_>>();
                for device in devices {
                    let subnets =
                        crate::ip::device::get_assigned_ipv4_addr_subnets(sync_ctx, device)
                            .collect::<Vec<_>>();
                    for subnet in subnets {
                        crate::device::del_ip_addr(sync_ctx, ctx, device, &subnet.addr())
                            .expect("failed to remove addr from device");
                    }
                }
            };

        #[ipv6]
        let remove_all_local_addrs =
            |sync_ctx: &mut crate::testutil::DummySyncCtx,
             ctx: &mut crate::testutil::DummyNonSyncCtx| {
                let devices = crate::ip::device::iter_ipv6_devices(sync_ctx)
                    .map(|(device, _state)| device)
                    .collect::<Vec<_>>();
                for device in devices {
                    let subnets =
                        crate::ip::device::get_assigned_ipv6_addr_subnets(sync_ctx, device)
                            .collect::<Vec<_>>();
                    for subnet in subnets {
                        crate::device::del_ip_addr(sync_ctx, ctx, device, &subnet.addr())
                            .expect("failed to remove addr from device");
                    }
                }
            };

        const LOCAL_DEVICE: DeviceId = DeviceId::new_ethernet(0);
        const OTHER_DEVICE: DeviceId = DeviceId::new_ethernet(1);
        let local_device = match device_type {
            DeviceType::Unspecified => None,
            DeviceType::LocalDevice => Some(LOCAL_DEVICE),
            DeviceType::OtherDevice => Some(OTHER_DEVICE),
        };

        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(&mut sync_ctx, &mut non_sync_ctx);
                }
                (local_ip, None)
            }
            AddressType::Unroutable => {
                remove_all_local_addrs(&mut sync_ctx, &mut non_sync_ctx);
                (local_ip, Some(local_ip))
            }
        };

        let (to_ip, device) = match remote_ip_type {
            AddressType::LocallyOwned => (
                local_ip,
                IpDeviceIdContext::<I>::loopback_id(&sync_ctx)
                    .expect("local test should have loopback device"),
            ),
            AddressType::Remote => (remote_ip, LOCAL_DEVICE),
            AddressType::Unspecified { can_select: _ } => {
                panic!("remote_ip_type cannot be unspecified")
            }
            AddressType::Unroutable => {
                match subnet.into() {
                    SubnetEither::V4(subnet) => {
                        crate::ip::del_route::<Ipv4, _, _>(&mut sync_ctx, &mut non_sync_ctx, subnet)
                            .expect("failed to delete IPv4 device route")
                    }
                    SubnetEither::V6(subnet) => {
                        crate::ip::del_route::<Ipv6, _, _>(&mut sync_ctx, &mut non_sync_ctx, subnet)
                            .expect("failed to delete IPv6 device route")
                    }
                }

                (remote_ip, LOCAL_DEVICE)
            }
        };

        #[ipv4]
        let builder = Ipv4PacketBuilder::new(
            expected_from_ip,
            to_ip,
            crate::ip::DEFAULT_TTL.get(),
            Ipv4Proto::Icmp,
        );

        #[ipv6]
        let builder = Ipv6PacketBuilder::new(
            expected_from_ip,
            to_ip,
            crate::ip::DEFAULT_TTL.get(),
            Ipv6Proto::Icmpv6,
        );

        let get_expected_result = |template| expected_result.map(|()| template);

        let template = IpSock {
            defn: IpSockDefinition {
                remote_ip: to_ip,
                local_ip: expected_from_ip,
                device: local_device,
                proto,
                hop_limit: None,
            },
        };

        let res = IpSocketHandler::<I, _>::new_ip_socket(
            &mut sync_ctx,
            &mut non_sync_ctx,
            local_device,
            from_ip,
            to_ip,
            proto,
            None,
        );
        assert_eq!(res, get_expected_result(template.clone()));

        #[ipv4]
        {
            // TTL is specified.
            let mut builder = Ipv4SocketBuilder::default();
            let _: &mut Ipv4SocketBuilder = builder.ttl(NonZeroU8::new(1).unwrap());
            assert_eq!(
                IpSocketHandler::<Ipv4, _>::new_ip_socket(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    local_device,
                    from_ip,
                    to_ip,
                    proto,
                    Some(builder),
                ),
                {
                    // The template socket, but with the TTL set to 1.
                    let mut x = template.clone();
                    let IpSock::<Ipv4, DeviceId> { defn } = &mut x;
                    defn.hop_limit = NonZeroU8::new(1);
                    get_expected_result(x)
                }
            );
        }

        #[ipv6]
        {
            // Hop Limit is specified.
            const SPECIFIED_HOP_LIMIT: u8 = 1;
            let mut builder = Ipv6SocketBuilder::default();
            let _: &mut Ipv6SocketBuilder =
                builder.hop_limit(NonZeroU8::new(SPECIFIED_HOP_LIMIT).unwrap());
            assert_eq!(
                IpSocketHandler::<Ipv6, _>::new_ip_socket(
                    &mut sync_ctx,
                    &mut non_sync_ctx,
                    local_device,
                    from_ip,
                    to_ip,
                    proto,
                    Some(builder),
                ),
                {
                    let mut template_with_hop_limit = template.clone();
                    let IpSock::<Ipv6, DeviceId> { defn } = &mut template_with_hop_limit;
                    defn.hop_limit = NonZeroU8::new(SPECIFIED_HOP_LIMIT);
                    let builder =
                        Ipv6PacketBuilder::new(expected_from_ip, to_ip, SPECIFIED_HOP_LIMIT, proto);
                    get_expected_result(template_with_hop_limit)
                }
            );
        }
    }

    #[ip_test]
    fn test_new_unroutable_local_to_remote<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unroutable,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(IpSockRouteError::Unroutable(
                IpSockUnroutableError::LocalAddrNotAssigned,
            )
            .into()),
        });
    }

    #[ip_test]
    fn test_new_local_to_unroutable_remote<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::Unroutable,
            device_type: DeviceType::Unspecified,
            expected_result: Err(IpSockRouteError::Unroutable(
                IpSockUnroutableError::NoRouteToRemoteAddr,
            )
            .into()),
        });
    }

    #[ip_test]
    fn test_new_local_to_remote<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        });
    }

    #[ip_test]
    fn test_new_unspecified_to_remote<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        });
    }

    #[ip_test]
    fn test_new_unspecified_to_remote_through_local_device<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::LocalDevice,
            expected_result: Ok(()),
        });
    }

    #[ip_test]
    fn test_new_unspecified_to_remote_through_other_device<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::OtherDevice,
            expected_result: Err(IpSockRouteError::Unroutable(
                IpSockUnroutableError::NoRouteToRemoteAddr,
            )
            .into()),
        });
    }

    #[ip_test]
    fn test_new_unspecified_to_remote_cant_select<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: false },
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(IpSockRouteError::NoLocalAddrAvailable.into()),
        });
    }

    #[ip_test]
    fn test_new_remote_to_remote<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Remote,
            remote_ip_type: AddressType::Remote,
            device_type: DeviceType::Unspecified,
            expected_result: Err(IpSockRouteError::Unroutable(
                IpSockUnroutableError::LocalAddrNotAssigned,
            )
            .into()),
        });
    }

    #[ip_test]
    fn test_new_local_to_local<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::LocallyOwned,
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        });
    }

    #[ip_test]
    fn test_new_unspecified_to_local<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Unspecified { can_select: true },
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Ok(()),
        });
    }

    #[ip_test]
    fn test_new_remote_to_local<I: Ip>() {
        test_new::<I>(NewSocketTestCase {
            local_ip_type: AddressType::Remote,
            remote_ip_type: AddressType::LocallyOwned,
            device_type: DeviceType::Unspecified,
            expected_result: Err(IpSockRouteError::Unroutable(
                IpSockUnroutableError::LocalAddrNotAssigned,
            )
            .into()),
        });
    }

    #[specialize_ip]
    fn test_send_local<I: Ip>(from_addr_type: AddressType, to_addr_type: AddressType) {
        set_logger_for_test();

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

        #[ipv4]
        let (subnet, local_ip, remote_ip, local_mac, proto, socket_builder) = {
            let DummyEventDispatcherConfig::<Ipv4Addr> {
                subnet,
                local_ip,
                remote_ip,
                local_mac,
                remote_mac: _,
            } = DUMMY_CONFIG_V4;

            (subnet, local_ip, remote_ip, local_mac, Ipv4Proto::Icmp, Ipv4SocketBuilder::default())
        };

        #[ipv6]
        let (subnet, local_ip, remote_ip, local_mac, proto, socket_builder) = {
            let DummyEventDispatcherConfig::<Ipv6Addr> {
                subnet,
                local_ip,
                remote_ip,
                local_mac,
                remote_mac: _,
            } = DUMMY_CONFIG_V6;

            (
                subnet,
                local_ip,
                remote_ip,
                local_mac,
                Ipv6Proto::Icmpv6,
                Ipv6SocketBuilder::default(),
            )
        };

        let mut builder = DummyEventDispatcherBuilder::default();
        let device_id = DeviceId::new_ethernet(builder.add_device(local_mac));
        let Ctx { mut sync_ctx, mut non_sync_ctx } = builder.build();
        crate::device::add_ip_addr_subnet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device_id,
            AddrSubnet::new(local_ip.get(), 16).unwrap(),
        )
        .unwrap();
        crate::device::add_ip_addr_subnet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            device_id,
            AddrSubnet::new(remote_ip.get(), 16).unwrap(),
        )
        .unwrap();
        match subnet.into() {
            SubnetEither::V4(subnet) => crate::ip::add_device_route::<Ipv4, _, _>(
                &mut sync_ctx,
                &mut non_sync_ctx,
                subnet,
                device_id,
            )
            .expect("install IPv4 device route on a fresh stack without routes"),
            SubnetEither::V6(subnet) => crate::ip::add_device_route::<Ipv6, _, _>(
                &mut sync_ctx,
                &mut non_sync_ctx,
                subnet,
                device_id,
            )
            .expect("install IPv6 device route on a fresh stack without routes"),
        }

        let loopback_device_id = crate::add_loopback_device(&mut sync_ctx, u16::MAX.into())
            .expect("create the loopback interface");
        crate::device::testutil::enable_device(
            &mut sync_ctx,
            &mut non_sync_ctx,
            loopback_device_id,
        );

        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 sync_ctx,
            &mut non_sync_ctx,
            None,
            from_ip,
            to_ip,
            proto,
            Some(socket_builder),
        )
        .unwrap();

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

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

        assert_eq!(non_sync_ctx.frames_sent().len(), 0);

        #[ipv4]
        assert_eq!(get_counter_val(&non_sync_ctx, "dispatch_receive_ipv4_packet"), 1);

        #[ipv6]
        assert_eq!(get_counter_val(&non_sync_ctx, "dispatch_receive_ipv6_packet"), 1);
    }

    #[ip_test]
    fn test_send_local_to_local<I: Ip>() {
        test_send_local::<I>(AddressType::LocallyOwned, AddressType::LocallyOwned);
    }

    #[ip_test]
    fn test_send_unspecified_to_local<I: Ip>() {
        test_send_local::<I>(
            AddressType::Unspecified { can_select: true },
            AddressType::LocallyOwned,
        );
    }

    #[ip_test]
    fn test_send_local_to_remote<I: Ip>() {
        test_send_local::<I>(AddressType::LocallyOwned, AddressType::Remote);
    }

    #[ip_test]
    #[specialize_ip]
    fn test_send<I: Ip>() {
        // Test various edge cases of the
        // `BufferIpSocketContext::send_ip_packet` method.

        #[ipv4]
        let (cfg, socket_builder, proto) = {
            let mut builder = Ipv4SocketBuilder::default();
            let _: &mut Ipv4SocketBuilder = builder.ttl(NonZeroU8::new(1).unwrap());
            (DUMMY_CONFIG_V4, builder, Ipv4Proto::Icmp)
        };

        #[ipv6]
        let (cfg, socket_builder, proto) = {
            let mut builder = Ipv6SocketBuilder::default();
            let _: &mut Ipv6SocketBuilder = builder.hop_limit(NonZeroU8::new(1).unwrap());
            (DUMMY_CONFIG_V6, builder, Ipv6Proto::Icmpv6)
        };

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

        let Ctx { mut sync_ctx, mut non_sync_ctx } =
            DummyEventDispatcherBuilder::from_config(cfg.clone()).build();

        // Create a normal, routable socket.
        let sock = IpSocketHandler::<I, _>::new_ip_socket(
            &mut sync_ctx,
            &mut non_sync_ctx,
            None,
            None,
            remote_ip,
            proto,
            Some(socket_builder),
        )
        .unwrap();

        #[ipv4]
        let curr_id = crate::ip::gen_ipv4_packet_id(&mut sync_ctx);

        #[ipv4]
        let check_frame = move |frame: &[u8], packet_count| {
            let (mut body, src_mac, dst_mac, _ethertype) = parse_ethernet_frame(frame).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.get());
            assert_eq!(packet.dst_ip(), remote_ip.get());
            assert_eq!(packet.proto(), 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]);
        };

        #[ipv6]
        let check_frame = move |frame: &[u8], _packet_count| {
            let (body, src_mac, dst_mac, src_ip, dst_ip, ip_proto, ttl) =
                parse_ip_packet_in_ethernet_frame::<Ipv6>(frame).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.get());
            assert_eq!(dst_ip, remote_ip.get());
            assert_eq!(ip_proto, proto);
            assert_eq!(ttl, 1);
        };
        let mut packet_count = 0;
        assert_eq!(non_sync_ctx.frames_sent().len(), packet_count);

        // Send a packet on the socket and make sure that the right contents
        // are sent.
        BufferIpSocketHandler::<I, _, _>::send_ip_packet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            &sock,
            (&[0u8][..]).into_serializer(),
            None,
        )
        .unwrap();
        let mut check_sent_frame = |non_sync_ctx: &crate::testutil::DummyNonSyncCtx| {
            packet_count += 1;
            assert_eq!(non_sync_ctx.frames_sent().len(), packet_count);
            let (dev, frame) = &non_sync_ctx.frames_sent()[packet_count - 1];
            assert_eq!(dev, &DeviceId::new_ethernet(0));
            check_frame(&frame, packet_count);
        };
        check_sent_frame(&non_sync_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 = BufferIpSocketHandler::<I, _, _>::send_ip_packet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            &sock,
            small_body_serializer,
            Some(Ipv6::MINIMUM_LINK_MTU.into()),
        );
        assert_matches::assert_matches!(res, Ok(()));
        check_sent_frame(&non_sync_ctx);

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

        assert_eq!(non_sync_ctx.frames_sent().len(), packet_count);
        // Try sending a packet which will be larger than the device's MTU,
        // and make sure it fails.
        let res = BufferIpSocketHandler::<I, _, _>::send_ip_packet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            &sock,
            (&[0; crate::ip::Ipv6::MINIMUM_LINK_MTU as usize][..]).into_serializer(),
            None,
        );
        assert_matches::assert_matches!(res, Err((_, IpSockSendError::Mtu)));

        // Make sure that sending on an unroutable socket fails.
        crate::ip::del_route::<I, _, _>(&mut sync_ctx, &mut non_sync_ctx, subnet).unwrap();
        let res = BufferIpSocketHandler::<I, _, _>::send_ip_packet(
            &mut sync_ctx,
            &mut non_sync_ctx,
            &sock,
            small_body_serializer,
            None,
        );
        assert_matches::assert_matches!(
            res,
            Err((_, IpSockSendError::Unroutable(IpSockUnroutableError::NoRouteToRemoteAddr)))
        );
    }
}
