Merge "[Thread] reduce JNI code for setting up the ICMPv6 socket" into main

This commit is contained in:
Treehugger Robot 2024-06-18 05:03:15 +00:00 • committed by Gerrit Code Review
commit 5637480c2c
2 changed files with 36 additions and 60 deletions

View file

@ -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 @@ public class InfraInterfaceController {
* @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;
}

View file

@ -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 @@ com_android_server_thread_InfraInterfaceController_createIcmp6Socket(JNIEnv *env
return -1;
}
struct icmp6_filter filter;
// Only accept Router Advertisements, Router Solicitations and Neighbor
// Advertisements.
ICMP6_FILTER_SETBLOCKALL(&filter);
@ -73,53 +67,6 @@ com_android_server_thread_InfraInterfaceController_createIcmp6Socket(JNIEnv *env
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 @@ com_android_server_thread_InfraInterfaceController_createIcmp6Socket(JNIEnv *env
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) {