1 /* 2 * Copyright (c) 1995, 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.util.NavigableSet; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.ArrayList; 32 import java.util.ServiceLoader; 33 import java.security.AccessController; 34 import java.io.ObjectStreamException; 35 import java.io.ObjectStreamField; 36 import java.io.IOException; 37 import java.io.ObjectInputStream; 38 import java.io.ObjectInputStream.GetField; 39 import java.io.ObjectOutputStream; 40 import java.io.ObjectOutputStream.PutField; 41 import java.util.concurrent.ConcurrentHashMap; 42 import java.util.concurrent.ConcurrentMap; 43 import java.util.concurrent.ConcurrentSkipListSet; 44 import java.util.concurrent.atomic.AtomicLong; 45 46 import sun.security.action.*; 47 import sun.net.InetAddressCachePolicy; 48 import sun.net.util.IPAddressUtil; 49 import sun.net.spi.nameservice.*; 50 51 /** 52 * This class represents an Internet Protocol (IP) address. 53 * 54 * <p> An IP address is either a 32-bit or 128-bit unsigned number 55 * used by IP, a lower-level protocol on which protocols like UDP and 56 * TCP are built. The IP address architecture is defined by <a 57 * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC 790: 58 * Assigned Numbers</i></a>, <a 59 * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC 1918: 60 * Address Allocation for Private Internets</i></a>, <a 61 * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365: 62 * Administratively Scoped IP Multicast</i></a>, and <a 63 * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 2373: IP 64 * Version 6 Addressing Architecture</i></a>. An instance of an 65 * InetAddress consists of an IP address and possibly its 66 * corresponding host name (depending on whether it is constructed 67 * with a host name or whether it has already done reverse host name 68 * resolution). 69 * 70 * <h3> Address types </h3> 71 * 72 * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types"> 73 * <tr><th valign=top><i>unicast</i></th> 74 * <td>An identifier for a single interface. A packet sent to 75 * a unicast address is delivered to the interface identified by 76 * that address. 77 * 78 * <p> The Unspecified Address -- Also called anylocal or wildcard 79 * address. It must never be assigned to any node. It indicates the 80 * absence of an address. One example of its use is as the target of 81 * bind, which allows a server to accept a client connection on any 82 * interface, in case the server host has multiple interfaces. 83 * 84 * <p> The <i>unspecified</i> address must not be used as 85 * the destination address of an IP packet. 86 * 87 * <p> The <i>Loopback</i> Addresses -- This is the address 88 * assigned to the loopback interface. Anything sent to this 89 * IP address loops around and becomes IP input on the local 90 * host. This address is often used when testing a 91 * client.</td></tr> 92 * <tr><th valign=top><i>multicast</i></th> 93 * <td>An identifier for a set of interfaces (typically belonging 94 * to different nodes). A packet sent to a multicast address is 95 * delivered to all interfaces identified by that address.</td></tr> 96 * </table></blockquote> 97 * 98 * <h4> IP address scope </h4> 99 * 100 * <p> <i>Link-local</i> addresses are designed to be used for addressing 101 * on a single link for purposes such as auto-address configuration, 102 * neighbor discovery, or when no routers are present. 103 * 104 * <p> <i>Site-local</i> addresses are designed to be used for addressing 105 * inside of a site without the need for a global prefix. 106 * 107 * <p> <i>Global</i> addresses are unique across the internet. 108 * 109 * <h4> Textual representation of IP addresses </h4> 110 * 111 * The textual representation of an IP address is address family specific. 112 * 113 * <p> 114 * 115 * For IPv4 address format, please refer to <A 116 * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6 117 * address format, please refer to <A 118 * HREF="Inet6Address.html#format">Inet6Address#format</A>. 119 * 120 * <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of 121 * System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P> 122 * 123 * <h4> Host Name Resolution </h4> 124 * 125 * Host name-to-IP address <i>resolution</i> is accomplished through 126 * the use of a combination of local machine configuration information 127 * and network naming services such as the Domain Name System (DNS) 128 * and Network Information Service(NIS). The particular naming 129 * services(s) being used is by default the local machine configured 130 * one. For any host name, its corresponding IP address is returned. 131 * 132 * <p> <i>Reverse name resolution</i> means that for any IP address, 133 * the host associated with the IP address is returned. 134 * 135 * <p> The InetAddress class provides methods to resolve host names to 136 * their IP addresses and vice versa. 137 * 138 * <h4> InetAddress Caching </h4> 139 * 140 * The InetAddress class has a cache to store successful as well as 141 * unsuccessful host name resolutions. 142 * 143 * <p> By default, when a security manager is installed, in order to 144 * protect against DNS spoofing attacks, 145 * the result of positive host name resolutions are 146 * cached forever. When a security manager is not installed, the default 147 * behavior is to cache entries for a finite (implementation dependent) 148 * period of time. The result of unsuccessful host 149 * name resolution is cached for a very short period of time (10 150 * seconds) to improve performance. 151 * 152 * <p> If the default behavior is not desired, then a Java security property 153 * can be set to a different Time-to-live (TTL) value for positive 154 * caching. Likewise, a system admin can configure a different 155 * negative caching TTL value when needed. 156 * 157 * <p> Two Java security properties control the TTL values used for 158 * positive and negative host name resolution caching: 159 * 160 * <blockquote> 161 * <dl> 162 * <dt><b>networkaddress.cache.ttl</b></dt> 163 * <dd>Indicates the caching policy for successful name lookups from 164 * the name service. The value is specified as an integer to indicate 165 * the number of seconds to cache the successful lookup. The default 166 * setting is to cache for an implementation specific period of time. 167 * <p> 168 * A value of -1 indicates "cache forever". 169 * </dd> 170 * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt> 171 * <dd>Indicates the caching policy for un-successful name lookups 172 * from the name service. The value is specified as an integer to 173 * indicate the number of seconds to cache the failure for 174 * un-successful lookups. 175 * <p> 176 * A value of 0 indicates "never cache". 177 * A value of -1 indicates "cache forever". 178 * </dd> 179 * </dl> 180 * </blockquote> 181 * 182 * @author Chris Warth 183 * @see java.net.InetAddress#getByAddress(byte[]) 184 * @see java.net.InetAddress#getByAddress(java.lang.String, byte[]) 185 * @see java.net.InetAddress#getAllByName(java.lang.String) 186 * @see java.net.InetAddress#getByName(java.lang.String) 187 * @see java.net.InetAddress#getLocalHost() 188 * @since 1.0 189 */ 190 public 191 class InetAddress implements java.io.Serializable { 192 /** 193 * Specify the address family: Internet Protocol, Version 4 194 * @since 1.4 195 */ 196 static final int IPv4 = 1; 197 198 /** 199 * Specify the address family: Internet Protocol, Version 6 200 * @since 1.4 201 */ 202 static final int IPv6 = 2; 203 204 /* Specify address family preference */ 205 static transient boolean preferIPv6Address = false; 206 207 static class InetAddressHolder { 208 209 InetAddressHolder() {} 210 211 InetAddressHolder(String hostName, int address, int family) { 212 this.hostName = hostName; 213 this.address = address; 214 this.family = family; 215 } 216 217 void init(String hostName, int family) { 218 this.hostName = hostName; 219 if (family != -1) { 220 this.family = family; 221 } 222 } 223 224 String hostName; 225 226 String getHostName() { 227 return hostName; 228 } 229 230 /** 231 * Holds a 32-bit IPv4 address. 232 */ 233 int address; 234 235 int getAddress() { 236 return address; 237 } 238 239 /** 240 * Specifies the address family type, for instance, '1' for IPv4 241 * addresses, and '2' for IPv6 addresses. 242 */ 243 int family; 244 245 int getFamily() { 246 return family; 247 } 248 } 249 250 /* Used to store the serializable fields of InetAddress */ 251 final transient InetAddressHolder holder; 252 253 InetAddressHolder holder() { 254 return holder; 255 } 256 257 /* Used to store the name service provider */ 258 private static List<NameService> nameServices = null; 259 260 /* Used to store the best available hostname */ 261 private transient String canonicalHostName = null; 262 263 /** use serialVersionUID from JDK 1.0.2 for interoperability */ 264 private static final long serialVersionUID = 3286316764910316507L; 265 266 /* 267 * Load net library into runtime, and perform initializations. 268 */ 269 static { 270 preferIPv6Address = java.security.AccessController.doPrivileged( 271 new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); 272 AccessController.doPrivileged( 273 new java.security.PrivilegedAction<Void>() { 274 public Void run() { 275 System.loadLibrary("net"); 276 return null; 277 } 278 }); 279 init(); 280 } 281 282 /** 283 * Constructor for the Socket.accept() method. 284 * This creates an empty InetAddress, which is filled in by 285 * the accept() method. This InetAddress, however, is not 286 * put in the address cache, since it is not created by name. 287 */ 288 InetAddress() { 289 holder = new InetAddressHolder(); 290 } 291 292 /** 293 * Replaces the de-serialized object with an Inet4Address object. 294 * 295 * @return the alternate object to the de-serialized object. 296 * 297 * @throws ObjectStreamException if a new object replacing this 298 * object could not be created 299 */ 300 private Object readResolve() throws ObjectStreamException { 301 // will replace the deserialized 'this' object 302 return new Inet4Address(holder().getHostName(), holder().getAddress()); 303 } 304 305 /** 306 * Utility routine to check if the InetAddress is an 307 * IP multicast address. 308 * @return a {@code boolean} indicating if the InetAddress is 309 * an IP multicast address 310 * @since 1.1 311 */ 312 public boolean isMulticastAddress() { 313 return false; 314 } 315 316 /** 317 * Utility routine to check if the InetAddress in a wildcard address. 318 * @return a {@code boolean} indicating if the Inetaddress is 319 * a wildcard address. 320 * @since 1.4 321 */ 322 public boolean isAnyLocalAddress() { 323 return false; 324 } 325 326 /** 327 * Utility routine to check if the InetAddress is a loopback address. 328 * 329 * @return a {@code boolean} indicating if the InetAddress is 330 * a loopback address; or false otherwise. 331 * @since 1.4 332 */ 333 public boolean isLoopbackAddress() { 334 return false; 335 } 336 337 /** 338 * Utility routine to check if the InetAddress is an link local address. 339 * 340 * @return a {@code boolean} indicating if the InetAddress is 341 * a link local address; or false if address is not a link local unicast address. 342 * @since 1.4 343 */ 344 public boolean isLinkLocalAddress() { 345 return false; 346 } 347 348 /** 349 * Utility routine to check if the InetAddress is a site local address. 350 * 351 * @return a {@code boolean} indicating if the InetAddress is 352 * a site local address; or false if address is not a site local unicast address. 353 * @since 1.4 354 */ 355 public boolean isSiteLocalAddress() { 356 return false; 357 } 358 359 /** 360 * Utility routine to check if the multicast address has global scope. 361 * 362 * @return a {@code boolean} indicating if the address has 363 * is a multicast address of global scope, false if it is not 364 * of global scope or it is not a multicast address 365 * @since 1.4 366 */ 367 public boolean isMCGlobal() { 368 return false; 369 } 370 371 /** 372 * Utility routine to check if the multicast address has node scope. 373 * 374 * @return a {@code boolean} indicating if the address has 375 * is a multicast address of node-local scope, false if it is not 376 * of node-local scope or it is not a multicast address 377 * @since 1.4 378 */ 379 public boolean isMCNodeLocal() { 380 return false; 381 } 382 383 /** 384 * Utility routine to check if the multicast address has link scope. 385 * 386 * @return a {@code boolean} indicating if the address has 387 * is a multicast address of link-local scope, false if it is not 388 * of link-local scope or it is not a multicast address 389 * @since 1.4 390 */ 391 public boolean isMCLinkLocal() { 392 return false; 393 } 394 395 /** 396 * Utility routine to check if the multicast address has site scope. 397 * 398 * @return a {@code boolean} indicating if the address has 399 * is a multicast address of site-local scope, false if it is not 400 * of site-local scope or it is not a multicast address 401 * @since 1.4 402 */ 403 public boolean isMCSiteLocal() { 404 return false; 405 } 406 407 /** 408 * Utility routine to check if the multicast address has organization scope. 409 * 410 * @return a {@code boolean} indicating if the address has 411 * is a multicast address of organization-local scope, 412 * false if it is not of organization-local scope 413 * or it is not a multicast address 414 * @since 1.4 415 */ 416 public boolean isMCOrgLocal() { 417 return false; 418 } 419 420 421 /** 422 * Test whether that address is reachable. Best effort is made by the 423 * implementation to try to reach the host, but firewalls and server 424 * configuration may block requests resulting in a unreachable status 425 * while some specific ports may be accessible. 426 * A typical implementation will use ICMP ECHO REQUESTs if the 427 * privilege can be obtained, otherwise it will try to establish 428 * a TCP connection on port 7 (Echo) of the destination host. 429 * <p> 430 * The timeout value, in milliseconds, indicates the maximum amount of time 431 * the try should take. If the operation times out before getting an 432 * answer, the host is deemed unreachable. A negative value will result 433 * in an IllegalArgumentException being thrown. 434 * 435 * @param timeout the time, in milliseconds, before the call aborts 436 * @return a {@code boolean} indicating if the address is reachable. 437 * @throws IOException if a network error occurs 438 * @throws IllegalArgumentException if {@code timeout} is negative. 439 * @since 1.5 440 */ 441 public boolean isReachable(int timeout) throws IOException { 442 return isReachable(null, 0 , timeout); 443 } 444 445 /** 446 * Test whether that address is reachable. Best effort is made by the 447 * implementation to try to reach the host, but firewalls and server 448 * configuration may block requests resulting in a unreachable status 449 * while some specific ports may be accessible. 450 * A typical implementation will use ICMP ECHO REQUESTs if the 451 * privilege can be obtained, otherwise it will try to establish 452 * a TCP connection on port 7 (Echo) of the destination host. 453 * <p> 454 * The {@code network interface} and {@code ttl} parameters 455 * let the caller specify which network interface the test will go through 456 * and the maximum number of hops the packets should go through. 457 * A negative value for the {@code ttl} will result in an 458 * IllegalArgumentException being thrown. 459 * <p> 460 * The timeout value, in milliseconds, indicates the maximum amount of time 461 * the try should take. If the operation times out before getting an 462 * answer, the host is deemed unreachable. A negative value will result 463 * in an IllegalArgumentException being thrown. 464 * 465 * @param netif the NetworkInterface through which the 466 * test will be done, or null for any interface 467 * @param ttl the maximum numbers of hops to try or 0 for the 468 * default 469 * @param timeout the time, in milliseconds, before the call aborts 470 * @throws IllegalArgumentException if either {@code timeout} 471 * or {@code ttl} are negative. 472 * @return a {@code boolean}indicating if the address is reachable. 473 * @throws IOException if a network error occurs 474 * @since 1.5 475 */ 476 public boolean isReachable(NetworkInterface netif, int ttl, 477 int timeout) throws IOException { 478 if (ttl < 0) 479 throw new IllegalArgumentException("ttl can't be negative"); 480 if (timeout < 0) 481 throw new IllegalArgumentException("timeout can't be negative"); 482 483 return impl.isReachable(this, timeout, netif, ttl); 484 } 485 486 /** 487 * Gets the host name for this IP address. 488 * 489 * <p>If this InetAddress was created with a host name, 490 * this host name will be remembered and returned; 491 * otherwise, a reverse name lookup will be performed 492 * and the result will be returned based on the system 493 * configured name lookup service. If a lookup of the name service 494 * is required, call 495 * {@link #getCanonicalHostName() getCanonicalHostName}. 496 * 497 * <p>If there is a security manager, its 498 * {@code checkConnect} method is first called 499 * with the hostname and {@code -1} 500 * as its arguments to see if the operation is allowed. 501 * If the operation is not allowed, it will return 502 * the textual representation of the IP address. 503 * 504 * @return the host name for this IP address, or if the operation 505 * is not allowed by the security check, the textual 506 * representation of the IP address. 507 * 508 * @see InetAddress#getCanonicalHostName 509 * @see SecurityManager#checkConnect 510 */ 511 public String getHostName() { 512 return getHostName(true); 513 } 514 515 /** 516 * Returns the hostname for this address. 517 * If the host is equal to null, then this address refers to any 518 * of the local machine's available network addresses. 519 * this is package private so SocketPermission can make calls into 520 * here without a security check. 521 * 522 * <p>If there is a security manager, this method first 523 * calls its {@code checkConnect} method 524 * with the hostname and {@code -1} 525 * as its arguments to see if the calling code is allowed to know 526 * the hostname for this IP address, i.e., to connect to the host. 527 * If the operation is not allowed, it will return 528 * the textual representation of the IP address. 529 * 530 * @return the host name for this IP address, or if the operation 531 * is not allowed by the security check, the textual 532 * representation of the IP address. 533 * 534 * @param check make security check if true 535 * 536 * @see SecurityManager#checkConnect 537 */ 538 String getHostName(boolean check) { 539 if (holder().getHostName() == null) { 540 holder().hostName = InetAddress.getHostFromNameService(this, check); 541 } 542 return holder().getHostName(); 543 } 544 545 /** 546 * Gets the fully qualified domain name for this IP address. 547 * Best effort method, meaning we may not be able to return 548 * the FQDN depending on the underlying system configuration. 549 * 550 * <p>If there is a security manager, this method first 551 * calls its {@code checkConnect} method 552 * with the hostname and {@code -1} 553 * as its arguments to see if the calling code is allowed to know 554 * the hostname for this IP address, i.e., to connect to the host. 555 * If the operation is not allowed, it will return 556 * the textual representation of the IP address. 557 * 558 * @return the fully qualified domain name for this IP address, 559 * or if the operation is not allowed by the security check, 560 * the textual representation of the IP address. 561 * 562 * @see SecurityManager#checkConnect 563 * 564 * @since 1.4 565 */ 566 public String getCanonicalHostName() { 567 if (canonicalHostName == null) { 568 canonicalHostName = 569 InetAddress.getHostFromNameService(this, true); 570 } 571 return canonicalHostName; 572 } 573 574 /** 575 * Returns the hostname for this address. 576 * 577 * <p>If there is a security manager, this method first 578 * calls its {@code checkConnect} method 579 * with the hostname and {@code -1} 580 * as its arguments to see if the calling code is allowed to know 581 * the hostname for this IP address, i.e., to connect to the host. 582 * If the operation is not allowed, it will return 583 * the textual representation of the IP address. 584 * 585 * @return the host name for this IP address, or if the operation 586 * is not allowed by the security check, the textual 587 * representation of the IP address. 588 * 589 * @param check make security check if true 590 * 591 * @see SecurityManager#checkConnect 592 */ 593 private static String getHostFromNameService(InetAddress addr, boolean check) { 594 String host = null; 595 for (NameService nameService : nameServices) { 596 try { 597 // first lookup the hostname 598 host = nameService.getHostByAddr(addr.getAddress()); 599 600 /* check to see if calling code is allowed to know 601 * the hostname for this IP address, ie, connect to the host 602 */ 603 if (check) { 604 SecurityManager sec = System.getSecurityManager(); 605 if (sec != null) { 606 sec.checkConnect(host, -1); 607 } 608 } 609 610 /* now get all the IP addresses for this hostname, 611 * and make sure one of them matches the original IP 612 * address. We do this to try and prevent spoofing. 613 */ 614 615 InetAddress[] arr = InetAddress.getAllByName0(host, check); 616 boolean ok = false; 617 618 if(arr != null) { 619 for(int i = 0; !ok && i < arr.length; i++) { 620 ok = addr.equals(arr[i]); 621 } 622 } 623 624 //XXX: if it looks a spoof just return the address? 625 if (!ok) { 626 host = addr.getHostAddress(); 627 return host; 628 } 629 630 break; 631 632 } catch (SecurityException e) { 633 host = addr.getHostAddress(); 634 break; 635 } catch (UnknownHostException e) { 636 host = addr.getHostAddress(); 637 // let next provider resolve the hostname 638 } 639 } 640 641 return host; 642 } 643 644 /** 645 * Returns the raw IP address of this {@code InetAddress} 646 * object. The result is in network byte order: the highest order 647 * byte of the address is in {@code getAddress()[0]}. 648 * 649 * @return the raw IP address of this object. 650 */ 651 public byte[] getAddress() { 652 return null; 653 } 654 655 /** 656 * Returns the IP address string in textual presentation. 657 * 658 * @return the raw IP address in a string format. 659 * @since 1.0.2 660 */ 661 public String getHostAddress() { 662 return null; 663 } 664 665 /** 666 * Returns a hashcode for this IP address. 667 * 668 * @return a hash code value for this IP address. 669 */ 670 public int hashCode() { 671 return -1; 672 } 673 674 /** 675 * Compares this object against the specified object. 676 * The result is {@code true} if and only if the argument is 677 * not {@code null} and it represents the same IP address as 678 * this object. 679 * <p> 680 * Two instances of {@code InetAddress} represent the same IP 681 * address if the length of the byte arrays returned by 682 * {@code getAddress} is the same for both, and each of the 683 * array components is the same for the byte arrays. 684 * 685 * @param obj the object to compare against. 686 * @return {@code true} if the objects are the same; 687 * {@code false} otherwise. 688 * @see java.net.InetAddress#getAddress() 689 */ 690 public boolean equals(Object obj) { 691 return false; 692 } 693 694 /** 695 * Converts this IP address to a {@code String}. The 696 * string returned is of the form: hostname / literal IP 697 * address. 698 * 699 * If the host name is unresolved, no reverse name service lookup 700 * is performed. The hostname part will be represented by an empty string. 701 * 702 * @return a string representation of this IP address. 703 */ 704 public String toString() { 705 String hostName = holder().getHostName(); 706 return ((hostName != null) ? hostName : "") 707 + "/" + getHostAddress(); 708 } 709 710 // mapping from host name to Addresses - either NameServiceAddresses (while 711 // still being looked-up by NameService(s)) or CachedAddresses when cached 712 private static final ConcurrentMap<String, Addresses> cache = 713 new ConcurrentHashMap<>(); 714 715 // CachedAddresses that have to expire are kept ordered in this NavigableSet 716 // which is scanned on each access 717 private static final NavigableSet<CachedAddresses> expirySet = 718 new ConcurrentSkipListSet<>(); 719 720 // common interface 721 private interface Addresses { 722 InetAddress[] get() throws UnknownHostException; 723 } 724 725 // a holder for cached addresses with required metadata 726 private static final class CachedAddresses implements Addresses, Comparable<CachedAddresses> { 727 private static final AtomicLong seq = new AtomicLong(); 728 final String host; 729 final InetAddress[] inetAddresses; 730 final long expiryTime; // time of expiry (in terms of System.nanoTime()) 731 final long id = seq.incrementAndGet(); // each instance is unique 732 733 CachedAddresses(String host, InetAddress[] inetAddresses, long expiryTime) { 734 this.host = host; 735 this.inetAddresses = inetAddresses; 736 this.expiryTime = expiryTime; 737 } 738 739 @Override 740 public InetAddress[] get() throws UnknownHostException { 741 if (inetAddresses == null) { 742 throw new UnknownHostException(host); 743 } 744 return inetAddresses; 745 } 746 747 @Override 748 public int compareTo(CachedAddresses other) { 749 // natural order is expiry time - 750 // compare difference of expiry times rather than 751 // expiry times directly, to avoid possible overflow. 752 // (see System.nanoTime() recommendations...) 753 long diff = this.expiryTime - other.expiryTime; 754 if (diff < 0L) return -1; 755 if (diff > 0L) return 1; 756 // ties are broken using unique id 757 return Long.compare(this.id, other.id); 758 } 759 } 760 761 // a name service lookup based Addresses implementation which replaces itself 762 // in cache when the result is obtained 763 private static final class NameServiceAddresses implements Addresses { 764 private final String host; 765 private final InetAddress reqAddr; 766 767 NameServiceAddresses(String host, InetAddress reqAddr) { 768 this.host = host; 769 this.reqAddr = reqAddr; 770 } 771 772 @Override 773 public InetAddress[] get() throws UnknownHostException { 774 Addresses addresses; 775 // only one thread is doing lookup to name service 776 // for particular host at any time. 777 synchronized (this) { 778 // re-check that we are still us + re-install us if slot empty 779 addresses = cache.putIfAbsent(host, this); 780 if (addresses == null) { 781 // this can happen when we were replaced by CachedAddresses in 782 // some other thread, then CachedAddresses expired and were 783 // removed from cache while we were waiting for lock... 784 addresses = this; 785 } 786 // still us ? 787 if (addresses == this) { 788 // lookup name services 789 InetAddress[] inetAddresses; 790 UnknownHostException ex; 791 int cachePolicy; 792 try { 793 inetAddresses = getAddressesFromNameService(host, reqAddr); 794 ex = null; 795 cachePolicy = InetAddressCachePolicy.get(); 796 } catch (UnknownHostException uhe) { 797 inetAddresses = null; 798 ex = uhe; 799 cachePolicy = InetAddressCachePolicy.getNegative(); 800 } 801 // remove or replace us with cached addresses according to cachePolicy 802 if (cachePolicy == InetAddressCachePolicy.NEVER) { 803 cache.remove(host, this); 804 } else { 805 CachedAddresses cachedAddresses = new CachedAddresses( 806 host, 807 inetAddresses, 808 cachePolicy == InetAddressCachePolicy.FOREVER 809 ? 0L 810 // cachePolicy is in [s] - we need [ns] 811 : System.nanoTime() + 1000_000_000L * cachePolicy 812 ); 813 if (cache.replace(host, this, cachedAddresses) && 814 cachePolicy != InetAddressCachePolicy.FOREVER) { 815 // schedule expiry 816 expirySet.add(cachedAddresses); 817 } 818 } 819 if (inetAddresses == null) { 820 throw ex == null ? new UnknownHostException(host) : ex; 821 } 822 return inetAddresses; 823 } 824 // else addresses != this 825 } 826 // delegate to different addresses when we are already replaced 827 // but outside of synchronized block to avoid any chance of dead-locking 828 return addresses.get(); 829 } 830 } 831 832 static InetAddressImpl impl; 833 834 private static NameService createNSProvider(String provider) { 835 if (provider == null) 836 return null; 837 838 NameService nameService = null; 839 if (provider.equals("default")) { 840 // initialize the default name service 841 nameService = new NameService() { 842 public InetAddress[] lookupAllHostAddr(String host) 843 throws UnknownHostException { 844 return impl.lookupAllHostAddr(host); 845 } 846 public String getHostByAddr(byte[] addr) 847 throws UnknownHostException { 848 return impl.getHostByAddr(addr); 849 } 850 }; 851 } else { 852 final String providerName = provider; 853 try { 854 nameService = java.security.AccessController.doPrivileged( 855 new java.security.PrivilegedExceptionAction<NameService>() { 856 public NameService run() { 857 Iterator<NameServiceDescriptor> itr = 858 ServiceLoader.load(NameServiceDescriptor.class) 859 .iterator(); 860 while (itr.hasNext()) { 861 NameServiceDescriptor nsd = itr.next(); 862 if (providerName. 863 equalsIgnoreCase(nsd.getType()+"," 864 +nsd.getProviderName())) { 865 try { 866 return nsd.createNameService(); 867 } catch (Exception e) { 868 e.printStackTrace(); 869 System.err.println( 870 "Cannot create name service:" 871 +providerName+": " + e); 872 } 873 } 874 } 875 876 return null; 877 } 878 } 879 ); 880 } catch (java.security.PrivilegedActionException e) { 881 } 882 } 883 884 return nameService; 885 } 886 887 static { 888 // create the impl 889 impl = InetAddressImplFactory.create(); 890 891 // get name service if provided and requested 892 String provider = null;; 893 String propPrefix = "sun.net.spi.nameservice.provider."; 894 int n = 1; 895 nameServices = new ArrayList<NameService>(); 896 provider = AccessController.doPrivileged( 897 new GetPropertyAction(propPrefix + n)); 898 while (provider != null) { 899 NameService ns = createNSProvider(provider); 900 if (ns != null) 901 nameServices.add(ns); 902 903 n++; 904 provider = AccessController.doPrivileged( 905 new GetPropertyAction(propPrefix + n)); 906 } 907 908 // if not designate any name services provider, 909 // create a default one 910 if (nameServices.size() == 0) { 911 NameService ns = createNSProvider("default"); 912 nameServices.add(ns); 913 } 914 } 915 916 /** 917 * Creates an InetAddress based on the provided host name and IP address. 918 * No name service is checked for the validity of the address. 919 * 920 * <p> The host name can either be a machine name, such as 921 * "{@code java.sun.com}", or a textual representation of its IP 922 * address. 923 * <p> No validity checking is done on the host name either. 924 * 925 * <p> If addr specifies an IPv4 address an instance of Inet4Address 926 * will be returned; otherwise, an instance of Inet6Address 927 * will be returned. 928 * 929 * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array 930 * must be 16 bytes long 931 * 932 * @param host the specified host 933 * @param addr the raw IP address in network byte order 934 * @return an InetAddress object created from the raw IP address. 935 * @exception UnknownHostException if IP address is of illegal length 936 * @since 1.4 937 */ 938 public static InetAddress getByAddress(String host, byte[] addr) 939 throws UnknownHostException { 940 if (host != null && host.length() > 0 && host.charAt(0) == '[') { 941 if (host.charAt(host.length()-1) == ']') { 942 host = host.substring(1, host.length() -1); 943 } 944 } 945 if (addr != null) { 946 if (addr.length == Inet4Address.INADDRSZ) { 947 return new Inet4Address(host, addr); 948 } else if (addr.length == Inet6Address.INADDRSZ) { 949 byte[] newAddr 950 = IPAddressUtil.convertFromIPv4MappedAddress(addr); 951 if (newAddr != null) { 952 return new Inet4Address(host, newAddr); 953 } else { 954 return new Inet6Address(host, addr); 955 } 956 } 957 } 958 throw new UnknownHostException("addr is of illegal length"); 959 } 960 961 962 /** 963 * Determines the IP address of a host, given the host's name. 964 * 965 * <p> The host name can either be a machine name, such as 966 * "{@code java.sun.com}", or a textual representation of its 967 * IP address. If a literal IP address is supplied, only the 968 * validity of the address format is checked. 969 * 970 * <p> For {@code host} specified in literal IPv6 address, 971 * either the form defined in RFC 2732 or the literal IPv6 address 972 * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also 973 * supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6 974 * scoped addresses. 975 * 976 * <p> If the host is {@code null} then an {@code InetAddress} 977 * representing an address of the loopback interface is returned. 978 * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a> 979 * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a> 980 * section 2.5.3. </p> 981 * 982 * @param host the specified host, or {@code null}. 983 * @return an IP address for the given host name. 984 * @exception UnknownHostException if no IP address for the 985 * {@code host} could be found, or if a scope_id was specified 986 * for a global IPv6 address. 987 * @exception SecurityException if a security manager exists 988 * and its checkConnect method doesn't allow the operation 989 */ 990 public static InetAddress getByName(String host) 991 throws UnknownHostException { 992 return InetAddress.getAllByName(host)[0]; 993 } 994 995 // called from deployment cache manager 996 private static InetAddress getByName(String host, InetAddress reqAddr) 997 throws UnknownHostException { 998 return InetAddress.getAllByName(host, reqAddr)[0]; 999 } 1000 1001 /** 1002 * Given the name of a host, returns an array of its IP addresses, 1003 * based on the configured name service on the system. 1004 * 1005 * <p> The host name can either be a machine name, such as 1006 * "{@code java.sun.com}", or a textual representation of its IP 1007 * address. If a literal IP address is supplied, only the 1008 * validity of the address format is checked. 1009 * 1010 * <p> For {@code host} specified in <i>literal IPv6 address</i>, 1011 * either the form defined in RFC 2732 or the literal IPv6 address 1012 * format defined in RFC 2373 is accepted. A literal IPv6 address may 1013 * also be qualified by appending a scoped zone identifier or scope_id. 1014 * The syntax and usage of scope_ids is described 1015 * <a href="Inet6Address.html#scoped">here</a>. 1016 * <p> If the host is {@code null} then an {@code InetAddress} 1017 * representing an address of the loopback interface is returned. 1018 * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a> 1019 * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a> 1020 * section 2.5.3. </p> 1021 * 1022 * <p> If there is a security manager and {@code host} is not 1023 * null and {@code host.length() } is not equal to zero, the 1024 * security manager's 1025 * {@code checkConnect} method is called 1026 * with the hostname and {@code -1} 1027 * as its arguments to see if the operation is allowed. 1028 * 1029 * @param host the name of the host, or {@code null}. 1030 * @return an array of all the IP addresses for a given host name. 1031 * 1032 * @exception UnknownHostException if no IP address for the 1033 * {@code host} could be found, or if a scope_id was specified 1034 * for a global IPv6 address. 1035 * @exception SecurityException if a security manager exists and its 1036 * {@code checkConnect} method doesn't allow the operation. 1037 * 1038 * @see SecurityManager#checkConnect 1039 */ 1040 public static InetAddress[] getAllByName(String host) 1041 throws UnknownHostException { 1042 return getAllByName(host, null); 1043 } 1044 1045 private static InetAddress[] getAllByName(String host, InetAddress reqAddr) 1046 throws UnknownHostException { 1047 1048 if (host == null || host.length() == 0) { 1049 InetAddress[] ret = new InetAddress[1]; 1050 ret[0] = impl.loopbackAddress(); 1051 return ret; 1052 } 1053 1054 boolean ipv6Expected = false; 1055 if (host.charAt(0) == '[') { 1056 // This is supposed to be an IPv6 literal 1057 if (host.length() > 2 && host.charAt(host.length()-1) == ']') { 1058 host = host.substring(1, host.length() -1); 1059 ipv6Expected = true; 1060 } else { 1061 // This was supposed to be a IPv6 address, but it's not! 1062 throw new UnknownHostException(host + ": invalid IPv6 address"); 1063 } 1064 } 1065 1066 // if host is an IP address, we won't do further lookup 1067 if (Character.digit(host.charAt(0), 16) != -1 1068 || (host.charAt(0) == ':')) { 1069 byte[] addr = null; 1070 int numericZone = -1; 1071 String ifname = null; 1072 // see if it is IPv4 address 1073 addr = IPAddressUtil.textToNumericFormatV4(host); 1074 if (addr == null) { 1075 // This is supposed to be an IPv6 literal 1076 // Check if a numeric or string zone id is present 1077 int pos; 1078 if ((pos=host.indexOf ('%')) != -1) { 1079 numericZone = checkNumericZone (host); 1080 if (numericZone == -1) { /* remainder of string must be an ifname */ 1081 ifname = host.substring (pos+1); 1082 } 1083 } 1084 if ((addr = IPAddressUtil.textToNumericFormatV6(host)) == null && host.contains(":")) { 1085 throw new UnknownHostException(host + ": invalid IPv6 address"); 1086 } 1087 } else if (ipv6Expected) { 1088 // Means an IPv4 litteral between brackets! 1089 throw new UnknownHostException("["+host+"]"); 1090 } 1091 InetAddress[] ret = new InetAddress[1]; 1092 if(addr != null) { 1093 if (addr.length == Inet4Address.INADDRSZ) { 1094 ret[0] = new Inet4Address(null, addr); 1095 } else { 1096 if (ifname != null) { 1097 ret[0] = new Inet6Address(null, addr, ifname); 1098 } else { 1099 ret[0] = new Inet6Address(null, addr, numericZone); 1100 } 1101 } 1102 return ret; 1103 } 1104 } else if (ipv6Expected) { 1105 // We were expecting an IPv6 Litteral, but got something else 1106 throw new UnknownHostException("["+host+"]"); 1107 } 1108 return getAllByName0(host, reqAddr, true, true); 1109 } 1110 1111 /** 1112 * Returns the loopback address. 1113 * <p> 1114 * The InetAddress returned will represent the IPv4 1115 * loopback address, 127.0.0.1, or the IPv6 loopback 1116 * address, ::1. The IPv4 loopback address returned 1117 * is only one of many in the form 127.*.*.* 1118 * 1119 * @return the InetAddress loopback instance. 1120 * @since 1.7 1121 */ 1122 public static InetAddress getLoopbackAddress() { 1123 return impl.loopbackAddress(); 1124 } 1125 1126 1127 /** 1128 * check if the literal address string has %nn appended 1129 * returns -1 if not, or the numeric value otherwise. 1130 * 1131 * %nn may also be a string that represents the displayName of 1132 * a currently available NetworkInterface. 1133 */ 1134 private static int checkNumericZone (String s) throws UnknownHostException { 1135 int percent = s.indexOf ('%'); 1136 int slen = s.length(); 1137 int digit, zone=0; 1138 if (percent == -1) { 1139 return -1; 1140 } 1141 for (int i=percent+1; i<slen; i++) { 1142 char c = s.charAt(i); 1143 if (c == ']') { 1144 if (i == percent+1) { 1145 /* empty per-cent field */ 1146 return -1; 1147 } 1148 break; 1149 } 1150 if ((digit = Character.digit (c, 10)) < 0) { 1151 return -1; 1152 } 1153 zone = (zone * 10) + digit; 1154 } 1155 return zone; 1156 } 1157 1158 private static InetAddress[] getAllByName0 (String host) 1159 throws UnknownHostException 1160 { 1161 return getAllByName0(host, true); 1162 } 1163 1164 /** 1165 * package private so SocketPermission can call it 1166 */ 1167 static InetAddress[] getAllByName0 (String host, boolean check) 1168 throws UnknownHostException { 1169 return getAllByName0 (host, null, check, true); 1170 } 1171 1172 /** 1173 * Designated lookup method. 1174 * 1175 * @param host host name to look up 1176 * @param reqAddr requested address to be the 1st in returned array 1177 * @param check perform security check 1178 * @param useCache use cached value if not expired else always 1179 * perform name service lookup (and cache the result) 1180 * @return array of InetAddress(es) 1181 * @throws UnknownHostException if host name is not found 1182 */ 1183 private static InetAddress[] getAllByName0(String host, 1184 InetAddress reqAddr, 1185 boolean check, 1186 boolean useCache) 1187 throws UnknownHostException { 1188 1189 /* If it gets here it is presumed to be a hostname */ 1190 1191 /* make sure the connection to the host is allowed, before we 1192 * give out a hostname 1193 */ 1194 if (check) { 1195 SecurityManager security = System.getSecurityManager(); 1196 if (security != null) { 1197 security.checkConnect(host, -1); 1198 } 1199 } 1200 1201 // remove expired addresses from cache - expirySet keeps them ordered 1202 // by expiry time so we only need to iterate the prefix of the NavigableSet... 1203 long now = System.nanoTime(); 1204 for (CachedAddresses caddrs : expirySet) { 1205 // compare difference of time instants rather than 1206 // time instants directly, to avoid possible overflow. 1207 // (see System.nanoTime() recommendations...) 1208 if ((caddrs.expiryTime - now) < 0L) { 1209 // ConcurrentSkipListSet uses weakly consistent iterator, 1210 // so removing while iterating is OK... 1211 if (expirySet.remove(caddrs)) { 1212 // ... remove from cache 1213 cache.remove(caddrs.host, caddrs); 1214 } 1215 } else { 1216 // we encountered 1st element that expires in future 1217 break; 1218 } 1219 } 1220 1221 // look-up or remove from cache 1222 Addresses addrs; 1223 if (useCache) { 1224 addrs = cache.get(host); 1225 } else { 1226 addrs = cache.remove(host); 1227 if (addrs != null) { 1228 if (addrs instanceof CachedAddresses) { 1229 // try removing from expirySet too if CachedAddresses 1230 expirySet.remove(addrs); 1231 } 1232 addrs = null; 1233 } 1234 } 1235 1236 if (addrs == null) { 1237 // create a NameServiceAddresses instance which will look up 1238 // the name service and install it within cache... 1239 Addresses oldAddrs = cache.putIfAbsent( 1240 host, 1241 addrs = new NameServiceAddresses(host, reqAddr) 1242 ); 1243 if (oldAddrs != null) { // lost putIfAbsent race 1244 addrs = oldAddrs; 1245 } 1246 } 1247 1248 // ask Addresses to get an array of InetAddress(es) and clone it 1249 return addrs.get().clone(); 1250 } 1251 1252 static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) 1253 throws UnknownHostException 1254 { 1255 InetAddress[] addresses = null; 1256 UnknownHostException ex = null; 1257 1258 for (NameService nameService : nameServices) { 1259 try { 1260 addresses = nameService.lookupAllHostAddr(host); 1261 break; 1262 } catch (UnknownHostException uhe) { 1263 if (host.equalsIgnoreCase("localhost")) { 1264 addresses = new InetAddress[] { impl.loopbackAddress() }; 1265 break; 1266 } 1267 else { 1268 ex = uhe; 1269 } 1270 } 1271 } 1272 1273 if (addresses == null) { 1274 throw ex == null ? new UnknownHostException(host) : ex; 1275 } 1276 1277 // More to do? 1278 if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) { 1279 // Find it? 1280 int i = 1; 1281 for (; i < addresses.length; i++) { 1282 if (addresses[i].equals(reqAddr)) { 1283 break; 1284 } 1285 } 1286 // Rotate 1287 if (i < addresses.length) { 1288 InetAddress tmp, tmp2 = reqAddr; 1289 for (int j = 0; j < i; j++) { 1290 tmp = addresses[j]; 1291 addresses[j] = tmp2; 1292 tmp2 = tmp; 1293 } 1294 addresses[i] = tmp2; 1295 } 1296 } 1297 1298 return addresses; 1299 } 1300 1301 /** 1302 * Returns an {@code InetAddress} object given the raw IP address . 1303 * The argument is in network byte order: the highest order 1304 * byte of the address is in {@code getAddress()[0]}. 1305 * 1306 * <p> This method doesn't block, i.e. no reverse name service lookup 1307 * is performed. 1308 * 1309 * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array 1310 * must be 16 bytes long 1311 * 1312 * @param addr the raw IP address in network byte order 1313 * @return an InetAddress object created from the raw IP address. 1314 * @exception UnknownHostException if IP address is of illegal length 1315 * @since 1.4 1316 */ 1317 public static InetAddress getByAddress(byte[] addr) 1318 throws UnknownHostException { 1319 return getByAddress(null, addr); 1320 } 1321 1322 private static final class CachedLocalHost { 1323 final String host; 1324 final InetAddress addr; 1325 final long expiryTime = System.nanoTime() + 5000_000_000L; // now + 5s; 1326 1327 CachedLocalHost(String host, InetAddress addr) { 1328 this.host = host; 1329 this.addr = addr; 1330 } 1331 } 1332 1333 private static volatile CachedLocalHost cachedLocalHost; 1334 1335 /** 1336 * Returns the address of the local host. This is achieved by retrieving 1337 * the name of the host from the system, then resolving that name into 1338 * an {@code InetAddress}. 1339 * 1340 * <P>Note: The resolved address may be cached for a short period of time. 1341 * </P> 1342 * 1343 * <p>If there is a security manager, its 1344 * {@code checkConnect} method is called 1345 * with the local host name and {@code -1} 1346 * as its arguments to see if the operation is allowed. 1347 * If the operation is not allowed, an InetAddress representing 1348 * the loopback address is returned. 1349 * 1350 * @return the address of the local host. 1351 * 1352 * @exception UnknownHostException if the local host name could not 1353 * be resolved into an address. 1354 * 1355 * @see SecurityManager#checkConnect 1356 * @see java.net.InetAddress#getByName(java.lang.String) 1357 */ 1358 public static InetAddress getLocalHost() throws UnknownHostException { 1359 1360 SecurityManager security = System.getSecurityManager(); 1361 try { 1362 // is cached data still valid? 1363 CachedLocalHost clh = cachedLocalHost; 1364 if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) { 1365 if (security != null) { 1366 security.checkConnect(clh.host, -1); 1367 } 1368 return clh.addr; 1369 } 1370 1371 String local = impl.getLocalHostName(); 1372 1373 if (security != null) { 1374 security.checkConnect(local, -1); 1375 } 1376 1377 InetAddress localAddr; 1378 if (local.equals("localhost")) { 1379 // shortcut for "localhost" host name 1380 localAddr = impl.loopbackAddress(); 1381 } else { 1382 // call getAllByName0 without security checks and 1383 // without using cached data 1384 try { 1385 localAddr = getAllByName0(local, null, false, false)[0]; 1386 } catch (UnknownHostException uhe) { 1387 // Rethrow with a more informative error message. 1388 UnknownHostException uhe2 = 1389 new UnknownHostException(local + ": " + 1390 uhe.getMessage()); 1391 uhe2.initCause(uhe); 1392 throw uhe2; 1393 } 1394 } 1395 cachedLocalHost = new CachedLocalHost(local, localAddr); 1396 return localAddr; 1397 } catch (java.lang.SecurityException e) { 1398 return impl.loopbackAddress(); 1399 } 1400 } 1401 1402 /** 1403 * Perform class load-time initializations. 1404 */ 1405 private static native void init(); 1406 1407 1408 /* 1409 * Returns the InetAddress representing anyLocalAddress 1410 * (typically 0.0.0.0 or ::0) 1411 */ 1412 static InetAddress anyLocalAddress() { 1413 return impl.anyLocalAddress(); 1414 } 1415 1416 /* 1417 * Load and instantiate an underlying impl class 1418 */ 1419 static InetAddressImpl loadImpl(String implName) { 1420 Object impl = null; 1421 1422 /* 1423 * Property "impl.prefix" will be prepended to the classname 1424 * of the implementation object we instantiate, to which we 1425 * delegate the real work (like native methods). This 1426 * property can vary across implementations of the java. 1427 * classes. The default is an empty String "". 1428 */ 1429 String prefix = AccessController.doPrivileged( 1430 new GetPropertyAction("impl.prefix", "")); 1431 try { 1432 impl = Class.forName("java.net." + prefix + implName).newInstance(); 1433 } catch (ClassNotFoundException e) { 1434 System.err.println("Class not found: java.net." + prefix + 1435 implName + ":\ncheck impl.prefix property " + 1436 "in your properties file."); 1437 } catch (InstantiationException e) { 1438 System.err.println("Could not instantiate: java.net." + prefix + 1439 implName + ":\ncheck impl.prefix property " + 1440 "in your properties file."); 1441 } catch (IllegalAccessException e) { 1442 System.err.println("Cannot access class: java.net." + prefix + 1443 implName + ":\ncheck impl.prefix property " + 1444 "in your properties file."); 1445 } 1446 1447 if (impl == null) { 1448 try { 1449 impl = Class.forName(implName).newInstance(); 1450 } catch (Exception e) { 1451 throw new Error("System property impl.prefix incorrect"); 1452 } 1453 } 1454 1455 return (InetAddressImpl) impl; 1456 } 1457 1458 private void readObjectNoData (ObjectInputStream s) throws 1459 IOException, ClassNotFoundException { 1460 if (getClass().getClassLoader() != null) { 1461 throw new SecurityException ("invalid address type"); 1462 } 1463 } 1464 1465 private static final long FIELDS_OFFSET; 1466 private static final sun.misc.Unsafe UNSAFE; 1467 1468 static { 1469 try { 1470 sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); 1471 FIELDS_OFFSET = unsafe.objectFieldOffset( 1472 InetAddress.class.getDeclaredField("holder") 1473 ); 1474 UNSAFE = unsafe; 1475 } catch (ReflectiveOperationException e) { 1476 throw new Error(e); 1477 } 1478 } 1479 1480 private void readObject (ObjectInputStream s) throws 1481 IOException, ClassNotFoundException { 1482 if (getClass().getClassLoader() != null) { 1483 throw new SecurityException ("invalid address type"); 1484 } 1485 GetField gf = s.readFields(); 1486 String host = (String)gf.get("hostName", null); 1487 int address= gf.get("address", 0); 1488 int family= gf.get("family", 0); 1489 InetAddressHolder h = new InetAddressHolder(host, address, family); 1490 UNSAFE.putObject(this, FIELDS_OFFSET, h); 1491 } 1492 1493 /* needed because the serializable fields no longer exist */ 1494 1495 /** 1496 * @serialField hostName String 1497 * @serialField address int 1498 * @serialField family int 1499 */ 1500 private static final ObjectStreamField[] serialPersistentFields = { 1501 new ObjectStreamField("hostName", String.class), 1502 new ObjectStreamField("address", int.class), 1503 new ObjectStreamField("family", int.class), 1504 }; 1505 1506 private void writeObject (ObjectOutputStream s) throws 1507 IOException { 1508 if (getClass().getClassLoader() != null) { 1509 throw new SecurityException ("invalid address type"); 1510 } 1511 PutField pf = s.putFields(); 1512 pf.put("hostName", holder().getHostName()); 1513 pf.put("address", holder().getAddress()); 1514 pf.put("family", holder().getFamily()); 1515 s.writeFields(); 1516 } 1517 } 1518 1519 /* 1520 * Simple factory to create the impl 1521 */ 1522 class InetAddressImplFactory { 1523 1524 static InetAddressImpl create() { 1525 return InetAddress.loadImpl(isIPv6Supported() ? 1526 "Inet6AddressImpl" : "Inet4AddressImpl"); 1527 } 1528 1529 static native boolean isIPv6Supported(); 1530 }