--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c Tue Mar 06 10:25:45 2012 +0800
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c Tue Mar 06 20:34:38 2012 +0000
@@ -36,12 +36,288 @@
#include <stdlib.h>
#include <ctype.h>
+#ifdef _ALLBSD_SOURCE
+#include <unistd.h>
+#include <sys/param.h>
+#endif
+
#include "jvm.h"
#include "jni_util.h"
#include "net_util.h"
#include "java_net_Inet4AddressImpl.h"
+#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
+#define HAS_GLIBC_GETHOSTBY_R 1
+#endif
+
+#if defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R)
+/* Use getaddrinfo(3), which is thread safe */
+/************************************************************************
+ * Inet4AddressImpl
+ */
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
+ char hostname[NI_MAXHOST+1];
+
+ hostname[0] = '\0';
+ if (JVM_GetHostName(hostname, NI_MAXHOST)) {
+ /* Something went wrong, maybe networking is not setup? */
+ strcpy(hostname, "localhost");
+ } else {
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+
+ error = getaddrinfo(hostname, NULL, &hints, &res);
+
+ if (error == 0) {
+ /* host is known to name service */
+ error = getnameinfo(res->ai_addr,
+ res->ai_addrlen,
+ hostname,
+ NI_MAXHOST,
+ NULL,
+ 0,
+ NI_NAMEREQD);
+
+ /* if getnameinfo fails hostname is still the value
+ from gethostname */
+
+ freeaddrinfo(res);
+ }
+ }
+ return (*env)->NewStringUTF(env, hostname);
+}
+
+static jclass ni_iacls;
+static jclass ni_ia4cls;
+static jmethodID ni_ia4ctrID;
+static jfieldID ni_iaaddressID;
+static jfieldID ni_iahostID;
+static jfieldID ni_iafamilyID;
+static int initialized = 0;
+
+/*
+ * Find an internet address for a given hostname. Note that this
+ * code only works for addresses of type INET. The translation
+ * of %d.%d.%d.%d to an address (int) occurs in java now, so the
+ * String "host" shouldn't *ever* be a %d.%d.%d.%d string
+ *
+ * Class: java_net_Inet4AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[[B
+ */
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
+ jstring host) {
+ const char *hostname;
+ jobject name;
+ jobjectArray ret = 0;
+ int retLen = 0;
+
+ int error=0;
+ struct addrinfo hints, *res, *resNew = NULL;
+
+ if (!initialized) {
+ ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
+ ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
+ ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
+ initialized = 1;
+ }
+
+ if (IS_NULL(host)) {
+ JNU_ThrowNullPointerException(env, "host is null");
+ return 0;
+ }
+ hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
+ CHECK_NULL_RETURN(hostname, NULL);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_INET;
+
+ /*
+ * Workaround for Solaris bug 4160367 - if a hostname contains a
+ * white space then 0.0.0.0 is returned
+ */
+ if (isspace((unsigned char)hostname[0])) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
+
+ error = getaddrinfo(hostname, NULL, &hints, &res);
+
+ if (error) {
+ /* report error */
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ } else {
+ int i = 0;
+ struct addrinfo *itr, *last = NULL, *iterator = res;
+ while (iterator != NULL) {
+ int skip = 0;
+ itr = resNew;
+
+ while (itr != NULL) {
+ struct sockaddr_in *addr1, *addr2;
+
+ addr1 = (struct sockaddr_in *)iterator->ai_addr;
+ addr2 = (struct sockaddr_in *)itr->ai_addr;
+ if (addr1->sin_addr.s_addr ==
+ addr2->sin_addr.s_addr) {
+ skip = 1;
+ break;
+ }
+
+ itr = itr->ai_next;
+ }
+
+ if (!skip) {
+ struct addrinfo *next
+ = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+ if (!next) {
+ JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ memcpy(next, iterator, sizeof(struct addrinfo));
+ next->ai_next = NULL;
+ if (resNew == NULL) {
+ resNew = next;
+ } else {
+ last->ai_next = next;
+ }
+ last = next;
+ i++;
+ }
+ iterator = iterator->ai_next;
+ }
+
+ retLen = i;
+ iterator = resNew;
+ i = 0;
+
+ name = (*env)->NewStringUTF(env, hostname);
+ if (IS_NULL(name)) {
+ goto cleanupAndReturn;
+ }
+
+ ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto cleanupAndReturn;
+ }
+
+ while (iterator != NULL) {
+ /* We need 4 bytes to store ipv4 address; */
+ int len = 4;
+
+ jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (IS_NULL(iaObj)) {
+ /* we may have memory to free at the end of this */
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ (*env)->SetIntField(env, iaObj, ni_iaaddressID,
+ ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
+ (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+ (*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);
+ i++;
+ iterator = iterator->ai_next;
+ }
+ }
+
+cleanupAndReturn:
+ {
+ struct addrinfo *iterator, *tmp;
+ iterator = resNew;
+ while (iterator != NULL) {
+ tmp = iterator;
+ iterator = iterator->ai_next;
+ free(tmp);
+ }
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ }
+
+ freeaddrinfo(res);
+
+ return ret;
+
+}
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getHostByAddr
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
+ jbyteArray addrArray) {
+ jstring ret = NULL;
+
+ char host[NI_MAXHOST+1];
+ jfieldID fid;
+ int error = 0;
+ jint family;
+ struct sockaddr *him ;
+ int len = 0;
+ jbyte caddr[4];
+ jint addr;
+
+ struct sockaddr_in him4;
+ struct sockaddr *sa;
+
+ /*
+ * For IPv4 addresses construct a sockaddr_in structure.
+ */
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ memset((char *) &him4, 0, sizeof(him4));
+ him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_family = AF_INET;
+ sa = (struct sockaddr *) &him4;
+ len = sizeof(him4);
+
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+ NI_NAMEREQD);
+
+ if (!error) {
+ ret = (*env)->NewStringUTF(env, host);
+ }
+
+ if (ret == NULL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
+ }
+
+ return ret;
+
+}
+
+#else /* defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R) */
+
/* the initial size of our hostent buffers */
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
@@ -292,6 +568,8 @@
return ret;
}
+#endif /* _ALLBSD_SOURCE */
+
#define SET_NONBLOCKING(fd) { \
int flags = fcntl(fd, F_GETFL); \
flags |= O_NONBLOCK; \
@@ -430,6 +708,7 @@
memset((char *) caddr, 0, sizeof(caddr));
memset((char *) &him, 0, sizeof(him));
+ memset((char *) &inf, 0, sizeof(inf));
sz = (*env)->GetArrayLength(env, addrArray);
if (sz != 4) {
return JNI_FALSE;