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