Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/java/net/Inet6AddressImpl.c
32287 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <errno.h>26#include <sys/time.h>27#include <sys/types.h>28#include <sys/socket.h>29#include <netinet/in.h>30#include <netdb.h>31#include <string.h>32#include <strings.h>33#include <stdlib.h>34#include <ctype.h>35#ifdef MACOSX36#include <ifaddrs.h>37#include <net/if.h>38#include <unistd.h> /* gethostname */39#endif4041#include "jvm.h"42#include "jni_util.h"43#include "net_util.h"44#ifndef IPV6_DEFS_H45#include <netinet/icmp6.h>46#endif4748#include "java_net_Inet4AddressImpl.h"49#include "java_net_Inet6AddressImpl.h"5051/* the initial size of our hostent buffers */52#ifndef NI_MAXHOST53#define NI_MAXHOST 102554#endif555657/************************************************************************58* Inet6AddressImpl59*/6061/*62* Class: java_net_Inet6AddressImpl63* Method: getLocalHostName64* Signature: ()Ljava/lang/String;65*/66JNIEXPORT jstring JNICALL67Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {68char hostname[NI_MAXHOST + 1];6970hostname[0] = '\0';71if (JVM_GetHostName(hostname, sizeof(hostname))) {72strcpy(hostname, "localhost");73#if defined(__solaris__) && defined(AF_INET6)74} else {75// try to resolve hostname via nameservice76// if it is known but getnameinfo fails, hostname will still be the77// value from gethostname78struct addrinfo hints, *res;7980// make sure string is null-terminated81hostname[NI_MAXHOST] = '\0';82memset(&hints, 0, sizeof(hints));83hints.ai_flags = AI_CANONNAME;84hints.ai_family = AF_UNSPEC;8586if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {87getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST,88NULL, 0, NI_NAMEREQD);89freeaddrinfo(res);90}91}92#else93} else {94// make sure string is null-terminated95hostname[NI_MAXHOST] = '\0';96}97#endif98return (*env)->NewStringUTF(env, hostname);99}100101#ifdef MACOSX102/* also called from Inet4AddressImpl.c */103__private_extern__ jobjectArray104lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)105{106jobjectArray result = NULL;107char myhostname[NI_MAXHOST+1];108struct ifaddrs *ifa = NULL;109int familyOrder = 0;110int count = 0, i, j;111int addrs4 = 0, addrs6 = 0, numV4Loopbacks = 0, numV6Loopbacks = 0;112jboolean includeLoopback = JNI_FALSE;113jobject name;114115initInetAddressIDs(env);116JNU_CHECK_EXCEPTION_RETURN(env, NULL);117118/* If the requested name matches this host's hostname, return IP addresses119* from all attached interfaces. (#2844683 et al) This prevents undesired120* PPP dialup, but may return addresses that don't actually correspond to121* the name (if the name actually matches something in DNS etc.122*/123myhostname[0] = '\0';124if (JVM_GetHostName(myhostname, NI_MAXHOST)) {125/* Something went wrong, maybe networking is not setup? */126return NULL;127}128myhostname[NI_MAXHOST] = '\0';129130if (strcmp(myhostname, hostname) != 0) {131// Non-self lookup132return NULL;133}134135if (getifaddrs(&ifa) != 0) {136NET_ThrowNew(env, errno, "Can't get local interface addresses");137return NULL;138}139140name = (*env)->NewStringUTF(env, hostname);141if (name == NULL) {142freeifaddrs(ifa);143return NULL;144}145146/* Iterate over the interfaces, and total up the number of IPv4 and IPv6147* addresses we have. Also keep a count of loopback addresses. We need to148* exclude them in the normal case, but return them if we don't get an IP149* address.150*/151struct ifaddrs *iter = ifa;152while (iter) {153int family = iter->ifa_addr->sa_family;154if (iter->ifa_name[0] != '\0' && iter->ifa_addr)155{156jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;157if (family == AF_INET) {158addrs4++;159if (isLoopback) numV4Loopbacks++;160} else if (family == AF_INET6 && includeV6) {161addrs6++;162if (isLoopback) numV6Loopbacks++;163} else {164/* We don't care e.g. AF_LINK */165}166}167iter = iter->ifa_next;168}169170if (addrs4 == numV4Loopbacks && addrs6 == numV6Loopbacks) {171// We don't have a real IP address, just loopback. We need to include172// loopback in our results.173includeLoopback = JNI_TRUE;174}175176/* Create and fill the Java array. */177int arraySize = addrs4 + addrs6 -178(includeLoopback ? 0 : (numV4Loopbacks + numV6Loopbacks));179result = (*env)->NewObjectArray(env, arraySize, ia_class, NULL);180if (!result) goto done;181182if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) {183i = includeLoopback ? addrs6 : (addrs6 - numV6Loopbacks);184j = 0;185} else {186i = 0;187j = includeLoopback ? addrs4 : (addrs4 - numV4Loopbacks);188}189190// Now loop around the ifaddrs191iter = ifa;192while (iter != NULL) {193jboolean isLoopback = iter->ifa_flags & IFF_LOOPBACK;194int family = iter->ifa_addr->sa_family;195196if (iter->ifa_name[0] != '\0' && iter->ifa_addr197&& (family == AF_INET || (family == AF_INET6 && includeV6))198&& (!isLoopback || includeLoopback))199{200int port;201int index = (family == AF_INET) ? i++ : j++;202jobject o = NET_SockaddrToInetAddress(env, iter->ifa_addr, &port);203if (!o) {204freeifaddrs(ifa);205if (!(*env)->ExceptionCheck(env))206JNU_ThrowOutOfMemoryError(env, "Object allocation failed");207return NULL;208}209setInetAddress_hostName(env, o, name);210if ((*env)->ExceptionCheck(env))211goto done;212(*env)->SetObjectArrayElement(env, result, index, o);213(*env)->DeleteLocalRef(env, o);214}215iter = iter->ifa_next;216}217218done:219freeifaddrs(ifa);220221return result;222}223#endif224225/*226* Find an internet address for a given hostname. Note that this227* code only works for addresses of type INET. The translation228* of %d.%d.%d.%d to an address (int) occurs in java now, so the229* String "host" shouldn't *ever* be a %d.%d.%d.%d string230*231* Class: java_net_Inet6AddressImpl232* Method: lookupAllHostAddr233* Signature: (Ljava/lang/String;)[[B234*/235236JNIEXPORT jobjectArray JNICALL237Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,238jstring host) {239const char *hostname;240jobjectArray ret = 0;241int retLen = 0;242243int getaddrinfo_error=0;244#ifdef AF_INET6245struct addrinfo hints, *res, *resNew = NULL;246#endif /* AF_INET6 */247248initInetAddressIDs(env);249JNU_CHECK_EXCEPTION_RETURN(env, NULL);250251if (IS_NULL(host)) {252JNU_ThrowNullPointerException(env, "host is null");253return 0;254}255hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);256CHECK_NULL_RETURN(hostname, NULL);257258#ifdef AF_INET6259/* Try once, with our static buffer. */260memset(&hints, 0, sizeof(hints));261hints.ai_flags = AI_CANONNAME;262hints.ai_family = AF_UNSPEC;263264#ifdef __solaris__265/*266* Workaround for Solaris bug 4160367 - if a hostname contains a267* white space then 0.0.0.0 is returned268*/269if (isspace((unsigned char)hostname[0])) {270JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",271hostname);272JNU_ReleaseStringPlatformChars(env, host, hostname);273return NULL;274}275#endif276277getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res);278279#ifdef MACOSX280if (getaddrinfo_error) {281/*282* If getaddrinfo fails looking up the local machine, attempt to get the283* address from getifaddrs. This ensures we get an IPv6 address for the284* local machine.285*/286ret = lookupIfLocalhost(env, hostname, JNI_TRUE);287if (ret != NULL || (*env)->ExceptionCheck(env)) {288JNU_ReleaseStringPlatformChars(env, host, hostname);289return ret;290}291}292#endif293294if (getaddrinfo_error) {295/* report error */296ThrowUnknownHostExceptionWithGaiError(297env, hostname, getaddrinfo_error);298JNU_ReleaseStringPlatformChars(env, host, hostname);299return NULL;300} else {301int i = 0;302int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;303struct addrinfo *itr, *last = NULL, *iterator = res;304while (iterator != NULL) {305int skip = 0;306itr = resNew;307while (itr != NULL) {308if (iterator->ai_family == itr->ai_family &&309iterator->ai_addrlen == itr->ai_addrlen) {310if (itr->ai_family == AF_INET) { /* AF_INET */311struct sockaddr_in *addr1, *addr2;312addr1 = (struct sockaddr_in *)iterator->ai_addr;313addr2 = (struct sockaddr_in *)itr->ai_addr;314if (addr1->sin_addr.s_addr ==315addr2->sin_addr.s_addr) {316skip = 1;317break;318}319} else {320int t;321struct sockaddr_in6 *addr1, *addr2;322addr1 = (struct sockaddr_in6 *)iterator->ai_addr;323addr2 = (struct sockaddr_in6 *)itr->ai_addr;324325for (t = 0; t < 16; t++) {326if (addr1->sin6_addr.s6_addr[t] !=327addr2->sin6_addr.s6_addr[t]) {328break;329}330}331if (t < 16) {332itr = itr->ai_next;333continue;334} else {335skip = 1;336break;337}338}339} else if (iterator->ai_family != AF_INET &&340iterator->ai_family != AF_INET6) {341/* we can't handle other family types */342skip = 1;343break;344}345itr = itr->ai_next;346}347348if (!skip) {349struct addrinfo *next350= (struct addrinfo*) malloc(sizeof(struct addrinfo));351if (!next) {352JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");353ret = NULL;354goto cleanupAndReturn;355}356memcpy(next, iterator, sizeof(struct addrinfo));357next->ai_next = NULL;358if (resNew == NULL) {359resNew = next;360} else {361last->ai_next = next;362}363last = next;364i++;365if (iterator->ai_family == AF_INET) {366inetCount ++;367} else if (iterator->ai_family == AF_INET6) {368inet6Count ++;369}370}371iterator = iterator->ai_next;372}373retLen = i;374iterator = resNew;375376ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);377378if (IS_NULL(ret)) {379/* we may have memory to free at the end of this */380goto cleanupAndReturn;381}382383if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) {384/* AF_INET addresses will be offset by inet6Count */385inetIndex = inet6Count;386inet6Index = 0;387} else {388/* AF_INET6 addresses will be offset by inetCount */389inetIndex = 0;390inet6Index = inetCount;391}392393while (iterator != NULL) {394int ret1;395if (iterator->ai_family == AF_INET) {396jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);397if (IS_NULL(iaObj)) {398ret = NULL;399goto cleanupAndReturn;400}401setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));402if ((*env)->ExceptionCheck(env))403goto cleanupAndReturn;404setInetAddress_hostName(env, iaObj, host);405if ((*env)->ExceptionCheck(env))406goto cleanupAndReturn;407(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);408inetIndex++;409} else if (iterator->ai_family == AF_INET6) {410jint scope = 0;411412jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);413if (IS_NULL(iaObj)) {414ret = NULL;415goto cleanupAndReturn;416}417ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));418if (!ret1) {419ret = NULL;420goto cleanupAndReturn;421}422423scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;424if (scope != 0) { /* zero is default value, no need to set */425setInet6Address_scopeid(env, iaObj, scope);426}427setInetAddress_hostName(env, iaObj, host);428if ((*env)->ExceptionCheck(env))429goto cleanupAndReturn;430(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);431inet6Index++;432}433iterator = iterator->ai_next;434}435}436437cleanupAndReturn:438{439struct addrinfo *iterator, *tmp;440iterator = resNew;441while (iterator != NULL) {442tmp = iterator;443iterator = iterator->ai_next;444free(tmp);445}446JNU_ReleaseStringPlatformChars(env, host, hostname);447}448449freeaddrinfo(res);450#endif /* AF_INET6 */451452return ret;453}454455/*456* Class: java_net_Inet6AddressImpl457* Method: getHostByAddr458* Signature: (I)Ljava/lang/String;459*/460JNIEXPORT jstring JNICALL461Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,462jbyteArray addrArray) {463464jstring ret = NULL;465466#ifdef AF_INET6467char host[NI_MAXHOST+1];468int error = 0;469int len = 0;470jbyte caddr[16];471472struct sockaddr_in him4;473struct sockaddr_in6 him6;474struct sockaddr *sa;475476/*477* For IPv4 addresses construct a sockaddr_in structure.478*/479if ((*env)->GetArrayLength(env, addrArray) == 4) {480jint addr;481(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);482addr = ((caddr[0]<<24) & 0xff000000);483addr |= ((caddr[1] <<16) & 0xff0000);484addr |= ((caddr[2] <<8) & 0xff00);485addr |= (caddr[3] & 0xff);486memset((void *) &him4, 0, sizeof(him4));487him4.sin_addr.s_addr = (uint32_t) htonl(addr);488him4.sin_family = AF_INET;489sa = (struct sockaddr *) &him4;490len = sizeof(him4);491} else {492/*493* For IPv6 address construct a sockaddr_in6 structure.494*/495(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);496memset((void *) &him6, 0, sizeof(him6));497memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );498him6.sin6_family = AF_INET6;499sa = (struct sockaddr *) &him6 ;500len = sizeof(him6) ;501}502503error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,504NI_NAMEREQD);505506if (!error) {507ret = (*env)->NewStringUTF(env, host);508CHECK_NULL_RETURN(ret, NULL);509}510#endif /* AF_INET6 */511512if (ret == NULL) {513JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);514}515516return ret;517}518519#define SET_NONBLOCKING(fd) { \520int flags = fcntl(fd, F_GETFL); \521flags |= O_NONBLOCK; \522fcntl(fd, F_SETFL, flags); \523}524525#ifdef AF_INET6526static jboolean527ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,528struct sockaddr_in6* netif, jint ttl) {529jint size;530jint n;531socklen_t len;532char sendbuf[1500];533unsigned char recvbuf[1500];534struct icmp6_hdr *icmp6;535struct sockaddr_in6 sa_recv;536jbyte *caddr, *recv_caddr;537jchar pid;538jint tmout2, seq = 1;539struct timeval tv;540size_t plen;541542#ifdef __linux__543{544int csum_offset;545/**546* For some strange reason, the linux kernel won't calculate the547* checksum of ICMPv6 packets unless you set this socket option548*/549csum_offset = 2;550setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));551}552#endif553554caddr = (jbyte *)&(him->sin6_addr);555556/* icmp_id is a 16 bit data type, therefore down cast the pid */557pid = (jchar)getpid();558size = 60*1024;559setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));560if (ttl > 0) {561setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));562}563if (netif != NULL) {564if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {565NET_ThrowNew(env, errno, "Can't bind socket");566close(fd);567return JNI_FALSE;568}569}570SET_NONBLOCKING(fd);571572do {573icmp6 = (struct icmp6_hdr *) sendbuf;574icmp6->icmp6_type = ICMP6_ECHO_REQUEST;575icmp6->icmp6_code = 0;576/* let's tag the ECHO packet with our pid so we can identify it */577icmp6->icmp6_id = htons(pid);578icmp6->icmp6_seq = htons(seq);579seq++;580icmp6->icmp6_cksum = 0;581gettimeofday(&tv, NULL);582memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));583plen = sizeof(struct icmp6_hdr) + sizeof(tv);584n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));585if (n < 0 && errno != EINPROGRESS) {586#ifdef __linux__587if (errno != EINVAL && errno != EHOSTUNREACH)588/*589* On some Linux versions, when a socket is bound to the590* loopback interface, sendto will fail and errno will be591* set to EINVAL or EHOSTUNREACH.592* When that happens, don't throw an exception, just return false.593*/594#endif /*__linux__ */595NET_ThrowNew(env, errno, "Can't send ICMP packet");596close(fd);597return JNI_FALSE;598}599600tmout2 = timeout > 1000 ? 1000 : timeout;601do {602tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);603604if (tmout2 >= 0) {605len = sizeof(sa_recv);606n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);607icmp6 = (struct icmp6_hdr *) (recvbuf);608recv_caddr = (jbyte *)&(sa_recv.sin6_addr);609/*610* We did receive something, but is it what we were expecting?611* I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and612* from the host that we are trying to determine is reachable.613*/614if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&615(ntohs(icmp6->icmp6_id) == pid)) {616if (NET_IsEqual(caddr, recv_caddr)) {617close(fd);618return JNI_TRUE;619}620if (NET_IsZeroAddr(caddr)) {621close(fd);622return JNI_TRUE;623}624}625}626} while (tmout2 > 0);627timeout -= 1000;628} while (timeout > 0);629close(fd);630return JNI_FALSE;631}632#endif /* AF_INET6 */633634/*635* Class: java_net_Inet6AddressImpl636* Method: isReachable0637* Signature: ([bII[bI)Z638*/639JNIEXPORT jboolean JNICALL640Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,641jbyteArray addrArray,642jint scope,643jint timeout,644jbyteArray ifArray,645jint ttl, jint if_scope) {646#ifdef AF_INET6647jbyte caddr[16];648jint fd, sz;649struct sockaddr_in6 him6;650struct sockaddr_in6 inf6;651struct sockaddr_in6* netif = NULL;652int len = 0;653int connect_rv = -1;654655/*656* If IPv6 is not enable, then we can't reach an IPv6 address, can we?657*/658if (!ipv6_available()) {659return JNI_FALSE;660}661/*662* If it's an IPv4 address, ICMP won't work with IPv4 mapped address,663* therefore, let's delegate to the Inet4Address method.664*/665sz = (*env)->GetArrayLength(env, addrArray);666if (sz == 4) {667return Java_java_net_Inet4AddressImpl_isReachable0(env, this,668addrArray,669timeout,670ifArray, ttl);671}672673memset((void *) caddr, 0, 16);674memset((void *) &him6, 0, sizeof(him6));675(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);676memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );677him6.sin6_family = AF_INET6;678#ifdef __linux__679if (scope > 0)680him6.sin6_scope_id = scope;681else682him6.sin6_scope_id = getDefaultIPv6Interface( &(him6.sin6_addr));683len = sizeof(struct sockaddr_in6);684#else685if (scope > 0)686him6.sin6_scope_id = scope;687len = sizeof(struct sockaddr_in6);688#endif689/*690* If a network interface was specified, let's create the address691* for it.692*/693if (!(IS_NULL(ifArray))) {694memset((void *) caddr, 0, 16);695memset((void *) &inf6, 0, sizeof(inf6));696(*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);697memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );698inf6.sin6_family = AF_INET6;699inf6.sin6_scope_id = if_scope;700netif = &inf6;701}702/*703* If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST704* otherwise we'll try a tcp socket to the Echo port (7).705* Note that this is empiric, and not connecting could mean it's blocked706* or the echo service has been disabled.707*/708709fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);710711if (fd != -1) { /* Good to go, let's do a ping */712return ping6(env, fd, &him6, timeout, netif, ttl);713}714715/* No good, let's fall back on TCP */716fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);717if (fd == JVM_IO_ERR) {718/* note: if you run out of fds, you may not be able to load719* the exception class, and get a NoClassDefFoundError720* instead.721*/722NET_ThrowNew(env, errno, "Can't create socket");723return JNI_FALSE;724}725if (ttl > 0) {726setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));727}728729/*730* A network interface was specified, so let's bind to it.731*/732if (netif != NULL) {733if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {734NET_ThrowNew(env, errno, "Can't bind socket");735close(fd);736return JNI_FALSE;737}738}739SET_NONBLOCKING(fd);740741/* no need to use NET_Connect as non-blocking */742him6.sin6_port = htons((short) 7); /* Echo port */743connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);744745/**746* connection established or refused immediately, either way it means747* we were able to reach the host!748*/749if (connect_rv == 0 || errno == ECONNREFUSED) {750close(fd);751return JNI_TRUE;752} else {753int optlen;754755switch (errno) {756case ENETUNREACH: /* Network Unreachable */757case EAFNOSUPPORT: /* Address Family not supported */758case EADDRNOTAVAIL: /* address is not available on the remote machine */759#ifdef __linux__760case EINVAL:761case EHOSTUNREACH:762/*763* On some Linux versions, when a socket is bound to the764* loopback interface, connect will fail and errno will765* be set to EINVAL or EHOSTUNREACH. When that happens,766* don't throw an exception, just return false.767*/768#endif /* __linux__ */769close(fd);770return JNI_FALSE;771}772773if (errno != EINPROGRESS) {774NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",775"connect failed");776close(fd);777return JNI_FALSE;778}779780timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);781782if (timeout >= 0) {783/* has connection been established */784optlen = sizeof(connect_rv);785if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,786&optlen) <0) {787connect_rv = errno;788}789if (connect_rv == 0 || ECONNREFUSED) {790close(fd);791return JNI_TRUE;792}793}794close(fd);795return JNI_FALSE;796}797#else /* AF_INET6 */798return JNI_FALSE;799#endif /* AF_INET6 */800}801802803