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