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 ---