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 "JNIHelp.h"
     21 #include <utils/misc.h>
     22 #include <android_runtime/AndroidRuntime.h>
     23 #include <utils/Log.h>
     24 #include <arpa/inet.h>
     25 #include <cutils/properties.h>
     26 
     27 extern "C" {
     28 int ifc_enable(const char *ifname);
     29 int ifc_disable(const char *ifname);
     30 int ifc_reset_connections(const char *ifname, int reset_mask);
     31 
     32 int dhcp_do_request(const char * const ifname,
     33                     const char *ipaddr,
     34                     const char *gateway,
     35                     uint32_t *prefixLength,
     36                     const char *dns[],
     37                     const char *server,
     38                     uint32_t *lease,
     39                     const char *vendorInfo,
     40                     const char *domains,
     41                     const char *mtu);
     42 
     43 int dhcp_do_request_renew(const char * const ifname,
     44                     const char *ipaddr,
     45                     const char *gateway,
     46                     uint32_t *prefixLength,
     47                     const char *dns[],
     48                     const char *server,
     49                     uint32_t *lease,
     50                     const char *vendorInfo,
     51                     const char *domains,
     52                     const char *mtu);
     53 
     54 int dhcp_stop(const char *ifname);
     55 int dhcp_release_lease(const char *ifname);
     56 char *dhcp_get_errmsg();
     57 }
     58 
     59 #define NETUTILS_PKG_NAME "android/net/NetworkUtils"
     60 
     61 namespace android {
     62 
     63 /*
     64  * The following remembers the jfieldID's of the fields
     65  * of the DhcpInfo Java object, so that we don't have
     66  * to look them up every time.
     67  */
     68 static struct fieldIds {
     69     jmethodID clear;
     70     jmethodID setInterfaceName;
     71     jmethodID addLinkAddress;
     72     jmethodID addGateway;
     73     jmethodID addDns;
     74     jmethodID setDomains;
     75     jmethodID setServerAddress;
     76     jmethodID setLeaseDuration;
     77     jmethodID setVendorInfo;
     78 } dhcpResultsFieldIds;
     79 
     80 static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
     81 {
     82     int result;
     83 
     84     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     85     result = ::ifc_enable(nameStr);
     86     env->ReleaseStringUTFChars(ifname, nameStr);
     87     return (jint)result;
     88 }
     89 
     90 static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname)
     91 {
     92     int result;
     93 
     94     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     95     result = ::ifc_disable(nameStr);
     96     env->ReleaseStringUTFChars(ifname, nameStr);
     97     return (jint)result;
     98 }
     99 
    100 static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
    101       jstring ifname, jint mask)
    102 {
    103     int result;
    104 
    105     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    106 
    107     ALOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
    108           env, clazz, nameStr, mask);
    109 
    110     result = ::ifc_reset_connections(nameStr, mask);
    111     env->ReleaseStringUTFChars(ifname, nameStr);
    112     return (jint)result;
    113 }
    114 
    115 static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
    116         jobject dhcpResults, bool renew)
    117 {
    118     int result;
    119     char  ipaddr[PROPERTY_VALUE_MAX];
    120     uint32_t prefixLength;
    121     char gateway[PROPERTY_VALUE_MAX];
    122     char    dns1[PROPERTY_VALUE_MAX];
    123     char    dns2[PROPERTY_VALUE_MAX];
    124     char    dns3[PROPERTY_VALUE_MAX];
    125     char    dns4[PROPERTY_VALUE_MAX];
    126     const char *dns[5] = {dns1, dns2, dns3, dns4, NULL};
    127     char  server[PROPERTY_VALUE_MAX];
    128     uint32_t lease;
    129     char vendorInfo[PROPERTY_VALUE_MAX];
    130     char domains[PROPERTY_VALUE_MAX];
    131     char mtu[PROPERTY_VALUE_MAX];
    132 
    133     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    134     if (nameStr == NULL) return (jboolean)false;
    135 
    136     if (renew) {
    137         result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
    138                 dns, server, &lease, vendorInfo, domains, mtu);
    139     } else {
    140         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
    141                 dns, server, &lease, vendorInfo, domains, mtu);
    142     }
    143     if (result != 0) {
    144         ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new");
    145     }
    146 
    147     env->ReleaseStringUTFChars(ifname, nameStr);
    148     if (result == 0) {
    149         env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
    150 
    151         // set mIfaceName
    152         // dhcpResults->setInterfaceName(ifname)
    153         env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
    154 
    155         // set the linkAddress
    156         // dhcpResults->addLinkAddress(inetAddress, prefixLength)
    157         result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
    158                 env->NewStringUTF(ipaddr), prefixLength);
    159     }
    160 
    161     if (result == 0) {
    162         // set the gateway
    163         // dhcpResults->addGateway(gateway)
    164         result = env->CallBooleanMethod(dhcpResults,
    165                 dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
    166     }
    167 
    168     if (result == 0) {
    169         // dhcpResults->addDns(new InetAddress(dns1))
    170         result = env->CallBooleanMethod(dhcpResults,
    171                 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
    172     }
    173 
    174     if (result == 0) {
    175         env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains,
    176                 env->NewStringUTF(domains));
    177 
    178         result = env->CallBooleanMethod(dhcpResults,
    179                 dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
    180 
    181         if (result == 0) {
    182             result = env->CallBooleanMethod(dhcpResults,
    183                     dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3));
    184             if (result == 0) {
    185                 result = env->CallBooleanMethod(dhcpResults,
    186                         dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4));
    187             }
    188         }
    189     }
    190 
    191     if (result == 0) {
    192         // dhcpResults->setServerAddress(new InetAddress(server))
    193         result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
    194                 env->NewStringUTF(server));
    195     }
    196 
    197     if (result == 0) {
    198         // dhcpResults->setLeaseDuration(lease)
    199         env->CallVoidMethod(dhcpResults,
    200                 dhcpResultsFieldIds.setLeaseDuration, lease);
    201 
    202         // dhcpResults->setVendorInfo(vendorInfo)
    203         env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
    204                 env->NewStringUTF(vendorInfo));
    205     }
    206     return (jboolean)(result == 0);
    207 }
    208 
    209 
    210 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
    211 {
    212     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
    213 }
    214 
    215 static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
    216 {
    217     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
    218 }
    219 
    220 
    221 static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
    222 {
    223     int result;
    224 
    225     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    226     result = ::dhcp_stop(nameStr);
    227     env->ReleaseStringUTFChars(ifname, nameStr);
    228     return (jboolean)(result == 0);
    229 }
    230 
    231 static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
    232 {
    233     int result;
    234 
    235     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
    236     result = ::dhcp_release_lease(nameStr);
    237     env->ReleaseStringUTFChars(ifname, nameStr);
    238     return (jboolean)(result == 0);
    239 }
    240 
    241 static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
    242 {
    243     return env->NewStringUTF(::dhcp_get_errmsg());
    244 }
    245 
    246 static void android_net_utils_markSocket(JNIEnv *env, jobject thiz, jint socket, jint mark)
    247 {
    248     if (setsockopt(socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
    249         jniThrowException(env, "java/lang/IllegalStateException", "Error marking socket");
    250     }
    251 }
    252 
    253 // ----------------------------------------------------------------------------
    254 
    255 /*
    256  * JNI registration.
    257  */
    258 static JNINativeMethod gNetworkUtilMethods[] = {
    259     /* name, signature, funcPtr */
    260 
    261     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
    262     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
    263     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
    264     { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
    265     { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
    266     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
    267     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
    268     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
    269     { "markSocket", "(II)V", (void*) android_net_utils_markSocket },
    270 };
    271 
    272 int register_android_net_NetworkUtils(JNIEnv* env)
    273 {
    274     jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults");
    275     LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
    276     dhcpResultsFieldIds.clear =
    277             env->GetMethodID(dhcpResultsClass, "clear", "()V");
    278     dhcpResultsFieldIds.setInterfaceName =
    279             env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
    280     dhcpResultsFieldIds.addLinkAddress =
    281             env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
    282     dhcpResultsFieldIds.addGateway =
    283             env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
    284     dhcpResultsFieldIds.addDns =
    285             env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
    286     dhcpResultsFieldIds.setDomains =
    287             env->GetMethodID(dhcpResultsClass, "setDomains", "(Ljava/lang/String;)V");
    288     dhcpResultsFieldIds.setServerAddress =
    289             env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z");
    290     dhcpResultsFieldIds.setLeaseDuration =
    291             env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V");
    292     dhcpResultsFieldIds.setVendorInfo =
    293             env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V");
    294 
    295     return AndroidRuntime::registerNativeMethods(env,
    296             NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
    297 }
    298 
    299 }; // namespace android
    300