• 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 <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