Merge "Move shared methods to NetUtils"
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index ecff6c7..a3bfbce 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -27,6 +27,10 @@
 // included in the bootclasspath, they could incorrectly be included in the SDK documentation even
 // though they are not in the current.txt files.
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 java_library {
   name: "net-utils-device-common",
   srcs: [
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkIdentityUtils.java b/staticlibs/framework/com/android/net/module/util/NetworkIdentityUtils.java
new file mode 100644
index 0000000..94e6017
--- /dev/null
+++ b/staticlibs/framework/com/android/net/module/util/NetworkIdentityUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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 android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Utilities to examine {@link android.net.NetworkIdentity}.
+ */
+public class NetworkIdentityUtils {
+    /**
+     * Scrub given IMSI on production builds.
+     */
+    @NonNull
+    public static String scrubSubscriberId(@Nullable String subscriberId) {
+        if (subscriberId != null) {
+            // TODO: parse this as MCC+MNC instead of hard-coding
+            return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
+        } else {
+            return "null";
+        }
+    }
+
+    /**
+     * Scrub given IMSI on production builds.
+     */
+    @Nullable
+    public static String[] scrubSubscriberIds(@Nullable String[] subscriberIds) {
+        if (subscriberIds == null) return null;
+        final String[] res = new String[subscriberIds.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = scrubSubscriberId(subscriberIds[i]);
+        }
+        return res;
+    }
+}
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
index a227505..5f62186 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
@@ -16,7 +16,10 @@
 
 package com.android.net.module.util;
 
+import android.net.InetAddresses;
+
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 
@@ -51,8 +54,6 @@
             (byte) 0xff, (byte) 0xff, (byte) 0xff,
     };
 
-    public static final int DEFAULT_LINK_MTU = 1500;
-
     /**
      * ARP constants.
      *
@@ -98,7 +99,11 @@
             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff);
     public static final Inet4Address IPV4_ADDR_ANY = makeInet4Address(
             (byte) 0, (byte) 0, (byte) 0, (byte) 0);
-
+    public static final Inet6Address IPV6_ADDR_ANY = makeInet6Address(new byte[]{
+            (byte) 0, (byte) 0, (byte) 0, (byte) 0,
+            (byte) 0, (byte) 0, (byte) 0, (byte) 0,
+            (byte) 0, (byte) 0, (byte) 0, (byte) 0,
+            (byte) 0, (byte) 0, (byte) 0, (byte) 0 });
     /**
      * IPv6 constants.
      *
@@ -112,6 +117,12 @@
     public static final int IPV6_SRC_ADDR_OFFSET = 8;
     public static final int IPV6_DST_ADDR_OFFSET = 24;
     public static final int IPV6_MIN_MTU = 1280;
+    public static final Inet6Address IPV6_ADDR_ALL_NODES_MULTICAST =
+            (Inet6Address) InetAddresses.parseNumericAddress("ff02::1");
+    public static final Inet6Address IPV6_ADDR_ALL_ROUTERS_MULTICAST =
+            (Inet6Address) InetAddresses.parseNumericAddress("ff02::2");
+    public static final Inet6Address IPV6_ADDR_ALL_HOSTS_MULTICAST =
+            (Inet6Address) InetAddresses.parseNumericAddress("ff02::3");
 
     /**
      * ICMPv6 constants.
@@ -182,6 +193,16 @@
         }
     }
 
+    /**
+     * Make an Inet6Address from 16 bytes in network byte order.
+     */
+    private static Inet6Address makeInet6Address(byte[] bytes) {
+        try {
+            return (Inet6Address) InetAddress.getByAddress(bytes);
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException("addr must be 16 bytes: this should never happen");
+        }
+    }
     private NetworkStackConstants() {
         throw new UnsupportedOperationException("This class is not to be instantiated");
     }
diff --git a/staticlibs/framework/com/android/net/module/util/ProxyUtils.java b/staticlibs/framework/com/android/net/module/util/ProxyUtils.java
index a7b8393..fdd7dca 100644
--- a/staticlibs/framework/com/android/net/module/util/ProxyUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/ProxyUtils.java
@@ -22,6 +22,8 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Collection of network common utilities.
@@ -30,6 +32,28 @@
  */
 public final class ProxyUtils {
 
+    public static final int PROXY_VALID             = 0;
+    public static final int PROXY_HOSTNAME_EMPTY    = 1;
+    public static final int PROXY_HOSTNAME_INVALID  = 2;
+    public static final int PROXY_PORT_EMPTY        = 3;
+    public static final int PROXY_PORT_INVALID      = 4;
+    public static final int PROXY_EXCLLIST_INVALID  = 5;
+
+    // Hostname / IP REGEX validation
+    // Matches blank input, ips, and domain names
+    private static final String NAME_IP_REGEX =
+            "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
+    private static final Pattern HOSTNAME_PATTERN;
+    private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$";
+    private static final Pattern EXCLLIST_PATTERN;
+    private static final String EXCL_REGEX =
+            "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*";
+    private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$";
+    static {
+        HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
+        EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
+    }
+
     /** Converts exclusion list from String to List. */
     public static List<String> exclusionStringAsList(String exclusionList) {
         if (exclusionList == null) {
@@ -45,4 +69,30 @@
         }
         return TextUtils.join(",", exclusionList);
     }
+
+    /**
+     * Validate syntax of hostname, port and exclusion list entries
+     */
+    public static int validate(String hostname, String port, String exclList) {
+        Matcher match = HOSTNAME_PATTERN.matcher(hostname);
+        Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
+
+        if (!match.matches()) return PROXY_HOSTNAME_INVALID;
+
+        if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID;
+
+        if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY;
+
+        if (port.length() > 0) {
+            if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY;
+            int portVal = -1;
+            try {
+                portVal = Integer.parseInt(port);
+            } catch (NumberFormatException ex) {
+                return PROXY_PORT_INVALID;
+            }
+            if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID;
+        }
+        return PROXY_VALID;
+    }
 }
diff --git a/staticlibs/native/bpf_syscall_wrappers/Android.bp b/staticlibs/native/bpf_syscall_wrappers/Android.bp
index ae6eee0..fa90655 100644
--- a/staticlibs/native/bpf_syscall_wrappers/Android.bp
+++ b/staticlibs/native/bpf_syscall_wrappers/Android.bp
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_library_headers {
     name: "bpf_syscall_wrappers",
     vendor_available: false,
diff --git a/staticlibs/native/netjniutils/Android.bp b/staticlibs/native/netjniutils/Android.bp
index 8417c52..d8e6a04 100644
--- a/staticlibs/native/netjniutils/Android.bp
+++ b/staticlibs/native/netjniutils/Android.bp
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_library_static {
     name: "libnetjniutils",
     srcs: ["netjniutils.cpp"],
diff --git a/staticlibs/tests/unit/Android.bp b/staticlibs/tests/unit/Android.bp
index c00202e..4ce4b0e 100644
--- a/staticlibs/tests/unit/Android.bp
+++ b/staticlibs/tests/unit/Android.bp
@@ -2,6 +2,10 @@
 // Build NetworkStaticLibTests package
 //########################################################################
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 android_library {
     name: "NetworkStaticLibTestsLib",
     srcs: ["src/**/*.java","src/**/*.kt"],
@@ -38,4 +42,3 @@
     jarjar_rules: "jarjar-rules.txt",
     test_suites: ["device-tests"],
 }
-
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/NetworkIdentityUtilsTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/NetworkIdentityUtilsTest.kt
new file mode 100644
index 0000000..2904e12
--- /dev/null
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/NetworkIdentityUtilsTest.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 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 androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.net.module.util.NetworkIdentityUtils.scrubSubscriberId
+import com.android.net.module.util.NetworkIdentityUtils.scrubSubscriberIds
+import com.android.testutils.assertContainsStringsExactly
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkIdentityUtilsTest {
+    @Test
+    fun testScrubSubscriberId() {
+        assertEquals("123456...", scrubSubscriberId("1234567890123"))
+        assertEquals("123456...", scrubSubscriberId("1234567"))
+        assertEquals("123...", scrubSubscriberId("123"))
+        assertEquals("...", scrubSubscriberId(""))
+        assertEquals("null", scrubSubscriberId(null))
+    }
+
+    @Test
+    fun testScrubSubscriberIds() {
+        assertContainsStringsExactly(scrubSubscriberIds(arrayOf("1234567", "", null))!!,
+                "123456...", "...", "null")
+        assertContainsStringsExactly(scrubSubscriberIds(arrayOf("12345"))!!, "12345...")
+        assertContainsStringsExactly(scrubSubscriberIds(arrayOf())!!)
+        assertNull(scrubSubscriberIds(null))
+    }
+}
\ No newline at end of file