Path: blob/master/src/java.base/share/native/libnet/net_util.c
41149 views
/*1* Copyright (c) 1998, 2021, 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 "net_util.h"2627#include "java_net_InetAddress.h"2829int IPv4_supported();30int IPv6_supported();31int reuseport_supported();3233static int IPv4_available;34static int IPv6_available;35static int REUSEPORT_available;3637JNIEXPORT jint JNICALL ipv4_available()38{39return IPv4_available;40}4142JNIEXPORT jint JNICALL ipv6_available()43{44return IPv6_available;45}4647JNIEXPORT jint JNICALL reuseport_available()48{49return REUSEPORT_available;50}5152JNIEXPORT jint JNICALL53DEF_JNI_OnLoad(JavaVM *vm, void *reserved)54{55JNIEnv *env;56jclass iCls;57jmethodID mid;58jstring s;59jint preferIPv4Stack;60if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {61return JNI_EVERSION; /* JNI version not supported */62}6364iCls = (*env)->FindClass(env, "java/lang/Boolean");65CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);66mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");67CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);68s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");69CHECK_NULL_RETURN(s, JNI_VERSION_1_2);70preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);7172/*73* Since we have initialized and loaded the socket library we will74* check now whether we have IPv6 on this platform and if the75* supporting socket APIs are available76*/77IPv4_available = IPv4_supported();78IPv6_available = IPv6_supported() & (!preferIPv4Stack);7980/* check if SO_REUSEPORT is supported on this platform */81REUSEPORT_available = reuseport_supported();82platformInit();8384return JNI_VERSION_1_2;85}8687static int initialized = 0;8889JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env) {90if (!initialized) {91Java_java_net_InetAddress_init(env, 0);92JNU_CHECK_EXCEPTION(env);93Java_java_net_Inet4Address_init(env, 0);94JNU_CHECK_EXCEPTION(env);95Java_java_net_Inet6Address_init(env, 0);96JNU_CHECK_EXCEPTION(env);97initialized = 1;98}99}100101/* The address, and family fields used to be in InetAddress102* but are now in an implementation object. So, there is an extra103* level of indirection to access them now.104*/105106extern jclass iac_class;107extern jfieldID ia_holderID;108extern jfieldID iac_addressID;109extern jfieldID iac_familyID;110111/**112* set_ methods return JNI_TRUE on success JNI_FALSE on error113* get_ methods that return +ve int return -1 on error114* get_ methods that return objects return NULL on error.115*/116jboolean setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {117jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);118CHECK_NULL_RETURN(holder, JNI_FALSE);119(*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);120(*env)->DeleteLocalRef(env, holder);121return JNI_TRUE;122}123124unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {125unsigned int id;126jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);127CHECK_NULL_RETURN(holder, 0);128id = (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID);129(*env)->DeleteLocalRef(env, holder);130return id;131}132133jboolean setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {134jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);135CHECK_NULL_RETURN(holder, JNI_FALSE);136(*env)->SetIntField(env, holder, ia6_scopeidID, scopeid);137if (scopeid > 0) {138(*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE);139}140(*env)->DeleteLocalRef(env, holder);141return JNI_TRUE;142}143144jboolean getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) {145jobject holder, addr;146147holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);148CHECK_NULL_RETURN(holder, JNI_FALSE);149addr = (*env)->GetObjectField(env, holder, ia6_ipaddressID);150CHECK_NULL_RETURN(addr, JNI_FALSE);151(*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest);152(*env)->DeleteLocalRef(env, addr);153(*env)->DeleteLocalRef(env, holder);154return JNI_TRUE;155}156157jboolean setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {158jobject holder;159jbyteArray addr;160161holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);162CHECK_NULL_RETURN(holder, JNI_FALSE);163addr = (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);164if (addr == NULL) {165addr = (*env)->NewByteArray(env, 16);166CHECK_NULL_RETURN(addr, JNI_FALSE);167(*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);168}169(*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);170(*env)->DeleteLocalRef(env, addr);171(*env)->DeleteLocalRef(env, holder);172return JNI_TRUE;173}174175void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {176jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);177CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");178(*env)->SetIntField(env, holder, iac_addressID, address);179(*env)->DeleteLocalRef(env, holder);180}181182void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {183jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);184CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");185(*env)->SetIntField(env, holder, iac_familyID, family);186(*env)->DeleteLocalRef(env, holder);187}188189void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {190jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);191CHECK_NULL_THROW_NPE(env, holder, "InetAddress holder is null");192(*env)->SetObjectField(env, holder, iac_hostNameID, host);193(*env)->SetObjectField(env, holder, iac_origHostNameID, host);194(*env)->DeleteLocalRef(env, holder);195}196197int getInetAddress_addr(JNIEnv *env, jobject iaObj) {198int addr;199jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);200CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);201addr = (*env)->GetIntField(env, holder, iac_addressID);202(*env)->DeleteLocalRef(env, holder);203return addr;204}205206int getInetAddress_family(JNIEnv *env, jobject iaObj) {207int family;208jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);209CHECK_NULL_THROW_NPE_RETURN(env, holder, "InetAddress holder is null", -1);210family = (*env)->GetIntField(env, holder, iac_familyID);211(*env)->DeleteLocalRef(env, holder);212return family;213}214215JNIEXPORT jobject JNICALL216NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) {217jobject iaObj;218if (sa->sa.sa_family == AF_INET6) {219jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr;220if (NET_IsIPv4Mapped(caddr)) {221int address;222iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);223CHECK_NULL_RETURN(iaObj, NULL);224address = NET_IPv4MappedToIPv4(caddr);225setInetAddress_addr(env, iaObj, address);226JNU_CHECK_EXCEPTION_RETURN(env, NULL);227setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);228JNU_CHECK_EXCEPTION_RETURN(env, NULL);229} else {230jboolean ret;231iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);232CHECK_NULL_RETURN(iaObj, NULL);233ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr);234if (ret == JNI_FALSE)235return NULL;236setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);237JNU_CHECK_EXCEPTION_RETURN(env, NULL);238setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id);239}240*port = ntohs(sa->sa6.sin6_port);241} else {242iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);243CHECK_NULL_RETURN(iaObj, NULL);244setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);245JNU_CHECK_EXCEPTION_RETURN(env, NULL);246setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr));247JNU_CHECK_EXCEPTION_RETURN(env, NULL);248*port = ntohs(sa->sa4.sin_port);249}250return iaObj;251}252253JNIEXPORT jboolean JNICALL254NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj)255{256jint family = getInetAddress_family(env, iaObj) ==257java_net_InetAddress_IPv4 ? AF_INET : AF_INET6;258JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);259if (sa->sa.sa_family == AF_INET6) {260jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr;261if (NET_IsIPv4Mapped(caddrNew)) {262int addrNew, addrCur;263if (family == AF_INET6) {264return JNI_FALSE;265}266addrNew = NET_IPv4MappedToIPv4(caddrNew);267addrCur = getInetAddress_addr(env, iaObj);268JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);269if (addrNew == addrCur) {270return JNI_TRUE;271} else {272return JNI_FALSE;273}274} else {275jbyte caddrCur[16];276if (family == AF_INET) {277return JNI_FALSE;278}279getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);280if (NET_IsEqual(caddrNew, caddrCur) &&281sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj))282{283return JNI_TRUE;284} else {285return JNI_FALSE;286}287}288} else {289int addrNew, addrCur;290if (family != AF_INET) {291return JNI_FALSE;292}293addrNew = ntohl(sa->sa4.sin_addr.s_addr);294addrCur = getInetAddress_addr(env, iaObj);295JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);296if (addrNew == addrCur) {297return JNI_TRUE;298} else {299return JNI_FALSE;300}301}302}303304JNIEXPORT jint JNICALL305NET_GetPortFromSockaddr(SOCKETADDRESS *sa) {306if (sa->sa.sa_family == AF_INET6) {307return ntohs(sa->sa6.sin6_port);308} else {309return ntohs(sa->sa4.sin_port);310}311}312313unsigned short314in_cksum(unsigned short *addr, int len) {315int nleft = len;316int sum = 0;317unsigned short *w = addr;318unsigned short answer = 0;319while(nleft > 1) {320sum += *w++;321nleft -= 2;322}323324if (nleft == 1) {325*(unsigned char *) (&answer) = *(unsigned char *)w;326sum += answer;327}328329sum = (sum >> 16) + (sum & 0xffff);330sum += (sum >> 16);331answer = ~sum;332return (answer);333}334335336