Skip to content

Commit 9f6a747

Browse files
committed
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
1 parent 67291cc commit 9f6a747

File tree

1 file changed

+64
-8
lines changed

1 file changed

+64
-8
lines changed

src/libstd/net/ip.rs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -502,12 +502,19 @@ impl Ipv4Addr {
502502
///
503503
/// The following return false:
504504
///
505-
/// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
506-
/// - the loopback address (127.0.0.0/8)
507-
/// - the link-local address (169.254.0.0/16)
508-
/// - the broadcast address (255.255.255.255/32)
509-
/// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
510-
/// - the unspecified address (0.0.0.0)
505+
/// - private addresses (see [`is_private()`](#method.is_private))
506+
/// - the loopback address (see [`is_loopback()`](#method.is_loopback))
507+
/// - the link-local address (see [`is_link_local()`](#method.is_link_local))
508+
/// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
509+
/// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
510+
/// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
511+
/// 0.0.0.0/8 block
512+
/// - addresses reserved for future protocols (see
513+
/// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
514+
/// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
515+
/// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved())
516+
/// - addresses reserved for networking devices benchmarking (see
517+
/// [`is_benchmarking`](#method.is_benchmarking))
511518
///
512519
/// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
513520
/// [`true`]: ../../std/primitive.bool.html
@@ -520,16 +527,65 @@ impl Ipv4Addr {
520527
/// use std::net::Ipv4Addr;
521528
///
522529
/// fn main() {
530+
/// // private addresses are not global
523531
/// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
524532
/// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
525533
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
534+
///
535+
/// // the 0.0.0.0/8 block is not global
536+
/// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
537+
/// // in particular, the unspecified address is not global
526538
/// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
539+
///
540+
/// // the loopback address is not global
541+
/// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
542+
///
543+
/// // link local addresses are not global
544+
/// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
545+
///
546+
/// // the broadcast address is not global
547+
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
548+
///
549+
/// // the broadcast address is not global
550+
/// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
551+
/// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
552+
/// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
553+
///
554+
/// // shared addresses are not global
555+
/// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
556+
///
557+
/// // addresses reserved for protocol assignment are not global
558+
/// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
559+
/// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
560+
///
561+
/// // addresses reserved for future use are not global
562+
/// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
563+
///
564+
/// // addresses reserved for network devices benchmarking are not global
565+
/// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
566+
///
567+
/// // All the other addresses are global
568+
/// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
527569
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
528570
/// }
529571
/// ```
530572
pub fn is_global(&self) -> bool {
531-
!self.is_private() && !self.is_loopback() && !self.is_link_local() &&
532-
!self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
573+
// check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
574+
// globally routable addresses in the 192.0.0.0/24 range.
575+
if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
576+
return true;
577+
}
578+
!self.is_private()
579+
&& !self.is_loopback()
580+
&& !self.is_link_local()
581+
&& !self.is_broadcast()
582+
&& !self.is_documentation()
583+
&& !self.is_shared()
584+
&& !self.is_ietf_protocol_assignment()
585+
&& !self.is_reserved()
586+
&& !self.is_benchmarking()
587+
// Make sure the address is not in 0.0.0.0/8
588+
&& self.octets()[0] != 0
533589
}
534590

535591
/// Returns [`true`] if this address is part of the Shared Address Space defined in

0 commit comments

Comments
 (0)