1 /* InetAddress.java -- Class to model an Internet address
2 Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
40 import gnu.classpath.Configuration;
41 import java.io.IOException;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.io.ObjectStreamException;
45 import java.io.Serializable;
48 * This class models an Internet address. It does not have a public
49 * constructor. Instead, new instances of this objects are created
50 * using the static methods getLocalHost(), getByName(), and
53 * This class fulfills the function of the C style functions gethostname(),
54 * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
55 * into their corresponding numeric addresses and vice versa.
57 * @author Aaron M. Renn <arenn@urbanophile.com>
60 * @specnote This class is not final since JK 1.4
62 public class InetAddress implements Serializable
64 private static final long serialVersionUID = 3286316764910316507L;
67 * Dummy InetAddress, used to bind socket to any (all) network interfaces.
69 static InetAddress ANY_IF;
71 private static final byte[] localhostAddress = { 127, 0, 0, 1 };
73 private static InetAddress localhost = null;
77 // load the shared library needed for name resolution
78 if (Configuration.INIT_LOAD_LIBRARY)
80 System.loadLibrary ("javanet");
83 byte[] zeros = { 0, 0, 0, 0 };
84 ANY_IF = new InetAddress (zeros, "0.0.0.0");
88 * The Serialized Form specifies that an int 'address' is saved/restored.
89 * This class uses a byte array internally so we'll just do the conversion
90 * at serialization time and leave the rest of the algorithm as is.
95 * An array of octets representing an IP address.
97 transient byte[] addr;
100 * The name of the host for this address.
105 * The field 'family' seems to be the AF_ value.
106 * FIXME: Much of the code in the other java.net classes does not make
107 * use of this family field. A better implementation would be to make
108 * use of getaddrinfo() and have other methods just check the family
109 * field rather than examining the length of the address each time.
114 * Initializes this object's addr instance variable from the passed in
115 * int array. Note that this constructor is protected and is called
116 * only by static methods in this class.
118 * @param ipaddr The IP number of this address as an array of bytes
120 InetAddress(byte[] address)
122 this (address, null);
126 * Initializes this object's addr instance variable from the passed in
127 * int array. Note that this constructor is protected and is called
128 * only by static methods in this class.
130 * @param ipaddr The IP number of this address as an array of bytes
131 * @param hostname The hostname of this IP address.
133 InetAddress(byte[] address, String hostname)
139 family = getFamily (address);
143 * Returns true if this address is a multicast address, false otherwise.
144 * An address is multicast if the high four bits are "1110". These are
145 * also known as "Class D" addresses.
147 * @return true if mulitcast, false if not
151 public boolean isMulticastAddress()
153 // Mask against high order bits of 1110
154 if (addr.length == 4)
155 return (addr[0] & 0xF0) == 0xE0;
157 // Mask against high order bits of 11111111
158 if (addr.length == 16)
159 return addr [0] == (byte) 0xFF;
165 * Utility routine to check if the InetAddress in a wildcard address
169 public boolean isAnyLocalAddress()
171 // This is the IPv4 implementation.
172 // Any class derived from InetAddress should override this.
173 return equals(ANY_IF);
177 * Utility routine to check if the InetAddress is a loopback address
181 public boolean isLoopbackAddress()
183 // This is the IPv4 implementation.
184 // Any class derived from InetAddress should override this.
185 return addr[0] == 0x7F;
189 * Utility routine to check if InetAddress is a link local address
193 public boolean isLinkLocalAddress()
195 // This is the IPv4 implementation.
196 // Any class derived from InetAddress should override this.
197 // XXX: This seems to not exist with IPv4 addresses
202 * Utility routine to check if InetAddress is a site local address
206 public boolean isSiteLocalAddress()
208 // This is the IPv4 implementation.
209 // Any class derived from InetAddress should override this.
214 // XXX: Suns JDK 1.4.1 (on Linux) seems to have a bug here:
215 // it says 172.16.0.0 - 172.255.255.255 are site local addresses
217 if (addr[0] == 0xAC && (addr[1] & 0xF0) == 0x01)
221 if (addr[0] == 0xC0 && addr[1] == 0xA8)
224 // XXX: Do we need to check more addresses here ?
229 * Utility routine to check if InetAddress is a global multicast address
233 public boolean isMCGlobal()
235 // This is the IPv4 implementation.
236 // Any class derived from InetAddress should override this.
237 // XXX: This seems to not exist with IPv4 addresses
242 * Utility reoutine to check if InetAddress is a node local multicast address
246 public boolean isMCNodeLocal()
248 // This is the IPv4 implementation.
249 // Any class derived from InetAddress should override this.
250 // XXX: This seems to not exist with IPv4 addresses
255 * Utility reoutine to check if InetAddress is a link local multicast address
259 public boolean isMCLinkLocal()
261 // This is the IPv4 implementation.
262 // Any class derived from InetAddress should override this.
263 if (! isMulticastAddress())
266 return (addr[0] == 0xE0 && addr[1] == 0x00 && addr[2] == 0x00);
270 * Utility routine to check if InetAddress is a site local multicast address
274 public boolean isMCSiteLocal()
276 // This is the IPv4 implementation.
277 // Any class derived from InetAddress should override this.
278 // XXX: This seems to not exist with IPv4 addresses
283 * Utility reoutine to check if InetAddress is a organization local
288 public boolean isMCOrgLocal()
290 // This is the IPv4 implementation.
291 // Any class derived from InetAddress should override this.
292 // XXX: This seems to not exist with IPv4 addresses
297 * Returns the hostname for this address. This will return the IP address
298 * as a String if there is no hostname available for this address
300 * @return The hostname for this address
302 public String getHostName()
304 if (hostName == null)
305 lookup (null, this, false);
311 * Returns the canonical hostname represented by this InetAddress
315 public String getCanonicalHostName()
317 SecurityManager sm = System.getSecurityManager();
322 sm.checkConnect (hostName, -1);
324 catch (SecurityException e)
326 return getHostAddress();
330 // Try to find the FDQN now
331 InetAddress address = new InetAddress (getAddress(), null);
332 return address.getHostName();
336 * Returns the IP address of this object as a byte array.
340 public byte[] getAddress()
342 // An experiment shows that JDK1.2 returns a different byte array each
343 // time. This makes sense, in terms of security.
344 return (byte[]) addr.clone();
347 /* Helper function due to a CNI limitation. */
348 private static InetAddress[] allocArray (int count)
350 return new InetAddress [count];
353 /* Helper function due to a CNI limitation. */
354 private static SecurityException checkConnect (String hostname)
356 SecurityManager s = System.getSecurityManager();
363 s.checkConnect (hostname, -1);
366 catch (SecurityException ex)
373 * Returns the IP address of this object as a String. The address is in
374 * the dotted octet notation, for example, "127.0.0.1".
376 * @return The IP address of this object in String form
380 public String getHostAddress()
382 StringBuffer sb = new StringBuffer(40);
384 int len = addr.length;
388 { // An IPv6 address.
392 return sb.toString();
394 int x = ((addr [i] & 0xFF) << 8) | (addr [i + 1] & 0xFF);
395 boolean empty = sb.length() == 0;
399 if (i == 10 && x == 0xFFFF)
400 { // IPv4-mapped IPv6 address.
401 sb.append (":FFFF:");
402 break; // Continue as IPv4 address;
405 { // IPv4-compatible IPv6 address.
407 break; // Continue as IPv4 address.
415 if (x != 0 || i >= 14)
416 sb.append (Integer.toHexString (x).toUpperCase());
422 sb.append (addr [i] & 0xff);
431 return sb.toString();
435 * Returns a hash value for this address. Useful for creating hash
436 * tables. Overrides Object.hashCode()
438 * @return A hash value for this address.
440 public int hashCode()
442 // There hashing algorithm is not specified, but a simple experiment
443 // shows that it is equal to the address, as a 32-bit big-endian integer.
445 int len = addr.length;
446 int i = len > 4 ? len - 4 : 0;
449 hash = (hash << 8) | (addr[i] & 0xFF);
455 * Tests this address for equality against another InetAddress. The two
456 * addresses are considered equal if they contain the exact same octets.
457 * This implementation overrides Object.equals()
459 * @param obj The address to test for equality
461 * @return true if the passed in object's address is equal to this one's,
464 public boolean equals(Object obj)
466 if (! (obj instanceof InetAddress))
469 // "The Java Class Libraries" 2nd edition says "If a machine has
470 // multiple names instances of InetAddress for different name of
471 // that same machine are not equal. This is because they have
472 // different host names." This violates the description in the
473 // JDK 1.2 API documentation. A little experimentation
474 // shows that the latter is correct.
475 byte[] addr2 = ((InetAddress) obj).addr;
477 if (addr.length != addr2.length)
480 for (int i = 0; i < addr.length; i++)
481 if (addr[i] != addr2[i])
488 * Converts this address to a String. This string contains the IP in
489 * dotted decimal form. For example: "127.0.0.1" This method is equivalent
490 * to getHostAddress() and overrides Object.toString()
492 * @return This address in String form
494 public String toString()
497 String address = getHostAddress();
499 if (hostName != null)
504 return host + "/" + address;
508 * Returns an InetAddress object given the raw IP address.
510 * The argument is in network byte order: the highest order byte of the
511 * address is in getAddress()[0].
513 * @param addr The IP address to create the InetAddress object from
515 * @exception UnknownHostException If IP address has illegal length
519 public static InetAddress getByAddress(byte[] addr)
520 throws UnknownHostException
522 return getByAddress(null, addr);
526 * Creates an InetAddress based on the provided host name and IP address.
527 * No name service is checked for the validity of the address.
529 * @param host The hostname of the InetAddress object to create
530 * @param addr The IP address to create the InetAddress object from
532 * @exception UnknownHostException If IP address is of illegal length
536 public static InetAddress getByAddress(String host, byte[] addr)
537 throws UnknownHostException
539 if (addr.length == 4)
540 return new Inet4Address(addr, host);
542 if (addr.length == 16)
543 return new Inet6Address(addr, host);
545 throw new UnknownHostException("IP address has illegal length");
549 * If host is a valid numeric IP address, return the numeric address.
550 * Otherwise, return null.
552 private static native byte[] aton (String host);
554 private static native InetAddress[] lookup (String hostname,
555 InetAddress addr, boolean all);
557 private static native int getFamily (byte[] address);
560 * Returns an InetAddress object representing the IP address of the given
561 * hostname. This name can be either a hostname such as "www.urbanophile.com"
562 * or an IP address in dotted decimal format such as "127.0.0.1". If the
563 * hostname is null or "", the hostname of the local machine is supplied by
564 * default. This method is equivalent to returning the first element in
565 * the InetAddress array returned from GetAllByName.
567 * @param hostname The name of the desired host, or null for the local machine.
569 * @return The address of the host as an InetAddress object.
571 * @exception UnknownHostException If no IP address for the host could
573 * @exception SecurityException If a security manager exists and its
574 * checkConnect method doesn't allow the operation
576 public static InetAddress getByName(String hostname)
577 throws UnknownHostException
579 SecurityManager s = System.getSecurityManager();
581 s.checkConnect(hostname, -1);
583 // Default to current host if necessary
584 if (hostname == null || hostname.length() == 0)
585 return getLocalHost();
587 // Assume that the host string is an IP address
588 byte[] address = aton(hostname);
591 if (address.length == 4)
592 return new Inet4Address (address, null);
593 else if (address.length == 16)
595 if ((address [10] == 0xFF) && (address [11] == 0xFF))
597 byte[] ip4addr = new byte [4];
598 ip4addr [0] = address [12];
599 ip4addr [1] = address [13];
600 ip4addr [2] = address [14];
601 ip4addr [3] = address [15];
602 return new Inet4Address (ip4addr, null);
604 return new Inet6Address (address, null);
607 throw new UnknownHostException ("Address has invalid length");
610 // Try to resolve the host by DNS
611 InetAddress[] addresses = getAllByName(hostname);
616 * Returns an array of InetAddress objects representing all the host/ip
617 * addresses of a given host, given the host's name. This name can be
618 * either a hostname such as "www.urbanophile.com" or an IP address in
619 * dotted decimal format such as "127.0.0.1". If the value is null, the
620 * hostname of the local machine is supplied by default.
622 * @param hostname The name of the desired host, or null for the
625 * @return All addresses of the host as an array of InetAddress objects.
627 * @exception UnknownHostException If no IP address for the host could
629 * @exception SecurityException If a security manager exists and its
630 * checkConnect method doesn't allow the operation
632 public static InetAddress[] getAllByName(String hostname)
633 throws UnknownHostException
635 SecurityManager s = System.getSecurityManager();
637 s.checkConnect(hostname, -1);
639 // Check if hostname is an IP address
640 byte[] address = aton (hostname);
643 InetAddress[] result = new InetAddress [1];
644 result [0] = new InetAddress (address, null);
648 // Try to resolve the hostname by DNS
649 return lookup (hostname, null, true);
653 * This native method looks up the hostname of the local machine
654 * we are on. If the actual hostname cannot be determined, then the
655 * value "localhost" will be used. This native method wrappers the
656 * "gethostname" function.
658 * @return The local hostname.
660 private static native String getLocalHostname();
663 * Returns an InetAddress object representing the address of the current
666 * @return The local host's address
668 * @exception UnknownHostException If no IP address for the host could
671 public static InetAddress getLocalHost() throws UnknownHostException
673 SecurityManager s = System.getSecurityManager();
675 // Experimentation shows that JDK1.2 does cache the result.
676 // However, if there is a security manager, and the cached result
677 // is other than "localhost", we need to check again.
678 if (localhost == null
679 || (s != null && localhost.addr != localhostAddress))
685 private static synchronized void getLocalHost (SecurityManager s)
686 throws UnknownHostException
688 // Check the localhost cache again, now that we've synchronized.
689 if (s == null && localhost != null)
692 String hostname = getLocalHostname();
696 // "The Java Class Libraries" suggests that if the security
697 // manager disallows getting the local host name, then
698 // we use the loopback host.
699 // However, the JDK 1.2 API claims to throw SecurityException,
700 // which seems to suggest SecurityException is *not* caught.
701 // In this case, experimentation shows that former is correct.
704 // This is wrong, if the name returned from getLocalHostname()
705 // is not a fully qualified name. FIXME.
706 s.checkConnect (hostname, -1);
708 catch (SecurityException ex)
714 if (hostname != null)
718 localhost = new InetAddress (null, null);
719 lookup (hostname, localhost, false);
726 if (localhost == null)
727 localhost = new InetAddress (localhostAddress, "localhost");
731 * Needed for serialization
733 private void readResolve() throws ObjectStreamException
735 // FIXME: implement this
738 private void readObject(ObjectInputStream ois)
739 throws IOException, ClassNotFoundException
741 ois.defaultReadObject();
743 addr[3] = (byte) address;
745 for (int i = 2; i >= 0; --i)
746 addr[i] = (byte) (address >>= 8);
748 // Ignore family from serialized data. Since the saved address is 32 bits
749 // the deserialized object will have an IPv4 address i.e. AF_INET family.
750 // FIXME: An alternative is to call the aton method on the deserialized
751 // hostname to get a new address. The Serialized Form doc is silent
752 // on how these fields are used.
753 family = getFamily (addr);
756 private void writeObject(ObjectOutputStream oos) throws IOException
758 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
759 // or a 16 byte IPv6 address.
760 int len = addr.length;
764 address = address << 8 | (((int) addr[i]) & 0xFF);
766 oos.defaultWriteObject();