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