From 02d815f3cec5fe7ccc36c3c985fff4279513135e Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:30:26 -0800 Subject: [PATCH 01/20] std::net: site-local ipv6 prefixes are global --- src/libstd/net/ip.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7f9f3b91a600b..14d677b89a0f8 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1104,12 +1104,20 @@ impl Ipv6Addr { /// /// - the loopback address /// - the link-local addresses - /// - the (deprecated) site-local addresses /// - unique local addresses /// - the unspecified address /// - the address range reserved for documentation /// + /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] + /// + /// ```no_rust + /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer + /// be supported in new implementations (i.e., new implementations must treat this prefix as + /// Global Unicast). + /// ``` + /// /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 /// /// # Examples /// @@ -1126,9 +1134,11 @@ impl Ipv6Addr { /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() - && !self.is_loopback() && !self.is_unicast_link_local() - && !self.is_unicast_site_local() && !self.is_unique_local() - && !self.is_unspecified() && !self.is_documentation() + && !self.is_loopback() + && !self.is_unicast_link_local() + && !self.is_unique_local() + && !self.is_unspecified() + && !self.is_documentation() } /// Returns the address's multicast scope if the address is multicast. From 5aea18411ed6baf471af0799f8926f105009dfcc Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:32:03 -0800 Subject: [PATCH 02/20] std::net: improve Ipv6Addr::is_unicast_site_local() doc - quote the RFC - add a link to the RFC - fix markdown --- src/libstd/net/ip.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 14d677b89a0f8..f70e07049f278 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1051,10 +1051,19 @@ impl Ipv6Addr { (self.segments()[0] & 0xffc0) == 0xfe80 } - /// Returns [`true`] if this is a deprecated unicast site-local address - /// (fec0::/10). + /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The + /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as: + /// + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111011| subnet ID | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` /// /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 /// /// # Examples /// From 1f0aa4043b6051602f016b61a393ef5981b5b831 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:33:02 -0800 Subject: [PATCH 03/20] std::net: add Ipv6Addr::is_unicast_link_local_strict() RFC 4291 is a little unclear about what is a unicast link local address. According to section 2.4, the entire fe80::/10 range is reserved for these addresses, but section 2.5.3 defines a stricter format for such addresses. After a discussion[0] is has been decided to add a different method for each definition, so this commit: - renames is_unicast_link_local() into is_unicast_link_local_strict() - relaxed the check in is_unicast_link_local() [0]: https://github.com/rust-lang/rust/issues/27709#issuecomment-400370706 --- src/libstd/net/ip.rs | 102 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f70e07049f278..4dd5e2cafbf24 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1027,12 +1027,81 @@ impl Ipv6Addr { (self.segments()[0] & 0xfe00) == 0xfc00 } - /// Returns [`true`] if the address is unicast and link-local (fe80::/10). + /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`). /// - /// This property is defined in [IETF RFC 4291]. + /// A common mis-conception is to think that "unicast link-local addresses start with + /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses: /// - /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| 0 | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// + /// This method validates the format defined in the RFC and won't recognize the following + /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example. + /// If you need a less strict validation use [`is_unicast_link_local()`] instead. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// fn main() { + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); + /// } + /// ``` + /// + /// # See also + /// + /// - [IETF RFC 4291 section 2.5.6] + /// - [RFC 4291 errata 4406] + /// + /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 + /// [`is_unicast_link_local()`](#method.is_unicast_link_local) + /// + pub fn is_unicast_link_local_strict(&self) -> bool { + (self.segments()[0] & 0xffff) == 0xfe80 + && (self.segments()[1] & 0xffff) == 0 + && (self.segments()[2] & 0xffff) == 0 + && (self.segments()[3] & 0xffff) == 0 + } + + /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`). + /// + /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4], + /// i.e. addresses with the following format: + /// + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| arbitratry value | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// + /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be + /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you + /// need a strict validation fully compliant with the RFC, use + /// [`is_unicast_link_local_strict()`]. /// /// # Examples /// @@ -1042,11 +1111,32 @@ impl Ipv6Addr { /// use std::net::Ipv6Addr; /// /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); /// } /// ``` + /// + /// # See also + /// + /// - [IETF RFC 4291 section 2.4] + /// - [RFC 4291 errata 4406] + /// + /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 + /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 + /// [`is_unicast_link_local_strict()`](#method.is_unicast_link_local_strict) + /// pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } From aea687c3148c7ae48833a0faef7e6ada24fce05c Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:34:04 -0800 Subject: [PATCH 04/20] std::net: fix doc markdown in Ipv6Addr::is_unique_local() --- src/libstd/net/ip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 4dd5e2cafbf24..0fea70c6ed785 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1003,7 +1003,7 @@ impl Ipv6Addr { } } - /// Returns [`true`] if this is a unique local address (fc00::/7). + /// Returns [`true`] if this is a unique local address (`fc00::/7`). /// /// This property is defined in [IETF RFC 4193]. /// From 8f679977e00dba29819aedbcfaf14927a4136430 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:36:23 -0800 Subject: [PATCH 05/20] std::net: add Ipv4Addr::is_reserved() --- src/libstd/net/ip.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 0fea70c6ed785..f94923d28d293 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,34 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] + /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the + /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since + /// it is obviously not reserved for future use. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this + /// // implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// } + /// ``` + pub fn is_reserved(&self) -> bool { + self.octets()[0] & 240 == 240 && !self.is_broadcast() + } + /// Returns [`true`] if this is a multicast address (224.0.0.0/4). /// /// Multicast addresses have a most significant octet between 224 and 239, From de3cf0d5eb30be7b2a297151af1528314664bd69 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:21 -0800 Subject: [PATCH 06/20] std::net: add Ipv4Addr::is_benchmarking() --- src/libstd/net/ip.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f94923d28d293..6e9c6588a1df9 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,31 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for + /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` + /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// [errate 423]: https://www.rfc-editor.org/errata/eid423 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// } + /// ``` + pub fn is_benchmarking(&self) -> bool { + self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 + } + /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since From f87b96773b0fbbfa24781c58af7a73b816c7d658 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:58 -0800 Subject: [PATCH 07/20] std::net: add Ipv4Addr::is_ietf_protocol_assignment() --- src/libstd/net/ip.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6e9c6588a1df9..998642f8346e1 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,40 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to + /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890]. + /// + /// Note that parts of this block are in use: + /// + /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600]) + /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723]) + /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155]) + /// + /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890 + /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600 + /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723 + /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); + /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); + /// } + /// ``` + pub fn is_ietf_protocol_assignment(&self) -> bool { + self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 + } + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. From 67291cc9711eb4ceb717dc0860aba499bcdf55f7 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:39:05 -0800 Subject: [PATCH 08/20] std::net: add Ipv4Addr::is_shared() --- src/libstd/net/ip.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 998642f8346e1..fd6b00619909f 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,28 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is part of the Shared Address Space defined in + /// [IETF RFC 6598] (`100.64.0.0/10`). + /// + /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// } + /// ``` + pub fn is_shared(&self) -> bool { + self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) + } + /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890]. /// From 9f6a747b32d55d0219a909eb29c136efbb98c473 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:40:21 -0800 Subject: [PATCH 09/20] std::net: fix Ipv4Addr::is_global() As per @therealbstern's comment[0]: The implementation of Ipv4::is_global is not complete, according to the IANA IPv4 Special-Purpose Address Registry. - It compares the address to 0.0.0.0, but anything in 0.0.0.0/8 should not be considered global. - 0/8 is not global and is currently forbidden because some systems used to treat it as the local network. - The implementation of Ipv4::is_unspecified is correct. 0.0.0.0 is the unspecified address. - It does not examine 100.64.0.0/10, which is "Shared Address Space" and not global. - Ditto 192.0.0.0/24 (IETF Protocol Assignments), except for 192.0.0.9/32 and 192.0.0.10/32, which are carved out as globally reachable. - 198.18.0.0/15 is for "Benchmarking" and should not be globally reachable. - 240.0.0.0/4 is reserved and not currently reachable --- src/libstd/net/ip.rs | 72 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index fd6b00619909f..8d00bee0e3665 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -502,12 +502,19 @@ impl Ipv4Addr { /// /// The following return false: /// - /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) - /// - the loopback address (127.0.0.0/8) - /// - the link-local address (169.254.0.0/16) - /// - the broadcast address (255.255.255.255/32) - /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24) - /// - the unspecified address (0.0.0.0) + /// - private addresses (see [`is_private()`](#method.is_private)) + /// - the loopback address (see [`is_loopback()`](#method.is_loopback)) + /// - the link-local address (see [`is_link_local()`](#method.is_link_local)) + /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast)) + /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation)) + /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole + /// 0.0.0.0/8 block + /// - addresses reserved for future protocols (see + /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except + /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable + /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved()) + /// - addresses reserved for networking devices benchmarking (see + /// [`is_benchmarking`](#method.is_benchmarking)) /// /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml /// [`true`]: ../../std/primitive.bool.html @@ -520,16 +527,65 @@ impl Ipv4Addr { /// use std::net::Ipv4Addr; /// /// fn main() { + /// // private addresses are not global /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// + /// // the 0.0.0.0/8 block is not global + /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); + /// // in particular, the unspecified address is not global /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); + /// + /// // the loopback address is not global + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); + /// + /// // link local addresses are not global + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); + /// + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// + /// // shared addresses are not global + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// + /// // addresses reserved for protocol assignment are not global + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); + /// + /// // addresses reserved for future use are not global + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// + /// // addresses reserved for network devices benchmarking are not global + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// + /// // All the other addresses are global + /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); /// } /// ``` pub fn is_global(&self) -> bool { - !self.is_private() && !self.is_loopback() && !self.is_link_local() && - !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() + // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two + // globally routable addresses in the 192.0.0.0/24 range. + if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a { + return true; + } + !self.is_private() + && !self.is_loopback() + && !self.is_link_local() + && !self.is_broadcast() + && !self.is_documentation() + && !self.is_shared() + && !self.is_ietf_protocol_assignment() + && !self.is_reserved() + && !self.is_benchmarking() + // Make sure the address is not in 0.0.0.0/8 + && self.octets()[0] != 0 } /// Returns [`true`] if this address is part of the Shared Address Space defined in From 810632000972343fefd0ec37b12f05a665fd12c6 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 16:31:14 -0800 Subject: [PATCH 10/20] std::net: fix documentation markdown --- src/libstd/net/ip.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 8d00bee0e3665..d8c5f27a9981f 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -512,7 +512,7 @@ impl Ipv4Addr { /// - addresses reserved for future protocols (see /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable - /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved()) + /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved) /// - addresses reserved for networking devices benchmarking (see /// [`is_benchmarking`](#method.is_benchmarking)) /// @@ -1237,11 +1237,13 @@ impl Ipv6Addr { /// /// - [IETF RFC 4291 section 2.5.6] /// - [RFC 4291 errata 4406] + /// - [`is_unicast_link_local()`] /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [`true`]: ../../std/primitive.bool.html /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - /// [`is_unicast_link_local()`](#method.is_unicast_link_local) + /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local /// pub fn is_unicast_link_local_strict(&self) -> bool { (self.segments()[0] & 0xffff) == 0xfe80 @@ -1300,7 +1302,7 @@ impl Ipv6Addr { /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 /// [`true`]: ../../std/primitive.bool.html /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - /// [`is_unicast_link_local_strict()`](#method.is_unicast_link_local_strict) + /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict /// pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 From c34bcc658b46fa0368c2faa75c0fa8767afab920 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 16:31:14 -0800 Subject: [PATCH 11/20] std::net: use macros to test ip properties --- src/libstd/net/ip.rs | 524 +++++++++++++++++++++++++++++++------------ 1 file changed, 381 insertions(+), 143 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d8c5f27a9981f..17200d7b94a43 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1786,8 +1786,8 @@ impl From<[u16; 8]> for IpAddr { #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use crate::net::*; - use crate::net::Ipv6MulticastScope::*; use crate::net::test::{tsa, sa6, sa4}; + use crate::str::FromStr; #[test] fn test_from_str_ipv4() { @@ -1951,164 +1951,402 @@ mod tests { #[test] fn ip_properties() { - fn check4(octets: &[u8; 4], unspec: bool, loopback: bool, - global: bool, multicast: bool, documentation: bool) { - let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])); - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_multicast(), multicast); - assert_eq!(ip.is_documentation(), documentation); + macro_rules! ip { + ($s:expr) => { + IpAddr::from_str($s).unwrap() + } } - fn check6(str_addr: &str, unspec: bool, loopback: bool, - global: bool, u_doc: bool, mcast: bool) { - let ip = IpAddr::V6(str_addr.parse().unwrap()); - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_documentation(), u_doc); - assert_eq!(ip.is_multicast(), mcast); + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & doc) == doc { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + }} } - // address unspec loopbk global multicast doc - check4(&[0, 0, 0, 0], true, false, false, false, false); - check4(&[0, 0, 0, 1], false, false, true, false, false); - check4(&[0, 1, 0, 0], false, false, true, false, false); - check4(&[10, 9, 8, 7], false, false, false, false, false); - check4(&[127, 1, 2, 3], false, true, false, false, false); - check4(&[172, 31, 254, 253], false, false, false, false, false); - check4(&[169, 254, 253, 242], false, false, false, false, false); - check4(&[192, 0, 2, 183], false, false, false, false, true); - check4(&[192, 1, 2, 183], false, false, true, false, false); - check4(&[192, 168, 254, 253], false, false, false, false, false); - check4(&[198, 51, 100, 0], false, false, false, false, true); - check4(&[203, 0, 113, 0], false, false, false, false, true); - check4(&[203, 2, 113, 0], false, false, true, false, false); - check4(&[224, 0, 0, 0], false, false, true, true, false); - check4(&[239, 255, 255, 255], false, false, true, true, false); - check4(&[255, 255, 255, 255], false, false, false, false, false); - - // address unspec loopbk global doc mcast - check6("::", true, false, false, false, false); - check6("::1", false, true, false, false, false); - check6("::0.0.0.2", false, false, true, false, false); - check6("1::", false, false, true, false, false); - check6("fc00::", false, false, false, false, false); - check6("fdff:ffff::", false, false, false, false, false); - check6("fe80:ffff::", false, false, false, false, false); - check6("febf:ffff::", false, false, false, false, false); - check6("fec0::", false, false, false, false, false); - check6("ff01::", false, false, false, false, true); - check6("ff02::", false, false, false, false, true); - check6("ff03::", false, false, false, false, true); - check6("ff04::", false, false, false, false, true); - check6("ff05::", false, false, false, false, true); - check6("ff08::", false, false, false, false, true); - check6("ff0e::", false, false, true, false, true); - check6("2001:db8:85a3::8a2e:370:7334", false, false, false, true, false); - check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true, false, false); + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; + + check!("0.0.0.0", unspec); + check!("0.0.0.1", global); + check!("0.1.0.0", global); + check!("10.9.8.7"); + check!("127.1.2.3", loopback); + check!("172.31.254.253"); + check!("169.254.253.242"); + check!("192.0.2.183", doc); + check!("192.1.2.183", global); + check!("192.168.254.253"); + check!("198.51.100.0", doc); + check!("203.0.113.0", doc); + check!("203.2.113.0", global); + check!("224.0.0.0", global|multicast); + check!("239.255.255.255", global|multicast); + check!("255.255.255.255"); + + check!("::", unspec); + check!("::1", loopback); + check!("::0.0.0.2", global); + check!("1::", global); + check!("fc00::"); + check!("fdff:ffff::"); + check!("fe80:ffff::"); + check!("febf:ffff::"); + check!("fec0::"); + check!("ff01::", multicast); + check!("ff02::", multicast); + check!("ff03::", multicast); + check!("ff04::", multicast); + check!("ff05::", multicast); + check!("ff08::", multicast); + check!("ff0e::", global|multicast); + check!("2001:db8:85a3::8a2e:370:7334", doc); + check!("102:304:506:708:90a:b0c:d0e:f10", global); } #[test] fn ipv4_properties() { - fn check(octets: &[u8; 4], unspec: bool, loopback: bool, - private: bool, link_local: bool, global: bool, - multicast: bool, broadcast: bool, documentation: bool) { - let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]); - assert_eq!(octets, &ip.octets()); - - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_private(), private); - assert_eq!(ip.is_link_local(), link_local); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_multicast(), multicast); - assert_eq!(ip.is_broadcast(), broadcast); - assert_eq!(ip.is_documentation(), documentation); + macro_rules! ip { + ($s:expr) => { + Ipv4Addr::from_str($s).unwrap() + } + } + + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let private: u8 = 1 << 2; + let link_local: u8 = 1 << 3; + let global: u8 = 1 << 4; + let multicast: u8 = 1 << 5; + let broadcast: u8 = 1 << 6; + let documentation: u8 = 1 << 7; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & private) == private { + assert!(ip!($s).is_private()); + } else { + assert!(!ip!($s).is_private()); + } + + if ($mask & link_local) == link_local { + assert!(ip!($s).is_link_local()); + } else { + assert!(!ip!($s).is_link_local()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & broadcast) == broadcast { + assert!(ip!($s).is_broadcast()); + } else { + assert!(!ip!($s).is_broadcast()); + } + + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + }} } - // address unspec loopbk privt linloc global multicast brdcast doc - check(&[0, 0, 0, 0], true, false, false, false, false, false, false, false); - check(&[0, 0, 0, 1], false, false, false, false, true, false, false, false); - check(&[0, 1, 0, 0], false, false, false, false, true, false, false, false); - check(&[10, 9, 8, 7], false, false, true, false, false, false, false, false); - check(&[127, 1, 2, 3], false, true, false, false, false, false, false, false); - check(&[172, 31, 254, 253], false, false, true, false, false, false, false, false); - check(&[169, 254, 253, 242], false, false, false, true, false, false, false, false); - check(&[192, 0, 2, 183], false, false, false, false, false, false, false, true); - check(&[192, 1, 2, 183], false, false, false, false, true, false, false, false); - check(&[192, 168, 254, 253], false, false, true, false, false, false, false, false); - check(&[198, 51, 100, 0], false, false, false, false, false, false, false, true); - check(&[203, 0, 113, 0], false, false, false, false, false, false, false, true); - check(&[203, 2, 113, 0], false, false, false, false, true, false, false, false); - check(&[224, 0, 0, 0], false, false, false, false, true, true, false, false); - check(&[239, 255, 255, 255], false, false, false, false, true, true, false, false); - check(&[255, 255, 255, 255], false, false, false, false, false, false, true, false); + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let private: u8 = 1 << 2; + let link_local: u8 = 1 << 3; + let global: u8 = 1 << 4; + let multicast: u8 = 1 << 5; + let broadcast: u8 = 1 << 6; + let documentation: u8 = 1 << 7; + + check!("0.0.0.0", unspec); + check!("0.0.0.1", global); + check!("0.1.0.0", global); + check!("10.9.8.7", private); + check!("127.1.2.3", loopback); + check!("172.31.254.253", private); + check!("169.254.253.242", link_local); + check!("192.0.2.183", documentation); + check!("192.1.2.183", global); + check!("192.168.254.253", private); + check!("198.51.100.0", documentation); + check!("203.0.113.0", documentation); + check!("203.2.113.0", global); + check!("224.0.0.0", global|multicast); + check!("239.255.255.255", global|multicast); + check!("255.255.255.255", broadcast); } #[test] fn ipv6_properties() { - fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool, - unique_local: bool, global: bool, - u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool, - m_scope: Option) { - let ip: Ipv6Addr = str_addr.parse().unwrap(); - assert_eq!(str_addr, ip.to_string()); - assert_eq!(&ip.octets(), octets); - assert_eq!(Ipv6Addr::from(*octets), ip); - - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_unique_local(), unique_local); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_unicast_link_local(), u_link_local); - assert_eq!(ip.is_unicast_site_local(), u_site_local); - assert_eq!(ip.is_unicast_global(), u_global); - assert_eq!(ip.is_documentation(), u_doc); - assert_eq!(ip.multicast_scope(), m_scope); - assert_eq!(ip.is_multicast(), m_scope.is_some()); + macro_rules! ip { + ($s:expr) => { + Ipv6Addr::from_str($s).unwrap() + } + } + + macro_rules! check { + ($s:expr, &[$($octet:expr),*], $mask:expr) => { + assert_eq!($s, ip!($s).to_string()); + let octets = &[$($octet),*]; + assert_eq!(&ip!($s).octets(), octets); + assert_eq!(Ipv6Addr::from(*octets), ip!($s)); + + let unspecified: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let unique_local: u16 = 1 << 2; + let global: u16 = 1 << 3; + let unicast_link_local: u16 = 1 << 4; + let unicast_site_local: u16 = 1 << 5; + let unicast_global: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let multicast_interface_local: u16 = 1 << 8; + let multicast_link_local: u16 = 1 << 9; + let multicast_realm_local: u16 = 1 << 10; + let multicast_admin_local: u16 = 1 << 11; + let multicast_site_local: u16 = 1 << 12; + let multicast_organization_local: u16 = 1 << 13; + let multicast_global: u16 = 1 << 14; + let multicast: u16 = multicast_interface_local + | multicast_admin_local + | multicast_global + | multicast_link_local + | multicast_realm_local + | multicast_site_local + | multicast_organization_local; + + if ($mask & unspecified) == unspecified { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + if ($mask & unique_local) == unique_local { + assert!(ip!($s).is_unique_local()); + } else { + assert!(!ip!($s).is_unique_local()); + } + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + if ($mask & unicast_link_local) == unicast_link_local { + assert!(ip!($s).is_unicast_link_local()); + } else { + assert!(!ip!($s).is_unicast_link_local()); + } + if ($mask & unicast_site_local) == unicast_site_local { + assert!(ip!($s).is_unicast_site_local()); + } else { + assert!(!ip!($s).is_unicast_site_local()); + } + if ($mask & unicast_global) == unicast_global { + assert!(ip!($s).is_unicast_global()); + } else { + assert!(!ip!($s).is_unicast_global()); + } + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + if ($mask & multicast) != 0 { + assert!(ip!($s).multicast_scope().is_some()); + assert!(ip!($s).is_multicast()); + } else { + assert!(ip!($s).multicast_scope().is_none()); + assert!(!ip!($s).is_multicast()); + } + if ($mask & multicast_interface_local) == multicast_interface_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::InterfaceLocal); + } + if ($mask & multicast_link_local) == multicast_link_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::LinkLocal); + } + if ($mask & multicast_realm_local) == multicast_realm_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::RealmLocal); + } + if ($mask & multicast_admin_local) == multicast_admin_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::AdminLocal); + } + if ($mask & multicast_site_local) == multicast_site_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::SiteLocal); + } + if ($mask & multicast_organization_local) == multicast_organization_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::OrganizationLocal); + } + if ($mask & multicast_global) == multicast_global { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::Global); + } + } } - // unspec loopbk uniqlo global unill unisl uniglo doc mscope - check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - true, false, false, false, false, false, false, false, None); - check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], - false, true, false, false, false, false, false, false, None); - check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], - false, false, false, true, false, false, true, false, None); - check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, true, false, false, true, false, None); - check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, true, false, false, false, false, false, None); - check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, true, false, false, false, false, false, None); - check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, true, false, false, false, None); - check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, true, false, false, false, None); - check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, true, false, false, None); - check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(InterfaceLocal)); - check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(LinkLocal)); - check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(RealmLocal)); - check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(AdminLocal)); - check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(SiteLocal)); - check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(OrganizationLocal)); - check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, true, false, false, false, false, Some(Global)); - check("2001:db8:85a3::8a2e:370:7334", - &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], - false, false, false, false, false, false, false, true, None); - check("102:304:506:708:90a:b0c:d0e:f10", - &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], - false, false, false, true, false, false, true, false, None); + let unspecified: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let unique_local: u16 = 1 << 2; + let global: u16 = 1 << 3; + let unicast_link_local: u16 = 1 << 4; + let unicast_site_local: u16 = 1 << 5; + let unicast_global: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let multicast_interface_local: u16 = 1 << 8; + let multicast_link_local: u16 = 1 << 9; + let multicast_realm_local: u16 = 1 << 10; + let multicast_admin_local: u16 = 1 << 11; + let multicast_site_local: u16 = 1 << 12; + let multicast_organization_local: u16 = 1 << 13; + let multicast_global: u16 = 1 << 14; + + check!("::", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unspecified); + + check!("::1", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + loopback); + + check!("::0.0.0.2", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], + global | unicast_global); + + check!("1::", + &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global); + + check!("fc00::", + &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unique_local); + + check!("fdff:ffff::", + &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unique_local); + + check!("fe80:ffff::", + &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("febf:ffff::", + &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("fec0::", + &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_site_local); + + check!("ff01::", + &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_interface_local); + + check!("ff02::", + &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_link_local); + + check!("ff03::", + &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_realm_local); + + check!("ff04::", + &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_admin_local); + + check!("ff05::", + &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_site_local); + + check!("ff08::", + &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_organization_local); + + check!("ff0e::", + &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_global | global); + + check!("2001:db8:85a3::8a2e:370:7334", + &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], + documentation); + + check!("102:304:506:708:90a:b0c:d0e:f10", + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + global| unicast_global); } #[test] From c302d2c78f94839473a7e9be3eb4756d0f1e2508 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 20 Apr 2019 22:33:05 +0200 Subject: [PATCH 12/20] std::net: fix Ipv4addr::is_global() tests Ipv4addr::is_global() previously considered 0/8 was global, but has now been fixed, so these tests needed to be fixed as well. --- src/libstd/net/ip.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 17200d7b94a43..cd78eb05c11ac 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2008,8 +2008,8 @@ mod tests { let doc: u8 = 1 << 4; check!("0.0.0.0", unspec); - check!("0.0.0.1", global); - check!("0.1.0.0", global); + check!("0.0.0.1"); + check!("0.1.0.0"); check!("10.9.8.7"); check!("127.1.2.3", loopback); check!("172.31.254.253"); @@ -2127,8 +2127,8 @@ mod tests { let documentation: u8 = 1 << 7; check!("0.0.0.0", unspec); - check!("0.0.0.1", global); - check!("0.1.0.0", global); + check!("0.0.0.1"); + check!("0.1.0.0"); check!("10.9.8.7", private); check!("127.1.2.3", loopback); check!("172.31.254.253", private); From 99d9bb640f0ea95ae6a7346c82a61008b2363c16 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sun, 21 Apr 2019 19:47:54 +0200 Subject: [PATCH 13/20] std::net: fix tests for site-local ipv6 addresses Ipv6Addr::is_unicast_global() now returns `true` for unicast site local addresses, since they are deprecated. --- src/libstd/net/ip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index cd78eb05c11ac..6f39575da2c49 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2032,7 +2032,7 @@ mod tests { check!("fdff:ffff::"); check!("fe80:ffff::"); check!("febf:ffff::"); - check!("fec0::"); + check!("fec0::", global); check!("ff01::", multicast); check!("ff02::", multicast); check!("ff03::", multicast); @@ -2310,7 +2310,7 @@ mod tests { check!("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_site_local); + unicast_site_local|unicast_global|global); check!("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], From 40d0127a091dbf3eb55ef57de5facc4983ee472d Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 15:27:14 +0200 Subject: [PATCH 14/20] std::net: tests for Ipv6addr::is_unicast_link_local{_strict}() --- src/libstd/net/ip.rs | 69 +++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6f39575da2c49..7ce8974e09fd5 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2164,16 +2164,17 @@ mod tests { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 5; - let unicast_global: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let multicast_interface_local: u16 = 1 << 8; - let multicast_link_local: u16 = 1 << 9; - let multicast_realm_local: u16 = 1 << 10; - let multicast_admin_local: u16 = 1 << 11; - let multicast_site_local: u16 = 1 << 12; - let multicast_organization_local: u16 = 1 << 13; - let multicast_global: u16 = 1 << 14; + let unicast_link_local_strict: u16 = 1 << 5; + let unicast_site_local: u16 = 1 << 6; + let unicast_global: u16 = 1 << 7; + let documentation: u16 = 1 << 8; + let multicast_interface_local: u16 = 1 << 9; + let multicast_link_local: u16 = 1 << 10; + let multicast_realm_local: u16 = 1 << 11; + let multicast_admin_local: u16 = 1 << 12; + let multicast_site_local: u16 = 1 << 13; + let multicast_organization_local: u16 = 1 << 14; + let multicast_global: u16 = 1 << 15; let multicast: u16 = multicast_interface_local | multicast_admin_local | multicast_global @@ -2207,6 +2208,11 @@ mod tests { } else { assert!(!ip!($s).is_unicast_link_local()); } + if ($mask & unicast_link_local_strict) == unicast_link_local_strict { + assert!(ip!($s).is_unicast_link_local_strict()); + } else { + assert!(!ip!($s).is_unicast_link_local_strict()); + } if ($mask & unicast_site_local) == unicast_site_local { assert!(ip!($s).is_unicast_site_local()); } else { @@ -2265,16 +2271,17 @@ mod tests { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 5; - let unicast_global: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let multicast_interface_local: u16 = 1 << 8; - let multicast_link_local: u16 = 1 << 9; - let multicast_realm_local: u16 = 1 << 10; - let multicast_admin_local: u16 = 1 << 11; - let multicast_site_local: u16 = 1 << 12; - let multicast_organization_local: u16 = 1 << 13; - let multicast_global: u16 = 1 << 14; + let unicast_link_local_strict: u16 = 1 << 5; + let unicast_site_local: u16 = 1 << 6; + let unicast_global: u16 = 1 << 7; + let documentation: u16 = 1 << 8; + let multicast_interface_local: u16 = 1 << 9; + let multicast_link_local: u16 = 1 << 10; + let multicast_realm_local: u16 = 1 << 11; + let multicast_admin_local: u16 = 1 << 12; + let multicast_site_local: u16 = 1 << 13; + let multicast_organization_local: u16 = 1 << 14; + let multicast_global: u16 = 1 << 15; check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -2304,10 +2311,32 @@ mod tests { &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + check!("fe80::", + &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local|unicast_link_local_strict); + check!("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + check!("febf::", + &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + &[0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + unicast_link_local); + + check!("fe80::ffff:ffff:ffff:ffff", + &[0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + unicast_link_local|unicast_link_local_strict); + + check!("fe80:0:0:1::", + &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + check!("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_site_local|unicast_global|global); From 9dcfd9f58ca808d586c186f983f5572667e56471 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 15:47:41 +0200 Subject: [PATCH 15/20] std::net: tests for Ipv4addr::is_benchmarking() also add test to Ipaddr, making sure that these addresses are not global. --- src/libstd/net/ip.rs | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7ce8974e09fd5..5e93a6c1e867b 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2023,6 +2023,9 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255"); + check!("198.18.0.0"); + check!("198.18.54.2"); + check!("198.19.255.255"); check!("::", unspec); check!("::1", loopback); @@ -2058,14 +2061,15 @@ mod tests { }; ($s:expr, $mask:expr) => {{ - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let private: u8 = 1 << 2; - let link_local: u8 = 1 << 3; - let global: u8 = 1 << 4; - let multicast: u8 = 1 << 5; - let broadcast: u8 = 1 << 6; - let documentation: u8 = 1 << 7; + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2114,17 +2118,24 @@ mod tests { } else { assert!(!ip!($s).is_documentation()); } + + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } }} } - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let private: u8 = 1 << 2; - let link_local: u8 = 1 << 3; - let global: u8 = 1 << 4; - let multicast: u8 = 1 << 5; - let broadcast: u8 = 1 << 6; - let documentation: u8 = 1 << 7; + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2142,6 +2153,9 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255", broadcast); + check!("198.18.0.0", benchmarking); + check!("198.18.54.2", benchmarking); + check!("198.19.255.255", benchmarking); } #[test] From a2bead8761306a46079edc8cc7cff84b85d8f891 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 16:00:58 +0200 Subject: [PATCH 16/20] std::net: tests for Ipv4addr::is_ietf_protocol_assignment() Also add tests to IpAddr to make sure these addresses are not global. --- src/libstd/net/ip.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 5e93a6c1e867b..4ff47257c3fc0 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2023,9 +2023,14 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255"); + // make sure benchmarking addresses are not global check!("198.18.0.0"); check!("198.18.54.2"); check!("198.19.255.255"); + // make sure addresses reserved for protocol assignment are not global + check!("192.0.0.0"); + check!("192.0.0.255"); + check!("192.0.0.100"); check!("::", unspec); check!("::1", loopback); @@ -2070,6 +2075,7 @@ mod tests { let broadcast: u16 = 1 << 6; let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; + let ietf_protocol_assignment: u16 = 1 << 9; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2124,6 +2130,12 @@ mod tests { } else { assert!(!ip!($s).is_benchmarking()); } + + if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment { + assert!(ip!($s).is_ietf_protocol_assignment()); + } else { + assert!(!ip!($s).is_ietf_protocol_assignment()); + } }} } @@ -2136,6 +2148,7 @@ mod tests { let broadcast: u16 = 1 << 6; let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; + let ietf_protocol_assignment: u16 = 1 << 9; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2156,6 +2169,9 @@ mod tests { check!("198.18.0.0", benchmarking); check!("198.18.54.2", benchmarking); check!("198.19.255.255", benchmarking); + check!("192.0.0.0", ietf_protocol_assignment); + check!("192.0.0.255", ietf_protocol_assignment); + check!("192.0.0.100", ietf_protocol_assignment); } #[test] From 66627777b54843dc6c5630e27dd995258b05ac6d Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 16:14:28 +0200 Subject: [PATCH 17/20] std::net: tests for Ipv4addr::is_reserved() Also add tests to IpAddr for make sure these addresses are not global or multicast. --- src/libstd/net/ip.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 4ff47257c3fc0..1322733bb15b8 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2031,6 +2031,10 @@ mod tests { check!("192.0.0.0"); check!("192.0.0.255"); check!("192.0.0.100"); + // make sure reserved addresses are not global + check!("240.0.0.0"); + check!("251.54.1.76"); + check!("254.255.255.255"); check!("::", unspec); check!("::1", loopback); @@ -2076,6 +2080,7 @@ mod tests { let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; + let reserved: u16 = 1 << 10; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2136,6 +2141,12 @@ mod tests { } else { assert!(!ip!($s).is_ietf_protocol_assignment()); } + + if ($mask & reserved) == reserved { + assert!(ip!($s).is_reserved()); + } else { + assert!(!ip!($s).is_reserved()); + } }} } @@ -2149,6 +2160,7 @@ mod tests { let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; + let reserved: u16 = 1 << 10; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2172,6 +2184,9 @@ mod tests { check!("192.0.0.0", ietf_protocol_assignment); check!("192.0.0.255", ietf_protocol_assignment); check!("192.0.0.100", ietf_protocol_assignment); + check!("240.0.0.0", reserved); + check!("251.54.1.76", reserved); + check!("254.255.255.255", reserved); } #[test] From 634dcd00b4f4a57cea0baae85d364d433897bf59 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 10:38:26 +0200 Subject: [PATCH 18/20] std::net: add warning in Ipv6Addr::is_unicast_site_local() doc site-local addresses are deprecated, so we should warn users about it. --- src/libstd/net/ip.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 1322733bb15b8..e3e257f5ac177 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1335,6 +1335,14 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); /// } /// ``` + /// + /// # Warning + /// + /// As per [RFC 3879], the whole `FEC0::/10` prefix is + /// deprecated. New software must not support site-local + /// addresses. + /// + /// [RFC 3879]: https://tools.ietf.org/html/rfc3879 pub fn is_unicast_site_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfec0 } From fe718ef07f56457740b59b196eed0f1226137895 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 10:40:15 +0200 Subject: [PATCH 19/20] std::net: add warning in Ipv4addr::is_reserved() documentation See @the8472 comment's on Github: https://github.com/rust-lang/rust/pull/60145#issuecomment-485424229 > I don't think is_reserved including ranges marked for future use is > a good idea since those future uses may be realized at at some point > and then old software with is_reserved filters may have false > positives. This is not a hypothetical concern, such issues have been > encountered before when IANA assigned previously reserved /8 address > blocks. --- src/libstd/net/ip.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index e3e257f5ac177..6ea49de49af64 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -677,6 +677,13 @@ impl Ipv4Addr { /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 /// [`true`]: ../../std/primitive.bool.html /// + /// # Warning + /// + /// As IANA assigns new addresses, this method will be + /// updated. This may result in non-reserved addresses being + /// treated as reserved in code that relies on an outdated version + /// of this method. + /// /// # Examples /// /// ``` From cddb838043fb0201c09bf0a8692001b04b3bec1a Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 12:00:23 +0200 Subject: [PATCH 20/20] std::net: tests for Ipv4addr::is_shared() --- src/libstd/net/ip.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6ea49de49af64..6b504056e5f87 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2050,6 +2050,10 @@ mod tests { check!("240.0.0.0"); check!("251.54.1.76"); check!("254.255.255.255"); + // make sure shared addresses are not global + check!("100.64.0.0"); + check!("100.127.255.255"); + check!("100.100.100.0"); check!("::", unspec); check!("::1", loopback); @@ -2096,6 +2100,7 @@ mod tests { let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2162,6 +2167,12 @@ mod tests { } else { assert!(!ip!($s).is_reserved()); } + + if ($mask & shared) == shared { + assert!(ip!($s).is_shared()); + } else { + assert!(!ip!($s).is_shared()); + } }} } @@ -2176,6 +2187,7 @@ mod tests { let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2202,6 +2214,9 @@ mod tests { check!("240.0.0.0", reserved); check!("251.54.1.76", reserved); check!("254.255.255.255", reserved); + check!("100.64.0.0", shared); + check!("100.127.255.255", shared); + check!("100.100.100.0", shared); } #[test]