1 /*
   2  * Copyright 1998-2008 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "jvm.h"
  28 #include "jni_util.h"
  29 #include "net_util.h"
  30 
  31 int IPv6_supported() ;
  32 
  33 static int IPv6_available;
  34 
  35 JNIEXPORT jint JNICALL ipv6_available()
  36 {
  37     return IPv6_available ;
  38 }
  39 
  40 JNIEXPORT jint JNICALL
  41 JNI_OnLoad(JavaVM *vm, void *reserved)
  42 {
  43     JNIEnv *env;
  44     jclass iCls;
  45     jmethodID mid;
  46     jstring s;
  47     jint preferIPv4Stack;
  48 
  49     if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2) == JNI_OK) {
  50         if (JVM_InitializeSocketLibrary() < 0) {
  51             JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError",
  52                             "failed to initialize net library.");
  53             return JNI_VERSION_1_2;
  54         }
  55     }
  56     iCls = (*env)->FindClass(env, "java/lang/Boolean");
  57     CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);
  58     mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");
  59     CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);
  60     s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");
  61     CHECK_NULL_RETURN(s, JNI_VERSION_1_2);
  62     preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
  63 
  64     /*
  65        Since we have initialized and loaded the Socket library we will
  66        check now to whether we have IPv6 on this platform and if the
  67        supporting socket APIs are available
  68     */
  69     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
  70     initLocalAddrTable ();
  71     return JNI_VERSION_1_2;
  72 }
  73 
  74 static int initialized = 0;
  75 
  76 void init(JNIEnv *env) {
  77     if (!initialized) {
  78         Java_java_net_InetAddress_init(env, 0);
  79         Java_java_net_Inet4Address_init(env, 0);
  80         Java_java_net_Inet6Address_init(env, 0);
  81         initialized = 1;
  82     }
  83 }
  84 
  85 JNIEXPORT jobject JNICALL
  86 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
  87     jobject iaObj;
  88     init(env);
  89 #ifdef AF_INET6
  90     if (him->sa_family == AF_INET6) {
  91         jbyteArray ipaddress;
  92 #ifdef WIN32
  93         struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
  94 #else
  95         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
  96 #endif
  97         jbyte *caddr = (jbyte *)&(him6->sin6_addr);
  98         if (NET_IsIPv4Mapped(caddr)) {
  99             int address;
 100             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);








 101             CHECK_NULL_RETURN(iaObj, NULL);
 102             address = NET_IPv4MappedToIPv4(caddr);
 103             (*env)->SetIntField(env, iaObj, ia_addressID, address);
 104             (*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
 105         } else {

 106             jint scope;
 107             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);







 108             CHECK_NULL_RETURN(iaObj, NULL);
 109             ipaddress = (*env)->NewByteArray(env, 16);
 110             CHECK_NULL_RETURN(ipaddress, NULL);
 111             (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
 112                                        (jbyte *)&(him6->sin6_addr));
 113 
 114             (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
 115 
 116             (*env)->SetIntField(env, iaObj, ia_familyID, IPv6);
 117             scope = getScopeID(him);
 118             (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
 119             if (scope > 0)
 120                 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
 121         }
 122         *port = ntohs(him6->sin6_port);
 123     } else
 124 #endif /* AF_INET6 */
 125         {
 126             struct sockaddr_in *him4 = (struct sockaddr_in *)him;
 127             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);









 128             CHECK_NULL_RETURN(iaObj, NULL);
 129             (*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
 130             (*env)->SetIntField(env, iaObj, ia_addressID,
 131                                 ntohl(him4->sin_addr.s_addr));
 132             *port = ntohs(him4->sin_port);
 133         }
 134     return iaObj;
 135 }
 136 
 137 JNIEXPORT jint JNICALL
 138 NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
 139 {
 140     jint family = AF_INET;
 141 
 142 #ifdef AF_INET6
 143     family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?
 144         AF_INET : AF_INET6;
 145     if (him->sa_family == AF_INET6) {
 146 #ifdef WIN32
 147         struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
 148 #else
 149         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
 150 #endif
 151         jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
 152         if (NET_IsIPv4Mapped(caddrNew)) {
 153             int addrNew;
 154             int addrCur;
 155             if (family == AF_INET6) {
 156                 return JNI_FALSE;
 157             }
 158             addrNew = NET_IPv4MappedToIPv4(caddrNew);
 159             addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
 160             if (addrNew == addrCur) {
 161                 return JNI_TRUE;
 162             } else {
 163                 return JNI_FALSE;
 164             }
 165         } else {
 166             jbyteArray ipaddress;
 167             jbyte caddrCur[16];
 168             int scope;
 169 
 170             if (family == AF_INET) {
 171                 return JNI_FALSE;
 172             }
 173             ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
 174             scope = (*env)->GetIntField(env, iaObj, ia6_scopeidID);
 175             (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddrCur);
 176             if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
 177                 return JNI_TRUE;
 178             } else {
 179                 return JNI_FALSE;
 180             }
 181         }
 182     } else
 183 #endif /* AF_INET6 */
 184         {
 185             struct sockaddr_in *him4 = (struct sockaddr_in *)him;
 186             int addrNew, addrCur;
 187             if (family != AF_INET) {
 188                 return JNI_FALSE;
 189             }
 190             addrNew = ntohl(him4->sin_addr.s_addr);
 191             addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
 192             if (addrNew == addrCur) {
 193                 return JNI_TRUE;
 194             } else {
 195                 return JNI_FALSE;
 196             }
 197         }
 198 }
 199 
 200 unsigned short
 201 in_cksum(unsigned short *addr, int len) {
 202     int nleft = len;
 203     int sum = 0;
 204     unsigned short *w = addr;
 205     unsigned short answer = 0;
 206     while(nleft > 1) {
 207         sum += *w++;
 208         nleft -= 2;
 209     }
 210 
 211     if (nleft == 1) {
 212         *(unsigned char *) (&answer) = *(unsigned char *)w;
 213         sum += answer;
 214     }
 215 
 216     sum = (sum >> 16) + (sum & 0xffff);
 217     sum += (sum >> 16);
 218     answer = ~sum;
 219     return (answer);
 220 }
--- EOF ---