Merge "Bypass VPN lockdown for clat initialization"

This commit is contained in:
Maciej Żenczykowski
2022-10-25 07:43:12 +00:00
committed by Gerrit Code Review
6 changed files with 26 additions and 15 deletions

View File

@@ -87,7 +87,8 @@ jstring com_android_server_connectivity_ClatCoordinator_selectIpv4Address(JNIEnv
// 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) {
JNIEnv* env, jobject clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str,
jint mark) {
ScopedUtfChars iface(env, ifaceStr);
ScopedUtfChars addr4(env, v4Str);
ScopedUtfChars prefix64(env, prefix64Str);
@@ -111,7 +112,7 @@ jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address(
}
in6_addr v6;
if (net::clat::generateIpv6Address(iface.c_str(), v4, nat64Prefix, &v6)) {
if (net::clat::generateIpv6Address(iface.c_str(), v4, nat64Prefix, &v6, mark)) {
jniThrowExceptionFmt(env, "java/io/IOException",
"Unable to find global source address on %s for %s", iface.c_str(),
prefix64.c_str());
@@ -447,7 +448,7 @@ static const JNINativeMethod gMethods[] = {
{"native_selectIpv4Address", "(Ljava/lang/String;I)Ljava/lang/String;",
(void*)com_android_server_connectivity_ClatCoordinator_selectIpv4Address},
{"native_generateIpv6Address",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;",
(void*)com_android_server_connectivity_ClatCoordinator_generateIpv6Address},
{"native_createTunInterface", "(Ljava/lang/String;)I",
(void*)com_android_server_connectivity_ClatCoordinator_createTunInterface},

View File

@@ -126,10 +126,19 @@ void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Pr
// Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
in6_addr* v6) {
in6_addr* v6, uint32_t mark) {
int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (s == -1) return -errno;
// Socket's mark affects routing decisions (network selection)
// An fwmark is necessary for clat to bypass the VPN during initialization.
if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
int ret = errno;
ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
close(s);
return -ret;
}
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) {
close(s);
return -errno;

View File

@@ -202,7 +202,8 @@ TEST_F(ClatUtils, GenerateIpv6AddressFailWithUlaSocketAddress) {
in6_addr v6;
EXPECT_EQ(1, inet_pton(AF_INET6, "::", &v6)); // initialize as zero
EXPECT_EQ(-ENETUNREACH, generateIpv6Address(tun.name().c_str(), v4, nat64Prefix, &v6));
// 0u is MARK_UNSET
EXPECT_EQ(-ENETUNREACH, generateIpv6Address(tun.name().c_str(), v4, nat64Prefix, &v6, 0u));
EXPECT_TRUE(IN6_IS_ADDR_ULA(&v6));
tun.destroy();

View File

@@ -24,7 +24,7 @@ bool isIpv4AddressFree(in_addr_t addr);
in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix);
int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
in6_addr* v6);
in6_addr* v6, uint32_t mark);
int detect_mtu(const struct in6_addr* plat_subnet, uint32_t plat_suffix, uint32_t mark);
int configure_packet_socket(int sock, in6_addr* addr, int ifindex);

View File

@@ -183,8 +183,8 @@ public class ClatCoordinator {
*/
@NonNull
public String generateIpv6Address(@NonNull String iface, @NonNull String v4,
@NonNull String prefix64) throws IOException {
return native_generateIpv6Address(iface, v4, prefix64);
@NonNull String prefix64, int mark) throws IOException {
return native_generateIpv6Address(iface, v4, prefix64, mark);
}
/**
@@ -629,10 +629,11 @@ public class ClatCoordinator {
}
// [2] Generate a checksum-neutral IID.
final Integer fwmark = getFwmark(netId);
final String pfx96Str = nat64Prefix.getAddress().getHostAddress();
final String v6Str;
try {
v6Str = mDeps.generateIpv6Address(iface, v4Str, pfx96Str);
v6Str = mDeps.generateIpv6Address(iface, v4Str, pfx96Str, fwmark);
} catch (IOException e) {
throw new IOException("no IPv6 addresses were available for clat: " + e);
}
@@ -676,7 +677,6 @@ public class ClatCoordinator {
}
// Detect ipv4 mtu.
final Integer fwmark = getFwmark(netId);
final int detectedMtu;
try {
detectedMtu = mDeps.detectMtu(pfx96Str,
@@ -931,7 +931,7 @@ public class ClatCoordinator {
private static native String native_selectIpv4Address(String v4addr, int prefixlen)
throws IOException;
private static native String native_generateIpv6Address(String iface, String v4,
String prefix64) throws IOException;
String prefix64, int mark) throws IOException;
private static native int native_createTunInterface(String tuniface) throws IOException;
private static native int native_detectMtu(String platSubnet, int platSuffix, int mark)
throws IOException;

View File

@@ -220,12 +220,12 @@ public class ClatCoordinatorTest {
*/
@Override
public String generateIpv6Address(@NonNull String iface, @NonNull String v4,
@NonNull String prefix64) throws IOException {
@NonNull String prefix64, int mark) throws IOException {
if (BASE_IFACE.equals(iface) && XLAT_LOCAL_IPV4ADDR_STRING.equals(v4)
&& NAT64_PREFIX_STRING.equals(prefix64)) {
return XLAT_LOCAL_IPV6ADDR_STRING;
}
fail("unsupported args: " + iface + ", " + v4 + ", " + prefix64);
fail("unsupported args: " + iface + ", " + v4 + ", " + prefix64 + ", " + mark);
return null;
}
@@ -417,7 +417,7 @@ public class ClatCoordinatorTest {
// Generate a checksum-neutral IID.
inOrder.verify(mDeps).generateIpv6Address(eq(BASE_IFACE),
eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(NAT64_PREFIX_STRING));
eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(NAT64_PREFIX_STRING), eq(MARK));
// Open, configure and bring up the tun interface.
inOrder.verify(mDeps).createTunInterface(eq(STACKED_IFACE));
@@ -617,7 +617,7 @@ public class ClatCoordinatorTest {
class FailureDependencies extends TestDependencies {
@Override
public String generateIpv6Address(@NonNull String iface, @NonNull String v4,
@NonNull String prefix64) throws IOException {
@NonNull String prefix64, int mark) throws IOException {
throw new IOException();
}
}