15b9c547cSRui Paulo /* 25b9c547cSRui Paulo * wpa_supplicant ctrl_iface helpers 35b9c547cSRui Paulo * Copyright (c) 2010-2011, Atheros Communications, Inc. 45b9c547cSRui Paulo * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. 55b9c547cSRui Paulo * 65b9c547cSRui Paulo * This software may be distributed under the terms of the BSD license. 75b9c547cSRui Paulo * See README for more details. 85b9c547cSRui Paulo */ 95b9c547cSRui Paulo 105b9c547cSRui Paulo #include "includes.h" 115b9c547cSRui Paulo #include <time.h> 125b9c547cSRui Paulo 135b9c547cSRui Paulo #include "common.h" 145b9c547cSRui Paulo #include "wpa_ctrl.h" 155b9c547cSRui Paulo #include "wpa_helpers.h" 165b9c547cSRui Paulo 175b9c547cSRui Paulo 185b9c547cSRui Paulo char *wpas_ctrl_path = "/var/run/wpa_supplicant/"; 195b9c547cSRui Paulo static int default_timeout = 60; 205b9c547cSRui Paulo 215b9c547cSRui Paulo 225b9c547cSRui Paulo static struct wpa_ctrl * wpa_open_ctrl(const char *ifname) 235b9c547cSRui Paulo { 245b9c547cSRui Paulo char buf[128]; 255b9c547cSRui Paulo struct wpa_ctrl *ctrl; 265b9c547cSRui Paulo 275b9c547cSRui Paulo os_snprintf(buf, sizeof(buf), "%s%s", wpas_ctrl_path, ifname); 285b9c547cSRui Paulo ctrl = wpa_ctrl_open(buf); 295b9c547cSRui Paulo if (ctrl == NULL) 305b9c547cSRui Paulo printf("wpa_command: wpa_ctrl_open(%s) failed\n", buf); 315b9c547cSRui Paulo return ctrl; 325b9c547cSRui Paulo } 335b9c547cSRui Paulo 345b9c547cSRui Paulo 355b9c547cSRui Paulo int wpa_command(const char *ifname, const char *cmd) 365b9c547cSRui Paulo { 375b9c547cSRui Paulo struct wpa_ctrl *ctrl; 385b9c547cSRui Paulo char buf[128]; 395b9c547cSRui Paulo size_t len; 405b9c547cSRui Paulo 415b9c547cSRui Paulo printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd); 425b9c547cSRui Paulo ctrl = wpa_open_ctrl(ifname); 435b9c547cSRui Paulo if (ctrl == NULL) 445b9c547cSRui Paulo return -1; 455b9c547cSRui Paulo len = sizeof(buf); 465b9c547cSRui Paulo if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL) < 0) { 475b9c547cSRui Paulo printf("wpa_command: wpa_ctrl_request failed\n"); 485b9c547cSRui Paulo wpa_ctrl_close(ctrl); 495b9c547cSRui Paulo return -1; 505b9c547cSRui Paulo } 515b9c547cSRui Paulo wpa_ctrl_close(ctrl); 525b9c547cSRui Paulo buf[len] = '\0'; 535b9c547cSRui Paulo if (strncmp(buf, "FAIL", 4) == 0) { 545b9c547cSRui Paulo printf("wpa_command: Command failed (FAIL received)\n"); 555b9c547cSRui Paulo return -1; 565b9c547cSRui Paulo } 575b9c547cSRui Paulo return 0; 585b9c547cSRui Paulo } 595b9c547cSRui Paulo 605b9c547cSRui Paulo 615b9c547cSRui Paulo int wpa_command_resp(const char *ifname, const char *cmd, 625b9c547cSRui Paulo char *resp, size_t resp_size) 635b9c547cSRui Paulo { 645b9c547cSRui Paulo struct wpa_ctrl *ctrl; 655b9c547cSRui Paulo size_t len; 665b9c547cSRui Paulo 675b9c547cSRui Paulo printf("wpa_command(ifname='%s', cmd='%s')\n", ifname, cmd); 685b9c547cSRui Paulo ctrl = wpa_open_ctrl(ifname); 695b9c547cSRui Paulo if (ctrl == NULL) 705b9c547cSRui Paulo return -1; 715b9c547cSRui Paulo len = resp_size; 725b9c547cSRui Paulo if (wpa_ctrl_request(ctrl, cmd, strlen(cmd), resp, &len, NULL) < 0) { 735b9c547cSRui Paulo printf("wpa_command: wpa_ctrl_request failed\n"); 745b9c547cSRui Paulo wpa_ctrl_close(ctrl); 755b9c547cSRui Paulo return -1; 765b9c547cSRui Paulo } 775b9c547cSRui Paulo wpa_ctrl_close(ctrl); 785b9c547cSRui Paulo resp[len] = '\0'; 795b9c547cSRui Paulo return 0; 805b9c547cSRui Paulo } 815b9c547cSRui Paulo 825b9c547cSRui Paulo 835b9c547cSRui Paulo struct wpa_ctrl * open_wpa_mon(const char *ifname) 845b9c547cSRui Paulo { 855b9c547cSRui Paulo struct wpa_ctrl *ctrl; 865b9c547cSRui Paulo 875b9c547cSRui Paulo ctrl = wpa_open_ctrl(ifname); 885b9c547cSRui Paulo if (ctrl == NULL) 895b9c547cSRui Paulo return NULL; 905b9c547cSRui Paulo if (wpa_ctrl_attach(ctrl) < 0) { 915b9c547cSRui Paulo wpa_ctrl_close(ctrl); 925b9c547cSRui Paulo return NULL; 935b9c547cSRui Paulo } 945b9c547cSRui Paulo 955b9c547cSRui Paulo return ctrl; 965b9c547cSRui Paulo } 975b9c547cSRui Paulo 985b9c547cSRui Paulo 995b9c547cSRui Paulo int get_wpa_cli_event2(struct wpa_ctrl *mon, 1005b9c547cSRui Paulo const char *event, const char *event2, 1015b9c547cSRui Paulo char *buf, size_t buf_size) 1025b9c547cSRui Paulo { 1035b9c547cSRui Paulo int fd, ret; 1045b9c547cSRui Paulo fd_set rfd; 1055b9c547cSRui Paulo char *pos; 1065b9c547cSRui Paulo struct timeval tv; 1075b9c547cSRui Paulo time_t start, now; 1085b9c547cSRui Paulo 1095b9c547cSRui Paulo printf("Waiting for wpa_cli event %s\n", event); 1105b9c547cSRui Paulo fd = wpa_ctrl_get_fd(mon); 1115b9c547cSRui Paulo if (fd < 0) 1125b9c547cSRui Paulo return -1; 1135b9c547cSRui Paulo 1145b9c547cSRui Paulo time(&start); 1155b9c547cSRui Paulo while (1) { 1165b9c547cSRui Paulo size_t len; 1175b9c547cSRui Paulo 1185b9c547cSRui Paulo FD_ZERO(&rfd); 1195b9c547cSRui Paulo FD_SET(fd, &rfd); 1205b9c547cSRui Paulo tv.tv_sec = default_timeout; 1215b9c547cSRui Paulo tv.tv_usec = 0; 1225b9c547cSRui Paulo ret = select(fd + 1, &rfd, NULL, NULL, &tv); 1235b9c547cSRui Paulo if (ret == 0) { 1245b9c547cSRui Paulo printf("Timeout on waiting for event %s\n", event); 1255b9c547cSRui Paulo return -1; 1265b9c547cSRui Paulo } 1275b9c547cSRui Paulo if (ret < 0) { 1285b9c547cSRui Paulo printf("select: %s\n", strerror(errno)); 1295b9c547cSRui Paulo return -1; 1305b9c547cSRui Paulo } 1315b9c547cSRui Paulo len = buf_size; 1325b9c547cSRui Paulo if (wpa_ctrl_recv(mon, buf, &len) < 0) { 1335b9c547cSRui Paulo printf("Failure while waiting for event %s\n", event); 1345b9c547cSRui Paulo return -1; 1355b9c547cSRui Paulo } 1365b9c547cSRui Paulo if (len == buf_size) 1375b9c547cSRui Paulo len--; 1385b9c547cSRui Paulo buf[len] = '\0'; 1395b9c547cSRui Paulo 1405b9c547cSRui Paulo pos = strchr(buf, '>'); 1415b9c547cSRui Paulo if (pos && 1425b9c547cSRui Paulo (strncmp(pos + 1, event, strlen(event)) == 0 || 1435b9c547cSRui Paulo (event2 && 1445b9c547cSRui Paulo strncmp(pos + 1, event2, strlen(event2)) == 0))) 1455b9c547cSRui Paulo return 0; /* Event found */ 1465b9c547cSRui Paulo 1475b9c547cSRui Paulo time(&now); 1485b9c547cSRui Paulo if ((int) (now - start) > default_timeout) { 1495b9c547cSRui Paulo printf("Timeout on waiting for event %s\n", event); 1505b9c547cSRui Paulo return -1; 1515b9c547cSRui Paulo } 1525b9c547cSRui Paulo } 1535b9c547cSRui Paulo } 1545b9c547cSRui Paulo 1555b9c547cSRui Paulo 1565b9c547cSRui Paulo int get_wpa_cli_event(struct wpa_ctrl *mon, 1575b9c547cSRui Paulo const char *event, char *buf, size_t buf_size) 1585b9c547cSRui Paulo { 1595b9c547cSRui Paulo return get_wpa_cli_event2(mon, event, NULL, buf, buf_size); 1605b9c547cSRui Paulo } 1615b9c547cSRui Paulo 1625b9c547cSRui Paulo 1635b9c547cSRui Paulo int get_wpa_status(const char *ifname, const char *field, char *obuf, 1645b9c547cSRui Paulo size_t obuf_size) 1655b9c547cSRui Paulo { 1665b9c547cSRui Paulo struct wpa_ctrl *ctrl; 1675b9c547cSRui Paulo char buf[4096]; 1685b9c547cSRui Paulo char *pos, *end; 1695b9c547cSRui Paulo size_t len, flen; 1705b9c547cSRui Paulo 1715b9c547cSRui Paulo ctrl = wpa_open_ctrl(ifname); 1725b9c547cSRui Paulo if (ctrl == NULL) 1735b9c547cSRui Paulo return -1; 1745b9c547cSRui Paulo len = sizeof(buf); 175*780fb4a2SCy Schubert if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len, 176*780fb4a2SCy Schubert NULL) < 0) { 1775b9c547cSRui Paulo wpa_ctrl_close(ctrl); 1785b9c547cSRui Paulo return -1; 1795b9c547cSRui Paulo } 1805b9c547cSRui Paulo wpa_ctrl_close(ctrl); 1815b9c547cSRui Paulo buf[len] = '\0'; 1825b9c547cSRui Paulo 1835b9c547cSRui Paulo flen = strlen(field); 1845b9c547cSRui Paulo pos = buf; 1855b9c547cSRui Paulo while (pos + flen < buf + len) { 1865b9c547cSRui Paulo if (pos > buf) { 1875b9c547cSRui Paulo if (*pos != '\n') { 1885b9c547cSRui Paulo pos++; 1895b9c547cSRui Paulo continue; 1905b9c547cSRui Paulo } 1915b9c547cSRui Paulo pos++; 1925b9c547cSRui Paulo } 1935b9c547cSRui Paulo if (strncmp(pos, field, flen) != 0 || pos[flen] != '=') { 1945b9c547cSRui Paulo pos++; 1955b9c547cSRui Paulo continue; 1965b9c547cSRui Paulo } 1975b9c547cSRui Paulo pos += flen + 1; 1985b9c547cSRui Paulo end = strchr(pos, '\n'); 1995b9c547cSRui Paulo if (end == NULL) 2005b9c547cSRui Paulo return -1; 2015b9c547cSRui Paulo *end++ = '\0'; 2025b9c547cSRui Paulo if (end - pos > (int) obuf_size) 2035b9c547cSRui Paulo return -1; 2045b9c547cSRui Paulo memcpy(obuf, pos, end - pos); 2055b9c547cSRui Paulo return 0; 2065b9c547cSRui Paulo } 2075b9c547cSRui Paulo 2085b9c547cSRui Paulo return -1; 2095b9c547cSRui Paulo } 2105b9c547cSRui Paulo 2115b9c547cSRui Paulo 2125b9c547cSRui Paulo int wait_ip_addr(const char *ifname, int timeout) 2135b9c547cSRui Paulo { 2145b9c547cSRui Paulo char ip[30]; 2155b9c547cSRui Paulo int count = timeout; 2165b9c547cSRui Paulo struct wpa_ctrl *ctrl; 2175b9c547cSRui Paulo 2185b9c547cSRui Paulo while (count > 0) { 2195b9c547cSRui Paulo printf("%s: ifname='%s' - %d seconds remaining\n", 2205b9c547cSRui Paulo __func__, ifname, count); 2215b9c547cSRui Paulo count--; 2225b9c547cSRui Paulo if (get_wpa_status(ifname, "ip_address", ip, sizeof(ip)) == 0 2235b9c547cSRui Paulo && strlen(ip) > 0) { 2245b9c547cSRui Paulo printf("IP address found: '%s'\n", ip); 2255b9c547cSRui Paulo return 0; 2265b9c547cSRui Paulo } 2275b9c547cSRui Paulo ctrl = wpa_open_ctrl(ifname); 2285b9c547cSRui Paulo if (ctrl == NULL) 2295b9c547cSRui Paulo return -1; 2305b9c547cSRui Paulo wpa_ctrl_close(ctrl); 2315b9c547cSRui Paulo sleep(1); 2325b9c547cSRui Paulo } 2335b9c547cSRui Paulo printf("%s: Could not get IP address for ifname='%s'", __func__, 2345b9c547cSRui Paulo ifname); 2355b9c547cSRui Paulo return -1; 2365b9c547cSRui Paulo } 2375b9c547cSRui Paulo 2385b9c547cSRui Paulo 2395b9c547cSRui Paulo int add_network(const char *ifname) 2405b9c547cSRui Paulo { 2415b9c547cSRui Paulo char res[30]; 2425b9c547cSRui Paulo 2435b9c547cSRui Paulo if (wpa_command_resp(ifname, "ADD_NETWORK", res, sizeof(res)) < 0) 2445b9c547cSRui Paulo return -1; 2455b9c547cSRui Paulo return atoi(res); 2465b9c547cSRui Paulo } 2475b9c547cSRui Paulo 2485b9c547cSRui Paulo 2495b9c547cSRui Paulo int set_network(const char *ifname, int id, const char *field, 2505b9c547cSRui Paulo const char *value) 2515b9c547cSRui Paulo { 2525b9c547cSRui Paulo char buf[200]; 2535b9c547cSRui Paulo snprintf(buf, sizeof(buf), "SET_NETWORK %d %s %s", id, field, value); 2545b9c547cSRui Paulo return wpa_command(ifname, buf); 2555b9c547cSRui Paulo } 2565b9c547cSRui Paulo 2575b9c547cSRui Paulo 2585b9c547cSRui Paulo int set_network_quoted(const char *ifname, int id, const char *field, 2595b9c547cSRui Paulo const char *value) 2605b9c547cSRui Paulo { 2615b9c547cSRui Paulo char buf[200]; 2625b9c547cSRui Paulo snprintf(buf, sizeof(buf), "SET_NETWORK %d %s \"%s\"", 2635b9c547cSRui Paulo id, field, value); 2645b9c547cSRui Paulo return wpa_command(ifname, buf); 2655b9c547cSRui Paulo } 2665b9c547cSRui Paulo 2675b9c547cSRui Paulo 2685b9c547cSRui Paulo int add_cred(const char *ifname) 2695b9c547cSRui Paulo { 2705b9c547cSRui Paulo char res[30]; 2715b9c547cSRui Paulo 2725b9c547cSRui Paulo if (wpa_command_resp(ifname, "ADD_CRED", res, sizeof(res)) < 0) 2735b9c547cSRui Paulo return -1; 2745b9c547cSRui Paulo return atoi(res); 2755b9c547cSRui Paulo } 2765b9c547cSRui Paulo 2775b9c547cSRui Paulo 2785b9c547cSRui Paulo int set_cred(const char *ifname, int id, const char *field, const char *value) 2795b9c547cSRui Paulo { 2805b9c547cSRui Paulo char buf[200]; 2815b9c547cSRui Paulo snprintf(buf, sizeof(buf), "SET_CRED %d %s %s", id, field, value); 2825b9c547cSRui Paulo return wpa_command(ifname, buf); 2835b9c547cSRui Paulo } 2845b9c547cSRui Paulo 2855b9c547cSRui Paulo 2865b9c547cSRui Paulo int set_cred_quoted(const char *ifname, int id, const char *field, 2875b9c547cSRui Paulo const char *value) 2885b9c547cSRui Paulo { 2895b9c547cSRui Paulo char buf[200]; 2905b9c547cSRui Paulo snprintf(buf, sizeof(buf), "SET_CRED %d %s \"%s\"", 2915b9c547cSRui Paulo id, field, value); 2925b9c547cSRui Paulo return wpa_command(ifname, buf); 2935b9c547cSRui Paulo } 294