Merge "Add NetworkStackModuleTest annotation."
diff --git a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
index b512a95..0f7bd80 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
@@ -22,6 +22,7 @@
 import static android.system.OsConstants.EPROTO;
 import static android.system.OsConstants.ETIMEDOUT;
 import static android.system.OsConstants.NETLINK_INET_DIAG;
+import static android.system.OsConstants.NETLINK_ROUTE;
 import static android.system.OsConstants.SOCK_CLOEXEC;
 import static android.system.OsConstants.SOCK_DGRAM;
 import static android.system.OsConstants.SOL_SOCKET;
@@ -41,9 +42,11 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.net.Inet6Address;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Objects;
 
 /**
  * Utilities for netlink related class that may not be able to fit into a specific class.
@@ -168,6 +171,31 @@
     }
 
     /**
+     * Send an RTM_NEWADDR message to kernel to add or update an IPv6 address.
+     *
+     * @param ifIndex interface index.
+     * @param ip IPv6 address to be added.
+     * @param prefixlen IPv6 address prefix length.
+     * @param flags IPv6 address flags.
+     * @param scope IPv6 address scope.
+     * @param preferred The preferred lifetime of IPv6 address.
+     * @param valid The valid lifetime of IPv6 address.
+     */
+    public static boolean sendRtmNewAddressRequest(int ifIndex, @NonNull final Inet6Address ip,
+            short prefixlen, int flags, byte scope, long preferred, long valid) {
+        Objects.requireNonNull(ip, "IPv6 address to be added should not be null.");
+        final byte[] msg = RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqNo*/, ip,
+                prefixlen, flags, scope, ifIndex, preferred, valid);
+        try {
+            NetlinkUtils.sendOneShotKernelMessage(NETLINK_ROUTE, msg);
+            return true;
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Fail to send RTM_NEWADDR to add " + ip.getHostAddress(), e);
+            return false;
+        }
+    }
+
+    /**
      * Create netlink socket with the given netlink protocol type.
      *
      * @return fd the fileDescriptor of the socket.
diff --git a/staticlibs/framework/com/android/net/module/util/DnsPacket.java b/staticlibs/framework/com/android/net/module/util/DnsPacket.java
index 702d114..79ca3a3 100644
--- a/staticlibs/framework/com/android/net/module/util/DnsPacket.java
+++ b/staticlibs/framework/com/android/net/module/util/DnsPacket.java
@@ -252,7 +252,7 @@
         // Refer to RFC 1035 section 2.3.4 for MAXNAMESIZE.
         // NAME_NORMAL and NAME_COMPRESSION are used for checking name compression,
         // refer to rfc 1035 section 4.1.4.
-        private static final int MAXNAMESIZE = 255;
+        public static final int MAXNAMESIZE = 255;
         public static final int NAME_NORMAL = 0;
         public static final int NAME_COMPRESSION = 0xC0;
 
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/NatPacketForwarderBase.java b/staticlibs/testutils/devicetests/com/android/testutils/NatPacketForwarderBase.java
index 85c6493..0a2b5d4 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/NatPacketForwarderBase.java
+++ b/staticlibs/testutils/devicetests/com/android/testutils/NatPacketForwarderBase.java
@@ -151,7 +151,8 @@
     private void processPacket() {
         final int len = PacketReflectorUtil.readPacket(mSrcFd, mBuf);
         if (len < 1) {
-            throw new IllegalStateException("Unexpected buffer length: " + len);
+            // Usually happens when socket read is being interrupted, e.g. stopping PacketForwarder.
+            return;
         }
 
         final int version = mBuf[0] >>> 4;
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/PacketReflectorUtil.kt b/staticlibs/testutils/devicetests/com/android/testutils/PacketReflectorUtil.kt
index b028045..498b1a3 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/PacketReflectorUtil.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/PacketReflectorUtil.kt
@@ -20,11 +20,12 @@
 
 import android.system.ErrnoException
 import android.system.Os
+import android.system.OsConstants
 import com.android.net.module.util.IpUtils
 import com.android.testutils.PacketReflector.IPV4_HEADER_LENGTH
 import com.android.testutils.PacketReflector.IPV6_HEADER_LENGTH
 import java.io.FileDescriptor
-import java.io.IOException
+import java.io.InterruptedIOException
 import java.net.InetAddress
 import java.nio.ByteBuffer
 
@@ -32,8 +33,15 @@
     return try {
         Os.read(fd, buf, 0, buf.size)
     } catch (e: ErrnoException) {
-        -1
-    } catch (e: IOException) {
+        // Ignore normal use cases such as the EAGAIN error indicates that the read operation
+        // cannot be completed immediately, or the EINTR error indicates that the read
+        // operation was interrupted by a signal.
+        if (e.errno == OsConstants.EAGAIN || e.errno == OsConstants.EINTR) {
+            -1
+        } else {
+            throw e
+        }
+    } catch (e: InterruptedIOException) {
         -1
     }
 }