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