android_net_NetUtils.cpp revision 31be7cf4c7aef140f2a576975a7fd31e062f6964
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_add_route(const char *ifname, const char *destStr, uint32_t prefixLen, const char *gwStr);
30int ifc_remove_host_routes(const char *ifname);
31int ifc_get_default_route(const char *ifname);
32int ifc_remove_default_route(const char *ifname);
33int ifc_reset_connections(const char *ifname);
34
35int dhcp_do_request(const char *ifname,
36                    const char *ipaddr,
37                    const char *gateway,
38                    uint32_t  *prefixLength,
39                    const char *dns1,
40                    const char *dns2,
41                    const char *server,
42                    uint32_t  *lease);
43
44int dhcp_do_request_renew(const char *ifname,
45                    const char *ipaddr,
46                    const char *gateway,
47                    uint32_t  *prefixLength,
48                    const char *dns1,
49                    const char *dns2,
50                    const char *server,
51                    uint32_t  *lease);
52
53int dhcp_stop(const char *ifname);
54int dhcp_release_lease(const char *ifname);
55char *dhcp_get_errmsg();
56}
57
58#define NETUTILS_PKG_NAME "android/net/NetworkUtils"
59
60namespace android {
61
62/*
63 * The following remembers the jfieldID's of the fields
64 * of the DhcpInfo Java object, so that we don't have
65 * to look them up every time.
66 */
67static struct fieldIds {
68    jclass dhcpInfoInternalClass;
69    jmethodID constructorId;
70    jfieldID ipaddress;
71    jfieldID gateway;
72    jfieldID prefixLength;
73    jfieldID dns1;
74    jfieldID dns2;
75    jfieldID serverAddress;
76    jfieldID leaseDuration;
77} dhcpInfoInternalFieldIds;
78
79static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
80{
81    int result;
82
83    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
84    result = ::ifc_enable(nameStr);
85    env->ReleaseStringUTFChars(ifname, nameStr);
86    return (jint)result;
87}
88
89static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname)
90{
91    int result;
92
93    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
94    result = ::ifc_disable(nameStr);
95    env->ReleaseStringUTFChars(ifname, nameStr);
96    return (jint)result;
97}
98
99static jint android_net_utils_addRoute(JNIEnv* env, jobject clazz, jstring ifname,
100          jstring dst, jint prefixLength, jstring gw)
101{
102    int result;
103
104    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
105    const char *dstStr = env->GetStringUTFChars(dst, NULL);
106    const char *gwStr = NULL;
107    if (gw != NULL) {
108        gwStr = env->GetStringUTFChars(gw, NULL);
109    }
110    result = ::ifc_add_route(nameStr, dstStr, prefixLength, gwStr);
111    env->ReleaseStringUTFChars(ifname, nameStr);
112    env->ReleaseStringUTFChars(dst, dstStr);
113    if (gw != NULL) {
114        env->ReleaseStringUTFChars(gw, gwStr);
115    }
116    return (jint)result;
117}
118
119static jint android_net_utils_removeHostRoutes(JNIEnv* env, jobject clazz, jstring ifname)
120{
121    int result;
122
123    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
124    result = ::ifc_remove_host_routes(nameStr);
125    env->ReleaseStringUTFChars(ifname, nameStr);
126    return (jint)result;
127}
128
129static jint android_net_utils_getDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)
130{
131    int result;
132
133    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
134    result = ::ifc_get_default_route(nameStr);
135    env->ReleaseStringUTFChars(ifname, nameStr);
136    return (jint)result;
137}
138
139static jint android_net_utils_removeDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)
140{
141    int result;
142
143    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
144    result = ::ifc_remove_default_route(nameStr);
145    env->ReleaseStringUTFChars(ifname, nameStr);
146    return (jint)result;
147}
148
149static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname)
150{
151    int result;
152
153    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
154    result = ::ifc_reset_connections(nameStr);
155    env->ReleaseStringUTFChars(ifname, nameStr);
156    return (jint)result;
157}
158
159static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
160        jobject info, bool renew)
161{
162    int result;
163    char  ipaddr[PROPERTY_VALUE_MAX];
164    uint32_t prefixLength;
165    char gateway[PROPERTY_VALUE_MAX];
166    char    dns1[PROPERTY_VALUE_MAX];
167    char    dns2[PROPERTY_VALUE_MAX];
168    char  server[PROPERTY_VALUE_MAX];
169    uint32_t lease;
170
171    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
172    if (nameStr == NULL) return (jboolean)false;
173
174    if (renew) {
175        result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
176                dns1, dns2, server, &lease);
177    } else {
178        result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
179                dns1, dns2, server, &lease);
180    }
181
182    env->ReleaseStringUTFChars(ifname, nameStr);
183    if (result == 0 && dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
184        env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
185        env->SetObjectField(info, dhcpInfoInternalFieldIds.gateway, env->NewStringUTF(gateway));
186        env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
187        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
188        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
189        env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
190                env->NewStringUTF(server));
191        env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
192    }
193    return (jboolean)(result == 0);
194}
195
196static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
197{
198    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
199}
200
201static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
202{
203    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
204}
205
206
207static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
208{
209    int result;
210
211    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
212    result = ::dhcp_stop(nameStr);
213    env->ReleaseStringUTFChars(ifname, nameStr);
214    return (jboolean)(result == 0);
215}
216
217static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
218{
219    int result;
220
221    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
222    result = ::dhcp_release_lease(nameStr);
223    env->ReleaseStringUTFChars(ifname, nameStr);
224    return (jboolean)(result == 0);
225}
226
227static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
228{
229    return env->NewStringUTF(::dhcp_get_errmsg());
230}
231
232// ----------------------------------------------------------------------------
233
234/*
235 * JNI registration.
236 */
237static JNINativeMethod gNetworkUtilMethods[] = {
238    /* name, signature, funcPtr */
239
240    { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
241    { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
242    { "addRoute", "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)I",
243       (void *)android_net_utils_addRoute },
244    { "removeHostRoutes", "(Ljava/lang/String;)I",  (void *)android_net_utils_removeHostRoutes },
245    { "getDefaultRouteNative", "(Ljava/lang/String;)I",
246       (void *)android_net_utils_getDefaultRoute },
247    { "removeDefaultRoute", "(Ljava/lang/String;)I",  (void *)android_net_utils_removeDefaultRoute },
248    { "resetConnections", "(Ljava/lang/String;)I",  (void *)android_net_utils_resetConnections },
249    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
250    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
251    { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
252    { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
253    { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
254};
255
256int register_android_net_NetworkUtils(JNIEnv* env)
257{
258    jclass netutils = env->FindClass(NETUTILS_PKG_NAME);
259    LOG_FATAL_IF(netutils == NULL, "Unable to find class " NETUTILS_PKG_NAME);
260
261    dhcpInfoInternalFieldIds.dhcpInfoInternalClass = env->FindClass("android/net/DhcpInfoInternal");
262    if (dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
263        dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "<init>", "()V");
264        dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
265        dhcpInfoInternalFieldIds.gateway = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "gateway", "Ljava/lang/String;");
266        dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "prefixLength", "I");
267        dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
268        dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
269        dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
270        dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "leaseDuration", "I");
271    }
272
273    return AndroidRuntime::registerNativeMethods(env,
274            NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
275}
276
277}; // namespace android
278