src/java.base/share/native/libnet/net_util.c
changeset 47216 71c04702a3d5
parent 43100 a7e3457672c7
child 51151 d6b131d2bc8b
child 56230 489867818774
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1998, 2017, 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 IPv6_supported();
       
    31 int reuseport_supported();
       
    32 
       
    33 static int IPv6_available;
       
    34 static int REUSEPORT_available;
       
    35 
       
    36 JNIEXPORT jint JNICALL ipv6_available()
       
    37 {
       
    38     return IPv6_available;
       
    39 }
       
    40 
       
    41 JNIEXPORT jint JNICALL reuseport_available()
       
    42 {
       
    43     return REUSEPORT_available;
       
    44 }
       
    45 
       
    46 JNIEXPORT jint JNICALL
       
    47 DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
       
    48 {
       
    49     JNIEnv *env;
       
    50     jclass iCls;
       
    51     jmethodID mid;
       
    52     jstring s;
       
    53     jint preferIPv4Stack;
       
    54     if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
       
    55         return JNI_EVERSION; /* JNI version not supported */
       
    56     }
       
    57 
       
    58     iCls = (*env)->FindClass(env, "java/lang/Boolean");
       
    59     CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);
       
    60     mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");
       
    61     CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);
       
    62     s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");
       
    63     CHECK_NULL_RETURN(s, JNI_VERSION_1_2);
       
    64     preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
       
    65 
       
    66     /*
       
    67      * Since we have initialized and loaded the socket library we will
       
    68      * check now whether we have IPv6 on this platform and if the
       
    69      * supporting socket APIs are available
       
    70      */
       
    71     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
       
    72 
       
    73     /* check if SO_REUSEPORT is supported on this platform */
       
    74     REUSEPORT_available = reuseport_supported();
       
    75     platformInit();
       
    76     parseExclusiveBindProperty(env);
       
    77 
       
    78     return JNI_VERSION_1_2;
       
    79 }
       
    80 
       
    81 static int initialized = 0;
       
    82 
       
    83 JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env) {
       
    84     if (!initialized) {
       
    85         Java_java_net_InetAddress_init(env, 0);
       
    86         JNU_CHECK_EXCEPTION(env);
       
    87         Java_java_net_Inet4Address_init(env, 0);
       
    88         JNU_CHECK_EXCEPTION(env);
       
    89         Java_java_net_Inet6Address_init(env, 0);
       
    90         JNU_CHECK_EXCEPTION(env);
       
    91         initialized = 1;
       
    92     }
       
    93 }
       
    94 
       
    95 /* The address, and family fields used to be in InetAddress
       
    96  * but are now in an implementation object. So, there is an extra
       
    97  * level of indirection to access them now.
       
    98  */
       
    99 
       
   100 extern jclass iac_class;
       
   101 extern jfieldID ia_holderID;
       
   102 extern jfieldID iac_addressID;
       
   103 extern jfieldID iac_familyID;
       
   104 
       
   105 /**
       
   106  * set_ methods return JNI_TRUE on success JNI_FALSE on error
       
   107  * get_ methods that return +ve int return -1 on error
       
   108  * get_ methods that return objects return NULL on error.
       
   109  */
       
   110 jobject getInet6Address_scopeifname(JNIEnv *env, jobject iaObj) {
       
   111     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
       
   112     CHECK_NULL_RETURN(holder, NULL);
       
   113     return (*env)->GetObjectField(env, holder, ia6_scopeifnameID);
       
   114 }
       
   115 
       
   116 jboolean setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) {
       
   117     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
       
   118     CHECK_NULL_RETURN(holder, JNI_FALSE);
       
   119     (*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname);
       
   120     return JNI_TRUE;
       
   121 }
       
   122 
       
   123 jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
       
   124     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
       
   125     CHECK_NULL_RETURN(holder, JNI_FALSE);
       
   126     return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);
       
   127 }
       
   128 
       
   129 unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
       
   130     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
       
   131     CHECK_NULL_RETURN(holder, 0);
       
   132     return (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID);
       
   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     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     return JNI_TRUE;
       
   154 }
       
   155 
       
   156 jboolean setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) {
       
   157     jobject holder;
       
   158     jbyteArray addr;
       
   159 
       
   160     holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
       
   161     CHECK_NULL_RETURN(holder, JNI_FALSE);
       
   162     addr =  (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID);
       
   163     if (addr == NULL) {
       
   164         addr = (*env)->NewByteArray(env, 16);
       
   165         CHECK_NULL_RETURN(addr, JNI_FALSE);
       
   166         (*env)->SetObjectField(env, holder, ia6_ipaddressID, addr);
       
   167     }
       
   168     (*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address);
       
   169     return JNI_TRUE;
       
   170 }
       
   171 
       
   172 void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
       
   173     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   174     (*env)->SetIntField(env, holder, iac_addressID, address);
       
   175 }
       
   176 
       
   177 void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
       
   178     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   179     (*env)->SetIntField(env, holder, iac_familyID, family);
       
   180 }
       
   181 
       
   182 void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
       
   183     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   184     (*env)->SetObjectField(env, holder, iac_hostNameID, host);
       
   185     (*env)->SetObjectField(env, holder, iac_origHostNameID, host);
       
   186 }
       
   187 
       
   188 int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
       
   189     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   190     return (*env)->GetIntField(env, holder, iac_addressID);
       
   191 }
       
   192 
       
   193 int getInetAddress_family(JNIEnv *env, jobject iaObj) {
       
   194     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   195     return (*env)->GetIntField(env, holder, iac_familyID);
       
   196 }
       
   197 
       
   198 jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
       
   199     jobject holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
       
   200     return (*env)->GetObjectField(env, holder, iac_hostNameID);
       
   201 }
       
   202 
       
   203 JNIEXPORT jobject JNICALL
       
   204 NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) {
       
   205     jobject iaObj;
       
   206     if (sa->sa.sa_family == AF_INET6) {
       
   207         jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr;
       
   208         if (NET_IsIPv4Mapped(caddr)) {
       
   209             int address;
       
   210             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
       
   211             CHECK_NULL_RETURN(iaObj, NULL);
       
   212             address = NET_IPv4MappedToIPv4(caddr);
       
   213             setInetAddress_addr(env, iaObj, address);
       
   214             setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
       
   215         } else {
       
   216             jboolean ret;
       
   217             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
       
   218             CHECK_NULL_RETURN(iaObj, NULL);
       
   219             ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr);
       
   220             if (ret == JNI_FALSE)
       
   221                 return NULL;
       
   222             setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
       
   223             setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id);
       
   224         }
       
   225         *port = ntohs(sa->sa6.sin6_port);
       
   226     } else {
       
   227         iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
       
   228         CHECK_NULL_RETURN(iaObj, NULL);
       
   229         setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
       
   230         setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr));
       
   231         *port = ntohs(sa->sa4.sin_port);
       
   232     }
       
   233     return iaObj;
       
   234 }
       
   235 
       
   236 JNIEXPORT jboolean JNICALL
       
   237 NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj)
       
   238 {
       
   239     jint family = getInetAddress_family(env, iaObj) ==
       
   240         java_net_InetAddress_IPv4 ? AF_INET : AF_INET6;
       
   241     if (sa->sa.sa_family == AF_INET6) {
       
   242         jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr;
       
   243         if (NET_IsIPv4Mapped(caddrNew)) {
       
   244             int addrNew, addrCur;
       
   245             if (family == AF_INET6) {
       
   246                 return JNI_FALSE;
       
   247             }
       
   248             addrNew = NET_IPv4MappedToIPv4(caddrNew);
       
   249             addrCur = getInetAddress_addr(env, iaObj);
       
   250             if (addrNew == addrCur) {
       
   251                 return JNI_TRUE;
       
   252             } else {
       
   253                 return JNI_FALSE;
       
   254             }
       
   255         } else {
       
   256             jbyte caddrCur[16];
       
   257             if (family == AF_INET) {
       
   258                 return JNI_FALSE;
       
   259             }
       
   260             getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
       
   261             if (NET_IsEqual(caddrNew, caddrCur) &&
       
   262                 sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj))
       
   263             {
       
   264                 return JNI_TRUE;
       
   265             } else {
       
   266                 return JNI_FALSE;
       
   267             }
       
   268         }
       
   269     } else {
       
   270         int addrNew, addrCur;
       
   271         if (family != AF_INET) {
       
   272             return JNI_FALSE;
       
   273         }
       
   274         addrNew = ntohl(sa->sa4.sin_addr.s_addr);
       
   275         addrCur = getInetAddress_addr(env, iaObj);
       
   276         if (addrNew == addrCur) {
       
   277             return JNI_TRUE;
       
   278         } else {
       
   279             return JNI_FALSE;
       
   280         }
       
   281     }
       
   282 }
       
   283 
       
   284 JNIEXPORT jint JNICALL
       
   285 NET_GetPortFromSockaddr(SOCKETADDRESS *sa) {
       
   286     if (sa->sa.sa_family == AF_INET6) {
       
   287         return ntohs(sa->sa6.sin6_port);
       
   288     } else {
       
   289         return ntohs(sa->sa4.sin_port);
       
   290     }
       
   291 }
       
   292 
       
   293 unsigned short
       
   294 in_cksum(unsigned short *addr, int len) {
       
   295     int nleft = len;
       
   296     int sum = 0;
       
   297     unsigned short *w = addr;
       
   298     unsigned short answer = 0;
       
   299     while(nleft > 1) {
       
   300         sum += *w++;
       
   301         nleft -= 2;
       
   302     }
       
   303 
       
   304     if (nleft == 1) {
       
   305         *(unsigned char *) (&answer) = *(unsigned char *)w;
       
   306         sum += answer;
       
   307     }
       
   308 
       
   309     sum = (sum >> 16) + (sum & 0xffff);
       
   310     sum += (sum >> 16);
       
   311     answer = ~sum;
       
   312     return (answer);
       
   313 }