1use core::borrow::{Borrow, BorrowMut};
2use core::fmt::{Binary, Debug, Display};
3use core::hash::Hash;
4use core::mem;
5use core::ops::{Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Not, RangeInclusive, Shl, Shr, Sub};
6
7use bitvec::{slice::BitSlice, BitArr};
8use num_traits::CheckedAdd;
9
10use super::Afi;
11use crate::{
12 concrete::{Ipv4, Ipv6},
13 error::Error,
14 parser,
15};
16
17pub trait Address<A: Afi>:
19 Copy
20 + Debug
21 + Default
22 + Hash
23 + Ord
24 + BitAnd<Self, Output = Self>
25 + BitOr<Self, Output = Self>
26 + BitXor<Self, Output = Self>
27 + Add<Self, Output = Self>
28 + CheckedAdd
29 + Not<Output = Self>
30 + Shl<Self::Length, Output = Self>
31 + Shr<Self::Length, Output = Self>
32 + 'static
33{
34 type Length: Length;
36
37 type LengthMap: LengthMap;
39
40 const MIN_LENGTH: Self::Length = Self::Length::ZERO;
43
44 const MAX_LENGTH: Self::Length;
47
48 const ZERO: Self;
50 const ONES: Self;
52
53 const BROADCAST: Option<Self>;
56
57 const LOCALHOST: Self;
59
60 const UNSPECIFIED: Self;
63
64 const LOOPBACK_RANGE: RangeInclusive<Self>;
67
68 const BENCHMARK_RANGE: RangeInclusive<Self>;
71
72 const MULTICAST_RANGE: RangeInclusive<Self>;
75
76 const LINK_LOCAL_RANGE: RangeInclusive<Self>;
79
80 const PROTOCOL_ASSIGNMENTS_RANGE: RangeInclusive<Self>;
83
84 const DOCUMENTATION_RANGES: &'static [RangeInclusive<Self>];
87
88 const PRIVATE_RANGES: Option<&'static [RangeInclusive<Self>]>;
91
92 const RESERVED_RANGE: Option<RangeInclusive<Self>>;
95
96 const SHARED_RANGE: Option<RangeInclusive<Self>>;
99
100 const THISNET_RANGE: Option<RangeInclusive<Self>>;
103
104 const ULA_RANGE: Option<RangeInclusive<Self>>;
107
108 fn leading_zeros(self) -> Self::Length;
110
111 fn to_be_bytes(self) -> A::Octets;
113
114 fn from_be_bytes(bytes: A::Octets) -> Self;
116
117 fn is_global(&self) -> bool;
121
122 fn parse_addr<S>(s: &S) -> Result<Self, Error>
133 where
134 S: AsRef<str> + ?Sized;
135
136 fn parse_length<S>(s: &S) -> Result<Self::Length, Error>
147 where
148 S: AsRef<str> + ?Sized;
149
150 fn parse_prefix<S>(s: &S) -> Result<(Self, Self::Length), Error>
162 where
163 S: AsRef<str> + ?Sized;
164
165 #[allow(clippy::type_complexity)]
177 fn parse_range<S>(s: &S) -> Result<(Self, Self::Length, Self::Length, Self::Length), Error>
178 where
179 S: AsRef<str> + ?Sized;
180}
181
182macro_rules! ipv4 {
183 ($a:literal, $b:literal, $c:literal, $d:literal) => {
184 u32::from_be_bytes([$a, $b, $c, $d])
185 };
186}
187
188impl Address<Ipv4> for u32 {
189 type Length = u8;
190 type LengthMap = BitArr!(for 33);
191
192 const MAX_LENGTH: Self::Length = 32;
193 const ZERO: Self = ipv4!(0, 0, 0, 0);
194 const ONES: Self = ipv4!(255, 255, 255, 255);
195
196 const BROADCAST: Option<Self> = Some(ipv4!(255, 255, 255, 255));
197 const LOCALHOST: Self = ipv4!(127, 0, 0, 1);
198 const UNSPECIFIED: Self = ipv4!(0, 0, 0, 0);
199
200 const LOOPBACK_RANGE: RangeInclusive<Self> = ipv4!(127, 0, 0, 0)..=ipv4!(127, 255, 255, 255);
201 const BENCHMARK_RANGE: RangeInclusive<Self> = ipv4!(198, 18, 0, 0)..=ipv4!(198, 19, 255, 255);
202 const MULTICAST_RANGE: RangeInclusive<Self> = ipv4!(224, 0, 0, 0)..=ipv4!(239, 255, 255, 255);
203 const LINK_LOCAL_RANGE: RangeInclusive<Self> =
204 ipv4!(169, 254, 0, 0)..=ipv4!(169, 254, 255, 255);
205 const PROTOCOL_ASSIGNMENTS_RANGE: RangeInclusive<Self> =
206 ipv4!(192, 0, 0, 0)..=ipv4!(192, 0, 0, 255);
207 const DOCUMENTATION_RANGES: &'static [RangeInclusive<Self>] = &[
208 ipv4!(192, 0, 2, 0)..=ipv4!(192, 0, 2, 255),
209 ipv4!(198, 51, 100, 0)..=ipv4!(198, 51, 100, 255),
210 ipv4!(203, 0, 113, 0)..=ipv4!(203, 0, 113, 255),
211 ];
212 const PRIVATE_RANGES: Option<&'static [RangeInclusive<Self>]> = Some(&[
213 ipv4!(10, 0, 0, 0)..=ipv4!(10, 255, 255, 255),
214 ipv4!(172, 16, 0, 0)..=ipv4!(172, 31, 255, 255),
215 ipv4!(192, 168, 0, 0)..=ipv4!(192, 168, 255, 255),
216 ]);
217 const RESERVED_RANGE: Option<RangeInclusive<Self>> =
218 Some(ipv4!(240, 0, 0, 0)..=ipv4!(255, 255, 255, 255));
219 const SHARED_RANGE: Option<RangeInclusive<Self>> =
220 Some(ipv4!(100, 64, 0, 0)..=ipv4!(100, 127, 255, 255));
221 const THISNET_RANGE: Option<RangeInclusive<Self>> =
222 Some(ipv4!(0, 0, 0, 0)..=ipv4!(0, 255, 255, 255));
223 const ULA_RANGE: Option<RangeInclusive<Self>> = None;
224
225 #[allow(clippy::cast_possible_truncation)]
226 fn leading_zeros(self) -> Self::Length {
227 self.leading_zeros() as Self::Length
228 }
229
230 fn to_be_bytes(self) -> <Ipv4 as Afi>::Octets {
231 self.to_be_bytes()
232 }
233
234 #[allow(clippy::only_used_in_recursion)]
237 fn from_be_bytes(bytes: <Ipv4 as Afi>::Octets) -> Self {
238 Self::from_be_bytes(bytes)
239 }
240
241 fn is_global(&self) -> bool {
242 if Self::LOOPBACK_RANGE.contains(self)
243 || Self::LINK_LOCAL_RANGE.contains(self)
244 || Self::BENCHMARK_RANGE.contains(self)
245 || Self::DOCUMENTATION_RANGES
246 .iter()
247 .any(|range| range.contains(self))
248 {
249 return false;
250 }
251 if let Some(ref broadcast) = Self::BROADCAST {
252 if broadcast == self {
253 return false;
254 }
255 }
256 if let Some(ranges) = Self::PRIVATE_RANGES {
257 if ranges.iter().any(|range| range.contains(self)) {
258 return false;
259 }
260 }
261 if let Some(range) = Self::SHARED_RANGE {
262 if range.contains(self) {
263 return false;
264 }
265 }
266 if let Some(range) = Self::RESERVED_RANGE {
267 if range.contains(self) {
268 return false;
269 }
270 }
271 if let Some(range) = Self::THISNET_RANGE {
272 if range.contains(self) {
273 return false;
274 }
275 }
276 if Self::MULTICAST_RANGE.contains(self)
278 && !(ipv4!(224, 0, 1, 0)..=ipv4!(238, 255, 255, 255)).contains(self)
279 {
280 return false;
281 }
282 if Self::PROTOCOL_ASSIGNMENTS_RANGE.contains(self)
283 && self != &ipv4!(192, 0, 0, 9)
285 && self != &ipv4!(192, 0, 0, 10)
287 {
288 return false;
289 }
290 true
291 }
292
293 fn parse_addr<S>(s: &S) -> Result<Self, Error>
294 where
295 S: AsRef<str> + ?Sized,
296 {
297 parser::ipv4::parse_addr(s.as_ref())
298 }
299
300 fn parse_length<S>(s: &S) -> Result<Self::Length, Error>
301 where
302 S: AsRef<str> + ?Sized,
303 {
304 parser::ipv4::parse_length(s.as_ref())
305 }
306
307 fn parse_prefix<S>(s: &S) -> Result<(Self, Self::Length), Error>
308 where
309 S: AsRef<str> + ?Sized,
310 {
311 parser::ipv4::parse_prefix(s.as_ref())
312 }
313
314 fn parse_range<S>(s: &S) -> Result<(Self, Self::Length, Self::Length, Self::Length), Error>
315 where
316 S: AsRef<str> + ?Sized,
317 {
318 parser::ipv4::parse_range(s.as_ref())
319 }
320}
321
322impl Address<Ipv6> for u128 {
323 type Length = u8;
324 type LengthMap = BitArr!(for 129);
325
326 const MAX_LENGTH: Self::Length = 128;
327 const ZERO: Self = 0x0000_0000_0000_0000_0000_0000_0000_0000;
328 const ONES: Self = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
329
330 const BROADCAST: Option<Self> = None;
331 const LOCALHOST: Self = 0x0000_0000_0000_0000_0000_0000_0000_0001;
332 const UNSPECIFIED: Self = Self::ZERO;
333
334 const LOOPBACK_RANGE: RangeInclusive<Self> = 0x1..=0x1;
335 const BENCHMARK_RANGE: RangeInclusive<Self> =
336 0x2001_0002_0000_0000_0000_0000_0000_0000..=0x2001_0002_0000_ffff_ffff_ffff_ffff_ffff;
337 const MULTICAST_RANGE: RangeInclusive<Self> =
338 0xff00_0000_0000_0000_0000_0000_0000_0000..=0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
339 const LINK_LOCAL_RANGE: RangeInclusive<Self> =
340 0xfe80_0000_0000_0000_0000_0000_0000_0000..=0xfebf_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
341 const PROTOCOL_ASSIGNMENTS_RANGE: RangeInclusive<Self> =
342 0x2001_0000_0000_0000_0000_0000_0000_0000..=0x2001_01ff_ffff_ffff_ffff_ffff_ffff_ffff;
343 const DOCUMENTATION_RANGES: &'static [RangeInclusive<Self>] =
344 &[(0x2001_0db8_0000_0000_0000_0000_0000_0000..=0x2001_0db8_ffff_ffff_ffff_ffff_ffff_ffff)];
345 const PRIVATE_RANGES: Option<&'static [RangeInclusive<Self>]> = None;
346 const RESERVED_RANGE: Option<RangeInclusive<Self>> = None;
347 const SHARED_RANGE: Option<RangeInclusive<Self>> = None;
348 const THISNET_RANGE: Option<RangeInclusive<Self>> = None;
349 const ULA_RANGE: Option<RangeInclusive<Self>> =
350 Some(0xfc00_0000_0000_0000_0000_0000_0000_0000..=0xfd00_0000_0000_0000_0000_0000_0000_0000);
351
352 #[allow(clippy::cast_possible_truncation)]
353 fn leading_zeros(self) -> Self::Length {
354 self.leading_zeros() as Self::Length
355 }
356
357 fn to_be_bytes(self) -> <Ipv6 as Afi>::Octets {
358 self.to_be_bytes()
359 }
360
361 fn from_be_bytes(bytes: <Ipv6 as Afi>::Octets) -> Self {
362 Self::from_be_bytes(bytes)
363 }
364
365 fn is_global(&self) -> bool {
366 if Self::LOOPBACK_RANGE.contains(self)
367 || Self::LINK_LOCAL_RANGE.contains(self)
368 || self == &Self::UNSPECIFIED
369 || Self::BENCHMARK_RANGE.contains(self)
370 || Self::DOCUMENTATION_RANGES
371 .iter()
372 .any(|range| range.contains(self))
373 {
374 return false;
375 }
376 if let Some(range) = Self::ULA_RANGE {
377 if range.contains(self) {
378 return false;
379 }
380 }
381 if Self::MULTICAST_RANGE.contains(self)
383 && self & 0x000f_0000_0000_0000_0000_0000_0000_0000
384 != 0x000e_0000_0000_0000_0000_0000_0000_0000
385 {
386 return false;
387 }
388 if Self::PROTOCOL_ASSIGNMENTS_RANGE.contains(self)
389 && !(0x2001_0000_0000_0000_0000_0000_0000_0000..=0x2001_0000_ffff_ffff_ffff_ffff_ffff_ffff).contains(self)
391 && self != &0x2001_0001_0000_0000_0000_0000_0000_0001
393 && self != &0x2001_0001_0000_0000_0000_0000_0000_0002
395 && !(0x2001_0003_0000_0000_0000_0000_0000_0000..=0x2001_0003_ffff_ffff_ffff_ffff_ffff_ffff).contains(self)
397 && !(0x2001_0004_0112_0000_0000_0000_0000_0000..=0x2001_0004_0112_ffff_ffff_ffff_ffff_ffff).contains(self)
399 && !(0x2001_0020_0000_0000_0000_0000_0000_0000..=0x2001_002f_ffff_ffff_ffff_ffff_ffff_ffff).contains(self)
401 {
402 return false;
403 }
404 true
405 }
406
407 fn parse_addr<S>(s: &S) -> Result<Self, Error>
408 where
409 S: AsRef<str> + ?Sized,
410 {
411 parser::ipv6::parse_addr(s.as_ref())
412 }
413
414 fn parse_length<S>(s: &S) -> Result<Self::Length, Error>
415 where
416 S: AsRef<str> + ?Sized,
417 {
418 parser::ipv6::parse_length(s.as_ref())
419 }
420
421 fn parse_prefix<S>(s: &S) -> Result<(Self, Self::Length), Error>
422 where
423 S: AsRef<str> + ?Sized,
424 {
425 parser::ipv6::parse_prefix(s.as_ref())
426 }
427
428 fn parse_range<S>(s: &S) -> Result<(Self, Self::Length, Self::Length, Self::Length), Error>
429 where
430 S: AsRef<str> + ?Sized,
431 {
432 parser::ipv6::parse_range(s.as_ref())
433 }
434}
435
436pub(crate) trait IntoIpv6Segments: Address<Ipv6> {
437 #[allow(unsafe_code)]
442 fn into_segments(self) -> [u16; 8] {
443 let [a, b, c, d, e, f, g, h]: [u16; 8] = unsafe { mem::transmute(self.to_be_bytes()) };
446 [
447 u16::from_be(a),
448 u16::from_be(b),
449 u16::from_be(c),
450 u16::from_be(d),
451 u16::from_be(e),
452 u16::from_be(f),
453 u16::from_be(g),
454 u16::from_be(h),
455 ]
456 }
457
458 #[allow(unsafe_code)]
459 #[allow(clippy::inline_always)]
460 #[inline(always)]
461 fn from_segments(segments: [u16; 8]) -> Self {
462 let octets = unsafe {
465 mem::transmute([
466 segments[0].to_be(),
467 segments[1].to_be(),
468 segments[2].to_be(),
469 segments[3].to_be(),
470 segments[4].to_be(),
471 segments[5].to_be(),
472 segments[6].to_be(),
473 segments[7].to_be(),
474 ])
475 };
476 Self::from_be_bytes(octets)
477 }
478}
479impl<P: Address<Ipv6>> IntoIpv6Segments for P {}
480
481pub trait Octets: Borrow<[u8]> + BorrowMut<[u8]> {
484 const LENGTH: usize;
486
487 const ZEROS: Self;
489}
490
491impl<const N: usize> Octets for [u8; N] {
492 const LENGTH: usize = N;
493 const ZEROS: Self = [0; N];
494}
495
496pub trait Length:
498 Copy
499 + Clone
500 + Debug
501 + Display
502 + Hash
503 + Ord
504 + Add<Output = Self>
505 + Sub<Output = Self>
506 + Into<usize>
507 + TryFrom<usize>
508{
509 const ZERO: Self;
511 const ONE: Self;
513}
514
515impl Length for u8 {
516 const ZERO: Self = 0;
517 const ONE: Self = 1;
518}
519
520pub trait LengthMap:
523 Copy
524 + Binary
525 + BitAnd<Output = Self>
526 + BitOr<Output = Self>
527 + Not<Output = Self>
528 + Default
529 + Deref<Target = BitSlice>
530 + DerefMut<Target = BitSlice>
531 + Eq
532{
533 const ZERO: Self;
535}
536
537impl LengthMap for BitArr!(for 33) {
538 const ZERO: Self = Self::ZERO;
539}
540
541impl LengthMap for BitArr!(for 129) {
542 const ZERO: Self = Self::ZERO;
543}