• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "wpa_work.h"
17 #include <sys/prctl.h>
18 
19 #define WPA_IFACE_NAME "wlan0"
20 #define WIFI_AUTH_FAILED_REASON_STR "WRONG_KEY"
21 #define WIFI_AUTH_FAILED_REASON_CODE "reason=2"
22 #define WPA_CTRL_REQUEST_OK "OK"
23 #define WPA_CTRL_REQUEST_FAIL "FAIL"
24 
25 #define SAMPLE_INFO(format, args...) \
26     do { \
27         fprintf(stderr, "\033[1;32m WpaCliSample(%s:%d):\t\033[0m" format, __func__, __LINE__, ##args); \
28         printf("\n"); \
29     } while (0)
30 
31 #define SAMPLE_ERROR(format, args...) \
32     do { \
33         fprintf(stderr, "\033[1;31m WpaCliSample(%s:%d):\t\033[0m" format, __func__, __LINE__, ##args); \
34         printf("\n"); \
35     } while (0)
36 
37 
38 static struct wpa_ctrl *g_monitorConn = NULL;
39 static pthread_t g_threadId = 0;
40 pthread_mutex_t g_mutex;
41 pthread_mutex_t g_monitorConnMutex;
42 static char g_mySsidD[40][40] = {0};
43 static int g_ssidCount = 0;
44 
45 static char g_useSsidD[40][40] = {0};
46 static int g_useSsidCount = 0;
47 
48 static pthread_t g_wpaThreadId = 0;
49 static pthread_t g_scanThreadId = 0;
50 static int g_scanAvailable = 0;
51 static int g_Connect = 0;
52 
DumpString(const char * buf,int len,const char * tag)53 static void DumpString(const char *buf, int len, const char *tag)
54 {
55     SAMPLE_INFO("%s dump start.", tag);
56     for (int i = 0; i < len; i++) {
57         printf("%c", buf[i]);
58     }
59     printf("\n");
60 
61     printf("\n");
62     SAMPLE_INFO("%s dump end.", tag);
63 }
64 
StrMatch(const char * a,const char * b)65 static int StrMatch(const char *a, const char *b)
66 {
67     return strncmp(a, b, strlen(b)) == 0;
68 }
69 
SendCtrlCommand(const char * cmd,char * reply,size_t * replyLen)70 static int SendCtrlCommand(const char *cmd, char *reply, size_t *replyLen)
71 {
72     static struct wpa_ctrl *ctrlConn = NULL;
73     int i = 0;
74     int reTime = 5;
75     while (i++ < reTime) { // check wpa init success
76         ctrlConn = wpa_ctrl_open(WPA_IFACE_NAME);
77         if (ctrlConn != NULL) {
78             break;
79         }
80         sleep(1);
81     }
82     if (ctrlConn == NULL) {
83         printf("%s:%d [ERROR] control connect handle is null\n", __FUNCTION__, __LINE__);
84         return -1;
85     }
86     size_t len = *replyLen - 1;
87     wpa_ctrl_request(ctrlConn, cmd, strlen(cmd), reply, &len, 0);
88     DumpString(reply, len, "SendCtrlCommand raw return");
89     if (ctrlConn != NULL) {
90         wpa_ctrl_close(ctrlConn);
91         ctrlConn = NULL;
92     }
93 
94     if (len != 0 && !StrMatch(reply, WPA_CTRL_REQUEST_FAIL)) {
95         *replyLen = len;
96         return 0;
97     }
98     SAMPLE_ERROR("send ctrl request [%s] failed.", cmd);
99     return -1;
100 }
101 
ProcessScanResult(const char * buf,int len)102 static void ProcessScanResult(const char *buf, int len)
103 {
104     int myUse1 = 1;
105     int myUse2 = 2;
106     int myUse5 = 5;
107 
108     int err = memset_s(g_mySsidD, sizeof(g_mySsidD), 0, sizeof(g_mySsidD));
109     g_ssidCount = 0;
110     if (err != EOK) {
111         return;
112     }
113     for (int i = 0; i < len; i++) {
114         if (buf[i] == 'E' && buf[i + myUse1] == 'S' && buf[i + myUse2] == 'S') {
115             int j;
116             printf("[ERROR]get the ESS i->%d\n", i);
117             i = i + myUse5;
118             for (j = 0; i < len && buf[i] != '\n'; i++) {
119                 g_mySsidD[g_ssidCount][j] = buf[i];
120                 j++;
121             }
122 
123             g_ssidCount++;
124         }
125     }
126 }
127 
ResetSSIDBuff(void)128 void ResetSSIDBuff(void)
129 {
130     g_useSsidCount = 0;
131 }
132 
GetIdNum(void)133 int GetIdNum(void)
134 {
135     return g_useSsidCount;
136 }
137 
GetCurrentConnInfo(char * ssid,int len)138 int GetCurrentConnInfo(char *ssid, int len)
139 {
140     int offset = 5;
141     char connInfo[2048] = {0};
142     size_t infoLen = sizeof(connInfo);
143     if (g_Connect == 0) {
144         printf("[LOG]GetCurrentConnInfo g_Connect -> 0 \n");
145         return -1;
146     }
147 
148     int ret = SendCtrlCommand("STATUS", connInfo, &infoLen);
149     if (ret == -1) {
150         printf("[ERROR]GetCurrentConnInfo Command(STATUS) Error \n");
151         return -1;
152     }
153     DumpString(connInfo, infoLen, "connInfo");
154     printf("[LOG]end the DumpStrint\n");
155     char *pos = strstr(connInfo, "ssid=");
156     if (pos == NULL) {
157         printf("[ERROR]strstr(ssid) is null");
158         return -1;
159     }
160     if (offset >= strlen(pos)) {
161         return -1;
162     }
163     pos += offset;
164     pos = strstr(pos, "ssid=");
165     if (pos == NULL) {
166         printf("[ERROR]second strstr(ssid) is null");
167         return -1;
168     }
169     char *end = strchr(pos, '\n');
170     if (end == NULL) {
171         printf("[ERROR]second strstr(end) is null");
172         return -1;
173     }
174     int ssidLen = end - pos - offset;
175     if (len < ssidLen) {
176         return -1;
177     }
178     int i = 0;
179     int myOffset = 5;
180     for (pos += myOffset; pos < end; pos++, i++) {
181         ssid[i] = *pos;
182     }
183     return 0;
184 }
185 
ExitWpaScan(void)186 void ExitWpaScan(void)
187 {
188     int ret;
189     if (g_scanThreadId != 0) {
190         ret = pthread_cancel(g_scanThreadId);
191         printf("[INFO]pthread_cancel(g_scanThreadId) ret -> %d \n", ret);
192         g_scanThreadId = 0;
193     }
194     if (g_wpaThreadId != 0) {
195         ret = pthread_cancel(g_wpaThreadId);
196         printf("[INFO]pthread_cancel(g_wpaThreadId) ret -> %d \n", ret);
197         g_wpaThreadId = 0;
198     }
199 }
200 
ExitWpa(void)201 void ExitWpa(void)
202 {
203     int ret;
204     pthread_mutex_lock(&g_monitorConnMutex);
205     if (g_monitorConn != NULL) {
206         wpa_ctrl_close(g_monitorConn);
207         printf("[INFO]wpa_ctrl_close(g_monitorConn).\n");
208         g_monitorConn = NULL;
209     }
210     pthread_mutex_unlock(&g_monitorConnMutex);
211     char result[100] = {0};
212     size_t len = sizeof(result);
213     printf("[INFO]ExitWpa TERMINATE begin.\n");
214     SendCtrlCommand("TERMINATE", result, &len);
215     printf("[INFO]ExitWpa TERMINATE end.\n");
216     sleep(1);
217     DeinitWifiService();
218     if (g_threadId != 0) {
219         ret = pthread_cancel(g_threadId);
220         if (ret != 0) {
221             printf("[ERROR]pthread_cancel(g_threadId) ret -> %d \n", ret);
222         }
223     }
224 
225     ret = pthread_mutex_destroy(&g_mutex);
226     if (ret != 0) {
227         printf("[ERROR]pthread_mutex_destroy ret -> %d \n", ret);
228     }
229     ret = pthread_mutex_destroy(&g_monitorConnMutex);
230     if (ret != 0) {
231         printf("[ERROR]pthread_mutex_destroy ret -> %d \n", ret);
232     }
233 }
234 
GetAndResetScanStat(void)235 int GetAndResetScanStat(void)
236 {
237     int ret = g_scanAvailable;
238     g_scanAvailable = 0;
239     return ret;
240 }
241 
GetSsid(const int ssidNum)242 char *GetSsid(const int ssidNum)
243 {
244     return g_useSsidD[ssidNum];
245 }
246 
LockWifiData()247 void LockWifiData()
248 {
249     pthread_mutex_lock(&g_mutex);
250 }
251 
UnLockWifiData()252 void UnLockWifiData()
253 {
254     pthread_mutex_unlock(&g_mutex);
255 }
256 
CheckSsid(void)257 static void CheckSsid(void)
258 {
259     int i, ret, err;
260     int checkSsid = 0x5C;
261 
262     err = memset_s(g_useSsidD, sizeof(g_useSsidD), 0, sizeof(g_useSsidD));
263     if (err != EOK) {
264         printf("[ERROR]memset_s g_useSsidD failed, err = %d\n", err);
265         return;
266     }
267     g_useSsidCount = 0;
268     for (i = 0; i < g_ssidCount; i++) {
269         int j = i + 1;
270         for (; j < g_ssidCount; j++) {
271             ret = strcmp(g_mySsidD[i], g_useSsidD[j]);
272             if (ret == 0) {
273                 break;
274             }
275         }
276         if ((g_mySsidD[i][0] == checkSsid) || (g_mySsidD[i][0] == 0)) {
277             continue;
278         }
279         if (j == g_ssidCount) {
280             err = strcpy_s(g_useSsidD[g_useSsidCount], sizeof(g_useSsidD[g_useSsidCount]), g_mySsidD[i]);
281             if (err != EOK) {
282                 continue;
283             }
284             g_useSsidCount++;
285         }
286     }
287 }
288 
WifiEventHandler(char * rawEvent,int len)289 static void WifiEventHandler(char *rawEvent, int len)
290 {
291     char *pos = rawEvent;
292     if (*pos == '<') {
293         pos = strchr(pos, '>');
294         if (pos) {
295             pos++;
296         } else {
297             pos = rawEvent;
298         }
299     }
300     if (StrMatch(pos, WPA_EVENT_CONNECTED)) {
301         SAMPLE_INFO("WIFI_EVENT_CONNECTED");
302         g_Connect = 1;
303         return;
304     }
305     if (StrMatch(pos, WPA_EVENT_SCAN_RESULTS)) {
306         pthread_mutex_lock(&g_mutex);
307         SAMPLE_INFO("WIFI_EVENT_SCAN_DONE");
308         char scanResult[4096] = {0};
309         size_t scanLen = sizeof(scanResult);
310         SendCtrlCommand("SCAN_RESULTS", scanResult, &scanLen);
311 
312         ProcessScanResult(scanResult, scanLen);
313         CheckSsid();
314         g_scanAvailable = 1;
315         pthread_mutex_unlock(&g_mutex);
316         return;
317     }
318     if (StrMatch(pos, WPA_EVENT_TEMP_DISABLED) && strstr(pos, WIFI_AUTH_FAILED_REASON_STR)) {
319         SAMPLE_INFO("WIFI_EVENT_WRONG_KEY");
320         return;
321     }
322     if (StrMatch(pos, WPA_EVENT_DISCONNECTED) && !strstr(pos, WIFI_AUTH_FAILED_REASON_CODE)) {
323         SAMPLE_INFO("WIFI_EVENT_DISCONNECTED");
324         return;
325     }
326 }
327 
CliRecvPending(void)328 static void CliRecvPending(void)
329 {
330     int pendingResult = -1;
331     pthread_mutex_lock(&g_monitorConnMutex);
332     if (g_monitorConn!= NULL) {
333         pendingResult = wpa_ctrl_pending(g_monitorConn);
334     }
335     while (pendingResult > 0) {
336         char buf[4096];
337         size_t len = sizeof(buf) - 1;
338         if (g_monitorConn != NULL) {
339             if (wpa_ctrl_recv(g_monitorConn, buf, &len) == 0) {
340                 buf[len] = '\0';
341                 SAMPLE_INFO("event received %s", buf);
342                 WifiEventHandler(buf, len);
343             } else {
344                 SAMPLE_INFO("could not read pending message.");
345                 break;
346             }
347             pendingResult = wpa_ctrl_pending(g_monitorConn);
348         }
349     }
350     pthread_mutex_unlock(&g_monitorConnMutex);
351 }
352 
MonitorTask(void * args)353 static void* MonitorTask(void *args)
354 {
355     (void)args;
356     int fd, ret;
357     fd_set rfd;
358     while (1) {
359         fd = -1;
360         pthread_mutex_lock(&g_monitorConnMutex);
361         if (g_monitorConn != NULL) {
362             fd = wpa_ctrl_get_fd(g_monitorConn);
363         } else {
364             pthread_mutex_unlock(&g_monitorConnMutex);
365             break;
366         }
367         pthread_mutex_unlock(&g_monitorConnMutex);
368         FD_ZERO(&rfd);
369         FD_SET(fd, &rfd);
370         ret = select(fd + 1, &rfd, NULL, NULL, NULL);
371         if (ret <= 0) {
372             SAMPLE_INFO("select failed ret = %d\n", ret);
373             break;
374         }
375         CliRecvPending();
376         sleep(1);
377     }
378     return NULL;
379 }
380 
TestNetworkConfig(const char * gSsid,const char * gPassWord)381 static void TestNetworkConfig(const char *gSsid, const char *gPassWord)
382 {
383     char networkId[20] = {0};
384     size_t networkIdLen = sizeof(networkId);
385     int ret = SendCtrlCommand("DISCONNECT", networkId, &networkIdLen);
386     ret += SendCtrlCommand("ADD_NETWORK", networkId, &networkIdLen);
387     if (ret != 0) {
388         SAMPLE_ERROR("add network failed.");
389         return;
390     }
391     SAMPLE_INFO("add network success, network id [%.*s]", networkIdLen, networkId);
392     char reply[100] = {0};
393     size_t replyLen = sizeof(reply);
394     char cmd[200] = {0};
395     int err = sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s ssid \"%s\"", networkIdLen, networkId, gSsid);
396     if (err < 0) {
397         printf("[ERROR]sprintf_s failed, err = %d\n", err);
398         return;
399     }
400     ret += SendCtrlCommand(cmd, reply, &replyLen);
401     replyLen = sizeof(reply);
402     err = sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s psk \"%s\"", networkIdLen, networkId, gPassWord);
403     if (err < 0) {
404         printf("[ERROR]sprintf_s failed, err = %d\n", err);
405         return;
406     }
407     ret += SendCtrlCommand(cmd, reply, &replyLen);
408     replyLen = sizeof(reply);
409     err = sprintf_s(cmd, sizeof(cmd), "ENABLE_NETWORK %.*s", networkIdLen, networkId);
410     if (err < 0) {
411         printf("[ERROR]sprintf_s failed, err = %d\n", err);
412         return;
413     }
414     ret += SendCtrlCommand(cmd, reply, &replyLen);
415     replyLen = sizeof(reply);
416     ret += SendCtrlCommand("RECONNECT", reply, &replyLen);
417     replyLen = sizeof(reply);
418     if (ret == 0) {
419         SAMPLE_INFO("network config success.");
420         return;
421     }
422     err = sprintf_s(cmd, sizeof(cmd), "REMOVE_NETWORK %.*s", networkIdLen, networkId);
423     if (err < 0) {
424         printf("[ERROR]sprintf_s failed, err = %d\n", err);
425         return;
426     }
427     SendCtrlCommand(cmd, reply, &replyLen);
428     SAMPLE_ERROR("network config failed remove network [%.*s].", networkIdLen, networkId);
429 }
430 
InitControlInterface()431 int InitControlInterface()
432 {
433     int i = 0;
434     int ret;
435     int reTime = 5;
436     while (i++ < reTime) { // create control interface for event monitor
437         g_monitorConn = wpa_ctrl_open(WPA_IFACE_NAME);
438         if (g_monitorConn != NULL) {
439             break;
440         }
441         sleep(1);
442     }
443     if (!g_monitorConn) {
444         SAMPLE_ERROR("open wpa control interface failed.");
445         return -1;
446     }
447 
448     ret = -1;
449     pthread_mutex_lock(&g_monitorConnMutex);
450     if (g_monitorConn!= NULL) {
451         ret = wpa_ctrl_attach(g_monitorConn);
452     }
453     pthread_mutex_unlock(&g_monitorConnMutex);
454     printf("[INFO]wpa_ctrl_attach return %d.\n", ret);
455     if (ret == 0) { // start monitor
456         ret = pthread_create(&g_wpaThreadId, NULL, MonitorTask, NULL); // create thread for read event
457         if (ret != 0) {
458             printf("[ERROR]thread error %s\n", strerror(ret));
459             return -1;
460         }
461         return 0;
462     }
463     return -1;
464 }
465 
WpaScanThread(void * args)466 void* WpaScanThread(void *args)
467 {
468     int mySleep = 2;
469     int ret = 0;
470     sleep(mySleep);
471     if (g_monitorConn == NULL) {
472         ret = InitControlInterface();
473         printf("%s:%d [INFO] InitControlInterface return %d.\n", __FUNCTION__, __LINE__, ret);
474         if (ret == -1) {
475             return NULL;
476         }
477     }
478     char reply[100] = {0};
479     size_t replyLen = sizeof(reply);
480     g_scanAvailable = 0;
481     SendCtrlCommand("SCAN", reply, &replyLen);
482     return NULL;
483 }
484 
WpaScanReconnect(const char * gSsid,const char * gPassWord,const int hiddenSwitch)485 void WpaScanReconnect(const char *gSsid, const char *gPassWord, const int hiddenSwitch)
486 {
487     if (HIDDEN_OPEN == hiddenSwitch) {
488         TestNetworkConfig(gSsid, gPassWord);
489     } else {
490         int ret = pthread_create(&g_scanThreadId, NULL, WpaScanThread, NULL); // create thread for read event
491         if (ret != 0) {
492             printf("[ERROR]thread error %s\n", strerror(ret));
493             return;
494         }
495     }
496 }
497 
ThreadMain()498 static void *ThreadMain()
499 {
500     prctl(PR_SET_NAME, "WPA_THREAD");
501     int i = 0;
502     int myfor = 5;
503     char *arg[20] = {0};
504     arg[i] = (char *)"wpa_supplicant";
505     arg[++i] = (char *)"-i";
506     arg[++i] = (char *)"wlan0";
507     arg[++i] = (char *)"-c";
508     arg[++i] = (char *)"/storage/app/run/com.huawei.setting/setting/assets/setting/resources/base/element/wpa_supplicant.conf";
509 
510     for (i = 0; i < myfor; i++) {
511         printf("[LOG]arg[%d]->%s \n", i, arg[i]);
512     }
513     wpa_main(myfor, arg);
514     return NULL;
515 }
516 
WpaClientStart(void)517 void WpaClientStart(void)
518 {
519     static int runStatus = 0;
520     if (runStatus == 0) {
521         int ret = pthread_create(&g_threadId, NULL, ThreadMain, NULL);
522         if (ret != 0) {
523             printf("[ERROR]thread error %s\n", strerror(ret));
524             return;
525         }
526         ret = pthread_mutex_init(&g_mutex, NULL);
527         if (ret != 0) {
528             printf("[ERROR]pthread_mutex_init error %s\n", strerror(ret));
529             return;
530         }
531 
532         pthread_mutexattr_t attr;
533         pthread_mutexattr_init(&attr);
534         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
535         ret = pthread_mutex_init(&g_monitorConnMutex, &attr);
536         if (ret != 0) {
537             printf("[ERROR]pthread_mutex_init error %s\n", strerror(ret));
538             return;
539         }
540         runStatus = 1;
541     }
542 }
543