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