blob: e5e24aae4031a6d62ea5c7eb499df385424a1974 [file] [log] [blame]
liuyangf01f2772024-10-18 16:33:46 +08001#include <string.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <pthread.h>
5#include <unistd.h>
6#include <sys/epoll.h>
7#include <errno.h>
8#include <sys/wait.h>
9#include <sys/types.h>
10
11#include "wpa_ctrl.h"
12#include "sta_ctrl.h"
liuyang09c3d7a2024-10-25 10:56:51 +080013#include "mbtk_log.h"
14
liuyangf01f2772024-10-18 16:33:46 +080015//#include "sta_log.h"
16
17#define WPA_SUPPLICANT_LOG_FILE "/data/wpa_supplicant.log"
18
19static void
20sta_ctrl_wpa_req_cb(char *msg, size_t len);
21
22static void*
23sta_ctrl_event_thread_run( void *arg );
24
25static sta_err_enum
26sta_ctrl_close_connection(void);
27
28static sta_err_enum
29sta_ctrl_open_connection(void);
30
31static sta_err_enum
32sta_ctrl_reconnect(void);
33
34static void
35sta_ctrl_recv_event(void);
36
37static sta_err_enum
38sta_ctrl_conf_file_parse
39(
40 const char *key,
41 char *value
42);
43
44extern struct wpa_ctrl;
45
46static struct wpa_ctrl *sta_ctrl_conn;
47static struct wpa_ctrl *sta_mon_conn;
48static int sta_ctrl_attached = 0;
49static pthread_t sta_event_thread_id = -1;
50static int sta_event_thread_is_running = 0;
51static char sta_ctrl_conf_file_path[50];
52static char sta_ctrl_ifname[10];
53static sta_ctrl_msg_cb sta_ctrl_msg = NULL;
54static int sta_ctrl_pipe_fd[2];
55
56static void
57sta_ctrl_wpa_req_cb(char *msg, size_t len)
58{
liuyang09c3d7a2024-10-25 10:56:51 +080059 LOGE("%s\n", msg);
liuyangf01f2772024-10-18 16:33:46 +080060}
61
62bool
63sta_ctrl_system
64(
65 const char *command
66)
67{
68 int result = TRUE;
69 FILE *stream = NULL;
70
liuyang09c3d7a2024-10-25 10:56:51 +080071 LOGE("system call: %s\n", command);
liuyangf01f2772024-10-18 16:33:46 +080072
73 stream = popen( command, "w" );
74 if( stream == NULL )
75 {
liuyang09c3d7a2024-10-25 10:56:51 +080076 LOGE("system command failed\n");
liuyangf01f2772024-10-18 16:33:46 +080077 result = FALSE;
78 }
79 else if( 0 > pclose( stream ) )
80 {
liuyang09c3d7a2024-10-25 10:56:51 +080081 LOGE("pclose command failed\n");
liuyangf01f2772024-10-18 16:33:46 +080082 }
83
84 return result;
85}
86
87/*
88* Return TRUE if process <name> is not running after 2 second.
89*/
90bool
91sta_ctrl_kill_check(const char *name)
92{
93#define PROCESS_KILL_RETRY 40
94 bool result;
95 int tmp = 0;
96 FILE *cmd;
97 char pid_s[STA_BUF_SIZE];
98 int pid;
99 tmp = snprintf(pid_s,STA_BUF_SIZE,
100 "pidof %s",name);
101 pid_s[tmp] = '\0';
102 tmp = 0;
103 while (tmp++ < PROCESS_KILL_RETRY)
104 {
105 usleep(50000);/*50 mili second*/
106 cmd = popen(pid_s, "r");
107 pid = 0;
108 bzero(pid_s, STA_BUF_SIZE);
109 if(cmd)
110 {
111 fgets(pid_s, STA_BUF_SIZE, cmd);
112 pclose(cmd);
113 }
114 pid = atoi(pid_s);
liuyang09c3d7a2024-10-25 10:56:51 +0800115 LOGE("%s pid =%d\n", name,pid);
liuyangf01f2772024-10-18 16:33:46 +0800116 /* If pid is zero we break from while*/
117 if(pid == 0)
118 {
119 result = TRUE;
120 goto exit_end;
121 }
122 }
123
liuyang09c3d7a2024-10-25 10:56:51 +0800124 LOGE("PID still running after waiting 2 second.\n");
liuyangf01f2772024-10-18 16:33:46 +0800125 result = FALSE;
126exit_end:
127#undef PROCESS_KILL_RETRY
128 return result;
129}
130
131/*
132* Return TRUE if process <name> is running.
133*/
134bool
135sta_ctrl_process_running(const char *name)
136{
137 char pid_s[STA_BUF_SIZE];
138 int tmp = snprintf(pid_s,STA_BUF_SIZE,
139 "pidof %s",name);
140 pid_s[tmp] = '\0';
141 FILE *cmd = popen(pid_s, "r");
142 bzero(pid_s, STA_BUF_SIZE);
143 if(cmd)
144 {
145 fgets(pid_s, STA_BUF_SIZE, cmd);
146 pclose(cmd);
147 }
148
149 int pid = atoi(pid_s);
liuyang09c3d7a2024-10-25 10:56:51 +0800150 LOGE("%s pid =%d\n", name,pid);
liuyangf01f2772024-10-18 16:33:46 +0800151 /* If pid is zero we break from while*/
152 if(pid == 0)
153 {
liuyang09c3d7a2024-10-25 10:56:51 +0800154 LOGE("%s not runnig.\n",name);
liuyangf01f2772024-10-18 16:33:46 +0800155 return FALSE;
156 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800157 LOGE("%s is runnig.\n",name);
liuyangf01f2772024-10-18 16:33:46 +0800158 return TRUE;
159 }
160}
161
162
163static void*
164sta_ctrl_event_thread_run( void *arg )
165{
liuyang09c3d7a2024-10-25 10:56:51 +0800166 LOGE("Thread[%ld] run().\n",pthread_self());
liuyangf01f2772024-10-18 16:33:46 +0800167
168 int nready;
169 struct epoll_event ev_sock,ev_pipe,events[20];
170 int epfd = epoll_create(256);
171 ev_sock.data.fd = wpa_ctrl_get_fd(sta_mon_conn);
172 ev_sock.events = EPOLLIN | EPOLLET;
173 epoll_ctl(epfd,EPOLL_CTL_ADD,wpa_ctrl_get_fd(sta_mon_conn),&ev_sock);
174
175 ev_pipe.data.fd = sta_ctrl_pipe_fd[0];
176 ev_pipe.events = EPOLLIN | EPOLLET;
177 epoll_ctl(epfd,EPOLL_CTL_ADD,sta_ctrl_pipe_fd[0],&ev_pipe);
178
179 for ( ; ; ) {
180 if(!sta_event_thread_is_running){
181 break;
182 }
liuyang09c3d7a2024-10-25 10:56:51 +0800183 LOGE("epoll_wait waitting...\n",nready);
liuyangf01f2772024-10-18 16:33:46 +0800184 nready = epoll_wait(epfd,events,20,-1);
liuyang09c3d7a2024-10-25 10:56:51 +0800185 LOGE("epoll_wait return.(count = %d)\n",nready);
liuyangf01f2772024-10-18 16:33:46 +0800186 int i;
187 for(i=0;i<nready;++i) {
188 if (events[i].events & EPOLLIN) {// Read
189 if (events[i].data.fd < 0)
190 continue;
191
192 if(sta_mon_conn // sta_mon_conn can not be NULL
193 && events[i].data.fd == wpa_ctrl_get_fd(sta_mon_conn)){
194 sta_ctrl_recv_event();
195 }else if(events[i].data.fd == sta_ctrl_pipe_fd[0]){
liuyang09c3d7a2024-10-25 10:56:51 +0800196 LOGE("Thread end.[fd = %d]\n",events[i].data.fd);
liuyangf01f2772024-10-18 16:33:46 +0800197 // End thread
198 char buf_end[10] = {0};
199 if(read(sta_ctrl_pipe_fd[0],buf_end,10) > 0
200 && strcmp(buf_end,"0") == 0){
201 sta_event_thread_is_running = 0;
202 break;
203 }
204 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800205 LOGE("No such fd[%d].\n",events[i].data.fd);
liuyangf01f2772024-10-18 16:33:46 +0800206 }
207 } else {
liuyang09c3d7a2024-10-25 10:56:51 +0800208 LOGE("event error.\n");
liuyangf01f2772024-10-18 16:33:46 +0800209 }
210 }
211 }
212
213 close(epfd);
liuyang09c3d7a2024-10-25 10:56:51 +0800214 LOGE("Thread exit.\n");
liuyangf01f2772024-10-18 16:33:46 +0800215 return ((void*)0);
216}
217
218static sta_err_enum
219sta_ctrl_close_connection(void)
220{
liuyang09c3d7a2024-10-25 10:56:51 +0800221 LOGE("start.\n");
liuyangf01f2772024-10-18 16:33:46 +0800222 if (sta_ctrl_conn == NULL)
223 return STA_ERR_UNKNOWN;
224
225 if (sta_ctrl_attached) {
226 wpa_ctrl_detach(sta_mon_conn);
227 sta_ctrl_attached = 0;
228 }
229 wpa_ctrl_close(sta_ctrl_conn);
230 sta_ctrl_conn = NULL;
231 if (sta_mon_conn) {
232 wpa_ctrl_close(sta_mon_conn);
233 sta_mon_conn = NULL;
234 }
235
liuyang09c3d7a2024-10-25 10:56:51 +0800236 LOGE("end.\n");
liuyangf01f2772024-10-18 16:33:46 +0800237 return STA_ERR_SUCCESS;
238}
239
240static sta_err_enum
241sta_ctrl_open_connection(void)
242{
243 sta_err_enum result = STA_ERR_SUCCESS;
244
245 if(sta_ctrl_conn){
246 return STA_ERR_UNKNOWN;
247 }
248
249 char ctrl_path[100] = {0};
250 result = sta_ctrl_conf_file_parse("ctrl_interface", ctrl_path);
251 if(STA_ERR_SUCCESS != result){
liuyang09c3d7a2024-10-25 10:56:51 +0800252 LOGE("sta_ctrl_conf_file_parse() fail(%d).\n",result);
liuyangf01f2772024-10-18 16:33:46 +0800253 return result;
254 }
255 snprintf(ctrl_path + strlen(ctrl_path),10,
256 "/%s",
257 sta_ctrl_ifname);
258
liuyang09c3d7a2024-10-25 10:56:51 +0800259 LOGE("ctrl_path = \"%s\"\n",ctrl_path);
liuyangf01f2772024-10-18 16:33:46 +0800260
261 sta_ctrl_conn = wpa_ctrl_open(ctrl_path);
262 if (sta_ctrl_conn == NULL) {
263 sleep(1);
264 return sta_ctrl_open_connection();
265 }
266
267 sta_mon_conn = wpa_ctrl_open(ctrl_path);
268 if (sta_mon_conn == NULL) {
269 return STA_ERR_UNKNOWN;
270 }
271
272 if (wpa_ctrl_attach(sta_mon_conn) == 0) {
273 sta_ctrl_attached = 1;
274 } else {
liuyang09c3d7a2024-10-25 10:56:51 +0800275 LOGE("Warning: Failed to attach to "
liuyangf01f2772024-10-18 16:33:46 +0800276 "wpa_supplicant.\n");
277 sta_ctrl_close_connection();
278 return STA_ERR_UNKNOWN;
279 }
280
281 if(!sta_event_thread_is_running) {
282 sta_event_thread_is_running = 1;
283 int ret = pthread_create(&sta_event_thread_id,
284 NULL,
285 sta_ctrl_event_thread_run,
286 NULL);
287 if( ret != 0 ) {
liuyang09c3d7a2024-10-25 10:56:51 +0800288 LOGE( "Create thread error!\n");
liuyangf01f2772024-10-18 16:33:46 +0800289 }
290 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800291 LOGE("sta_event_thread is running.\n");
liuyangf01f2772024-10-18 16:33:46 +0800292 return STA_ERR_UNKNOWN;
293 }
294 return result;
295}
296
297static sta_err_enum
298sta_ctrl_reconnect(void)
299{
300 if(STA_ERR_SUCCESS == sta_ctrl_close_connection()){
301 return sta_ctrl_open_connection();
302 }else{
303 return STA_ERR_UNKNOWN;
304 }
305}
306
307static void
308sta_ctrl_recv_event(void)
309{
liuyang09c3d7a2024-10-25 10:56:51 +0800310 LOGE("start.\n");
liuyangf01f2772024-10-18 16:33:46 +0800311 if (sta_ctrl_conn == NULL) {
312 sta_ctrl_reconnect();
liuyang09c3d7a2024-10-25 10:56:51 +0800313 LOGE("sta_ctrl_conn == NULL:end.\n");
liuyangf01f2772024-10-18 16:33:46 +0800314 return;
315 }
316
317 while (wpa_ctrl_pending(sta_mon_conn) > 0) {
318 char buf[4096];
319 size_t len = sizeof(buf) - 1;
320 if (wpa_ctrl_recv(sta_mon_conn, buf, &len) == 0) {
321 buf[len] = '\0';
liuyang09c3d7a2024-10-25 10:56:51 +0800322 LOGE("<<%s>>\n",buf);
liuyangf01f2772024-10-18 16:33:46 +0800323 if(sta_ctrl_msg)
324 sta_ctrl_msg(buf);
325 } else {
liuyang09c3d7a2024-10-25 10:56:51 +0800326 LOGE("Could not read pending message.\n");
liuyangf01f2772024-10-18 16:33:46 +0800327 break;
328 }
329 }
330
331 if (wpa_ctrl_pending(sta_mon_conn) < 0) {
liuyang09c3d7a2024-10-25 10:56:51 +0800332 LOGE("Connection to wpa_supplicant lost - trying to "
liuyangf01f2772024-10-18 16:33:46 +0800333 "reconnect\n");
334 sta_ctrl_reconnect();
335 }
336
liuyang09c3d7a2024-10-25 10:56:51 +0800337 LOGE("end.\n");
liuyangf01f2772024-10-18 16:33:46 +0800338}
339
340static sta_err_enum
341sta_ctrl_conf_file_parse
342(
343 const char *key,
344 char *value
345)
346{
347 sta_err_enum result = STA_ERR_UNKNOWN;
348 FILE *fd = fopen(sta_ctrl_conf_file_path,"r");
349 if(!fd){
liuyang09c3d7a2024-10-25 10:56:51 +0800350 LOGE("Open file(%s) fail(%d).\n",sta_ctrl_conf_file_path,errno);
liuyangf01f2772024-10-18 16:33:46 +0800351 return STA_ERR_UNKNOWN;
352 }
353
354 char buf[1024];
355 while(fgets(buf,1024,fd)){
356 char *start = strstr(buf,key);
357 if(start){ // Find key
358 char *tmp = start + strlen(start) -1;
359 while(*tmp){
360 if(*tmp == '\r'
361 || *tmp == '\n'){
362 *tmp = '\0';
363 }else{
364 break;
365 }
366 *tmp--;
367 }
368
369 int size = snprintf(value,100,
370 "%s",
371 start + strlen(key) + 1);
372 value[size] = '\0';
373 result = STA_ERR_SUCCESS;
374 break;
375 }
376 }
377
378 fclose(fd);
379
380 return result;
381}
382
383/***************************************************************/
384/************************ Public Fuction ***********************/
385/***************************************************************/
386sta_err_enum
387sta_ctrl_cmd_process
388(
389 const char *cmd,
390 char *reply,
391 size_t reply_len
392)
393{
394 sta_err_enum result = STA_ERR_SUCCESS;
395 bzero(reply,reply_len);
396 reply_len = reply_len - 1;
397 int ret = wpa_ctrl_request(sta_ctrl_conn,
398 cmd,
399 strlen(cmd),
400 reply,
401 &reply_len,
402 sta_ctrl_wpa_req_cb);
403 if (ret == -2) {
liuyang09c3d7a2024-10-25 10:56:51 +0800404 LOGE("command timed out.\n");
liuyangf01f2772024-10-18 16:33:46 +0800405 result = STA_ERR_TIMEOUT;
406 goto end_fail;
407 } else if (ret < 0) {
liuyang09c3d7a2024-10-25 10:56:51 +0800408 LOGE("command failed.\n");
liuyangf01f2772024-10-18 16:33:46 +0800409 result = STA_ERR_UNKNOWN;
410 goto end_fail;
411 } else {
412 reply[reply_len] = '\0';
liuyang09c3d7a2024-10-25 10:56:51 +0800413 LOGE("1:%s\n", reply);
liuyangf01f2772024-10-18 16:33:46 +0800414
415 if(reply_len > 0 && reply[reply_len - 1] != '\n')
liuyang09c3d7a2024-10-25 10:56:51 +0800416 LOGE("\n");
liuyangf01f2772024-10-18 16:33:46 +0800417 }
418
419end_success:
420
421 return result;
422end_fail:
423
424 return result;
425}
426
427/**
428* Open or close wlan driver.
429*/
430sta_err_enum
431sta_ctrl_driver_init(bool open)
432{
433 sta_err_enum result = STA_ERR_SUCCESS;
434
435 FILE *fd_tmp = NULL;
436 if(open){
437 fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh sta start","r");
438 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800439 fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh sta stop","r");
liuyangf01f2772024-10-18 16:33:46 +0800440 }
441
442 if(fd_tmp){
443 char buf[200] = {0};
444 fgets(buf,200,fd_tmp);
445 pclose(fd_tmp);
446 if(strlen(buf) > 0){
liuyang09c3d7a2024-10-25 10:56:51 +0800447 LOGE("Driver %s fail.(%s)\n",(open?"open":"close"),buf);
liuyangf01f2772024-10-18 16:33:46 +0800448 result = STA_ERR_DRIVER;
449 }else{// Open wpa_supplicant
liuyang09c3d7a2024-10-25 10:56:51 +0800450 LOGE("Driver %s success.\n",(open?"open":"close"));
liuyangf01f2772024-10-18 16:33:46 +0800451 }
452 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800453 LOGE("Driver %s fail.(%s)\n",(open?"open":"close"));
liuyangf01f2772024-10-18 16:33:46 +0800454 result = STA_ERR_DRIVER;
455 }
456
457 return result;
458}
459
460sta_err_enum
461sta_ctrl_wpa_init
462(
463 const char *conf_file,
464 const char *interface,
465 sta_ctrl_msg_cb cb
466)
467{
468 sta_err_enum result = STA_ERR_SUCCESS;
469 if(!conf_file
470 || strlen(conf_file) == 0){
471 result = STA_ERR_UNKNOWN;
472 goto end_fail;
473 }
474
475 if(!interface
476 || strlen(interface) == 0){
477 result = STA_ERR_UNKNOWN;
478 goto end_fail;
479 }
480
481 sta_ctrl_msg = cb;
482
483 int size = snprintf(sta_ctrl_conf_file_path,
484 50,
485 "%s",
486 conf_file);
487 sta_ctrl_conf_file_path[size] = '\0';
488 size = snprintf(sta_ctrl_ifname,
489 10,
490 "%s",
491 interface);
492 sta_ctrl_ifname[size] = '\0';
493
494 if(pipe(sta_ctrl_pipe_fd)){
liuyang09c3d7a2024-10-25 10:56:51 +0800495 LOGE("pipe() fail(%d).\n",errno);
liuyangf01f2772024-10-18 16:33:46 +0800496 result = STA_ERR_UNKNOWN;
497 goto end_fail;
498 }
499
500 FILE *fd_tmp = popen("pidof wpa_supplicant","r");
501 if(fd_tmp){
502 char buf[200] = {0};
503 fgets(buf,200,fd_tmp);
504 pclose(fd_tmp);
505 if(strlen(buf) > 0){
liuyang09c3d7a2024-10-25 10:56:51 +0800506 LOGE("wpa_supplicant is running.(%s)\n",buf);
liuyangf01f2772024-10-18 16:33:46 +0800507 }else{// Open wpa_supplicant
508 bzero(buf,200);
509
510 snprintf(buf,200,
511 "wpa_supplicant -Dnl80211 -c%s -i%s -f%s -ddd &",
512 conf_file,
513 interface,
514 WPA_SUPPLICANT_LOG_FILE);
515
516 /*
517 snprintf(buf,200,
518 "wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wifi/wpa_supplicant.conf -B");
519 */
520 if (sta_ctrl_system(buf)){
liuyang09c3d7a2024-10-25 10:56:51 +0800521 LOGE("\"%s\" success.\n",buf);
liuyangf01f2772024-10-18 16:33:46 +0800522 sleep(1);
523 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800524 LOGE("\"%s\" fail.\n",buf);
liuyangf01f2772024-10-18 16:33:46 +0800525 result = STA_ERR_UNKNOWN;
526 goto end_fail;
527 }
528 }
529 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800530 LOGE("\"pidof wpa_supplicant\" fail\n");
liuyangf01f2772024-10-18 16:33:46 +0800531 result = STA_ERR_UNKNOWN;
532 goto end_fail;
533 }
534
535 result = sta_ctrl_open_connection();
536 if(STA_ERR_SUCCESS != result) {
liuyang09c3d7a2024-10-25 10:56:51 +0800537 LOGE("sta_ctrl_open_connection() fail(%d).\n",result);
liuyangf01f2772024-10-18 16:33:46 +0800538 goto end_fail;
539 }
540
541end_success:
542
543 return result;
544end_fail:
545
546 return result;
547}
548
549sta_err_enum
550sta_ctrl_wpa_deinit
551(
552 void
553)
554{
555 sta_err_enum result = STA_ERR_SUCCESS;
556 result = sta_ctrl_close_connection();
557 if(STA_ERR_SUCCESS != result){
558 goto end_fail;
559 }
560
561 bzero(sta_ctrl_conf_file_path,50);
562 bzero(sta_ctrl_ifname,10);
563
564 sta_event_thread_is_running = 0;
565 // End thread.
566 write(sta_ctrl_pipe_fd[1],"0",1);
567
568
liuyang09c3d7a2024-10-25 10:56:51 +0800569 LOGE("Waitting for thread(%ld) exit.\n",sta_event_thread_id);
liuyangf01f2772024-10-18 16:33:46 +0800570
571 pthread_join(sta_event_thread_id,NULL);
572
liuyang09c3d7a2024-10-25 10:56:51 +0800573 LOGE("pthread_join() return.\n");
liuyangf01f2772024-10-18 16:33:46 +0800574
575
576 close(sta_ctrl_pipe_fd[0]);
577 close(sta_ctrl_pipe_fd[1]);
578
579 sta_event_thread_id = -1;
580 sta_ctrl_msg = NULL;
581
582 // Stop process wpa_supplicant
583 if(sta_ctrl_system("killall -15 wpa_supplicant")
584 && sta_ctrl_kill_check("wpa_supplicant")){
liuyang09c3d7a2024-10-25 10:56:51 +0800585 LOGE("\"killall -15 wpa_supplicant\" success.\n");
liuyangf01f2772024-10-18 16:33:46 +0800586 }else{
587 if(sta_ctrl_system("killall -9 wpa_supplicant")){
liuyang09c3d7a2024-10-25 10:56:51 +0800588 LOGE("\"killall -9 wpa_supplicant\" success.\n");
liuyangf01f2772024-10-18 16:33:46 +0800589 }else{
liuyang09c3d7a2024-10-25 10:56:51 +0800590 LOGE("\"killall -9 wpa_supplicant\" fail.\n");
liuyangf01f2772024-10-18 16:33:46 +0800591 }
592 }
593
594end_success:
liuyang09c3d7a2024-10-25 10:56:51 +0800595 LOGE("sta_ctrl_wpa_deinit() end(success).\n");
liuyangf01f2772024-10-18 16:33:46 +0800596 return result;
597end_fail:
liuyang09c3d7a2024-10-25 10:56:51 +0800598 LOGE("sta_ctrl_wpa_deinit() end(fail)[%s].\n",result);
liuyangf01f2772024-10-18 16:33:46 +0800599 return result;
600}
601