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