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