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