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
23 * questions.
24 */
25 #include <dlfcn.h>
26 #include <errno.h>
27 #include <net/if.h>
28 #include <netinet/tcp.h> // defines TCP_NODELAY
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <sys/time.h>
33
34 #if defined(__linux__)
35 #include <arpa/inet.h>
36 #include <net/route.h>
37 #include <sys/utsname.h>
38 #endif
39
40 #if defined(__solaris__)
41 #include <inet/nd.h>
42 #include <limits.h>
43 #include <stropts.h>
44 #include <sys/filio.h>
45 #include <sys/sockio.h>
46 #endif
47
48 #if defined(MACOSX)
49 #include <sys/sysctl.h>
50 #endif
51
52 #include "jvm.h"
53 #include "net_util.h"
54
55 #include "java_net_SocketOptions.h"
56 #include "java_net_InetAddress.h"
57
58 #if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
59 #define IPV6_FLOWINFO_SEND 33
60 #endif
61
62 #if defined(__solaris__) && !defined(MAXINT)
63 #define MAXINT INT_MAX
64 #endif
65
66 /*
67 * EXCLBIND socket options only on Solaris
68 */
69 #if defined(__solaris__) && !defined(TCP_EXCLBIND)
70 #define TCP_EXCLBIND 0x21
71 #endif
72 #if defined(__solaris__) && !defined(UDP_EXCLBIND)
73 #define UDP_EXCLBIND 0x0101
74 #endif
75
76 #define RESTARTABLE(_cmd, _result) do { \
77 do { \
78 _result = _cmd; \
79 } while((_result == -1) && (errno == EINTR)); \
80 } while(0)
81
82 int NET_SocketAvailable(int s, int *pbytes) {
83 int result;
84 RESTARTABLE(ioctl(s, FIONREAD, pbytes), result);
85 return result;
86 }
87
88 #ifdef __solaris__
89 static int init_tcp_max_buf, init_udp_max_buf;
90 static int tcp_max_buf;
91 static int udp_max_buf;
92 static int useExclBind = 0;
93
94 /*
95 * Get the specified parameter from the specified driver. The value
96 * of the parameter is assumed to be an 'int'. If the parameter
97 * cannot be obtained return -1
98 */
99 int net_getParam(char *driver, char *param)
100 {
101 struct strioctl stri;
102 char buf [64];
103 int s;
104 int value;
105
106 s = open (driver, O_RDWR);
107 if (s < 0) {
108 return -1;
109 }
110 strncpy (buf, param, sizeof(buf));
111 stri.ic_cmd = ND_GET;
112 stri.ic_timout = 0;
113 stri.ic_dp = buf;
114 stri.ic_len = sizeof(buf);
115 if (ioctl (s, I_STR, &stri) < 0) {
116 value = -1;
117 } else {
118 value = atoi(buf);
119 }
120 close (s);
121 return value;
122 }
123
124 /*
125 * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
126 * for Solaris versions that do not support the ioctl() in net_getParam().
127 * Ugly, but only called once (for each sotype).
128 *
129 * As an optimization, we make a guess using the default values for Solaris
130 * assuming they haven't been modified with ndd.
131 */
132
133 #define MAX_TCP_GUESS 1024 * 1024
134 #define MAX_UDP_GUESS 2 * 1024 * 1024
135
136 #define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
137
138 static int findMaxBuf(int fd, int opt, int sotype) {
139 int a = 0;
140 int b = MAXINT;
141 int initial_guess;
142 int limit = -1;
143
144 if (sotype == SOCK_DGRAM) {
145 initial_guess = MAX_UDP_GUESS;
146 } else {
147 initial_guess = MAX_TCP_GUESS;
148 }
149
150 if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
151 initial_guess++;
152 if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
153 FAIL_IF_NOT_ENOBUFS;
154 return initial_guess - 1;
155 }
156 a = initial_guess;
157 } else {
158 FAIL_IF_NOT_ENOBUFS;
159 b = initial_guess - 1;
160 }
161 do {
162 int mid = a + (b-a)/2;
163 if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
164 limit = mid;
165 a = mid + 1;
166 } else {
167 FAIL_IF_NOT_ENOBUFS;
168 b = mid - 1;
169 }
170 } while (b >= a);
171
172 return limit;
173 }
174 #endif
175
176 void
177 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
178 const char *defaultDetail) {
179 JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
180 }
181
182 void
183 NET_ThrowCurrent(JNIEnv *env, char *msg) {
184 NET_ThrowNew(env, errno, msg);
185 }
186
187 void
188 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
189 char fullMsg[512];
190 if (!msg) {
191 msg = "no further information";
192 }
193 switch(errorNumber) {
194 case EBADF:
195 jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
266 */
267 #ifdef __linux__
268 {
269 FILE *fP = fopen("/proc/net/if_inet6", "r");
270 char buf[255];
271 char *bufP;
272
273 if (fP == NULL) {
274 close(fd);
275 return JNI_FALSE;
276 }
277 bufP = fgets(buf, sizeof(buf), fP);
278 fclose(fP);
279 if (bufP == NULL) {
280 close(fd);
281 return JNI_FALSE;
282 }
283 }
284 #endif
285
286 /**
287 * On Solaris 8 it's possible to create INET6 sockets even
288 * though IPv6 is not enabled on all interfaces. Thus we
289 * query the number of IPv6 addresses to verify that IPv6
290 * has been configured on at least one interface.
291 *
292 * On Linux it doesn't matter - if IPv6 is built-in the
293 * kernel then IPv6 addresses will be bound automatically
294 * to all interfaces.
295 */
296 #ifdef __solaris__
297
298 #ifdef SIOCGLIFNUM
299 {
300 struct lifnum numifs;
301
302 numifs.lifn_family = AF_INET6;
303 numifs.lifn_flags = 0;
304 if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
305 /**
306 * SIOCGLIFNUM failed - assume IPv6 not configured
307 */
308 close(fd);
309 return JNI_FALSE;
310 }
311 /**
312 * If no IPv6 addresses then return false. If count > 0
313 * it's possible that all IPv6 addresses are "down" but
314 * that's okay as they may be brought "up" while the
315 * VM is running.
316 */
317 if (numifs.lifn_count == 0) {
318 close(fd);
319 return JNI_FALSE;
320 }
321 }
322 #else
323 /* SIOCGLIFNUM not defined in build environment ??? */
324 close(fd);
325 return JNI_FALSE;
326 #endif
327
328 #endif /* __solaris */
329
330 /*
331 * OK we may have the stack available in the kernel,
332 * we should also check if the APIs are available.
333 */
334 ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
335 close(fd);
336 if (ipv6_fn == NULL ) {
337 return JNI_FALSE;
338 } else {
339 return JNI_TRUE;
340 }
341 }
342 #endif /* DONT_ENABLE_IPV6 */
343
344 jint reuseport_supported()
345 {
346 /* Do a simple dummy call, and try to figure out from that */
347 int one = 1;
348 int rv, s;
349 s = socket(PF_INET, SOCK_STREAM, 0);
386 }
387 free(buf);
388 }
389 }
390
391 #if defined(_AIX)
392
393 /* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */
394 extern void aix_close_init();
395
396 void platformInit () {
397 aix_close_init();
398 }
399
400 #else
401
402 void platformInit () {}
403
404 #endif
405
406 void parseExclusiveBindProperty(JNIEnv *env) {
407 #ifdef __solaris__
408 jstring s, flagSet;
409 jclass iCls;
410 jmethodID mid;
411
412 s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
413 CHECK_NULL(s);
414 iCls = (*env)->FindClass(env, "java/lang/System");
415 CHECK_NULL(iCls);
416 mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
417 "(Ljava/lang/String;)Ljava/lang/String;");
418 CHECK_NULL(mid);
419 flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
420 if (flagSet != NULL) {
421 useExclBind = 1;
422 }
423 #endif
424 }
425
426 JNIEXPORT jint JNICALL
427 NET_EnableFastTcpLoopback(int fd) {
428 return 0;
429 }
430
431 /**
432 * See net_util.h for documentation
433 */
434 JNIEXPORT int JNICALL
435 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
436 SOCKETADDRESS *sa, int *len,
437 jboolean v4MappedAddress)
438 {
439 jint family = getInetAddress_family(env, iaObj);
440 JNU_CHECK_EXCEPTION_RETURN(env, -1);
441 memset((char *)sa, 0, sizeof(SOCKETADDRESS));
442
443 if (ipv6_available() &&
444 !(family == java_net_InetAddress_IPv4 &&
445 v4MappedAddress == JNI_FALSE))
571 { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
572 { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
573 { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
574 };
575
576 int i;
577
578 if (ipv6_available()) {
579 switch (cmd) {
580 // Different multicast options if IPv6 is enabled
581 case java_net_SocketOptions_IP_MULTICAST_IF:
582 case java_net_SocketOptions_IP_MULTICAST_IF2:
583 *level = IPPROTO_IPV6;
584 *optname = IPV6_MULTICAST_IF;
585 return 0;
586
587 case java_net_SocketOptions_IP_MULTICAST_LOOP:
588 *level = IPPROTO_IPV6;
589 *optname = IPV6_MULTICAST_LOOP;
590 return 0;
591 #if (defined(__solaris__) || defined(MACOSX))
592 // Map IP_TOS request to IPV6_TCLASS
593 case java_net_SocketOptions_IP_TOS:
594 *level = IPPROTO_IPV6;
595 *optname = IPV6_TCLASS;
596 return 0;
597 #endif
598 }
599 }
600
601 /*
602 * Map the Java level option to the native level
603 */
604 for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
605 if (cmd == opts[i].cmd) {
606 *level = opts[i].level;
607 *optname = opts[i].optname;
608 return 0;
609 }
610 }
611
720 (void *)&optval, sizeof(optval)) < 0) {
721 return -1;
722 }
723 /*
724 * Let's also set the IPV6_TCLASS flag.
725 * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
726 * This helps in mixed environments where IPv4 and IPv6 sockets
727 * are connecting.
728 */
729 if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
730 arg, len) < 0) {
731 return -1;
732 }
733 }
734 #endif
735
736 iptos = (int *)arg;
737 *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
738 }
739
740 /*
741 * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
742 * the value when it exceeds the system limit.
743 */
744 #ifdef __solaris__
745 if (level == SOL_SOCKET) {
746 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
747 int sotype=0;
748 socklen_t arglen;
749 int *bufsize, maxbuf;
750 int ret;
751
752 /* Attempt with the original size */
753 ret = setsockopt(fd, level, opt, arg, len);
754 if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
755 return ret;
756
757 /* Exceeded system limit so clamp and retry */
758
759 arglen = sizeof(sotype);
760 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
761 &arglen) < 0) {
762 return -1;
763 }
764
765 /*
766 * We try to get tcp_maxbuf (and udp_max_buf) using
767 * an ioctl() that isn't available on all versions of Solaris.
768 * If that fails, we use the search algorithm in findMaxBuf()
769 */
770 if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
771 tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
772 if (tcp_max_buf == -1) {
773 tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
774 if (tcp_max_buf == -1) {
775 return -1;
776 }
777 }
778 init_tcp_max_buf = 1;
779 } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
780 udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
781 if (udp_max_buf == -1) {
782 udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
783 if (udp_max_buf == -1) {
784 return -1;
785 }
786 }
787 init_udp_max_buf = 1;
788 }
789
790 maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
791 bufsize = (int *)arg;
792 if (*bufsize > maxbuf) {
793 *bufsize = maxbuf;
794 }
795 }
796 }
797 #endif
798
799 #ifdef _AIX
800 if (level == SOL_SOCKET) {
801 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
802 /*
803 * Just try to set the requested size. If it fails we will leave the
804 * socket option as is. Setting the buffer size means only a hint in
805 * the jse2/java software layer, see javadoc. In the previous
806 * solution the buffer has always been truncated to a length of
807 * 0x100000 Byte, even if the technical limit has not been reached.
808 * This kind of absolute truncation was unexpected in the jck tests.
809 */
810 int ret = setsockopt(fd, level, opt, arg, len);
811 if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {
812 // Accept failure because of insufficient buffer memory resources.
813 return 0;
814 } else {
815 // Deliver all other kinds of errors.
816 return ret;
817 }
818 }
891 arglen = sizeof(sotype);
892 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
893 return -1;
894 }
895
896 if (sotype == SOCK_DGRAM) {
897 setsockopt(fd, level, SO_REUSEPORT, arg, len);
898 }
899 }
900 #endif
901
902 return setsockopt(fd, level, opt, arg, len);
903 }
904
905 /*
906 * Wrapper for bind system call - performs any necessary pre/post
907 * processing to deal with OS specific issues :-
908 *
909 * Linux allows a socket to bind to 127.0.0.255 which must be
910 * caught.
911 *
912 * On Solaris with IPv6 enabled we must use an exclusive
913 * bind to guarantee a unique port number across the IPv4 and
914 * IPv6 port spaces.
915 *
916 */
917 int
918 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
919 {
920 #if defined(__solaris__)
921 int level = -1;
922 int exclbind = -1;
923 #endif
924 int rv;
925 int arg, alen;
926
927 #ifdef __linux__
928 /*
929 * ## get bugId for this issue - goes back to 1.2.2 port ##
930 * ## When IPv6 is enabled this will be an IPv4-mapped
931 * ## with family set to AF_INET6
932 */
933 if (sa->sa.sa_family == AF_INET) {
934 if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
935 errno = EADDRNOTAVAIL;
936 return -1;
937 }
938 }
939 #endif
940
941 #if defined(__solaris__)
942 /*
943 * Solaris has separate IPv4 and IPv6 port spaces so we
944 * use an exclusive bind when SO_REUSEADDR is not used to
945 * give the illusion of a unified port space.
946 * This also avoids problems with IPv6 sockets connecting
947 * to IPv4 mapped addresses whereby the socket conversion
948 * results in a late bind that fails because the
949 * corresponding IPv4 port is in use.
950 */
951 alen = sizeof(arg);
952
953 if (useExclBind ||
954 getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
955 {
956 if (useExclBind || arg == 0) {
957 /*
958 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
959 * property is true so enable TCP_EXCLBIND or
960 * UDP_EXCLBIND
961 */
962 alen = sizeof(arg);
963 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
964 {
965 if (arg == SOCK_STREAM) {
966 level = IPPROTO_TCP;
967 exclbind = TCP_EXCLBIND;
968 } else {
969 level = IPPROTO_UDP;
970 exclbind = UDP_EXCLBIND;
971 }
972 }
973
974 arg = 1;
975 setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
976 }
977 }
978
979 #endif
980
981 rv = bind(fd, &sa->sa, len);
982
983 #if defined(__solaris__)
984 if (rv < 0) {
985 int en = errno;
986 /* Restore *_EXCLBIND if the bind fails */
987 if (exclbind != -1) {
988 int arg = 0;
989 setsockopt(fd, level, exclbind, (char *)&arg,
990 sizeof(arg));
991 }
992 errno = en;
993 }
994 #endif
995
996 return rv;
997 }
998
999 /**
1000 * Wrapper for poll with timeout on a single file descriptor.
1001 *
1002 * flags (defined in net_util_md.h can be any combination of
1003 * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
1004 *
1005 * The function will return when either the socket is ready for one
1006 * of the specified operations or the timeout expired.
1007 *
1008 * It returns the time left from the timeout (possibly 0), or -1 if it expired.
1009 */
1010
1011 jint
1012 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
1013 {
1014 jlong prevNanoTime = JVM_NanoTime(env, 0);
|
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
23 * questions.
24 */
25 #include <dlfcn.h>
26 #include <errno.h>
27 #include <net/if.h>
28 #include <netinet/tcp.h> // defines TCP_NODELAY
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <sys/time.h>
33
34 #if defined(__linux__)
35 #include <arpa/inet.h>
36 #include <net/route.h>
37 #include <sys/utsname.h>
38 #endif
39
40 #if defined(MACOSX)
41 #include <sys/sysctl.h>
42 #endif
43
44 #include "jvm.h"
45 #include "net_util.h"
46
47 #include "java_net_SocketOptions.h"
48 #include "java_net_InetAddress.h"
49
50 #if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
51 #define IPV6_FLOWINFO_SEND 33
52 #endif
53
54 #define RESTARTABLE(_cmd, _result) do { \
55 do { \
56 _result = _cmd; \
57 } while((_result == -1) && (errno == EINTR)); \
58 } while(0)
59
60 int NET_SocketAvailable(int s, int *pbytes) {
61 int result;
62 RESTARTABLE(ioctl(s, FIONREAD, pbytes), result);
63 return result;
64 }
65
66 void
67 NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
68 const char *defaultDetail) {
69 JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
70 }
71
72 void
73 NET_ThrowCurrent(JNIEnv *env, char *msg) {
74 NET_ThrowNew(env, errno, msg);
75 }
76
77 void
78 NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
79 char fullMsg[512];
80 if (!msg) {
81 msg = "no further information";
82 }
83 switch(errorNumber) {
84 case EBADF:
85 jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
156 */
157 #ifdef __linux__
158 {
159 FILE *fP = fopen("/proc/net/if_inet6", "r");
160 char buf[255];
161 char *bufP;
162
163 if (fP == NULL) {
164 close(fd);
165 return JNI_FALSE;
166 }
167 bufP = fgets(buf, sizeof(buf), fP);
168 fclose(fP);
169 if (bufP == NULL) {
170 close(fd);
171 return JNI_FALSE;
172 }
173 }
174 #endif
175
176 /*
177 * OK we may have the stack available in the kernel,
178 * we should also check if the APIs are available.
179 */
180 ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
181 close(fd);
182 if (ipv6_fn == NULL ) {
183 return JNI_FALSE;
184 } else {
185 return JNI_TRUE;
186 }
187 }
188 #endif /* DONT_ENABLE_IPV6 */
189
190 jint reuseport_supported()
191 {
192 /* Do a simple dummy call, and try to figure out from that */
193 int one = 1;
194 int rv, s;
195 s = socket(PF_INET, SOCK_STREAM, 0);
232 }
233 free(buf);
234 }
235 }
236
237 #if defined(_AIX)
238
239 /* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */
240 extern void aix_close_init();
241
242 void platformInit () {
243 aix_close_init();
244 }
245
246 #else
247
248 void platformInit () {}
249
250 #endif
251
252 JNIEXPORT jint JNICALL
253 NET_EnableFastTcpLoopback(int fd) {
254 return 0;
255 }
256
257 /**
258 * See net_util.h for documentation
259 */
260 JNIEXPORT int JNICALL
261 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
262 SOCKETADDRESS *sa, int *len,
263 jboolean v4MappedAddress)
264 {
265 jint family = getInetAddress_family(env, iaObj);
266 JNU_CHECK_EXCEPTION_RETURN(env, -1);
267 memset((char *)sa, 0, sizeof(SOCKETADDRESS));
268
269 if (ipv6_available() &&
270 !(family == java_net_InetAddress_IPv4 &&
271 v4MappedAddress == JNI_FALSE))
397 { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
398 { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
399 { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
400 };
401
402 int i;
403
404 if (ipv6_available()) {
405 switch (cmd) {
406 // Different multicast options if IPv6 is enabled
407 case java_net_SocketOptions_IP_MULTICAST_IF:
408 case java_net_SocketOptions_IP_MULTICAST_IF2:
409 *level = IPPROTO_IPV6;
410 *optname = IPV6_MULTICAST_IF;
411 return 0;
412
413 case java_net_SocketOptions_IP_MULTICAST_LOOP:
414 *level = IPPROTO_IPV6;
415 *optname = IPV6_MULTICAST_LOOP;
416 return 0;
417 #if defined(MACOSX)
418 // Map IP_TOS request to IPV6_TCLASS
419 case java_net_SocketOptions_IP_TOS:
420 *level = IPPROTO_IPV6;
421 *optname = IPV6_TCLASS;
422 return 0;
423 #endif
424 }
425 }
426
427 /*
428 * Map the Java level option to the native level
429 */
430 for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
431 if (cmd == opts[i].cmd) {
432 *level = opts[i].level;
433 *optname = opts[i].optname;
434 return 0;
435 }
436 }
437
546 (void *)&optval, sizeof(optval)) < 0) {
547 return -1;
548 }
549 /*
550 * Let's also set the IPV6_TCLASS flag.
551 * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
552 * This helps in mixed environments where IPv4 and IPv6 sockets
553 * are connecting.
554 */
555 if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
556 arg, len) < 0) {
557 return -1;
558 }
559 }
560 #endif
561
562 iptos = (int *)arg;
563 *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
564 }
565
566 #ifdef _AIX
567 if (level == SOL_SOCKET) {
568 if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
569 /*
570 * Just try to set the requested size. If it fails we will leave the
571 * socket option as is. Setting the buffer size means only a hint in
572 * the jse2/java software layer, see javadoc. In the previous
573 * solution the buffer has always been truncated to a length of
574 * 0x100000 Byte, even if the technical limit has not been reached.
575 * This kind of absolute truncation was unexpected in the jck tests.
576 */
577 int ret = setsockopt(fd, level, opt, arg, len);
578 if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {
579 // Accept failure because of insufficient buffer memory resources.
580 return 0;
581 } else {
582 // Deliver all other kinds of errors.
583 return ret;
584 }
585 }
658 arglen = sizeof(sotype);
659 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
660 return -1;
661 }
662
663 if (sotype == SOCK_DGRAM) {
664 setsockopt(fd, level, SO_REUSEPORT, arg, len);
665 }
666 }
667 #endif
668
669 return setsockopt(fd, level, opt, arg, len);
670 }
671
672 /*
673 * Wrapper for bind system call - performs any necessary pre/post
674 * processing to deal with OS specific issues :-
675 *
676 * Linux allows a socket to bind to 127.0.0.255 which must be
677 * caught.
678 */
679 int
680 NET_Bind(int fd, SOCKETADDRESS *sa, int len)
681 {
682 int rv;
683 int arg, alen;
684
685 #ifdef __linux__
686 /*
687 * ## get bugId for this issue - goes back to 1.2.2 port ##
688 * ## When IPv6 is enabled this will be an IPv4-mapped
689 * ## with family set to AF_INET6
690 */
691 if (sa->sa.sa_family == AF_INET) {
692 if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
693 errno = EADDRNOTAVAIL;
694 return -1;
695 }
696 }
697 #endif
698
699 rv = bind(fd, &sa->sa, len);
700
701 return rv;
702 }
703
704 /**
705 * Wrapper for poll with timeout on a single file descriptor.
706 *
707 * flags (defined in net_util_md.h can be any combination of
708 * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
709 *
710 * The function will return when either the socket is ready for one
711 * of the specified operations or the timeout expired.
712 *
713 * It returns the time left from the timeout (possibly 0), or -1 if it expired.
714 */
715
716 jint
717 NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
718 {
719 jlong prevNanoTime = JVM_NanoTime(env, 0);
|