1 /*
2 * Copyright (c) 2025 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 #include "wpa_common_cmd.h"
16
17 #include <hdf_log.h>
18 #include <string.h>
19 #include <securec.h>
20 #include <hdf_base.h>
21 #include <osal_time.h>
22 #include <osal_mem.h>
23 #include <arpa/inet.h>
24 #include <dirent.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <dlfcn.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <dlfcn.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <pthread.h>
34
35 #include "hdi_wpa_hal.h"
36 #include "utils/common.h"
37 #include "wpa_supplicant_i.h"
38 #include "ctrl_iface.h"
39 #include "main.h"
40 #include "wps_supplicant.h"
41 #include "config.h"
42 #include "common/defs.h"
43 #include "common/wpa_ctrl.h"
44 #include "ethernet_eap_client.h"
45 #include "securec.h"
46 #include "wpa_hdi_util.h"
47
48 #ifdef LOG_TAG
49 #undef LOG_TAG
50 #endif
51 #define LOG_TAG "EthWpaCmd"
52 #ifdef LOG_DOMAIN
53 #undef LOG_DOMAIN
54 #endif
55 #define LOG_DOMAIN 0xD0015b0
56
57 #define BUF_SIZE 2048
58 #define START_CMD_BUF_SIZE 512
59 #define WPA_CMD_RETURN_TIMEOUT (-2)
60 #define WPA_SLEEP_TIME (100 * 1000) /* 100ms */
61 #define MAX_WPA_WAIT_TIMES 30
62 #define CTRL_LEN 128
63
64 pthread_t g_tid;
65 pthread_mutex_t g_wpaLock = PTHREAD_MUTEX_INITIALIZER;
66
SplitCmdString(const char * startCmd,struct WpaMainParam * pParam)67 static void SplitCmdString(const char *startCmd, struct WpaMainParam *pParam)
68 {
69 if (pParam == NULL) {
70 return;
71 }
72 if (startCmd == NULL) {
73 pParam->argc = 0;
74 return;
75 }
76 const char *p = startCmd;
77 int i = 0;
78 int j = 0;
79 while (*p != '\0') {
80 if (*p == ' ') {
81 if (j <= MAX_WPA_MAIN_ARGV_LEN - 1) {
82 pParam->argv[i][j] = '\0';
83 } else {
84 pParam->argv[i][MAX_WPA_MAIN_ARGV_LEN - 1] = '\0';
85 }
86 ++i;
87 j = 0;
88 if (i >= MAX_WPA_MAIN_ARGC_NUM) {
89 break;
90 }
91 } else {
92 if (j < MAX_WPA_MAIN_ARGV_LEN - 1) {
93 pParam->argv[i][j] = *p;
94 ++j;
95 }
96 }
97 ++p;
98 }
99 if (i >= MAX_WPA_MAIN_ARGC_NUM) {
100 pParam->argc = MAX_WPA_MAIN_ARGC_NUM;
101 } else {
102 pParam->argc = i + 1;
103 }
104 }
105
WpaThreadMain(void * p)106 static void *WpaThreadMain(void *p)
107 {
108 const char *startCmd;
109 struct WpaMainParam param = {0};
110 char *tmpArgv[MAX_WPA_MAIN_ARGC_NUM] = {0};
111 if (p == NULL) {
112 HDF_LOGE("%{public}s: input parameter invalid!", __func__);
113 return NULL;
114 }
115 startCmd = (const char *)p;
116 HDF_LOGI("%{public}s: run wpa_main -> %{public}s.", __func__, startCmd);
117 SplitCmdString(startCmd, ¶m);
118 for (int i = 0; i < param.argc; i++) {
119 tmpArgv[i] = param.argv[i];
120 }
121 int ret = wpa_main(param.argc, tmpArgv);
122 HDF_LOGI("%{public}s: run wpa_main ret:%{public}d.", __func__, ret);
123 g_tid = 0;
124 return NULL;
125 }
126
StartWpaSupplicant(const char * startCmd)127 static int32_t StartWpaSupplicant(const char *startCmd)
128 {
129 int32_t ret;
130 int32_t times = 0;
131 if (startCmd == NULL) {
132 HDF_LOGE("%{public}s input parameter invalid!", __func__);
133 return HDF_ERR_INVALID_PARAM ;
134 }
135 while (g_tid != 0) {
136 HDF_LOGI("%{public}s: wpa_supplicant is already running!", __func__);
137 usleep(WPA_SLEEP_TIME);
138 times++;
139 if (times > MAX_WPA_WAIT_TIMES) {
140 HDF_LOGE("%{public}s: wait supplicant time out!", __func__);
141 return HDF_FAILURE;
142 }
143 }
144 ret = pthread_create(&g_tid, NULL, WpaThreadMain, (void *)startCmd);
145 if (ret != HDF_SUCCESS) {
146 HDF_LOGE("%{public}s: Create wpa thread failed, error code: %{public}d", __func__, ret);
147 return HDF_FAILURE;
148 }
149 pthread_setname_np(g_tid, "WpaMainThread");
150 HDF_LOGI("%{public}s: pthread_create successfully.", __func__);
151 usleep(WPA_SLEEP_TIME);
152 EthWpaInstance *pWpaInstance = GetEthWpaGlobalInstance();
153 if (pWpaInstance == NULL) {
154 HDF_LOGE("Get wpa interface failed!");
155 return HDF_FAILURE;
156 }
157 if (pWpaInstance->wpaCliConnect(pWpaInstance) < 0) {
158 HDF_LOGE("Failed to connect to wpa!");
159 return HDF_FAILURE;
160 }
161 return HDF_SUCCESS;
162 }
163
RemoveLostCtrl(void)164 static void RemoveLostCtrl(void)
165 {
166 DIR *dir = NULL;
167 char path[CTRL_LEN];
168 struct dirent *entry;
169 dir = opendir(CONFIG_ROOR_DIR);
170 if (dir == NULL) {
171 HDF_LOGE("can not open dir");
172 return;
173 }
174 while ((entry = readdir(dir)) != NULL) {
175 if (strncmp(entry->d_name, "wpa_ctrl_", strlen("wpa_ctrl_")) != 0) {
176 continue;
177 }
178 int ret = sprintf_s(path, sizeof(path), "%s/%s", CONFIG_ROOR_DIR, entry->d_name);
179 if (ret == -1) {
180 HDF_LOGE("sprintf_s dir name fail");
181 break;
182 }
183 if (entry->d_type != DT_DIR) {
184 remove(path);
185 }
186 }
187 closedir(dir);
188 }
189
EthStartEap(struct IEthernet * self,const char * ifName)190 int32_t EthStartEap(struct IEthernet *self, const char *ifName)
191 {
192 int32_t ret;
193 (void)self;
194 HDF_LOGI("enter %{public}s", __func__);
195 InitEthWpaGlobalInstance();
196 EthWpaInstance *pWpaInstance = GetEthWpaGlobalInstance();
197 if (pWpaInstance == NULL) {
198 HDF_LOGI("fail get global interface");
199 return HDF_FAILURE;
200 }
201 pthread_mutex_lock(&g_wpaLock);
202 RemoveLostCtrl();
203 char startCmd[START_CMD_BUF_SIZE];
204 ret = sprintf_s(startCmd, sizeof(startCmd), "%s -i%s", START_CMD, ifName);
205 if (ret == -1) {
206 pthread_mutex_unlock(&g_wpaLock);
207 HDF_LOGE("%{public}s: sprintf_s start cmd fail", __func__);
208 return HDF_FAILURE;
209 }
210 ret = StartWpaSupplicant(startCmd);
211 if (ret != HDF_SUCCESS) {
212 HDF_LOGE("%{public}s: StartWpaSupplicant failed, error code: %{public}d", __func__, ret);
213 pthread_mutex_unlock(&g_wpaLock);
214 return HDF_FAILURE;
215 }
216 pthread_mutex_unlock(&g_wpaLock);
217 HDF_LOGI("%{public}s: wpa_supplicant start successfully!", __func__);
218 return HDF_SUCCESS;
219 }
220
StopWpaSupplicant(void)221 static int32_t StopWpaSupplicant(void)
222 {
223 EthWpaInstance *pWpaInstance = GetEthWpaGlobalInstance();
224 if (pWpaInstance == NULL) {
225 HDF_LOGE("%{public}s: Get wpa global interface failed!", __func__);
226 return HDF_FAILURE;
227 }
228 int ret = pWpaInstance->wpaCliTerminate();
229 HDF_LOGI("%{public}s: wpaCliTerminate ret = %{public}d", __func__, ret);
230 return HDF_SUCCESS;
231 }
232
EthStopEap(struct IEthernet * self,const char * ifName)233 int32_t EthStopEap(struct IEthernet *self, const char *ifName)
234 {
235 int32_t ret;
236 int32_t times = 0;
237 (void)self;
238 pthread_mutex_lock(&g_wpaLock);
239 HDF_LOGI("enter %{public}s", __func__);
240 ret = StopWpaSupplicant();
241 if (ret != HDF_SUCCESS) {
242 HDF_LOGE("%{public}s: stop failed, error code: %{public}d", __func__, ret);
243 pthread_mutex_unlock(&g_wpaLock);
244 return HDF_FAILURE;
245 }
246 while (g_tid != 0) {
247 HDF_LOGI("%{public}s: wpa_supplicant is not stop!", __func__);
248 usleep(WPA_SLEEP_TIME);
249 times++;
250 if (times > MAX_WPA_WAIT_TIMES) {
251 HDF_LOGE("%{public}s: wait supplicant stop time out!", __func__);
252 break;
253 }
254 }
255 ReleaseEthWpaGlobalInstance();
256 pthread_mutex_unlock(&g_wpaLock);
257 HDF_LOGI("%{public}s: wpa_supplicant stop successfully!", __func__);
258 return HDF_SUCCESS;
259 }
260
EthEapShellCmd(struct IEthernet * self,const char * ifName,const char * cmd)261 int32_t EthEapShellCmd(struct IEthernet *self, const char *ifName, const char *cmd)
262 {
263 (void)self;
264 HDF_LOGI("enter %{public}s", __func__);
265 pthread_mutex_lock(&g_wpaLock);
266 if (ifName == NULL || cmd == NULL) {
267 pthread_mutex_unlock(&g_wpaLock);
268 HDF_LOGE("%{public}s: input param invalid!", __func__);
269 return HDF_ERR_INVALID_PARAM;
270 }
271 EthWpaInstance *pWpaInstance = GetEthWpaGlobalInstance();
272 if (pWpaInstance == NULL) {
273 pthread_mutex_unlock(&g_wpaLock);
274 HDF_LOGE("%{public}s: pWpaInstance = NULL", __func__);
275 return HDF_FAILURE;
276 }
277 int ret = pWpaInstance->wpaCliCmdStaShellCmd(pWpaInstance, ifName, cmd);
278 if (ret < 0) {
279 pthread_mutex_unlock(&g_wpaLock);
280 HDF_LOGE("%{public}s: fail ret = %{public}d", __func__, ret);
281 return HDF_FAILURE;
282 }
283 pthread_mutex_unlock(&g_wpaLock);
284 HDF_LOGI("%{public}s: success", __func__);
285 return HDF_SUCCESS;
286 }
287
EthRegisterEapEventCallback(struct IEthernet * self,struct IEthernetCallback * cbFunc,const char * ifName)288 int32_t EthRegisterEapEventCallback(struct IEthernet *self, struct IEthernetCallback *cbFunc,
289 const char *ifName)
290 {
291 int32_t ret = HDF_FAILURE;
292 (void)self;
293 pthread_mutex_lock(&g_wpaLock);
294 if (cbFunc == NULL || ifName == NULL) {
295 pthread_mutex_unlock(&g_wpaLock);
296 HDF_LOGE("%{public}s: input parameter invalid!", __func__);
297 return HDF_ERR_INVALID_PARAM;
298 }
299 ret = EthEapClientRegisterCallback(cbFunc, ifName);
300 if (ret != HDF_SUCCESS) {
301 HDF_LOGE("%{public}s: Register failed!, error code: %{public}d", __func__, ret);
302 } else {
303 HDF_LOGI("%{public}s: Register success", __func__);
304 }
305 pthread_mutex_unlock(&g_wpaLock);
306 return ret;
307 }
308
EthUnregisterEapEventCallback(struct IEthernet * self,struct IEthernetCallback * cbFunc,const char * ifName)309 int32_t EthUnregisterEapEventCallback(struct IEthernet *self, struct IEthernetCallback *cbFunc,
310 const char *ifName)
311 {
312 (void)self;
313 pthread_mutex_lock(&g_wpaLock);
314 if (cbFunc == NULL || ifName == NULL) {
315 pthread_mutex_unlock(&g_wpaLock);
316 HDF_LOGE("%{public}s: input parameter invalid!", __func__);
317 return HDF_ERR_INVALID_PARAM;
318 }
319 int32_t ret = EthEapClientUnregisterCallback(cbFunc, ifName);
320 if (ret != HDF_SUCCESS) {
321 HDF_LOGE("%{public}s: Unregister failed!, error code: %{public}d", __func__, ret);
322 } else {
323 HDF_LOGI("%{public}s: Register success", __func__);
324 }
325 pthread_mutex_unlock(&g_wpaLock);
326 return HDF_SUCCESS;
327 }
328