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 (*env)->SetObjectField(env, holder, iac_origHostNameID, host);
181 }
182
getInetAddress_addr(JNIEnv * env,jobject iaObj)183 int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
184 jobject holder;
185 // Android-changed: initInetAddrs(env);
186 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
187 return (*env)->GetIntField(env, holder, iac_addressID);
188 }
189
getInetAddress_family(JNIEnv * env,jobject iaObj)190 int getInetAddress_family(JNIEnv *env, jobject iaObj) {
191 jobject holder;
192
193 // Android-changed: initInetAddrs(env);
194 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
195 return (*env)->GetIntField(env, holder, iac_familyID);
196 }
197
getInetAddress_hostName(JNIEnv * env,jobject iaObj)198 jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
199 jobject holder;
200 // Android-changed: initInetAddrs(env);
201 holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
202 return (*env)->GetObjectField(env, holder, iac_hostNameID);
203 }
204
205 JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv * env,struct sockaddr * him,int * port)206 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
207 jobject iaObj;
208 // Android-changed: initInetAddrs(env);
209 #ifdef AF_INET6
210 if (him->sa_family == AF_INET6) {
211 jbyteArray ipaddress;
212 #ifdef WIN32
213 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
214 #else
215 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
216 #endif
217 jbyte *caddr = (jbyte *)&(him6->sin6_addr);
218 if (NET_IsIPv4Mapped(caddr)) {
219 int address;
220 static jclass inet4Cls = 0;
221 if (inet4Cls == 0) {
222 jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
223 CHECK_NULL_RETURN(c, NULL);
224 inet4Cls = (*env)->NewGlobalRef(env, c);
225 CHECK_NULL_RETURN(inet4Cls, NULL);
226 (*env)->DeleteLocalRef(env, c);
227 }
228 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
229 CHECK_NULL_RETURN(iaObj, NULL);
230 address = NET_IPv4MappedToIPv4(caddr);
231 setInetAddress_addr(env, iaObj, address);
232 setInetAddress_family(env, iaObj, IPv4);
233 } else {
234 static jclass inet6Cls = 0;
235 jint scope;
236 int ret;
237 if (inet6Cls == 0) {
238 jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
239 CHECK_NULL_RETURN(c, NULL);
240 inet6Cls = (*env)->NewGlobalRef(env, c);
241 CHECK_NULL_RETURN(inet6Cls, NULL);
242 (*env)->DeleteLocalRef(env, c);
243 }
244 iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
245 CHECK_NULL_RETURN(iaObj, NULL);
246 ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
247 // Android-changed: Appease compiler type checking.
248 // CHECK_NULL_RETURN(ret, NULL);
249 if (ret == JNI_FALSE) return NULL;
250 setInetAddress_family(env, iaObj, IPv6);
251 scope = getScopeID(him);
252 setInet6Address_scopeid(env, iaObj, scope);
253 }
254 *port = ntohs(him6->sin6_port);
255 } else
256 #endif /* AF_INET6 */
257 if (him->sa_family == AF_INET) {
258 struct sockaddr_in *him4 = (struct sockaddr_in *)him;
259 static jclass inet4Cls = 0;
260
261 if (inet4Cls == 0) {
262 jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
263 CHECK_NULL_RETURN(c, NULL);
264 inet4Cls = (*env)->NewGlobalRef(env, c);
265 CHECK_NULL_RETURN(inet4Cls, NULL);
266 (*env)->DeleteLocalRef(env, c);
267 }
268 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
269 CHECK_NULL_RETURN(iaObj, NULL);
270 setInetAddress_family(env, iaObj, IPv4);
271 setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
272 *port = ntohs(him4->sin_port);
273 } else {
274 // Unknown family
275 char errmsg[255];
276 snprintf(errmsg, sizeof(errmsg), "Unknown socket family: %d", him->sa_family);
277 JNU_ThrowByName(env, "java/net/SocketException", errmsg);
278 return NULL;
279 }
280 return iaObj;
281 }
282
283 JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv * env,struct sockaddr * him,jobject iaObj)284 NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
285 {
286 jint family = AF_INET;
287
288 #ifdef AF_INET6
289 family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
290 if (him->sa_family == AF_INET6) {
291 #ifdef WIN32
292 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
293 #else
294 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
295 #endif
296 jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
297 if (NET_IsIPv4Mapped(caddrNew)) {
298 int addrNew;
299 int addrCur;
300 if (family == AF_INET6) {
301 return JNI_FALSE;
302 }
303 addrNew = NET_IPv4MappedToIPv4(caddrNew);
304 addrCur = getInetAddress_addr(env, iaObj);
305 if (addrNew == addrCur) {
306 return JNI_TRUE;
307 } else {
308 return JNI_FALSE;
309 }
310 } else {
311 jbyteArray ipaddress;
312 jbyte caddrCur[16];
313 int scope;
314
315 if (family == AF_INET) {
316 return JNI_FALSE;
317 }
318 scope = getInet6Address_scopeid(env, iaObj);
319 getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
320 if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
321 return JNI_TRUE;
322 } else {
323 return JNI_FALSE;
324 }
325 }
326 } else
327 #endif /* AF_INET6 */
328 {
329 struct sockaddr_in *him4 = (struct sockaddr_in *)him;
330 int addrNew, addrCur;
331 if (family != AF_INET) {
332 return JNI_FALSE;
333 }
334 addrNew = ntohl(him4->sin_addr.s_addr);
335 addrCur = getInetAddress_addr(env, iaObj);
336 if (addrNew == addrCur) {
337 return JNI_TRUE;
338 } else {
339 return JNI_FALSE;
340 }
341 }
342 }
343
344 unsigned short
in_cksum(unsigned short * addr,int len)345 in_cksum(unsigned short *addr, int len) {
346 int nleft = len;
347 int sum = 0;
348 unsigned short *w = addr;
349 unsigned short answer = 0;
350 while(nleft > 1) {
351 sum += *w++;
352 nleft -= 2;
353 }
354
355 if (nleft == 1) {
356 *(unsigned char *) (&answer) = *(unsigned char *)w;
357 sum += answer;
358 }
359
360 sum = (sum >> 16) + (sum & 0xffff);
361 sum += (sum >> 16);
362 answer = ~sum;
363 return (answer);
364 }
365