Skip to content

Commit 3df25ae

Browse files
committed
Auto merge of #75019 - nanpuyue:to_ipv4_mapped, r=LukasKalbertodt
Add Ipv6Addr::to_ipv4_mapped * add Ipv6Addr::to_ipv4_mapped * ~~deprecate Ipv4Addr::to_ipv6_compatible & Ipv6Addr::to_ipv4~~ reference: #75150 According to [IETF RFC 4291](https://tools.ietf.org/html/rfc4291#page-10), the "IPv4-Compatible IPv6 address" is deprecated. > 2.5.5.1. IPv4-Compatible IPv6 Address > > The "IPv4-Compatible IPv6 address" was defined to assist in the IPv6 > transition. The format of the "IPv4-Compatible IPv6 address" is as > follows: > > | 80 bits | 16 | 32 bits | > +--------------------------------------+--------------------------+ > |0000..............................0000|0000| IPv4 address | > +--------------------------------------+----+---------------------+ > > Note: The IPv4 address used in the "IPv4-Compatible IPv6 address" > must be a globally-unique IPv4 unicast address. > > The "IPv4-Compatible IPv6 address" is now deprecated because the > current IPv6 transition mechanisms no longer use these addresses. > New or updated implementations are not required to support this > address type. And the current implementation of `Ipv4Addr::to_ipv6_compatible`is incorrect: it does not check whether the IPv4 address is a globally-unique IPv4 unicast address. Please let me know if there are any issues with this pull request.
2 parents ded20c9 + d892a07 commit 3df25ae

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

library/std/src/net/ip.rs

+40
Original file line numberDiff line numberDiff line change
@@ -1473,6 +1473,37 @@ impl Ipv6Addr {
14731473
(self.segments()[0] & 0xff00) == 0xff00
14741474
}
14751475

1476+
/// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
1477+
/// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
1478+
///
1479+
/// `::ffff:a.b.c.d` becomes `a.b.c.d`.
1480+
/// All addresses *not* starting with `::ffff` will return `None`.
1481+
///
1482+
/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1483+
/// [`None`]: ../../std/option/enum.Option.html#variant.None
1484+
/// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1485+
///
1486+
/// # Examples
1487+
///
1488+
/// ```
1489+
/// #![feature(ip)]
1490+
///
1491+
/// use std::net::{Ipv4Addr, Ipv6Addr};
1492+
///
1493+
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
1494+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
1495+
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
1496+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
1497+
/// ```
1498+
pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1499+
match self.octets() {
1500+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1501+
Some(Ipv4Addr::new(a, b, c, d))
1502+
}
1503+
_ => None,
1504+
}
1505+
}
1506+
14761507
/// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
14771508
/// neither IPv4-compatible or IPv4-mapped.
14781509
///
@@ -2070,6 +2101,15 @@ mod tests {
20702101
);
20712102
}
20722103

2104+
#[test]
2105+
fn ipv6_to_ipv4_mapped() {
2106+
assert_eq!(
2107+
Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
2108+
Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2109+
);
2110+
assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
2111+
}
2112+
20732113
#[test]
20742114
fn ipv6_to_ipv4() {
20752115
assert_eq!(

0 commit comments

Comments
 (0)