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