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