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