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