1 /* 2 * Copyright (c) 2001, 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 <sys/types.h> 27 #include <sys/socket.h> 28 #include <string.h> 29 #include <netinet/in.h> 30 #include <netinet/tcp.h> 31 32 #include "jni.h" 33 #include "jni_util.h" 34 #include "jvm.h" 35 #include "jlong.h" 36 #include "sun_nio_ch_Net.h" 37 #include "net_util.h" 38 #include "net_util_md.h" 39 #include "nio_util.h" 40 #include "nio.h" 41 42 #ifdef _ALLBSD_SOURCE 43 44 #ifndef IP_BLOCK_SOURCE 45 46 #define IP_ADD_SOURCE_MEMBERSHIP 70 /* join a source-specific group */ 47 #define IP_DROP_SOURCE_MEMBERSHIP 71 /* drop a single source */ 48 #define IP_BLOCK_SOURCE 72 /* block a source */ 49 #define IP_UNBLOCK_SOURCE 73 /* unblock a source */ 50 51 #endif /* IP_BLOCK_SOURCE */ 52 53 #ifndef MCAST_BLOCK_SOURCE 54 55 #define MCAST_JOIN_SOURCE_GROUP 82 /* join a source-specific group */ 56 #define MCAST_LEAVE_SOURCE_GROUP 83 /* leave a single source */ 57 #define MCAST_BLOCK_SOURCE 84 /* block a source */ 58 #define MCAST_UNBLOCK_SOURCE 85 /* unblock a source */ 59 60 #endif /* MCAST_BLOCK_SOURCE */ 61 62 #ifndef IPV6_ADD_MEMBERSHIP 63 64 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP 65 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP 66 67 #endif /* IPV6_ADD_MEMBERSHIP */ 68 69 struct my_ip_mreq_source { 70 struct in_addr imr_multiaddr; 71 struct in_addr imr_interface; 72 struct in_addr imr_sourceaddr; 73 }; 74 75 struct my_group_source_req { 76 uint32_t gsr_interface; /* interface index */ 77 struct sockaddr_storage gsr_group; /* group address */ 78 struct sockaddr_storage gsr_source; /* source address */ 79 }; 80 81 #else /* _ALLBSD_SOURCE */ 82 83 #define my_ip_mreq_source ip_mreq_source 84 #define my_group_source_req group_source_req 85 86 #endif 87 88 89 #define COPY_INET6_ADDRESS(env, source, target) \ 90 (*env)->GetByteArrayRegion(env, source, 0, 16, target) 91 92 /* 93 * Copy IPv6 group, interface index, and IPv6 source address 94 * into group_source_req structure. 95 */ 96 #ifdef AF_INET6 97 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index, 98 jbyteArray source, struct my_group_source_req* req) 99 { 100 struct sockaddr_in6* sin6; 101 102 req->gsr_interface = (uint32_t)index; 103 104 sin6 = (struct sockaddr_in6*)&(req->gsr_group); 105 sin6->sin6_family = AF_INET6; 106 COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr)); 107 108 sin6 = (struct sockaddr_in6*)&(req->gsr_source); 109 sin6->sin6_family = AF_INET6; 110 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr)); 111 } 112 #endif 113 114 JNIEXPORT void JNICALL 115 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) 116 { 117 /* Here because Windows native code does need to init IDs */ 118 } 119 120 JNIEXPORT jboolean JNICALL 121 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) 122 { 123 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; 124 } 125 126 JNIEXPORT jint JNICALL 127 Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { 128 return -1; 129 } 130 131 JNIEXPORT jboolean JNICALL 132 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl) 133 { 134 #ifdef MACOSX 135 /* for now IPv6 sockets cannot join IPv4 multicast groups */ 136 return JNI_FALSE; 137 #else 138 return JNI_TRUE; 139 #endif 140 } 141 142 JNIEXPORT jboolean JNICALL 143 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl) 144 { 145 #ifdef __solaris__ 146 return JNI_TRUE; 147 #else 148 return JNI_FALSE; 149 #endif 150 } 151 152 JNIEXPORT int JNICALL 153 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, 154 jboolean stream, jboolean reuse) 155 { 156 int fd; 157 int type = (stream ? SOCK_STREAM : SOCK_DGRAM); 158 #ifdef AF_INET6 159 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET; 160 #else 161 int domain = AF_INET; 162 #endif 163 164 fd = socket(domain, type, 0); 165 if (fd < 0) { 166 return handleSocketError(env, errno); 167 } 168 169 #ifdef AF_INET6 170 /* Disable IPV6_V6ONLY to ensure dual-socket support */ 171 if (domain == AF_INET6) { 172 int arg = 0; 173 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, 174 sizeof(int)) < 0) { 175 JNU_ThrowByNameWithLastError(env, 176 JNU_JAVANETPKG "SocketException", 177 "sun.nio.ch.Net.setIntOption"); 178 close(fd); 179 return -1; 180 } 181 } 182 #endif 183 184 if (reuse) { 185 int arg = 1; 186 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, 187 sizeof(arg)) < 0) { 188 JNU_ThrowByNameWithLastError(env, 189 JNU_JAVANETPKG "SocketException", 190 "sun.nio.ch.Net.setIntOption"); 191 close(fd); 192 return -1; 193 } 194 } 195 #if defined(__linux__) && defined(AF_INET6) 196 /* By default, Linux uses the route default */ 197 if (domain == AF_INET6 && type == SOCK_DGRAM) { 198 int arg = 1; 199 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg, 200 sizeof(arg)) < 0) { 201 JNU_ThrowByNameWithLastError(env, 202 JNU_JAVANETPKG "SocketException", 203 "sun.nio.ch.Net.setIntOption"); 204 close(fd); 205 return -1; 206 } 207 } 208 #endif 209 return fd; 210 } 211 212 JNIEXPORT void JNICALL 213 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6, 214 jboolean useExclBind, jobject iao, int port) 215 { 216 SOCKADDR sa; 217 int sa_len = SOCKADDR_LEN; 218 int rv = 0; 219 220 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { 221 return; 222 } 223 224 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); 225 if (rv != 0) { 226 handleSocketError(env, errno); 227 } 228 } 229 230 JNIEXPORT void JNICALL 231 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog) 232 { 233 if (listen(fdval(env, fdo), backlog) < 0) 234 handleSocketError(env, errno); 235 } 236 237 JNIEXPORT jint JNICALL 238 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, 239 jobject fdo, jobject iao, jint port) 240 { 241 SOCKADDR sa; 242 int sa_len = SOCKADDR_LEN; 243 int rv; 244 245 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, 246 &sa_len, preferIPv6) != 0) 247 { 248 return IOS_THROWN; 249 } 250 251 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len); 252 if (rv != 0) { 253 if (errno == EINPROGRESS) { 254 return IOS_UNAVAILABLE; 255 } else if (errno == EINTR) { 256 return IOS_INTERRUPTED; 257 } 258 return handleSocketError(env, errno); 259 } 260 return 1; 261 } 262 263 JNIEXPORT jint JNICALL 264 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo) 265 { 266 SOCKADDR sa; 267 socklen_t sa_len = SOCKADDR_LEN; 268 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { 269 #ifdef _ALLBSD_SOURCE 270 /* 271 * XXXBSD: 272 * ECONNRESET is specific to the BSDs. We can not return an error, 273 * as the calling Java code with raise a java.lang.Error given the expectation 274 * that getsockname() will never fail. According to the Single UNIX Specification, 275 * it shouldn't fail. As such, we just fill in generic Linux-compatible values. 276 */ 277 if (errno == ECONNRESET) { 278 struct sockaddr_in *sin; 279 sin = (struct sockaddr_in *) &sa; 280 bzero(sin, sizeof(*sin)); 281 sin->sin_len = sizeof(struct sockaddr_in); 282 sin->sin_family = AF_INET; 283 sin->sin_port = htonl(0); 284 sin->sin_addr.s_addr = INADDR_ANY; 285 } else { 286 handleSocketError(env, errno); 287 return -1; 288 } 289 #else /* _ALLBSD_SOURCE */ 290 handleSocketError(env, errno); 291 return -1; 292 #endif /* _ALLBSD_SOURCE */ 293 } 294 return NET_GetPortFromSockaddr((struct sockaddr *)&sa); 295 } 296 297 JNIEXPORT jobject JNICALL 298 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo) 299 { 300 SOCKADDR sa; 301 socklen_t sa_len = SOCKADDR_LEN; 302 int port; 303 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { 304 #ifdef _ALLBSD_SOURCE 305 /* 306 * XXXBSD: 307 * ECONNRESET is specific to the BSDs. We can not return an error, 308 * as the calling Java code with raise a java.lang.Error with the expectation 309 * that getsockname() will never fail. According to the Single UNIX Specification, 310 * it shouldn't fail. As such, we just fill in generic Linux-compatible values. 311 */ 312 if (errno == ECONNRESET) { 313 struct sockaddr_in *sin; 314 sin = (struct sockaddr_in *) &sa; 315 bzero(sin, sizeof(*sin)); 316 sin->sin_len = sizeof(struct sockaddr_in); 317 sin->sin_family = AF_INET; 318 sin->sin_port = htonl(0); 319 sin->sin_addr.s_addr = INADDR_ANY; 320 } else { 321 handleSocketError(env, errno); 322 return NULL; 323 } 324 #else /* _ALLBSD_SOURCE */ 325 handleSocketError(env, errno); 326 return NULL; 327 #endif /* _ALLBSD_SOURCE */ 328 } 329 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); 330 } 331 332 JNIEXPORT jint JNICALL 333 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 334 jboolean mayNeedConversion, jint level, jint opt) 335 { 336 int result; 337 struct linger linger; 338 u_char carg; 339 void *arg; 340 socklen_t arglen; 341 int n; 342 343 /* Option value is an int except for a few specific cases */ 344 345 arg = (void *)&result; 346 arglen = sizeof(result); 347 348 if (level == IPPROTO_IP && 349 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { 350 arg = (void*)&carg; 351 arglen = sizeof(carg); 352 } 353 354 if (level == SOL_SOCKET && opt == SO_LINGER) { 355 arg = (void *)&linger; 356 arglen = sizeof(linger); 357 } 358 359 if (mayNeedConversion) { 360 n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen); 361 } else { 362 n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); 363 } 364 if (n < 0) { 365 JNU_ThrowByNameWithLastError(env, 366 JNU_JAVANETPKG "SocketException", 367 "sun.nio.ch.Net.getIntOption"); 368 return -1; 369 } 370 371 if (level == IPPROTO_IP && 372 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) 373 { 374 return (jint)carg; 375 } 376 377 if (level == SOL_SOCKET && opt == SO_LINGER) 378 return linger.l_onoff ? (jint)linger.l_linger : (jint)-1; 379 380 return (jint)result; 381 } 382 383 JNIEXPORT void JNICALL 384 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 385 jboolean mayNeedConversion, jint level, jint opt, jint arg) 386 { 387 int result; 388 struct linger linger; 389 u_char carg; 390 void *parg; 391 socklen_t arglen; 392 int n; 393 394 /* Option value is an int except for a few specific cases */ 395 396 parg = (void*)&arg; 397 arglen = sizeof(arg); 398 399 if (level == IPPROTO_IP && 400 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { 401 parg = (void*)&carg; 402 arglen = sizeof(carg); 403 carg = (u_char)arg; 404 } 405 406 if (level == SOL_SOCKET && opt == SO_LINGER) { 407 parg = (void *)&linger; 408 arglen = sizeof(linger); 409 if (arg >= 0) { 410 linger.l_onoff = 1; 411 linger.l_linger = arg; 412 } else { 413 linger.l_onoff = 0; 414 linger.l_linger = 0; 415 } 416 } 417 418 if (mayNeedConversion) { 419 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen); 420 } else { 421 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen); 422 } 423 if (n < 0) { 424 JNU_ThrowByNameWithLastError(env, 425 JNU_JAVANETPKG "SocketException", 426 "sun.nio.ch.Net.setIntOption"); 427 } 428 } 429 430 JNIEXPORT jint JNICALL 431 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo, 432 jint group, jint interf, jint source) 433 { 434 struct ip_mreq mreq; 435 struct my_ip_mreq_source mreq_source; 436 int opt, n, optlen; 437 void* optval; 438 439 if (source == 0) { 440 mreq.imr_multiaddr.s_addr = htonl(group); 441 mreq.imr_interface.s_addr = htonl(interf); 442 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; 443 optval = (void*)&mreq; 444 optlen = sizeof(mreq); 445 } else { 446 #ifdef MACOSX 447 /* no IPv4 include-mode filtering for now */ 448 return IOS_UNAVAILABLE; 449 #else 450 mreq_source.imr_multiaddr.s_addr = htonl(group); 451 mreq_source.imr_sourceaddr.s_addr = htonl(source); 452 mreq_source.imr_interface.s_addr = htonl(interf); 453 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP; 454 optval = (void*)&mreq_source; 455 optlen = sizeof(mreq_source); 456 #endif 457 } 458 459 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen); 460 if (n < 0) { 461 if (join && (errno == ENOPROTOOPT)) 462 return IOS_UNAVAILABLE; 463 handleSocketError(env, errno); 464 } 465 return 0; 466 } 467 468 JNIEXPORT jint JNICALL 469 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo, 470 jint group, jint interf, jint source) 471 { 472 #ifdef MACOSX 473 /* no IPv4 exclude-mode filtering for now */ 474 return IOS_UNAVAILABLE; 475 #else 476 struct my_ip_mreq_source mreq_source; 477 int n; 478 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE; 479 480 mreq_source.imr_multiaddr.s_addr = htonl(group); 481 mreq_source.imr_sourceaddr.s_addr = htonl(source); 482 mreq_source.imr_interface.s_addr = htonl(interf); 483 484 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, 485 (void*)&mreq_source, sizeof(mreq_source)); 486 if (n < 0) { 487 if (block && (errno == ENOPROTOOPT)) 488 return IOS_UNAVAILABLE; 489 handleSocketError(env, errno); 490 } 491 return 0; 492 #endif 493 } 494 495 JNIEXPORT jint JNICALL 496 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo, 497 jbyteArray group, jint index, jbyteArray source) 498 { 499 #ifdef AF_INET6 500 struct ipv6_mreq mreq6; 501 struct my_group_source_req req; 502 int opt, n, optlen; 503 void* optval; 504 505 if (source == NULL) { 506 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr)); 507 mreq6.ipv6mr_interface = (int)index; 508 opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; 509 optval = (void*)&mreq6; 510 optlen = sizeof(mreq6); 511 } else { 512 #ifdef MACOSX 513 /* no IPv6 include-mode filtering for now */ 514 return IOS_UNAVAILABLE; 515 #else 516 initGroupSourceReq(env, group, index, source, &req); 517 opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP; 518 optval = (void*)&req; 519 optlen = sizeof(req); 520 #endif 521 } 522 523 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen); 524 if (n < 0) { 525 if (join && (errno == ENOPROTOOPT)) 526 return IOS_UNAVAILABLE; 527 handleSocketError(env, errno); 528 } 529 return 0; 530 #else 531 JNU_ThrowInternalError(env, "Should not get here"); 532 return IOS_THROWN; 533 #endif /* AF_INET6 */ 534 } 535 536 JNIEXPORT jint JNICALL 537 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo, 538 jbyteArray group, jint index, jbyteArray source) 539 { 540 #ifdef AF_INET6 541 #ifdef MACOSX 542 /* no IPv6 exclude-mode filtering for now */ 543 return IOS_UNAVAILABLE; 544 #else 545 struct my_group_source_req req; 546 int n; 547 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE; 548 549 initGroupSourceReq(env, group, index, source, &req); 550 551 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, 552 (void*)&req, sizeof(req)); 553 if (n < 0) { 554 if (block && (errno == ENOPROTOOPT)) 555 return IOS_UNAVAILABLE; 556 handleSocketError(env, errno); 557 } 558 return 0; 559 #endif 560 #else 561 JNU_ThrowInternalError(env, "Should not get here"); 562 return IOS_THROWN; 563 #endif 564 } 565 566 JNIEXPORT void JNICALL 567 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf) 568 { 569 struct in_addr in; 570 socklen_t arglen = sizeof(struct in_addr); 571 int n; 572 573 in.s_addr = htonl(interf); 574 575 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, 576 (void*)&(in.s_addr), arglen); 577 if (n < 0) { 578 handleSocketError(env, errno); 579 } 580 } 581 582 JNIEXPORT jint JNICALL 583 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo) 584 { 585 struct in_addr in; 586 socklen_t arglen = sizeof(struct in_addr); 587 int n; 588 589 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen); 590 if (n < 0) { 591 handleSocketError(env, errno); 592 return -1; 593 } 594 return ntohl(in.s_addr); 595 } 596 597 JNIEXPORT void JNICALL 598 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index) 599 { 600 int value = (jint)index; 601 socklen_t arglen = sizeof(value); 602 int n; 603 604 n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, 605 (void*)&(index), arglen); 606 if (n < 0) { 607 handleSocketError(env, errno); 608 } 609 } 610 611 JNIEXPORT jint JNICALL 612 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo) 613 { 614 int index; 615 socklen_t arglen = sizeof(index); 616 int n; 617 618 n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen); 619 if (n < 0) { 620 handleSocketError(env, errno); 621 return -1; 622 } 623 return (jint)index; 624 } 625 626 JNIEXPORT void JNICALL 627 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) 628 { 629 int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD : 630 (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR; 631 if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN)) 632 handleSocketError(env, errno); 633 } 634 635 /* Declared in nio_util.h */ 636 637 jint 638 handleSocketError(JNIEnv *env, jint errorValue) 639 { 640 char *xn; 641 switch (errorValue) { 642 case EINPROGRESS: /* Non-blocking connect */ 643 return 0; 644 #ifdef EPROTO 645 case EPROTO: 646 xn = JNU_JAVANETPKG "ProtocolException"; 647 break; 648 #endif 649 case ECONNREFUSED: 650 xn = JNU_JAVANETPKG "ConnectException"; 651 break; 652 case ETIMEDOUT: 653 xn = JNU_JAVANETPKG "ConnectException"; 654 break; 655 case EHOSTUNREACH: 656 xn = JNU_JAVANETPKG "NoRouteToHostException"; 657 break; 658 case EADDRINUSE: /* Fall through */ 659 case EADDRNOTAVAIL: 660 xn = JNU_JAVANETPKG "BindException"; 661 break; 662 default: 663 xn = JNU_JAVANETPKG "SocketException"; 664 break; 665 } 666 errno = errorValue; 667 JNU_ThrowByNameWithLastError(env, xn, "NioSocketError"); 668 return IOS_THROWN; 669 }