1 /*
2 * Copyright (c) 2020 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 "utils/includes.h"
17 #include "pthread.h"
18 #include "common/wpa_ctrl.h"
19 #include "securec.h"
20
21
22 #define WPA_IFACE_NAME "wlan0"
23 #define WIFI_AUTH_FAILED_REASON_STR "WRONG_KEY"
24 #define WIFI_AUTH_FAILED_REASON_CODE "reason=2"
25 #define WPA_CTRL_REQUEST_OK "OK"
26 #define WPA_CTRL_REQUEST_FAIL "FAIL"
27
28 #define SAMPLE_INFO(format, args...) \
29 do { \
30 fprintf(stderr, "\033[1;32m WpaCliSample(%s:%d):\t\033[0m" format, __func__, __LINE__, ##args); \
31 printf("\n"); \
32 } while (0)
33
34 #define SAMPLE_ERROR(format, args...) \
35 do { \
36 fprintf(stderr, "\033[1;31m WpaCliSample(%s:%d):\t\033[0m" format, __func__, __LINE__, ##args); \
37 printf("\n"); \
38 } while (0)
39
40
41 static struct wpa_ctrl *g_monitorConn;
42 static struct wpa_ctrl *g_ctrlConn;
43 static pthread_t g_wpaThreadId;
44 static int g_scanAvailable = 0;
45
DumpString(const char *buf, int len, const char *tag)46 static void DumpString(const char *buf, int len, const char *tag)
47 {
48 SAMPLE_INFO("%s dump start.", tag);
49 for (int i = 0; i < len; i++) {
50 printf("%c", buf[i]);
51 }
52 printf("\n");
53 SAMPLE_INFO("%s dump end.", tag);
54 }
55
StrMatch(const char *a, const char *b)56 static int StrMatch(const char *a, const char *b)
57 {
58 return strncmp(a, b, strlen(b)) == 0;
59 }
60
WifiEventHandler(char *rawEvent, int len)61 static void WifiEventHandler(char *rawEvent, int len)
62 {
63 char *pos = rawEvent;
64 if (*pos == '<') {
65 pos = strchr(pos, '>');
66 if (pos) {
67 pos++;
68 } else {
69 pos = rawEvent;
70 }
71 }
72 if (StrMatch(pos, WPA_EVENT_CONNECTED)) {
73 SAMPLE_INFO("WIFI_EVENT_CONNECTED");
74 return;
75 }
76 if (StrMatch(pos, WPA_EVENT_SCAN_RESULTS)) {
77 SAMPLE_INFO("WIFI_EVENT_SCAN_DONE");
78 g_scanAvailable = 1;
79 return;
80 }
81 if (StrMatch(pos, WPA_EVENT_TEMP_DISABLED) && strstr(pos, WIFI_AUTH_FAILED_REASON_STR)) {
82 SAMPLE_INFO("WIFI_EVENT_WRONG_KEY");
83 return;
84 }
85 if (StrMatch(pos, WPA_EVENT_DISCONNECTED) && !strstr(pos, WIFI_AUTH_FAILED_REASON_CODE)) {
86 SAMPLE_INFO("WIFI_EVENT_DISCONNECTED");
87 return;
88 }
89 }
90
CliRecvPending(void)91 static void CliRecvPending(void)
92 {
93 while (wpa_ctrl_pending(g_monitorConn)) {
94 char buf[4096];
95 size_t len = sizeof(buf) - 1;
96 if (wpa_ctrl_recv(g_monitorConn, buf, &len) == 0) {
97 buf[len] = '\0';
98 SAMPLE_INFO("event received %s", buf);
99 WifiEventHandler(buf, len);
100 } else {
101 SAMPLE_INFO("could not read pending message.");
102 break;
103 }
104 }
105 }
106
MonitorTask(void *args)107 static void* MonitorTask(void *args)
108 {
109 (void)args;
110 int fd, ret;
111 fd_set rfd;
112 while (1) {
113 fd = wpa_ctrl_get_fd(g_monitorConn);
114 FD_ZERO(&rfd);
115 FD_SET(fd, &rfd);
116 ret = select(fd + 1, &rfd, NULL, NULL, NULL);
117 if (ret <= 0) {
118 SAMPLE_INFO("select failed ret = %d\n", ret);
119 break;
120 }
121 CliRecvPending();
122 sleep(1);
123 }
124 return NULL;
125 }
126
SendCtrlCommand(const char *cmd, char *reply, size_t *replyLen)127 static int SendCtrlCommand(const char *cmd, char *reply, size_t *replyLen)
128 {
129 size_t len = *replyLen - 1;
130 wpa_ctrl_request(g_ctrlConn, cmd, strlen(cmd), reply, &len, 0);
131 DumpString(reply, len, "SendCtrlCommand raw return");
132 if (len != 0 && !StrMatch(reply, WPA_CTRL_REQUEST_FAIL)) {
133 *replyLen = len;
134 return 0;
135 }
136 SAMPLE_ERROR("send ctrl request [%s] failed.", cmd);
137 return -1;
138 }
139
TestNetworkConfig(void)140 static void TestNetworkConfig(void)
141 {
142 char networkId[20] = {0};
143 size_t networkIdLen = sizeof(networkId);
144 int ret = SendCtrlCommand("DISCONNECT", networkId, &networkIdLen);
145 ret += SendCtrlCommand("ADD_NETWORK", networkId, &networkIdLen);
146 if (ret != 0) {
147 SAMPLE_ERROR("add network failed.");
148 return;
149 }
150 SAMPLE_INFO("add network success, network id [%.*s]", networkIdLen, networkId);
151 char reply[100] = {0};
152 size_t replyLen = sizeof(reply);
153 char cmd[200] = {0};
154 int temp = 0;
155 temp = sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s ssid \"example\"", networkIdLen, networkId);
156 if (temp != 0) {
157 printf("result is %d\n", temp);
158 };
159 ret += SendCtrlCommand(cmd, reply, &replyLen);
160 replyLen = sizeof(reply);
161 temp = sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s psk \"012345678\"", networkIdLen, networkId);
162 if (temp != 0) {
163 printf("result is %d\n", temp);
164 };
165 ret += SendCtrlCommand(cmd, reply, &replyLen);
166 replyLen = sizeof(reply);
167 temp = sprintf_s(cmd, sizeof(cmd), "ENABLE_NETWORK %.*s", networkIdLen, networkId);
168 if (temp != 0) {
169 printf("result is %d\n", temp);
170 };
171 ret += SendCtrlCommand(cmd, reply, &replyLen);
172 replyLen = sizeof(reply);
173 ret += SendCtrlCommand("RECONNECT", reply, &replyLen);
174 replyLen = sizeof(reply);
175 if (ret == 0) {
176 SAMPLE_INFO("network config success.");
177 return;
178 }
179 temp = sprintf_s(cmd, sizeof(cmd), "REMOVE_NETWORK %.*s", networkIdLen, networkId);
180 if (temp != 0) {
181 printf("result is %d\n", temp);
182 };
183 SendCtrlCommand(cmd, reply, &replyLen);
184 SAMPLE_ERROR("network config failed remove network [%.*s].", networkIdLen, networkId);
185 }
186
TestCliConnection(void)187 static void TestCliConnection(void)
188 {
189 char reply[100] = {0};
190 size_t replyLen = sizeof(reply);
191 int ret = SendCtrlCommand("PING", reply, &replyLen);
192 if (ret == 0 && StrMatch(reply, "PONG")) {
193 SAMPLE_INFO("connect to wpa success.");
194 return;
195 }
196 SAMPLE_INFO("connect to wpa failed, err = %s.", reply);
197 }
198
TestScannull199 static void TestScan()
200 {
201 char reply[100] = {0};
202 size_t replyLen = sizeof(reply);
203 g_scanAvailable = 0;
204 SendCtrlCommand("SCAN", reply, &replyLen);
205 while (1) {
206 sleep(1);
207 if (g_scanAvailable == 1) {
208 SAMPLE_INFO("scan result received.");
209 break;
210 }
211 SAMPLE_INFO("waiting scan result.");
212 }
213 char scanResult[4096] = {0};
214 size_t scanLen = sizeof(scanResult);
215 int ret = SendCtrlCommand("SCAN_RESULTS", scanResult, &scanLen);
216 if (ret != 0) {
217 SAMPLE_ERROR("request scan results failed.");
218 return;
219 }
220 DumpString(scanResult, scanLen, "scan results");
221 }
222
StartTestnull223 static void StartTest()
224 {
225 TestCliConnection(); // test if wpa control interface connected successfully
226 TestScan(); // test scan and get scan results
227 TestNetworkConfig(); // test config network and connect
228 }
229
InitControlInterfacenull230 int InitControlInterface()
231 {
232 g_ctrlConn = wpa_ctrl_open(WPA_IFACE_NAME); // create control interface for send cmd
233 g_monitorConn = wpa_ctrl_open(WPA_IFACE_NAME); // create control interface for event monitor
234 if (!g_ctrlConn || !g_monitorConn) {
235 SAMPLE_ERROR("open wpa control interface failed.");
236 return -1;
237 }
238 if (wpa_ctrl_attach(g_monitorConn) == 0) { // start monitor
239 pthread_create(&g_wpaThreadId, NULL, MonitorTask, NULL); // create thread for read event
240 return 0;
241 }
242 return -1;
243 }
244
mainnull245 int main()
246 {
247 if (InitControlInterface() != 0) {
248 SAMPLE_ERROR("control interface init failed, exit client.");
249 return -1;
250 }
251 SAMPLE_INFO("control interface init success.");
252 StartTest();
253 pthread_join(g_wpaThreadId, NULL);
254 SAMPLE_INFO("test finished, exit client.");
255 }
256