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