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