Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/nio/ch/Net.c
32288 views
1
/*
2
* Copyright (c) 2001, 2013, 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
23
* questions.
24
*/
25
26
#include <sys/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
33
#include "jni.h"
34
#include "jni_util.h"
35
#include "jvm.h"
36
#include "jlong.h"
37
#include "sun_nio_ch_Net.h"
38
#include "net_util.h"
39
#include "net_util_md.h"
40
#include "nio_util.h"
41
#include "nio.h"
42
#include "sun_nio_ch_PollArrayWrapper.h"
43
44
#ifdef _AIX
45
#include <sys/utsname.h>
46
#endif
47
48
/**
49
* IP_MULTICAST_ALL supported since 2.6.31 but may not be available at
50
* build time.
51
*/
52
#ifdef __linux__
53
#ifndef IP_MULTICAST_ALL
54
#define IP_MULTICAST_ALL 49
55
#endif
56
#endif
57
58
#if defined(_ALLBSD_SOURCE) || defined(_AIX) || defined(__ANDROID__)
59
60
#ifndef IP_BLOCK_SOURCE
61
62
#if defined(_AIX)
63
64
#define IP_BLOCK_SOURCE 58 /* Block data from a given source to a given group */
65
#define IP_UNBLOCK_SOURCE 59 /* Unblock data from a given source to a given group */
66
#define IP_ADD_SOURCE_MEMBERSHIP 60 /* Join a source-specific group */
67
#define IP_DROP_SOURCE_MEMBERSHIP 61 /* Leave a source-specific group */
68
69
#else
70
71
#define IP_ADD_SOURCE_MEMBERSHIP 70 /* join a source-specific group */
72
#define IP_DROP_SOURCE_MEMBERSHIP 71 /* drop a single source */
73
#define IP_BLOCK_SOURCE 72 /* block a source */
74
#define IP_UNBLOCK_SOURCE 73 /* unblock a source */
75
76
#endif /* _AIX */
77
78
#endif /* IP_BLOCK_SOURCE */
79
80
#ifndef MCAST_BLOCK_SOURCE
81
82
#if defined(_AIX)
83
84
#define MCAST_BLOCK_SOURCE 64
85
#define MCAST_UNBLOCK_SOURCE 65
86
#define MCAST_JOIN_SOURCE_GROUP 66
87
#define MCAST_LEAVE_SOURCE_GROUP 67
88
89
#else
90
91
#define MCAST_JOIN_SOURCE_GROUP 82 /* join a source-specific group */
92
#define MCAST_LEAVE_SOURCE_GROUP 83 /* leave a single source */
93
#define MCAST_BLOCK_SOURCE 84 /* block a source */
94
#define MCAST_UNBLOCK_SOURCE 85 /* unblock a source */
95
96
#endif /* _AIX */
97
98
#endif /* MCAST_BLOCK_SOURCE */
99
100
#ifndef IPV6_ADD_MEMBERSHIP
101
102
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
103
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
104
105
#endif /* IPV6_ADD_MEMBERSHIP */
106
107
#if defined(_AIX)
108
109
struct my_ip_mreq_source {
110
struct in_addr imr_multiaddr;
111
struct in_addr imr_sourceaddr;
112
struct in_addr imr_interface;
113
};
114
115
#else
116
117
struct my_ip_mreq_source {
118
struct in_addr imr_multiaddr;
119
struct in_addr imr_interface;
120
struct in_addr imr_sourceaddr;
121
};
122
123
#endif /* _AIX */
124
125
struct my_group_source_req {
126
uint32_t gsr_interface; /* interface index */
127
struct sockaddr_storage gsr_group; /* group address */
128
struct sockaddr_storage gsr_source; /* source address */
129
};
130
131
#else /* _ALLBSD_SOURCE */
132
133
#define my_ip_mreq_source ip_mreq_source
134
#define my_group_source_req group_source_req
135
136
#endif
137
138
139
#define COPY_INET6_ADDRESS(env, source, target) \
140
(*env)->GetByteArrayRegion(env, source, 0, 16, target)
141
142
/*
143
* Copy IPv6 group, interface index, and IPv6 source address
144
* into group_source_req structure.
145
*/
146
#ifdef AF_INET6
147
static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
148
jbyteArray source, struct my_group_source_req* req)
149
{
150
struct sockaddr_in6* sin6;
151
152
req->gsr_interface = (uint32_t)index;
153
154
sin6 = (struct sockaddr_in6*)&(req->gsr_group);
155
sin6->sin6_family = AF_INET6;
156
COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
157
158
sin6 = (struct sockaddr_in6*)&(req->gsr_source);
159
sin6->sin6_family = AF_INET6;
160
COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
161
}
162
#endif
163
164
#ifdef _AIX
165
166
/*
167
* Checks whether or not "socket extensions for multicast source filters" is supported.
168
* Returns JNI_TRUE if it is supported, JNI_FALSE otherwise
169
*/
170
static jboolean isSourceFilterSupported(){
171
static jboolean alreadyChecked = JNI_FALSE;
172
static jboolean result = JNI_TRUE;
173
if (alreadyChecked != JNI_TRUE){
174
struct utsname uts;
175
memset(&uts, 0, sizeof(uts));
176
strcpy(uts.sysname, "?");
177
const int utsRes = uname(&uts);
178
int major = -1;
179
int minor = -1;
180
major = atoi(uts.version);
181
minor = atoi(uts.release);
182
if (strcmp(uts.sysname, "AIX") == 0) {
183
if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1
184
result = JNI_FALSE;
185
}
186
}
187
alreadyChecked = JNI_TRUE;
188
}
189
return result;
190
}
191
192
#endif /* _AIX */
193
194
JNIEXPORT void JNICALL
195
Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
196
{
197
/* Here because Windows native code does need to init IDs */
198
}
199
200
JNIEXPORT jboolean JNICALL
201
Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
202
{
203
return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
204
}
205
206
JNIEXPORT jint JNICALL
207
Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
208
return -1;
209
}
210
211
JNIEXPORT jboolean JNICALL
212
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
213
{
214
#if defined(MACOSX) || defined(_AIX)
215
/* for now IPv6 sockets cannot join IPv4 multicast groups */
216
return JNI_FALSE;
217
#else
218
return JNI_TRUE;
219
#endif
220
}
221
222
JNIEXPORT jboolean JNICALL
223
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
224
{
225
#ifdef __solaris__
226
return JNI_TRUE;
227
#else
228
return JNI_FALSE;
229
#endif
230
}
231
232
JNIEXPORT int JNICALL
233
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
234
jboolean stream, jboolean reuse, jboolean ignored)
235
{
236
int fd;
237
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
238
#ifdef AF_INET6
239
int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
240
#else
241
int domain = AF_INET;
242
#endif
243
244
fd = socket(domain, type, 0);
245
if (fd < 0) {
246
return handleSocketError(env, errno);
247
}
248
249
#ifdef AF_INET6
250
/* Disable IPV6_V6ONLY to ensure dual-socket support */
251
if (domain == AF_INET6) {
252
int arg = 0;
253
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
254
sizeof(int)) < 0) {
255
JNU_ThrowByNameWithLastError(env,
256
JNU_JAVANETPKG "SocketException",
257
"Unable to set IPV6_V6ONLY");
258
close(fd);
259
return -1;
260
}
261
}
262
#endif
263
264
if (reuse) {
265
int arg = 1;
266
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
267
sizeof(arg)) < 0) {
268
JNU_ThrowByNameWithLastError(env,
269
JNU_JAVANETPKG "SocketException",
270
"Unable to set SO_REUSEADDR");
271
close(fd);
272
return -1;
273
}
274
}
275
276
#if defined(__linux__)
277
if (type == SOCK_DGRAM) {
278
int arg = 0;
279
int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
280
if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
281
(errno != ENOPROTOOPT)) {
282
JNU_ThrowByNameWithLastError(env,
283
JNU_JAVANETPKG "SocketException",
284
"Unable to set IP_MULTICAST_ALL");
285
close(fd);
286
return -1;
287
}
288
}
289
#endif
290
291
#if defined(__linux__) && defined(AF_INET6)
292
/* By default, Linux uses the route default */
293
if (domain == AF_INET6 && type == SOCK_DGRAM) {
294
int arg = 1;
295
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
296
sizeof(arg)) < 0) {
297
JNU_ThrowByNameWithLastError(env,
298
JNU_JAVANETPKG "SocketException",
299
"Unable to set IPV6_MULTICAST_HOPS");
300
close(fd);
301
return -1;
302
}
303
}
304
#endif
305
return fd;
306
}
307
308
JNIEXPORT void JNICALL
309
Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6,
310
jboolean useExclBind, jobject iao, int port)
311
{
312
SOCKADDR sa;
313
int sa_len = SOCKADDR_LEN;
314
int rv = 0;
315
316
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
317
return;
318
}
319
320
rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
321
if (rv != 0) {
322
handleSocketError(env, errno);
323
}
324
}
325
326
JNIEXPORT void JNICALL
327
Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
328
{
329
if (listen(fdval(env, fdo), backlog) < 0)
330
handleSocketError(env, errno);
331
}
332
333
JNIEXPORT jint JNICALL
334
Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
335
jobject fdo, jobject iao, jint port)
336
{
337
SOCKADDR sa;
338
int sa_len = SOCKADDR_LEN;
339
int rv;
340
341
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
342
&sa_len, preferIPv6) != 0)
343
{
344
return IOS_THROWN;
345
}
346
347
rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
348
if (rv != 0) {
349
if (errno == EINPROGRESS) {
350
return IOS_UNAVAILABLE;
351
} else if (errno == EINTR) {
352
return IOS_INTERRUPTED;
353
}
354
return handleSocketError(env, errno);
355
}
356
return 1;
357
}
358
359
JNIEXPORT jint JNICALL
360
Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
361
{
362
SOCKADDR sa;
363
socklen_t sa_len = SOCKADDR_LEN;
364
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
365
#ifdef _ALLBSD_SOURCE
366
/*
367
* XXXBSD:
368
* ECONNRESET is specific to the BSDs. We can not return an error,
369
* as the calling Java code with raise a java.lang.Error given the expectation
370
* that getsockname() will never fail. According to the Single UNIX Specification,
371
* it shouldn't fail. As such, we just fill in generic Linux-compatible values.
372
*/
373
if (errno == ECONNRESET) {
374
struct sockaddr_in *sin;
375
sin = (struct sockaddr_in *) &sa;
376
bzero(sin, sizeof(*sin));
377
sin->sin_len = sizeof(struct sockaddr_in);
378
sin->sin_family = AF_INET;
379
sin->sin_port = htonl(0);
380
sin->sin_addr.s_addr = INADDR_ANY;
381
} else {
382
handleSocketError(env, errno);
383
return -1;
384
}
385
#else /* _ALLBSD_SOURCE */
386
handleSocketError(env, errno);
387
return -1;
388
#endif /* _ALLBSD_SOURCE */
389
}
390
return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
391
}
392
393
JNIEXPORT jobject JNICALL
394
Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
395
{
396
SOCKADDR sa;
397
socklen_t sa_len = SOCKADDR_LEN;
398
int port;
399
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
400
#ifdef _ALLBSD_SOURCE
401
/*
402
* XXXBSD:
403
* ECONNRESET is specific to the BSDs. We can not return an error,
404
* as the calling Java code with raise a java.lang.Error with the expectation
405
* that getsockname() will never fail. According to the Single UNIX Specification,
406
* it shouldn't fail. As such, we just fill in generic Linux-compatible values.
407
*/
408
if (errno == ECONNRESET) {
409
struct sockaddr_in *sin;
410
sin = (struct sockaddr_in *) &sa;
411
bzero(sin, sizeof(*sin));
412
sin->sin_len = sizeof(struct sockaddr_in);
413
sin->sin_family = AF_INET;
414
sin->sin_port = htonl(0);
415
sin->sin_addr.s_addr = INADDR_ANY;
416
} else {
417
handleSocketError(env, errno);
418
return NULL;
419
}
420
#else /* _ALLBSD_SOURCE */
421
handleSocketError(env, errno);
422
return NULL;
423
#endif /* _ALLBSD_SOURCE */
424
}
425
return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
426
}
427
428
JNIEXPORT jint JNICALL
429
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
430
jboolean mayNeedConversion, jint level, jint opt)
431
{
432
int result;
433
struct linger linger;
434
u_char carg;
435
void *arg;
436
socklen_t arglen;
437
int n;
438
439
/* Option value is an int except for a few specific cases */
440
441
arg = (void *)&result;
442
arglen = sizeof(result);
443
444
if (level == IPPROTO_IP &&
445
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
446
arg = (void*)&carg;
447
arglen = sizeof(carg);
448
}
449
450
if (level == SOL_SOCKET && opt == SO_LINGER) {
451
arg = (void *)&linger;
452
arglen = sizeof(linger);
453
}
454
455
if (mayNeedConversion) {
456
n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen);
457
} else {
458
n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
459
}
460
if (n < 0) {
461
JNU_ThrowByNameWithLastError(env,
462
JNU_JAVANETPKG "SocketException",
463
"sun.nio.ch.Net.getIntOption");
464
return -1;
465
}
466
467
if (level == IPPROTO_IP &&
468
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
469
{
470
return (jint)carg;
471
}
472
473
if (level == SOL_SOCKET && opt == SO_LINGER)
474
return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
475
476
return (jint)result;
477
}
478
479
JNIEXPORT void JNICALL
480
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
481
jboolean mayNeedConversion, jint level,
482
jint opt, jint arg, jboolean isIPv6)
483
{
484
int result;
485
struct linger linger;
486
u_char carg;
487
void *parg;
488
socklen_t arglen;
489
int n;
490
491
/* Option value is an int except for a few specific cases */
492
493
parg = (void*)&arg;
494
arglen = sizeof(arg);
495
496
if (level == IPPROTO_IP &&
497
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
498
parg = (void*)&carg;
499
arglen = sizeof(carg);
500
carg = (u_char)arg;
501
}
502
503
if (level == SOL_SOCKET && opt == SO_LINGER) {
504
parg = (void *)&linger;
505
arglen = sizeof(linger);
506
if (arg >= 0) {
507
linger.l_onoff = 1;
508
linger.l_linger = arg;
509
} else {
510
linger.l_onoff = 0;
511
linger.l_linger = 0;
512
}
513
}
514
515
if (mayNeedConversion) {
516
n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
517
} else {
518
n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
519
}
520
if (n < 0) {
521
JNU_ThrowByNameWithLastError(env,
522
JNU_JAVANETPKG "SocketException",
523
"sun.nio.ch.Net.setIntOption");
524
}
525
#ifdef __linux__
526
if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS && isIPv6) {
527
// set the V4 option also
528
setsockopt(fdval(env, fdo), IPPROTO_IP, IP_TOS, parg, arglen);
529
}
530
#endif
531
}
532
533
JNIEXPORT jint JNICALL
534
Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
535
jint group, jint interf, jint source)
536
{
537
struct ip_mreq mreq;
538
struct my_ip_mreq_source mreq_source;
539
int opt, n, optlen;
540
void* optval;
541
542
if (source == 0) {
543
mreq.imr_multiaddr.s_addr = htonl(group);
544
mreq.imr_interface.s_addr = htonl(interf);
545
opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
546
optval = (void*)&mreq;
547
optlen = sizeof(mreq);
548
} else {
549
#ifdef MACOSX
550
/* no IPv4 include-mode filtering for now */
551
return IOS_UNAVAILABLE;
552
#else
553
554
#ifdef _AIX
555
/* check AIX for support of source filtering */
556
if (isSourceFilterSupported() != JNI_TRUE){
557
return IOS_UNAVAILABLE;
558
}
559
#endif
560
561
mreq_source.imr_multiaddr.s_addr = htonl(group);
562
mreq_source.imr_sourceaddr.s_addr = htonl(source);
563
mreq_source.imr_interface.s_addr = htonl(interf);
564
opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
565
optval = (void*)&mreq_source;
566
optlen = sizeof(mreq_source);
567
#endif
568
}
569
570
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
571
if (n < 0) {
572
if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
573
return IOS_UNAVAILABLE;
574
handleSocketError(env, errno);
575
}
576
return 0;
577
}
578
579
JNIEXPORT jint JNICALL
580
Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
581
jint group, jint interf, jint source)
582
{
583
#ifdef MACOSX
584
/* no IPv4 exclude-mode filtering for now */
585
return IOS_UNAVAILABLE;
586
#else
587
struct my_ip_mreq_source mreq_source;
588
int n;
589
int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
590
591
#ifdef _AIX
592
/* check AIX for support of source filtering */
593
if (isSourceFilterSupported() != JNI_TRUE){
594
return IOS_UNAVAILABLE;
595
}
596
#endif
597
598
mreq_source.imr_multiaddr.s_addr = htonl(group);
599
mreq_source.imr_sourceaddr.s_addr = htonl(source);
600
mreq_source.imr_interface.s_addr = htonl(interf);
601
602
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
603
(void*)&mreq_source, sizeof(mreq_source));
604
if (n < 0) {
605
if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
606
return IOS_UNAVAILABLE;
607
handleSocketError(env, errno);
608
}
609
return 0;
610
#endif
611
}
612
613
JNIEXPORT jint JNICALL
614
Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
615
jbyteArray group, jint index, jbyteArray source)
616
{
617
#ifdef AF_INET6
618
struct ipv6_mreq mreq6;
619
struct my_group_source_req req;
620
int opt, n, optlen;
621
void* optval;
622
623
if (source == NULL) {
624
COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
625
mreq6.ipv6mr_interface = (int)index;
626
opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
627
optval = (void*)&mreq6;
628
optlen = sizeof(mreq6);
629
} else {
630
#ifdef MACOSX
631
/* no IPv6 include-mode filtering for now */
632
return IOS_UNAVAILABLE;
633
#else
634
initGroupSourceReq(env, group, index, source, &req);
635
opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
636
optval = (void*)&req;
637
optlen = sizeof(req);
638
#endif
639
}
640
641
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
642
if (n < 0) {
643
if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
644
return IOS_UNAVAILABLE;
645
handleSocketError(env, errno);
646
}
647
return 0;
648
#else
649
JNU_ThrowInternalError(env, "Should not get here");
650
return IOS_THROWN;
651
#endif /* AF_INET6 */
652
}
653
654
JNIEXPORT jint JNICALL
655
Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
656
jbyteArray group, jint index, jbyteArray source)
657
{
658
#ifdef AF_INET6
659
#ifdef MACOSX
660
/* no IPv6 exclude-mode filtering for now */
661
return IOS_UNAVAILABLE;
662
#else
663
struct my_group_source_req req;
664
int n;
665
int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
666
667
initGroupSourceReq(env, group, index, source, &req);
668
669
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
670
(void*)&req, sizeof(req));
671
if (n < 0) {
672
if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP))
673
return IOS_UNAVAILABLE;
674
handleSocketError(env, errno);
675
}
676
return 0;
677
#endif
678
#else
679
JNU_ThrowInternalError(env, "Should not get here");
680
return IOS_THROWN;
681
#endif
682
}
683
684
JNIEXPORT void JNICALL
685
Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
686
{
687
struct in_addr in;
688
socklen_t arglen = sizeof(struct in_addr);
689
int n;
690
691
in.s_addr = htonl(interf);
692
693
n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
694
(void*)&(in.s_addr), arglen);
695
if (n < 0) {
696
handleSocketError(env, errno);
697
}
698
}
699
700
JNIEXPORT jint JNICALL
701
Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
702
{
703
struct in_addr in;
704
socklen_t arglen = sizeof(struct in_addr);
705
int n;
706
707
n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
708
if (n < 0) {
709
handleSocketError(env, errno);
710
return -1;
711
}
712
return ntohl(in.s_addr);
713
}
714
715
JNIEXPORT void JNICALL
716
Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
717
{
718
int value = (jint)index;
719
socklen_t arglen = sizeof(value);
720
int n;
721
722
n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
723
(void*)&(index), arglen);
724
if (n < 0) {
725
handleSocketError(env, errno);
726
}
727
}
728
729
JNIEXPORT jint JNICALL
730
Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
731
{
732
int index;
733
socklen_t arglen = sizeof(index);
734
int n;
735
736
n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
737
if (n < 0) {
738
handleSocketError(env, errno);
739
return -1;
740
}
741
return (jint)index;
742
}
743
744
JNIEXPORT void JNICALL
745
Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
746
{
747
int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
748
(jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
749
if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN))
750
handleSocketError(env, errno);
751
}
752
753
JNIEXPORT jint JNICALL
754
Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlong timeout)
755
{
756
struct pollfd pfd;
757
int rv;
758
pfd.fd = fdval(env, fdo);
759
pfd.events = events;
760
rv = poll(&pfd, 1, timeout);
761
762
if (rv >= 0) {
763
return pfd.revents;
764
} else if (errno == EINTR) {
765
return IOS_INTERRUPTED;
766
} else {
767
handleSocketError(env, errno);
768
return IOS_THROWN;
769
}
770
}
771
772
JNIEXPORT jshort JNICALL
773
Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this)
774
{
775
return (jshort)POLLIN;
776
}
777
778
JNIEXPORT jshort JNICALL
779
Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this)
780
{
781
return (jshort)POLLOUT;
782
}
783
784
JNIEXPORT jshort JNICALL
785
Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this)
786
{
787
return (jshort)POLLERR;
788
}
789
790
JNIEXPORT jshort JNICALL
791
Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this)
792
{
793
return (jshort)POLLHUP;
794
}
795
796
JNIEXPORT jshort JNICALL
797
Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)
798
{
799
return (jshort)POLLNVAL;
800
}
801
802
JNIEXPORT jshort JNICALL
803
Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)
804
{
805
return (jshort)POLLOUT;
806
}
807
808
809
/* Declared in nio_util.h */
810
811
jint
812
handleSocketError(JNIEnv *env, jint errorValue)
813
{
814
char *xn;
815
switch (errorValue) {
816
case EINPROGRESS: /* Non-blocking connect */
817
return 0;
818
#ifdef EPROTO
819
case EPROTO:
820
xn = JNU_JAVANETPKG "ProtocolException";
821
break;
822
#endif
823
case ECONNREFUSED:
824
xn = JNU_JAVANETPKG "ConnectException";
825
break;
826
case ETIMEDOUT:
827
xn = JNU_JAVANETPKG "ConnectException";
828
break;
829
case EHOSTUNREACH:
830
xn = JNU_JAVANETPKG "NoRouteToHostException";
831
break;
832
case EADDRINUSE: /* Fall through */
833
case EADDRNOTAVAIL:
834
xn = JNU_JAVANETPKG "BindException";
835
break;
836
default:
837
xn = JNU_JAVANETPKG "SocketException";
838
break;
839
}
840
errno = errorValue;
841
JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
842
return IOS_THROWN;
843
}
844
845