blob: c6d9de3016ed3f6244a9dd4881e0a8763235e89e
1 | #define LOG_NDEBUG 0 |
2 | #define LOCAL_TAG "PPPOE_JNI" |
3 | |
4 | |
5 | /* |
6 | dalvik/libnativehelper/include/nativehelper/jni.h |
7 | */ |
8 | #include <jni.h> |
9 | |
10 | #include <JNIHelp.h> |
11 | |
12 | #include <android_runtime/AndroidRuntime.h> |
13 | |
14 | #include <utils/Log.h> |
15 | #include <stdio.h> |
16 | #include <stdlib.h> |
17 | |
18 | #include <unistd.h> |
19 | |
20 | #include <sys/socket.h> |
21 | #include <netinet/in.h> |
22 | |
23 | #include <sys/un.h> |
24 | #include <netwrapper.h> |
25 | #include "pppoe_status.h" |
26 | #include <android/log.h> |
27 | |
28 | #include "cutils/properties.h" |
29 | |
30 | #define PPPOE_PLUGIN_CMD_LEN_MAX 256 |
31 | #define PPPOE_CONNECT_CMD_LEN_MAX 512 |
32 | |
33 | #define TRACE() LOGI("[%s::%d]\n",__FUNCTION__,__LINE__) |
34 | using namespace android; |
35 | |
36 | |
37 | struct fields_t { |
38 | JavaVM *gJavaVM ; |
39 | JNIEnv* env; |
40 | jmethodID post_event; |
41 | }; |
42 | |
43 | static struct fields_t fields; |
44 | |
45 | extern int get_pppoe_status( const char *phy_if_name); |
46 | |
47 | static char pppoe_connect_cmd[PPPOE_CONNECT_CMD_LEN_MAX]; |
48 | |
49 | static char pppoe_disconnect_cmd[512] = "ppp-stop"; |
50 | static char pppoe_terminate_cmd[512] = "ppp-terminate"; |
51 | |
52 | static char pppoe_plugin_cmd[PPPOE_PLUGIN_CMD_LEN_MAX]; |
53 | |
54 | #define PPPD_OPTIONS_LEN 512 |
55 | static char pppd_options[PPPD_OPTIONS_LEN + 1] = {"debug logfd 1 noipdefault noauth default-asyncmap defaultroute show-password nodetach mtu 1492 mru 1492 noaccomp nodeflate nopcomp novj usepeerdns novjccomp lcp-echo-interval 20 lcp-echo-failure 3"}; |
56 | |
57 | |
58 | |
59 | static char* create_pppoe_plugin_cmd(char *pid_file, char *phy_if) |
60 | { |
61 | int len; |
62 | len = snprintf(pppoe_plugin_cmd, PPPOE_PLUGIN_CMD_LEN_MAX, |
63 | "'pppoe -p %s -I %s -T 80 -U -m 1412'", |
64 | pid_file, phy_if); |
65 | if ( len < 0 || len >= PPPOE_PLUGIN_CMD_LEN_MAX ) { |
66 | return NULL; |
67 | } |
68 | |
69 | return pppoe_plugin_cmd; |
70 | } |
71 | |
72 | |
73 | static char* create_pppoe_connect_cmd |
74 | (char *plugin_cmd, char *options, char *username, char *pwd) |
75 | { |
76 | int len; |
77 | len = snprintf(pppoe_connect_cmd, PPPOE_CONNECT_CMD_LEN_MAX, |
78 | "pppd pty %s %s user %s password %s &", |
79 | plugin_cmd, options, username, pwd); |
80 | if ( len < 0 || len >= PPPOE_CONNECT_CMD_LEN_MAX ) { |
81 | return NULL; |
82 | } |
83 | |
84 | return pppoe_connect_cmd; |
85 | } |
86 | |
87 | #include "../../ppp/pppd/pathnames.h" |
88 | #define CONFIG_FILE _ROOT_PATH "/etc/ppp/pppd_options.conf" |
89 | |
90 | |
91 | |
92 | /* Handy routine to read very long lines in text files. |
93 | * This means we read the whole line and avoid any nasty buffer overflows. */ |
94 | static ssize_t get_line(char **line, size_t *len, FILE *fp) |
95 | { |
96 | char *p; |
97 | size_t last = 0; |
98 | |
99 | while(!feof(fp)) { |
100 | if (*line == NULL || last != 0) { |
101 | *len += BUFSIZ; |
102 | *line = (char*)realloc(*line, *len); |
103 | } |
104 | p = *line + last; |
105 | memset(p, 0, BUFSIZ); |
106 | if (fgets(p, BUFSIZ, fp) == NULL) |
107 | break; |
108 | last += strlen(p); |
109 | if (last && (*line)[last - 1] == '\n') { |
110 | (*line)[last - 1] = '\0'; |
111 | break; |
112 | } |
113 | } |
114 | return last; |
115 | } |
116 | |
117 | static const char PPPOE_PHY_IF_PROP_NAME[] = "net.pppoe.phyif"; |
118 | |
119 | static jboolean com_amlogic_PppoeOperation_connect |
120 | (JNIEnv *env, jobject obj, jstring jstr_if_name, jstring jstr_account, jstring jstr_passwd) |
121 | { |
122 | char *p_ifname; |
123 | char *p_user; |
124 | char *p_passwd; |
125 | struct netwrapper_ctrl * ctrl; |
126 | char *p; |
127 | |
128 | FILE *f; |
129 | f = fopen(CONFIG_FILE, "r"); |
130 | __android_log_print(ANDROID_LOG_INFO, LOCAL_TAG,"Try Open %s", CONFIG_FILE); |
131 | |
132 | if (f) { |
133 | char *line, *option, *p, *buffer = NULL; |
134 | size_t len = 0; |
135 | |
136 | get_line(&buffer, &len, f); |
137 | __android_log_print(ANDROID_LOG_INFO, LOCAL_TAG,"get_line: [%s]", buffer); |
138 | if (buffer){ |
139 | strncpy(pppd_options, buffer, sizeof(pppd_options) - 1); |
140 | free(buffer); |
141 | } |
142 | fclose(f); |
143 | } |
144 | |
145 | p_ifname = (char *)env->GetStringUTFChars(jstr_if_name, NULL); |
146 | p_user = (char *)env->GetStringUTFChars(jstr_account, NULL); |
147 | p_passwd = (char *)env->GetStringUTFChars(jstr_passwd, NULL); |
148 | |
149 | property_set(PPPOE_PHY_IF_PROP_NAME, p_ifname); |
150 | |
151 | p = create_pppoe_plugin_cmd((char*)PPPOE_PIDFILE, p_ifname); |
152 | if (!p) { |
153 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"failed to create plug_in command\n"); |
154 | return -1; |
155 | } |
156 | |
157 | __android_log_print(ANDROID_LOG_INFO, LOCAL_TAG,"plug_in command: %s\n", p); |
158 | |
159 | p = create_pppoe_connect_cmd(p, pppd_options, p_user, p_passwd); |
160 | if (!p) { |
161 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"failed to create connect command\n"); |
162 | return -1; |
163 | } |
164 | |
165 | __android_log_print(ANDROID_LOG_INFO, LOCAL_TAG,"connect command: %s\n", p); |
166 | |
167 | |
168 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"ppp.connect\n"); |
169 | |
170 | ctrl = netwrapper_ctrl_open(PPPOE_WRAPPER_CLIENT_PATH, PPPOE_WRAPPER_SERVER_PATH); |
171 | if (ctrl == NULL) { |
172 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG, "Failed to connect to pppd\n"); |
173 | return -1; |
174 | } |
175 | |
176 | netwrapper_ctrl_request(ctrl, pppoe_connect_cmd, strlen(pppoe_connect_cmd)); |
177 | |
178 | netwrapper_ctrl_close(ctrl); |
179 | |
180 | env->ReleaseStringUTFChars(jstr_if_name, p_ifname); |
181 | env->ReleaseStringUTFChars(jstr_account, p_user); |
182 | env->ReleaseStringUTFChars(jstr_passwd, p_passwd); |
183 | |
184 | return 1; |
185 | } |
186 | |
187 | |
188 | |
189 | jboolean com_amlogic_PppoeOperation_disconnect |
190 | (JNIEnv *env, jobject obj) |
191 | { |
192 | struct netwrapper_ctrl * ctrl; |
193 | |
194 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"ppp.disconnect\n"); |
195 | |
196 | ctrl = netwrapper_ctrl_open(PPPOE_WRAPPER_CLIENT_PATH, PPPOE_WRAPPER_SERVER_PATH); |
197 | if (ctrl == NULL) { |
198 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG, "Failed to connect to pppd\n"); |
199 | return -1; |
200 | } |
201 | |
202 | netwrapper_ctrl_request(ctrl, pppoe_disconnect_cmd, strlen(pppoe_disconnect_cmd)); |
203 | |
204 | netwrapper_ctrl_close(ctrl); |
205 | |
206 | return 1; |
207 | } |
208 | |
209 | jboolean com_amlogic_PppoeOperation_terminate |
210 | (JNIEnv *env, jobject obj) |
211 | { |
212 | struct netwrapper_ctrl * ctrl; |
213 | |
214 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"ppp.terminate\n"); |
215 | |
216 | ctrl = netwrapper_ctrl_open(PPPOE_WRAPPER_CLIENT_PATH, PPPOE_WRAPPER_SERVER_PATH); |
217 | if (ctrl == NULL) { |
218 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG, "Failed to connect to pppd\n"); |
219 | return -1; |
220 | } |
221 | |
222 | netwrapper_ctrl_request(ctrl, pppoe_terminate_cmd, strlen(pppoe_terminate_cmd)); |
223 | |
224 | netwrapper_ctrl_close(ctrl); |
225 | |
226 | return 1; |
227 | } |
228 | |
229 | |
230 | jint com_amlogic_PppoeOperation_status |
231 | (JNIEnv *env, jobject obj, jstring jstr_if_name) |
232 | { |
233 | char *p_ifname; |
234 | int status; |
235 | |
236 | __android_log_print(ANDROID_LOG_ERROR, LOCAL_TAG,"ppp.status\n"); |
237 | |
238 | p_ifname = (char *)env->GetStringUTFChars(jstr_if_name, NULL); |
239 | status = get_pppoe_status(p_ifname); |
240 | |
241 | env->ReleaseStringUTFChars(jstr_if_name, p_ifname); |
242 | |
243 | return status; |
244 | } |
245 | |
246 | |
247 | static JNINativeMethod gPppoeJNIMethods[] = { |
248 | /* name, signature, funcPtr */ |
249 | { "connect", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", (void*) com_amlogic_PppoeOperation_connect }, |
250 | { "disconnect", "()Z", (void*) com_amlogic_PppoeOperation_disconnect }, |
251 | { "terminate", "()Z", (void*) com_amlogic_PppoeOperation_terminate }, |
252 | { "status", "(Ljava/lang/String;)I", (void*) com_amlogic_PppoeOperation_status }, |
253 | }; |
254 | |
255 | |
256 | #define PPPOE_CLASS_NAME "com/amlogic/pppoe/PppoeOperation" |
257 | |
258 | |
259 | int register_pppoe_jni(JNIEnv* env) |
260 | { |
261 | int ret; |
262 | jclass pppoe = env->FindClass(PPPOE_CLASS_NAME); |
263 | if (NULL == pppoe) { |
264 | LOGI("%s:Unable to find class %s", __FUNCTION__, PPPOE_CLASS_NAME); |
265 | return -1; |
266 | } |
267 | else { |
268 | LOGI("%s:class %s FOUND", __FUNCTION__, PPPOE_CLASS_NAME); |
269 | } |
270 | |
271 | TRACE(); |
272 | ret = android::AndroidRuntime::registerNativeMethods(env, |
273 | PPPOE_CLASS_NAME, gPppoeJNIMethods, NELEM(gPppoeJNIMethods)); |
274 | return ret; |
275 | } |
276 | |
277 | |
278 | JNIEXPORT jint |
279 | JNI_OnLoad(JavaVM* vm, void* reserved) |
280 | { |
281 | jint ret; |
282 | JNIEnv* env = NULL; |
283 | TRACE(); |
284 | if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env) { |
285 | LOGE("GetEnv failed!"); |
286 | return -1; |
287 | } |
288 | fields.gJavaVM = vm; |
289 | fields.env = env; |
290 | TRACE(); |
291 | ret = register_pppoe_jni(env); |
292 | LOGI("register_pppoe_jni=%d\n", ret); |
293 | if (ret == 0) { |
294 | return JNI_VERSION_1_4; |
295 | } else { |
296 | return -1; |
297 | } |
298 | } |
299 | |
300 | |
301 | JNIEXPORT void |
302 | JNI_OnUnload(JavaVM* vm, void* reserved) |
303 | { |
304 | return; |
305 | } |
306 | |
307 | |
308 |