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