Fix date in last entry.
[official-gcc.git] / libjava / java / net / InetAddress.java
blob34d4ad1eed9289fa236edbc01c3a3b7e9883f3db
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 java.io.ObjectInputStream;
42 import java.io.ObjectOutputStream;
43 import java.io.IOException;
44 import java.io.Serializable;
45 import java.io.ObjectStreamException;
48 * Written using on-line Java Platform 1.2 API Specification, as well
49 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
50 * (The latter turns out to have some errors ...)
51 * Status: Believed complete and correct.
54 /**
55 * This class models an Internet address. It does not have a public
56 * constructor. Instead, new instances of this objects are created
57 * using the static methods getLocalHost(), getByName(), and
58 * getAllByName().
59 * <p>
60 * This class fulfills the function of the C style functions gethostname(),
61 * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
62 * into their corresponding numeric addresses and vice versa.
64 * @author Aaron M. Renn <arenn@urbanophile.com>
65 * @author Per Bothner
67 * @specnote This class is not final since JK 1.4
69 public class InetAddress implements Serializable
71 // The Serialized Form specifies that an int 'address' is saved/restored.
72 // This class uses a byte array internally so we'll just do the conversion
73 // at serialization time and leave the rest of the algorithm as is.
74 private int address;
75 transient byte[] addr;
76 String hostName;
77 // The field 'family' seems to be the AF_ value.
78 // FIXME: Much of the code in the other java.net classes does not make
79 // use of this family field. A better implementation would be to make
80 // use of getaddrinfo() and have other methods just check the family
81 // field rather than examining the length of the address each time.
82 int family;
83 private static final long serialVersionUID = 3286316764910316507L;
85 /**
86 * Needed for serialization
88 private void readResolve () throws ObjectStreamException
90 // FIXME: implement this
93 private void readObject(ObjectInputStream ois)
94 throws IOException, ClassNotFoundException
96 ois.defaultReadObject();
97 addr = new byte[4];
98 addr[3] = (byte) address;
99 for (int i = 2; i >= 0; --i)
100 addr[i] = (byte) (address >>= 8);
101 // Ignore family from serialized data. Since the saved address is 32 bits
102 // the deserialized object will have an IPv4 address i.e. AF_INET family.
103 // FIXME: An alternative is to call the aton method on the deserialized
104 // hostname to get a new address. The Serialized Form doc is silent
105 // on how these fields are used.
106 family = getFamily (addr);
109 private void writeObject(ObjectOutputStream oos) throws IOException
111 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
112 // or a 16 byte IPv6 address.
113 int len = addr.length;
114 int i = len - 4;
115 for (; i < len; i++)
116 address = address << 8 | (((int) addr[i]) & 0xFF);
117 oos.defaultWriteObject();
120 private static native int getFamily (byte[] address);
122 InetAddress (byte[] address, String hostname)
124 addr = address;
125 hostName = hostname;
126 if (address != null)
127 family = getFamily (address);
131 * Utility routine to check if the InetAddress is an IP multicast address
133 * @since 1.1
135 public boolean isMulticastAddress ()
137 int len = addr.length;
138 if (len == 4)
139 return (addr[0] & 0xF0) == 0xE0;
140 if (len == 16)
141 return addr[0] == (byte) 0xFF;
142 return false;
146 * Utility routine to check if the InetAddress in a wildcard address
148 * @since 1.4
150 public boolean isAnyLocalAddress ()
152 // This is the IPv4 implementation.
153 // Any class derived from InetAddress should override this.
154 return addr == zeros;
158 * Utility routine to check if the InetAddress is a loopback address
160 * @since 1.4
162 public boolean isLoopbackAddress ()
164 // This is the IPv4 implementation.
165 // Any class derived from InetAddress should override this.
167 return addr[0] == 0x7F;
171 * Utility routine to check if InetAddress is a link local address
173 * @since 1.4
175 public boolean isLinkLocalAddress ()
177 // This is the IPv4 implementation.
178 // Any class derived from InetAddress should override this.
180 // XXX: This seems to not exist with IPv4 addresses
181 return false;
185 * Utility routine to check if InetAddress is a site local address
187 * @since 1.4
189 public boolean isSiteLocalAddress ()
191 // This is the IPv4 implementation.
192 // Any class derived from InetAddress should override this.
194 // 10.0.0.0/8
195 if (addr[0] == 0x0A)
196 return true;
198 // XXX: Suns JDK 1.4.1 (on Linux) seems to have a bug here:
199 // it says 172.16.0.0 - 172.255.255.255 are site local addresses
201 // 172.16.0.0/12
202 if (addr[0] == 0xAC && (addr[1] & 0xF0) == 0x01)
203 return true;
205 // 192.168.0.0/16
206 if (addr[0] == 0xC0 && addr[1] == 0xA8)
207 return true;
209 // XXX: Do we need to check more addresses here ?
210 return false;
214 * Utility routine to check if InetAddress is a global multicast address
216 * @since 1.4
218 public boolean isMCGlobal ()
220 // This is the IPv4 implementation.
221 // Any class derived from InetAddress should override this.
223 // XXX: This seems to not exist with IPv4 addresses
224 return false;
228 * Utility reoutine to check if InetAddress is a node local multicast address
230 * @since 1.4
232 public boolean isMCNodeLocal ()
234 // This is the IPv4 implementation.
235 // Any class derived from InetAddress should override this.
237 // XXX: This seems to not exist with IPv4 addresses
238 return false;
242 * Utility reoutine to check if InetAddress is a link local multicast address
244 * @since 1.4
246 public boolean isMCLinkLocal ()
248 // This is the IPv4 implementation.
249 // Any class derived from InetAddress should override this.
251 if (!isMulticastAddress ())
252 return false;
254 return (addr[0] == 0xE0
255 && addr[1] == 0x00
256 && addr[2] == 0x00);
260 * Utility reoutine to check if InetAddress is a site local multicast address
262 * @since 1.4
264 public boolean isMCSiteLocal ()
266 // This is the IPv4 implementation.
267 // Any class derived from InetAddress should override this.
269 // XXX: This seems to not exist with IPv4 addresses
270 return false;
274 * Utility reoutine to check if InetAddress is a organization local
275 * multicast address
277 * @since 1.4
279 public boolean isMCOrgLocal ()
281 // This is the IPv4 implementation.
282 // Any class derived from InetAddress should override this.
284 // XXX: This seems to not exist with IPv4 addresses
285 return false;
289 * Returns the hostname represented by this InetAddress
291 public String getHostName ()
293 if (hostName == null)
294 lookup (null, this, false);
296 return hostName;
300 * Returns the canonical hostname represented by this InetAddress
302 * @since 1.4
304 public String getCanonicalHostName ()
306 SecurityManager sm = System.getSecurityManager ();
307 if (sm != null)
311 sm.checkConnect (hostName, -1);
313 catch (SecurityException e)
315 return getHostAddress ();
319 // Try to find the FDQN now
320 InetAddress address = new InetAddress (getAddress (), null);
321 return address.getHostName ();
325 * Returns the IP address of this InetAddress as array of bytes
327 public byte[] getAddress ()
329 // An experiment shows that JDK1.2 returns a different byte array each
330 // time. This makes sense, in terms of security.
331 return (byte[]) addr.clone();
334 /* Helper function due to a CNI limitation. */
335 private static InetAddress[] allocArray (int count)
337 return new InetAddress[count];
340 /* Helper function due to a CNI limitation. */
341 private static SecurityException checkConnect (String hostname)
343 SecurityManager s = System.getSecurityManager();
344 if (s == null)
345 return null;
348 s.checkConnect(hostname, -1);
349 return null;
351 catch (SecurityException ex)
353 return ex;
358 * Returns the IP address as string
360 * @since 1.0.2
362 public String getHostAddress ()
364 StringBuffer sbuf = new StringBuffer(40);
365 int len = addr.length;
366 int i = 0;
367 if (len == 16)
368 { // An IPv6 address.
369 for (; ; i += 2)
371 if (i >= 16)
372 return sbuf.toString();
373 int x = ((addr[i] & 0xFF) << 8) | (addr[i+1] & 0xFF);
374 boolean empty = sbuf.length() == 0;
375 if (empty)
377 if (i == 10 && x == 0xFFFF)
378 { // IPv4-mapped IPv6 address.
379 sbuf.append(":FFFF:");
380 break; // Continue as IPv4 address;
382 else if (i == 12)
383 { // IPv4-compatible IPv6 address.
384 sbuf.append(':');
385 break; // Continue as IPv4 address.
387 else if (i > 0)
388 sbuf.append("::");
390 else
391 sbuf.append(':');
392 if (x != 0 || i >= 14)
393 sbuf.append(Integer.toHexString(x).toUpperCase());
396 for ( ; ; )
398 sbuf.append(addr[i] & 0xFF);
399 i++;
400 if (i == len)
401 break;
402 sbuf.append('.');
405 return sbuf.toString();
409 * Returns a hashcode of the InetAddress
411 public int hashCode()
413 // There hashing algorithm is not specified, but a simple experiment
414 // shows that it is equal to the address, as a 32-bit big-endian integer.
415 int hash = 0;
416 int len = addr.length;
417 int i = len > 4 ? len - 4 : 0;
418 for ( ; i < len; i++)
419 hash = (hash << 8) | (addr[i] & 0xFF);
420 return hash;
424 * Compares the InetAddress object with another one.
426 public boolean equals (Object obj)
428 if (obj == null || ! (obj instanceof InetAddress))
429 return false;
431 // "The Java Class Libraries" 2nd edition says "If a machine has
432 // multiple names instances of InetAddress for different name of
433 // that same machine are not equal. This is because they have
434 // different host names." This violates the description in the
435 // JDK 1.2 API documentation. A little experimentation
436 // shows that the latter is correct.
437 byte[] addr1 = addr;
438 byte[] addr2 = ((InetAddress) obj).addr;
439 if (addr1.length != addr2.length)
440 return false;
441 for (int i = addr1.length; --i >= 0; )
442 if (addr1[i] != addr2[i])
443 return false;
444 return true;
448 * Returns then <code>InetAddress</code> as string
450 public String toString()
452 String result;
453 String address = getHostAddress();
454 if (hostName != null)
455 result = hostName + "/" + address;
456 else
457 result = address;
458 return result;
462 * Returns an InetAddress object given the raw IP address.
464 * The argument is in network byte order: the highest order byte of the
465 * address is in getAddress()[0].
467 * @param addr The IP address to create the InetAddress object from
469 * @exception UnknownHostException If IP address has illegal length
471 * @since 1.4
473 public static InetAddress getByAddress(byte[] addr)
474 throws UnknownHostException
476 if (addr.length != 4 && addr.length != 16)
477 throw new UnknownHostException ("IP address has illegal length");
479 if (addr.length == 4)
480 return new Inet4Address (addr, null);
482 return new Inet6Address (addr, null);
486 * Creates an InetAddress based on the provided host name and IP address.
487 * No name service is checked for the validity of the address.
489 * @param host The hostname of the InetAddress object to create
490 * @param addr The IP address to create the InetAddress object from
492 * @exception UnknownHostException If IP address is of illegal length
494 * @since 1.4
496 public static InetAddress getByAddress (String host, byte[] addr)
497 throws UnknownHostException
499 if (addr.length == 4)
500 return new Inet4Address (addr, host);
502 if (addr.length == 16)
503 return new Inet6Address (addr, host);
505 throw new UnknownHostException ("IP address has illegal length");
508 /** If host is a valid numeric IP address, return the numeric address.
509 * Otherwise, return null. */
510 private static native byte[] aton (String host);
512 private static native InetAddress[] lookup (String hostname,
513 InetAddress addr, boolean all);
516 * Determines the IP address of a host, given the host's name.
518 * @exception UnknownHostException If no IP address for the host could
519 * be found
520 * @exception SecurityException If a security manager exists and its
521 * checkConnect method doesn't allow the operation
523 public static InetAddress getByName (String hostname)
524 throws UnknownHostException
526 SecurityManager sm = System.getSecurityManager();
527 if (sm != null)
528 sm.checkConnect (hostname, -1);
530 // Default to current host if necessary
531 if (hostname == null)
532 return getLocalHost();
534 // Assume that the host string is an IP address
535 byte[] address = aton (hostname);
536 if (address != null)
538 if (address.length == 4)
539 return new Inet4Address (address, null);
540 else if (address.length == 16)
542 if ((address[10] == 0xFF) && (address[11] == 0xFF))
544 byte[] ip4addr = new byte[4];
545 ip4addr[0] = address[12];
546 ip4addr[1] = address[13];
547 ip4addr[2] = address[14];
548 ip4addr[3] = address[15];
549 return new Inet4Address (ip4addr, null);
551 return new Inet6Address (address, null);
553 else
554 throw new UnknownHostException ("Address has invalid length");
557 // Try to resolve the host by DNS
558 InetAddress[] addresses = getAllByName (hostname);
559 return addresses[0];
563 * Given the name of a host, returns an array of its IP addresses,
564 * based on the configured name service on the system.
566 * @exception UnknownHostException If no IP address for the host could
567 * be found
568 * @exception SecurityException If a security manager exists and its
569 * checkConnect method doesn't allow the operation
571 public static InetAddress[] getAllByName (String hostname)
572 throws UnknownHostException
574 SecurityManager sm = System.getSecurityManager();
575 if (sm != null)
576 sm.checkConnect(hostname, -1);
578 // Check if hostname is an IP address
579 byte[] address = aton (hostname);
580 if (address != null)
582 InetAddress[] result = new InetAddress[1];
583 result[0] = new InetAddress(address, null);
584 return result;
587 // Try to resolve the hostname by DNS
588 return lookup (hostname, null, true);
591 static final byte[] zeros = {0,0,0,0};
593 /* dummy InetAddress, used to bind socket to any (all) network interfaces */
594 static final InetAddress ANY_IF = new InetAddress(zeros, null);
596 private static final byte[] localhostAddress = { 127, 0, 0, 1 };
598 private static native String getLocalHostname ();
600 private static InetAddress localhost = null;
603 * Returns the local host
605 * @exception UnknownHostException If no IP address for the host could
606 * be found
608 public static InetAddress getLocalHost() throws UnknownHostException
610 SecurityManager s = System.getSecurityManager();
611 // Experimentation shows that JDK1.2 does cache the result.
612 // However, if there is a security manager, and the cached result
613 // is other than "localhost", we need to check again.
614 if (localhost == null
615 || (s != null && localhost.addr != localhostAddress))
616 getLocalHost(s);
617 return localhost;
620 private static synchronized void getLocalHost(SecurityManager s)
621 throws UnknownHostException
623 // Check the localhost cache again, now that we've synchronized.
624 if (s == null && localhost != null)
625 return;
626 String hostname = getLocalHostname();
627 if (s != null)
629 // "The Java Class Libraries" suggests that if the security
630 // manager disallows getting the local host name, then
631 // we use the loopback host.
632 // However, the JDK 1.2 API claims to throw SecurityException,
633 // which seems to suggest SecurityException is *not* caught.
634 // In this case, experimentation shows that former is correct.
637 // This is wrong, if the name returned from getLocalHostname()
638 // is not a fully qualified name. FIXME.
639 s.checkConnect(hostname, -1);
641 catch (SecurityException ex)
643 hostname = null;
646 if (hostname != null)
650 localhost = new InetAddress(null, null);
651 lookup(hostname, localhost, false);
653 catch (Exception ex)
657 if (localhost == null)
658 localhost = new InetAddress (localhostAddress, "localhost");