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