1 /*
2 * Copyright (C) 2021-2022 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 "wifi_hostapd_hal.h"
17 #include <malloc.h>
18 #include <poll.h>
19 #include <pthread.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #ifndef OHOS_ARCH_LITE
25 #include <sys/ioctl.h>
26 #include <linux/wireless.h>
27 #endif
28 #include "securec.h"
29 #include "wpa_ctrl.h"
30 #include "wifi_common_def.h"
31 #include "wifi_hal_callback.h"
32 #include "wifi_log.h"
33
34 #undef LOG_TAG
35 #define LOG_TAG "WifiHostapdHal"
36
37 /**
38 * Blocklist configuration file name. This parameter is used by hostapd in an earlier version.
39 */
40 #define CONFIG_DENY_MAC_FILE_NAME "deny_mac.conf"
41 #define SLEEP_TIME_100_MS (100 * 1000)
42 #define CONFIG_PATH_DIR CONFIG_ROOR_DIR"/wpa_supplicant"
43 #define CTRL_LEN 128
44 #define IFACENAME_LEN 6
45 #define CFGNAME_LEN 30
46
47 #if (AP_NUM > 1)
48 #define WIFI_5G_CFG "hostapd_0.conf"
49 #define WIFI_2G_CFG "hostapd_1.conf"
50 #define HOSTAPD_5G_CFG CONFIG_ROOR_DIR"/wpa_supplicant/"WIFI_5G_CFG
51 #define HOSTAPD_2G_CFG CONFIG_ROOR_DIR"/wpa_supplicant/"WIFI_2G_CFG
52 #define HOSTAPD_5G_UDPPORT "127.0.0.1:9866"
53 #define HOSTAPD_2G_UDPPORT "127.0.0.1:9877"
54
55 WifiHostapdHalDeviceInfo g_hostapdHalDevInfo[] = {
56 {AP_5G_MAIN_INSTANCE, NULL, WIFI_5G_CFG, HOSTAPD_5G_CFG, HOSTAPD_5G_UDPPORT},
57 {AP_2G_MAIN_INSTANCE, NULL, WIFI_2G_CFG, HOSTAPD_2G_CFG, HOSTAPD_2G_UDPPORT},
58 };
59 #else
60 #define AP_IFNAME "wlan0"
61 #define AP_IFNAME_COEX "wlan1"
62 #define WIFI_DEFAULT_CFG "hostapd.conf"
63 #define WIFI_COEX_CFG "hostapd_coex.conf"
64 #define HOSTAPD_CTRL_INTERFACE CONFIG_ROOR_DIR"/sockets/wpa/wlan0"
65 #define HOSTAPD_CTRL_INTERFACE_COEX CONFIG_ROOR_DIR"/sockets/wpa/wlan1"
66 #define HOSTAPD_DEFAULT_CFG CONFIG_ROOR_DIR"/wpa_supplicant/"WIFI_DEFAULT_CFG
67 #define HOSTAPD_DEFAULT_CFG_COEX CONFIG_ROOR_DIR"/wpa_supplicant/"WIFI_COEX_CFG
68 #define HOSTAPD_DEFAULT_UDPPORT "127.0.0.1:9877"
69 #define AP_SET_CFG_DELAY 500000
70 #define SOFTAP_MAX_BUFFER_SIZE 4096
71 #define IFNAMSIZ 16
72
73 // from OSTAPD_DEFAULT_CFG CONFIG_ROOR_DIR"/wpa_supplicant/"WIFI_DEFAULT_CFG
74
75 WifiHostapdHalDeviceInfo g_hostapdHalDevInfo[] = {
76 {AP_2G_MAIN_INSTANCE, NULL, WIFI_DEFAULT_CFG, HOSTAPD_DEFAULT_CFG, HOSTAPD_DEFAULT_UDPPORT}
77 };
78 char g_ctrlInterfacel[CTRL_LEN] = {0};
79 char g_hostapdCfg[CTRL_LEN] = {0};
80 char g_apIfaceName[IFACENAME_LEN] = {0};
81 char g_apCfgName[CFGNAME_LEN] = {0};
82 #endif
83 #define HOSTAPD_CFG_VALUE_ON 1
84
InitCfg(char * ifaceName)85 void InitCfg(char *ifaceName)
86 {
87 if (strncmp(ifaceName, AP_IFNAME_COEX, IFACENAME_LEN - 1) == 0) {
88 if (memcpy_s(g_apCfgName, CFGNAME_LEN, WIFI_COEX_CFG, sizeof(WIFI_COEX_CFG)) != EOK) {
89 LOGE("memcpy cfg fail");
90 }
91 if (memcpy_s(g_apIfaceName, IFACENAME_LEN, AP_IFNAME_COEX, sizeof(AP_IFNAME_COEX)) != EOK) {
92 LOGE("memcpy ap name fail");
93 }
94 if (memcpy_s(g_hostapdCfg, CTRL_LEN, HOSTAPD_DEFAULT_CFG_COEX,
95 sizeof(HOSTAPD_DEFAULT_CFG_COEX)) != EOK) {
96 LOGE("memcpy hostapd fail");
97 }
98 if (memcpy_s(g_ctrlInterfacel, CTRL_LEN, HOSTAPD_CTRL_INTERFACE_COEX,
99 sizeof(HOSTAPD_CTRL_INTERFACE_COEX)) != EOK) {
100 LOGE("memcpy ctrl fail");
101 }
102 } else {
103 if (memcpy_s(g_apCfgName, CFGNAME_LEN, WIFI_DEFAULT_CFG, sizeof(WIFI_DEFAULT_CFG)) != EOK) {
104 LOGE("memcpy cfg fail");
105 }
106 if (memcpy_s(g_apIfaceName, IFACENAME_LEN, AP_IFNAME, sizeof(AP_IFNAME)) != EOK) {
107 LOGE("memcpy ap name fail");
108 }
109 if (memcpy_s(g_hostapdCfg, CTRL_LEN, HOSTAPD_DEFAULT_CFG,
110 sizeof(HOSTAPD_DEFAULT_CFG)) != EOK) {
111 LOGE("memcpy hostapd fail");
112 }
113 if (memcpy_s(g_ctrlInterfacel, CTRL_LEN, HOSTAPD_CTRL_INTERFACE,
114 sizeof(HOSTAPD_CTRL_INTERFACE)) != EOK) {
115 LOGE("memcpy ctrl fail");
116 }
117 }
118 g_hostapdHalDevInfo[0].cfgName = g_apCfgName;
119 g_hostapdHalDevInfo[0].config = g_hostapdCfg;
120 }
121
GetWifiCfg(int * len)122 WifiHostapdHalDeviceInfo *GetWifiCfg(int *len)
123 {
124 *len = sizeof(g_hostapdHalDevInfo) / sizeof(WifiHostapdHalDeviceInfo);
125 return g_hostapdHalDevInfo;
126 }
127 /*
128 * The wpa_ctrl_pending interface provided by the WPA does not wait for the response.
129 * As a result, the CPU usage is high. Reconstructed
130 */
MyWpaCtrlPending(struct wpa_ctrl * ctrl)131 static int MyWpaCtrlPending(struct wpa_ctrl *ctrl)
132 {
133 if (ctrl == NULL) {
134 return -1;
135 }
136 struct pollfd pfd;
137 if (memset_s(&pfd, sizeof(pfd), 0, sizeof(pfd)) != EOK) {
138 return -1;
139 }
140 pfd.fd = wpa_ctrl_get_fd(ctrl);
141 pfd.events = POLLIN;
142 int ret = poll(&pfd, 1, 100); /* 100 ms */
143 if (ret < 0) {
144 LOGE("poll failed! errno = %{public}d", errno);
145 if (errno == EINTR) {
146 return 0;
147 }
148 return -1;
149 } else if (ret == 0) {
150 return 0;
151 } else {
152 return 1;
153 }
154 }
155
DelCallbackMessage(const char * msg,int id)156 static void DelCallbackMessage(const char *msg, int id)
157 {
158 if (msg == NULL) {
159 return;
160 }
161 if (strncmp(msg, AP_STA_CONNECTED, strlen(AP_STA_CONNECTED)) == 0 ||
162 strncmp(msg, AP_STA_DISCONNECTED, strlen(AP_STA_DISCONNECTED)) == 0) {
163 WifiHalCbStaJoin(msg, id);
164 } else if (strncmp(msg, AP_EVENT_ENABLED, strlen(AP_EVENT_ENABLED)) == 0 ||
165 strncmp(msg, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0 ||
166 strncmp(msg, WPA_EVENT_TERMINATING, strlen(WPA_EVENT_TERMINATING)) == 0) {
167 if (strncmp(msg, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0 &&
168 g_hostapdHalDevInfo[id].hostapdHalDev->execDisable == 1) {
169 g_hostapdHalDevInfo[id].hostapdHalDev->execDisable = 0;
170 return;
171 }
172 WifiHalCbApState(msg, id);
173 if (strncmp(msg, WPA_EVENT_TERMINATING, strlen(WPA_EVENT_TERMINATING)) == 0) {
174 g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag = 0;
175 }
176 } else if (strncmp(msg, AP_STA_POSSIBLE_PSK_MISMATCH, strlen(AP_STA_POSSIBLE_PSK_MISMATCH)) == 0) {
177 WifiHalCbApState(msg, id);
178 }
179 }
180
HostapdReceiveCallback(void * arg)181 static void *HostapdReceiveCallback(void *arg)
182 {
183 if (arg == NULL) {
184 LOGE("%{public}s arg is null", __func__);
185 return NULL;
186 }
187 WifiHostapdHalDeviceInfo *halDeviceInfo = arg;
188 int id = halDeviceInfo->id;
189 if (halDeviceInfo->hostapdHalDev == NULL ||
190 halDeviceInfo->hostapdHalDev->ctrlRecv == NULL) {
191 LOGE("%{public}s invalid HalDev or ctrlRecv", __func__);
192 return NULL;
193 }
194 struct wpa_ctrl *ctrl = halDeviceInfo->hostapdHalDev->ctrlRecv;
195 char *buf = (char *)calloc(BUFSIZE_RECV, sizeof(char));
196 if (buf == NULL) {
197 LOGE("In hostapd deal receive message thread, failed to calloc buff!");
198 return NULL;
199 }
200 while (g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag) {
201 int ret = MyWpaCtrlPending(ctrl);
202 if (ret < 0) {
203 LOGE("hostapd thread get event message failed!");
204 break;
205 } else if (ret == 0) {
206 continue;
207 }
208 if (memset_s(buf, BUFSIZE_RECV, 0, BUFSIZE_RECV) != EOK) {
209 LOGE("thread clear buffer cache failed!");
210 break;
211 }
212 size_t len = BUFSIZE_RECV - 1;
213 ret = wpa_ctrl_recv(ctrl, buf, &len);
214 if (ret < 0) {
215 LOGE("hostapd thread read event message failed!");
216 break;
217 }
218 if (len <= 0) {
219 continue;
220 }
221 char *p = buf;
222 if (*p == '<') {
223 p = strchr(p, '>');
224 (p == NULL) ? (p = buf) : (p++);
225 }
226 DelCallbackMessage(p, id);
227 }
228 free(buf);
229 buf = NULL;
230 LOGI("=====================hostapd thread exist=======================");
231 return NULL;
232 }
233
ReleaseHostapdCtrl(int id)234 void ReleaseHostapdCtrl(int id)
235 {
236 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL) {
237 return;
238 }
239 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn != NULL) {
240 wpa_ctrl_close(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn);
241 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn = NULL;
242 }
243 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv != NULL) {
244 wpa_ctrl_close(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv);
245 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv = NULL;
246 }
247 return;
248 }
249
InitHostapdCtrl(const char * ifname,int id)250 int InitHostapdCtrl(const char *ifname, int id)
251 {
252 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL || ifname == NULL) {
253 return -1;
254 }
255 int flag = 0;
256 do {
257 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv = wpa_ctrl_open(ifname);
258 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv == NULL) {
259 LOGE("open hostapd control interface ctrlRecv failed!");
260 break;
261 }
262 if (wpa_ctrl_attach(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv) != 0) {
263 LOGE("attach hostapd monitor interface failed!");
264 break;
265 }
266 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn = wpa_ctrl_open(ifname);
267 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn == NULL) {
268 LOGE("open hostapd control interface ctrlConn failed!");
269 break;
270 }
271 flag += 1;
272 } while (0);
273 if (!flag) {
274 ReleaseHostapdCtrl(id);
275 return -1;
276 }
277 return 0;
278 }
279
GetDestPort(char * destPort,size_t len,int id)280 void GetDestPort(char *destPort, size_t len, int id)
281 {
282 if (strcpy_s(destPort, len, g_hostapdHalDevInfo[id].udpPort) != EOK) {
283 LOGW("failed to copy the destPort");
284 }
285 }
286
GetCtrlInterface(char * ctrl_path,size_t len,int id)287 void GetCtrlInterface(char *ctrl_path, size_t len, int id)
288 {
289 if (strcpy_s(ctrl_path, len, g_ctrlInterfacel) != EOK) {
290 LOGW("failed to copy the ctrl_path");
291 }
292 }
293
HostapdCliConnect(int id)294 static int HostapdCliConnect(int id)
295 {
296 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL) {
297 LOGE("hostapdHalDev is NULL!");
298 return -1;
299 }
300 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn != NULL) {
301 LOGE("Hostapd already initialized!");
302 return 0;
303 }
304 int retryCount = 20;
305 char ifname[BUFFER_SIZE_128] = {0};
306 #ifdef WPA_CTRL_IFACE_UNIX
307 GetCtrlInterface(ifname, sizeof(ifname), id);
308 #else
309 GetDestPort(ifname, sizeof(ifname), id);
310 #endif
311 while (retryCount-- > 0) {
312 int ret = InitHostapdCtrl(ifname, id);
313 if (ret == 0) {
314 LOGI("Global hostapd interface connect successfully!");
315 break;
316 } else {
317 LOGD("Init hostapd ctrl failed: %{public}d", ret);
318 }
319 usleep(SLEEP_TIME_100_MS);
320 }
321 if (retryCount <= 0) {
322 LOGD("Retry init hostapd ctrl failed, retryCount: %{public}d", retryCount);
323 return -1;
324 }
325 g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag = 1;
326 if (pthread_create(&g_hostapdHalDevInfo[id].hostapdHalDev->tid, NULL,
327 HostapdReceiveCallback, &g_hostapdHalDevInfo[id]) != 0) {
328 g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag = 0;
329 ReleaseHostapdCtrl(id);
330 LOGE("Create hostapd monitor thread failed!");
331 return -1;
332 }
333 pthread_setname_np(g_hostapdHalDevInfo[id].hostapdHalDev->tid, "HostapdCBThread");
334 return 0;
335 }
336
HostapdCliClose(int id)337 static int HostapdCliClose(int id)
338 {
339 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL) {
340 return 0;
341 }
342 if (g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn != NULL) {
343 g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag = 0;
344 pthread_join(g_hostapdHalDevInfo[id].hostapdHalDev->tid, NULL);
345 g_hostapdHalDevInfo[id].hostapdHalDev->tid = 0;
346 wpa_ctrl_close(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv);
347 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlRecv = NULL;
348 wpa_ctrl_close(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn);
349 g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn = NULL;
350 }
351 return 0;
352 }
353
WpaCtrlCommand(struct wpa_ctrl * ctrl,const char * cmd,char * buf,size_t bufSize)354 static int WpaCtrlCommand(struct wpa_ctrl *ctrl, const char *cmd, char *buf, size_t bufSize)
355 {
356 if (ctrl == NULL || cmd == NULL || buf == NULL || bufSize <= 0) {
357 LOGE("Request parameters not correct");
358 return -1;
359 }
360 size_t len = bufSize - 1;
361 int ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL);
362 if (ret == REQUEST_FAILED) {
363 LOGE("Command timed out.");
364 return ret;
365 } else if (ret < 0) {
366 LOGE("Command failed.");
367 return -1;
368 }
369
370 buf[len] = '\0';
371 if (memcmp(buf, "FAIL", FAIL_LENGTH) == 0) {
372 LOGD("Command result not ok, return %{public}s", buf);
373 return -1;
374 }
375 return 0;
376 }
377
EnableAp(int id)378 static int EnableAp(int id)
379 {
380 char buf[BUFSIZE_REQUEST_SMALL] = {0};
381 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "ENABLE", buf, sizeof(buf));
382 }
383
SetApName(const char * name,int id)384 static int SetApName(const char *name, int id)
385 {
386 if (name == NULL) {
387 return -1;
388 }
389 char cmd[BUFSIZE_CMD] = {0};
390 char buf[BUFSIZE_REQUEST_SMALL] = {0};
391
392 if (sprintf_s(cmd, sizeof(cmd), "SET ssid %s", name) < 0) {
393 return -1;
394 }
395 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
396 }
397
SetApRsnPairwise(const char * type,int id)398 static int SetApRsnPairwise(const char *type, int id)
399 {
400 if (type == NULL) {
401 return -1;
402 }
403
404 char cmd[BUFSIZE_CMD] = {0};
405 char buf[BUFSIZE_REQUEST_SMALL] = {0};
406
407 if (sprintf_s(cmd, sizeof(cmd), "SET rsn_pairwise %s", type) < 0) {
408 return -1;
409 }
410 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
411 }
412
SetApWpaPairwise(const char * type,int id)413 static int SetApWpaPairwise(const char *type, int id)
414 {
415 if (type == NULL) {
416 return -1;
417 }
418 char cmd[BUFSIZE_CMD] = {0};
419 char buf[BUFSIZE_REQUEST_SMALL] = {0};
420
421 if (sprintf_s(cmd, sizeof(cmd), "SET wpa_pairwise %s", type) < 0) {
422 return -1;
423 }
424 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
425 }
426
SetApWpaKeyMgmt(const char * type,int id)427 static int SetApWpaKeyMgmt(const char *type, int id)
428 {
429 if (type == NULL) {
430 return -1;
431 }
432 char cmd[BUFSIZE_CMD] = {0};
433 char buf[BUFSIZE_REQUEST_SMALL] = {0};
434
435 if (sprintf_s(cmd, sizeof(cmd), "SET wpa_key_mgmt %s", type) < 0) {
436 return -1;
437 }
438 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
439 }
440
SetApWpaValue(int securityType,int id)441 static int SetApWpaValue(int securityType, int id)
442 {
443 int retval = -1;
444 char cmd[BUFSIZE_CMD] = {0};
445 char buf[BUFSIZE_REQUEST_SMALL] = {0};
446
447 switch (securityType) {
448 case NONE:
449 retval = sprintf_s(cmd, sizeof(cmd), "SET wpa 0"); /* The authentication mode is NONE. */
450 break;
451 case WPA_PSK:
452 retval = sprintf_s(cmd, sizeof(cmd), "SET wpa 1"); /* The authentication mode is WPA-PSK. */
453 break;
454 case WPA2_PSK:
455 retval = sprintf_s(cmd, sizeof(cmd), "SET wpa 2"); /* The authentication mode is WPA2-PSK. */
456 break;
457 default:
458 LOGE("Unknown encryption type!");
459 return retval;
460 }
461 if (retval < 0) {
462 return -1;
463 }
464
465 retval = WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
466 if (retval == 0 && securityType != NONE) {
467 /*
468 * If the value of wpa is switched between 0, 1, and 2, the wpa_key_mgmt,
469 * wpa_pairwise, and rsn_pairwise attributes must be set. Otherwise, the
470 * enable or STA cannot be connected.
471 */
472 retval = SetApWpaKeyMgmt("WPA-PSK", id);
473 }
474 if (retval == 0 && securityType == WPA_PSK) {
475 retval = SetApWpaPairwise("CCMP", id);
476 }
477 if (retval == 0 && securityType == WPA2_PSK) {
478 retval = SetApRsnPairwise("CCMP", id);
479 }
480 return retval;
481 }
482
SetApPasswd(const char * pass,int id)483 static int SetApPasswd(const char *pass, int id)
484 {
485 if (pass == NULL) {
486 return -1;
487 }
488 char cmd[BUFSIZE_CMD] = {0};
489 char buf[BUFSIZE_REQUEST_SMALL] = {0};
490
491 if (sprintf_s(cmd, sizeof(cmd), "SET wpa_passphrase %s", pass) < 0) {
492 return -1;
493 }
494 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
495 }
496
SetApChannel(int channel,int id)497 static int SetApChannel(int channel, int id)
498 {
499 char cmd[BUFSIZE_CMD] = {0};
500 char buf[BUFSIZE_REQUEST_SMALL] = {0};
501
502 if (sprintf_s(cmd, sizeof(cmd), "SET channel %d", channel) < 0) {
503 return -1;
504 }
505 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
506 }
507
SetApWmm(int value,int id)508 static int SetApWmm(int value, int id)
509 {
510 char cmd[BUFSIZE_CMD] = {0};
511 char buf[BUFSIZE_REQUEST_SMALL] = {0};
512
513 if (sprintf_s(cmd, sizeof(cmd), "SET wmm_enabled %d", value) < 0) {
514 return -1;
515 }
516 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
517 }
518
SetAp80211n(int value,int id)519 static int SetAp80211n(int value, int id)
520 {
521 char cmd[BUFSIZE_CMD] = {0};
522 char buf[BUFSIZE_REQUEST_SMALL] = {0};
523
524 if (sprintf_s(cmd, sizeof(cmd), "SET ieee80211n %d", value) < 0) {
525 return -1;
526 }
527 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
528 }
529
SetApBand(int band,int id)530 static int SetApBand(int band, int id)
531 {
532 char cmd[BUFSIZE_CMD] = {0};
533 char buf[BUFSIZE_REQUEST_SMALL] = {0};
534 const char *hwMode = NULL;
535
536 switch (band) {
537 case AP_NONE_BAND:
538 hwMode = "any"; /* Unknown frequency band */
539 break;
540 case AP_2GHZ_BAND:
541 hwMode = "g"; /* BAND_2_4_GHZ */
542 break;
543 case AP_5GHZ_BAND:
544 hwMode = "a"; /* BAND_5_GHZ */
545 break;
546 default:
547 LOGE("Invalid band!");
548 return -1;
549 }
550
551 if (sprintf_s(cmd, sizeof(cmd), "SET hw_mode %s", hwMode) < 0) {
552 return -1;
553 }
554 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
555 }
556
557 #ifndef OHOS_ARCH_LITE
SendPrivateCmd(struct iwreq * wrq,struct iw_priv_args * privPtr,const char * fName,int bufLen,int sock,char dataBuf[])558 static int SendPrivateCmd(struct iwreq *wrq, struct iw_priv_args *privPtr, const char *fName,
559 int bufLen, int sock, char dataBuf[])
560 {
561 int i, j, ret;
562 int cmd = 0;
563 int subCmd = 0;
564
565 if (wrq == NULL || privPtr == NULL || fName == NULL) {
566 return -1;
567 }
568 for (i = 0; i < wrq->u.data.length; i++) {
569 if (strncmp(privPtr[i].name, fName, strlen(fName)) == 0) {
570 cmd = (int)privPtr[i].cmd;
571 break;
572 }
573 }
574 if (i == wrq->u.data.length) {
575 LOGE("fName: %{public}s - function not supported", fName);
576 return -1;
577 }
578 if (cmd < SIOCDEVPRIVATE) {
579 for (j = 0; j < i; j++) {
580 if ((privPtr[j].set_args == privPtr[i].set_args) &&
581 (privPtr[j].get_args == privPtr[i].get_args) &&
582 (privPtr[j].name[0] == '\0')) {
583 break;
584 }
585 }
586 if (j == i) {
587 LOGE("fName: %{public}s - invalid private ioctl", fName);
588 return -1;
589 }
590 subCmd = cmd;
591 cmd = (int)privPtr[j].cmd;
592 }
593 wrq->ifr_name[IFNAMSIZ - 1] = '\0';
594 if ((bufLen == 0) && (*dataBuf != 0)) {
595 wrq->u.data.length = strlen(dataBuf) + 1;
596 } else {
597 wrq->u.data.length = (uint16_t)bufLen;
598 }
599 wrq->u.data.pointer = dataBuf;
600 wrq->u.data.flags = (uint16_t)subCmd;
601 ret = ioctl(sock, cmd, wrq);
602 LOGD("the data length is:%d, ret is %d", wrq->u.data.length, ret);
603 return ret;
604 }
605
SetCommandHwHisi(const char * iface,const char * fName,unsigned int bufLen,char dataBuf[])606 static int SetCommandHwHisi(const char *iface, const char *fName, unsigned int bufLen, char dataBuf[])
607 {
608 char buf[SOFTAP_MAX_BUFFER_SIZE] = { 0 };
609 struct iwreq wrq;
610 int ret;
611
612 if (iface == NULL || fName == NULL) {
613 LOGE("SetCommandHwHisi: iface or fName is null.");
614 return -1;
615 }
616
617 ret = strncpy_s(wrq.ifr_name, sizeof(wrq.ifr_name), g_apIfaceName, strlen(g_apIfaceName));
618 if (ret != EOK) {
619 LOGE("%{public}s strncpy_s wrq fail", __func__);
620 return -1;
621 }
622 wrq.ifr_name[IFNAMSIZ - 1] = '\0';
623 wrq.u.data.pointer = buf;
624 wrq.u.data.length = sizeof(buf) / sizeof(struct iw_priv_args);
625 wrq.u.data.flags = 0;
626 LOGD("the interface name is: %{public}s", wrq.ifr_name);
627
628 int sock = socket(AF_INET, SOCK_DGRAM, 0);
629 if (sock < 0) {
630 LOGE("Softap SetCommandHw - failed to open socket");
631 return -1;
632 }
633 ret = ioctl(sock, SIOCGIWPRIV, &wrq);
634 if (ret < 0) {
635 LOGE("SIOCGIPRIV failed: %{public}d", ret);
636 close(sock);
637 return ret;
638 }
639 struct iw_priv_args *privPtr = (struct iw_priv_args *)wrq.u.data.pointer;
640 ret = strncpy_s(wrq.ifr_name, sizeof(wrq.ifr_name), g_apIfaceName, strlen(g_apIfaceName));
641 if (ret != EOK) {
642 LOGE("%{public}s strncpy_s wrq fail", __func__);
643 close(sock);
644 return -1;
645 }
646 ret = SendPrivateCmd(&wrq, privPtr, fName, bufLen, sock, dataBuf);
647 close(sock);
648 return ret;
649 }
650
AddParam(unsigned int position,const char * cmd,const char * arg,char outDataBuf[],unsigned int outSize)651 static int AddParam(unsigned int position, const char *cmd, const char *arg, char outDataBuf[], unsigned int outSize)
652 {
653 if (position < 0) {
654 LOGE("%{public}s position < 0", __func__);
655 return position;
656 }
657 if (cmd == NULL || arg == NULL) {
658 LOGE("%{public}s cmd == NULL || arg == NULL", __func__);
659 return -1;
660 }
661 if ((unsigned int)(position + strlen(cmd) + strlen(arg) + 3) >= outSize) { // 3: for "=" "," and terminator
662 LOGE("%{public}s Command line is too big", __func__);
663 return -1;
664 }
665
666 int ret = sprintf_s(&outDataBuf[position], outSize - position, "%s=%s,", cmd, arg);
667 if (ret == -1) {
668 LOGE("%{public}s sprintf_s cmd fail", __func__);
669 return -1;
670 }
671 position += ret;
672 return position;
673 }
674
SetApMaxConnHw(int maxConn,int channel)675 static int SetApMaxConnHw(int maxConn, int channel)
676 {
677 char dataBuf[SOFTAP_MAX_BUFFER_SIZE] = { 0 };
678 if (memset_s(dataBuf, SOFTAP_MAX_BUFFER_SIZE, 0, SOFTAP_MAX_BUFFER_SIZE) != EOK) {
679 LOGE("SetApMaxConnHw memset_s fail");
680 return -1;
681 }
682 int index = 0;
683 if ((index = AddParam(index, "ASCII_CMD", "AP_CFG", dataBuf, SOFTAP_MAX_BUFFER_SIZE)) == -1) {
684 LOGE("AddParam ASCII_CMD fail");
685 return -1;
686 }
687 char chann[10] = {0};
688 if (sprintf_s(chann, sizeof(chann), "%d", channel) == -1) {
689 LOGE("AddParam CHANNEL sprintf_s failed");
690 return -1;
691 }
692 if ((index = AddParam(index, "CHANNEL", chann, dataBuf, SOFTAP_MAX_BUFFER_SIZE)) == -1) {
693 LOGE("AddParam CHANNEL fail");
694 return -1;
695 }
696 char maxStaNum[10] = {0};
697 if (sprintf_s(maxStaNum, sizeof(maxStaNum), "%d", maxConn) == -1) {
698 LOGE("AddParam maxStaNum sprintf_s failed");
699 return -1;
700 }
701 if ((index = AddParam(index, "MAX_SCB", maxStaNum, dataBuf, SOFTAP_MAX_BUFFER_SIZE)) == -1) {
702 LOGE("AddParam MAX_SCB fail");
703 return -1;
704 }
705 if ((unsigned int)(index + 4) >= sizeof(dataBuf)) { // 4 : for "END" and terminator
706 LOGE("Command line is too big");
707 return -1;
708 }
709 int ret = sprintf_s(&dataBuf[index], sizeof(dataBuf) - index, "END");
710 if (ret == -1) {
711 LOGE("sprintf_s fail.");
712 return -1;
713 }
714 LOGD("the command is :%{public}s", dataBuf);
715
716 ret = SetCommandHwHisi(AP_IFNAME, "AP_SET_CFG", SOFTAP_MAX_BUFFER_SIZE, dataBuf);
717 if (ret) {
718 LOGE("SetSoftapHw - failed: %{public}d", ret);
719 } else {
720 LOGI("SetSoftapHw - Ok");
721 usleep(AP_SET_CFG_DELAY);
722 }
723 return 0;
724 }
725 #endif
726
SetApMaxConn(int maxConn,int id)727 static int SetApMaxConn(int maxConn, int id)
728 {
729 char cmd[BUFSIZE_CMD] = {0};
730 char buf[BUFSIZE_REQUEST_SMALL] = {0};
731
732 if (sprintf_s(cmd, sizeof(cmd), "SET max_num_sta %d", maxConn) < 0) {
733 return -1;
734 }
735 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
736 }
737
SetApInfo(HostapdConfig * info,int id)738 static int SetApInfo(HostapdConfig *info, int id)
739 {
740 if (info == NULL) {
741 return -1;
742 }
743 int retval = -1;
744 if (info->securityType != NONE) {
745 int passwdLen = strlen(info->preSharedKey);
746 if (passwdLen < PASSWD_MIN_LEN || passwdLen != info->preSharedKeyLen) {
747 LOGE("password is invalid!");
748 return retval;
749 }
750 if ((retval = SetApPasswd((char *)info->preSharedKey, id)) != 0) {
751 LOGE("SetApPasswd failed. retval %{public}d", retval);
752 return retval;
753 }
754 }
755 if ((retval = SetApName((char *)info->ssid, id)) != 0) {
756 LOGE("SetApName failed. retval %{public}d", retval);
757 return retval;
758 }
759 if ((retval = SetApWpaValue(info->securityType, id)) != 0) {
760 LOGE("SetApWpaValue failed. retval %{public}d", retval);
761 return retval;
762 }
763 if ((retval = SetApBand(info->band, id)) != 0) {
764 LOGE("SetApBand failed. retval %{public}d", retval);
765 return retval;
766 }
767 if ((retval = SetAp80211n(HOSTAPD_CFG_VALUE_ON, id)) != 0) {
768 // only log error
769 LOGE("SetAp80211n failed. retval %{public}d", retval);
770 }
771 if ((retval = SetApWmm(HOSTAPD_CFG_VALUE_ON, id)) != 0) {
772 // only log error
773 LOGE("SetApWmm failed. retval %{public}d", retval);
774 }
775 if ((retval = SetApChannel(info->channel, id)) != 0) {
776 LOGE("SetApChannel failed. retval %{public}d", retval);
777 return retval;
778 }
779 #ifndef OHOS_ARCH_LITE
780 if (info->maxConn >= 0) {
781 int wpaRet = SetApMaxConn(info->maxConn, id);
782 retval = SetApMaxConnHw(info->maxConn, info->channel);
783 LOGI("SetApMaxConn:%{public}d SetApMaxConnHw:%{public}d", wpaRet, retval);
784 }
785 #endif
786 return retval;
787 }
788
DisableAp(int id)789 static int DisableAp(int id)
790 {
791 char buf[BUFSIZE_REQUEST_SMALL] = {0};
792 g_hostapdHalDevInfo[id].hostapdHalDev->execDisable = 1;
793 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "DISABLE", buf, sizeof(buf));
794 }
795
ModBlockList(const char * mac,int id)796 static int ModBlockList(const char *mac, int id)
797 {
798 if (mac == NULL) {
799 return -1;
800 }
801 char buf[BUFSIZE_REQUEST_SMALL] = {0};
802 char cmd[BUFSIZE_CMD] = {0};
803 char file[FILE_NAME_SIZE] = {0};
804 if (snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s/%s", CONFIG_PATH_DIR, CONFIG_DENY_MAC_FILE_NAME) < 0) {
805 return -1;
806 }
807 FILE *fp = fopen(file, "w");
808 if (fp == NULL) {
809 return -1;
810 }
811 if (fprintf(fp, "%s\n", mac) < 0) {
812 fclose(fp);
813 return -1;
814 }
815 fclose(fp);
816 if (sprintf_s(cmd, sizeof(cmd), "SET deny_mac_file %s/%s", CONFIG_PATH_DIR, CONFIG_DENY_MAC_FILE_NAME) < 0) {
817 return -1;
818 }
819 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
820 }
821
AddBlocklist(const char * mac,int id)822 static int AddBlocklist(const char *mac, int id)
823 {
824 if (mac == NULL) {
825 return -1;
826 }
827 char cmd[BUFSIZE_CMD] = {0};
828 char buf[BUFSIZE_REQUEST_SMALL] = {0};
829
830 if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "DENY_ACL ADD_MAC %s", mac) < 0) {
831 return -1;
832 }
833 if (WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf)) != 0) {
834 LOGE("AddBlocklist Failed");
835 return -1;
836 }
837 if (strncasecmp(buf, "UNKNOWN COMMAND", UNKNOWN_COMMAND_LENGTH) == 0) {
838 LOGD("AddBlocklist DENY_ACL command return %{public}s, use SET command", buf);
839 /**
840 * The hostapd of an earlier version does not support the DENY_ACL command and uses the configuration file.
841 */
842 return ModBlockList(mac, id);
843 }
844 return 0;
845 }
846
DelBlocklist(const char * mac,int id)847 static int DelBlocklist(const char *mac, int id)
848 {
849 if (mac == NULL) {
850 return -1;
851 }
852 char cmd[BUFSIZE_CMD] = {0};
853 char buf[BUFSIZE_REQUEST_SMALL] = {0};
854
855 if (sprintf_s(cmd, sizeof(cmd), "DENY_ACL DEL_MAC %s", mac) < 0) {
856 return -1;
857 }
858 if (WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf)) != 0) {
859 LOGE("DelBlocklist Failed");
860 return -1;
861 }
862 if (strncasecmp(buf, "UNKNOWN COMMAND", UNKNOWN_COMMAND_LENGTH) == 0) {
863 LOGD("DelBlocklist DENY_ACL command return %{public}s, use SET command", buf);
864 if (sprintf_s(cmd, sizeof(cmd), "-%s", mac) < 0) {
865 return -1;
866 }
867 return ModBlockList(cmd, id);
868 }
869 return 0;
870 }
871
GetApStatus(StatusInfo * info,int id)872 static int GetApStatus(StatusInfo *info, int id)
873 {
874 if (info == NULL) {
875 return -1;
876 }
877 char *buf = (char *)calloc(BUFSIZE_RECV, sizeof(char));
878 if (buf == NULL) {
879 return -1;
880 }
881
882 if (WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "STATUS", buf, BUFSIZE_RECV) != 0) {
883 LOGE("Status WpaCtrlCommand failed");
884 free(buf);
885 buf = NULL;
886 return -1;
887 }
888
889 char *p = strstr(buf, "state=");
890 if (p == NULL) {
891 LOGD("Status not find state result!");
892 free(buf);
893 buf = NULL;
894 return 0;
895 }
896 p += strlen("state="); // skip state=
897 unsigned pos = 0;
898 while (pos < sizeof(info->state) - 1 && *p != '\0' && *p != '\n') {
899 info->state[pos++] = *p;
900 ++p;
901 }
902 info->state[pos] = 0;
903 free(buf);
904 buf = NULL;
905 return 0;
906 }
907
ShowConnectedDevList(char * buf,int size,int id)908 static int ShowConnectedDevList(char *buf, int size, int id)
909 {
910 if (buf == NULL) {
911 return -1;
912 }
913 char cmd[BUFSIZE_CMD] = {0};
914 char *reqBuf = (char *)calloc(BUFSIZE_REQUEST, sizeof(char));
915 if (reqBuf == NULL) {
916 return -1;
917 }
918 if (WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "STA-FIRST",
919 reqBuf, BUFSIZE_REQUEST) != 0) {
920 LOGE("HostapdCliCmdListSta Failed");
921 free(reqBuf);
922 reqBuf = NULL;
923 return -1;
924 }
925 do {
926 char *pos = reqBuf;
927 while (*pos != '\0' && *pos != '\n') { /* return station info, first line is mac address */
928 pos++;
929 }
930 *pos = '\0';
931 if (strcmp(reqBuf, "") != 0) {
932 int bufLen = strlen(buf);
933 int staLen = strlen(reqBuf);
934 if (bufLen + staLen + 1 >= size) {
935 free(reqBuf);
936 reqBuf = NULL;
937 return 0;
938 }
939 buf[bufLen++] = ',';
940 for (int i = 0; i < staLen; ++i) {
941 buf[bufLen + i] = reqBuf[i];
942 }
943 buf[bufLen + staLen] = '\0';
944 }
945 if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "STA-NEXT %s", reqBuf) < 0) {
946 break;
947 }
948 } while (WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, reqBuf, BUFSIZE_REQUEST) == 0);
949 free(reqBuf);
950 reqBuf = NULL;
951 return 0;
952 }
953
ReloadApConfigInfo(int id)954 static int ReloadApConfigInfo(int id)
955 {
956 char buf[BUFSIZE_REQUEST_SMALL] = {0};
957 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "RELOAD", buf, sizeof(buf));
958 }
959
DisConnectedDev(const char * mac,int id)960 static int DisConnectedDev(const char *mac, int id)
961 {
962 if (mac == NULL) {
963 return -1;
964 }
965 char cmd[BUFSIZE_CMD] = {0};
966 char buf[BUFSIZE_REQUEST_SMALL] = {0};
967
968 if (sprintf_s(cmd, sizeof(cmd), "DISASSOCIATE %s", mac) < 0) {
969 return -1;
970 }
971 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
972 }
973
SetCountryCode(const char * code,int id)974 static int SetCountryCode(const char *code, int id)
975 {
976 if (code == NULL) {
977 return -1;
978 }
979 char cmd[BUFSIZE_CMD] = {0};
980 char buf[BUFSIZE_REQUEST_SMALL] = {0};
981
982 if (sprintf_s(cmd, sizeof(cmd), "SET country_code %s", code) < 0) {
983 return -1;
984 }
985 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, cmd, buf, sizeof(buf));
986 }
987
TerminateAp(int id)988 static int TerminateAp(int id)
989 {
990 if (id < 0 || id >= AP_MAX_INSTANCE) {
991 LOGE("Invalid id: %{public}d!", id);
992 return -1;
993 }
994
995 char buf[BUFSIZE_REQUEST_SMALL] = {0};
996 g_hostapdHalDevInfo[id].hostapdHalDev->execDisable = 1;
997 return WpaCtrlCommand(g_hostapdHalDevInfo[id].hostapdHalDev->ctrlConn, "TERMINATE", buf, sizeof(buf));
998 }
999
InitHostapdHal(int id)1000 static int InitHostapdHal(int id)
1001 {
1002 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL) {
1003 return -1;
1004 }
1005 g_hostapdHalDevInfo[id].hostapdHalDev->threadRunFlag = 1;
1006 if (HostapdCliConnect(id) != 0) {
1007 return -1;
1008 }
1009 return 0;
1010 }
1011
GetWifiHostapdDev(int id)1012 WifiHostapdHalDevice *GetWifiHostapdDev(int id)
1013 {
1014 if (id < 0 || id >= AP_MAX_INSTANCE) {
1015 LOGE("Invalid id: %{public}d!", id);
1016 return NULL;
1017 }
1018
1019 if (g_hostapdHalDevInfo[id].hostapdHalDev != NULL) {
1020 return g_hostapdHalDevInfo[id].hostapdHalDev;
1021 }
1022
1023 g_hostapdHalDevInfo[id].hostapdHalDev = (WifiHostapdHalDevice *)calloc(1, sizeof(WifiHostapdHalDevice));
1024 if (g_hostapdHalDevInfo[id].hostapdHalDev == NULL) {
1025 LOGE("hostapdHalDev is NULL");
1026 return NULL;
1027 }
1028
1029 /* ************ Register hostapd_cli Interface ************************* */
1030 g_hostapdHalDevInfo[id].hostapdHalDev->enableAp = EnableAp;
1031 g_hostapdHalDevInfo[id].hostapdHalDev->disableAp = DisableAp;
1032 g_hostapdHalDevInfo[id].hostapdHalDev->setApInfo = SetApInfo;
1033 g_hostapdHalDevInfo[id].hostapdHalDev->addBlocklist = AddBlocklist;
1034 g_hostapdHalDevInfo[id].hostapdHalDev->delBlocklist = DelBlocklist;
1035 g_hostapdHalDevInfo[id].hostapdHalDev->status = GetApStatus;
1036 g_hostapdHalDevInfo[id].hostapdHalDev->showConnectedDevList = ShowConnectedDevList;
1037 g_hostapdHalDevInfo[id].hostapdHalDev->reloadApConfigInfo = ReloadApConfigInfo;
1038 g_hostapdHalDevInfo[id].hostapdHalDev->disConnectedDev = DisConnectedDev;
1039 g_hostapdHalDevInfo[id].hostapdHalDev->setCountryCode = SetCountryCode;
1040 g_hostapdHalDevInfo[id].hostapdHalDev->terminateAp = TerminateAp;
1041
1042 if (InitHostapdHal(id) != 0) {
1043 LOGE("InitHostapdHal return failed!!");
1044 free(g_hostapdHalDevInfo[id].hostapdHalDev);
1045 g_hostapdHalDevInfo[id].hostapdHalDev = NULL;
1046 return NULL;
1047 }
1048 return g_hostapdHalDevInfo[id].hostapdHalDev;
1049 }
1050
ReleaseHostapdDev(int id)1051 void ReleaseHostapdDev(int id)
1052 {
1053 if (g_hostapdHalDevInfo[id].hostapdHalDev != NULL) {
1054 HostapdCliClose(id);
1055 free(g_hostapdHalDevInfo[id].hostapdHalDev);
1056 g_hostapdHalDevInfo[id].hostapdHalDev = NULL;
1057 }
1058 }