summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Benson <gbenson@redhat.com>2006-09-08 08:59:56 +0000
committerGary Benson <gbenson@redhat.com>2006-09-08 08:59:56 +0000
commit0ae878b1c7ebd515bdd68de62adfc848e07b12d9 (patch)
tree0a8b7a6c25dd02b73995b92059f75729224162dc
parentea6df337f9f6bc1fefb78e5d2ebce16593e3b6e9 (diff)
downloadclasspath-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--NEWS1
-rw-r--r--configure.ac1
-rw-r--r--include/java_net_VMInetAddress.h1
-rw-r--r--java/net/Inet4Address.java2
-rw-r--r--java/net/InetAddress.java185
-rw-r--r--native/jni/java-net/java_net_VMInetAddress.c87
-rw-r--r--native/jni/native-lib/cpnet.c44
-rw-r--r--native/jni/native-lib/cpnet.h1
-rw-r--r--vm/reference/java/net/VMInetAddress.java10
9 files changed, 223 insertions, 109 deletions
diff --git a/NEWS b/NEWS
index 6482ee1bc..8ad03d662 100644
--- a/NEWS
+++ b/NEWS
@@ -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);
}