diff --git a/service/Android.bp b/service/Android.bp index e376ff76e5..d1a9004106 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -65,6 +65,7 @@ cc_library_shared { "libbase_headers", ], static_libs: [ + "libbase", "libclat", "libip_checksum", "libnetjniutils", diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp index a9d794697a..0272bc14b2 100644 --- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp +++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp @@ -19,17 +19,22 @@ #include #include #include +#include #include #include +#include #include +#include "libclat/bpfhelper.h" #include "libclat/clatutils.h" #include "nativehelper/scoped_utf_chars.h" // Sync from system/netd/include/netid_client.h #define MARK_UNSET 0u +#define DEVICEPREFIX "v4-" + namespace android { static void throwIOException(JNIEnv* env, const char* msg, int error) { jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error)); @@ -237,6 +242,67 @@ static void com_android_server_connectivity_ClatCoordinator_configurePacketSocke } } +int initTracker(const std::string& iface, const std::string& pfx96, const std::string& v4, + const std::string& v6, net::clat::ClatdTracker* output) { + strlcpy(output->iface, iface.c_str(), sizeof(output->iface)); + output->ifIndex = if_nametoindex(iface.c_str()); + if (output->ifIndex == 0) { + ALOGE("interface %s not found", output->iface); + return -1; + } + + unsigned len = snprintf(output->v4iface, sizeof(output->v4iface), + "%s%s", DEVICEPREFIX, iface.c_str()); + if (len >= sizeof(output->v4iface)) { + ALOGE("interface name too long '%s'", output->v4iface); + return -1; + } + + output->v4ifIndex = if_nametoindex(output->v4iface); + if (output->v4ifIndex == 0) { + ALOGE("v4-interface %s not found", output->v4iface); + return -1; + } + + if (!inet_pton(AF_INET6, pfx96.c_str(), &output->pfx96)) { + ALOGE("invalid IPv6 address specified for plat prefix: %s", pfx96.c_str()); + return -1; + } + + if (!inet_pton(AF_INET, v4.c_str(), &output->v4)) { + ALOGE("Invalid IPv4 address %s", v4.c_str()); + return -1; + } + + if (!inet_pton(AF_INET6, v6.c_str(), &output->v6)) { + ALOGE("Invalid source address %s", v6.c_str()); + return -1; + } + + return 0; +} + +// TODO: fork clatd and rename to .._startClatd. +static jint com_android_server_connectivity_ClatCoordinator_maybeStartBpf( + JNIEnv* env, jobject clazz, jobject tunJavaFd, jobject readSockJavaFd, + jobject writeSockJavaFd, jstring iface, jstring pfx96, jstring v4, jstring v6) { + ScopedUtfChars ifaceStr(env, iface); + ScopedUtfChars pfx96Str(env, pfx96); + ScopedUtfChars v4Str(env, v4); + ScopedUtfChars v6Str(env, v6); + + // Start BPF if any + if (!net::clat::initMaps()) { + net::clat::ClatdTracker tracker = {}; + if (!initTracker(ifaceStr.c_str(), pfx96Str.c_str(), v4Str.c_str(), v6Str.c_str(), + &tracker)) { + net::clat::maybeStartBpf(tracker); + } + } + + return 0; // TODO: return forked clatd pid. +} + /* * JNI registration. */ @@ -259,6 +325,10 @@ static const JNINativeMethod gMethods[] = { (void*)com_android_server_connectivity_ClatCoordinator_addAnycastSetsockopt}, {"native_configurePacketSocket", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)com_android_server_connectivity_ClatCoordinator_configurePacketSocket}, + {"native_maybeStartBpf", + "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/lang/" + "String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", + (void*)com_android_server_connectivity_ClatCoordinator_maybeStartBpf}, }; 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 4d243c482a..a7859745a8 100644 --- a/service/src/com/android/server/connectivity/ClatCoordinator.java +++ b/service/src/com/android/server/connectivity/ClatCoordinator.java @@ -162,6 +162,15 @@ public class ClatCoordinator { throws IOException { native_configurePacketSocket(sock, v6, ifindex); } + + /** + * Maybe start bpf. + */ + public int maybeStartBpf(@NonNull FileDescriptor tunfd, @NonNull FileDescriptor readsock6, + @NonNull FileDescriptor writesock6, @NonNull String iface, @NonNull String pfx96, + @NonNull String v4, @NonNull String v6) throws IOException { + return native_maybeStartBpf(tunfd, readsock6, writesock6, iface, pfx96, v4, v6); + } } @VisibleForTesting @@ -304,6 +313,14 @@ public class ClatCoordinator { throw new IOException("configure packet socket failed: " + e); } + // [5] Maybe start bpf. + try { + mDeps.maybeStartBpf(tunFd.getFileDescriptor(), readSock6.getFileDescriptor(), + writeSock6.getFileDescriptor(), iface, pfx96, v4, v6); + } catch (IOException e) { + throw new IOException("Error start bpf on " + iface + ": " + e); + } + // TODO: start clatd and returns local xlat464 v6 address. return null; } @@ -321,4 +338,7 @@ public class ClatCoordinator { int ifindex) throws IOException; private static native void native_configurePacketSocket(FileDescriptor sock, String v6, int ifindex) throws IOException; + private static native int native_maybeStartBpf(FileDescriptor tunfd, FileDescriptor readsock6, + FileDescriptor writesock6, String iface, String pfx96, String v4, String v6) + throws IOException; }