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