diff options
author | Gary Benson <gbenson@redhat.com> | 2006-09-08 08:59:56 +0000 |
---|---|---|
committer | Gary Benson <gbenson@redhat.com> | 2006-09-08 08:59:56 +0000 |
commit | 0ae878b1c7ebd515bdd68de62adfc848e07b12d9 (patch) | |
tree | 0a8b7a6c25dd02b73995b92059f75729224162dc | |
parent | ea6df337f9f6bc1fefb78e5d2ebce16593e3b6e9 (diff) | |
download | classpath-0ae878b1c7ebd515bdd68de62adfc848e07b12d9.tar.gz |
2006-09-08 Gary Benson <gbenson@redhat.com>
* java/net/InetAddress.java
(inaddr_any): Removed.
(ANY_IF, LOCALHOST): Create using getByAddress.
(<init>): Updated javadoc.
(getHostName): Cache hostname even if the lookup failed.
(getByAddress): Create Inet4Address objects when passed
IPv4-mapped IPv6 addresses.
(aton): Removed.
(getAllByName): Create address objects using getByAddress.
Do not perform security checks unless actually required.
Do not strip whitespace from the hostname.
(getInaddrAny): Removed.
(getLocalHost): Return the loopback address if getByName
throws a SecurityException.
(readResolve): Updated javadoc.
* vm/reference/java/net/VMInetAddress.java (aton): Declared.
* include/java_net_VMInetAddress.h
(Java_java_net_VMInetAddress_aton): Likewise.
* native/jni/java-net/java_net_VMInetAddress.c
(Java_java_net_VMInetAddress_aton): New method.
* native/jni/native-lib/cpnet.h (cpnet_aton): Declared.
* native/jni/native-lib/cpnet.c (cpnet_aton): New method.
* configure.ac (AC_CHECK_FUNCS): Checks for cpnet_aton.
* java/net/Inet4Address.java (writeReplace): Updated javadoc.
* NEWS: Added note about updated VM interface.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | include/java_net_VMInetAddress.h | 1 | ||||
-rw-r--r-- | java/net/Inet4Address.java | 2 | ||||
-rw-r--r-- | java/net/InetAddress.java | 185 | ||||
-rw-r--r-- | native/jni/java-net/java_net_VMInetAddress.c | 87 | ||||
-rw-r--r-- | native/jni/native-lib/cpnet.c | 44 | ||||
-rw-r--r-- | native/jni/native-lib/cpnet.h | 1 | ||||
-rw-r--r-- | vm/reference/java/net/VMInetAddress.java | 10 |
9 files changed, 223 insertions, 109 deletions
@@ -16,6 +16,7 @@ New in release 0.93 (UNRELEASED) * Added firstNonNullClassLoader method to vm/reference/gnu/classpath/VMStackWalker.java. VMs are encouraged to provide a more efficient implementation. +* Added aton method to vm/reference/java/net/VMInetAddress.java. New in release 0.92 (Aug 9, 2006) diff --git a/configure.ac b/configure.ac index 99a3fc5fe..1f6826118 100644 --- a/configure.ac +++ b/configure.ac @@ -373,6 +373,7 @@ if test "x${COMPILE_JNI}" = xyes; then fcntl \ mmap munmap mincore msync madvise getpagesize sysconf \ lstat readlink \ + inet_aton inet_addr inet_pton \ ]) LIBMAGIC= diff --git a/include/java_net_VMInetAddress.h b/include/java_net_VMInetAddress.h index 54b57f220..66f473577 100644 --- a/include/java_net_VMInetAddress.h +++ b/include/java_net_VMInetAddress.h @@ -14,6 +14,7 @@ JNIEXPORT jstring JNICALL Java_java_net_VMInetAddress_getLocalHostname (JNIEnv * JNIEXPORT jbyteArray JNICALL Java_java_net_VMInetAddress_lookupInaddrAny (JNIEnv *env, jclass); JNIEXPORT jstring JNICALL Java_java_net_VMInetAddress_getHostByAddr (JNIEnv *env, jclass, jbyteArray); JNIEXPORT jobjectArray JNICALL Java_java_net_VMInetAddress_getHostByName (JNIEnv *env, jclass, jstring); +JNIEXPORT jbyteArray JNICALL Java_java_net_VMInetAddress_aton (JNIEnv *env, jclass, jstring); #ifdef __cplusplus } diff --git a/java/net/Inet4Address.java b/java/net/Inet4Address.java index c80f1f175..2a0f2b439 100644 --- a/java/net/Inet4Address.java +++ b/java/net/Inet4Address.java @@ -57,7 +57,7 @@ public final class Inet4Address extends InetAddress static final long serialVersionUID = 3286316764910316507L; /** - * needed for serialization + * Inet4Address objects are serialized as InetAddress objects. */ private Object writeReplace() throws ObjectStreamException { diff --git a/java/net/InetAddress.java b/java/net/InetAddress.java index ce65bc773..0c281fb6b 100644 --- a/java/net/InetAddress.java +++ b/java/net/InetAddress.java @@ -1,5 +1,6 @@ /* InetAddress.java -- Class to model an Internet address - Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,7 +44,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; -import java.util.StringTokenizer; /** * This class models an Internet address. It does not have a public @@ -57,6 +57,7 @@ import java.util.StringTokenizer; * * @author Aaron M. Renn (arenn@urbanophile.com) * @author Per Bothner + * @author Gary Benson (gbenson@redhat.com) * * @specnote This class is not final since JK 1.4 */ @@ -65,37 +66,47 @@ public class InetAddress implements Serializable private static final long serialVersionUID = 3286316764910316507L; /** - * The special IP address INADDR_ANY. - */ - private static InetAddress inaddr_any; - - /** * Dummy InetAddress, used to bind socket to any (all) network interfaces. */ static InetAddress ANY_IF; - + static + { + byte[] addr; + try + { + addr = VMInetAddress.lookupInaddrAny(); + } + catch (UnknownHostException e) + { + // Make one up and hope it works. + addr = new byte[] {0, 0, 0, 0}; + } + try + { + ANY_IF = getByAddress(addr); + } + catch (UnknownHostException e) + { + throw new RuntimeException("should never happen", e); + } + ANY_IF.hostName = ANY_IF.getHostName(); + } + /** * Stores static localhost address object. */ static InetAddress LOCALHOST; - static { - // precompute the ANY_IF address try { - ANY_IF = getInaddrAny(); - - byte[] ip_localhost = { 127, 0, 0, 1 }; - LOCALHOST = new Inet4Address(ip_localhost, "localhost"); + LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1}); } - catch (UnknownHostException uhe) + catch (UnknownHostException e) { - // Hmmm, make one up and hope that it works. - byte[] zeros = { 0, 0, 0, 0 }; - ANY_IF = new Inet4Address(zeros, "0.0.0.0"); + throw new RuntimeException("should never happen", e); } - } + } /** * The Serialized Form specifies that an int 'address' is saved/restored. @@ -124,9 +135,13 @@ public class InetAddress implements Serializable int family; /** - * Initializes this object's addr instance variable from the passed in - * byte array. Note that this constructor is protected and is called - * only by static methods in this class. + * Constructor. Prior to the introduction of IPv6 support in 1.4, + * methods such as InetAddress.getByName() would return InetAddress + * objects. From 1.4 such methods returned either Inet4Address or + * Inet6Address objects, but for compatibility Inet4Address objects + * are serialized as InetAddresses. As such, there are only two + * places where it is appropriate to invoke this constructor: within + * subclasses constructors and within Inet4Address.writeReplace(). * * @param ipaddr The IP number of this address as an array of bytes * @param hostname The hostname of this IP address. @@ -304,12 +319,13 @@ public class InetAddress implements Serializable try { hostName = VMInetAddress.getHostByAddr(addr); - return hostName; } catch (UnknownHostException e) { - return getHostAddress(); + hostName = getHostAddress(); } + + return hostName; } /** @@ -488,48 +504,22 @@ public class InetAddress implements Serializable return new Inet4Address(addr, host); if (addr.length == 16) - return new Inet6Address(addr, host); - - throw new UnknownHostException("IP address has illegal length"); - } - - /** - * If hostname is a valid numeric IP address, return the numeric address. - * Otherwise, return null. - * - * @param hostname the name of the host - */ - private static byte[] aton(String hostname) - { - StringTokenizer st = new StringTokenizer(hostname, "."); - - if (st.countTokens() == 4) { - int index; - byte[] address = new byte[4]; - - for (index = 0; index < 4; index++) + for (int i = 0; i < 12; i++) { - try - { - short n = Short.parseShort(st.nextToken()); - - if ((n < 0) || (n > 255)) - break; - - address[index] = (byte) n; - } - catch (NumberFormatException e) - { - break; - } + if (addr[i] != (i < 10 ? 0 : (byte) 0xFF)) + return new Inet6Address(addr, host); } - - if (index == 4) - return address; + + byte[] ip4addr = new byte[4]; + ip4addr[0] = addr[12]; + ip4addr[1] = addr[13]; + ip4addr[2] = addr[14]; + ip4addr[3] = addr[15]; + return new Inet4Address(ip4addr, host); } - return null; + throw new UnknownHostException("IP address has illegal length"); } /** @@ -577,63 +567,34 @@ public class InetAddress implements Serializable public static InetAddress[] getAllByName(String hostname) throws UnknownHostException { - SecurityManager s = System.getSecurityManager(); - if (s != null) - s.checkConnect(hostname, -1); - - InetAddress[] addresses; + // If null or the empty string is supplied, the loopback address + // is returned. + if (hostname == null || hostname.length() == 0) + return new InetAddress[] {LOCALHOST}; - if (hostname != null) - hostname = hostname.trim(); + // Check if hostname is an IP address + byte[] address = VMInetAddress.aton(hostname); + if (address != null) + return new InetAddress[] {getByAddress(address)}; - // Default to current host if necessary - if (hostname == null || hostname.equals("")) - { - addresses = new InetAddress[1]; - addresses[0] = LOCALHOST; - return addresses; - } + // Perform security check before resolving + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(hostname, -1); - // Not in cache, try the lookup + // Resolve the hostname byte[][] iplist = VMInetAddress.getHostByName(hostname); - if (iplist.length == 0) throw new UnknownHostException(hostname); - addresses = new InetAddress[iplist.length]; - + InetAddress[] addresses = new InetAddress[iplist.length]; for (int i = 0; i < iplist.length; i++) - { - if (iplist[i].length != 4) - throw new UnknownHostException(hostname); - - addresses[i] = new Inet4Address(iplist[i], hostname); - } + addresses[i] = getByAddress(hostname, iplist[i]); return addresses; } /** - * Returns the special address INADDR_ANY used for binding to a local - * port on all IP addresses hosted by a the local host. - * - * @return An InetAddress object representing INDADDR_ANY - * - * @exception UnknownHostException If an error occurs - */ - static InetAddress getInaddrAny() throws UnknownHostException - { - if (inaddr_any == null) - { - byte[] tmp = VMInetAddress.lookupInaddrAny(); - inaddr_any = new Inet4Address(tmp, null); - inaddr_any.hostName = inaddr_any.getHostName(); - } - - return inaddr_any; - } - - /** * Returns an InetAddress object representing the address of the current * host. * @@ -645,11 +606,19 @@ public class InetAddress implements Serializable public static InetAddress getLocalHost() throws UnknownHostException { String hostname = VMInetAddress.getLocalHostname(); - return getByName(hostname); + try + { + return getByName(hostname); + } + catch (SecurityException e) + { + return LOCALHOST; + } } - /* - * Needed for serialization + /** + * Inet4Address objects are serialized as InetAddress objects. + * This deserializes them back into Inet4Address objects. */ private Object readResolve() throws ObjectStreamException { diff --git a/native/jni/java-net/java_net_VMInetAddress.c b/native/jni/java-net/java_net_VMInetAddress.c index 2ca0545fe..fc921ecef 100644 --- a/native/jni/java-net/java_net_VMInetAddress.c +++ b/native/jni/java-net/java_net_VMInetAddress.c @@ -299,4 +299,91 @@ Java_java_net_VMInetAddress_getHostByName (JNIEnv * env, #endif /* not WITHOUT_NETWORK */ } +/*************************************************************************/ + +/* + * Return the IP address represented by a literal address. + * Will return null if the literal address is not valid. + */ +JNIEXPORT jbyteArray JNICALL +Java_java_net_VMInetAddress_aton (JNIEnv *env, + jclass class + __attribute__ ((__unused__)), + jstring host) +{ +#ifndef WITHOUT_NETWORK + const char *hostname; + cpnet_address *address; + int result; + jbyte *octets; + jbyteArray ret_octets; + + hostname = (*env)->GetStringUTFChars (env, host, 0); + if (!hostname) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Null hostname"); + return (jbyteArray) NULL; + } + + result = cpnet_aton (env, hostname, &address); + if (result != CPNATIVE_OK) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + if (address) + cpnet_freeAddress (env, address); + return (jbyteArray) NULL; + } + if (!address) + return (jbyteArray) NULL; + + if (cpnet_isIPV6Address (address)) + { + ret_octets = (jbyteArray) (*env)->NewByteArray (env, 16); + + if (!ret_octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + cpnet_freeAddress (env, address); + return (jbyteArray) NULL; + } + + octets = (*env)->GetByteArrayElements (env, ret_octets, 0); + + cpnet_IPV6AddressToBytes (address, octets); + + (*env)->ReleaseByteArrayElements (env, ret_octets, octets, 0); + } + else if (cpnet_isIPV4Address (address)) + { + ret_octets = (jbyteArray) (*env)->NewByteArray (env, 4); + + if (!ret_octets) + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + cpnet_freeAddress (env, address); + return (jbyteArray) NULL; + } + + octets = (*env)->GetByteArrayElements (env, ret_octets, 0); + + cpnet_IPV4AddressToBytes (address, octets); + + (*env)->ReleaseByteArrayElements (env, ret_octets, octets, 0); + } + else + { + JCL_ThrowException (env, UNKNOWN_HOST_EXCEPTION, "Internal Error"); + cpnet_freeAddress (env, address); + return (jbyteArray) NULL; + } + + cpnet_freeAddress (env, address); + + return (ret_octets); + +#else /* not WITHOUT_NETWORK */ + return (jbyteArray) NULL; +#endif /* not WITHOUT_NETWORK */ +} + /* end of file */ diff --git a/native/jni/native-lib/cpnet.c b/native/jni/native-lib/cpnet.c index c112ac2a7..e8d0a5f07 100644 --- a/native/jni/native-lib/cpnet.c +++ b/native/jni/native-lib/cpnet.c @@ -49,6 +49,7 @@ exception statement from your version. */ #include <sys/ioctl.h> #include <sys/time.h> #include <unistd.h> +#include <arpa/inet.h> #include "cpnet.h" @@ -709,6 +710,49 @@ jint cpnet_getHostByAddr (JNIEnv *env UNUSED, cpnet_address *addr, char *hostnam return 0; } +jint cpnet_aton (JNIEnv *env, const char *hostname, cpnet_address **addr) +{ + jbyte *bytes = NULL; +#ifdef HAVE_INET_PTON + jbyte inet6_addr[16]; +#endif + +#ifdef HAVE_INET_ATON + struct in_addr laddr; + if (inet_aton (hostname, &laddr)) + { + bytes = (jbyte *) &laddr; + } +#elif defined(HAVE_INET_ADDR) +#if ! HAVE_IN_ADDR_T + typedef jint in_addr_t; +#endif + in_addr_t laddr = inet_addr (hostname); + if (laddr != (in_addr_t)(-1)) + { + bytes = (jbyte *) &laddr; + } +#endif + if (bytes) + { + *addr = cpnet_newIPV4Address(env); + cpnet_bytesToIPV4Address(*addr, bytes); + return 0; + } + +#ifdef HAVE_INET_PTON + if (inet_pton (AF_INET6, hostname, inet6_addr) > 0) + { + *addr = cpnet_newIPV6Address(env); + cpnet_bytesToIPV6Address(*addr, inet6_addr); + return 0; + } +#endif + + *addr = NULL; + return 0; +} + void cpnet_freeAddresses(JNIEnv * env, cpnet_address **addr, jint addresses_count) { jint i; diff --git a/native/jni/native-lib/cpnet.h b/native/jni/native-lib/cpnet.h index 0c7c215f8..3705c76ec 100644 --- a/native/jni/native-lib/cpnet.h +++ b/native/jni/native-lib/cpnet.h @@ -94,6 +94,7 @@ JNIEXPORT jint cpnet_getAvailableBytes (JNIEnv *env, jint fd, jint *availableByt JNIEXPORT jint cpnet_getHostname (JNIEnv *env, char *hostname, jint hostname_len); JNIEXPORT jint cpnet_getHostByName (JNIEnv *env, const char *hostname, cpnet_address ***adresses, jint *addresses_count); JNIEXPORT jint cpnet_getHostByAddr (JNIEnv *env, cpnet_address *addr, char *hostname, jint hostname_len); +JNIEXPORT jint cpnet_aton (JNIEnv *env, const char *hostname, cpnet_address **addr); JNIEXPORT void cpnet_freeAddresses(JNIEnv * env, cpnet_address **addr, jint addresses_count); static inline cpnet_address *cpnet_newIPV4Address(JNIEnv * env) diff --git a/vm/reference/java/net/VMInetAddress.java b/vm/reference/java/net/VMInetAddress.java index 19f5d7d34..a99c216b9 100644 --- a/vm/reference/java/net/VMInetAddress.java +++ b/vm/reference/java/net/VMInetAddress.java @@ -84,4 +84,14 @@ class VMInetAddress implements Serializable */ public static native byte[][] getHostByName(String hostname) throws UnknownHostException; + + /** + * Return the IP address represented by a literal address. + * Will return null if the literal address is not valid. + * + * @param address the name of the host + * + * @return The IP address as a byte array + */ + public static native byte[] aton(String address); } |