1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.net; 28 29 import java.io.IOException; 30 import java.io.InvalidObjectException; 31 import java.io.ObjectInputStream; 32 import java.io.ObjectOutputStream; 33 import java.io.ObjectStreamField; 34 import java.util.Enumeration; 35 import java.util.Arrays; 36 import libcore.io.Libcore; 37 import static android.system.OsConstants.*; 38 39 /** 40 * This class represents an Internet Protocol version 6 (IPv6) address. 41 * Defined by <a href="http://www.ietf.org/rfc/rfc2373.txt"> 42 * <i>RFC 2373: IP Version 6 Addressing Architecture</i></a>. 43 * 44 * <h3> <A NAME="format">Textual representation of IP addresses</a> </h3> 45 * 46 * Textual representation of IPv6 address used as input to methods 47 * takes one of the following forms: 48 * 49 * <ol> 50 * <li><p> <A NAME="lform">The preferred form</a> is x:x:x:x:x:x:x:x, 51 * where the 'x's are 52 * the hexadecimal values of the eight 16-bit pieces of the 53 * address. This is the full form. For example, 54 * 55 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 56 * <tr><td>{@code 1080:0:0:0:8:800:200C:417A}<td></tr> 57 * </table></blockquote> 58 * 59 * <p> Note that it is not necessary to write the leading zeros in 60 * an individual field. However, there must be at least one numeral 61 * in every field, except as described below.</li> 62 * 63 * <li><p> Due to some methods of allocating certain styles of IPv6 64 * addresses, it will be common for addresses to contain long 65 * strings of zero bits. In order to make writing addresses 66 * containing zero bits easier, a special syntax is available to 67 * compress the zeros. The use of "::" indicates multiple groups 68 * of 16-bits of zeros. The "::" can only appear once in an address. 69 * The "::" can also be used to compress the leading and/or trailing 70 * zeros in an address. For example, 71 * 72 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 73 * <tr><td>{@code 1080::8:800:200C:417A}<td></tr> 74 * </table></blockquote> 75 * 76 * <li><p> An alternative form that is sometimes more convenient 77 * when dealing with a mixed environment of IPv4 and IPv6 nodes is 78 * x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values 79 * of the six high-order 16-bit pieces of the address, and the 'd's 80 * are the decimal values of the four low-order 8-bit pieces of the 81 * standard IPv4 representation address, for example, 82 * 83 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 84 * <tr><td>{@code ::FFFF:129.144.52.38}<td></tr> 85 * <tr><td>{@code ::129.144.52.38}<td></tr> 86 * </table></blockquote> 87 * 88 * <p> where "::FFFF:d.d.d.d" and "::d.d.d.d" are, respectively, the 89 * general forms of an IPv4-mapped IPv6 address and an 90 * IPv4-compatible IPv6 address. Note that the IPv4 portion must be 91 * in the "d.d.d.d" form. The following forms are invalid: 92 * 93 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 94 * <tr><td>{@code ::FFFF:d.d.d}<td></tr> 95 * <tr><td>{@code ::FFFF:d.d}<td></tr> 96 * <tr><td>{@code ::d.d.d}<td></tr> 97 * <tr><td>{@code ::d.d}<td></tr> 98 * </table></blockquote> 99 * 100 * <p> The following form: 101 * 102 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 103 * <tr><td>{@code ::FFFF:d}<td></tr> 104 * </table></blockquote> 105 * 106 * <p> is valid, however it is an unconventional representation of 107 * the IPv4-compatible IPv6 address, 108 * 109 * <blockquote><table cellpadding=0 cellspacing=0 summary="layout"> 110 * <tr><td>{@code ::255.255.0.d}<td></tr> 111 * </table></blockquote> 112 * 113 * <p> while "::d" corresponds to the general IPv6 address 114 * "0:0:0:0:0:0:0:d".</li> 115 * </ol> 116 * 117 * <p> For methods that return a textual representation as output 118 * value, the full form is used. Inet6Address will return the full 119 * form because it is unambiguous when used in combination with other 120 * textual data. 121 * 122 * <h4> Special IPv6 address </h4> 123 * 124 * <blockquote> 125 * <table cellspacing=2 summary="Description of IPv4-mapped address"> 126 * <tr><th valign=top><i>IPv4-mapped address</i></th> 127 * <td>Of the form::ffff:w.x.y.z, this IPv6 address is used to 128 * represent an IPv4 address. It allows the native program to 129 * use the same address data structure and also the same 130 * socket when communicating with both IPv4 and IPv6 nodes. 131 * 132 * <p>In InetAddress and Inet6Address, it is used for internal 133 * representation; it has no functional role. Java will never 134 * return an IPv4-mapped address. These classes can take an 135 * IPv4-mapped address as input, both in byte array and text 136 * representation. However, it will be converted into an IPv4 137 * address.</td></tr> 138 * </table></blockquote> 139 * 140 * <h4><A NAME="scoped">Textual representation of IPv6 scoped addresses</a></h4> 141 * 142 * <p> The textual representation of IPv6 addresses as described above can be 143 * extended to specify IPv6 scoped addresses. This extension to the basic 144 * addressing architecture is described in [draft-ietf-ipngwg-scoping-arch-04.txt]. 145 * 146 * <p> Because link-local and site-local addresses are non-global, it is possible 147 * that different hosts may have the same destination address and may be 148 * reachable through different interfaces on the same originating system. In 149 * this case, the originating system is said to be connected to multiple zones 150 * of the same scope. In order to disambiguate which is the intended destination 151 * zone, it is possible to append a zone identifier (or <i>scope_id</i>) to an 152 * IPv6 address. 153 * 154 * <p> The general format for specifying the <i>scope_id</i> is the following: 155 * 156 * <blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote> 157 * <p> The IPv6-address is a literal IPv6 address as described above. 158 * The <i>scope_id</i> refers to an interface on the local system, and it can be 159 * specified in two ways. 160 * <ol><li><i>As a numeric identifier.</i> This must be a positive integer 161 * that identifies the particular interface and scope as understood by the 162 * system. Usually, the numeric values can be determined through administration 163 * tools on the system. Each interface may have multiple values, one for each 164 * scope. If the scope is unspecified, then the default value used is zero.</li> 165 * <li><i>As a string.</i> This must be the exact string that is returned by 166 * {@link java.net.NetworkInterface#getName()} for the particular interface in 167 * question. When an Inet6Address is created in this way, the numeric scope-id 168 * is determined at the time the object is created by querying the relevant 169 * NetworkInterface.</li></ol> 170 * 171 * <p> Note also, that the numeric <i>scope_id</i> can be retrieved from 172 * Inet6Address instances returned from the NetworkInterface class. This can be 173 * used to find out the current scope ids configured on the system. 174 * @since 1.4 175 */ 176 177 public final 178 class Inet6Address extends InetAddress { 179 final static int INADDRSZ = 16; 180 181 // BEGIN Android-removed: Remove special handling for link-local addresses. 182 /* 183 * cached scope_id - for link-local address use only. 184 * 185 private transient int cached_scope_id; // 0 186 */ 187 // END Android-removed: Remove special handling for link-local addresses. 188 189 // BEGIN Android-added: Define special-purpose IPv6 address. 190 /** 191 * Reserved address for {@code INADDR_ANY}, to specify any IPv6 address at all. 192 * 193 * @hide 194 */ 195 public static final InetAddress ANY = 196 new Inet6Address("::", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0); 197 198 /** 199 * Loopback address to the local host. 200 * 201 * @hide 202 */ 203 public static final InetAddress LOOPBACK = new Inet6Address("ip6-localhost", 204 new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 0); 205 // END Android-added: Define special-purpose IPv6 address. 206 207 private class Inet6AddressHolder { 208 Inet6AddressHolder()209 private Inet6AddressHolder() { 210 ipaddress = new byte[INADDRSZ]; 211 } 212 Inet6AddressHolder( byte[] ipaddress, int scope_id, boolean scope_id_set, NetworkInterface ifname, boolean scope_ifname_set)213 private Inet6AddressHolder( 214 byte[] ipaddress, int scope_id, boolean scope_id_set, 215 NetworkInterface ifname, boolean scope_ifname_set) 216 { 217 this.ipaddress = ipaddress; 218 this.scope_id = scope_id; 219 this.scope_id_set = scope_id_set; 220 this.scope_ifname_set = scope_ifname_set; 221 this.scope_ifname = ifname; 222 } 223 224 /** 225 * Holds a 128-bit (16 bytes) IPv6 address. 226 */ 227 byte[] ipaddress; 228 229 /** 230 * scope_id. The scope specified when the object is created. If the object 231 * is created with an interface name, then the scope_id is not determined 232 * until the time it is needed. 233 */ 234 int scope_id; // 0 235 236 /** 237 * This will be set to true when the scope_id field contains a valid 238 * integer scope_id. 239 */ 240 boolean scope_id_set; // false 241 242 /** 243 * scoped interface. scope_id is derived from this as the scope_id of the first 244 * address whose scope is the same as this address for the named interface. 245 */ 246 NetworkInterface scope_ifname; // null 247 248 /** 249 * set if the object is constructed with a scoped 250 * interface instead of a numeric scope id. 251 */ 252 boolean scope_ifname_set; // false; 253 setAddr(byte addr[])254 void setAddr(byte addr[]) { 255 if (addr.length == INADDRSZ) { // normal IPv6 address 256 System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ); 257 } 258 } 259 init(byte addr[], int scope_id)260 void init(byte addr[], int scope_id) { 261 setAddr(addr); 262 263 // Android-changed: was >= 0. 264 if (scope_id > 0) { 265 this.scope_id = scope_id; 266 this.scope_id_set = true; 267 } 268 } 269 init(byte addr[], NetworkInterface nif)270 void init(byte addr[], NetworkInterface nif) 271 throws UnknownHostException 272 { 273 setAddr(addr); 274 275 if (nif != null) { 276 this.scope_id = deriveNumericScope(ipaddress, nif); 277 this.scope_id_set = true; 278 this.scope_ifname = nif; 279 this.scope_ifname_set = true; 280 } 281 } 282 283 // Android-removed: getnameinfo returns smarter representations than getHostAddress(). 284 /* 285 String getHostAddress() { 286 String s = numericToTextFormat(ipaddress); 287 if (scope_ifname != null) { // must check this first 288 s = s + "%" + scope_ifname.getName(); 289 } else if (scope_id_set) { 290 s = s + "%" + scope_id; 291 } 292 return s; 293 } 294 */ 295 equals(Object o)296 public boolean equals(Object o) { 297 if (! (o instanceof Inet6AddressHolder)) { 298 return false; 299 } 300 Inet6AddressHolder that = (Inet6AddressHolder)o; 301 302 return Arrays.equals(this.ipaddress, that.ipaddress); 303 } 304 hashCode()305 public int hashCode() { 306 if (ipaddress != null) { 307 308 int hash = 0; 309 int i=0; 310 while (i<INADDRSZ) { 311 int j=0; 312 int component=0; 313 while (j<4 && i<INADDRSZ) { 314 component = (component << 8) + ipaddress[i]; 315 j++; 316 i++; 317 } 318 hash += component; 319 } 320 return hash; 321 322 } else { 323 return 0; 324 } 325 } 326 isIPv4CompatibleAddress()327 boolean isIPv4CompatibleAddress() { 328 if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) && 329 (ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) && 330 (ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) && 331 (ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) && 332 (ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) && 333 (ipaddress[10] == 0x00) && (ipaddress[11] == 0x00)) { 334 return true; 335 } 336 return false; 337 } 338 isMulticastAddress()339 boolean isMulticastAddress() { 340 return ((ipaddress[0] & 0xff) == 0xff); 341 } 342 isAnyLocalAddress()343 boolean isAnyLocalAddress() { 344 byte test = 0x00; 345 for (int i = 0; i < INADDRSZ; i++) { 346 test |= ipaddress[i]; 347 } 348 return (test == 0x00); 349 } 350 isLoopbackAddress()351 boolean isLoopbackAddress() { 352 byte test = 0x00; 353 for (int i = 0; i < 15; i++) { 354 test |= ipaddress[i]; 355 } 356 return (test == 0x00) && (ipaddress[15] == 0x01); 357 } 358 isLinkLocalAddress()359 boolean isLinkLocalAddress() { 360 return ((ipaddress[0] & 0xff) == 0xfe 361 && (ipaddress[1] & 0xc0) == 0x80); 362 } 363 364 isSiteLocalAddress()365 boolean isSiteLocalAddress() { 366 return ((ipaddress[0] & 0xff) == 0xfe 367 && (ipaddress[1] & 0xc0) == 0xc0); 368 } 369 isMCGlobal()370 boolean isMCGlobal() { 371 return ((ipaddress[0] & 0xff) == 0xff 372 && (ipaddress[1] & 0x0f) == 0x0e); 373 } 374 isMCNodeLocal()375 boolean isMCNodeLocal() { 376 return ((ipaddress[0] & 0xff) == 0xff 377 && (ipaddress[1] & 0x0f) == 0x01); 378 } 379 isMCLinkLocal()380 boolean isMCLinkLocal() { 381 return ((ipaddress[0] & 0xff) == 0xff 382 && (ipaddress[1] & 0x0f) == 0x02); 383 } 384 isMCSiteLocal()385 boolean isMCSiteLocal() { 386 return ((ipaddress[0] & 0xff) == 0xff 387 && (ipaddress[1] & 0x0f) == 0x05); 388 } 389 isMCOrgLocal()390 boolean isMCOrgLocal() { 391 return ((ipaddress[0] & 0xff) == 0xff 392 && (ipaddress[1] & 0x0f) == 0x08); 393 } 394 } 395 396 private final transient Inet6AddressHolder holder6; 397 398 private static final long serialVersionUID = 6880410070516793377L; 399 400 // BEGIN Android-removed: Android doesn't need to call native init. 401 /* 402 // Perform native initialization 403 static { init(); } 404 // END Android-removed: Android doesn't need to call native init. 405 */ 406 Inet6Address()407 Inet6Address() { 408 super(); 409 holder.init(null, AF_INET6); 410 holder6 = new Inet6AddressHolder(); 411 } 412 413 /* checking of value for scope_id should be done by caller 414 * scope_id must be >= 0, or -1 to indicate not being set 415 */ Inet6Address(String hostName, byte addr[], int scope_id)416 Inet6Address(String hostName, byte addr[], int scope_id) { 417 holder.init(hostName, AF_INET6); 418 holder6 = new Inet6AddressHolder(); 419 holder6.init(addr, scope_id); 420 } 421 Inet6Address(String hostName, byte addr[])422 Inet6Address(String hostName, byte addr[]) { 423 holder6 = new Inet6AddressHolder(); 424 try { 425 initif (hostName, addr, null); 426 } catch (UnknownHostException e) {} /* cant happen if ifname is null */ 427 } 428 Inet6Address(String hostName, byte addr[], NetworkInterface nif)429 Inet6Address (String hostName, byte addr[], NetworkInterface nif) 430 throws UnknownHostException 431 { 432 holder6 = new Inet6AddressHolder(); 433 initif (hostName, addr, nif); 434 } 435 Inet6Address(String hostName, byte addr[], String ifname)436 Inet6Address (String hostName, byte addr[], String ifname) 437 throws UnknownHostException 438 { 439 holder6 = new Inet6AddressHolder(); 440 initstr (hostName, addr, ifname); 441 } 442 443 /** 444 * Create an Inet6Address in the exact manner of {@link 445 * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is 446 * set to the value corresponding to the given interface for the address 447 * type specified in {@code addr}. The call will fail with an 448 * UnknownHostException if the given interface does not have a numeric 449 * scope_id assigned for the given address type (eg. link-local or site-local). 450 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6 451 * scoped addresses. 452 * 453 * @param host the specified host 454 * @param addr the raw IP address in network byte order 455 * @param nif an interface this address must be associated with. 456 * @return an Inet6Address object created from the raw IP address. 457 * @throws UnknownHostException 458 * if IP address is of illegal length, or if the interface does not 459 * have a numeric scope_id assigned for the given address type. 460 * 461 * @since 1.5 462 */ getByAddress(String host, byte[] addr, NetworkInterface nif)463 public static Inet6Address getByAddress(String host, byte[] addr, 464 NetworkInterface nif) 465 throws UnknownHostException 466 { 467 if (host != null && host.length() > 0 && host.charAt(0) == '[') { 468 if (host.charAt(host.length()-1) == ']') { 469 host = host.substring(1, host.length() -1); 470 } 471 } 472 if (addr != null) { 473 if (addr.length == Inet6Address.INADDRSZ) { 474 return new Inet6Address(host, addr, nif); 475 } 476 } 477 throw new UnknownHostException("addr is of illegal length"); 478 } 479 480 /** 481 * Create an Inet6Address in the exact manner of {@link 482 * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is 483 * set to the given numeric value. The scope_id is not checked to determine 484 * if it corresponds to any interface on the system. 485 * See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6 486 * scoped addresses. 487 * 488 * @param host the specified host 489 * @param addr the raw IP address in network byte order 490 * @param scope_id the numeric scope_id for the address. 491 * @return an Inet6Address object created from the raw IP address. 492 * @throws UnknownHostException if IP address is of illegal length. 493 * 494 * @since 1.5 495 */ getByAddress(String host, byte[] addr, int scope_id)496 public static Inet6Address getByAddress(String host, byte[] addr, 497 int scope_id) 498 throws UnknownHostException 499 { 500 if (host != null && host.length() > 0 && host.charAt(0) == '[') { 501 if (host.charAt(host.length()-1) == ']') { 502 host = host.substring(1, host.length() -1); 503 } 504 } 505 if (addr != null) { 506 if (addr.length == Inet6Address.INADDRSZ) { 507 return new Inet6Address(host, addr, scope_id); 508 } 509 } 510 throw new UnknownHostException("addr is of illegal length"); 511 } 512 initstr(String hostName, byte addr[], String ifname)513 private void initstr(String hostName, byte addr[], String ifname) 514 throws UnknownHostException 515 { 516 try { 517 NetworkInterface nif = NetworkInterface.getByName (ifname); 518 if (nif == null) { 519 throw new UnknownHostException ("no such interface " + ifname); 520 } 521 initif (hostName, addr, nif); 522 } catch (SocketException e) { 523 throw new UnknownHostException ("SocketException thrown" + ifname); 524 } 525 } 526 initif(String hostName, byte addr[], NetworkInterface nif)527 private void initif(String hostName, byte addr[], NetworkInterface nif) 528 throws UnknownHostException 529 { 530 int family = -1; 531 holder6.init(addr, nif); 532 533 if (addr.length == INADDRSZ) { // normal IPv6 address 534 family = AF_INET6; 535 } 536 holder.init(hostName, family); 537 } 538 539 /* check the two Ipv6 addresses and return false if they are both 540 * non global address types, but not the same. 541 * (ie. one is sitelocal and the other linklocal) 542 * return true otherwise. 543 */ 544 isDifferentLocalAddressType( byte[] thisAddr, byte[] otherAddr)545 private static boolean isDifferentLocalAddressType( 546 byte[] thisAddr, byte[] otherAddr) { 547 548 if (Inet6Address.isLinkLocalAddress(thisAddr) && 549 !Inet6Address.isLinkLocalAddress(otherAddr)) { 550 return false; 551 } 552 if (Inet6Address.isSiteLocalAddress(thisAddr) && 553 !Inet6Address.isSiteLocalAddress(otherAddr)) { 554 return false; 555 } 556 return true; 557 } 558 deriveNumericScope(byte[] thisAddr, NetworkInterface ifc)559 private static int deriveNumericScope (byte[] thisAddr, NetworkInterface ifc) throws UnknownHostException { 560 Enumeration<InetAddress> addresses = ifc.getInetAddresses(); 561 while (addresses.hasMoreElements()) { 562 InetAddress addr = addresses.nextElement(); 563 if (!(addr instanceof Inet6Address)) { 564 continue; 565 } 566 Inet6Address ia6_addr = (Inet6Address)addr; 567 /* check if site or link local prefixes match */ 568 if (!isDifferentLocalAddressType(thisAddr, ia6_addr.getAddress())){ 569 /* type not the same, so carry on searching */ 570 continue; 571 } 572 /* found a matching address - return its scope_id */ 573 return ia6_addr.getScopeId(); 574 } 575 throw new UnknownHostException ("no scope_id found"); 576 } 577 deriveNumericScope(String ifname)578 private int deriveNumericScope (String ifname) throws UnknownHostException { 579 Enumeration<NetworkInterface> en; 580 try { 581 en = NetworkInterface.getNetworkInterfaces(); 582 } catch (SocketException e) { 583 throw new UnknownHostException ("could not enumerate local network interfaces"); 584 } 585 while (en.hasMoreElements()) { 586 NetworkInterface ifc = en.nextElement(); 587 if (ifc.getName().equals (ifname)) { 588 return deriveNumericScope(holder6.ipaddress, ifc); 589 } 590 } 591 throw new UnknownHostException ("No matching address found for interface : " +ifname); 592 } 593 594 /** 595 * @serialField ipaddress byte[] 596 * @serialField scope_id int 597 * @serialField scope_id_set boolean 598 * @serialField scope_ifname_set boolean 599 * @serialField ifname String 600 */ 601 602 private static final ObjectStreamField[] serialPersistentFields = { 603 new ObjectStreamField("ipaddress", byte[].class), 604 new ObjectStreamField("scope_id", int.class), 605 new ObjectStreamField("scope_id_set", boolean.class), 606 new ObjectStreamField("scope_ifname_set", boolean.class), 607 new ObjectStreamField("ifname", String.class) 608 }; 609 610 private static final long FIELDS_OFFSET; 611 private static final sun.misc.Unsafe UNSAFE; 612 613 static { 614 try { 615 sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); 616 FIELDS_OFFSET = unsafe.objectFieldOffset( 617 Inet6Address.class.getDeclaredField("holder6")); 618 UNSAFE = unsafe; 619 } catch (ReflectiveOperationException e) { 620 throw new Error(e); 621 } 622 } 623 624 /** 625 * restore the state of this object from stream 626 * including the scope information, only if the 627 * scoped interface name is valid on this system 628 */ readObject(ObjectInputStream s)629 private void readObject(ObjectInputStream s) 630 throws IOException, ClassNotFoundException { 631 NetworkInterface scope_ifname = null; 632 633 // Android-changed: was getClass().getClassLoader() != null. 634 if (getClass().getClassLoader() != Class.class.getClassLoader()) { 635 throw new SecurityException ("invalid address type"); 636 } 637 638 ObjectInputStream.GetField gf = s.readFields(); 639 byte[] ipaddress = (byte[])gf.get("ipaddress", null); 640 int scope_id = (int)gf.get("scope_id", -1); 641 boolean scope_id_set = (boolean)gf.get("scope_id_set", false); 642 boolean scope_ifname_set = (boolean)gf.get("scope_ifname_set", false); 643 String ifname = (String)gf.get("ifname", null); 644 645 if (ifname != null && !"".equals (ifname)) { 646 try { 647 scope_ifname = NetworkInterface.getByName(ifname); 648 if (scope_ifname == null) { 649 /* the interface does not exist on this system, so we clear 650 * the scope information completely */ 651 scope_id_set = false; 652 scope_ifname_set = false; 653 scope_id = 0; 654 } else { 655 scope_ifname_set = true; 656 try { 657 scope_id = deriveNumericScope (ipaddress, scope_ifname); 658 } catch (UnknownHostException e) { 659 // typically should not happen, but it may be that 660 // the machine being used for deserialization has 661 // the same interface name but without IPv6 configured. 662 } 663 } 664 } catch (SocketException e) {} 665 } 666 667 /* if ifname was not supplied, then the numeric info is used */ 668 669 ipaddress = ipaddress.clone(); 670 671 // Check that our invariants are satisfied 672 if (ipaddress.length != INADDRSZ) { 673 throw new InvalidObjectException("invalid address length: "+ 674 ipaddress.length); 675 } 676 677 if (holder().getFamily() != AF_INET6) { 678 throw new InvalidObjectException("invalid address family type"); 679 } 680 681 Inet6AddressHolder h = new Inet6AddressHolder( 682 ipaddress, scope_id, scope_id_set, scope_ifname, scope_ifname_set 683 ); 684 685 UNSAFE.putObject(this, FIELDS_OFFSET, h); 686 } 687 688 /** 689 * default behavior is overridden in order to write the 690 * scope_ifname field as a String, rather than a NetworkInterface 691 * which is not serializable 692 */ writeObject(ObjectOutputStream s)693 private synchronized void writeObject(ObjectOutputStream s) 694 throws IOException 695 { 696 String ifname = null; 697 698 if (holder6.scope_ifname != null) { 699 ifname = holder6.scope_ifname.getName(); 700 holder6.scope_ifname_set = true; 701 } 702 ObjectOutputStream.PutField pfields = s.putFields(); 703 pfields.put("ipaddress", holder6.ipaddress); 704 pfields.put("scope_id", holder6.scope_id); 705 pfields.put("scope_id_set", holder6.scope_id_set); 706 pfields.put("scope_ifname_set", holder6.scope_ifname_set); 707 pfields.put("ifname", ifname); 708 s.writeFields(); 709 } 710 711 /** 712 * Utility routine to check if the InetAddress is an IP multicast 713 * address. 11111111 at the start of the address identifies the 714 * address as being a multicast address. 715 * 716 * @return a {@code boolean} indicating if the InetAddress is an IP 717 * multicast address 718 * 719 * @since JDK1.1 720 */ 721 @Override isMulticastAddress()722 public boolean isMulticastAddress() { 723 return holder6.isMulticastAddress(); 724 } 725 726 /** 727 * Utility routine to check if the InetAddress in a wildcard address. 728 * 729 * @return a {@code boolean} indicating if the Inetaddress is 730 * a wildcard address. 731 * 732 * @since 1.4 733 */ 734 @Override isAnyLocalAddress()735 public boolean isAnyLocalAddress() { 736 return holder6.isAnyLocalAddress(); 737 } 738 739 /** 740 * Utility routine to check if the InetAddress is a loopback address. 741 * 742 * @return a {@code boolean} indicating if the InetAddress is a loopback 743 * address; or false otherwise. 744 * 745 * @since 1.4 746 */ 747 @Override isLoopbackAddress()748 public boolean isLoopbackAddress() { 749 return holder6.isLoopbackAddress(); 750 } 751 752 /** 753 * Utility routine to check if the InetAddress is an link local address. 754 * 755 * @return a {@code boolean} indicating if the InetAddress is a link local 756 * address; or false if address is not a link local unicast address. 757 * 758 * @since 1.4 759 */ 760 @Override isLinkLocalAddress()761 public boolean isLinkLocalAddress() { 762 return holder6.isLinkLocalAddress(); 763 } 764 765 /* static version of above */ isLinkLocalAddress(byte[] ipaddress)766 static boolean isLinkLocalAddress(byte[] ipaddress) { 767 return ((ipaddress[0] & 0xff) == 0xfe 768 && (ipaddress[1] & 0xc0) == 0x80); 769 } 770 771 /** 772 * Utility routine to check if the InetAddress is a site local address. 773 * 774 * @return a {@code boolean} indicating if the InetAddress is a site local 775 * address; or false if address is not a site local unicast address. 776 * 777 * @since 1.4 778 */ 779 @Override isSiteLocalAddress()780 public boolean isSiteLocalAddress() { 781 return holder6.isSiteLocalAddress(); 782 } 783 784 /* static version of above */ isSiteLocalAddress(byte[] ipaddress)785 static boolean isSiteLocalAddress(byte[] ipaddress) { 786 return ((ipaddress[0] & 0xff) == 0xfe 787 && (ipaddress[1] & 0xc0) == 0xc0); 788 } 789 790 /** 791 * Utility routine to check if the multicast address has global scope. 792 * 793 * @return a {@code boolean} indicating if the address has is a multicast 794 * address of global scope, false if it is not of global scope or 795 * it is not a multicast address 796 * 797 * @since 1.4 798 */ 799 @Override isMCGlobal()800 public boolean isMCGlobal() { 801 return holder6.isMCGlobal(); 802 } 803 804 /** 805 * Utility routine to check if the multicast address has node scope. 806 * 807 * @return a {@code boolean} indicating if the address has is a multicast 808 * address of node-local scope, false if it is not of node-local 809 * scope or it is not a multicast address 810 * 811 * @since 1.4 812 */ 813 @Override isMCNodeLocal()814 public boolean isMCNodeLocal() { 815 return holder6.isMCNodeLocal(); 816 } 817 818 /** 819 * Utility routine to check if the multicast address has link scope. 820 * 821 * @return a {@code boolean} indicating if the address has is a multicast 822 * address of link-local scope, false if it is not of link-local 823 * scope or it is not a multicast address 824 * 825 * @since 1.4 826 */ 827 @Override isMCLinkLocal()828 public boolean isMCLinkLocal() { 829 return holder6.isMCLinkLocal(); 830 } 831 832 /** 833 * Utility routine to check if the multicast address has site scope. 834 * 835 * @return a {@code boolean} indicating if the address has is a multicast 836 * address of site-local scope, false if it is not of site-local 837 * scope or it is not a multicast address 838 * 839 * @since 1.4 840 */ 841 @Override isMCSiteLocal()842 public boolean isMCSiteLocal() { 843 return holder6.isMCSiteLocal(); 844 } 845 846 /** 847 * Utility routine to check if the multicast address has organization scope. 848 * 849 * @return a {@code boolean} indicating if the address has is a multicast 850 * address of organization-local scope, false if it is not of 851 * organization-local scope or it is not a multicast address 852 * 853 * @since 1.4 854 */ 855 @Override isMCOrgLocal()856 public boolean isMCOrgLocal() { 857 return holder6.isMCOrgLocal(); 858 } 859 /** 860 * Returns the raw IP address of this {@code InetAddress} object. The result 861 * is in network byte order: the highest order byte of the address is in 862 * {@code getAddress()[0]}. 863 * 864 * @return the raw IP address of this object. 865 */ 866 @Override getAddress()867 public byte[] getAddress() { 868 return holder6.ipaddress.clone(); 869 } 870 871 /** 872 * Returns the numeric scopeId, if this instance is associated with 873 * an interface. If no scoped_id is set, the returned value is zero. 874 * 875 * @return the scopeId, or zero if not set. 876 * 877 * @since 1.5 878 */ getScopeId()879 public int getScopeId() { 880 return holder6.scope_id; 881 } 882 883 /** 884 * Returns the scoped interface, if this instance was created with 885 * with a scoped interface. 886 * 887 * @return the scoped interface, or null if not set. 888 * @since 1.5 889 */ getScopedInterface()890 public NetworkInterface getScopedInterface() { 891 return holder6.scope_ifname; 892 } 893 894 /** 895 * Returns the IP address string in textual presentation. If the instance 896 * was created specifying a scope identifier then the scope id is appended 897 * to the IP address preceded by a "%" (per-cent) character. This can be 898 * either a numeric value or a string, depending on which was used to create 899 * the instance. 900 * 901 * @return the raw IP address in a string format. 902 */ 903 @Override getHostAddress()904 public String getHostAddress() { 905 // Android-changed: getnameinfo returns smarter representations than getHostAddress(). 906 // return holder6.getHostAddress(); 907 return Libcore.os.getnameinfo(this, NI_NUMERICHOST); // Can't throw. 908 } 909 910 /** 911 * Returns a hashcode for this IP address. 912 * 913 * @return a hash code value for this IP address. 914 */ 915 @Override hashCode()916 public int hashCode() { 917 return holder6.hashCode(); 918 } 919 920 /** 921 * Compares this object against the specified object. The result is {@code 922 * true} if and only if the argument is not {@code null} and it represents 923 * the same IP address as this object. 924 * 925 * <p> Two instances of {@code InetAddress} represent the same IP address 926 * if the length of the byte arrays returned by {@code getAddress} is the 927 * same for both, and each of the array components is the same for the byte 928 * arrays. 929 * 930 * @param obj the object to compare against. 931 * 932 * @return {@code true} if the objects are the same; {@code false} otherwise. 933 * 934 * @see java.net.InetAddress#getAddress() 935 */ 936 @Override equals(Object obj)937 public boolean equals(Object obj) { 938 if (obj == null || !(obj instanceof Inet6Address)) 939 return false; 940 941 Inet6Address inetAddr = (Inet6Address)obj; 942 943 return holder6.equals(inetAddr.holder6); 944 } 945 946 /** 947 * Utility routine to check if the InetAddress is an 948 * IPv4 compatible IPv6 address. 949 * 950 * @return a {@code boolean} indicating if the InetAddress is an IPv4 951 * compatible IPv6 address; or false if address is IPv4 address. 952 * 953 * @since 1.4 954 */ isIPv4CompatibleAddress()955 public boolean isIPv4CompatibleAddress() { 956 return holder6.isIPv4CompatibleAddress(); 957 } 958 959 // Utilities 960 private final static int INT16SZ = 2; 961 962 /* 963 * Convert IPv6 binary address into presentation (printable) format. 964 * 965 * @param src a byte array representing the IPv6 numeric address 966 * @return a String representing an IPv6 address in 967 * textual representation format 968 * @since 1.4 969 */ numericToTextFormat(byte[] src)970 static String numericToTextFormat(byte[] src) { 971 StringBuilder sb = new StringBuilder(39); 972 for (int i = 0; i < (INADDRSZ / INT16SZ); i++) { 973 sb.append(Integer.toHexString(((src[i<<1]<<8) & 0xff00) 974 | (src[(i<<1)+1] & 0xff))); 975 if (i < (INADDRSZ / INT16SZ) -1 ) { 976 sb.append(":"); 977 } 978 } 979 return sb.toString(); 980 } 981 982 // BEGIN Android-removed: Android doesn't need to call native init. 983 /* 984 * Perform class load-time initializations. 985 * 986 private static native void init(); 987 */ 988 // END Android-removed: Android doesn't need to call native init. 989 } 990