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