diff options
4 files changed, 243 insertions, 43 deletions
diff --git a/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java b/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java index 6a1628eb..f43a6eaf 100644 --- a/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java +++ b/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptions.java @@ -24,8 +24,12 @@ import android.net.LinkAddress; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttribute; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dns; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv6Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv6Dns; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv6Subnet; import java.net.Inet4Address; import java.net.Inet6Address; @@ -131,6 +135,72 @@ public final class TunnelModeChildSessionOptions extends ChildSessionOptions { } /** + * Adds internal DNS server requests to TunnelModeChildSessionOptions being built. + * + * @param addressFamily the address family. Only OsConstants.AF_INET and + * OsConstants.AF_INET6 are allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDnsServerRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Dns()); + } + return this; + } else if (addressFamily == AF_INET6) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv6Dns()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** + * Adds internal DNS server requests to TunnelModeChildSessionOptions being built. + * + * @param address the requested DNS server address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalDnsServerRequest(@NonNull InetAddress address) { + if (address instanceof Inet4Address) { + mConfigRequestList.add(new ConfigAttributeIpv4Dns((Inet4Address) address)); + return this; + } else if (address instanceof Inet6Address) { + mConfigRequestList.add(new ConfigAttributeIpv6Dns((Inet6Address) address)); + return this; + } else { + throw new IllegalArgumentException("Invalid address " + address); + } + } + + /** + * Adds internal subnet requests to TunnelModeChildSessionOptions being built. + * + * @param addressFamily the address family. Only OsConstants.AF_INET and + * OsConstants.AF_INET6 are allowed. + * @param numOfRequest the number of requests for this type of address. + * @return Builder this, to facilitate chaining. + */ + public Builder addInternalSubnetRequest(int addressFamily, int numOfRequest) { + if (addressFamily == AF_INET) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv4Subnet()); + } + return this; + } else if (addressFamily == AF_INET6) { + for (int i = 0; i < numOfRequest; i++) { + mConfigRequestList.add(new ConfigAttributeIpv6Subnet()); + } + return this; + } else { + throw new IllegalArgumentException("Invalid address family: " + addressFamily); + } + } + + /** * Validates, builds and returns the TunnelModeChildSessionOptions. * * @return the validated TunnelModeChildSessionOptions. diff --git a/src/java/com/android/ike/ikev2/message/IkeConfigPayload.java b/src/java/com/android/ike/ikev2/message/IkeConfigPayload.java index 6d05732b..3211920c 100644 --- a/src/java/com/android/ike/ikev2/message/IkeConfigPayload.java +++ b/src/java/com/android/ike/ikev2/message/IkeConfigPayload.java @@ -21,6 +21,7 @@ import android.net.LinkAddress; import com.android.ike.ikev2.IkeManager; import com.android.ike.ikev2.exceptions.InvalidSyntaxException; +import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -200,6 +201,9 @@ public final class IkeConfigPayload extends IkePayload { case CONFIG_ATTR_INTERNAL_IP4_DNS: configList.add(new ConfigAttributeIpv4Dns(value)); break; + case CONFIG_ATTR_INTERNAL_IP4_DHCP: + configList.add(new ConfigAttributeIpv4Dhcp(value)); + break; case CONFIG_ATTR_INTERNAL_IP6_ADDRESS: configList.add(new ConfigAttributeIpv6Address(value)); break; @@ -213,10 +217,13 @@ public final class IkeConfigPayload extends IkePayload { configList.add(new ConfigAttributeIpv6Subnet(value)); break; default: - // Ignore unrecognized attribute type. + IkeManager.getIkeLog() + .i( + "IkeConfigPayload", + "Unrecognized attribute type: " + attributeType); } - // TODO: Support DHCP4, App version and supported attribute list + // TODO: Support App version and supported attribute list } return configList; @@ -342,14 +349,15 @@ public final class IkeConfigPayload extends IkePayload { /** * Construct an instance without a specified address for an outbound packet. * - * <p>It should be only used in a configuration request. + * <p>It must be only used in a configuration request. */ public ConfigAttributeIpv4Address() { super(CONFIG_ATTR_INTERNAL_IP4_ADDRESS); } /** Construct an instance with a decoded inbound packet. */ - public ConfigAttributeIpv4Address(byte[] value) throws InvalidSyntaxException { + @VisibleForTesting + ConfigAttributeIpv4Address(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP4_ADDRESS, value); } } @@ -362,15 +370,16 @@ public final class IkeConfigPayload extends IkePayload { */ public static class ConfigAttributeIpv4Netmask extends ConfigAttrIpv4AddressBase { /** - * Construct an instance without a specified address for an outbound packet. + * Construct an instance without a specified netmask for an outbound packet. * - * <p>It should be only used in a configuration request. + * <p>It must be only used in a configuration request. */ public ConfigAttributeIpv4Netmask() { super(CONFIG_ATTR_INTERNAL_IP4_NETMASK); } /** Construct an instance with a decoded inbound packet. */ + @VisibleForTesting public ConfigAttributeIpv4Netmask(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP4_NETMASK, value); @@ -388,6 +397,29 @@ public final class IkeConfigPayload extends IkePayload { } } + /** This class represents Configuration Attribute for IPv4 DHCP server. */ + public static class ConfigAttributeIpv4Dhcp extends ConfigAttrIpv4AddressBase { + /** Construct an instance with specified DHCP server address for an outbound packet. */ + public ConfigAttributeIpv4Dhcp(Inet4Address ipv4Address) { + super(CONFIG_ATTR_INTERNAL_IP4_DHCP, ipv4Address); + } + + /** + * Construct an instance without a specified DHCP server address for an outbound packet. + * + * <p>It must be only used in a configuration request. + */ + public ConfigAttributeIpv4Dhcp() { + super(CONFIG_ATTR_INTERNAL_IP4_DHCP); + } + + /** Construct an instance with a decoded inbound packet. */ + @VisibleForTesting + ConfigAttributeIpv4Dhcp(byte[] value) throws InvalidSyntaxException { + super(CONFIG_ATTR_INTERNAL_IP4_DHCP, value); + } + } + /** * This class represents Configuration Attribute for IPv4 DNS. * @@ -395,17 +427,23 @@ public final class IkeConfigPayload extends IkePayload { * client, we will only support building an empty DNS attribute for an outbound IKE packet. */ public static class ConfigAttributeIpv4Dns extends ConfigAttrIpv4AddressBase { + /** Construct an instance with specified DNS server address for an outbound packet. */ + public ConfigAttributeIpv4Dns(Inet4Address ipv4Address) { + super(CONFIG_ATTR_INTERNAL_IP4_DNS, ipv4Address); + } + /** - * Construct an instance without a specified address for an outbound packet. + * Construct an instance without a specified DNS server address for an outbound packet. * - * <p>It should be only used in a configuration request. + * <p>It must be only used in a configuration request. */ public ConfigAttributeIpv4Dns() { super(CONFIG_ATTR_INTERNAL_IP4_DNS); } /** Construct an instance with a decoded inbound packet. */ - public ConfigAttributeIpv4Dns(byte[] value) throws InvalidSyntaxException { + @VisibleForTesting + ConfigAttributeIpv4Dns(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP4_DNS, value); } } @@ -416,7 +454,8 @@ public final class IkeConfigPayload extends IkePayload { public final LinkAddress linkAddress; - protected ConfigAttributeIpv4Subnet(LinkAddress ipv4LinkAddress) { + /** Construct an instance with specified subnet for an outbound packet. */ + public ConfigAttributeIpv4Subnet(LinkAddress ipv4LinkAddress) { super(CONFIG_ATTR_INTERNAL_IP4_SUBNET); if (!ipv4LinkAddress.isIpv4()) { @@ -426,12 +465,19 @@ public final class IkeConfigPayload extends IkePayload { this.linkAddress = ipv4LinkAddress; } - protected ConfigAttributeIpv4Subnet() { + /** + * Construct an instance without a specified subnet for an outbound packet. + * + * <p>It must be only used in a configuration request. + */ + public ConfigAttributeIpv4Subnet() { super(CONFIG_ATTR_INTERNAL_IP4_SUBNET); this.linkAddress = null; } - protected ConfigAttributeIpv4Subnet(byte[] value) throws InvalidSyntaxException { + /** Construct an instance with a decoded inbound packet. */ + @VisibleForTesting + ConfigAttributeIpv4Subnet(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP4_SUBNET, value.length); if (value.length == VALUE_LEN_NOT_INCLUDED) { @@ -569,36 +615,38 @@ public final class IkeConfigPayload extends IkePayload { /** * Construct an instance without a specified address for an outbound packet. * - * <p>It should be only used in a configuration request. + * <p>It must be only used in a configuration request. */ public ConfigAttributeIpv6Address() { super(CONFIG_ATTR_INTERNAL_IP6_ADDRESS); } /** Construct an instance with a decoded inbound packet. */ - public ConfigAttributeIpv6Address(byte[] value) throws InvalidSyntaxException { + @VisibleForTesting + ConfigAttributeIpv6Address(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP6_ADDRESS, value); } } /** This class represents Configuration Attribute for IPv6 subnets. */ public static class ConfigAttributeIpv6Subnet extends ConfigAttrIpv6AddrRangeBase { - /** Construct an instance with specified address for an outbound packet. */ + /** Construct an instance with specified subnet for an outbound packet. */ public ConfigAttributeIpv6Subnet(LinkAddress ipv6LinkAddress) { super(CONFIG_ATTR_INTERNAL_IP6_SUBNET, ipv6LinkAddress); } /** - * Construct an instance without a specified address for an outbound packet. + * Construct an instance without a specified subnet for an outbound packet. * - * <p>It should be only used in a configuration request. + * <p>It must be only used in a configuration request. */ public ConfigAttributeIpv6Subnet() { super(CONFIG_ATTR_INTERNAL_IP6_SUBNET); } /** Construct an instance with a decoded inbound packet. */ - public ConfigAttributeIpv6Subnet(byte[] value) throws InvalidSyntaxException { + @VisibleForTesting + ConfigAttributeIpv6Subnet(byte[] value) throws InvalidSyntaxException { super(CONFIG_ATTR_INTERNAL_IP6_SUBNET, value); } } @@ -612,7 +660,18 @@ public final class IkeConfigPayload extends IkePayload { public static class ConfigAttributeIpv6Dns extends ConfigAttribute { public final Inet6Address address; - protected ConfigAttributeIpv6Dns() { + /** Construct an instance with specified DNS server address for an outbound packet. */ + public ConfigAttributeIpv6Dns(Inet6Address ipv6Address) { + super(CONFIG_ATTR_INTERNAL_IP6_DNS); + address = ipv6Address; + } + + /** + * Construct an instance without a specified DNS server address for an outbound packet. + * + * <p>It must be only used in a configuration request. + */ + public ConfigAttributeIpv6Dns() { super(CONFIG_ATTR_INTERNAL_IP6_DNS); this.address = null; } diff --git a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java index a67d44f9..5ed6480c 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/TunnelModeChildSessionOptionsTest.java @@ -20,8 +20,12 @@ import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_DNS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_SUBNET; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -52,6 +56,11 @@ public final class TunnelModeChildSessionOptionsTest { private static final Inet6Address IPV6_ADDRESS = (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:db8::1")); + private static final Inet4Address IPV4_DNS_SERVER = + (Inet4Address) (InetAddressUtils.parseNumericAddress("8.8.8.8")); + private static final Inet6Address IPV6_DNS_SERVER = + (Inet6Address) (InetAddressUtils.parseNumericAddress("2001:4860:4860::8888")); + private ChildSaProposal mSaProposal; @Before @@ -130,4 +139,43 @@ public final class TunnelModeChildSessionOptionsTest { } } + + @Test + public void testBuildChildSessionOptionsWithDnsServerReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalDnsServerRequest(AF_INET, 1) + .addInternalDnsServerRequest(AF_INET6, 1) + .addInternalDnsServerRequest(IPV4_DNS_SERVER) + .addInternalDnsServerRequest(IPV6_DNS_SERVER) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_DNS, 2); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_DNS, 2); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } + + @Test + public void testBuildChildSessionOptionsWithSubnetReq() { + TunnelModeChildSessionOptions childOptions = + new TunnelModeChildSessionOptions.Builder() + .addSaProposal(mSaProposal) + .addInternalSubnetRequest(AF_INET, 1) + .addInternalSubnetRequest(AF_INET6, 1) + .build(); + + verifyCommon(childOptions); + + SparseArray<Integer> exptectedAttrCntMap = new SparseArray<>(); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP4_SUBNET, 1); + exptectedAttrCntMap.put(CONFIG_ATTR_INTERNAL_IP6_SUBNET, 1); + + verifyAttrTypes(exptectedAttrCntMap, childOptions); + } } + diff --git a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java index 9ee6a620..e8a67d79 100644 --- a/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java +++ b/tests/iketests/src/java/com/android/ike/ikev2/message/IkeConfigPayloadTest.java @@ -17,6 +17,7 @@ package com.android.ike.ikev2.message; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; +import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DHCP; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; import static com.android.ike.ikev2.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; @@ -47,6 +48,7 @@ import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv4AddressBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttrIpv6AddrRangeBase; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttribute; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Address; +import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Dns; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; import com.android.ike.ikev2.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; @@ -104,6 +106,13 @@ public final class IkeConfigPayloadTest { private static final byte[] IPV4_DNS_ATTRIBUTE_WITHOUT_VALUE = TestUtils.hexStringToByteArray("00030000"); + private static final Inet4Address IPV4_DHCP = + (Inet4Address) (InetAddressUtils.parseNumericAddress("192.0.2.200")); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITH_VALUE = + TestUtils.hexStringToByteArray("00060004c00002c8"); + private static final byte[] IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE = + TestUtils.hexStringToByteArray("00060000"); + private static final byte[] IPV4_SUBNET_ATTRIBUTE_VALUE = TestUtils.hexStringToByteArray("c0000264fffffff0"); private static final byte[] IPV4_SUBNET_ATTRIBUTE_WITH_VALUE = @@ -420,6 +429,44 @@ public final class IkeConfigPayloadTest { } @Test + public void testDecodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(IPV4_DHCP.getAddress()); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertEquals(IPV4_DHCP, attribute.address); + } + + @Test + public void testDecodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(new byte[0]); + + assertEquals(CONFIG_ATTR_INTERNAL_IP4_DHCP, attribute.attributeType); + assertNull(attribute.address); + } + + @Test + public void testEncodeIpv4DhcpWithValue() throws Exception { + ConfigAttributeIpv4Dhcp attributeIp4Dhcp = new ConfigAttributeIpv4Dhcp(IPV4_DHCP); + + verifyEncodeIpv4AddresBaseAttribute( + attributeIp4Dhcp, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITH_VALUE, + IPV4_DHCP); + } + + @Test + public void testEncodeIpv4DhcpWithoutValue() throws Exception { + ConfigAttributeIpv4Dhcp attribute = new ConfigAttributeIpv4Dhcp(); + + verifyEncodeIpv4AddresBaseAttribute( + attribute, + CONFIG_ATTR_INTERNAL_IP4_DHCP, + IPV4_DHCP_ATTRIBUTE_WITHOUT_VALUE, + null /*expectedAddress*/); + } + + @Test public void testDecodeIpv4SubnetWithValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(IPV4_SUBNET_ATTRIBUTE_VALUE); @@ -450,18 +497,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv4SubnetWithValue() throws Exception { - ConfigAttributeIpv4Subnet attributeIp4Subnet = - new ConfigAttributeIpv4Subnet(IPV4_LINK_ADDRESS); - - verifyBuildAndEncodeAttributeCommon( - attributeIp4Subnet, - CONFIG_ATTR_INTERNAL_IP4_SUBNET, - IPV4_SUBNET_ATTRIBUTE_WITH_VALUE); - assertEquals(IPV4_LINK_ADDRESS, attributeIp4Subnet.linkAddress); - } - - @Test public void testEncodeIpv4SubnetWithoutValue() throws Exception { ConfigAttributeIpv4Subnet attributeIp4Subnet = new ConfigAttributeIpv4Subnet(); @@ -559,18 +594,6 @@ public final class IkeConfigPayloadTest { } @Test - public void testEncodeIpv6SubnetWithValue() throws Exception { - ConfigAttributeIpv6Subnet attributeIp6Subnet = - new ConfigAttributeIpv6Subnet(IPV6_LINK_ADDRESS); - - verifyEncodeIpv6RangeBaseAttribute( - attributeIp6Subnet, - CONFIG_ATTR_INTERNAL_IP6_SUBNET, - IPV6_SUBNET_ATTRIBUTE_WITH_VALUE, - IPV6_LINK_ADDRESS); - } - - @Test public void testEncodeIpv6SubnetWithoutValue() throws Exception { ConfigAttributeIpv6Subnet attributeIp6Subnet = new ConfigAttributeIpv6Subnet(); |