[CLATJ#12] ClatCoordinator: open packet socket with a given mark

Move the packet socket initialization from netd to jni because
mainline module is going to launch clatd. Need to provide packet
socket for reading local 464xlat IPv6 packets.

Bug: 212345928
Test: flash and boot
Run "atest ClatCoordinatorTest" in a followup commit.

Change-Id: I1cef6e099403f883d668081fb5e917863f5a3c2a
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index eefb94b..c658464 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -27,6 +27,10 @@
 #include "nativehelper/scoped_utf_chars.h"
 
 namespace android {
+static void throwIOException(JNIEnv* env, const char* msg, int error) {
+    jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error));
+}
+
 jstring com_android_server_connectivity_ClatCoordinator_selectIpv4Address(JNIEnv* env,
                                                                           jobject clazz,
                                                                           jstring v4addr,
@@ -145,6 +149,18 @@
     return ret;
 }
 
+static jint com_android_server_connectivity_ClatCoordinator_openPacketSocket(JNIEnv* env,
+                                                                              jobject clazz) {
+    // Will eventually be bound to htons(ETH_P_IPV6) protocol,
+    // but only after appropriate bpf filter is attached.
+    int sock = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+    if (sock < 0) {
+        throwIOException(env, "packet socket failed", errno);
+        return -1;
+    }
+    return sock;
+}
+
 /*
  * JNI registration.
  */
@@ -159,6 +175,8 @@
          (void*)com_android_server_connectivity_ClatCoordinator_createTunInterface},
         {"detectMtu", "(Ljava/lang/String;II)I",
          (void*)com_android_server_connectivity_ClatCoordinator_detectMtu},
+        {"openPacketSocket", "()I",
+         (void*)com_android_server_connectivity_ClatCoordinator_openPacketSocket},
 };
 
 int register_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index d122f3c..bc635ed 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -121,6 +121,13 @@
                 throws IOException {
             return detectMtu(platSubnet, platSuffix, mark);
         }
+
+        /**
+         * Open packet socket.
+         */
+        public int jniOpenPacketSocket() throws IOException {
+            return openPacketSocket();
+        }
     }
 
     @VisibleForTesting
@@ -221,6 +228,19 @@
                     + ifConfig.prefixLength + " failed on " + ifConfig.ifName + ": " + e);
         }
 
+        // [4] Open and configure local 464xlat read/write sockets.
+        // Opens a packet socket to receive IPv6 packets in clatd.
+        final ParcelFileDescriptor readSock6;
+        try {
+            // Use a JNI call to get native file descriptor instead of Os.socket() because we would
+            // like to use ParcelFileDescriptor to close file descriptor automatically. But ctor
+            // ParcelFileDescriptor(FileDescriptor fd) is a @hide function. Need to use native file
+            // descriptor to initialize ParcelFileDescriptor object instead.
+            readSock6 = mDeps.adoptFd(mDeps.jniOpenPacketSocket());
+        } catch (IOException e) {
+            throw new IOException("Open packet socket failed: " + e);
+        }
+
         // TODO: start clatd and returns local xlat464 v6 address.
         return null;
     }
@@ -232,4 +252,5 @@
     private static native int createTunInterface(String tuniface) throws IOException;
     private static native int detectMtu(String platSubnet, int platSuffix, int mark)
             throws IOException;
+    private static native int openPacketSocket() throws IOException;
 }