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/Inet4AddressImpl.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
#include <WinError.h>
37
38
#include "java_net_InetAddress.h"
39
#include "java_net_Inet4AddressImpl.h"
40
#include "net_util.h"
41
#include "icmp.h"
42
43
44
/*
45
* Returns true if hostname is in dotted IP address format. Note that this
46
* function performs a syntax check only. For each octet it just checks that
47
* the octet is at most 3 digits.
48
*/
49
jboolean isDottedIPAddress(const char *hostname, unsigned int *addrp) {
50
char *c = (char *)hostname;
51
int octets = 0;
52
unsigned int cur = 0;
53
int digit_cnt = 0;
54
55
while (*c) {
56
if (*c == '.') {
57
if (digit_cnt == 0) {
58
return JNI_FALSE;
59
} else {
60
if (octets < 4) {
61
addrp[octets++] = cur;
62
cur = 0;
63
digit_cnt = 0;
64
} else {
65
return JNI_FALSE;
66
}
67
}
68
c++;
69
continue;
70
}
71
72
if ((*c < '0') || (*c > '9')) {
73
return JNI_FALSE;
74
}
75
76
digit_cnt++;
77
if (digit_cnt > 3) {
78
return JNI_FALSE;
79
}
80
81
/* don't check if current octet > 255 */
82
cur = cur*10 + (*c - '0');
83
84
/* Move onto next character and check for EOF */
85
c++;
86
if (*c == '\0') {
87
if (octets < 4) {
88
addrp[octets++] = cur;
89
} else {
90
return JNI_FALSE;
91
}
92
}
93
}
94
95
return (jboolean)(octets == 4);
96
}
97
98
/*
99
* Inet4AddressImpl
100
*/
101
102
/*
103
* Class: java_net_Inet4AddressImpl
104
* Method: getLocalHostName
105
* Signature: ()Ljava/lang/String;
106
*/
107
JNIEXPORT jstring JNICALL
108
Java_java_net_Inet4AddressImpl_getLocalHostName (JNIEnv *env, jobject this) {
109
char hostname[256];
110
111
if (gethostname(hostname, sizeof hostname) == -1) {
112
strcpy(hostname, "localhost");
113
}
114
return JNU_NewStringPlatform(env, hostname);
115
}
116
117
/*
118
* Find an internet address for a given hostname. Not this this
119
* code only works for addresses of type INET. The translation
120
* of %d.%d.%d.%d to an address (int) occurs in java now, so the
121
* String "host" shouldn't be a %d.%d.%d.%d string. The only
122
* exception should be when any of the %d are out of range and
123
* we fallback to a lookup.
124
*
125
* Class: java_net_Inet4AddressImpl
126
* Method: lookupAllHostAddr
127
* Signature: (Ljava/lang/String;)[[B
128
*
129
* This is almost shared code
130
*/
131
132
JNIEXPORT jobjectArray JNICALL
133
Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
134
jstring host) {
135
const char *hostname;
136
struct hostent *hp;
137
unsigned int addr[4];
138
139
jobjectArray ret = NULL;
140
141
initInetAddressIDs(env);
142
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
143
144
if (IS_NULL(host)) {
145
JNU_ThrowNullPointerException(env, "host argument");
146
return NULL;
147
}
148
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
149
CHECK_NULL_RETURN(hostname, NULL);
150
151
/*
152
* The NT/2000 resolver tolerates a space in front of localhost. This
153
* is not consistent with other implementations of gethostbyname.
154
* In addition we must do a white space check on Solaris to avoid a
155
* bug whereby 0.0.0.0 is returned if any host name has a white space.
156
*/
157
if (isspace(hostname[0])) {
158
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname);
159
goto cleanupAndReturn;
160
}
161
162
/*
163
* If the format is x.x.x.x then don't use gethostbyname as Windows
164
* is unable to handle octets which are out of range.
165
*/
166
if (isDottedIPAddress(hostname, &addr[0])) {
167
unsigned int address;
168
jobject iaObj;
169
170
/*
171
* Are any of the octets out of range?
172
*/
173
if (addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255) {
174
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname);
175
goto cleanupAndReturn;
176
}
177
178
/*
179
* Return an byte array with the populated address.
180
*/
181
address = (addr[3]<<24) & 0xff000000;
182
address |= (addr[2]<<16) & 0xff0000;
183
address |= (addr[1]<<8) & 0xff00;
184
address |= addr[0];
185
186
ret = (*env)->NewObjectArray(env, 1, ia_class, NULL);
187
188
if (IS_NULL(ret)) {
189
goto cleanupAndReturn;
190
}
191
192
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
193
if (IS_NULL(iaObj)) {
194
ret = NULL;
195
goto cleanupAndReturn;
196
}
197
setInetAddress_addr(env, iaObj, ntohl(address));
198
if ((*env)->ExceptionCheck(env))
199
goto cleanupAndReturn;
200
(*env)->SetObjectArrayElement(env, ret, 0, iaObj);
201
JNU_ReleaseStringPlatformChars(env, host, hostname);
202
return ret;
203
}
204
205
/*
206
* Perform the lookup
207
*/
208
if ((hp = gethostbyname((char*)hostname)) != NULL) {
209
struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
210
int len = sizeof(struct in_addr);
211
int i = 0;
212
213
while (*addrp != (struct in_addr *) 0) {
214
i++;
215
addrp++;
216
}
217
218
ret = (*env)->NewObjectArray(env, i, ia_class, NULL);
219
220
if (IS_NULL(ret)) {
221
goto cleanupAndReturn;
222
}
223
224
addrp = (struct in_addr **) hp->h_addr_list;
225
i = 0;
226
while (*addrp != (struct in_addr *) 0) {
227
jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
228
if (IS_NULL(iaObj)) {
229
ret = NULL;
230
goto cleanupAndReturn;
231
}
232
setInetAddress_addr(env, iaObj, ntohl((*addrp)->s_addr));
233
if ((*env)->ExceptionCheck(env))
234
goto cleanupAndReturn;
235
setInetAddress_hostName(env, iaObj, host);
236
if ((*env)->ExceptionCheck(env))
237
goto cleanupAndReturn;
238
(*env)->SetObjectArrayElement(env, ret, i, iaObj);
239
addrp++;
240
i++;
241
}
242
} else if (WSAGetLastError() == WSATRY_AGAIN) {
243
NET_ThrowByNameWithLastError(env,
244
JNU_JAVANETPKG "UnknownHostException",
245
hostname);
246
} else {
247
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", hostname);
248
}
249
250
cleanupAndReturn:
251
JNU_ReleaseStringPlatformChars(env, host, hostname);
252
return ret;
253
}
254
255
/*
256
* Class: java_net_Inet4AddressImpl
257
* Method: getHostByAddr
258
* Signature: (I)Ljava/lang/String;
259
*/
260
JNIEXPORT jstring JNICALL
261
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
262
jbyteArray addrArray) {
263
struct hostent *hp;
264
jbyte caddr[4];
265
jint addr;
266
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
267
addr = ((caddr[0]<<24) & 0xff000000);
268
addr |= ((caddr[1] <<16) & 0xff0000);
269
addr |= ((caddr[2] <<8) & 0xff00);
270
addr |= (caddr[3] & 0xff);
271
addr = htonl(addr);
272
273
hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
274
if (hp == NULL) {
275
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", 0);
276
return NULL;
277
}
278
if (hp->h_name == NULL) { /* Deal with bug in Windows XP */
279
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", 0);
280
return NULL;
281
}
282
return JNU_NewStringPlatform(env, hp->h_name);
283
}
284
285
286
static BOOL
287
WindowsVersionCheck(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) {
288
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
289
DWORDLONG const dwlConditionMask = VerSetConditionMask(
290
VerSetConditionMask(
291
VerSetConditionMask(
292
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
293
VER_MINORVERSION, VER_GREATER_EQUAL),
294
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
295
296
osvi.dwMajorVersion = wMajorVersion;
297
osvi.dwMinorVersion = wMinorVersion;
298
osvi.wServicePackMajor = wServicePackMajor;
299
300
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
301
}
302
303
static BOOL
304
isVistaSP1OrGreater() {
305
return WindowsVersionCheck(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
306
}
307
308
static jboolean
309
tcp_ping4(JNIEnv *env,
310
jbyteArray addrArray,
311
jint timeout,
312
jbyteArray ifArray,
313
jint ttl)
314
{
315
jint addr;
316
jbyte caddr[4];
317
jint fd;
318
struct sockaddr_in him;
319
struct sockaddr_in* netif = NULL;
320
struct sockaddr_in inf;
321
int len = 0;
322
WSAEVENT hEvent;
323
int connect_rv = -1;
324
int sz;
325
326
/**
327
* Convert IP address from byte array to integer
328
*/
329
sz = (*env)->GetArrayLength(env, addrArray);
330
if (sz != 4) {
331
return JNI_FALSE;
332
}
333
memset((char *) &him, 0, sizeof(him));
334
memset((char *) caddr, 0, sizeof(caddr));
335
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
336
addr = ((caddr[0]<<24) & 0xff000000);
337
addr |= ((caddr[1] <<16) & 0xff0000);
338
addr |= ((caddr[2] <<8) & 0xff00);
339
addr |= (caddr[3] & 0xff);
340
addr = htonl(addr);
341
/**
342
* Socket address
343
*/
344
him.sin_addr.s_addr = addr;
345
him.sin_family = AF_INET;
346
len = sizeof(him);
347
348
/**
349
* If a network interface was specified, let's convert its address
350
* as well.
351
*/
352
if (!(IS_NULL(ifArray))) {
353
memset((char *) caddr, 0, sizeof(caddr));
354
(*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
355
addr = ((caddr[0]<<24) & 0xff000000);
356
addr |= ((caddr[1] <<16) & 0xff0000);
357
addr |= ((caddr[2] <<8) & 0xff00);
358
addr |= (caddr[3] & 0xff);
359
addr = htonl(addr);
360
inf.sin_addr.s_addr = addr;
361
inf.sin_family = AF_INET;
362
inf.sin_port = 0;
363
netif = &inf;
364
}
365
366
/*
367
* Can't create a raw socket, so let's try a TCP socket
368
*/
369
fd = NET_Socket(AF_INET, SOCK_STREAM, 0);
370
if (fd == JVM_IO_ERR) {
371
/* note: if you run out of fds, you may not be able to load
372
* the exception class, and get a NoClassDefFoundError
373
* instead.
374
*/
375
NET_ThrowNew(env, WSAGetLastError(), "Can't create socket");
376
return JNI_FALSE;
377
}
378
if (ttl > 0) {
379
setsockopt(fd, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(ttl));
380
}
381
/*
382
* A network interface was specified, so let's bind to it.
383
*/
384
if (netif != NULL) {
385
if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
386
NET_ThrowNew(env, WSAGetLastError(), "Can't bind socket");
387
closesocket(fd);
388
return JNI_FALSE;
389
}
390
}
391
392
/*
393
* Make the socket non blocking so we can use select/poll.
394
*/
395
hEvent = WSACreateEvent();
396
WSAEventSelect(fd, hEvent, FD_READ|FD_CONNECT|FD_CLOSE);
397
398
/* no need to use NET_Connect as non-blocking */
399
him.sin_port = htons(7); /* Echo */
400
connect_rv = connect(fd, (struct sockaddr *)&him, len);
401
402
/**
403
* connection established or refused immediately, either way it means
404
* we were able to reach the host!
405
*/
406
if (connect_rv == 0 || WSAGetLastError() == WSAECONNREFUSED) {
407
WSACloseEvent(hEvent);
408
closesocket(fd);
409
return JNI_TRUE;
410
} else {
411
int optlen;
412
413
switch (WSAGetLastError()) {
414
case WSAEHOSTUNREACH: /* Host Unreachable */
415
case WSAENETUNREACH: /* Network Unreachable */
416
case WSAENETDOWN: /* Network is down */
417
case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
418
WSACloseEvent(hEvent);
419
closesocket(fd);
420
return JNI_FALSE;
421
}
422
423
if (WSAGetLastError() != WSAEWOULDBLOCK) {
424
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
425
"connect failed");
426
WSACloseEvent(hEvent);
427
closesocket(fd);
428
return JNI_FALSE;
429
}
430
431
timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
432
433
/* has connection been established */
434
435
if (timeout >= 0) {
436
optlen = sizeof(connect_rv);
437
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
438
&optlen) <0) {
439
connect_rv = WSAGetLastError();
440
}
441
442
if (connect_rv == 0 || connect_rv == WSAECONNREFUSED) {
443
WSACloseEvent(hEvent);
444
closesocket(fd);
445
return JNI_TRUE;
446
}
447
}
448
}
449
WSACloseEvent(hEvent);
450
closesocket(fd);
451
return JNI_FALSE;
452
}
453
454
/**
455
* ping implementation.
456
* Send a ICMP_ECHO_REQUEST packet every second until either the timeout
457
* expires or a answer is received.
458
* Returns true is an ECHO_REPLY is received, otherwise, false.
459
*/
460
static jboolean
461
ping4(JNIEnv *env,
462
unsigned long src_addr,
463
unsigned long dest_addr,
464
jint timeout,
465
HANDLE hIcmpFile)
466
{
467
// See https://msdn.microsoft.com/en-us/library/aa366050%28VS.85%29.aspx
468
469
DWORD dwRetVal = 0;
470
char SendData[32] = {0};
471
LPVOID ReplyBuffer = NULL;
472
DWORD ReplySize = 0;
473
jboolean ret = JNI_FALSE;
474
475
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366051%28v=vs.85%29.aspx
476
ReplySize = sizeof(ICMP_ECHO_REPLY) // The buffer should be large enough
477
// to hold at least one ICMP_ECHO_REPLY
478
// structure
479
+ sizeof(SendData) // plus RequestSize bytes of data.
480
+ 8; // This buffer should also be large enough
481
// to also hold 8 more bytes of data
482
// (the size of an ICMP error message)
483
484
ReplyBuffer = (VOID*) malloc(ReplySize);
485
if (ReplyBuffer == NULL) {
486
IcmpCloseHandle(hIcmpFile);
487
NET_ThrowNew(env, -1, "Unable to allocate memory");
488
return JNI_FALSE;
489
}
490
491
if (src_addr == 0) {
492
dwRetVal = IcmpSendEcho(hIcmpFile, // HANDLE IcmpHandle,
493
dest_addr, // IPAddr DestinationAddress,
494
SendData, // LPVOID RequestData,
495
sizeof(SendData), // WORD RequestSize,
496
NULL, // PIP_OPTION_INFORMATION RequestOptions,
497
ReplyBuffer,// LPVOID ReplyBuffer,
498
ReplySize, // DWORD ReplySize,
499
// Note: IcmpSendEcho and its derivatives
500
// seem to have an undocumented minimum
501
// timeout of 1000ms below which the
502
// api behaves inconsistently.
503
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
504
} else {
505
dwRetVal = IcmpSendEcho2Ex(hIcmpFile, // HANDLE IcmpHandle,
506
NULL, // HANDLE Event
507
NULL, // PIO_APC_ROUTINE ApcRoutine
508
NULL, // ApcContext
509
src_addr, // IPAddr SourceAddress,
510
dest_addr, // IPAddr DestinationAddress,
511
SendData, // LPVOID RequestData,
512
sizeof(SendData), // WORD RequestSize,
513
NULL, // PIP_OPTION_INFORMATION RequestOptions,
514
ReplyBuffer,// LPVOID ReplyBuffer,
515
ReplySize, // DWORD ReplySize,
516
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
517
}
518
519
if (dwRetVal == 0) { // if the call failed
520
TCHAR *buf;
521
DWORD err = WSAGetLastError();
522
switch (err) {
523
case ERROR_NO_NETWORK:
524
case ERROR_NETWORK_UNREACHABLE:
525
case ERROR_HOST_UNREACHABLE:
526
case ERROR_PROTOCOL_UNREACHABLE:
527
case ERROR_PORT_UNREACHABLE:
528
case ERROR_REQUEST_ABORTED:
529
case ERROR_INCORRECT_ADDRESS:
530
case ERROR_HOST_DOWN:
531
case ERROR_INVALID_COMPUTERNAME:
532
case ERROR_INVALID_NETNAME:
533
case WSAEHOSTUNREACH: /* Host Unreachable */
534
case WSAENETUNREACH: /* Network Unreachable */
535
case WSAENETDOWN: /* Network is down */
536
case WSAEPFNOSUPPORT: /* Protocol Family unsupported */
537
case IP_REQ_TIMED_OUT:
538
break;
539
default:
540
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
541
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
542
(LPTSTR)&buf, 0, NULL);
543
NET_ThrowNew(env, err, buf);
544
LocalFree(buf);
545
break;
546
}
547
} else {
548
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
549
550
// This is to take into account the undocumented minimum
551
// timeout mentioned in the IcmpSendEcho call above.
552
// We perform an extra check to make sure that our
553
// roundtrip time was less than our desired timeout
554
// for cases where that timeout is < 1000ms.
555
if (pEchoReply->Status == IP_SUCCESS
556
&& (int)pEchoReply->RoundTripTime <= timeout)
557
{
558
ret = JNI_TRUE;
559
}
560
}
561
562
free(ReplyBuffer);
563
IcmpCloseHandle(hIcmpFile);
564
565
return ret;
566
}
567
568
/*
569
* Class: java_net_Inet4AddressImpl
570
* Method: isReachable0
571
* Signature: ([bI[bI)Z
572
*/
573
JNIEXPORT jboolean JNICALL
574
Java_java_net_Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
575
jbyteArray addrArray,
576
jint timeout,
577
jbyteArray ifArray,
578
jint ttl) {
579
580
if (isVistaSP1OrGreater()) {
581
jint src_addr = 0;
582
jint dest_addr = 0;
583
jbyte caddr[4];
584
int sz;
585
HANDLE hIcmpFile;
586
587
/**
588
* Convert IP address from byte array to integer
589
*/
590
sz = (*env)->GetArrayLength(env, addrArray);
591
if (sz != 4) {
592
return JNI_FALSE;
593
}
594
memset((char *) caddr, 0, sizeof(caddr));
595
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
596
dest_addr = ((caddr[0]<<24) & 0xff000000);
597
dest_addr |= ((caddr[1] <<16) & 0xff0000);
598
dest_addr |= ((caddr[2] <<8) & 0xff00);
599
dest_addr |= (caddr[3] & 0xff);
600
dest_addr = htonl(dest_addr);
601
602
/**
603
* If a network interface was specified, let's convert its address
604
* as well.
605
*/
606
if (!(IS_NULL(ifArray))) {
607
memset((char *) caddr, 0, sizeof(caddr));
608
(*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
609
src_addr = ((caddr[0]<<24) & 0xff000000);
610
src_addr |= ((caddr[1] <<16) & 0xff0000);
611
src_addr |= ((caddr[2] <<8) & 0xff00);
612
src_addr |= (caddr[3] & 0xff);
613
src_addr = htonl(src_addr);
614
}
615
616
hIcmpFile = IcmpCreateFile();
617
if (hIcmpFile == INVALID_HANDLE_VALUE) {
618
int err = WSAGetLastError();
619
if (err == ERROR_ACCESS_DENIED) {
620
// fall back to TCP echo if access is denied to ICMP
621
return tcp_ping4(env, addrArray, timeout, ifArray, ttl);
622
} else {
623
NET_ThrowNew(env, err, "Unable to create ICMP file handle");
624
return JNI_FALSE;
625
}
626
} else {
627
return ping4(env, src_addr, dest_addr, timeout, hIcmpFile);
628
}
629
} else {
630
tcp_ping4(env, addrArray, timeout, ifArray, ttl);
631
}
632
}
633
634