Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/native/libnet/net_util.c
41149 views
1
/*
2
* Copyright (c) 1998, 2021, 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 "net_util.h"
27
28
#include "java_net_InetAddress.h"
29
30
int IPv4_supported();
31
int IPv6_supported();
32
int reuseport_supported();
33
34
static int IPv4_available;
35
static int IPv6_available;
36
static int REUSEPORT_available;
37
38
JNIEXPORT jint JNICALL ipv4_available()
39
{
40
return IPv4_available;
41
}
42
43
JNIEXPORT jint JNICALL ipv6_available()
44
{
45
return IPv6_available;
46
}
47
48
JNIEXPORT jint JNICALL reuseport_available()
49
{
50
return REUSEPORT_available;
51
}
52
53
JNIEXPORT jint JNICALL
54
DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
55
{
56
JNIEnv *env;
57
jclass iCls;
58
jmethodID mid;
59
jstring s;
60
jint preferIPv4Stack;
61
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
62
return JNI_EVERSION; /* JNI version not supported */
63
}
64
65
iCls = (*env)->FindClass(env, "java/lang/Boolean");
66
CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);
67
mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");
68
CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);
69
s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");
70
CHECK_NULL_RETURN(s, JNI_VERSION_1_2);
71
preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
72
73
/*
74
* Since we have initialized and loaded the socket library we will
75
* check now whether we have IPv6 on this platform and if the
76
* supporting socket APIs are available
77
*/
78
IPv4_available = IPv4_supported();
79
IPv6_available = IPv6_supported() & (!preferIPv4Stack);
80
81
/* check if SO_REUSEPORT is supported on this platform */
82
REUSEPORT_available = reuseport_supported();
83
platformInit();
84
85
return JNI_VERSION_1_2;
86
}
87
88
static int initialized = 0;
89
90
JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env) {
91
if (!initialized) {
92
Java_java_net_InetAddress_init(env, 0);
93
JNU_CHECK_EXCEPTION(env);
94
Java_java_net_Inet4Address_init(env, 0);
95
JNU_CHECK_EXCEPTION(env);
96
Java_java_net_Inet6Address_init(env, 0);
97
JNU_CHECK_EXCEPTION(env);
98
initialized = 1;
99
}
100
}
101
102
/* The address, and family fields used to be in InetAddress
103
* but are now in an implementation object. So, there is an extra
104
* level of indirection to access them now.
105
*/
106
107
extern jclass iac_class;
108
extern jfieldID ia_holderID;
109
extern jfieldID iac_addressID;
110
extern jfieldID iac_familyID;
111
112
/**
113
* set_ methods return JNI_TRUE on success JNI_FALSE on error
114
* get_ methods that return +ve int return -1 on error
115
* get_ methods that return objects return NULL on error.
116
*/
117
jboolean setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {
118
jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
119
CHECK_NULL_RETURN(holder, JNI_FALSE);
120
(*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);
121
(*env)->DeleteLocalRef(env, holder);
122
return JNI_TRUE;
123
}
124
125
unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
126
unsigned int id;
127
jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
128
CHECK_NULL_RETURN(holder, 0);
129
id = (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID);
130
(*env)->DeleteLocalRef(env, holder);
131
return id;
132
}
133
134
jboolean setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {
135
jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
136
CHECK_NULL_RETURN(holder, JNI_FALSE);
137
(*env)->SetIntField(env, holder, ia6_scopeidID, scopeid);
138
if (scopeid > 0) {
139
(*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE);
140
}
141
(*env)->DeleteLocalRef(env, holder);
142
return JNI_TRUE;
143
}
144
145
jboolean getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) {
146
jobject holder, addr;
147
148
holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
149
CHECK_NULL_RETURN(holder, JNI_FALSE);
150
addr = (*env)->GetObjectField(env, holder, ia6_ipaddressID);
151
CHECK_NULL_RETURN(addr, JNI_FALSE);
152
(*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest);
153
(*env)->DeleteLocalRef(env, addr);
154
(*env)->DeleteLocalRef(env, holder);
155
return JNI_TRUE;
156
}
157
158
jboolean setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {
159
jobject holder;
160
jbyteArray addr;
161
162
holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
163
CHECK_NULL_RETURN(holder, JNI_FALSE);
164
addr = (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);
165
if (addr == NULL) {
166
addr = (*env)->NewByteArray(env, 16);
167
CHECK_NULL_RETURN(addr, JNI_FALSE);
168
(*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);
169
}
170
(*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);
171
(*env)->DeleteLocalRef(env, addr);
172
(*env)->DeleteLocalRef(env, holder);
173
return JNI_TRUE;
174
}
175
176
void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
177
jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
178
CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");
179
(*env)->SetIntField(env, holder, iac_addressID, address);
180
(*env)->DeleteLocalRef(env, holder);
181
}
182
183
void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
184
jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
185
CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");
186
(*env)->SetIntField(env, holder, iac_familyID, family);
187
(*env)->DeleteLocalRef(env, holder);
188
}
189
190
void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
191
jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
192
CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");
193
(*env)->SetObjectField(env, holder, iac_hostNameID, host);
194
(*env)->SetObjectField(env, holder, iac_origHostNameID, host);
195
(*env)->DeleteLocalRef(env, holder);
196
}
197
198
int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
199
int addr;
200
jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
201
CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);
202
addr = (*env)->GetIntField(env, holder, iac_addressID);
203
(*env)->DeleteLocalRef(env, holder);
204
return addr;
205
}
206
207
int getInetAddress_family(JNIEnv *env, jobject iaObj) {
208
int family;
209
jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
210
CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);
211
family = (*env)->GetIntField(env, holder, iac_familyID);
212
(*env)->DeleteLocalRef(env, holder);
213
return family;
214
}
215
216
JNIEXPORT jobject JNICALL
217
NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) {
218
jobject iaObj;
219
if (sa->sa.sa_family == AF_INET6) {
220
jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr;
221
if (NET_IsIPv4Mapped(caddr)) {
222
int address;
223
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
224
CHECK_NULL_RETURN(iaObj, NULL);
225
address = NET_IPv4MappedToIPv4(caddr);
226
setInetAddress_addr(env, iaObj, address);
227
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
228
setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
229
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
230
} else {
231
jboolean ret;
232
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
233
CHECK_NULL_RETURN(iaObj, NULL);
234
ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr);
235
if (ret == JNI_FALSE)
236
return NULL;
237
setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
238
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
239
setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id);
240
}
241
*port = ntohs(sa->sa6.sin6_port);
242
} else {
243
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
244
CHECK_NULL_RETURN(iaObj, NULL);
245
setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
246
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
247
setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr));
248
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
249
*port = ntohs(sa->sa4.sin_port);
250
}
251
return iaObj;
252
}
253
254
JNIEXPORT jboolean JNICALL
255
NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj)
256
{
257
jint family = getInetAddress_family(env, iaObj) ==
258
java_net_InetAddress_IPv4 ? AF_INET : AF_INET6;
259
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
260
if (sa->sa.sa_family == AF_INET6) {
261
jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr;
262
if (NET_IsIPv4Mapped(caddrNew)) {
263
int addrNew, addrCur;
264
if (family == AF_INET6) {
265
return JNI_FALSE;
266
}
267
addrNew = NET_IPv4MappedToIPv4(caddrNew);
268
addrCur = getInetAddress_addr(env, iaObj);
269
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
270
if (addrNew == addrCur) {
271
return JNI_TRUE;
272
} else {
273
return JNI_FALSE;
274
}
275
} else {
276
jbyte caddrCur[16];
277
if (family == AF_INET) {
278
return JNI_FALSE;
279
}
280
getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
281
if (NET_IsEqual(caddrNew, caddrCur) &&
282
sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj))
283
{
284
return JNI_TRUE;
285
} else {
286
return JNI_FALSE;
287
}
288
}
289
} else {
290
int addrNew, addrCur;
291
if (family != AF_INET) {
292
return JNI_FALSE;
293
}
294
addrNew = ntohl(sa->sa4.sin_addr.s_addr);
295
addrCur = getInetAddress_addr(env, iaObj);
296
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
297
if (addrNew == addrCur) {
298
return JNI_TRUE;
299
} else {
300
return JNI_FALSE;
301
}
302
}
303
}
304
305
JNIEXPORT jint JNICALL
306
NET_GetPortFromSockaddr(SOCKETADDRESS *sa) {
307
if (sa->sa.sa_family == AF_INET6) {
308
return ntohs(sa->sa6.sin6_port);
309
} else {
310
return ntohs(sa->sa4.sin_port);
311
}
312
}
313
314
unsigned short
315
in_cksum(unsigned short *addr, int len) {
316
int nleft = len;
317
int sum = 0;
318
unsigned short *w = addr;
319
unsigned short answer = 0;
320
while(nleft > 1) {
321
sum += *w++;
322
nleft -= 2;
323
}
324
325
if (nleft == 1) {
326
*(unsigned char *) (&answer) = *(unsigned char *)w;
327
sum += answer;
328
}
329
330
sum = (sum >> 16) + (sum & 0xffff);
331
sum += (sum >> 16);
332
answer = ~sum;
333
return (answer);
334
}
335
336