about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-12 16:30:46 +0000
committerbors <bors@rust-lang.org>2020-08-12 16:30:46 +0000
commit3df25ae186e89c885d9a71cd37fbd7a37e39fc85 (patch)
tree9b52046f5e87a28f9c4da32fc80810cfe041eff0 /library/std/src
parentded20c98be8585b2a9fe4eeadd1be5524f6ffb17 (diff)
parentd892a07c67dfa4f347b62ecf96de184c41dae5dd (diff)
downloadrust-3df25ae186e89c885d9a71cd37fbd7a37e39fc85.tar.gz
rust-3df25ae186e89c885d9a71cd37fbd7a37e39fc85.zip
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.
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/net/ip.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index ccaacbf1a58..2c0025bcba0 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -1473,6 +1473,37 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xff00) == 0xff00
     }
 
+    /// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
+    /// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
+    ///
+    /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
+    /// All addresses *not* starting with `::ffff` will return `None`.
+    ///
+    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
+    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
+    /// ```
+    pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+        match self.octets() {
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+                Some(Ipv4Addr::new(a, b, c, d))
+            }
+            _ => None,
+        }
+    }
+
     /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
     /// neither IPv4-compatible or IPv4-mapped.
     ///
@@ -2071,6 +2102,15 @@ mod tests {
     }
 
     #[test]
+    fn ipv6_to_ipv4_mapped() {
+        assert_eq!(
+            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
+            Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+        );
+        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
+    }
+
+    #[test]
     fn ipv6_to_ipv4() {
         assert_eq!(
             Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),