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