From 1be13078f50c68e2d21c498d024bdec98b8ed2af Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:30:26 -0800 Subject: [PATCH 01/11] 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 8685cb7388705..ff3b34e97c222 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1105,12 +1105,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 /// @@ -1127,9 +1135,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 1f09865d955a6ce5e4c939935ada9ea26a7edd46 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:32:03 -0800 Subject: [PATCH 02/11] 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 ff3b34e97c222..976634c407060 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1052,10 +1052,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 d2eae67293d4e3c143df4d0e2660f7b4c7c97f41 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:33:02 -0800 Subject: [PATCH 03/11] 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 976634c407060..7628677b7a044 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1028,12 +1028,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 /// @@ -1043,11 +1112,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 3c0f8531c9020cced12ce94f8337d009b2264a0e Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:34:04 -0800 Subject: [PATCH 04/11] 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 7628677b7a044..e3d02b9129e4d 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1004,7 +1004,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 268c5430a49a79054d93800ebf085f9b524912f7 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:36:23 -0800 Subject: [PATCH 05/11] std::net: add Ipv6Addr::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 e3d02b9129e4d..4be85ac5147b7 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -541,6 +541,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 f0dd4f973108dbb4793591bfb1dde039103f9821 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:21 -0800 Subject: [PATCH 06/11] std::net: add Ipv6Addr::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 4be85ac5147b7..f609c06216b43 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -541,6 +541,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 8d23452a8f6b3a8c6eac0e586091def6ce3c91e0 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:58 -0800 Subject: [PATCH 07/11] std::net: add Ipv6Addr::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 f609c06216b43..ed188d2f18763 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -541,6 +541,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 83500ff8eabf0abfaa1e3c154292a6d3f41ab75b Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:39:05 -0800 Subject: [PATCH 08/11] std::net: add Ipv6Addr::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 ed188d2f18763..8b4878bd81e3a 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -541,6 +541,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 ece344a8603220616a49ed57dbaa593137b6cb7e Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:40:21 -0800 Subject: [PATCH 09/11] 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 8b4878bd81e3a..ac89c210c832b 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -511,12 +511,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 @@ -529,16 +536,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 bf19000eccac403e94f45f16b1eb7c44bb432645 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:48:54 -0800 Subject: [PATCH 10/11] wip: fix tests --- 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 ac89c210c832b..ed083891b9203 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1950,8 +1950,8 @@ mod tests { // 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(&[0, 0, 0, 1], false, false, false, false, false); + check4(&[0, 1, 0, 0], false, false, false, 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); @@ -2007,8 +2007,8 @@ mod tests { // 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(&[0, 0, 0, 1], false, false, false, false, false, false, false, false); + check(&[0, 1, 0, 0], false, false, false, false, false, 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); From f47f20d7dd011645458d2620e12fc909e7aa40e5 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 16:31:14 -0800 Subject: [PATCH 11/11] fix markdown --- src/libstd/net/ip.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index ed083891b9203..90c3530cff1ff 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1238,11 +1238,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 @@ -1301,7 +1303,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