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