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
25 extern "C" {
26 int ifc_enable(const char *ifname);
27 int ifc_disable(const char *ifname);
28 int ifc_add_host_route(const char *ifname, uint32_t addr);
29 int ifc_remove_host_routes(const char *ifname);
30 int ifc_set_default_route(const char *ifname, uint32_t gateway);
31 int ifc_get_default_route(const char *ifname);
32 int ifc_remove_default_route(const char *ifname);
33 int ifc_reset_connections(const char *ifname);
34 int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
35
36 int dhcp_do_request(const char *ifname,
37 in_addr_t *ipaddr,
38 in_addr_t *gateway,
39 in_addr_t *mask,
40 in_addr_t *dns1,
41 in_addr_t *dns2,
42 in_addr_t *server,
43 uint32_t *lease);
44 int dhcp_stop(const char *ifname);
45 int dhcp_release_lease(const char *ifname);
46 char *dhcp_get_errmsg();
47
48 int dhcp_do_request_renew(const char *ifname,
49 in_addr_t *ipaddr,
50 in_addr_t *gateway,
51 in_addr_t *mask,
52 in_addr_t *dns1,
53 in_addr_t *dns2,
54 in_addr_t *server,
55 uint32_t *lease);
56 }
57
58 #define NETUTILS_PKG_NAME "android/net/NetworkUtils"
59
60 namespace 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 */
67 static struct fieldIds {
68 jclass dhcpInfoClass;
69 jmethodID constructorId;
70 jfieldID ipaddress;
71 jfieldID gateway;
72 jfieldID netmask;
73 jfieldID dns1;
74 jfieldID dns2;
75 jfieldID serverAddress;
76 jfieldID leaseDuration;
77 } dhcpInfoFieldIds;
78
android_net_utils_enableInterface(JNIEnv * env,jobject clazz,jstring ifname)79 static 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
android_net_utils_disableInterface(JNIEnv * env,jobject clazz,jstring ifname)89 static 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
android_net_utils_addHostRoute(JNIEnv * env,jobject clazz,jstring ifname,jint addr)99 static jint android_net_utils_addHostRoute(JNIEnv* env, jobject clazz, jstring ifname, jint addr)
100 {
101 int result;
102
103 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
104 result = ::ifc_add_host_route(nameStr, addr);
105 env->ReleaseStringUTFChars(ifname, nameStr);
106 return (jint)result;
107 }
108
android_net_utils_removeHostRoutes(JNIEnv * env,jobject clazz,jstring ifname)109 static jint android_net_utils_removeHostRoutes(JNIEnv* env, jobject clazz, jstring ifname)
110 {
111 int result;
112
113 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
114 result = ::ifc_remove_host_routes(nameStr);
115 env->ReleaseStringUTFChars(ifname, nameStr);
116 return (jint)result;
117 }
118
android_net_utils_setDefaultRoute(JNIEnv * env,jobject clazz,jstring ifname,jint gateway)119 static jint android_net_utils_setDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname, jint gateway)
120 {
121 int result;
122
123 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
124 result = ::ifc_set_default_route(nameStr, gateway);
125 env->ReleaseStringUTFChars(ifname, nameStr);
126 return (jint)result;
127 }
128
android_net_utils_getDefaultRoute(JNIEnv * env,jobject clazz,jstring ifname)129 static 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
android_net_utils_removeDefaultRoute(JNIEnv * env,jobject clazz,jstring ifname)139 static 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
android_net_utils_resetConnections(JNIEnv * env,jobject clazz,jstring ifname)149 static 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
android_net_utils_runDhcp(JNIEnv * env,jobject clazz,jstring ifname,jobject info)159 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
160 {
161 int result;
162 in_addr_t ipaddr, gateway, mask, dns1, dns2, server;
163 uint32_t lease;
164
165 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
166 result = ::dhcp_do_request(nameStr, &ipaddr, &gateway, &mask,
167 &dns1, &dns2, &server, &lease);
168 env->ReleaseStringUTFChars(ifname, nameStr);
169 if (result == 0 && dhcpInfoFieldIds.dhcpInfoClass != NULL) {
170 env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr);
171 env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway);
172 env->SetIntField(info, dhcpInfoFieldIds.netmask, mask);
173 env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1);
174 env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2);
175 env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server);
176 env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease);
177 }
178 return (jboolean)(result == 0);
179 }
180
android_net_utils_stopDhcp(JNIEnv * env,jobject clazz,jstring ifname)181 static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
182 {
183 int result;
184
185 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
186 result = ::dhcp_stop(nameStr);
187 env->ReleaseStringUTFChars(ifname, nameStr);
188 return (jboolean)(result == 0);
189 }
190
android_net_utils_releaseDhcpLease(JNIEnv * env,jobject clazz,jstring ifname)191 static jboolean android_net_utils_releaseDhcpLease(JNIEnv* env, jobject clazz, jstring ifname)
192 {
193 int result;
194
195 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
196 result = ::dhcp_release_lease(nameStr);
197 env->ReleaseStringUTFChars(ifname, nameStr);
198 return (jboolean)(result == 0);
199 }
200
android_net_utils_getDhcpError(JNIEnv * env,jobject clazz)201 static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
202 {
203 return env->NewStringUTF(::dhcp_get_errmsg());
204 }
205
android_net_utils_configureInterface(JNIEnv * env,jobject clazz,jstring ifname,jint ipaddr,jint mask,jint gateway,jint dns1,jint dns2)206 static jboolean android_net_utils_configureInterface(JNIEnv* env,
207 jobject clazz,
208 jstring ifname,
209 jint ipaddr,
210 jint mask,
211 jint gateway,
212 jint dns1,
213 jint dns2)
214 {
215 int result;
216 uint32_t lease;
217
218 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
219 result = ::ifc_configure(nameStr, ipaddr, mask, gateway, dns1, dns2);
220 env->ReleaseStringUTFChars(ifname, nameStr);
221 return (jboolean)(result == 0);
222 }
223
android_net_utils_runDhcpRenew(JNIEnv * env,jobject clazz,jstring ifname,jobject info)224 static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
225 {
226 int result = -1;
227 in_addr_t ipaddr, gateway, mask, dns1, dns2, server;
228 uint32_t lease;
229
230 const char *nameStr = env->GetStringUTFChars(ifname, NULL);
231 result = ::dhcp_do_request_renew(nameStr, &ipaddr, &gateway, &mask,
232 &dns1, &dns2, &server, &lease);
233 env->ReleaseStringUTFChars(ifname, nameStr);
234 if (result == 0 && dhcpInfoFieldIds.dhcpInfoClass != NULL) {
235 env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr);
236 env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway);
237 env->SetIntField(info, dhcpInfoFieldIds.netmask, mask);
238 env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1);
239 env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2);
240 env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server);
241 env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease);
242 }
243
244 return (jboolean)(result == 0);
245 }
246 // ----------------------------------------------------------------------------
247
248 /*
249 * JNI registration.
250 */
251 static JNINativeMethod gNetworkUtilMethods[] = {
252 /* name, signature, funcPtr */
253
254 { "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface },
255 { "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface },
256 { "addHostRoute", "(Ljava/lang/String;I)I", (void *)android_net_utils_addHostRoute },
257 { "removeHostRoutes", "(Ljava/lang/String;)I", (void *)android_net_utils_removeHostRoutes },
258 { "setDefaultRoute", "(Ljava/lang/String;I)I", (void *)android_net_utils_setDefaultRoute },
259 { "getDefaultRoute", "(Ljava/lang/String;)I", (void *)android_net_utils_getDefaultRoute },
260 { "removeDefaultRoute", "(Ljava/lang/String;)I", (void *)android_net_utils_removeDefaultRoute },
261 { "resetConnections", "(Ljava/lang/String;)I", (void *)android_net_utils_resetConnections },
262 { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfo;)Z", (void *)android_net_utils_runDhcp },
263 { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
264 { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
265 { "configureNative", "(Ljava/lang/String;IIIII)Z", (void *)android_net_utils_configureInterface },
266 { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
267 { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfo;)Z", (void *)android_net_utils_runDhcpRenew}
268 };
269
register_android_net_NetworkUtils(JNIEnv * env)270 int register_android_net_NetworkUtils(JNIEnv* env)
271 {
272 jclass netutils = env->FindClass(NETUTILS_PKG_NAME);
273 LOG_FATAL_IF(netutils == NULL, "Unable to find class " NETUTILS_PKG_NAME);
274
275 dhcpInfoFieldIds.dhcpInfoClass = env->FindClass("android/net/DhcpInfo");
276 if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
277 dhcpInfoFieldIds.constructorId = env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass, "<init>", "()V");
278 dhcpInfoFieldIds.ipaddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "ipAddress", "I");
279 dhcpInfoFieldIds.gateway = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "gateway", "I");
280 dhcpInfoFieldIds.netmask = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "netmask", "I");
281 dhcpInfoFieldIds.dns1 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
282 dhcpInfoFieldIds.dns2 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
283 dhcpInfoFieldIds.serverAddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "serverAddress", "I");
284 dhcpInfoFieldIds.leaseDuration = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "leaseDuration", "I");
285 }
286
287 return AndroidRuntime::registerNativeMethods(env,
288 NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
289 }
290
291 }; // namespace android
292