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