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