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