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