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