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)
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. */
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.
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
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>
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.
75 transient byte[] addr
;
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.
83 private static final long serialVersionUID
= 3286316764910316507L;
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();
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
;
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
)
127 family
= getFamily (address
);
131 * Utility routine to check if the InetAddress is an IP multicast address
135 public boolean isMulticastAddress ()
137 int len
= addr
.length
;
139 return (addr
[0] & 0xF0) == 0xE0;
141 return addr
[0] == (byte) 0xFF;
146 * Utility routine to check if the InetAddress in a wildcard address
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
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
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
185 * Utility routine to check if InetAddress is a site local address
189 public boolean isSiteLocalAddress ()
191 // This is the IPv4 implementation.
192 // Any class derived from InetAddress should override this.
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
202 if (addr
[0] == 0xAC && (addr
[1] & 0xF0) == 0x01)
206 if (addr
[0] == 0xC0 && addr
[1] == 0xA8)
209 // XXX: Do we need to check more addresses here ?
214 * Utility routine to check if InetAddress is a global multicast address
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
228 * Utility reoutine to check if InetAddress is a node local multicast address
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
242 * Utility reoutine to check if InetAddress is a link local multicast address
246 public boolean isMCLinkLocal ()
248 // This is the IPv4 implementation.
249 // Any class derived from InetAddress should override this.
251 if (!isMulticastAddress ())
254 return (addr
[0] == 0xE0
260 * Utility reoutine to check if InetAddress is a site local multicast address
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
274 * Utility reoutine to check if InetAddress is a organization local
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
289 * Returns the hostname represented by this InetAddress
291 public String
getHostName ()
293 if (hostName
== null)
294 lookup (null, this, false);
300 * Returns the canonical hostname represented by this InetAddress
304 public String
getCanonicalHostName ()
306 SecurityManager sm
= System
.getSecurityManager ();
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();
348 s
.checkConnect(hostname
, -1);
351 catch (SecurityException ex
)
358 * Returns the IP address as string
362 public String
getHostAddress ()
364 StringBuffer sbuf
= new StringBuffer(40);
365 int len
= addr
.length
;
368 { // An IPv6 address.
372 return sbuf
.toString();
373 int x
= ((addr
[i
] & 0xFF) << 8) | (addr
[i
+1] & 0xFF);
374 boolean empty
= sbuf
.length() == 0;
377 if (i
== 10 && x
== 0xFFFF)
378 { // IPv4-mapped IPv6 address.
379 sbuf
.append(":FFFF:");
380 break; // Continue as IPv4 address;
383 { // IPv4-compatible IPv6 address.
385 break; // Continue as IPv4 address.
392 if (x
!= 0 || i
>= 14)
393 sbuf
.append(Integer
.toHexString(x
).toUpperCase());
398 sbuf
.append(addr
[i
] & 0xFF);
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.
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);
424 * Compares the InetAddress object with another one.
426 public boolean equals (Object obj
)
428 if (obj
== null || ! (obj
instanceof InetAddress
))
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.
438 byte[] addr2
= ((InetAddress
) obj
).addr
;
439 if (addr1
.length
!= addr2
.length
)
441 for (int i
= addr1
.length
; --i
>= 0; )
442 if (addr1
[i
] != addr2
[i
])
448 * Returns then <code>InetAddress</code> as string
450 public String
toString()
453 String address
= getHostAddress();
454 if (hostName
!= null)
455 result
= hostName
+ "/" + address
;
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
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
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
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();
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
);
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);
554 throw new UnknownHostException ("Address has invalid length");
557 // Try to resolve the host by DNS
558 InetAddress
[] addresses
= getAllByName (hostname
);
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
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();
576 sm
.checkConnect(hostname
, -1);
578 // Check if hostname is an IP address
579 byte[] address
= aton (hostname
);
582 InetAddress
[] result
= new InetAddress
[1];
583 result
[0] = new InetAddress(address
, null);
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
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
))
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)
626 String hostname
= getLocalHostname();
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
)
646 if (hostname
!= null)
650 localhost
= new InetAddress(null, null);
651 lookup(hostname
, localhost
, false);
657 if (localhost
== null)
658 localhost
= new InetAddress (localhostAddress
, "localhost");