1 /* 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <windows.h> 27 #include <winsock2.h> 28 #include <ctype.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <malloc.h> 32 #include <sys/types.h> 33 #include <process.h> 34 35 #include "java_net_InetAddress.h" 36 #include "java_net_Inet4AddressImpl.h" 37 #include "java_net_Inet6AddressImpl.h" 38 #include "net_util.h" 39 #include "icmp.h" 40 41 #ifdef WIN32 42 #ifndef _WIN64 43 44 /* Retain this code a little longer to support building in 45 * old environments. _MSC_VER is defined as: 46 * 1200 for MSVC++ 6.0 47 * 1310 for Vc7 48 */ 49 #if defined(_MSC_VER) && _MSC_VER < 1310 50 #define sockaddr_in6 SOCKADDR_IN6 51 #endif 52 #endif 53 #define uint32_t UINT32 54 #endif 55 56 /* 57 * Inet6AddressImpl 58 */ 59 60 /* 61 * Class: java_net_Inet6AddressImpl 62 * Method: getLocalHostName 63 * Signature: ()Ljava/lang/String; 64 */ 65 JNIEXPORT jstring JNICALL 66 Java_java_net_Inet6AddressImpl_getLocalHostName (JNIEnv *env, jobject this) { 67 char hostname [256]; 68 69 if (gethostname (hostname, sizeof (hostname)) == -1) { 70 strcpy (hostname, "localhost"); 71 } 72 return JNU_NewStringPlatform (env, hostname); 73 } 74 75 JNIEXPORT jobjectArray JNICALL 76 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, 77 jstring host) { 78 const char *hostname; 79 jobjectArray ret = 0; 80 int retLen = 0; 81 jboolean preferIPv6Address; 82 83 int error=0; 84 struct addrinfo hints, *res, *resNew = NULL; 85 86 initInetAddressIDs(env); 87 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 88 89 if (IS_NULL(host)) { 90 JNU_ThrowNullPointerException(env, "host is null"); 91 return 0; 92 } 93 hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); 94 CHECK_NULL_RETURN(hostname, NULL); 95 96 /* get the address preference */ 97 preferIPv6Address 98 = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID); 99 100 /* Try once, with our static buffer. */ 101 memset(&hints, 0, sizeof(hints)); 102 hints.ai_flags = AI_CANONNAME; 103 hints.ai_family = AF_UNSPEC; 104 105 error = getaddrinfo(hostname, NULL, &hints, &res); 106 107 if (error) { 108 if (WSAGetLastError() == WSATRY_AGAIN) { 109 NET_ThrowByNameWithLastError(env, 110 JNU_JAVANETPKG "UnknownHostException", 111 hostname); 112 JNU_ReleaseStringPlatformChars(env, host, hostname); 113 return NULL; 114 } else { 115 /* report error */ 116 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", 117 (char *)hostname); 118 JNU_ReleaseStringPlatformChars(env, host, hostname); 119 return NULL; 120 } 121 } else { 122 int i = 0; 123 int inetCount = 0, inet6Count = 0, inetIndex, inet6Index; 124 struct addrinfo *itr, *last, *iterator = res; 125 while (iterator != NULL) { 126 int skip = 0; 127 itr = resNew; 128 while (itr != NULL) { 129 if (iterator->ai_family == itr->ai_family && 130 iterator->ai_addrlen == itr->ai_addrlen) { 131 if (itr->ai_family == AF_INET) { /* AF_INET */ 132 struct sockaddr_in *addr1, *addr2; 133 addr1 = (struct sockaddr_in *)iterator->ai_addr; 134 addr2 = (struct sockaddr_in *)itr->ai_addr; 135 if (addr1->sin_addr.s_addr == 136 addr2->sin_addr.s_addr) { 137 skip = 1; 138 break; 139 } 140 } else { 141 int t; 142 struct sockaddr_in6 *addr1, *addr2; 143 addr1 = (struct sockaddr_in6 *)iterator->ai_addr; 144 addr2 = (struct sockaddr_in6 *)itr->ai_addr; 145 146 for (t = 0; t < 16; t++) { 147 if (addr1->sin6_addr.s6_addr[t] != 148 addr2->sin6_addr.s6_addr[t]) { 149 break; 150 } 151 } 152 if (t < 16) { 153 itr = itr->ai_next; 154 continue; 155 } else { 156 skip = 1; 157 break; 158 } 159 } 160 } else if (iterator->ai_family != AF_INET && 161 iterator->ai_family != AF_INET6) { 162 /* we can't handle other family types */ 163 skip = 1; 164 break; 165 } 166 itr = itr->ai_next; 167 } 168 169 if (!skip) { 170 struct addrinfo *next 171 = (struct addrinfo*) malloc(sizeof(struct addrinfo)); 172 if (!next) { 173 JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); 174 ret = NULL; 175 goto cleanupAndReturn; 176 } 177 memcpy(next, iterator, sizeof(struct addrinfo)); 178 next->ai_next = NULL; 179 if (resNew == NULL) { 180 resNew = next; 181 } else { 182 last->ai_next = next; 183 } 184 last = next; 185 i++; 186 if (iterator->ai_family == AF_INET) { 187 inetCount ++; 188 } else if (iterator->ai_family == AF_INET6) { 189 inet6Count ++; 190 } 191 } 192 iterator = iterator->ai_next; 193 } 194 retLen = i; 195 iterator = resNew; 196 i = 0; 197 ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL); 198 199 if (IS_NULL(ret)) { 200 /* we may have memory to free at the end of this */ 201 goto cleanupAndReturn; 202 } 203 204 if (preferIPv6Address) { 205 inetIndex = inet6Count; 206 inet6Index = 0; 207 } else { 208 inetIndex = 0; 209 inet6Index = inetCount; 210 } 211 212 while (iterator != NULL) { 213 if (iterator->ai_family == AF_INET) { 214 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); 215 if (IS_NULL(iaObj)) { 216 ret = NULL; 217 goto cleanupAndReturn; 218 } 219 setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); 220 setInetAddress_hostName(env, iaObj, host); 221 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); 222 inetIndex ++; 223 } else if (iterator->ai_family == AF_INET6) { 224 jint scope = 0; 225 jboolean ret1; 226 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); 227 if (IS_NULL(iaObj)) { 228 ret = NULL; 229 goto cleanupAndReturn; 230 } 231 ret1 = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); 232 if (ret1 == JNI_FALSE) { 233 ret = NULL; 234 goto cleanupAndReturn; 235 } 236 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; 237 if (scope != 0) { /* zero is default value, no need to set */ 238 setInet6Address_scopeid(env, iaObj, scope); 239 } 240 setInetAddress_hostName(env, iaObj, host); 241 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); 242 inet6Index ++; 243 } 244 iterator = iterator->ai_next; 245 } 246 } 247 248 cleanupAndReturn: 249 { 250 struct addrinfo *iterator, *tmp; 251 iterator = resNew; 252 while (iterator != NULL) { 253 tmp = iterator; 254 iterator = iterator->ai_next; 255 free(tmp); 256 } 257 JNU_ReleaseStringPlatformChars(env, host, hostname); 258 } 259 260 freeaddrinfo(res); 261 262 return ret; 263 } 264 265 /* 266 * Class: java_net_Inet6AddressImpl 267 * Method: getHostByAddr 268 * Signature: (I)Ljava/lang/String; 269 */ 270 JNIEXPORT jstring JNICALL 271 Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, 272 jbyteArray addrArray) { 273 jstring ret = NULL; 274 275 char host[NI_MAXHOST+1]; 276 int error = 0; 277 int len = 0; 278 jbyte caddr[16]; 279 280 struct sockaddr_in him4; 281 struct sockaddr_in6 him6; 282 struct sockaddr *sa; 283 284 /* 285 * For IPv4 addresses construct a sockaddr_in structure. 286 */ 287 if ((*env)->GetArrayLength(env, addrArray) == 4) { 288 jint addr; 289 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); 290 addr = ((caddr[0]<<24) & 0xff000000); 291 addr |= ((caddr[1] <<16) & 0xff0000); 292 addr |= ((caddr[2] <<8) & 0xff00); 293 addr |= (caddr[3] & 0xff); 294 memset((char *) &him4, 0, sizeof(him4)); 295 him4.sin_addr.s_addr = (uint32_t) htonl(addr); 296 him4.sin_family = AF_INET; 297 sa = (struct sockaddr *) &him4; 298 len = sizeof(him4); 299 } else { 300 /* 301 * For IPv6 address construct a sockaddr_in6 structure. 302 */ 303 (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); 304 memset((char *) &him6, 0, sizeof(him6)); 305 memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); 306 him6.sin6_family = AF_INET6; 307 sa = (struct sockaddr *) &him6 ; 308 len = sizeof(him6) ; 309 } 310 311 error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD); 312 313 if (!error) { 314 ret = (*env)->NewStringUTF(env, host); 315 CHECK_NULL_RETURN(ret, NULL); 316 } 317 318 if (ret == NULL) { 319 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL); 320 } 321 322 return ret; 323 } 324 325 #ifdef AF_INET6 326 327 328 /** 329 * ping implementation. 330 * Send a ICMP_ECHO_REQUEST packet every second until either the timeout 331 * expires or a answer is received. 332 * Returns true is an ECHO_REPLY is received, otherwise, false. 333 */ 334 static jboolean 335 ping6(JNIEnv *env, jint fd, struct SOCKADDR_IN6* him, jint timeout, 336 struct SOCKADDR_IN6* netif, jint ttl) { 337 jint size; 338 jint n, len, i; 339 char sendbuf[1500]; 340 char auxbuf[1500]; 341 unsigned char recvbuf[1500]; 342 struct icmp6_hdr *icmp6; 343 struct SOCKADDR_IN6 sa_recv; 344 unsigned short pid, seq; 345 int read_rv = 0; 346 WSAEVENT hEvent; 347 struct ip6_pseudo_hdr *pseudo_ip6; 348 int timestamp; 349 int tmout2; 350 351 /* Initialize the sequence number to a suitable random number and 352 shift right one place to allow sufficient room for increamenting. */ 353 seq = ((unsigned short)rand()) >> 1; 354 355 /* icmp_id is a 16 bit data type, therefore down cast the pid */ 356 pid = (unsigned short) _getpid(); 357 358 size = 60*1024; 359 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&size, sizeof(size)); 360 /** 361 * A TTL was specified, let's set the socket option. 362 */ 363 if (ttl > 0) { 364 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *) &ttl, sizeof(ttl)); 365 } 366 367 /** 368 * A network interface was specified, let's bind to it. 369 */ 370 if (netif != NULL) { 371 if (NET_Bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) < 0){ 372 NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket to interface"); 373 closesocket(fd); 374 return JNI_FALSE; 375 } 376 } 377 378 /* 379 * Make the socket non blocking 380 */ 381 hEvent = WSACreateEvent(); 382 WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE); 383 384 /** 385 * send 1 ICMP REQUEST every second until either we get a valid reply 386 * or the timeout expired. 387 */ 388 do { 389 /* let's tag the ECHO packet with our pid so we can identify it */ 390 timestamp = GetCurrentTime(); 391 memset(sendbuf, 0, 1500); 392 icmp6 = (struct icmp6_hdr *) sendbuf; 393 icmp6->icmp6_type = ICMP6_ECHO_REQUEST; 394 icmp6->icmp6_code = 0; 395 icmp6->icmp6_id = htons(pid); 396 icmp6->icmp6_seq = htons(seq); 397 icmp6->icmp6_cksum = 0; 398 memcpy((icmp6 + 1), ×tamp, sizeof(int)); 399 if (netif != NULL) { 400 memset(auxbuf, 0, 1500); 401 pseudo_ip6 = (struct ip6_pseudo_hdr*) auxbuf; 402 memcpy(&pseudo_ip6->ip6_src, &netif->sin6_addr, sizeof(struct in6_addr)); 403 memcpy(&pseudo_ip6->ip6_dst, &him->sin6_addr, sizeof(struct in6_addr)); 404 pseudo_ip6->ip6_plen= htonl( 64 ); 405 pseudo_ip6->ip6_nxt = htonl( IPPROTO_ICMPV6 ); 406 memcpy(auxbuf + sizeof(struct ip6_pseudo_hdr), icmp6, 64); 407 /** 408 * We shouldn't have to do that as computing the checksum is supposed 409 * to be done by the IPv6 stack. Unfortunately windows, here too, is 410 * uterly broken, or non compliant, so let's do it. 411 * Problem is to compute the checksum I need to know the source address 412 * which happens only if I know the interface to be used... 413 */ 414 icmp6->icmp6_cksum = in_cksum((u_short *)pseudo_ip6, sizeof(struct ip6_pseudo_hdr) + 64); 415 } 416 417 /** 418 * Ping! 419 */ 420 n = sendto(fd, sendbuf, 64, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6)); 421 if (n < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEADDRNOTAVAIL)) { 422 // Happens when using a "tunnel interface" for instance. 423 // Or trying to send a packet on a different scope. 424 closesocket(fd); 425 WSACloseEvent(hEvent); 426 return JNI_FALSE; 427 } 428 if (n < 0 && WSAGetLastError() != WSAEWOULDBLOCK) { 429 NET_ThrowNew(env, WSAGetLastError(), "Can't send ICMP packet"); 430 closesocket(fd); 431 WSACloseEvent(hEvent); 432 return JNI_FALSE; 433 } 434 435 tmout2 = timeout > 1000 ? 1000 : timeout; 436 do { 437 tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); 438 439 if (tmout2 >= 0) { 440 len = sizeof(sa_recv); 441 memset(recvbuf, 0, 1500); 442 /** 443 * For some unknown reason, besides plain stupidity, windows 444 * truncates the first 4 bytes of the icmpv6 header some we can't 445 * check for the ICMP_ECHOREPLY value. 446 * we'll check the other values, though 447 */ 448 n = recvfrom(fd, recvbuf + 4, sizeof(recvbuf) - 4, 0, (struct sockaddr*) &sa_recv, &len); 449 icmp6 = (struct icmp6_hdr *) (recvbuf); 450 memcpy(&i, (icmp6 + 1), sizeof(int)); 451 /** 452 * Is that the reply we were expecting? 453 */ 454 if (n >= 8 && ntohs(icmp6->icmp6_seq) == seq && 455 ntohs(icmp6->icmp6_id) == pid && i == timestamp) { 456 closesocket(fd); 457 WSACloseEvent(hEvent); 458 return JNI_TRUE; 459 } 460 } 461 } while (tmout2 > 0); 462 timeout -= 1000; 463 seq++; 464 } while (timeout > 0); 465 closesocket(fd); 466 WSACloseEvent(hEvent); 467 return JNI_FALSE; 468 } 469 #endif /* AF_INET6 */ 470 471 /* 472 * Class: java_net_Inet6AddressImpl 473 * Method: isReachable0 474 * Signature: ([bII[bI)Z 475 */ 476 JNIEXPORT jboolean JNICALL 477 Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this, 478 jbyteArray addrArray, 479 jint scope, 480 jint timeout, 481 jbyteArray ifArray, 482 jint ttl, jint if_scope) { 483 #ifdef AF_INET6 484 jbyte caddr[16]; 485 jint fd, sz; 486 struct sockaddr_in6 him6; 487 struct sockaddr_in6* netif = NULL; 488 struct sockaddr_in6 inf6; 489 WSAEVENT hEvent; 490 int len = 0; 491 int connect_rv = -1; 492 493 /* 494 * If IPv6 is not enable, then we can't reach an IPv6 address, can we? 495 * Actually, we probably shouldn't even get here. 496 */ 497 if (!ipv6_available()) { 498 return JNI_FALSE; 499 } 500 /* 501 * If it's an IPv4 address, ICMP won't work with IPv4 mapped address, 502 * therefore, let's delegate to the Inet4Address method. 503 */ 504 sz = (*env)->GetArrayLength(env, addrArray); 505 if (sz == 4) { 506 return Java_java_net_Inet4AddressImpl_isReachable0(env, this, 507 addrArray, 508 timeout, 509 ifArray, ttl); 510 } 511 512 memset((char *) caddr, 0, 16); 513 memset((char *) &him6, 0, sizeof(him6)); 514 (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); 515 memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); 516 him6.sin6_family = AF_INET6; 517 if (scope > 0) { 518 him6.sin6_scope_id = scope; 519 } 520 len = sizeof(struct sockaddr_in6); 521 /** 522 * A network interface was specified, let's convert the address 523 */ 524 if (!(IS_NULL(ifArray))) { 525 memset((char *) caddr, 0, 16); 526 memset((char *) &inf6, 0, sizeof(inf6)); 527 (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr); 528 memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) ); 529 inf6.sin6_family = AF_INET6; 530 inf6.sin6_port = 0; 531 inf6.sin6_scope_id = if_scope; 532 netif = &inf6; 533 } 534 535 #if 0 536 /* 537 * Windows implementation of ICMP & RAW sockets is too unreliable for now. 538 * Therefore it's best not to try it at all and rely only on TCP 539 * We may revisit and enable this code in the future. 540 */ 541 542 /* 543 * Right now, windows doesn't generate the ICMP checksum automatically 544 * so we have to compute it, but we can do it only if we know which 545 * interface will be used. Therefore, don't try to use ICMP if no 546 * interface was specified. 547 * When ICMPv6 support improves in windows, we may change this. 548 */ 549 if (!(IS_NULL(ifArray))) { 550 /* 551 * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST 552 * otherwise we'll try a tcp socket to the Echo port (7). 553 * Note that this is empiric, and not connecting could mean it's blocked 554 * or the echo servioe has been disabled. 555 */ 556 fd = NET_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 557 558 if (fd != -1) { /* Good to go, let's do a ping */ 559 return ping6(env, fd, &him6, timeout, netif, ttl); 560 } 561 } 562 #endif 563 564 /* No good, let's fall back on TCP */ 565 fd = NET_Socket(AF_INET6, SOCK_STREAM, 0); 566 if (fd == SOCKET_ERROR) { 567 /* note: if you run out of fds, you may not be able to load 568 * the exception class, and get a NoClassDefFoundError 569 * instead. 570 */ 571 NET_ThrowNew(env, errno, "Can't create socket"); 572 return JNI_FALSE; 573 } 574 575 /** 576 * A TTL was specified, let's set the socket option. 577 */ 578 if (ttl > 0) { 579 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *)&ttl, sizeof(ttl)); 580 } 581 582 /** 583 * A network interface was specified, let's bind to it. 584 */ 585 if (netif != NULL) { 586 if (NET_Bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) < 0) { 587 NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket to interface"); 588 closesocket(fd); 589 return JNI_FALSE; 590 } 591 } 592 593 /** 594 * Make the socket non blocking. 595 */ 596 hEvent = WSACreateEvent(); 597 WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE); 598 599 /* no need to use NET_Connect as non-blocking */ 600 him6.sin6_port = htons((short) 7); /* Echo port */ 601 connect_rv = connect(fd, (struct sockaddr *)&him6, len); 602 603 /** 604 * connection established or refused immediately, either way it means 605 * we were able to reach the host! 606 */ 607 if (connect_rv == 0 || WSAGetLastError() == WSAECONNREFUSED) { 608 WSACloseEvent(hEvent); 609 closesocket(fd); 610 return JNI_TRUE; 611 } else { 612 int optlen; 613 614 switch (WSAGetLastError()) { 615 case WSAEHOSTUNREACH: /* Host Unreachable */ 616 case WSAENETUNREACH: /* Network Unreachable */ 617 case WSAENETDOWN: /* Network is down */ 618 case WSAEPFNOSUPPORT: /* Protocol Family unsupported */ 619 WSACloseEvent(hEvent); 620 closesocket(fd); 621 return JNI_FALSE; 622 } 623 624 if (WSAGetLastError() != WSAEWOULDBLOCK) { 625 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", 626 "connect failed"); 627 WSACloseEvent(hEvent); 628 closesocket(fd); 629 return JNI_FALSE; 630 } 631 632 timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout); 633 634 if (timeout >= 0) { 635 /* has connection been established? */ 636 optlen = sizeof(connect_rv); 637 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, 638 &optlen) <0) { 639 connect_rv = WSAGetLastError(); 640 } 641 642 if (connect_rv == 0 || connect_rv == WSAECONNREFUSED) { 643 WSACloseEvent(hEvent); 644 closesocket(fd); 645 return JNI_TRUE; 646 } 647 } 648 } 649 WSACloseEvent(hEvent); 650 closesocket(fd); 651 #endif /* AF_INET6 */ 652 return JNI_FALSE; 653 }