1 /*
2  * Copyright (C) 2010 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;
18 
19 import static android.net.RouteInfo.RTN_THROW;
20 import static android.net.RouteInfo.RTN_UNICAST;
21 import static android.net.RouteInfo.RTN_UNREACHABLE;
22 
23 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
24 import static com.android.testutils.ParcelUtils.parcelingRoundTrip;
25 
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotEquals;
29 import static org.junit.Assert.assertNull;
30 import static org.junit.Assert.assertTrue;
31 import static org.junit.Assert.fail;
32 
33 import android.net.LinkProperties.ProvisioningChange;
34 import android.os.Build;
35 import android.system.OsConstants;
36 import android.util.ArraySet;
37 
38 import androidx.core.os.BuildCompat;
39 import androidx.test.filters.SmallTest;
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
43 import com.android.testutils.DevSdkIgnoreRule;
44 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
45 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
46 
47 import org.junit.Rule;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 import java.net.Inet4Address;
52 import java.net.Inet6Address;
53 import java.net.InetAddress;
54 import java.util.Arrays;
55 import java.util.Collection;
56 import java.util.Collections;
57 import java.util.List;
58 import java.util.Set;
59 
60 @RunWith(AndroidJUnit4.class)
61 @SmallTest
62 public class LinkPropertiesTest {
63     @Rule
64     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
65 
66     private static final InetAddress ADDRV4 = address("75.208.6.1");
67     private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
68     private static final InetAddress DNS1 = address("75.208.7.1");
69     private static final InetAddress DNS2 = address("69.78.7.1");
70     private static final InetAddress DNS6 = address("2001:4860:4860::8888");
71     private static final InetAddress PRIVDNS1 = address("1.1.1.1");
72     private static final InetAddress PRIVDNS2 = address("1.0.0.1");
73     private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111");
74     private static final InetAddress PCSCFV4 = address("10.77.25.37");
75     private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1");
76     private static final InetAddress GATEWAY1 = address("75.208.8.1");
77     private static final InetAddress GATEWAY2 = address("69.78.8.1");
78     private static final InetAddress GATEWAY61 = address("fe80::6:0000:613");
79     private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
80     private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
81     private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
82     private static final Inet4Address DHCPSERVER = (Inet4Address) address("192.0.2.1");
83     private static final String NAME = "qmi0";
84     private static final String DOMAINS = "google.com";
85     private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
86     private static final String TCP_BUFFER_SIZES = "524288,1048576,2097152,262144,524288,1048576";
87     private static final int MTU = 1500;
88     private static final LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
89     private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
90     private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
91     private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi");
92 
93     // CaptivePortalData cannot be in a constant as it does not exist on Q.
94     // The test runner also crashes when scanning for tests if it is a return type.
getCaptivePortalData()95     private static Object getCaptivePortalData() {
96         return new CaptivePortalData.Builder()
97                 .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build();
98     }
99 
address(String addrString)100     private static InetAddress address(String addrString) {
101         return InetAddresses.parseNumericAddress(addrString);
102     }
103 
isAtLeastR()104     private static boolean isAtLeastR() {
105         // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R)
106         return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR();
107     }
108 
checkEmpty(final LinkProperties lp)109     private void checkEmpty(final LinkProperties lp) {
110         assertEquals(0, lp.getAllInterfaceNames().size());
111         assertEquals(0, lp.getAllAddresses().size());
112         assertEquals(0, lp.getDnsServers().size());
113         assertEquals(0, lp.getValidatedPrivateDnsServers().size());
114         assertEquals(0, lp.getPcscfServers().size());
115         assertEquals(0, lp.getAllRoutes().size());
116         assertEquals(0, lp.getAllLinkAddresses().size());
117         assertEquals(0, lp.getStackedLinks().size());
118         assertEquals(0, lp.getMtu());
119         assertNull(lp.getPrivateDnsServerName());
120         assertNull(lp.getDomains());
121         assertNull(lp.getHttpProxy());
122         assertNull(lp.getTcpBufferSizes());
123         assertNull(lp.getNat64Prefix());
124         assertFalse(lp.isProvisioned());
125         assertFalse(lp.isIpv4Provisioned());
126         assertFalse(lp.isIpv6Provisioned());
127         assertFalse(lp.isPrivateDnsActive());
128 
129         if (isAtLeastR()) {
130             assertNull(lp.getDhcpServerAddress());
131             assertFalse(lp.isWakeOnLanSupported());
132             assertNull(lp.getCaptivePortalApiUrl());
133             assertNull(lp.getCaptivePortalData());
134         }
135     }
136 
makeTestObject()137     private LinkProperties makeTestObject() {
138         final LinkProperties lp = new LinkProperties();
139         lp.setInterfaceName(NAME);
140         lp.addLinkAddress(LINKADDRV4);
141         lp.addLinkAddress(LINKADDRV6);
142         lp.addDnsServer(DNS1);
143         lp.addDnsServer(DNS2);
144         lp.addValidatedPrivateDnsServer(PRIVDNS1);
145         lp.addValidatedPrivateDnsServer(PRIVDNS2);
146         lp.setUsePrivateDns(true);
147         lp.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
148         lp.addPcscfServer(PCSCFV6);
149         lp.setDomains(DOMAINS);
150         lp.addRoute(new RouteInfo(GATEWAY1));
151         lp.addRoute(new RouteInfo(GATEWAY2));
152         lp.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
153         lp.setMtu(MTU);
154         lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
155         lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
156         if (isAtLeastR()) {
157             lp.setDhcpServerAddress(DHCPSERVER);
158             lp.setWakeOnLanSupported(true);
159             lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
160             lp.setCaptivePortalData((CaptivePortalData) getCaptivePortalData());
161         }
162         return lp;
163     }
164 
assertLinkPropertiesEqual(LinkProperties source, LinkProperties target)165     public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
166         // Check implementation of equals(), element by element.
167         assertTrue(source.isIdenticalInterfaceName(target));
168         assertTrue(target.isIdenticalInterfaceName(source));
169 
170         assertTrue(source.isIdenticalAddresses(target));
171         assertTrue(target.isIdenticalAddresses(source));
172 
173         assertTrue(source.isIdenticalDnses(target));
174         assertTrue(target.isIdenticalDnses(source));
175 
176         assertTrue(source.isIdenticalPrivateDns(target));
177         assertTrue(target.isIdenticalPrivateDns(source));
178 
179         assertTrue(source.isIdenticalValidatedPrivateDnses(target));
180         assertTrue(target.isIdenticalValidatedPrivateDnses(source));
181 
182         assertTrue(source.isIdenticalPcscfs(target));
183         assertTrue(target.isIdenticalPcscfs(source));
184 
185         assertTrue(source.isIdenticalRoutes(target));
186         assertTrue(target.isIdenticalRoutes(source));
187 
188         assertTrue(source.isIdenticalHttpProxy(target));
189         assertTrue(target.isIdenticalHttpProxy(source));
190 
191         assertTrue(source.isIdenticalStackedLinks(target));
192         assertTrue(target.isIdenticalStackedLinks(source));
193 
194         assertTrue(source.isIdenticalMtu(target));
195         assertTrue(target.isIdenticalMtu(source));
196 
197         assertTrue(source.isIdenticalTcpBufferSizes(target));
198         assertTrue(target.isIdenticalTcpBufferSizes(source));
199 
200         if (isAtLeastR()) {
201             assertTrue(source.isIdenticalDhcpServerAddress(target));
202             assertTrue(source.isIdenticalDhcpServerAddress(source));
203 
204             assertTrue(source.isIdenticalWakeOnLan(target));
205             assertTrue(target.isIdenticalWakeOnLan(source));
206 
207             assertTrue(source.isIdenticalCaptivePortalApiUrl(target));
208             assertTrue(target.isIdenticalCaptivePortalApiUrl(source));
209 
210             assertTrue(source.isIdenticalCaptivePortalData(target));
211             assertTrue(target.isIdenticalCaptivePortalData(source));
212         }
213 
214         // Check result of equals().
215         assertTrue(source.equals(target));
216         assertTrue(target.equals(source));
217 
218         // Check hashCode.
219         assertEquals(source.hashCode(), target.hashCode());
220     }
221 
222     @Test
testEqualsNull()223     public void testEqualsNull() {
224         LinkProperties source = new LinkProperties();
225         LinkProperties target = new LinkProperties();
226 
227         assertFalse(source == target);
228         assertLinkPropertiesEqual(source, target);
229     }
230 
231     @Test
testEqualsSameOrder()232     public void testEqualsSameOrder() throws Exception {
233         LinkProperties source = new LinkProperties();
234         source.setInterfaceName(NAME);
235         // set 2 link addresses
236         source.addLinkAddress(LINKADDRV4);
237         source.addLinkAddress(LINKADDRV6);
238         // set 2 dnses
239         source.addDnsServer(DNS1);
240         source.addDnsServer(DNS2);
241         // set 1 pcscf
242         source.addPcscfServer(PCSCFV6);
243         // set 2 gateways
244         source.addRoute(new RouteInfo(GATEWAY1));
245         source.addRoute(new RouteInfo(GATEWAY2));
246         source.setMtu(MTU);
247 
248         LinkProperties target = new LinkProperties();
249 
250         // All fields are same
251         target.setInterfaceName(NAME);
252         target.addLinkAddress(LINKADDRV4);
253         target.addLinkAddress(LINKADDRV6);
254         target.addDnsServer(DNS1);
255         target.addDnsServer(DNS2);
256         target.addPcscfServer(PCSCFV6);
257         target.addRoute(new RouteInfo(GATEWAY1));
258         target.addRoute(new RouteInfo(GATEWAY2));
259         target.setMtu(MTU);
260 
261         assertLinkPropertiesEqual(source, target);
262 
263         target.clear();
264         // change Interface Name
265         target.setInterfaceName("qmi1");
266         target.addLinkAddress(LINKADDRV4);
267         target.addLinkAddress(LINKADDRV6);
268         target.addDnsServer(DNS1);
269         target.addDnsServer(DNS2);
270         target.addPcscfServer(PCSCFV6);
271         target.addRoute(new RouteInfo(GATEWAY1));
272         target.addRoute(new RouteInfo(GATEWAY2));
273         target.setMtu(MTU);
274         assertFalse(source.equals(target));
275 
276         target.clear();
277         target.setInterfaceName(NAME);
278         // change link addresses
279         target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32));
280         target.addLinkAddress(LINKADDRV6);
281         target.addDnsServer(DNS1);
282         target.addDnsServer(DNS2);
283         target.addPcscfServer(PCSCFV6);
284         target.addRoute(new RouteInfo(GATEWAY1));
285         target.addRoute(new RouteInfo(GATEWAY2));
286         target.setMtu(MTU);
287         assertFalse(source.equals(target));
288 
289         target.clear();
290         target.setInterfaceName(NAME);
291         target.addLinkAddress(LINKADDRV4);
292         target.addLinkAddress(LINKADDRV6);
293         // change dnses
294         target.addDnsServer(address("75.208.7.2"));
295         target.addDnsServer(DNS2);
296         target.addPcscfServer(PCSCFV6);
297         target.addRoute(new RouteInfo(GATEWAY1));
298         target.addRoute(new RouteInfo(GATEWAY2));
299         target.setMtu(MTU);
300         assertFalse(source.equals(target));
301 
302         target.clear();
303         target.setInterfaceName(NAME);
304         target.addLinkAddress(LINKADDRV4);
305         target.addLinkAddress(LINKADDRV6);
306         target.addDnsServer(address("75.208.7.2"));
307         target.addDnsServer(DNS2);
308         // change pcscf
309         target.addPcscfServer(address("2001::1"));
310         target.addRoute(new RouteInfo(GATEWAY1));
311         target.addRoute(new RouteInfo(GATEWAY2));
312         target.setMtu(MTU);
313         assertFalse(source.equals(target));
314 
315         target.clear();
316         target.setInterfaceName(NAME);
317         target.addLinkAddress(LINKADDRV4);
318         target.addLinkAddress(LINKADDRV6);
319         target.addDnsServer(DNS1);
320         target.addDnsServer(DNS2);
321         // change gateway
322         target.addRoute(new RouteInfo(address("75.208.8.2")));
323         target.setMtu(MTU);
324         target.addRoute(new RouteInfo(GATEWAY2));
325         assertFalse(source.equals(target));
326 
327         target.clear();
328         target.setInterfaceName(NAME);
329         target.addLinkAddress(LINKADDRV4);
330         target.addLinkAddress(LINKADDRV6);
331         target.addDnsServer(DNS1);
332         target.addDnsServer(DNS2);
333         target.addRoute(new RouteInfo(GATEWAY1));
334         target.addRoute(new RouteInfo(GATEWAY2));
335         // change mtu
336         target.setMtu(1440);
337         assertFalse(source.equals(target));
338     }
339 
340     @Test
testEqualsDifferentOrder()341     public void testEqualsDifferentOrder() throws Exception {
342         LinkProperties source = new LinkProperties();
343         source.setInterfaceName(NAME);
344         // set 2 link addresses
345         source.addLinkAddress(LINKADDRV4);
346         source.addLinkAddress(LINKADDRV6);
347         // set 2 dnses
348         source.addDnsServer(DNS1);
349         source.addDnsServer(DNS2);
350         // set 2 gateways
351         source.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1));
352         source.addRoute(new RouteInfo(GATEWAY2));
353         source.setMtu(MTU);
354 
355         LinkProperties target = new LinkProperties();
356         // Exchange order
357         target.setInterfaceName(NAME);
358         target.addLinkAddress(LINKADDRV6);
359         target.addLinkAddress(LINKADDRV4);
360         target.addDnsServer(DNS2);
361         target.addDnsServer(DNS1);
362         target.addRoute(new RouteInfo(GATEWAY2));
363         target.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1));
364         target.setMtu(MTU);
365 
366         assertLinkPropertiesEqual(source, target);
367     }
368 
369     @Test
testEqualsDuplicated()370     public void testEqualsDuplicated() throws Exception {
371         LinkProperties source = new LinkProperties();
372         // set 3 link addresses, eg, [A, A, B]
373         source.addLinkAddress(LINKADDRV4);
374         source.addLinkAddress(LINKADDRV4);
375         source.addLinkAddress(LINKADDRV6);
376 
377         LinkProperties target = new LinkProperties();
378         // set 3 link addresses, eg, [A, B, B]
379         target.addLinkAddress(LINKADDRV4);
380         target.addLinkAddress(LINKADDRV6);
381         target.addLinkAddress(LINKADDRV6);
382 
383         assertLinkPropertiesEqual(source, target);
384     }
385 
assertAllRoutesHaveInterface(String iface, LinkProperties lp)386     private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
387         for (RouteInfo r : lp.getRoutes()) {
388             assertEquals(iface, r.getInterface());
389         }
390     }
391 
assertAllRoutesNotHaveInterface(String iface, LinkProperties lp)392     private void assertAllRoutesNotHaveInterface(String iface, LinkProperties lp) {
393         for (RouteInfo r : lp.getRoutes()) {
394             assertNotEquals(iface, r.getInterface());
395         }
396     }
397 
398     @Test
testRouteInterfaces()399     public void testRouteInterfaces() {
400         LinkAddress prefix1 = new LinkAddress(address("2001:db8:1::"), 48);
401         LinkAddress prefix2 = new LinkAddress(address("2001:db8:2::"), 48);
402         InetAddress address = ADDRV6;
403 
404         // Add a route with no interface to a LinkProperties with no interface. No errors.
405         LinkProperties lp = new LinkProperties();
406         RouteInfo r = new RouteInfo(prefix1, address, null);
407         assertTrue(lp.addRoute(r));
408         assertEquals(1, lp.getRoutes().size());
409         assertAllRoutesHaveInterface(null, lp);
410 
411         // Adding the same route twice has no effect.
412         assertFalse(lp.addRoute(r));
413         assertEquals(1, lp.getRoutes().size());
414 
415         // Add a route with an interface. Expect an exception.
416         r = new RouteInfo(prefix2, address, "wlan0");
417         try {
418           lp.addRoute(r);
419           fail("Adding wlan0 route to LP with no interface, expect exception");
420         } catch (IllegalArgumentException expected) {}
421 
422         // Change the interface name. All the routes should change their interface name too.
423         lp.setInterfaceName("rmnet0");
424         assertAllRoutesHaveInterface("rmnet0", lp);
425         assertAllRoutesNotHaveInterface(null, lp);
426         assertAllRoutesNotHaveInterface("wlan0", lp);
427 
428         // Now add a route with the wrong interface. This causes an exception too.
429         try {
430           lp.addRoute(r);
431           fail("Adding wlan0 route to rmnet0 LP, expect exception");
432         } catch (IllegalArgumentException expected) {}
433 
434         // If the interface name matches, the route is added.
435         r = new RouteInfo(prefix2, null, "wlan0");
436         lp.setInterfaceName("wlan0");
437         lp.addRoute(r);
438         assertEquals(2, lp.getRoutes().size());
439         assertAllRoutesHaveInterface("wlan0", lp);
440         assertAllRoutesNotHaveInterface("rmnet0", lp);
441 
442         // Routes with null interfaces are converted to wlan0.
443         r = RouteInfo.makeHostRoute(ADDRV6, null);
444         lp.addRoute(r);
445         assertEquals(3, lp.getRoutes().size());
446         assertAllRoutesHaveInterface("wlan0", lp);
447 
448         // Check routes are updated correctly when calling setInterfaceName.
449         LinkProperties lp2 = new LinkProperties(lp);
450         assertAllRoutesHaveInterface("wlan0", lp2);
451         final CompareResult<RouteInfo> cr1 =
452                 new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
453         assertEquals(0, cr1.added.size());
454         assertEquals(0, cr1.removed.size());
455 
456         lp2.setInterfaceName("p2p0");
457         assertAllRoutesHaveInterface("p2p0", lp2);
458         assertAllRoutesNotHaveInterface("wlan0", lp2);
459         final CompareResult<RouteInfo> cr2 =
460                 new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
461         assertEquals(3, cr2.added.size());
462         assertEquals(3, cr2.removed.size());
463 
464         // Remove route with incorrect interface, no route removed.
465         lp.removeRoute(new RouteInfo(prefix2, null, null));
466         assertEquals(3, lp.getRoutes().size());
467 
468         // Check remove works when interface is correct.
469         lp.removeRoute(new RouteInfo(prefix2, null, "wlan0"));
470         assertEquals(2, lp.getRoutes().size());
471         assertAllRoutesHaveInterface("wlan0", lp);
472         assertAllRoutesNotHaveInterface("p2p0", lp);
473     }
474 
475     @Test
testStackedInterfaces()476     public void testStackedInterfaces() {
477         LinkProperties rmnet0 = new LinkProperties();
478         rmnet0.setInterfaceName("rmnet0");
479         rmnet0.addLinkAddress(LINKADDRV6);
480 
481         LinkProperties clat4 = new LinkProperties();
482         clat4.setInterfaceName("clat4");
483         clat4.addLinkAddress(LINKADDRV4);
484 
485         assertEquals(0, rmnet0.getStackedLinks().size());
486         assertEquals(1, rmnet0.getAddresses().size());
487         assertEquals(1, rmnet0.getLinkAddresses().size());
488         assertEquals(1, rmnet0.getAllAddresses().size());
489         assertEquals(1, rmnet0.getAllLinkAddresses().size());
490         assertEquals(1, rmnet0.getAllInterfaceNames().size());
491         assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
492 
493         rmnet0.addStackedLink(clat4);
494         assertEquals(1, rmnet0.getStackedLinks().size());
495         assertEquals(1, rmnet0.getAddresses().size());
496         assertEquals(1, rmnet0.getLinkAddresses().size());
497         assertEquals(2, rmnet0.getAllAddresses().size());
498         assertEquals(2, rmnet0.getAllLinkAddresses().size());
499         assertEquals(2, rmnet0.getAllInterfaceNames().size());
500         assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
501         assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1));
502 
503         rmnet0.addStackedLink(clat4);
504         assertEquals(1, rmnet0.getStackedLinks().size());
505         assertEquals(1, rmnet0.getAddresses().size());
506         assertEquals(1, rmnet0.getLinkAddresses().size());
507         assertEquals(2, rmnet0.getAllAddresses().size());
508         assertEquals(2, rmnet0.getAllLinkAddresses().size());
509         assertEquals(2, rmnet0.getAllInterfaceNames().size());
510         assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
511         assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1));
512 
513         assertEquals(0, clat4.getStackedLinks().size());
514 
515         // Modify an item in the returned collection to see what happens.
516         for (LinkProperties link : rmnet0.getStackedLinks()) {
517             if (link.getInterfaceName().equals("clat4")) {
518                link.setInterfaceName("newname");
519             }
520         }
521         for (LinkProperties link : rmnet0.getStackedLinks()) {
522             assertFalse("newname".equals(link.getInterfaceName()));
523         }
524 
525         assertTrue(rmnet0.removeStackedLink("clat4"));
526         assertEquals(0, rmnet0.getStackedLinks().size());
527         assertEquals(1, rmnet0.getAddresses().size());
528         assertEquals(1, rmnet0.getLinkAddresses().size());
529         assertEquals(1, rmnet0.getAllAddresses().size());
530         assertEquals(1, rmnet0.getAllLinkAddresses().size());
531         assertEquals(1, rmnet0.getAllInterfaceNames().size());
532         assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0));
533 
534         assertFalse(rmnet0.removeStackedLink("clat4"));
535     }
536 
getFirstLinkAddress(LinkProperties lp)537     private LinkAddress getFirstLinkAddress(LinkProperties lp) {
538         return lp.getLinkAddresses().iterator().next();
539     }
540 
541     @Test
testAddressMethods()542     public void testAddressMethods() {
543         LinkProperties lp = new LinkProperties();
544 
545         // No addresses.
546         assertFalse(lp.hasIpv4Address());
547         assertFalse(lp.hasGlobalIpv6Address());
548 
549         // Addresses on stacked links don't count.
550         LinkProperties stacked = new LinkProperties();
551         stacked.setInterfaceName("stacked");
552         lp.addStackedLink(stacked);
553         stacked.addLinkAddress(LINKADDRV4);
554         stacked.addLinkAddress(LINKADDRV6);
555         assertTrue(stacked.hasIpv4Address());
556         assertTrue(stacked.hasGlobalIpv6Address());
557         assertFalse(lp.hasIpv4Address());
558         assertFalse(lp.hasGlobalIpv6Address());
559         lp.removeStackedLink("stacked");
560         assertFalse(lp.hasIpv4Address());
561         assertFalse(lp.hasGlobalIpv6Address());
562 
563         // Addresses on the base link.
564         // Check the return values of hasIpvXAddress and ensure the add/remove methods return true
565         // iff something changes.
566         assertEquals(0, lp.getLinkAddresses().size());
567         assertTrue(lp.addLinkAddress(LINKADDRV6));
568         assertEquals(1, lp.getLinkAddresses().size());
569         assertFalse(lp.hasIpv4Address());
570         assertTrue(lp.hasGlobalIpv6Address());
571 
572         assertTrue(lp.removeLinkAddress(LINKADDRV6));
573         assertEquals(0, lp.getLinkAddresses().size());
574 
575         assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL));
576         assertEquals(1, lp.getLinkAddresses().size());
577         assertFalse(lp.hasGlobalIpv6Address());
578 
579         assertTrue(lp.addLinkAddress(LINKADDRV4));
580         assertEquals(2, lp.getLinkAddresses().size());
581         assertTrue(lp.hasIpv4Address());
582         assertFalse(lp.hasGlobalIpv6Address());
583 
584         assertTrue(lp.addLinkAddress(LINKADDRV6));
585         assertEquals(3, lp.getLinkAddresses().size());
586         assertTrue(lp.hasIpv4Address());
587         assertTrue(lp.hasGlobalIpv6Address());
588 
589         assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL));
590         assertEquals(2, lp.getLinkAddresses().size());
591         assertTrue(lp.hasIpv4Address());
592         assertTrue(lp.hasGlobalIpv6Address());
593 
594         // Adding an address twice has no effect.
595         // Removing an address that's not present has no effect.
596         assertFalse(lp.addLinkAddress(LINKADDRV4));
597         assertEquals(2, lp.getLinkAddresses().size());
598         assertTrue(lp.hasIpv4Address());
599         assertTrue(lp.removeLinkAddress(LINKADDRV4));
600         assertEquals(1, lp.getLinkAddresses().size());
601         assertFalse(lp.hasIpv4Address());
602         assertFalse(lp.removeLinkAddress(LINKADDRV4));
603         assertEquals(1, lp.getLinkAddresses().size());
604 
605         // Adding an address that's already present but with different properties causes the
606         // existing address to be updated and returns true.
607         // Start with only LINKADDRV6.
608         assertEquals(1, lp.getLinkAddresses().size());
609         assertEquals(LINKADDRV6, getFirstLinkAddress(lp));
610 
611         // Create a LinkAddress object for the same address, but with different flags.
612         LinkAddress deprecated = new LinkAddress(ADDRV6, 128,
613                 OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE);
614         assertTrue(deprecated.isSameAddressAs(LINKADDRV6));
615         assertFalse(deprecated.equals(LINKADDRV6));
616 
617         // Check that adding it updates the existing address instead of adding a new one.
618         assertTrue(lp.addLinkAddress(deprecated));
619         assertEquals(1, lp.getLinkAddresses().size());
620         assertEquals(deprecated, getFirstLinkAddress(lp));
621         assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp)));
622 
623         // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties.
624         assertTrue(lp.removeLinkAddress(LINKADDRV6));
625         assertEquals(0, lp.getLinkAddresses().size());
626     }
627 
628     @Test
testLinkAddresses()629     public void testLinkAddresses() {
630         final LinkProperties lp = new LinkProperties();
631         lp.addLinkAddress(LINKADDRV4);
632         lp.addLinkAddress(LINKADDRV6);
633 
634         final LinkProperties lp2 = new LinkProperties();
635         lp2.addLinkAddress(LINKADDRV6);
636 
637         final LinkProperties lp3 = new LinkProperties();
638         final List<LinkAddress> linkAddresses = Arrays.asList(LINKADDRV4);
639         lp3.setLinkAddresses(linkAddresses);
640 
641         assertFalse(lp.equals(lp2));
642         assertFalse(lp2.equals(lp3));
643 
644         lp.removeLinkAddress(LINKADDRV4);
645         assertTrue(lp.equals(lp2));
646 
647         lp2.setLinkAddresses(lp3.getLinkAddresses());
648         assertTrue(lp2.equals(lp3));
649     }
650 
651     @Test
testNat64Prefix()652     public void testNat64Prefix() throws Exception {
653         LinkProperties lp = new LinkProperties();
654         lp.addLinkAddress(LINKADDRV4);
655         lp.addLinkAddress(LINKADDRV6);
656 
657         assertNull(lp.getNat64Prefix());
658 
659         IpPrefix p = new IpPrefix("64:ff9b::/96");
660         lp.setNat64Prefix(p);
661         assertEquals(p, lp.getNat64Prefix());
662 
663         p = new IpPrefix("2001:db8:a:b:1:2:3::/96");
664         lp.setNat64Prefix(p);
665         assertEquals(p, lp.getNat64Prefix());
666 
667         p = new IpPrefix("2001:db8:a:b:1:2::/80");
668         try {
669             lp.setNat64Prefix(p);
670         } catch (IllegalArgumentException expected) {
671         }
672 
673         p = new IpPrefix("64:ff9b::/64");
674         try {
675             lp.setNat64Prefix(p);
676         } catch (IllegalArgumentException expected) {
677         }
678 
679         assertEquals(new IpPrefix("2001:db8:a:b:1:2:3::/96"), lp.getNat64Prefix());
680 
681         lp.setNat64Prefix(null);
682         assertNull(lp.getNat64Prefix());
683     }
684 
685     @Test
testIsProvisioned()686     public void testIsProvisioned() {
687         LinkProperties lp4 = new LinkProperties();
688         assertFalse("v4only:empty", lp4.isProvisioned());
689         lp4.addLinkAddress(LINKADDRV4);
690         assertFalse("v4only:addr-only", lp4.isProvisioned());
691         lp4.addDnsServer(DNS1);
692         assertFalse("v4only:addr+dns", lp4.isProvisioned());
693         lp4.addRoute(new RouteInfo(GATEWAY1));
694         assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
695         assertTrue("v4only:addr+dns+route", lp4.isIpv4Provisioned());
696         assertFalse("v4only:addr+dns+route", lp4.isIpv6Provisioned());
697 
698         LinkProperties lp6 = new LinkProperties();
699         assertFalse("v6only:empty", lp6.isProvisioned());
700         lp6.addLinkAddress(LINKADDRV6LINKLOCAL);
701         assertFalse("v6only:fe80-only", lp6.isProvisioned());
702         lp6.addDnsServer(DNS6);
703         assertFalse("v6only:fe80+dns", lp6.isProvisioned());
704         lp6.addRoute(new RouteInfo(GATEWAY61));
705         assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
706         lp6.addLinkAddress(LINKADDRV6);
707         assertTrue("v6only:fe80+global+dns+route", lp6.isIpv6Provisioned());
708         assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
709         lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
710         assertFalse("v6only:global+dns+route", lp6.isIpv4Provisioned());
711         assertTrue("v6only:global+dns+route", lp6.isIpv6Provisioned());
712         assertTrue("v6only:global+dns+route", lp6.isProvisioned());
713 
714         LinkProperties lp46 = new LinkProperties();
715         lp46.addLinkAddress(LINKADDRV4);
716         lp46.addLinkAddress(LINKADDRV6);
717         lp46.addDnsServer(DNS1);
718         lp46.addDnsServer(DNS6);
719         assertFalse("dualstack:missing-routes", lp46.isProvisioned());
720         lp46.addRoute(new RouteInfo(GATEWAY1));
721         assertTrue("dualstack:v4-provisioned", lp46.isIpv4Provisioned());
722         assertFalse("dualstack:v4-provisioned", lp46.isIpv6Provisioned());
723         assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
724         lp46.addRoute(new RouteInfo(GATEWAY61));
725         assertTrue("dualstack:both-provisioned", lp46.isIpv4Provisioned());
726         assertTrue("dualstack:both-provisioned", lp46.isIpv6Provisioned());
727         assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
728 
729         // A link with an IPv6 address and default route, but IPv4 DNS server.
730         LinkProperties mixed = new LinkProperties();
731         mixed.addLinkAddress(LINKADDRV6);
732         mixed.addDnsServer(DNS1);
733         mixed.addRoute(new RouteInfo(GATEWAY61));
734         assertFalse("mixed:addr6+route6+dns4", mixed.isIpv4Provisioned());
735         assertFalse("mixed:addr6+route6+dns4", mixed.isIpv6Provisioned());
736         assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
737     }
738 
739     @Test
testCompareProvisioning()740     public void testCompareProvisioning() {
741         LinkProperties v4lp = new LinkProperties();
742         v4lp.addLinkAddress(LINKADDRV4);
743         v4lp.addRoute(new RouteInfo(GATEWAY1));
744         v4lp.addDnsServer(DNS1);
745         assertTrue(v4lp.isProvisioned());
746 
747         LinkProperties v4r = new LinkProperties(v4lp);
748         v4r.removeDnsServer(DNS1);
749         assertFalse(v4r.isProvisioned());
750 
751         assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED,
752                 LinkProperties.compareProvisioning(v4r, v4r));
753         assertEquals(ProvisioningChange.LOST_PROVISIONING,
754                 LinkProperties.compareProvisioning(v4lp, v4r));
755         assertEquals(ProvisioningChange.GAINED_PROVISIONING,
756                 LinkProperties.compareProvisioning(v4r, v4lp));
757         assertEquals(ProvisioningChange.STILL_PROVISIONED,
758                 LinkProperties.compareProvisioning(v4lp, v4lp));
759 
760         // Check that losing IPv4 provisioning on a dualstack network is
761         // seen as a total loss of provisioning.
762         LinkProperties v6lp = new LinkProperties();
763         v6lp.addLinkAddress(LINKADDRV6);
764         v6lp.addRoute(new RouteInfo(GATEWAY61));
765         v6lp.addDnsServer(DNS6);
766         assertFalse(v6lp.isIpv4Provisioned());
767         assertTrue(v6lp.isIpv6Provisioned());
768         assertTrue(v6lp.isProvisioned());
769 
770         LinkProperties v46lp = new LinkProperties(v6lp);
771         v46lp.addLinkAddress(LINKADDRV4);
772         v46lp.addRoute(new RouteInfo(GATEWAY1));
773         v46lp.addDnsServer(DNS1);
774         assertTrue(v46lp.isIpv4Provisioned());
775         assertTrue(v46lp.isIpv6Provisioned());
776         assertTrue(v46lp.isProvisioned());
777 
778         assertEquals(ProvisioningChange.STILL_PROVISIONED,
779                 LinkProperties.compareProvisioning(v4lp, v46lp));
780         assertEquals(ProvisioningChange.STILL_PROVISIONED,
781                 LinkProperties.compareProvisioning(v6lp, v46lp));
782         assertEquals(ProvisioningChange.LOST_PROVISIONING,
783                 LinkProperties.compareProvisioning(v46lp, v6lp));
784         assertEquals(ProvisioningChange.LOST_PROVISIONING,
785                 LinkProperties.compareProvisioning(v46lp, v4lp));
786 
787         // Check that losing and gaining a secondary router does not change
788         // the provisioning status.
789         LinkProperties v6lp2 = new LinkProperties(v6lp);
790         v6lp2.addRoute(new RouteInfo(GATEWAY62));
791         assertTrue(v6lp2.isProvisioned());
792 
793         assertEquals(ProvisioningChange.STILL_PROVISIONED,
794                 LinkProperties.compareProvisioning(v6lp2, v6lp));
795         assertEquals(ProvisioningChange.STILL_PROVISIONED,
796                 LinkProperties.compareProvisioning(v6lp, v6lp2));
797     }
798 
799     @Test
testIsReachable()800     public void testIsReachable() {
801         final LinkProperties v4lp = new LinkProperties();
802         assertFalse(v4lp.isReachable(DNS1));
803         assertFalse(v4lp.isReachable(DNS2));
804 
805         // Add an on-link route, making the on-link DNS server reachable,
806         // but there is still no IPv4 address.
807         assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16))));
808         assertFalse(v4lp.isReachable(DNS1));
809         assertFalse(v4lp.isReachable(DNS2));
810 
811         // Adding an IPv4 address (right now, any IPv4 address) means we use
812         // the routes to compute likely reachability.
813         assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16)));
814         assertTrue(v4lp.isReachable(DNS1));
815         assertFalse(v4lp.isReachable(DNS2));
816 
817         // Adding a default route makes the off-link DNS server reachable.
818         assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1)));
819         assertTrue(v4lp.isReachable(DNS1));
820         assertTrue(v4lp.isReachable(DNS2));
821 
822         final LinkProperties v6lp = new LinkProperties();
823         final InetAddress kLinkLocalDns = address("fe80::6:1");
824         final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43");
825         final InetAddress kOnLinkDns = address("2001:db8:85a3::53");
826         assertFalse(v6lp.isReachable(kLinkLocalDns));
827         assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
828         assertFalse(v6lp.isReachable(kOnLinkDns));
829         assertFalse(v6lp.isReachable(DNS6));
830 
831         // Add a link-local route, making the link-local DNS servers reachable. Because
832         // we assume the presence of an IPv6 link-local address, link-local DNS servers
833         // are considered reachable, but only those with a non-zero scope identifier.
834         assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64))));
835         assertFalse(v6lp.isReachable(kLinkLocalDns));
836         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
837         assertFalse(v6lp.isReachable(kOnLinkDns));
838         assertFalse(v6lp.isReachable(DNS6));
839 
840         // Add a link-local address--nothing changes.
841         assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL));
842         assertFalse(v6lp.isReachable(kLinkLocalDns));
843         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
844         assertFalse(v6lp.isReachable(kOnLinkDns));
845         assertFalse(v6lp.isReachable(DNS6));
846 
847         // Add a global route on link, but no global address yet. DNS servers reachable
848         // via a route that doesn't require a gateway: give them the benefit of the
849         // doubt and hope the link-local source address suffices for communication.
850         assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64))));
851         assertFalse(v6lp.isReachable(kLinkLocalDns));
852         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
853         assertTrue(v6lp.isReachable(kOnLinkDns));
854         assertFalse(v6lp.isReachable(DNS6));
855 
856         // Add a global address; the on-link global address DNS server is (still)
857         // presumed reachable.
858         assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64)));
859         assertFalse(v6lp.isReachable(kLinkLocalDns));
860         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
861         assertTrue(v6lp.isReachable(kOnLinkDns));
862         assertFalse(v6lp.isReachable(DNS6));
863 
864         // Adding a default route makes the off-link DNS server reachable.
865         assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62)));
866         assertFalse(v6lp.isReachable(kLinkLocalDns));
867         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
868         assertTrue(v6lp.isReachable(kOnLinkDns));
869         assertTrue(v6lp.isReachable(DNS6));
870 
871         // Check isReachable on stacked links. This requires that the source IP address be assigned
872         // on the interface returned by the route lookup.
873         LinkProperties stacked = new LinkProperties();
874 
875         // Can't add a stacked link without an interface name.
876         stacked.setInterfaceName("v4-test0");
877         v6lp.addStackedLink(stacked);
878 
879         InetAddress stackedAddress = address("192.0.0.4");
880         LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
881         assertFalse(v6lp.isReachable(stackedAddress));
882         stacked.addLinkAddress(stackedLinkAddress);
883         assertFalse(v6lp.isReachable(stackedAddress));
884         stacked.addRoute(new RouteInfo(stackedLinkAddress));
885         assertTrue(stacked.isReachable(stackedAddress));
886         assertTrue(v6lp.isReachable(stackedAddress));
887 
888         assertFalse(v6lp.isReachable(DNS1));
889         stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
890         assertTrue(v6lp.isReachable(DNS1));
891     }
892 
893     @Test
testLinkPropertiesEnsureDirectlyConnectedRoutes()894     public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
895         // IPv4 case: no route added initially
896         LinkProperties rmnet0 = new LinkProperties();
897         rmnet0.setInterfaceName("rmnet0");
898         rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8"));
899         RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
900                 rmnet0.getInterfaceName());
901 
902         // Since no routes is added explicitly, getAllRoutes() should return empty.
903         assertTrue(rmnet0.getAllRoutes().isEmpty());
904         rmnet0.ensureDirectlyConnectedRoutes();
905         // ensureDirectlyConnectedRoutes() should have added the missing local route.
906         assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes());
907 
908         // IPv4 case: both direct and default routes added initially
909         LinkProperties rmnet1 = new LinkProperties();
910         rmnet1.setInterfaceName("rmnet1");
911         rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
912         RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"),
913                 rmnet1.getInterfaceName());
914         RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
915                 rmnet1.getInterfaceName());
916         rmnet1.addRoute(defaultRoute1);
917         rmnet1.addRoute(directRoute1);
918 
919         // Check added routes
920         assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
921         // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected
922         // route is already part of the configuration.
923         rmnet1.ensureDirectlyConnectedRoutes();
924         assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
925 
926         // IPv6 case: only default routes added initially
927         LinkProperties rmnet2 = new LinkProperties();
928         rmnet2.setInterfaceName("rmnet2");
929         rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
930         rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
931         RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"),
932                 rmnet2.getInterfaceName());
933         RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
934                 rmnet2.getInterfaceName());
935         RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
936                 rmnet2.getInterfaceName());
937         rmnet2.addRoute(defaultRoute2);
938 
939         assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes());
940         rmnet2.ensureDirectlyConnectedRoutes();
941         assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2),
942                 rmnet2.getAllRoutes());
943 
944         // Corner case: no interface name
945         LinkProperties rmnet3 = new LinkProperties();
946         rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24"));
947         RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null,
948                 rmnet3.getInterfaceName());
949 
950         assertTrue(rmnet3.getAllRoutes().isEmpty());
951         rmnet3.ensureDirectlyConnectedRoutes();
952         assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
953     }
954 
assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual)955     private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
956         Set<RouteInfo> expectedSet = new ArraySet<>(expected);
957         Set<RouteInfo> actualSet = new ArraySet<>(actual);
958         // Duplicated entries in actual routes are considered failures
959         assertEquals(actual.size(), actualSet.size());
960 
961         assertEquals(expectedSet, actualSet);
962     }
963 
makeLinkPropertiesForParceling()964     private static LinkProperties makeLinkPropertiesForParceling() {
965         LinkProperties source = new LinkProperties();
966         source.setInterfaceName(NAME);
967 
968         source.addLinkAddress(LINKADDRV4);
969         source.addLinkAddress(LINKADDRV6);
970 
971         source.addDnsServer(DNS1);
972         source.addDnsServer(DNS2);
973         source.addDnsServer(GATEWAY62);
974 
975         source.addPcscfServer(TESTIPV4ADDR);
976         source.addPcscfServer(TESTIPV6ADDR);
977 
978         source.setUsePrivateDns(true);
979         source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);
980 
981         source.setDomains(DOMAINS);
982 
983         source.addRoute(new RouteInfo(GATEWAY1));
984         source.addRoute(new RouteInfo(GATEWAY2));
985 
986         source.addValidatedPrivateDnsServer(DNS6);
987         source.addValidatedPrivateDnsServer(GATEWAY61);
988         source.addValidatedPrivateDnsServer(TESTIPV6ADDR);
989 
990         source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));
991 
992         source.setMtu(MTU);
993 
994         source.setTcpBufferSizes(TCP_BUFFER_SIZES);
995 
996         source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
997 
998         final LinkProperties stacked = new LinkProperties();
999         stacked.setInterfaceName("test-stacked");
1000         source.addStackedLink(stacked);
1001 
1002         return source;
1003     }
1004 
1005     @Test @IgnoreAfter(Build.VERSION_CODES.Q)
testLinkPropertiesParcelable_Q()1006     public void testLinkPropertiesParcelable_Q() throws Exception {
1007         final LinkProperties source = makeLinkPropertiesForParceling();
1008         assertParcelingIsLossless(source);
1009     }
1010 
1011     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testLinkPropertiesParcelable()1012     public void testLinkPropertiesParcelable() throws Exception {
1013         final LinkProperties source = makeLinkPropertiesForParceling();
1014 
1015         source.setWakeOnLanSupported(true);
1016         source.setCaptivePortalApiUrl(CAPPORT_API_URL);
1017         source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData());
1018         source.setDhcpServerAddress((Inet4Address) GATEWAY1);
1019         assertParcelingIsLossless(new LinkProperties(source, true /* parcelSensitiveFields */));
1020 
1021         // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared.
1022         final LinkProperties sanitized = new LinkProperties(source);
1023         sanitized.setCaptivePortalApiUrl(null);
1024         sanitized.setCaptivePortalData(null);
1025         assertEquals(sanitized, parcelingRoundTrip(source));
1026     }
1027 
1028     // Parceling of the scope was broken until Q-QPR2
1029     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testLinkLocalDnsServerParceling()1030     public void testLinkLocalDnsServerParceling() throws Exception {
1031         final String strAddress = "fe80::1%lo";
1032         final LinkProperties lp = new LinkProperties();
1033         lp.addDnsServer(address(strAddress));
1034         final LinkProperties unparceled = parcelingRoundTrip(lp);
1035         // Inet6Address#equals does not test for the scope id
1036         assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress());
1037     }
1038 
1039     @Test
testParcelUninitialized()1040     public void testParcelUninitialized() throws Exception {
1041         LinkProperties empty = new LinkProperties();
1042         assertParcelingIsLossless(empty);
1043     }
1044 
1045     @Test
testConstructor()1046     public void testConstructor() {
1047         LinkProperties lp = new LinkProperties();
1048         checkEmpty(lp);
1049         assertLinkPropertiesEqual(lp, new LinkProperties(lp));
1050         assertLinkPropertiesEqual(lp, new LinkProperties());
1051 
1052         lp = makeTestObject();
1053         assertLinkPropertiesEqual(lp, new LinkProperties(lp));
1054     }
1055 
1056     @Test
testDnsServers()1057     public void testDnsServers() {
1058         final LinkProperties lp = new LinkProperties();
1059         final List<InetAddress> dnsServers = Arrays.asList(DNS1, DNS2);
1060         lp.setDnsServers(dnsServers);
1061         assertEquals(2, lp.getDnsServers().size());
1062         assertEquals(DNS1, lp.getDnsServers().get(0));
1063         assertEquals(DNS2, lp.getDnsServers().get(1));
1064 
1065         lp.removeDnsServer(DNS1);
1066         assertEquals(1, lp.getDnsServers().size());
1067         assertEquals(DNS2, lp.getDnsServers().get(0));
1068 
1069         lp.addDnsServer(DNS6);
1070         assertEquals(2, lp.getDnsServers().size());
1071         assertEquals(DNS2, lp.getDnsServers().get(0));
1072         assertEquals(DNS6, lp.getDnsServers().get(1));
1073     }
1074 
1075     @Test
testValidatedPrivateDnsServers()1076     public void testValidatedPrivateDnsServers() {
1077         final LinkProperties lp = new LinkProperties();
1078         final List<InetAddress> privDnsServers = Arrays.asList(PRIVDNS1, PRIVDNS2);
1079         lp.setValidatedPrivateDnsServers(privDnsServers);
1080         assertEquals(2, lp.getValidatedPrivateDnsServers().size());
1081         assertEquals(PRIVDNS1, lp.getValidatedPrivateDnsServers().get(0));
1082         assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(1));
1083 
1084         lp.removeValidatedPrivateDnsServer(PRIVDNS1);
1085         assertEquals(1, lp.getValidatedPrivateDnsServers().size());
1086         assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0));
1087 
1088         lp.addValidatedPrivateDnsServer(PRIVDNS6);
1089         assertEquals(2, lp.getValidatedPrivateDnsServers().size());
1090         assertEquals(PRIVDNS2, lp.getValidatedPrivateDnsServers().get(0));
1091         assertEquals(PRIVDNS6, lp.getValidatedPrivateDnsServers().get(1));
1092     }
1093 
1094     @Test
testPcscfServers()1095     public void testPcscfServers() {
1096         final LinkProperties lp = new LinkProperties();
1097         final List<InetAddress> pcscfServers = Arrays.asList(PCSCFV4);
1098         lp.setPcscfServers(pcscfServers);
1099         assertEquals(1, lp.getPcscfServers().size());
1100         assertEquals(PCSCFV4, lp.getPcscfServers().get(0));
1101 
1102         lp.removePcscfServer(PCSCFV4);
1103         assertEquals(0, lp.getPcscfServers().size());
1104 
1105         lp.addPcscfServer(PCSCFV6);
1106         assertEquals(1, lp.getPcscfServers().size());
1107         assertEquals(PCSCFV6, lp.getPcscfServers().get(0));
1108     }
1109 
1110     @Test
testTcpBufferSizes()1111     public void testTcpBufferSizes() {
1112         final LinkProperties lp = makeTestObject();
1113         assertEquals(TCP_BUFFER_SIZES, lp.getTcpBufferSizes());
1114 
1115         lp.setTcpBufferSizes(null);
1116         assertNull(lp.getTcpBufferSizes());
1117     }
1118 
1119     @Test
testHasIpv6DefaultRoute()1120     public void testHasIpv6DefaultRoute() {
1121         final LinkProperties lp = makeTestObject();
1122         assertFalse(lp.hasIPv6DefaultRoute());
1123 
1124         lp.addRoute(new RouteInfo(GATEWAY61));
1125         assertTrue(lp.hasIPv6DefaultRoute());
1126     }
1127 
1128     @Test
testHttpProxy()1129     public void testHttpProxy() {
1130         final LinkProperties lp = makeTestObject();
1131         assertTrue(lp.getHttpProxy().equals(ProxyInfo.buildDirectProxy("test", 8888)));
1132     }
1133 
1134     @Test
testPrivateDnsServerName()1135     public void testPrivateDnsServerName() {
1136         final LinkProperties lp = makeTestObject();
1137         assertEquals(PRIV_DNS_SERVER_NAME, lp.getPrivateDnsServerName());
1138 
1139         lp.setPrivateDnsServerName(null);
1140         assertNull(lp.getPrivateDnsServerName());
1141     }
1142 
1143     @Test
testUsePrivateDns()1144     public void testUsePrivateDns() {
1145         final LinkProperties lp = makeTestObject();
1146         assertTrue(lp.isPrivateDnsActive());
1147 
1148         lp.clear();
1149         assertFalse(lp.isPrivateDnsActive());
1150     }
1151 
1152     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testDhcpServerAddress()1153     public void testDhcpServerAddress() {
1154         final LinkProperties lp = makeTestObject();
1155         assertEquals(DHCPSERVER, lp.getDhcpServerAddress());
1156 
1157         lp.clear();
1158         assertNull(lp.getDhcpServerAddress());
1159     }
1160 
1161     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testWakeOnLanSupported()1162     public void testWakeOnLanSupported() {
1163         final LinkProperties lp = makeTestObject();
1164         assertTrue(lp.isWakeOnLanSupported());
1165 
1166         lp.clear();
1167         assertFalse(lp.isWakeOnLanSupported());
1168     }
1169 
1170     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testCaptivePortalApiUrl()1171     public void testCaptivePortalApiUrl() {
1172         final LinkProperties lp = makeTestObject();
1173         assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl());
1174 
1175         lp.clear();
1176         assertNull(lp.getCaptivePortalApiUrl());
1177     }
1178 
1179     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testCaptivePortalData()1180     public void testCaptivePortalData() {
1181         final LinkProperties lp = makeTestObject();
1182         assertEquals(getCaptivePortalData(), lp.getCaptivePortalData());
1183 
1184         lp.clear();
1185         assertNull(lp.getCaptivePortalData());
1186     }
1187 
makeIpv4LinkProperties()1188     private LinkProperties makeIpv4LinkProperties() {
1189         final LinkProperties linkProperties = new LinkProperties();
1190         linkProperties.setInterfaceName(NAME);
1191         linkProperties.addLinkAddress(LINKADDRV4);
1192         linkProperties.addDnsServer(DNS1);
1193         linkProperties.addRoute(new RouteInfo(GATEWAY1));
1194         linkProperties.addRoute(new RouteInfo(GATEWAY2));
1195         return linkProperties;
1196     }
1197 
makeIpv6LinkProperties()1198     private LinkProperties makeIpv6LinkProperties() {
1199         final LinkProperties linkProperties = new LinkProperties();
1200         linkProperties.setInterfaceName(NAME);
1201         linkProperties.addLinkAddress(LINKADDRV6);
1202         linkProperties.addDnsServer(DNS6);
1203         linkProperties.addRoute(new RouteInfo(GATEWAY61));
1204         linkProperties.addRoute(new RouteInfo(GATEWAY62));
1205         return linkProperties;
1206     }
1207 
1208     @Test
testHasIpv4DefaultRoute()1209     public void testHasIpv4DefaultRoute() {
1210         final LinkProperties Ipv4 = makeIpv4LinkProperties();
1211         assertTrue(Ipv4.hasIpv4DefaultRoute());
1212         final LinkProperties Ipv6 = makeIpv6LinkProperties();
1213         assertFalse(Ipv6.hasIpv4DefaultRoute());
1214     }
1215 
1216     @Test
testHasIpv4DnsServer()1217     public void testHasIpv4DnsServer() {
1218         final LinkProperties Ipv4 = makeIpv4LinkProperties();
1219         assertTrue(Ipv4.hasIpv4DnsServer());
1220         final LinkProperties Ipv6 = makeIpv6LinkProperties();
1221         assertFalse(Ipv6.hasIpv4DnsServer());
1222     }
1223 
1224     @Test
testHasIpv6DnsServer()1225     public void testHasIpv6DnsServer() {
1226         final LinkProperties Ipv4 = makeIpv4LinkProperties();
1227         assertFalse(Ipv4.hasIpv6DnsServer());
1228         final LinkProperties Ipv6 = makeIpv6LinkProperties();
1229         assertTrue(Ipv6.hasIpv6DnsServer());
1230     }
1231 
1232     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testHasIpv4UnreachableDefaultRoute()1233     public void testHasIpv4UnreachableDefaultRoute() {
1234         final LinkProperties lp = makeTestObject();
1235         assertFalse(lp.hasIpv4UnreachableDefaultRoute());
1236         assertFalse(lp.hasIpv6UnreachableDefaultRoute());
1237 
1238         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
1239         assertTrue(lp.hasIpv4UnreachableDefaultRoute());
1240         assertFalse(lp.hasIpv6UnreachableDefaultRoute());
1241     }
1242 
1243     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testHasIpv6UnreachableDefaultRoute()1244     public void testHasIpv6UnreachableDefaultRoute() {
1245         final LinkProperties lp = makeTestObject();
1246         assertFalse(lp.hasIpv6UnreachableDefaultRoute());
1247         assertFalse(lp.hasIpv4UnreachableDefaultRoute());
1248 
1249         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
1250         assertTrue(lp.hasIpv6UnreachableDefaultRoute());
1251         assertFalse(lp.hasIpv4UnreachableDefaultRoute());
1252     }
1253 
1254     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testRouteAddWithSameKey()1255     public void testRouteAddWithSameKey() throws Exception {
1256         LinkProperties lp = new LinkProperties();
1257         lp.setInterfaceName("wlan0");
1258         final IpPrefix v6 = new IpPrefix("64:ff9b::/96");
1259         lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1280));
1260         assertEquals(1, lp.getRoutes().size());
1261         lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1500));
1262         assertEquals(1, lp.getRoutes().size());
1263         final IpPrefix v4 = new IpPrefix("192.0.2.128/25");
1264         lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_UNICAST, 1460));
1265         assertEquals(2, lp.getRoutes().size());
1266         lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_THROW, 1460));
1267         assertEquals(2, lp.getRoutes().size());
1268     }
1269 }
1270