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
16 #include "hdi_wpa_hal.h"
17
18 #include <poll.h>
19 #include <unistd.h>
20 #include <hdf_log.h>
21 #include <pthread.h>
22
23 #include "wpa_common_cmd.h"
24 #include "ethernet_eap_client.h"
25 #include "common/wpa_ctrl.h"
26 #include "securec.h"
27
28 #ifdef LOG_TAG
29 #undef LOG_TAG
30 #endif
31 #define LOG_TAG "EthHdiWpaHal"
32 #ifdef LOG_DOMAIN
33 #undef LOG_DOMAIN
34 #endif
35 #define LOG_DOMAIN 0xD0015b0
36
37 #define WPA_TRY_CONNECT_TIMES 20
38 #define WPA_TRY_CONNECT_SLEEP_TIME (100 * 1000) /* 100ms */
39 #define WPA_CMD_BUF_LEN 256
40 #define WPA_CMD_REPLY_BUF_LEN 64
41 #define CMD_BUFFER_SIZE 2148
42 #define MAX_NAME_LEN 12
43 #define REPLY_BUF_LENGTH (4096 * 10)
44 #define REPLY_BUF_SMALL_LENGTH 64
45 #define REPLY_BUF_STA_INFO_LENGTH 2048
46 #define CMD_BUFFER_MIN_SIZE 15
47
48 static EthWpaInstance *g_wpaInstance = NULL;
49
GetEthWpaInsCtrl(void)50 static WpaCtrl *GetEthWpaInsCtrl(void)
51 {
52 if (g_wpaInstance == NULL) {
53 HDF_LOGE("GetEthWpaInsCtrl g_wpaInstance = NULL!");
54 return NULL;
55 }
56 return &g_wpaInstance->staCtrl;
57 }
58
InitWpaCtrl(WpaCtrl * pCtrl,const char * ctrlPath)59 int InitWpaCtrl(WpaCtrl *pCtrl, const char *ctrlPath)
60 {
61 if (pCtrl == NULL || ctrlPath == NULL) {
62 return -1;
63 }
64 pCtrl->pSend = wpa_ctrl_open(ctrlPath);
65 if (pCtrl->pSend == NULL) {
66 HDF_LOGE("open wpa control send interface failed!");
67 ReleaseWpaCtrl(pCtrl);
68 return -1;
69 }
70 return 0;
71 }
72
ReleaseWpaCtrl(WpaCtrl * pCtrl)73 void ReleaseWpaCtrl(WpaCtrl *pCtrl)
74 {
75 if (pCtrl == NULL) {
76 return;
77 }
78 if (pCtrl->pSend != NULL) {
79 wpa_ctrl_close(pCtrl->pSend);
80 pCtrl->pSend = NULL;
81 }
82 if (pCtrl->pRecv != NULL) {
83 wpa_ctrl_close(pCtrl->pRecv);
84 pCtrl->pRecv = NULL;
85 }
86 }
87
StaCliCmd(WpaCtrl * ctrl,const char * cmd,char * buf,size_t bufLen)88 static int StaCliCmd(WpaCtrl *ctrl, const char *cmd, char *buf, size_t bufLen)
89 {
90 HDF_LOGI("enter StaCliCmd");
91 if (ctrl == NULL || ctrl->pSend == NULL || cmd == NULL || buf == NULL || bufLen == 0) {
92 HDF_LOGE("StaCliCmd, invalid param");
93 return -1;
94 }
95 size_t len = bufLen - 1;
96 HDF_LOGI("wpa_ctrl_request -> cmd: %{public}s", cmd);
97 int ret = wpa_ctrl_request(ctrl->pSend, cmd, strlen(cmd), buf, &len, NULL);
98 if (ret < 0) {
99 HDF_LOGE("[%{public}s] command failed.", cmd);
100 return -1;
101 }
102 buf[len] = '\0';
103 HDF_LOGI("wpa_ctrl_request -> buf: %{public}s", buf);
104 if (strncmp(buf, "FAIL\n", strlen("FAIL\n")) == 0 ||
105 strncmp(buf, "UNKNOWN COMMAND\n", strlen("UNKNOWN COMMAND\n")) == 0) {
106 HDF_LOGE("%{public}s request success, but response %{public}s", cmd, buf);
107 return -1;
108 }
109 return 0;
110 }
111
WpaCliCmd(const char * cmd,char * buf,size_t bufLen)112 int WpaCliCmd(const char *cmd, char *buf, size_t bufLen)
113 {
114 int ret = -1;
115 HDF_LOGI("enter WpaCliCmd");
116 if (cmd == NULL || buf == NULL || bufLen == 0) {
117 HDF_LOGE("WpaCliCmd, invalid parameters!");
118 return ret;
119 }
120 ret = StaCliCmd(GetEthWpaInsCtrl(), cmd, buf, bufLen);
121 return ret;
122 }
123
WpaCliConnect(EthWpaInstance * p)124 static int WpaCliConnect(EthWpaInstance *p)
125 {
126 HDF_LOGI("Wpa connect start.");
127 if (p == NULL) {
128 HDF_LOGE("Wpa connect parameter error.");
129 return -1;
130 }
131 if (p->staCtrl.pSend != NULL) {
132 HDF_LOGE("Wpa is already connected.");
133 return 0;
134 }
135 int count = WPA_TRY_CONNECT_TIMES;
136 char *ctrlPath = WPA_CTRL_OPEN_IFNAME;
137 while (count-- > 0) {
138 if (!InitWpaCtrl(&p->staCtrl, ctrlPath)) {
139 HDF_LOGI("Global wpa interface connect successfully!");
140 break;
141 } else {
142 HDF_LOGE("Init wpaCtrl failed.");
143 }
144 usleep(WPA_TRY_CONNECT_SLEEP_TIME);
145 }
146 if (count <= 0) {
147 return -1;
148 }
149 HDF_LOGI("Wpa connect finish.");
150 return 0;
151 }
152
WpaCliClose(EthWpaInstance * p)153 static void WpaCliClose(EthWpaInstance *p)
154 {
155 HDF_LOGI("Wpa connect close.");
156 if (p->tid != 0) {
157 pthread_join(p->tid, NULL);
158 p->tid = 0;
159 }
160 ReleaseWpaCtrl(&p->staCtrl);
161 return;
162 }
163
WpaCliTerminate(void)164 static int WpaCliTerminate(void)
165 {
166 HDF_LOGI("enter WpaCliTerminate.");
167 char cmd[WPA_CMD_BUF_LEN] = {0};
168 char buf[WPA_CMD_REPLY_BUF_LEN] = {0};
169 if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "TERMINATE") < 0) {
170 HDF_LOGE("WpaCliTerminate, snprintf err");
171 return -1;
172 }
173 return WpaCliCmd(cmd, buf, sizeof(buf));
174 }
175
WpaCliCmdSetNetwork(EthWpaInstance * p,const char * ifName,const char * name,const char * value)176 static int WpaCliCmdSetNetwork(EthWpaInstance *p, const char *ifName, const char *name, const char *value)
177 {
178 char cmd[CMD_BUFFER_SIZE] = {0};
179 char buf[REPLY_BUF_SMALL_LENGTH] = {0};
180 int res = snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "IFNAME=%s SET_NETWORK %d %s %s", ifName,
181 0, name, value);
182 HDF_LOGI("%{public}s cmd= %{private}s", __func__, cmd);
183 if (res < 0) {
184 HDF_LOGE("%{public}s Internal error, set request message failed!", __func__);
185 return -1;
186 }
187 return WpaCliCmd(cmd, buf, sizeof(buf));
188 }
189
WpaCliCmdStaShellCmd(EthWpaInstance * p,const char * ifName,const char * params)190 static int WpaCliCmdStaShellCmd(EthWpaInstance *p, const char *ifName, const char *params)
191 {
192 if (params == NULL) {
193 return -1;
194 }
195 char cmd[CMD_BUFFER_SIZE] = {0};
196 char buf[REPLY_BUF_SMALL_LENGTH] = {0};
197 if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "IFNAME=%s STA_SHELL %s", ifName, params) < 0) {
198 HDF_LOGE("WpaCliCmdStaShellCmd, snprintf_s err");
199 return -1;
200 }
201 return WpaCliCmd(cmd, buf, sizeof(buf));
202 }
203
InitEthWpaGlobalInstance(void)204 void InitEthWpaGlobalInstance(void)
205 {
206 HDF_LOGI("enter InitEthWpaGlobalInstance.");
207 if (g_wpaInstance != NULL) {
208 return;
209 }
210 g_wpaInstance = (EthWpaInstance *)calloc(1, sizeof(EthWpaInstance));
211 if (g_wpaInstance == NULL) {
212 HDF_LOGE("Failed to create wpa interface!");
213 return;
214 }
215 g_wpaInstance->wpaCliConnect = WpaCliConnect;
216 g_wpaInstance->wpaCliClose = WpaCliClose;
217 g_wpaInstance->wpaCliTerminate = WpaCliTerminate;
218 g_wpaInstance->wpaCliCmdSetNetwork = WpaCliCmdSetNetwork;
219 g_wpaInstance->wpaCliCmdStaShellCmd = WpaCliCmdStaShellCmd;
220 }
221
GetEthWpaGlobalInstance(void)222 EthWpaInstance *GetEthWpaGlobalInstance(void)
223 {
224 return g_wpaInstance;
225 }
226
ReleaseEthWpaGlobalInstance(void)227 void ReleaseEthWpaGlobalInstance(void)
228 {
229 HDF_LOGI("enter ReleaseEthWpaGlobalInstance.");
230 if (g_wpaInstance == NULL) {
231 return;
232 }
233 WpaCliClose(g_wpaInstance);
234 free(g_wpaInstance);
235 g_wpaInstance = NULL;
236 }
237