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