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