Skip to content

Commit 1583b00

Browse files
committed
Change Ipv6Addr::is_loopback to include IPv4-mapped loopback addresses
1 parent c838138 commit 1583b00

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

library/std/src/net/ip.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1193,25 +1193,45 @@ impl Ipv6Addr {
11931193
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
11941194
}
11951195

1196-
/// Returns [`true`] if this is a loopback address (::1).
1196+
/// Returns [`true`] if this is either:
1197+
/// - the [loopback address] as defined in [IETF RFC 4291 section 2.5.3] (`::1`).
1198+
/// - an IPv4-mapped address representing an IPv4 loopback address as defined in [IETF RFC 1122] (`::ffff:127.0.0.0/104`).
11971199
///
1198-
/// This property is defined in [IETF RFC 4291].
1200+
/// Note that this returns [`false`] for an IPv4-compatible address representing an IPv4 loopback address (`::127.0.0.0/104`).
11991201
///
1200-
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1202+
/// [loopback address]: Ipv6Addr::LOCALHOST
1203+
/// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
1204+
/// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
12011205
///
12021206
/// # Examples
12031207
///
12041208
/// ```
12051209
/// use std::net::Ipv6Addr;
12061210
///
1207-
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
1211+
/// // `true` for the IPv6 loopback address (`::1`)
1212+
/// assert_eq!(Ipv6Addr::LOCALHOST.is_loopback(), true);
12081213
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
1214+
///
1215+
/// use std::net::Ipv4Addr;
1216+
///
1217+
/// // `true` for an IPv4-mapped address representing an IPv4 loopback address (`::ffff:127.0.0.1`)
1218+
/// assert_eq!(Ipv4Addr::LOCALHOST.to_ipv6_mapped().is_loopback(), true);
1219+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), true);
1220+
///
1221+
/// // `false` for an IPv4-compatible address representing an IPv4 loopback address (`::127.0.0.1`)
1222+
/// assert_eq!(Ipv4Addr::LOCALHOST.to_ipv6_compatible().is_loopback(), false);
1223+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7f00, 0x1).is_loopback(), false);
12091224
/// ```
12101225
#[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
12111226
#[stable(since = "1.7.0", feature = "ip_17")]
1227+
#[rustc_allow_const_fn_unstable(const_ipv6)]
12121228
#[inline]
12131229
pub const fn is_loopback(&self) -> bool {
1214-
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
1230+
if let Some(ipv4) = self.to_ipv4_mapped() {
1231+
ipv4.is_loopback()
1232+
} else {
1233+
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
1234+
}
12151235
}
12161236

12171237
/// Returns [`true`] if the address appears to be globally routable.

0 commit comments

Comments
 (0)