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 java.net.Inet4Address; 20 import java.net.Inet6Address; 21 import java.net.InetAddress; 22 import java.net.InterfaceAddress; 23 import java.net.NetworkInterface; 24 import java.net.SocketException; 25 import java.util.Arrays; 26 import java.util.Collections; 27 import java.util.Comparator; 28 import java.util.List; 29 30 import android.net.LinkAddress; 31 import android.os.Parcel; 32 import android.test.AndroidTestCase; 33 import static android.test.MoreAsserts.assertNotEqual; 34 import android.test.suitebuilder.annotation.SmallTest; 35 36 import static android.system.OsConstants.IFA_F_DADFAILED; 37 import static android.system.OsConstants.IFA_F_DEPRECATED; 38 import static android.system.OsConstants.IFA_F_OPTIMISTIC; 39 import static android.system.OsConstants.IFA_F_PERMANENT; 40 import static android.system.OsConstants.IFA_F_TEMPORARY; 41 import static android.system.OsConstants.IFA_F_TENTATIVE; 42 import static android.system.OsConstants.RT_SCOPE_HOST; 43 import static android.system.OsConstants.RT_SCOPE_LINK; 44 import static android.system.OsConstants.RT_SCOPE_SITE; 45 import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 46 47 /** 48 * Tests for {@link LinkAddress}. 49 */ 50 public class LinkAddressTest extends AndroidTestCase { 51 52 private static final String V4 = "192.0.2.1"; 53 private static final String V6 = "2001:db8::1"; 54 private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4); 55 private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6); 56 testConstants()57 public void testConstants() { 58 // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero. 59 assertNotEqual(0, RT_SCOPE_HOST); 60 assertNotEqual(0, RT_SCOPE_LINK); 61 assertNotEqual(0, RT_SCOPE_SITE); 62 63 assertNotEqual(0, IFA_F_DEPRECATED); 64 assertNotEqual(0, IFA_F_PERMANENT); 65 assertNotEqual(0, IFA_F_TENTATIVE); 66 } 67 testConstructors()68 public void testConstructors() throws SocketException { 69 LinkAddress address; 70 71 // Valid addresses work as expected. 72 address = new LinkAddress(V4_ADDRESS, 25); 73 assertEquals(V4_ADDRESS, address.getAddress()); 74 assertEquals(25, address.getPrefixLength()); 75 assertEquals(0, address.getFlags()); 76 assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); 77 78 address = new LinkAddress(V6_ADDRESS, 127); 79 assertEquals(V6_ADDRESS, address.getAddress()); 80 assertEquals(127, address.getPrefixLength()); 81 assertEquals(0, address.getFlags()); 82 assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); 83 84 // Nonsensical flags/scopes or combinations thereof are acceptable. 85 address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK); 86 assertEquals(V6_ADDRESS, address.getAddress()); 87 assertEquals(64, address.getPrefixLength()); 88 assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags()); 89 assertEquals(RT_SCOPE_LINK, address.getScope()); 90 91 address = new LinkAddress(V4 + "/23", 123, 456); 92 assertEquals(V4_ADDRESS, address.getAddress()); 93 assertEquals(23, address.getPrefixLength()); 94 assertEquals(123, address.getFlags()); 95 assertEquals(456, address.getScope()); 96 97 // InterfaceAddress doesn't have a constructor. Fetch some from an interface. 98 List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses(); 99 100 // We expect to find 127.0.0.1/8 and ::1/128, in any order. 101 LinkAddress ipv4Loopback, ipv6Loopback; 102 assertEquals(2, addrs.size()); 103 if (addrs.get(0).getAddress() instanceof Inet4Address) { 104 ipv4Loopback = new LinkAddress(addrs.get(0)); 105 ipv6Loopback = new LinkAddress(addrs.get(1)); 106 } else { 107 ipv4Loopback = new LinkAddress(addrs.get(1)); 108 ipv6Loopback = new LinkAddress(addrs.get(0)); 109 } 110 111 assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress()); 112 assertEquals(8, ipv4Loopback.getPrefixLength()); 113 114 assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress()); 115 assertEquals(128, ipv6Loopback.getPrefixLength()); 116 117 // Null addresses are rejected. 118 try { 119 address = new LinkAddress(null, 24); 120 fail("Null InetAddress should cause IllegalArgumentException"); 121 } catch(IllegalArgumentException expected) {} 122 123 try { 124 address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 125 fail("Null string should cause IllegalArgumentException"); 126 } catch(IllegalArgumentException expected) {} 127 128 try { 129 address = new LinkAddress((InterfaceAddress) null); 130 fail("Null string should cause NullPointerException"); 131 } catch(NullPointerException expected) {} 132 133 // Invalid prefix lengths are rejected. 134 try { 135 address = new LinkAddress(V4_ADDRESS, -1); 136 fail("Negative IPv4 prefix length should cause IllegalArgumentException"); 137 } catch(IllegalArgumentException expected) {} 138 139 try { 140 address = new LinkAddress(V6_ADDRESS, -1); 141 fail("Negative IPv6 prefix length should cause IllegalArgumentException"); 142 } catch(IllegalArgumentException expected) {} 143 144 try { 145 address = new LinkAddress(V4_ADDRESS, 33); 146 fail("/33 IPv4 prefix length should cause IllegalArgumentException"); 147 } catch(IllegalArgumentException expected) {} 148 149 try { 150 address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 151 fail("/33 IPv4 prefix length should cause IllegalArgumentException"); 152 } catch(IllegalArgumentException expected) {} 153 154 155 try { 156 address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 157 fail("/129 IPv6 prefix length should cause IllegalArgumentException"); 158 } catch(IllegalArgumentException expected) {} 159 160 try { 161 address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 162 fail("/129 IPv6 prefix length should cause IllegalArgumentException"); 163 } catch(IllegalArgumentException expected) {} 164 165 // Multicast addresses are rejected. 166 try { 167 address = new LinkAddress("224.0.0.2/32"); 168 fail("IPv4 multicast address should cause IllegalArgumentException"); 169 } catch(IllegalArgumentException expected) {} 170 171 try { 172 address = new LinkAddress("ff02::1/128"); 173 fail("IPv6 multicast address should cause IllegalArgumentException"); 174 } catch(IllegalArgumentException expected) {} 175 } 176 testAddressScopes()177 public void testAddressScopes() { 178 assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope()); 179 assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope()); 180 181 assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope()); 182 assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope()); 183 assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope()); 184 assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope()); 185 186 assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope()); 187 188 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope()); 189 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope()); 190 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope()); 191 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope()); 192 } 193 assertIsSameAddressAs(LinkAddress l1, LinkAddress l2)194 private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) { 195 assertTrue(l1 + " unexpectedly does not have same address as " + l2, 196 l1.isSameAddressAs(l2)); 197 assertTrue(l2 + " unexpectedly does not have same address as " + l1, 198 l2.isSameAddressAs(l1)); 199 } 200 assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2)201 private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) { 202 assertFalse(l1 + " unexpectedly has same address as " + l2, 203 l1.isSameAddressAs(l2)); 204 assertFalse(l2 + " unexpectedly has same address as " + l1, 205 l1.isSameAddressAs(l2)); 206 } 207 assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2)208 private void assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2) { 209 assertTrue(l1 + " unexpectedly not equal to " + l2, l1.equals(l2)); 210 assertTrue(l2 + " unexpectedly not equal to " + l1, l2.equals(l1)); 211 assertEquals(l1.hashCode(), l2.hashCode()); 212 } 213 assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2)214 private void assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2) { 215 assertFalse(l1 + " unexpectedly equal to " + l2, l1.equals(l2)); 216 assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1)); 217 } 218 testEqualsAndSameAddressAs()219 public void testEqualsAndSameAddressAs() { 220 LinkAddress l1, l2, l3; 221 222 l1 = new LinkAddress("2001:db8::1/64"); 223 l2 = new LinkAddress("2001:db8::1/64"); 224 assertLinkAddressesEqual(l1, l2); 225 assertIsSameAddressAs(l1, l2); 226 227 l2 = new LinkAddress("2001:db8::1/65"); 228 assertLinkAddressesNotEqual(l1, l2); 229 assertIsNotSameAddressAs(l1, l2); 230 231 l2 = new LinkAddress("2001:db8::2/64"); 232 assertLinkAddressesNotEqual(l1, l2); 233 assertIsNotSameAddressAs(l1, l2); 234 235 236 l1 = new LinkAddress("192.0.2.1/24"); 237 l2 = new LinkAddress("192.0.2.1/24"); 238 assertLinkAddressesEqual(l1, l2); 239 assertIsSameAddressAs(l1, l2); 240 241 l2 = new LinkAddress("192.0.2.1/23"); 242 assertLinkAddressesNotEqual(l1, l2); 243 assertIsNotSameAddressAs(l1, l2); 244 245 l2 = new LinkAddress("192.0.2.2/24"); 246 assertLinkAddressesNotEqual(l1, l2); 247 assertIsNotSameAddressAs(l1, l2); 248 249 250 // Check equals() and isSameAddressAs() on identical addresses with different flags. 251 l1 = new LinkAddress(V6_ADDRESS, 64); 252 l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); 253 assertLinkAddressesEqual(l1, l2); 254 assertIsSameAddressAs(l1, l2); 255 256 l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE); 257 assertLinkAddressesNotEqual(l1, l2); 258 assertIsSameAddressAs(l1, l2); 259 260 // Check equals() and isSameAddressAs() on identical addresses with different scope. 261 l1 = new LinkAddress(V4_ADDRESS, 24); 262 l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE); 263 assertLinkAddressesEqual(l1, l2); 264 assertIsSameAddressAs(l1, l2); 265 266 l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST); 267 assertLinkAddressesNotEqual(l1, l2); 268 assertIsSameAddressAs(l1, l2); 269 270 // Addresses with the same start or end bytes aren't equal between families. 271 l1 = new LinkAddress("32.1.13.184/24"); 272 l2 = new LinkAddress("2001:db8::1/24"); 273 l3 = new LinkAddress("::2001:db8/24"); 274 275 byte[] ipv4Bytes = l1.getAddress().getAddress(); 276 byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4); 277 byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16); 278 assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes)); 279 assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes)); 280 281 assertLinkAddressesNotEqual(l1, l2); 282 assertIsNotSameAddressAs(l1, l2); 283 284 assertLinkAddressesNotEqual(l1, l3); 285 assertIsNotSameAddressAs(l1, l3); 286 287 // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address. 288 // TODO: Investigate fixing this. 289 String addressString = V4 + "/24"; 290 l1 = new LinkAddress(addressString); 291 l2 = new LinkAddress("::ffff:" + addressString); 292 assertLinkAddressesEqual(l1, l2); 293 assertIsSameAddressAs(l1, l2); 294 } 295 testHashCode()296 public void testHashCode() { 297 LinkAddress l; 298 299 l = new LinkAddress(V4_ADDRESS, 23); 300 assertEquals(-982787, l.hashCode()); 301 302 l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST); 303 assertEquals(-971865, l.hashCode()); 304 305 l = new LinkAddress(V4_ADDRESS, 27); 306 assertEquals(-982743, l.hashCode()); 307 308 l = new LinkAddress(V6_ADDRESS, 64); 309 assertEquals(1076522926, l.hashCode()); 310 311 l = new LinkAddress(V6_ADDRESS, 128); 312 assertEquals(1076523630, l.hashCode()); 313 314 l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE); 315 assertEquals(1076524846, l.hashCode()); 316 } 317 passThroughParcel(LinkAddress l)318 private LinkAddress passThroughParcel(LinkAddress l) { 319 Parcel p = Parcel.obtain(); 320 LinkAddress l2 = null; 321 try { 322 l.writeToParcel(p, 0); 323 p.setDataPosition(0); 324 l2 = LinkAddress.CREATOR.createFromParcel(p); 325 } finally { 326 p.recycle(); 327 } 328 assertNotNull(l2); 329 return l2; 330 } 331 assertParcelingIsLossless(LinkAddress l)332 private void assertParcelingIsLossless(LinkAddress l) { 333 LinkAddress l2 = passThroughParcel(l); 334 assertEquals(l, l2); 335 } 336 testParceling()337 public void testParceling() { 338 LinkAddress l; 339 340 l = new LinkAddress(V6_ADDRESS, 64, 123, 456); 341 assertParcelingIsLossless(l); 342 343 l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); 344 assertParcelingIsLossless(l); 345 } 346 assertGlobalPreferred(LinkAddress l, String msg)347 private void assertGlobalPreferred(LinkAddress l, String msg) { 348 assertTrue(msg, l.isGlobalPreferred()); 349 } 350 assertNotGlobalPreferred(LinkAddress l, String msg)351 private void assertNotGlobalPreferred(LinkAddress l, String msg) { 352 assertFalse(msg, l.isGlobalPreferred()); 353 } 354 testIsGlobalPreferred()355 public void testIsGlobalPreferred() { 356 LinkAddress l; 357 358 l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE); 359 assertGlobalPreferred(l, "v4,global,noflags"); 360 361 l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE); 362 assertGlobalPreferred(l, "v4-rfc1918,global,noflags"); 363 364 l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE); 365 assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags"); 366 367 l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST); 368 assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags"); 369 370 l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); 371 assertGlobalPreferred(l, "v6,global,noflags"); 372 373 l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 374 assertGlobalPreferred(l, "v6,global,permanent"); 375 376 // IPv6 ULAs are not acceptable "global preferred" addresses. 377 l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE); 378 assertNotGlobalPreferred(l, "v6,ula1,noflags"); 379 380 l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE); 381 assertNotGlobalPreferred(l, "v6,ula2,noflags"); 382 383 l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE); 384 assertGlobalPreferred(l, "v6,global,tempaddr"); 385 386 l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED), 387 RT_SCOPE_UNIVERSE); 388 assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed"); 389 390 l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED), 391 RT_SCOPE_UNIVERSE); 392 assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated"); 393 394 l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE); 395 assertNotGlobalPreferred(l, "v6,site-local,tempaddr"); 396 397 l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK); 398 assertNotGlobalPreferred(l, "v6,link-local,tempaddr"); 399 400 l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST); 401 assertNotGlobalPreferred(l, "v6,node-local,tempaddr"); 402 403 l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST); 404 assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent"); 405 406 l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE), 407 RT_SCOPE_UNIVERSE); 408 assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative"); 409 410 l = new LinkAddress(V6_ADDRESS, 64, 411 (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC), 412 RT_SCOPE_UNIVERSE); 413 assertGlobalPreferred(l, "v6,global,tempaddr+optimistic"); 414 } 415 } 416