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