1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2006, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "eloop.h" 19 #include "wpa.h" 20 #include "wpa_supplicant.h" 21 #include "config.h" 22 #include "eapol_sm.h" 23 #include "wpa_supplicant_i.h" 24 #include "ctrl_iface.h" 25 #include "l2_packet.h" 26 #include "preauth.h" 27 #include "pmksa_cache.h" 28 #include "wpa_ctrl.h" 29 #include "eap.h" 30 31 32 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 33 char *buf, int len); 34 35 36 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 37 char *cmd) 38 { 39 char *value; 40 int ret = 0; 41 42 value = os_strchr(cmd, ' '); 43 if (value == NULL) 44 return -1; 45 *value++ = '\0'; 46 47 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 48 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 49 eapol_sm_configure(wpa_s->eapol, 50 atoi(value), -1, -1, -1); 51 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 52 eapol_sm_configure(wpa_s->eapol, 53 -1, atoi(value), -1, -1); 54 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 55 eapol_sm_configure(wpa_s->eapol, 56 -1, -1, atoi(value), -1); 57 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 58 eapol_sm_configure(wpa_s->eapol, 59 -1, -1, -1, atoi(value)); 60 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 61 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 62 atoi(value))) 63 ret = -1; 64 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 65 0) { 66 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 67 atoi(value))) 68 ret = -1; 69 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 70 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 71 ret = -1; 72 } else 73 ret = -1; 74 75 return ret; 76 } 77 78 79 #ifdef IEEE8021X_EAPOL 80 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 81 char *addr) 82 { 83 u8 bssid[ETH_ALEN]; 84 85 if (hwaddr_aton(addr, bssid)) { 86 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 87 "'%s'", addr); 88 return -1; 89 } 90 91 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 92 rsn_preauth_deinit(wpa_s->wpa); 93 if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid)) 94 return -1; 95 96 return 0; 97 } 98 #endif /* IEEE8021X_EAPOL */ 99 100 101 #ifdef CONFIG_PEERKEY 102 /* MLME-STKSTART.request(peer) */ 103 static int wpa_supplicant_ctrl_iface_stkstart( 104 struct wpa_supplicant *wpa_s, char *addr) 105 { 106 u8 peer[ETH_ALEN]; 107 108 if (hwaddr_aton(addr, peer)) { 109 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 110 "address '%s'", peer); 111 return -1; 112 } 113 114 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 115 MAC2STR(peer)); 116 117 return wpa_sm_stkstart(wpa_s->wpa, peer); 118 } 119 #endif /* CONFIG_PEERKEY */ 120 121 122 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 123 char *rsp) 124 { 125 #ifdef IEEE8021X_EAPOL 126 char *pos, *id_pos; 127 int id; 128 struct wpa_ssid *ssid; 129 130 pos = os_strchr(rsp, '-'); 131 if (pos == NULL) 132 return -1; 133 *pos++ = '\0'; 134 id_pos = pos; 135 pos = os_strchr(pos, ':'); 136 if (pos == NULL) 137 return -1; 138 *pos++ = '\0'; 139 id = atoi(id_pos); 140 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 141 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 142 (u8 *) pos, os_strlen(pos)); 143 144 ssid = wpa_config_get_network(wpa_s->conf, id); 145 if (ssid == NULL) { 146 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 147 "to update", id); 148 return -1; 149 } 150 151 if (os_strcmp(rsp, "IDENTITY") == 0) { 152 os_free(ssid->identity); 153 ssid->identity = (u8 *) os_strdup(pos); 154 ssid->identity_len = os_strlen(pos); 155 ssid->pending_req_identity = 0; 156 if (ssid == wpa_s->current_ssid) 157 wpa_s->reassociate = 1; 158 } else if (os_strcmp(rsp, "PASSWORD") == 0) { 159 os_free(ssid->password); 160 ssid->password = (u8 *) os_strdup(pos); 161 ssid->password_len = os_strlen(pos); 162 ssid->pending_req_password = 0; 163 if (ssid == wpa_s->current_ssid) 164 wpa_s->reassociate = 1; 165 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { 166 os_free(ssid->new_password); 167 ssid->new_password = (u8 *) os_strdup(pos); 168 ssid->new_password_len = os_strlen(pos); 169 ssid->pending_req_new_password = 0; 170 if (ssid == wpa_s->current_ssid) 171 wpa_s->reassociate = 1; 172 } else if (os_strcmp(rsp, "PIN") == 0) { 173 os_free(ssid->pin); 174 ssid->pin = os_strdup(pos); 175 ssid->pending_req_pin = 0; 176 if (ssid == wpa_s->current_ssid) 177 wpa_s->reassociate = 1; 178 } else if (os_strcmp(rsp, "OTP") == 0) { 179 os_free(ssid->otp); 180 ssid->otp = (u8 *) os_strdup(pos); 181 ssid->otp_len = os_strlen(pos); 182 os_free(ssid->pending_req_otp); 183 ssid->pending_req_otp = NULL; 184 ssid->pending_req_otp_len = 0; 185 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { 186 os_free(ssid->private_key_passwd); 187 ssid->private_key_passwd = (u8 *) os_strdup(pos); 188 ssid->pending_req_passphrase = 0; 189 if (ssid == wpa_s->current_ssid) 190 wpa_s->reassociate = 1; 191 } else { 192 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); 193 return -1; 194 } 195 196 return 0; 197 #else /* IEEE8021X_EAPOL */ 198 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 199 return -1; 200 #endif /* IEEE8021X_EAPOL */ 201 } 202 203 204 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 205 const char *params, 206 char *buf, size_t buflen) 207 { 208 char *pos, *end, tmp[30]; 209 int res, verbose, ret; 210 211 verbose = os_strcmp(params, "-VERBOSE") == 0; 212 pos = buf; 213 end = buf + buflen; 214 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 215 struct wpa_ssid *ssid = wpa_s->current_ssid; 216 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 217 MAC2STR(wpa_s->bssid)); 218 if (ret < 0 || ret >= end - pos) 219 return pos - buf; 220 pos += ret; 221 if (ssid) { 222 u8 *_ssid = ssid->ssid; 223 size_t ssid_len = ssid->ssid_len; 224 u8 ssid_buf[MAX_SSID_LEN]; 225 if (ssid_len == 0) { 226 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 227 if (_res < 0) 228 ssid_len = 0; 229 else 230 ssid_len = _res; 231 _ssid = ssid_buf; 232 } 233 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 234 wpa_ssid_txt(_ssid, ssid_len), 235 ssid->id); 236 if (ret < 0 || ret >= end - pos) 237 return pos - buf; 238 pos += ret; 239 240 if (ssid->id_str) { 241 ret = os_snprintf(pos, end - pos, 242 "id_str=%s\n", 243 ssid->id_str); 244 if (ret < 0 || ret >= end - pos) 245 return pos - buf; 246 pos += ret; 247 } 248 } 249 250 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 251 } 252 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 253 wpa_supplicant_state_txt(wpa_s->wpa_state)); 254 if (ret < 0 || ret >= end - pos) 255 return pos - buf; 256 pos += ret; 257 258 if (wpa_s->l2 && 259 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 260 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 261 if (ret < 0 || ret >= end - pos) 262 return pos - buf; 263 pos += ret; 264 } 265 266 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || 267 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 268 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 269 verbose); 270 if (res >= 0) 271 pos += res; 272 } 273 274 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 275 if (res >= 0) 276 pos += res; 277 278 return pos - buf; 279 } 280 281 282 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 283 char *cmd) 284 { 285 char *pos; 286 int id; 287 struct wpa_ssid *ssid; 288 u8 bssid[ETH_ALEN]; 289 290 /* cmd: "<network id> <BSSID>" */ 291 pos = os_strchr(cmd, ' '); 292 if (pos == NULL) 293 return -1; 294 *pos++ = '\0'; 295 id = atoi(cmd); 296 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 297 if (hwaddr_aton(pos, bssid)) { 298 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 299 return -1; 300 } 301 302 ssid = wpa_config_get_network(wpa_s->conf, id); 303 if (ssid == NULL) { 304 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 305 "to update", id); 306 return -1; 307 } 308 309 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 310 ssid->bssid_set = 311 os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0; 312 313 314 return 0; 315 } 316 317 #ifdef ANDROID 318 static int wpa_supplicant_ctrl_iface_blacklist( 319 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 320 { 321 struct wpa_ssid *ssid; 322 u8 bssid[ETH_ALEN]; 323 struct wpa_blacklist *e; 324 char *pos, *end; 325 int ret; 326 327 /* cmd: "BLACKLIST [<BSSID>]" */ 328 if (*cmd == '\0') { 329 pos = buf; 330 end = buf + buflen; 331 332 e = wpa_s->blacklist; 333 while (e) { 334 ret = os_snprintf(pos, end-pos, 335 "%02x:%02x:%02x:%02x:%02x:%02x\n", 336 e->bssid[0], 337 e->bssid[1], 338 e->bssid[2], 339 e->bssid[3], 340 e->bssid[4], 341 e->bssid[5]); 342 if (ret < 0 || ret >= end - pos) 343 return pos - buf; 344 pos += ret; 345 e = e->next; 346 } 347 return pos - buf; 348 } 349 wpa_printf(MSG_DEBUG, "CTRL_IFACE: bssid='%s'", cmd); 350 351 ++cmd; 352 if (os_strncmp(cmd, "clear", 5) == 0) { 353 wpa_blacklist_clear(wpa_s); 354 return 0; 355 } 356 357 if (hwaddr_aton(cmd, bssid)) { 358 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd); 359 return -1; 360 } 361 362 /* 363 * Add the BSSID twice, so its count will be 2, causing it to be 364 * skipped when processing scan results. 365 */ 366 ret = wpa_blacklist_add(wpa_s, bssid); 367 if (ret != 0) 368 return ret; 369 return wpa_blacklist_add(wpa_s, bssid); 370 } 371 #endif 372 373 static int wpa_supplicant_ctrl_iface_list_networks( 374 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 375 { 376 char *pos, *end; 377 struct wpa_ssid *ssid; 378 int ret; 379 380 pos = buf; 381 end = buf + buflen; 382 ret = os_snprintf(pos, end - pos, 383 "network id / ssid / bssid / flags\n"); 384 if (ret < 0 || ret >= end - pos) 385 return pos - buf; 386 pos += ret; 387 388 ssid = wpa_s->conf->ssid; 389 while (ssid) { 390 ret = os_snprintf(pos, end - pos, "%d\t%s", 391 ssid->id, 392 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 393 if (ret < 0 || ret >= end - pos) 394 return pos - buf; 395 pos += ret; 396 if (ssid->bssid_set) { 397 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 398 MAC2STR(ssid->bssid)); 399 } else { 400 ret = os_snprintf(pos, end - pos, "\tany"); 401 } 402 if (ret < 0 || ret >= end - pos) 403 return pos - buf; 404 pos += ret; 405 ret = os_snprintf(pos, end - pos, "\t%s%s", 406 ssid == wpa_s->current_ssid ? 407 "[CURRENT]" : "", 408 ssid->disabled ? "[DISABLED]" : ""); 409 if (ret < 0 || ret >= end - pos) 410 return pos - buf; 411 pos += ret; 412 ret = os_snprintf(pos, end - pos, "\n"); 413 if (ret < 0 || ret >= end - pos) 414 return pos - buf; 415 pos += ret; 416 417 ssid = ssid->next; 418 } 419 420 return pos - buf; 421 } 422 423 424 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 425 { 426 int first = 1, ret; 427 ret = os_snprintf(pos, end - pos, "-"); 428 if (ret < 0 || ret >= end - pos) 429 return pos; 430 pos += ret; 431 if (cipher & WPA_CIPHER_NONE) { 432 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 433 if (ret < 0 || ret >= end - pos) 434 return pos; 435 pos += ret; 436 first = 0; 437 } 438 if (cipher & WPA_CIPHER_WEP40) { 439 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 440 if (ret < 0 || ret >= end - pos) 441 return pos; 442 pos += ret; 443 first = 0; 444 } 445 if (cipher & WPA_CIPHER_WEP104) { 446 ret = os_snprintf(pos, end - pos, "%sWEP104", 447 first ? "" : "+"); 448 if (ret < 0 || ret >= end - pos) 449 return pos; 450 pos += ret; 451 first = 0; 452 } 453 if (cipher & WPA_CIPHER_TKIP) { 454 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 455 if (ret < 0 || ret >= end - pos) 456 return pos; 457 pos += ret; 458 first = 0; 459 } 460 if (cipher & WPA_CIPHER_CCMP) { 461 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 462 if (ret < 0 || ret >= end - pos) 463 return pos; 464 pos += ret; 465 first = 0; 466 } 467 return pos; 468 } 469 470 471 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 472 const u8 *ie, size_t ie_len) 473 { 474 struct wpa_ie_data data; 475 int first, ret; 476 477 ret = os_snprintf(pos, end - pos, "[%s-", proto); 478 if (ret < 0 || ret >= end - pos) 479 return pos; 480 pos += ret; 481 482 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 483 ret = os_snprintf(pos, end - pos, "?]"); 484 if (ret < 0 || ret >= end - pos) 485 return pos; 486 pos += ret; 487 return pos; 488 } 489 490 first = 1; 491 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 492 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 493 if (ret < 0 || ret >= end - pos) 494 return pos; 495 pos += ret; 496 first = 0; 497 } 498 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 499 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 500 if (ret < 0 || ret >= end - pos) 501 return pos; 502 pos += ret; 503 first = 0; 504 } 505 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 506 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 507 if (ret < 0 || ret >= end - pos) 508 return pos; 509 pos += ret; 510 first = 0; 511 } 512 513 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 514 515 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 516 ret = os_snprintf(pos, end - pos, "-preauth"); 517 if (ret < 0 || ret >= end - pos) 518 return pos; 519 pos += ret; 520 } 521 522 ret = os_snprintf(pos, end - pos, "]"); 523 if (ret < 0 || ret >= end - pos) 524 return pos; 525 pos += ret; 526 527 return pos; 528 } 529 530 531 static int wpa_supplicant_ctrl_iface_scan_results( 532 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 533 { 534 char *pos, *end, *retpos; 535 struct wpa_scan_result *res; 536 int i, ret; 537 538 if (wpa_s->scan_results == NULL && 539 wpa_supplicant_get_scan_results(wpa_s) < 0) 540 return 0; 541 if (wpa_s->scan_results == NULL) 542 return 0; 543 544 pos = buf; 545 end = buf + buflen; 546 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 547 "flags / ssid\n"); 548 if (ret < 0 || ret >= end - pos) 549 return pos - buf; 550 pos += ret; 551 552 for (i = 0; i < wpa_s->num_scan_results; i++) { 553 retpos = pos; 554 res = &wpa_s->scan_results[i]; 555 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 556 MAC2STR(res->bssid), res->freq, res->level); 557 if (ret < 0 || ret >= end - pos) 558 return retpos - buf; 559 pos += ret; 560 if (res->wpa_ie_len) { 561 pos = wpa_supplicant_ie_txt(pos, end, "WPA", 562 res->wpa_ie, 563 res->wpa_ie_len); 564 } 565 if (res->rsn_ie_len) { 566 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", 567 res->rsn_ie, 568 res->rsn_ie_len); 569 } 570 if (!res->wpa_ie_len && !res->rsn_ie_len && 571 res->caps & IEEE80211_CAP_PRIVACY) { 572 ret = os_snprintf(pos, end - pos, "[WEP]"); 573 if (ret < 0 || ret >= end - pos) 574 return retpos - buf; 575 pos += ret; 576 } 577 if (res->caps & IEEE80211_CAP_IBSS) { 578 ret = os_snprintf(pos, end - pos, "[IBSS]"); 579 if (ret < 0 || ret >= end - pos) 580 return retpos - buf; 581 pos += ret; 582 } 583 if (!res->wpa_ie_len && !res->rsn_ie_len) { 584 ret = os_snprintf(pos, end - pos, "\t"); 585 if (ret < 0 || ret >= end - pos) 586 return retpos - buf; 587 pos += ret; 588 } 589 590 ret = os_snprintf(pos, end - pos, "\t%s", 591 wpa_ssid_txt(res->ssid, res->ssid_len)); 592 if (ret < 0 || ret >= end - pos) 593 return retpos - buf; 594 pos += ret; 595 596 ret = os_snprintf(pos, end - pos, "\n"); 597 if (ret < 0 || ret >= end - pos) 598 return retpos - buf; 599 pos += ret; 600 } 601 602 return pos - buf; 603 } 604 605 606 static int wpa_supplicant_ctrl_iface_select_network( 607 struct wpa_supplicant *wpa_s, char *cmd) 608 { 609 int id; 610 struct wpa_ssid *ssid; 611 612 /* cmd: "<network id>" or "any" */ 613 if (os_strcmp(cmd, "any") == 0) { 614 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 615 ssid = wpa_s->conf->ssid; 616 while (ssid) { 617 ssid->disabled = 0; 618 ssid = ssid->next; 619 } 620 wpa_s->reassociate = 1; 621 wpa_supplicant_req_scan(wpa_s, 0, 0); 622 return 0; 623 } 624 625 id = atoi(cmd); 626 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 627 628 ssid = wpa_config_get_network(wpa_s->conf, id); 629 if (ssid == NULL) { 630 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 631 "id=%d", id); 632 return -1; 633 } 634 635 if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) 636 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); 637 638 /* Mark all other networks disabled and trigger reassociation */ 639 ssid = wpa_s->conf->ssid; 640 while (ssid) { 641 ssid->disabled = id != ssid->id; 642 ssid = ssid->next; 643 } 644 wpa_s->reassociate = 1; 645 wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; 646 wpa_supplicant_req_scan(wpa_s, 0, 0); 647 648 return 0; 649 } 650 651 652 static int wpa_supplicant_ctrl_iface_enable_network( 653 struct wpa_supplicant *wpa_s, char *cmd) 654 { 655 int id; 656 struct wpa_ssid *ssid; 657 658 /* cmd: "<network id>" */ 659 id = atoi(cmd); 660 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 661 662 ssid = wpa_config_get_network(wpa_s->conf, id); 663 if (ssid == NULL) { 664 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 665 "id=%d", id); 666 return -1; 667 } 668 669 if (wpa_s->current_ssid == NULL && ssid->disabled) { 670 /* 671 * Try to reassociate since there is no current configuration 672 * and a new network was made available. */ 673 wpa_s->reassociate = 1; 674 #ifdef ANDROID 675 wpa_supplicant_req_scan(wpa_s, 2, 0); 676 #else 677 wpa_supplicant_req_scan(wpa_s, 0, 0); 678 #endif 679 } 680 ssid->disabled = 0; 681 682 return 0; 683 } 684 685 686 static int wpa_supplicant_ctrl_iface_disable_network( 687 struct wpa_supplicant *wpa_s, char *cmd) 688 { 689 int id; 690 struct wpa_ssid *ssid; 691 692 /* cmd: "<network id>" */ 693 id = atoi(cmd); 694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 695 696 ssid = wpa_config_get_network(wpa_s->conf, id); 697 if (ssid == NULL) { 698 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 699 "id=%d", id); 700 return -1; 701 } 702 703 if (ssid == wpa_s->current_ssid) 704 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); 705 ssid->disabled = 1; 706 707 return 0; 708 } 709 710 711 static int wpa_supplicant_ctrl_iface_add_network( 712 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 713 { 714 struct wpa_ssid *ssid; 715 int ret; 716 717 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 718 719 ssid = wpa_config_add_network(wpa_s->conf); 720 if (ssid == NULL) 721 return -1; 722 ssid->disabled = 1; 723 wpa_config_set_network_defaults(ssid); 724 725 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 726 if (ret < 0 || (size_t) ret >= buflen) 727 return -1; 728 return ret; 729 } 730 731 732 static int wpa_supplicant_ctrl_iface_remove_network( 733 struct wpa_supplicant *wpa_s, char *cmd) 734 { 735 int id; 736 struct wpa_ssid *ssid; 737 738 /* cmd: "<network id>" */ 739 id = atoi(cmd); 740 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 741 742 ssid = wpa_config_get_network(wpa_s->conf, id); 743 if (ssid == NULL || 744 wpa_config_remove_network(wpa_s->conf, id) < 0) { 745 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 746 "id=%d", id); 747 return -1; 748 } 749 750 if (ssid == wpa_s->current_ssid) { 751 /* 752 * Invalidate the EAP session cache if the current network is 753 * removed. 754 */ 755 eapol_sm_invalidate_cached_session(wpa_s->eapol); 756 757 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); 758 } 759 760 return 0; 761 } 762 763 764 static int wpa_supplicant_ctrl_iface_set_network( 765 struct wpa_supplicant *wpa_s, char *cmd) 766 { 767 int id; 768 struct wpa_ssid *ssid; 769 char *name, *value; 770 771 /* cmd: "<network id> <variable name> <value>" */ 772 name = os_strchr(cmd, ' '); 773 if (name == NULL) 774 return -1; 775 *name++ = '\0'; 776 777 value = os_strchr(name, ' '); 778 if (value == NULL) 779 return -1; 780 *value++ = '\0'; 781 782 id = atoi(cmd); 783 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 784 id, name); 785 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 786 (u8 *) value, os_strlen(value)); 787 788 ssid = wpa_config_get_network(wpa_s->conf, id); 789 if (ssid == NULL) { 790 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 791 "id=%d", id); 792 return -1; 793 } 794 795 if (wpa_config_set(ssid, name, value, 0) < 0) { 796 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 797 "variable '%s'", name); 798 return -1; 799 } else { 800 if (os_strcmp(name, "priority") == 0) { 801 wpa_config_update_prio_list(wpa_s->conf); 802 } 803 } 804 805 if (wpa_s->current_ssid == ssid) { 806 /* 807 * Invalidate the EAP session cache if anything in the current 808 * configuration changes. 809 */ 810 eapol_sm_invalidate_cached_session(wpa_s->eapol); 811 } 812 813 if ((os_strcmp(name, "psk") == 0 && 814 value[0] == '"' && ssid->ssid_len) || 815 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 816 wpa_config_update_psk(ssid); 817 818 return 0; 819 } 820 821 822 static int wpa_supplicant_ctrl_iface_get_network( 823 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 824 { 825 int id; 826 struct wpa_ssid *ssid; 827 char *name, *value; 828 829 /* cmd: "<network id> <variable name>" */ 830 name = os_strchr(cmd, ' '); 831 if (name == NULL || buflen == 0) 832 return -1; 833 *name++ = '\0'; 834 835 id = atoi(cmd); 836 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 837 id, name); 838 839 ssid = wpa_config_get_network(wpa_s->conf, id); 840 if (ssid == NULL) { 841 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 842 "id=%d", id); 843 return -1; 844 } 845 846 value = wpa_config_get_no_key(ssid, name); 847 if (value == NULL) { 848 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 849 "variable '%s'", name); 850 return -1; 851 } 852 853 os_snprintf(buf, buflen, "%s", value); 854 buf[buflen - 1] = '\0'; 855 856 os_free(value); 857 858 return os_strlen(buf); 859 } 860 861 862 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 863 { 864 int ret; 865 866 if (!wpa_s->conf->update_config) { 867 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 868 "to update configuration (update_config=0)"); 869 return -1; 870 } 871 872 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 873 if (ret) { 874 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 875 "update configuration"); 876 } else { 877 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 878 " updated"); 879 } 880 881 return ret; 882 } 883 884 885 static int wpa_supplicant_ctrl_iface_get_capability( 886 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 887 size_t buflen) 888 { 889 struct wpa_driver_capa capa; 890 int res, first = 1, ret; 891 char *pos, *end, *strict; 892 char field[30]; 893 894 /* Determine whether or not strict checking was requested */ 895 os_snprintf(field, sizeof(field), "%s", _field); 896 field[sizeof(field) - 1] = '\0'; 897 strict = os_strchr(field, ' '); 898 if (strict != NULL) { 899 *strict++ = '\0'; 900 if (os_strcmp(strict, "strict") != 0) 901 return -1; 902 } 903 904 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 905 field, strict ? strict : ""); 906 907 if (os_strcmp(field, "eap") == 0) { 908 return eap_get_names(buf, buflen); 909 } 910 911 res = wpa_drv_get_capa(wpa_s, &capa); 912 913 pos = buf; 914 end = pos + buflen; 915 916 if (os_strcmp(field, "pairwise") == 0) { 917 if (res < 0) { 918 if (strict) 919 return 0; 920 ret = os_snprintf(buf, buflen, "CCMP TKIP NONE"); 921 if (ret < 0 || (size_t) ret >= buflen) 922 return -1; 923 return ret; 924 } 925 926 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 927 ret = os_snprintf(pos, end - pos, "%sCCMP", 928 first ? "" : " "); 929 if (ret < 0 || ret >= end - pos) 930 return pos - buf; 931 pos += ret; 932 first = 0; 933 } 934 935 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 936 ret = os_snprintf(pos, end - pos, "%sTKIP", 937 first ? "" : " "); 938 if (ret < 0 || ret >= end - pos) 939 return pos - buf; 940 pos += ret; 941 first = 0; 942 } 943 944 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 945 ret = os_snprintf(pos, end - pos, "%sNONE", 946 first ? "" : " "); 947 if (ret < 0 || ret >= end - pos) 948 return pos - buf; 949 pos += ret; 950 first = 0; 951 } 952 953 return pos - buf; 954 } 955 956 if (os_strcmp(field, "group") == 0) { 957 if (res < 0) { 958 if (strict) 959 return 0; 960 ret = os_snprintf(buf, buflen, 961 "CCMP TKIP WEP104 WEP40"); 962 if (ret < 0 || (size_t) ret >= buflen) 963 return -1; 964 return ret; 965 } 966 967 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 968 ret = os_snprintf(pos, end - pos, "%sCCMP", 969 first ? "" : " "); 970 if (ret < 0 || ret >= end - pos) 971 return pos - buf; 972 pos += ret; 973 first = 0; 974 } 975 976 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 977 ret = os_snprintf(pos, end - pos, "%sTKIP", 978 first ? "" : " "); 979 if (ret < 0 || ret >= end - pos) 980 return pos - buf; 981 pos += ret; 982 first = 0; 983 } 984 985 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 986 ret = os_snprintf(pos, end - pos, "%sWEP104", 987 first ? "" : " "); 988 if (ret < 0 || ret >= end - pos) 989 return pos - buf; 990 pos += ret; 991 first = 0; 992 } 993 994 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 995 ret = os_snprintf(pos, end - pos, "%sWEP40", 996 first ? "" : " "); 997 if (ret < 0 || ret >= end - pos) 998 return pos - buf; 999 pos += ret; 1000 first = 0; 1001 } 1002 1003 return pos - buf; 1004 } 1005 1006 if (os_strcmp(field, "key_mgmt") == 0) { 1007 if (res < 0) { 1008 if (strict) 1009 return 0; 1010 ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP " 1011 "IEEE8021X WPA-NONE NONE"); 1012 if (ret < 0 || (size_t) ret >= buflen) 1013 return -1; 1014 return ret; 1015 } 1016 1017 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 1018 if (ret < 0 || ret >= end - pos) 1019 return pos - buf; 1020 pos += ret; 1021 1022 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1023 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 1024 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 1025 if (ret < 0 || ret >= end - pos) 1026 return pos - buf; 1027 pos += ret; 1028 } 1029 1030 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1031 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1032 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 1033 if (ret < 0 || ret >= end - pos) 1034 return pos - buf; 1035 pos += ret; 1036 } 1037 1038 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1039 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 1040 if (ret < 0 || ret >= end - pos) 1041 return pos - buf; 1042 pos += ret; 1043 } 1044 1045 return pos - buf; 1046 } 1047 1048 if (os_strcmp(field, "proto") == 0) { 1049 if (res < 0) { 1050 if (strict) 1051 return 0; 1052 ret = os_snprintf(buf, buflen, "RSN WPA"); 1053 if (ret < 0 || (size_t) ret >= buflen) 1054 return -1; 1055 return ret; 1056 } 1057 1058 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1059 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1060 ret = os_snprintf(pos, end - pos, "%sRSN", 1061 first ? "" : " "); 1062 if (ret < 0 || ret >= end - pos) 1063 return pos - buf; 1064 pos += ret; 1065 first = 0; 1066 } 1067 1068 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1069 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 1070 ret = os_snprintf(pos, end - pos, "%sWPA", 1071 first ? "" : " "); 1072 if (ret < 0 || ret >= end - pos) 1073 return pos - buf; 1074 pos += ret; 1075 first = 0; 1076 } 1077 1078 return pos - buf; 1079 } 1080 1081 if (os_strcmp(field, "auth_alg") == 0) { 1082 if (res < 0) { 1083 if (strict) 1084 return 0; 1085 ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP"); 1086 if (ret < 0 || (size_t) ret >= buflen) 1087 return -1; 1088 return ret; 1089 } 1090 1091 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 1092 ret = os_snprintf(pos, end - pos, "%sOPEN", 1093 first ? "" : " "); 1094 if (ret < 0 || ret >= end - pos) 1095 return pos - buf; 1096 pos += ret; 1097 first = 0; 1098 } 1099 1100 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 1101 ret = os_snprintf(pos, end - pos, "%sSHARED", 1102 first ? "" : " "); 1103 if (ret < 0 || ret >= end - pos) 1104 return pos - buf; 1105 pos += ret; 1106 first = 0; 1107 } 1108 1109 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 1110 ret = os_snprintf(pos, end - pos, "%sLEAP", 1111 first ? "" : " "); 1112 if (ret < 0 || ret >= end - pos) 1113 return pos - buf; 1114 pos += ret; 1115 first = 0; 1116 } 1117 1118 return pos - buf; 1119 } 1120 1121 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 1122 field); 1123 1124 return -1; 1125 } 1126 1127 1128 static int wpa_supplicant_ctrl_iface_ap_scan( 1129 struct wpa_supplicant *wpa_s, char *cmd) 1130 { 1131 int ap_scan = atoi(cmd); 1132 1133 if (ap_scan < 0 || ap_scan > 2) 1134 return -1; 1135 #ifdef ANDROID 1136 if ((ap_scan == 2) && (wpa_s->wpa_state != WPA_COMPLETED)) { 1137 return 0; 1138 } 1139 #endif 1140 wpa_s->conf->ap_scan = ap_scan; 1141 return 0; 1142 } 1143 1144 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, 1145 char *cmd, char *buf, size_t buflen) 1146 { 1147 int ret; 1148 1149 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 1150 if( ret == 0 ) { 1151 ret = sprintf(buf, "%s\n", "OK"); 1152 } 1153 return( ret ); 1154 } 1155 1156 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 1157 char *buf, size_t *resp_len) 1158 { 1159 char *reply; 1160 const int reply_size = 4096; 1161 int ctrl_rsp = 0; 1162 int reply_len; 1163 1164 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 1165 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1166 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 1167 (const u8 *) buf, os_strlen(buf)); 1168 } else { 1169 if (os_strcmp(buf, "PING") != 0) 1170 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", 1171 (const u8 *) buf, os_strlen(buf)); 1172 } 1173 1174 reply = os_malloc(reply_size); 1175 if (reply == NULL) { 1176 *resp_len = 1; 1177 return NULL; 1178 } 1179 1180 os_memcpy(reply, "OK\n", 3); 1181 reply_len = 3; 1182 1183 if (os_strcmp(buf, "PING") == 0) { 1184 os_memcpy(reply, "PONG\n", 5); 1185 reply_len = 5; 1186 } else if (os_strcmp(buf, "MIB") == 0) { 1187 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 1188 if (reply_len >= 0) { 1189 int res; 1190 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 1191 reply_size - reply_len); 1192 if (res < 0) 1193 reply_len = -1; 1194 else 1195 reply_len += res; 1196 } 1197 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 1198 reply_len = wpa_supplicant_ctrl_iface_status( 1199 wpa_s, buf + 6, reply, reply_size); 1200 } else if (os_strcmp(buf, "PMKSA") == 0) { 1201 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size); 1202 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1203 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 1204 reply_len = -1; 1205 } else if (os_strcmp(buf, "LOGON") == 0) { 1206 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 1207 } else if (os_strcmp(buf, "LOGOFF") == 0) { 1208 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 1209 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 1210 wpa_s->disconnected = 0; 1211 wpa_s->reassociate = 1; 1212 wpa_supplicant_req_scan(wpa_s, 0, 0); 1213 } else if (os_strcmp(buf, "RECONNECT") == 0) { 1214 if (wpa_s->disconnected) { 1215 wpa_s->disconnected = 0; 1216 wpa_s->reassociate = 1; 1217 wpa_supplicant_req_scan(wpa_s, 0, 0); 1218 } 1219 #ifdef IEEE8021X_EAPOL 1220 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 1221 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 1222 reply_len = -1; 1223 #endif /* IEEE8021X_EAPOL */ 1224 #ifdef CONFIG_PEERKEY 1225 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 1226 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 1227 reply_len = -1; 1228 #endif /* CONFIG_PEERKEY */ 1229 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 1230 { 1231 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 1232 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 1233 reply_len = -1; 1234 else 1235 ctrl_rsp = 1; 1236 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 1237 if (wpa_supplicant_reload_configuration(wpa_s)) 1238 reply_len = -1; 1239 } else if (os_strcmp(buf, "TERMINATE") == 0) { 1240 eloop_terminate(); 1241 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 1242 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 1243 reply_len = -1; 1244 #ifdef ANDROID 1245 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 1246 reply_len = wpa_supplicant_ctrl_iface_blacklist( 1247 wpa_s, buf + 9, reply, reply_size); 1248 if (os_strlen(buf) > 10 && reply_len == 0) { 1249 struct wpa_blacklist *bl = wpa_s->blacklist; 1250 if (os_strncmp(buf+10, "clear", 5) == 0 || 1251 (bl != NULL && os_memcmp(bl->bssid, wpa_s->bssid, ETH_ALEN) == 0)) { 1252 wpa_s->disconnected = 0; 1253 wpa_s->reassociate = 1; 1254 wpa_supplicant_req_scan(wpa_s, 0, 0); 1255 } 1256 } 1257 #endif 1258 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 1259 reply_len = wpa_supplicant_ctrl_iface_list_networks( 1260 wpa_s, reply, reply_size); 1261 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 1262 wpa_s->reassociate = 0; 1263 wpa_s->disconnected = 1; 1264 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); 1265 } else if (os_strcmp(buf, "SCAN") == 0) { 1266 #ifdef ANDROID 1267 if (!wpa_s->scan_ongoing && ((wpa_s->wpa_state <= WPA_SCANNING) || 1268 (wpa_s->wpa_state >= WPA_COMPLETED))) { 1269 #endif 1270 wpa_s->scan_req = 2; 1271 wpa_supplicant_req_scan(wpa_s, 0, 0); 1272 #ifdef ANDROID 1273 } else { 1274 wpa_printf(MSG_DEBUG, "Ongoing Scan action..."); 1275 } 1276 #endif 1277 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 1278 reply_len = wpa_supplicant_ctrl_iface_scan_results( 1279 wpa_s, reply, reply_size); 1280 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 1281 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 1282 reply_len = -1; 1283 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 1284 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 1285 reply_len = -1; 1286 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 1287 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 1288 reply_len = -1; 1289 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 1290 reply_len = wpa_supplicant_ctrl_iface_add_network( 1291 wpa_s, reply, reply_size); 1292 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 1293 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 1294 reply_len = -1; 1295 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1296 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 1297 reply_len = -1; 1298 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 1299 reply_len = wpa_supplicant_ctrl_iface_get_network( 1300 wpa_s, buf + 12, reply, reply_size); 1301 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 1302 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 1303 reply_len = -1; 1304 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 1305 reply_len = wpa_supplicant_ctrl_iface_get_capability( 1306 wpa_s, buf + 15, reply, reply_size); 1307 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 1308 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 1309 reply_len = -1; 1310 } else if (os_strcmp(buf, "INTERFACES") == 0) { 1311 reply_len = wpa_supplicant_global_iface_interfaces( 1312 wpa_s->global, reply, reply_size); 1313 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 1314 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size); 1315 } else { 1316 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1317 reply_len = 16; 1318 } 1319 1320 if (reply_len < 0) { 1321 os_memcpy(reply, "FAIL\n", 5); 1322 reply_len = 5; 1323 } 1324 1325 if (ctrl_rsp) 1326 eapol_sm_notify_ctrl_response(wpa_s->eapol); 1327 1328 *resp_len = reply_len; 1329 return reply; 1330 } 1331 1332 1333 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 1334 char *cmd) 1335 { 1336 struct wpa_interface iface; 1337 char *pos; 1338 1339 /* 1340 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 1341 * TAB<bridge_ifname> 1342 */ 1343 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 1344 1345 os_memset(&iface, 0, sizeof(iface)); 1346 1347 do { 1348 iface.ifname = pos = cmd; 1349 pos = os_strchr(pos, '\t'); 1350 if (pos) 1351 *pos++ = '\0'; 1352 if (iface.ifname[0] == '\0') 1353 return -1; 1354 if (pos == NULL) 1355 break; 1356 1357 iface.confname = pos; 1358 pos = os_strchr(pos, '\t'); 1359 if (pos) 1360 *pos++ = '\0'; 1361 if (iface.confname[0] == '\0') 1362 iface.confname = NULL; 1363 if (pos == NULL) 1364 break; 1365 1366 iface.driver = pos; 1367 pos = os_strchr(pos, '\t'); 1368 if (pos) 1369 *pos++ = '\0'; 1370 if (iface.driver[0] == '\0') 1371 iface.driver = NULL; 1372 if (pos == NULL) 1373 break; 1374 1375 iface.ctrl_interface = pos; 1376 pos = os_strchr(pos, '\t'); 1377 if (pos) 1378 *pos++ = '\0'; 1379 if (iface.ctrl_interface[0] == '\0') 1380 iface.ctrl_interface = NULL; 1381 if (pos == NULL) 1382 break; 1383 1384 iface.driver_param = pos; 1385 pos = os_strchr(pos, '\t'); 1386 if (pos) 1387 *pos++ = '\0'; 1388 if (iface.driver_param[0] == '\0') 1389 iface.driver_param = NULL; 1390 if (pos == NULL) 1391 break; 1392 1393 iface.bridge_ifname = pos; 1394 pos = os_strchr(pos, '\t'); 1395 if (pos) 1396 *pos++ = '\0'; 1397 if (iface.bridge_ifname[0] == '\0') 1398 iface.bridge_ifname = NULL; 1399 if (pos == NULL) 1400 break; 1401 } while (0); 1402 1403 if (wpa_supplicant_get_iface(global, iface.ifname)) 1404 return -1; 1405 1406 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 1407 } 1408 1409 1410 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 1411 char *cmd) 1412 { 1413 struct wpa_supplicant *wpa_s; 1414 1415 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 1416 1417 wpa_s = wpa_supplicant_get_iface(global, cmd); 1418 if (wpa_s == NULL) 1419 return -1; 1420 return wpa_supplicant_remove_iface(global, wpa_s); 1421 } 1422 1423 1424 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 1425 char *buf, int len) 1426 { 1427 int res; 1428 char *pos, *end; 1429 struct wpa_supplicant *wpa_s; 1430 1431 wpa_s = global->ifaces; 1432 pos = buf; 1433 end = buf + len; 1434 1435 while (wpa_s) { 1436 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 1437 if (res < 0 || res >= end - pos) { 1438 *pos = '\0'; 1439 break; 1440 } 1441 pos += res; 1442 wpa_s = wpa_s->next; 1443 } 1444 return pos - buf; 1445 } 1446 1447 1448 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 1449 char *buf, size_t *resp_len) 1450 { 1451 char *reply; 1452 const int reply_size = 4096; 1453 int reply_len; 1454 1455 if (os_strcmp(buf, "PING") != 0) 1456 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", 1457 (const u8 *) buf, os_strlen(buf)); 1458 1459 reply = os_malloc(reply_size); 1460 if (reply == NULL) { 1461 *resp_len = 1; 1462 return NULL; 1463 } 1464 1465 os_memcpy(reply, "OK\n", 3); 1466 reply_len = 3; 1467 1468 if (os_strcmp(buf, "PING") == 0) { 1469 os_memcpy(reply, "PONG\n", 5); 1470 reply_len = 5; 1471 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 1472 if (wpa_supplicant_global_iface_add(global, buf + 14)) 1473 reply_len = -1; 1474 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 1475 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 1476 reply_len = -1; 1477 } else if (os_strcmp(buf, "INTERFACES") == 0) { 1478 reply_len = wpa_supplicant_global_iface_interfaces( 1479 global, reply, reply_size); 1480 } else if (os_strcmp(buf, "TERMINATE") == 0) { 1481 eloop_terminate(); 1482 } else { 1483 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1484 reply_len = 16; 1485 } 1486 1487 if (reply_len < 0) { 1488 os_memcpy(reply, "FAIL\n", 5); 1489 reply_len = 5; 1490 } 1491 1492 *resp_len = reply_len; 1493 return reply; 1494 } 1495