1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt  * wpa_supplicant ctrl_iface helpers
3*a1157835SDaniel Fojt  * Copyright (c) 2010-2011, Atheros Communications, Inc.
4*a1157835SDaniel Fojt  * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
5*a1157835SDaniel Fojt  *
6*a1157835SDaniel Fojt  * This software may be distributed under the terms of the BSD license.
7*a1157835SDaniel Fojt  * See README for more details.
8*a1157835SDaniel Fojt  */
9*a1157835SDaniel Fojt 
10*a1157835SDaniel Fojt #include "includes.h"
11*a1157835SDaniel Fojt #include <time.h>
12*a1157835SDaniel Fojt 
13*a1157835SDaniel Fojt #include "common.h"
14*a1157835SDaniel Fojt #include "wpa_ctrl.h"
15*a1157835SDaniel Fojt #include "wpa_helpers.h"
16*a1157835SDaniel Fojt 
17*a1157835SDaniel Fojt 
18*a1157835SDaniel Fojt char *wpas_ctrl_path = "/var/run/wpa_supplicant/";
19*a1157835SDaniel Fojt static int default_timeout = 60;
20*a1157835SDaniel Fojt 
21*a1157835SDaniel Fojt 
wpa_open_ctrl(const char * ifname)22*a1157835SDaniel Fojt static struct wpa_ctrl * wpa_open_ctrl(const char *ifname)
23*a1157835SDaniel Fojt {
24*a1157835SDaniel Fojt 	char buf[128];
25*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
26*a1157835SDaniel Fojt 
27*a1157835SDaniel Fojt 	os_snprintf(buf, sizeof(buf), "%s%s", wpas_ctrl_path, ifname);
28*a1157835SDaniel Fojt 	ctrl = wpa_ctrl_open(buf);
29*a1157835SDaniel Fojt 	if (ctrl == NULL)
30*a1157835SDaniel Fojt 		printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
31*a1157835SDaniel Fojt 	return ctrl;
32*a1157835SDaniel Fojt }
33*a1157835SDaniel Fojt 
34*a1157835SDaniel Fojt 
wpa_command(const char * ifname,const char * cmd)35*a1157835SDaniel Fojt int wpa_command(const char *ifname, const char *cmd)
36*a1157835SDaniel Fojt {
37*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
38*a1157835SDaniel Fojt 	char buf[128];
39*a1157835SDaniel Fojt 	size_t len;
40*a1157835SDaniel Fojt 
41*a1157835SDaniel Fojt 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
42*a1157835SDaniel Fojt 	ctrl = wpa_open_ctrl(ifname);
43*a1157835SDaniel Fojt 	if (ctrl == NULL)
44*a1157835SDaniel Fojt 		return -1;
45*a1157835SDaniel Fojt 	len = sizeof(buf);
46*a1157835SDaniel Fojt 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
47*a1157835SDaniel Fojt 		printf("wpa_command: wpa_ctrl_request failed\n");
48*a1157835SDaniel Fojt 		wpa_ctrl_close(ctrl);
49*a1157835SDaniel Fojt 		return -1;
50*a1157835SDaniel Fojt 	}
51*a1157835SDaniel Fojt 	wpa_ctrl_close(ctrl);
52*a1157835SDaniel Fojt 	buf[len] = '\0';
53*a1157835SDaniel Fojt 	if (strncmp(buf, "FAIL", 4) == 0) {
54*a1157835SDaniel Fojt 		printf("wpa_command: Command failed (FAIL received)\n");
55*a1157835SDaniel Fojt 		return -1;
56*a1157835SDaniel Fojt 	}
57*a1157835SDaniel Fojt 	return 0;
58*a1157835SDaniel Fojt }
59*a1157835SDaniel Fojt 
60*a1157835SDaniel Fojt 
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)61*a1157835SDaniel Fojt int wpa_command_resp(const char *ifname, const char *cmd,
62*a1157835SDaniel Fojt 		     char *resp, size_t resp_size)
63*a1157835SDaniel Fojt {
64*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
65*a1157835SDaniel Fojt 	size_t len;
66*a1157835SDaniel Fojt 
67*a1157835SDaniel Fojt 	printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
68*a1157835SDaniel Fojt 	ctrl = wpa_open_ctrl(ifname);
69*a1157835SDaniel Fojt 	if (ctrl == NULL)
70*a1157835SDaniel Fojt 		return -1;
71*a1157835SDaniel Fojt 	len = resp_size;
72*a1157835SDaniel Fojt 	if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
73*a1157835SDaniel Fojt 		printf("wpa_command: wpa_ctrl_request failed\n");
74*a1157835SDaniel Fojt 		wpa_ctrl_close(ctrl);
75*a1157835SDaniel Fojt 		return -1;
76*a1157835SDaniel Fojt 	}
77*a1157835SDaniel Fojt 	wpa_ctrl_close(ctrl);
78*a1157835SDaniel Fojt 	resp[len] = '\0';
79*a1157835SDaniel Fojt 	return 0;
80*a1157835SDaniel Fojt }
81*a1157835SDaniel Fojt 
82*a1157835SDaniel Fojt 
open_wpa_mon(const char * ifname)83*a1157835SDaniel Fojt struct wpa_ctrl * open_wpa_mon(const char *ifname)
84*a1157835SDaniel Fojt {
85*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
86*a1157835SDaniel Fojt 
87*a1157835SDaniel Fojt 	ctrl = wpa_open_ctrl(ifname);
88*a1157835SDaniel Fojt 	if (ctrl == NULL)
89*a1157835SDaniel Fojt 		return NULL;
90*a1157835SDaniel Fojt 	if (wpa_ctrl_attach(ctrl) < 0) {
91*a1157835SDaniel Fojt 		wpa_ctrl_close(ctrl);
92*a1157835SDaniel Fojt 		return NULL;
93*a1157835SDaniel Fojt 	}
94*a1157835SDaniel Fojt 
95*a1157835SDaniel Fojt 	return ctrl;
96*a1157835SDaniel Fojt }
97*a1157835SDaniel Fojt 
98*a1157835SDaniel Fojt 
get_wpa_cli_event2(struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)99*a1157835SDaniel Fojt int get_wpa_cli_event2(struct wpa_ctrl *mon,
100*a1157835SDaniel Fojt 		       const char *event, const char *event2,
101*a1157835SDaniel Fojt 		       char *buf, size_t buf_size)
102*a1157835SDaniel Fojt {
103*a1157835SDaniel Fojt 	int fd, ret;
104*a1157835SDaniel Fojt 	fd_set rfd;
105*a1157835SDaniel Fojt 	char *pos;
106*a1157835SDaniel Fojt 	struct timeval tv;
107*a1157835SDaniel Fojt 	time_t start, now;
108*a1157835SDaniel Fojt 
109*a1157835SDaniel Fojt 	printf("Waiting for wpa_cli event %s\n", event);
110*a1157835SDaniel Fojt 	fd = wpa_ctrl_get_fd(mon);
111*a1157835SDaniel Fojt 	if (fd < 0)
112*a1157835SDaniel Fojt 		return -1;
113*a1157835SDaniel Fojt 
114*a1157835SDaniel Fojt 	time(&start);
115*a1157835SDaniel Fojt 	while (1) {
116*a1157835SDaniel Fojt 		size_t len;
117*a1157835SDaniel Fojt 
118*a1157835SDaniel Fojt 		FD_ZERO(&rfd);
119*a1157835SDaniel Fojt 		FD_SET(fd, &rfd);
120*a1157835SDaniel Fojt 		tv.tv_sec = default_timeout;
121*a1157835SDaniel Fojt 		tv.tv_usec = 0;
122*a1157835SDaniel Fojt 		ret = select(fd + 1, &rfd, NULL, NULL, &tv);
123*a1157835SDaniel Fojt 		if (ret == 0) {
124*a1157835SDaniel Fojt 			printf("Timeout on waiting for event %s\n", event);
125*a1157835SDaniel Fojt 			return -1;
126*a1157835SDaniel Fojt 		}
127*a1157835SDaniel Fojt 		if (ret < 0) {
128*a1157835SDaniel Fojt 			printf("select: %s\n", strerror(errno));
129*a1157835SDaniel Fojt 			return -1;
130*a1157835SDaniel Fojt 		}
131*a1157835SDaniel Fojt 		len = buf_size;
132*a1157835SDaniel Fojt 		if (wpa_ctrl_recv(mon, buf, &len) < 0) {
133*a1157835SDaniel Fojt 			printf("Failure while waiting for event %s\n", event);
134*a1157835SDaniel Fojt 			return -1;
135*a1157835SDaniel Fojt 		}
136*a1157835SDaniel Fojt 		if (len == buf_size)
137*a1157835SDaniel Fojt 			len--;
138*a1157835SDaniel Fojt 		buf[len] = '\0';
139*a1157835SDaniel Fojt 
140*a1157835SDaniel Fojt 		pos = strchr(buf, '>');
141*a1157835SDaniel Fojt 		if (pos &&
142*a1157835SDaniel Fojt 		    (strncmp(pos + 1, event, strlen(event)) == 0 ||
143*a1157835SDaniel Fojt 		     (event2 &&
144*a1157835SDaniel Fojt 		      strncmp(pos + 1, event2, strlen(event2)) == 0)))
145*a1157835SDaniel Fojt 			return 0; /* Event found */
146*a1157835SDaniel Fojt 
147*a1157835SDaniel Fojt 		time(&now);
148*a1157835SDaniel Fojt 		if ((int) (now - start) > default_timeout) {
149*a1157835SDaniel Fojt 			printf("Timeout on waiting for event %s\n", event);
150*a1157835SDaniel Fojt 			return -1;
151*a1157835SDaniel Fojt 		}
152*a1157835SDaniel Fojt 	}
153*a1157835SDaniel Fojt }
154*a1157835SDaniel Fojt 
155*a1157835SDaniel Fojt 
get_wpa_cli_event(struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)156*a1157835SDaniel Fojt int get_wpa_cli_event(struct wpa_ctrl *mon,
157*a1157835SDaniel Fojt 		      const char *event, char *buf, size_t buf_size)
158*a1157835SDaniel Fojt {
159*a1157835SDaniel Fojt 	return get_wpa_cli_event2(mon, event, NULL, buf, buf_size);
160*a1157835SDaniel Fojt }
161*a1157835SDaniel Fojt 
162*a1157835SDaniel Fojt 
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)163*a1157835SDaniel Fojt int get_wpa_status(const char *ifname, const char *field, char *obuf,
164*a1157835SDaniel Fojt 		   size_t obuf_size)
165*a1157835SDaniel Fojt {
166*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
167*a1157835SDaniel Fojt 	char buf[4096];
168*a1157835SDaniel Fojt 	char *pos, *end;
169*a1157835SDaniel Fojt 	size_t len, flen;
170*a1157835SDaniel Fojt 
171*a1157835SDaniel Fojt 	ctrl = wpa_open_ctrl(ifname);
172*a1157835SDaniel Fojt 	if (ctrl == NULL)
173*a1157835SDaniel Fojt 		return -1;
174*a1157835SDaniel Fojt 	len = sizeof(buf);
175*a1157835SDaniel Fojt 	if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len,
176*a1157835SDaniel Fojt 			     NULL) < 0) {
177*a1157835SDaniel Fojt 		wpa_ctrl_close(ctrl);
178*a1157835SDaniel Fojt 		return -1;
179*a1157835SDaniel Fojt 	}
180*a1157835SDaniel Fojt 	wpa_ctrl_close(ctrl);
181*a1157835SDaniel Fojt 	buf[len] = '\0';
182*a1157835SDaniel Fojt 
183*a1157835SDaniel Fojt 	flen = strlen(field);
184*a1157835SDaniel Fojt 	pos = buf;
185*a1157835SDaniel Fojt 	while (pos + flen < buf + len) {
186*a1157835SDaniel Fojt 		if (pos > buf) {
187*a1157835SDaniel Fojt 			if (*pos != '\n') {
188*a1157835SDaniel Fojt 				pos++;
189*a1157835SDaniel Fojt 				continue;
190*a1157835SDaniel Fojt 			}
191*a1157835SDaniel Fojt 			pos++;
192*a1157835SDaniel Fojt 		}
193*a1157835SDaniel Fojt 		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
194*a1157835SDaniel Fojt 			pos++;
195*a1157835SDaniel Fojt 			continue;
196*a1157835SDaniel Fojt 		}
197*a1157835SDaniel Fojt 		pos += flen + 1;
198*a1157835SDaniel Fojt 		end = strchr(pos, '\n');
199*a1157835SDaniel Fojt 		if (end == NULL)
200*a1157835SDaniel Fojt 			return -1;
201*a1157835SDaniel Fojt 		*end++ = '\0';
202*a1157835SDaniel Fojt 		if (end - pos > (int) obuf_size)
203*a1157835SDaniel Fojt 			return -1;
204*a1157835SDaniel Fojt 		memcpy(obuf, pos, end - pos);
205*a1157835SDaniel Fojt 		return 0;
206*a1157835SDaniel Fojt 	}
207*a1157835SDaniel Fojt 
208*a1157835SDaniel Fojt 	return -1;
209*a1157835SDaniel Fojt }
210*a1157835SDaniel Fojt 
211*a1157835SDaniel Fojt 
wait_ip_addr(const char * ifname,int timeout)212*a1157835SDaniel Fojt int wait_ip_addr(const char *ifname, int timeout)
213*a1157835SDaniel Fojt {
214*a1157835SDaniel Fojt 	char ip[30];
215*a1157835SDaniel Fojt 	int count = timeout;
216*a1157835SDaniel Fojt 	struct wpa_ctrl *ctrl;
217*a1157835SDaniel Fojt 
218*a1157835SDaniel Fojt 	while (count > 0) {
219*a1157835SDaniel Fojt 		printf("%s: ifname='%s' - %d seconds remaining\n",
220*a1157835SDaniel Fojt 		       __func__, ifname, count);
221*a1157835SDaniel Fojt 		count--;
222*a1157835SDaniel Fojt 		if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
223*a1157835SDaniel Fojt 		    && strlen(ip) > 0) {
224*a1157835SDaniel Fojt 			printf("IP address found: '%s'\n", ip);
225*a1157835SDaniel Fojt 			if (strncmp(ip, "169.254.", 8) != 0)
226*a1157835SDaniel Fojt 				return 0;
227*a1157835SDaniel Fojt 		}
228*a1157835SDaniel Fojt 		ctrl = wpa_open_ctrl(ifname);
229*a1157835SDaniel Fojt 		if (ctrl == NULL)
230*a1157835SDaniel Fojt 			return -1;
231*a1157835SDaniel Fojt 		wpa_ctrl_close(ctrl);
232*a1157835SDaniel Fojt 		sleep(1);
233*a1157835SDaniel Fojt 	}
234*a1157835SDaniel Fojt 	printf("%s: Could not get IP address for ifname='%s'", __func__,
235*a1157835SDaniel Fojt 	       ifname);
236*a1157835SDaniel Fojt 	return -1;
237*a1157835SDaniel Fojt }
238*a1157835SDaniel Fojt 
239*a1157835SDaniel Fojt 
add_network(const char * ifname)240*a1157835SDaniel Fojt int add_network(const char *ifname)
241*a1157835SDaniel Fojt {
242*a1157835SDaniel Fojt 	char res[30];
243*a1157835SDaniel Fojt 
244*a1157835SDaniel Fojt 	if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
245*a1157835SDaniel Fojt 		return -1;
246*a1157835SDaniel Fojt 	return atoi(res);
247*a1157835SDaniel Fojt }
248*a1157835SDaniel Fojt 
249*a1157835SDaniel Fojt 
set_network(const char * ifname,int id,const char * field,const char * value)250*a1157835SDaniel Fojt int set_network(const char *ifname, int id, const char *field,
251*a1157835SDaniel Fojt 		const char *value)
252*a1157835SDaniel Fojt {
253*a1157835SDaniel Fojt 	char buf[200];
254*a1157835SDaniel Fojt 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
255*a1157835SDaniel Fojt 	return wpa_command(ifname, buf);
256*a1157835SDaniel Fojt }
257*a1157835SDaniel Fojt 
258*a1157835SDaniel Fojt 
set_network_quoted(const char * ifname,int id,const char * field,const char * value)259*a1157835SDaniel Fojt int set_network_quoted(const char *ifname, int id, const char *field,
260*a1157835SDaniel Fojt 		       const char *value)
261*a1157835SDaniel Fojt {
262*a1157835SDaniel Fojt 	char buf[200];
263*a1157835SDaniel Fojt 	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
264*a1157835SDaniel Fojt 		 id, field, value);
265*a1157835SDaniel Fojt 	return wpa_command(ifname, buf);
266*a1157835SDaniel Fojt }
267*a1157835SDaniel Fojt 
268*a1157835SDaniel Fojt 
add_cred(const char * ifname)269*a1157835SDaniel Fojt int add_cred(const char *ifname)
270*a1157835SDaniel Fojt {
271*a1157835SDaniel Fojt 	char res[30];
272*a1157835SDaniel Fojt 
273*a1157835SDaniel Fojt 	if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
274*a1157835SDaniel Fojt 		return -1;
275*a1157835SDaniel Fojt 	return atoi(res);
276*a1157835SDaniel Fojt }
277*a1157835SDaniel Fojt 
278*a1157835SDaniel Fojt 
set_cred(const char * ifname,int id,const char * field,const char * value)279*a1157835SDaniel Fojt int set_cred(const char *ifname, int id, const char *field, const char *value)
280*a1157835SDaniel Fojt {
281*a1157835SDaniel Fojt 	char buf[200];
282*a1157835SDaniel Fojt 	snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
283*a1157835SDaniel Fojt 	return wpa_command(ifname, buf);
284*a1157835SDaniel Fojt }
285*a1157835SDaniel Fojt 
286*a1157835SDaniel Fojt 
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)287*a1157835SDaniel Fojt int set_cred_quoted(const char *ifname, int id, const char *field,
288*a1157835SDaniel Fojt 		    const char *value)
289*a1157835SDaniel Fojt {
290*a1157835SDaniel Fojt 	char buf[200];
291*a1157835SDaniel Fojt 	snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
292*a1157835SDaniel Fojt 		 id, field, value);
293*a1157835SDaniel Fojt 	return wpa_command(ifname, buf);
294*a1157835SDaniel Fojt }
295