netstack3_base/device/
address.rs
1use core::fmt::{Debug, Display};
8use core::hash::Hash;
9
10use net_types::ip::{
11 AddrSubnet, GenericOverIp, Ip, IpAddress, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Ipv6SourceAddr,
12};
13use net_types::{NonMappedAddr, NonMulticastAddr, SpecifiedAddr, UnicastAddr, Witness};
14
15use crate::device::{AnyDevice, DeviceIdContext};
16use crate::inspect::InspectableValue;
17use crate::socket::SocketIpAddr;
18
19pub trait AssignedAddrIpExt: Ip {
22 type AssignedWitness: Witness<Self::Addr>
24 + Copy
25 + Eq
26 + PartialEq
27 + Debug
28 + Display
29 + Hash
30 + Send
31 + Sync
32 + Into<SpecifiedAddr<Self::Addr>>;
33}
34
35impl AssignedAddrIpExt for Ipv4 {
36 type AssignedWitness = Ipv4DeviceAddr;
37}
38
39impl AssignedAddrIpExt for Ipv6 {
40 type AssignedWitness = Ipv6DeviceAddr;
41}
42
43pub trait WeakIpAddressId<A: IpAddress>:
45 Clone + Eq + Debug + Hash + Send + Sync + InspectableValue + 'static
46{
47 type Strong: IpAddressId<A>;
49
50 fn upgrade(&self) -> Option<Self::Strong>;
54
55 fn is_assigned(&self) -> bool;
57}
58
59pub trait IpAddressId<A: IpAddress>: Clone + Eq + Debug + Hash {
61 type Weak: WeakIpAddressId<A>;
63
64 fn downgrade(&self) -> Self::Weak;
66
67 fn addr(&self) -> IpDeviceAddr<A>;
73
74 fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
76 where
77 A::Version: AssignedAddrIpExt;
78}
79
80pub trait IpDeviceAddressIdContext<I: Ip>: DeviceIdContext<AnyDevice> {
82 type AddressId: IpAddressId<I::Addr, Weak = Self::WeakAddressId>;
84 type WeakAddressId: WeakIpAddressId<I::Addr, Strong = Self::AddressId>;
86}
87
88#[derive(Copy, Clone, Debug, Eq, GenericOverIp, Hash, PartialEq)]
90#[generic_over_ip(A, IpAddress)]
91pub struct IpDeviceAddr<A: IpAddress>(NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>);
92
93impl<A: IpAddress> Display for IpDeviceAddr<A> {
94 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95 let Self(addr) = self;
96 write!(f, "{}", addr)
97 }
98}
99
100impl<A: IpAddress> IpDeviceAddr<A> {
101 pub fn addr(self) -> A {
103 let Self(addr) = self;
104 ***addr
105 }
106
107 pub fn into_inner(self) -> NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>> {
109 let IpDeviceAddr(addr) = self;
110 addr
111 }
112
113 pub fn new(addr: A) -> Option<IpDeviceAddr<A>> {
115 Some(IpDeviceAddr(NonMulticastAddr::new(NonMappedAddr::new(SpecifiedAddr::new(addr)?)?)?))
116 }
117
118 pub fn new_from_witness(addr: NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>) -> Self {
120 Self(addr)
121 }
122
123 pub fn new_from_socket_ip_addr(addr: SocketIpAddr<A>) -> Option<Self> {
125 NonMulticastAddr::new(addr.into_inner()).map(Self)
126 }
127}
128
129impl IpDeviceAddr<Ipv6Addr> {
130 pub fn new_from_ipv6_device_addr(addr: Ipv6DeviceAddr) -> Self {
132 let addr: UnicastAddr<NonMappedAddr<Ipv6Addr>> = addr.transpose();
133 let addr: NonMappedAddr<SpecifiedAddr<Ipv6Addr>> = addr.into_specified().transpose();
134 let addr = unsafe { NonMulticastAddr::new_unchecked(addr) };
137 Self(addr)
138 }
139
140 pub fn new_from_ipv6_source(addr: Ipv6SourceAddr) -> Option<Self> {
142 match addr {
143 Ipv6SourceAddr::Unicast(addr) => Some(Self::new_from_ipv6_device_addr(addr)),
144 Ipv6SourceAddr::Unspecified => None,
145 }
146 }
147}
148
149impl<A: IpAddress> From<IpDeviceAddr<A>> for SpecifiedAddr<A> {
150 fn from(addr: IpDeviceAddr<A>) -> Self {
151 **addr.into_inner()
152 }
153}
154
155impl<A: IpAddress> AsRef<SpecifiedAddr<A>> for IpDeviceAddr<A> {
156 fn as_ref(&self) -> &SpecifiedAddr<A> {
157 let Self(addr) = self;
158 addr.as_ref()
159 }
160}
161
162impl<A: IpAddress> From<IpDeviceAddr<A>> for SocketIpAddr<A> {
163 fn from(addr: IpDeviceAddr<A>) -> Self {
164 SocketIpAddr::new_from_witness(*addr.into_inner())
165 }
166}
167
168#[derive(Debug)]
169pub enum IpDeviceAddrError {
170 NotNonMapped,
171 NotNonMulticast,
172}
173
174impl<A: IpAddress> TryFrom<SpecifiedAddr<A>> for IpDeviceAddr<A> {
175 type Error = IpDeviceAddrError;
176 fn try_from(addr: SpecifiedAddr<A>) -> Result<Self, Self::Error> {
177 Ok(IpDeviceAddr::new_from_witness(
178 NonMulticastAddr::new(NonMappedAddr::new(addr).ok_or(IpDeviceAddrError::NotNonMapped)?)
179 .ok_or(IpDeviceAddrError::NotNonMulticast)?,
180 ))
181 }
182}
183
184pub type Ipv4DeviceAddr = NonMulticastAddr<NonMappedAddr<SpecifiedAddr<Ipv4Addr>>>;
192
193pub type Ipv6DeviceAddr = NonMappedAddr<UnicastAddr<Ipv6Addr>>;
198
199#[cfg(any(test, feature = "testutils"))]
200pub mod testutil {
201 use net_types::ip::GenericOverIp;
202
203 use super::*;
204 use crate::inspect::Inspector;
205 use crate::testutil::FakeCoreCtx;
206 use crate::StrongDeviceIdentifier;
207
208 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
210 pub struct FakeWeakAddressId<T>(pub T);
211
212 impl<A: IpAddress, T: IpAddressId<A> + Send + Sync + 'static> WeakIpAddressId<A>
213 for FakeWeakAddressId<T>
214 {
215 type Strong = T;
216
217 fn upgrade(&self) -> Option<Self::Strong> {
218 let Self(inner) = self;
219 Some(inner.clone())
220 }
221
222 fn is_assigned(&self) -> bool {
223 true
224 }
225 }
226
227 impl<T> InspectableValue for FakeWeakAddressId<T> {
228 fn record<I: Inspector>(&self, _name: &str, _inspector: &mut I) {
229 unimplemented!()
230 }
231 }
232
233 impl<A: IpAddress> IpAddressId<A>
234 for AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
235 where
236 A::Version: AssignedAddrIpExt,
237 {
238 type Weak = FakeWeakAddressId<Self>;
239
240 fn downgrade(&self) -> Self::Weak {
241 FakeWeakAddressId(self.clone())
242 }
243
244 fn addr(&self) -> IpDeviceAddr<A> {
245 #[derive(GenericOverIp)]
246 #[generic_over_ip(I, Ip)]
247 struct WrapIn<I: AssignedAddrIpExt>(I::AssignedWitness);
248 A::Version::map_ip(
249 WrapIn(self.addr()),
250 |WrapIn(v4_addr)| IpDeviceAddr::new_from_witness(v4_addr),
251 |WrapIn(v6_addr)| IpDeviceAddr::new_from_ipv6_device_addr(v6_addr),
252 )
253 }
254
255 fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness> {
256 self.clone()
257 }
258 }
259
260 impl<I: AssignedAddrIpExt, S, Meta, DeviceId: StrongDeviceIdentifier>
261 IpDeviceAddressIdContext<I> for FakeCoreCtx<S, Meta, DeviceId>
262 {
263 type AddressId = AddrSubnet<I::Addr, I::AssignedWitness>;
264 type WeakAddressId = FakeWeakAddressId<Self::AddressId>;
265 }
266}