1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.shared;
18 
19 import static android.net.InetAddresses.parseNumericAddress;
20 import static android.net.ip.IIpClient.PROV_IPV4_DHCP;
21 import static android.net.ip.IIpClient.PROV_IPV4_DISABLED;
22 import static android.net.ip.IIpClient.PROV_IPV4_STATIC;
23 import static android.net.ip.IIpClient.PROV_IPV6_DISABLED;
24 import static android.net.ip.IIpClient.PROV_IPV6_LINKLOCAL;
25 import static android.net.ip.IIpClient.PROV_IPV6_SLAAC;
26 import static android.net.ip.IIpClient.HOSTNAME_SETTING_UNSET;
27 import static android.net.ip.IIpClient.HOSTNAME_SETTING_DO_NOT_SEND;
28 import static android.net.ip.IIpClient.HOSTNAME_SETTING_SEND;
29 import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
30 import static android.net.shared.ProvisioningConfiguration.ipv4ProvisioningModeToString;
31 import static android.net.shared.ProvisioningConfiguration.ipv6ProvisioningModeToString;
32 
33 import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
34 
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertNotEquals;
38 import static org.junit.Assert.assertTrue;
39 
40 import android.net.LinkAddress;
41 import android.net.MacAddress;
42 import android.net.Network;
43 import android.net.ProvisioningConfigurationParcelable;
44 import android.net.StaticIpConfiguration;
45 import android.net.apf.ApfCapabilities;
46 import android.net.networkstack.aidl.dhcp.DhcpOption;
47 import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
48 
49 import androidx.test.filters.SmallTest;
50 import androidx.test.runner.AndroidJUnit4;
51 
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 
56 import java.nio.ByteBuffer;
57 import java.util.ArrayList;
58 import java.util.Collections;
59 import java.util.List;
60 import java.util.function.Consumer;
61 
62 /**
63  * Tests for {@link ProvisioningConfiguration}.
64  */
65 @RunWith(AndroidJUnit4.class)
66 @SmallTest
67 public class ProvisioningConfigurationTest {
68     private ProvisioningConfiguration mConfig;
69 
makeScanResultInfo(final String ssid)70     private ScanResultInfo makeScanResultInfo(final String ssid) {
71         final byte[] payload = new byte[] {
72             (byte) 0x00, (byte) 0x17, (byte) 0xF2, (byte) 0x06, (byte) 0x01,
73             (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x00,
74         };
75         final ScanResultInfo.InformationElement ie =
76                 new ScanResultInfo.InformationElement(0xdd /* vendor specific IE id */,
77                         ByteBuffer.wrap(payload));
78         return new ScanResultInfo(ssid, "01:02:03:04:05:06" /* bssid string */,
79                 Collections.singletonList(ie));
80     }
81 
makeCustomizedDhcpOptions(byte type, final byte[] value)82     private List<DhcpOption> makeCustomizedDhcpOptions(byte type, final byte[] value) {
83         final DhcpOption option = new DhcpOption();
84         option.type = type;
85         option.value = value;
86 
87         final List<DhcpOption> options = new ArrayList<DhcpOption>();
88         options.add(option);
89         return options;
90     }
91 
makeTestProvisioningConfiguration()92     private ProvisioningConfiguration makeTestProvisioningConfiguration() {
93         final ProvisioningConfiguration config = new ProvisioningConfiguration();
94         config.mUsingMultinetworkPolicyTracker = true;
95         config.mUsingIpReachabilityMonitor = true;
96         config.mRequestedPreDhcpActionMs = 42;
97         config.mInitialConfig = new InitialConfiguration();
98         config.mInitialConfig.ipAddresses.add(
99                 new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
100         config.mStaticIpConfig = new StaticIpConfiguration();
101         config.mStaticIpConfig.ipAddress =
102                 new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
103         // Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
104         config.mApfCapabilities = new ApfCapabilities(1, 2, 3);
105         config.mProvisioningTimeoutMs = 4200;
106         config.mIPv6AddrGenMode = 123;
107         config.mNetwork = new Network(321);
108         config.mDisplayName = "test_config";
109         config.mEnablePreconnection = false;
110         config.mScanResultInfo = makeScanResultInfo("ssid");
111         config.mLayer2Info = new Layer2Information("some l2key", "some cluster",
112                 MacAddress.fromString("00:01:02:03:04:05"));
113         config.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
114                 new String("android-dhcp-11").getBytes());
115         config.mIPv4ProvisioningMode = PROV_IPV4_DHCP;
116         config.mIPv6ProvisioningMode = PROV_IPV6_SLAAC;
117         config.mUniqueEui64AddressesOnly = false;
118         config.mCreatorUid = 10136;
119         config.mHostnameSetting = HOSTNAME_SETTING_SEND;
120         return config;
121     }
122 
makeTestProvisioningConfigurationParcelable()123     private ProvisioningConfigurationParcelable makeTestProvisioningConfigurationParcelable() {
124         final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
125         p.enableIPv4 = true;
126         p.enableIPv6 = true;
127         p.uniqueEui64AddressesOnly = false;
128         p.usingMultinetworkPolicyTracker = true;
129         p.usingIpReachabilityMonitor = true;
130         p.requestedPreDhcpActionMs = 42;
131         final InitialConfiguration initialConfig = new InitialConfiguration();
132         initialConfig.ipAddresses.add(
133                 new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
134         p.initialConfig = initialConfig.toStableParcelable();
135         p.staticIpConfig = new StaticIpConfiguration();
136         p.staticIpConfig.ipAddress =
137                 new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
138         p.apfCapabilities = new ApfCapabilities(1, 2, 3);
139         p.provisioningTimeoutMs = 4200;
140         p.ipv6AddrGenMode = 123;
141         p.network = new Network(321);
142         p.displayName = "test_config";
143         p.enablePreconnection = false;
144         final ScanResultInfo scanResultInfo = makeScanResultInfo("ssid");
145         p.scanResultInfo = scanResultInfo.toStableParcelable();
146         final Layer2Information layer2Info = new Layer2Information("some l2key", "some cluster",
147                 MacAddress.fromString("00:01:02:03:04:05"));
148         p.layer2Info = layer2Info.toStableParcelable();
149         p.options = makeCustomizedDhcpOptions((byte) 60, new String("android-dhcp-11").getBytes());
150         p.creatorUid = 10136;
151         p.hostnameSetting = HOSTNAME_SETTING_SEND;
152         return p;
153     }
154 
155     @Before
setUp()156     public void setUp() {
157         mConfig = makeTestProvisioningConfiguration();
158         // Any added field must be included in equals() to be tested properly
159         assertFieldCountEquals(19, ProvisioningConfiguration.class);
160     }
161 
162     @Test
testParcelUnparcel()163     public void testParcelUnparcel() {
164         doParcelUnparcelTest();
165     }
166 
167     @Test
testParcelUnparcel_NullInitialConfiguration()168     public void testParcelUnparcel_NullInitialConfiguration() {
169         mConfig.mInitialConfig = null;
170         doParcelUnparcelTest();
171     }
172 
173     @Test
testParcelUnparcel_NullStaticConfiguration()174     public void testParcelUnparcel_NullStaticConfiguration() {
175         mConfig.mStaticIpConfig = null;
176         doParcelUnparcelTest();
177     }
178 
179     @Test
testParcelUnparcel_NullApfCapabilities()180     public void testParcelUnparcel_NullApfCapabilities() {
181         mConfig.mApfCapabilities = null;
182         doParcelUnparcelTest();
183     }
184 
185     @Test
testParcelUnparcel_NullNetwork()186     public void testParcelUnparcel_NullNetwork() {
187         mConfig.mNetwork = null;
188         doParcelUnparcelTest();
189     }
190 
191     @Test
testParcelUnparcel_NullScanResultInfo()192     public void testParcelUnparcel_NullScanResultInfo() {
193         mConfig.mScanResultInfo = null;
194         doParcelUnparcelTest();
195     }
196 
197     @Test
testParcelUnparcel_NullCustomizedDhcpOptions()198     public void testParcelUnparcel_NullCustomizedDhcpOptions() {
199         mConfig.mDhcpOptions = null;
200         doParcelUnparcelTest();
201     }
202 
203     @Test
testParcelUnparcel_WithPreDhcpConnection()204     public void testParcelUnparcel_WithPreDhcpConnection() {
205         mConfig.mEnablePreconnection = true;
206         doParcelUnparcelTest();
207     }
208 
209     @Test
testParcelUnparcel_DisabledIpProvisioningMode()210     public void testParcelUnparcel_DisabledIpProvisioningMode() {
211         mConfig.mIPv4ProvisioningMode = PROV_IPV4_DISABLED;
212         mConfig.mIPv6ProvisioningMode = PROV_IPV6_DISABLED;
213         doParcelUnparcelTest();
214 
215         assertFalse(mConfig.toStableParcelable().enableIPv4);
216         assertFalse(mConfig.toStableParcelable().enableIPv6);
217     }
218 
219     @Test
testParcelUnparcel_enabledIpProvisioningMode()220     public void testParcelUnparcel_enabledIpProvisioningMode() {
221         mConfig.mIPv4ProvisioningMode = PROV_IPV4_DHCP;
222         mConfig.mIPv6ProvisioningMode = PROV_IPV6_SLAAC;
223         doParcelUnparcelTest();
224 
225         assertTrue(mConfig.toStableParcelable().enableIPv4);
226         assertTrue(mConfig.toStableParcelable().enableIPv6);
227     }
228 
229     @Test
testParcelUnparcel_IpProvisioningModefromOldStableParcelable()230     public void testParcelUnparcel_IpProvisioningModefromOldStableParcelable() {
231         final ProvisioningConfigurationParcelable p = makeTestProvisioningConfigurationParcelable();
232         final ProvisioningConfiguration unparceled = fromStableParcelable(p,
233                 11 /* interface version */);
234         assertEquals(mConfig, unparceled);
235     }
236 
237     @Test
testParcelUnparcel_WithIpv6LinkLocalOnly()238     public void testParcelUnparcel_WithIpv6LinkLocalOnly() {
239         mConfig.mIPv6ProvisioningMode = PROV_IPV6_LINKLOCAL;
240         doParcelUnparcelTest();
241     }
242 
doParcelUnparcelTest()243     private void doParcelUnparcelTest() {
244         final ProvisioningConfiguration unparceled =
245                 fromStableParcelable(mConfig.toStableParcelable(), 12 /* interface version */);
246         assertEquals(mConfig, unparceled);
247     }
248 
249     @Test
testEquals()250     public void testEquals() {
251         assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
252 
253         assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
254         assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
255         assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
256         assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add(
257                 new LinkAddress(parseNumericAddress("192.168.47.47"), 16)));
258         assertNotEqualsAfterChange(c -> c.mInitialConfig = null);
259         assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress =
260                 new LinkAddress(parseNumericAddress("2001:db8::47"), 64));
261         assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null);
262         assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6));
263         assertNotEqualsAfterChange(c -> c.mApfCapabilities = null);
264         assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++);
265         assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++);
266         assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123));
267         assertNotEqualsAfterChange(c -> c.mNetwork = null);
268         assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
269         assertNotEqualsAfterChange(c -> c.mDisplayName = null);
270         assertNotEqualsAfterChange(c -> c.mEnablePreconnection = true);
271         assertNotEqualsAfterChange(c -> c.mScanResultInfo = null);
272         assertNotEqualsAfterChange(c -> c.mScanResultInfo = makeScanResultInfo("another ssid"));
273         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("another l2key",
274                 "some cluster", MacAddress.fromString("00:01:02:03:04:05")));
275         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("some l2key",
276                 "another cluster", MacAddress.fromString("00:01:02:03:04:05")));
277         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("some l2key",
278                 "some cluster", MacAddress.fromString("01:02:03:04:05:06")));
279         assertNotEqualsAfterChange(c -> c.mLayer2Info = null);
280         assertNotEqualsAfterChange(c -> c.mDhcpOptions = new ArrayList<DhcpOption>());
281         assertNotEqualsAfterChange(c -> c.mDhcpOptions = null);
282         assertNotEqualsAfterChange(c -> c.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
283                   new String("vendor-class-identifier").getBytes()));
284         assertNotEqualsAfterChange(c -> c.mDhcpOptions = makeCustomizedDhcpOptions((byte) 77,
285                   new String("vendor-class-identifier").getBytes()));
286         assertNotEqualsAfterChange(c -> c.mIPv4ProvisioningMode = PROV_IPV4_DISABLED);
287         assertNotEqualsAfterChange(c -> c.mIPv4ProvisioningMode = PROV_IPV4_STATIC);
288         assertNotEqualsAfterChange(c -> c.mIPv6ProvisioningMode = PROV_IPV6_DISABLED);
289         assertNotEqualsAfterChange(c -> c.mIPv6ProvisioningMode = PROV_IPV6_LINKLOCAL);
290         assertNotEqualsAfterChange(c -> c.mUniqueEui64AddressesOnly = true);
291         assertNotEqualsAfterChange(c -> c.mCreatorUid = 10138);
292         assertNotEqualsAfterChange(c -> c.mHostnameSetting = HOSTNAME_SETTING_UNSET);
293         assertNotEqualsAfterChange(c -> c.mHostnameSetting = HOSTNAME_SETTING_DO_NOT_SEND);
294         assertFieldCountEquals(19, ProvisioningConfiguration.class);
295     }
296 
assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator)297     private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {
298         final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig);
299         mutator.accept(newConfig);
300         assertNotEquals(mConfig, newConfig);
301     }
302 
303     @Test
testParcelableToString()304     public void testParcelableToString() {
305         String str = mConfig.toStableParcelable().toString();
306 
307         // check a few fields. Comprehensive toString tests exist in aidl_integration_test,
308         // but we want to make sure that the toString function requested in the AIDL file
309         // is there
310         assertTrue(str, str.contains("00:01:02:03:04:05"));
311         assertTrue(str, str.contains("some l2key, cluster: some cluster"));
312 
313         final ProvisioningConfigurationParcelable parcelWithNull = mConfig.toStableParcelable();
314         parcelWithNull.layer2Info.bssid = null;
315         str = parcelWithNull.toString();
316 
317         assertTrue(str, str.contains("bssid: null"));
318     }
319 
320     @Test
testIpProvisioningModeToString()321     public void testIpProvisioningModeToString() {
322         assertEquals("disabled", ipv4ProvisioningModeToString(PROV_IPV4_DISABLED));
323         assertEquals("static", ipv4ProvisioningModeToString(PROV_IPV4_STATIC));
324         assertEquals("dhcp", ipv4ProvisioningModeToString(PROV_IPV4_DHCP));
325         assertEquals("unknown", ipv4ProvisioningModeToString(0x03 /* unknown mode */));
326 
327         assertEquals("disabled", ipv6ProvisioningModeToString(PROV_IPV6_DISABLED));
328         assertEquals("slaac", ipv6ProvisioningModeToString(PROV_IPV6_SLAAC));
329         assertEquals("link-local", ipv6ProvisioningModeToString(PROV_IPV6_LINKLOCAL));
330         assertEquals("unknown", ipv6ProvisioningModeToString(0x03 /* unknown mode */));
331     }
332 }
333