1 /* InetAddress.java -- Class to model an Internet address
2 Copyright (C) 1998, 1999, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, 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
.IOException
;
42 import java
.io
.ObjectInputStream
;
43 import java
.io
.ObjectOutputStream
;
44 import java
.io
.ObjectStreamException
;
45 import java
.io
.Serializable
;
46 import java
.util
.StringTokenizer
;
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
54 * <p>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.</p>
58 * @author Aaron M. Renn (arenn@urbanophile.com)
61 * @specnote This class is not final since JK 1.4
63 public class InetAddress
implements Serializable
65 private static final long serialVersionUID
= 3286316764910316507L;
68 * The special IP address INADDR_ANY.
70 private static InetAddress inaddr_any
;
73 * Dummy InetAddress, used to bind socket to any (all) network interfaces.
75 static InetAddress ANY_IF
;
78 * Stores static localhost address object.
80 static InetAddress LOCALHOST
;
84 // precompute the ANY_IF address
87 ANY_IF
= getInaddrAny();
89 byte[] ip_localhost
= { 127, 0, 0, 1 };
90 LOCALHOST
= new Inet4Address(ip_localhost
, "localhost");
92 catch (UnknownHostException uhe
)
94 // Hmmm, make one up and hope that it works.
95 byte[] zeros
= { 0, 0, 0, 0 };
96 ANY_IF
= new Inet4Address(zeros
, "0.0.0.0");
101 * The Serialized Form specifies that an int 'address' is saved/restored.
102 * This class uses a byte array internally so we'll just do the conversion
103 * at serialization time and leave the rest of the algorithm as is.
108 * An array of octets representing an IP address.
110 transient byte[] addr
;
113 * The name of the host for this address.
118 * The field 'family' seems to be the AF_ value.
119 * FIXME: Much of the code in the other java.net classes does not make
120 * use of this family field. A better implementation would be to make
121 * use of getaddrinfo() and have other methods just check the family
122 * field rather than examining the length of the address each time.
127 * Initializes this object's addr instance variable from the passed in
128 * byte 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[] ipaddr
, String hostname
)
136 addr
= (null == ipaddr
) ?
null : (byte[]) ipaddr
.clone();
139 family
= 2; /* AF_INET */
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;
161 * Utility routine to check if the InetAddress in a wildcard address
165 public boolean isAnyLocalAddress()
167 // This is the IPv4 implementation.
168 // Any class derived from InetAddress should override this.
169 return equals(ANY_IF
);
173 * Utility routine to check if the InetAddress is a loopback address
177 public boolean isLoopbackAddress()
179 // This is the IPv4 implementation.
180 // Any class derived from InetAddress should override this.
181 return (addr
[0] & 0xff) == 0x7f;
185 * Utility routine to check if InetAddress is a link local address
189 public boolean isLinkLocalAddress()
191 // This is the IPv4 implementation.
192 // Any class derived from InetAddress should override this.
193 // XXX: This seems to not exist with IPv4 addresses
198 * Utility routine to check if InetAddress is a site local address
202 public boolean isSiteLocalAddress()
204 // This is the IPv4 implementation.
205 // Any class derived from InetAddress should override this.
208 if ((addr
[0] & 0xff) == 0x0a)
212 if ((addr
[0] & 0xff) == 0xac && (addr
[1] & 0xf0) == 0x10)
216 if ((addr
[0] & 0xff) == 0xc0 && (addr
[1] & 0xff) == 0xa8)
219 // XXX: Do we need to check more addresses here ?
224 * Utility routine to check if InetAddress is a global multicast address
228 public boolean isMCGlobal()
230 // This is the IPv4 implementation.
231 // Any class derived from InetAddress should override this.
232 // XXX: This seems to not exist with IPv4 addresses
237 * Utility routine to check if InetAddress is a node local multicast address.
241 public boolean isMCNodeLocal()
243 // This is the IPv4 implementation.
244 // Any class derived from InetAddress should override this.
245 // XXX: This seems to not exist with IPv4 addresses
250 * Utility routine to check if InetAddress is a link local multicast address.
254 public boolean isMCLinkLocal()
256 // This is the IPv4 implementation.
257 // Any class derived from InetAddress should override this.
258 if (! isMulticastAddress())
261 return ((addr
[0] & 0xff) == 0xe0
262 && (addr
[1] & 0xff) == 0x00
263 && (addr
[2] & 0xff) == 0x00);
267 * Utility routine to check if InetAddress is a site local multicast address.
271 public boolean isMCSiteLocal()
273 // This is the IPv4 implementation.
274 // Any class derived from InetAddress should override this.
275 // XXX: This seems to not exist with IPv4 addresses
280 * Utility routine to check if InetAddress is a organization local
285 public boolean isMCOrgLocal()
287 // This is the IPv4 implementation.
288 // Any class derived from InetAddress should override this.
289 // XXX: This seems to not exist with IPv4 addresses
294 * Returns the hostname for this address. This will return the IP address
295 * as a String if there is no hostname available for this address
297 * @return The hostname for this address
299 public String
getHostName()
301 if (hostName
!= null)
306 hostName
= VMInetAddress
.getHostByAddr(addr
);
309 catch (UnknownHostException e
)
311 return getHostAddress();
316 * Returns the canonical hostname represented by this InetAddress
320 public String
getCanonicalHostName()
322 SecurityManager sm
= System
.getSecurityManager();
327 sm
.checkConnect(hostName
, -1);
329 catch (SecurityException e
)
331 return getHostAddress();
335 // Try to find the FDQN now
337 byte[] ipaddr
= getAddress();
339 if (ipaddr
.length
== 16)
340 address
= new Inet6Address(getAddress(), null);
342 address
= new Inet4Address(getAddress(), null);
344 return address
.getHostName();
348 * Returns the IP address of this object as a byte array.
352 public byte[] getAddress()
354 // An experiment shows that JDK1.2 returns a different byte array each
355 // time. This makes sense, in terms of security.
356 return (byte[]) addr
.clone();
360 * Returns the IP address of this object as a String. The address is in
361 * the dotted octet notation, for example, "127.0.0.1".
363 * @return The IP address of this object in String form
367 public String
getHostAddress()
369 StringBuffer sb
= new StringBuffer(40);
371 int len
= addr
.length
;
376 sb
.append(addr
[i
] & 0xff);
385 return sb
.toString();
389 * Returns a hash value for this address. Useful for creating hash
390 * tables. Overrides Object.hashCode()
392 * @return A hash value for this address.
394 public int hashCode()
396 // There hashing algorithm is not specified, but a simple experiment
397 // shows that it is equal to the address, as a 32-bit big-endian integer.
399 int len
= addr
.length
;
400 int i
= len
> 4 ? len
- 4 : 0;
403 hash
= (hash
<< 8) | (addr
[i
] & 0xff);
409 * Tests this address for equality against another InetAddress. The two
410 * addresses are considered equal if they contain the exact same octets.
411 * This implementation overrides Object.equals()
413 * @param obj The address to test for equality
415 * @return true if the passed in object's address is equal to this one's,
418 public boolean equals(Object obj
)
420 if (! (obj
instanceof InetAddress
))
423 // "The Java Class Libraries" 2nd edition says "If a machine has
424 // multiple names instances of InetAddress for different name of
425 // that same machine are not equal. This is because they have
426 // different host names." This violates the description in the
427 // JDK 1.2 API documentation. A little experimentation
428 // shows that the latter is correct.
429 byte[] addr2
= ((InetAddress
) obj
).addr
;
431 if (addr
.length
!= addr2
.length
)
434 for (int i
= 0; i
< addr
.length
; i
++)
435 if (addr
[i
] != addr2
[i
])
442 * Converts this address to a String. This string contains the IP in
443 * dotted decimal form. For example: "127.0.0.1" This method is equivalent
444 * to getHostAddress() and overrides Object.toString()
446 * @return This address in String form
448 public String
toString()
450 String addr
= getHostAddress();
451 String host
= (hostName
!= null) ? hostName
: "";
452 return host
+ "/" + addr
;
456 * Returns an InetAddress object given the raw IP address.
458 * The argument is in network byte order: the highest order byte of the
459 * address is in getAddress()[0].
461 * @param addr The IP address to create the InetAddress object from
463 * @exception UnknownHostException If IP address has illegal length
467 public static InetAddress
getByAddress(byte[] addr
)
468 throws UnknownHostException
470 return getByAddress(null, addr
);
474 * Creates an InetAddress based on the provided host name and IP address.
475 * No name service is checked for the validity of the address.
477 * @param host The hostname of the InetAddress object to create
478 * @param addr The IP address to create the InetAddress object from
480 * @exception UnknownHostException If IP address is of illegal length
484 public static InetAddress
getByAddress(String host
, byte[] addr
)
485 throws UnknownHostException
487 if (addr
.length
== 4)
488 return new Inet4Address(addr
, host
);
490 if (addr
.length
== 16)
491 return new Inet6Address(addr
, host
);
493 throw new UnknownHostException("IP address has illegal length");
497 * If hostname is a valid numeric IP address, return the numeric address.
498 * Otherwise, return null.
500 * @param hostname the name of the host
502 private static byte[] aton(String hostname
)
504 StringTokenizer st
= new StringTokenizer(hostname
, ".");
506 if (st
.countTokens() == 4)
509 byte[] address
= new byte[4];
511 for (index
= 0; index
< 4; index
++)
515 short n
= Short
.parseShort(st
.nextToken());
517 if ((n
< 0) || (n
> 255))
520 address
[index
] = (byte) n
;
522 catch (NumberFormatException e
)
536 * Returns an InetAddress object representing the IP address of the given
537 * hostname. This name can be either a hostname such as "www.urbanophile.com"
538 * or an IP address in dotted decimal format such as "127.0.0.1". If the
539 * hostname is null or "", the hostname of the local machine is supplied by
540 * default. This method is equivalent to returning the first element in
541 * the InetAddress array returned from GetAllByName.
543 * @param hostname The name of the desired host, or null for the local
546 * @return The address of the host as an InetAddress object.
548 * @exception UnknownHostException If no IP address for the host could
550 * @exception SecurityException If a security manager exists and its
551 * checkConnect method doesn't allow the operation
553 public static InetAddress
getByName(String hostname
)
554 throws UnknownHostException
556 InetAddress
[] addresses
= getAllByName(hostname
);
561 * Returns an array of InetAddress objects representing all the host/ip
562 * addresses of a given host, given the host's name. This name can be
563 * either a hostname such as "www.urbanophile.com" or an IP address in
564 * dotted decimal format such as "127.0.0.1". If the value is null, the
565 * hostname of the local machine is supplied by default.
567 * @param hostname The name of the desired host, or null for the
568 * local loopback address.
570 * @return All addresses of the host as an array of InetAddress objects.
572 * @exception UnknownHostException If no IP address for the host could
574 * @exception SecurityException If a security manager exists and its
575 * checkConnect method doesn't allow the operation
577 public static InetAddress
[] getAllByName(String hostname
)
578 throws UnknownHostException
580 SecurityManager s
= System
.getSecurityManager();
582 s
.checkConnect(hostname
, -1);
584 InetAddress
[] addresses
;
586 if (hostname
!= null)
587 hostname
= hostname
.trim();
589 // Default to current host if necessary
590 if (hostname
== null || hostname
.equals(""))
592 addresses
= new InetAddress
[1];
593 addresses
[0] = LOCALHOST
;
597 // Not in cache, try the lookup
598 byte[][] iplist
= VMInetAddress
.getHostByName(hostname
);
600 if (iplist
.length
== 0)
601 throw new UnknownHostException(hostname
);
603 addresses
= new InetAddress
[iplist
.length
];
605 for (int i
= 0; i
< iplist
.length
; i
++)
607 if (iplist
[i
].length
!= 4)
608 throw new UnknownHostException(hostname
);
610 addresses
[i
] = new Inet4Address(iplist
[i
], hostname
);
617 * Returns the special address INADDR_ANY used for binding to a local
618 * port on all IP addresses hosted by a the local host.
620 * @return An InetAddress object representing INDADDR_ANY
622 * @exception UnknownHostException If an error occurs
624 static InetAddress
getInaddrAny() throws UnknownHostException
626 if (inaddr_any
== null)
628 byte[] tmp
= VMInetAddress
.lookupInaddrAny();
629 inaddr_any
= new Inet4Address(tmp
, null);
630 inaddr_any
.hostName
= inaddr_any
.getHostName();
637 * Returns an InetAddress object representing the address of the current
640 * @return The local host's address
642 * @exception UnknownHostException If no IP address for the host could
645 public static InetAddress
getLocalHost() throws UnknownHostException
647 String hostname
= VMInetAddress
.getLocalHostname();
648 return getByName(hostname
);
652 * Needed for serialization
654 private void readResolve() throws ObjectStreamException
656 // FIXME: implement this
659 private void readObject(ObjectInputStream ois
)
660 throws IOException
, ClassNotFoundException
662 ois
.defaultReadObject();
664 addr
[3] = (byte) address
;
666 for (int i
= 2; i
>= 0; --i
)
667 addr
[i
] = (byte) (address
>>= 8);
669 family
= 2; /* AF_INET */
672 private void writeObject(ObjectOutputStream oos
) throws IOException
674 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
675 // or a 16 byte IPv6 address.
676 int len
= addr
.length
;
680 address
= address
<< 8 | (addr
[i
] & 0xff);
682 oos
.defaultWriteObject();