FYI: Doesn't apply anymore on latest proxmox-ve-rs master and needs a rebase, probably due to
746d7a0be "partially fix #6176: config: guest: change default for firewall key" On Fri Apr 4, 2025 at 3:55 PM CEST, Stefan Hanreich wrote: > Some of the types defined in this crate have been moved to > proxmox-network-types so they can be re-used across crates. This is a > preparation for the fabrics patch series, where those types will get > used by addtional, new, crates. > > Remove the types that have been moved and adjust the imports for them > accordingly. This patch has no functional changes, except for one in > the firewall ipset type. There we had a blanket From implementation: > > impl<T: Into<Cidr>> From<T> for IpsetAddress > > This is no longer possible due to the orphan rule, so it has been > replaced with a simple From<Cidr> implementation. All call sites that > used the blanket implementation for the trait have been adjusted as > well. > > Signed-off-by: Stefan Hanreich <s.hanre...@proxmox.com> > --- > > Notes: > This depends on the changes in the proxmox repository. > > Cargo.toml | 2 + > proxmox-ve-config/Cargo.toml | 1 + > proxmox-ve-config/debian/control | 6 +- > proxmox-ve-config/src/firewall/cluster.rs | 3 +- > proxmox-ve-config/src/firewall/ct_helper.rs | 2 +- > proxmox-ve-config/src/firewall/host.rs | 4 +- > .../src/firewall/types/address.rs | 1395 +---------------- > proxmox-ve-config/src/firewall/types/alias.rs | 2 +- > proxmox-ve-config/src/firewall/types/ipset.rs | 8 +- > proxmox-ve-config/src/firewall/types/mod.rs | 1 - > proxmox-ve-config/src/firewall/types/rule.rs | 5 +- > .../src/firewall/types/rule_match.rs | 6 +- > proxmox-ve-config/src/guest/vm.rs | 87 +- > proxmox-ve-config/src/host/utils.rs | 2 +- > proxmox-ve-config/src/sdn/config.rs | 9 +- > proxmox-ve-config/src/sdn/ipam.rs | 11 +- > proxmox-ve-config/src/sdn/mod.rs | 3 +- > proxmox-ve-config/tests/sdn/main.rs | 11 +- > 18 files changed, 60 insertions(+), 1498 deletions(-) > > diff --git a/Cargo.toml b/Cargo.toml > index dc7f312..b6e6df7 100644 > --- a/Cargo.toml > +++ b/Cargo.toml > @@ -15,3 +15,5 @@ homepage = "https://proxmox.com" > exclude = [ "debian" ] > rust-version = "1.82" > > +[workspace.dependencies] > +proxmox-network-types = { version = "0.1" } > diff --git a/proxmox-ve-config/Cargo.toml b/proxmox-ve-config/Cargo.toml > index b20ced1..2f3544b 100644 > --- a/proxmox-ve-config/Cargo.toml > +++ b/proxmox-ve-config/Cargo.toml > @@ -17,6 +17,7 @@ serde_json = "1" > serde_plain = "1" > serde_with = "3" > > +proxmox-network-types = { workspace = true } > proxmox-schema = "4" > proxmox-sys = "0.6.4" > proxmox-sortable-macro = "0.1.3" > diff --git a/proxmox-ve-config/debian/control > b/proxmox-ve-config/debian/control > index 60ebcbc..d498520 100644 > --- a/proxmox-ve-config/debian/control > +++ b/proxmox-ve-config/debian/control > @@ -2,13 +2,14 @@ Source: rust-proxmox-ve-config > Section: rust > Priority: optional > Build-Depends: debhelper-compat (= 13), > - dh-sequence-cargo, > - cargo:native <!nocheck>, > + dh-sequence-cargo > +Build-Depends-Arch: cargo:native <!nocheck>, > rustc:native <!nocheck>, > libstd-rust-dev <!nocheck>, > librust-anyhow-1+default-dev <!nocheck>, > librust-log-0.4+default-dev <!nocheck>, > librust-nix-0.26+default-dev <!nocheck>, > + librust-proxmox-network-types-0.1+default-dev <!nocheck>, > librust-proxmox-schema-4+default-dev <!nocheck>, > librust-proxmox-sortable-macro-0.1+default-dev (>= 0.1.3-~~) <!nocheck>, > librust-proxmox-sys-0.6+default-dev (>= 0.6.4-~~) <!nocheck>, > @@ -33,6 +34,7 @@ Depends: > librust-anyhow-1+default-dev, > librust-log-0.4+default-dev, > librust-nix-0.26+default-dev, > + librust-proxmox-network-types-0.1+default-dev, > librust-proxmox-schema-4+default-dev, > librust-proxmox-sortable-macro-0.1+default-dev (>= 0.1.3-~~), > librust-proxmox-sys-0.6+default-dev (>= 0.6.4-~~), > diff --git a/proxmox-ve-config/src/firewall/cluster.rs > b/proxmox-ve-config/src/firewall/cluster.rs > index ce3dd53..8879a69 100644 > --- a/proxmox-ve-config/src/firewall/cluster.rs > +++ b/proxmox-ve-config/src/firewall/cluster.rs > @@ -134,6 +134,8 @@ pub struct Options { > > #[cfg(test)] > mod tests { > + use proxmox_network_types::ip_address::Cidr; > + > use crate::firewall::types::{ > address::IpList, > alias::{AliasName, AliasScope}, > @@ -143,7 +145,6 @@ mod tests { > rule_match::{ > Icmpv6, Icmpv6Code, IpAddrMatch, IpMatch, Ports, Protocol, > RuleMatch, Tcp, Udp, > }, > - Cidr, > }; > > use super::*; > diff --git a/proxmox-ve-config/src/firewall/ct_helper.rs > b/proxmox-ve-config/src/firewall/ct_helper.rs > index 40e4fee..57fe9aa 100644 > --- a/proxmox-ve-config/src/firewall/ct_helper.rs > +++ b/proxmox-ve-config/src/firewall/ct_helper.rs > @@ -3,7 +3,7 @@ use serde::Deserialize; > use std::collections::HashMap; > use std::sync::OnceLock; > > -use crate::firewall::types::address::Family; > +use proxmox_network_types::ip_address::Family; > use crate::firewall::types::rule_match::{Ports, Protocol, Tcp, Udp}; > > #[derive(Clone, Debug, Deserialize)] > diff --git a/proxmox-ve-config/src/firewall/host.rs > b/proxmox-ve-config/src/firewall/host.rs > index 394896c..dcb49bb 100644 > --- a/proxmox-ve-config/src/firewall/host.rs > +++ b/proxmox-ve-config/src/firewall/host.rs > @@ -4,13 +4,15 @@ use std::net::IpAddr; > use anyhow::{bail, Error}; > use serde::Deserialize; > > +use proxmox_network_types::ip_address::Cidr; > + > use crate::host::utils::{host_ips, network_interface_cidrs}; > use proxmox_sys::nodename; > > use crate::firewall::parse; > use crate::firewall::types::log::LogLevel; > use crate::firewall::types::rule::Direction; > -use crate::firewall::types::{Alias, Cidr, Rule}; > +use crate::firewall::types::{Alias, Rule}; > > /// default setting for the enabled key > pub const HOST_ENABLED_DEFAULT: bool = true; > diff --git a/proxmox-ve-config/src/firewall/types/address.rs > b/proxmox-ve-config/src/firewall/types/address.rs > index 9b73d3d..548b813 100644 > --- a/proxmox-ve-config/src/firewall/types/address.rs > +++ b/proxmox-ve-config/src/firewall/types/address.rs > @@ -1,600 +1,9 @@ > -use std::fmt::{self, Display}; > -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; > +use std::fmt; > use std::ops::Deref; > > -use anyhow::{bail, format_err, Error}; > -use serde_with::{DeserializeFromStr, SerializeDisplay}; > - > -#[derive(Clone, Copy, Debug, Eq, PartialEq)] > -pub enum Family { > - V4, > - V6, > -} > - > -impl Family { > - pub fn is_ipv4(&self) -> bool { > - *self == Self::V4 > - } > - > - pub fn is_ipv6(&self) -> bool { > - *self == Self::V6 > - } > -} > - > -impl fmt::Display for Family { > - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { > - match self { > - Family::V4 => f.write_str("Ipv4"), > - Family::V6 => f.write_str("Ipv6"), > - } > - } > -} > - > -#[derive( > - Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, > SerializeDisplay, DeserializeFromStr, > -)] > -pub enum Cidr { > - Ipv4(Ipv4Cidr), > - Ipv6(Ipv6Cidr), > -} > - > -impl Cidr { > - pub fn new_v4(addr: impl Into<Ipv4Addr>, mask: u8) -> Result<Self, > Error> { > - Ok(Cidr::Ipv4(Ipv4Cidr::new(addr, mask)?)) > - } > - > - pub fn new_v6(addr: impl Into<Ipv6Addr>, mask: u8) -> Result<Self, > Error> { > - Ok(Cidr::Ipv6(Ipv6Cidr::new(addr, mask)?)) > - } > - > - pub const fn family(&self) -> Family { > - match self { > - Cidr::Ipv4(_) => Family::V4, > - Cidr::Ipv6(_) => Family::V6, > - } > - } > - > - pub fn is_ipv4(&self) -> bool { > - matches!(self, Cidr::Ipv4(_)) > - } > - > - pub fn is_ipv6(&self) -> bool { > - matches!(self, Cidr::Ipv6(_)) > - } > - > - pub fn contains_address(&self, ip: &IpAddr) -> bool { > - match (self, ip) { > - (Cidr::Ipv4(cidr), IpAddr::V4(ip)) => cidr.contains_address(ip), > - (Cidr::Ipv6(cidr), IpAddr::V6(ip)) => cidr.contains_address(ip), > - _ => false, > - } > - } > -} > - > -impl fmt::Display for Cidr { > - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { > - match self { > - Self::Ipv4(ip) => f.write_str(ip.to_string().as_str()), > - Self::Ipv6(ip) => f.write_str(ip.to_string().as_str()), > - } > - } > -} > - > -impl std::str::FromStr for Cidr { > - type Err = Error; > - > - fn from_str(s: &str) -> Result<Self, Error> { > - if let Ok(ip) = s.parse::<Ipv4Cidr>() { > - return Ok(Cidr::Ipv4(ip)); > - } > - > - if let Ok(ip) = s.parse::<Ipv6Cidr>() { > - return Ok(Cidr::Ipv6(ip)); > - } > - > - bail!("invalid ip address or CIDR: {s:?}"); > - } > -} > - > -impl From<Ipv4Cidr> for Cidr { > - fn from(cidr: Ipv4Cidr) -> Self { > - Cidr::Ipv4(cidr) > - } > -} > - > -impl From<Ipv6Cidr> for Cidr { > - fn from(cidr: Ipv6Cidr) -> Self { > - Cidr::Ipv6(cidr) > - } > -} > - > -impl From<IpAddr> for Cidr { > - fn from(value: IpAddr) -> Self { > - match value { > - IpAddr::V4(addr) => Ipv4Cidr::from(addr).into(), > - IpAddr::V6(addr) => Ipv6Cidr::from(addr).into(), > - } > - } > -} > - > -const IPV4_LENGTH: u8 = 32; > - > -#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] > -pub struct Ipv4Cidr { > - addr: Ipv4Addr, > - mask: u8, > -} > - > -impl Ipv4Cidr { > - pub fn new(addr: impl Into<Ipv4Addr>, mask: u8) -> Result<Self, Error> { > - if mask > 32 { > - bail!("mask out of range for ipv4 cidr ({mask})"); > - } > - > - Ok(Self { > - addr: addr.into(), > - mask, > - }) > - } > - > - pub fn contains_address(&self, other: &Ipv4Addr) -> bool { > - let bits = u32::from_be_bytes(self.addr.octets()); > - let other_bits = u32::from_be_bytes(other.octets()); > - > - let shift_amount: u32 = IPV4_LENGTH.saturating_sub(self.mask).into(); > - > - bits.checked_shr(shift_amount).unwrap_or(0) > - == other_bits.checked_shr(shift_amount).unwrap_or(0) > - } > - > - pub fn address(&self) -> &Ipv4Addr { > - &self.addr > - } > - > - pub fn mask(&self) -> u8 { > - self.mask > - } > -} > - > -impl<T: Into<Ipv4Addr>> From<T> for Ipv4Cidr { > - fn from(value: T) -> Self { > - Self { > - addr: value.into(), > - mask: 32, > - } > - } > -} > - > -impl std::str::FromStr for Ipv4Cidr { > - type Err = Error; > - > - fn from_str(s: &str) -> Result<Self, Error> { > - Ok(match s.find('/') { > - None => Self { > - addr: s.parse()?, > - mask: 32, > - }, > - Some(pos) => { > - let mask: u8 = s[(pos + 1)..] > - .parse() > - .map_err(|_| format_err!("invalid mask in ipv4 cidr: > {s:?}"))?; > - > - Self::new(s[..pos].parse::<Ipv4Addr>()?, mask)? > - } > - }) > - } > -} > - > -impl fmt::Display for Ipv4Cidr { > - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { > - write!(f, "{}/{}", &self.addr, self.mask) > - } > -} > - > -const IPV6_LENGTH: u8 = 128; > - > -#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] > -pub struct Ipv6Cidr { > - addr: Ipv6Addr, > - mask: u8, > -} > - > -impl Ipv6Cidr { > - pub fn new(addr: impl Into<Ipv6Addr>, mask: u8) -> Result<Self, Error> { > - if mask > IPV6_LENGTH { > - bail!("mask out of range for ipv6 cidr"); > - } > - > - Ok(Self { > - addr: addr.into(), > - mask, > - }) > - } > - > - pub fn contains_address(&self, other: &Ipv6Addr) -> bool { > - let bits = u128::from_be_bytes(self.addr.octets()); > - let other_bits = u128::from_be_bytes(other.octets()); > - > - let shift_amount: u32 = IPV6_LENGTH.saturating_sub(self.mask).into(); > - > - bits.checked_shr(shift_amount).unwrap_or(0) > - == other_bits.checked_shr(shift_amount).unwrap_or(0) > - } > - > - pub fn address(&self) -> &Ipv6Addr { > - &self.addr > - } > - > - pub fn mask(&self) -> u8 { > - self.mask > - } > -} > - > -impl std::str::FromStr for Ipv6Cidr { > - type Err = Error; > - > - fn from_str(s: &str) -> Result<Self, Error> { > - Ok(match s.find('/') { > - None => Self { > - addr: s.parse()?, > - mask: 128, > - }, > - Some(pos) => { > - let mask: u8 = s[(pos + 1)..] > - .parse() > - .map_err(|_| format_err!("invalid mask in ipv6 cidr: > {s:?}"))?; > - > - Self::new(s[..pos].parse::<Ipv6Addr>()?, mask)? > - } > - }) > - } > -} > - > -impl fmt::Display for Ipv6Cidr { > - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { > - write!(f, "{}/{}", &self.addr, self.mask) > - } > -} > - > -impl<T: Into<Ipv6Addr>> From<T> for Ipv6Cidr { > - fn from(addr: T) -> Self { > - Self { > - addr: addr.into(), > - mask: 128, > - } > - } > -} > - > -#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] > -pub enum IpRangeError { > - MismatchedFamilies, > - StartGreaterThanLast, > - InvalidFormat, > -} > - > -impl std::error::Error for IpRangeError {} > - > -impl Display for IpRangeError { > - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { > - f.write_str(match self { > - IpRangeError::MismatchedFamilies => "mismatched ip address > families", > - IpRangeError::StartGreaterThanLast => "start is greater than > last", > - IpRangeError::InvalidFormat => "invalid ip range format", > - }) > - } > -} > - > -/// Represents a range of IPv4 or IPv6 addresses. > -/// > -/// For more information see [`AddressRange`] > -#[derive( > - Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, SerializeDisplay, > DeserializeFromStr, > -)] > -pub enum IpRange { > - V4(AddressRange<Ipv4Addr>), > - V6(AddressRange<Ipv6Addr>), > -} > - > -impl IpRange { > - /// Returns the family of the IpRange. > - pub fn family(&self) -> Family { > - match self { > - IpRange::V4(_) => Family::V4, > - IpRange::V6(_) => Family::V6, > - } > - } > - > - /// Creates a new [`IpRange`] from two [`IpAddr`]. > - /// > - /// # Errors > - /// > - /// This function will return an error if start and last IP address are > not from the same family. > - pub fn new(start: impl Into<IpAddr>, last: impl Into<IpAddr>) -> > Result<Self, IpRangeError> { > - match (start.into(), last.into()) { > - (IpAddr::V4(start), IpAddr::V4(last)) => Self::new_v4(start, > last), > - (IpAddr::V6(start), IpAddr::V6(last)) => Self::new_v6(start, > last), > - _ => Err(IpRangeError::MismatchedFamilies), > - } > - } > - > - /// construct a new Ipv4 Range > - pub fn new_v4( > - start: impl Into<Ipv4Addr>, > - last: impl Into<Ipv4Addr>, > - ) -> Result<Self, IpRangeError> { > - Ok(IpRange::V4(AddressRange::new_v4(start, last)?)) > - } > - > - pub fn new_v6( > - start: impl Into<Ipv6Addr>, > - last: impl Into<Ipv6Addr>, > - ) -> Result<Self, IpRangeError> { > - Ok(IpRange::V6(AddressRange::new_v6(start, last)?)) > - } > - > - /// Converts an IpRange into the minimal amount of CIDRs. > - /// > - /// see the concrete implementations of [`AddressRange<Ipv4Addr>`] or > [`AddressRange<Ipv6Addr>`] > - /// respectively > - pub fn to_cidrs(&self) -> Vec<Cidr> { > - match self { > - IpRange::V4(range) => > range.to_cidrs().into_iter().map(Cidr::from).collect(), > - IpRange::V6(range) => > range.to_cidrs().into_iter().map(Cidr::from).collect(), > - } > - } > -} > - > -impl std::str::FromStr for IpRange { > - type Err = IpRangeError; > - > - fn from_str(s: &str) -> Result<Self, Self::Err> { > - if let Ok(range) = s.parse() { > - return Ok(IpRange::V4(range)); > - } > - > - if let Ok(range) = s.parse() { > - return Ok(IpRange::V6(range)); > - } > - > - Err(IpRangeError::InvalidFormat) > - } > -} > - > -impl fmt::Display for IpRange { > - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { > - match self { > - IpRange::V4(range) => range.fmt(f), > - IpRange::V6(range) => range.fmt(f), > - } > - } > -} > - > -/// Represents a range of IP addresses from start to last. > -/// > -/// This type is for encapsulation purposes for the [`IpRange`] enum and > should be instantiated via > -/// that enum. > -/// > -/// # Invariants > -/// > -/// * start and last have the same IP address family > -/// * start is less than or equal to last > -/// > -/// # Textual representation > -/// > -/// Two IP addresses separated by a hyphen, e.g.: `127.0.0.1-127.0.0.255` > -#[derive( > - Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, SerializeDisplay, > DeserializeFromStr, > -)] > -pub struct AddressRange<T> { > - start: T, > - last: T, > -} > - > -impl AddressRange<Ipv4Addr> { > - pub(crate) fn new_v4( > - start: impl Into<Ipv4Addr>, > - last: impl Into<Ipv4Addr>, > - ) -> Result<AddressRange<Ipv4Addr>, IpRangeError> { > - let (start, last) = (start.into(), last.into()); > - > - if start > last { > - return Err(IpRangeError::StartGreaterThanLast); > - } > - > - Ok(Self { start, last }) > - } > - > - /// Returns the minimum amount of CIDRs that exactly represent the range > - /// > - /// The idea behind this algorithm is as follows: > - /// > - /// Start iterating with current = start of the IP range > - /// > - /// Find two netmasks > - /// * The largest CIDR that the current IP can be the first of > - /// * The largest CIDR that *only* contains IPs from current - last > - /// > - /// Add the smaller of the two CIDRs to our result and current to the > first IP that is in > - /// the range but not in the CIDR we just added. Proceed until we > reached the last of the IP > - /// range. > - /// > - pub fn to_cidrs(&self) -> Vec<Ipv4Cidr> { > - let mut cidrs = Vec::new(); > - > - let mut current = u32::from_be_bytes(self.start.octets()); > - let last = u32::from_be_bytes(self.last.octets()); > - > - if current == last { > - // valid Ipv4 since netmask is 32 > - cidrs.push(Ipv4Cidr::new(current, 32).unwrap()); > - return cidrs; > - } > - > - // special case this, since this is the only possibility of overflow > - // when calculating delta_min_mask - makes everything a lot easier > - if current == u32::MIN && last == u32::MAX { > - // valid Ipv4 since it is `0.0.0.0/0` > - cidrs.push(Ipv4Cidr::new(current, 0).unwrap()); > - return cidrs; > - } > - > - while current <= last { > - // netmask of largest CIDR that current IP can be the first of > - // cast is safe, because trailing zeroes can at most be 32 > - let current_max_mask = IPV4_LENGTH - (current.trailing_zeros() > as u8); > - > - // netmask of largest CIDR that *only* contains IPs of the > remaining range > - // is at most 32 due to unwrap_or returning 32 and ilog2 being > at most 31 > - let delta_min_mask = ((last - current) + 1) // safe due to > special case above > - .checked_ilog2() // should never occur due to special case, > but for good measure > - .map(|mask| IPV4_LENGTH - mask as u8) > - .unwrap_or(IPV4_LENGTH); > - > - // at most 32, due to current/delta being at most 32 > - let netmask = u8::max(current_max_mask, delta_min_mask); > - > - // netmask is at most 32, therefore safe to unwrap > - cidrs.push(Ipv4Cidr::new(current, netmask).unwrap()); > - > - let delta = 2u32.saturating_pow((IPV4_LENGTH - netmask).into()); > - > - if let Some(result) = current.checked_add(delta) { > - current = result > - } else { > - // we reached the end of IP address space > - break; > - } > - } > - > - cidrs > - } > -} > - > -impl AddressRange<Ipv6Addr> { > - pub(crate) fn new_v6( > - start: impl Into<Ipv6Addr>, > - last: impl Into<Ipv6Addr>, > - ) -> Result<AddressRange<Ipv6Addr>, IpRangeError> { > - let (start, last) = (start.into(), last.into()); > - > - if start > last { > - return Err(IpRangeError::StartGreaterThanLast); > - } > - > - Ok(Self { start, last }) > - } > - > - /// Returns the minimum amount of CIDRs that exactly represent the > [`AddressRange`]. > - /// > - /// This function works analogous to the IPv4 version, please refer to > the respective > - /// documentation of [`AddressRange<Ipv4Addr>`] > - pub fn to_cidrs(&self) -> Vec<Ipv6Cidr> { > - let mut cidrs = Vec::new(); > - > - let mut current = u128::from_be_bytes(self.start.octets()); > - let last = u128::from_be_bytes(self.last.octets()); > - > - if current == last { > - // valid Ipv6 since netmask is 128 > - cidrs.push(Ipv6Cidr::new(current, 128).unwrap()); > - return cidrs; > - } > - > - // special case this, since this is the only possibility of overflow > - // when calculating delta_min_mask - makes everything a lot easier > - if current == u128::MIN && last == u128::MAX { > - // valid Ipv6 since it is `::/0` > - cidrs.push(Ipv6Cidr::new(current, 0).unwrap()); > - return cidrs; > - } > - > - while current <= last { > - // netmask of largest CIDR that current IP can be the first of > - // cast is safe, because trailing zeroes can at most be 128 > - let current_max_mask = IPV6_LENGTH - (current.trailing_zeros() > as u8); > - > - // netmask of largest CIDR that *only* contains IPs of the > remaining range > - // is at most 128 due to unwrap_or returning 128 and ilog2 being > at most 31 > - let delta_min_mask = ((last - current) + 1) // safe due to > special case above > - .checked_ilog2() // should never occur due to special case, > but for good measure > - .map(|mask| IPV6_LENGTH - mask as u8) > - .unwrap_or(IPV6_LENGTH); > - > - // at most 128, due to current/delta being at most 128 > - let netmask = u8::max(current_max_mask, delta_min_mask); > - > - // netmask is at most 128, therefore safe to unwrap > - cidrs.push(Ipv6Cidr::new(current, netmask).unwrap()); > - > - let delta = 2u128.saturating_pow((IPV6_LENGTH - netmask).into()); > - > - if let Some(result) = current.checked_add(delta) { > - current = result > - } else { > - // we reached the end of IP address space > - break; > - } > - } > - > - cidrs > - } > -} > - > -impl<T> AddressRange<T> { > - pub fn start(&self) -> &T { > - &self.start > - } > - > - pub fn last(&self) -> &T { > - &self.last > - } > -} > - > -impl std::str::FromStr for AddressRange<Ipv4Addr> { > - type Err = IpRangeError; > - > - fn from_str(s: &str) -> Result<Self, Self::Err> { > - if let Some((start, last)) = s.split_once('-') { > - let start_address = start > - .parse::<Ipv4Addr>() > - .map_err(|_| IpRangeError::InvalidFormat)?; > - > - let last_address = last > - .parse::<Ipv4Addr>() > - .map_err(|_| IpRangeError::InvalidFormat)?; > - > - return Self::new_v4(start_address, last_address); > - } > - > - Err(IpRangeError::InvalidFormat) > - } > -} > - > -impl std::str::FromStr for AddressRange<Ipv6Addr> { > - type Err = IpRangeError; > - > - fn from_str(s: &str) -> Result<Self, Self::Err> { > - if let Some((start, last)) = s.split_once('-') { > - let start_address = start > - .parse::<Ipv6Addr>() > - .map_err(|_| IpRangeError::InvalidFormat)?; > - > - let last_address = last > - .parse::<Ipv6Addr>() > - .map_err(|_| IpRangeError::InvalidFormat)?; > - > - return Self::new_v6(start_address, last_address); > - } > - > - Err(IpRangeError::InvalidFormat) > - } > -} > - > -impl<T: fmt::Display> fmt::Display for AddressRange<T> { > - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { > - write!(f, "{}-{}", self.start, self.last) > - } > -} > +use anyhow::{bail, Error}; > +use proxmox_network_types::ip_address::{Cidr, Family, IpRange}; > +use serde_with::DeserializeFromStr; > > #[derive(Clone, Debug)] > #[cfg_attr(test, derive(Eq, PartialEq))] > @@ -741,84 +150,6 @@ impl IpList { > #[cfg(test)] > mod tests { > use super::*; > - use std::net::{Ipv4Addr, Ipv6Addr}; > - > - #[test] > - fn test_v4_cidr() { > - let mut cidr: Ipv4Cidr = "0.0.0.0/0".parse().expect("valid IPv4 > CIDR"); > - > - assert_eq!(cidr.addr, Ipv4Addr::new(0, 0, 0, 0)); > - assert_eq!(cidr.mask, 0); > - > - assert!(cidr.contains_address(&Ipv4Addr::new(0, 0, 0, 0))); > - assert!(cidr.contains_address(&Ipv4Addr::new(255, 255, 255, 255))); > - > - cidr = "192.168.100.1".parse().expect("valid IPv4 CIDR"); > - > - assert_eq!(cidr.addr, Ipv4Addr::new(192, 168, 100, 1)); > - assert_eq!(cidr.mask, 32); > - > - assert!(cidr.contains_address(&Ipv4Addr::new(192, 168, 100, 1))); > - assert!(!cidr.contains_address(&Ipv4Addr::new(192, 168, 100, 2))); > - assert!(!cidr.contains_address(&Ipv4Addr::new(192, 168, 100, 0))); > - > - cidr = "10.100.5.0/24".parse().expect("valid IPv4 CIDR"); > - > - assert_eq!(cidr.mask, 24); > - > - assert!(cidr.contains_address(&Ipv4Addr::new(10, 100, 5, 0))); > - assert!(cidr.contains_address(&Ipv4Addr::new(10, 100, 5, 1))); > - assert!(cidr.contains_address(&Ipv4Addr::new(10, 100, 5, 100))); > - assert!(cidr.contains_address(&Ipv4Addr::new(10, 100, 5, 255))); > - assert!(!cidr.contains_address(&Ipv4Addr::new(10, 100, 4, 255))); > - assert!(!cidr.contains_address(&Ipv4Addr::new(10, 100, 6, 0))); > - > - "0.0.0.0/-1".parse::<Ipv4Cidr>().unwrap_err(); > - "0.0.0.0/33".parse::<Ipv4Cidr>().unwrap_err(); > - "256.256.256.256/10".parse::<Ipv4Cidr>().unwrap_err(); > - > - "fe80::1/64".parse::<Ipv4Cidr>().unwrap_err(); > - "qweasd".parse::<Ipv4Cidr>().unwrap_err(); > - "".parse::<Ipv4Cidr>().unwrap_err(); > - } > - > - #[test] > - fn test_v6_cidr() { > - let mut cidr: Ipv6Cidr = "abab::1/64".parse().expect("valid IPv6 > CIDR"); > - > - assert_eq!(cidr.addr, Ipv6Addr::new(0xABAB, 0, 0, 0, 0, 0, 0, 1)); > - assert_eq!(cidr.mask, 64); > - > - assert!(cidr.contains_address(&Ipv6Addr::new(0xABAB, 0, 0, 0, 0, 0, > 0, 0))); > - assert!(cidr.contains_address(&Ipv6Addr::new( > - 0xABAB, 0, 0, 0, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA > - ))); > - assert!(cidr.contains_address(&Ipv6Addr::new( > - 0xABAB, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF > - ))); > - assert!(!cidr.contains_address(&Ipv6Addr::new(0xABAB, 0, 0, 1, 0, 0, > 0, 0))); > - assert!(!cidr.contains_address(&Ipv6Addr::new( > - 0xABAA, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF > - ))); > - > - cidr = "eeee::1".parse().expect("valid IPv6 CIDR"); > - > - assert_eq!(cidr.mask, 128); > - > - assert!(cidr.contains_address(&Ipv6Addr::new(0xEEEE, 0, 0, 0, 0, 0, > 0, 1))); > - assert!(!cidr.contains_address(&Ipv6Addr::new( > - 0xEEED, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF > - ))); > - assert!(!cidr.contains_address(&Ipv6Addr::new(0xEEEE, 0, 0, 0, 0, 0, > 0, 0))); > - > - "eeee::1/-1".parse::<Ipv6Cidr>().unwrap_err(); > - "eeee::1/129".parse::<Ipv6Cidr>().unwrap_err(); > - "gggg::1/64".parse::<Ipv6Cidr>().unwrap_err(); > - > - "192.168.0.1".parse::<Ipv6Cidr>().unwrap_err(); > - "qweasd".parse::<Ipv6Cidr>().unwrap_err(); > - "".parse::<Ipv6Cidr>().unwrap_err(); > - } > > #[test] > fn test_parse_ip_entry() { > @@ -942,721 +273,5 @@ mod tests { > ]) > .expect_err("cannot mix ip families in ip list"); > } > - > - #[test] > - fn test_ip_range() { > - IpRange::new([10, 0, 0, 2], [10, 0, 0, 1]).unwrap_err(); > - > - IpRange::new( > - [0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x1000], > - [0x2001, 0x0db8, 0, 0, 0, 0, 0, 0], > - ) > - .unwrap_err(); > - > - let v4_range = IpRange::new([10, 0, 0, 0], [10, 0, 0, 100]).unwrap(); > - assert_eq!(v4_range.family(), Family::V4); > - > - let v6_range = IpRange::new( > - [0x2001, 0x0db8, 0, 0, 0, 0, 0, 0], > - [0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x1000], > - ) > - .unwrap(); > - assert_eq!(v6_range.family(), Family::V6); > - > - "10.0.0.1-10.0.0.100".parse::<IpRange>().unwrap(); > - "2001:db8::1-2001:db8::f".parse::<IpRange>().unwrap(); > - > - "10.0.0.1-2001:db8::1000".parse::<IpRange>().unwrap_err(); > - "2001:db8::1-192.168.0.2".parse::<IpRange>().unwrap_err(); > - > - "10.0.0.1-10.0.0.0".parse::<IpRange>().unwrap_err(); > - "2001:db8::1-2001:db8::0".parse::<IpRange>().unwrap_err(); > - } > - > - #[test] > - fn test_ipv4_to_cidrs() { > - let range = AddressRange::new_v4([192, 168, 0, 100], [192, 168, 0, > 100]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([192, 168, 0, 100], 32).unwrap()], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([192, 168, 0, 100], [192, 168, 0, > 200]).unwrap(); > - > - assert_eq!( > - [ > - Ipv4Cidr::new([192, 168, 0, 100], 30).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 104], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 112], 28).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 128], 26).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 192], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 200], 32).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([192, 168, 0, 101], [192, 168, 0, > 200]).unwrap(); > - > - assert_eq!( > - [ > - Ipv4Cidr::new([192, 168, 0, 101], 32).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 102], 31).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 104], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 112], 28).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 128], 26).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 192], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 200], 32).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([192, 168, 0, 101], [192, 168, 0, > 101]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([192, 168, 0, 101], 32).unwrap()], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([192, 168, 0, 101], [192, 168, 0, > 201]).unwrap(); > - > - assert_eq!( > - [ > - Ipv4Cidr::new([192, 168, 0, 101], 32).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 102], 31).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 104], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 112], 28).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 128], 26).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 192], 29).unwrap(), > - Ipv4Cidr::new([192, 168, 0, 200], 31).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([192, 168, 0, 0], [192, 168, 0, > 255]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([192, 168, 0, 0], 24).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([0, 0, 0, 0], [255, 255, 255, > 255]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([0, 0, 0, 0], 0).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([0, 0, 0, 1], [255, 255, 255, > 255]).unwrap(); > - > - assert_eq!( > - [ > - Ipv4Cidr::new([0, 0, 0, 1], 32).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 2], 31).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 4], 30).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 8], 29).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 16], 28).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 32], 27).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 64], 26).unwrap(), > - Ipv4Cidr::new([0, 0, 0, 128], 25).unwrap(), > - Ipv4Cidr::new([0, 0, 1, 0], 24).unwrap(), > - Ipv4Cidr::new([0, 0, 2, 0], 23).unwrap(), > - Ipv4Cidr::new([0, 0, 4, 0], 22).unwrap(), > - Ipv4Cidr::new([0, 0, 8, 0], 21).unwrap(), > - Ipv4Cidr::new([0, 0, 16, 0], 20).unwrap(), > - Ipv4Cidr::new([0, 0, 32, 0], 19).unwrap(), > - Ipv4Cidr::new([0, 0, 64, 0], 18).unwrap(), > - Ipv4Cidr::new([0, 0, 128, 0], 17).unwrap(), > - Ipv4Cidr::new([0, 1, 0, 0], 16).unwrap(), > - Ipv4Cidr::new([0, 2, 0, 0], 15).unwrap(), > - Ipv4Cidr::new([0, 4, 0, 0], 14).unwrap(), > - Ipv4Cidr::new([0, 8, 0, 0], 13).unwrap(), > - Ipv4Cidr::new([0, 16, 0, 0], 12).unwrap(), > - Ipv4Cidr::new([0, 32, 0, 0], 11).unwrap(), > - Ipv4Cidr::new([0, 64, 0, 0], 10).unwrap(), > - Ipv4Cidr::new([0, 128, 0, 0], 9).unwrap(), > - Ipv4Cidr::new([1, 0, 0, 0], 8).unwrap(), > - Ipv4Cidr::new([2, 0, 0, 0], 7).unwrap(), > - Ipv4Cidr::new([4, 0, 0, 0], 6).unwrap(), > - Ipv4Cidr::new([8, 0, 0, 0], 5).unwrap(), > - Ipv4Cidr::new([16, 0, 0, 0], 4).unwrap(), > - Ipv4Cidr::new([32, 0, 0, 0], 3).unwrap(), > - Ipv4Cidr::new([64, 0, 0, 0], 2).unwrap(), > - Ipv4Cidr::new([128, 0, 0, 0], 1).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([0, 0, 0, 0], [255, 255, 255, > 254]).unwrap(); > - > - assert_eq!( > - [ > - Ipv4Cidr::new([0, 0, 0, 0], 1).unwrap(), > - Ipv4Cidr::new([128, 0, 0, 0], 2).unwrap(), > - Ipv4Cidr::new([192, 0, 0, 0], 3).unwrap(), > - Ipv4Cidr::new([224, 0, 0, 0], 4).unwrap(), > - Ipv4Cidr::new([240, 0, 0, 0], 5).unwrap(), > - Ipv4Cidr::new([248, 0, 0, 0], 6).unwrap(), > - Ipv4Cidr::new([252, 0, 0, 0], 7).unwrap(), > - Ipv4Cidr::new([254, 0, 0, 0], 8).unwrap(), > - Ipv4Cidr::new([255, 0, 0, 0], 9).unwrap(), > - Ipv4Cidr::new([255, 128, 0, 0], 10).unwrap(), > - Ipv4Cidr::new([255, 192, 0, 0], 11).unwrap(), > - Ipv4Cidr::new([255, 224, 0, 0], 12).unwrap(), > - Ipv4Cidr::new([255, 240, 0, 0], 13).unwrap(), > - Ipv4Cidr::new([255, 248, 0, 0], 14).unwrap(), > - Ipv4Cidr::new([255, 252, 0, 0], 15).unwrap(), > - Ipv4Cidr::new([255, 254, 0, 0], 16).unwrap(), > - Ipv4Cidr::new([255, 255, 0, 0], 17).unwrap(), > - Ipv4Cidr::new([255, 255, 128, 0], 18).unwrap(), > - Ipv4Cidr::new([255, 255, 192, 0], 19).unwrap(), > - Ipv4Cidr::new([255, 255, 224, 0], 20).unwrap(), > - Ipv4Cidr::new([255, 255, 240, 0], 21).unwrap(), > - Ipv4Cidr::new([255, 255, 248, 0], 22).unwrap(), > - Ipv4Cidr::new([255, 255, 252, 0], 23).unwrap(), > - Ipv4Cidr::new([255, 255, 254, 0], 24).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 0], 25).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 128], 26).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 192], 27).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 224], 28).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 240], 29).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 248], 30).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 252], 31).unwrap(), > - Ipv4Cidr::new([255, 255, 255, 254], 32).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([0, 0, 0, 0], [0, 0, 0, > 0]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([0, 0, 0, 0], 32).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v4([255, 255, 255, 255], [255, 255, > 255, 255]).unwrap(); > - > - assert_eq!( > - [Ipv4Cidr::new([255, 255, 255, 255], 32).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - } > - > - #[test] > - fn test_ipv6_to_cidrs() { > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1000], > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1000], > - ) > - .unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1000], > 128).unwrap()], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1000], > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2000], > - ) > - .unwrap(); > - > - assert_eq!( > - [ > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1000], > 116).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2000], > 128).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2000], > - ) > - .unwrap(); > - > - assert_eq!( > - [ > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > 128).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1002], > 127).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1004], > 126).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1008], > 125).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1010], > 124).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1020], > 123).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1040], > 122).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1080], > 121).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1100], > 120).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1200], > 119).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1400], > 118).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1800], > 117).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2000], > 128).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > - ) > - .unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > 128).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2001], > - ) > - .unwrap(); > - > - assert_eq!( > - [ > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1001], > 128).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1002], > 127).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1004], > 126).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1008], > 125).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1010], > 124).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1020], > 123).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1040], > 122).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1080], > 121).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1100], > 120).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1200], > 119).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1400], > 118).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x1800], > 117).unwrap(), > - Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0x2000], > 127).unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0], > - [0x2001, 0x0DB8, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF], > - ) > - .unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new([0x2001, 0x0DB8, 0, 0, 0, 0, 0, 0], 64).unwrap()], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0, 0, 0, 0, 0, 0, 0, 0], > - [ > - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFF, > - ], > - ) > - .unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new([0, 0, 0, 0, 0, 0, 0, 0], 0).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0, 0, 0, 0, 0, 0, 0, 0x0001], > - [ > - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFF, > - ], > - ) > - .unwrap(); > - > - assert_eq!( > - [ > - "::1/128".parse::<Ipv6Cidr>().unwrap(), > - "::2/127".parse::<Ipv6Cidr>().unwrap(), > - "::4/126".parse::<Ipv6Cidr>().unwrap(), > - "::8/125".parse::<Ipv6Cidr>().unwrap(), > - "::10/124".parse::<Ipv6Cidr>().unwrap(), > - "::20/123".parse::<Ipv6Cidr>().unwrap(), > - "::40/122".parse::<Ipv6Cidr>().unwrap(), > - "::80/121".parse::<Ipv6Cidr>().unwrap(), > - "::100/120".parse::<Ipv6Cidr>().unwrap(), > - "::200/119".parse::<Ipv6Cidr>().unwrap(), > - "::400/118".parse::<Ipv6Cidr>().unwrap(), > - "::800/117".parse::<Ipv6Cidr>().unwrap(), > - "::1000/116".parse::<Ipv6Cidr>().unwrap(), > - "::2000/115".parse::<Ipv6Cidr>().unwrap(), > - "::4000/114".parse::<Ipv6Cidr>().unwrap(), > - "::8000/113".parse::<Ipv6Cidr>().unwrap(), > - "::1:0/112".parse::<Ipv6Cidr>().unwrap(), > - "::2:0/111".parse::<Ipv6Cidr>().unwrap(), > - "::4:0/110".parse::<Ipv6Cidr>().unwrap(), > - "::8:0/109".parse::<Ipv6Cidr>().unwrap(), > - "::10:0/108".parse::<Ipv6Cidr>().unwrap(), > - "::20:0/107".parse::<Ipv6Cidr>().unwrap(), > - "::40:0/106".parse::<Ipv6Cidr>().unwrap(), > - "::80:0/105".parse::<Ipv6Cidr>().unwrap(), > - "::100:0/104".parse::<Ipv6Cidr>().unwrap(), > - "::200:0/103".parse::<Ipv6Cidr>().unwrap(), > - "::400:0/102".parse::<Ipv6Cidr>().unwrap(), > - "::800:0/101".parse::<Ipv6Cidr>().unwrap(), > - "::1000:0/100".parse::<Ipv6Cidr>().unwrap(), > - "::2000:0/99".parse::<Ipv6Cidr>().unwrap(), > - "::4000:0/98".parse::<Ipv6Cidr>().unwrap(), > - "::8000:0/97".parse::<Ipv6Cidr>().unwrap(), > - "::1:0:0/96".parse::<Ipv6Cidr>().unwrap(), > - "::2:0:0/95".parse::<Ipv6Cidr>().unwrap(), > - "::4:0:0/94".parse::<Ipv6Cidr>().unwrap(), > - "::8:0:0/93".parse::<Ipv6Cidr>().unwrap(), > - "::10:0:0/92".parse::<Ipv6Cidr>().unwrap(), > - "::20:0:0/91".parse::<Ipv6Cidr>().unwrap(), > - "::40:0:0/90".parse::<Ipv6Cidr>().unwrap(), > - "::80:0:0/89".parse::<Ipv6Cidr>().unwrap(), > - "::100:0:0/88".parse::<Ipv6Cidr>().unwrap(), > - "::200:0:0/87".parse::<Ipv6Cidr>().unwrap(), > - "::400:0:0/86".parse::<Ipv6Cidr>().unwrap(), > - "::800:0:0/85".parse::<Ipv6Cidr>().unwrap(), > - "::1000:0:0/84".parse::<Ipv6Cidr>().unwrap(), > - "::2000:0:0/83".parse::<Ipv6Cidr>().unwrap(), > - "::4000:0:0/82".parse::<Ipv6Cidr>().unwrap(), > - "::8000:0:0/81".parse::<Ipv6Cidr>().unwrap(), > - "::1:0:0:0/80".parse::<Ipv6Cidr>().unwrap(), > - "::2:0:0:0/79".parse::<Ipv6Cidr>().unwrap(), > - "::4:0:0:0/78".parse::<Ipv6Cidr>().unwrap(), > - "::8:0:0:0/77".parse::<Ipv6Cidr>().unwrap(), > - "::10:0:0:0/76".parse::<Ipv6Cidr>().unwrap(), > - "::20:0:0:0/75".parse::<Ipv6Cidr>().unwrap(), > - "::40:0:0:0/74".parse::<Ipv6Cidr>().unwrap(), > - "::80:0:0:0/73".parse::<Ipv6Cidr>().unwrap(), > - "::100:0:0:0/72".parse::<Ipv6Cidr>().unwrap(), > - "::200:0:0:0/71".parse::<Ipv6Cidr>().unwrap(), > - "::400:0:0:0/70".parse::<Ipv6Cidr>().unwrap(), > - "::800:0:0:0/69".parse::<Ipv6Cidr>().unwrap(), > - "::1000:0:0:0/68".parse::<Ipv6Cidr>().unwrap(), > - "::2000:0:0:0/67".parse::<Ipv6Cidr>().unwrap(), > - "::4000:0:0:0/66".parse::<Ipv6Cidr>().unwrap(), > - "::8000:0:0:0/65".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:1::/64".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:2::/63".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:4::/62".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:8::/61".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:10::/60".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:20::/59".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:40::/58".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:80::/57".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:100::/56".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:200::/55".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:400::/54".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:800::/53".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:1000::/52".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:2000::/51".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:4000::/50".parse::<Ipv6Cidr>().unwrap(), > - "0:0:0:8000::/49".parse::<Ipv6Cidr>().unwrap(), > - "0:0:1::/48".parse::<Ipv6Cidr>().unwrap(), > - "0:0:2::/47".parse::<Ipv6Cidr>().unwrap(), > - "0:0:4::/46".parse::<Ipv6Cidr>().unwrap(), > - "0:0:8::/45".parse::<Ipv6Cidr>().unwrap(), > - "0:0:10::/44".parse::<Ipv6Cidr>().unwrap(), > - "0:0:20::/43".parse::<Ipv6Cidr>().unwrap(), > - "0:0:40::/42".parse::<Ipv6Cidr>().unwrap(), > - "0:0:80::/41".parse::<Ipv6Cidr>().unwrap(), > - "0:0:100::/40".parse::<Ipv6Cidr>().unwrap(), > - "0:0:200::/39".parse::<Ipv6Cidr>().unwrap(), > - "0:0:400::/38".parse::<Ipv6Cidr>().unwrap(), > - "0:0:800::/37".parse::<Ipv6Cidr>().unwrap(), > - "0:0:1000::/36".parse::<Ipv6Cidr>().unwrap(), > - "0:0:2000::/35".parse::<Ipv6Cidr>().unwrap(), > - "0:0:4000::/34".parse::<Ipv6Cidr>().unwrap(), > - "0:0:8000::/33".parse::<Ipv6Cidr>().unwrap(), > - "0:1::/32".parse::<Ipv6Cidr>().unwrap(), > - "0:2::/31".parse::<Ipv6Cidr>().unwrap(), > - "0:4::/30".parse::<Ipv6Cidr>().unwrap(), > - "0:8::/29".parse::<Ipv6Cidr>().unwrap(), > - "0:10::/28".parse::<Ipv6Cidr>().unwrap(), > - "0:20::/27".parse::<Ipv6Cidr>().unwrap(), > - "0:40::/26".parse::<Ipv6Cidr>().unwrap(), > - "0:80::/25".parse::<Ipv6Cidr>().unwrap(), > - "0:100::/24".parse::<Ipv6Cidr>().unwrap(), > - "0:200::/23".parse::<Ipv6Cidr>().unwrap(), > - "0:400::/22".parse::<Ipv6Cidr>().unwrap(), > - "0:800::/21".parse::<Ipv6Cidr>().unwrap(), > - "0:1000::/20".parse::<Ipv6Cidr>().unwrap(), > - "0:2000::/19".parse::<Ipv6Cidr>().unwrap(), > - "0:4000::/18".parse::<Ipv6Cidr>().unwrap(), > - "0:8000::/17".parse::<Ipv6Cidr>().unwrap(), > - "1::/16".parse::<Ipv6Cidr>().unwrap(), > - "2::/15".parse::<Ipv6Cidr>().unwrap(), > - "4::/14".parse::<Ipv6Cidr>().unwrap(), > - "8::/13".parse::<Ipv6Cidr>().unwrap(), > - "10::/12".parse::<Ipv6Cidr>().unwrap(), > - "20::/11".parse::<Ipv6Cidr>().unwrap(), > - "40::/10".parse::<Ipv6Cidr>().unwrap(), > - "80::/9".parse::<Ipv6Cidr>().unwrap(), > - "100::/8".parse::<Ipv6Cidr>().unwrap(), > - "200::/7".parse::<Ipv6Cidr>().unwrap(), > - "400::/6".parse::<Ipv6Cidr>().unwrap(), > - "800::/5".parse::<Ipv6Cidr>().unwrap(), > - "1000::/4".parse::<Ipv6Cidr>().unwrap(), > - "2000::/3".parse::<Ipv6Cidr>().unwrap(), > - "4000::/2".parse::<Ipv6Cidr>().unwrap(), > - "8000::/1".parse::<Ipv6Cidr>().unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [0, 0, 0, 0, 0, 0, 0, 0], > - [ > - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFE, > - ], > - ) > - .unwrap(); > - > - assert_eq!( > - [ > - "::/1".parse::<Ipv6Cidr>().unwrap(), > - "8000::/2".parse::<Ipv6Cidr>().unwrap(), > - "c000::/3".parse::<Ipv6Cidr>().unwrap(), > - "e000::/4".parse::<Ipv6Cidr>().unwrap(), > - "f000::/5".parse::<Ipv6Cidr>().unwrap(), > - "f800::/6".parse::<Ipv6Cidr>().unwrap(), > - "fc00::/7".parse::<Ipv6Cidr>().unwrap(), > - "fe00::/8".parse::<Ipv6Cidr>().unwrap(), > - "ff00::/9".parse::<Ipv6Cidr>().unwrap(), > - "ff80::/10".parse::<Ipv6Cidr>().unwrap(), > - "ffc0::/11".parse::<Ipv6Cidr>().unwrap(), > - "ffe0::/12".parse::<Ipv6Cidr>().unwrap(), > - "fff0::/13".parse::<Ipv6Cidr>().unwrap(), > - "fff8::/14".parse::<Ipv6Cidr>().unwrap(), > - "fffc::/15".parse::<Ipv6Cidr>().unwrap(), > - "fffe::/16".parse::<Ipv6Cidr>().unwrap(), > - "ffff::/17".parse::<Ipv6Cidr>().unwrap(), > - "ffff:8000::/18".parse::<Ipv6Cidr>().unwrap(), > - "ffff:c000::/19".parse::<Ipv6Cidr>().unwrap(), > - "ffff:e000::/20".parse::<Ipv6Cidr>().unwrap(), > - "ffff:f000::/21".parse::<Ipv6Cidr>().unwrap(), > - "ffff:f800::/22".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fc00::/23".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fe00::/24".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ff00::/25".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ff80::/26".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffc0::/27".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffe0::/28".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fff0::/29".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fff8::/30".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fffc::/31".parse::<Ipv6Cidr>().unwrap(), > - "ffff:fffe::/32".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff::/33".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:8000::/34".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:c000::/35".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:e000::/36".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:f000::/37".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:f800::/38".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fc00::/39".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fe00::/40".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ff00::/41".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ff80::/42".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffc0::/43".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffe0::/44".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fff0::/45".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fff8::/46".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fffc::/47".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:fffe::/48".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff::/49".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:8000::/50".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:c000::/51".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:e000::/52".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:f000::/53".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:f800::/54".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fc00::/55".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fe00::/56".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ff00::/57".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ff80::/58".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffc0::/59".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffe0::/60".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fff0::/61".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fff8::/62".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fffc::/63".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:fffe::/64".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff::/65".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:8000::/66".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:c000::/67".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:e000::/68".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:f000::/69".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:f800::/70".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fc00::/71".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fe00::/72".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ff00::/73".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ff80::/74".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ffc0::/75".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ffe0::/76".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fff0::/77".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fff8::/78".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fffc::/79".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:fffe::/80".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ffff::/81".parse::<Ipv6Cidr>().unwrap(), > - "ffff:ffff:ffff:ffff:ffff:8000::/82" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:c000::/83" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:e000::/84" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:f000::/85" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:f800::/86" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fc00::/87" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fe00::/88" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ff00::/89" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ff80::/90" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffc0::/91" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffe0::/92" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fff0::/93" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fff8::/94" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fffc::/95" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:fffe::/96" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff::/97" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:8000:0/98" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:c000:0/99" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:e000:0/100" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:f000:0/101" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:f800:0/102" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fc00:0/103" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fe00:0/104" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ff00:0/105" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ff80:0/106" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffc0:0/107" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffe0:0/108" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fff0:0/109" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fff8:0/110" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fffc:0/111" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:fffe:0/112" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0/113" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000/114" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:c000/115" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:e000/116" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:f000/117" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:f800/118" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00/119" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00/120" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00/121" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80/122" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0/123" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0/124" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0/125" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8/126" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc/127" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/128" > - .parse::<Ipv6Cidr>() > - .unwrap(), > - ], > - range.to_cidrs().as_slice() > - ); > - > - let range = > - AddressRange::new_v6([0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, > 0, 0, 0]).unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new([0, 0, 0, 0, 0, 0, 0, 0], 128).unwrap(),], > - range.to_cidrs().as_slice() > - ); > - > - let range = AddressRange::new_v6( > - [ > - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFF, > - ], > - [ > - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFF, > - ], > - ) > - .unwrap(); > - > - assert_eq!( > - [Ipv6Cidr::new( > - [0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, > 0xFFFF], > - 128 > - ) > - .unwrap(),], > - range.to_cidrs().as_slice() > - ); > - } > } > + > diff --git a/proxmox-ve-config/src/firewall/types/alias.rs > b/proxmox-ve-config/src/firewall/types/alias.rs > index 7bc2fb8..a463e52 100644 > --- a/proxmox-ve-config/src/firewall/types/alias.rs > +++ b/proxmox-ve-config/src/firewall/types/alias.rs > @@ -2,10 +2,10 @@ use std::fmt::Display; > use std::str::FromStr; > > use anyhow::{bail, format_err, Error}; > +use proxmox_network_types::ip_address::Cidr; > use serde_with::{DeserializeFromStr, SerializeDisplay}; > > use crate::firewall::parse::{match_name, match_non_whitespace}; > -use crate::firewall::types::address::Cidr; > > #[derive(Debug, Clone)] > #[cfg_attr(test, derive(Eq, PartialEq))] > diff --git a/proxmox-ve-config/src/firewall/types/ipset.rs > b/proxmox-ve-config/src/firewall/types/ipset.rs > index fe5a930..2aaf261 100644 > --- a/proxmox-ve-config/src/firewall/types/ipset.rs > +++ b/proxmox-ve-config/src/firewall/types/ipset.rs > @@ -3,10 +3,10 @@ use std::ops::{Deref, DerefMut}; > use std::str::FromStr; > > use anyhow::{bail, format_err, Error}; > +use proxmox_network_types::ip_address::{Cidr, IpRange}; > use serde_with::DeserializeFromStr; > > use crate::firewall::parse::match_non_whitespace; > -use crate::firewall::types::address::{Cidr, IpRange}; > use crate::firewall::types::alias::AliasName; > use crate::guest::vm::NetworkConfig; > > @@ -112,9 +112,9 @@ impl FromStr for IpsetAddress { > } > } > > -impl<T: Into<Cidr>> From<T> for IpsetAddress { > - fn from(cidr: T) -> Self { > - IpsetAddress::Cidr(cidr.into()) > +impl From<Cidr> for IpsetAddress { > + fn from(cidr: Cidr) -> Self { > + IpsetAddress::Cidr(cidr) > } > } > > diff --git a/proxmox-ve-config/src/firewall/types/mod.rs > b/proxmox-ve-config/src/firewall/types/mod.rs > index 8fd551e..567b302 100644 > --- a/proxmox-ve-config/src/firewall/types/mod.rs > +++ b/proxmox-ve-config/src/firewall/types/mod.rs > @@ -7,7 +7,6 @@ pub mod port; > pub mod rule; > pub mod rule_match; > > -pub use address::Cidr; > pub use alias::Alias; > pub use group::Group; > pub use ipset::Ipset; > diff --git a/proxmox-ve-config/src/firewall/types/rule.rs > b/proxmox-ve-config/src/firewall/types/rule.rs > index 2c8f49c..b6b83d2 100644 > --- a/proxmox-ve-config/src/firewall/types/rule.rs > +++ b/proxmox-ve-config/src/firewall/types/rule.rs > @@ -247,13 +247,14 @@ impl FromStr for RuleGroup { > > #[cfg(test)] > mod tests { > + use proxmox_network_types::ip_address::{Cidr, IpRange}; > + > use crate::firewall::types::{ > - address::{IpEntry, IpList, IpRange}, > + address::{IpEntry, IpList}, > alias::{AliasName, AliasScope}, > ipset::{IpsetName, IpsetScope}, > log::LogLevel, > rule_match::{Icmp, IcmpCode, IpAddrMatch, IpMatch, Ports, Protocol, > Udp}, > - Cidr, > }; > > use super::*; > diff --git a/proxmox-ve-config/src/firewall/types/rule_match.rs > b/proxmox-ve-config/src/firewall/types/rule_match.rs > index 94d8624..3256497 100644 > --- a/proxmox-ve-config/src/firewall/types/rule_match.rs > +++ b/proxmox-ve-config/src/firewall/types/rule_match.rs > @@ -7,10 +7,11 @@ use serde::Deserialize; > use anyhow::{bail, format_err, Error}; > use serde::de::IntoDeserializer; > > +use proxmox_network_types::ip_address::Family; > use proxmox_sortable_macro::sortable; > > use crate::firewall::parse::{match_name, match_non_whitespace, SomeStr}; > -use crate::firewall::types::address::{Family, IpList}; > +use crate::firewall::types::address::IpList; > use crate::firewall::types::alias::AliasName; > use crate::firewall::types::ipset::IpsetName; > use crate::firewall::types::log::LogLevel; > @@ -770,7 +771,8 @@ impl fmt::Display for Icmpv6Code { > > #[cfg(test)] > mod tests { > - use crate::firewall::types::{alias::AliasScope::Guest, Cidr}; > + use proxmox_network_types::ip_address::Cidr; > + use crate::firewall::types::alias::AliasScope::Guest; > > use super::*; > > diff --git a/proxmox-ve-config/src/guest/vm.rs > b/proxmox-ve-config/src/guest/vm.rs > index 3476b93..aa47e26 100644 > --- a/proxmox-ve-config/src/guest/vm.rs > +++ b/proxmox-ve-config/src/guest/vm.rs > @@ -1,79 +1,14 @@ > -use core::fmt::Display; > use std::io; > use std::str::FromStr; > -use std::{collections::HashMap, net::Ipv6Addr}; > +use std::collections::HashMap; > > use proxmox_schema::property_string::PropertyIterator; > > use anyhow::{bail, Error}; > -use serde_with::DeserializeFromStr; > +use proxmox_network_types::ip_address::{Ipv4Cidr, Ipv6Cidr}; > +use proxmox_network_types::mac_address::MacAddress; > > use crate::firewall::parse::{match_digits, parse_bool}; > -use crate::firewall::types::address::{Ipv4Cidr, Ipv6Cidr}; > - > -#[derive(Clone, Debug, DeserializeFromStr, PartialEq, Eq, Hash, PartialOrd, > Ord)] > -pub struct MacAddress([u8; 6]); > - > -static LOCAL_PART: [u8; 8] = [0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, > 0x00]; > -static EUI64_MIDDLE_PART: [u8; 2] = [0xFF, 0xFE]; > - > -impl MacAddress { > - pub fn new(address: [u8; 6]) -> Self { > - Self(address) > - } > - > - /// generates a link local IPv6-address according to RFC 4291 (Appendix > A) > - pub fn eui64_link_local_address(&self) -> Ipv6Addr { > - let head = &self.0[..3]; > - let tail = &self.0[3..]; > - > - let mut eui64_address: Vec<u8> = LOCAL_PART > - .iter() > - .chain(head.iter()) > - .chain(EUI64_MIDDLE_PART.iter()) > - .chain(tail.iter()) > - .copied() > - .collect(); > - > - // we need to flip the 7th bit of the first eui64 byte > - eui64_address[8] ^= 0x02; > - > - Ipv6Addr::from( > - TryInto::<[u8; 16]>::try_into(eui64_address).expect("is an u8 > array with 16 entries"), > - ) > - } > -} > - > -impl FromStr for MacAddress { > - type Err = Error; > - > - fn from_str(s: &str) -> Result<Self, Self::Err> { > - let split = s.split(':'); > - > - let parsed = split > - .into_iter() > - .map(|elem| u8::from_str_radix(elem, 16)) > - .collect::<Result<Vec<u8>, _>>() > - .map_err(Error::msg)?; > - > - if parsed.len() != 6 { > - bail!("Invalid amount of elements in MAC address!"); > - } > - > - let address = &parsed.as_slice()[0..6]; > - Ok(Self(address.try_into().unwrap())) > - } > -} > - > -impl Display for MacAddress { > - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { > - write!( > - f, > - "{:<02X}:{:<02X}:{:<02X}:{:<02X}:{:<02X}:{:<02X}", > - self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5] > - ) > - } > -} > > #[derive(Debug, Clone, Copy)] > #[cfg_attr(test, derive(Eq, PartialEq))] > @@ -266,6 +201,8 @@ impl NetworkConfig { > > #[cfg(test)] > mod tests { > + use std::net::Ipv6Addr; > + > use super::*; > > #[test] > @@ -314,7 +251,7 @@ mod tests { > network_device, > NetworkDevice { > model: NetworkDeviceModel::VirtIO, > - mac_address: MacAddress([0xAA, 0xAA, 0xAA, 0x17, 0x19, > 0x81]), > + mac_address: MacAddress::new([0xAA, 0xAA, 0xAA, 0x17, 0x19, > 0x81]), > firewall: true, > ip: None, > ip6: None, > @@ -329,7 +266,7 @@ mod tests { > network_device, > NetworkDevice { > model: NetworkDeviceModel::VirtIO, > - mac_address: MacAddress([0xAA, 0xAA, 0xAA, 0x17, 0x19, > 0x81]), > + mac_address: MacAddress::new([0xAA, 0xAA, 0xAA, 0x17, 0x19, > 0x81]), > firewall: true, > ip: None, > ip6: None, > @@ -345,7 +282,7 @@ mod tests { > network_device, > NetworkDevice { > model: NetworkDeviceModel::Veth, > - mac_address: MacAddress([0xAA, 0xAA, 0xAA, 0xE2, 0x3E, > 0x24]), > + mac_address: MacAddress::new([0xAA, 0xAA, 0xAA, 0xE2, 0x3E, > 0x24]), > firewall: false, > ip: None, > ip6: None, > @@ -435,7 +372,7 @@ vmgenid: 706fbe99-d28b-4047-a9cd-3677c859ca8a" > network_config.network_devices()[&0], > NetworkDevice { > model: NetworkDeviceModel::VirtIO, > - mac_address: MacAddress([0xAA, 0xBB, 0xCC, 0xF2, 0xFE, > 0x75]), > + mac_address: MacAddress::new([0xAA, 0xBB, 0xCC, 0xF2, 0xFE, > 0x75]), > firewall: true, > ip: None, > ip6: None, > @@ -465,7 +402,7 @@ unprivileged: 1" > network_config.network_devices()[&0], > NetworkDevice { > model: NetworkDeviceModel::Veth, > - mac_address: MacAddress([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x11]), > + mac_address: MacAddress::new([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x11]), > firewall: true, > ip: None, > ip6: None, > @@ -476,7 +413,7 @@ unprivileged: 1" > network_config.network_devices()[&2], > NetworkDevice { > model: NetworkDeviceModel::Veth, > - mac_address: MacAddress([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x12]), > + mac_address: MacAddress::new([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x12]), > firewall: false, > ip: > Some(Ipv4Cidr::from_str("123.123.123.123/24").expect("valid ipv4")), > ip6: None, > @@ -487,7 +424,7 @@ unprivileged: 1" > network_config.network_devices()[&5], > NetworkDevice { > model: NetworkDeviceModel::Veth, > - mac_address: MacAddress([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x13]), > + mac_address: MacAddress::new([0xBC, 0x24, 0x11, 0x47, 0x83, > 0x13]), > firewall: true, > ip: None, > ip6: Some(Ipv6Cidr::from_str("fd80::1/64").expect("valid > ipv6")), > diff --git a/proxmox-ve-config/src/host/utils.rs > b/proxmox-ve-config/src/host/utils.rs > index b1dc8e9..3dee72b 100644 > --- a/proxmox-ve-config/src/host/utils.rs > +++ b/proxmox-ve-config/src/host/utils.rs > @@ -1,6 +1,6 @@ > use std::net::{IpAddr, ToSocketAddrs}; > > -use crate::firewall::types::Cidr; > +use proxmox_network_types::ip_address::Cidr; > > use nix::sys::socket::{AddressFamily, SockaddrLike}; > use proxmox_sys::nodename; > diff --git a/proxmox-ve-config/src/sdn/config.rs > b/proxmox-ve-config/src/sdn/config.rs > index 7ee1101..9949be0 100644 > --- a/proxmox-ve-config/src/sdn/config.rs > +++ b/proxmox-ve-config/src/sdn/config.rs > @@ -6,17 +6,16 @@ use std::{ > str::FromStr, > }; > > +use proxmox_network_types::ip_address::{Cidr, IpRange, IpRangeError}; > use proxmox_schema::{property_string::PropertyString, ApiType, ObjectSchema, > StringSchema}; > - > use serde::Deserialize; > use serde_with::{DeserializeFromStr, SerializeDisplay}; > > use crate::{ > common::Allowlist, > firewall::types::{ > - address::{IpRange, IpRangeError}, > ipset::{IpsetEntry, IpsetName, IpsetScope}, > - Cidr, Ipset, > + Ipset, > }, > sdn::{SdnNameError, SubnetName, VnetName, ZoneName}, > }; > @@ -587,10 +586,10 @@ impl SdnConfig { > ipset_all_wo_gateway.push((*subnet.cidr()).into()); > > if let Some(gateway) = subnet.gateway { > - let gateway_nomatch = IpsetEntry::new(gateway, true, > None); > + let gateway_nomatch = > IpsetEntry::new(Cidr::from(gateway), true, None); > ipset_all_wo_gateway.push(gateway_nomatch); > > - ipset_gateway.push(gateway.into()); > + ipset_gateway.push(Cidr::from(gateway).into()); > } > > > ipset_dhcp.extend(subnet.dhcp_range.iter().cloned().map(IpsetEntry::from)); > diff --git a/proxmox-ve-config/src/sdn/ipam.rs > b/proxmox-ve-config/src/sdn/ipam.rs > index 598b835..9c6985b 100644 > --- a/proxmox-ve-config/src/sdn/ipam.rs > +++ b/proxmox-ve-config/src/sdn/ipam.rs > @@ -7,13 +7,16 @@ use std::{ > > use serde::Deserialize; > > +use proxmox_network_types::ip_address::Cidr; > +use proxmox_network_types::mac_address::MacAddress; > + > use crate::{ > common::Allowlist, > firewall::types::{ > - ipset::{IpsetEntry, IpsetScope}, > - Cidr, Ipset, > + ipset::IpsetScope, > + Ipset, > }, > - guest::{types::Vmid, vm::MacAddress}, > + guest::types::Vmid, > sdn::{SdnNameError, SubnetName, ZoneName}, > }; > > @@ -339,7 +342,7 @@ impl Ipam { > .or_insert_with(|| { > Ipset::from_parts(IpsetScope::Sdn, > format!("guest-ipam-{}", entry.vmid)) > }) > - .push(IpsetEntry::from(entry.ip)); > + .push(Cidr::from(entry.ip).into()); > > acc > }) > diff --git a/proxmox-ve-config/src/sdn/mod.rs > b/proxmox-ve-config/src/sdn/mod.rs > index c8dc724..cde6fed 100644 > --- a/proxmox-ve-config/src/sdn/mod.rs > +++ b/proxmox-ve-config/src/sdn/mod.rs > @@ -3,10 +3,9 @@ pub mod ipam; > > use std::{error::Error, fmt::Display, str::FromStr}; > > +use proxmox_network_types::ip_address::Cidr; > use serde_with::DeserializeFromStr; > > -use crate::firewall::types::Cidr; > - > #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] > pub enum SdnNameError { > Empty, > diff --git a/proxmox-ve-config/tests/sdn/main.rs > b/proxmox-ve-config/tests/sdn/main.rs > index 1815bec..2ab0e5c 100644 > --- a/proxmox-ve-config/tests/sdn/main.rs > +++ b/proxmox-ve-config/tests/sdn/main.rs > @@ -3,18 +3,17 @@ use std::{ > str::FromStr, > }; > > -use proxmox_ve_config::{ > - firewall::types::{address::IpRange, Cidr}, > - guest::vm::MacAddress, > - sdn::{ > +use proxmox_network_types::ip_address::{Cidr, IpRange}; > +use proxmox_network_types::mac_address::MacAddress; > + > +use proxmox_ve_config::sdn::{ > config::{ > RunningConfig, SdnConfig, SdnConfigError, SubnetConfig, > VnetConfig, ZoneConfig, > ZoneType, > }, > ipam::{Ipam, IpamDataVm, IpamEntry, IpamJson}, > SubnetName, VnetName, ZoneName, > - }, > -}; > + }; > > #[test] > fn parse_running_config() { _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel