Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/nio/ch/Net.c
32288 views
/*1* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <sys/poll.h>26#include <sys/types.h>27#include <sys/socket.h>28#include <string.h>29#include <netinet/in.h>30#include <netinet/tcp.h>3132#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#include "sun_nio_ch_PollArrayWrapper.h"4243#ifdef _AIX44#include <sys/utsname.h>45#endif4647/**48* IP_MULTICAST_ALL supported since 2.6.31 but may not be available at49* build time.50*/51#ifdef __linux__52#ifndef IP_MULTICAST_ALL53#define IP_MULTICAST_ALL 4954#endif55#endif5657#if defined(_ALLBSD_SOURCE) || defined(_AIX) || defined(__ANDROID__)5859#ifndef IP_BLOCK_SOURCE6061#if defined(_AIX)6263#define IP_BLOCK_SOURCE 58 /* Block data from a given source to a given group */64#define IP_UNBLOCK_SOURCE 59 /* Unblock data from a given source to a given group */65#define IP_ADD_SOURCE_MEMBERSHIP 60 /* Join a source-specific group */66#define IP_DROP_SOURCE_MEMBERSHIP 61 /* Leave a source-specific group */6768#else6970#define IP_ADD_SOURCE_MEMBERSHIP 70 /* join a source-specific group */71#define IP_DROP_SOURCE_MEMBERSHIP 71 /* drop a single source */72#define IP_BLOCK_SOURCE 72 /* block a source */73#define IP_UNBLOCK_SOURCE 73 /* unblock a source */7475#endif /* _AIX */7677#endif /* IP_BLOCK_SOURCE */7879#ifndef MCAST_BLOCK_SOURCE8081#if defined(_AIX)8283#define MCAST_BLOCK_SOURCE 6484#define MCAST_UNBLOCK_SOURCE 6585#define MCAST_JOIN_SOURCE_GROUP 6686#define MCAST_LEAVE_SOURCE_GROUP 678788#else8990#define MCAST_JOIN_SOURCE_GROUP 82 /* join a source-specific group */91#define MCAST_LEAVE_SOURCE_GROUP 83 /* leave a single source */92#define MCAST_BLOCK_SOURCE 84 /* block a source */93#define MCAST_UNBLOCK_SOURCE 85 /* unblock a source */9495#endif /* _AIX */9697#endif /* MCAST_BLOCK_SOURCE */9899#ifndef IPV6_ADD_MEMBERSHIP100101#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP102#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP103104#endif /* IPV6_ADD_MEMBERSHIP */105106#if defined(_AIX)107108struct my_ip_mreq_source {109struct in_addr imr_multiaddr;110struct in_addr imr_sourceaddr;111struct in_addr imr_interface;112};113114#else115116struct my_ip_mreq_source {117struct in_addr imr_multiaddr;118struct in_addr imr_interface;119struct in_addr imr_sourceaddr;120};121122#endif /* _AIX */123124struct my_group_source_req {125uint32_t gsr_interface; /* interface index */126struct sockaddr_storage gsr_group; /* group address */127struct sockaddr_storage gsr_source; /* source address */128};129130#else /* _ALLBSD_SOURCE */131132#define my_ip_mreq_source ip_mreq_source133#define my_group_source_req group_source_req134135#endif136137138#define COPY_INET6_ADDRESS(env, source, target) \139(*env)->GetByteArrayRegion(env, source, 0, 16, target)140141/*142* Copy IPv6 group, interface index, and IPv6 source address143* into group_source_req structure.144*/145#ifdef AF_INET6146static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,147jbyteArray source, struct my_group_source_req* req)148{149struct sockaddr_in6* sin6;150151req->gsr_interface = (uint32_t)index;152153sin6 = (struct sockaddr_in6*)&(req->gsr_group);154sin6->sin6_family = AF_INET6;155COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));156157sin6 = (struct sockaddr_in6*)&(req->gsr_source);158sin6->sin6_family = AF_INET6;159COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));160}161#endif162163#ifdef _AIX164165/*166* Checks whether or not "socket extensions for multicast source filters" is supported.167* Returns JNI_TRUE if it is supported, JNI_FALSE otherwise168*/169static jboolean isSourceFilterSupported(){170static jboolean alreadyChecked = JNI_FALSE;171static jboolean result = JNI_TRUE;172if (alreadyChecked != JNI_TRUE){173struct utsname uts;174memset(&uts, 0, sizeof(uts));175strcpy(uts.sysname, "?");176const int utsRes = uname(&uts);177int major = -1;178int minor = -1;179major = atoi(uts.version);180minor = atoi(uts.release);181if (strcmp(uts.sysname, "AIX") == 0) {182if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1183result = JNI_FALSE;184}185}186alreadyChecked = JNI_TRUE;187}188return result;189}190191#endif /* _AIX */192193JNIEXPORT void JNICALL194Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)195{196/* Here because Windows native code does need to init IDs */197}198199JNIEXPORT jboolean JNICALL200Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)201{202return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;203}204205JNIEXPORT jint JNICALL206Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {207return -1;208}209210JNIEXPORT jboolean JNICALL211Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)212{213#if defined(MACOSX) || defined(_AIX)214/* for now IPv6 sockets cannot join IPv4 multicast groups */215return JNI_FALSE;216#else217return JNI_TRUE;218#endif219}220221JNIEXPORT jboolean JNICALL222Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)223{224#ifdef __solaris__225return JNI_TRUE;226#else227return JNI_FALSE;228#endif229}230231JNIEXPORT int JNICALL232Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,233jboolean stream, jboolean reuse, jboolean ignored)234{235int fd;236int type = (stream ? SOCK_STREAM : SOCK_DGRAM);237#ifdef AF_INET6238int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;239#else240int domain = AF_INET;241#endif242243fd = socket(domain, type, 0);244if (fd < 0) {245return handleSocketError(env, errno);246}247248#ifdef AF_INET6249/* Disable IPV6_V6ONLY to ensure dual-socket support */250if (domain == AF_INET6) {251int arg = 0;252if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,253sizeof(int)) < 0) {254JNU_ThrowByNameWithLastError(env,255JNU_JAVANETPKG "SocketException",256"Unable to set IPV6_V6ONLY");257close(fd);258return -1;259}260}261#endif262263if (reuse) {264int arg = 1;265if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,266sizeof(arg)) < 0) {267JNU_ThrowByNameWithLastError(env,268JNU_JAVANETPKG "SocketException",269"Unable to set SO_REUSEADDR");270close(fd);271return -1;272}273}274275#if defined(__linux__)276if (type == SOCK_DGRAM) {277int arg = 0;278int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;279if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&280(errno != ENOPROTOOPT)) {281JNU_ThrowByNameWithLastError(env,282JNU_JAVANETPKG "SocketException",283"Unable to set IP_MULTICAST_ALL");284close(fd);285return -1;286}287}288#endif289290#if defined(__linux__) && defined(AF_INET6)291/* By default, Linux uses the route default */292if (domain == AF_INET6 && type == SOCK_DGRAM) {293int arg = 1;294if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,295sizeof(arg)) < 0) {296JNU_ThrowByNameWithLastError(env,297JNU_JAVANETPKG "SocketException",298"Unable to set IPV6_MULTICAST_HOPS");299close(fd);300return -1;301}302}303#endif304return fd;305}306307JNIEXPORT void JNICALL308Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6,309jboolean useExclBind, jobject iao, int port)310{311SOCKADDR sa;312int sa_len = SOCKADDR_LEN;313int rv = 0;314315if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {316return;317}318319rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);320if (rv != 0) {321handleSocketError(env, errno);322}323}324325JNIEXPORT void JNICALL326Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)327{328if (listen(fdval(env, fdo), backlog) < 0)329handleSocketError(env, errno);330}331332JNIEXPORT jint JNICALL333Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,334jobject fdo, jobject iao, jint port)335{336SOCKADDR sa;337int sa_len = SOCKADDR_LEN;338int rv;339340if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,341&sa_len, preferIPv6) != 0)342{343return IOS_THROWN;344}345346rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);347if (rv != 0) {348if (errno == EINPROGRESS) {349return IOS_UNAVAILABLE;350} else if (errno == EINTR) {351return IOS_INTERRUPTED;352}353return handleSocketError(env, errno);354}355return 1;356}357358JNIEXPORT jint JNICALL359Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)360{361SOCKADDR sa;362socklen_t sa_len = SOCKADDR_LEN;363if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {364#ifdef _ALLBSD_SOURCE365/*366* XXXBSD:367* ECONNRESET is specific to the BSDs. We can not return an error,368* as the calling Java code with raise a java.lang.Error given the expectation369* that getsockname() will never fail. According to the Single UNIX Specification,370* it shouldn't fail. As such, we just fill in generic Linux-compatible values.371*/372if (errno == ECONNRESET) {373struct sockaddr_in *sin;374sin = (struct sockaddr_in *) &sa;375bzero(sin, sizeof(*sin));376sin->sin_len = sizeof(struct sockaddr_in);377sin->sin_family = AF_INET;378sin->sin_port = htonl(0);379sin->sin_addr.s_addr = INADDR_ANY;380} else {381handleSocketError(env, errno);382return -1;383}384#else /* _ALLBSD_SOURCE */385handleSocketError(env, errno);386return -1;387#endif /* _ALLBSD_SOURCE */388}389return NET_GetPortFromSockaddr((struct sockaddr *)&sa);390}391392JNIEXPORT jobject JNICALL393Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)394{395SOCKADDR sa;396socklen_t sa_len = SOCKADDR_LEN;397int port;398if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {399#ifdef _ALLBSD_SOURCE400/*401* XXXBSD:402* ECONNRESET is specific to the BSDs. We can not return an error,403* as the calling Java code with raise a java.lang.Error with the expectation404* that getsockname() will never fail. According to the Single UNIX Specification,405* it shouldn't fail. As such, we just fill in generic Linux-compatible values.406*/407if (errno == ECONNRESET) {408struct sockaddr_in *sin;409sin = (struct sockaddr_in *) &sa;410bzero(sin, sizeof(*sin));411sin->sin_len = sizeof(struct sockaddr_in);412sin->sin_family = AF_INET;413sin->sin_port = htonl(0);414sin->sin_addr.s_addr = INADDR_ANY;415} else {416handleSocketError(env, errno);417return NULL;418}419#else /* _ALLBSD_SOURCE */420handleSocketError(env, errno);421return NULL;422#endif /* _ALLBSD_SOURCE */423}424return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);425}426427JNIEXPORT jint JNICALL428Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,429jboolean mayNeedConversion, jint level, jint opt)430{431int result;432struct linger linger;433u_char carg;434void *arg;435socklen_t arglen;436int n;437438/* Option value is an int except for a few specific cases */439440arg = (void *)&result;441arglen = sizeof(result);442443if (level == IPPROTO_IP &&444(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {445arg = (void*)&carg;446arglen = sizeof(carg);447}448449if (level == SOL_SOCKET && opt == SO_LINGER) {450arg = (void *)&linger;451arglen = sizeof(linger);452}453454if (mayNeedConversion) {455n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen);456} else {457n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);458}459if (n < 0) {460JNU_ThrowByNameWithLastError(env,461JNU_JAVANETPKG "SocketException",462"sun.nio.ch.Net.getIntOption");463return -1;464}465466if (level == IPPROTO_IP &&467(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))468{469return (jint)carg;470}471472if (level == SOL_SOCKET && opt == SO_LINGER)473return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;474475return (jint)result;476}477478JNIEXPORT void JNICALL479Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,480jboolean mayNeedConversion, jint level,481jint opt, jint arg, jboolean isIPv6)482{483int result;484struct linger linger;485u_char carg;486void *parg;487socklen_t arglen;488int n;489490/* Option value is an int except for a few specific cases */491492parg = (void*)&arg;493arglen = sizeof(arg);494495if (level == IPPROTO_IP &&496(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {497parg = (void*)&carg;498arglen = sizeof(carg);499carg = (u_char)arg;500}501502if (level == SOL_SOCKET && opt == SO_LINGER) {503parg = (void *)&linger;504arglen = sizeof(linger);505if (arg >= 0) {506linger.l_onoff = 1;507linger.l_linger = arg;508} else {509linger.l_onoff = 0;510linger.l_linger = 0;511}512}513514if (mayNeedConversion) {515n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);516} else {517n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);518}519if (n < 0) {520JNU_ThrowByNameWithLastError(env,521JNU_JAVANETPKG "SocketException",522"sun.nio.ch.Net.setIntOption");523}524#ifdef __linux__525if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS && isIPv6) {526// set the V4 option also527setsockopt(fdval(env, fdo), IPPROTO_IP, IP_TOS, parg, arglen);528}529#endif530}531532JNIEXPORT jint JNICALL533Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,534jint group, jint interf, jint source)535{536struct ip_mreq mreq;537struct my_ip_mreq_source mreq_source;538int opt, n, optlen;539void* optval;540541if (source == 0) {542mreq.imr_multiaddr.s_addr = htonl(group);543mreq.imr_interface.s_addr = htonl(interf);544opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;545optval = (void*)&mreq;546optlen = sizeof(mreq);547} else {548#ifdef MACOSX549/* no IPv4 include-mode filtering for now */550return IOS_UNAVAILABLE;551#else552553#ifdef _AIX554/* check AIX for support of source filtering */555if (isSourceFilterSupported() != JNI_TRUE){556return IOS_UNAVAILABLE;557}558#endif559560mreq_source.imr_multiaddr.s_addr = htonl(group);561mreq_source.imr_sourceaddr.s_addr = htonl(source);562mreq_source.imr_interface.s_addr = htonl(interf);563opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;564optval = (void*)&mreq_source;565optlen = sizeof(mreq_source);566#endif567}568569n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);570if (n < 0) {571if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))572return IOS_UNAVAILABLE;573handleSocketError(env, errno);574}575return 0;576}577578JNIEXPORT jint JNICALL579Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,580jint group, jint interf, jint source)581{582#ifdef MACOSX583/* no IPv4 exclude-mode filtering for now */584return IOS_UNAVAILABLE;585#else586struct my_ip_mreq_source mreq_source;587int n;588int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;589590#ifdef _AIX591/* check AIX for support of source filtering */592if (isSourceFilterSupported() != JNI_TRUE){593return IOS_UNAVAILABLE;594}595#endif596597mreq_source.imr_multiaddr.s_addr = htonl(group);598mreq_source.imr_sourceaddr.s_addr = htonl(source);599mreq_source.imr_interface.s_addr = htonl(interf);600601n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,602(void*)&mreq_source, sizeof(mreq_source));603if (n < 0) {604if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))605return IOS_UNAVAILABLE;606handleSocketError(env, errno);607}608return 0;609#endif610}611612JNIEXPORT jint JNICALL613Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,614jbyteArray group, jint index, jbyteArray source)615{616#ifdef AF_INET6617struct ipv6_mreq mreq6;618struct my_group_source_req req;619int opt, n, optlen;620void* optval;621622if (source == NULL) {623COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));624mreq6.ipv6mr_interface = (int)index;625opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;626optval = (void*)&mreq6;627optlen = sizeof(mreq6);628} else {629#ifdef MACOSX630/* no IPv6 include-mode filtering for now */631return IOS_UNAVAILABLE;632#else633initGroupSourceReq(env, group, index, source, &req);634opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;635optval = (void*)&req;636optlen = sizeof(req);637#endif638}639640n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);641if (n < 0) {642if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))643return IOS_UNAVAILABLE;644handleSocketError(env, errno);645}646return 0;647#else648JNU_ThrowInternalError(env, "Should not get here");649return IOS_THROWN;650#endif /* AF_INET6 */651}652653JNIEXPORT jint JNICALL654Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,655jbyteArray group, jint index, jbyteArray source)656{657#ifdef AF_INET6658#ifdef MACOSX659/* no IPv6 exclude-mode filtering for now */660return IOS_UNAVAILABLE;661#else662struct my_group_source_req req;663int n;664int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;665666initGroupSourceReq(env, group, index, source, &req);667668n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,669(void*)&req, sizeof(req));670if (n < 0) {671if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))672return IOS_UNAVAILABLE;673handleSocketError(env, errno);674}675return 0;676#endif677#else678JNU_ThrowInternalError(env, "Should not get here");679return IOS_THROWN;680#endif681}682683JNIEXPORT void JNICALL684Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)685{686struct in_addr in;687socklen_t arglen = sizeof(struct in_addr);688int n;689690in.s_addr = htonl(interf);691692n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,693(void*)&(in.s_addr), arglen);694if (n < 0) {695handleSocketError(env, errno);696}697}698699JNIEXPORT jint JNICALL700Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)701{702struct in_addr in;703socklen_t arglen = sizeof(struct in_addr);704int n;705706n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);707if (n < 0) {708handleSocketError(env, errno);709return -1;710}711return ntohl(in.s_addr);712}713714JNIEXPORT void JNICALL715Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)716{717int value = (jint)index;718socklen_t arglen = sizeof(value);719int n;720721n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,722(void*)&(index), arglen);723if (n < 0) {724handleSocketError(env, errno);725}726}727728JNIEXPORT jint JNICALL729Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)730{731int index;732socklen_t arglen = sizeof(index);733int n;734735n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);736if (n < 0) {737handleSocketError(env, errno);738return -1;739}740return (jint)index;741}742743JNIEXPORT void JNICALL744Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)745{746int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :747(jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;748if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN))749handleSocketError(env, errno);750}751752JNIEXPORT jint JNICALL753Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlong timeout)754{755struct pollfd pfd;756int rv;757pfd.fd = fdval(env, fdo);758pfd.events = events;759rv = poll(&pfd, 1, timeout);760761if (rv >= 0) {762return pfd.revents;763} else if (errno == EINTR) {764return IOS_INTERRUPTED;765} else {766handleSocketError(env, errno);767return IOS_THROWN;768}769}770771JNIEXPORT jshort JNICALL772Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this)773{774return (jshort)POLLIN;775}776777JNIEXPORT jshort JNICALL778Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this)779{780return (jshort)POLLOUT;781}782783JNIEXPORT jshort JNICALL784Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this)785{786return (jshort)POLLERR;787}788789JNIEXPORT jshort JNICALL790Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this)791{792return (jshort)POLLHUP;793}794795JNIEXPORT jshort JNICALL796Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)797{798return (jshort)POLLNVAL;799}800801JNIEXPORT jshort JNICALL802Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)803{804return (jshort)POLLOUT;805}806807808/* Declared in nio_util.h */809810jint811handleSocketError(JNIEnv *env, jint errorValue)812{813char *xn;814switch (errorValue) {815case EINPROGRESS: /* Non-blocking connect */816return 0;817#ifdef EPROTO818case EPROTO:819xn = JNU_JAVANETPKG "ProtocolException";820break;821#endif822case ECONNREFUSED:823xn = JNU_JAVANETPKG "ConnectException";824break;825case ETIMEDOUT:826xn = JNU_JAVANETPKG "ConnectException";827break;828case EHOSTUNREACH:829xn = JNU_JAVANETPKG "NoRouteToHostException";830break;831case EADDRINUSE: /* Fall through */832case EADDRNOTAVAIL:833xn = JNU_JAVANETPKG "BindException";834break;835default:836xn = JNU_JAVANETPKG "SocketException";837break;838}839errno = errorValue;840JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");841return IOS_THROWN;842}843844845