netstack3_base/device/
address.rsuse core::fmt::{Debug, Display};
use core::hash::Hash;
use net_types::ip::{
AddrSubnet, GenericOverIp, Ip, IpAddress, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr,
};
use net_types::{NonMappedAddr, NonMulticastAddr, SpecifiedAddr, UnicastAddr, Witness};
use crate::device::{AnyDevice, DeviceIdContext};
use crate::socket::SocketIpAddr;
pub trait AssignedAddrIpExt: Ip {
type AssignedWitness: Witness<Self::Addr>
+ Copy
+ Eq
+ PartialEq
+ Debug
+ Display
+ Hash
+ Send
+ Sync
+ Into<SpecifiedAddr<Self::Addr>>;
}
impl AssignedAddrIpExt for Ipv4 {
type AssignedWitness = Ipv4DeviceAddr;
}
impl AssignedAddrIpExt for Ipv6 {
type AssignedWitness = Ipv6DeviceAddr;
}
pub trait WeakIpAddressId<A: IpAddress>: Clone + Eq + Debug + Hash + Send + Sync + 'static {
type Strong: IpAddressId<A>;
fn upgrade(&self) -> Option<Self::Strong>;
}
pub trait IpAddressId<A: IpAddress>: Clone + Eq + Debug + Hash {
type Weak: WeakIpAddressId<A>;
fn downgrade(&self) -> Self::Weak;
fn addr(&self) -> IpDeviceAddr<A>;
fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
where
A::Version: AssignedAddrIpExt;
}
pub trait IpDeviceAddressIdContext<I: Ip>: DeviceIdContext<AnyDevice> {
type AddressId: IpAddressId<I::Addr, Weak = Self::WeakAddressId>;
type WeakAddressId: WeakIpAddressId<I::Addr, Strong = Self::AddressId>;
}
#[derive(Copy, Clone, Debug, Eq, GenericOverIp, Hash, PartialEq)]
#[generic_over_ip(A, IpAddress)]
pub struct IpDeviceAddr<A: IpAddress>(NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>);
impl<A: IpAddress> Display for IpDeviceAddr<A> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Self(addr) = self;
write!(f, "{}", addr)
}
}
impl<A: IpAddress> IpDeviceAddr<A> {
pub fn addr(self) -> A {
let Self(addr) = self;
***addr
}
pub fn into_inner(self) -> NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>> {
let IpDeviceAddr(addr) = self;
addr
}
pub fn new(addr: A) -> Option<IpDeviceAddr<A>> {
Some(IpDeviceAddr(NonMulticastAddr::new(NonMappedAddr::new(SpecifiedAddr::new(addr)?)?)?))
}
pub fn new_from_witness(addr: NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>) -> Self {
Self(addr)
}
pub fn new_from_socket_ip_addr(addr: SocketIpAddr<A>) -> Option<Self> {
NonMulticastAddr::new(addr.into_inner()).map(Self)
}
}
impl IpDeviceAddr<Ipv6Addr> {
pub fn new_from_ipv6_device_addr(addr: Ipv6DeviceAddr) -> Self {
let addr: UnicastAddr<NonMappedAddr<Ipv6Addr>> = addr.transpose();
let addr: NonMappedAddr<SpecifiedAddr<Ipv6Addr>> = addr.into_specified().transpose();
let addr = unsafe { NonMulticastAddr::new_unchecked(addr) };
Self(addr)
}
pub fn new_from_ipv6_source(addr: Ipv6SourceAddr) -> Option<Self> {
match addr {
Ipv6SourceAddr::Unicast(addr) => Some(Self::new_from_ipv6_device_addr(addr)),
Ipv6SourceAddr::Unspecified => None,
}
}
}
impl<A: IpAddress> From<IpDeviceAddr<A>> for SpecifiedAddr<A> {
fn from(addr: IpDeviceAddr<A>) -> Self {
**addr.into_inner()
}
}
impl<A: IpAddress> AsRef<SpecifiedAddr<A>> for IpDeviceAddr<A> {
fn as_ref(&self) -> &SpecifiedAddr<A> {
let Self(addr) = self;
addr.as_ref()
}
}
impl<A: IpAddress> From<IpDeviceAddr<A>> for SocketIpAddr<A> {
fn from(addr: IpDeviceAddr<A>) -> Self {
SocketIpAddr::new_from_witness(*addr.into_inner())
}
}
#[derive(Debug)]
pub enum IpDeviceAddrError {
NotNonMapped,
NotNonMulticast,
}
impl<A: IpAddress> TryFrom<SpecifiedAddr<A>> for IpDeviceAddr<A> {
type Error = IpDeviceAddrError;
fn try_from(addr: SpecifiedAddr<A>) -> Result<Self, Self::Error> {
Ok(IpDeviceAddr::new_from_witness(
NonMulticastAddr::new(NonMappedAddr::new(addr).ok_or(IpDeviceAddrError::NotNonMapped)?)
.ok_or(IpDeviceAddrError::NotNonMulticast)?,
))
}
}
pub type Ipv4DeviceAddr = NonMulticastAddr<NonMappedAddr<SpecifiedAddr<Ipv4Addr>>>;
pub type Ipv6DeviceAddr = NonMappedAddr<UnicastAddr<Ipv6Addr>>;
#[cfg(any(test, feature = "testutils"))]
pub mod testutil {
use net_types::ip::GenericOverIp;
use super::*;
use crate::testutil::FakeCoreCtx;
use crate::StrongDeviceIdentifier;
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct FakeWeakAddressId<T>(pub T);
impl<A: IpAddress, T: IpAddressId<A> + Send + Sync + 'static> WeakIpAddressId<A>
for FakeWeakAddressId<T>
{
type Strong = T;
fn upgrade(&self) -> Option<Self::Strong> {
let Self(inner) = self;
Some(inner.clone())
}
}
impl<A: IpAddress> IpAddressId<A>
for AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
where
A::Version: AssignedAddrIpExt,
{
type Weak = FakeWeakAddressId<Self>;
fn downgrade(&self) -> Self::Weak {
FakeWeakAddressId(self.clone())
}
fn addr(&self) -> IpDeviceAddr<A> {
#[derive(GenericOverIp)]
#[generic_over_ip(I, Ip)]
struct WrapIn<I: AssignedAddrIpExt>(I::AssignedWitness);
A::Version::map_ip(
WrapIn(self.addr()),
|WrapIn(v4_addr)| IpDeviceAddr::new_from_witness(v4_addr),
|WrapIn(v6_addr)| IpDeviceAddr::new_from_ipv6_device_addr(v6_addr),
)
}
fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness> {
self.clone()
}
}
impl<I: AssignedAddrIpExt, S, Meta, DeviceId: StrongDeviceIdentifier>
IpDeviceAddressIdContext<I> for FakeCoreCtx<S, Meta, DeviceId>
{
type AddressId = AddrSubnet<I::Addr, I::AssignedWitness>;
type WeakAddressId = FakeWeakAddressId<Self::AddressId>;
}
}