annotate src/solaris/native/sun/nio/ch/Net.c @ 683:14f50aee4989

6754988: Update copyright year Summary: Update for files that have been modified starting July 2008 Reviewed-by: ohair, tbell
author xdono
date Thu, 02 Oct 2008 19:58:32 -0700
parents 343253d05123
children 06c5f60e40e9 5b5df0632ecf
rev   line source
duke@0 1 /*
xdono@683 2 * Copyright 2001-2008 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@562 42 /**
alanb@562 43 * Definitions for source-specific multicast to allow for building
alanb@562 44 * with older header files.
alanb@562 45 */
alanb@562 46
alanb@562 47 #ifdef __solaris__
alanb@562 48
alanb@562 49 #ifndef IP_BLOCK_SOURCE
alanb@562 50
alanb@562 51 #define IP_BLOCK_SOURCE 0x15
alanb@562 52 #define IP_UNBLOCK_SOURCE 0x16
alanb@562 53 #define IP_ADD_SOURCE_MEMBERSHIP 0x17
alanb@562 54 #define IP_DROP_SOURCE_MEMBERSHIP 0x18
alanb@562 55
alanb@562 56 #define MCAST_BLOCK_SOURCE 0x2b
alanb@562 57 #define MCAST_UNBLOCK_SOURCE 0x2c
alanb@562 58 #define MCAST_JOIN_SOURCE_GROUP 0x2d
alanb@562 59 #define MCAST_LEAVE_SOURCE_GROUP 0x2e
alanb@562 60
alanb@562 61 #endif /* IP_BLOCK_SOURCE */
alanb@562 62
alanb@562 63 struct my_ip_mreq_source {
alanb@562 64 struct in_addr imr_multiaddr;
alanb@562 65 struct in_addr imr_sourceaddr;
alanb@562 66 struct in_addr imr_interface;
alanb@562 67 };
alanb@562 68
alanb@562 69 /*
alanb@562 70 * Use #pragma pack() construct to force 32-bit alignment on amd64.
alanb@562 71 */
alanb@562 72 #if defined(amd64)
alanb@562 73 #pragma pack(4)
alanb@562 74 #endif
alanb@562 75
alanb@562 76 struct my_group_source_req {
alanb@562 77 uint32_t gsr_interface; /* interface index */
alanb@562 78 struct sockaddr_storage gsr_group; /* group address */
alanb@562 79 struct sockaddr_storage gsr_source; /* source address */
alanb@562 80 };
alanb@562 81
alanb@562 82 #if defined(amd64)
alanb@562 83 #pragma pack()
alanb@562 84 #endif
alanb@562 85
alanb@562 86 #endif /* __solaris__ */
alanb@562 87
alanb@562 88
duke@0 89 #ifdef __linux__
duke@0 90
alanb@562 91 #ifndef IP_BLOCK_SOURCE
alanb@562 92
alanb@562 93 #define IP_BLOCK_SOURCE 38
alanb@562 94 #define IP_UNBLOCK_SOURCE 37
alanb@562 95 #define IP_ADD_SOURCE_MEMBERSHIP 39
alanb@562 96 #define IP_DROP_SOURCE_MEMBERSHIP 40
alanb@562 97
alanb@562 98 #define MCAST_BLOCK_SOURCE 43
alanb@562 99 #define MCAST_UNBLOCK_SOURCE 44
alanb@562 100 #define MCAST_JOIN_SOURCE_GROUP 42
alanb@562 101 #define MCAST_LEAVE_SOURCE_GROUP 45
alanb@562 102
alanb@562 103 #endif /* IP_BLOCK_SOURCE */
alanb@562 104
alanb@562 105 struct my_ip_mreq_source {
alanb@562 106 struct in_addr imr_multiaddr;
alanb@562 107 struct in_addr imr_interface;
alanb@562 108 struct in_addr imr_sourceaddr;
alanb@562 109 };
alanb@562 110
alanb@562 111 struct my_group_source_req {
alanb@562 112 uint32_t gsr_interface; /* interface index */
alanb@562 113 struct sockaddr_storage gsr_group; /* group address */
alanb@562 114 struct sockaddr_storage gsr_source; /* source address */
alanb@562 115 };
alanb@562 116
alanb@562 117 #endif /* __linux__ */
alanb@562 118
alanb@562 119
alanb@562 120 #define COPY_INET6_ADDRESS(env, source, target) \
alanb@562 121 (*env)->GetByteArrayRegion(env, source, 0, 16, target)
alanb@562 122
alanb@562 123 /*
alanb@562 124 * Copy IPv6 group, interface index, and IPv6 source address
alanb@562 125 * into group_source_req structure.
alanb@562 126 */
alanb@562 127 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
alanb@562 128 jbyteArray source, struct my_group_source_req* req)
alanb@562 129 {
alanb@562 130 struct sockaddr_in6* sin6;
alanb@562 131
alanb@562 132 req->gsr_interface = (uint32_t)index;
alanb@562 133
alanb@562 134 sin6 = (struct sockaddr_in6*)&(req->gsr_group);
alanb@562 135 sin6->sin6_family = AF_INET6;
alanb@562 136 COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
alanb@562 137
alanb@562 138 sin6 = (struct sockaddr_in6*)&(req->gsr_source);
alanb@562 139 sin6->sin6_family = AF_INET6;
alanb@562 140 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
alanb@562 141 }
alanb@562 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@562 150 JNIEXPORT jboolean JNICALL
alanb@562 151 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
alanb@562 152 {
alanb@562 153 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
alanb@562 154 }
alanb@562 155
duke@0 156 JNIEXPORT int JNICALL
alanb@562 157 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
alanb@562 158 jboolean stream, jboolean reuse)
duke@0 159 {
duke@0 160 int fd;
alanb@562 161 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
alanb@562 162 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
duke@0 163
alanb@562 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@562 170 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
alanb@562 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@562 175 close(fd);
alanb@562 176 return -1;
duke@0 177 }
duke@0 178 }
alanb@562 179 #ifdef __linux__
alanb@562 180 /* By default, Linux uses the route default */
alanb@562 181 if (domain == AF_INET6 && type == SOCK_DGRAM) {
alanb@562 182 int arg = 1;
alanb@562 183 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
alanb@562 184 sizeof(arg)) < 0) {
alanb@562 185 JNU_ThrowByNameWithLastError(env,
alanb@562 186 JNU_JAVANETPKG "SocketException",
alanb@562 187 "sun.nio.ch.Net.setIntOption");
alanb@562 188 close(fd);
alanb@562 189 return -1;
alanb@562 190 }
alanb@562 191 }
alanb@562 192 #endif
duke@0 193 return fd;
duke@0 194 }
duke@0 195
duke@0 196 JNIEXPORT void JNICALL
alanb@562 197 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@562 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@562 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@562 214 JNIEXPORT void JNICALL
alanb@562 215 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
alanb@562 216 {
alanb@562 217 if (listen(fdval(env, fdo), backlog) < 0)
alanb@562 218 handleSocketError(env, errno);
alanb@562 219 }
alanb@562 220
duke@0 221 JNIEXPORT jint JNICALL
alanb@562 222 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@562 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@562 229 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
alanb@562 230 &sa_len, preferIPv6) != 0)
alanb@562 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;
alanb@437 251 socklen_t 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;
alanb@437 263 socklen_t 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@562 272 JNIEXPORT jint JNICALL
alanb@562 273 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@562 274 jboolean mayNeedConversion, jint level, jint opt)
alanb@562 275 {
alanb@562 276 int result;
alanb@562 277 struct linger linger;
alanb@562 278 u_char carg;
alanb@562 279 void *arg;
alanb@562 280 int arglen, n;
duke@0 281
alanb@562 282 /* Option value is an int except for a few specific cases */
duke@0 283
alanb@562 284 arg = (void *)&result;
alanb@562 285 arglen = sizeof(result);
duke@0 286
alanb@562 287 if (level == IPPROTO_IP &&
alanb@562 288 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@562 289 arg = (void*)&carg;
alanb@562 290 arglen = sizeof(carg);
duke@0 291 }
duke@0 292
alanb@562 293 if (level == SOL_SOCKET && opt == SO_LINGER) {
alanb@562 294 arg = (void *)&linger;
alanb@562 295 arglen = sizeof(linger);
duke@0 296 }
duke@0 297
alanb@562 298 if (mayNeedConversion) {
alanb@562 299 n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
alanb@562 300 } else {
alanb@562 301 n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
duke@0 302 }
alanb@562 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@562 310 if (level == IPPROTO_IP &&
alanb@562 311 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
alanb@562 312 {
alanb@562 313 return (jint)carg;
alanb@562 314 }
alanb@562 315
alanb@562 316 if (level == SOL_SOCKET && opt == SO_LINGER)
alanb@562 317 return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
alanb@562 318
alanb@562 319 return (jint)result;
duke@0 320 }
duke@0 321
duke@0 322 JNIEXPORT void JNICALL
alanb@562 323 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@562 324 jboolean mayNeedConversion, jint level, jint opt, jint arg)
duke@0 325 {
duke@0 326 int result;
duke@0 327 struct linger linger;
alanb@562 328 u_char carg;
duke@0 329 void *parg;
alanb@562 330 int arglen, n;
duke@0 331
alanb@562 332 /* Option value is an int except for a few specific cases */
alanb@562 333
alanb@562 334 parg = (void*)&arg;
alanb@562 335 arglen = sizeof(arg);
alanb@562 336
alanb@562 337 if (level == IPPROTO_IP &&
alanb@562 338 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@562 339 parg = (void*)&carg;
alanb@562 340 arglen = sizeof(carg);
alanb@562 341 carg = (u_char)arg;
duke@0 342 }
duke@0 343
alanb@562 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@562 356 if (mayNeedConversion) {
alanb@562 357 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
alanb@562 358 } else {
alanb@562 359 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
alanb@562 360 }
alanb@562 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@562 368 JNIEXPORT jint JNICALL
alanb@562 369 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@562 370 jint group, jint interf, jint source)
alanb@562 371 {
alanb@562 372 struct ip_mreq mreq;
alanb@562 373 struct my_ip_mreq_source mreq_source;
alanb@562 374 int opt, n, optlen;
alanb@562 375 void* optval;
duke@0 376
alanb@562 377 if (source == 0) {
alanb@562 378 mreq.imr_multiaddr.s_addr = htonl(group);
alanb@562 379 mreq.imr_interface.s_addr = htonl(interf);
alanb@562 380 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
alanb@562 381 optval = (void*)&mreq;
alanb@562 382 optlen = sizeof(mreq);
alanb@562 383 } else {
alanb@562 384 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@562 385 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@562 386 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@562 387 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
alanb@562 388 optval = (void*)&mreq_source;
alanb@562 389 optlen = sizeof(mreq_source);
alanb@562 390 }
alanb@562 391
alanb@562 392 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
alanb@562 393 if (n < 0) {
alanb@562 394 if (join && (errno == ENOPROTOOPT))
alanb@562 395 return IOS_UNAVAILABLE;
alanb@562 396 handleSocketError(env, errno);
alanb@562 397 }
alanb@562 398 return 0;
alanb@562 399 }
alanb@562 400
alanb@562 401 JNIEXPORT jint JNICALL
alanb@562 402 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@562 403 jint group, jint interf, jint source)
alanb@562 404 {
alanb@562 405 struct my_ip_mreq_source mreq_source;
alanb@562 406 int n;
alanb@562 407 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
alanb@562 408
alanb@562 409 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@562 410 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@562 411 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@562 412
alanb@562 413 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
alanb@562 414 (void*)&mreq_source, sizeof(mreq_source));
alanb@562 415 if (n < 0) {
alanb@562 416 if (block && (errno == ENOPROTOOPT))
alanb@562 417 return IOS_UNAVAILABLE;
alanb@562 418 handleSocketError(env, errno);
alanb@562 419 }
alanb@562 420 return 0;
alanb@562 421 }
alanb@562 422
alanb@562 423 JNIEXPORT jint JNICALL
alanb@562 424 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@562 425 jbyteArray group, jint index, jbyteArray source)
alanb@562 426 {
alanb@562 427 struct ipv6_mreq mreq6;
alanb@562 428 struct my_group_source_req req;
alanb@562 429 int opt, n, optlen;
alanb@562 430 void* optval;
alanb@562 431
alanb@562 432 if (source == NULL) {
alanb@562 433 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
alanb@562 434 mreq6.ipv6mr_interface = (int)index;
alanb@562 435 opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
alanb@562 436 optval = (void*)&mreq6;
alanb@562 437 optlen = sizeof(mreq6);
alanb@562 438 } else {
alanb@562 439 #ifdef __linux__
alanb@562 440 /* Include-mode filtering broken on Linux at least to 2.6.24 */
alanb@562 441 return IOS_UNAVAILABLE;
alanb@562 442 #else
alanb@562 443 initGroupSourceReq(env, group, index, source, &req);
alanb@562 444 opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
alanb@562 445 optval = (void*)&req;
alanb@562 446 optlen = sizeof(req);
alanb@562 447 #endif
alanb@562 448 }
alanb@562 449
alanb@562 450 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
alanb@562 451 if (n < 0) {
alanb@562 452 if (join && (errno == ENOPROTOOPT))
alanb@562 453 return IOS_UNAVAILABLE;
alanb@562 454 handleSocketError(env, errno);
alanb@562 455 }
alanb@562 456 return 0;
alanb@562 457 }
alanb@562 458
alanb@562 459 JNIEXPORT jint JNICALL
alanb@562 460 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@562 461 jbyteArray group, jint index, jbyteArray source)
alanb@562 462 {
alanb@562 463 struct my_group_source_req req;
alanb@562 464 int n;
alanb@562 465 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
alanb@562 466
alanb@562 467 initGroupSourceReq(env, group, index, source, &req);
alanb@562 468
alanb@562 469 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
alanb@562 470 (void*)&req, sizeof(req));
alanb@562 471 if (n < 0) {
alanb@562 472 if (block && (errno == ENOPROTOOPT))
alanb@562 473 return IOS_UNAVAILABLE;
alanb@562 474 handleSocketError(env, errno);
alanb@562 475 }
alanb@562 476 return 0;
alanb@562 477 }
alanb@562 478
alanb@562 479 JNIEXPORT void JNICALL
alanb@562 480 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
alanb@562 481 {
alanb@562 482 struct in_addr in;
alanb@562 483 int arglen = sizeof(struct in_addr);
alanb@562 484 int n;
alanb@562 485
alanb@562 486 in.s_addr = htonl(interf);
alanb@562 487
alanb@562 488 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
alanb@562 489 (void*)&(in.s_addr), arglen);
alanb@562 490 if (n < 0) {
alanb@562 491 handleSocketError(env, errno);
alanb@562 492 }
alanb@562 493 }
alanb@562 494
alanb@562 495 JNIEXPORT jint JNICALL
alanb@562 496 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
alanb@562 497 {
alanb@562 498 struct in_addr in;
alanb@562 499 int arglen = sizeof(struct in_addr);
alanb@562 500 int n;
alanb@562 501
alanb@562 502 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
alanb@562 503 if (n < 0) {
alanb@562 504 handleSocketError(env, errno);
alanb@562 505 return -1;
alanb@562 506 }
alanb@562 507 return ntohl(in.s_addr);
alanb@562 508 }
alanb@562 509
alanb@562 510 JNIEXPORT void JNICALL
alanb@562 511 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
alanb@562 512 {
alanb@562 513 int value = (jint)index;
alanb@562 514 int arglen = sizeof(value);
alanb@562 515 int n;
alanb@562 516
alanb@562 517 n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
alanb@562 518 (void*)&(index), arglen);
alanb@562 519 if (n < 0) {
alanb@562 520 handleSocketError(env, errno);
alanb@562 521 }
alanb@562 522 }
alanb@562 523
alanb@562 524 JNIEXPORT jint JNICALL
alanb@562 525 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
alanb@562 526 {
alanb@562 527 int index;
alanb@562 528 int arglen = sizeof(index);
alanb@562 529 int n;
alanb@562 530
alanb@562 531 n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
alanb@562 532 if (n < 0) {
alanb@562 533 handleSocketError(env, errno);
alanb@562 534 return -1;
alanb@562 535 }
alanb@562 536 return (jint)index;
alanb@562 537 }
alanb@562 538
alanb@562 539 JNIEXPORT void JNICALL
alanb@562 540 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
alanb@562 541 {
alanb@562 542 int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
alanb@562 543 (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
alanb@562 544 if (shutdown(fdval(env, fdo), how) < 0)
alanb@562 545 handleSocketError(env, errno);
alanb@562 546 }
duke@0 547
duke@0 548 /* Declared in nio_util.h */
duke@0 549
duke@0 550 jint
duke@0 551 handleSocketError(JNIEnv *env, jint errorValue)
duke@0 552 {
duke@0 553 char *xn;
duke@0 554 switch (errorValue) {
duke@0 555 case EINPROGRESS: /* Non-blocking connect */
duke@0 556 return 0;
duke@0 557 case EPROTO:
duke@0 558 xn = JNU_JAVANETPKG "ProtocolException";
duke@0 559 break;
duke@0 560 case ECONNREFUSED:
duke@0 561 xn = JNU_JAVANETPKG "ConnectException";
duke@0 562 break;
duke@0 563 case ETIMEDOUT:
duke@0 564 xn = JNU_JAVANETPKG "ConnectException";
duke@0 565 break;
duke@0 566 case EHOSTUNREACH:
duke@0 567 xn = JNU_JAVANETPKG "NoRouteToHostException";
duke@0 568 break;
duke@0 569 case EADDRINUSE: /* Fall through */
duke@0 570 case EADDRNOTAVAIL:
duke@0 571 xn = JNU_JAVANETPKG "BindException";
duke@0 572 break;
duke@0 573 default:
duke@0 574 xn = JNU_JAVANETPKG "SocketException";
duke@0 575 break;
duke@0 576 }
duke@0 577 errno = errorValue;
duke@0 578 JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
duke@0 579 return IOS_THROWN;
duke@0 580 }