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 <poll.h>
17 #include <unistd.h>
18 #include <hdf_log.h>
19 #include <pthread.h>
20 #include "securec.h"
21 #include "hdi_wpa_hal.h"
22 #include "hdi_wpa_common.h"
23 #include "wpa_common_cmd.h"
24 #ifndef OHOS_EUPDATER
25 #include "wpa_client.h"
26 #endif
27 
28 #undef LOG_TAG
29 #define LOG_TAG "HdiWpaHal"
30 
31 #define WPA_TRY_CONNECT_TIMES 20
32 #define WPA_TRY_CONNECT_SLEEP_TIME (100 * 1000) /* 100ms */
33 #define WPA_CMD_BUF_LEN 256
34 #define WPA_CMD_REPLY_BUF_SMALL_LEN 64
35 #define P2P_SERVICE_INFO_FIRST_SECTION 1
36 #define P2P_SERVICE_INFO_SECOND_SECTION 2
37 #define P2P_SERVICE_INFO_THIRD_SECTION 3
38 #define P2P_SERVICE_DISC_REQ_ONE 1
39 #define P2P_SERVICE_DISC_REQ_TWO 2
40 #define P2P_SERVICE_DISC_REQ_THREE 3
41 #define P2P_SERVICE_DISC_REQ_FOUR 4
42 #define P2P_SERVICE_DISC_REQ_FIVE 5
43 #define WPA_CB_CONNECTED 1
44 #define WPA_CB_DISCONNECTED 2
45 #define WPA_CB_ASSOCIATING 3
46 #define WPA_CB_ASSOCIATED 4
47 #define WPS_EVENT_PBC_OVERLAP "WPS-OVERLAP-DETECTED PBC session overlap"
48 #define WPA_EVENT_BSSID_CHANGED "WPA-EVENT-BSSID-CHANGED "
49 #define WPA_EVENT_ASSOCIATING "Request association with "
50 #define WPA_EVENT_ASSOCIATED "Associated with "
51 #define REPLY_BUF_LENGTH 4096
52 #define CONNECTION_PWD_WRONG_STATUS 1
53 #define CONNECTION_FULL_STATUS 17
54 #define CONNECTION_REJECT_STATUS 37
55 #define WLAN_STATUS_AUTH_TIMEOUT 16
56 #define MAC_AUTH_RSP2_TIMEOUT 5201
57 #define MAC_AUTH_RSP4_TIMEOUT 5202
58 #define MAC_ASSOC_RSP_TIMEOUT 5203
59 #define SSID_EMPTY_LENGTH 1
60 static const int MAX_IFACE_LEN = 6;
61 
62 #define WPA_CTRL_OPEN_IFNAME "@abstract:"CONFIG_ROOR_DIR"/sockets/wpa/wlan0"
63 
64 static WifiWpaInterface *g_wpaInterface = NULL;
65 
WpaCliConnect(WifiWpaInterface * p)66 static int WpaCliConnect(WifiWpaInterface *p)
67 {
68     HDF_LOGI("Wpa connect start.");
69     if (p == NULL) {
70         HDF_LOGE("Wpa connect parameter error.");
71         return -1;
72     }
73     if (p->staCtrl.pSend != NULL && p->p2pCtrl.pSend != NULL && p->chbaCtrl.pSend != NULL &&
74         p->commonCtrl.pSend != NULL) {
75         HDF_LOGE("Wpa is already connected.");
76         return 0;
77     }
78     int count = WPA_TRY_CONNECT_TIMES;
79     while (count-- > 0) {
80         if (!InitWpaCtrl(&p->staCtrl, WPA_CTRL_OPEN_IFNAME) && !InitWpaCtrl(&p->p2pCtrl, WPA_CTRL_OPEN_IFNAME) &&
81             !InitWpaCtrl(&p->chbaCtrl, WPA_CTRL_OPEN_IFNAME) && !InitWpaCtrl(&p->commonCtrl, WPA_CTRL_OPEN_IFNAME)) {
82             HDF_LOGI("Global wpa interface connect successfully!");
83             break;
84         } else {
85             HDF_LOGE("Init wpaCtrl failed.");
86         }
87         usleep(WPA_TRY_CONNECT_SLEEP_TIME);
88     }
89     if (count <= 0) {
90         return -1;
91     }
92     p->threadRunFlag = 1;
93     HDF_LOGI("Wpa connect finish.");
94     return 0;
95 }
96 
WpaCliClose(WifiWpaInterface * p)97 static void WpaCliClose(WifiWpaInterface *p)
98 {
99     HDF_LOGI("Wpa connect close.");
100     if (p->tid != 0) {
101         p->threadRunFlag = 0;
102         pthread_join(p->tid, NULL);
103         p->tid = 0;
104     }
105     ReleaseWpaCtrl(&p->staCtrl);
106     ReleaseWpaCtrl(&p->p2pCtrl);
107     ReleaseWpaCtrl(&p->chbaCtrl);
108     ReleaseWpaCtrl(&p->commonCtrl);
109     return;
110 }
111 
WpaCliAddIface(WifiWpaInterface * p,const AddInterfaceArgv * argv,bool isWpaAdd)112 static int WpaCliAddIface(WifiWpaInterface *p, const AddInterfaceArgv *argv, bool isWpaAdd)
113 {
114     HDF_LOGI("enter WpaCliAddIface");
115     if (p == NULL || argv == NULL) {
116         return -1;
117     }
118     WpaIfaceInfo *info = p->ifaces;
119     while (info != NULL) {
120         if (strncmp(info->name, argv->name, MAX_IFACE_LEN) == 0) {
121             return 0;
122         }
123         info = info->next;
124     }
125     info = (WpaIfaceInfo *)calloc(1, sizeof(WpaIfaceInfo));
126     if (info == NULL) {
127         return -1;
128     }
129     if (strcpy_s(info->name, sizeof(info->name), argv->name) != 0) {
130         HDF_LOGI("WpaCliAddIface strcpy_s fail");
131         free(info);
132         info = NULL;
133         return -1;
134     }
135     char cmd[WPA_CMD_BUF_LEN] = {0};
136     char buf[WPA_CMD_REPLY_BUF_SMALL_LEN] = {0};
137     HDF_LOGI("Add interface start.");
138     if (isWpaAdd && (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "INTERFACE_ADD %s\t%s",
139         argv->name, argv->confName) < 0 || WpaCliCmd(cmd, buf, sizeof(buf)) != 0)) {
140         free(info);
141         info = NULL;
142         HDF_LOGI("WpaCliAddIface failed, cmd: %{public}s, buf: %{public}s", cmd, buf);
143         return -1;
144     }
145     HDF_LOGI("Add interface finish, cmd: %{public}s, buf: %{public}s", cmd, buf);
146     info->next = p->ifaces;
147     p->ifaces = info;
148     return 0;
149 }
150 
WpaCliRemoveIface(WifiWpaInterface * p,const char * name)151 static int WpaCliRemoveIface(WifiWpaInterface *p, const char *name)
152 {
153     HDF_LOGI("enter WpaCliRemoveIface.");
154     if (p == NULL || name == NULL) {
155         return -1;
156     }
157     WpaIfaceInfo *prev = NULL;
158     WpaIfaceInfo *info = p->ifaces;
159     while (info != NULL) {
160         if (strncmp(info->name, name, MAX_IFACE_LEN) == 0) {
161             break;
162         }
163         prev = info;
164         info = info->next;
165     }
166     if (info == NULL) {
167         HDF_LOGI("the WpaInterface info is null");
168         return 0;
169     }
170     char cmd[WPA_CMD_BUF_LEN] = {0};
171     char buf[WPA_CMD_REPLY_BUF_SMALL_LEN] = {0};
172     if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "INTERFACE_REMOVE %s", name) < 0 ||
173         WpaCliCmd(cmd, buf, sizeof(buf)) != 0) {
174         return -1;
175     }
176     if (prev == NULL) {
177         p->ifaces = info->next;
178     } else {
179         prev->next = info->next;
180     }
181     HDF_LOGI("Remove interface finish, cmd: %{public}s, buf: %{public}s", cmd, buf);
182     free(info);
183     info = NULL;
184     return 0;
185 }
186 
WpaCliWpaTerminate(void)187 static int WpaCliWpaTerminate(void)
188 {
189     HDF_LOGI("enter WpaCliWpaTerminate.");
190     char cmd[WPA_CMD_BUF_LEN] = {0};
191     char buf[WPA_CMD_REPLY_BUF_SMALL_LEN] = {0};
192     if (snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, "TERMINATE") < 0) {
193         HDF_LOGE("WpaCliWpaTerminate, snprintf err");
194         return -1;
195     }
196     return WpaCliCmd(cmd, buf, sizeof(buf));
197 }
198 
InitWifiWpaGlobalInterface(void)199 void InitWifiWpaGlobalInterface(void)
200 {
201     HDF_LOGI("enter InitWifiWpaGlobalInterface.");
202     if (g_wpaInterface != NULL) {
203         return;
204     }
205     g_wpaInterface = (WifiWpaInterface *)calloc(1, sizeof(WifiWpaInterface));
206     if (g_wpaInterface == NULL) {
207         HDF_LOGE("Failed to create wpa interface!");
208         return;
209     }
210     g_wpaInterface->wpaCliConnect = WpaCliConnect;
211     g_wpaInterface->wpaCliClose = WpaCliClose;
212     g_wpaInterface->wpaCliAddIface = WpaCliAddIface;
213     g_wpaInterface->wpaCliRemoveIface = WpaCliRemoveIface;
214     g_wpaInterface->wpaCliTerminate = WpaCliWpaTerminate;
215     g_wpaInterface->ifaces = NULL;
216 }
217 
GetWifiWpaGlobalInterface(void)218 WifiWpaInterface *GetWifiWpaGlobalInterface(void)
219 {
220     HDF_LOGI("enter GetWifiWpaGlobalInterface.");
221     return g_wpaInterface;
222 }
223 
ReleaseWpaGlobalInterface(void)224 void ReleaseWpaGlobalInterface(void)
225 {
226     HDF_LOGI("enter ReleaseWpaGlobalInterface.");
227     if (g_wpaInterface == NULL) {
228         return;
229     }
230     WpaIfaceInfo *p = g_wpaInterface->ifaces;
231     while (p != NULL) {
232         WpaIfaceInfo *q = p->next;
233         free(p);
234         p = q;
235     }
236     WpaCliClose(g_wpaInterface);
237     free(g_wpaInterface);
238     g_wpaInterface = NULL;
239 }
240 
GetStaCtrl(void)241 WpaCtrl *GetStaCtrl(void)
242 {
243     HDF_LOGI("enter GetStaCtrl");
244     if (g_wpaInterface == NULL) {
245         HDF_LOGE("GetStaCtrl g_wpaInterface = NULL!");
246         return NULL;
247     }
248     return &g_wpaInterface->staCtrl;
249 }
250 
GetP2pCtrl(void)251 WpaCtrl *GetP2pCtrl(void)
252 {
253     HDF_LOGI("enter GetP2pCtrl");
254     if (g_wpaInterface == NULL) {
255         HDF_LOGE("GetP2pCtrl g_wpaInterface = NULL!");
256         return NULL;
257     }
258     return &g_wpaInterface->p2pCtrl;
259 }
260 
GetChbaCtrl(void)261 WpaCtrl *GetChbaCtrl(void)
262 {
263     HDF_LOGI("enter GetChbaCtrl");
264     if (g_wpaInterface == NULL) {
265         HDF_LOGE("GetChbaCtrl g_wpaInterface = NULL!");
266         return NULL;
267     }
268     return &g_wpaInterface->chbaCtrl;
269 }
270 
GetCommonCtrl(void)271 WpaCtrl *GetCommonCtrl(void)
272 {
273     HDF_LOGI("enter GetCommonCtrl");
274     if (g_wpaInterface == NULL) {
275         HDF_LOGE("GetCommonCtrl g_wpaInterface = NULL!");
276         return NULL;
277     }
278     return &g_wpaInterface->commonCtrl;
279 }
280 
ReleaseIfaceCtrl(char * ifName,int len)281 void ReleaseIfaceCtrl(char *ifName, int len)
282 {
283     if (g_wpaInterface == NULL) {
284         return;
285     }
286     if (len < IFNAME_LEN_MIN || len > IFNAME_LEN_MAX) {
287         HDF_LOGE("ifname is invalid");
288         return;
289     }
290     if (strncmp(ifName, "wlan0", strlen("wlan0")) == 0) {
291         ReleaseWpaCtrl(&(g_wpaInterface->staCtrl));
292         ReleaseWpaCtrl(&(g_wpaInterface->p2pCtrl));
293         ReleaseWpaCtrl(&(g_wpaInterface->chbaCtrl));
294 #ifndef OHOS_EUPDATER
295         ReleaseEventCallback();
296         ClearHdfWpaRemoteObj();
297 #endif
298     }
299 }