[Thread] reduce JNI code for setting up the ICMPv6 socket

Bug: 316103631
Test: atest ThreadNetworkIntegrationTests

Change-Id: I64a0cb22d4ed2208328123d8dace3463a92af01e
diff --git a/thread/service/java/com/android/server/thread/InfraInterfaceController.java b/thread/service/java/com/android/server/thread/InfraInterfaceController.java
index be54cbc..e72c9ee 100644
--- a/thread/service/java/com/android/server/thread/InfraInterfaceController.java
+++ b/thread/service/java/com/android/server/thread/InfraInterfaceController.java
@@ -16,14 +16,30 @@
 
 package com.android.server.thread;
 
-import android.os.ParcelFileDescriptor;
+import static android.system.OsConstants.IPPROTO_IPV6;
+import static android.system.OsConstants.IPPROTO_RAW;
+import static android.system.OsConstants.IPV6_CHECKSUM;
+import static android.system.OsConstants.IPV6_MULTICAST_HOPS;
+import static android.system.OsConstants.IPV6_RECVHOPLIMIT;
+import static android.system.OsConstants.IPV6_RECVPKTINFO;
+import static android.system.OsConstants.IPV6_UNICAST_HOPS;
 
+import android.net.util.SocketUtils;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import java.io.FileDescriptor;
 import java.io.IOException;
 
 /** Controller for the infrastructure network interface. */
 public class InfraInterfaceController {
     private static final String TAG = "InfraIfController";
 
+    private static final int ENABLE = 1;
+    private static final int IPV6_CHECKSUM_OFFSET = 2;
+    private static final int HOP_LIMIT = 255;
+
     static {
         System.loadLibrary("service-thread-jni");
     }
@@ -37,8 +53,21 @@
      * @throws IOException when fails to create the socket.
      */
     public ParcelFileDescriptor createIcmp6Socket(String infraInterfaceName) throws IOException {
-        return ParcelFileDescriptor.adoptFd(nativeCreateIcmp6Socket(infraInterfaceName));
+        ParcelFileDescriptor parcelFd =
+                ParcelFileDescriptor.adoptFd(nativeCreateFilteredIcmp6Socket());
+        FileDescriptor fd = parcelFd.getFileDescriptor();
+        try {
+            Os.setsockoptInt(fd, IPPROTO_RAW, IPV6_CHECKSUM, IPV6_CHECKSUM_OFFSET);
+            Os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, ENABLE);
+            Os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, ENABLE);
+            Os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, HOP_LIMIT);
+            Os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, HOP_LIMIT);
+            SocketUtils.bindSocketToInterface(fd, infraInterfaceName);
+        } catch (ErrnoException e) {
+            throw new IOException("Failed to setsockopt for the ICMPv6 socket", e);
+        }
+        return parcelFd;
     }
 
-    private static native int nativeCreateIcmp6Socket(String interfaceName) throws IOException;
+    private static native int nativeCreateFilteredIcmp6Socket() throws IOException;
 }
diff --git a/thread/service/jni/com_android_server_thread_InfraInterfaceController.cpp b/thread/service/jni/com_android_server_thread_InfraInterfaceController.cpp
index 5d24eab..1f260f2 100644
--- a/thread/service/jni/com_android_server_thread_InfraInterfaceController.cpp
+++ b/thread/service/jni/com_android_server_thread_InfraInterfaceController.cpp
@@ -42,15 +42,8 @@
 
 namespace android {
 static jint
-com_android_server_thread_InfraInterfaceController_createIcmp6Socket(JNIEnv *env, jobject clazz,
-                                                                     jstring interfaceName) {
-  ScopedUtfChars ifName(env, interfaceName);
-
-  struct icmp6_filter filter;
-  constexpr int kEnable = 1;
-  constexpr int kIpv6ChecksumOffset = 2;
-  constexpr int kHopLimit = 255;
-
+com_android_server_thread_InfraInterfaceController_createFilteredIcmp6Socket(JNIEnv *env,
+                                                                             jobject clazz) {
   // Initializes the ICMPv6 socket.
   int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
   if (sock == -1) {
@@ -59,6 +52,7 @@
     return -1;
   }
 
+  struct icmp6_filter filter;
   // Only accept Router Advertisements, Router Solicitations and Neighbor
   // Advertisements.
   ICMP6_FILTER_SETBLOCKALL(&filter);
@@ -73,53 +67,6 @@
     return -1;
   }
 
-  // We want a source address and interface index.
-
-  if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &kEnable, sizeof(kEnable)) != 0) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "failed to setsockopt IPV6_RECVPKTINFO (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
-  if (setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &kIpv6ChecksumOffset,
-                 sizeof(kIpv6ChecksumOffset)) != 0) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "failed to setsockopt IPV6_CHECKSUM (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
-  // We need to be able to reject RAs arriving from off-link.
-  if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &kEnable, sizeof(kEnable)) != 0) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "failed to setsockopt IPV6_RECVHOPLIMIT (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
-  if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kHopLimit, sizeof(kHopLimit)) != 0) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "failed to setsockopt IPV6_UNICAST_HOPS (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
-  if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit)) != 0) {
-    jniThrowExceptionFmt(env, "java/io/IOException",
-                         "failed to create the setsockopt IPV6_MULTICAST_HOPS (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
-  if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifName.c_str(), strlen(ifName.c_str()))) {
-    jniThrowExceptionFmt(env, "java/io/IOException", "failed to setsockopt SO_BINDTODEVICE (%s)",
-                         strerror(errno));
-    close(sock);
-    return -1;
-  }
-
   return sock;
 }
 
@@ -129,8 +76,8 @@
 
 static const JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    {"nativeCreateIcmp6Socket", "(Ljava/lang/String;)I",
-     (void *)com_android_server_thread_InfraInterfaceController_createIcmp6Socket},
+    {"nativeCreateFilteredIcmp6Socket", "()I",
+     (void *)com_android_server_thread_InfraInterfaceController_createFilteredIcmp6Socket},
 };
 
 int register_com_android_server_thread_InfraInterfaceController(JNIEnv *env) {