39 |
package java.net; |
package java.net; |
40 |
|
|
41 |
import java.io.Serializable; |
import java.io.Serializable; |
42 |
import java.util.Hashtable; |
import java.util.HashMap; |
43 |
import java.util.StringTokenizer; |
import java.util.StringTokenizer; |
44 |
|
|
45 |
import gnu.classpath.Configuration; |
import gnu.classpath.Configuration; |
46 |
|
|
47 |
/** |
/** |
48 |
* This class models an Internet address. It does not have a public |
* This class models an Internet address. It does not have a public |
49 |
* constructor. Instead, new instances of this objects are created |
* constructor. Instead, new instances of this objects are created |
50 |
* using the static methods getLocalHost(), getByName(), and |
* using the static methods getLocalHost(), getByName(), and |
51 |
* getAllByName(). |
* getAllByName(). |
52 |
* <p> |
* <p> |
53 |
* This class fulfills the function of the C style functions gethostname(), |
* This class fulfills the function of the C style functions gethostname(), |
54 |
* gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names |
* gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names |
55 |
* into their corresponding numeric addresses and vice versa. |
* into their corresponding numeric addresses and vice versa. |
56 |
* |
* |
57 |
* @version 0.5 |
* @version 0.5 |
58 |
* |
* |
59 |
* @author Aaron M. Renn (arenn@urbanophile.com) |
* @author Aaron M. Renn (arenn@urbanophile.com) |
60 |
*/ |
*/ |
61 |
public final class InetAddress implements Serializable |
public class InetAddress implements Serializable |
62 |
{ |
{ |
63 |
|
|
64 |
/*************************************************************************/ |
/*************************************************************************/ |
79 |
private static final long serialVersionUID = 3286316764910316507L; |
private static final long serialVersionUID = 3286316764910316507L; |
80 |
|
|
81 |
/** |
/** |
82 |
* The default DNS hash table size |
* The default DNS hash table size, |
83 |
|
* use a prime number happy with hash table |
84 |
*/ |
*/ |
85 |
private static final int DEFAULT_CACHE_SIZE = 400; |
private static final int DEFAULT_CACHE_SIZE = 89; |
86 |
|
|
87 |
/** |
/** |
88 |
* The default caching period in minutes |
* The default caching period in minutes |
119 |
private static int cache_purge_pct = 0; |
private static int cache_purge_pct = 0; |
120 |
|
|
121 |
/** |
/** |
122 |
* Hashtable to use as DNS lookup cache |
* HashMap to use as DNS lookup cachem |
123 |
|
* use HashMap because all accesses to cache are already synchronized |
124 |
*/ |
*/ |
125 |
private static Hashtable cache; |
private static HashMap cache; |
126 |
|
|
127 |
// Static initializer for the cache |
// Static initializer for the cache |
128 |
static |
static |
142 |
|
|
143 |
// Create the cache |
// Create the cache |
144 |
if (cache_size != 0) |
if (cache_size != 0) |
145 |
cache = new Hashtable(cache_size); |
cache = new HashMap (cache_size); |
146 |
|
|
147 |
// precompute the ANY_IF address |
// precompute the ANY_IF address |
148 |
try |
try |
152 |
catch (UnknownHostException uhe) |
catch (UnknownHostException uhe) |
153 |
{ |
{ |
154 |
// Hmmm, make one up and hope that it works. |
// Hmmm, make one up and hope that it works. |
155 |
int[] zeros = {0,0,0,0}; |
byte[] zeros = {0,0,0,0}; |
156 |
ANY_IF = new InetAddress(zeros); |
ANY_IF = new InetAddress(zeros); |
157 |
} |
} |
158 |
} |
} |
166 |
/** |
/** |
167 |
* An array of octets representing an IP address |
* An array of octets representing an IP address |
168 |
*/ |
*/ |
169 |
transient int[] my_ip; |
transient byte[] addr; |
170 |
|
|
171 |
/** |
/** |
172 |
* The name of the host for this address |
* The name of the host for this address |
207 |
private static synchronized InetAddress[] |
private static synchronized InetAddress[] |
208 |
checkCacheFor(String hostname) |
checkCacheFor(String hostname) |
209 |
{ |
{ |
210 |
InetAddress[] addrs = null; |
InetAddress[] addresses = null; |
211 |
|
|
212 |
if (cache_size == 0) |
if (cache_size == 0) |
213 |
return(null); |
return(null); |
217 |
return(null); |
return(null); |
218 |
|
|
219 |
if (obj instanceof InetAddress[]) |
if (obj instanceof InetAddress[]) |
220 |
addrs = (InetAddress[])obj; |
addresses = (InetAddress[])obj; |
221 |
|
|
222 |
if (addrs == null) |
if (addresses == null) |
223 |
return(null); |
return(null); |
224 |
|
|
225 |
if (cache_period != -1) |
if (cache_period != -1) |
226 |
if ((System.currentTimeMillis() - addrs[0].lookup_time) > cache_period) |
if ((System.currentTimeMillis() - addresses[0].lookup_time) > cache_period) |
227 |
{ |
{ |
228 |
cache.remove(hostname); |
cache.remove(hostname); |
229 |
return(null); |
return(null); |
230 |
} |
} |
231 |
|
|
232 |
return(addrs); |
return addresses; |
233 |
} |
} |
234 |
|
|
235 |
/*************************************************************************/ |
/*************************************************************************/ |
241 |
* lookups should set the cache size to be very large. |
* lookups should set the cache size to be very large. |
242 |
* |
* |
243 |
* @param hostname The hostname to cache this address under |
* @param hostname The hostname to cache this address under |
244 |
* @param addr The InetAddress or InetAddress array to store |
* @param obj The InetAddress or InetAddress array to store |
245 |
*/ |
*/ |
246 |
private static synchronized void |
private static synchronized void |
247 |
addToCache(String hostname, Object addr) |
addToCache(String hostname, Object obj) |
248 |
{ |
{ |
249 |
if (cache_size == 0) |
if (cache_size == 0) |
250 |
return; |
return; |
256 |
; //*** Add code to purge later. |
; //*** Add code to purge later. |
257 |
} |
} |
258 |
|
|
259 |
cache.put(hostname, addr); |
cache.put (hostname, obj); |
260 |
} |
} |
261 |
|
|
262 |
/*************************************************************************/ |
/*************************************************************************/ |
274 |
{ |
{ |
275 |
if (inaddr_any == null) |
if (inaddr_any == null) |
276 |
{ |
{ |
277 |
int[] addr = lookupInaddrAny(); |
byte[] tmp = lookupInaddrAny(); |
278 |
inaddr_any = new InetAddress(addr); |
inaddr_any = new InetAddress (tmp); |
279 |
} |
} |
280 |
|
|
281 |
return(inaddr_any); |
return(inaddr_any); |
302 |
// Default to current host if necessary |
// Default to current host if necessary |
303 |
if (hostname == null) |
if (hostname == null) |
304 |
{ |
{ |
305 |
InetAddress addr = getLocalHost(); |
InetAddress local = getLocalHost (); |
306 |
return(getAllByName(addr.getHostName())); |
return getAllByName (local.getHostName ()); |
307 |
} |
} |
308 |
|
|
309 |
// Check the cache for this host before doing a lookup |
// Check the cache for this host before doing a lookup |
310 |
InetAddress[] addrs = checkCacheFor(hostname); |
InetAddress[] addresses = checkCacheFor (hostname); |
311 |
if (addrs != null) |
if (addresses != null) |
312 |
return(addrs); |
return(addresses); |
313 |
|
|
314 |
// Not in cache, try the lookup |
// Not in cache, try the lookup |
315 |
int[][] iplist = getHostByName(hostname); |
byte[][] iplist = getHostByName(hostname); |
316 |
if (iplist.length == 0) |
if (iplist.length == 0) |
317 |
throw new UnknownHostException(hostname); |
throw new UnknownHostException(hostname); |
318 |
|
|
319 |
addrs = new InetAddress[iplist.length]; |
addresses = new InetAddress [iplist.length]; |
320 |
|
|
321 |
for (int i = 0; i < iplist.length; i++) |
for (int i = 0; i < iplist.length; i++) |
322 |
{ |
{ |
327 |
// canonical names of these ip's when the user asks for the hostname |
// canonical names of these ip's when the user asks for the hostname |
328 |
// But do specify the host alias so if the IP returned won't |
// But do specify the host alias so if the IP returned won't |
329 |
// reverse lookup we don't throw an exception. |
// reverse lookup we don't throw an exception. |
330 |
addrs[i] = new InetAddress(iplist[i], null, hostname); |
addresses[i] = new InetAddress (iplist [i], null, hostname); |
331 |
} |
} |
332 |
|
|
333 |
addToCache(hostname, addrs); |
addToCache (hostname, addresses); |
334 |
|
|
335 |
return(addrs); |
return addresses; |
336 |
} |
} |
337 |
|
|
338 |
/*************************************************************************/ |
/*************************************************************************/ |
356 |
{ |
{ |
357 |
// Default to current host if necessary |
// Default to current host if necessary |
358 |
if (hostname == null) |
if (hostname == null) |
359 |
return(getLocalHost()); |
return getLocalHost(); |
360 |
|
|
361 |
// First, check to see if it is an IP address. If so, then don't |
// First, check to see if it is an IP address. If so, then don't |
362 |
// do a DNS lookup. |
// do a DNS lookup. |
364 |
if (st.countTokens() == 4) |
if (st.countTokens() == 4) |
365 |
{ |
{ |
366 |
int i; |
int i; |
367 |
int[] ip = new int[4]; |
byte[] ip = new byte[4]; |
368 |
for (i = 0; i < 4; i++) |
for (i = 0; i < 4; i++) |
369 |
{ |
{ |
370 |
try |
try |
371 |
{ |
{ |
372 |
ip[i] = Integer.parseInt(st.nextToken()); |
ip[i] = Byte.parseByte(st.nextToken()); |
373 |
if ((ip[i] < 0) || (ip[1] > 255)) |
if ((ip[i] < 0) || (ip[1] > 255)) |
374 |
break; |
break; |
375 |
} |
} |
384 |
} |
} |
385 |
} |
} |
386 |
|
|
387 |
// Wasn't and IP, so try the lookup |
// Wasn't an IP, so try the lookup |
388 |
InetAddress[] addrs = getAllByName(hostname); |
InetAddress[] addresses = getAllByName (hostname); |
389 |
|
|
390 |
return(addrs[0]); |
return addresses [0]; |
391 |
} |
} |
392 |
|
|
393 |
/*************************************************************************/ |
/*************************************************************************/ |
400 |
* |
* |
401 |
* @exception UnknownHostException If an error occurs |
* @exception UnknownHostException If an error occurs |
402 |
*/ |
*/ |
403 |
public static InetAddress |
public static InetAddress getLocalHost() throws UnknownHostException |
|
getLocalHost() throws UnknownHostException |
|
404 |
{ |
{ |
405 |
String hostname = getLocalHostName(); |
String hostname = getLocalHostName(); |
406 |
|
return getByName (hostname); |
|
return(getByName(hostname)); |
|
407 |
} |
} |
408 |
|
|
409 |
/*************************************************************************/ |
/*************************************************************************/ |
413 |
*/ |
*/ |
414 |
|
|
415 |
/** |
/** |
416 |
* Initializes this object's my_ip instance variable from the passed in |
* Initializes this object's addr instance variable from the passed in |
417 |
* int array. Note that this constructor is protected and is called |
* int array. Note that this constructor is protected and is called |
418 |
* only by static methods in this class. |
* only by static methods in this class. |
419 |
* |
* |
420 |
* @param addr The IP number of this address as an array of bytes |
* @param ipaddr The IP number of this address as an array of bytes |
421 |
*/ |
*/ |
422 |
private |
//private |
423 |
InetAddress(int[] addr) |
public |
424 |
|
InetAddress(byte[] ipaddr) |
425 |
{ |
{ |
426 |
this(addr, null, null); |
this (ipaddr, null, null); |
427 |
} |
} |
428 |
|
|
429 |
/*************************************************************************/ |
/*************************************************************************/ |
430 |
|
|
431 |
/** |
/** |
432 |
* Initializes this object's my_ip instance variable from the passed in |
* Initializes this object's addr instance variable from the passed in |
433 |
* int array. Note that this constructor is protected and is called |
* int array. Note that this constructor is protected and is called |
434 |
* only by static methods in this class. |
* only by static methods in this class. |
435 |
* |
* |
436 |
* @param addr The IP number of this address as an array of bytes |
* @param ipaddr The IP number of this address as an array of bytes |
437 |
* @param hostname The hostname of this IP address. |
* @param hostname The hostname of this IP address. |
438 |
*/ |
*/ |
439 |
private |
//private |
440 |
InetAddress(int[] addr, String hostname) |
public |
441 |
|
InetAddress(byte[] ipaddr, String hostname) |
442 |
{ |
{ |
443 |
this(addr, hostname, null); |
this (ipaddr, hostname, null); |
444 |
} |
} |
445 |
|
|
446 |
/*************************************************************************/ |
/*************************************************************************/ |
447 |
|
|
448 |
/** |
/** |
449 |
* Initializes this object's my_ip instance variable from the passed in |
* Initializes this object's addr instance variable from the passed in |
450 |
* int array. Note that this constructor is protected and is called |
* int array. Note that this constructor is protected and is called |
451 |
* only by static methods in this class. |
* only by static methods in this class. |
452 |
* |
* |
453 |
* @param addr The IP number of this address as an array of bytes |
* @param ipaddr The IP number of this address as an array of bytes |
454 |
* @param hostname The hostname of this IP address. |
* @param hostname The hostname of this IP address. |
455 |
* @param hostname_alias A backup hostname to use if hostname is null to prevent reverse lookup failures |
* @param hostname_alias A backup hostname to use if hostname is null to prevent reverse lookup failures |
456 |
*/ |
*/ |
457 |
private |
//private |
458 |
InetAddress(int[] addr, String hostname, String hostname_alias) |
public |
459 |
|
InetAddress(byte[] ipaddr, String hostname, String hostname_alias) |
460 |
{ |
{ |
461 |
my_ip = new int[addr.length]; |
addr = new byte [ipaddr.length]; |
462 |
|
|
463 |
for (int i = 0; i < addr.length; i++) |
for (int i = 0; i < ipaddr.length; i++) |
464 |
my_ip[i] = addr[i]; |
addr [i] = ipaddr [i]; |
465 |
|
|
466 |
this.hostName = hostname; |
this.hostName = hostname; |
467 |
this.hostname_alias = hostname_alias; |
this.hostname_alias = hostname_alias; |
486 |
* addresses are considered equal if they contain the exact same octets. |
* addresses are considered equal if they contain the exact same octets. |
487 |
* This implementation overrides Object.equals() |
* This implementation overrides Object.equals() |
488 |
* |
* |
489 |
* @param addr The address to test for equality |
* @param obj The address to test for equality |
490 |
* |
* |
491 |
* @return true if the passed in object's address is equal to this one's, false otherwise |
* @return true if the passed in object's address is equal to this one's, |
492 |
|
* false otherwise |
493 |
*/ |
*/ |
494 |
public boolean |
public boolean |
495 |
equals(Object addr) |
equals(Object obj) |
496 |
{ |
{ |
497 |
if (!(addr instanceof InetAddress)) |
if (! (obj instanceof InetAddress)) |
498 |
return(false); |
return false; |
499 |
|
|
500 |
byte[] test_ip = ((InetAddress)addr).getAddress(); |
byte[] test_ip = ((InetAddress) obj).getAddress(); |
501 |
|
|
502 |
if (test_ip.length != my_ip.length) |
if (test_ip.length != addr.length) |
503 |
return(false); |
return(false); |
504 |
|
|
505 |
for (int i = 0; i < my_ip.length; i++) |
for (int i = 0; i < addr.length; i++) |
506 |
if (test_ip[i] != (byte)my_ip[i]) |
if (test_ip [i] != (byte) addr [i]) |
507 |
return(false); |
return(false); |
508 |
|
|
509 |
return(true); |
return(true); |
519 |
public byte[] |
public byte[] |
520 |
getAddress() |
getAddress() |
521 |
{ |
{ |
522 |
byte[] addr = new byte[my_ip.length]; |
byte[] ipaddr = new byte [addr.length]; |
523 |
|
|
524 |
for (int i = 0; i < my_ip.length; i++) |
for (int i = 0; i < addr.length; i++) |
525 |
{ |
{ |
526 |
addr[i] = (byte)my_ip[i]; |
ipaddr [i] = (byte) addr [i]; |
527 |
} |
} |
528 |
|
|
529 |
return(addr); |
return ipaddr; |
530 |
} |
} |
531 |
|
|
532 |
/*************************************************************************/ |
/*************************************************************************/ |
540 |
public String |
public String |
541 |
getHostAddress() |
getHostAddress() |
542 |
{ |
{ |
543 |
StringBuffer addr = new StringBuffer(); |
StringBuffer sb = new StringBuffer(); |
544 |
|
|
545 |
for (int i = 0; i < my_ip.length; i++) |
for (int i = 0; i < addr.length; i++) |
546 |
{ |
{ |
547 |
addr.append((int)my_ip[i]); |
sb.append ((int) addr [i]); |
548 |
if (i < (my_ip.length - 1)) |
if (i < (addr.length - 1)) |
549 |
addr.append("."); |
sb.append("."); |
550 |
} |
} |
551 |
|
|
552 |
return(addr.toString()); |
return sb.toString(); |
553 |
} |
} |
554 |
|
|
555 |
/*************************************************************************/ |
/*************************************************************************/ |
568 |
|
|
569 |
try |
try |
570 |
{ |
{ |
571 |
hostName = getHostByAddr(my_ip); |
hostName = getHostByAddr (addr); |
572 |
return(hostName); |
return(hostName); |
573 |
} |
} |
574 |
catch (UnknownHostException e) |
catch (UnknownHostException e) |
595 |
|
|
596 |
// Its obvious here that I have no idea how to generate a good |
// Its obvious here that I have no idea how to generate a good |
597 |
// hash key |
// hash key |
598 |
for (int i = 0; i < my_ip.length; i++) |
for (int i = 0; i < addr.length; i++) |
599 |
val1 = val1 + (my_ip[i] << ((my_ip.length - i) / 8)); |
val1 = val1 + (addr [i] << ((addr.length - i) / 8)); |
600 |
|
|
601 |
for (int i = 0; i < my_ip.length; i++) |
for (int i = 0; i < addr.length; i++) |
602 |
val2 = val2 + (my_ip[i] * 10 * i); |
val2 = val2 + (addr [i] * 10 * i); |
603 |
|
|
604 |
val1 = (val1 >> 1) ^ val2; |
val1 = (val1 >> 1) ^ val2; |
605 |
|
|
618 |
public boolean |
public boolean |
619 |
isMulticastAddress() |
isMulticastAddress() |
620 |
{ |
{ |
621 |
if (my_ip.length == 0) |
if (addr.length == 0) |
622 |
return(false); |
return(false); |
623 |
|
|
624 |
// Mask against high order bits of 1110 |
// Mask against high order bits of 1110 |
625 |
if ((my_ip[0] & 0xF0) == 224) |
if ((addr [0] & 0xF0) == 224) |
626 |
return(true); |
return(true); |
627 |
|
|
628 |
return(false); |
return(false); |
643 |
return(getHostAddress()); |
return(getHostAddress()); |
644 |
} |
} |
645 |
|
|
646 |
|
/** |
647 |
|
* Returns an InetAddress object given the raw IP address. |
648 |
|
* |
649 |
|
* The argument is in network byte order: the highest order byte of the |
650 |
|
* address is in getAddress()[0]. |
651 |
|
* |
652 |
|
* @param addr The IP address to create the InetAddress object from |
653 |
|
* |
654 |
|
* @exception UnknownHostException If IP address has illegal length |
655 |
|
* |
656 |
|
* @since 1.4 |
657 |
|
*/ |
658 |
|
public static InetAddress getByAddress(byte[] addr) |
659 |
|
throws UnknownHostException |
660 |
|
{ |
661 |
|
if (addr.length != 4 && addr.length != 16) |
662 |
|
throw new UnknownHostException ("IP address has illegal length"); |
663 |
|
|
664 |
|
if (addr.length == 4) |
665 |
|
return new Inet4Address (addr, null); |
666 |
|
|
667 |
|
return new Inet6Address (addr, null); |
668 |
|
} |
669 |
|
|
670 |
/*************************************************************************/ |
/*************************************************************************/ |
671 |
|
|
672 |
/* |
/* |
688 |
/** |
/** |
689 |
* Returns the value of the special address INADDR_ANY |
* Returns the value of the special address INADDR_ANY |
690 |
*/ |
*/ |
691 |
private static native int[] lookupInaddrAny() throws UnknownHostException; |
private static native byte[] lookupInaddrAny() throws UnknownHostException; |
692 |
|
|
693 |
/*************************************************************************/ |
/*************************************************************************/ |
694 |
|
|
702 |
* |
* |
703 |
* @exception UnknownHostException If the reverse lookup fails |
* @exception UnknownHostException If the reverse lookup fails |
704 |
*/ |
*/ |
705 |
private static native String getHostByAddr(int[] ip) throws UnknownHostException; |
private static native String getHostByAddr(byte[] ip) throws UnknownHostException; |
706 |
|
|
707 |
/*************************************************************************/ |
/*************************************************************************/ |
708 |
|
|
710 |
* Returns a list of all IP addresses for a given hostname. Will throw |
* Returns a list of all IP addresses for a given hostname. Will throw |
711 |
* an UnknownHostException if the hostname cannot be resolved. |
* an UnknownHostException if the hostname cannot be resolved. |
712 |
*/ |
*/ |
713 |
private static native int[][] getHostByName(String hostname) throws UnknownHostException; |
private static native byte[][] getHostByName(String hostname) throws UnknownHostException; |
714 |
|
|
715 |
} // class InetAddress |
} // class InetAddress |
716 |
|
|