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 static jclass inet4Cls = 0; 101 if (inet4Cls == 0) { 102 jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); 103 CHECK_NULL_RETURN(c, NULL); 104 inet4Cls = (*env)->NewGlobalRef(env, c); 105 CHECK_NULL_RETURN(inet4Cls, NULL); 106 (*env)->DeleteLocalRef(env, c); 107 } 108 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); 109 CHECK_NULL_RETURN(iaObj, NULL); 110 address = NET_IPv4MappedToIPv4(caddr); 111 (*env)->SetIntField(env, iaObj, ia_addressID, address); 112 (*env)->SetIntField(env, iaObj, ia_familyID, IPv4); 113 } else { 114 static jclass inet6Cls = 0; 115 jint scope; 116 if (inet6Cls == 0) { 117 jclass c = (*env)->FindClass(env, "java/net/Inet6Address"); 118 CHECK_NULL_RETURN(c, NULL); 119 inet6Cls = (*env)->NewGlobalRef(env, c); 120 CHECK_NULL_RETURN(inet6Cls, NULL); 121 (*env)->DeleteLocalRef(env, c); 122 } 123 iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); 124 CHECK_NULL_RETURN(iaObj, NULL); 125 ipaddress = (*env)->NewByteArray(env, 16); 126 CHECK_NULL_RETURN(ipaddress, NULL); 127 (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, 128 (jbyte *)&(him6->sin6_addr)); 129 130 (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress); 131 132 (*env)->SetIntField(env, iaObj, ia_familyID, IPv6); 133 scope = getScopeID(him); 134 (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); 135 if (scope > 0) 136 (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); 137 } 138 *port = ntohs(him6->sin6_port); 139 } else 140 #endif /* AF_INET6 */ 141 { 142 struct sockaddr_in *him4 = (struct sockaddr_in *)him; 143 static jclass inet4Cls = 0; 144 145 if (inet4Cls == 0) { 146 jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); 147 CHECK_NULL_RETURN(c, NULL); 148 inet4Cls = (*env)->NewGlobalRef(env, c); 149 CHECK_NULL_RETURN(inet4Cls, NULL); 150 (*env)->DeleteLocalRef(env, c); 151 } 152 iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); 153 CHECK_NULL_RETURN(iaObj, NULL); 154 (*env)->SetIntField(env, iaObj, ia_familyID, IPv4); 155 (*env)->SetIntField(env, iaObj, ia_addressID, 156 ntohl(him4->sin_addr.s_addr)); 157 *port = ntohs(him4->sin_port); 158 } 159 return iaObj; 160 } 161 162 JNIEXPORT jint JNICALL 163 NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) 164 { 165 jint family = AF_INET; 166 167 #ifdef AF_INET6 168 family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4? 169 AF_INET : AF_INET6; 170 if (him->sa_family == AF_INET6) { 171 #ifdef WIN32 172 struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; 173 #else 174 struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; 175 #endif 176 jbyte *caddrNew = (jbyte *)&(him6->sin6_addr); 177 if (NET_IsIPv4Mapped(caddrNew)) { 178 int addrNew; 179 int addrCur; 180 if (family == AF_INET6) { 181 return JNI_FALSE; 182 } 183 addrNew = NET_IPv4MappedToIPv4(caddrNew); 184 addrCur = (*env)->GetIntField(env, iaObj, ia_addressID); 185 if (addrNew == addrCur) { 186 return JNI_TRUE; 187 } else { 188 return JNI_FALSE; 189 } 190 } else { 191 jbyteArray ipaddress; 192 jbyte caddrCur[16]; 193 int scope; 194 195 if (family == AF_INET) { 196 return JNI_FALSE; 197 } 198 ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); 199 scope = (*env)->GetIntField(env, iaObj, ia6_scopeidID); 200 (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddrCur); 201 if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) { 202 return JNI_TRUE; 203 } else { 204 return JNI_FALSE; 205 } 206 } 207 } else 208 #endif /* AF_INET6 */ 209 { 210 struct sockaddr_in *him4 = (struct sockaddr_in *)him; 211 int addrNew, addrCur; 212 if (family != AF_INET) { 213 return JNI_FALSE; 214 } 215 addrNew = ntohl(him4->sin_addr.s_addr); 216 addrCur = (*env)->GetIntField(env, iaObj, ia_addressID); 217 if (addrNew == addrCur) { 218 return JNI_TRUE; 219 } else { 220 return JNI_FALSE; 221 } 222 } 223 } 224 225 unsigned short 226 in_cksum(unsigned short *addr, int len) { 227 int nleft = len; 228 int sum = 0; 229 unsigned short *w = addr; 230 unsigned short answer = 0; 231 while(nleft > 1) { 232 sum += *w++; 233 nleft -= 2; 234 } 235 236 if (nleft == 1) { 237 *(unsigned char *) (&answer) = *(unsigned char *)w; 238 sum += answer; 239 } 240 241 sum = (sum >> 16) + (sum & 0xffff); 242 sum += (sum >> 16); 243 answer = ~sum; 244 return (answer); 245 } --- EOF ---