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