[CLATJ#8] ClatCoordinator: select IPv6 address with checksum-neutral IID
Select a local 464xlat IPv6 address for clatd. The IPv6 address has
checksum-neutral IID. The native function is moved from netd to
libclat. Its test is moved from netd as well.
Bug: 212345928
Test: flash and boot
Run "atest ClatCoordinatorTest" in a followup commit.
Change-Id: I11520e5c086e475999847d829dd6341b14199b39
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index e042bf3..e3e5000 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -52,6 +52,46 @@
return env->NewStringUTF(addrstr);
}
+// Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
+jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address(
+ JNIEnv* env, jobject clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str) {
+ ScopedUtfChars iface(env, ifaceStr);
+ ScopedUtfChars addr4(env, v4Str);
+ ScopedUtfChars prefix64(env, prefix64Str);
+
+ if (iface.c_str() == nullptr) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Invalid null interface name");
+ return nullptr;
+ }
+
+ in_addr v4;
+ if (inet_pton(AF_INET, addr4.c_str(), &v4) != 1) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Invalid clat v4 address %s",
+ addr4.c_str());
+ return nullptr;
+ }
+
+ in6_addr nat64Prefix;
+ if (inet_pton(AF_INET6, prefix64.c_str(), &nat64Prefix) != 1) {
+ jniThrowExceptionFmt(env, "java/io/IOException", "Invalid prefix %s", prefix64.c_str());
+ return nullptr;
+ }
+
+ in6_addr v6;
+ if (net::clat::generateIpv6Address(iface.c_str(), v4, nat64Prefix, &v6)) {
+ jniThrowExceptionFmt(env, "java/io/IOException",
+ "Unable to find global source address on %s for %s", iface.c_str(),
+ prefix64.c_str());
+ return nullptr;
+ }
+
+ char addrstr[INET6_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET6, (void*)&v6, addrstr, sizeof(addrstr))) {
+ return nullptr;
+ }
+ return env->NewStringUTF(addrstr);
+}
+
/*
* JNI registration.
*/
@@ -59,6 +99,9 @@
/* name, signature, funcPtr */
{"selectIpv4Address", "(Ljava/lang/String;I)Ljava/lang/String;",
(void*)com_android_server_connectivity_ClatCoordinator_selectIpv4Address},
+ {"generateIpv6Address",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void*)com_android_server_connectivity_ClatCoordinator_generateIpv6Address},
};
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 cf22e24..11deb78 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -66,6 +66,15 @@
throws IOException {
return selectIpv4Address(v4addr, prefixlen);
}
+
+ /**
+ * Generate a checksum-neutral IID.
+ */
+ @NonNull
+ public String jniGenerateIpv6Address(@NonNull String iface, @NonNull String v4,
+ @NonNull String prefix64) throws IOException {
+ return generateIpv6Address(iface, v4, prefix64);
+ }
}
public ClatCoordinator(@NonNull Dependencies deps) {
@@ -91,10 +100,21 @@
throw new IOException("no IPv4 addresses were available for clat: " + e);
}
+ // [2] Generate a checksum-neutral IID.
+ final String pfx96 = nat64Prefix.getAddress().getHostAddress();
+ final String v6;
+ try {
+ v6 = mDeps.jniGenerateIpv6Address(iface, v4, pfx96);
+ } catch (IOException e) {
+ throw new IOException("no IPv6 addresses were available for clat: " + e);
+ }
+
// TODO: start clatd and returns local xlat464 v6 address.
return null;
}
private static native String selectIpv4Address(String v4addr, int prefixlen)
throws IOException;
+ private static native String generateIpv6Address(String iface, String v4, String prefix64)
+ throws IOException;
}