From 48daf91e777130516b82b5edc66d0a2e854af4a8 Mon Sep 17 00:00:00 2001 From: Pierre Barre Date: Sat, 11 Jan 2020 17:56:49 +0100 Subject: [PATCH] Fix network handling. Fixes: - `is_subnet_of` was broken if the supernet was not the network address. - Display now prints the network ip and not the initial ip. - Tests that were asserting against `.ip()`. Adds: - A regression test. --- src/ipv4.rs | 34 +++++++++++++++------------------- src/ipv6.rs | 21 ++++++++++----------- src/lib.rs | 8 -------- tests/test_json.rs | 16 ++++++++-------- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/ipv4.rs b/src/ipv4.rs index d9b1db2..b1de013 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -70,17 +70,13 @@ impl Ipv4Network { } } - pub fn ip(&self) -> Ipv4Addr { - self.addr - } - pub fn prefix(&self) -> u8 { self.prefix } /// Checks if the given `Ipv4Network` is a subnet of the other. pub fn is_subnet_of(self, other: Ipv4Network) -> bool { - other.ip() <= self.ip() && other.broadcast() >= self.broadcast() + other.network() <= self.network() && other.broadcast() >= self.broadcast() } /// Checks if the given `Ipv4Network` is a supernet of the other. @@ -90,9 +86,9 @@ impl Ipv4Network { /// Checks if the given `Ipv4Network` is partly contained in other. pub fn overlaps(self, other: Ipv4Network) -> bool { - other.contains(self.ip()) + other.contains(self.network()) || (other.contains(self.broadcast()) - || (self.contains(other.ip()) || (self.contains(other.broadcast())))) + || (self.contains(other.network()) || (self.contains(other.broadcast())))) } /// Returns the mask for this `Ipv4Network`. @@ -217,7 +213,7 @@ impl Ipv4Network { impl fmt::Display for Ipv4Network { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{}/{}", self.ip(), self.prefix()) + write!(fmt, "{}/{}", self.network(), self.prefix()) } } @@ -231,7 +227,7 @@ impl fmt::Display for Ipv4Network { /// /// let new = Ipv4Network::new(Ipv4Addr::new(10, 1, 9, 32), 16).unwrap(); /// let from_cidr: Ipv4Network = "10.1.9.32/16".parse().unwrap(); -/// assert_eq!(new.ip(), from_cidr.ip()); +/// assert_eq!(new.network(), from_cidr.network()); /// assert_eq!(new.prefix(), from_cidr.prefix()); /// ``` impl FromStr for Ipv4Network { @@ -327,21 +323,21 @@ mod test { #[test] fn parse_v4_24bit() { let cidr: Ipv4Network = "127.1.0.0/24".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv4Addr::new(127, 1, 0, 0)); + assert_eq!(cidr.network(), Ipv4Addr::new(127, 1, 0, 0)); assert_eq!(cidr.prefix(), 24); } #[test] fn parse_v4_32bit() { let cidr: Ipv4Network = "127.0.0.0/32".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv4Addr::new(127, 0, 0, 0)); + assert_eq!(cidr.network(), Ipv4Addr::new(127, 0, 0, 0)); assert_eq!(cidr.prefix(), 32); } #[test] fn parse_v4_noprefix() { let cidr: Ipv4Network = "127.0.0.0".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv4Addr::new(127, 0, 0, 0)); + assert_eq!(cidr.network(), Ipv4Addr::new(127, 0, 0, 0)); assert_eq!(cidr.prefix(), 32); } @@ -363,13 +359,6 @@ mod test { assert_eq!(None, cidr); } - #[test] - fn parse_v4_non_zero_host_bits() { - let cidr: Ipv4Network = "10.1.1.1/24".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv4Addr::new(10, 1, 1, 1)); - assert_eq!(cidr.prefix(), 24); - } - #[test] fn parse_v4_fail_prefix() { let cidr: Option = "0/39".parse().ok(); @@ -557,6 +546,13 @@ mod test { ), true, ); + test_cases.insert( + ( + "10.0.0.0/30".parse().unwrap(), + "10.0.0.1/24".parse().unwrap(), + ), + true, + ); test_cases.insert( ( "10.0.0.0/30".parse().unwrap(), diff --git a/src/ipv6.rs b/src/ipv6.rs index 129edab..e8bb9b3 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -112,17 +112,13 @@ impl Ipv6Network { Ipv6Addr::from(broadcast) } - pub fn ip(&self) -> Ipv6Addr { - self.addr - } - pub fn prefix(&self) -> u8 { self.prefix } /// Checks if the given `Ipv6Network` is a subnet of the other. pub fn is_subnet_of(self, other: Ipv6Network) -> bool { - other.ip() <= self.ip() && other.broadcast() >= self.broadcast() + other.network() <= self.network() && other.broadcast() >= self.broadcast() } /// Checks if the given `Ipv6Network` is a supernet of the other. @@ -132,9 +128,9 @@ impl Ipv6Network { /// Checks if the given `Ipv6Network` is partly contained in other. pub fn overlaps(self, other: Ipv6Network) -> bool { - other.contains(self.ip()) + other.contains(self.network()) || (other.contains(self.broadcast()) - || (self.contains(other.ip()) || (self.contains(other.broadcast())))) + || (self.contains(other.network()) || (self.contains(other.broadcast())))) } /// Returns the mask for this `Ipv6Network`. @@ -258,7 +254,7 @@ impl IntoIterator for &'_ Ipv6Network { impl fmt::Display for Ipv6Network { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{}/{}", self.ip(), self.prefix()) + write!(fmt, "{}/{}", self.network(), self.prefix()) } } @@ -326,21 +322,24 @@ mod test { #[test] fn parse_v6() { let cidr: Ipv6Network = "::1/0".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + assert_eq!(cidr.network(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); assert_eq!(cidr.prefix(), 0); } #[test] fn parse_v6_2() { let cidr: Ipv6Network = "FF01:0:0:17:0:0:0:2/64".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2)); + assert_eq!( + cidr.network(), + Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0) + ); assert_eq!(cidr.prefix(), 64); } #[test] fn parse_v6_noprefix() { let cidr: Ipv6Network = "::1".parse().unwrap(); - assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + assert_eq!(cidr.network(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); assert_eq!(cidr.prefix(), 128); } diff --git a/src/lib.rs b/src/lib.rs index 524dd9c..c692725 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,14 +73,6 @@ impl IpNetwork { Self::new(netaddr, prefix) } - /// Returns the IP part of a given `IpNetwork` - pub fn ip(&self) -> IpAddr { - match *self { - IpNetwork::V4(ref a) => IpAddr::V4(a.ip()), - IpNetwork::V6(ref a) => IpAddr::V6(a.ip()), - } - } - /// Returns the prefix of the given `IpNetwork` /// /// # Example diff --git a/tests/test_json.rs b/tests/test_json.rs index 2ad039f..5f03ced 100644 --- a/tests/test_json.rs +++ b/tests/test_json.rs @@ -17,7 +17,7 @@ mod tests { let mystruct: MyStruct = ::serde_json::from_str(json_string).unwrap(); - assert_eq!(mystruct.ipnetwork.ip(), Ipv4Addr::new(127, 1, 0, 0)); + assert_eq!(mystruct.ipnetwork.network(), Ipv4Addr::new(127, 1, 0, 0)); assert_eq!(mystruct.ipnetwork.prefix(), 24); assert_eq!(::serde_json::to_string(&mystruct).unwrap(), json_string); @@ -25,7 +25,7 @@ mod tests { #[test] fn test_ipv6_json() { - let json_string = r#"{"ipnetwork":"::1/0"}"#; + let json_string = r#"{"ipnetwork":"::/0"}"#; #[derive(Serialize, Deserialize)] struct MyStruct { @@ -35,8 +35,8 @@ mod tests { let mystruct: MyStruct = ::serde_json::from_str(json_string).unwrap(); assert_eq!( - mystruct.ipnetwork.ip(), - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1) + mystruct.ipnetwork.network(), + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0) ); assert_eq!(mystruct.ipnetwork.prefix(), 0); @@ -45,7 +45,7 @@ mod tests { #[test] fn test_ipnetwork_json() { - let json_string = r#"{"ipnetwork":["127.1.0.0/24","::1/0"]}"#; + let json_string = r#"{"ipnetwork":["127.1.0.0/24","::/0"]}"#; #[derive(Serialize, Deserialize)] struct MyStruct { @@ -54,11 +54,11 @@ mod tests { let mystruct: MyStruct = ::serde_json::from_str(json_string).unwrap(); - assert_eq!(mystruct.ipnetwork[0].ip(), Ipv4Addr::new(127, 1, 0, 0)); + assert_eq!(mystruct.ipnetwork[0].network(), Ipv4Addr::new(127, 1, 0, 0)); assert_eq!(mystruct.ipnetwork[0].prefix(), 24); assert_eq!( - mystruct.ipnetwork[1].ip(), - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1) + mystruct.ipnetwork[1].network(), + Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0) ); assert_eq!(mystruct.ipnetwork[1].prefix(), 0);