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