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  
18  char *wpas_ctrl_path = "/var/run/wpa_supplicant/";
19  static int default_timeout = 60;
20  
21  
wpa_open_ctrl(const char * ifname)22  static 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  
wpa_command(const char * ifname,const char * cmd)35  int 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  
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)61  int 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  
open_wpa_mon(const char * ifname)83  struct 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  
get_wpa_cli_event2(struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)99  int 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  
get_wpa_cli_event(struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)156  int 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  
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)163  int 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-NO_EVENTS", 16, buf, &len,
176  			     NULL) < 0) {
177  		wpa_ctrl_close(ctrl);
178  		return -1;
179  	}
180  	wpa_ctrl_close(ctrl);
181  	buf[len] = '\0';
182  
183  	flen = strlen(field);
184  	pos = buf;
185  	while (pos + flen < buf + len) {
186  		if (pos > buf) {
187  			if (*pos != '\n') {
188  				pos++;
189  				continue;
190  			}
191  			pos++;
192  		}
193  		if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
194  			pos++;
195  			continue;
196  		}
197  		pos += flen + 1;
198  		end = strchr(pos, '\n');
199  		if (end == NULL)
200  			return -1;
201  		*end++ = '\0';
202  		if (end - pos > (int) obuf_size)
203  			return -1;
204  		memcpy(obuf, pos, end - pos);
205  		return 0;
206  	}
207  
208  	return -1;
209  }
210  
211  
wait_ip_addr(const char * ifname,int timeout)212  int wait_ip_addr(const char *ifname, int timeout)
213  {
214  	char ip[30];
215  	int count = timeout;
216  	struct wpa_ctrl *ctrl;
217  
218  	while (count > 0) {
219  		printf("%s: ifname='%s' - %d seconds remaining\n",
220  		       __func__, ifname, count);
221  		count--;
222  		if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
223  		    && strlen(ip) > 0) {
224  			printf("IP address found: '%s'\n", ip);
225  			if (strncmp(ip, "169.254.", 8) != 0)
226  				return 0;
227  		}
228  		ctrl = wpa_open_ctrl(ifname);
229  		if (ctrl == NULL)
230  			return -1;
231  		wpa_ctrl_close(ctrl);
232  		sleep(1);
233  	}
234  	printf("%s: Could not get IP address for ifname='%s'", __func__,
235  	       ifname);
236  	return -1;
237  }
238  
239  
add_network(const char * ifname)240  int add_network(const char *ifname)
241  {
242  	char res[30];
243  
244  	if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
245  		return -1;
246  	return atoi(res);
247  }
248  
249  
set_network(const char * ifname,int id,const char * field,const char * value)250  int set_network(const char *ifname, int id, const char *field,
251  		const char *value)
252  {
253  	char buf[200];
254  	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
255  	return wpa_command(ifname, buf);
256  }
257  
258  
set_network_quoted(const char * ifname,int id,const char * field,const char * value)259  int set_network_quoted(const char *ifname, int id, const char *field,
260  		       const char *value)
261  {
262  	char buf[200];
263  	snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
264  		 id, field, value);
265  	return wpa_command(ifname, buf);
266  }
267  
268  
add_cred(const char * ifname)269  int add_cred(const char *ifname)
270  {
271  	char res[30];
272  
273  	if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
274  		return -1;
275  	return atoi(res);
276  }
277  
278  
set_cred(const char * ifname,int id,const char * field,const char * value)279  int set_cred(const char *ifname, int id, const char *field, const char *value)
280  {
281  	char buf[200];
282  	snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
283  	return wpa_command(ifname, buf);
284  }
285  
286  
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)287  int set_cred_quoted(const char *ifname, int id, const char *field,
288  		    const char *value)
289  {
290  	char buf[200];
291  	snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
292  		 id, field, value);
293  	return wpa_command(ifname, buf);
294  }
295