Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/java/net/net_util.c
38829 views
/*1* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "jni.h"26#include "jvm.h"27#include "jni_util.h"28#include "net_util.h"2930int IPv6_supported() ;3132static int IPv6_available;3334JNIEXPORT jint JNICALL ipv6_available()35{36return IPv6_available ;37}3839JNIEXPORT jint JNICALL40JNI_OnLoad(JavaVM *vm, void *reserved)41{42JNIEnv *env;43jclass iCls;44jmethodID mid;45jstring s;46jint preferIPv4Stack;4748if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2) == JNI_OK) {49if (JVM_InitializeSocketLibrary() < 0) {50JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError",51"failed to initialize net library.");52return JNI_VERSION_1_2;53}54}55iCls = (*env)->FindClass(env, "java/lang/Boolean");56CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);57mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");58CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);59s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");60CHECK_NULL_RETURN(s, JNI_VERSION_1_2);61preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);6263/*64Since we have initialized and loaded the Socket library we will65check now to whether we have IPv6 on this platform and if the66supporting socket APIs are available67*/68IPv6_available = IPv6_supported() & (!preferIPv4Stack);69platformInit();70parseExclusiveBindProperty(env);7172return JNI_VERSION_1_2;73}7475static int initialized = 0;7677JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env) {78if (!initialized) {79Java_java_net_InetAddress_init(env, 0);80JNU_CHECK_EXCEPTION(env);81Java_java_net_Inet4Address_init(env, 0);82JNU_CHECK_EXCEPTION(env);83Java_java_net_Inet6Address_init(env, 0);84JNU_CHECK_EXCEPTION(env);85initialized = 1;86}87}8889/* The address, and family fields used to be in InetAddress90* but are now in an implementation object. So, there is an extra91* level of indirection to access them now.92*/9394extern jclass iac_class;95extern jfieldID ia_holderID;96extern jfieldID iac_addressID;97extern jfieldID iac_familyID;9899/**100* set_ methods return JNI_TRUE on success JNI_FALSE on error101* get_ methods that return +ve int return -1 on error102* get_ methods that return objects return NULL on error.103*/104jobject getInet6Address_scopeifname(JNIEnv *env, jobject iaObj) {105jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);106CHECK_NULL_RETURN(holder, NULL);107return (*env)->GetObjectField(env, holder, ia6_scopeifnameID);108}109110int setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {111jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);112CHECK_NULL_RETURN(holder, JNI_FALSE);113(*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);114return JNI_TRUE;115}116117int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {118jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);119CHECK_NULL_RETURN(holder, -1);120return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);121}122123int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {124jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);125CHECK_NULL_RETURN(holder, -1);126return (*env)->GetIntField(env, holder, ia6_scopeidID);127}128129int setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {130jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);131CHECK_NULL_RETURN(holder, JNI_FALSE);132(*env)->SetIntField(env, holder, ia6_scopeidID, scopeid);133if (scopeid > 0) {134(*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE);135}136return JNI_TRUE;137}138139140int getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) {141jobject holder, addr;142jbyteArray barr;143144holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);145CHECK_NULL_RETURN(holder, JNI_FALSE);146addr = (*env)->GetObjectField(env, holder, ia6_ipaddressID);147CHECK_NULL_RETURN(addr, JNI_FALSE);148(*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest);149return JNI_TRUE;150}151152int setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {153jobject holder;154jbyteArray addr;155156holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);157CHECK_NULL_RETURN(holder, JNI_FALSE);158addr = (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);159if (addr == NULL) {160addr = (*env)->NewByteArray(env, 16);161CHECK_NULL_RETURN(addr, JNI_FALSE);162(*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);163}164(*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);165return JNI_TRUE;166}167168void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {169jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);170CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");171(*env)->SetIntField(env, holder, iac_addressID, address);172}173174void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {175jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);176CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");177(*env)->SetIntField(env, holder, iac_familyID, family);178}179180void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {181jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);182CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");183(*env)->SetObjectField(env, holder, iac_hostNameID, host);184(*env)->SetObjectField(env, holder, iac_origHostNameID, host);185}186187int getInetAddress_addr(JNIEnv *env, jobject iaObj) {188jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);189CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);190return (*env)->GetIntField(env, holder, iac_addressID);191}192193int getInetAddress_family(JNIEnv *env, jobject iaObj) {194jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);195CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);196return (*env)->GetIntField(env, holder, iac_familyID);197}198199jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {200jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);201CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", NULL);202return (*env)->GetObjectField(env, holder, iac_hostNameID);203}204205JNIEXPORT jobject JNICALL206NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {207jobject iaObj;208#ifdef AF_INET6209if (him->sa_family == AF_INET6) {210jbyteArray ipaddress;211#ifdef WIN32212struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;213#else214struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;215#endif216jbyte *caddr = (jbyte *)&(him6->sin6_addr);217if (NET_IsIPv4Mapped(caddr)) {218int address;219iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);220CHECK_NULL_RETURN(iaObj, NULL);221address = NET_IPv4MappedToIPv4(caddr);222setInetAddress_addr(env, iaObj, address);223JNU_CHECK_EXCEPTION_RETURN(env, NULL);224setInetAddress_family(env, iaObj, IPv4);225JNU_CHECK_EXCEPTION_RETURN(env, NULL);226} else {227jint scope;228int ret;229iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);230CHECK_NULL_RETURN(iaObj, NULL);231ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));232CHECK_NULL_RETURN(ret, NULL);233setInetAddress_family(env, iaObj, IPv6);234JNU_CHECK_EXCEPTION_RETURN(env, NULL);235scope = getScopeID(him);236setInet6Address_scopeid(env, iaObj, scope);237}238*port = ntohs(him6->sin6_port);239} else240#endif /* AF_INET6 */241{242struct sockaddr_in *him4 = (struct sockaddr_in *)him;243iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);244CHECK_NULL_RETURN(iaObj, NULL);245setInetAddress_family(env, iaObj, IPv4);246JNU_CHECK_EXCEPTION_RETURN(env, NULL);247setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));248JNU_CHECK_EXCEPTION_RETURN(env, NULL);249*port = ntohs(him4->sin_port);250}251return iaObj;252}253254JNIEXPORT jint JNICALL255NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)256{257jint family = AF_INET;258259#ifdef AF_INET6260family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;261JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);262if (him->sa_family == AF_INET6) {263#ifdef WIN32264struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;265#else266struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;267#endif268jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);269if (NET_IsIPv4Mapped(caddrNew)) {270int addrNew;271int addrCur;272if (family == AF_INET6) {273return JNI_FALSE;274}275addrNew = NET_IPv4MappedToIPv4(caddrNew);276addrCur = getInetAddress_addr(env, iaObj);277JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);278if (addrNew == addrCur) {279return JNI_TRUE;280} else {281return JNI_FALSE;282}283} else {284jbyteArray ipaddress;285jbyte caddrCur[16];286int scope;287288if (family == AF_INET) {289return JNI_FALSE;290}291scope = getInet6Address_scopeid(env, iaObj);292getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);293if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {294return JNI_TRUE;295} else {296return JNI_FALSE;297}298}299} else300#endif /* AF_INET6 */301{302struct sockaddr_in *him4 = (struct sockaddr_in *)him;303int addrNew, addrCur;304if (family != AF_INET) {305return JNI_FALSE;306}307addrNew = ntohl(him4->sin_addr.s_addr);308addrCur = getInetAddress_addr(env, iaObj);309JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);310if (addrNew == addrCur) {311return JNI_TRUE;312} else {313return JNI_FALSE;314}315}316}317318unsigned short319in_cksum(unsigned short *addr, int len) {320int nleft = len;321int sum = 0;322unsigned short *w = addr;323unsigned short answer = 0;324while(nleft > 1) {325sum += *w++;326nleft -= 2;327}328329if (nleft == 1) {330*(unsigned char *) (&answer) = *(unsigned char *)w;331sum += answer;332}333334sum = (sum >> 16) + (sum & 0xffff);335sum += (sum >> 16);336answer = ~sum;337return (answer);338}339340341