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/java/net/net_util_md.c
32287 views
1
/*
2
* Copyright (c) 1997, 2018, 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 <errno.h>
27
#include <string.h>
28
#include <sys/types.h>
29
#include <sys/socket.h>
30
#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
31
#include <netinet/in.h>
32
#include <net/if.h>
33
#include <netdb.h>
34
#include <stdlib.h>
35
#include <dlfcn.h>
36
#include <sys/time.h>
37
38
#ifndef _ALLBSD_SOURCE
39
# ifndef __ANDROID__
40
# include <values.h>
41
# else
42
# include "values.h"
43
# endif
44
#else
45
#include <limits.h>
46
#include <sys/param.h>
47
#include <sys/sysctl.h>
48
#ifndef MAXINT
49
#define MAXINT INT_MAX
50
#endif
51
#endif
52
53
#ifdef __solaris__
54
#include <sys/sockio.h>
55
#include <stropts.h>
56
#include <inet/nd.h>
57
#endif
58
59
#if defined(__linux__) || defined(__ANDROID__)
60
#include <arpa/inet.h>
61
#include <net/route.h>
62
#include <sys/utsname.h>
63
64
#ifndef IPV6_FLOWINFO_SEND
65
#define IPV6_FLOWINFO_SEND 33
66
#endif
67
68
#endif
69
70
#include "jni_util.h"
71
#include "jvm.h"
72
#include "net_util.h"
73
74
#include "java_net_SocketOptions.h"
75
76
/*
77
* EXCLBIND socket options only on Solaris
78
*/
79
#if defined(__solaris__) && !defined(TCP_EXCLBIND)
80
#define TCP_EXCLBIND 0x21
81
#endif
82
#if defined(__solaris__) && !defined(UDP_EXCLBIND)
83
#define UDP_EXCLBIND 0x0101
84
#endif
85
86
void setDefaultScopeID(JNIEnv *env, struct sockaddr *him)
87
{
88
#ifdef MACOSX
89
static jclass ni_class = NULL;
90
static jfieldID ni_defaultIndexID;
91
if (ni_class == NULL) {
92
jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
93
CHECK_NULL(c);
94
c = (*env)->NewGlobalRef(env, c);
95
CHECK_NULL(c);
96
ni_defaultIndexID = (*env)->GetStaticFieldID(
97
env, c, "defaultIndex", "I");
98
CHECK_NULL(ni_defaultIndexID);
99
ni_class = c;
100
}
101
int defaultIndex;
102
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him;
103
if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0) &&
104
(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
105
IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
106
defaultIndex = (*env)->GetStaticIntField(env, ni_class,
107
ni_defaultIndexID);
108
sin6->sin6_scope_id = defaultIndex;
109
}
110
#endif
111
}
112
113
int getDefaultScopeID(JNIEnv *env) {
114
static jclass ni_class = NULL;
115
static jfieldID ni_defaultIndexID;
116
int defaultIndex = 0;
117
118
if (ni_class == NULL) {
119
jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
120
CHECK_NULL_RETURN(c, 0);
121
c = (*env)->NewGlobalRef(env, c);
122
CHECK_NULL_RETURN(c, 0);
123
ni_defaultIndexID = (*env)->GetStaticFieldID(env, c,
124
"defaultIndex", "I");
125
CHECK_NULL_RETURN(ni_defaultIndexID, 0);
126
ni_class = c;
127
}
128
defaultIndex = (*env)->GetStaticIntField(env, ni_class,
129
ni_defaultIndexID);
130
return defaultIndex;
131
}
132
133
#ifdef __solaris__
134
static int init_tcp_max_buf, init_udp_max_buf;
135
static int tcp_max_buf;
136
static int udp_max_buf;
137
static int useExclBind = 0;
138
139
/*
140
* Get the specified parameter from the specified driver. The value
141
* of the parameter is assumed to be an 'int'. If the parameter
142
* cannot be obtained return -1
143
*/
144
int net_getParam(char *driver, char *param)
145
{
146
struct strioctl stri;
147
char buf [64];
148
int s;
149
int value;
150
151
s = open (driver, O_RDWR);
152
if (s < 0) {
153
return -1;
154
}
155
strncpy (buf, param, sizeof(buf));
156
stri.ic_cmd = ND_GET;
157
stri.ic_timout = 0;
158
stri.ic_dp = buf;
159
stri.ic_len = sizeof(buf);
160
if (ioctl (s, I_STR, &stri) < 0) {
161
value = -1;
162
} else {
163
value = atoi(buf);
164
}
165
close (s);
166
return value;
167
}
168
169
/*
170
* Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
171
* for Solaris versions that do not support the ioctl() in net_getParam().
172
* Ugly, but only called once (for each sotype).
173
*
174
* As an optimization, we make a guess using the default values for Solaris
175
* assuming they haven't been modified with ndd.
176
*/
177
178
#define MAX_TCP_GUESS 1024 * 1024
179
#define MAX_UDP_GUESS 2 * 1024 * 1024
180
181
#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
182
183
static int findMaxBuf(int fd, int opt, int sotype) {
184
int a = 0;
185
int b = MAXINT;
186
int initial_guess;
187
int limit = -1;
188
189
if (sotype == SOCK_DGRAM) {
190
initial_guess = MAX_UDP_GUESS;
191
} else {
192
initial_guess = MAX_TCP_GUESS;
193
}
194
195
if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
196
initial_guess++;
197
if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
198
FAIL_IF_NOT_ENOBUFS;
199
return initial_guess - 1;
200
}
201
a = initial_guess;
202
} else {
203
FAIL_IF_NOT_ENOBUFS;
204
b = initial_guess - 1;
205
}
206
do {
207
int mid = a + (b-a)/2;
208
if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
209
limit = mid;
210
a = mid + 1;
211
} else {
212
FAIL_IF_NOT_ENOBUFS;
213
b = mid - 1;
214
}
215
} while (b >= a);
216
217
return limit;
218
}
219
#endif
220
221
#ifdef __linux__
222
static int vinit = 0;
223
static int kernelV24 = 0;
224
static int vinit24 = 0;
225
226
int kernelIsV24 () {
227
if (!vinit24) {
228
struct utsname sysinfo;
229
if (uname(&sysinfo) == 0) {
230
sysinfo.release[3] = '\0';
231
if (strcmp(sysinfo.release, "2.4") == 0) {
232
kernelV24 = JNI_TRUE;
233
}
234
}
235
vinit24 = 1;
236
}
237
return kernelV24;
238
}
239
240
int getScopeID (struct sockaddr *him) {
241
struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
242
return hext->sin6_scope_id;
243
}
244
245
int cmpScopeID (unsigned int scope, struct sockaddr *him) {
246
struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
247
return hext->sin6_scope_id == scope;
248
}
249
250
#else
251
252
int getScopeID (struct sockaddr *him) {
253
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
254
return him6->sin6_scope_id;
255
}
256
257
int cmpScopeID (unsigned int scope, struct sockaddr *him) {
258
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
259
return him6->sin6_scope_id == scope;
260
}
261
262
#endif
263
264
265
void
266
NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
267
const char *defaultDetail) {
268
JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);
269
}
270
271
void
272
NET_ThrowCurrent(JNIEnv *env, char *msg) {
273
NET_ThrowNew(env, errno, msg);
274
}
275
276
void
277
NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
278
char fullMsg[512];
279
if (!msg) {
280
msg = "no further information";
281
}
282
switch(errorNumber) {
283
case EBADF:
284
jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
285
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
286
break;
287
case EINTR:
288
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);
289
break;
290
default:
291
errno = errorNumber;
292
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);
293
break;
294
}
295
}
296
297
298
jfieldID
299
NET_GetFileDescriptorID(JNIEnv *env)
300
{
301
jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
302
CHECK_NULL_RETURN(cls, NULL);
303
return (*env)->GetFieldID(env, cls, "fd", "I");
304
}
305
306
#if defined(DONT_ENABLE_IPV6)
307
jint IPv6_supported()
308
{
309
return JNI_FALSE;
310
}
311
312
#else /* !DONT_ENABLE_IPV6 */
313
314
jint IPv6_supported()
315
{
316
#ifndef AF_INET6
317
return JNI_FALSE;
318
#endif
319
320
#ifdef AF_INET6
321
int fd;
322
void *ipv6_fn;
323
SOCKADDR sa;
324
socklen_t sa_len = sizeof(sa);
325
326
fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;
327
if (fd < 0) {
328
/*
329
* TODO: We really cant tell since it may be an unrelated error
330
* for now we will assume that AF_INET6 is not available
331
*/
332
return JNI_FALSE;
333
}
334
335
/*
336
* If fd 0 is a socket it means we've been launched from inetd or
337
* xinetd. If it's a socket then check the family - if it's an
338
* IPv4 socket then we need to disable IPv6.
339
*/
340
if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) {
341
struct sockaddr *saP = (struct sockaddr *)&sa;
342
if (saP->sa_family != AF_INET6) {
343
close(fd);
344
return JNI_FALSE;
345
}
346
}
347
348
/**
349
* Linux - check if any interface has an IPv6 address.
350
* Don't need to parse the line - we just need an indication.
351
*/
352
#ifdef __linux__
353
{
354
FILE *fP = fopen("/proc/net/if_inet6", "r");
355
char buf[255];
356
char *bufP;
357
358
if (fP == NULL) {
359
close(fd);
360
return JNI_FALSE;
361
}
362
bufP = fgets(buf, sizeof(buf), fP);
363
fclose(fP);
364
if (bufP == NULL) {
365
close(fd);
366
return JNI_FALSE;
367
}
368
}
369
#endif
370
371
/**
372
* On Solaris 8 it's possible to create INET6 sockets even
373
* though IPv6 is not enabled on all interfaces. Thus we
374
* query the number of IPv6 addresses to verify that IPv6
375
* has been configured on at least one interface.
376
*
377
* On Linux it doesn't matter - if IPv6 is built-in the
378
* kernel then IPv6 addresses will be bound automatically
379
* to all interfaces.
380
*/
381
#ifdef __solaris__
382
383
#ifdef SIOCGLIFNUM
384
{
385
struct lifnum numifs;
386
387
numifs.lifn_family = AF_INET6;
388
numifs.lifn_flags = 0;
389
if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
390
/**
391
* SIOCGLIFNUM failed - assume IPv6 not configured
392
*/
393
close(fd);
394
return JNI_FALSE;
395
}
396
/**
397
* If no IPv6 addresses then return false. If count > 0
398
* it's possible that all IPv6 addresses are "down" but
399
* that's okay as they may be brought "up" while the
400
* VM is running.
401
*/
402
if (numifs.lifn_count == 0) {
403
close(fd);
404
return JNI_FALSE;
405
}
406
}
407
#else
408
/* SIOCGLIFNUM not defined in build environment ??? */
409
close(fd);
410
return JNI_FALSE;
411
#endif
412
413
#endif /* __solaris */
414
415
/*
416
* OK we may have the stack available in the kernel,
417
* we should also check if the APIs are available.
418
*/
419
ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
420
close(fd);
421
if (ipv6_fn == NULL ) {
422
return JNI_FALSE;
423
} else {
424
return JNI_TRUE;
425
}
426
#endif /* AF_INET6 */
427
}
428
#endif /* DONT_ENABLE_IPV6 */
429
430
void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
431
const char* hostname,
432
int gai_error)
433
{
434
int size;
435
char *buf;
436
const char *format = "%s: %s";
437
const char *error_string = gai_strerror(gai_error);
438
if (error_string == NULL)
439
error_string = "unknown error";
440
441
size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
442
buf = (char *) malloc(size);
443
if (buf) {
444
jstring s;
445
sprintf(buf, format, hostname, error_string);
446
s = JNU_NewStringPlatform(env, buf);
447
if (s != NULL) {
448
jobject x = JNU_NewObjectByName(env,
449
"java/net/UnknownHostException",
450
"(Ljava/lang/String;)V", s);
451
if (x != NULL)
452
(*env)->Throw(env, x);
453
}
454
free(buf);
455
}
456
}
457
458
void
459
NET_AllocSockaddr(struct sockaddr **him, int *len) {
460
#ifdef AF_INET6
461
if (ipv6_available()) {
462
struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));
463
*him = (struct sockaddr*)him6;
464
*len = sizeof(struct sockaddr_in6);
465
} else
466
#endif /* AF_INET6 */
467
{
468
struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
469
*him = (struct sockaddr*)him4;
470
*len = sizeof(struct sockaddr_in);
471
}
472
}
473
474
#if defined(__linux__) && defined(AF_INET6)
475
476
477
/* following code creates a list of addresses from the kernel
478
* routing table that are routed via the loopback address.
479
* We check all destination addresses against this table
480
* and override the scope_id field to use the relevant value for "lo"
481
* in order to work-around the Linux bug that prevents packets destined
482
* for certain local addresses from being sent via a physical interface.
483
*/
484
485
struct loopback_route {
486
struct in6_addr addr; /* destination address */
487
int plen; /* prefix length */
488
};
489
490
static struct loopback_route *loRoutes = 0;
491
static int nRoutes = 0; /* number of routes */
492
static int loRoutes_size = 16; /* initial size */
493
static int lo_scope_id = 0;
494
495
static void initLoopbackRoutes();
496
497
void printAddr (struct in6_addr *addr) {
498
int i;
499
for (i=0; i<16; i++) {
500
printf ("%02x", addr->s6_addr[i]);
501
}
502
printf ("\n");
503
}
504
505
static jboolean needsLoopbackRoute (struct in6_addr* dest_addr) {
506
int byte_count;
507
int extra_bits, i;
508
struct loopback_route *ptr;
509
510
if (loRoutes == 0) {
511
initLoopbackRoutes();
512
}
513
514
for (ptr = loRoutes, i=0; i<nRoutes; i++, ptr++) {
515
struct in6_addr *target_addr=&ptr->addr;
516
int dest_plen = ptr->plen;
517
byte_count = dest_plen >> 3;
518
extra_bits = dest_plen & 0x3;
519
520
if (byte_count > 0) {
521
if (memcmp(target_addr, dest_addr, byte_count)) {
522
continue; /* no match */
523
}
524
}
525
526
if (extra_bits > 0) {
527
unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
528
unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
529
unsigned char mask = 0xff << (8 - extra_bits);
530
if ((c1 & mask) != (c2 & mask)) {
531
continue;
532
}
533
}
534
return JNI_TRUE;
535
}
536
return JNI_FALSE;
537
}
538
539
540
static void initLoopbackRoutes() {
541
FILE *f;
542
char srcp[8][5];
543
char hopp[8][5];
544
int dest_plen, src_plen, use, refcnt, metric;
545
unsigned long flags;
546
char dest_str[40];
547
struct in6_addr dest_addr;
548
char device[16];
549
struct loopback_route *loRoutesTemp;
550
551
if (loRoutes != 0) {
552
free (loRoutes);
553
}
554
loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));
555
if (loRoutes == 0) {
556
return;
557
}
558
/*
559
* Scan /proc/net/ipv6_route looking for a matching
560
* route.
561
*/
562
if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
563
return ;
564
}
565
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
566
"%4s%4s%4s%4s%4s%4s%4s%4s %02x "
567
"%4s%4s%4s%4s%4s%4s%4s%4s "
568
"%08x %08x %08x %08lx %8s",
569
dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
570
&dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
571
&dest_plen,
572
srcp[0], srcp[1], srcp[2], srcp[3],
573
srcp[4], srcp[5], srcp[6], srcp[7],
574
&src_plen,
575
hopp[0], hopp[1], hopp[2], hopp[3],
576
hopp[4], hopp[5], hopp[6], hopp[7],
577
&metric, &use, &refcnt, &flags, device) == 31) {
578
579
/*
580
* Some routes should be ignored
581
*/
582
if ( (dest_plen < 0 || dest_plen > 128) ||
583
(src_plen != 0) ||
584
#ifndef __ANDROID__
585
(flags & (RTF_POLICY | RTF_FLOW)) ||
586
#endif
587
((flags & RTF_REJECT) && dest_plen == 0) ) {
588
continue;
589
}
590
591
/*
592
* Convert the destination address
593
*/
594
dest_str[4] = ':';
595
dest_str[9] = ':';
596
dest_str[14] = ':';
597
dest_str[19] = ':';
598
dest_str[24] = ':';
599
dest_str[29] = ':';
600
dest_str[34] = ':';
601
dest_str[39] = '\0';
602
603
if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
604
/* not an Ipv6 address */
605
continue;
606
}
607
if (strcmp(device, "lo") != 0) {
608
/* Not a loopback route */
609
continue;
610
} else {
611
if (nRoutes == loRoutes_size) {
612
loRoutesTemp = realloc (loRoutes, loRoutes_size *
613
sizeof (struct loopback_route) * 2);
614
615
if (loRoutesTemp == 0) {
616
free(loRoutes);
617
loRoutes = NULL;
618
nRoutes = 0;
619
fclose (f);
620
return;
621
}
622
loRoutes=loRoutesTemp;
623
loRoutes_size *= 2;
624
}
625
memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));
626
loRoutes[nRoutes].plen = dest_plen;
627
nRoutes ++;
628
}
629
}
630
631
fclose (f);
632
{
633
/* now find the scope_id for "lo" */
634
635
char devname[21];
636
char addr6p[8][5];
637
int plen, scope, dad_status, if_idx;
638
639
if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
640
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
641
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
642
addr6p[4], addr6p[5], addr6p[6], addr6p[7],
643
&if_idx, &plen, &scope, &dad_status, devname) == 13) {
644
645
if (strcmp(devname, "lo") == 0) {
646
/*
647
* Found - so just return the index
648
*/
649
fclose(f);
650
lo_scope_id = if_idx;
651
return;
652
}
653
}
654
fclose(f);
655
}
656
}
657
}
658
659
/*
660
* Following is used for binding to local addresses. Equivalent
661
* to code above, for bind().
662
*/
663
664
struct localinterface {
665
int index;
666
char localaddr [16];
667
};
668
669
static struct localinterface *localifs = 0;
670
static int localifsSize = 0; /* size of array */
671
static int nifs = 0; /* number of entries used in array */
672
673
/* not thread safe: make sure called once from one thread */
674
675
static void initLocalIfs () {
676
/* Android port:
677
* - Android 5.x cause crashes.
678
* - Android 6+ read /proc/net/if_inet6 gives "permission denied", so it skips.
679
* So, skip them to fix Android 5.x crashes.
680
*/
681
#ifndef __ANDROID__
682
FILE *f;
683
unsigned char staddr [16];
684
char ifname [33];
685
struct localinterface *lif=0;
686
int index, x1, x2, x3;
687
unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;
688
689
if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {
690
return ;
691
}
692
while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "
693
"%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,
694
&u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,
695
&index, &x1, &x2, &x3, ifname) == 21) {
696
staddr[0] = (unsigned char)u0;
697
staddr[1] = (unsigned char)u1;
698
staddr[2] = (unsigned char)u2;
699
staddr[3] = (unsigned char)u3;
700
staddr[4] = (unsigned char)u4;
701
staddr[5] = (unsigned char)u5;
702
staddr[6] = (unsigned char)u6;
703
staddr[7] = (unsigned char)u7;
704
staddr[8] = (unsigned char)u8;
705
staddr[9] = (unsigned char)u9;
706
staddr[10] = (unsigned char)ua;
707
staddr[11] = (unsigned char)ub;
708
staddr[12] = (unsigned char)uc;
709
staddr[13] = (unsigned char)ud;
710
staddr[14] = (unsigned char)ue;
711
staddr[15] = (unsigned char)uf;
712
nifs ++;
713
if (nifs > localifsSize) {
714
localifs = (struct localinterface *) realloc (
715
localifs, sizeof (struct localinterface)* (localifsSize+5));
716
if (localifs == 0) {
717
nifs = 0;
718
fclose (f);
719
return;
720
}
721
lif = localifs + localifsSize;
722
localifsSize += 5;
723
} else {
724
lif ++;
725
}
726
memcpy (lif->localaddr, staddr, 16);
727
lif->index = index;
728
}
729
fclose (f);
730
#endif
731
}
732
733
/* return the scope_id (interface index) of the
734
* interface corresponding to the given address
735
* returns 0 if no match found
736
*/
737
738
static int getLocalScopeID (char *addr) {
739
struct localinterface *lif;
740
int i;
741
if (localifs == 0) {
742
initLocalIfs();
743
}
744
for (i=0, lif=localifs; i<nifs; i++, lif++) {
745
if (memcmp (addr, lif->localaddr, 16) == 0) {
746
return lif->index;
747
}
748
}
749
return 0;
750
}
751
752
void platformInit () {
753
initLoopbackRoutes();
754
initLocalIfs();
755
}
756
757
#elif defined(_AIX)
758
759
/* Initialize stubs for blocking I/O workarounds (see src/solaris/native/java/net/linux_close.c) */
760
extern void aix_close_init();
761
762
void platformInit () {
763
aix_close_init();
764
}
765
766
#else
767
768
void platformInit () {}
769
770
#endif
771
772
void parseExclusiveBindProperty(JNIEnv *env) {
773
#ifdef __solaris__
774
jstring s, flagSet;
775
jclass iCls;
776
jmethodID mid;
777
778
s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
779
CHECK_NULL(s);
780
iCls = (*env)->FindClass(env, "java/lang/System");
781
CHECK_NULL(iCls);
782
mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
783
"(Ljava/lang/String;)Ljava/lang/String;");
784
CHECK_NULL(mid);
785
flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
786
if (flagSet != NULL) {
787
useExclBind = 1;
788
}
789
#endif
790
}
791
792
JNIEXPORT jint JNICALL
793
NET_EnableFastTcpLoopback(int fd) {
794
return 0;
795
}
796
797
/* In the case of an IPv4 Inetaddress this method will return an
798
* IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
799
* Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
800
*/
801
JNIEXPORT int JNICALL
802
NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
803
int *len, jboolean v4MappedAddress) {
804
jint family;
805
family = getInetAddress_family(env, iaObj);
806
JNU_CHECK_EXCEPTION_RETURN(env, -1);
807
#ifdef AF_INET6
808
/* needs work. 1. family 2. clean up him6 etc deallocate memory */
809
if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
810
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
811
jbyte caddr[16];
812
jint address;
813
814
815
if (family == IPv4) { /* will convert to IPv4-mapped address */
816
memset((char *) caddr, 0, 16);
817
address = getInetAddress_addr(env, iaObj);
818
JNU_CHECK_EXCEPTION_RETURN(env, -1);
819
if (address == INADDR_ANY) {
820
/* we would always prefer IPv6 wildcard address
821
caddr[10] = 0xff;
822
caddr[11] = 0xff; */
823
} else {
824
caddr[10] = 0xff;
825
caddr[11] = 0xff;
826
caddr[12] = ((address >> 24) & 0xff);
827
caddr[13] = ((address >> 16) & 0xff);
828
caddr[14] = ((address >> 8) & 0xff);
829
caddr[15] = (address & 0xff);
830
}
831
} else {
832
getInet6Address_ipaddress(env, iaObj, (char *)caddr);
833
}
834
memset((char *)him6, 0, sizeof(struct sockaddr_in6));
835
him6->sin6_port = htons(port);
836
memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
837
him6->sin6_family = AF_INET6;
838
*len = sizeof(struct sockaddr_in6) ;
839
840
#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
841
// XXXBSD: should we do something with scope id here ? see below linux comment
842
/* MMM: Come back to this! */
843
#endif
844
845
/*
846
* On Linux if we are connecting to a link-local address
847
* we need to specify the interface in the scope_id (2.4 kernel only)
848
*
849
* If the scope was cached the we use the cached value. If not cached but
850
* specified in the Inet6Address we use that, but we first check if the
851
* address needs to be routed via the loopback interface. In this case,
852
* we override the specified value with that of the loopback interface.
853
* If no cached value exists and no value was specified by user, then
854
* we try to determine a value from the routing table. In all these
855
* cases the used value is cached for further use.
856
*/
857
#ifdef __linux__
858
if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
859
int cached_scope_id = 0, scope_id = 0;
860
861
if (ia6_cachedscopeidID) {
862
cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
863
/* if cached value exists then use it. Otherwise, check
864
* if scope is set in the address.
865
*/
866
if (!cached_scope_id) {
867
if (ia6_scopeidID) {
868
scope_id = getInet6Address_scopeid(env, iaObj);
869
}
870
if (scope_id != 0) {
871
/* check user-specified value for loopback case
872
* that needs to be overridden
873
*/
874
if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {
875
cached_scope_id = lo_scope_id;
876
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
877
}
878
} else {
879
/*
880
* Otherwise consult the IPv6 routing tables to
881
* try determine the appropriate interface.
882
*/
883
if (kernelIsV24()) {
884
cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
885
} else {
886
cached_scope_id = getLocalScopeID( (char *)&(him6->sin6_addr) );
887
if (cached_scope_id == 0) {
888
cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
889
}
890
}
891
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
892
}
893
}
894
}
895
896
/*
897
* If we have a scope_id use the extended form
898
* of sockaddr_in6.
899
*/
900
901
struct sockaddr_in6 *him6 =
902
(struct sockaddr_in6 *)him;
903
him6->sin6_scope_id = cached_scope_id != 0 ?
904
cached_scope_id : scope_id;
905
*len = sizeof(struct sockaddr_in6);
906
}
907
#else
908
/* handle scope_id for solaris */
909
910
if (family != IPv4) {
911
if (ia6_scopeidID) {
912
him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
913
}
914
}
915
#endif
916
} else
917
#endif /* AF_INET6 */
918
{
919
struct sockaddr_in *him4 = (struct sockaddr_in*)him;
920
jint address;
921
if (family == IPv6) {
922
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
923
return -1;
924
}
925
memset((char *) him4, 0, sizeof(struct sockaddr_in));
926
address = getInetAddress_addr(env, iaObj);
927
JNU_CHECK_EXCEPTION_RETURN(env, -1);
928
him4->sin_port = htons((short) port);
929
him4->sin_addr.s_addr = (uint32_t) htonl(address);
930
him4->sin_family = AF_INET;
931
*len = sizeof(struct sockaddr_in);
932
}
933
return 0;
934
}
935
936
void
937
NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
938
#ifdef AF_INET6
939
if (him->sa_family == AF_INET6) {
940
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
941
him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
942
}
943
#endif /* AF_INET6 */
944
}
945
946
JNIEXPORT jint JNICALL
947
NET_GetPortFromSockaddr(struct sockaddr *him) {
948
#ifdef AF_INET6
949
if (him->sa_family == AF_INET6) {
950
return ntohs(((struct sockaddr_in6*)him)->sin6_port);
951
952
} else
953
#endif /* AF_INET6 */
954
{
955
return ntohs(((struct sockaddr_in*)him)->sin_port);
956
}
957
}
958
959
int
960
NET_IsIPv4Mapped(jbyte* caddr) {
961
int i;
962
for (i = 0; i < 10; i++) {
963
if (caddr[i] != 0x00) {
964
return 0; /* false */
965
}
966
}
967
968
if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
969
return 1; /* true */
970
}
971
return 0; /* false */
972
}
973
974
int
975
NET_IPv4MappedToIPv4(jbyte* caddr) {
976
return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
977
| (caddr[15] & 0xff);
978
}
979
980
int
981
NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
982
int i;
983
for (i = 0; i < 16; i++) {
984
if (caddr1[i] != caddr2[i]) {
985
return 0; /* false */
986
}
987
}
988
return 1;
989
}
990
991
int NET_IsZeroAddr(jbyte* caddr) {
992
int i;
993
for (i = 0; i < 16; i++) {
994
if (caddr[i] != 0) {
995
return 0;
996
}
997
}
998
return 1;
999
}
1000
1001
/*
1002
* Map the Java level socket option to the platform specific
1003
* level and option name.
1004
*/
1005
int
1006
NET_MapSocketOption(jint cmd, int *level, int *optname) {
1007
static struct {
1008
jint cmd;
1009
int level;
1010
int optname;
1011
} const opts[] = {
1012
{ java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },
1013
{ java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },
1014
{ java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },
1015
{ java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },
1016
{ java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },
1017
{ java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },
1018
{ java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },
1019
{ java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },
1020
{ java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },
1021
{ java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
1022
{ java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
1023
{ java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
1024
};
1025
1026
int i;
1027
1028
#ifdef AF_INET6
1029
if (ipv6_available()) {
1030
switch (cmd) {
1031
// Different multicast options if IPv6 is enabled
1032
case java_net_SocketOptions_IP_MULTICAST_IF:
1033
case java_net_SocketOptions_IP_MULTICAST_IF2:
1034
*level = IPPROTO_IPV6;
1035
*optname = IPV6_MULTICAST_IF;
1036
return 0;
1037
1038
case java_net_SocketOptions_IP_MULTICAST_LOOP:
1039
*level = IPPROTO_IPV6;
1040
*optname = IPV6_MULTICAST_LOOP;
1041
return 0;
1042
#if (defined(__solaris__) || defined(MACOSX))
1043
// Map IP_TOS request to IPV6_TCLASS
1044
case java_net_SocketOptions_IP_TOS:
1045
*level = IPPROTO_IPV6;
1046
*optname = IPV6_TCLASS;
1047
return 0;
1048
#endif
1049
}
1050
}
1051
#endif
1052
1053
/*
1054
* Map the Java level option to the native level
1055
*/
1056
for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
1057
if (cmd == opts[i].cmd) {
1058
*level = opts[i].level;
1059
*optname = opts[i].optname;
1060
return 0;
1061
}
1062
}
1063
1064
/* not found */
1065
return -1;
1066
}
1067
1068
/*
1069
* Determine the default interface for an IPv6 address.
1070
*
1071
* 1. Scans /proc/net/ipv6_route for a matching route
1072
* (eg: fe80::/10 or a route for the specific address).
1073
* This will tell us the interface to use (eg: "eth0").
1074
*
1075
* 2. Lookup /proc/net/if_inet6 to map the interface
1076
* name to an interface index.
1077
*
1078
* Returns :-
1079
* -1 if error
1080
* 0 if no matching interface
1081
* >1 interface index to use for the link-local address.
1082
*/
1083
#if defined(__linux__) && defined(AF_INET6)
1084
int getDefaultIPv6Interface(struct in6_addr *target_addr) {
1085
FILE *f;
1086
char srcp[8][5];
1087
char hopp[8][5];
1088
int dest_plen, src_plen, use, refcnt, metric;
1089
unsigned long flags;
1090
char dest_str[40];
1091
struct in6_addr dest_addr;
1092
char device[16];
1093
jboolean match = JNI_FALSE;
1094
1095
/*
1096
* Scan /proc/net/ipv6_route looking for a matching
1097
* route.
1098
*/
1099
if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
1100
return -1;
1101
}
1102
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
1103
"%4s%4s%4s%4s%4s%4s%4s%4s %02x "
1104
"%4s%4s%4s%4s%4s%4s%4s%4s "
1105
"%08x %08x %08x %08lx %8s",
1106
dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
1107
&dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
1108
&dest_plen,
1109
srcp[0], srcp[1], srcp[2], srcp[3],
1110
srcp[4], srcp[5], srcp[6], srcp[7],
1111
&src_plen,
1112
hopp[0], hopp[1], hopp[2], hopp[3],
1113
hopp[4], hopp[5], hopp[6], hopp[7],
1114
&metric, &use, &refcnt, &flags, device) == 31) {
1115
1116
/*
1117
* Some routes should be ignored
1118
*/
1119
if ( (dest_plen < 0 || dest_plen > 128) ||
1120
(src_plen != 0) ||
1121
#ifndef __ANDROID__
1122
(flags & (RTF_POLICY | RTF_FLOW)) ||
1123
#endif
1124
((flags & RTF_REJECT) && dest_plen == 0) ) {
1125
continue;
1126
}
1127
1128
/*
1129
* Convert the destination address
1130
*/
1131
dest_str[4] = ':';
1132
dest_str[9] = ':';
1133
dest_str[14] = ':';
1134
dest_str[19] = ':';
1135
dest_str[24] = ':';
1136
dest_str[29] = ':';
1137
dest_str[34] = ':';
1138
dest_str[39] = '\0';
1139
1140
if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
1141
/* not an Ipv6 address */
1142
continue;
1143
} else {
1144
/*
1145
* The prefix len (dest_plen) indicates the number of bits we
1146
* need to match on.
1147
*
1148
* dest_plen / 8 => number of bytes to match
1149
* dest_plen % 8 => number of additional bits to match
1150
*
1151
* eg: fe80::/10 => match 1 byte + 2 additional bits in the
1152
* the next byte.
1153
*/
1154
int byte_count = dest_plen >> 3;
1155
int extra_bits = dest_plen & 0x3;
1156
1157
if (byte_count > 0) {
1158
if (memcmp(target_addr, &dest_addr, byte_count)) {
1159
continue; /* no match */
1160
}
1161
}
1162
1163
if (extra_bits > 0) {
1164
unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
1165
unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
1166
unsigned char mask = 0xff << (8 - extra_bits);
1167
if ((c1 & mask) != (c2 & mask)) {
1168
continue;
1169
}
1170
}
1171
1172
/*
1173
* We have a match
1174
*/
1175
match = JNI_TRUE;
1176
break;
1177
}
1178
}
1179
fclose(f);
1180
1181
/*
1182
* If there's a match then we lookup the interface
1183
* index.
1184
*/
1185
if (match) {
1186
char devname[21];
1187
char addr6p[8][5];
1188
int plen, scope, dad_status, if_idx;
1189
1190
if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
1191
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
1192
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1193
addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1194
&if_idx, &plen, &scope, &dad_status, devname) == 13) {
1195
1196
if (strcmp(devname, device) == 0) {
1197
/*
1198
* Found - so just return the index
1199
*/
1200
fclose(f);
1201
return if_idx;
1202
}
1203
}
1204
fclose(f);
1205
} else {
1206
/*
1207
* Couldn't open /proc/net/if_inet6
1208
*/
1209
return -1;
1210
}
1211
}
1212
1213
/*
1214
* If we get here it means we didn't there wasn't any
1215
* route or we couldn't get the index of the interface.
1216
*/
1217
return 0;
1218
}
1219
#endif
1220
1221
1222
/*
1223
* Wrapper for getsockopt system routine - does any necessary
1224
* pre/post processing to deal with OS specific oddities :-
1225
*
1226
* On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed
1227
* to compensate for an incorrect value returned by the kernel.
1228
*/
1229
int
1230
NET_GetSockOpt(int fd, int level, int opt, void *result,
1231
int *len)
1232
{
1233
int rv;
1234
socklen_t socklen = *len;
1235
1236
rv = getsockopt(fd, level, opt, result, &socklen);
1237
*len = socklen;
1238
1239
if (rv < 0) {
1240
return rv;
1241
}
1242
1243
#ifdef __linux__
1244
/*
1245
* On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This
1246
* stems from additional socket structures in the send
1247
* and receive buffers.
1248
*/
1249
if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
1250
|| (opt == SO_RCVBUF))) {
1251
int n = *((int *)result);
1252
n /= 2;
1253
*((int *)result) = n;
1254
}
1255
#endif
1256
1257
/* Workaround for Mac OS treating linger value as
1258
* signed integer
1259
*/
1260
#ifdef MACOSX
1261
if (level == SOL_SOCKET && opt == SO_LINGER) {
1262
struct linger* to_cast = (struct linger*)result;
1263
to_cast->l_linger = (unsigned short)to_cast->l_linger;
1264
}
1265
#endif
1266
return rv;
1267
}
1268
1269
/*
1270
* Wrapper for setsockopt system routine - performs any
1271
* necessary pre/post processing to deal with OS specific
1272
* issue :-
1273
*
1274
* On Solaris need to limit the suggested value for SO_SNDBUF
1275
* and SO_RCVBUF to the kernel configured limit
1276
*
1277
* For IP_TOS socket option need to mask off bits as this
1278
* aren't automatically masked by the kernel and results in
1279
* an error.
1280
*/
1281
int
1282
NET_SetSockOpt(int fd, int level, int opt, const void *arg,
1283
int len)
1284
{
1285
1286
#ifndef IPTOS_TOS_MASK
1287
#define IPTOS_TOS_MASK 0x1e
1288
#endif
1289
#ifndef IPTOS_PREC_MASK
1290
#define IPTOS_PREC_MASK 0xe0
1291
#endif
1292
1293
#if defined(_ALLBSD_SOURCE)
1294
#if defined(KIPC_MAXSOCKBUF)
1295
int mib[3];
1296
size_t rlen;
1297
#endif
1298
1299
int *bufsize;
1300
1301
#ifdef __APPLE__
1302
static int maxsockbuf = -1;
1303
#else
1304
static long maxsockbuf = -1;
1305
#endif
1306
#endif
1307
1308
/*
1309
* IPPROTO/IP_TOS :-
1310
* 1. IPv6 on Solaris/Mac OS:
1311
* Set the TOS OR Traffic Class value to cater for
1312
* IPv6 and IPv4 scenarios.
1313
* 2. IPv6 on Linux: By default Linux ignores flowinfo
1314
* field so enable IPV6_FLOWINFO_SEND so that flowinfo
1315
* will be examined. We also set the IPv4 TOS option in this case.
1316
* 3. IPv4: set socket option based on ToS and Precedence
1317
* fields (otherwise get invalid argument)
1318
*/
1319
if (level == IPPROTO_IP && opt == IP_TOS) {
1320
int *iptos;
1321
1322
#if defined(AF_INET6) && defined(__linux__)
1323
if (ipv6_available()) {
1324
int optval = 1;
1325
if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
1326
(void *)&optval, sizeof(optval)) < 0) {
1327
return -1;
1328
}
1329
/*
1330
* Let's also set the IPV6_TCLASS flag.
1331
* Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
1332
* This helps in mixed environments where IPv4 and IPv6 sockets
1333
* are connecting.
1334
*/
1335
if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
1336
arg, len) < 0) {
1337
return -1;
1338
}
1339
}
1340
#endif
1341
1342
iptos = (int *)arg;
1343
*iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
1344
}
1345
1346
/*
1347
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
1348
* the value when it exceeds the system limit.
1349
*/
1350
#ifdef __solaris__
1351
if (level == SOL_SOCKET) {
1352
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
1353
int sotype=0, arglen;
1354
int *bufsize, maxbuf;
1355
int ret;
1356
1357
/* Attempt with the original size */
1358
ret = setsockopt(fd, level, opt, arg, len);
1359
if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
1360
return ret;
1361
1362
/* Exceeded system limit so clamp and retry */
1363
1364
arglen = sizeof(sotype);
1365
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
1366
&arglen) < 0) {
1367
return -1;
1368
}
1369
1370
/*
1371
* We try to get tcp_maxbuf (and udp_max_buf) using
1372
* an ioctl() that isn't available on all versions of Solaris.
1373
* If that fails, we use the search algorithm in findMaxBuf()
1374
*/
1375
if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
1376
tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
1377
if (tcp_max_buf == -1) {
1378
tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
1379
if (tcp_max_buf == -1) {
1380
return -1;
1381
}
1382
}
1383
init_tcp_max_buf = 1;
1384
} else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
1385
udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
1386
if (udp_max_buf == -1) {
1387
udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
1388
if (udp_max_buf == -1) {
1389
return -1;
1390
}
1391
}
1392
init_udp_max_buf = 1;
1393
}
1394
1395
maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
1396
bufsize = (int *)arg;
1397
if (*bufsize > maxbuf) {
1398
*bufsize = maxbuf;
1399
}
1400
}
1401
}
1402
#endif
1403
1404
#ifdef _AIX
1405
if (level == SOL_SOCKET) {
1406
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
1407
/*
1408
* Just try to set the requested size. If it fails we will leave the
1409
* socket option as is. Setting the buffer size means only a hint in
1410
* the jse2/java software layer, see javadoc. In the previous
1411
* solution the buffer has always been truncated to a length of
1412
* 0x100000 Byte, even if the technical limit has not been reached.
1413
* This kind of absolute truncation was unexpected in the jck tests.
1414
*/
1415
int ret = setsockopt(fd, level, opt, arg, len);
1416
if ((ret == 0) || (ret == -1 && errno == ENOBUFS)) {
1417
// Accept failure because of insufficient buffer memory resources.
1418
return 0;
1419
} else {
1420
// Deliver all other kinds of errors.
1421
return ret;
1422
}
1423
}
1424
}
1425
#endif
1426
1427
/*
1428
* On Linux the receive buffer is used for both socket
1429
* structures and the the packet payload. The implication
1430
* is that if SO_RCVBUF is too small then small packets
1431
* must be discarded.
1432
*/
1433
#ifdef __linux__
1434
if (level == SOL_SOCKET && opt == SO_RCVBUF) {
1435
int *bufsize = (int *)arg;
1436
if (*bufsize < 1024) {
1437
*bufsize = 1024;
1438
}
1439
}
1440
#endif
1441
1442
#if defined(_ALLBSD_SOURCE)
1443
/*
1444
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
1445
* ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
1446
* an ENOBUFS error.
1447
*/
1448
if (level == SOL_SOCKET) {
1449
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
1450
#ifdef KIPC_MAXSOCKBUF
1451
if (maxsockbuf == -1) {
1452
mib[0] = CTL_KERN;
1453
mib[1] = KERN_IPC;
1454
mib[2] = KIPC_MAXSOCKBUF;
1455
rlen = sizeof(maxsockbuf);
1456
if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
1457
maxsockbuf = 1024;
1458
1459
#if 1
1460
/* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
1461
problem. It should be removed when kern.ipc.maxsockbuf
1462
will be real value. */
1463
maxsockbuf = (maxsockbuf/5)*4;
1464
#endif
1465
}
1466
#elif defined(__OpenBSD__)
1467
maxsockbuf = SB_MAX;
1468
#else
1469
maxsockbuf = 64 * 1024; /* XXX: NetBSD */
1470
#endif
1471
1472
bufsize = (int *)arg;
1473
if (*bufsize > maxsockbuf) {
1474
*bufsize = maxsockbuf;
1475
}
1476
1477
if (opt == SO_RCVBUF && *bufsize < 1024) {
1478
*bufsize = 1024;
1479
}
1480
1481
}
1482
}
1483
#endif
1484
1485
#if defined(_ALLBSD_SOURCE) || defined(_AIX)
1486
/*
1487
* On Solaris, SO_REUSEADDR will allow multiple datagram
1488
* sockets to bind to the same port. The network jck tests check
1489
* for this "feature", so we need to emulate it by turning on
1490
* SO_REUSEPORT as well for that combination.
1491
*/
1492
if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
1493
int sotype;
1494
socklen_t arglen;
1495
1496
arglen = sizeof(sotype);
1497
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
1498
return -1;
1499
}
1500
1501
if (sotype == SOCK_DGRAM) {
1502
setsockopt(fd, level, SO_REUSEPORT, arg, len);
1503
}
1504
}
1505
#endif
1506
1507
return setsockopt(fd, level, opt, arg, len);
1508
}
1509
1510
/*
1511
* Wrapper for bind system call - performs any necessary pre/post
1512
* processing to deal with OS specific issues :-
1513
*
1514
* Linux allows a socket to bind to 127.0.0.255 which must be
1515
* caught.
1516
*
1517
* On Solaris with IPv6 enabled we must use an exclusive
1518
* bind to guarantee a unique port number across the IPv4 and
1519
* IPv6 port spaces.
1520
*
1521
*/
1522
int
1523
NET_Bind(int fd, struct sockaddr *him, int len)
1524
{
1525
#if defined(__solaris__) && defined(AF_INET6)
1526
int level = -1;
1527
int exclbind = -1;
1528
#endif
1529
int rv;
1530
int arg, alen;
1531
1532
#ifdef __linux__
1533
/*
1534
* ## get bugId for this issue - goes back to 1.2.2 port ##
1535
* ## When IPv6 is enabled this will be an IPv4-mapped
1536
* ## with family set to AF_INET6
1537
*/
1538
if (him->sa_family == AF_INET) {
1539
struct sockaddr_in *sa = (struct sockaddr_in *)him;
1540
if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
1541
errno = EADDRNOTAVAIL;
1542
return -1;
1543
}
1544
}
1545
#endif
1546
1547
#if defined(__solaris__)
1548
/*
1549
* Solaris has separate IPv4 and IPv6 port spaces so we
1550
* use an exclusive bind when SO_REUSEADDR is not used to
1551
* give the illusion of a unified port space.
1552
* This also avoids problems with IPv6 sockets connecting
1553
* to IPv4 mapped addresses whereby the socket conversion
1554
* results in a late bind that fails because the
1555
* corresponding IPv4 port is in use.
1556
*/
1557
alen = sizeof(arg);
1558
if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1559
(char *)&arg, &alen) == 0) {
1560
if (useExclBind || arg == 0) {
1561
/*
1562
* SO_REUSEADDR is disabled or sun.net.useExclusiveBind
1563
* property is true so enable TCP_EXCLBIND or
1564
* UDP_EXCLBIND
1565
*/
1566
alen = sizeof(arg);
1567
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
1568
&alen) == 0) {
1569
if (arg == SOCK_STREAM) {
1570
level = IPPROTO_TCP;
1571
exclbind = TCP_EXCLBIND;
1572
} else {
1573
level = IPPROTO_UDP;
1574
exclbind = UDP_EXCLBIND;
1575
}
1576
}
1577
1578
arg = 1;
1579
setsockopt(fd, level, exclbind, (char *)&arg,
1580
sizeof(arg));
1581
}
1582
}
1583
1584
#endif
1585
1586
rv = bind(fd, him, len);
1587
1588
#if defined(__solaris__) && defined(AF_INET6)
1589
if (rv < 0) {
1590
int en = errno;
1591
/* Restore *_EXCLBIND if the bind fails */
1592
if (exclbind != -1) {
1593
int arg = 0;
1594
setsockopt(fd, level, exclbind, (char *)&arg,
1595
sizeof(arg));
1596
}
1597
errno = en;
1598
}
1599
#endif
1600
1601
return rv;
1602
}
1603
1604
/**
1605
* Wrapper for select/poll with timeout on a single file descriptor.
1606
*
1607
* flags (defined in net_util_md.h can be any combination of
1608
* NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
1609
*
1610
* The function will return when either the socket is ready for one
1611
* of the specified operations or the timeout expired.
1612
*
1613
* It returns the time left from the timeout (possibly 0), or -1 if it expired.
1614
*/
1615
1616
jint
1617
NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
1618
{
1619
jlong prevTime = JVM_CurrentTimeMillis(env, 0);
1620
jint read_rv;
1621
1622
while (1) {
1623
jlong newTime;
1624
#ifndef USE_SELECT
1625
{
1626
struct pollfd pfd;
1627
pfd.fd = fd;
1628
pfd.events = 0;
1629
if (flags & NET_WAIT_READ)
1630
pfd.events |= POLLIN;
1631
if (flags & NET_WAIT_WRITE)
1632
pfd.events |= POLLOUT;
1633
if (flags & NET_WAIT_CONNECT)
1634
pfd.events |= POLLOUT;
1635
1636
errno = 0;
1637
read_rv = NET_Poll(&pfd, 1, timeout);
1638
}
1639
#else
1640
{
1641
fd_set rd, wr, ex;
1642
struct timeval t;
1643
1644
t.tv_sec = timeout / 1000;
1645
t.tv_usec = (timeout % 1000) * 1000;
1646
1647
FD_ZERO(&rd);
1648
FD_ZERO(&wr);
1649
FD_ZERO(&ex);
1650
if (flags & NET_WAIT_READ) {
1651
FD_SET(fd, &rd);
1652
}
1653
if (flags & NET_WAIT_WRITE) {
1654
FD_SET(fd, &wr);
1655
}
1656
if (flags & NET_WAIT_CONNECT) {
1657
FD_SET(fd, &wr);
1658
FD_SET(fd, &ex);
1659
}
1660
1661
errno = 0;
1662
read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
1663
}
1664
#endif
1665
1666
newTime = JVM_CurrentTimeMillis(env, 0);
1667
timeout -= (newTime - prevTime);
1668
if (timeout <= 0) {
1669
return read_rv > 0 ? 0 : -1;
1670
}
1671
prevTime = newTime;
1672
1673
if (read_rv > 0) {
1674
break;
1675
}
1676
1677
1678
} /* while */
1679
1680
return timeout;
1681
}
1682
1683
#if !defined(__solaris__)
1684
long NET_GetCurrentTime() {
1685
struct timeval time;
1686
gettimeofday(&time, NULL);
1687
return (time.tv_sec * 1000 + time.tv_usec / 1000);
1688
}
1689
1690
int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime) {
1691
return NET_Timeout0(s, timeout, currentTime);
1692
}
1693
1694
int NET_Timeout(int s, long timeout) {
1695
long currentTime = (timeout > 0) ? NET_GetCurrentTime() : 0;
1696
return NET_Timeout0(s, timeout, currentTime);
1697
}
1698
#endif
1699
1700