Fix a bug in InetAddressUtils, and add a test.
InetAddressUtils's parcelInetAddress and #unparcelInetAddress
methods do not correctly parcel scoped IPv6 addresses. Fix this
by using the same code that LinkProperties uses, and add a test.
Bug: 182785371
Test: atest NetworkStaticLibTests
Change-Id: Idc9fcbcf4b2b0746c19831fef68b0ddc206eb161
diff --git a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java
index 6300328..31d0729 100644
--- a/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/InetAddressUtils.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -27,6 +28,8 @@
*/
public class InetAddressUtils {
+ private static final int INET6_ADDR_LENGTH = 16;
+
/**
* Writes an InetAddress to a parcel. The address may be null. This is likely faster than
* calling writeSerializable.
@@ -35,6 +38,13 @@
public static void parcelInetAddress(Parcel parcel, InetAddress address, int flags) {
byte[] addressArray = (address != null) ? address.getAddress() : null;
parcel.writeByteArray(addressArray);
+ if (address instanceof Inet6Address) {
+ final Inet6Address v6Address = (Inet6Address) address;
+ final boolean hasScopeId = v6Address.getScopeId() != 0;
+ parcel.writeBoolean(hasScopeId);
+ if (hasScopeId) parcel.writeInt(v6Address.getScopeId());
+ }
+
}
/**
@@ -47,7 +57,14 @@
if (addressArray == null) {
return null;
}
+
try {
+ if (addressArray.length == INET6_ADDR_LENGTH) {
+ final boolean hasScopeId = in.readBoolean();
+ final int scopeId = hasScopeId ? in.readInt() : 0;
+ return Inet6Address.getByAddress(null /* host */, addressArray, scopeId);
+ }
+
return InetAddress.getByAddress(addressArray);
} catch (UnknownHostException e) {
return null;
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
new file mode 100644
index 0000000..2736c53
--- /dev/null
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/InetAddressUtilsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InetAddressUtilsTest {
+
+ private InetAddress parcelUnparcelAddress(InetAddress addr) {
+ Parcel p = Parcel.obtain();
+ InetAddressUtils.parcelInetAddress(p, addr, 0 /* flags */);
+ p.setDataPosition(0);
+ byte[] marshalled = p.marshall();
+ p.recycle();
+ p = Parcel.obtain();
+ p.unmarshall(marshalled, 0, marshalled.length);
+ p.setDataPosition(0);
+ InetAddress out = InetAddressUtils.unparcelInetAddress(p);
+ p.recycle();
+ return out;
+ }
+
+ @Test
+ public void testParcelUnparcelIpv4Address() throws Exception {
+ InetAddress ipv4 = InetAddress.getByName("192.0.2.1");
+ assertEquals(ipv4, parcelUnparcelAddress(ipv4));
+ }
+
+ @Test
+ public void testParcelUnparcelIpv6Address() throws Exception {
+ InetAddress ipv6 = InetAddress.getByName("2001:db8::1");
+ assertEquals(ipv6, parcelUnparcelAddress(ipv6));
+ }
+
+ @Test
+ public void testParcelUnparcelScopedIpv6Address() throws Exception {
+ InetAddress ipv6 = InetAddress.getByName("fe80::1%42");
+ assertEquals(42, ((Inet6Address) ipv6).getScopeId());
+ Inet6Address out = (Inet6Address) parcelUnparcelAddress(ipv6);
+ assertEquals(ipv6, out);
+ assertEquals(42, out.getScopeId());
+ }
+}