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