13c260e60Schristos /*
23c260e60Schristos * wpa_supplicant ctrl_iface helpers
33c260e60Schristos * Copyright (c) 2010-2011, Atheros Communications, Inc.
43c260e60Schristos * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
53c260e60Schristos *
63c260e60Schristos * This software may be distributed under the terms of the BSD license.
73c260e60Schristos * See README for more details.
83c260e60Schristos */
93c260e60Schristos
103c260e60Schristos #include "includes.h"
113c260e60Schristos #include <time.h>
123c260e60Schristos
133c260e60Schristos #include "common.h"
143c260e60Schristos #include "wpa_ctrl.h"
153c260e60Schristos #include "wpa_helpers.h"
163c260e60Schristos
173c260e60Schristos
183c260e60Schristos char *wpas_ctrl_path = "/var/run/wpa_supplicant/";
193c260e60Schristos static int default_timeout = 60;
203c260e60Schristos
213c260e60Schristos
wpa_open_ctrl(const char * ifname)223c260e60Schristos static struct wpa_ctrl * wpa_open_ctrl(const char *ifname)
233c260e60Schristos {
243c260e60Schristos char buf[128];
253c260e60Schristos struct wpa_ctrl *ctrl;
263c260e60Schristos
273c260e60Schristos os_snprintf(buf, sizeof(buf), "%s%s", wpas_ctrl_path, ifname);
283c260e60Schristos ctrl = wpa_ctrl_open(buf);
293c260e60Schristos if (ctrl == NULL)
303c260e60Schristos printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf);
313c260e60Schristos return ctrl;
323c260e60Schristos }
333c260e60Schristos
343c260e60Schristos
wpa_command(const char * ifname,const char * cmd)353c260e60Schristos int wpa_command(const char *ifname, const char *cmd)
363c260e60Schristos {
373c260e60Schristos struct wpa_ctrl *ctrl;
383c260e60Schristos char buf[128];
393c260e60Schristos size_t len;
403c260e60Schristos
413c260e60Schristos printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
423c260e60Schristos ctrl = wpa_open_ctrl(ifname);
433c260e60Schristos if (ctrl == NULL)
443c260e60Schristos return -1;
453c260e60Schristos len = sizeof(buf);
463c260e60Schristos if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) {
473c260e60Schristos printf("wpa_command: wpa_ctrl_request failed\n");
483c260e60Schristos wpa_ctrl_close(ctrl);
493c260e60Schristos return -1;
503c260e60Schristos }
513c260e60Schristos wpa_ctrl_close(ctrl);
523c260e60Schristos buf[len] = '\0';
533c260e60Schristos if (strncmp(buf, "FAIL", 4) == 0) {
543c260e60Schristos printf("wpa_command: Command failed (FAIL received)\n");
553c260e60Schristos return -1;
563c260e60Schristos }
573c260e60Schristos return 0;
583c260e60Schristos }
593c260e60Schristos
603c260e60Schristos
wpa_command_resp(const char * ifname,const char * cmd,char * resp,size_t resp_size)613c260e60Schristos int wpa_command_resp(const char *ifname, const char *cmd,
623c260e60Schristos char *resp, size_t resp_size)
633c260e60Schristos {
643c260e60Schristos struct wpa_ctrl *ctrl;
653c260e60Schristos size_t len;
663c260e60Schristos
673c260e60Schristos printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd);
683c260e60Schristos ctrl = wpa_open_ctrl(ifname);
693c260e60Schristos if (ctrl == NULL)
703c260e60Schristos return -1;
713c260e60Schristos len = resp_size;
723c260e60Schristos if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) {
733c260e60Schristos printf("wpa_command: wpa_ctrl_request failed\n");
743c260e60Schristos wpa_ctrl_close(ctrl);
753c260e60Schristos return -1;
763c260e60Schristos }
773c260e60Schristos wpa_ctrl_close(ctrl);
783c260e60Schristos resp[len] = '\0';
793c260e60Schristos return 0;
803c260e60Schristos }
813c260e60Schristos
823c260e60Schristos
open_wpa_mon(const char * ifname)833c260e60Schristos struct wpa_ctrl * open_wpa_mon(const char *ifname)
843c260e60Schristos {
853c260e60Schristos struct wpa_ctrl *ctrl;
863c260e60Schristos
873c260e60Schristos ctrl = wpa_open_ctrl(ifname);
883c260e60Schristos if (ctrl == NULL)
893c260e60Schristos return NULL;
903c260e60Schristos if (wpa_ctrl_attach(ctrl) < 0) {
913c260e60Schristos wpa_ctrl_close(ctrl);
923c260e60Schristos return NULL;
933c260e60Schristos }
943c260e60Schristos
953c260e60Schristos return ctrl;
963c260e60Schristos }
973c260e60Schristos
983c260e60Schristos
get_wpa_cli_event2(struct wpa_ctrl * mon,const char * event,const char * event2,char * buf,size_t buf_size)993c260e60Schristos int get_wpa_cli_event2(struct wpa_ctrl *mon,
1003c260e60Schristos const char *event, const char *event2,
1013c260e60Schristos char *buf, size_t buf_size)
1023c260e60Schristos {
1033c260e60Schristos int fd, ret;
1043c260e60Schristos fd_set rfd;
1053c260e60Schristos char *pos;
1063c260e60Schristos struct timeval tv;
1073c260e60Schristos time_t start, now;
1083c260e60Schristos
1093c260e60Schristos printf("Waiting for wpa_cli event %s\n", event);
1103c260e60Schristos fd = wpa_ctrl_get_fd(mon);
1113c260e60Schristos if (fd < 0)
1123c260e60Schristos return -1;
1133c260e60Schristos
1143c260e60Schristos time(&start);
1153c260e60Schristos while (1) {
1163c260e60Schristos size_t len;
1173c260e60Schristos
1183c260e60Schristos FD_ZERO(&rfd);
1193c260e60Schristos FD_SET(fd, &rfd);
1203c260e60Schristos tv.tv_sec = default_timeout;
1213c260e60Schristos tv.tv_usec = 0;
1223c260e60Schristos ret = select(fd + 1, &rfd, NULL, NULL, &tv);
1233c260e60Schristos if (ret == 0) {
1243c260e60Schristos printf("Timeout on waiting for event %s\n", event);
1253c260e60Schristos return -1;
1263c260e60Schristos }
1273c260e60Schristos if (ret < 0) {
1283c260e60Schristos printf("select: %s\n", strerror(errno));
1293c260e60Schristos return -1;
1303c260e60Schristos }
1313c260e60Schristos len = buf_size;
1323c260e60Schristos if (wpa_ctrl_recv(mon, buf, &len) < 0) {
1333c260e60Schristos printf("Failure while waiting for event %s\n", event);
1343c260e60Schristos return -1;
1353c260e60Schristos }
1363c260e60Schristos if (len == buf_size)
1373c260e60Schristos len--;
1383c260e60Schristos buf[len] = '\0';
1393c260e60Schristos
1403c260e60Schristos pos = strchr(buf, '>');
1413c260e60Schristos if (pos &&
1423c260e60Schristos (strncmp(pos + 1, event, strlen(event)) == 0 ||
1433c260e60Schristos (event2 &&
1443c260e60Schristos strncmp(pos + 1, event2, strlen(event2)) == 0)))
1453c260e60Schristos return 0; /* Event found */
1463c260e60Schristos
1473c260e60Schristos time(&now);
1483c260e60Schristos if ((int) (now - start) > default_timeout) {
1493c260e60Schristos printf("Timeout on waiting for event %s\n", event);
1503c260e60Schristos return -1;
1513c260e60Schristos }
1523c260e60Schristos }
1533c260e60Schristos }
1543c260e60Schristos
1553c260e60Schristos
get_wpa_cli_event(struct wpa_ctrl * mon,const char * event,char * buf,size_t buf_size)1563c260e60Schristos int get_wpa_cli_event(struct wpa_ctrl *mon,
1573c260e60Schristos const char *event, char *buf, size_t buf_size)
1583c260e60Schristos {
1593c260e60Schristos return get_wpa_cli_event2(mon, event, NULL, buf, buf_size);
1603c260e60Schristos }
1613c260e60Schristos
1623c260e60Schristos
get_wpa_status(const char * ifname,const char * field,char * obuf,size_t obuf_size)1633c260e60Schristos int get_wpa_status(const char *ifname, const char *field, char *obuf,
1643c260e60Schristos size_t obuf_size)
1653c260e60Schristos {
1663c260e60Schristos struct wpa_ctrl *ctrl;
1673c260e60Schristos char buf[4096];
1683c260e60Schristos char *pos, *end;
1693c260e60Schristos size_t len, flen;
1703c260e60Schristos
1713c260e60Schristos ctrl = wpa_open_ctrl(ifname);
1723c260e60Schristos if (ctrl == NULL)
1733c260e60Schristos return -1;
1743c260e60Schristos len = sizeof(buf);
17536ebd06eSchristos if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len,
17636ebd06eSchristos NULL) < 0) {
1773c260e60Schristos wpa_ctrl_close(ctrl);
1783c260e60Schristos return -1;
1793c260e60Schristos }
1803c260e60Schristos wpa_ctrl_close(ctrl);
1813c260e60Schristos buf[len] = '\0';
1823c260e60Schristos
1833c260e60Schristos flen = strlen(field);
1843c260e60Schristos pos = buf;
1853c260e60Schristos while (pos + flen < buf + len) {
1863c260e60Schristos if (pos > buf) {
1873c260e60Schristos if (*pos != '\n') {
1883c260e60Schristos pos++;
1893c260e60Schristos continue;
1903c260e60Schristos }
1913c260e60Schristos pos++;
1923c260e60Schristos }
1933c260e60Schristos if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') {
1943c260e60Schristos pos++;
1953c260e60Schristos continue;
1963c260e60Schristos }
1973c260e60Schristos pos += flen + 1;
1983c260e60Schristos end = strchr(pos, '\n');
1993c260e60Schristos if (end == NULL)
2003c260e60Schristos return -1;
2013c260e60Schristos *end++ = '\0';
2023c260e60Schristos if (end - pos > (int) obuf_size)
2033c260e60Schristos return -1;
2043c260e60Schristos memcpy(obuf, pos, end - pos);
2053c260e60Schristos return 0;
2063c260e60Schristos }
2073c260e60Schristos
2083c260e60Schristos return -1;
2093c260e60Schristos }
2103c260e60Schristos
2113c260e60Schristos
wait_ip_addr(const char * ifname,int timeout)2123c260e60Schristos int wait_ip_addr(const char *ifname, int timeout)
2133c260e60Schristos {
2143c260e60Schristos char ip[30];
2153c260e60Schristos int count = timeout;
2163c260e60Schristos struct wpa_ctrl *ctrl;
2173c260e60Schristos
2183c260e60Schristos while (count > 0) {
2193c260e60Schristos printf("%s: ifname='%s' - %d seconds remaining\n",
2203c260e60Schristos __func__, ifname, count);
2213c260e60Schristos count--;
2223c260e60Schristos if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0
2233c260e60Schristos && strlen(ip) > 0) {
2243c260e60Schristos printf("IP address found: '%s'\n", ip);
225*0a73ee0aSchristos if (strncmp(ip, "169.254.", 8) != 0)
2263c260e60Schristos return 0;
2273c260e60Schristos }
2283c260e60Schristos ctrl = wpa_open_ctrl(ifname);
2293c260e60Schristos if (ctrl == NULL)
2303c260e60Schristos return -1;
2313c260e60Schristos wpa_ctrl_close(ctrl);
2323c260e60Schristos sleep(1);
2333c260e60Schristos }
2343c260e60Schristos printf("%s: Could not get IP address for ifname='%s'", __func__,
2353c260e60Schristos ifname);
2363c260e60Schristos return -1;
2373c260e60Schristos }
2383c260e60Schristos
2393c260e60Schristos
add_network(const char * ifname)2403c260e60Schristos int add_network(const char *ifname)
2413c260e60Schristos {
2423c260e60Schristos char res[30];
2433c260e60Schristos
2443c260e60Schristos if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0)
2453c260e60Schristos return -1;
2463c260e60Schristos return atoi(res);
2473c260e60Schristos }
2483c260e60Schristos
2493c260e60Schristos
set_network(const char * ifname,int id,const char * field,const char * value)2503c260e60Schristos int set_network(const char *ifname, int id, const char *field,
2513c260e60Schristos const char *value)
2523c260e60Schristos {
2533c260e60Schristos char buf[200];
2543c260e60Schristos snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value);
2553c260e60Schristos return wpa_command(ifname, buf);
2563c260e60Schristos }
2573c260e60Schristos
2583c260e60Schristos
set_network_quoted(const char * ifname,int id,const char * field,const char * value)2593c260e60Schristos int set_network_quoted(const char *ifname, int id, const char *field,
2603c260e60Schristos const char *value)
2613c260e60Schristos {
2623c260e60Schristos char buf[200];
2633c260e60Schristos snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"",
2643c260e60Schristos id, field, value);
2653c260e60Schristos return wpa_command(ifname, buf);
2663c260e60Schristos }
2673c260e60Schristos
2683c260e60Schristos
add_cred(const char * ifname)2693c260e60Schristos int add_cred(const char *ifname)
2703c260e60Schristos {
2713c260e60Schristos char res[30];
2723c260e60Schristos
2733c260e60Schristos if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0)
2743c260e60Schristos return -1;
2753c260e60Schristos return atoi(res);
2763c260e60Schristos }
2773c260e60Schristos
2783c260e60Schristos
set_cred(const char * ifname,int id,const char * field,const char * value)2793c260e60Schristos int set_cred(const char *ifname, int id, const char *field, const char *value)
2803c260e60Schristos {
2813c260e60Schristos char buf[200];
2823c260e60Schristos snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value);
2833c260e60Schristos return wpa_command(ifname, buf);
2843c260e60Schristos }
2853c260e60Schristos
2863c260e60Schristos
set_cred_quoted(const char * ifname,int id,const char * field,const char * value)2873c260e60Schristos int set_cred_quoted(const char *ifname, int id, const char *field,
2883c260e60Schristos const char *value)
2893c260e60Schristos {
2903c260e60Schristos char buf[200];
2913c260e60Schristos snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"",
2923c260e60Schristos id, field, value);
2933c260e60Schristos return wpa_command(ifname, buf);
2943c260e60Schristos }
295