1 /*
2 * Copyright (c) 1998, 2012, 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 "jni.h"
27 #include "jvm.h"
28 #include "jni_util.h"
29 #include "net_util.h"
30
31 int IPv6_supported();
32
33 static int IPv6_available;
34
ipv6_available()35 JNIEXPORT jint JNICALL ipv6_available()
36 {
37 return IPv6_available ;
38 }
39
40 JNIEXPORT jint JNICALL
net_JNI_OnLoad(JavaVM * vm,void * ignored)41 net_JNI_OnLoad(JavaVM *vm, void* ignored)
42 {
43 JNIEnv *env;
44
45 if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2) == JNI_OK) {
46 if (JVM_InitializeSocketLibrary() < 0) {
47 JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError",
48 "failed to initialize net library.");
49 return JNI_VERSION_1_2;
50 }
51 }
52
53 /*
54 Since we have initialized and loaded the Socket library we will
55 check now to whether we have IPv6 on this platform and if the
56 supporting socket APIs are available
57 */
58 IPv6_available = IPv6_supported();
59 initLocalAddrTable();
60 parseExclusiveBindProperty(env);
61
62 return JNI_VERSION_1_2;
63 }
64
65 /* The address, and family fields used to be in InetAddress
66 * but are now in an implementation object. So, there is an extra
67 * level of indirection to access them now.
68 */
69
70 extern jclass iac_class;
71 extern jfieldID ia_holderID;
72 extern jfieldID iac_addressID;
73 extern jfieldID iac_familyID;
74
75 /**
76 * set_ methods return JNI_TRUE on success JNI_FALSE on error
77 * get_ methods that return +ve int return -1 on error
78 * get_ methods that return objects return NULL on error.
79 */
getInet6Address_scopeifname(JNIEnv * env,jobject iaObj)80 jobject getInet6Address_scopeifname(JNIEnv *env, jobject iaObj) {
81 jobject holder;
82
83 // Android-changed: initInetAddrs(env);
84 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
85 CHECK_NULL_RETURN(holder, NULL);
86 return (*env)->GetObjectField(env, holder, ia6_scopeifnameID);
87 }
88
setInet6Address_scopeifname(JNIEnv * env,jobject iaObj,jobject scopeifname)89 int setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {
90 jobject holder;
91
92 // Android-changed: initInetAddrs(env);
93 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
94 CHECK_NULL_RETURN(holder, JNI_FALSE);
95 (*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);
96 return JNI_TRUE;
97 }
98
getInet6Address_scopeid_set(JNIEnv * env,jobject iaObj)99 int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
100 jobject holder;
101
102 // Android-changed: initInetAddrs(env);
103 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
104 CHECK_NULL_RETURN(holder, -1);
105 return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);
106 }
107
getInet6Address_scopeid(JNIEnv * env,jobject iaObj)108 int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
109 jobject holder;
110
111 // Android-changed: initInetAddrs(env);
112 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
113 CHECK_NULL_RETURN(holder, -1);
114 return (*env)->GetIntField(env, holder, ia6_scopeidID);
115 }
116
setInet6Address_scopeid(JNIEnv * env,jobject iaObj,int scopeid)117 int setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {
118 jobject holder;
119
120 // Android-changed: initInetAddrs(env);
121 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
122 CHECK_NULL_RETURN(holder, JNI_FALSE);
123 (*env)->SetIntField(env, holder, ia6_scopeidID, scopeid);
124 if (scopeid > 0) {
125 (*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE);
126 }
127 return JNI_TRUE;
128 }
129
130
getInet6Address_ipaddress(JNIEnv * env,jobject iaObj,char * dest)131 int getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) {
132 jobject holder, addr;
133 jbyteArray barr;
134
135 // Android-changed: initInetAddrs(env);
136 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
137 CHECK_NULL_RETURN(holder, JNI_FALSE);
138 addr = (*env)->GetObjectField(env, holder, ia6_ipaddressID);
139 CHECK_NULL_RETURN(addr, JNI_FALSE);
140 (*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest);
141 return JNI_TRUE;
142 }
143
setInet6Address_ipaddress(JNIEnv * env,jobject iaObj,char * address)144 int setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {
145 jobject holder;
146 jbyteArray addr;
147
148 // Android-changed: initInetAddrs(env);
149 holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
150 CHECK_NULL_RETURN(holder, JNI_FALSE);
151 addr = (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);
152 if (addr == NULL) {
153 addr = (*env)->NewByteArray(env, 16);
154 CHECK_NULL_RETURN(addr, JNI_FALSE);
155 (*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);
156 }
157 (*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);
158 return JNI_TRUE;
159 }
160
setInetAddress_addr(JNIEnv * env,jobject iaObj,int address)161 void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
162 jobject holder;
163 // Android-changed: initInetAddrs(env);
164 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
165 (*env)->SetIntField(env, holder, iac_addressID, address);
166 }
167
setInetAddress_family(JNIEnv * env,jobject iaObj,int family)168 void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
169 jobject holder;
170 // Android-changed: initInetAddrs(env);
171 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
172 (*env)->SetIntField(env, holder, iac_familyID, family);
173 }
174
setInetAddress_hostName(JNIEnv * env,jobject iaObj,jobject host)175 void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
176 jobject holder;
177 // Android-changed: initInetAddrs(env);
178 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
179 (*env)->SetObjectField(env, holder, iac_hostNameID, host);
180 }
181
getInetAddress_addr(JNIEnv * env,jobject iaObj)182 int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
183 jobject holder;
184 // Android-changed: initInetAddrs(env);
185 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
186 return (*env)->GetIntField(env, holder, iac_addressID);
187 }
188
getInetAddress_family(JNIEnv * env,jobject iaObj)189 int getInetAddress_family(JNIEnv *env, jobject iaObj) {
190 jobject holder;
191
192 // Android-changed: initInetAddrs(env);
193 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
194 return (*env)->GetIntField(env, holder, iac_familyID);
195 }
196
getInetAddress_hostName(JNIEnv * env,jobject iaObj)197 jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
198 jobject holder;
199 // Android-changed: initInetAddrs(env);
200 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
201 return (*env)->GetObjectField(env, holder, iac_hostNameID);
202 }
203
204 JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv * env,struct sockaddr * him,int * port)205 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
206 jobject iaObj;
207 // Android-changed: initInetAddrs(env);
208 #ifdef AF_INET6
209 if (him->sa_family == AF_INET6) {
210 jbyteArray ipaddress;
211 #ifdef WIN32
212 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
213 #else
214 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
215 #endif
216 jbyte *caddr = (jbyte *)&(him6->sin6_addr);
217 if (NET_IsIPv4Mapped(caddr)) {
218 int address;
219 static jclass inet4Cls = 0;
220 if (inet4Cls == 0) {
221 jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
222 CHECK_NULL_RETURN(c, NULL);
223 inet4Cls = (*env)->NewGlobalRef(env, c);
224 CHECK_NULL_RETURN(inet4Cls, NULL);
225 (*env)->DeleteLocalRef(env, c);
226 }
227 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
228 CHECK_NULL_RETURN(iaObj, NULL);
229 address = NET_IPv4MappedToIPv4(caddr);
230 setInetAddress_addr(env, iaObj, address);
231 setInetAddress_family(env, iaObj, IPv4);
232 } else {
233 static jclass inet6Cls = 0;
234 jint scope;
235 int ret;
236 if (inet6Cls == 0) {
237 jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
238 CHECK_NULL_RETURN(c, NULL);
239 inet6Cls = (*env)->NewGlobalRef(env, c);
240 CHECK_NULL_RETURN(inet6Cls, NULL);
241 (*env)->DeleteLocalRef(env, c);
242 }
243 iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
244 CHECK_NULL_RETURN(iaObj, NULL);
245 ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
246 // Android-changed: Appease compiler type checking.
247 // CHECK_NULL_RETURN(ret, NULL);
248 if (ret == JNI_FALSE) return NULL;
249 setInetAddress_family(env, iaObj, IPv6);
250 scope = getScopeID(him);
251 setInet6Address_scopeid(env, iaObj, scope);
252 }
253 *port = ntohs(him6->sin6_port);
254 } else
255 #endif /* AF_INET6 */
256 if (him->sa_family == AF_INET) {
257 struct sockaddr_in *him4 = (struct sockaddr_in *)him;
258 static jclass inet4Cls = 0;
259
260 if (inet4Cls == 0) {
261 jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
262 CHECK_NULL_RETURN(c, NULL);
263 inet4Cls = (*env)->NewGlobalRef(env, c);
264 CHECK_NULL_RETURN(inet4Cls, NULL);
265 (*env)->DeleteLocalRef(env, c);
266 }
267 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
268 CHECK_NULL_RETURN(iaObj, NULL);
269 setInetAddress_family(env, iaObj, IPv4);
270 setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
271 *port = ntohs(him4->sin_port);
272 } else {
273 // Unknown family
274 char errmsg[255];
275 snprintf(errmsg, sizeof(errmsg), "Unknown socket family: %d", him->sa_family);
276 JNU_ThrowByName(env, "java/net/SocketException", errmsg);
277 return NULL;
278 }
279 return iaObj;
280 }
281
282 JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv * env,struct sockaddr * him,jobject iaObj)283 NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
284 {
285 jint family = AF_INET;
286
287 #ifdef AF_INET6
288 family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
289 if (him->sa_family == AF_INET6) {
290 #ifdef WIN32
291 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
292 #else
293 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
294 #endif
295 jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
296 if (NET_IsIPv4Mapped(caddrNew)) {
297 int addrNew;
298 int addrCur;
299 if (family == AF_INET6) {
300 return JNI_FALSE;
301 }
302 addrNew = NET_IPv4MappedToIPv4(caddrNew);
303 addrCur = getInetAddress_addr(env, iaObj);
304 if (addrNew == addrCur) {
305 return JNI_TRUE;
306 } else {
307 return JNI_FALSE;
308 }
309 } else {
310 jbyteArray ipaddress;
311 jbyte caddrCur[16];
312 int scope;
313
314 if (family == AF_INET) {
315 return JNI_FALSE;
316 }
317 scope = getInet6Address_scopeid(env, iaObj);
318 getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
319 if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
320 return JNI_TRUE;
321 } else {
322 return JNI_FALSE;
323 }
324 }
325 } else
326 #endif /* AF_INET6 */
327 {
328 struct sockaddr_in *him4 = (struct sockaddr_in *)him;
329 int addrNew, addrCur;
330 if (family != AF_INET) {
331 return JNI_FALSE;
332 }
333 addrNew = ntohl(him4->sin_addr.s_addr);
334 addrCur = getInetAddress_addr(env, iaObj);
335 if (addrNew == addrCur) {
336 return JNI_TRUE;
337 } else {
338 return JNI_FALSE;
339 }
340 }
341 }
342
343 unsigned short
in_cksum(unsigned short * addr,int len)344 in_cksum(unsigned short *addr, int len) {
345 int nleft = len;
346 int sum = 0;
347 unsigned short *w = addr;
348 unsigned short answer = 0;
349 while(nleft > 1) {
350 sum += *w++;
351 nleft -= 2;
352 }
353
354 if (nleft == 1) {
355 *(unsigned char *) (&answer) = *(unsigned char *)w;
356 sum += answer;
357 }
358
359 sum = (sum >> 16) + (sum & 0xffff);
360 sum += (sum >> 16);
361 answer = ~sum;
362 return (answer);
363 }
364