From 52366e0fb1fb91a7fd9901779b02cf304cf3213e Mon Sep 17 00:00:00 2001 From: Motomu Utsumi Date: Mon, 23 Oct 2023 17:03:42 +0900 Subject: [PATCH] Add util method to generate IPv4-mapped IPv6 address from IPv4 address Bug: 295800201 Test: NetworkStaticLibTests Change-Id: Ia10e7dd14edfabe0edf5c9e12ceae54a1ff88d13 --- .../net/module/util/InetAddressUtils.java | 26 +++++++++++++++++++ .../net/module/util/InetAddressUtilsTest.java | 15 +++++++++++ 2 files changed, 41 insertions(+) diff --git a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java index 40fc59fb6d..4b27a972b1 100644 --- a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java +++ b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java @@ -21,6 +21,7 @@ import android.os.Parcel; import android.util.Log; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; @@ -32,6 +33,7 @@ import java.net.UnknownHostException; public class InetAddressUtils { private static final String TAG = InetAddressUtils.class.getSimpleName(); + private static final int INET4_ADDR_LENGTH = 4; private static final int INET6_ADDR_LENGTH = 16; /** @@ -93,5 +95,29 @@ public class InetAddressUtils { } } + /** + * Create a v4-mapped v6 address from v4 address + * + * @param v4Addr Inet4Address which is converted to v4-mapped v6 address + * @return v4-mapped v6 address + */ + public static Inet6Address v4MappedV6Address(@NonNull final Inet4Address v4Addr) { + final byte[] v6AddrBytes = new byte[INET6_ADDR_LENGTH]; + v6AddrBytes[10] = (byte) 0xFF; + v6AddrBytes[11] = (byte) 0xFF; + System.arraycopy(v4Addr.getAddress(), 0 /* srcPos */, v6AddrBytes, 12 /* dstPos */, + INET4_ADDR_LENGTH); + try { + // Using Inet6Address.getByAddress since InetAddress.getByAddress converts v4-mapped v6 + // address to v4 address internally and returns Inet4Address + return Inet6Address.getByAddress(null /* host */, v6AddrBytes, -1 /* scope_id */); + } catch (UnknownHostException impossible) { + // getByAddress throws UnknownHostException when the argument is the invalid length + // but INET6_ADDR_LENGTH(16) is the valid length. + Log.wtf(TAG, "Failed to generate v4-mapped v6 address from " + v4Addr, impossible); + return null; + } + } + private InetAddressUtils() {} } diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java index bb2b9332a4..66427fc660 100644 --- a/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java +++ b/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java @@ -18,6 +18,7 @@ package com.android.net.module.util; import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -30,6 +31,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -92,4 +94,17 @@ public class InetAddressUtilsTest { assertEquals(localAddrStr + "%" + scopeId, updatedLocalAddr.getHostAddress()); assertEquals(scopeId, updatedLocalAddr.getScopeId()); } + + @Test + public void testV4MappedV6Address() throws Exception { + final Inet4Address v4Addr = (Inet4Address) InetAddress.getByName("192.0.2.1"); + final Inet6Address v4MappedV6Address = InetAddressUtils.v4MappedV6Address(v4Addr); + final byte[] expectedAddrBytes = new byte[]{ + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, + (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01, + }; + assertArrayEquals(expectedAddrBytes, v4MappedV6Address.getAddress()); + } }