android_net_NetUtils.cpp revision 4717c261b2c670d5c0925e3527a864aa52db6ac0
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 *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
41int 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
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 setServerAddress;
72    jmethodID setLeaseDuration;
73    jmethodID setVendorInfo;
74} dhcpResultsFieldIds;
75
76static 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
86static 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
96static 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
111static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
112        jobject dhcpResults, 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->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
138
139        // set mIfaceName
140        // dhcpResults->setInterfaceName(ifname)
141        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
142
143        // set the linkAddress
144        // dhcpResults->addLinkAddress(inetAddress, prefixLength)
145        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
146                env->NewStringUTF(ipaddr), prefixLength);
147    }
148
149    if (result == 0) {
150        // set the gateway
151        // dhcpResults->addGateway(gateway)
152        result = env->CallBooleanMethod(dhcpResults,
153                dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
154    }
155
156    if (result == 0) {
157        // dhcpResults->addDns(new InetAddress(dns1))
158        result = env->CallBooleanMethod(dhcpResults,
159                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
160    }
161
162    if (result == 0) {
163        result = env->CallBooleanMethod(dhcpResults,
164                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
165    }
166
167    if (result == 0) {
168        // dhcpResults->setServerAddress(new InetAddress(server))
169        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
170                env->NewStringUTF(server));
171    }
172
173    if (result == 0) {
174        // dhcpResults->setLeaseDuration(lease)
175        env->CallVoidMethod(dhcpResults,
176                dhcpResultsFieldIds.setLeaseDuration, lease);
177
178        // dhcpResults->setVendorInfo(vendorInfo)
179        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
180                env->NewStringUTF(vendorInfo));
181    }
182    return (jboolean)(result == 0);
183}
184
185
186static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
187{
188    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
189}
190
191static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
192{
193    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
194}
195
196
197static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
198{
199    int result;
200
201    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
202    result = ::dhcp_stop(nameStr);
203    env->ReleaseStringUTFChars(ifname, nameStr);
204    return (jboolean)(result == 0);
205}
206
207static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
208{
209    int result;
210
211    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
212    result = ::dhcp_release_lease(nameStr);
213    env->ReleaseStringUTFChars(ifname, nameStr);
214    return (jboolean)(result == 0);
215}
216
217static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
218{
219    return env->NewStringUTF(::dhcp_get_errmsg());
220}
221
222// ----------------------------------------------------------------------------
223
224/*
225 * JNI registration.
226 */
227static JNINativeMethod gNetworkUtilMethods[] = {
228    /* name, signature, funcPtr */
229
230    { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
231    { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
232    { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
233    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
234    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
235    { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
236    { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
237    { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
238};
239
240int register_android_net_NetworkUtils(JNIEnv* env)
241{
242    jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults");
243    LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
244    dhcpResultsFieldIds.clear =
245            env->GetMethodID(dhcpResultsClass, "clear", "()V");
246    dhcpResultsFieldIds.setInterfaceName =
247            env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
248    dhcpResultsFieldIds.addLinkAddress =
249            env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
250    dhcpResultsFieldIds.addGateway =
251            env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
252    dhcpResultsFieldIds.addDns =
253            env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
254    dhcpResultsFieldIds.setServerAddress =
255            env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z");
256    dhcpResultsFieldIds.setLeaseDuration =
257            env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V");
258    dhcpResultsFieldIds.setVendorInfo =
259            env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V");
260
261    return AndroidRuntime::registerNativeMethods(env,
262            NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
263}
264
265}; // namespace android
266