annotate src/solaris/native/sun/nio/ch/Net.c @ 353:5996f2328c7c

Fixes/updates for nio2-b92 - NPE in multicast sample when network interface not specified - IPv6 hop count uses route default (linux only)) - DatagramChannel#getOption throws UOE instead of IAE for bogus option - CREATE and TRUNCATE combination of open options does not work (win only) - setOwner fails to set owner when privileges available (win only)) - moveTo across volumes or copyTo preserving attributes didn't copy security attrs (win only) - Directory attributes not copied correctly when moving/copying across fs (solaris/linux only) - ACL set/get throws confusing message when NFSv4 ACLs not supported on fs (solaris only) - Timer thread visible to user supplied ThreadFactory - Provider permission checks insufficient - NamedAttributeView#read missing IAE - NamedAttributeView#read didn't handle read-only buffer (linux only) - NamedAttributeView confusing exception when attribute name larger than max (linux only) - NamedAttributeView missing null check (win only) - Unable to access named attributes of sym links (win only) - ArrayIndexOutOfBounds when name empty (solaris only) - Eliminate IoFuture - CompletionHandler should define three methods - Clarify how cancellation should behave - Remove bogus UOE from attribute package - Path missing getFileSystem method - Part one of updates to AsynchronousChannelGroup
author alanb
date Tue, 24 Jun 2008 20:05:07 +0100
parents 939fd6c3984a
children 89772d193b62
rev   line source
duke@0 1 /*
duke@0 2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation. Sun designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
duke@0 9 * by Sun in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
duke@0 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@0 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@0 23 * have any questions.
duke@0 24 */
duke@0 25
duke@0 26 #include <sys/types.h>
duke@0 27 #include <sys/socket.h>
duke@0 28 #include <string.h>
duke@0 29 #include <netinet/in.h>
duke@0 30 #include <netinet/tcp.h>
duke@0 31
duke@0 32 #include "jni.h"
duke@0 33 #include "jni_util.h"
duke@0 34 #include "jvm.h"
duke@0 35 #include "jlong.h"
duke@0 36 #include "sun_nio_ch_Net.h"
duke@0 37 #include "net_util.h"
duke@0 38 #include "net_util_md.h"
duke@0 39 #include "nio_util.h"
duke@0 40 #include "nio.h"
duke@0 41
alanb@350 42 /**
alanb@350 43 * Definitions for source-specific multicast to allow for building
alanb@350 44 * with older header files.
alanb@350 45 */
alanb@350 46
alanb@350 47 #ifdef __solaris__
alanb@350 48
alanb@350 49 #ifndef IP_BLOCK_SOURCE
alanb@350 50
alanb@350 51 #define IP_BLOCK_SOURCE 0x15
alanb@350 52 #define IP_UNBLOCK_SOURCE 0x16
alanb@350 53 #define IP_ADD_SOURCE_MEMBERSHIP 0x17
alanb@350 54 #define IP_DROP_SOURCE_MEMBERSHIP 0x18
alanb@350 55
alanb@350 56 #define MCAST_BLOCK_SOURCE 0x2b
alanb@350 57 #define MCAST_UNBLOCK_SOURCE 0x2c
alanb@350 58 #define MCAST_JOIN_SOURCE_GROUP 0x2d
alanb@350 59 #define MCAST_LEAVE_SOURCE_GROUP 0x2e
alanb@350 60
alanb@350 61 #endif /* IP_BLOCK_SOURCE */
alanb@350 62
alanb@350 63 struct my_ip_mreq_source {
alanb@350 64 struct in_addr imr_multiaddr;
alanb@350 65 struct in_addr imr_sourceaddr;
alanb@350 66 struct in_addr imr_interface;
alanb@350 67 };
alanb@350 68
alanb@350 69 /*
alanb@350 70 * Use #pragma pack() construct to force 32-bit alignment on amd64.
alanb@350 71 */
alanb@350 72 #if defined(amd64)
alanb@350 73 #pragma pack(4)
alanb@350 74 #endif
alanb@350 75
alanb@350 76 struct my_group_source_req {
alanb@350 77 uint32_t gsr_interface; /* interface index */
alanb@350 78 struct sockaddr_storage gsr_group; /* group address */
alanb@350 79 struct sockaddr_storage gsr_source; /* source address */
alanb@350 80 };
alanb@350 81
alanb@350 82 #if defined(amd64)
alanb@350 83 #pragma pack()
alanb@350 84 #endif
alanb@350 85
alanb@350 86 #endif /* __solaris__ */
alanb@350 87
alanb@350 88
duke@0 89 #ifdef __linux__
duke@0 90
alanb@350 91 #ifndef IP_BLOCK_SOURCE
alanb@350 92
alanb@350 93 #define IP_BLOCK_SOURCE 38
alanb@350 94 #define IP_UNBLOCK_SOURCE 37
alanb@350 95 #define IP_ADD_SOURCE_MEMBERSHIP 39
alanb@350 96 #define IP_DROP_SOURCE_MEMBERSHIP 40
alanb@350 97
alanb@350 98 #define MCAST_BLOCK_SOURCE 43
alanb@350 99 #define MCAST_UNBLOCK_SOURCE 44
alanb@350 100 #define MCAST_JOIN_SOURCE_GROUP 42
alanb@350 101 #define MCAST_LEAVE_SOURCE_GROUP 45
alanb@350 102
alanb@350 103 #endif /* IP_BLOCK_SOURCE */
alanb@350 104
alanb@350 105 struct my_ip_mreq_source {
alanb@350 106 struct in_addr imr_multiaddr;
alanb@350 107 struct in_addr imr_interface;
alanb@350 108 struct in_addr imr_sourceaddr;
alanb@350 109 };
alanb@350 110
alanb@350 111 struct my_group_source_req {
alanb@350 112 uint32_t gsr_interface; /* interface index */
alanb@350 113 struct sockaddr_storage gsr_group; /* group address */
alanb@350 114 struct sockaddr_storage gsr_source; /* source address */
alanb@350 115 };
alanb@350 116
alanb@350 117 #endif /* __linux__ */
alanb@350 118
alanb@350 119
alanb@350 120 #define COPY_INET6_ADDRESS(env, source, target) \
alanb@350 121 (*env)->GetByteArrayRegion(env, source, 0, 16, target)
alanb@350 122
alanb@350 123 /*
alanb@350 124 * Copy IPv6 group, interface index, and IPv6 source address
alanb@350 125 * into group_source_req structure.
alanb@350 126 */
alanb@350 127 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
alanb@350 128 jbyteArray source, struct my_group_source_req* req)
alanb@350 129 {
alanb@350 130 struct sockaddr_in6* sin6;
alanb@350 131
alanb@350 132 req->gsr_interface = (uint32_t)index;
alanb@350 133
alanb@350 134 sin6 = (struct sockaddr_in6*)&(req->gsr_group);
alanb@350 135 sin6->sin6_family = AF_INET6;
alanb@350 136 COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
alanb@350 137
alanb@350 138 sin6 = (struct sockaddr_in6*)&(req->gsr_source);
alanb@350 139 sin6->sin6_family = AF_INET6;
alanb@350 140 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
alanb@350 141 }
alanb@350 142
duke@0 143
duke@0 144 JNIEXPORT void JNICALL
duke@0 145 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
duke@0 146 {
duke@0 147 /* Here because Windows native code does need to init IDs */
duke@0 148 }
duke@0 149
alanb@350 150 JNIEXPORT jboolean JNICALL
alanb@350 151 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
alanb@350 152 {
alanb@350 153 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
alanb@350 154 }
alanb@350 155
duke@0 156 JNIEXPORT int JNICALL
alanb@350 157 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
alanb@350 158 jboolean stream, jboolean reuse)
duke@0 159 {
duke@0 160 int fd;
alanb@350 161 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
alanb@350 162 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
duke@0 163
alanb@350 164 fd = socket(domain, type, 0);
duke@0 165 if (fd < 0) {
duke@0 166 return handleSocketError(env, errno);
duke@0 167 }
duke@0 168 if (reuse) {
duke@0 169 int arg = 1;
alanb@350 170 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
alanb@350 171 sizeof(arg)) < 0) {
duke@0 172 JNU_ThrowByNameWithLastError(env,
duke@0 173 JNU_JAVANETPKG "SocketException",
duke@0 174 "sun.nio.ch.Net.setIntOption");
alanb@353 175 close(fd);
alanb@353 176 return -1;
duke@0 177 }
duke@0 178 }
alanb@353 179 #ifdef __linux__
alanb@353 180 /* By default, Linux uses the route default */
alanb@353 181 if (domain == AF_INET6 && type == SOCK_DGRAM) {
alanb@353 182 int arg = 1;
alanb@353 183 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
alanb@353 184 sizeof(arg)) < 0) {
alanb@353 185 JNU_ThrowByNameWithLastError(env,
alanb@353 186 JNU_JAVANETPKG "SocketException",
alanb@353 187 "sun.nio.ch.Net.setIntOption");
alanb@353 188 close(fd);
alanb@353 189 return -1;
alanb@353 190 }
alanb@353 191 }
alanb@353 192 #endif
duke@0 193 return fd;
duke@0 194 }
duke@0 195
duke@0 196 JNIEXPORT void JNICALL
alanb@350 197 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@350 198 jobject fdo, jobject iao, int port)
duke@0 199 {
duke@0 200 SOCKADDR sa;
duke@0 201 int sa_len = SOCKADDR_LEN;
duke@0 202 int rv = 0;
duke@0 203
alanb@350 204 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
duke@0 205 return;
duke@0 206 }
duke@0 207
duke@0 208 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 209 if (rv != 0) {
duke@0 210 handleSocketError(env, errno);
duke@0 211 }
duke@0 212 }
duke@0 213
alanb@350 214 JNIEXPORT void JNICALL
alanb@350 215 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
alanb@350 216 {
alanb@350 217 if (listen(fdval(env, fdo), backlog) < 0)
alanb@350 218 handleSocketError(env, errno);
alanb@350 219 }
alanb@350 220
duke@0 221 JNIEXPORT jint JNICALL
alanb@350 222 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@350 223 jobject fdo, jobject iao, jint port)
duke@0 224 {
duke@0 225 SOCKADDR sa;
duke@0 226 int sa_len = SOCKADDR_LEN;
duke@0 227 int rv;
duke@0 228
alanb@350 229 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
alanb@350 230 &sa_len, preferIPv6) != 0)
alanb@350 231 {
duke@0 232 return IOS_THROWN;
duke@0 233 }
duke@0 234
duke@0 235 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 236 if (rv != 0) {
duke@0 237 if (errno == EINPROGRESS) {
duke@0 238 return IOS_UNAVAILABLE;
duke@0 239 } else if (errno == EINTR) {
duke@0 240 return IOS_INTERRUPTED;
duke@0 241 }
duke@0 242 return handleSocketError(env, errno);
duke@0 243 }
duke@0 244 return 1;
duke@0 245 }
duke@0 246
duke@0 247 JNIEXPORT jint JNICALL
duke@0 248 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 249 {
duke@0 250 SOCKADDR sa;
duke@0 251 int sa_len = SOCKADDR_LEN;
duke@0 252 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 253 handleSocketError(env, errno);
duke@0 254 return -1;
duke@0 255 }
duke@0 256 return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
duke@0 257 }
duke@0 258
duke@0 259 JNIEXPORT jobject JNICALL
duke@0 260 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 261 {
duke@0 262 SOCKADDR sa;
duke@0 263 int sa_len = SOCKADDR_LEN;
duke@0 264 int port;
duke@0 265 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 266 handleSocketError(env, errno);
duke@0 267 return NULL;
duke@0 268 }
duke@0 269 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
duke@0 270 }
duke@0 271
alanb@350 272 JNIEXPORT jint JNICALL
alanb@350 273 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@350 274 jboolean mayNeedConversion, jint level, jint opt)
alanb@350 275 {
alanb@350 276 int result;
alanb@350 277 struct linger linger;
alanb@350 278 u_char carg;
alanb@350 279 void *arg;
alanb@350 280 int arglen, n;
duke@0 281
alanb@350 282 /* Option value is an int except for a few specific cases */
duke@0 283
alanb@350 284 arg = (void *)&result;
alanb@350 285 arglen = sizeof(result);
duke@0 286
alanb@350 287 if (level == IPPROTO_IP &&
alanb@350 288 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@350 289 arg = (void*)&carg;
alanb@350 290 arglen = sizeof(carg);
duke@0 291 }
duke@0 292
alanb@350 293 if (level == SOL_SOCKET && opt == SO_LINGER) {
alanb@350 294 arg = (void *)&linger;
alanb@350 295 arglen = sizeof(linger);
duke@0 296 }
duke@0 297
alanb@350 298 if (mayNeedConversion) {
alanb@350 299 n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
alanb@350 300 } else {
alanb@350 301 n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
duke@0 302 }
alanb@350 303 if (n < 0) {
duke@0 304 JNU_ThrowByNameWithLastError(env,
duke@0 305 JNU_JAVANETPKG "SocketException",
duke@0 306 "sun.nio.ch.Net.getIntOption");
duke@0 307 return -1;
duke@0 308 }
duke@0 309
alanb@350 310 if (level == IPPROTO_IP &&
alanb@350 311 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
alanb@350 312 {
alanb@350 313 return (jint)carg;
alanb@350 314 }
alanb@350 315
alanb@350 316 if (level == SOL_SOCKET && opt == SO_LINGER)
alanb@350 317 return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
alanb@350 318
alanb@350 319 return (jint)result;
duke@0 320 }
duke@0 321
duke@0 322 JNIEXPORT void JNICALL
alanb@350 323 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@350 324 jboolean mayNeedConversion, jint level, jint opt, jint arg)
duke@0 325 {
duke@0 326 int result;
duke@0 327 struct linger linger;
alanb@350 328 u_char carg;
duke@0 329 void *parg;
alanb@350 330 int arglen, n;
duke@0 331
alanb@350 332 /* Option value is an int except for a few specific cases */
alanb@350 333
alanb@350 334 parg = (void*)&arg;
alanb@350 335 arglen = sizeof(arg);
alanb@350 336
alanb@350 337 if (level == IPPROTO_IP &&
alanb@350 338 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@350 339 parg = (void*)&carg;
alanb@350 340 arglen = sizeof(carg);
alanb@350 341 carg = (u_char)arg;
duke@0 342 }
duke@0 343
alanb@350 344 if (level == SOL_SOCKET && opt == SO_LINGER) {
duke@0 345 parg = (void *)&linger;
duke@0 346 arglen = sizeof(linger);
duke@0 347 if (arg >= 0) {
duke@0 348 linger.l_onoff = 1;
duke@0 349 linger.l_linger = arg;
duke@0 350 } else {
duke@0 351 linger.l_onoff = 0;
duke@0 352 linger.l_linger = 0;
duke@0 353 }
duke@0 354 }
duke@0 355
alanb@350 356 if (mayNeedConversion) {
alanb@350 357 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
alanb@350 358 } else {
alanb@350 359 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
alanb@350 360 }
alanb@350 361 if (n < 0) {
duke@0 362 JNU_ThrowByNameWithLastError(env,
duke@0 363 JNU_JAVANETPKG "SocketException",
duke@0 364 "sun.nio.ch.Net.setIntOption");
duke@0 365 }
duke@0 366 }
duke@0 367
alanb@350 368 JNIEXPORT jint JNICALL
alanb@350 369 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@350 370 jint group, jint interf, jint source)
alanb@350 371 {
alanb@350 372 struct ip_mreq mreq;
alanb@350 373 struct my_ip_mreq_source mreq_source;
alanb@350 374 int opt, n, optlen;
alanb@350 375 void* optval;
duke@0 376
alanb@350 377 if (source == 0) {
alanb@350 378 mreq.imr_multiaddr.s_addr = htonl(group);
alanb@350 379 mreq.imr_interface.s_addr = htonl(interf);
alanb@350 380 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
alanb@350 381 optval = (void*)&mreq;
alanb@350 382 optlen = sizeof(mreq);
alanb@350 383 } else {
alanb@350 384 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@350 385 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@350 386 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@350 387 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
alanb@350 388 optval = (void*)&mreq_source;
alanb@350 389 optlen = sizeof(mreq_source);
alanb@350 390 }
alanb@350 391
alanb@350 392 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
alanb@350 393 if (n < 0) {
alanb@350 394 if (join && (errno == ENOPROTOOPT))
alanb@350 395 return IOS_UNAVAILABLE;
alanb@350 396 handleSocketError(env, errno);
alanb@350 397 }
alanb@350 398 return 0;
alanb@350 399 }
alanb@350 400
alanb@350 401 JNIEXPORT jint JNICALL
alanb@350 402 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@350 403 jint group, jint interf, jint source)
alanb@350 404 {
alanb@350 405 struct my_ip_mreq_source mreq_source;
alanb@350 406 int n;
alanb@350 407 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
alanb@350 408
alanb@350 409 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@350 410 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@350 411 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@350 412
alanb@350 413 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
alanb@350 414 (void*)&mreq_source, sizeof(mreq_source));
alanb@350 415 if (n < 0) {
alanb@350 416 if (block && (errno == ENOPROTOOPT))
alanb@350 417 return IOS_UNAVAILABLE;
alanb@350 418 handleSocketError(env, errno);
alanb@350 419 }
alanb@350 420 return 0;
alanb@350 421 }
alanb@350 422
alanb@350 423 JNIEXPORT jint JNICALL
alanb@350 424 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@350 425 jbyteArray group, jint index, jbyteArray source)
alanb@350 426 {
alanb@350 427 struct ipv6_mreq mreq6;
alanb@350 428 struct my_group_source_req req;
alanb@350 429 int opt, n, optlen;
alanb@350 430 void* optval;
alanb@350 431
alanb@350 432 if (source == NULL) {
alanb@350 433 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
alanb@350 434 mreq6.ipv6mr_interface = (int)index;
alanb@350 435 opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
alanb@350 436 optval = (void*)&mreq6;
alanb@350 437 optlen = sizeof(mreq6);
alanb@350 438 } else {
alanb@350 439 #ifdef __linux__
alanb@350 440 /* Include-mode filtering broken on Linux at least to 2.6.24 */
alanb@350 441 return IOS_UNAVAILABLE;
alanb@350 442 #else
alanb@350 443 initGroupSourceReq(env, group, index, source, &req);
alanb@350 444 opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
alanb@350 445 optval = (void*)&req;
alanb@350 446 optlen = sizeof(req);
alanb@350 447 #endif
alanb@350 448 }
alanb@350 449
alanb@350 450 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
alanb@350 451 if (n < 0) {
alanb@350 452 if (join && (errno == ENOPROTOOPT))
alanb@350 453 return IOS_UNAVAILABLE;
alanb@350 454 handleSocketError(env, errno);
alanb@350 455 }
alanb@350 456 return 0;
alanb@350 457 }
alanb@350 458
alanb@350 459 JNIEXPORT jint JNICALL
alanb@350 460 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@350 461 jbyteArray group, jint index, jbyteArray source)
alanb@350 462 {
alanb@350 463 struct my_group_source_req req;
alanb@350 464 int n;
alanb@350 465 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
alanb@350 466
alanb@350 467 initGroupSourceReq(env, group, index, source, &req);
alanb@350 468
alanb@350 469 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
alanb@350 470 (void*)&req, sizeof(req));
alanb@350 471 if (n < 0) {
alanb@350 472 if (block && (errno == ENOPROTOOPT))
alanb@350 473 return IOS_UNAVAILABLE;
alanb@350 474 handleSocketError(env, errno);
alanb@350 475 }
alanb@350 476 return 0;
alanb@350 477 }
alanb@350 478
alanb@350 479 JNIEXPORT void JNICALL
alanb@350 480 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
alanb@350 481 {
alanb@350 482 struct in_addr in;
alanb@350 483 int arglen = sizeof(struct in_addr);
alanb@350 484 int n;
alanb@350 485
alanb@350 486 in.s_addr = htonl(interf);
alanb@350 487
alanb@350 488 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
alanb@350 489 (void*)&(in.s_addr), arglen);
alanb@350 490 if (n < 0) {
alanb@350 491 handleSocketError(env, errno);
alanb@350 492 }
alanb@350 493 }
alanb@350 494
alanb@350 495 JNIEXPORT jint JNICALL
alanb@350 496 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
alanb@350 497 {
alanb@350 498 struct in_addr in;
alanb@350 499 int arglen = sizeof(struct in_addr);
alanb@350 500 int n;
alanb@350 501
alanb@350 502 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
alanb@350 503 if (n < 0) {
alanb@350 504 handleSocketError(env, errno);
alanb@350 505 return -1;
alanb@350 506 }
alanb@350 507 return ntohl(in.s_addr);
alanb@350 508 }
alanb@350 509
alanb@350 510 JNIEXPORT void JNICALL
alanb@350 511 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
alanb@350 512 {
alanb@350 513 int value = (jint)index;
alanb@350 514 int arglen = sizeof(value);
alanb@350 515 int n;
alanb@350 516
alanb@350 517 n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
alanb@350 518 (void*)&(index), arglen);
alanb@350 519 if (n < 0) {
alanb@350 520 handleSocketError(env, errno);
alanb@350 521 }
alanb@350 522 }
alanb@350 523
alanb@350 524 JNIEXPORT jint JNICALL
alanb@350 525 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
alanb@350 526 {
alanb@350 527 int index;
alanb@350 528 int arglen = sizeof(index);
alanb@350 529 int n;
alanb@350 530
alanb@350 531 n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
alanb@350 532 if (n < 0) {
alanb@350 533 handleSocketError(env, errno);
alanb@350 534 return -1;
alanb@350 535 }
alanb@350 536 return (jint)index;
alanb@350 537 }
alanb@350 538
alanb@350 539 JNIEXPORT void JNICALL
alanb@350 540 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint how) {
alanb@350 541 if (shutdown(fdval(env, fdo), how) < 0)
alanb@350 542 handleSocketError(env, errno);
alanb@350 543 }
duke@0 544
duke@0 545 /* Declared in nio_util.h */
duke@0 546
duke@0 547 jint
duke@0 548 handleSocketError(JNIEnv *env, jint errorValue)
duke@0 549 {
duke@0 550 char *xn;
duke@0 551 switch (errorValue) {
duke@0 552 case EINPROGRESS: /* Non-blocking connect */
duke@0 553 return 0;
duke@0 554 case EPROTO:
duke@0 555 xn = JNU_JAVANETPKG "ProtocolException";
duke@0 556 break;
duke@0 557 case ECONNREFUSED:
duke@0 558 xn = JNU_JAVANETPKG "ConnectException";
duke@0 559 break;
duke@0 560 case ETIMEDOUT:
duke@0 561 xn = JNU_JAVANETPKG "ConnectException";
duke@0 562 break;
duke@0 563 case EHOSTUNREACH:
duke@0 564 xn = JNU_JAVANETPKG "NoRouteToHostException";
duke@0 565 break;
duke@0 566 case EADDRINUSE: /* Fall through */
duke@0 567 case EADDRNOTAVAIL:
duke@0 568 xn = JNU_JAVANETPKG "BindException";
duke@0 569 break;
duke@0 570 default:
duke@0 571 xn = JNU_JAVANETPKG "SocketException";
duke@0 572 break;
duke@0 573 }
duke@0 574 errno = errorValue;
duke@0 575 JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
duke@0 576 return IOS_THROWN;
duke@0 577 }