1 /*
2  * Copyright (C) 2013 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.system.OsConstants.IFA_F_DADFAILED;
20 import static android.system.OsConstants.IFA_F_DEPRECATED;
21 import static android.system.OsConstants.IFA_F_OPTIMISTIC;
22 import static android.system.OsConstants.IFA_F_PERMANENT;
23 import static android.system.OsConstants.IFA_F_TEMPORARY;
24 import static android.system.OsConstants.IFA_F_TENTATIVE;
25 import static android.system.OsConstants.RT_SCOPE_HOST;
26 import static android.system.OsConstants.RT_SCOPE_LINK;
27 import static android.system.OsConstants.RT_SCOPE_SITE;
28 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
29 
30 import static com.android.testutils.MiscAsserts.assertEqualBothWays;
31 import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
32 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
33 
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertNotEquals;
37 import static org.junit.Assert.assertTrue;
38 import static org.junit.Assert.fail;
39 
40 import android.os.Build;
41 import android.os.SystemClock;
42 
43 import androidx.test.filters.SmallTest;
44 import androidx.test.runner.AndroidJUnit4;
45 
46 import com.android.testutils.ConnectivityModuleTest;
47 import com.android.testutils.DevSdkIgnoreRule;
48 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
49 
50 import org.junit.Rule;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 
54 import java.net.Inet4Address;
55 import java.net.Inet6Address;
56 import java.net.InetAddress;
57 import java.net.InterfaceAddress;
58 import java.net.NetworkInterface;
59 import java.net.SocketException;
60 import java.util.Arrays;
61 import java.util.List;
62 
63 @RunWith(AndroidJUnit4.class)
64 @SmallTest
65 @ConnectivityModuleTest
66 public class LinkAddressTest {
67     @Rule
68     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
69 
70     private static final String V4 = "192.0.2.1";
71     private static final String V6 = "2001:db8::1";
72     private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4);
73     private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6);
74 
75     @Test
testConstants()76     public void testConstants() {
77         // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
78         assertNotEquals(0, RT_SCOPE_HOST);
79         assertNotEquals(0, RT_SCOPE_LINK);
80         assertNotEquals(0, RT_SCOPE_SITE);
81 
82         assertNotEquals(0, IFA_F_DEPRECATED);
83         assertNotEquals(0, IFA_F_PERMANENT);
84         assertNotEquals(0, IFA_F_TENTATIVE);
85     }
86 
87     @Test
testConstructors()88     public void testConstructors() throws SocketException {
89         LinkAddress address;
90 
91         // Valid addresses work as expected.
92         address = new LinkAddress(V4_ADDRESS, 25);
93         assertEquals(V4_ADDRESS, address.getAddress());
94         assertEquals(25, address.getPrefixLength());
95         assertEquals(0, address.getFlags());
96         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
97         assertTrue(address.isIpv4());
98 
99         address = new LinkAddress(V6_ADDRESS, 127);
100         assertEquals(V6_ADDRESS, address.getAddress());
101         assertEquals(127, address.getPrefixLength());
102         assertEquals(0, address.getFlags());
103         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
104         assertTrue(address.isIpv6());
105 
106         // Nonsensical flags/scopes or combinations thereof are acceptable.
107         address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
108         assertEquals(V6_ADDRESS, address.getAddress());
109         assertEquals(64, address.getPrefixLength());
110         assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
111         assertEquals(RT_SCOPE_LINK, address.getScope());
112         assertTrue(address.isIpv6());
113 
114         address = new LinkAddress(V4 + "/23", 123, 456);
115         assertEquals(V4_ADDRESS, address.getAddress());
116         assertEquals(23, address.getPrefixLength());
117         assertEquals(123, address.getFlags());
118         assertEquals(456, address.getScope());
119         assertTrue(address.isIpv4());
120 
121         address = new LinkAddress("/64", 1 /* flags */, 2 /* scope */);
122         assertEquals(Inet6Address.LOOPBACK, address.getAddress());
123         assertEquals(64, address.getPrefixLength());
124         assertEquals(1, address.getFlags());
125         assertEquals(2, address.getScope());
126         assertTrue(address.isIpv6());
127 
128         address = new LinkAddress("[2001:db8::123]/64", 3 /* flags */, 4 /* scope */);
129         assertEquals(InetAddresses.parseNumericAddress("2001:db8::123"), address.getAddress());
130         assertEquals(64, address.getPrefixLength());
131         assertEquals(3, address.getFlags());
132         assertEquals(4, address.getScope());
133         assertTrue(address.isIpv6());
134 
135         // InterfaceAddress doesn't have a constructor. Fetch some from an interface.
136         List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
137 
138         // We expect to find 127.0.0.1/8 and ::1/128, in any order.
139         LinkAddress ipv4Loopback, ipv6Loopback;
140         assertEquals(2, addrs.size());
141         if (addrs.get(0).getAddress() instanceof Inet4Address) {
142             ipv4Loopback = new LinkAddress(addrs.get(0));
143             ipv6Loopback = new LinkAddress(addrs.get(1));
144         } else {
145             ipv4Loopback = new LinkAddress(addrs.get(1));
146             ipv6Loopback = new LinkAddress(addrs.get(0));
147         }
148 
149         assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress());
150         assertEquals(8, ipv4Loopback.getPrefixLength());
151 
152         assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress());
153         assertEquals(128, ipv6Loopback.getPrefixLength());
154 
155         // Null addresses are rejected.
156         try {
157             address = new LinkAddress(null, 24);
158             fail("Null InetAddress should cause IllegalArgumentException");
159         } catch(IllegalArgumentException expected) {}
160 
161         try {
162             address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
163             fail("Null string should cause IllegalArgumentException");
164         } catch(IllegalArgumentException expected) {}
165 
166         try {
167             address = new LinkAddress((InterfaceAddress) null);
168             fail("Null string should cause NullPointerException");
169         } catch(NullPointerException expected) {}
170 
171         // Invalid prefix lengths are rejected.
172         try {
173             address = new LinkAddress(V4_ADDRESS, -1);
174             fail("Negative IPv4 prefix length should cause IllegalArgumentException");
175         } catch(IllegalArgumentException expected) {}
176 
177         try {
178             address = new LinkAddress(V6_ADDRESS, -1);
179             fail("Negative IPv6 prefix length should cause IllegalArgumentException");
180         } catch(IllegalArgumentException expected) {}
181 
182         try {
183             address = new LinkAddress(V4_ADDRESS, 33);
184             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
185         } catch(IllegalArgumentException expected) {}
186 
187         try {
188             address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
189             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
190         } catch(IllegalArgumentException expected) {}
191 
192 
193         try {
194             address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
195             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
196         } catch(IllegalArgumentException expected) {}
197 
198         try {
199             address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
200             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
201         } catch(IllegalArgumentException expected) {}
202 
203         // Multicast addresses are rejected.
204         try {
205             address = new LinkAddress("224.0.0.2/32");
206             fail("IPv4 multicast address should cause IllegalArgumentException");
207         } catch(IllegalArgumentException expected) {}
208 
209         try {
210             address = new LinkAddress("ff02::1/128");
211             fail("IPv6 multicast address should cause IllegalArgumentException");
212         } catch(IllegalArgumentException expected) {}
213     }
214 
215     @Test
testAddressScopes()216     public void testAddressScopes() {
217         assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
218         assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
219 
220         assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope());
221         assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope());
222         assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope());
223         assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope());
224 
225         assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope());
226 
227         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope());
228         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope());
229         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope());
230         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope());
231     }
232 
assertIsSameAddressAs(LinkAddress l1, LinkAddress l2)233     private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) {
234         assertTrue(l1 + " unexpectedly does not have same address as " + l2,
235                 l1.isSameAddressAs(l2));
236         assertTrue(l2 + " unexpectedly does not have same address as " + l1,
237                 l2.isSameAddressAs(l1));
238     }
239 
assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2)240     private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) {
241         assertFalse(l1 + " unexpectedly has same address as " + l2,
242                 l1.isSameAddressAs(l2));
243         assertFalse(l2 + " unexpectedly has same address as " + l1,
244                 l1.isSameAddressAs(l2));
245     }
246 
247     @Test
testEqualsAndSameAddressAs()248     public void testEqualsAndSameAddressAs() {
249         LinkAddress l1, l2, l3;
250 
251         l1 = new LinkAddress("2001:db8::1/64");
252         l2 = new LinkAddress("2001:db8::1/64");
253         assertEqualBothWays(l1, l2);
254         assertIsSameAddressAs(l1, l2);
255 
256         l2 = new LinkAddress("2001:db8::1/65");
257         assertNotEqualEitherWay(l1, l2);
258         assertIsNotSameAddressAs(l1, l2);
259 
260         l2 = new LinkAddress("2001:db8::2/64");
261         assertNotEqualEitherWay(l1, l2);
262         assertIsNotSameAddressAs(l1, l2);
263 
264 
265         l1 = new LinkAddress("192.0.2.1/24");
266         l2 = new LinkAddress("192.0.2.1/24");
267         assertEqualBothWays(l1, l2);
268         assertIsSameAddressAs(l1, l2);
269 
270         l2 = new LinkAddress("192.0.2.1/23");
271         assertNotEqualEitherWay(l1, l2);
272         assertIsNotSameAddressAs(l1, l2);
273 
274         l2 = new LinkAddress("192.0.2.2/24");
275         assertNotEqualEitherWay(l1, l2);
276         assertIsNotSameAddressAs(l1, l2);
277 
278 
279         // Check equals() and isSameAddressAs() on identical addresses with different flags.
280         l1 = new LinkAddress(V6_ADDRESS, 64);
281         l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
282         assertEqualBothWays(l1, l2);
283         assertIsSameAddressAs(l1, l2);
284 
285         l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE);
286         assertNotEqualEitherWay(l1, l2);
287         assertIsSameAddressAs(l1, l2);
288 
289         // Check equals() and isSameAddressAs() on identical addresses with different scope.
290         l1 = new LinkAddress(V4_ADDRESS, 24);
291         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE);
292         assertEqualBothWays(l1, l2);
293         assertIsSameAddressAs(l1, l2);
294 
295         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST);
296         assertNotEqualEitherWay(l1, l2);
297         assertIsSameAddressAs(l1, l2);
298 
299         // Addresses with the same start or end bytes aren't equal between families.
300         l1 = new LinkAddress("32.1.13.184/24");
301         l2 = new LinkAddress("2001:db8::1/24");
302         l3 = new LinkAddress("::2001:db8/24");
303 
304         byte[] ipv4Bytes = l1.getAddress().getAddress();
305         byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4);
306         byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16);
307         assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes));
308         assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes));
309 
310         assertNotEqualEitherWay(l1, l2);
311         assertIsNotSameAddressAs(l1, l2);
312 
313         assertNotEqualEitherWay(l1, l3);
314         assertIsNotSameAddressAs(l1, l3);
315 
316         // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address.
317         // TODO: Investigate fixing this.
318         String addressString = V4 + "/24";
319         l1 = new LinkAddress(addressString);
320         l2 = new LinkAddress("::ffff:" + addressString);
321         assertEqualBothWays(l1, l2);
322         assertIsSameAddressAs(l1, l2);
323     }
324 
325     @Test
testHashCode()326     public void testHashCode() {
327         LinkAddress l1, l2;
328 
329         l1 = new LinkAddress(V4_ADDRESS, 23);
330         l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
331         assertNotEquals(l1.hashCode(), l2.hashCode());
332 
333         l1 = new LinkAddress(V6_ADDRESS, 128);
334         l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
335         assertNotEquals(l1.hashCode(), l2.hashCode());
336     }
337 
338     @Test
testParceling()339     public void testParceling() {
340         LinkAddress l;
341 
342         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
343         assertParcelingIsLossless(l);
344 
345         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
346         assertParcelingIsLossless(l);
347     }
348 
349     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testLifetimeParceling()350     public void testLifetimeParceling() {
351         final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L);
352         assertParcelingIsLossless(l);
353     }
354 
355     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testDeprecationTime()356     public void testDeprecationTime() {
357         try {
358             new LinkAddress(V6_ADDRESS, 64, 0, 456,
359                     LinkAddress.LIFETIME_UNKNOWN, 100000L);
360             fail("Only one time provided should cause exception");
361         } catch (IllegalArgumentException expected) { }
362 
363         try {
364             new LinkAddress(V6_ADDRESS, 64, 0, 456,
365                     200000L, 100000L);
366             fail("deprecation time later than expiration time should cause exception");
367         } catch (IllegalArgumentException expected) { }
368 
369         try {
370             new LinkAddress(V6_ADDRESS, 64, 0, 456,
371                     -2, 100000L);
372             fail("negative deprecation time should cause exception");
373         } catch (IllegalArgumentException expected) { }
374 
375         LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
376         assertEquals(100000L, addr.getDeprecationTime());
377     }
378 
379     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testExpirationTime()380     public void testExpirationTime() {
381         try {
382             new LinkAddress(V6_ADDRESS, 64, 0, 456,
383                     200000L, LinkAddress.LIFETIME_UNKNOWN);
384             fail("Only one time provided should cause exception");
385         } catch (IllegalArgumentException expected) { }
386 
387         try {
388             new LinkAddress(V6_ADDRESS, 64, 0, 456,
389                     100000L, -2);
390             fail("negative expiration time should cause exception");
391         } catch (IllegalArgumentException expected) { }
392 
393         LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
394         assertEquals(200000L, addr.getExpirationTime());
395     }
396 
397     @Test
testGetFlags()398     public void testGetFlags() {
399         LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
400         assertEquals(123, l.getFlags());
401     }
402 
403     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testGetFlags_Deprecation()404     public void testGetFlags_Deprecation() {
405         // Test if deprecated bit was added/remove automatically based on the provided deprecation
406         // time
407         LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
408                 1L, LinkAddress.LIFETIME_PERMANENT);
409         // Check if the flag is added automatically.
410         assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
411 
412         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
413                 SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT);
414         // Check if the flag is removed automatically.
415         assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0);
416 
417         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
418                 LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT);
419         // Check if the permanent flag is added.
420         assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0);
421 
422         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST,
423                 1000L, SystemClock.elapsedRealtime() + 100000L);
424         // Check if the permanent flag is removed
425         assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0);
426     }
427 
assertGlobalPreferred(LinkAddress l, String msg)428     private void assertGlobalPreferred(LinkAddress l, String msg) {
429         assertTrue(msg, l.isGlobalPreferred());
430     }
431 
assertNotGlobalPreferred(LinkAddress l, String msg)432     private void assertNotGlobalPreferred(LinkAddress l, String msg) {
433         assertFalse(msg, l.isGlobalPreferred());
434     }
435 
436     @Test
testIsGlobalPreferred()437     public void testIsGlobalPreferred() {
438         LinkAddress l;
439 
440         l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE);
441         assertGlobalPreferred(l, "v4,global,noflags");
442 
443         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE);
444         assertGlobalPreferred(l, "v4-rfc1918,global,noflags");
445 
446         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE);
447         assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags");
448 
449         l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST);
450         assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags");
451 
452         l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
453         assertGlobalPreferred(l, "v6,global,noflags");
454 
455         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
456         assertGlobalPreferred(l, "v6,global,permanent");
457 
458         // IPv6 ULAs are not acceptable "global preferred" addresses.
459         l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE);
460         assertNotGlobalPreferred(l, "v6,ula1,noflags");
461 
462         l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE);
463         assertNotGlobalPreferred(l, "v6,ula2,noflags");
464 
465         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE);
466         assertGlobalPreferred(l, "v6,global,tempaddr");
467 
468         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED),
469                             RT_SCOPE_UNIVERSE);
470         assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed");
471 
472         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED),
473                             RT_SCOPE_UNIVERSE);
474         assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated");
475 
476         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE);
477         assertNotGlobalPreferred(l, "v6,site-local,tempaddr");
478 
479         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK);
480         assertNotGlobalPreferred(l, "v6,link-local,tempaddr");
481 
482         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST);
483         assertNotGlobalPreferred(l, "v6,node-local,tempaddr");
484 
485         l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST);
486         assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent");
487 
488         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE),
489                             RT_SCOPE_UNIVERSE);
490         assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative");
491 
492         l = new LinkAddress(V6_ADDRESS, 64,
493                             (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
494                             RT_SCOPE_UNIVERSE);
495         assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
496     }
497 
498     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testIsGlobalPreferred_DeprecatedInFuture()499     public void testIsGlobalPreferred_DeprecatedInFuture() {
500         final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
501                 RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
502                 SystemClock.elapsedRealtime() + 200000);
503         // Although the deprecated bit is set, but the deprecation time is in the future, test
504         // if the flag is removed automatically.
505         assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future");
506     }
507 }
508