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