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. // Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address( 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 iface(env, ifaceStr);
ScopedUtfChars addr4(env, v4Str); ScopedUtfChars addr4(env, v4Str);
ScopedUtfChars prefix64(env, prefix64Str); ScopedUtfChars prefix64(env, prefix64Str);
@@ -111,7 +112,7 @@ jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address(
} }
in6_addr v6; 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", jniThrowExceptionFmt(env, "java/io/IOException",
"Unable to find global source address on %s for %s", iface.c_str(), "Unable to find global source address on %s for %s", iface.c_str(),
prefix64.c_str()); prefix64.c_str());
@@ -447,7 +448,7 @@ static const JNINativeMethod gMethods[] = {
{"native_selectIpv4Address", "(Ljava/lang/String;I)Ljava/lang/String;", {"native_selectIpv4Address", "(Ljava/lang/String;I)Ljava/lang/String;",
(void*)com_android_server_connectivity_ClatCoordinator_selectIpv4Address}, (void*)com_android_server_connectivity_ClatCoordinator_selectIpv4Address},
{"native_generateIpv6Address", {"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}, (void*)com_android_server_connectivity_ClatCoordinator_generateIpv6Address},
{"native_createTunInterface", "(Ljava/lang/String;)I", {"native_createTunInterface", "(Ljava/lang/String;)I",
(void*)com_android_server_connectivity_ClatCoordinator_createTunInterface}, (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. // 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, 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); int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (s == -1) return -errno; 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) { if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) {
close(s); close(s);
return -errno; return -errno;

View File

@@ -202,7 +202,8 @@ TEST_F(ClatUtils, GenerateIpv6AddressFailWithUlaSocketAddress) {
in6_addr v6; in6_addr v6;
EXPECT_EQ(1, inet_pton(AF_INET6, "::", &v6)); // initialize as zero 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)); EXPECT_TRUE(IN6_IS_ADDR_ULA(&v6));
tun.destroy(); 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); in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix); 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, 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 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); int configure_packet_socket(int sock, in6_addr* addr, int ifindex);

View File

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

View File

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