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 } --- EOF ---