1/* 2 * Copyright 2008, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "NetUtils" 18 19#include "jni.h" 20#include <utils/misc.h> 21#include <android_runtime/AndroidRuntime.h> 22#include <utils/Log.h> 23#include <arpa/inet.h> 24#include <cutils/properties.h> 25 26extern "C" { 27int ifc_enable(const char *ifname); 28int ifc_disable(const char *ifname); 29int ifc_reset_connections(const char *ifname, int reset_mask); 30 31int dhcp_do_request(const char * const ifname, 32 const char *ipaddr, 33 const char *gateway, 34 uint32_t *prefixLength, 35 const char *dns[], 36 const char *server, 37 uint32_t *lease, 38 const char *vendorInfo, 39 const char *domains); 40 41int dhcp_do_request_renew(const char * const ifname, 42 const char *ipaddr, 43 const char *gateway, 44 uint32_t *prefixLength, 45 const char *dns[], 46 const char *server, 47 uint32_t *lease, 48 const char *vendorInfo, 49 const char *domains); 50 51int dhcp_stop(const char *ifname); 52int dhcp_release_lease(const char *ifname); 53char *dhcp_get_errmsg(); 54} 55 56#define NETUTILS_PKG_NAME "android/net/NetworkUtils" 57 58namespace android { 59 60/* 61 * The following remembers the jfieldID's of the fields 62 * of the DhcpInfo Java object, so that we don't have 63 * to look them up every time. 64 */ 65static struct fieldIds { 66 jmethodID clear; 67 jmethodID setInterfaceName; 68 jmethodID addLinkAddress; 69 jmethodID addGateway; 70 jmethodID addDns; 71 jmethodID setDomains; 72 jmethodID setServerAddress; 73 jmethodID setLeaseDuration; 74 jmethodID setVendorInfo; 75} dhcpResultsFieldIds; 76 77static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname) 78{ 79 int result; 80 81 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 82 result = ::ifc_enable(nameStr); 83 env->ReleaseStringUTFChars(ifname, nameStr); 84 return (jint)result; 85} 86 87static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname) 88{ 89 int result; 90 91 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 92 result = ::ifc_disable(nameStr); 93 env->ReleaseStringUTFChars(ifname, nameStr); 94 return (jint)result; 95} 96 97static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, 98 jstring ifname, jint mask) 99{ 100 int result; 101 102 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 103 104 ALOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n", 105 env, clazz, nameStr, mask); 106 107 result = ::ifc_reset_connections(nameStr, mask); 108 env->ReleaseStringUTFChars(ifname, nameStr); 109 return (jint)result; 110} 111 112static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname, 113 jobject dhcpResults, bool renew) 114{ 115 int result; 116 char ipaddr[PROPERTY_VALUE_MAX]; 117 uint32_t prefixLength; 118 char gateway[PROPERTY_VALUE_MAX]; 119 char dns1[PROPERTY_VALUE_MAX]; 120 char dns2[PROPERTY_VALUE_MAX]; 121 char dns3[PROPERTY_VALUE_MAX]; 122 char dns4[PROPERTY_VALUE_MAX]; 123 const char *dns[5] = {dns1, dns2, dns3, dns4, NULL}; 124 char server[PROPERTY_VALUE_MAX]; 125 uint32_t lease; 126 char vendorInfo[PROPERTY_VALUE_MAX]; 127 char domains[PROPERTY_VALUE_MAX]; 128 129 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 130 if (nameStr == NULL) return (jboolean)false; 131 132 if (renew) { 133 result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength, 134 dns, server, &lease, vendorInfo, domains); 135 } else { 136 result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, 137 dns, server, &lease, vendorInfo, domains); 138 } 139 if (result != 0) { 140 ALOGD("dhcp_do_request failed"); 141 } 142 143 env->ReleaseStringUTFChars(ifname, nameStr); 144 if (result == 0) { 145 env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear); 146 147 // set mIfaceName 148 // dhcpResults->setInterfaceName(ifname) 149 env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname); 150 151 // set the linkAddress 152 // dhcpResults->addLinkAddress(inetAddress, prefixLength) 153 result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress, 154 env->NewStringUTF(ipaddr), prefixLength); 155 } 156 157 if (result == 0) { 158 // set the gateway 159 // dhcpResults->addGateway(gateway) 160 result = env->CallBooleanMethod(dhcpResults, 161 dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway)); 162 } 163 164 if (result == 0) { 165 // dhcpResults->addDns(new InetAddress(dns1)) 166 result = env->CallBooleanMethod(dhcpResults, 167 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1)); 168 } 169 170 if (result == 0) { 171 env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains, 172 env->NewStringUTF(domains)); 173 174 result = env->CallBooleanMethod(dhcpResults, 175 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2)); 176 177 if (result == 0) { 178 result = env->CallBooleanMethod(dhcpResults, 179 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3)); 180 if (result == 0) { 181 result = env->CallBooleanMethod(dhcpResults, 182 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4)); 183 } 184 } 185 } 186 187 if (result == 0) { 188 // dhcpResults->setServerAddress(new InetAddress(server)) 189 result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress, 190 env->NewStringUTF(server)); 191 } 192 193 if (result == 0) { 194 // dhcpResults->setLeaseDuration(lease) 195 env->CallVoidMethod(dhcpResults, 196 dhcpResultsFieldIds.setLeaseDuration, lease); 197 198 // dhcpResults->setVendorInfo(vendorInfo) 199 env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo, 200 env->NewStringUTF(vendorInfo)); 201 } 202 return (jboolean)(result == 0); 203} 204 205 206static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info) 207{ 208 return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false); 209} 210 211static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info) 212{ 213 return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true); 214} 215 216 217static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname) 218{ 219 int result; 220 221 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 222 result = ::dhcp_stop(nameStr); 223 env->ReleaseStringUTFChars(ifname, nameStr); 224 return (jboolean)(result == 0); 225} 226 227static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname) 228{ 229 int result; 230 231 const char *nameStr = env->GetStringUTFChars(ifname, NULL); 232 result = ::dhcp_release_lease(nameStr); 233 env->ReleaseStringUTFChars(ifname, nameStr); 234 return (jboolean)(result == 0); 235} 236 237static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz) 238{ 239 return env->NewStringUTF(::dhcp_get_errmsg()); 240} 241 242// ---------------------------------------------------------------------------- 243 244/* 245 * JNI registration. 246 */ 247static JNINativeMethod gNetworkUtilMethods[] = { 248 /* name, signature, funcPtr */ 249 250 { "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface }, 251 { "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface }, 252 { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections }, 253 { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcp }, 254 { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z", (void *)android_net_utils_runDhcpRenew }, 255 { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp }, 256 { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, 257 { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, 258}; 259 260int register_android_net_NetworkUtils(JNIEnv* env) 261{ 262 jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults"); 263 LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults"); 264 dhcpResultsFieldIds.clear = 265 env->GetMethodID(dhcpResultsClass, "clear", "()V"); 266 dhcpResultsFieldIds.setInterfaceName = 267 env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V"); 268 dhcpResultsFieldIds.addLinkAddress = 269 env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z"); 270 dhcpResultsFieldIds.addGateway = 271 env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z"); 272 dhcpResultsFieldIds.addDns = 273 env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z"); 274 dhcpResultsFieldIds.setDomains = 275 env->GetMethodID(dhcpResultsClass, "setDomains", "(Ljava/lang/String;)V"); 276 dhcpResultsFieldIds.setServerAddress = 277 env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z"); 278 dhcpResultsFieldIds.setLeaseDuration = 279 env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V"); 280 dhcpResultsFieldIds.setVendorInfo = 281 env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V"); 282 283 return AndroidRuntime::registerNativeMethods(env, 284 NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods)); 285} 286 287}; // namespace android 288