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