1 /*
2 * Copyright (c) 2001, 2019, 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
24 */
25
26 #include <poll.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <string.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <limits.h>
33
34 #include "jni.h"
35 #include "jni_util.h"
36 #include "jvm.h"
37 #include "jlong.h"
38 #include "sun_nio_ch_Net.h"
39 #include "net_util.h"
40 #include "net_util_md.h"
41 #include "nio_util.h"
42 #include "nio.h"
43
44 #ifdef _AIX
45 #include <stdlib.h>
46 #include <sys/utsname.h>
47 #endif
48
49 /**
50 * IP_MULTICAST_ALL supported since 2.6.31 but may not be available at
51 * build time.
52 */
53 #ifdef __linux__
54 #ifndef IP_MULTICAST_ALL
55 #define IP_MULTICAST_ALL 49
56 #endif
57 #endif
58
59 /**
60 * IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP may not be defined on OSX and AIX
61 */
62 #if defined(__APPLE__) || defined(_AIX)
63 #ifndef IPV6_ADD_MEMBERSHIP
64 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
65 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
66 #endif
67 #endif
68
69 #define COPY_INET6_ADDRESS(env, source, target) \
70 (*env)->GetByteArrayRegion(env, source, 0, 16, target)
71
72 /*
73 * Copy IPv6 group, interface index, and IPv6 source address
74 * into group_source_req structure.
75 */
76 static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
77 jbyteArray source, struct group_source_req *req)
78 {
79 struct sockaddr_in6* sin6;
80
81 req->gsr_interface = (uint32_t)index;
82
83 sin6 = (struct sockaddr_in6 *)&(req->gsr_group);
84 sin6->sin6_family = AF_INET6;
85 COPY_INET6_ADDRESS(env, group, (jbyte *)&(sin6->sin6_addr));
86
87 sin6 = (struct sockaddr_in6 *)&(req->gsr_source);
88 sin6->sin6_family = AF_INET6;
89 COPY_INET6_ADDRESS(env, source, (jbyte *)&(sin6->sin6_addr));
90 }
91
92 #ifdef _AIX
93
94 /*
95 * Checks whether or not "socket extensions for multicast source filters" is supported.
96 * Returns JNI_TRUE if it is supported, JNI_FALSE otherwise
97 */
98 static jboolean isSourceFilterSupported(){
99 static jboolean alreadyChecked = JNI_FALSE;
100 static jboolean result = JNI_TRUE;
101 if (alreadyChecked != JNI_TRUE){
102 struct utsname uts;
103 memset(&uts, 0, sizeof(uts));
104 strcpy(uts.sysname, "?");
105 const int utsRes = uname(&uts);
106 int major = -1;
107 int minor = -1;
108 major = atoi(uts.version);
109 minor = atoi(uts.release);
110 if (strcmp(uts.sysname, "AIX") == 0) {
111 if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1
112 result = JNI_FALSE;
113 }
114 }
115 alreadyChecked = JNI_TRUE;
116 }
117 return result;
118 }
119
120 #endif /* _AIX */
121
122 static jclass isa_class; /* java.net.InetSocketAddress */
123 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
124
125 JNIEXPORT void JNICALL
126 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
127 {
128 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
129 CHECK_NULL(cls);
130 isa_class = (*env)->NewGlobalRef(env, cls);
131 if (isa_class == NULL) {
132 JNU_ThrowOutOfMemoryError(env, NULL);
133 return;
134 }
135 isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
136 CHECK_NULL(isa_ctorID);
137
138 initInetAddressIDs(env);
139 }
140
141 JNIEXPORT jboolean JNICALL
166 return JNI_FALSE;
167 #endif
168 }
169
170 JNIEXPORT jboolean JNICALL
171 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
172 {
173 #if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
174 /* IPv6 sockets can join IPv4 multicast groups */
175 return JNI_TRUE;
176 #else
177 /* IPv6 sockets cannot join IPv4 multicast groups */
178 return JNI_FALSE;
179 #endif
180 }
181
182 JNIEXPORT jboolean JNICALL
183 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
184 {
185 #if defined(__APPLE__) || defined(__solaris__)
186 /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
187 return JNI_TRUE;
188 #else
189 /* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */
190 return JNI_FALSE;
191 #endif
192 }
193
194 JNIEXPORT jboolean JNICALL
195 Java_sun_nio_ch_Net_canUseIPv6OptionsWithIPv4LocalAddress0(JNIEnv* env, jclass cl)
196 {
197 /* IPV6_XXX socket options can be used on IPv6 sockets bound to IPv4 address */
198 return JNI_TRUE;
199 }
200
201 JNIEXPORT jint JNICALL
202 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
203 jboolean stream, jboolean reuse, jboolean ignored)
204 {
205 int fd;
206 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
207 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
208
209 fd = socket(domain, type, 0);
539 } else {
540 linger.l_onoff = 0;
541 linger.l_linger = 0;
542 }
543 }
544
545 if (mayNeedConversion) {
546 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
547 } else {
548 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
549 }
550 if (n < 0) {
551 JNU_ThrowByNameWithLastError(env,
552 JNU_JAVANETPKG "SocketException",
553 "sun.nio.ch.Net.setIntOption");
554 }
555 }
556
557 JNIEXPORT jint JNICALL
558 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
559 jint group, jint interf, jint source)
560 {
561 struct ip_mreq mreq;
562 struct ip_mreq_source mreq_source;
563 int opt, n, optlen;
564 void* optval;
565
566 if (source == 0) {
567 mreq.imr_multiaddr.s_addr = htonl(group);
568 mreq.imr_interface.s_addr = htonl(interf);
569 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
570 optval = (void*)&mreq;
571 optlen = sizeof(mreq);
572 } else {
573
574 #ifdef _AIX
575 /* check AIX for support of source filtering */
576 if (isSourceFilterSupported() != JNI_TRUE){
577 return IOS_UNAVAILABLE;
578 }
579 #endif
580
581 mreq_source.imr_multiaddr.s_addr = htonl(group);
582 mreq_source.imr_sourceaddr.s_addr = htonl(source);
583 mreq_source.imr_interface.s_addr = htonl(interf);
584 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
585 optval = (void*)&mreq_source;
586 optlen = sizeof(mreq_source);
587 }
588
589 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
590 if (n < 0) {
591 if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
592 return IOS_UNAVAILABLE;
593 handleSocketError(env, errno);
594 }
595 return 0;
596 }
597
598 JNIEXPORT jint JNICALL
599 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
600 jint group, jint interf, jint source)
601 {
602 #ifdef __APPLE__
603 /* no IPv4 exclude-mode filtering for now */
604 return IOS_UNAVAILABLE;
605 #else
606 struct ip_mreq_source mreq_source;
607 int n;
608 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
609
610 #ifdef _AIX
611 /* check AIX for support of source filtering */
612 if (isSourceFilterSupported() != JNI_TRUE){
613 return IOS_UNAVAILABLE;
614 }
615 #endif
616
617 mreq_source.imr_multiaddr.s_addr = htonl(group);
618 mreq_source.imr_sourceaddr.s_addr = htonl(source);
619 mreq_source.imr_interface.s_addr = htonl(interf);
620
621 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
622 (void*)&mreq_source, sizeof(mreq_source));
623 if (n < 0) {
624 if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
625 return IOS_UNAVAILABLE;
626 handleSocketError(env, errno);
627 }
628 return 0;
629 #endif
630 }
631
632 JNIEXPORT jint JNICALL
633 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
634 jbyteArray group, jint index, jbyteArray source)
635 {
636 struct ipv6_mreq mreq6;
637 struct group_source_req req;
638 int opt, n, optlen;
639 void* optval;
640
641 if (source == NULL) {
642 COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
643 mreq6.ipv6mr_interface = (int)index;
644 opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
645 optval = (void*)&mreq6;
646 optlen = sizeof(mreq6);
647 } else {
648 #ifdef __APPLE__
649 /* no IPv6 include-mode filtering for now */
650 return IOS_UNAVAILABLE;
651 #else
652 initGroupSourceReq(env, group, index, source, &req);
653 opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
654 optval = (void*)&req;
655 optlen = sizeof(req);
656 #endif
657 }
658
659 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
660 if (n < 0) {
661 if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
662 return IOS_UNAVAILABLE;
663 handleSocketError(env, errno);
664 }
665 return 0;
666 }
667
668 JNIEXPORT jint JNICALL
669 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
670 jbyteArray group, jint index, jbyteArray source)
671 {
672 #ifdef __APPLE__
673 /* no IPv6 exclude-mode filtering for now */
674 return IOS_UNAVAILABLE;
675 #else
676 struct group_source_req req;
677 int n;
678 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
679
680 initGroupSourceReq(env, group, index, source, &req);
681
682 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
683 (void*)&req, sizeof(req));
684 if (n < 0) {
685 if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
686 return IOS_UNAVAILABLE;
687 handleSocketError(env, errno);
688 }
689 return 0;
690 #endif
691 }
692
693 JNIEXPORT void JNICALL
694 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
695 {
696 struct in_addr in;
697 socklen_t arglen = sizeof(struct in_addr);
698 int n;
699
700 in.s_addr = htonl(interf);
701
702 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
703 (void*)&(in.s_addr), arglen);
704 if (n < 0) {
705 handleSocketError(env, errno);
706 }
707 }
708
709 JNIEXPORT jint JNICALL
710 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
711 {
712 struct in_addr in;
713 socklen_t arglen = sizeof(struct in_addr);
714 int n;
715
716 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
717 if (n < 0) {
718 handleSocketError(env, errno);
719 return -1;
720 }
721 return ntohl(in.s_addr);
|
1 /*
2 * Copyright (c) 2001, 2020, 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
24 */
25
26 #include <poll.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <string.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <limits.h>
33
34 #include "jni.h"
35 #include "jni_util.h"
36 #include "jvm.h"
37 #include "jlong.h"
38 #include "sun_nio_ch_Net.h"
39 #include "net_util.h"
40 #include "net_util_md.h"
41 #include "nio_util.h"
42 #include "nio.h"
43
44 /**
45 * Use MCAST_JOIN_GROUP/MCAST_BLOCK_SOURCE on platforms that support it.
46 */
47 #if defined(__linux__) || defined(__solaris__)
48 #include "nio_multicast.h"
49 #define USE_MCAST_XXX 1
50 #endif
51
52 /**
53 * IP_MULTICAST_ALL supported since 2.6.31 (and glibc 2.15) but may not be
54 * available at build time.
55 */
56 #ifdef __linux__
57 #ifndef IP_MULTICAST_ALL
58 #define IP_MULTICAST_ALL 49
59 #endif
60 #endif
61
62 static jclass isa_class; /* java.net.InetSocketAddress */
63 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
64
65 JNIEXPORT void JNICALL
66 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
67 {
68 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
69 CHECK_NULL(cls);
70 isa_class = (*env)->NewGlobalRef(env, cls);
71 if (isa_class == NULL) {
72 JNU_ThrowOutOfMemoryError(env, NULL);
73 return;
74 }
75 isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
76 CHECK_NULL(isa_ctorID);
77
78 initInetAddressIDs(env);
79 }
80
81 JNIEXPORT jboolean JNICALL
106 return JNI_FALSE;
107 #endif
108 }
109
110 JNIEXPORT jboolean JNICALL
111 Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
112 {
113 #if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
114 /* IPv6 sockets can join IPv4 multicast groups */
115 return JNI_TRUE;
116 #else
117 /* IPv6 sockets cannot join IPv4 multicast groups */
118 return JNI_FALSE;
119 #endif
120 }
121
122 JNIEXPORT jboolean JNICALL
123 Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
124 {
125 #if defined(__APPLE__) || defined(__solaris__)
126 /* IPv6 sockets use IPPROTO_IPV6 level options to join IPv4 multicast groups */
127 return JNI_TRUE;
128 #else
129 /* IPv6 sockets use IPPROTO_IP level options to join IPv4 multicast groups */
130 return JNI_FALSE;
131 #endif
132 }
133
134 JNIEXPORT jboolean JNICALL
135 Java_sun_nio_ch_Net_canUseIPv6OptionsWithIPv4LocalAddress0(JNIEnv* env, jclass cl)
136 {
137 /* IPV6_XXX socket options can be used on IPv6 sockets bound to IPv4 address */
138 return JNI_TRUE;
139 }
140
141 JNIEXPORT jint JNICALL
142 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
143 jboolean stream, jboolean reuse, jboolean ignored)
144 {
145 int fd;
146 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
147 int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
148
149 fd = socket(domain, type, 0);
479 } else {
480 linger.l_onoff = 0;
481 linger.l_linger = 0;
482 }
483 }
484
485 if (mayNeedConversion) {
486 n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
487 } else {
488 n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
489 }
490 if (n < 0) {
491 JNU_ThrowByNameWithLastError(env,
492 JNU_JAVANETPKG "SocketException",
493 "sun.nio.ch.Net.setIntOption");
494 }
495 }
496
497 JNIEXPORT jint JNICALL
498 Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
499 jint group, jint index, jint infAddress, jint source)
500 {
501 int n;
502 int fd = fdval(env, fdo);
503 #ifdef USE_MCAST_XXX
504 if (source == 0) {
505 int opt = (join) ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP;
506 struct group_req req;
507 initGroupReq4(env, &req, index, group);
508 n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&req, sizeof(req));
509 } else {
510 int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
511 struct group_source_req req;
512 initGroupSourceReq4(env, &req, index, group, source);
513 n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&req, sizeof(req));
514 }
515 #else
516 if (source == 0) {
517 int opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
518 struct ip_mreq mreq;
519 mreq.imr_multiaddr.s_addr = htonl(group);
520 mreq.imr_interface.s_addr = htonl(infAddress);
521 n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&mreq, sizeof(mreq));
522 } else {
523 int opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
524 struct ip_mreq_source mreq_source;
525 mreq_source.imr_multiaddr.s_addr = htonl(group);
526 mreq_source.imr_interface.s_addr = htonl(infAddress);
527 mreq_source.imr_sourceaddr.s_addr = htonl(source);
528 n = setsockopt(fd, IPPROTO_IP, opt, (const void*)&mreq_source, sizeof(mreq_source));
529 }
530 #endif
531 if (n == -1) {
532 handleSocketError(env, errno);
533 }
534 return 0;
535 }
536
537 JNIEXPORT jint JNICALL
538 Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
539 jint group, jint index, jint infAddress, jint source)
540 {
541 #if defined(__APPLE__)
542 /* no IPv4 exclude-mode filtering on this platform */
543 return IOS_UNAVAILABLE;
544 #else
545 int n;
546 int fd = fdval(env, fdo);
547 #if USE_MCAST_XXX
548 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
549 struct group_source_req req;
550 initGroupSourceReq4(env, &req, index, group, source);
551 n = setsockopt(fd, IPPROTO_IP, opt, (const char*)&req, sizeof(req));
552 #else
553 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
554 struct ip_mreq_source mreq_source;
555 mreq_source.imr_multiaddr.s_addr = htonl(group);
556 mreq_source.imr_interface.s_addr = htonl(infAddress);
557 mreq_source.imr_sourceaddr.s_addr = htonl(source);
558 n = setsockopt(fd, IPPROTO_IP, opt, (void*)&mreq_source, sizeof(mreq_source));
559 #endif
560 if (n == -1) {
561 handleSocketError(env, errno);
562 }
563 return 0;
564 #endif
565 }
566
567 JNIEXPORT jint JNICALL
568 Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
569 jbyteArray group, jint index, jbyteArray source)
570 {
571 int n;
572 int fd = fdval(env, fdo);
573 #ifdef USE_MCAST_XXX
574 if (source == NULL) {
575 int opt = (join) ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP;
576 struct group_req req;
577 initGroupReq6(env, &req, index, group);
578 n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&req, sizeof(req));
579 } else {
580 int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
581 struct group_source_req req;
582 initGroupSourceReq6(env, &req, index, group, source);
583 n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&req, sizeof(req));
584 }
585 #else
586 #ifndef IPV6_ADD_MEMBERSHIP
587 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
588 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
589 #endif
590 if (source == NULL) {
591 int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
592 struct ipv6_mreq mreq6;
593 mreq6.ipv6mr_interface = (int)index;
594 (*env)->GetByteArrayRegion(env, group, 0, 16, (jbyte*)&(mreq6.ipv6mr_multiaddr));
595 n = setsockopt(fd, IPPROTO_IPV6, opt, (const void*)&mreq6, sizeof(mreq6));
596 } else {
597 /* no IPv6 include-mode filtering */
598 return IOS_UNAVAILABLE;
599 }
600 #endif
601 if (n == -1) {
602 handleSocketError(env, errno);
603 }
604 return 0;
605 }
606
607 JNIEXPORT jint JNICALL
608 Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
609 jbyteArray group, jint index, jbyteArray source)
610 {
611 #ifdef USE_MCAST_XXX
612 int n;
613 int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
614 struct group_source_req req;
615 initGroupSourceReq6(env, &req, index, group, source);
616 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req));
617 if (n == -1) {
618 handleSocketError(env, errno);
619 }
620 return 0;
621 #else
622 /* no IPv6 exclude-mode filtering */
623 return IOS_UNAVAILABLE;
624 #endif
625 }
626
627 JNIEXPORT void JNICALL
628 Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint infAddress)
629 {
630 struct in_addr in;
631 socklen_t arglen = sizeof(struct in_addr);
632 int n;
633
634 in.s_addr = htonl(infAddress);
635 n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
636 (void*)&(in.s_addr), arglen);
637 if (n < 0) {
638 handleSocketError(env, errno);
639 }
640 }
641
642 JNIEXPORT jint JNICALL
643 Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
644 {
645 struct in_addr in;
646 socklen_t arglen = sizeof(struct in_addr);
647 int n;
648
649 n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
650 if (n < 0) {
651 handleSocketError(env, errno);
652 return -1;
653 }
654 return ntohl(in.s_addr);
|