Test Ikev2VpnProfile provisioned with IkeTunnelConnectionParams

Bug: 223841137
Test: atest CtsNetTestCases FrameworksNetTests
Change-Id: I683f6242e4ed4a469893e3a17fe7b479a7a768e5
This commit is contained in:
chiachangwang
2022-04-14 21:31:26 +08:00
parent 0366028f64
commit 476e2a08bf
4 changed files with 161 additions and 75 deletions

View File

@@ -20,8 +20,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
@@ -51,6 +49,7 @@ import android.net.ProxyInfo;
import android.net.TestNetworkInterface; import android.net.TestNetworkInterface;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.cts.util.CtsNetUtils; import android.net.cts.util.CtsNetUtils;
import android.net.cts.util.IkeSessionTestUtils;
import android.net.ipsec.ike.IkeTunnelConnectionParams; import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.os.Build; import android.os.Build;
import android.os.Process; import android.os.Process;
@@ -252,6 +251,28 @@ public class Ikev2VpnTest {
return builder.build(); return builder.build();
} }
private Ikev2VpnProfile buildIkev2VpnProfileIkeTunConnParams(
final boolean isRestrictedToTestNetworks, final boolean requiresValidation,
final boolean testIpv6) throws Exception {
final IkeTunnelConnectionParams params =
new IkeTunnelConnectionParams(testIpv6
? IkeSessionTestUtils.IKE_PARAMS_V6 : IkeSessionTestUtils.IKE_PARAMS_V4,
IkeSessionTestUtils.CHILD_PARAMS);
final Ikev2VpnProfileBuilderShim builderShim =
Ikev2VpnProfileBuilderShimImpl.newInstance(null, null, params)
.setRequiresInternetValidation(requiresValidation)
.setProxy(TEST_PROXY_INFO)
.setMaxMtu(TEST_MTU)
.setMetered(false);
final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
if (isRestrictedToTestNetworks) {
builder.restrictToTestNetworks();
}
return builder.build();
}
private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote, private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote,
boolean isRestrictedToTestNetworks, boolean requiresValidation) throws Exception { boolean isRestrictedToTestNetworks, boolean requiresValidation) throws Exception {
final Ikev2VpnProfileBuilderShim builder = final Ikev2VpnProfileBuilderShim builder =
@@ -325,8 +346,8 @@ public class Ikev2VpnTest {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
assumeTrue(TestUtils.shouldTestTApis()); assumeTrue(TestUtils.shouldTestTApis());
final IkeTunnelConnectionParams expectedParams = final IkeTunnelConnectionParams expectedParams = new IkeTunnelConnectionParams(
new IkeTunnelConnectionParams(IKE_PARAMS, CHILD_PARAMS); IkeSessionTestUtils.IKE_PARAMS_V6, IkeSessionTestUtils.CHILD_PARAMS);
final Ikev2VpnProfileBuilderShim ikeProfileBuilder = final Ikev2VpnProfileBuilderShim ikeProfileBuilder =
Ikev2VpnProfileBuilderShimImpl.newInstance(null, null, expectedParams); Ikev2VpnProfileBuilderShimImpl.newInstance(null, null, expectedParams);
// Verify the other Ike options could not be set with IkeTunnelConnectionParams. // Verify the other Ike options could not be set with IkeTunnelConnectionParams.
@@ -472,7 +493,8 @@ public class Ikev2VpnTest {
} }
private void checkStartStopVpnProfileBuildsNetworks(@NonNull IkeTunUtils tunUtils, private void checkStartStopVpnProfileBuildsNetworks(@NonNull IkeTunUtils tunUtils,
boolean testIpv6, boolean requiresValidation, boolean testSessionKey) boolean testIpv6, boolean requiresValidation, boolean testSessionKey,
boolean testIkeTunConnParams)
throws Exception { throws Exception {
String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4; String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4; String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4;
@@ -482,8 +504,11 @@ public class Ikev2VpnTest {
// Requires MANAGE_TEST_NETWORKS to provision a test-mode profile. // Requires MANAGE_TEST_NETWORKS to provision a test-mode profile.
mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true);
final Ikev2VpnProfile profile = buildIkev2VpnProfilePsk(serverAddr, final Ikev2VpnProfile profile = testIkeTunConnParams
true /* isRestrictedToTestNetworks */, requiresValidation); ? buildIkev2VpnProfileIkeTunConnParams(true /* isRestrictedToTestNetworks */,
requiresValidation, testIpv6)
: buildIkev2VpnProfilePsk(serverAddr, true /* isRestrictedToTestNetworks */,
requiresValidation);
assertNull(sVpnMgr.provisionVpnProfile(profile)); assertNull(sVpnMgr.provisionVpnProfile(profile));
final TestableNetworkCallback cb = new TestableNetworkCallback(TIMEOUT_MS); final TestableNetworkCallback cb = new TestableNetworkCallback(TIMEOUT_MS);
@@ -564,6 +589,7 @@ public class Ikev2VpnTest {
private final boolean mTestIpv6Only; private final boolean mTestIpv6Only;
private final boolean mRequiresValidation; private final boolean mRequiresValidation;
private final boolean mTestSessionKey; private final boolean mTestSessionKey;
private final boolean mTestIkeTunConnParams;
/** /**
* Constructs the test * Constructs the test
@@ -573,10 +599,11 @@ public class Ikev2VpnTest {
* @param testSessionKey if true, start VPN by calling startProvisionedVpnProfileSession() * @param testSessionKey if true, start VPN by calling startProvisionedVpnProfileSession()
*/ */
VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation, VerifyStartStopVpnProfileTest(boolean testIpv6Only, boolean requiresValidation,
boolean testSessionKey) { boolean testSessionKey, boolean testIkeTunConnParams) {
mTestIpv6Only = testIpv6Only; mTestIpv6Only = testIpv6Only;
mRequiresValidation = requiresValidation; mRequiresValidation = requiresValidation;
mTestSessionKey = testSessionKey; mTestSessionKey = testSessionKey;
mTestIkeTunConnParams = testIkeTunConnParams;
} }
@Override @Override
@@ -584,8 +611,8 @@ public class Ikev2VpnTest {
throws Exception { throws Exception {
final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor()); final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor());
checkStartStopVpnProfileBuildsNetworks( checkStartStopVpnProfileBuildsNetworks(tunUtils, mTestIpv6Only, mRequiresValidation,
tunUtils, mTestIpv6Only, mRequiresValidation, mTestSessionKey); mTestSessionKey, mTestIkeTunConnParams);
} }
@Override @Override
@@ -603,53 +630,83 @@ public class Ikev2VpnTest {
} }
} }
@Test private void doTestStartStopVpnProfile(boolean testIpv6Only, boolean requiresValidation,
public void testStartStopVpnProfileV4() throws Exception { boolean testSessionKey, boolean testIkeTunConnParams) throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
// Requires shell permission to update appops. // Requires shell permission to update appops.
runWithShellPermissionIdentity( runWithShellPermissionIdentity(
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest( new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(
false /* testIpv6Only */, false /* requiresValidation */, testIpv6Only, requiresValidation, testSessionKey , testIkeTunConnParams)));
false /* testSessionKey */))); }
runWithShellPermissionIdentity( @Test
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest( public void testStartStopVpnProfileV4() throws Exception {
false /* testIpv6Only */, true /* requiresValidation */, doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
false /* testSessionKey */))); false /* testSessionKey */, false /* testIkeTunConnParams */);
}
@Test @IgnoreUpTo(SC_V2)
public void testStartStopVpnProfileV4WithValidation() throws Exception {
assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */,
false /* testSessionKey */, false /* testIkeTunConnParams */);
} }
@Test @Test
public void testStartStopVpnProfileV6() throws Exception { public void testStartStopVpnProfileV6() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
false /* testSessionKey */, false /* testIkeTunConnParams */);
}
// Requires shell permission to update appops. @Test @IgnoreUpTo(SC_V2)
runWithShellPermissionIdentity( public void testStartStopVpnProfileV6WithValidation() throws Exception {
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest( assumeTrue(TestUtils.shouldTestTApis());
true /* testIpv6Only */, false /* requiresValidation */, doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */,
false /* testSessionKey */))); false /* testSessionKey */, false /* testIkeTunConnParams */);
runWithShellPermissionIdentity( }
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(
true /* testIpv6Only */, true /* requiresValidation */, @Test @IgnoreUpTo(SC_V2)
false /* testSessionKey */))); public void testStartStopVpnProfileIkeTunConnParamsV4() throws Exception {
assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
false /* testSessionKey */, true /* testIkeTunConnParams */);
}
@Test @IgnoreUpTo(SC_V2)
public void testStartStopVpnProfileIkeTunConnParamsV4WithValidation() throws Exception {
assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(false /* testIpv6Only */, true /* requiresValidation */,
false /* testSessionKey */, true /* testIkeTunConnParams */);
}
@Test @IgnoreUpTo(SC_V2)
public void testStartStopVpnProfileIkeTunConnParamsV6() throws Exception {
assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
false /* testSessionKey */, true /* testIkeTunConnParams */);
}
@Test @IgnoreUpTo(SC_V2)
public void testStartStopVpnProfileIkeTunConnParamsV6WithValidation() throws Exception {
assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(true /* testIpv6Only */, true /* requiresValidation */,
false /* testSessionKey */, true /* testIkeTunConnParams */);
} }
@IgnoreUpTo(SC_V2) @IgnoreUpTo(SC_V2)
@Test @Test
public void testStartProvisionedVpnProfileSession() throws Exception { public void testStartProvisionedVpnV4ProfileSession() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
assumeTrue(TestUtils.shouldTestTApis()); assumeTrue(TestUtils.shouldTestTApis());
doTestStartStopVpnProfile(false /* testIpv6Only */, false /* requiresValidation */,
true /* testSessionKey */, false /* testIkeTunConnParams */);
}
// Requires shell permission to update appops. @IgnoreUpTo(SC_V2)
runWithShellPermissionIdentity( @Test
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest( public void testStartProvisionedVpnV6ProfileSession() throws Exception {
false /* testIpv6Only */, false /* requiresValidation */, assumeTrue(TestUtils.shouldTestTApis());
true /* testSessionKey */))); doTestStartStopVpnProfile(true /* testIpv6Only */, false /* requiresValidation */,
true /* testSessionKey */, false /* testIkeTunConnParams */);
runWithShellPermissionIdentity(
new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(
true /* testIpv6Only */, false /* requiresValidation */,
true /* testSessionKey */)));
} }
private static class CertificateAndKey { private static class CertificateAndKey {

View File

@@ -16,44 +16,73 @@
package android.net.cts.util; package android.net.cts.util;
import static android.net.ipsec.ike.SaProposal.DH_GROUP_4096_BIT_MODP;
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128; import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
import static android.net.ipsec.ike.SaProposal.KEY_LEN_UNUSED; import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
import android.net.InetAddresses;
import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.IkeFqdnIdentification; import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeIpv4AddrIdentification;
import android.net.ipsec.ike.IkeIpv6AddrIdentification;
import android.net.ipsec.ike.IkeSaProposal; import android.net.ipsec.ike.IkeSaProposal;
import android.net.ipsec.ike.IkeSessionParams; import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.SaProposal;
import android.net.ipsec.ike.TunnelModeChildSessionParams; import android.net.ipsec.ike.TunnelModeChildSessionParams;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
/** Shared testing parameters and util methods for testing IKE */ /** Shared testing parameters and util methods for testing IKE */
public class IkeSessionTestUtils { public class IkeSessionTestUtils {
private static final String TEST_CLIENT_ADDR = "test.client.com"; private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2";
private static final String TEST_SERVER_ADDR = "test.server.com"; private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2";
private static final String TEST_SERVER = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; private static final String TEST_IDENTITY = "client.cts.android.com";
private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes();
public static final IkeSessionParams IKE_PARAMS_V4 = getTestIkeSessionParams(false);
public static final IkeSessionParams IKE_PARAMS_V6 = getTestIkeSessionParams(true);
public static final IkeSaProposal SA_PROPOSAL = new IkeSaProposal.Builder() public static final TunnelModeChildSessionParams CHILD_PARAMS = getChildSessionParams();
.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_3DES, KEY_LEN_UNUSED)
.addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96)
.addPseudorandomFunction(SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)
.addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
.build();
public static final ChildSaProposal CHILD_PROPOSAL = new ChildSaProposal.Builder()
.addEncryptionAlgorithm(SaProposal.ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128)
.addIntegrityAlgorithm(SaProposal.INTEGRITY_ALGORITHM_NONE)
.addDhGroup(SaProposal.DH_GROUP_1024_BIT_MODP)
.build();
public static final IkeSessionParams IKE_PARAMS = private static TunnelModeChildSessionParams getChildSessionParams() {
new IkeSessionParams.Builder() final TunnelModeChildSessionParams.Builder childOptionsBuilder =
.setServerHostname(TEST_SERVER) new TunnelModeChildSessionParams.Builder()
.addSaProposal(SA_PROPOSAL) .addSaProposal(getChildSaProposals());
.setLocalIdentification(new IkeFqdnIdentification(TEST_CLIENT_ADDR))
.setRemoteIdentification(new IkeFqdnIdentification(TEST_SERVER_ADDR)) return childOptionsBuilder.build();
.setAuthPsk("psk".getBytes()) }
.build();
public static final TunnelModeChildSessionParams CHILD_PARAMS = private static IkeSessionParams getTestIkeSessionParams(boolean testIpv6) {
new TunnelModeChildSessionParams.Builder() final String testServer = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
.addSaProposal(CHILD_PROPOSAL) final InetAddress addr = InetAddresses.parseNumericAddress(testServer);
.build(); final IkeSessionParams.Builder ikeOptionsBuilder =
new IkeSessionParams.Builder()
.setServerHostname(testServer)
.setLocalIdentification(new IkeFqdnIdentification(TEST_IDENTITY))
.setRemoteIdentification(testIpv6
? new IkeIpv6AddrIdentification((Inet6Address) addr)
: new IkeIpv4AddrIdentification((Inet4Address) addr))
.setAuthPsk(TEST_PSK)
.addSaProposal(getIkeSaProposals());
return ikeOptionsBuilder.build();
}
private static IkeSaProposal getIkeSaProposals() {
return new IkeSaProposal.Builder()
.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256)
.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128)
.addDhGroup(DH_GROUP_4096_BIT_MODP)
.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC).build();
}
private static ChildSaProposal getChildSaProposals() {
return new ChildSaProposal.Builder()
.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128)
.build();
}
} }

View File

@@ -17,7 +17,7 @@
package android.net; package android.net;
import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS; import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS; import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V6;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
@@ -448,7 +448,7 @@ public class Ikev2VpnProfileTest {
@Test @Test
public void testConversionIsLosslessWithIkeTunConnParams() throws Exception { public void testConversionIsLosslessWithIkeTunConnParams() throws Exception {
final IkeTunnelConnectionParams tunnelParams = final IkeTunnelConnectionParams tunnelParams =
new IkeTunnelConnectionParams(IKE_PARAMS, CHILD_PARAMS); new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
// Config authentication related fields is not required while building with // Config authentication related fields is not required while building with
// IkeTunnelConnectionParams. // IkeTunnelConnectionParams.
final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams).build(); final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams).build();
@@ -464,9 +464,9 @@ public class Ikev2VpnProfileTest {
// Verify building with IkeTunnelConnectionParams // Verify building with IkeTunnelConnectionParams
final IkeTunnelConnectionParams tunnelParams = final IkeTunnelConnectionParams tunnelParams =
new IkeTunnelConnectionParams(IKE_PARAMS, CHILD_PARAMS); new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
final IkeTunnelConnectionParams tunnelParams2 = final IkeTunnelConnectionParams tunnelParams2 =
new IkeTunnelConnectionParams(IKE_PARAMS, CHILD_PARAMS); new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
assertEquals(new Ikev2VpnProfile.Builder(tunnelParams).build(), assertEquals(new Ikev2VpnProfile.Builder(tunnelParams).build(),
new Ikev2VpnProfile.Builder(tunnelParams2).build()); new Ikev2VpnProfile.Builder(tunnelParams2).build());
} }

View File

@@ -17,7 +17,7 @@
package com.android.internal.net; package com.android.internal.net;
import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS; import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS; import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V4;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT; import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelSane;
@@ -128,7 +128,7 @@ public class VpnProfileTest {
private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) { private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) {
final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */, final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
false /* excludesLocalRoutes */, true /* requiresPlatformValidation */, false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
new IkeTunnelConnectionParams(IKE_PARAMS, CHILD_PARAMS)); new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS));
p.name = "foo"; p.name = "foo";
p.server = "bar"; p.server = "bar";