netstack3_base/device/
address.rs1use 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 + Into<IpDeviceAddr<Self::Addr>>;
34}
35
36impl AssignedAddrIpExt for Ipv4 {
37 type AssignedWitness = Ipv4DeviceAddr;
38}
39
40impl AssignedAddrIpExt for Ipv6 {
41 type AssignedWitness = Ipv6DeviceAddr;
42}
43
44pub trait WeakIpAddressId<A: IpAddress>:
46 Clone + Eq + Debug + Hash + Send + Sync + InspectableValue + 'static
47{
48 type Strong: IpAddressId<A>;
50
51 fn upgrade(&self) -> Option<Self::Strong>;
55
56 fn is_assigned(&self) -> bool;
58}
59
60pub trait IpAddressId<A: IpAddress>: Clone + Eq + Debug + Hash {
62 type Weak: WeakIpAddressId<A>;
64
65 fn downgrade(&self) -> Self::Weak;
67
68 fn addr(&self) -> IpDeviceAddr<A>;
74
75 fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
77 where
78 A::Version: AssignedAddrIpExt;
79}
80
81pub trait IpDeviceAddressIdContext<I: Ip>: DeviceIdContext<AnyDevice> {
83 type AddressId: IpAddressId<I::Addr, Weak = Self::WeakAddressId>;
85 type WeakAddressId: WeakIpAddressId<I::Addr, Strong = Self::AddressId>;
87}
88
89#[derive(Copy, Clone, Debug, Eq, GenericOverIp, Hash, PartialEq)]
91#[generic_over_ip(A, IpAddress)]
92pub struct IpDeviceAddr<A: IpAddress>(NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>);
93
94impl<A: IpAddress> Display for IpDeviceAddr<A> {
95 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
96 let Self(addr) = self;
97 write!(f, "{}", addr)
98 }
99}
100
101impl<A: IpAddress> IpDeviceAddr<A> {
102 pub fn addr(self) -> A {
104 let Self(addr) = self;
105 ***addr
106 }
107
108 pub fn into_inner(self) -> NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>> {
110 let IpDeviceAddr(addr) = self;
111 addr
112 }
113
114 pub fn new(addr: A) -> Option<IpDeviceAddr<A>> {
116 Some(IpDeviceAddr(NonMulticastAddr::new(NonMappedAddr::new(SpecifiedAddr::new(addr)?)?)?))
117 }
118
119 pub fn new_from_witness(addr: NonMulticastAddr<NonMappedAddr<SpecifiedAddr<A>>>) -> Self {
121 Self(addr)
122 }
123
124 pub fn new_from_socket_ip_addr(addr: SocketIpAddr<A>) -> Option<Self> {
126 NonMulticastAddr::new(addr.into_inner()).map(Self)
127 }
128}
129
130impl IpDeviceAddr<Ipv6Addr> {
131 pub fn new_from_ipv6_device_addr(addr: Ipv6DeviceAddr) -> Self {
133 let addr: UnicastAddr<NonMappedAddr<Ipv6Addr>> = addr.transpose();
134 let addr: NonMappedAddr<SpecifiedAddr<Ipv6Addr>> = addr.into_specified().transpose();
135 let addr = unsafe { NonMulticastAddr::new_unchecked(addr) };
138 Self(addr)
139 }
140
141 pub fn new_from_ipv6_source(addr: Ipv6SourceAddr) -> Option<Self> {
143 match addr {
144 Ipv6SourceAddr::Unicast(addr) => Some(Self::new_from_ipv6_device_addr(addr)),
145 Ipv6SourceAddr::Unspecified => None,
146 }
147 }
148}
149
150impl<A: IpAddress> From<IpDeviceAddr<A>> for SpecifiedAddr<A> {
151 fn from(addr: IpDeviceAddr<A>) -> Self {
152 **addr.into_inner()
153 }
154}
155
156impl<A: IpAddress> AsRef<SpecifiedAddr<A>> for IpDeviceAddr<A> {
157 fn as_ref(&self) -> &SpecifiedAddr<A> {
158 let Self(addr) = self;
159 addr.as_ref()
160 }
161}
162
163impl<A: IpAddress> From<IpDeviceAddr<A>> for SocketIpAddr<A> {
164 fn from(addr: IpDeviceAddr<A>) -> Self {
165 SocketIpAddr::new_from_witness(*addr.into_inner())
166 }
167}
168
169#[derive(Debug)]
170pub enum IpDeviceAddrError {
171 NotNonMapped,
172 NotNonMulticast,
173}
174
175impl<A: IpAddress> TryFrom<SpecifiedAddr<A>> for IpDeviceAddr<A> {
176 type Error = IpDeviceAddrError;
177 fn try_from(addr: SpecifiedAddr<A>) -> Result<Self, Self::Error> {
178 Ok(IpDeviceAddr::new_from_witness(
179 NonMulticastAddr::new(NonMappedAddr::new(addr).ok_or(IpDeviceAddrError::NotNonMapped)?)
180 .ok_or(IpDeviceAddrError::NotNonMulticast)?,
181 ))
182 }
183}
184
185pub type Ipv4DeviceAddr = NonMulticastAddr<NonMappedAddr<SpecifiedAddr<Ipv4Addr>>>;
193
194impl From<Ipv4DeviceAddr> for IpDeviceAddr<Ipv4Addr> {
195 fn from(addr: Ipv4DeviceAddr) -> IpDeviceAddr<Ipv4Addr> {
196 IpDeviceAddr::new_from_witness(addr)
197 }
198}
199
200pub type Ipv6DeviceAddr = NonMappedAddr<UnicastAddr<Ipv6Addr>>;
205
206impl From<Ipv6DeviceAddr> for IpDeviceAddr<Ipv6Addr> {
207 fn from(addr: Ipv6DeviceAddr) -> IpDeviceAddr<Ipv6Addr> {
208 IpDeviceAddr::new_from_ipv6_device_addr(addr)
209 }
210}
211
212#[cfg(any(test, feature = "testutils"))]
213pub mod testutil {
214 use net_types::ip::GenericOverIp;
215
216 use super::*;
217 use crate::inspect::Inspector;
218 use crate::testutil::FakeCoreCtx;
219 use crate::StrongDeviceIdentifier;
220
221 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
223 pub struct FakeWeakAddressId<T>(pub T);
224
225 impl<A: IpAddress, T: IpAddressId<A> + Send + Sync + 'static> WeakIpAddressId<A>
226 for FakeWeakAddressId<T>
227 {
228 type Strong = T;
229
230 fn upgrade(&self) -> Option<Self::Strong> {
231 let Self(inner) = self;
232 Some(inner.clone())
233 }
234
235 fn is_assigned(&self) -> bool {
236 true
237 }
238 }
239
240 impl<T> InspectableValue for FakeWeakAddressId<T> {
241 fn record<I: Inspector>(&self, _name: &str, _inspector: &mut I) {
242 unimplemented!()
243 }
244 }
245
246 impl<A: IpAddress> IpAddressId<A>
247 for AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness>
248 where
249 A::Version: AssignedAddrIpExt,
250 {
251 type Weak = FakeWeakAddressId<Self>;
252
253 fn downgrade(&self) -> Self::Weak {
254 FakeWeakAddressId(self.clone())
255 }
256
257 fn addr(&self) -> IpDeviceAddr<A> {
258 #[derive(GenericOverIp)]
259 #[generic_over_ip(I, Ip)]
260 struct WrapIn<I: AssignedAddrIpExt>(I::AssignedWitness);
261 A::Version::map_ip(
262 WrapIn(self.addr()),
263 |WrapIn(v4_addr)| IpDeviceAddr::new_from_witness(v4_addr),
264 |WrapIn(v6_addr)| IpDeviceAddr::new_from_ipv6_device_addr(v6_addr),
265 )
266 }
267
268 fn addr_sub(&self) -> AddrSubnet<A, <A::Version as AssignedAddrIpExt>::AssignedWitness> {
269 self.clone()
270 }
271 }
272
273 impl<I: AssignedAddrIpExt, S, Meta, DeviceId: StrongDeviceIdentifier>
274 IpDeviceAddressIdContext<I> for FakeCoreCtx<S, Meta, DeviceId>
275 {
276 type AddressId = AddrSubnet<I::Addr, I::AssignedWitness>;
277 type WeakAddressId = FakeWeakAddressId<Self::AddressId>;
278 }
279}