Home | History | Annotate | Download | only in jni
      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 
     26 extern "C" {
     27 int ifc_enable(const char *ifname);
     28 int ifc_disable(const char *ifname);
     29 int ifc_reset_connections(const char *ifname, int reset_mask);
     30 
     31 int dhcp_do_request(const char *ifname,
     32                     const char *ipaddr,
     33                     const char *gateway,
     34                     uint32_t *prefixLength,
     35                     const char *dns1,
     36                     const char *dns2,
     37                     const char *server,
     38                     uint32_t *lease,
     39                     const char *vendorInfo);
     40 
     41 int dhcp_do_request_renew(const char *ifname,
     42                     const char *ipaddr,
     43                     const char *gateway,
     44                     uint32_t *prefixLength,
     45                     const char *dns1,
     46                     const char *dns2,
     47                     const char *server,
     48                     uint32_t *lease,
     49                     const char *vendorInfo);
     50 
     51 int dhcp_stop(const char *ifname);
     52 int dhcp_release_lease(const char *ifname);
     53 char *dhcp_get_errmsg();
     54 }
     55 
     56 #define NETUTILS_PKG_NAME "android/net/NetworkUtils"
     57 
     58 namespace 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  */
     65 static struct fieldIds {
     66     jmethodID constructorId;
     67     jfieldID ipaddress;
     68     jfieldID prefixLength;
     69     jfieldID dns1;
     70     jfieldID dns2;
     71     jfieldID serverAddress;
     72     jfieldID leaseDuration;
     73     jfieldID vendorInfo;
     74 } dhcpInfoInternalFieldIds;
     75 
     76 static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
     77 {
     78     int result;
     79 
     80     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     81     result = ::ifc_enable(nameStr);
     82     env->ReleaseStringUTFChars(ifname, nameStr);
     83     return (jint)result;
     84 }
     85 
     86 static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname)
     87 {
     88     int result;
     89 
     90     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     91     result = ::ifc_disable(nameStr);
     92     env->ReleaseStringUTFChars(ifname, nameStr);
     93     return (jint)result;
     94 }
     95 
     96 static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
     97       jstring ifname, jint mask)
     98 {
     99     int result;
    100 
    101     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    102 
    103     ALOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
    104           env, clazz, nameStr, mask);
    105 
    106     result = ::ifc_reset_connections(nameStr, mask);
    107     env->ReleaseStringUTFChars(ifname, nameStr);
    108     return (jint)result;
    109 }
    110 
    111 static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
    112         jobject info, bool renew)
    113 {
    114     int result;
    115     char  ipaddr[PROPERTY_VALUE_MAX];
    116     uint32_t prefixLength;
    117     char gateway[PROPERTY_VALUE_MAX];
    118     char    dns1[PROPERTY_VALUE_MAX];
    119     char    dns2[PROPERTY_VALUE_MAX];
    120     char  server[PROPERTY_VALUE_MAX];
    121     uint32_t lease;
    122     char vendorInfo[PROPERTY_VALUE_MAX];
    123 
    124     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    125     if (nameStr == NULL) return (jboolean)false;
    126 
    127     if (renew) {
    128         result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
    129                 dns1, dns2, server, &lease, vendorInfo);
    130     } else {
    131         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
    132                 dns1, dns2, server, &lease, vendorInfo);
    133     }
    134 
    135     env->ReleaseStringUTFChars(ifname, nameStr);
    136     if (result == 0) {
    137         env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
    138 
    139         // set the gateway
    140         jclass cls = env->FindClass("java/net/InetAddress");
    141         jmethodID method = env->GetStaticMethodID(cls, "getByName",
    142                 "(Ljava/lang/String;)Ljava/net/InetAddress;");
    143         jvalue args[1];
    144         args[0].l = env->NewStringUTF(gateway);
    145         jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
    146 
    147         if (!env->ExceptionOccurred()) {
    148             cls = env->FindClass("android/net/RouteInfo");
    149             method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
    150             args[0].l = inetAddressObject;
    151             jobject routeInfoObject = env->NewObjectA(cls, method, args);
    152 
    153             cls = env->FindClass("android/net/DhcpInfoInternal");
    154             method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
    155             args[0].l = routeInfoObject;
    156             env->CallVoidMethodA(info, method, args);
    157         } else {
    158             // if we have an exception (host not found perhaps), just don't add the route
    159             env->ExceptionClear();
    160         }
    161 
    162         env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
    163         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
    164         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
    165         env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
    166                 env->NewStringUTF(server));
    167         env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
    168         env->SetObjectField(info, dhcpInfoInternalFieldIds.vendorInfo, env->NewStringUTF(vendorInfo));
    169     }
    170     return (jboolean)(result == 0);
    171 }
    172 
    173 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
    174 {
    175     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
    176 }
    177 
    178 static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
    179 {
    180     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
    181 }
    182 
    183 
    184 static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
    185 {
    186     int result;
    187 
    188     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    189     result = ::dhcp_stop(nameStr);
    190     env->ReleaseStringUTFChars(ifname, nameStr);
    191     return (jboolean)(result == 0);
    192 }
    193 
    194 static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
    195 {
    196     int result;
    197 
    198     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    199     result = ::dhcp_release_lease(nameStr);
    200     env->ReleaseStringUTFChars(ifname, nameStr);
    201     return (jboolean)(result == 0);
    202 }
    203 
    204 static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
    205 {
    206     return env->NewStringUTF(::dhcp_get_errmsg());
    207 }
    208 
    209 // ----------------------------------------------------------------------------
    210 
    211 /*
    212  * JNI registration.
    213  */
    214 static JNINativeMethod gNetworkUtilMethods[] = {
    215     /* name, signature, funcPtr */
    216 
    217     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
    218     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
    219     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
    220     { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
    221     { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
    222     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
    223     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
    224     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
    225 };
    226 
    227 int register_android_net_NetworkUtils(JNIEnv* env)
    228 {
    229     jclass dhcpInfoInternalClass = env->FindClass("android/net/DhcpInfoInternal");
    230     LOG_FATAL_IF(dhcpInfoInternalClass == NULL, "Unable to find class android/net/DhcpInfoInternal");
    231     dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalClass, "<init>", "()V");
    232     dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
    233     dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalClass, "prefixLength", "I");
    234     dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
    235     dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
    236     dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
    237     dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalClass, "leaseDuration", "I");
    238     dhcpInfoInternalFieldIds.vendorInfo = env->GetFieldID(dhcpInfoInternalClass, "vendorInfo", "Ljava/lang/String;");
    239 
    240     return AndroidRuntime::registerNativeMethods(env,
    241             NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
    242 }
    243 
    244 }; // namespace android
    245