1 /*
2  * Copyright (C) 2021 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 <stdlib.h>
16 #include <string.h>
17 #include <stddef.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include "mock_wpa_ctrl.h"
22 #include "wifi_hal_common_func.h"
23 
24 static std::vector<int> gPipeFd;
25 static int gUsePipeFdNum = 0;
26 const int OncePipeFdNum = 2;
27 const int MaxExactCmdLength = 32;
28 
29 static std::map<std::string, std::string> gSupportedCmd;
30 
MockSetWpaExpectCmdResponse(const std::string & cmd,const std::string & response)31 void MockSetWpaExpectCmdResponse(const std::string &cmd, const std::string &response)
32 {
33     gSupportedCmd[cmd] = response;
34 }
35 
MockEraseSupportedCmd(const std::string & cmd)36 void MockEraseSupportedCmd(const std::string &cmd)
37 {
38     gSupportedCmd.erase(cmd);
39 }
40 
MockInitGlobalCmd(void)41 void MockInitGlobalCmd(void)
42 {
43     gSupportedCmd["INTERFACE_ADD"] = "OK";
44     gSupportedCmd["INTERFACE_REMOVE"] = "OK";
45 }
46 
MockInitStaSupportedCmd(void)47 void MockInitStaSupportedCmd(void)
48 {
49     gSupportedCmd["STATUS"] = "OK";
50     gSupportedCmd["ADD_NETWORK"] = "OK";
51     gSupportedCmd["RECONNECT"] = "OK";
52     gSupportedCmd["REASSOCIATE"] = "OK";
53     gSupportedCmd["DISCONNECT"] = "OK";
54     gSupportedCmd["SAVE_CONFIG"] = "OK";
55     gSupportedCmd["SET_NETWORK"] = "OK";
56     gSupportedCmd["ENABLE_NETWORK"] = "OK";
57     gSupportedCmd["SELECT_NETWORK"] = "OK";
58     gSupportedCmd["DISABLE_NETWORK"] = "OK";
59     gSupportedCmd["REMOVE_NETWORK"] = "OK";
60     gSupportedCmd["GET_NETWORK"] = "OK";
61     gSupportedCmd["WPS_PBC"] = "OK";
62     gSupportedCmd["WPS_PIN"] = "OK";
63     gSupportedCmd["WPS_CANCEL"] = "OK";
64     gSupportedCmd["SET"] = "OK";
65     gSupportedCmd["GET"] = "OK";
66     gSupportedCmd["STA_AUTOCONNECT"] = "OK";
67     gSupportedCmd["RECONFIGURE"] = "OK";
68     gSupportedCmd["LIST_NETWORKS"] = "OK";
69     gSupportedCmd["SIGNAL_POLL"] = "OK";
70     return;
71 }
72 
MockInitApSupportedCmd(void)73 void MockInitApSupportedCmd(void)
74 {
75     gSupportedCmd["ENABLE"] = "OK";
76     gSupportedCmd["SET"] = "OK";
77     gSupportedCmd["STATUS"] = "OK";
78     gSupportedCmd["DISABLE"] = "OK";
79     gSupportedCmd["DENY_ACL"] = "OK";
80     gSupportedCmd["STA-FIRST"] = "OK";
81     gSupportedCmd["STA-NEXT"] = "OK";
82     gSupportedCmd["RELOAD"] = "OK";
83     gSupportedCmd["DEAUTHENTICATE"] = "OK";
84     gSupportedCmd["DISASSOCIATE"] = "OK";
85     return;
86 }
87 
MockInitP2pSupportedCmd(void)88 void MockInitP2pSupportedCmd(void)
89 {
90     gSupportedCmd["P2P_STOP_FIND"] = "OK";
91     gSupportedCmd["P2P_FIND"] = "OK";
92     gSupportedCmd["SET"] = "OK";
93     gSupportedCmd["STATUS"] = "OK";
94     gSupportedCmd["P2P_FLUSH"] = "OK";
95     gSupportedCmd["P2P_SERVICE_FLUSH"] = "OK";
96     gSupportedCmd["P2P_PROV_DISC"] = "OK";
97     gSupportedCmd["P2P_GROUP_ADD"] = "OK";
98     gSupportedCmd["SAVE_CONFIG"] = "OK";
99     gSupportedCmd["LIST_NETWORKS"] = "OK";
100     gSupportedCmd["P2P_PEER"] = "OK\n";
101     gSupportedCmd["P2P_SERV_DISC_RESP"] = "OK";
102     gSupportedCmd["P2P_SERV_DISC_EXTERNAL"] = "OK";
103     gSupportedCmd["DRIVER"] = "OK";
104     gSupportedCmd["P2P_SERV_DISC_CANCEL_REQ"] = "OK";
105     gSupportedCmd["P2P_SERV_DISC_REQ"] = "OK";
106     gSupportedCmd["P2P_SERVICE_ADD"] = "OK";
107     gSupportedCmd["P2P_SERVICE_DEL"] = "OK";
108     gSupportedCmd["P2P_INVITE"] = "OK";
109     gSupportedCmd["P2P_CANCEL"] = "OK";
110     gSupportedCmd["P2P_SET"] = "OK";
111     gSupportedCmd["P2P_EXT_LISTEN"] = "OK";
112     gSupportedCmd["WFD_SUBELEM_SET"] = "OK";
113     gSupportedCmd["REMOVE_NETWORK"] = "OK";
114     gSupportedCmd["P2P_GROUP_REMOVE"] = "OK";
115     gSupportedCmd["WPS_PBC"] = "OK";
116     gSupportedCmd["WPS_PIN"] = "OK";
117     gSupportedCmd["P2P_CONNECT"] = "OK";
118     return;
119 }
120 
MockWpaCallback(struct wpa_ctrl * send,const char * message)121 void MockWpaCallback(struct wpa_ctrl *send, const char *message)
122 {
123     if (send == NULL || message == NULL) {
124         return;
125     }
126     write(send->s, message, strlen(message));
127     return;
128 }
129 
SetNonBlock(int fd)130 static void SetNonBlock(int fd)
131 {
132     int flags = fcntl(fd, F_GETFL, 0);
133     if (flags < 0) {
134         return;
135     }
136     flags |= O_NONBLOCK;
137     fcntl(fd, F_SETFL, flags);
138     return;
139 }
140 
wpa_ctrl_open(const char * ctrl_path)141 struct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path)
142 {
143     (void)ctrl_path;
144     struct wpa_ctrl *ctrl = (struct wpa_ctrl *)calloc(1, sizeof(struct wpa_ctrl));
145     if (ctrl == NULL) {
146         return NULL;
147     }
148     if (gUsePipeFdNum % OncePipeFdNum == 0) {
149         int pipeFd[OncePipeFdNum] = {0};
150         pipe(pipeFd);
151         SetNonBlock(pipeFd[0]);
152         gPipeFd.push_back(pipeFd[0]);
153         gPipeFd.push_back(pipeFd[1]);
154     }
155     if (gUsePipeFdNum % OncePipeFdNum == 0) {
156         ctrl->s = gPipeFd[gUsePipeFdNum + 1];
157     } else {
158         ctrl->s = gPipeFd[gUsePipeFdNum - 1];
159     }
160     ++gUsePipeFdNum;
161     return ctrl;
162 }
163 
wpa_ctrl_open2(const char * ctrl_path,const char * cli_path)164 struct wpa_ctrl * wpa_ctrl_open2(const char *ctrl_path, const char *cli_path)
165 {
166     (void)cli_path;
167     return wpa_ctrl_open(ctrl_path);
168 }
169 
wpa_ctrl_close(struct wpa_ctrl * ctrl)170 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
171 {
172     if (ctrl == NULL) {
173         return;
174     }
175     close(ctrl->s);
176     for (auto iter = gPipeFd.begin(); iter != gPipeFd.end(); ++iter) {
177         if (*iter == ctrl->s) {
178             gPipeFd.erase(iter);
179             break;
180         }
181     }
182     --gUsePipeFdNum;
183     free(ctrl);
184     return;
185 }
186 
GetExactCmd(const char * cmd,char * out,int out_len)187 static void GetExactCmd(const char *cmd, char *out, int out_len)
188 {
189     if (cmd == NULL || out == NULL) {
190         return;
191     }
192     int i = 0;
193     int j = 0;
194     if (strncmp(cmd, "IFNAME=", strlen("IFNAME=")) == 0) {
195         const char *p = strchr(cmd, ' ');
196         if (p == NULL) {
197             return;
198         }
199         j = p - cmd + 1;
200     }
201     while (i < out_len - 1 && cmd[i + j] != '\0' && cmd[i + j] != ' ') {
202         out[i] = cmd[i + j];
203         ++i;
204     }
205     out[i] = '\0';
206     return;
207 }
208 
CheckInputCmdArgs(const char * cmd)209 static int CheckInputCmdArgs(const char *cmd)
210 {
211     (void)cmd;
212     return 0;
213 }
214 
wpa_ctrl_request(struct wpa_ctrl * ctrl,const char * cmd,size_t cmd_len,char * reply,size_t * reply_len,void (* msg_cb)(char * msg,size_t len))215 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len,
216     void (*msg_cb)(char *msg, size_t len))
217 {
218     if (ctrl == NULL || cmd == NULL || reply == NULL || reply_len == NULL) {
219         return -1;
220     }
221     (void)cmd_len;
222     (void)msg_cb;
223     char exactCmd[MaxExactCmdLength] = {0};
224     GetExactCmd(cmd, exactCmd, MaxExactCmdLength);
225     std::map<std::string, std::string>::iterator iter = gSupportedCmd.find(std::string(exactCmd));
226     if (iter == gSupportedCmd.end()) {
227         StrSafeCopy(reply, *reply_len, "UNKNOWN COMMAND\n");
228         *reply_len = strlen(reply);
229         return -1;
230     }
231     if (CheckInputCmdArgs(cmd) < 0) {
232         StrSafeCopy(reply, *reply_len, "FAIL\n");
233     } else {
234         StrSafeCopy(reply, *reply_len, iter->second.c_str());
235     }
236     *reply_len = strlen(reply);
237     return 0;
238 }
239 
wpa_ctrl_attach(struct wpa_ctrl * ctrl)240 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
241 {
242     (void)ctrl;
243     return 0;
244 }
245 
wpa_ctrl_detach(struct wpa_ctrl * ctrl)246 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
247 {
248     (void)ctrl;
249     return 0;
250 }
251 
wpa_ctrl_recv(struct wpa_ctrl * ctrl,char * reply,size_t * reply_len)252 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
253 {
254     size_t pos = 0;
255     while (pos < *reply_len) {
256         int ret = read(ctrl->s, reply + pos, 1);
257         if (ret <= 0) {
258             break;
259         }
260         if (reply[pos] == '\n') {
261             break;
262         }
263         ++pos;
264     }
265     *reply_len = pos;
266     reply[pos] = '\0';
267     return 0;
268 }
269 
wpa_ctrl_pending(struct wpa_ctrl * ctrl)270 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
271 {
272     (void)ctrl;
273     return 0;
274 }
275 
wpa_ctrl_get_fd(struct wpa_ctrl * ctrl)276 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
277 {
278     if (ctrl != NULL) {
279         return ctrl->s;
280     }
281     return -1;
282 }