Hi all,
This commit merges a bunch of funky stuff from GCJ's InetAddress
(including all the fixes I've been working on over the past week
or so) and adds a bunch of other stuff I noticed while merging.
Particular hilights are that "raw" InetAddress objects no longer
exist anywhere (only Inet4Address and Inet6Address objects are
ever created now) and that a couple of excessive security checks
were relaxed.
Cheers,
Gary
Index: ChangeLog
===================================================================
RCS file: /cvsroot/classpath/classpath/ChangeLog,v
retrieving revision 1.8513
diff -u -r1.8513 ChangeLog
--- ChangeLog 7 Sep 2006 11:42:13 -0000 1.8513
+++ ChangeLog 8 Sep 2006 08:23:15 -0000
@@ -1,3 +1,31 @@
+2006-09-08 Gary Benson <[EMAIL PROTECTED]>
+
+ * 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.
+
2006-09-07 David Gilbert <[EMAIL PROTECTED]>
* javax/swing/plaf/basic/BasicInternalFrameUI.java
Index: java/net/InetAddress.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/net/InetAddress.java,v
retrieving revision 1.46
diff -u -r1.46 InetAddress.java
--- java/net/InetAddress.java 6 Feb 2006 12:50:03 -0000 1.46
+++ java/net/InetAddress.java 8 Sep 2006 08:23:19 -0000
@@ -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.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 @@
*
* @author Aaron M. Renn ([EMAIL PROTECTED])
* @author Per Bothner
+ * @author Gary Benson ([EMAIL PROTECTED])
*
* @specnote This class is not final since JK 1.4
*/
@@ -65,37 +66,47 @@
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 @@
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 @@
try
{
hostName = VMInetAddress.getHostByAddr(addr);
- return hostName;
}
catch (UnknownHostException e)
{
- return getHostAddress();
+ hostName = getHostAddress();
}
+
+ return hostName;
}
/**
@@ -488,48 +504,22 @@
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 static InetAddress[] getAllByName(String hostname)
throws UnknownHostException
{
- SecurityManager s = System.getSecurityManager();
- if (s != null)
- s.checkConnect(hostname, -1);
+ // If null or the empty string is supplied, the loopback address
+ // is returned.
+ if (hostname == null || hostname.length() == 0)
+ return new InetAddress[] {LOCALHOST};
+
+ // Check if hostname is an IP address
+ byte[] address = VMInetAddress.aton(hostname);
+ if (address != null)
+ return new InetAddress[] {getByAddress(address)};
- InetAddress[] addresses;
-
- if (hostname != null)
- hostname = hostname.trim();
-
- // 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 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
{
Index: vm/reference/java/net/VMInetAddress.java
===================================================================
RCS file:
/cvsroot/classpath/classpath/vm/reference/java/net/VMInetAddress.java,v
retrieving revision 1.3
diff -u -r1.3 VMInetAddress.java
--- vm/reference/java/net/VMInetAddress.java 2 Mar 2006 00:36:44 -0000
1.3
+++ vm/reference/java/net/VMInetAddress.java 8 Sep 2006 08:23:21 -0000
@@ -84,4 +84,14 @@
*/
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);
}
Index: include/java_net_VMInetAddress.h
===================================================================
RCS file: /cvsroot/classpath/classpath/include/java_net_VMInetAddress.h,v
retrieving revision 1.1
diff -u -r1.1 java_net_VMInetAddress.h
--- include/java_net_VMInetAddress.h 11 Apr 2005 18:58:38 -0000 1.1
+++ include/java_net_VMInetAddress.h 8 Sep 2006 08:23:23 -0000
@@ -14,6 +14,7 @@
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
}
Index: native/jni/java-net/java_net_VMInetAddress.c
===================================================================
RCS file:
/cvsroot/classpath/classpath/native/jni/java-net/java_net_VMInetAddress.c,v
retrieving revision 1.8
diff -u -r1.8 java_net_VMInetAddress.c
--- native/jni/java-net/java_net_VMInetAddress.c 21 Aug 2006 23:34:45
-0000 1.8
+++ native/jni/java-net/java_net_VMInetAddress.c 8 Sep 2006 08:23:26
-0000
@@ -299,4 +299,91 @@
#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 */
Index: native/jni/native-lib/cpnet.h
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/native-lib/cpnet.h,v
retrieving revision 1.2
diff -u -r1.2 cpnet.h
--- native/jni/native-lib/cpnet.h 21 Aug 2006 23:34:46 -0000 1.2
+++ native/jni/native-lib/cpnet.h 8 Sep 2006 08:23:29 -0000
@@ -94,6 +94,7 @@
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)
Index: native/jni/native-lib/cpnet.c
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/native-lib/cpnet.c,v
retrieving revision 1.3
diff -u -r1.3 cpnet.c
--- native/jni/native-lib/cpnet.c 31 Aug 2006 19:56:03 -0000 1.3
+++ native/jni/native-lib/cpnet.c 8 Sep 2006 08:23:31 -0000
@@ -49,6 +49,7 @@
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include "cpnet.h"
@@ -709,6 +710,49 @@
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;
Index: configure.ac
===================================================================
RCS file: /cvsroot/classpath/classpath/configure.ac,v
retrieving revision 1.181
diff -u -r1.181 configure.ac
--- configure.ac 31 Aug 2006 19:56:03 -0000 1.181
+++ configure.ac 8 Sep 2006 08:23:34 -0000
@@ -373,6 +373,7 @@
fcntl \
mmap munmap mincore msync madvise getpagesize sysconf \
lstat readlink \
+ inet_aton inet_addr inet_pton \
])
LIBMAGIC=
Index: java/net/Inet4Address.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/net/Inet4Address.java,v
retrieving revision 1.18
diff -u -r1.18 Inet4Address.java
--- java/net/Inet4Address.java 2 Oct 2005 22:58:42 -0000 1.18
+++ java/net/Inet4Address.java 8 Sep 2006 08:23:37 -0000
@@ -57,7 +57,7 @@
static final long serialVersionUID = 3286316764910316507L;
/**
- * needed for serialization
+ * Inet4Address objects are serialized as InetAddress objects.
*/
private Object writeReplace() throws ObjectStreamException
{
Index: NEWS
===================================================================
RCS file: /cvsroot/classpath/classpath/NEWS,v
retrieving revision 1.166
diff -u -r1.166 NEWS
--- NEWS 5 Sep 2006 21:19:20 -0000 1.166
+++ NEWS 8 Sep 2006 08:23:40 -0000
@@ -16,6 +16,7 @@
* 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)