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