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