Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/java/net/Inet6AddressImpl.c
32287 views
1
/*
2
* Copyright (c) 2000, 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 <windows.h>
27
#include <winsock2.h>
28
#include <ctype.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <malloc.h>
32
#include <sys/types.h>
33
#include <process.h>
34
#include <iphlpapi.h>
35
#include <icmpapi.h>
36
37
#include "java_net_InetAddress.h"
38
#include "java_net_Inet4AddressImpl.h"
39
#include "java_net_Inet6AddressImpl.h"
40
#include "net_util.h"
41
#include "icmp.h"
42
43
#ifdef WIN32
44
#ifndef _WIN64
45
46
/* Retain this code a little longer to support building in
47
* old environments. _MSC_VER is defined as:
48
* 1200 for MSVC++ 6.0
49
* 1310 for Vc7
50
*/
51
#if defined(_MSC_VER) && _MSC_VER < 1310
52
#define sockaddr_in6 SOCKADDR_IN6
53
#endif
54
#endif
55
#define uint32_t UINT32
56
#endif
57
58
/*
59
* Inet6AddressImpl
60
*/
61
62
/*
63
* Class: java_net_Inet6AddressImpl
64
* Method: getLocalHostName
65
* Signature: ()Ljava/lang/String;
66
*/
67
JNIEXPORT jstring JNICALL
68
Java_java_net_Inet6AddressImpl_getLocalHostName (JNIEnv *env, jobject this) {
69
char hostname [256];
70
71
if (gethostname (hostname, sizeof (hostname)) == -1) {
72
strcpy (hostname, "localhost");
73
}
74
return JNU_NewStringPlatform (env, hostname);
75
}
76
77
JNIEXPORT jobjectArray JNICALL
78
Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
79
jstring host) {
80
const char *hostname;
81
jobjectArray ret = 0;
82
int retLen = 0;
83
jboolean preferIPv6Address;
84
85
int error=0;
86
struct addrinfo hints, *res, *resNew = NULL;
87
88
initInetAddressIDs(env);
89
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
90
91
if (IS_NULL(host)) {
92
JNU_ThrowNullPointerException(env, "host is null");
93
return 0;
94
}
95
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
96
CHECK_NULL_RETURN(hostname, NULL);
97
98
/* get the address preference */
99
preferIPv6Address
100
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
101
102
/* Try once, with our static buffer. */
103
memset(&hints, 0, sizeof(hints));
104
hints.ai_flags = AI_CANONNAME;
105
hints.ai_family = AF_UNSPEC;
106
107
error = getaddrinfo(hostname, NULL, &hints, &res);
108
109
if (error) {
110
if (WSAGetLastError() == WSATRY_AGAIN) {
111
NET_ThrowByNameWithLastError(env,
112
JNU_JAVANETPKG "UnknownHostException",
113
hostname);
114
JNU_ReleaseStringPlatformChars(env, host, hostname);
115
return NULL;
116
} else {
117
/* report error */
118
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
119
(char *)hostname);
120
JNU_ReleaseStringPlatformChars(env, host, hostname);
121
return NULL;
122
}
123
} else {
124
int i = 0;
125
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
126
struct addrinfo *itr, *last, *iterator = res;
127
while (iterator != NULL) {
128
int skip = 0;
129
itr = resNew;
130
while (itr != NULL) {
131
if (iterator->ai_family == itr->ai_family &&
132
iterator->ai_addrlen == itr->ai_addrlen) {
133
if (itr->ai_family == AF_INET) { /* AF_INET */
134
struct sockaddr_in *addr1, *addr2;
135
addr1 = (struct sockaddr_in *)iterator->ai_addr;
136
addr2 = (struct sockaddr_in *)itr->ai_addr;
137
if (addr1->sin_addr.s_addr ==
138
addr2->sin_addr.s_addr) {
139
skip = 1;
140
break;
141
}
142
} else {
143
int t;
144
struct sockaddr_in6 *addr1, *addr2;
145
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
146
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
147
148
for (t = 0; t < 16; t++) {
149
if (addr1->sin6_addr.s6_addr[t] !=
150
addr2->sin6_addr.s6_addr[t]) {
151
break;
152
}
153
}
154
if (t < 16) {
155
itr = itr->ai_next;
156
continue;
157
} else {
158
skip = 1;
159
break;
160
}
161
}
162
} else if (iterator->ai_family != AF_INET &&
163
iterator->ai_family != AF_INET6) {
164
/* we can't handle other family types */
165
skip = 1;
166
break;
167
}
168
itr = itr->ai_next;
169
}
170
171
if (!skip) {
172
struct addrinfo *next
173
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
174
if (!next) {
175
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
176
ret = NULL;
177
goto cleanupAndReturn;
178
}
179
memcpy(next, iterator, sizeof(struct addrinfo));
180
next->ai_next = NULL;
181
if (resNew == NULL) {
182
resNew = next;
183
} else {
184
last->ai_next = next;
185
}
186
last = next;
187
i++;
188
if (iterator->ai_family == AF_INET) {
189
inetCount ++;
190
} else if (iterator->ai_family == AF_INET6) {
191
inet6Count ++;
192
}
193
}
194
iterator = iterator->ai_next;
195
}
196
retLen = i;
197
iterator = resNew;
198
i = 0;
199
ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);
200
201
if (IS_NULL(ret)) {
202
/* we may have memory to free at the end of this */
203
goto cleanupAndReturn;
204
}
205
206
if (preferIPv6Address) {
207
inetIndex = inet6Count;
208
inet6Index = 0;
209
} else {
210
inetIndex = 0;
211
inet6Index = inetCount;
212
}
213
214
while (iterator != NULL) {
215
if (iterator->ai_family == AF_INET) {
216
jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
217
if (IS_NULL(iaObj)) {
218
ret = NULL;
219
goto cleanupAndReturn;
220
}
221
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
222
if ((*env)->ExceptionCheck(env))
223
goto cleanupAndReturn;
224
setInetAddress_hostName(env, iaObj, host);
225
if ((*env)->ExceptionCheck(env))
226
goto cleanupAndReturn;
227
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
228
inetIndex ++;
229
} else if (iterator->ai_family == AF_INET6) {
230
jint scope = 0, ret1;
231
jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
232
if (IS_NULL(iaObj)) {
233
ret = NULL;
234
goto cleanupAndReturn;
235
}
236
ret1 = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
237
238
if (ret1 == JNI_FALSE) {
239
ret = NULL;
240
goto cleanupAndReturn;
241
}
242
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
243
if (scope != 0) { /* zero is default value, no need to set */
244
setInet6Address_scopeid(env, iaObj, scope);
245
}
246
setInetAddress_hostName(env, iaObj, host);
247
if ((*env)->ExceptionCheck(env))
248
goto cleanupAndReturn;
249
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
250
inet6Index ++;
251
}
252
iterator = iterator->ai_next;
253
}
254
}
255
256
cleanupAndReturn:
257
{
258
struct addrinfo *iterator, *tmp;
259
iterator = resNew;
260
while (iterator != NULL) {
261
tmp = iterator;
262
iterator = iterator->ai_next;
263
free(tmp);
264
}
265
JNU_ReleaseStringPlatformChars(env, host, hostname);
266
}
267
268
freeaddrinfo(res);
269
270
return ret;
271
}
272
273
/*
274
* Class: java_net_Inet6AddressImpl
275
* Method: getHostByAddr
276
* Signature: (I)Ljava/lang/String;
277
*/
278
JNIEXPORT jstring JNICALL
279
Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
280
jbyteArray addrArray) {
281
jstring ret = NULL;
282
283
char host[NI_MAXHOST+1];
284
int error = 0;
285
int len = 0;
286
jbyte caddr[16];
287
288
struct sockaddr_in him4;
289
struct sockaddr_in6 him6;
290
struct sockaddr *sa;
291
292
/*
293
* For IPv4 addresses construct a sockaddr_in structure.
294
*/
295
if ((*env)->GetArrayLength(env, addrArray) == 4) {
296
jint addr;
297
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
298
addr = ((caddr[0]<<24) & 0xff000000);
299
addr |= ((caddr[1] <<16) & 0xff0000);
300
addr |= ((caddr[2] <<8) & 0xff00);
301
addr |= (caddr[3] & 0xff);
302
memset((char *) &him4, 0, sizeof(him4));
303
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
304
him4.sin_family = AF_INET;
305
sa = (struct sockaddr *) &him4;
306
len = sizeof(him4);
307
} else {
308
/*
309
* For IPv6 address construct a sockaddr_in6 structure.
310
*/
311
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
312
memset((char *) &him6, 0, sizeof(him6));
313
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
314
him6.sin6_family = AF_INET6;
315
sa = (struct sockaddr *) &him6 ;
316
len = sizeof(him6) ;
317
}
318
319
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
320
321
if (!error) {
322
ret = (*env)->NewStringUTF(env, host);
323
CHECK_NULL_RETURN(ret, NULL);
324
}
325
326
if (ret == NULL) {
327
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
328
}
329
330
return ret;
331
}
332
333
#ifdef AF_INET6
334
335
/**
336
* ping implementation using tcp port 7 (echo)
337
*/
338
static jboolean
339
tcp_ping6(JNIEnv *env,
340
jint timeout,
341
jint ttl,
342
struct sockaddr_in6 him6,
343
struct sockaddr_in6* netif,
344
int len)
345
{
346
jint fd;
347
WSAEVENT hEvent;
348
int connect_rv = -1;
349
350
fd = NET_Socket(AF_INET6, SOCK_STREAM, 0);
351
if (fd == SOCKET_ERROR) {
352
/* note: if you run out of fds, you may not be able to load
353
* the exception class, and get a NoClassDefFoundError
354
* instead.
355
*/
356
NET_ThrowNew(env, errno, "Can't create socket");
357
return JNI_FALSE;
358
}
359
360
/**
361
* A TTL was specified, let's set the socket option.
362
*/
363
if (ttl > 0) {
364
setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *)&ttl, sizeof(ttl));
365
}
366
367
/**
368
* A network interface was specified, let's bind to it.
369
*/
370
if (netif != NULL) {
371
if (NET_Bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) < 0) {
372
NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket to interface");
373
closesocket(fd);
374
return JNI_FALSE;
375
}
376
}
377
378
/**
379
* Make the socket non blocking.
380
*/
381
hEvent = WSACreateEvent();
382
WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE);
383
384
/* no need to use NET_Connect as non-blocking */
385
him6.sin6_port = htons((short) 7); /* Echo port */
386
connect_rv = connect(fd, (struct sockaddr *)&him6, len);
387
388
/**
389
* connection established or refused immediately, either way it means
390
* we were able to reach the host!
391
*/
392
if (connect_rv == 0 || WSAGetLastError() == WSAECONNREFUSED) {
393
WSACloseEvent(hEvent);
394
closesocket(fd);
395
return JNI_TRUE;
396
} else {
397
int optlen;
398
399
switch (WSAGetLastError()) {
400
case WSAEHOSTUNREACH: /* Host Unreachable */
401
case WSAENETUNREACH: /* Network Unreachable */
402
case WSAENETDOWN: /* Network is down */
403
case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
404
WSACloseEvent(hEvent);
405
closesocket(fd);
406
return JNI_FALSE;
407
}
408
409
if (WSAGetLastError() != WSAEWOULDBLOCK) {
410
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
411
"connect failed");
412
WSACloseEvent(hEvent);
413
closesocket(fd);
414
return JNI_FALSE;
415
}
416
417
timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
418
419
if (timeout >= 0) {
420
/* has connection been established? */
421
optlen = sizeof(connect_rv);
422
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
423
&optlen) <0) {
424
connect_rv = WSAGetLastError();
425
}
426
427
if (connect_rv == 0 || connect_rv == WSAECONNREFUSED) {
428
WSACloseEvent(hEvent);
429
closesocket(fd);
430
return JNI_TRUE;
431
}
432
}
433
}
434
WSACloseEvent(hEvent);
435
closesocket(fd);
436
return JNI_FALSE;
437
}
438
439
/**
440
* ping implementation.
441
* Send a ICMP_ECHO_REQUEST packet every second until either the timeout
442
* expires or a answer is received.
443
* Returns true is an ECHO_REPLY is received, otherwise, false.
444
*/
445
static jboolean
446
ping6(JNIEnv *env,
447
struct sockaddr_in6* src,
448
struct sockaddr_in6* dest,
449
jint timeout,
450
HANDLE hIcmpFile)
451
{
452
DWORD dwRetVal = 0;
453
char SendData[32] = {0};
454
LPVOID ReplyBuffer = NULL;
455
DWORD ReplySize = 0;
456
IP_OPTION_INFORMATION ipInfo = {255, 0, 0, 0, NULL};
457
struct sockaddr_in6 sa6Source;
458
459
ReplySize = sizeof(ICMPV6_ECHO_REPLY) + sizeof(SendData);
460
ReplyBuffer = (VOID*) malloc(ReplySize);
461
if (ReplyBuffer == NULL) {
462
IcmpCloseHandle(hIcmpFile);
463
NET_ThrowNew(env, -1, "Unable to allocate memory");
464
return JNI_FALSE;
465
}
466
467
//define local source information
468
sa6Source.sin6_addr = in6addr_any;
469
sa6Source.sin6_family = AF_INET6;
470
sa6Source.sin6_flowinfo = 0;
471
sa6Source.sin6_port = 0;
472
473
dwRetVal = Icmp6SendEcho2(hIcmpFile, // HANDLE IcmpHandle,
474
NULL, // HANDLE Event,
475
NULL, // PIO_APC_ROUTINE ApcRoutine,
476
NULL, // PVOID ApcContext,
477
&sa6Source, // struct sockaddr_in6 *SourceAddress,
478
dest, // struct sockaddr_in6 *DestinationAddress,
479
SendData, // LPVOID RequestData,
480
sizeof(SendData), // WORD RequestSize,
481
&ipInfo, // PIP_OPTION_INFORMATION RequestOptions,
482
ReplyBuffer, // LPVOID ReplyBuffer,
483
ReplySize, // DWORD ReplySize,
484
timeout); // DWORD Timeout
485
486
free(ReplyBuffer);
487
IcmpCloseHandle(hIcmpFile);
488
489
490
if (dwRetVal != 0) {
491
return JNI_TRUE;
492
} else {
493
return JNI_FALSE;
494
}
495
}
496
#endif /* AF_INET6 */
497
498
/*
499
* Class: java_net_Inet6AddressImpl
500
* Method: isReachable0
501
* Signature: ([bII[bI)Z
502
*/
503
JNIEXPORT jboolean JNICALL
504
Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
505
jbyteArray addrArray,
506
jint scope,
507
jint timeout,
508
jbyteArray ifArray,
509
jint ttl, jint if_scope) {
510
#ifdef AF_INET6
511
jbyte caddr[16];
512
jint sz;
513
struct sockaddr_in6 him6;
514
struct sockaddr_in6* netif = NULL;
515
struct sockaddr_in6 inf6;
516
int len = 0;
517
HANDLE hIcmpFile;
518
519
/*
520
* If IPv6 is not enable, then we can't reach an IPv6 address, can we?
521
* Actually, we probably shouldn't even get here.
522
*/
523
if (!ipv6_available()) {
524
return JNI_FALSE;
525
}
526
/*
527
* If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
528
* therefore, let's delegate to the Inet4Address method.
529
*/
530
sz = (*env)->GetArrayLength(env, addrArray);
531
if (sz == 4) {
532
return Java_java_net_Inet4AddressImpl_isReachable0(env, this,
533
addrArray,
534
timeout,
535
ifArray, ttl);
536
}
537
538
memset((char *) caddr, 0, 16);
539
memset((char *) &him6, 0, sizeof(him6));
540
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
541
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
542
him6.sin6_family = AF_INET6;
543
if (scope > 0) {
544
him6.sin6_scope_id = scope;
545
}
546
len = sizeof(struct sockaddr_in6);
547
548
/**
549
* A network interface was specified, let's convert the address
550
*/
551
if (!(IS_NULL(ifArray))) {
552
memset((char *) caddr, 0, 16);
553
memset((char *) &inf6, 0, sizeof(inf6));
554
(*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
555
memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
556
inf6.sin6_family = AF_INET6;
557
inf6.sin6_port = 0;
558
inf6.sin6_scope_id = if_scope;
559
netif = &inf6;
560
}
561
562
hIcmpFile = Icmp6CreateFile();
563
if (hIcmpFile == INVALID_HANDLE_VALUE) {
564
int err = WSAGetLastError();
565
if (err == ERROR_ACCESS_DENIED) {
566
// fall back to TCP echo if access is denied to ICMP
567
return tcp_ping6(env, timeout, ttl, him6, netif, len);
568
} else {
569
NET_ThrowNew(env, err, "Unable to create ICMP file handle");
570
return JNI_FALSE;
571
}
572
} else {
573
return ping6(env, netif, &him6, timeout, hIcmpFile);
574
}
575
576
#endif /* AF_INET6 */
577
return JNI_FALSE;
578
}
579
580