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 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 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 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 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 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 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 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 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 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 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 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 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 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 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