0001: /*
0002: * @(#)InetAddress.java 1.89 06/10/10
0003: *
0004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: *
0026: */
0027:
0028: package java.net;
0029:
0030: import java.util.HashMap;
0031: import java.util.LinkedHashMap;
0032: import java.util.Random;
0033: import java.util.Iterator;
0034: import java.util.LinkedList;
0035: import java.security.AccessController;
0036: import java.io.ObjectStreamException;
0037: import sun.security.action.*;
0038: import sun.net.InetAddressCachePolicy;
0039: import sun.misc.Service;
0040: import sun.net.spi.nameservice.*;
0041:
0042: /**
0043: * This class represents an Internet Protocol (IP) address.
0044: *
0045: * <p> An IP address is either a 32-bit or 128-bit unsigned number
0046: * used by IP, a lower-level protocol on which protocols like UDP and
0047: * TCP are built. The IP address architecture is defined by <a
0048: * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC 790:
0049: * Assigned Numbers</i></a>, <a
0050: * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC 1918:
0051: * Address Allocation for Private Internets</i></a>, <a
0052: * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365:
0053: * Administratively Scoped IP Multicast</i></a>, and <a
0054: * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 2373: IP
0055: * Version 6 Addressing Architecture</i></a>. An instance of an
0056: * InetAddress consists of an IP address and possibly its
0057: * corresponding host name (depending on whether it is constructed
0058: * with a host name or whether it has already done reverse host name
0059: * resolution).
0060: *
0061: * <h4> Address types </h4>
0062: *
0063: * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types">
0064: * <tr><th valign=top><i>unicast</i></th>
0065: * <td>An identifier for a single interface. A packet sent to
0066: * a unicast address is delivered to the interface identified by
0067: * that address.
0068: *
0069: * <p> The Unspecified Address -- Also called anylocal or wildcard
0070: * address. It must never be assigned to any node. It indicates the
0071: * absence of an address. One example of its use is as the target of
0072: * bind, which allows a server to accept a client connection on any
0073: * interface, in case the server host has multiple interfaces.
0074: *
0075: * <p> The <i>unspecified</i> address must not be used as
0076: * the destination address of an IP packet.
0077: *
0078: * <p> The <i>Loopback</i> Addresses -- This is the address
0079: * assigned to the loopback interface. Anything sent to this
0080: * IP address loops around and becomes IP input on the local
0081: * host. This address is often used when testing a
0082: * client.</td></tr>
0083: * <tr><th valign=top><i>multicast</i></th>
0084: * <td>An identifier for a set of interfaces (typically belonging
0085: * to different nodes). A packet sent to a multicast address is
0086: * delivered to all interfaces identified by that address.</td></tr>
0087: * </table></blockquote>
0088: *
0089: * <h4> IP address scope </h4>
0090: *
0091: * <p> <i>Link-local</i> addresses are designed to be used for addressing
0092: * on a single link for purposes such as auto-address configuration,
0093: * neighbor discovery, or when no routers are present.
0094: *
0095: * <p> <i>Site-local</i> addresses are designed to be used for addressing
0096: * inside of a site without the need for a global prefix.
0097: *
0098: * <p> <i>Global</i> addresses are unique across the internet.
0099: *
0100: * <h4> Textual representation of IP addresses </h4>
0101: *
0102: * The textual representation of an IP address is address family specific.
0103: *
0104: * <p>
0105: *
0106: * For IPv4 address format, please refer to <A
0107: * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
0108: * address format, please refer to <A
0109: * HREF="Inet6Address.html#format">Inet6Address#format</A>.
0110: *
0111: * <h4> Host Name Resolution </h4>
0112: *
0113: * Host name-to-IP address <i>resolution</i> is accomplished through
0114: * the use of a combination of local machine configuration information
0115: * and network naming services such as the Domain Name System (DNS)
0116: * and Network Information Service(NIS). The particular naming
0117: * services(s) being used is by default the local machine configured
0118: * one. For any host name, its corresponding IP address is returned.
0119: *
0120: * <p> <i>Reverse name resolution</i> means that for any IP address,
0121: * the host associated with the IP address is returned.
0122: *
0123: * <p> The InetAddress class provides methods to resolve host names to
0124: * their IP addresses and vise versa.
0125: *
0126: * <h4> InetAddress Caching </h4>
0127: *
0128: * The InetAddress class has a cache to store successful as well as
0129: * unsuccessful host name resolutions. The positive caching is there
0130: * to guard against DNS spoofing attacks; while the negative caching
0131: * is used to improve performance.
0132: *
0133: * <p> By default, the result of positive host name resolutions are
0134: * cached forever, because there is no general rule to decide when it
0135: * is safe to remove cache entries. The result of unsuccessful host
0136: * name resolution is cached for a very short period of time (10
0137: * seconds) to improve performance.
0138: *
0139: * <p> Under certain circumstances where it can be determined that DNS
0140: * spoofing attacks are not possible, a Java security property can be
0141: * set to a different Time-to-live (TTL) value for positive
0142: * caching. Likewise, a system admin can configure a different
0143: * negative caching TTL value when needed.
0144: *
0145: * <p> Two Java security properties control the TTL values used for
0146: * positive and negative host name resolution caching:
0147: *
0148: * <blockquote>
0149: * <dl>
0150: * <dt><b>networkaddress.cache.ttl</b> (default: -1)</dt>
0151: * <dd>Indicates the caching policy for successful name lookups from
0152: * the name service. The value is specified as as integer to indicate
0153: * the number of seconds to cache the successful lookup.
0154: * <p>
0155: * A value of -1 indicates "cache forever".
0156: * </dt><p>
0157: * <p>
0158: * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
0159: * <dd>Indicates the caching policy for un-successful name lookups
0160: * from the name service. The value is specified as as integer to
0161: * indicate the number of seconds to cache the failure for
0162: * un-successful lookups.
0163: * <p>
0164: * A value of 0 indicates "never cache".
0165: * A value of -1 indicates "cache forever".
0166: * </dd>
0167: * </dl>
0168: * </blockquote>
0169: *
0170: * @author Chris Warth
0171: * @version 1.89, 10/10/06
0172: * @see java.net.InetAddress#getByAddress(byte[])
0173: * @see java.net.InetAddress#getByAddress(java.lang.String, byte[])
0174: * @see java.net.InetAddress#getAllByName(java.lang.String)
0175: * @see java.net.InetAddress#getByName(java.lang.String)
0176: * @see java.net.InetAddress#getLocalHost()
0177: * @since JDK1.0
0178: */
0179: public class InetAddress implements java.io.Serializable {
0180: /**
0181: * Specify the address family: Internet Protocol, Version 4
0182: * @since 1.4
0183: */
0184: static final int IPv4 = 1;
0185:
0186: /**
0187: * Specify the address family: Internet Protocol, Version 6
0188: * @since 1.4
0189: */
0190: static final int IPv6 = 2;
0191:
0192: /* Specify address family preference */
0193: static transient boolean preferIPv6Address = false;
0194:
0195: /**
0196: * @serial
0197: */
0198: String hostName;
0199:
0200: /**
0201: * Holds a 32-bit IPv4 address.
0202: *
0203: * @serial
0204: */
0205: int address;
0206:
0207: /**
0208: * Specifies the address family type, for instance, '1' for IPv4
0209: * addresses, and '2' for IPv6 addresses.
0210: *
0211: * @serial
0212: */
0213: int family;
0214:
0215: /* Used to store the name service provider */
0216: private static NameService nameService = null;
0217:
0218: /* Used to store the best available hostname */
0219: private transient String canonicalHostName = null;
0220:
0221: /** use serialVersionUID from JDK 1.0.2 for interoperability */
0222: private static final long serialVersionUID = 3286316764910316507L;
0223:
0224: /*
0225: * Load net library into runtime, and perform initializations.
0226: */
0227: static {
0228: preferIPv6Address = ((Boolean) java.security.AccessController
0229: .doPrivileged(new GetBooleanAction(
0230: "java.net.preferIPv6Addresses")))
0231: .booleanValue();
0232: AccessController.doPrivileged(new LoadLibraryAction("net"));
0233: /*
0234: * Wrap the init() method in a privileged block so that it
0235: * can read system properties. In j2se1.4.2 this is done
0236: * in the InetAddress OnLoad() function & this is executed
0237: * by the system class loader.
0238: */
0239: java.security.AccessController
0240: .doPrivileged(new java.security.PrivilegedAction() {
0241: public Object run() {
0242: init();
0243: return null;
0244: }
0245: });
0246: }
0247:
0248: /**
0249: * Constructor for the Socket.accept() method.
0250: * This creates an empty InetAddress, which is filled in by
0251: * the accept() method. This InetAddress, however, is not
0252: * put in the address cache, since it is not created by name.
0253: */
0254: InetAddress() {
0255: }
0256:
0257: /**
0258: * Replaces the de-serialized object with an Inet4Address object.
0259: *
0260: * @return the alternate object to the de-serialized object.
0261: *
0262: * @throws ObjectStreamException if a new object replacing this
0263: * object could not be created
0264: */
0265: private Object readResolve() throws ObjectStreamException {
0266: // will replace the deserialized 'this' object
0267: return new Inet4Address(this .hostName, this .address);
0268: }
0269:
0270: /**
0271: * Utility routine to check if the InetAddress is an
0272: * IP multicast address.
0273: * @return a <code>boolean</code> indicating if the InetAddress is
0274: * an IP multicast address
0275: * @since JDK1.1
0276: */
0277: public boolean isMulticastAddress() {
0278: return false;
0279: }
0280:
0281: /**
0282: * Utility routine to check if the InetAddress in a wildcard address.
0283: * @return a <code>boolean</code> indicating if the Inetaddress is
0284: * a wildcard address.
0285: * @since 1.4
0286: */
0287: public boolean isAnyLocalAddress() {
0288: return false;
0289: }
0290:
0291: /**
0292: * Utility routine to check if the InetAddress is a loopback address.
0293: *
0294: * @return a <code>boolean</code> indicating if the InetAddress is
0295: * a loopback address; or false otherwise.
0296: * @since 1.4
0297: */
0298: public boolean isLoopbackAddress() {
0299: return false;
0300: }
0301:
0302: /**
0303: * Utility routine to check if the InetAddress is an link local address.
0304: *
0305: * @return a <code>boolean</code> indicating if the InetAddress is
0306: * a link local address; or false if address is not a link local unicast address.
0307: * @since 1.4
0308: */
0309: public boolean isLinkLocalAddress() {
0310: return false;
0311: }
0312:
0313: /**
0314: * Utility routine to check if the InetAddress is a site local address.
0315: *
0316: * @return a <code>boolean</code> indicating if the InetAddress is
0317: * a site local address; or false if address is not a site local unicast address.
0318: * @since 1.4
0319: */
0320: public boolean isSiteLocalAddress() {
0321: return false;
0322: }
0323:
0324: /**
0325: * Utility routine to check if the multicast address has global scope.
0326: *
0327: * @return a <code>boolean</code> indicating if the address has
0328: * is a multicast address of global scope, false if it is not
0329: * of global scope or it is not a multicast address
0330: * @since 1.4
0331: */
0332: public boolean isMCGlobal() {
0333: return false;
0334: }
0335:
0336: /**
0337: * Utility routine to check if the multicast address has node scope.
0338: *
0339: * @return a <code>boolean</code> indicating if the address has
0340: * is a multicast address of node-local scope, false if it is not
0341: * of node-local scope or it is not a multicast address
0342: * @since 1.4
0343: */
0344: public boolean isMCNodeLocal() {
0345: return false;
0346: }
0347:
0348: /**
0349: * Utility routine to check if the multicast address has link scope.
0350: *
0351: * @return a <code>boolean</code> indicating if the address has
0352: * is a multicast address of link-local scope, false if it is not
0353: * of link-local scope or it is not a multicast address
0354: * @since 1.4
0355: */
0356: public boolean isMCLinkLocal() {
0357: return false;
0358: }
0359:
0360: /**
0361: * Utility routine to check if the multicast address has site scope.
0362: *
0363: * @return a <code>boolean</code> indicating if the address has
0364: * is a multicast address of site-local scope, false if it is not
0365: * of site-local scope or it is not a multicast address
0366: * @since 1.4
0367: */
0368: public boolean isMCSiteLocal() {
0369: return false;
0370: }
0371:
0372: /**
0373: * Utility routine to check if the multicast address has organization scope.
0374: *
0375: * @return a <code>boolean</code> indicating if the address has
0376: * is a multicast address of organization-local scope,
0377: * false if it is not of organization-local scope
0378: * or it is not a multicast address
0379: * @since 1.4
0380: */
0381: public boolean isMCOrgLocal() {
0382: return false;
0383: }
0384:
0385: /**
0386: * Gets the host name for this IP address.
0387: *
0388: * <p>If this InetAddress was created with a host name,
0389: * this host name will be remembered and returned;
0390: * otherwise, a reverse name lookup will be performed
0391: * and the result will be returned based on the system
0392: * configured name lookup service. If a lookup of the name service
0393: * is required, call
0394: * {@link #getCanonicalHostName() getCanonicalHostName}.
0395: *
0396: * <p>If there is a security manager, its
0397: * <code>checkConnect</code> method is first called
0398: * with the hostname and <code>-1</code>
0399: * as its arguments to see if the operation is allowed.
0400: * If the operation is not allowed, it will return
0401: * the textual representation of the IP address.
0402: *
0403: * @return the host name for this IP address, or if the operation
0404: * is not allowed by the security check, the textual
0405: * representation of the IP address.
0406: *
0407: * @see InetAddress#getCanonicalHostName
0408: * @see SecurityManager#checkConnect
0409: */
0410: public String getHostName() {
0411: return getHostName(true);
0412: }
0413:
0414: /**
0415: * Returns the hostname for this address.
0416: * If the host is equal to null, then this address refers to any
0417: * of the local machine's available network addresses.
0418: * this is package private so SocketPermission can make calls into
0419: * here without a security check.
0420: *
0421: * <p>If there is a security manager, this method first
0422: * calls its <code>checkConnect</code> method
0423: * with the hostname and <code>-1</code>
0424: * as its arguments to see if the calling code is allowed to know
0425: * the hostname for this IP address, i.e., to connect to the host.
0426: * If the operation is not allowed, it will return
0427: * the textual representation of the IP address.
0428: *
0429: * @return the host name for this IP address, or if the operation
0430: * is not allowed by the security check, the textual
0431: * representation of the IP address.
0432: *
0433: * @param check make security check if true
0434: *
0435: * @see SecurityManager#checkConnect
0436: */
0437: String getHostName(boolean check) {
0438: if (hostName == null) {
0439: hostName = InetAddress.getHostFromNameService(this , check);
0440: }
0441: return hostName;
0442: }
0443:
0444: /**
0445: * Gets the fully qualified domain name for this IP address.
0446: * Best effort method, meaning we may not be able to return
0447: * the FQDN depending on the underlying system configuration.
0448: *
0449: * <p>If there is a security manager, this method first
0450: * calls its <code>checkConnect</code> method
0451: * with the hostname and <code>-1</code>
0452: * as its arguments to see if the calling code is allowed to know
0453: * the hostname for this IP address, i.e., to connect to the host.
0454: * If the operation is not allowed, it will return
0455: * the textual representation of the IP address.
0456: *
0457: * @return the fully qualified domain name for this IP address,
0458: * or if the operation is not allowed by the security check,
0459: * the textual representation of the IP address.
0460: *
0461: * @see SecurityManager#checkConnect
0462: *
0463: * @since 1.4
0464: */
0465: public String getCanonicalHostName() {
0466: if (canonicalHostName == null) {
0467: canonicalHostName = InetAddress.getHostFromNameService(
0468: this , true);
0469: }
0470: return canonicalHostName;
0471: }
0472:
0473: /**
0474: * Returns the hostname for this address.
0475: *
0476: * <p>If there is a security manager, this method first
0477: * calls its <code>checkConnect</code> method
0478: * with the hostname and <code>-1</code>
0479: * as its arguments to see if the calling code is allowed to know
0480: * the hostname for this IP address, i.e., to connect to the host.
0481: * If the operation is not allowed, it will return
0482: * the textual representation of the IP address.
0483: *
0484: * @return the host name for this IP address, or if the operation
0485: * is not allowed by the security check, the textual
0486: * representation of the IP address.
0487: *
0488: * @param check make security check if true
0489: *
0490: * @see SecurityManager#checkConnect
0491: */
0492: private static String getHostFromNameService(InetAddress addr,
0493: boolean check) {
0494: String host;
0495: try {
0496: // first lookup the hostname
0497: host = nameService.getHostByAddr(addr.getAddress());
0498:
0499: /* check to see if calling code is allowed to know
0500: * the hostname for this IP address, ie, connect to the host
0501: */
0502: if (check) {
0503: SecurityManager sec = System.getSecurityManager();
0504: if (sec != null) {
0505: sec.checkConnect(host, -1);
0506: }
0507: }
0508:
0509: /* now get all the IP addresses for this hostname,
0510: * and make sure one of them matches the original IP
0511: * address. We do this to try and prevent spoofing.
0512: */
0513:
0514: InetAddress[] arr = InetAddress.getAllByName0(host, check);
0515: boolean ok = false;
0516:
0517: if (arr != null) {
0518: for (int i = 0; !ok && i < arr.length; i++) {
0519: ok = addr.equals(arr[i]);
0520: }
0521: }
0522:
0523: //NOTE: if it looks a spoof just return the address?
0524: if (!ok) {
0525: host = addr.getHostAddress();
0526: return host;
0527: }
0528:
0529: } catch (SecurityException e) {
0530: host = addr.getHostAddress();
0531: } catch (UnknownHostException e) {
0532: host = addr.getHostAddress();
0533: }
0534: return host;
0535: }
0536:
0537: /**
0538: * Returns the raw IP address of this <code>InetAddress</code>
0539: * object. The result is in network byte order: the highest order
0540: * byte of the address is in <code>getAddress()[0]</code>.
0541: *
0542: * @return the raw IP address of this object.
0543: */
0544: public byte[] getAddress() {
0545: return null;
0546: }
0547:
0548: /**
0549: * Returns the IP address string in textual presentation.
0550: *
0551: * @return the raw IP address in a string format.
0552: * @since JDK1.0.2
0553: */
0554: public String getHostAddress() {
0555: return null;
0556: }
0557:
0558: /**
0559: * Returns a hashcode for this IP address.
0560: *
0561: * @return a hash code value for this IP address.
0562: */
0563: public int hashCode() {
0564: return -1;
0565: }
0566:
0567: /**
0568: * Compares this object against the specified object.
0569: * The result is <code>true</code> if and only if the argument is
0570: * not <code>null</code> and it represents the same IP address as
0571: * this object.
0572: * <p>
0573: * Two instances of <code>InetAddress</code> represent the same IP
0574: * address if the length of the byte arrays returned by
0575: * <code>getAddress</code> is the same for both, and each of the
0576: * array components is the same for the byte arrays.
0577: *
0578: * @param obj the object to compare against.
0579: * @return <code>true</code> if the objects are the same;
0580: * <code>false</code> otherwise.
0581: * @see java.net.InetAddress#getAddress()
0582: */
0583: public boolean equals(Object obj) {
0584: return false;
0585: }
0586:
0587: /**
0588: * Converts this IP address to a <code>String</code>. The
0589: * string returned is of the form: hostname / literal IP
0590: * address.
0591: *
0592: * If the host name is unresolved, no reverse name service loopup
0593: * is performed. The hostname part will be represented by an empty string.
0594: *
0595: * @return a string representation of this IP address.
0596: */
0597: public String toString() {
0598: return ((hostName != null) ? hostName : "") + "/"
0599: + getHostAddress();
0600: }
0601:
0602: /*
0603: * Cached addresses - our own litle nis, not!
0604: */
0605: private static Cache addressCache = new Cache(
0606: InetAddressCachePolicy.get());
0607:
0608: private static Cache negativeCache = new Cache(
0609: InetAddressCachePolicy.getNegative());
0610:
0611: private static boolean addressCacheInit = false;
0612:
0613: static InetAddress[] unknown_array; // put THIS in cache
0614:
0615: static InetAddressImpl impl;
0616:
0617: private static HashMap lookupTable = new HashMap();
0618:
0619: /**
0620: * Represents a cache entry
0621: */
0622: static final class CacheEntry {
0623:
0624: CacheEntry(Object address, long expiration) {
0625: this .address = address;
0626: this .expiration = expiration;
0627: }
0628:
0629: Object address;
0630: long expiration;
0631: }
0632:
0633: /**
0634: * A cache that manages entries based on a policy specified
0635: * at creation time.
0636: */
0637: static final class Cache {
0638: private int policy;
0639: private LinkedHashMap cache;
0640:
0641: /**
0642: * Create cache with specific policy
0643: */
0644: public Cache(int policy) {
0645: this .policy = policy;
0646: cache = new LinkedHashMap();
0647: }
0648:
0649: /**
0650: * Add an entry to the cache. If there's already an
0651: * entry then for this host then the entry will be
0652: * replaced.
0653: */
0654: public Cache put(String host, Object address) {
0655: if (policy == InetAddressCachePolicy.NEVER) {
0656: return this ;
0657: }
0658:
0659: // purge any expired entries
0660:
0661: if (policy != InetAddressCachePolicy.FOREVER) {
0662:
0663: // As we iterate in insertion order we can
0664: // terminate when a non-expired entry is found.
0665: LinkedList expired = new LinkedList();
0666: Iterator i = cache.keySet().iterator();
0667: long now = System.currentTimeMillis();
0668: while (i.hasNext()) {
0669: String key = (String) i.next();
0670: CacheEntry entry = (CacheEntry) cache.get(key);
0671:
0672: if (entry.expiration >= 0 && entry.expiration < now) {
0673: expired.add(key);
0674: } else {
0675: break;
0676: }
0677: }
0678:
0679: i = expired.iterator();
0680: while (i.hasNext()) {
0681: cache.remove(i.next());
0682: }
0683: }
0684:
0685: // create new entry and add it to the cache
0686: // -- as a HashMap replaces existing entries we
0687: // don't need to explicitly check if there is
0688: // already an entry for this host.
0689: long expiration;
0690: if (policy == InetAddressCachePolicy.FOREVER) {
0691: expiration = -1;
0692: } else {
0693: expiration = System.currentTimeMillis()
0694: + (policy * 1000);
0695: }
0696: CacheEntry entry = new CacheEntry(address, expiration);
0697: cache.put(host, entry);
0698: return this ;
0699: }
0700:
0701: /**
0702: * Query the cache for the specific host. If found then
0703: * return its CacheEntry, or null if not found.
0704: */
0705: public CacheEntry get(String host) {
0706: if (policy == InetAddressCachePolicy.NEVER) {
0707: return null;
0708: }
0709: CacheEntry entry = (CacheEntry) cache.get(host);
0710:
0711: // check if entry has expired
0712: if (entry != null
0713: && policy != InetAddressCachePolicy.FOREVER) {
0714: if (entry.expiration >= 0
0715: && entry.expiration < System
0716: .currentTimeMillis()) {
0717: cache.remove(host);
0718: entry = null;
0719: }
0720: }
0721:
0722: return entry;
0723: }
0724: }
0725:
0726: /*
0727: * Initialize cache and insert anyLocalAddress into the
0728: * unknown array with no expiry.
0729: */
0730: private static void cacheInitIfNeeded() {
0731: // Uncomment this line if assertions are always
0732: // turned on for libraries
0733: //assert Thread.holdsLock(addressCache);
0734: if (addressCacheInit) {
0735: return;
0736: }
0737: unknown_array = new InetAddress[1];
0738: unknown_array[0] = impl.anyLocalAddress();
0739:
0740: addressCache.put(impl.anyLocalAddress().getHostName(),
0741: unknown_array);
0742:
0743: addressCacheInit = true;
0744: }
0745:
0746: /*
0747: * Cache the given hostname and address.
0748: */
0749: private static void cacheAddress(String hostname, Object address,
0750: boolean success) {
0751:
0752: synchronized (addressCache) {
0753: cacheInitIfNeeded();
0754: if (success) {
0755: addressCache.put(hostname, address);
0756: } else {
0757: negativeCache.put(hostname, address);
0758: }
0759: }
0760: }
0761:
0762: /*
0763: * Lookup hostname in cache (positive & negative cache). If
0764: * found return address, null if not found.
0765: */
0766: private static Object getCachedAddress(String hostname) {
0767: hostname = hostname.toLowerCase();
0768:
0769: // search both positive & negative caches
0770:
0771: synchronized (addressCache) {
0772: CacheEntry entry;
0773:
0774: cacheInitIfNeeded();
0775:
0776: entry = (CacheEntry) addressCache.get(hostname);
0777: if (entry == null) {
0778: entry = (CacheEntry) negativeCache.get(hostname);
0779: }
0780:
0781: if (entry != null) {
0782: return entry.address;
0783: }
0784: }
0785:
0786: // not found
0787: return null;
0788: }
0789:
0790: static {
0791: // create the impl
0792: impl = (new InetAddressImplFactory()).create();
0793:
0794: // get name service if provided and requested
0795: String provider = null;
0796: ;
0797: String propPrefix = "sun.net.spi.nameservice.provider.";
0798: int n = 1;
0799: while (nameService == null) {
0800: provider = (String) AccessController
0801: .doPrivileged(new GetPropertyAction(propPrefix + n,
0802: "default"));
0803: n++;
0804: if (provider.equals("default")) {
0805: // initialize the default name service
0806: nameService = new NameService() {
0807: public byte[][] lookupAllHostAddr(String host)
0808: throws UnknownHostException {
0809: return impl.lookupAllHostAddr(host);
0810: }
0811:
0812: public String getHostByAddr(byte[] addr)
0813: throws UnknownHostException {
0814: return impl.getHostByAddr(addr);
0815: }
0816: };
0817: break;
0818: }
0819:
0820: final String providerName = provider;
0821:
0822: try {
0823: java.security.AccessController
0824: .doPrivileged(new java.security.PrivilegedExceptionAction() {
0825: public Object run() {
0826: Iterator itr = Service
0827: .providers(NameServiceDescriptor.class);
0828: while (itr.hasNext()) {
0829: NameServiceDescriptor nsd = (NameServiceDescriptor) itr
0830: .next();
0831: if (providerName
0832: .equalsIgnoreCase(nsd
0833: .getType()
0834: + ","
0835: + nsd
0836: .getProviderName())) {
0837: try {
0838: nameService = nsd
0839: .createNameService();
0840: break;
0841: } catch (Exception e) {
0842: e.printStackTrace();
0843: System.err
0844: .println("Cannot create name service:"
0845: + providerName
0846: + ": " + e);
0847: }
0848: }
0849: } /* while */
0850: return null;
0851: }
0852: });
0853: } catch (java.security.PrivilegedActionException e) {
0854: }
0855:
0856: }
0857: }
0858:
0859: /**
0860: * Create an InetAddress based on the provided host name and IP address
0861: * No name service is checked for the validity of the address.
0862: *
0863: * <p> The host name can either be a machine name, such as
0864: * "<code>java.sun.com</code>", or a textual representation of its IP
0865: * address.
0866: *
0867: * <p> For <code>host</code> specified in literal IPv6 address,
0868: * either the form defined in RFC 2732 or the literal IPv6 address
0869: * format defined in RFC 2373 is accepted.
0870: *
0871: * <p> If addr specifies an IPv4 address an instance of Inet4Address
0872: * will be returned; otherwise, an instance of Inet6Address
0873: * will be returned.
0874: *
0875: * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
0876: * must be 16 bytes long
0877: *
0878: * @param host the specified host
0879: * @param addr the raw IP address in network byte order
0880: * @return an InetAddress object created from the raw IP address.
0881: * @exception UnknownHostException if IP address is of illegal length
0882: * @since 1.4
0883: */
0884: public static InetAddress getByAddress(String host, byte[] addr)
0885: throws UnknownHostException {
0886: if (host != null && host.length() > 0 && host.charAt(0) == '[') {
0887: if (host.charAt(host.length() - 1) == ']') {
0888: host = host.substring(1, host.length() - 1);
0889: }
0890: }
0891: if (addr != null) {
0892: if (addr.length == Inet4Address.INADDRSZ) {
0893: return new Inet4Address(host, addr);
0894: } else if (addr.length == Inet6Address.INADDRSZ) {
0895: byte[] newAddr = Inet6Address
0896: .convertFromIPv4MappedAddress(addr);
0897: if (newAddr != null) {
0898: return new Inet4Address(host, newAddr);
0899: } else {
0900: return new Inet6Address(host, addr);
0901: }
0902: }
0903: }
0904: throw new UnknownHostException("addr is of illegal length");
0905: }
0906:
0907: /**
0908: * Determines the IP address of a host, given the host's name.
0909: *
0910: * <p> The host name can either be a machine name, such as
0911: * "<code>java.sun.com</code>", or a textual representation of its
0912: * IP address. If a literal IP address is supplied, only the
0913: * validity of the address format is checked.
0914: *
0915: * <p> For <code>host</code> specified in literal IPv6 address,
0916: * either the form defined in RFC 2732 or the literal IPv6 address
0917: * format defined in RFC 2373 is accepted.
0918: *
0919: * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
0920: * representing an address of the loopback interface is returned.
0921: * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
0922: * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
0923: * section 2.5.3. </p>
0924: *
0925: * @param host the specified host, or <code>null</code>.
0926: * @return an IP address for the given host name.
0927: * @exception UnknownHostException if no IP address for the
0928: * <code>host</code> could be found.
0929: * @exception SecurityException if a security manager exists
0930: * and its checkConnect method doesn't allow the operation
0931: */
0932: public static InetAddress getByName(String host)
0933: throws UnknownHostException {
0934: return InetAddress.getAllByName(host)[0];
0935: }
0936:
0937: /**
0938: * Given the name of a host, returns an array of its IP addresses,
0939: * based on the configured name service on the system.
0940: *
0941: * <p> The host name can either be a machine name, such as
0942: * "<code>java.sun.com</code>", or a textual representation of its IP
0943: * address. If a literal IP address is supplied, only the
0944: * validity of the address format is checked.
0945: *
0946: * <p> For <code>host</code> specified in literal IPv6 address,
0947: * either the form defined in RFC 2732 or the literal IPv6 address
0948: * format defined in RFC 2373 is accepted.
0949: *
0950: * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
0951: * representing an address of the loopback interface is returned.
0952: * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a>
0953: * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>
0954: * section 2.5.3. </p>
0955: *
0956: * <p> If there is a security manager and <code>host</code> is not
0957: * null and <code>host.length() </code> is not equal to zero, the
0958: * security manager's
0959: * <code>checkConnect</code> method is called
0960: * with the hostname and <code>-1</code>
0961: * as its arguments to see if the operation is allowed.
0962: *
0963: * @param host the name of the host, or <code>null</code>.
0964: * @return an array of all the IP addresses for a given host name.
0965: *
0966: * @exception UnknownHostException if no IP address for the
0967: * <code>host</code> could be found.
0968: * @exception SecurityException if a security manager exists and its
0969: * <code>checkConnect</code> method doesn't allow the operation.
0970: *
0971: * @see SecurityManager#checkConnect
0972: */
0973: public static InetAddress[] getAllByName(String host)
0974: throws UnknownHostException {
0975:
0976: if (host == null || host.length() == 0) {
0977: InetAddress[] ret = new InetAddress[1];
0978: ret[0] = impl.loopbackAddress();
0979: return ret;
0980: }
0981:
0982: boolean ipv6Expected = false;
0983: if (host.charAt(0) == '[') {
0984: // This is supposed to be an IPv6 litteral
0985: if (host.length() > 2
0986: && host.charAt(host.length() - 1) == ']') {
0987: host = host.substring(1, host.length() - 1);
0988: ipv6Expected = true;
0989: } else {
0990: // This was supposed to be a IPv6 address, but it's not!
0991: throw new UnknownHostException(host);
0992: }
0993: }
0994:
0995: // if host is an IP address, we won't do further lookup
0996: if (Character.digit(host.charAt(0), 16) != -1
0997: || (host.charAt(0) == ':')) {
0998: byte[] addr = null;
0999: // see if it is IPv4 address
1000: addr = Inet4Address.textToNumericFormat(host);
1001: if (addr == null) {
1002: // see if it is IPv6 address
1003: addr = Inet6Address.textToNumericFormat(host);
1004: } else if (ipv6Expected) {
1005: // Means an IPv4 litteral between brackets!
1006: throw new UnknownHostException("[" + host + "]");
1007: }
1008: InetAddress[] ret = new InetAddress[1];
1009: if (addr != null) {
1010: if (addr.length == Inet4Address.INADDRSZ) {
1011: ret[0] = new Inet4Address(null, addr);
1012: } else {
1013: ret[0] = new Inet6Address(null, addr);
1014: }
1015: return ret;
1016: }
1017: } else if (ipv6Expected) {
1018: // We were expecting an IPv6 Litteral, but got something else
1019: throw new UnknownHostException("[" + host + "]");
1020: }
1021: return getAllByName0(host);
1022: }
1023:
1024: private static InetAddress[] getAllByName0(String host)
1025: throws UnknownHostException {
1026: return getAllByName0(host, true);
1027: }
1028:
1029: /**
1030: * package private so SocketPermission can call it
1031: */
1032: static InetAddress[] getAllByName0(String host, boolean check)
1033: throws UnknownHostException {
1034: /* If it gets here it is presumed to be a hostname */
1035: /* Cache.get can return: null, unknownAddress, or InetAddress[] */
1036: Object obj = null;
1037: Object objcopy = null;
1038:
1039: /* make sure the connection to the host is allowed, before we
1040: * give out a hostname
1041: */
1042: if (check) {
1043: SecurityManager security = System.getSecurityManager();
1044: if (security != null) {
1045: security.checkConnect(host, -1);
1046: }
1047: }
1048:
1049: obj = getCachedAddress(host);
1050:
1051: /* If no entry in cache, then do the host lookup */
1052: if (obj == null) {
1053: try {
1054: obj = getAddressFromNameService(host);
1055: } catch (UnknownHostException uhe) {
1056: throw new UnknownHostException(host + ": "
1057: + uhe.getMessage());
1058: }
1059: }
1060:
1061: if (obj == unknown_array)
1062: throw new UnknownHostException(host);
1063:
1064: /* Make a copy of the InetAddress array */
1065: objcopy = ((InetAddress[]) obj).clone();
1066:
1067: return (InetAddress[]) objcopy;
1068: }
1069:
1070: private static Object getAddressFromNameService(String host)
1071: throws UnknownHostException {
1072: Object obj = null;
1073: boolean success = false;
1074:
1075: // Check whether the host is in the lookupTable.
1076: // 1) If the host isn't in the lookupTable when
1077: // checkLookupTable() is called, checkLookupTable()
1078: // would add the host in the lookupTable and
1079: // return null. So we will do the lookup.
1080: // 2) If the host is in the lookupTable when
1081: // checkLookupTable() is called, the current thread
1082: // would be blocked until the host is removed
1083: // from the lookupTable. Then this thread
1084: // should try to look up the addressCache.
1085: // i) if it found the address in the
1086: // addressCache, checkLookupTable() would
1087: // return the address.
1088: // ii) if it didn't find the address in the
1089: // addressCache for any reason,
1090: // it should add the host in the
1091: // lookupTable and return null so the
1092: // following code would do a lookup itself.
1093: if ((obj = checkLookupTable(host)) == null) {
1094: // This is the first thread which looks up the address
1095: // this host or the cache entry for this host has been
1096: // expired so this thread should do the lookup.
1097: try {
1098: /*
1099: * Do not put the call to lookup() inside the
1100: * constructor. if you do you will still be
1101: * allocating space when the lookup fails.
1102: */
1103: byte[][] byte_array;
1104: byte_array = nameService.lookupAllHostAddr(host);
1105: InetAddress[] addr_array = new InetAddress[byte_array.length];
1106:
1107: for (int i = 0; i < byte_array.length; i++) {
1108: byte addr[] = byte_array[i];
1109: if (addr.length == Inet4Address.INADDRSZ) {
1110: addr_array[i] = new Inet4Address(host, addr);
1111: } else {
1112: addr_array[i] = new Inet6Address(host, addr);
1113: }
1114: }
1115: obj = addr_array;
1116: success = true;
1117: } catch (UnknownHostException uhe) {
1118: obj = unknown_array;
1119: success = false;
1120: throw uhe;
1121: } finally {
1122: try {
1123: // Cache the address.
1124: cacheAddress(host, obj, success);
1125: } finally {
1126: // Delete the host from the lookupTable, and
1127: // notify all threads waiting for the monitor
1128: // for lookupTable.
1129: updateLookupTable(host);
1130: }
1131: }
1132: }
1133:
1134: return obj;
1135: }
1136:
1137: private static Object checkLookupTable(String host) {
1138: // make sure obj is null.
1139: Object obj = null;
1140:
1141: synchronized (lookupTable) {
1142: // If the host isn't in the lookupTable, add it in the
1143: // lookuptable and return null. The caller should do
1144: // the lookup.
1145: if (lookupTable.containsKey(host) == false) {
1146: lookupTable.put(host, null);
1147: return obj;
1148: }
1149:
1150: // If the host is in the lookupTable, it means that another
1151: // thread is trying to look up the address of this host.
1152: // This thread should wait.
1153: while (lookupTable.containsKey(host)) {
1154: try {
1155: lookupTable.wait();
1156: } catch (InterruptedException e) {
1157: }
1158: }
1159: }
1160:
1161: // The other thread has finished looking up the address of
1162: // the host. This thread should retry to get the address
1163: // from the addressCache. If it doesn't get the address from
1164: // the cache, it will try to look up the address itself.
1165: obj = getCachedAddress(host);
1166: if (obj == null) {
1167: synchronized (lookupTable) {
1168: lookupTable.put(host, null);
1169: }
1170: }
1171:
1172: return obj;
1173: }
1174:
1175: private static void updateLookupTable(String host) {
1176: synchronized (lookupTable) {
1177: lookupTable.remove(host);
1178: lookupTable.notifyAll();
1179: }
1180: }
1181:
1182: /**
1183: * Returns an <code>InetAddress</code> object given the raw IP address .
1184: * The argument is in network byte order: the highest order
1185: * byte of the address is in <code>getAddress()[0]</code>.
1186: *
1187: * <p> This method doesn't block, i.e. no reverse name service lookup
1188: * is performed.
1189: *
1190: * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
1191: * must be 16 bytes long
1192: *
1193: * @param addr the raw IP address in network byte order
1194: * @return an InetAddress object created from the raw IP address.
1195: * @exception UnknownHostException if IP address is of illegal length
1196: * @since 1.4
1197: */
1198: public static InetAddress getByAddress(byte[] addr)
1199: throws UnknownHostException {
1200: return getByAddress(null, addr);
1201: }
1202:
1203: /**
1204: * Returns the local host.
1205: *
1206: * <p>If there is a security manager, its
1207: * <code>checkConnect</code> method is called
1208: * with the local host name and <code>-1</code>
1209: * as its arguments to see if the operation is allowed.
1210: * If the operation is not allowed, an InetAddress representing
1211: * the loopback address is returned.
1212: *
1213: * @return the IP address of the local host.
1214: *
1215: * @exception UnknownHostException if no IP address for the
1216: * <code>host</code> could be found.
1217: *
1218: * @see SecurityManager#checkConnect
1219: */
1220: public static InetAddress getLocalHost()
1221: throws UnknownHostException {
1222:
1223: SecurityManager security = System.getSecurityManager();
1224: try {
1225: String local = impl.getLocalHostName();
1226:
1227: if (security != null) {
1228: security.checkConnect(local, -1);
1229: }
1230: // we are calling getAddressFromNameService directly
1231: // to avoid getting localHost from cache
1232:
1233: InetAddress[] localAddrs;
1234: try {
1235: localAddrs = (InetAddress[]) InetAddress
1236: .getAddressFromNameService(local);
1237: } catch (UnknownHostException uhe) {
1238: throw new UnknownHostException(local + ": "
1239: + uhe.getMessage());
1240: }
1241: return localAddrs[0];
1242: } catch (java.lang.SecurityException e) {
1243: return impl.loopbackAddress();
1244: }
1245: }
1246:
1247: /**
1248: * Perform class load-time initializations.
1249: */
1250: private static native void init();
1251:
1252: /*
1253: * Returns the InetAddress representing anyLocalAddress
1254: * (typically 0.0.0.0 or ::0)
1255: */
1256: static InetAddress anyLocalAddress() {
1257: return impl.anyLocalAddress();
1258: }
1259:
1260: /*
1261: * Load and instantiate an underlying impl class
1262: */
1263: static Object loadImpl(String implName) {
1264: Object impl;
1265:
1266: /*
1267: * Property "impl.prefix" will be prepended to the classname
1268: * of the implementation object we instantiate, to which we
1269: * delegate the real work (like native methods). This
1270: * property can vary across implementations of the java.
1271: * classes. The default is an empty String "".
1272: */
1273: String prefix = (String) AccessController
1274: .doPrivileged(new GetPropertyAction("impl.prefix", ""));
1275: impl = null;
1276: try {
1277: impl = Class.forName("java.net." + prefix + implName)
1278: .newInstance();
1279: } catch (ClassNotFoundException e) {
1280: System.err.println("Class not found: java.net." + prefix
1281: + implName + ":\ncheck impl.prefix property "
1282: + "in your properties file.");
1283: } catch (InstantiationException e) {
1284: System.err.println("Could not instantiate: java.net."
1285: + prefix + implName
1286: + ":\ncheck impl.prefix property "
1287: + "in your properties file.");
1288: } catch (IllegalAccessException e) {
1289: System.err.println("Cannot access class: java.net."
1290: + prefix + implName
1291: + ":\ncheck impl.prefix property "
1292: + "in your properties file.");
1293: }
1294:
1295: if (impl == null) {
1296: try {
1297: impl = Class.forName(implName).newInstance();
1298: } catch (Exception e) {
1299: throw new Error("System property impl.prefix incorrect");
1300: }
1301: }
1302:
1303: return impl;
1304: }
1305:
1306: /* Check java.net.preferIPv4Stack property. Used by
1307: init_IPv6Available() */
1308: private static boolean preferIPv4Stack() {
1309: Boolean res = (Boolean) java.security.AccessController
1310: .doPrivileged(new sun.security.action.GetBooleanAction(
1311: "java.net.preferIPv4Stack"));
1312: return res.booleanValue();
1313: }
1314: }
1315:
1316: /*
1317: * Simple factory to create the impl
1318: */
1319: class InetAddressImplFactory {
1320:
1321: static InetAddressImpl create() {
1322: Object o;
1323: if (isIPv6Supported()) {
1324: o = InetAddress.loadImpl("Inet6AddressImpl");
1325: } else {
1326: o = InetAddress.loadImpl("Inet4AddressImpl");
1327: }
1328: return (InetAddressImpl) o;
1329: }
1330:
1331: private static native boolean isIPv6Supported();
1332: }
|