2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / java / net / InetAddress.java
blob0a69c1aab07fcee27497183ff96a3e71eda33ab8
1 /* InetAddress.java -- Class to model an Internet address
2 Copyright (C) 1998, 1999, 2002 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)
9 any later version.
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
19 02111-1307 USA.
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
24 combination.
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. */
39 package java.net;
41 import gnu.classpath.Configuration;
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.io.ObjectStreamException;
46 import java.io.Serializable;
48 /**
49 * This class models an Internet address. It does not have a public
50 * constructor. Instead, new instances of this objects are created
51 * using the static methods getLocalHost(), getByName(), and
52 * getAllByName().
53 * <p>
54 * This class fulfills the function of the C style functions gethostname(),
55 * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
56 * into their corresponding numeric addresses and vice versa.
58 * @author Aaron M. Renn <arenn@urbanophile.com>
59 * @author Per Bothner
61 * @specnote This class is not final since JK 1.4
63 public class InetAddress implements Serializable
65 private static final long serialVersionUID = 3286316764910316507L;
67 /**
68 * Dummy InetAddress, used to bind socket to any (all) network interfaces.
70 static InetAddress ANY_IF;
72 private static final byte[] localhostAddress = { 127, 0, 0, 1 };
74 private static InetAddress localhost = null;
76 static
78 // load the shared library needed for name resolution
79 if (Configuration.INIT_LOAD_LIBRARY)
81 System.loadLibrary ("javanet");
84 byte[] zeros = { 0, 0, 0, 0 };
85 ANY_IF = new InetAddress (zeros, "0.0.0.0");
88 /**
89 * The Serialized Form specifies that an int 'address' is saved/restored.
90 * This class uses a byte array internally so we'll just do the conversion
91 * at serialization time and leave the rest of the algorithm as is.
93 private int address;
95 /**
96 * An array of octets representing an IP address.
98 transient byte[] addr;
101 * The name of the host for this address.
103 String hostName;
106 * The field 'family' seems to be the AF_ value.
107 * FIXME: Much of the code in the other java.net classes does not make
108 * use of this family field. A better implementation would be to make
109 * use of getaddrinfo() and have other methods just check the family
110 * field rather than examining the length of the address each time.
112 int family;
115 * Initializes this object's addr instance variable from the passed in
116 * int array. Note that this constructor is protected and is called
117 * only by static methods in this class.
119 * @param ipaddr The IP number of this address as an array of bytes
121 InetAddress (byte[] address)
123 this (address, null);
127 * Initializes this object's addr instance variable from the passed in
128 * int array. Note that this constructor is protected and is called
129 * only by static methods in this class.
131 * @param ipaddr The IP number of this address as an array of bytes
132 * @param hostname The hostname of this IP address.
134 InetAddress (byte[] address, String hostname)
136 addr = address;
137 hostName = hostname;
139 if (address != null)
140 family = getFamily (address);
144 * Returns true if this address is a multicast address, false otherwise.
145 * An address is multicast if the high four bits are "1110". These are
146 * also known as "Class D" addresses.
148 * @return true if mulitcast, false if not
150 * @since 1.1
152 public boolean isMulticastAddress()
154 // Mask against high order bits of 1110
155 if (addr.length == 4)
156 return (addr [0] & 0xF0) == 0xE0;
158 // Mask against high order bits of 11111111
159 if (addr.length == 16)
160 return addr [0] == (byte) 0xFF;
162 return false;
166 * Utility routine to check if the InetAddress in a wildcard address
168 * @since 1.4
170 public boolean isAnyLocalAddress()
172 // This is the IPv4 implementation.
173 // Any class derived from InetAddress should override this.
174 return equals (ANY_IF);
178 * Utility routine to check if the InetAddress is a loopback address
180 * @since 1.4
182 public boolean isLoopbackAddress()
184 // This is the IPv4 implementation.
185 // Any class derived from InetAddress should override this.
187 return addr [0] == 0x7F;
191 * Utility routine to check if InetAddress is a link local address
193 * @since 1.4
195 public boolean isLinkLocalAddress()
197 // This is the IPv4 implementation.
198 // Any class derived from InetAddress should override this.
200 // XXX: This seems to not exist with IPv4 addresses
201 return false;
205 * Utility routine to check if InetAddress is a site local address
207 * @since 1.4
209 public boolean isSiteLocalAddress()
211 // This is the IPv4 implementation.
212 // Any class derived from InetAddress should override this.
214 // 10.0.0.0/8
215 if (addr [0] == 0x0A)
216 return true;
218 // XXX: Suns JDK 1.4.1 (on Linux) seems to have a bug here:
219 // it says 172.16.0.0 - 172.255.255.255 are site local addresses
221 // 172.16.0.0/12
222 if (addr [0] == 0xAC
223 && (addr [1] & 0xF0) == 0x01)
224 return true;
226 // 192.168.0.0/16
227 if (addr [0] == 0xC0
228 && addr [1] == 0xA8)
229 return true;
231 // XXX: Do we need to check more addresses here ?
232 return false;
236 * Utility routine to check if InetAddress is a global multicast address
238 * @since 1.4
240 public boolean isMCGlobal()
242 // This is the IPv4 implementation.
243 // Any class derived from InetAddress should override this.
245 // XXX: This seems to not exist with IPv4 addresses
246 return false;
250 * Utility reoutine to check if InetAddress is a node local multicast address
252 * @since 1.4
254 public boolean isMCNodeLocal()
256 // This is the IPv4 implementation.
257 // Any class derived from InetAddress should override this.
259 // XXX: This seems to not exist with IPv4 addresses
260 return false;
264 * Utility reoutine to check if InetAddress is a link local multicast address
266 * @since 1.4
268 public boolean isMCLinkLocal()
270 // This is the IPv4 implementation.
271 // Any class derived from InetAddress should override this.
273 if (!isMulticastAddress())
274 return false;
276 return (addr [0] == 0xE0
277 && addr [1] == 0x00
278 && addr [2] == 0x00);
282 * Utility routine to check if InetAddress is a site local multicast address
284 * @since 1.4
286 public boolean isMCSiteLocal()
288 // This is the IPv4 implementation.
289 // Any class derived from InetAddress should override this.
291 // XXX: This seems to not exist with IPv4 addresses
292 return false;
296 * Utility reoutine to check if InetAddress is a organization local
297 * multicast address
299 * @since 1.4
301 public boolean isMCOrgLocal()
303 // This is the IPv4 implementation.
304 // Any class derived from InetAddress should override this.
306 // XXX: This seems to not exist with IPv4 addresses
307 return false;
311 * Returns the hostname for this address. This will return the IP address
312 * as a String if there is no hostname available for this address
314 * @return The hostname for this address
316 public String getHostName()
318 if (hostName == null)
319 lookup (null, this, false);
321 return hostName;
325 * Returns the canonical hostname represented by this InetAddress
327 * @since 1.4
329 public String getCanonicalHostName()
331 SecurityManager sm = System.getSecurityManager();
332 if (sm != null)
336 sm.checkConnect (hostName, -1);
338 catch (SecurityException e)
340 return getHostAddress();
344 // Try to find the FDQN now
345 InetAddress address = new InetAddress (getAddress(), null);
346 return address.getHostName();
350 * Returns the IP address of this object as a byte array.
352 * @return IP address
354 public byte[] getAddress()
356 // An experiment shows that JDK1.2 returns a different byte array each
357 // time. This makes sense, in terms of security.
358 return (byte[]) addr.clone();
361 /* Helper function due to a CNI limitation. */
362 private static InetAddress[] allocArray (int count)
364 return new InetAddress [count];
367 /* Helper function due to a CNI limitation. */
368 private static SecurityException checkConnect (String hostname)
370 SecurityManager s = System.getSecurityManager();
372 if (s == null)
373 return null;
377 s.checkConnect (hostname, -1);
378 return null;
380 catch (SecurityException ex)
382 return ex;
387 * Returns the IP address of this object as a String. The address is in
388 * the dotted octet notation, for example, "127.0.0.1".
390 * @return The IP address of this object in String form
392 * @since 1.0.2
394 public String getHostAddress()
396 StringBuffer sb = new StringBuffer (40);
397 int len = addr.length;
398 int i = 0;
400 if (len == 16)
401 { // An IPv6 address.
402 for ( ; ; i += 2)
404 if (i >= 16)
405 return sb.toString();
407 int x = ((addr [i] & 0xFF) << 8) | (addr [i + 1] & 0xFF);
408 boolean empty = sb.length() == 0;
410 if (empty)
412 if (i == 10 && x == 0xFFFF)
413 { // IPv4-mapped IPv6 address.
414 sb.append (":FFFF:");
415 break; // Continue as IPv4 address;
417 else if (i == 12)
418 { // IPv4-compatible IPv6 address.
419 sb.append (':');
420 break; // Continue as IPv4 address.
422 else if (i > 0)
423 sb.append ("::");
425 else
426 sb.append (':');
428 if (x != 0 || i >= 14)
429 sb.append (Integer.toHexString (x).toUpperCase());
433 for ( ; ; )
435 sb.append (addr [i] & 0xff);
436 i++;
438 if (i == len)
439 break;
441 sb.append ('.');
444 return sb.toString();
448 * Returns a hash value for this address. Useful for creating hash
449 * tables. Overrides Object.hashCode()
451 * @return A hash value for this address.
453 public int hashCode()
455 // There hashing algorithm is not specified, but a simple experiment
456 // shows that it is equal to the address, as a 32-bit big-endian integer.
457 int hash = 0;
458 int len = addr.length;
459 int i = len > 4 ? len - 4 : 0;
461 for ( ; i < len; i++)
462 hash = (hash << 8) | (addr[i] & 0xFF);
464 return hash;
468 * Tests this address for equality against another InetAddress. The two
469 * addresses are considered equal if they contain the exact same octets.
470 * This implementation overrides Object.equals()
472 * @param obj The address to test for equality
474 * @return true if the passed in object's address is equal to this one's,
475 * false otherwise
477 public boolean equals (Object obj)
479 if (! (obj instanceof InetAddress))
480 return false;
482 // "The Java Class Libraries" 2nd edition says "If a machine has
483 // multiple names instances of InetAddress for different name of
484 // that same machine are not equal. This is because they have
485 // different host names." This violates the description in the
486 // JDK 1.2 API documentation. A little experimentation
487 // shows that the latter is correct.
488 byte[] addr2 = ((InetAddress) obj).addr;
490 if (addr.length != addr2.length)
491 return false;
493 for (int i = 0; i < addr.length; i++)
494 if (addr [i] != addr2 [i])
495 return false;
497 return true;
501 * Converts this address to a String. This string contains the IP in
502 * dotted decimal form. For example: "127.0.0.1" This method is equivalent
503 * to getHostAddress() and overrides Object.toString()
505 * @return This address in String form
507 public String toString()
509 String host;
510 String address = getHostAddress();
512 if (hostName != null)
513 host = hostName;
514 else
515 host = address;
517 return host + "/" + address;
521 * Returns an InetAddress object given the raw IP address.
523 * The argument is in network byte order: the highest order byte of the
524 * address is in getAddress()[0].
526 * @param addr The IP address to create the InetAddress object from
528 * @exception UnknownHostException If IP address has illegal length
530 * @since 1.4
532 public static InetAddress getByAddress (byte[] addr)
533 throws UnknownHostException
535 return getByAddress (null, addr);
539 * Creates an InetAddress based on the provided host name and IP address.
540 * No name service is checked for the validity of the address.
542 * @param host The hostname of the InetAddress object to create
543 * @param addr The IP address to create the InetAddress object from
545 * @exception UnknownHostException If IP address is of illegal length
547 * @since 1.4
549 public static InetAddress getByAddress (String host, byte[] addr)
550 throws UnknownHostException
552 if (addr.length == 4)
553 return new Inet4Address (addr, host);
555 if (addr.length == 16)
556 return new Inet6Address (addr, host);
558 throw new UnknownHostException ("IP address has illegal length");
562 * If host is a valid numeric IP address, return the numeric address.
563 * Otherwise, return null.
565 private static native byte[] aton (String host);
567 private static native InetAddress[] lookup (String hostname,
568 InetAddress addr, boolean all);
570 private static native int getFamily (byte[] address);
573 * Returns an InetAddress object representing the IP address of the given
574 * hostname. This name can be either a hostname such as "www.urbanophile.com"
575 * or an IP address in dotted decimal format such as "127.0.0.1". If the
576 * hostname is null, the hostname of the local machine is supplied by
577 * default. This method is equivalent to returning the first element in
578 * the InetAddress array returned from GetAllByName.
580 * @param hostname The name of the desired host, or null for the local machine.
582 * @return The address of the host as an InetAddress object.
584 * @exception UnknownHostException If no IP address for the host could
585 * be found
586 * @exception SecurityException If a security manager exists and its
587 * checkConnect method doesn't allow the operation
589 public static InetAddress getByName (String hostname)
590 throws UnknownHostException
592 SecurityManager s = System.getSecurityManager();
593 if (s != null)
594 s.checkConnect (hostname, -1);
596 // Default to current host if necessary
597 if (hostname == null)
598 return getLocalHost();
600 // Assume that the host string is an IP address
601 byte[] address = aton (hostname);
602 if (address != null)
604 if (address.length == 4)
605 return new Inet4Address (address, null);
606 else if (address.length == 16)
608 if ((address [10] == 0xFF) && (address [11] == 0xFF))
610 byte[] ip4addr = new byte [4];
611 ip4addr [0] = address [12];
612 ip4addr [1] = address [13];
613 ip4addr [2] = address [14];
614 ip4addr [3] = address [15];
615 return new Inet4Address (ip4addr, null);
617 return new Inet6Address (address, null);
619 else
620 throw new UnknownHostException ("Address has invalid length");
623 // Try to resolve the host by DNS
624 InetAddress[] addresses = getAllByName (hostname);
625 return addresses [0];
629 * Returns an array of InetAddress objects representing all the host/ip
630 * addresses of a given host, given the host's name. This name can be
631 * either a hostname such as "www.urbanophile.com" or an IP address in
632 * dotted decimal format such as "127.0.0.1". If the value is null, the
633 * hostname of the local machine is supplied by default.
635 * @param @param hostname The name of the desired host, or null for the
636 * local machine.
638 * @return All addresses of the host as an array of InetAddress objects.
640 * @exception UnknownHostException If no IP address for the host could
641 * be found
642 * @exception SecurityException If a security manager exists and its
643 * checkConnect method doesn't allow the operation
645 public static InetAddress[] getAllByName (String hostname)
646 throws UnknownHostException
648 SecurityManager s = System.getSecurityManager();
649 if (s != null)
650 s.checkConnect (hostname, -1);
652 // Check if hostname is an IP address
653 byte[] address = aton (hostname);
654 if (address != null)
656 InetAddress[] result = new InetAddress [1];
657 result [0] = new InetAddress (address, null);
658 return result;
661 // Try to resolve the hostname by DNS
662 return lookup (hostname, null, true);
665 private static native String getLocalHostname();
668 * Returns an InetAddress object representing the address of the current
669 * host.
671 * @return The local host's address
673 * @exception UnknownHostException If no IP address for the host could
674 * be found
676 public static InetAddress getLocalHost() throws UnknownHostException
678 SecurityManager s = System.getSecurityManager();
680 // Experimentation shows that JDK1.2 does cache the result.
681 // However, if there is a security manager, and the cached result
682 // is other than "localhost", we need to check again.
683 if (localhost == null
684 || (s != null && localhost.addr != localhostAddress))
685 getLocalHost (s);
687 return localhost;
690 private static synchronized void getLocalHost (SecurityManager s)
691 throws UnknownHostException
693 // Check the localhost cache again, now that we've synchronized.
694 if (s == null && localhost != null)
695 return;
697 String hostname = getLocalHostname();
699 if (s != null)
701 // "The Java Class Libraries" suggests that if the security
702 // manager disallows getting the local host name, then
703 // we use the loopback host.
704 // However, the JDK 1.2 API claims to throw SecurityException,
705 // which seems to suggest SecurityException is *not* caught.
706 // In this case, experimentation shows that former is correct.
709 // This is wrong, if the name returned from getLocalHostname()
710 // is not a fully qualified name. FIXME.
711 s.checkConnect (hostname, -1);
713 catch (SecurityException ex)
715 hostname = null;
719 if (hostname != null)
723 localhost = new InetAddress (null, null);
724 lookup (hostname, localhost, false);
726 catch (Exception ex)
731 if (localhost == null)
732 localhost = new InetAddress (localhostAddress, "localhost");
736 * Needed for serialization
738 private void readResolve() throws ObjectStreamException
740 // FIXME: implement this
743 private void readObject (ObjectInputStream ois)
744 throws IOException, ClassNotFoundException
746 ois.defaultReadObject();
747 addr = new byte [4];
748 addr [3] = (byte) address;
750 for (int i = 2; i >= 0; --i)
751 addr [i] = (byte) (address >>= 8);
753 // Ignore family from serialized data. Since the saved address is 32 bits
754 // the deserialized object will have an IPv4 address i.e. AF_INET family.
755 // FIXME: An alternative is to call the aton method on the deserialized
756 // hostname to get a new address. The Serialized Form doc is silent
757 // on how these fields are used.
758 family = getFamily (addr);
761 private void writeObject (ObjectOutputStream oos) throws IOException
763 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
764 // or a 16 byte IPv6 address.
765 int len = addr.length;
766 int i = len - 4;
768 for (; i < len; i++)
769 address = address << 8 | (((int) addr [i]) & 0xFF);
771 oos.defaultWriteObject();