1use std::{convert::TryFrom, fmt, net::Ipv6Addr, str::FromStr};
2
3use crate::{
4 error::IpNetworkError,
5 parse::{cidr_parts, parse_prefix},
6};
7
8const IPV6_BITS: u8 = 128;
9const IPV6_SEGMENT_BITS: u8 = 16;
10
11#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub struct Ipv6Network {
14 addr: Ipv6Addr,
15 prefix: u8,
16}
17
18#[cfg(feature = "serde")]
19impl<'de> serde::Deserialize<'de> for Ipv6Network {
20 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21 where
22 D: serde::Deserializer<'de>,
23 {
24 let s = <String>::deserialize(deserializer)?;
25 Ipv6Network::from_str(&s).map_err(serde::de::Error::custom)
26 }
27}
28
29#[cfg(feature = "serde")]
30impl serde::Serialize for Ipv6Network {
31 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32 where
33 S: serde::Serializer,
34 {
35 serializer.collect_str(self)
36 }
37}
38
39#[cfg(feature = "schemars")]
40impl schemars::JsonSchema for Ipv6Network {
41 fn schema_name() -> std::borrow::Cow<'static, str> {
42 std::borrow::Cow::Borrowed("Ipv6Network")
43 }
44
45 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
46 schemars::json_schema!({
47 "type": "string",
48 "pattern": concat!(
49 r#"^("#,
50 r#"([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}"#,
51 r#"|([0-9a-fA-F]{1,4}:){1,7}:"#,
52 r#"|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}"#,
53 r#"|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}"#,
54 r#"|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}"#,
55 r#"|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}"#,
56 r#"|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}"#,
57 r#"|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})"#,
58 r#"|:((:[0-9a-fA-F]{1,4}){1,7}|:)"#,
59 r#"|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}"#,
60 r#"|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"#,
61 r#"|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"#,
62 r#"")[/](12[0-8]|1[0-1][0-9]|[0-9]?[0-9])$"#,
63 ),
64 "x-rust-type": "ipnetwork::Ipv6Network"
65 })
66 }
67}
68
69impl Ipv6Network {
70 pub const fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Network, IpNetworkError> {
74 match Ipv6Network::new_checked(addr, prefix) {
75 Some(a) => Ok(a),
76 None => Err(IpNetworkError::InvalidPrefix),
77 }
78 }
79
80 pub const fn new_checked(addr: Ipv6Addr, prefix: u8) -> Option<Ipv6Network> {
113 if prefix > IPV6_BITS {
114 None
115 } else {
116 Some(Ipv6Network {
117 addr,
118 prefix,
119 })
120 }
121 }
122
123 pub fn with_netmask(netaddr: Ipv6Addr, netmask: Ipv6Addr) -> Result<Self, IpNetworkError> {
127 let prefix = ipv6_mask_to_prefix(netmask)?;
128 let net = Self {
129 addr: netaddr,
130 prefix,
131 };
132 Ok(net)
133 }
134
135 pub fn iter(&self) -> Ipv6NetworkIterator {
143 let dec = u128::from(self.addr);
144 let max = u128::MAX;
145 let prefix = self.prefix;
146
147 let mask = max.checked_shl(u32::from(IPV6_BITS - prefix)).unwrap_or(0);
148 let start: u128 = dec & mask;
149
150 let mask = max.checked_shr(u32::from(prefix)).unwrap_or(0);
151 let end: u128 = dec | mask;
152
153 Ipv6NetworkIterator {
154 next: Some(start),
155 end,
156 }
157 }
158
159 pub const fn ip(&self) -> Ipv6Addr {
160 self.addr
161 }
162
163 pub const fn prefix(&self) -> u8 {
164 self.prefix
165 }
166
167 pub fn is_subnet_of(self, other: Ipv6Network) -> bool {
169 other.ip() <= self.ip() && other.broadcast() >= self.broadcast()
170 }
171
172 pub fn is_supernet_of(self, other: Ipv6Network) -> bool {
174 other.is_subnet_of(self)
175 }
176
177 pub fn overlaps(self, other: Ipv6Network) -> bool {
179 other.contains(self.ip())
180 || other.contains(self.broadcast())
181 || self.contains(other.ip())
182 || self.contains(other.broadcast())
183 }
184
185 pub const fn mask(&self) -> Ipv6Addr {
200 debug_assert!(self.prefix <= IPV6_BITS);
201
202 if self.prefix == 0 {
203 return Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
204 }
205 let mask = u128::MAX << (IPV6_BITS - self.prefix);
206 Ipv6Addr::from_bits(mask)
207 }
208
209 pub const fn network(&self) -> Ipv6Addr {
222 let mask = self.mask().to_bits();
223 let network = self.addr.to_bits() & mask;
224 Ipv6Addr::from_bits(network)
225 }
226
227 pub const fn broadcast(&self) -> Ipv6Addr {
240 let mask = self.mask().to_bits();
241 let broadcast = self.addr.to_bits() | !mask;
242 Ipv6Addr::from_bits(broadcast)
243 }
244
245 #[inline]
258 pub const fn contains(&self, ip: Ipv6Addr) -> bool {
259 let ip = ip.to_bits();
260 let net = self.network().to_bits();
261 let mask = self.mask().to_bits();
262 (ip & mask) == net
263 }
264
265 pub fn size(&self) -> u128 {
280 debug_assert!(self.prefix <= IPV6_BITS);
281
282 if self.prefix == 0 {
283 return u128::MAX;
284 }
285 1 << (IPV6_BITS - self.prefix)
286 }
287
288 pub fn nth(self, n: u128) -> Option<Ipv6Addr> {
304 if n < self.size() {
305 let net = u128::from(self.network());
306 Some(Ipv6Addr::from(net + n))
307 } else {
308 None
309 }
310 }
311}
312
313impl FromStr for Ipv6Network {
327 type Err = IpNetworkError;
328 fn from_str(s: &str) -> Result<Self, Self::Err> {
329 let (addr_str, prefix_str) = cidr_parts(s)?;
330 let addr = Ipv6Addr::from_str(addr_str)?;
331 let prefix = parse_prefix(prefix_str.unwrap_or(&IPV6_BITS.to_string()), IPV6_BITS)?;
332 Ipv6Network::new(addr, prefix)
333 }
334}
335
336impl TryFrom<&str> for Ipv6Network {
337 type Error = IpNetworkError;
338
339 fn try_from(s: &str) -> Result<Self, Self::Error> {
340 Ipv6Network::from_str(s)
341 }
342}
343
344impl From<Ipv6Addr> for Ipv6Network {
345 fn from(a: Ipv6Addr) -> Ipv6Network {
346 Ipv6Network {
347 addr: a,
348 prefix: 128,
349 }
350 }
351}
352
353#[derive(Clone, Debug)]
354pub struct Ipv6NetworkIterator {
355 next: Option<u128>,
356 end: u128,
357}
358
359impl Iterator for Ipv6NetworkIterator {
360 type Item = Ipv6Addr;
361
362 fn next(&mut self) -> Option<Ipv6Addr> {
363 let next = self.next?;
364 self.next = if next == self.end { None } else { Some(next + 1) };
365 Some(next.into())
366 }
367
368 fn size_hint(&self) -> (usize, Option<usize>) {
369 if let Some(n) = self.next {
370 let elms = (self.end - n + 1) as usize;
371 (elms, Some(elms))
372 } else {
373 (0, None)
374 }
375 }
376}
377
378impl IntoIterator for &'_ Ipv6Network {
379 type IntoIter = Ipv6NetworkIterator;
380 type Item = Ipv6Addr;
381 fn into_iter(self) -> Ipv6NetworkIterator {
382 self.iter()
383 }
384}
385
386impl fmt::Display for Ipv6Network {
387 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
388 write!(fmt, "{}/{}", self.ip(), self.prefix())
389 }
390}
391
392pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
395 match ipv6_mask_to_prefix_checked(mask) {
396 Some(prefix) => Ok(prefix),
397 None => Err(IpNetworkError::InvalidPrefix),
398 }
399}
400
401pub const fn ipv6_mask_to_prefix_checked(mask: Ipv6Addr) -> Option<u8> {
406 let mask = mask.segments();
407
408 let mut prefix = 0;
410 let mut i = 0;
411 while i < mask.len() {
412 let segment = mask[i];
413 i += 1;
414 if segment == 0xffff {
415 prefix += IPV6_SEGMENT_BITS;
416 } else if segment == 0 {
417 break;
419 } else {
420 let prefix_bits = (!segment).leading_zeros() as u8;
421 if segment << prefix_bits != 0 {
423 return None;
424 }
425 prefix += prefix_bits;
426 break;
427 }
428 }
429
430 while i < mask.len() {
432 let segment = mask[i];
433 i += 1;
434 if segment != 0 {
435 return None;
436 }
437 }
438
439 Some(prefix)
440}
441
442#[cfg(test)]
443mod test {
444 use std::{collections::HashMap, net::Ipv6Addr};
445
446 use super::*;
447
448 #[test]
449 fn create_v6() {
450 let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24).unwrap();
451 assert_eq!(cidr.prefix(), 24);
452 }
453
454 #[test]
455 fn parse_netmask_broken_v6() {
456 assert_eq!(
457 "FF01:0:0:17:0:0:0:2/255.255.255.0".parse::<Ipv6Network>(),
458 Err(IpNetworkError::InvalidPrefix)
459 );
460 }
461
462 #[test]
463 fn create_v6_invalid_prefix() {
464 let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 129);
465 assert!(cidr.is_err());
466 }
467
468 #[test]
469 fn create_checked_v6() {
470 let cidr = Ipv6Network::new_checked(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24).unwrap();
471 assert_eq!(cidr.prefix(), 24);
472 }
473
474 #[test]
475 #[should_panic]
476 fn try_create_invalid_checked_v6() {
477 Ipv6Network::new_checked(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 129).unwrap();
478 }
479
480 #[test]
481 fn parse_v6() {
482 let cidr: Ipv6Network = "::1/0".parse().unwrap();
483 assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
484 assert_eq!(cidr.prefix(), 0);
485 }
486
487 #[test]
488 fn parse_v6_2() {
489 let cidr: Ipv6Network = "FF01:0:0:17:0:0:0:2/64".parse().unwrap();
490 assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2));
491 assert_eq!(cidr.prefix(), 64);
492 }
493
494 #[test]
495 fn parse_v6_noprefix() {
496 let cidr: Ipv6Network = "::1".parse().unwrap();
497 assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
498 assert_eq!(cidr.prefix(), 128);
499 }
500
501 #[test]
502 fn parse_v6_fail_addr() {
503 let cidr: Option<Ipv6Network> = "2001::1::/8".parse().ok();
504 assert_eq!(None, cidr);
505 }
506
507 #[test]
508 fn parse_v6_fail_prefix() {
509 let cidr: Option<Ipv6Network> = "::1/129".parse().ok();
510 assert_eq!(None, cidr);
511 }
512
513 #[test]
514 fn parse_v6_fail_two_slashes() {
515 let cidr: Option<Ipv6Network> = "::1/24/".parse().ok();
516 assert_eq!(None, cidr);
517 }
518
519 #[test]
520 fn mask_v6() {
521 let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 40).unwrap();
522 let mask = cidr.mask();
523 assert_eq!(mask, Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0));
524 }
525
526 #[test]
527 fn contains_v6() {
528 let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
529 let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0x7fff, 0, 0, 0x2);
530 assert!(cidr.contains(ip));
531 }
532
533 #[test]
534 fn not_contains_v6() {
535 let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
536 let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0xffff, 0, 0, 0x2);
537 assert!(!cidr.contains(ip));
538 }
539
540 #[test]
541 fn v6_mask_to_prefix() {
542 let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
543 let prefix = ipv6_mask_to_prefix(mask).unwrap();
544 assert_eq!(prefix, 48);
545 }
546
547 #[test]
548 fn invalid_v6_mask_to_prefix() {
549 let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
550 let prefix = ipv6_mask_to_prefix(mask);
551 assert!(prefix.is_err());
552 }
553
554 #[test]
555 fn ipv6network_with_netmask() {
556 {
557 let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
559 let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
560 let net = Ipv6Network::with_netmask(addr, mask).unwrap();
561 let expected = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 48).unwrap();
562 assert_eq!(net, expected);
563 }
564 {
565 let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
567 let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
568 Ipv6Network::with_netmask(addr, mask).unwrap_err();
569 }
570 }
571
572 #[test]
573 fn iterator_v6() {
574 let cidr: Ipv6Network = "2001:db8::/126".parse().unwrap();
575 let mut iter = cidr.iter();
576 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), iter.next().unwrap());
577 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), iter.next().unwrap());
578 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2), iter.next().unwrap());
579 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 3), iter.next().unwrap());
580 assert_eq!(None, iter.next());
581 }
582
583 #[test]
584 fn iterator_v6_tiny() {
585 let cidr: Ipv6Network = "2001:db8::/128".parse().unwrap();
586 let mut iter = cidr.iter();
587 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), iter.next().unwrap());
588 assert_eq!(None, iter.next());
589 }
590
591 #[test]
592 fn iterator_v6_huge() {
593 let cidr: Ipv6Network = "2001:db8::/0".parse().unwrap();
594 let mut iter = cidr.iter();
595 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), iter.next().unwrap());
596 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), iter.next().unwrap());
597 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2), iter.next().unwrap());
598 }
599
600 #[test]
601 fn iterator_v6_size_hint() {
602 let cidr: Ipv6Network = "2001:db8::/128".parse().unwrap();
603 let mut iter = cidr.iter();
604 assert_eq!((1, Some(1)), iter.size_hint());
605 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0), iter.next().unwrap());
606 assert_eq!((0, None), iter.size_hint());
607 }
608
609 #[test]
610 fn network_v6() {
611 let cidr: Ipv6Network = "2001:db8::0/96".parse().unwrap();
612 let net = cidr.network();
613 let expected: Ipv6Addr = "2001:db8::".parse().unwrap();
614 assert_eq!(net, expected);
615 }
616
617 #[test]
618 fn broadcast_v6() {
619 let cidr: Ipv6Network = "2001:db8::0/96".parse().unwrap();
620 let net = cidr.broadcast();
621 let expected: Ipv6Addr = "2001:db8::ffff:ffff".parse().unwrap();
622 assert_eq!(net, expected);
623 }
624
625 #[test]
626 fn size_v6() {
627 let cidr: Ipv6Network = "2001:db8::0/96".parse().unwrap();
628 assert_eq!(cidr.size(), 4294967296);
629 }
630
631 #[test]
632 fn ipv6network_from_ipv6addr() {
633 let net = Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
634 let expected = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap();
635 assert_eq!(net, expected);
636 }
637
638 #[test]
639 fn test_send() {
640 fn assert_send<T: Send>() {}
641 assert_send::<Ipv6Network>();
642 }
643
644 #[test]
645 fn test_sync() {
646 fn assert_sync<T: Sync>() {}
647 assert_sync::<Ipv6Network>();
648 }
649
650 #[test]
652 fn test_is_subnet_of() {
653 let mut test_cases: HashMap<(Ipv6Network, Ipv6Network), bool> = HashMap::new();
654
655 test_cases.insert(("2000:999::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), false);
656 test_cases.insert(("2000:aaa::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), true);
657 test_cases.insert(("2000:bbb::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), false);
658 test_cases.insert(("2000:aaa::/48".parse().unwrap(), "2000:aaa::/56".parse().unwrap()), false);
659
660 for (key, val) in test_cases.iter() {
661 let (src, dest) = (key.0, key.1);
662 assert_eq!(src.is_subnet_of(dest), *val, "testing with {src} and {dest}");
663 }
664 }
665
666 #[test]
667 fn test_is_supernet_of() {
668 let mut test_cases: HashMap<(Ipv6Network, Ipv6Network), bool> = HashMap::new();
669
670 test_cases.insert(("2000:999::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), false);
671 test_cases.insert(("2000:aaa::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), false);
672 test_cases.insert(("2000:bbb::/56".parse().unwrap(), "2000:aaa::/48".parse().unwrap()), false);
673 test_cases.insert(("2000:aaa::/48".parse().unwrap(), "2000:aaa::/56".parse().unwrap()), true);
674
675 for (key, val) in test_cases.iter() {
676 let (src, dest) = (key.0, key.1);
677 assert_eq!(src.is_supernet_of(dest), *val, "testing with {src} and {dest}");
678 }
679 }
680
681 #[test]
682 fn test_overlaps() {
683 let other: Ipv6Network = "2001:DB8:ACAD::1/64".parse().unwrap();
684 let other2: Ipv6Network = "2001:DB8:ACAD::20:2/64".parse().unwrap();
685
686 assert!(other2.overlaps(other));
687 }
688
689 #[test]
690 fn edges() {
691 let low: Ipv6Network = "::0/120".parse().unwrap();
692 let low_addrs: Vec<Ipv6Addr> = low.iter().collect();
693 assert_eq!(256, low_addrs.len());
694
695 let high: Ipv6Network = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00/120".parse().unwrap();
696 let high_addrs: Vec<Ipv6Addr> = high.iter().collect();
697 assert_eq!(256, high_addrs.len());
698 }
699
700 #[test]
701 fn test_nth_ipv6() {
702 let net = Ipv6Network::from_str("ff01::/32").unwrap();
703
704 assert_eq!(net.nth(0).unwrap(), Ipv6Addr::from_str("ff01:0:0:0:0:0:0:0").unwrap());
705 assert_eq!(net.nth(255).unwrap(), Ipv6Addr::from_str("ff01::ff").unwrap());
706 assert_eq!(net.nth(65538).unwrap(), Ipv6Addr::from_str("ff01::1:2").unwrap());
707 assert_eq!(net.nth(net.size()), None);
708 }
709
710 #[test]
711 fn test_mask_with_prefix_0() {
712 let network: Ipv6Network = "0::/0".parse().unwrap();
713 let mask = network.mask();
714 assert_eq!(mask, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
715 }
716
717 #[test]
718 fn test_size_with_prefix_0() {
719 let network: Ipv6Network = "0::/0".parse().unwrap();
720 assert_eq!(network.size(), u128::MAX);
721 }
722}