Support converting TunnelModeConfigRequest to/from PersistableBundle
Bug: 163604823 Test: FrameworksVcnTests(add new tests) Change-Id: I9c53d4252edb0e8816c84d280b48c4725bd0edc8
This commit is contained in:
@@ -16,17 +16,34 @@
|
||||
|
||||
package android.net.vcn.persistablebundleutils;
|
||||
|
||||
import static android.system.OsConstants.AF_INET;
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
|
||||
import static com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.ipsec.ike.ChildSaProposal;
|
||||
import android.net.ipsec.ike.IkeTrafficSelector;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4Address;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4Netmask;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6Address;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer;
|
||||
import android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest;
|
||||
import android.os.PersistableBundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.vcn.util.PersistableBundleUtils;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -37,15 +54,99 @@ import java.util.Objects;
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||
public final class TunnelModeChildSessionParamsUtils {
|
||||
private static final String TAG = TunnelModeChildSessionParamsUtils.class.getSimpleName();
|
||||
|
||||
private static final String INBOUND_TS_KEY = "INBOUND_TS_KEY";
|
||||
private static final String OUTBOUND_TS_KEY = "OUTBOUND_TS_KEY";
|
||||
private static final String SA_PROPOSALS_KEY = "SA_PROPOSALS_KEY";
|
||||
private static final String HARD_LIFETIME_SEC_KEY = "HARD_LIFETIME_SEC_KEY";
|
||||
private static final String SOFT_LIFETIME_SEC_KEY = "SOFT_LIFETIME_SEC_KEY";
|
||||
private static final String CONFIG_REQUESTS_KEY = "CONFIG_REQUESTS_KEY";
|
||||
|
||||
private static class ConfigRequest {
|
||||
private static final int TYPE_IPV4_ADDRESS = 1;
|
||||
private static final int TYPE_IPV6_ADDRESS = 2;
|
||||
private static final int TYPE_IPV4_DNS = 3;
|
||||
private static final int TYPE_IPV6_DNS = 4;
|
||||
private static final int TYPE_IPV4_DHCP = 5;
|
||||
private static final int TYPE_IPV4_NETMASK = 6;
|
||||
|
||||
private static final String TYPE_KEY = "type";
|
||||
private static final String VALUE_KEY = "address";
|
||||
private static final String IP6_PREFIX_LEN = "ip6PrefixLen";
|
||||
|
||||
private static final int PREFIX_LEN_UNUSED = -1;
|
||||
|
||||
public final int type;
|
||||
public final int ip6PrefixLen;
|
||||
|
||||
// Null when it is an empty request
|
||||
@Nullable public final InetAddress address;
|
||||
|
||||
ConfigRequest(TunnelModeChildConfigRequest config) {
|
||||
int prefixLen = PREFIX_LEN_UNUSED;
|
||||
|
||||
if (config instanceof ConfigRequestIpv4Address) {
|
||||
type = TYPE_IPV4_ADDRESS;
|
||||
address = ((ConfigRequestIpv4Address) config).getAddress();
|
||||
} else if (config instanceof ConfigRequestIpv6Address) {
|
||||
type = TYPE_IPV6_ADDRESS;
|
||||
address = ((ConfigRequestIpv6Address) config).getAddress();
|
||||
if (address != null) {
|
||||
prefixLen = ((ConfigRequestIpv6Address) config).getPrefixLength();
|
||||
}
|
||||
} else if (config instanceof ConfigRequestIpv4DnsServer) {
|
||||
type = TYPE_IPV4_DNS;
|
||||
address = null;
|
||||
} else if (config instanceof ConfigRequestIpv6DnsServer) {
|
||||
type = TYPE_IPV6_DNS;
|
||||
address = null;
|
||||
} else if (config instanceof ConfigRequestIpv4DhcpServer) {
|
||||
type = TYPE_IPV4_DHCP;
|
||||
address = null;
|
||||
} else if (config instanceof ConfigRequestIpv4Netmask) {
|
||||
type = TYPE_IPV4_NETMASK;
|
||||
address = null;
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown TunnelModeChildConfigRequest");
|
||||
}
|
||||
|
||||
ip6PrefixLen = prefixLen;
|
||||
}
|
||||
|
||||
ConfigRequest(PersistableBundle in) {
|
||||
Objects.requireNonNull(in, "PersistableBundle was null");
|
||||
|
||||
type = in.getInt(TYPE_KEY);
|
||||
ip6PrefixLen = in.getInt(IP6_PREFIX_LEN);
|
||||
|
||||
String addressStr = in.getString(VALUE_KEY);
|
||||
if (addressStr == null) {
|
||||
address = null;
|
||||
} else {
|
||||
address = InetAddresses.parseNumericAddress(addressStr);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public PersistableBundle toPersistableBundle() {
|
||||
final PersistableBundle result = new PersistableBundle();
|
||||
|
||||
result.putInt(TYPE_KEY, type);
|
||||
result.putInt(IP6_PREFIX_LEN, ip6PrefixLen);
|
||||
|
||||
if (address != null) {
|
||||
result.putString(VALUE_KEY, address.getHostAddress());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** Serializes a TunnelModeChildSessionParams to a PersistableBundle. */
|
||||
@NonNull
|
||||
public static PersistableBundle toPersistableBundle(TunnelModeChildSessionParams params) {
|
||||
public static PersistableBundle toPersistableBundle(
|
||||
@NonNull TunnelModeChildSessionParams params) {
|
||||
final PersistableBundle result = new PersistableBundle();
|
||||
|
||||
final PersistableBundle saProposalBundle =
|
||||
@@ -68,7 +169,13 @@ public final class TunnelModeChildSessionParamsUtils {
|
||||
result.putInt(HARD_LIFETIME_SEC_KEY, params.getHardLifetimeSeconds());
|
||||
result.putInt(SOFT_LIFETIME_SEC_KEY, params.getSoftLifetimeSeconds());
|
||||
|
||||
// TODO: b/163604823 Support serializing configuration requests.
|
||||
final List<ConfigRequest> reqList = new ArrayList<>();
|
||||
for (TunnelModeChildConfigRequest req : params.getConfigurationRequests()) {
|
||||
reqList.add(new ConfigRequest(req));
|
||||
}
|
||||
final PersistableBundle configReqListBundle =
|
||||
PersistableBundleUtils.fromList(reqList, ConfigRequest::toPersistableBundle);
|
||||
result.putPersistableBundle(CONFIG_REQUESTS_KEY, configReqListBundle);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -109,8 +216,69 @@ public final class TunnelModeChildSessionParamsUtils {
|
||||
|
||||
builder.setLifetimeSeconds(
|
||||
in.getInt(HARD_LIFETIME_SEC_KEY), in.getInt(SOFT_LIFETIME_SEC_KEY));
|
||||
final PersistableBundle configReqListBundle = in.getPersistableBundle(CONFIG_REQUESTS_KEY);
|
||||
Objects.requireNonNull(configReqListBundle, "Config request list was null");
|
||||
final List<ConfigRequest> reqList =
|
||||
PersistableBundleUtils.toList(configReqListBundle, ConfigRequest::new);
|
||||
|
||||
// TODO: b/163604823 Support deserializing configuration requests.
|
||||
boolean hasIpv4AddressReq = false;
|
||||
boolean hasIpv4NetmaskReq = false;
|
||||
for (ConfigRequest req : reqList) {
|
||||
switch (req.type) {
|
||||
case ConfigRequest.TYPE_IPV4_ADDRESS:
|
||||
hasIpv4AddressReq = true;
|
||||
if (req.address == null) {
|
||||
builder.addInternalAddressRequest(AF_INET);
|
||||
} else {
|
||||
builder.addInternalAddressRequest((Inet4Address) req.address);
|
||||
}
|
||||
break;
|
||||
case ConfigRequest.TYPE_IPV6_ADDRESS:
|
||||
if (req.address == null) {
|
||||
builder.addInternalAddressRequest(AF_INET6);
|
||||
} else {
|
||||
builder.addInternalAddressRequest(
|
||||
(Inet6Address) req.address, req.ip6PrefixLen);
|
||||
}
|
||||
break;
|
||||
case ConfigRequest.TYPE_IPV4_NETMASK:
|
||||
// Do not need to set netmask because it will be automatically set by the
|
||||
// builder when an IPv4 internal address request is set.
|
||||
hasIpv4NetmaskReq = true;
|
||||
break;
|
||||
case ConfigRequest.TYPE_IPV4_DNS:
|
||||
if (req.address != null) {
|
||||
Log.w(TAG, "Requesting a specific IPv4 DNS server is unsupported");
|
||||
}
|
||||
builder.addInternalDnsServerRequest(AF_INET);
|
||||
break;
|
||||
case ConfigRequest.TYPE_IPV6_DNS:
|
||||
if (req.address != null) {
|
||||
Log.w(TAG, "Requesting a specific IPv6 DNS server is unsupported");
|
||||
}
|
||||
builder.addInternalDnsServerRequest(AF_INET6);
|
||||
break;
|
||||
case ConfigRequest.TYPE_IPV4_DHCP:
|
||||
if (req.address != null) {
|
||||
Log.w(TAG, "Requesting a specific IPv4 DHCP server is unsupported");
|
||||
}
|
||||
builder.addInternalDhcpServerRequest(AF_INET);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unrecognized config request type: " + req.type);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasIpv4AddressReq != hasIpv4NetmaskReq) {
|
||||
Log.w(
|
||||
TAG,
|
||||
String.format(
|
||||
"Expect IPv4 address request and IPv4 netmask request either both"
|
||||
+ " exist or both absent, but found hasIpv4AddressReq exists? %b,"
|
||||
+ " hasIpv4AddressReq exists? %b, ",
|
||||
hasIpv4AddressReq, hasIpv4NetmaskReq));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package android.net.vcn.persistablebundleutils;
|
||||
|
||||
import static android.system.OsConstants.AF_INET;
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.net.InetAddresses;
|
||||
@@ -30,6 +33,8 @@ import androidx.test.runner.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -88,4 +93,25 @@ public class TunnelModeChildSessionParamsUtilsTest {
|
||||
createBuilderMinimum().setLifetimeSeconds(hardLifetime, softLifetime).build();
|
||||
verifyPersistableBundleEncodeDecodeIsLossless(sessionParams);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetConfigRequestsEncodeDecodeIsLossless() throws Exception {
|
||||
final int ipv6PrefixLen = 64;
|
||||
final Inet4Address ipv4Address =
|
||||
(Inet4Address) InetAddresses.parseNumericAddress("192.0.2.100");
|
||||
final Inet6Address ipv6Address =
|
||||
(Inet6Address) InetAddresses.parseNumericAddress("2001:db8::1");
|
||||
|
||||
final TunnelModeChildSessionParams sessionParams =
|
||||
createBuilderMinimum()
|
||||
.addInternalAddressRequest(AF_INET)
|
||||
.addInternalAddressRequest(AF_INET6)
|
||||
.addInternalAddressRequest(ipv4Address)
|
||||
.addInternalAddressRequest(ipv6Address, ipv6PrefixLen)
|
||||
.addInternalDnsServerRequest(AF_INET)
|
||||
.addInternalDnsServerRequest(AF_INET6)
|
||||
.addInternalDhcpServerRequest(AF_INET)
|
||||
.build();
|
||||
verifyPersistableBundleEncodeDecodeIsLossless(sessionParams);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user