提交 24937a15 编写于 作者: N ngmr

7112670: Inet4AddressImpl should use getaddrinfo/getnameinfo

Reviewed-by: chegar, alanb, mduigou, ngmr
Contributed-by: NCharles Lee <littlee@linux.vnet.ibm.com>
上级 1f779117
...@@ -43,8 +43,9 @@ ...@@ -43,8 +43,9 @@
#include "java_net_Inet4AddressImpl.h" #include "java_net_Inet4AddressImpl.h"
/* the initial size of our hostent buffers */ /* the initial size of our hostent buffers */
#define HENT_BUF_SIZE 1024 #ifndef NI_MAXHOST
#define BIG_HENT_BUF_SIZE 10240 /* a jumbo-sized one */ #define NI_MAXHOST 1025
#endif
/************************************************************************ /************************************************************************
* Inet4AddressImpl * Inet4AddressImpl
...@@ -57,60 +58,36 @@ ...@@ -57,60 +58,36 @@
*/ */
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[MAXHOSTNAMELEN+1]; char hostname[NI_MAXHOST+1];
hostname[0] = '\0'; hostname[0] = '\0';
if (JVM_GetHostName(hostname, sizeof(hostname))) { if (JVM_GetHostName(hostname, sizeof(hostname))) {
/* Something went wrong, maybe networking is not setup? */ /* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost"); strcpy(hostname, "localhost");
} else { } else {
#ifdef __linux__ hostname[NI_MAXHOST] = '\0';
/* On Linux gethostname() says "host.domain.sun.com". On struct addrinfo hints, *res;
* Solaris gethostname() says "host", so extra work is needed. int error;
*/
#else bzero(&hints, sizeof(hints));
/* Solaris doesn't want to give us a fully qualified domain name. hints.ai_flags = AI_CANONNAME;
* We do a reverse lookup to try and get one. This works hints.ai_family = AF_INET;
* if DNS occurs before NIS in /etc/resolv.conf, but fails
* if NIS comes first (it still gets only a partial name). error = getaddrinfo(hostname, NULL, &hints, &res);
* We use thread-safe system calls.
*/ if (error == 0) {/* host is known to name service */
#endif /* __linux__ */ getnameinfo(res->ai_addr,
struct hostent res, res2, *hp; res->ai_addrlen,
// these buffers must be pointer-aligned so they are declared hostname,
// with pointer type MAXHOSTNAMELEN,
char *buf[HENT_BUF_SIZE/(sizeof (char *))]; NULL,
char *buf2[HENT_BUF_SIZE/(sizeof (char *))]; 0,
int h_error=0; NI_NAMEREQD);
// ensure null-terminated /* if getnameinfo fails hostname is still the value
hostname[MAXHOSTNAMELEN] = '\0'; from gethostname */
#ifdef __GLIBC__ freeaddrinfo(res);
gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
#else
hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
#endif
if (hp) {
#ifdef __GLIBC__
gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
&res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
#else
hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
&res2, (char*)buf2, sizeof(buf2), &h_error);
#endif
if (hp) {
/*
* If gethostbyaddr_r() found a fully qualified host name,
* returns that name. Otherwise, returns the hostname
* found by gethostname().
*/
char *p = hp->h_name;
if ((strlen(hp->h_name) > strlen(hostname))
&& (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
&& (*(p + strlen(hostname)) == '.'))
strcpy(hostname, hp->h_name);
}
} }
} }
return (*env)->NewStringUTF(env, hostname); return (*env)->NewStringUTF(env, hostname);
...@@ -140,14 +117,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -140,14 +117,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
jstring host) { jstring host) {
const char *hostname; const char *hostname;
jobjectArray ret = 0; jobjectArray ret = 0;
struct hostent res, *hp = 0; int retLen = 0;
// this buffer must be pointer-aligned so is declared int error = 0;
// with pointer type struct addrinfo hints, *res, *resNew = NULL;
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
/* temporary buffer, on the off chance we need to expand */
char *tmp = NULL;
int h_error=0;
if (!initialized) { if (!initialized) {
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress"); ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
...@@ -168,6 +140,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -168,6 +140,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
CHECK_NULL_RETURN(hostname, NULL); CHECK_NULL_RETURN(hostname, NULL);
/* Try once, with our static buffer. */
bzero(&hints, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
#ifdef __solaris__ #ifdef __solaris__
/* /*
* Workaround for Solaris bug 4160367 - if a hostname contains a * Workaround for Solaris bug 4160367 - if a hostname contains a
...@@ -181,69 +158,93 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -181,69 +158,93 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
} }
#endif #endif
/* Try once, with our static buffer. */ error = getaddrinfo(hostname, NULL, &hints, &res);
#ifdef __GLIBC__
gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
#else
hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
#endif
/* With the re-entrant system calls, it's possible that the buffer if (error) {
* we pass to it is not large enough to hold an exceptionally /* report error */
* large DNS entry. This is signaled by errno->ERANGE. We try once ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
* more, with a very big size. JNU_ReleaseStringPlatformChars(env, host, hostname);
*/ return NULL;
if (hp == NULL && errno == ERANGE) { } else {
if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
#ifdef __GLIBC__
gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
&hp, &h_error);
#else
hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
&h_error);
#endif
}
}
if (hp != NULL) {
struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
int i = 0; int i = 0;
struct addrinfo *itr, *last = NULL, *iterator = res;
while (iterator != NULL) {
// remove the duplicate one
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;
}
while (*addrp != (struct in_addr *) 0) { if (!skip) {
i++; struct addrinfo *next
addrp++; = (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;
} }
ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL); retLen = i;
iterator = resNew;
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
if (IS_NULL(ret)) { if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */ /* we may have memory to free at the end of this */
goto cleanupAndReturn; goto cleanupAndReturn;
} }
addrp = (struct in_addr **) hp->h_addr_list;
i = 0; i = 0;
while (*addrp) { while (iterator != NULL) {
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
(*env)->SetIntField(env, iaObj, ni_iaaddressID, (*env)->SetIntField(env, iaObj, ni_iaaddressID,
ntohl((*addrp)->s_addr)); ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
(*env)->SetObjectField(env, iaObj, ni_iahostID, host); (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, i, iaObj); (*env)->SetObjectArrayElement(env, ret, i++, iaObj);
addrp++; iterator = iterator->ai_next;
i++;
} }
} else {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname);
ret = NULL;
} }
cleanupAndReturn: cleanupAndReturn:
JNU_ReleaseStringPlatformChars(env, host, hostname); {
if (tmp != NULL) { struct addrinfo *iterator, *tmp;
free(tmp); iterator = resNew;
while (iterator != NULL) {
tmp = iterator;
iterator = iterator->ai_next;
free(tmp);
}
JNU_ReleaseStringPlatformChars(env, host, hostname);
} }
freeaddrinfo(res);
return ret; return ret;
} }
...@@ -256,63 +257,39 @@ JNIEXPORT jstring JNICALL ...@@ -256,63 +257,39 @@ JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this, Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
jbyteArray addrArray) { jbyteArray addrArray) {
jstring ret = NULL; jstring ret = NULL;
jint addr;
struct hostent hent, *hp = 0;
// this buffer must be pointer-aligned so is declared
// with pointer type
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
int h_error = 0;
char *tmp = NULL;
/* char host[NI_MAXHOST+1];
* We are careful here to use the reentrant version of int error = 0;
* gethostbyname because at the Java level this routine is not int len = 0;
* protected by any synchronization. jbyte caddr[16];
*
* Still keeping the reentrant platform dependent calls temporarily struct sockaddr_in him4;
* We should probably conform to one interface later. struct sockaddr_in6 him6;
* struct sockaddr *sa;
*/
jbyte caddr[4]; jint addr;
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
addr = ((caddr[0]<<24) & 0xff000000); addr = ((caddr[0]<<24) & 0xff000000);
addr |= ((caddr[1] <<16) & 0xff0000); addr |= ((caddr[1] <<16) & 0xff0000);
addr |= ((caddr[2] <<8) & 0xff00); addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff); addr |= (caddr[3] & 0xff);
addr = htonl(addr); memset((void *) &him4, 0, sizeof(him4));
#ifdef __GLIBC__ him4.sin_addr.s_addr = (uint32_t) htonl(addr);
gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent, him4.sin_family = AF_INET;
(char*)buf, sizeof(buf), &hp, &h_error); sa = (struct sockaddr *) &him4;
#else len = sizeof(him4);
hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
(char*)buf, sizeof(buf), &h_error); error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
#endif NI_NAMEREQD);
/* With the re-entrant system calls, it's possible that the buffer
* we pass to it is not large enough to hold an exceptionally if (!error) {
* large DNS entry. This is signaled by errno->ERANGE. We try once ret = (*env)->NewStringUTF(env, host);
* more, with a very big size.
*/
if (hp == NULL && errno == ERANGE) {
if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
#ifdef __GLIBC__
gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
&hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
#else
hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
&hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
#endif
} else {
JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
}
} }
if (hp == NULL) {
if (ret == NULL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL); JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
} else {
ret = (*env)->NewStringUTF(env, hp->h_name);
}
if (tmp) {
free(tmp);
} }
return ret; return ret;
} }
......
...@@ -82,31 +82,29 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { ...@@ -82,31 +82,29 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
* We use thread-safe system calls. * We use thread-safe system calls.
*/ */
#ifdef AF_INET6 #ifdef AF_INET6
if (NET_addrtransAvailable()) { struct addrinfo hints, *res;
struct addrinfo hints, *res; int error;
int error;
bzero(&hints, sizeof(hints));
bzero(&hints, sizeof(hints)); hints.ai_flags = AI_CANONNAME;
hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
error = getaddrinfo(hostname, NULL, &hints, &res);
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
if (error == 0) {
if (error == 0) { /* host is known to name service */
/* host is known to name service */ error = getnameinfo(res->ai_addr,
error = (*getnameinfo_ptr)(res->ai_addr, res->ai_addrlen,
res->ai_addrlen, hostname,
hostname, NI_MAXHOST,
NI_MAXHOST, NULL,
NULL, 0,
0, NI_NAMEREQD);
NI_NAMEREQD);
/* if getnameinfo fails hostname is still the value
/* if getnameinfo fails hostname is still the value from gethostname */
from gethostname */
freeaddrinfo(res);
(*freeaddrinfo_ptr)(res);
}
} }
#endif /* AF_INET6 */ #endif /* AF_INET6 */
#endif /* __linux__ */ #endif /* __linux__ */
...@@ -173,193 +171,191 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -173,193 +171,191 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
CHECK_NULL_RETURN(hostname, NULL); CHECK_NULL_RETURN(hostname, NULL);
#ifdef AF_INET6 #ifdef AF_INET6
if (NET_addrtransAvailable()) { static jfieldID ia_preferIPv6AddressID;
static jfieldID ia_preferIPv6AddressID; if (ia_preferIPv6AddressID == NULL) {
jclass c = (*env)->FindClass(env,"java/net/InetAddress");
if (c) {
ia_preferIPv6AddressID =
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
}
if (ia_preferIPv6AddressID == NULL) { if (ia_preferIPv6AddressID == NULL) {
jclass c = (*env)->FindClass(env,"java/net/InetAddress"); JNU_ReleaseStringPlatformChars(env, host, hostname);
if (c) { return NULL;
ia_preferIPv6AddressID =
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
}
if (ia_preferIPv6AddressID == NULL) {
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
}
} }
/* get the address preference */ }
preferIPv6Address /* get the address preference */
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID); preferIPv6Address
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
/* Try once, with our static buffer. */ /* Try once, with our static buffer. */
bzero(&hints, sizeof(hints)); bzero(&hints, sizeof(hints));
hints.ai_flags = AI_CANONNAME; hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
#ifdef __solaris__ #ifdef __solaris__
/* /*
* Workaround for Solaris bug 4160367 - if a hostname contains a * Workaround for Solaris bug 4160367 - if a hostname contains a
* white space then 0.0.0.0 is returned * white space then 0.0.0.0 is returned
*/ */
if (isspace((unsigned char)hostname[0])) { if (isspace((unsigned char)hostname[0])) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
hostname); hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL; return NULL;
} }
#endif #endif
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); error = getaddrinfo(hostname, NULL, &hints, &res);
if (error) { if (error) {
/* report error */ /* report error */
ThrowUnknownHostExceptionWithGaiError(env, hostname, error); ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL; return NULL;
} else { } else {
int i = 0; int i = 0;
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index; int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
struct addrinfo *itr, *last = NULL, *iterator = res; struct addrinfo *itr, *last = NULL, *iterator = res;
while (iterator != NULL) { while (iterator != NULL) {
int skip = 0; int skip = 0;
itr = resNew; itr = resNew;
while (itr != NULL) { while (itr != NULL) {
if (iterator->ai_family == itr->ai_family && if (iterator->ai_family == itr->ai_family &&
iterator->ai_addrlen == itr->ai_addrlen) { iterator->ai_addrlen == itr->ai_addrlen) {
if (itr->ai_family == AF_INET) { /* AF_INET */ if (itr->ai_family == AF_INET) { /* AF_INET */
struct sockaddr_in *addr1, *addr2; struct sockaddr_in *addr1, *addr2;
addr1 = (struct sockaddr_in *)iterator->ai_addr; addr1 = (struct sockaddr_in *)iterator->ai_addr;
addr2 = (struct sockaddr_in *)itr->ai_addr; addr2 = (struct sockaddr_in *)itr->ai_addr;
if (addr1->sin_addr.s_addr == if (addr1->sin_addr.s_addr ==
addr2->sin_addr.s_addr) { addr2->sin_addr.s_addr) {
skip = 1; skip = 1;
break;
}
} else {
int t;
struct sockaddr_in6 *addr1, *addr2;
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
for (t = 0; t < 16; t++) {
if (addr1->sin6_addr.s6_addr[t] !=
addr2->sin6_addr.s6_addr[t]) {
break; break;
} }
}
if (t < 16) {
itr = itr->ai_next;
continue;
} else { } else {
int t; skip = 1;
struct sockaddr_in6 *addr1, *addr2; break;
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
for (t = 0; t < 16; t++) {
if (addr1->sin6_addr.s6_addr[t] !=
addr2->sin6_addr.s6_addr[t]) {
break;
}
}
if (t < 16) {
itr = itr->ai_next;
continue;
} else {
skip = 1;
break;
}
} }
} else if (iterator->ai_family != AF_INET &&
iterator->ai_family != AF_INET6) {
/* we can't handle other family types */
skip = 1;
break;
} }
itr = itr->ai_next; } else if (iterator->ai_family != AF_INET &&
iterator->ai_family != AF_INET6) {
/* we can't handle other family types */
skip = 1;
break;
} }
itr = itr->ai_next;
}
if (!skip) { if (!skip) {
struct addrinfo *next struct addrinfo *next
= (struct addrinfo*) malloc(sizeof(struct addrinfo)); = (struct addrinfo*) malloc(sizeof(struct addrinfo));
if (!next) { if (!next) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
memcpy(next, iterator, sizeof(struct addrinfo)); memcpy(next, iterator, sizeof(struct addrinfo));
next->ai_next = NULL; next->ai_next = NULL;
if (resNew == NULL) { if (resNew == NULL) {
resNew = next; resNew = next;
} else { } else {
last->ai_next = next; last->ai_next = next;
} }
last = next; last = next;
i++; i++;
if (iterator->ai_family == AF_INET) { if (iterator->ai_family == AF_INET) {
inetCount ++; inetCount ++;
} else if (iterator->ai_family == AF_INET6) { } else if (iterator->ai_family == AF_INET6) {
inet6Count ++; inet6Count ++;
}
} }
iterator = iterator->ai_next;
} }
retLen = i; iterator = iterator->ai_next;
iterator = resNew; }
retLen = i;
iterator = resNew;
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL); ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
if (IS_NULL(ret)) { if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */ /* we may have memory to free at the end of this */
goto cleanupAndReturn; goto cleanupAndReturn;
} }
if (preferIPv6Address) { if (preferIPv6Address) {
/* AF_INET addresses will be offset by inet6Count */ /* AF_INET addresses will be offset by inet6Count */
inetIndex = inet6Count; inetIndex = inet6Count;
inet6Index = 0; inet6Index = 0;
} else { } else {
/* AF_INET6 addresses will be offset by inetCount */ /* AF_INET6 addresses will be offset by inetCount */
inetIndex = 0; inetIndex = 0;
inet6Index = inetCount; inet6Index = inetCount;
} }
while (iterator != NULL) { while (iterator != NULL) {
if (iterator->ai_family == AF_INET) { if (iterator->ai_family == AF_INET) {
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
(*env)->SetIntField(env, iaObj, ni_iaaddressID, (*env)->SetIntField(env, iaObj, ni_iaaddressID,
ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
(*env)->SetObjectField(env, iaObj, ni_iahostID, host); (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
inetIndex++; inetIndex++;
} else if (iterator->ai_family == AF_INET6) { } else if (iterator->ai_family == AF_INET6) {
jint scope = 0; jint scope = 0;
jbyteArray ipaddress; jbyteArray ipaddress;
jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
ipaddress = (*env)->NewByteArray(env, 16); ipaddress = (*env)->NewByteArray(env, 16);
if (IS_NULL(ipaddress)) { if (IS_NULL(ipaddress)) {
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16, (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
(jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
#ifdef __linux__ #ifdef __linux__
if (!kernelIsV22()) { if (!kernelIsV22()) {
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
} }
#else #else
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
#endif #endif
if (scope != 0) { /* zero is default value, no need to set */ if (scope != 0) { /* zero is default value, no need to set */
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
} }
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
(*env)->SetObjectField(env, iaObj, ni_iahostID, host); (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
inet6Index++; inet6Index++;
}
iterator = iterator->ai_next;
} }
iterator = iterator->ai_next;
} }
} }
cleanupAndReturn: cleanupAndReturn:
{ {
struct addrinfo *iterator, *tmp; struct addrinfo *iterator, *tmp;
iterator = resNew; iterator = resNew;
while (iterator != NULL) { while (iterator != NULL) {
tmp = iterator; tmp = iterator;
...@@ -369,8 +365,7 @@ cleanupAndReturn: ...@@ -369,8 +365,7 @@ cleanupAndReturn:
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
} }
if (NET_addrtransAvailable()) freeaddrinfo(res);
(*freeaddrinfo_ptr)(res);
#endif /* AF_INET6 */ #endif /* AF_INET6 */
return ret; return ret;
...@@ -393,44 +388,42 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, ...@@ -393,44 +388,42 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
int len = 0; int len = 0;
jbyte caddr[16]; jbyte caddr[16];
if (NET_addrtransAvailable()) { struct sockaddr_in him4;
struct sockaddr_in him4; struct sockaddr_in6 him6;
struct sockaddr_in6 him6; struct sockaddr *sa;
struct sockaddr *sa;
/*
* For IPv4 addresses construct a sockaddr_in structure.
*/
if ((*env)->GetArrayLength(env, addrArray) == 4) {
jint addr;
(*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((void *) &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);
} else {
/* /*
* For IPv4 addresses construct a sockaddr_in structure. * For IPv6 address construct a sockaddr_in6 structure.
*/ */
if ((*env)->GetArrayLength(env, addrArray) == 4) { (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
jint addr; memset((void *) &him6, 0, sizeof(him6));
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
addr = ((caddr[0]<<24) & 0xff000000); him6.sin6_family = AF_INET6;
addr |= ((caddr[1] <<16) & 0xff0000); sa = (struct sockaddr *) &him6 ;
addr |= ((caddr[2] <<8) & 0xff00); len = sizeof(him6) ;
addr |= (caddr[3] & 0xff); }
memset((void *) &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);
} else {
/*
* For IPv6 address construct a sockaddr_in6 structure.
*/
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
memset((void *) &him6, 0, sizeof(him6));
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
him6.sin6_family = AF_INET6;
sa = (struct sockaddr *) &him6 ;
len = sizeof(him6) ;
}
error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0, error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
NI_NAMEREQD); NI_NAMEREQD);
if (!error) { if (!error) {
ret = (*env)->NewStringUTF(env, host); ret = (*env)->NewStringUTF(env, host);
}
} }
#endif /* AF_INET6 */ #endif /* AF_INET6 */
......
...@@ -377,37 +377,12 @@ jint IPv6_supported() ...@@ -377,37 +377,12 @@ jint IPv6_supported()
* we should also check if the APIs are available. * we should also check if the APIs are available.
*/ */
ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton"); ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
close(fd);
if (ipv6_fn == NULL ) { if (ipv6_fn == NULL ) {
close(fd);
return JNI_FALSE; return JNI_FALSE;
} else {
return JNI_TRUE;
} }
/*
* We've got the library, let's get the pointers to some
* IPV6 specific functions. We have to do that because, at least
* on Solaris we may build on a system without IPV6 networking
* libraries, therefore we can't have a hard link to these
* functions.
*/
getaddrinfo_ptr = (getaddrinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
freeaddrinfo_ptr = (freeaddrinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
gai_strerror_ptr = (gai_strerror_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
getnameinfo_ptr = (getnameinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
/* We need all 3 of them */
getaddrinfo_ptr = NULL;
}
close(fd);
return JNI_TRUE;
#endif /* AF_INET6 */ #endif /* AF_INET6 */
} }
...@@ -920,10 +895,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) { ...@@ -920,10 +895,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
return 1; return 1;
} }
jboolean NET_addrtransAvailable() {
return (jboolean)(getaddrinfo_ptr != NULL);
}
/* /*
* Map the Java level socket option to the platform specific * Map the Java level socket option to the platform specific
* level and option name. * level and option name.
......
...@@ -102,10 +102,6 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, ...@@ -102,10 +102,6 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
const char* hostname, const char* hostname,
int gai_error); int gai_error);
/* do we have address translation support */
extern jboolean NET_addrtransAvailable();
#define NET_WAIT_READ 0x01 #define NET_WAIT_READ 0x01
#define NET_WAIT_WRITE 0x02 #define NET_WAIT_WRITE 0x02
#define NET_WAIT_CONNECT 0x04 #define NET_WAIT_CONNECT 0x04
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册