1 /* 2 * Copyright (c) 2000, 2011, 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 <errno.h> 27 #include <sys/time.h> 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include <netdb.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 37 #include "jvm.h" 38 #include "jni_util.h" 39 #include "net_util.h" 40 #ifndef IPV6_DEFS_H 41 #include <netinet/icmp6.h> 42 #endif 43 44 #include "java_net_Inet4AddressImpl.h" 45 #include "java_net_Inet6AddressImpl.h" 46 47 /* the initial size of our hostent buffers */ 48 #ifndef NI_MAXHOST 49 #define NI_MAXHOST 1025 50 #endif 51 52 53 /************************************************************************ 54 * Inet6AddressImpl 55 */ 56 57 /* 58 * Class: java_net_Inet6AddressImpl 59 * Method: getLocalHostName 60 * Signature: ()Ljava/lang/String; 61 */ 62 JNIEXPORT jstring JNICALL 63 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { 64 char hostname[NI_MAXHOST+1]; 65 66 hostname[0] = '\0'; 67 if (JVM_GetHostName(hostname, sizeof(hostname))) { 68 /* Something went wrong, maybe networking is not setup? */ 69 strcpy(hostname, "localhost"); 70 } else { 71 // ensure null-terminated 72 hostname[NI_MAXHOST] = '\0'; 73 #ifdef __linux__ 74 /* On Linux gethostname() says "host.domain.sun.com". On 75 * Solaris gethostname() says "host", so extra work is needed. 76 */ 77 #else 78 /* Solaris doesn't want to give us a fully qualified domain name. 79 * We do a reverse lookup to try and get one. This works 80 * if DNS occurs before NIS in /etc/resolv.conf, but fails 81 * if NIS comes first (it still gets only a partial name). 82 * We use thread-safe system calls. 83 */ 84 #ifdef AF_INET6 85 if (NET_addrtransAvailable()) { 86 struct addrinfo hints, *res; 87 int error; 88 89 bzero(&hints, sizeof(hints)); 90 hints.ai_flags = AI_CANONNAME; 91 hints.ai_family = AF_UNSPEC; 92 93 error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); 94 95 if (error == 0) { 96 /* host is known to name service */ 97 error = (*getnameinfo_ptr)(res->ai_addr, 98 res->ai_addrlen, 99 hostname, 100 NI_MAXHOST, 101 NULL, 102 0, 103 NI_NAMEREQD); 104 105 /* if getnameinfo fails hostname is still the value 106 from gethostname */ 107 108 (*freeaddrinfo_ptr)(res); 109 } 110 } 111 #endif /* AF_INET6 */ 112 #endif /* __linux__ */ 113 } 114 return (*env)->NewStringUTF(env, hostname); 115 } 116 117 static jclass ni_iacls; 118 static jclass ni_ia4cls; 119 static jclass ni_ia6cls; 120 static jmethodID ni_ia4ctrID; 121 static jmethodID ni_ia6ctrID; 122 static jfieldID ni_iaaddressID; 123 static jfieldID ni_iahostID; 124 static jfieldID ni_iafamilyID; 125 static jfieldID ni_ia6ipaddressID; 126 static int initialized = 0; 127 128 /* 129 * Find an internet address for a given hostname. Note that this 130 * code only works for addresses of type INET. The translation 131 * of %d.%d.%d.%d to an address (int) occurs in java now, so the 132 * String "host" shouldn't *ever* be a %d.%d.%d.%d string 133 * 134 * Class: java_net_Inet6AddressImpl 135 * Method: lookupAllHostAddr 136 * Signature: (Ljava/lang/String;)[[B 137 */ 138 139 JNIEXPORT jobjectArray JNICALL 140 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, 141 jstring host) { 142 const char *hostname; 143 jobjectArray ret = 0; 144 int retLen = 0; 145 jboolean preferIPv6Address; 146 147 int error=0; 148 #ifdef AF_INET6 149 struct addrinfo hints, *res, *resNew = NULL; 150 #endif /* AF_INET6 */ 151 152 if (!initialized) { 153 ni_iacls = (*env)->FindClass(env, "java/net/InetAddress"); 154 ni_iacls = (*env)->NewGlobalRef(env, ni_iacls); 155 ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address"); 156 ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls); 157 ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address"); 158 ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); 159 ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V"); 160 ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V"); 161 ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I"); 162 ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I"); 163 ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;"); 164 ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); 165 initialized = 1; 166 } 167 168 if (IS_NULL(host)) { 169 JNU_ThrowNullPointerException(env, "host is null"); 170 return 0; 171 } 172 hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); 173 CHECK_NULL_RETURN(hostname, NULL); 174 175 #ifdef AF_INET6 176 if (NET_addrtransAvailable()) { 177 static jfieldID ia_preferIPv6AddressID; 178 if (ia_preferIPv6AddressID == NULL) { 179 jclass c = (*env)->FindClass(env,"java/net/InetAddress"); 180 if (c) { 181 ia_preferIPv6AddressID = 182 (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z"); 183 } 184 if (ia_preferIPv6AddressID == NULL) { 185 JNU_ReleaseStringPlatformChars(env, host, hostname); 186 return NULL; 187 } 188 } 189 /* get the address preference */ 190 preferIPv6Address 191 = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID); 192 193 /* Try once, with our static buffer. */ 194 bzero(&hints, sizeof(hints)); 195 hints.ai_flags = AI_CANONNAME; 196 hints.ai_family = AF_UNSPEC; 197 198 #ifdef __solaris__ 199 /* 200 * Workaround for Solaris bug 4160367 - if a hostname contains a 201 * white space then 0.0.0.0 is returned 202 */ 203 if (isspace((unsigned char)hostname[0])) { 204 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", 205 hostname); 206 JNU_ReleaseStringPlatformChars(env, host, hostname); 207 return NULL; 208 } 209 #endif 210 211 error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); 212 213 if (error) { 214 /* report error */ 215 ThrowUnknownHostExceptionWithGaiError(env, hostname, error); 216 JNU_ReleaseStringPlatformChars(env, host, hostname); 217 return NULL; 218 } else { 219 int i = 0; 220 int inetCount = 0, inet6Count = 0, inetIndex, inet6Index; 221 struct addrinfo *itr, *last = NULL, *iterator = res; 222 while (iterator != NULL) { 223 int skip = 0; 224 itr = resNew; 225 while (itr != NULL) { 226 if (iterator->ai_family == itr->ai_family && 227 iterator->ai_addrlen == itr->ai_addrlen) { 228 if (itr->ai_family == AF_INET) { /* AF_INET */ 229 struct sockaddr_in *addr1, *addr2; 230 addr1 = (struct sockaddr_in *)iterator->ai_addr; 231 addr2 = (struct sockaddr_in *)itr->ai_addr; 232 if (addr1->sin_addr.s_addr == 233 addr2->sin_addr.s_addr) { 234 skip = 1; 235 break; 236 } 237 } else { 238 int t; 239 struct sockaddr_in6 *addr1, *addr2; 240 addr1 = (struct sockaddr_in6 *)iterator->ai_addr; 241 addr2 = (struct sockaddr_in6 *)itr->ai_addr; 242 243 for (t = 0; t < 16; t++) { 244 if (addr1->sin6_addr.s6_addr[t] != 245 addr2->sin6_addr.s6_addr[t]) { 246 break; 247 } 248 } 249 if (t < 16) { 250 itr = itr->ai_next; 251 continue; 252 } else { 253 skip = 1; 254 break; 255 } 256 } 257 } else if (iterator->ai_family != AF_INET && 258 iterator->ai_family != AF_INET6) { 259 /* we can't handle other family types */ 260 skip = 1; 261 break; 262 } 263 itr = itr->ai_next; 264 } 265 266 if (!skip) { 267 struct addrinfo *next 268 = (struct addrinfo*) malloc(sizeof(struct addrinfo)); 269 if (!next) { 270 JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); 271 ret = NULL; 272 goto cleanupAndReturn; 273 } 274 memcpy(next, iterator, sizeof(struct addrinfo)); 275 next->ai_next = NULL; 276 if (resNew == NULL) { 277 resNew = next; 278 } else { 279 last->ai_next = next; 280 } 281 last = next; 282 i++; 283 if (iterator->ai_family == AF_INET) { 284 inetCount ++; 285 } else if (iterator->ai_family == AF_INET6) { 286 inet6Count ++; 287 } 288 } 289 iterator = iterator->ai_next; 290 } 291 retLen = i; 292 iterator = resNew; 293 294 ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL); 295 296 if (IS_NULL(ret)) { 297 /* we may have memory to free at the end of this */ 298 goto cleanupAndReturn; 299 } 300 301 if (preferIPv6Address) { 302 /* AF_INET addresses will be offset by inet6Count */ 303 inetIndex = inet6Count; 304 inet6Index = 0; 305 } else { 306 /* AF_INET6 addresses will be offset by inetCount */ 307 inetIndex = 0; 308 inet6Index = inetCount; 309 } 310 311 while (iterator != NULL) { 312 if (iterator->ai_family == AF_INET) { 313 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); 314 if (IS_NULL(iaObj)) { 315 ret = NULL; 316 goto cleanupAndReturn; 317 } 318 (*env)->SetIntField(env, iaObj, ni_iaaddressID, 319 ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr)); 320 (*env)->SetObjectField(env, iaObj, ni_iahostID, host); 321 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); 322 inetIndex++; 323 } else if (iterator->ai_family == AF_INET6) { 324 jint scope = 0; 325 jbyteArray ipaddress; 326 327 jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); 328 if (IS_NULL(iaObj)) { 329 ret = NULL; 330 goto cleanupAndReturn; 331 } 332 ipaddress = (*env)->NewByteArray(env, 16); 333 if (IS_NULL(ipaddress)) { 334 ret = NULL; 335 goto cleanupAndReturn; 336 } 337 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, 338 (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); 339 #ifdef __linux__ 340 if (!kernelIsV22()) { 341 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; 342 } 343 #else 344 scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; 345 #endif 346 if (scope != 0) { /* zero is default value, no need to set */ 347 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); 348 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); 349 } 350 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); 351 (*env)->SetObjectField(env, iaObj, ni_iahostID, host); 352 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); 353 inet6Index++; 354 } 355 iterator = iterator->ai_next; 356 } 357 } 358 } 359 360 cleanupAndReturn: 361 { 362 struct addrinfo *iterator, *tmp; 363 iterator = resNew; 364 while (iterator != NULL) { 365 tmp = iterator; 366 iterator = iterator->ai_next; 367 free(tmp); 368 } 369 JNU_ReleaseStringPlatformChars(env, host, hostname); 370 } 371 372 if (NET_addrtransAvailable()) 373 (*freeaddrinfo_ptr)(res); 374 #endif /* AF_INET6 */ 375 376 return ret; 377 } 378 379 /* 380 * Class: java_net_Inet6AddressImpl 381 * Method: getHostByAddr 382 * Signature: (I)Ljava/lang/String; 383 */ 384 JNIEXPORT jstring JNICALL 385 Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, 386 jbyteArray addrArray) { 387 388 jstring ret = NULL; 389 390 #ifdef AF_INET6 391 char host[NI_MAXHOST+1]; 392 int error = 0; 393 int len = 0; 394 jbyte caddr[16]; 395 396 if (NET_addrtransAvailable()) { 397 struct sockaddr_in him4; 398 struct sockaddr_in6 him6; 399 struct sockaddr *sa; 400 401 /* 402 * For IPv4 addresses construct a sockaddr_in structure. 403 */ 404 if ((*env)->GetArrayLength(env, addrArray) == 4) { 405 jint addr; 406 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); 407 addr = ((caddr[0]<<24) & 0xff000000); 408 addr |= ((caddr[1] <<16) & 0xff0000); 409 addr |= ((caddr[2] <<8) & 0xff00); 410 addr |= (caddr[3] & 0xff); 411 memset((void *) &him4, 0, sizeof(him4)); 412 him4.sin_addr.s_addr = (uint32_t) htonl(addr); 413 him4.sin_family = AF_INET; 414 sa = (struct sockaddr *) &him4; 415 len = sizeof(him4); 416 } else { 417 /* 418 * For IPv6 address construct a sockaddr_in6 structure. 419 */ 420 (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); 421 memset((void *) &him6, 0, sizeof(him6)); 422 memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); 423 him6.sin6_family = AF_INET6; 424 sa = (struct sockaddr *) &him6 ; 425 len = sizeof(him6) ; 426 } 427 428 error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0, 429 NI_NAMEREQD); 430 431 if (!error) { 432 ret = (*env)->NewStringUTF(env, host); 433 } 434 } 435 #endif /* AF_INET6 */ 436 437 if (ret == NULL) { 438 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL); 439 } 440 441 return ret; 442 } 443 444 #define SET_NONBLOCKING(fd) { \ 445 int flags = fcntl(fd, F_GETFL); \ 446 flags |= O_NONBLOCK; \ 447 fcntl(fd, F_SETFL, flags); \ 448 } 449 450 #ifdef AF_INET6 451 static jboolean 452 ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout, 453 struct sockaddr_in6* netif, jint ttl) { 454 jint size; 455 jint n; 456 socklen_t len; 457 char sendbuf[1500]; 458 unsigned char recvbuf[1500]; 459 struct icmp6_hdr *icmp6; 460 struct sockaddr_in6 sa_recv; 461 jbyte *caddr, *recv_caddr; 462 jchar pid; 463 jint tmout2, seq = 1; 464 struct timeval tv; 465 size_t plen; 466 467 #ifdef __linux__ 468 { 469 int csum_offset; 470 /** 471 * For some strange reason, the linux kernel won't calculate the 472 * checksum of ICMPv6 packets unless you set this socket option 473 */ 474 csum_offset = 2; 475 setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int)); 476 } 477 #endif 478 479 caddr = (jbyte *)&(him->sin6_addr); 480 481 /* icmp_id is a 16 bit data type, therefore down cast the pid */ 482 pid = (jchar)getpid(); 483 size = 60*1024; 484 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); 485 if (ttl > 0) { 486 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); 487 } 488 if (netif != NULL) { 489 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) { 490 NET_ThrowNew(env, errno, "Can't bind socket"); 491 close(fd); 492 return JNI_FALSE; 493 } 494 } 495 SET_NONBLOCKING(fd); 496 497 do { 498 icmp6 = (struct icmp6_hdr *) sendbuf; 499 icmp6->icmp6_type = ICMP6_ECHO_REQUEST; 500 icmp6->icmp6_code = 0; 501 /* let's tag the ECHO packet with our pid so we can identify it */ 502 icmp6->icmp6_id = htons(pid); 503 icmp6->icmp6_seq = htons(seq); 504 seq++; 505 icmp6->icmp6_cksum = 0; 506 gettimeofday(&tv, NULL); 507 memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv)); 508 plen = sizeof(struct icmp6_hdr) + sizeof(tv); 509 n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6)); 510 if (n < 0 && errno != EINPROGRESS) { 511 #ifdef __linux__ 512 if (errno != EINVAL) 513 /* 514 * On some Linuxes, when bound to the loopback interface, sendto 515 * will fail and errno will be set to EINVAL. When that happens, 516 * don't throw an exception, just return false. 517 */ 518 #endif /*__linux__ */ 519 NET_ThrowNew(env, errno, "Can't send ICMP packet"); 520 close(fd); 521 return JNI_FALSE; 522 } 523 524 tmout2 = timeout > 1000 ? 1000 : timeout; 525 do { 526 tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); 527 528 if (tmout2 >= 0) { 529 len = sizeof(sa_recv); 530 n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len); 531 icmp6 = (struct icmp6_hdr *) (recvbuf); 532 recv_caddr = (jbyte *)&(sa_recv.sin6_addr); 533 /* 534 * We did receive something, but is it what we were expecting? 535 * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and 536 * from the host that we are trying to determine is reachable. 537 */ 538 if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY && 539 (ntohs(icmp6->icmp6_id) == pid) && 540 NET_IsEqual(caddr, recv_caddr)) { 541 close(fd); 542 return JNI_TRUE; 543 } 544 } 545 } while (tmout2 > 0); 546 timeout -= 1000; 547 } while (timeout > 0); 548 close(fd); 549 return JNI_FALSE; 550 } 551 #endif /* AF_INET6 */ 552 553 /* 554 * Class: java_net_Inet6AddressImpl 555 * Method: isReachable0 556 * Signature: ([bII[bI)Z 557 */ 558 JNIEXPORT jboolean JNICALL 559 Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this, 560 jbyteArray addrArray, 561 jint scope, 562 jint timeout, 563 jbyteArray ifArray, 564 jint ttl, jint if_scope) { 565 #ifdef AF_INET6 566 jbyte caddr[16]; 567 jint fd, sz; 568 struct sockaddr_in6 him6; 569 struct sockaddr_in6 inf6; 570 struct sockaddr_in6* netif = NULL; 571 int len = 0; 572 int connect_rv = -1; 573 574 /* 575 * If IPv6 is not enable, then we can't reach an IPv6 address, can we? 576 */ 577 if (!ipv6_available()) { 578 return JNI_FALSE; 579 } 580 /* 581 * If it's an IPv4 address, ICMP won't work with IPv4 mapped address, 582 * therefore, let's delegate to the Inet4Address method. 583 */ 584 sz = (*env)->GetArrayLength(env, addrArray); 585 if (sz == 4) { 586 return Java_java_net_Inet4AddressImpl_isReachable0(env, this, 587 addrArray, 588 timeout, 589 ifArray, ttl); 590 } 591 592 memset((void *) caddr, 0, 16); 593 memset((void *) &him6, 0, sizeof(him6)); 594 (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr); 595 memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) ); 596 him6.sin6_family = AF_INET6; 597 #ifdef __linux__ 598 if (scope > 0) 599 him6.sin6_scope_id = scope; 600 else 601 him6.sin6_scope_id = getDefaultIPv6Interface( &(him6.sin6_addr)); 602 len = sizeof(struct sockaddr_in6); 603 #else 604 if (scope > 0) 605 him6.sin6_scope_id = scope; 606 len = sizeof(struct sockaddr_in6); 607 #endif 608 /* 609 * If a network interface was specified, let's create the address 610 * for it. 611 */ 612 if (!(IS_NULL(ifArray))) { 613 memset((void *) caddr, 0, 16); 614 memset((void *) &inf6, 0, sizeof(inf6)); 615 (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr); 616 memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) ); 617 inf6.sin6_family = AF_INET6; 618 inf6.sin6_scope_id = if_scope; 619 netif = &inf6; 620 } 621 /* 622 * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST 623 * otherwise we'll try a tcp socket to the Echo port (7). 624 * Note that this is empiric, and not connecting could mean it's blocked 625 * or the echo servioe has been disabled. 626 */ 627 628 fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 629 630 if (fd != -1) { /* Good to go, let's do a ping */ 631 return ping6(env, fd, &him6, timeout, netif, ttl); 632 } 633 634 /* No good, let's fall back on TCP */ 635 fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0); 636 if (fd == JVM_IO_ERR) { 637 /* note: if you run out of fds, you may not be able to load 638 * the exception class, and get a NoClassDefFoundError 639 * instead. 640 */ 641 NET_ThrowNew(env, errno, "Can't create socket"); 642 return JNI_FALSE; 643 } 644 if (ttl > 0) { 645 setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); 646 } 647 648 /* 649 * A network interface was specified, so let's bind to it. 650 */ 651 if (netif != NULL) { 652 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) { 653 NET_ThrowNew(env, errno, "Can't bind socket"); 654 close(fd); 655 return JNI_FALSE; 656 } 657 } 658 SET_NONBLOCKING(fd); 659 660 /* no need to use NET_Connect as non-blocking */ 661 him6.sin6_port = htons((short) 7); /* Echo port */ 662 connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len); 663 664 /** 665 * connection established or refused immediately, either way it means 666 * we were able to reach the host! 667 */ 668 if (connect_rv == 0 || errno == ECONNREFUSED) { 669 close(fd); 670 return JNI_TRUE; 671 } else { 672 int optlen; 673 674 switch (errno) { 675 case ENETUNREACH: /* Network Unreachable */ 676 case EAFNOSUPPORT: /* Address Family not supported */ 677 case EADDRNOTAVAIL: /* address is not available on the remote machine */ 678 #ifdef __linux__ 679 case EINVAL: 680 /* 681 * On some Linuxes, when bound to the loopback interface, connect 682 * will fail and errno will be set to EINVAL. When that happens, 683 * don't throw an exception, just return false. 684 */ 685 #endif /* __linux__ */ 686 close(fd); 687 return JNI_FALSE; 688 } 689 690 if (errno != EINPROGRESS) { 691 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", 692 "connect failed"); 693 close(fd); 694 return JNI_FALSE; 695 } 696 697 timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout); 698 699 if (timeout >= 0) { 700 /* has connection been established */ 701 optlen = sizeof(connect_rv); 702 if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, 703 &optlen) <0) { 704 connect_rv = errno; 705 } 706 if (connect_rv == 0 || ECONNREFUSED) { 707 close(fd); 708 return JNI_TRUE; 709 } 710 } 711 close(fd); 712 return JNI_FALSE; 713 } 714 #else /* AF_INET6 */ 715 return JNI_FALSE; 716 #endif /* AF_INET6 */ 717 }