blob: 5f884e16ae06e7d43bc21c0f61807c492ccff694 [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
3 * Copyright (c) 2010-2011, Atheros Communications, Inc.
4 * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
5 * All Rights Reserved.
6 * Licensed under the Clear BSD license. See README for more details.
7 */
8
9#include "sigma_dut.h"
10#include <sys/stat.h>
11#include "wpa_ctrl.h"
12#include "wpa_helpers.h"
13
14
15extern char *sigma_main_ifname;
16extern char *sigma_station_ifname;
17extern char *sigma_wpas_ctrl;
18
19
20char * get_main_ifname(void)
21{
22 enum driver_type drv = get_driver_type();
23 enum openwrt_driver_type openwrt_drv = get_openwrt_driver_type();
24
25 if (sigma_main_ifname)
26 return sigma_main_ifname;
27
28 if (if_nametoindex("p2p0") > 0)
29 return "p2p0";
30 if (if_nametoindex("wlan1") > 0) {
31 struct stat s;
32 if (stat("/sys/module/mac80211", &s) == 0 &&
33 if_nametoindex("wlan0")) {
34 /*
35 * Likely a dual-radio AP device; use wlan0 for STA/P2P
36 * operations.
37 */
38 return "wlan0";
39 }
40 return "wlan1";
41 }
42 if (if_nametoindex("wlan0") > 0)
43 return "wlan0";
44
45 if (drv == DRIVER_ATHEROS || openwrt_drv == OPENWRT_DRIVER_ATHEROS) {
46 if (if_nametoindex("ath2") > 0)
47 return "ath2";
48 else if (if_nametoindex("ath1") > 0)
49 return "ath1";
50 else
51 return "ath0";
52 }
53
54 return "unknown";
55}
56
57
58char * get_station_ifname(void)
59{
60 if (sigma_station_ifname)
61 return sigma_station_ifname;
62
63 /*
64 * If we have both wlan0 and wlan1, assume the first one is the station
65 * interface.
66 */
67 if (if_nametoindex("wlan1") > 0 && if_nametoindex("wlan0") > 0)
68 return "wlan0";
69
70 if (if_nametoindex("ath0") > 0)
71 return "ath0";
72
73 /* If nothing else matches, hope for best and guess.. */
74 return "wlan0";
75}
76
77
78void dut_ifc_reset(struct sigma_dut *dut)
79{
80 char buf[256];
81 char *ifc = get_station_ifname();
82
83 snprintf(buf, sizeof(buf), "ifconfig %s down", ifc);
84 run_system(dut, buf);
85 snprintf(buf, sizeof(buf), "ifconfig %s up", ifc);
86 run_system(dut, buf);
87}
88
89
90int wpa_command(const char *ifname, const char *cmd)
91{
92 struct wpa_ctrl *ctrl;
93 char buf[128];
94 size_t len;
95
96 printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
97 snprintf(buf, sizeof(buf), "%s%s", sigma_wpas_ctrl, ifname);
98 ctrl = wpa_ctrl_open(buf);
99 if (ctrl == NULL) {
100 printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
101 return -1;
102 }
103 len = sizeof(buf);
104 if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
105 printf("wpa_command: wpa_ctrl_request failed\n");
106 wpa_ctrl_close(ctrl);
107 return -1;
108 }
109 wpa_ctrl_close(ctrl);
110 buf[len] = '\0';
111 if (strncmp(buf, "FAIL", 4) == 0) {
112 printf("wpa_command: Command failed (FAIL received)\n");
113 return -1;
114 }
115 return 0;
116}
117
118
119int wpa_command_resp(const char *ifname, const char *cmd,
120 char *resp, size_t resp_size)
121{
122 struct wpa_ctrl *ctrl;
123 char buf[128];
124 size_t len;
125
126 printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
127 snprintf(buf, sizeof(buf), "%s%s", sigma_wpas_ctrl, ifname);
128 ctrl = wpa_ctrl_open(buf);
129 if (ctrl == NULL) {
130 printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
131 return -1;
132 }
133 len = resp_size;
134 if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
135 printf("wpa_command: wpa_ctrl_request failed\n");
136 wpa_ctrl_close(ctrl);
137 return -1;
138 }
139 wpa_ctrl_close(ctrl);
140 resp[len] = '\0';
141 return 0;
142}
143
144
145struct wpa_ctrl * open_wpa_mon(const char *ifname)
146{
147 struct wpa_ctrl *ctrl;
148 char path[256];
149
150 snprintf(path, sizeof(path), "%s%s", sigma_wpas_ctrl, ifname);
151 ctrl = wpa_ctrl_open(path);
152 if (ctrl == NULL)
153 return NULL;
154 if (wpa_ctrl_attach(ctrl) < 0) {
155 wpa_ctrl_close(ctrl);
156 return NULL;
157 }
158
159 return ctrl;
160}
161
162
163int get_wpa_cli_events(struct sigma_dut *dut, struct wpa_ctrl *mon,
164 const char **events, char *buf, size_t buf_size)
165{
166 int fd, ret;
167 fd_set rfd;
168 char *pos;
169 struct timeval tv;
170 time_t start, now;
171 int i;
172
173 for (i = 0; events[i]; i++) {
174 sigma_dut_print(dut, DUT_MSG_DEBUG,
175 "Waiting for wpa_cli event: %s", events[i]);
176 }
177 fd = wpa_ctrl_get_fd(mon);
178 if (fd < 0)
179 return -1;
180
181 time(&start);
182 while (1) {
183 size_t len;
184
185 FD_ZERO(&rfd);
186 FD_SET(fd, &rfd);
187
188 time(&now);
189 if ((unsigned int) (now - start) >= dut->default_timeout)
190 tv.tv_sec = 1;
191 else
192 tv.tv_sec = dut->default_timeout -
193 (unsigned int) (now - start) + 1;
194 tv.tv_usec = 0;
195 ret = select(fd + 1, &rfd, NULL, NULL, &tv);
196 if (ret == 0) {
197 sigma_dut_print(dut, DUT_MSG_INFO, "Timeout on "
198 "waiting for events");
199 return -1;
200 }
201 if (ret < 0) {
202 sigma_dut_print(dut, DUT_MSG_INFO, "select: %s",
203 strerror(errno));
204 return -1;
205 }
206 len = buf_size;
207 if (wpa_ctrl_recv(mon, buf, &len) < 0) {
208 sigma_dut_print(dut, DUT_MSG_ERROR, "Failure while "
209 "waiting for events");
210 return -1;
211 }
212 if (len == buf_size)
213 len--;
214 buf[len] = '\0';
215
216 pos = strchr(buf, '>');
217 if (pos) {
218 for (i = 0; events[i]; i++) {
219 if (strncmp(pos + 1, events[i],
220 strlen(events[i])) == 0)
221 return 0; /* Event found */
222 }
223 }
224
225 time(&now);
226 if ((unsigned int) (now - start) > dut->default_timeout) {
227 sigma_dut_print(dut, DUT_MSG_INFO, "Timeout on "
228 "waiting for event");
229 return -1;
230 }
231 }
232}
233
234
235int get_wpa_cli_event2(struct sigma_dut *dut, struct wpa_ctrl *mon,
236 const char *event, const char *event2,
237 char *buf, size_t buf_size)
238{
239 const char *events[3] = { event, event2, NULL };
240 return get_wpa_cli_events(dut, mon, events, buf, buf_size);
241}
242
243
244int get_wpa_cli_event(struct sigma_dut *dut, struct wpa_ctrl *mon,
245 const char *event, char *buf, size_t buf_size)
246{
247 return get_wpa_cli_event2(dut, mon, event, NULL, buf, buf_size);
248}
249
250
251int get_wpa_status(const char *ifname, const char *field, char *obuf,
252 size_t obuf_size)
253{
254 struct wpa_ctrl *ctrl;
255 char buf[4096];
256 char *pos, *end;
257 size_t len, flen;
258
259 snprintf(buf, sizeof(buf), "%s%s", sigma_wpas_ctrl, ifname);
260 ctrl = wpa_ctrl_open(buf);
261 if (ctrl == NULL)
262 return -1;
263 len = sizeof(buf);
264 if (wpa_ctrl_request(ctrl, "STATUS", 6, buf, &len, NULL) < 0) {
265 wpa_ctrl_close(ctrl);
266 return -1;
267 }
268 wpa_ctrl_close(ctrl);
269 buf[len] = '\0';
270
271 flen = strlen(field);
272 pos = buf;
273 while (pos + flen < buf + len) {
274 if (pos > buf) {
275 if (*pos != '\n') {
276 pos++;
277 continue;
278 }
279 pos++;
280 }
281 if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
282 pos++;
283 continue;
284 }
285 pos += flen + 1;
286 end = strchr(pos, '\n');
287 if (end == NULL)
288 return -1;
289 *end++ = '\0';
290 if (end - pos > (int) obuf_size)
291 return -1;
292 memcpy(obuf, pos, end - pos);
293 return 0;
294 }
295
296 return -1;
297}
298
299
300int wait_ip_addr(struct sigma_dut *dut, const char *ifname, int timeout)
301{
302 char ip[30];
303 int count = timeout;
304
305 while (count > 0) {
306 sigma_dut_print(dut, DUT_MSG_DEBUG, "%s: ifname='%s' - %d "
307 "seconds remaining",
308 __func__, ifname, count);
309 count--;
310 if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
311 && strlen(ip) > 0) {
312 sigma_dut_print(dut, DUT_MSG_INFO, "IP address "
313 "found: '%s'", ip);
314 return 0;
315 }
316 sleep(1);
317 }
318 sigma_dut_print(dut, DUT_MSG_INFO, "%s: Could not get IP address for "
319 "ifname='%s'", __func__, ifname);
320 return -1;
321}
322
323
324void remove_wpa_networks(const char *ifname)
325{
326 char buf[4096];
327 char cmd[256];
328 char *pos;
329
330 if (wpa_command_resp(ifname, "LIST_NETWORKS", buf, sizeof(buf)) < 0)
331 return;
332
333 /* Skip the first line (header) */
334 pos = strchr(buf, '\n');
335 if (pos == NULL)
336 return;
337 pos++;
338 while (pos && pos[0]) {
339 int id = atoi(pos);
340 snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %d", id);
341 wpa_command(ifname, cmd);
342 pos = strchr(pos, '\n');
343 if (pos)
344 pos++;
345 }
346}
347
348
349int add_network(const char *ifname)
350{
351 char res[30];
352
353 if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
354 return -1;
355 return atoi(res);
356}
357
358
359int set_network(const char *ifname, int id, const char *field,
360 const char *value)
361{
362 char buf[200];
363 snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
364 return wpa_command(ifname, buf);
365}
366
367
368int set_network_quoted(const char *ifname, int id, const char *field,
369 const char *value)
370{
371 char buf[200];
372 snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
373 id, field, value);
374 return wpa_command(ifname, buf);
375}
376
377
378int add_cred(const char *ifname)
379{
380 char res[30];
381
382 if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
383 return -1;
384 return atoi(res);
385}
386
387
388int set_cred(const char *ifname, int id, const char *field, const char *value)
389{
390 char buf[200];
391 snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
392 return wpa_command(ifname, buf);
393}
394
395
396int set_cred_quoted(const char *ifname, int id, const char *field,
397 const char *value)
398{
399 char buf[200];
400 snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
401 id, field, value);
402 return wpa_command(ifname, buf);
403}
404
405
406int start_sta_mode(struct sigma_dut *dut)
407{
408 FILE *f;
409 char buf[100];
410 char *ifname;
411 char *tmp, *pos;
412
413 if (dut->mode == SIGMA_MODE_STATION)
414 return 0;
415
416 if (dut->mode == SIGMA_MODE_AP) {
417 if (system("killall hostapd") == 0) {
418 int i;
419
420 /* Wait some time to allow hostapd to complete cleanup
421 * before starting a new process */
422 for (i = 0; i < 10; i++) {
423 usleep(500000);
424 if (system("pidof hostapd") != 0)
425 break;
426 }
427 }
428 }
429
430 if (dut->mode == SIGMA_MODE_SNIFFER && dut->sniffer_ifname) {
431 snprintf(buf, sizeof(buf), "ifconfig %s down",
432 dut->sniffer_ifname);
433 if (system(buf) != 0) {
434 sigma_dut_print(dut, DUT_MSG_INFO,
435 "Failed to run '%s'", buf);
436 }
437 snprintf(buf, sizeof(buf), "iw dev %s set type station",
438 dut->sniffer_ifname);
439 if (system(buf) != 0) {
440 sigma_dut_print(dut, DUT_MSG_INFO,
441 "Failed to run '%s'", buf);
442 }
443 }
444
445 dut->mode = SIGMA_MODE_STATION;
446
447 ifname = get_main_ifname();
448 if (wpa_command(ifname, "PING") == 0)
449 return 0; /* wpa_supplicant is already running */
450
451 /* Start wpa_supplicant */
452 f = fopen(SIGMA_TMPDIR "/sigma_dut-sta.conf", "w");
453 if (f == NULL)
454 return -1;
455
456 tmp = strdup(sigma_wpas_ctrl);
457 if (tmp == NULL) {
458 fclose(f);
459 return -1;
460 }
461 pos = tmp;
462 while (pos[0] != '\0' && pos[1] != '\0')
463 pos++;
464 if (*pos == '/')
465 *pos = '\0';
466 fprintf(f, "ctrl_interface=%s\n", tmp);
467 free(tmp);
468 fprintf(f, "device_name=Test client\n");
469 fprintf(f, "device_type=1-0050F204-1\n");
470 fclose(f);
471
472#ifdef __QNXNTO__
473 snprintf(buf, sizeof(buf), "wpa_supplicant -Dqca -i%s -B "
474 "-c" SIGMA_TMPDIR "/sigma_dut-sta.conf", ifname);
475#else /*__QNXNTO__*/
476 snprintf(buf, sizeof(buf), "wpa_supplicant -Dnl80211 -i%s -B "
477 "-c" SIGMA_TMPDIR "/sigma_dut-sta.conf", ifname);
478#endif /*__QNXNTO__*/
479 if (system(buf) != 0) {
480 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
481 return -1;
482 }
483
484 sleep(1);
485
486 if (wpa_command(ifname, "PING")) {
487 sigma_dut_print(dut, DUT_MSG_INFO, "Failed to communicate "
488 "with wpa_supplicant");
489 return -1;
490 }
491
492 return 0;
493}
494
495
496void stop_sta_mode(struct sigma_dut *dut)
497{
498 wpa_command("wlan0", "TERMINATE");
499 wpa_command("wlan1", "TERMINATE");
500 wpa_command("ath0", "TERMINATE");
501 wpa_command("ath1", "TERMINATE");
502}