xref: /wlan-dirver/utils/sigma-dut/wpa_helpers.c (revision c9bc15d17a819fcb399b5df722c4227d26799eb3)
1 /*
2  * Sigma Control API DUT (station/AP)
3  * Copyright (c) 2010-2011, Atheros Communications, Inc.
4  * Copyright (c) 2011-2014, 2016, Qualcomm Atheros, Inc.
5  * Copyright (c) 2018, The Linux Foundation
6  * All Rights Reserved.
7  * Licensed under the Clear BSD license. See README for more details.
8  */
9 
10 #include "sigma_dut.h"
11 #include <sys/stat.h>
12 #include "wpa_ctrl.h"
13 #include "wpa_helpers.h"
14 
15 
16 #define DEFAULT_HAPD_CTRL_PATH "/var/run/hostapd/"
17 
18 extern char *sigma_wpas_ctrl;
19 extern char *client_socket_path;
20 extern char *sigma_hapd_ctrl;
21 
22 
get_main_ifname(struct sigma_dut * dut)23 const char * get_main_ifname(struct sigma_dut *dut)
24 {
25 	enum driver_type drv = get_driver_type(dut);
26 	enum openwrt_driver_type openwrt_drv = get_openwrt_driver_type();
27 
28 	if (dut->main_ifname) {
29 		if (dut->use_5g && dut->main_ifname_5g)
30 			return dut->main_ifname_5g;
31 		if (!dut->use_5g && dut->main_ifname_2g)
32 			return dut->main_ifname_2g;
33 		return dut->main_ifname;
34 	}
35 
36 	if (drv == DRIVER_ATHEROS || openwrt_drv == OPENWRT_DRIVER_ATHEROS) {
37 		if (if_nametoindex("ath2") > 0)
38 			return "ath2";
39 		else if (if_nametoindex("ath1") > 0)
40 			return "ath1";
41 		else
42 			return "ath0";
43 	}
44 
45 	if (if_nametoindex("p2p0") > 0)
46 		return "p2p0";
47 	if (if_nametoindex("wlan1") > 0) {
48 		struct stat s;
49 		if (stat("/sys/module/mac80211", &s) == 0 &&
50 		    if_nametoindex("wlan0")) {
51 			/*
52 			 * Likely a dual-radio AP device; use wlan0 for STA/P2P
53 			 * operations.
54 			 */
55 			return "wlan0";
56 		}
57 		return "wlan1";
58 	}
59 	if (if_nametoindex("wlan0") > 0)
60 		return "wlan0";
61 
62 	return "unknown";
63 }
64 
65 
get_station_ifname(struct sigma_dut * dut)66 const char * get_station_ifname(struct sigma_dut *dut)
67 {
68 	if (dut->station_ifname) {
69 		if (dut->use_5g && dut->station_ifname_5g)
70 			return dut->station_ifname_5g;
71 		if (!dut->use_5g && dut->station_ifname_2g)
72 			return dut->station_ifname_2g;
73 		return dut->station_ifname;
74 	}
75 
76 	/*
77 	 * If we have both wlan0 and wlan1, assume the first one is the station
78 	 * interface.
79 	 */
80 	if (if_nametoindex("wlan1") > 0 && if_nametoindex("wlan0") > 0)
81 		return "wlan0";
82 
83 	if (if_nametoindex("ath0") > 0)
84 		return "ath0";
85 
86 	/* If nothing else matches, hope for best and guess.. */
87 	return "wlan0";
88 }
89 
90 
get_p2p_ifname(struct sigma_dut * dut,const char * primary_ifname)91 const char * get_p2p_ifname(struct sigma_dut *dut, const char *primary_ifname)
92 {
93 	if (strcmp(get_station_ifname(dut), primary_ifname) != 0)
94 		return primary_ifname;
95 
96 	if (dut->p2p_ifname)
97 		return dut->p2p_ifname;
98 
99 	return get_station_ifname(dut);
100 }
101 
102 
dut_ifc_reset(struct sigma_dut * dut)103 void dut_ifc_reset(struct sigma_dut *dut)
104 {
105 	char buf[256];
106 	const char *ifc = get_station_ifname(dut);
107 
108 	snprintf(buf, sizeof(buf), "ifconfig %s down", ifc);
109 	run_system(dut, buf);
110 	snprintf(buf, sizeof(buf), "ifconfig %s up", ifc);
111 	run_system(dut, buf);
112 }
113 
114 
wpa_ctrl_command(const char * path,const char * ifname,const char * cmd)115 int wpa_ctrl_command(const char *path, const char *ifname, const char *cmd)
116 {
117 	struct wpa_ctrl *ctrl;
118 	char buf[128];
119 	size_t len;
120 
121 	snprintf(buf, sizeof(buf), "%s%s", path, ifname);
122 	ctrl = wpa_ctrl_open2(buf, client_socket_path);
123 	if (ctrl == NULL) {
124 		printf("wpa_command: wpa_ctrl_open2(%s) failed\n", buf);
125 		return -1;
126 	}
127 	len = sizeof(buf);
128 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
129 		printf("wpa_command: wpa_ctrl_request failed\n");
130 		wpa_ctrl_close(ctrl);
131 		return -1;
132 	}
133 	wpa_ctrl_close(ctrl);
134 	buf[len] = '\0';
135 	if (strncmp(buf, "FAIL", 4) == 0) {
136 		printf("wpa_command: Command failed (FAIL received)\n");
137 		return -1;
138 	}
139 	return 0;
140 }
141 
142 
wpa_command(const char * ifname,const char * cmd)143 int wpa_command(const char *ifname, const char *cmd)
144 {
145 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
146 	return wpa_ctrl_command(sigma_wpas_ctrl, ifname, cmd);
147 }
148 
149 
hapd_command(const char * ifname,const char * cmd)150 int hapd_command(const char *ifname, const char *cmd)
151 {
152 	const char *path = sigma_hapd_ctrl ? sigma_hapd_ctrl :
153 		DEFAULT_HAPD_CTRL_PATH;
154 
155 	printf("hapd_command(ifname='%s', cmd='%s')\n", ifname, cmd);
156 	return wpa_ctrl_command(path, ifname, cmd);
157 }
158 
159 
wpa_ctrl_command_resp(const char * path,const char * ifname,const char * cmd,char * resp,size_t resp_size)160 int wpa_ctrl_command_resp(const char *path, const char *ifname,
161 			  const char *cmd, char *resp, size_t resp_size)
162 {
163 	struct wpa_ctrl *ctrl;
164 	char buf[128];
165 	size_t len;
166 
167 	snprintf(buf, sizeof(buf), "%s%s", path, ifname);
168 	ctrl = wpa_ctrl_open2(buf, client_socket_path);
169 	if (ctrl == NULL) {
170 		printf("wpa_command: wpa_ctrl_open2(%s) failed\n", buf);
171 		return -1;
172 	}
173 	len = resp_size;
174 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
175 		printf("wpa_command: wpa_ctrl_request failed\n");
176 		wpa_ctrl_close(ctrl);
177 		return -1;
178 	}
179 	wpa_ctrl_close(ctrl);
180 	resp[len] = '\0';
181 	return 0;
182 }
183 
184 
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)185 int wpa_command_resp(const char *ifname, const char *cmd,
186 		     char *resp, size_t resp_size)
187 {
188 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
189 	return wpa_ctrl_command_resp(sigma_wpas_ctrl, ifname, cmd,
190 				     resp, resp_size);
191 }
192 
193 
hapd_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)194 int hapd_command_resp(const char *ifname, const char *cmd,
195 		      char *resp, size_t resp_size)
196 {
197 	const char *path = sigma_hapd_ctrl ? sigma_hapd_ctrl :
198 		DEFAULT_HAPD_CTRL_PATH;
199 
200 	printf("hapd_command(ifname='%s', cmd='%s')\n", ifname, cmd);
201 	return wpa_ctrl_command_resp(path, ifname, cmd, resp, resp_size);
202 }
203 
204 
open_wpa_ctrl_mon(const char * ctrl_path,const char * ifname)205 struct wpa_ctrl * open_wpa_ctrl_mon(const char *ctrl_path, const char *ifname)
206 {
207 	struct wpa_ctrl *ctrl;
208 	char path[256];
209 
210 	snprintf(path, sizeof(path), "%s%s", ctrl_path, ifname);
211 	ctrl = wpa_ctrl_open2(path, client_socket_path);
212 	if (ctrl == NULL)
213 		return NULL;
214 	if (wpa_ctrl_attach(ctrl) < 0) {
215 		wpa_ctrl_close(ctrl);
216 		return NULL;
217 	}
218 
219 	return ctrl;
220 }
221 
222 
open_wpa_mon(const char * ifname)223 struct wpa_ctrl * open_wpa_mon(const char *ifname)
224 {
225 	return open_wpa_ctrl_mon(sigma_wpas_ctrl, ifname);
226 }
227 
228 
open_hapd_mon(const char * ifname)229 struct wpa_ctrl * open_hapd_mon(const char *ifname)
230 {
231 	const char *path = sigma_hapd_ctrl ?
232 		sigma_hapd_ctrl : DEFAULT_HAPD_CTRL_PATH;
233 
234 	return open_wpa_ctrl_mon(path, ifname);
235 }
236 
237 
get_wpa_cli_events(struct sigma_dut * dut,struct wpa_ctrl * mon,const char ** events,char * buf,size_t buf_size)238 int get_wpa_cli_events(struct sigma_dut *dut, struct wpa_ctrl *mon,
239 		       const char **events, char *buf, size_t buf_size)
240 {
241 	int fd, ret;
242 	fd_set rfd;
243 	char *pos;
244 	struct timeval tv;
245 	time_t start, now;
246 	int i;
247 
248 	for (i = 0; events[i]; i++) {
249 		sigma_dut_print(dut, DUT_MSG_DEBUG,
250 				"Waiting for wpa_cli event: %s", events[i]);
251 	}
252 	fd = wpa_ctrl_get_fd(mon);
253 	if (fd < 0)
254 		return -1;
255 
256 	time(&start);
257 	while (1) {
258 		size_t len;
259 
260 		FD_ZERO(&rfd);
261 		FD_SET(fd, &rfd);
262 
263 		time(&now);
264 		if ((unsigned int) (now - start) >= dut->default_timeout)
265 			tv.tv_sec = 1;
266 		else
267 			tv.tv_sec = dut->default_timeout -
268 				(unsigned int) (now - start) + 1;
269 		tv.tv_usec = 0;
270 		ret = select(fd + 1, &rfd, NULL, NULL, &tv);
271 		if (ret == 0) {
272 			sigma_dut_print(dut, DUT_MSG_INFO, "Timeout on "
273 					"waiting for events");
274 			return -1;
275 		}
276 		if (ret < 0) {
277 			sigma_dut_print(dut, DUT_MSG_INFO, "select: %s",
278 					strerror(errno));
279 			return -1;
280 		}
281 		len = buf_size;
282 		if (wpa_ctrl_recv(mon, buf, &len) < 0) {
283 			sigma_dut_print(dut, DUT_MSG_ERROR, "Failure while "
284 					"waiting for events");
285 			return -1;
286 		}
287 		if (len == buf_size)
288 			len--;
289 		buf[len] = '\0';
290 
291 		pos = strchr(buf, '>');
292 		if (pos) {
293 			for (i = 0; events[i]; i++) {
294 				if (strncmp(pos + 1, events[i],
295 					    strlen(events[i])) == 0)
296 					return 0; /* Event found */
297 			}
298 		}
299 
300 		time(&now);
301 		if ((unsigned int) (now - start) > dut->default_timeout) {
302 			sigma_dut_print(dut, DUT_MSG_INFO, "Timeout on "
303 					"waiting for event");
304 			return -1;
305 		}
306 	}
307 }
308 
309 
get_wpa_cli_event2(struct sigma_dut * dut,struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)310 int get_wpa_cli_event2(struct sigma_dut *dut, struct wpa_ctrl *mon,
311 		       const char *event, const char *event2,
312 		       char *buf, size_t buf_size)
313 {
314 	const char *events[3] = { event, event2, NULL };
315 	return get_wpa_cli_events(dut, mon, events, buf, buf_size);
316 }
317 
318 
get_wpa_cli_event(struct sigma_dut * dut,struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)319 int get_wpa_cli_event(struct sigma_dut *dut, struct wpa_ctrl *mon,
320 		      const char *event, char *buf, size_t buf_size)
321 {
322 	return get_wpa_cli_event2(dut, mon, event, NULL, buf, buf_size);
323 }
324 
325 
326 /*
327  * signal_poll cmd output sample
328  * RSSI=-51
329  * LINKSPEED=866
330  * NOISE=-101
331  * FREQUENCY=5180
332  * AVG_RSSI=-50
333  */
get_wpa_signal_poll(struct sigma_dut * dut,const char * ifname,const char * field,char * obuf,size_t obuf_size)334 int get_wpa_signal_poll(struct sigma_dut *dut, const char *ifname,
335 			const char *field, char *obuf, size_t obuf_size)
336 {
337 	struct wpa_ctrl *ctrl;
338 	char buf[4096];
339 	char *pos, *end;
340 	size_t len, flen;
341 
342 	snprintf(buf, sizeof(buf), "%s%s", sigma_wpas_ctrl, ifname);
343 	ctrl = wpa_ctrl_open2(buf, client_socket_path);
344 	if (!ctrl) {
345 		sigma_dut_print(dut, DUT_MSG_ERROR,
346 				"Failed to connect to wpa_supplicant");
347 		return -1;
348 	}
349 
350 	len = sizeof(buf);
351 	if (wpa_ctrl_request(ctrl, "SIGNAL_POLL", 11, buf, &len, NULL) < 0) {
352 		wpa_ctrl_close(ctrl);
353 		sigma_dut_print(dut, DUT_MSG_ERROR, "ctrl request failed");
354 		return -1;
355 	}
356 	buf[len] = '\0';
357 
358 	wpa_ctrl_close(ctrl);
359 
360 	flen = strlen(field);
361 	pos = buf;
362 	while (pos + flen < buf + len) {
363 		if (pos > buf) {
364 			if (*pos != '\n') {
365 				pos++;
366 				continue;
367 			}
368 			pos++;
369 		}
370 		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
371 			pos++;
372 			continue;
373 		}
374 		pos += flen + 1;
375 		end = strchr(pos, '\n');
376 		if (!end) {
377 			sigma_dut_print(dut, DUT_MSG_ERROR,
378 					"Could not find signal poll field '%s' - end is NULL",
379 					field);
380 			return -1;
381 		}
382 		*end++ = '\0';
383 		if (end - pos > (int) obuf_size) {
384 			sigma_dut_print(dut, DUT_MSG_ERROR,
385 					"signal poll out buffer is too small");
386 			return -1;
387 		}
388 		memcpy(obuf, pos, end - pos);
389 		return 0;
390 	}
391 
392 	sigma_dut_print(dut, DUT_MSG_ERROR, "signal poll param not found");
393 	return -1;
394 }
395 
396 
get_wpa_ssid_bssid(struct sigma_dut * dut,const char * ifname,char * buf,size_t buf_size)397 int get_wpa_ssid_bssid(struct sigma_dut *dut, const char *ifname,
398 		       char *buf, size_t buf_size)
399 {
400 	struct wpa_ctrl *ctrl;
401 	char buf_local[4096];
402 	char *network, *ssid, *bssid;
403 	size_t buf_size_local;
404 	unsigned int count = 0;
405 	int len, res;
406 	char *save_ptr_network = NULL;
407 
408 	ctrl = open_wpa_mon(ifname);
409 	if (!ctrl) {
410 		sigma_dut_print(dut, DUT_MSG_ERROR,
411 				"Failed to connect to wpa_supplicant");
412 		return -1;
413 	}
414 
415 	wpa_command(ifname, "BSS_FLUSH");
416 	if (wpa_command(ifname, "SCAN TYPE=ONLY")) {
417 		wpa_ctrl_detach(ctrl);
418 		wpa_ctrl_close(ctrl);
419 		sigma_dut_print(dut, DUT_MSG_ERROR, "SCAN command failed");
420 		return -1;
421 	}
422 
423 	res = get_wpa_cli_event(dut, ctrl, "CTRL-EVENT-SCAN-RESULTS",
424 				buf_local, sizeof(buf_local));
425 	wpa_ctrl_detach(ctrl);
426 	buf_size_local = sizeof(buf_local);
427 	if (res < 0 || wpa_ctrl_request(ctrl, "BSS RANGE=ALL MASK=0x1002", 25,
428 					buf_local, &buf_size_local, NULL) < 0) {
429 		wpa_ctrl_close(ctrl);
430 		sigma_dut_print(dut, DUT_MSG_ERROR, "BSS ctrl request failed");
431 		return -1;
432 	}
433 	buf_local[buf_size_local] = '\0';
434 
435 	wpa_ctrl_close(ctrl);
436 
437 	/* Below is BSS RANGE=ALL MASK=0x1002 command sample output which is
438 	 * parsed to get the BSSID and SSID parameters.
439 	 * Even number of lines, first line BSSID of network 1, second line SSID
440 	 * of network 1, ...
441 	 *
442 	 * bssid=xx:xx:xx:xx:xx:x1
443 	 * ssid=SSID1
444 	 * bssid=xx:xx:xx:xx:xx:x2
445 	 * ssid=SSID2
446 	 */
447 
448 	network = strtok_r(buf_local, "\n", &save_ptr_network);
449 
450 	while (network) {
451 		sigma_dut_print(dut, DUT_MSG_DEBUG, "BSSID: %s", network);
452 		bssid = NULL;
453 		if (!strtok_r(network, "=", &bssid)) {
454 			sigma_dut_print(dut, DUT_MSG_ERROR,
455 					"Invalid BSS result: BSSID not found");
456 			return -1;
457 		}
458 		network = strtok_r(NULL, "\n", &save_ptr_network);
459 		if (network) {
460 			sigma_dut_print(dut, DUT_MSG_DEBUG, "SSID: %s",
461 					network);
462 			ssid = NULL;
463 			if (!strtok_r(network, "=", &ssid)) {
464 				sigma_dut_print(dut, DUT_MSG_ERROR,
465 						"Invalid BSS result: SSID is null");
466 				return -1;
467 			}
468 		} else {
469 			sigma_dut_print(dut, DUT_MSG_ERROR,
470 					"Invalid BSS result: SSID not found");
471 			return -1;
472 		}
473 
474 		/* Skip comma for first entry */
475 		count++;
476 		len = snprintf(buf, buf_size, "%sSSID%d,%s,BSSID%d,%s",
477 			       count > 1 ? "," : "",
478 			       count, ssid, count, bssid);
479 		if (len < 0 || (size_t) len >= buf_size) {
480 			buf[0] = '\0';
481 			return 0;
482 		}
483 
484 		buf_size -= len;
485 		buf += len;
486 
487 		network = strtok_r(NULL, "\n", &save_ptr_network);
488 	}
489 
490 	return 0;
491 }
492 
493 
get_wpa_ctrl_status_field(const char * path,const char * ifname,const char * cmd,const char * field,char * obuf,size_t obuf_size)494 static int get_wpa_ctrl_status_field(const char *path, const char *ifname,
495 				     const char *cmd, const char *field,
496 				     char *obuf, size_t obuf_size)
497 {
498 	struct wpa_ctrl *ctrl;
499 	char buf[4096];
500 	char *pos, *end;
501 	size_t len, flen;
502 
503 	snprintf(buf, sizeof(buf), "%s%s", path, ifname);
504 	ctrl = wpa_ctrl_open2(buf, client_socket_path);
505 	if (ctrl == NULL)
506 		return -1;
507 	len = sizeof(buf);
508 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
509 		wpa_ctrl_close(ctrl);
510 		return -1;
511 	}
512 	wpa_ctrl_close(ctrl);
513 	buf[len] = '\0';
514 
515 	flen = strlen(field);
516 	pos = buf;
517 	while (pos + flen < buf + len) {
518 		if (pos > buf) {
519 			if (*pos != '\n') {
520 				pos++;
521 				continue;
522 			}
523 			pos++;
524 		}
525 		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
526 			pos++;
527 			continue;
528 		}
529 		pos += flen + 1;
530 		end = strchr(pos, '\n');
531 		if (end == NULL)
532 			return -1;
533 		*end++ = '\0';
534 		if (end - pos > (int) obuf_size)
535 			return -1;
536 		memcpy(obuf, pos, end - pos);
537 		return 0;
538 	}
539 
540 	return -1;
541 }
542 
543 
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)544 int get_wpa_status(const char *ifname, const char *field, char *obuf,
545 		   size_t obuf_size)
546 {
547 	return get_wpa_ctrl_status_field(sigma_wpas_ctrl, ifname, "STATUS",
548 					 field, obuf, obuf_size);
549 }
550 
551 
get_hapd_config(const char * ifname,const char * field,char * obuf,size_t obuf_size)552 int get_hapd_config(const char *ifname, const char *field, char *obuf,
553 		    size_t obuf_size)
554 {
555 	const char *path = sigma_hapd_ctrl ?
556 		sigma_hapd_ctrl : DEFAULT_HAPD_CTRL_PATH;
557 
558 	return get_wpa_ctrl_status_field(path, ifname, "GET_CONFIG",
559 					 field, obuf, obuf_size);
560 }
561 
562 
wait_ip_addr(struct sigma_dut * dut,const char * ifname,int timeout)563 int wait_ip_addr(struct sigma_dut *dut, const char *ifname, int timeout)
564 {
565 	char ip[30];
566 	int count = timeout;
567 
568 	while (count > 0) {
569 		sigma_dut_print(dut, DUT_MSG_DEBUG, "%s: ifname='%s' - %d "
570 				"seconds remaining",
571 				__func__, ifname, count);
572 		count--;
573 		if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
574 		    && strlen(ip) > 0) {
575 			sigma_dut_print(dut, DUT_MSG_INFO, "IP address "
576 					"found: '%s'", ip);
577 			return 0;
578 		}
579 		sleep(1);
580 	}
581 	sigma_dut_print(dut, DUT_MSG_INFO, "%s: Could not get IP address for "
582 			"ifname='%s'", __func__, ifname);
583 	return -1;
584 }
585 
586 
remove_wpa_networks(const char * ifname)587 void remove_wpa_networks(const char *ifname)
588 {
589 	char buf[4096];
590 	char cmd[256];
591 	char *pos;
592 
593 	if (wpa_command_resp(ifname, "LIST_NETWORKS", buf, sizeof(buf)) < 0)
594 		return;
595 
596 	/* Skip the first line (header) */
597 	pos = strchr(buf, '\n');
598 	if (pos == NULL)
599 		return;
600 	pos++;
601 	while (pos && pos[0]) {
602 		int id = atoi(pos);
603 		snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %d", id);
604 		wpa_command(ifname, cmd);
605 		pos = strchr(pos, '\n');
606 		if (pos)
607 			pos++;
608 	}
609 }
610 
611 
add_network(const char * ifname)612 int add_network(const char *ifname)
613 {
614 	char res[30];
615 
616 	if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
617 		return -1;
618 	return atoi(res);
619 }
620 
621 
set_network(const char * ifname,int id,const char * field,const char * value)622 int set_network(const char *ifname, int id, const char *field,
623 		const char *value)
624 {
625 	char buf[200];
626 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
627 	return wpa_command(ifname, buf);
628 }
629 
630 
set_network_quoted(const char * ifname,int id,const char * field,const char * value)631 int set_network_quoted(const char *ifname, int id, const char *field,
632 		       const char *value)
633 {
634 	char buf[200];
635 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
636 		 id, field, value);
637 	return wpa_command(ifname, buf);
638 }
639 
640 
add_cred(const char * ifname)641 int add_cred(const char *ifname)
642 {
643 	char res[30];
644 
645 	if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
646 		return -1;
647 	return atoi(res);
648 }
649 
650 
set_cred(const char * ifname,int id,const char * field,const char * value)651 int set_cred(const char *ifname, int id, const char *field, const char *value)
652 {
653 	char buf[200];
654 	snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
655 	return wpa_command(ifname, buf);
656 }
657 
658 
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)659 int set_cred_quoted(const char *ifname, int id, const char *field,
660 		    const char *value)
661 {
662 	char buf[200];
663 	snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
664 		 id, field, value);
665 	return wpa_command(ifname, buf);
666 }
667 
668 
concat_sigma_tmpdir(struct sigma_dut * dut,const char * src,char * dst,size_t len)669 const char * concat_sigma_tmpdir(struct sigma_dut *dut, const char *src,
670 				 char *dst, size_t len)
671 {
672 	snprintf(dst, len, "%s%s", dut->sigma_tmpdir, src);
673 
674 	return dst;
675 }
676 
677 
start_sta_mode(struct sigma_dut * dut)678 int start_sta_mode(struct sigma_dut *dut)
679 {
680 	FILE *f;
681 	char buf[256];
682 	char sta_conf_path[100];
683 	const char *ifname;
684 	char *tmp, *pos;
685 
686 	if (dut->mode == SIGMA_MODE_STATION) {
687 		if ((dut->use_5g && dut->sta_2g_started) ||
688 		    (!dut->use_5g && dut->sta_5g_started)) {
689 			stop_sta_mode(dut);
690 			sleep(1);
691 		} else {
692 			return 0;
693 		}
694 	}
695 
696 	if (dut->mode == SIGMA_MODE_AP) {
697 		if (system("killall hostapd") == 0) {
698 			int i;
699 
700 			/* Wait some time to allow hostapd to complete cleanup
701 			 * before starting a new process */
702 			for (i = 0; i < 10; i++) {
703 				usleep(500000);
704 				if (system("pidof hostapd") != 0)
705 					break;
706 			}
707 		}
708 	}
709 
710 	if (dut->mode == SIGMA_MODE_SNIFFER && dut->sniffer_ifname) {
711 		snprintf(buf, sizeof(buf), "ifconfig %s down",
712 			 dut->sniffer_ifname);
713 		if (system(buf) != 0) {
714 			sigma_dut_print(dut, DUT_MSG_INFO,
715 					"Failed to run '%s'", buf);
716 		}
717 		snprintf(buf, sizeof(buf), "iw dev %s set type station",
718 			 dut->sniffer_ifname);
719 		if (system(buf) != 0) {
720 			sigma_dut_print(dut, DUT_MSG_INFO,
721 					"Failed to run '%s'", buf);
722 		}
723 	}
724 
725 	dut->mode = SIGMA_MODE_STATION;
726 
727 	ifname = get_main_ifname(dut);
728 	if (wpa_command(ifname, "PING") == 0)
729 		return 0; /* wpa_supplicant is already running */
730 
731 	/* Start wpa_supplicant */
732 	f = fopen(concat_sigma_tmpdir(dut, "/sigma_dut-sta.conf", sta_conf_path,
733 				      sizeof(sta_conf_path)), "w");
734 	if (f == NULL)
735 		return -1;
736 
737 	tmp = strdup(sigma_wpas_ctrl);
738 	if (tmp == NULL) {
739 		fclose(f);
740 		return -1;
741 	}
742 	pos = tmp;
743 	while (pos[0] != '\0' && pos[1] != '\0')
744 		pos++;
745 	if (*pos == '/')
746 		*pos = '\0';
747 	fprintf(f, "ctrl_interface=%s\n", tmp);
748 	free(tmp);
749 	fprintf(f, "device_name=Test client\n");
750 	fprintf(f, "device_type=1-0050F204-1\n");
751 	if (is_60g_sigma_dut(dut)) {
752 		fprintf(f, "eapol_version=2\n");
753 		fprintf(f,
754 			"config_methods=display push_button keypad virtual_display physical_display virtual_push_button\n");
755 	}
756 	fclose(f);
757 
758 #ifdef  __QNXNTO__
759 	snprintf(buf, sizeof(buf),
760 		 "wpa_supplicant -Dqca -i%s -B %s%s%s -c %s/sigma_dut-sta.conf",
761 		 ifname,
762 		 dut->wpa_supplicant_debug_log ? "-K -t -ddd " : "",
763 		 (dut->wpa_supplicant_debug_log &&
764 		  dut->wpa_supplicant_debug_log[0]) ? "-f " : "",
765 		 dut->wpa_supplicant_debug_log ?
766 		 dut->wpa_supplicant_debug_log : "",
767 		 dut->sigma_tmpdir);
768 #else /*__QNXNTO__*/
769 	snprintf(buf, sizeof(buf),
770 		 "%swpa_supplicant -Dnl80211 -i%s -B %s%s%s -c %s/sigma_dut-sta.conf",
771 		 file_exists("wpa_supplicant") ? "./" : "",
772 		 ifname,
773 		 dut->wpa_supplicant_debug_log ? "-K -t -ddd " : "",
774 		 (dut->wpa_supplicant_debug_log &&
775 		  dut->wpa_supplicant_debug_log[0]) ? "-f " : "",
776 		 dut->wpa_supplicant_debug_log ?
777 		 dut->wpa_supplicant_debug_log : "",
778 		 dut->sigma_tmpdir);
779 #endif /*__QNXNTO__*/
780 	if (system(buf) != 0) {
781 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to run '%s'", buf);
782 		return -1;
783 	}
784 
785 	sleep(1);
786 
787 	if (wpa_command(ifname, "PING")) {
788 		sigma_dut_print(dut, DUT_MSG_INFO, "Failed to communicate "
789 				"with wpa_supplicant");
790 		return -1;
791 	}
792 	if (dut->use_5g)
793 		dut->sta_5g_started = 1;
794 	else
795 		dut->sta_2g_started = 1;
796 
797 	return 0;
798 }
799 
800 
stop_sta_mode(struct sigma_dut * dut)801 void stop_sta_mode(struct sigma_dut *dut)
802 {
803 	if (is_60g_sigma_dut(dut)) {
804 		wpa_command(get_main_ifname(dut), "TERMINATE");
805 		return;
806 	}
807 
808 	wpa_command("wlan0", "TERMINATE");
809 	wpa_command("wlan1", "TERMINATE");
810 	wpa_command("ath0", "TERMINATE");
811 	wpa_command("ath1", "TERMINATE");
812 	if (dut->main_ifname_2g)
813 		wpa_command(dut->main_ifname_2g, "TERMINATE");
814 	if (dut->main_ifname_5g)
815 		wpa_command(dut->main_ifname_5g, "TERMINATE");
816 	if (dut->station_ifname_2g)
817 		wpa_command(dut->station_ifname_2g, "TERMINATE");
818 	if (dut->station_ifname_5g)
819 		wpa_command(dut->station_ifname_5g, "TERMINATE");
820 	dut->sta_2g_started = 0;
821 	dut->sta_5g_started = 0;
822 }
823