Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/java/net/Inet4AddressImpl.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_systm.h>30#include <netinet/in.h>31#include <netinet/ip.h>32#include <netinet/ip_icmp.h>33#include <netdb.h>34#include <string.h>35#include <stdlib.h>36#include <ctype.h>3738#ifdef _ALLBSD_SOURCE39#include <unistd.h>40#include <sys/param.h>41#endif4243#include "jvm.h"44#include "jni_util.h"45#include "net_util.h"4647#include "java_net_Inet4AddressImpl.h"4849#if !defined(__ANDROID__) && defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))50#define HAS_GLIBC_GETHOSTBY_R 151#endif525354#if defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R)55extern jobjectArray lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6);5657/* Use getaddrinfo(3), which is thread safe */58/************************************************************************59* Inet4AddressImpl60*/6162/*63* Class: java_net_Inet4AddressImpl64* Method: getLocalHostName65* Signature: ()Ljava/lang/String;66*/67JNIEXPORT jstring JNICALL68Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {69char hostname[NI_MAXHOST + 1];7071hostname[0] = '\0';72if (JVM_GetHostName(hostname, NI_MAXHOST)) {73strcpy(hostname, "localhost");74#if defined(__solaris__)75} else {76// try to resolve hostname via nameservice77// if it is known but getnameinfo fails, hostname will still be the78// value from gethostname79struct addrinfo hints, *res;8081// make sure string is null-terminated82hostname[NI_MAXHOST] = '\0';83memset(&hints, 0, sizeof(hints));84hints.ai_flags = AI_CANONNAME;85hints.ai_family = AF_INET;8687if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {88getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST,89NULL, 0, NI_NAMEREQD);90freeaddrinfo(res);91}92}93#else94} else {95// make sure string is null-terminated96hostname[NI_MAXHOST] = '\0';97}98#endif99return (*env)->NewStringUTF(env, hostname);100}101102/*103* Find an internet address for a given hostname. Note that this104* code only works for addresses of type INET. The translation105* of %d.%d.%d.%d to an address (int) occurs in java now, so the106* String "host" shouldn't *ever* be a %d.%d.%d.%d string107*108* Class: java_net_Inet4AddressImpl109* Method: lookupAllHostAddr110* Signature: (Ljava/lang/String;)[[B111*/112113JNIEXPORT jobjectArray JNICALL114Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,115jstring host) {116const char *hostname;117jobject name;118jobjectArray ret = 0;119int retLen = 0;120121int getaddrinfo_error=0;122struct addrinfo hints, *res, *resNew = NULL;123124initInetAddressIDs(env);125JNU_CHECK_EXCEPTION_RETURN(env, NULL);126127if (IS_NULL(host)) {128JNU_ThrowNullPointerException(env, "host is null");129return 0;130}131hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);132CHECK_NULL_RETURN(hostname, NULL);133134memset(&hints, 0, sizeof(hints));135hints.ai_flags = AI_CANONNAME;136hints.ai_family = AF_INET;137138/*139* Workaround for Solaris bug 4160367 - if a hostname contains a140* white space then 0.0.0.0 is returned141*/142if (isspace((unsigned char)hostname[0])) {143JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",144(char *)hostname);145JNU_ReleaseStringPlatformChars(env, host, hostname);146return NULL;147}148149getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res);150151#ifdef MACOSX152if (getaddrinfo_error) {153// If getaddrinfo fails try getifaddrs.154ret = lookupIfLocalhost(env, hostname, JNI_FALSE);155if (ret != NULL || (*env)->ExceptionCheck(env)) {156JNU_ReleaseStringPlatformChars(env, host, hostname);157return ret;158}159}160#endif161162if (getaddrinfo_error) {163/* report error */164ThrowUnknownHostExceptionWithGaiError(165env, hostname, getaddrinfo_error);166JNU_ReleaseStringPlatformChars(env, host, hostname);167return NULL;168} else {169int i = 0;170struct addrinfo *itr, *last = NULL, *iterator = res;171while (iterator != NULL) {172int skip = 0;173itr = resNew;174175while (itr != NULL) {176struct sockaddr_in *addr1, *addr2;177178addr1 = (struct sockaddr_in *)iterator->ai_addr;179addr2 = (struct sockaddr_in *)itr->ai_addr;180if (addr1->sin_addr.s_addr ==181addr2->sin_addr.s_addr) {182skip = 1;183break;184}185186itr = itr->ai_next;187}188189if (!skip) {190struct addrinfo *next191= (struct addrinfo*) malloc(sizeof(struct addrinfo));192if (!next) {193JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");194ret = NULL;195goto cleanupAndReturn;196}197memcpy(next, iterator, sizeof(struct addrinfo));198next->ai_next = NULL;199if (resNew == NULL) {200resNew = next;201} else {202last->ai_next = next;203}204last = next;205i++;206}207iterator = iterator->ai_next;208}209210retLen = i;211iterator = resNew;212i = 0;213214name = (*env)->NewStringUTF(env, hostname);215if (IS_NULL(name)) {216goto cleanupAndReturn;217}218219ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);220if (IS_NULL(ret)) {221/* we may have memory to free at the end of this */222goto cleanupAndReturn;223}224225while (iterator != NULL) {226/* We need 4 bytes to store ipv4 address; */227int len = 4;228229jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);230if (IS_NULL(iaObj)) {231/* we may have memory to free at the end of this */232ret = NULL;233goto cleanupAndReturn;234}235setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));236if ((*env)->ExceptionCheck(env))237goto cleanupAndReturn;238setInetAddress_hostName(env, iaObj, name);239if ((*env)->ExceptionCheck(env))240goto cleanupAndReturn;241(*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);242i++;243iterator = iterator->ai_next;244}245}246247cleanupAndReturn:248{249struct addrinfo *iterator, *tmp;250iterator = resNew;251while (iterator != NULL) {252tmp = iterator;253iterator = iterator->ai_next;254free(tmp);255}256JNU_ReleaseStringPlatformChars(env, host, hostname);257}258259freeaddrinfo(res);260261return ret;262263}264265/*266* Class: java_net_Inet4AddressImpl267* Method: getHostByAddr268* Signature: (I)Ljava/lang/String;269*/270JNIEXPORT jstring JNICALL271Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,272jbyteArray addrArray) {273jstring ret = NULL;274275char host[NI_MAXHOST+1];276jfieldID fid;277int error = 0;278jint family;279struct sockaddr *him ;280int len = 0;281jbyte caddr[4];282jint addr;283284struct sockaddr_in him4;285struct sockaddr *sa;286287/*288* For IPv4 addresses construct a sockaddr_in structure.289*/290(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);291addr = ((caddr[0]<<24) & 0xff000000);292addr |= ((caddr[1] <<16) & 0xff0000);293addr |= ((caddr[2] <<8) & 0xff00);294addr |= (caddr[3] & 0xff);295memset((char *) &him4, 0, sizeof(him4));296him4.sin_addr.s_addr = (uint32_t) htonl(addr);297him4.sin_family = AF_INET;298sa = (struct sockaddr *) &him4;299len = sizeof(him4);300301error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,302NI_NAMEREQD);303304if (!error) {305ret = (*env)->NewStringUTF(env, host);306}307308if (ret == NULL) {309JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);310}311312return ret;313314}315316#else /* defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R) */317318/* the initial size of our hostent buffers */319#ifndef NI_MAXHOST320#define NI_MAXHOST 1025321#endif322323/************************************************************************324* Inet4AddressImpl325*/326327/*328* Class: java_net_Inet4AddressImpl329* Method: getLocalHostName330* Signature: ()Ljava/lang/String;331*/332JNIEXPORT jstring JNICALL333Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {334char hostname[NI_MAXHOST+1];335336hostname[0] = '\0';337if (JVM_GetHostName(hostname, sizeof(hostname))) {338/* Something went wrong, maybe networking is not setup? */339strcpy(hostname, "localhost");340} else {341struct addrinfo hints, *res;342int error;343344hostname[NI_MAXHOST] = '\0';345memset(&hints, 0, sizeof(hints));346hints.ai_flags = AI_CANONNAME;347hints.ai_family = AF_INET;348349error = getaddrinfo(hostname, NULL, &hints, &res);350351if (error == 0) {/* host is known to name service */352getnameinfo(res->ai_addr,353res->ai_addrlen,354hostname,355NI_MAXHOST,356NULL,3570,358NI_NAMEREQD);359360/* if getnameinfo fails hostname is still the value361from gethostname */362363freeaddrinfo(res);364}365}366return (*env)->NewStringUTF(env, hostname);367}368369/*370* Find an internet address for a given hostname. Note that this371* code only works for addresses of type INET. The translation372* of %d.%d.%d.%d to an address (int) occurs in java now, so the373* String "host" shouldn't *ever* be a %d.%d.%d.%d string374*375* Class: java_net_Inet4AddressImpl376* Method: lookupAllHostAddr377* Signature: (Ljava/lang/String;)[[B378*/379380JNIEXPORT jobjectArray JNICALL381Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,382jstring host) {383const char *hostname;384jobjectArray ret = 0;385int retLen = 0;386int error = 0;387struct addrinfo hints, *res, *resNew = NULL;388389initInetAddressIDs(env);390JNU_CHECK_EXCEPTION_RETURN(env, NULL);391392if (IS_NULL(host)) {393JNU_ThrowNullPointerException(env, "host is null");394return 0;395}396hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);397CHECK_NULL_RETURN(hostname, NULL);398399/* Try once, with our static buffer. */400memset(&hints, 0, sizeof(hints));401hints.ai_flags = AI_CANONNAME;402hints.ai_family = AF_INET;403404#ifdef __solaris__405/*406* Workaround for Solaris bug 4160367 - if a hostname contains a407* white space then 0.0.0.0 is returned408*/409if (isspace((unsigned char)hostname[0])) {410JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",411(char *)hostname);412JNU_ReleaseStringPlatformChars(env, host, hostname);413return NULL;414}415#endif416417error = getaddrinfo(hostname, NULL, &hints, &res);418419if (error) {420/* report error */421ThrowUnknownHostExceptionWithGaiError(env, hostname, error);422JNU_ReleaseStringPlatformChars(env, host, hostname);423return NULL;424} else {425int i = 0;426struct addrinfo *itr, *last = NULL, *iterator = res;427428while (iterator != NULL) {429// remove the duplicate one430int skip = 0;431itr = resNew;432while (itr != NULL) {433struct sockaddr_in *addr1, *addr2;434addr1 = (struct sockaddr_in *)iterator->ai_addr;435addr2 = (struct sockaddr_in *)itr->ai_addr;436if (addr1->sin_addr.s_addr ==437addr2->sin_addr.s_addr) {438skip = 1;439break;440}441itr = itr->ai_next;442}443444if (!skip) {445struct addrinfo *next446= (struct addrinfo*) malloc(sizeof(struct addrinfo));447if (!next) {448JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");449ret = NULL;450goto cleanupAndReturn;451}452memcpy(next, iterator, sizeof(struct addrinfo));453next->ai_next = NULL;454if (resNew == NULL) {455resNew = next;456} else {457last->ai_next = next;458}459last = next;460i++;461}462iterator = iterator->ai_next;463}464465retLen = i;466iterator = resNew;467468ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);469470if (IS_NULL(ret)) {471/* we may have memory to free at the end of this */472goto cleanupAndReturn;473}474475i = 0;476while (iterator != NULL) {477jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);478if (IS_NULL(iaObj)) {479ret = NULL;480goto cleanupAndReturn;481}482setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));483if ((*env)->ExceptionCheck(env))484goto cleanupAndReturn;485setInetAddress_hostName(env, iaObj, host);486if ((*env)->ExceptionCheck(env))487goto cleanupAndReturn;488(*env)->SetObjectArrayElement(env, ret, i++, iaObj);489iterator = iterator->ai_next;490}491}492493cleanupAndReturn:494{495struct addrinfo *iterator, *tmp;496iterator = resNew;497while (iterator != NULL) {498tmp = iterator;499iterator = iterator->ai_next;500free(tmp);501}502JNU_ReleaseStringPlatformChars(env, host, hostname);503}504505freeaddrinfo(res);506507return ret;508}509510/*511* Class: java_net_Inet4AddressImpl512* Method: getHostByAddr513* Signature: (I)Ljava/lang/String;514*/515JNIEXPORT jstring JNICALL516Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,517jbyteArray addrArray) {518jstring ret = NULL;519520char host[NI_MAXHOST+1];521int error = 0;522int len = 0;523jbyte caddr[4];524525struct sockaddr_in him4;526struct sockaddr *sa;527528jint addr;529(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);530addr = ((caddr[0]<<24) & 0xff000000);531addr |= ((caddr[1] <<16) & 0xff0000);532addr |= ((caddr[2] <<8) & 0xff00);533addr |= (caddr[3] & 0xff);534memset((void *) &him4, 0, sizeof(him4));535him4.sin_addr.s_addr = (uint32_t) htonl(addr);536him4.sin_family = AF_INET;537sa = (struct sockaddr *) &him4;538len = sizeof(him4);539540error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,541NI_NAMEREQD);542543if (!error) {544ret = (*env)->NewStringUTF(env, host);545}546547if (ret == NULL) {548JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);549}550551return ret;552}553554#endif /* _ALLBSD_SOURCE */555556#define SET_NONBLOCKING(fd) { \557int flags = fcntl(fd, F_GETFL); \558flags |= O_NONBLOCK; \559fcntl(fd, F_SETFL, flags); \560}561562/**563* ping implementation.564* Send a ICMP_ECHO_REQUEST packet every second until either the timeout565* expires or a answer is received.566* Returns true is an ECHO_REPLY is received, otherwise, false.567*/568static jboolean569ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,570struct sockaddr_in* netif, jint ttl) {571jint size;572jint n, hlen1, icmplen;573socklen_t len;574char sendbuf[1500];575char recvbuf[1500];576struct icmp *icmp;577struct ip *ip;578struct sockaddr_in sa_recv;579jchar pid;580jint tmout2, seq = 1;581struct timeval tv;582size_t plen;583584/* icmp_id is a 16 bit data type, therefore down cast the pid */585pid = (jchar)getpid();586size = 60*1024;587setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));588/*589* sets the ttl (max number of hops)590*/591if (ttl > 0) {592setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));593}594/*595* a specific interface was specified, so let's bind the socket596* to that interface to ensure the requests are sent only through it.597*/598if (netif != NULL) {599if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {600NET_ThrowNew(env, errno, "Can't bind socket");601close(fd);602return JNI_FALSE;603}604}605/*606* Make the socket non blocking so we can use select607*/608SET_NONBLOCKING(fd);609do {610/*611* create the ICMP request612*/613icmp = (struct icmp *) sendbuf;614icmp->icmp_type = ICMP_ECHO;615icmp->icmp_code = 0;616icmp->icmp_id = htons(pid);617icmp->icmp_seq = htons(seq);618seq++;619gettimeofday(&tv, NULL);620memcpy(icmp->icmp_data, &tv, sizeof(tv));621plen = ICMP_ADVLENMIN + sizeof(tv);622icmp->icmp_cksum = 0;623icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);624/*625* send it626*/627n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,628sizeof(struct sockaddr));629if (n < 0 && errno != EINPROGRESS ) {630#ifdef __linux__631if (errno != EINVAL && errno != EHOSTUNREACH)632/*633* On some Linux versions, when a socket is bound to the loopback634* interface, sendto will fail and errno will be set to635* EINVAL or EHOSTUNREACH. When that happens, don't throw an636* exception, just return false.637*/638#endif /*__linux__ */639NET_ThrowNew(env, errno, "Can't send ICMP packet");640close(fd);641return JNI_FALSE;642}643644tmout2 = timeout > 1000 ? 1000 : timeout;645do {646tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);647if (tmout2 >= 0) {648len = sizeof(sa_recv);649n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);650ip = (struct ip*) recvbuf;651hlen1 = (ip->ip_hl) << 2;652icmp = (struct icmp *) (recvbuf + hlen1);653icmplen = n - hlen1;654/*655* We did receive something, but is it what we were expecting?656* I.E.: A ICMP_ECHOREPLY packet with the proper PID.657*/658if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY659&& (ntohs(icmp->icmp_id) == pid)) {660if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {661close(fd);662return JNI_TRUE;663}664665if (him->sin_addr.s_addr == 0) {666close(fd);667return JNI_TRUE;668}669}670671}672} while (tmout2 > 0);673timeout -= 1000;674} while (timeout >0);675close(fd);676return JNI_FALSE;677}678679/*680* Class: java_net_Inet4AddressImpl681* Method: isReachable0682* Signature: ([bI[bI)Z683*/684JNIEXPORT jboolean JNICALL685Java_java_net_Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,686jbyteArray addrArray,687jint timeout,688jbyteArray ifArray,689jint ttl) {690jint addr;691jbyte caddr[4];692jint fd;693struct sockaddr_in him;694struct sockaddr_in* netif = NULL;695struct sockaddr_in inf;696int len = 0;697int connect_rv = -1;698int sz;699700memset((char *) caddr, 0, sizeof(caddr));701memset((char *) &him, 0, sizeof(him));702memset((char *) &inf, 0, sizeof(inf));703sz = (*env)->GetArrayLength(env, addrArray);704if (sz != 4) {705return JNI_FALSE;706}707(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);708addr = ((caddr[0]<<24) & 0xff000000);709addr |= ((caddr[1] <<16) & 0xff0000);710addr |= ((caddr[2] <<8) & 0xff00);711addr |= (caddr[3] & 0xff);712addr = htonl(addr);713him.sin_addr.s_addr = addr;714him.sin_family = AF_INET;715len = sizeof(him);716/*717* If a network interface was specified, let's create the address718* for it.719*/720if (!(IS_NULL(ifArray))) {721memset((char *) caddr, 0, sizeof(caddr));722(*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);723addr = ((caddr[0]<<24) & 0xff000000);724addr |= ((caddr[1] <<16) & 0xff0000);725addr |= ((caddr[2] <<8) & 0xff00);726addr |= (caddr[3] & 0xff);727addr = htonl(addr);728inf.sin_addr.s_addr = addr;729inf.sin_family = AF_INET;730inf.sin_port = 0;731netif = &inf;732}733734/*735* Let's try to create a RAW socket to send ICMP packets736* This usually requires "root" privileges, so it's likely to fail.737*/738fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);739if (fd != -1) {740/*741* It didn't fail, so we can use ICMP_ECHO requests.742*/743return ping4(env, fd, &him, timeout, netif, ttl);744}745746/*747* Can't create a raw socket, so let's try a TCP socket748*/749fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);750if (fd == JVM_IO_ERR) {751/* note: if you run out of fds, you may not be able to load752* the exception class, and get a NoClassDefFoundError753* instead.754*/755NET_ThrowNew(env, errno, "Can't create socket");756return JNI_FALSE;757}758if (ttl > 0) {759setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));760}761762/*763* A network interface was specified, so let's bind to it.764*/765if (netif != NULL) {766if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {767NET_ThrowNew(env, errno, "Can't bind socket");768close(fd);769return JNI_FALSE;770}771}772773/*774* Make the socket non blocking so we can use select/poll.775*/776SET_NONBLOCKING(fd);777778/* no need to use NET_Connect as non-blocking */779him.sin_port = htons(7); /* Echo */780connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);781782/**783* connection established or refused immediately, either way it means784* we were able to reach the host!785*/786if (connect_rv == 0 || errno == ECONNREFUSED) {787close(fd);788return JNI_TRUE;789} else {790int optlen;791792switch (errno) {793case ENETUNREACH: /* Network Unreachable */794case EAFNOSUPPORT: /* Address Family not supported */795case EADDRNOTAVAIL: /* address is not available on the remote machine */796#ifdef __linux__797case EINVAL:798case EHOSTUNREACH:799/*800* On some Linux versions, when a socket is bound to the loopback801* interface, connect will fail and errno will be set to EINVAL802* or EHOSTUNREACH. When that happens, don't throw an exception,803* just return false.804*/805#endif /* __linux__ */806close(fd);807return JNI_FALSE;808}809810if (errno != EINPROGRESS) {811NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",812"connect failed");813close(fd);814return JNI_FALSE;815}816817timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);818if (timeout >= 0) {819/* has connection been established? */820optlen = sizeof(connect_rv);821if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,822&optlen) <0) {823connect_rv = errno;824}825if (connect_rv == 0 || connect_rv == ECONNREFUSED) {826close(fd);827return JNI_TRUE;828}829}830close(fd);831return JNI_FALSE;832}833}834835836