annotate src/solaris/native/sun/nio/ch/Net.c @ 2320:a11b4063024f

Merge
author alanb
date Mon, 01 Feb 2010 13:13:46 +0000
parents daac7df87419 8df0ffac7f4d
children
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 */
chegar@2289 127 #ifdef AF_INET6
alanb@562 128 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
alanb@562 129 jbyteArray source, struct my_group_source_req* req)
alanb@562 130 {
alanb@562 131 struct sockaddr_in6* sin6;
alanb@562 132
alanb@562 133 req->gsr_interface = (uint32_t)index;
alanb@562 134
alanb@562 135 sin6 = (struct sockaddr_in6*)&(req->gsr_group);
alanb@562 136 sin6->sin6_family = AF_INET6;
alanb@562 137 COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
alanb@562 138
alanb@562 139 sin6 = (struct sockaddr_in6*)&(req->gsr_source);
alanb@562 140 sin6->sin6_family = AF_INET6;
alanb@562 141 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
alanb@562 142 }
chegar@2289 143 #endif
duke@0 144
duke@0 145 JNIEXPORT void JNICALL
duke@0 146 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
duke@0 147 {
duke@0 148 /* Here because Windows native code does need to init IDs */
duke@0 149 }
duke@0 150
alanb@562 151 JNIEXPORT jboolean JNICALL
alanb@562 152 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
alanb@562 153 {
alanb@562 154 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
alanb@562 155 }
alanb@562 156
duke@0 157 JNIEXPORT int JNICALL
alanb@562 158 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
alanb@562 159 jboolean stream, jboolean reuse)
duke@0 160 {
duke@0 161 int fd;
alanb@562 162 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
chegar@2289 163 #ifdef AF_INET6
alanb@562 164 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
chegar@2289 165 #else
chegar@2289 166 int domain = AF_INET;
chegar@2289 167 #endif
duke@0 168
alanb@562 169 fd = socket(domain, type, 0);
duke@0 170 if (fd < 0) {
duke@0 171 return handleSocketError(env, errno);
duke@0 172 }
duke@0 173 if (reuse) {
duke@0 174 int arg = 1;
alanb@562 175 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
alanb@562 176 sizeof(arg)) < 0) {
duke@0 177 JNU_ThrowByNameWithLastError(env,
duke@0 178 JNU_JAVANETPKG "SocketException",
duke@0 179 "sun.nio.ch.Net.setIntOption");
alanb@562 180 close(fd);
alanb@562 181 return -1;
duke@0 182 }
duke@0 183 }
chegar@2289 184 #if defined(__linux__) && defined(AF_INET6)
alanb@562 185 /* By default, Linux uses the route default */
alanb@562 186 if (domain == AF_INET6 && type == SOCK_DGRAM) {
alanb@562 187 int arg = 1;
alanb@562 188 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
alanb@562 189 sizeof(arg)) < 0) {
alanb@562 190 JNU_ThrowByNameWithLastError(env,
alanb@562 191 JNU_JAVANETPKG "SocketException",
alanb@562 192 "sun.nio.ch.Net.setIntOption");
alanb@562 193 close(fd);
alanb@562 194 return -1;
alanb@562 195 }
alanb@562 196 }
alanb@562 197 #endif
duke@0 198 return fd;
duke@0 199 }
duke@0 200
duke@0 201 JNIEXPORT void JNICALL
alanb@562 202 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@562 203 jobject fdo, jobject iao, int port)
duke@0 204 {
duke@0 205 SOCKADDR sa;
duke@0 206 int sa_len = SOCKADDR_LEN;
duke@0 207 int rv = 0;
duke@0 208
alanb@562 209 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
duke@0 210 return;
duke@0 211 }
duke@0 212
duke@0 213 rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 214 if (rv != 0) {
duke@0 215 handleSocketError(env, errno);
duke@0 216 }
duke@0 217 }
duke@0 218
alanb@562 219 JNIEXPORT void JNICALL
alanb@562 220 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
alanb@562 221 {
alanb@562 222 if (listen(fdval(env, fdo), backlog) < 0)
alanb@562 223 handleSocketError(env, errno);
alanb@562 224 }
alanb@562 225
duke@0 226 JNIEXPORT jint JNICALL
alanb@562 227 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
alanb@562 228 jobject fdo, jobject iao, jint port)
duke@0 229 {
duke@0 230 SOCKADDR sa;
duke@0 231 int sa_len = SOCKADDR_LEN;
duke@0 232 int rv;
duke@0 233
alanb@562 234 if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
alanb@562 235 &sa_len, preferIPv6) != 0)
alanb@562 236 {
duke@0 237 return IOS_THROWN;
duke@0 238 }
duke@0 239
duke@0 240 rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
duke@0 241 if (rv != 0) {
duke@0 242 if (errno == EINPROGRESS) {
duke@0 243 return IOS_UNAVAILABLE;
duke@0 244 } else if (errno == EINTR) {
duke@0 245 return IOS_INTERRUPTED;
duke@0 246 }
duke@0 247 return handleSocketError(env, errno);
duke@0 248 }
duke@0 249 return 1;
duke@0 250 }
duke@0 251
duke@0 252 JNIEXPORT jint JNICALL
duke@0 253 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 254 {
duke@0 255 SOCKADDR sa;
alanb@437 256 socklen_t sa_len = SOCKADDR_LEN;
duke@0 257 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 258 handleSocketError(env, errno);
duke@0 259 return -1;
duke@0 260 }
duke@0 261 return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
duke@0 262 }
duke@0 263
duke@0 264 JNIEXPORT jobject JNICALL
duke@0 265 Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
duke@0 266 {
duke@0 267 SOCKADDR sa;
alanb@437 268 socklen_t sa_len = SOCKADDR_LEN;
duke@0 269 int port;
duke@0 270 if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
duke@0 271 handleSocketError(env, errno);
duke@0 272 return NULL;
duke@0 273 }
duke@0 274 return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
duke@0 275 }
duke@0 276
alanb@562 277 JNIEXPORT jint JNICALL
alanb@562 278 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@562 279 jboolean mayNeedConversion, jint level, jint opt)
alanb@562 280 {
alanb@562 281 int result;
alanb@562 282 struct linger linger;
alanb@562 283 u_char carg;
alanb@562 284 void *arg;
alanb@562 285 int arglen, n;
duke@0 286
alanb@562 287 /* Option value is an int except for a few specific cases */
duke@0 288
alanb@562 289 arg = (void *)&result;
alanb@562 290 arglen = sizeof(result);
duke@0 291
alanb@562 292 if (level == IPPROTO_IP &&
alanb@562 293 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@562 294 arg = (void*)&carg;
alanb@562 295 arglen = sizeof(carg);
duke@0 296 }
duke@0 297
alanb@562 298 if (level == SOL_SOCKET && opt == SO_LINGER) {
alanb@562 299 arg = (void *)&linger;
alanb@562 300 arglen = sizeof(linger);
duke@0 301 }
duke@0 302
alanb@562 303 if (mayNeedConversion) {
alanb@562 304 n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
alanb@562 305 } else {
alanb@562 306 n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
duke@0 307 }
alanb@562 308 if (n < 0) {
duke@0 309 JNU_ThrowByNameWithLastError(env,
duke@0 310 JNU_JAVANETPKG "SocketException",
duke@0 311 "sun.nio.ch.Net.getIntOption");
duke@0 312 return -1;
duke@0 313 }
duke@0 314
alanb@562 315 if (level == IPPROTO_IP &&
alanb@562 316 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
alanb@562 317 {
alanb@562 318 return (jint)carg;
alanb@562 319 }
alanb@562 320
alanb@562 321 if (level == SOL_SOCKET && opt == SO_LINGER)
alanb@562 322 return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
alanb@562 323
alanb@562 324 return (jint)result;
duke@0 325 }
duke@0 326
duke@0 327 JNIEXPORT void JNICALL
alanb@562 328 Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
alanb@562 329 jboolean mayNeedConversion, jint level, jint opt, jint arg)
duke@0 330 {
duke@0 331 int result;
duke@0 332 struct linger linger;
alanb@562 333 u_char carg;
duke@0 334 void *parg;
alanb@562 335 int arglen, n;
duke@0 336
alanb@562 337 /* Option value is an int except for a few specific cases */
alanb@562 338
alanb@562 339 parg = (void*)&arg;
alanb@562 340 arglen = sizeof(arg);
alanb@562 341
alanb@562 342 if (level == IPPROTO_IP &&
alanb@562 343 (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
alanb@562 344 parg = (void*)&carg;
alanb@562 345 arglen = sizeof(carg);
alanb@562 346 carg = (u_char)arg;
duke@0 347 }
duke@0 348
alanb@562 349 if (level == SOL_SOCKET && opt == SO_LINGER) {
duke@0 350 parg = (void *)&linger;
duke@0 351 arglen = sizeof(linger);
duke@0 352 if (arg >= 0) {
duke@0 353 linger.l_onoff = 1;
duke@0 354 linger.l_linger = arg;
duke@0 355 } else {
duke@0 356 linger.l_onoff = 0;
duke@0 357 linger.l_linger = 0;
duke@0 358 }
duke@0 359 }
duke@0 360
alanb@562 361 if (mayNeedConversion) {
alanb@562 362 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
alanb@562 363 } else {
alanb@562 364 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
alanb@562 365 }
alanb@562 366 if (n < 0) {
duke@0 367 JNU_ThrowByNameWithLastError(env,
duke@0 368 JNU_JAVANETPKG "SocketException",
duke@0 369 "sun.nio.ch.Net.setIntOption");
duke@0 370 }
duke@0 371 }
duke@0 372
alanb@562 373 JNIEXPORT jint JNICALL
alanb@562 374 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@562 375 jint group, jint interf, jint source)
alanb@562 376 {
alanb@562 377 struct ip_mreq mreq;
alanb@562 378 struct my_ip_mreq_source mreq_source;
alanb@562 379 int opt, n, optlen;
alanb@562 380 void* optval;
duke@0 381
alanb@562 382 if (source == 0) {
alanb@562 383 mreq.imr_multiaddr.s_addr = htonl(group);
alanb@562 384 mreq.imr_interface.s_addr = htonl(interf);
alanb@562 385 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
alanb@562 386 optval = (void*)&mreq;
alanb@562 387 optlen = sizeof(mreq);
alanb@562 388 } else {
alanb@562 389 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@562 390 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@562 391 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@562 392 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
alanb@562 393 optval = (void*)&mreq_source;
alanb@562 394 optlen = sizeof(mreq_source);
alanb@562 395 }
alanb@562 396
alanb@562 397 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
alanb@562 398 if (n < 0) {
alanb@562 399 if (join && (errno == ENOPROTOOPT))
alanb@562 400 return IOS_UNAVAILABLE;
alanb@562 401 handleSocketError(env, errno);
alanb@562 402 }
alanb@562 403 return 0;
alanb@562 404 }
alanb@562 405
alanb@562 406 JNIEXPORT jint JNICALL
alanb@562 407 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@562 408 jint group, jint interf, jint source)
alanb@562 409 {
alanb@562 410 struct my_ip_mreq_source mreq_source;
alanb@562 411 int n;
alanb@562 412 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
alanb@562 413
alanb@562 414 mreq_source.imr_multiaddr.s_addr = htonl(group);
alanb@562 415 mreq_source.imr_sourceaddr.s_addr = htonl(source);
alanb@562 416 mreq_source.imr_interface.s_addr = htonl(interf);
alanb@562 417
alanb@562 418 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
alanb@562 419 (void*)&mreq_source, sizeof(mreq_source));
alanb@562 420 if (n < 0) {
alanb@562 421 if (block && (errno == ENOPROTOOPT))
alanb@562 422 return IOS_UNAVAILABLE;
alanb@562 423 handleSocketError(env, errno);
alanb@562 424 }
alanb@562 425 return 0;
alanb@562 426 }
alanb@562 427
alanb@562 428 JNIEXPORT jint JNICALL
alanb@562 429 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
alanb@562 430 jbyteArray group, jint index, jbyteArray source)
alanb@562 431 {
chegar@2289 432 #ifdef AF_INET6
alanb@562 433 struct ipv6_mreq mreq6;
alanb@562 434 struct my_group_source_req req;
alanb@562 435 int opt, n, optlen;
alanb@562 436 void* optval;
alanb@562 437
alanb@562 438 if (source == NULL) {
alanb@562 439 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
alanb@562 440 mreq6.ipv6mr_interface = (int)index;
alanb@562 441 opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
alanb@562 442 optval = (void*)&mreq6;
alanb@562 443 optlen = sizeof(mreq6);
alanb@562 444 } else {
alanb@562 445 #ifdef __linux__
alanb@562 446 /* Include-mode filtering broken on Linux at least to 2.6.24 */
alanb@562 447 return IOS_UNAVAILABLE;
alanb@562 448 #else
alanb@562 449 initGroupSourceReq(env, group, index, source, &req);
alanb@562 450 opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
alanb@562 451 optval = (void*)&req;
alanb@562 452 optlen = sizeof(req);
alanb@562 453 #endif
alanb@562 454 }
alanb@562 455
alanb@562 456 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
alanb@562 457 if (n < 0) {
alanb@562 458 if (join && (errno == ENOPROTOOPT))
alanb@562 459 return IOS_UNAVAILABLE;
alanb@562 460 handleSocketError(env, errno);
alanb@562 461 }
alanb@562 462 return 0;
chegar@2289 463 #else
chegar@2289 464 JNU_ThrowInternalError(env, "Should not get here");
chegar@2289 465 return IOS_THROWN;
chegar@2289 466 #endif /* AF_INET6 */
alanb@562 467 }
alanb@562 468
alanb@562 469 JNIEXPORT jint JNICALL
alanb@562 470 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
alanb@562 471 jbyteArray group, jint index, jbyteArray source)
alanb@562 472 {
chegar@2289 473 #ifdef AF_INET6
alanb@562 474 struct my_group_source_req req;
alanb@562 475 int n;
alanb@562 476 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
alanb@562 477
alanb@562 478 initGroupSourceReq(env, group, index, source, &req);
alanb@562 479
alanb@562 480 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
alanb@562 481 (void*)&req, sizeof(req));
alanb@562 482 if (n < 0) {
alanb@562 483 if (block && (errno == ENOPROTOOPT))
alanb@562 484 return IOS_UNAVAILABLE;
alanb@562 485 handleSocketError(env, errno);
alanb@562 486 }
alanb@562 487 return 0;
chegar@2289 488 #else
chegar@2289 489 JNU_ThrowInternalError(env, "Should not get here");
chegar@2289 490 return IOS_THROWN;
chegar@2289 491 #endif
alanb@562 492 }
alanb@562 493
alanb@562 494 JNIEXPORT void JNICALL
alanb@562 495 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
alanb@562 496 {
alanb@562 497 struct in_addr in;
alanb@562 498 int arglen = sizeof(struct in_addr);
alanb@562 499 int n;
alanb@562 500
alanb@562 501 in.s_addr = htonl(interf);
alanb@562 502
alanb@562 503 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
alanb@562 504 (void*)&(in.s_addr), arglen);
alanb@562 505 if (n < 0) {
alanb@562 506 handleSocketError(env, errno);
alanb@562 507 }
alanb@562 508 }
alanb@562 509
alanb@562 510 JNIEXPORT jint JNICALL
alanb@562 511 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
alanb@562 512 {
alanb@562 513 struct in_addr in;
alanb@562 514 int arglen = sizeof(struct in_addr);
alanb@562 515 int n;
alanb@562 516
alanb@562 517 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
alanb@562 518 if (n < 0) {
alanb@562 519 handleSocketError(env, errno);
alanb@562 520 return -1;
alanb@562 521 }
alanb@562 522 return ntohl(in.s_addr);
alanb@562 523 }
alanb@562 524
alanb@562 525 JNIEXPORT void JNICALL
alanb@562 526 Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
alanb@562 527 {
alanb@562 528 int value = (jint)index;
alanb@562 529 int arglen = sizeof(value);
alanb@562 530 int n;
alanb@562 531
alanb@562 532 n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
alanb@562 533 (void*)&(index), arglen);
alanb@562 534 if (n < 0) {
alanb@562 535 handleSocketError(env, errno);
alanb@562 536 }
alanb@562 537 }
alanb@562 538
alanb@562 539 JNIEXPORT jint JNICALL
alanb@562 540 Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
alanb@562 541 {
alanb@562 542 int index;
alanb@562 543 int arglen = sizeof(index);
alanb@562 544 int n;
alanb@562 545
alanb@562 546 n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
alanb@562 547 if (n < 0) {
alanb@562 548 handleSocketError(env, errno);
alanb@562 549 return -1;
alanb@562 550 }
alanb@562 551 return (jint)index;
alanb@562 552 }
alanb@562 553
alanb@562 554 JNIEXPORT void JNICALL
alanb@562 555 Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
alanb@562 556 {
alanb@562 557 int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
alanb@562 558 (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
alanb@1737 559 if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN))
alanb@562 560 handleSocketError(env, errno);
alanb@562 561 }
duke@0 562
duke@0 563 /* Declared in nio_util.h */
duke@0 564
duke@0 565 jint
duke@0 566 handleSocketError(JNIEnv *env, jint errorValue)
duke@0 567 {
duke@0 568 char *xn;
duke@0 569 switch (errorValue) {
duke@0 570 case EINPROGRESS: /* Non-blocking connect */
duke@0 571 return 0;
duke@0 572 case EPROTO:
duke@0 573 xn = JNU_JAVANETPKG "ProtocolException";
duke@0 574 break;
duke@0 575 case ECONNREFUSED:
duke@0 576 xn = JNU_JAVANETPKG "ConnectException";
duke@0 577 break;
duke@0 578 case ETIMEDOUT:
duke@0 579 xn = JNU_JAVANETPKG "ConnectException";
duke@0 580 break;
duke@0 581 case EHOSTUNREACH:
duke@0 582 xn = JNU_JAVANETPKG "NoRouteToHostException";
duke@0 583 break;
duke@0 584 case EADDRINUSE: /* Fall through */
duke@0 585 case EADDRNOTAVAIL:
duke@0 586 xn = JNU_JAVANETPKG "BindException";
duke@0 587 break;
duke@0 588 default:
duke@0 589 xn = JNU_JAVANETPKG "SocketException";
duke@0 590 break;
duke@0 591 }
duke@0 592 errno = errorValue;
duke@0 593 JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
duke@0 594 return IOS_THROWN;
duke@0 595 }