1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2008, 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 "config.h" 21 #include "eapol_supp/eapol_supp_sm.h" 22 #include "wpa_supplicant_i.h" 23 #include "blacklist.h" 24 #include "ctrl_iface.h" 25 #include "l2_packet/l2_packet.h" 26 #include "preauth.h" 27 #include "pmksa_cache.h" 28 #include "wpa_ctrl.h" 29 #include "eap_peer/eap.h" 30 #include "ieee802_11_defs.h" 31 #include "wps_supplicant.h" 32 #include "wps/wps.h" 33 34 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 35 char *buf, int len); 36 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 37 char *buf, int len); 38 39 40 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 41 char *cmd) 42 { 43 char *value; 44 int ret = 0; 45 46 value = os_strchr(cmd, ' '); 47 if (value == NULL) 48 return -1; 49 *value++ = '\0'; 50 51 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 52 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 53 eapol_sm_configure(wpa_s->eapol, 54 atoi(value), -1, -1, -1); 55 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 56 eapol_sm_configure(wpa_s->eapol, 57 -1, atoi(value), -1, -1); 58 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 59 eapol_sm_configure(wpa_s->eapol, 60 -1, -1, atoi(value), -1); 61 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 62 eapol_sm_configure(wpa_s->eapol, 63 -1, -1, -1, atoi(value)); 64 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 65 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 66 atoi(value))) 67 ret = -1; 68 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 69 0) { 70 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 71 atoi(value))) 72 ret = -1; 73 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 74 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 75 ret = -1; 76 } else 77 ret = -1; 78 79 return ret; 80 } 81 82 83 #ifdef IEEE8021X_EAPOL 84 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 85 char *addr) 86 { 87 u8 bssid[ETH_ALEN]; 88 struct wpa_ssid *ssid = wpa_s->current_ssid; 89 90 if (hwaddr_aton(addr, bssid)) { 91 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 92 "'%s'", addr); 93 return -1; 94 } 95 96 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 97 rsn_preauth_deinit(wpa_s->wpa); 98 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 99 return -1; 100 101 return 0; 102 } 103 #endif /* IEEE8021X_EAPOL */ 104 105 106 #ifdef CONFIG_PEERKEY 107 /* MLME-STKSTART.request(peer) */ 108 static int wpa_supplicant_ctrl_iface_stkstart( 109 struct wpa_supplicant *wpa_s, char *addr) 110 { 111 u8 peer[ETH_ALEN]; 112 113 if (hwaddr_aton(addr, peer)) { 114 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 115 "address '%s'", peer); 116 return -1; 117 } 118 119 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 120 MAC2STR(peer)); 121 122 return wpa_sm_stkstart(wpa_s->wpa, peer); 123 } 124 #endif /* CONFIG_PEERKEY */ 125 126 127 #ifdef CONFIG_IEEE80211R 128 static int wpa_supplicant_ctrl_iface_ft_ds( 129 struct wpa_supplicant *wpa_s, char *addr) 130 { 131 u8 target_ap[ETH_ALEN]; 132 133 if (hwaddr_aton(addr, target_ap)) { 134 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 135 "address '%s'", target_ap); 136 return -1; 137 } 138 139 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 140 141 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap); 142 } 143 #endif /* CONFIG_IEEE80211R */ 144 145 146 #ifdef CONFIG_WPS 147 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 148 char *cmd) 149 { 150 u8 bssid[ETH_ALEN]; 151 152 if (cmd == NULL || os_strcmp(cmd, "any") == 0) 153 return wpas_wps_start_pbc(wpa_s, NULL); 154 155 if (hwaddr_aton(cmd, bssid)) { 156 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 157 cmd); 158 return -1; 159 } 160 161 return wpas_wps_start_pbc(wpa_s, bssid); 162 } 163 164 165 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 166 char *cmd, char *buf, 167 size_t buflen) 168 { 169 u8 bssid[ETH_ALEN], *_bssid = bssid; 170 char *pin; 171 int ret; 172 173 pin = os_strchr(cmd, ' '); 174 if (pin) 175 *pin++ = '\0'; 176 177 if (os_strcmp(cmd, "any") == 0) 178 _bssid = NULL; 179 else if (hwaddr_aton(cmd, bssid)) { 180 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 181 cmd); 182 return -1; 183 } 184 185 if (pin) { 186 ret = wpas_wps_start_pin(wpa_s, _bssid, pin); 187 if (ret < 0) 188 return -1; 189 ret = os_snprintf(buf, buflen, "%s", pin); 190 if (ret < 0 || (size_t) ret >= buflen) 191 return -1; 192 return ret; 193 } 194 195 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL); 196 if (ret < 0) 197 return -1; 198 199 /* Return the generated PIN */ 200 ret = os_snprintf(buf, buflen, "%08d", ret); 201 if (ret < 0 || (size_t) ret >= buflen) 202 return -1; 203 return ret; 204 } 205 206 207 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 208 char *cmd) 209 { 210 u8 bssid[ETH_ALEN], *_bssid = bssid; 211 char *pin; 212 213 pin = os_strchr(cmd, ' '); 214 if (pin == NULL) 215 return -1; 216 *pin++ = '\0'; 217 218 if (os_strcmp(cmd, "any") == 0) 219 _bssid = NULL; 220 else if (hwaddr_aton(cmd, bssid)) { 221 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 222 cmd); 223 return -1; 224 } 225 226 return wpas_wps_start_reg(wpa_s, _bssid, pin); 227 } 228 #endif /* CONFIG_WPS */ 229 230 231 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 232 char *rsp) 233 { 234 #ifdef IEEE8021X_EAPOL 235 char *pos, *id_pos; 236 int id; 237 struct wpa_ssid *ssid; 238 struct eap_peer_config *eap; 239 240 pos = os_strchr(rsp, '-'); 241 if (pos == NULL) 242 return -1; 243 *pos++ = '\0'; 244 id_pos = pos; 245 pos = os_strchr(pos, ':'); 246 if (pos == NULL) 247 return -1; 248 *pos++ = '\0'; 249 id = atoi(id_pos); 250 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 251 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 252 (u8 *) pos, os_strlen(pos)); 253 254 ssid = wpa_config_get_network(wpa_s->conf, id); 255 if (ssid == NULL) { 256 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 257 "to update", id); 258 return -1; 259 } 260 eap = &ssid->eap; 261 262 if (os_strcmp(rsp, "IDENTITY") == 0) { 263 os_free(eap->identity); 264 eap->identity = (u8 *) os_strdup(pos); 265 eap->identity_len = os_strlen(pos); 266 eap->pending_req_identity = 0; 267 if (ssid == wpa_s->current_ssid) 268 wpa_s->reassociate = 1; 269 } else if (os_strcmp(rsp, "PASSWORD") == 0) { 270 os_free(eap->password); 271 eap->password = (u8 *) os_strdup(pos); 272 eap->password_len = os_strlen(pos); 273 eap->pending_req_password = 0; 274 if (ssid == wpa_s->current_ssid) 275 wpa_s->reassociate = 1; 276 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { 277 os_free(eap->new_password); 278 eap->new_password = (u8 *) os_strdup(pos); 279 eap->new_password_len = os_strlen(pos); 280 eap->pending_req_new_password = 0; 281 if (ssid == wpa_s->current_ssid) 282 wpa_s->reassociate = 1; 283 } else if (os_strcmp(rsp, "PIN") == 0) { 284 os_free(eap->pin); 285 eap->pin = os_strdup(pos); 286 eap->pending_req_pin = 0; 287 if (ssid == wpa_s->current_ssid) 288 wpa_s->reassociate = 1; 289 } else if (os_strcmp(rsp, "OTP") == 0) { 290 os_free(eap->otp); 291 eap->otp = (u8 *) os_strdup(pos); 292 eap->otp_len = os_strlen(pos); 293 os_free(eap->pending_req_otp); 294 eap->pending_req_otp = NULL; 295 eap->pending_req_otp_len = 0; 296 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { 297 os_free(eap->private_key_passwd); 298 eap->private_key_passwd = (u8 *) os_strdup(pos); 299 eap->pending_req_passphrase = 0; 300 if (ssid == wpa_s->current_ssid) 301 wpa_s->reassociate = 1; 302 } else { 303 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); 304 return -1; 305 } 306 307 return 0; 308 #else /* IEEE8021X_EAPOL */ 309 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 310 return -1; 311 #endif /* IEEE8021X_EAPOL */ 312 } 313 314 315 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 316 const char *params, 317 char *buf, size_t buflen) 318 { 319 char *pos, *end, tmp[30]; 320 int res, verbose, ret; 321 322 verbose = os_strcmp(params, "-VERBOSE") == 0; 323 pos = buf; 324 end = buf + buflen; 325 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 326 struct wpa_ssid *ssid = wpa_s->current_ssid; 327 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 328 MAC2STR(wpa_s->bssid)); 329 if (ret < 0 || ret >= end - pos) 330 return pos - buf; 331 pos += ret; 332 if (ssid) { 333 u8 *_ssid = ssid->ssid; 334 size_t ssid_len = ssid->ssid_len; 335 u8 ssid_buf[MAX_SSID_LEN]; 336 if (ssid_len == 0) { 337 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 338 if (_res < 0) 339 ssid_len = 0; 340 else 341 ssid_len = _res; 342 _ssid = ssid_buf; 343 } 344 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 345 wpa_ssid_txt(_ssid, ssid_len), 346 ssid->id); 347 if (ret < 0 || ret >= end - pos) 348 return pos - buf; 349 pos += ret; 350 351 if (ssid->id_str) { 352 ret = os_snprintf(pos, end - pos, 353 "id_str=%s\n", 354 ssid->id_str); 355 if (ret < 0 || ret >= end - pos) 356 return pos - buf; 357 pos += ret; 358 } 359 } 360 361 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 362 } 363 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 364 wpa_supplicant_state_txt(wpa_s->wpa_state)); 365 if (ret < 0 || ret >= end - pos) 366 return pos - buf; 367 pos += ret; 368 369 if (wpa_s->l2 && 370 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 371 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 372 if (ret < 0 || ret >= end - pos) 373 return pos - buf; 374 pos += ret; 375 } 376 377 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 378 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 379 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 380 verbose); 381 if (res >= 0) 382 pos += res; 383 } 384 385 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 386 if (res >= 0) 387 pos += res; 388 389 return pos - buf; 390 } 391 392 393 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 394 char *cmd) 395 { 396 char *pos; 397 int id; 398 struct wpa_ssid *ssid; 399 u8 bssid[ETH_ALEN]; 400 401 /* cmd: "<network id> <BSSID>" */ 402 pos = os_strchr(cmd, ' '); 403 if (pos == NULL) 404 return -1; 405 *pos++ = '\0'; 406 id = atoi(cmd); 407 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 408 if (hwaddr_aton(pos, bssid)) { 409 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 410 return -1; 411 } 412 413 ssid = wpa_config_get_network(wpa_s->conf, id); 414 if (ssid == NULL) { 415 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 416 "to update", id); 417 return -1; 418 } 419 420 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 421 ssid->bssid_set = !is_zero_ether_addr(bssid); 422 423 return 0; 424 } 425 426 #ifdef ANDROID 427 static int wpa_supplicant_ctrl_iface_blacklist( 428 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 429 { 430 u8 bssid[ETH_ALEN]; 431 struct wpa_blacklist *e; 432 char *pos, *end; 433 int ret; 434 435 /* cmd: "BLACKLIST [<BSSID>]" */ 436 if (*cmd == '\0') { 437 pos = buf; 438 end = buf + buflen; 439 440 e = wpa_s->blacklist; 441 while (e) { 442 ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid)); 443 if (ret < 0 || ret >= end - pos) 444 return pos - buf; 445 pos += ret; 446 e = e->next; 447 } 448 return pos - buf; 449 } 450 451 ++cmd; 452 if (os_strncmp(cmd, "clear", 5) == 0) { 453 wpa_blacklist_clear(wpa_s); 454 os_memcpy(buf, "OK\n", 3); 455 return 3; 456 } 457 458 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 459 if (hwaddr_aton(cmd, bssid)) { 460 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd); 461 return -1; 462 } 463 464 /* 465 * Add the BSSID twice, so its count will be 2, causing it to be 466 * skipped when processing scan results. 467 */ 468 ret = wpa_blacklist_add(wpa_s, bssid); 469 if (ret != 0) 470 return -1; 471 ret = wpa_blacklist_add(wpa_s, bssid); 472 if (ret != 0) 473 return -1; 474 os_memcpy(buf, "OK\n", 3); 475 return 3; 476 } 477 478 479 extern int wpa_debug_level; 480 extern int wpa_debug_timestamp; 481 static int wpa_supplicant_ctrl_iface_log_level( 482 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 483 { 484 char *pos, *end, *stamp; 485 int ret; 486 487 if (cmd == NULL) { 488 return -1; 489 } 490 491 /* cmd: "LOG_LEVEL [<level>]" */ 492 if (*cmd == '\0') { 493 pos = buf; 494 end = buf + buflen; 495 ret = os_snprintf(pos, end-pos, "Current level: %d\n" 496 "{0-MSGDUMP, 1-DEBUG, 2-INFO, 3-WARNING, 4-ERROR}\n" 497 "Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp); 498 if (ret < 0 || ret >= end - pos) 499 ret = 0; 500 501 return ret; 502 } 503 504 while (*cmd == ' ') { 505 cmd++; 506 } 507 508 stamp = os_strchr(cmd, ' '); 509 if (stamp) { 510 *stamp++ = '\0'; 511 while (*stamp == ' ') { 512 stamp++; 513 } 514 } 515 516 if (cmd && os_strlen(cmd)) { 517 wpa_debug_level = atoi(cmd); 518 } 519 520 if (stamp && os_strlen(stamp)) { 521 wpa_debug_timestamp = atoi(stamp); 522 } 523 524 os_memcpy(buf, "OK\n", 3); 525 return 3; 526 } 527 #endif 528 529 static int wpa_supplicant_ctrl_iface_list_networks( 530 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 531 { 532 char *pos, *end; 533 struct wpa_ssid *ssid; 534 int ret; 535 536 pos = buf; 537 end = buf + buflen; 538 ret = os_snprintf(pos, end - pos, 539 "network id / ssid / bssid / flags\n"); 540 if (ret < 0 || ret >= end - pos) 541 return pos - buf; 542 pos += ret; 543 544 ssid = wpa_s->conf->ssid; 545 while (ssid) { 546 ret = os_snprintf(pos, end - pos, "%d\t%s", 547 ssid->id, 548 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 549 if (ret < 0 || ret >= end - pos) 550 return pos - buf; 551 pos += ret; 552 if (ssid->bssid_set) { 553 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 554 MAC2STR(ssid->bssid)); 555 } else { 556 ret = os_snprintf(pos, end - pos, "\tany"); 557 } 558 if (ret < 0 || ret >= end - pos) 559 return pos - buf; 560 pos += ret; 561 ret = os_snprintf(pos, end - pos, "\t%s%s", 562 ssid == wpa_s->current_ssid ? 563 "[CURRENT]" : "", 564 ssid->disabled ? "[DISABLED]" : ""); 565 if (ret < 0 || ret >= end - pos) 566 return pos - buf; 567 pos += ret; 568 ret = os_snprintf(pos, end - pos, "\n"); 569 if (ret < 0 || ret >= end - pos) 570 return pos - buf; 571 pos += ret; 572 573 ssid = ssid->next; 574 } 575 576 return pos - buf; 577 } 578 579 580 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 581 { 582 int first = 1, ret; 583 ret = os_snprintf(pos, end - pos, "-"); 584 if (ret < 0 || ret >= end - pos) 585 return pos; 586 pos += ret; 587 if (cipher & WPA_CIPHER_NONE) { 588 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 589 if (ret < 0 || ret >= end - pos) 590 return pos; 591 pos += ret; 592 first = 0; 593 } 594 if (cipher & WPA_CIPHER_WEP40) { 595 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 596 if (ret < 0 || ret >= end - pos) 597 return pos; 598 pos += ret; 599 first = 0; 600 } 601 if (cipher & WPA_CIPHER_WEP104) { 602 ret = os_snprintf(pos, end - pos, "%sWEP104", 603 first ? "" : "+"); 604 if (ret < 0 || ret >= end - pos) 605 return pos; 606 pos += ret; 607 first = 0; 608 } 609 if (cipher & WPA_CIPHER_TKIP) { 610 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 611 if (ret < 0 || ret >= end - pos) 612 return pos; 613 pos += ret; 614 first = 0; 615 } 616 if (cipher & WPA_CIPHER_CCMP) { 617 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 618 if (ret < 0 || ret >= end - pos) 619 return pos; 620 pos += ret; 621 first = 0; 622 } 623 return pos; 624 } 625 626 627 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 628 const u8 *ie, size_t ie_len) 629 { 630 struct wpa_ie_data data; 631 int first, ret; 632 633 ret = os_snprintf(pos, end - pos, "[%s-", proto); 634 if (ret < 0 || ret >= end - pos) 635 return pos; 636 pos += ret; 637 638 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 639 ret = os_snprintf(pos, end - pos, "?]"); 640 if (ret < 0 || ret >= end - pos) 641 return pos; 642 pos += ret; 643 return pos; 644 } 645 646 first = 1; 647 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 648 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 649 if (ret < 0 || ret >= end - pos) 650 return pos; 651 pos += ret; 652 first = 0; 653 } 654 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 655 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 656 if (ret < 0 || ret >= end - pos) 657 return pos; 658 pos += ret; 659 first = 0; 660 } 661 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 662 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 663 if (ret < 0 || ret >= end - pos) 664 return pos; 665 pos += ret; 666 first = 0; 667 } 668 #ifdef CONFIG_IEEE80211R 669 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 670 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 671 first ? "" : "+"); 672 if (ret < 0 || ret >= end - pos) 673 return pos; 674 pos += ret; 675 first = 0; 676 } 677 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 678 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 679 first ? "" : "+"); 680 if (ret < 0 || ret >= end - pos) 681 return pos; 682 pos += ret; 683 first = 0; 684 } 685 #endif /* CONFIG_IEEE80211R */ 686 #ifdef CONFIG_IEEE80211W 687 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 688 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 689 first ? "" : "+"); 690 if (ret < 0 || ret >= end - pos) 691 return pos; 692 pos += ret; 693 first = 0; 694 } 695 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 696 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 697 first ? "" : "+"); 698 if (ret < 0 || ret >= end - pos) 699 return pos; 700 pos += ret; 701 first = 0; 702 } 703 #endif /* CONFIG_IEEE80211W */ 704 705 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 706 707 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 708 ret = os_snprintf(pos, end - pos, "-preauth"); 709 if (ret < 0 || ret >= end - pos) 710 return pos; 711 pos += ret; 712 } 713 714 ret = os_snprintf(pos, end - pos, "]"); 715 if (ret < 0 || ret >= end - pos) 716 return pos; 717 pos += ret; 718 719 return pos; 720 } 721 722 static char * wpa_supplicant_wps_ie_txt(char *pos, char *end, 723 const struct wpa_scan_res *res) 724 { 725 #ifdef CONFIG_WPS 726 struct wpabuf *wps_ie; 727 int ret; 728 const char *txt; 729 730 wps_ie = wpa_scan_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE); 731 if (wps_ie == NULL) 732 return pos; 733 734 if (wps_is_selected_pbc_registrar(wps_ie)) 735 txt = "[WPS-PBC]"; 736 else if (wps_is_selected_pin_registrar(wps_ie)) 737 txt = "[WPS-PIN]"; 738 else 739 txt = "[WPS]"; 740 741 ret = os_snprintf(pos, end - pos, "%s", txt); 742 if (ret >= 0 && ret < end - pos) 743 pos += ret; 744 wpabuf_free(wps_ie); 745 #endif /* CONFIG_WPS */ 746 747 return pos; 748 } 749 750 751 /* Format one result on one text line into a buffer. */ 752 static int wpa_supplicant_ctrl_iface_scan_result( 753 const struct wpa_scan_res *res, char *buf, size_t buflen) 754 { 755 char *pos, *end; 756 int ret; 757 const u8 *ie, *ie2; 758 759 pos = buf; 760 end = buf + buflen; 761 762 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 763 MAC2STR(res->bssid), res->freq, res->level); 764 if (ret < 0 || ret >= end - pos) 765 return -1; 766 pos += ret; 767 ie = wpa_scan_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 768 if (ie) 769 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 770 ie2 = wpa_scan_get_ie(res, WLAN_EID_RSN); 771 if (ie2) 772 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 773 pos = wpa_supplicant_wps_ie_txt(pos, end, res); 774 if (!ie && !ie2 && res->caps & IEEE80211_CAP_PRIVACY) { 775 ret = os_snprintf(pos, end - pos, "[WEP]"); 776 if (ret < 0 || ret >= end - pos) 777 return -1; 778 pos += ret; 779 } 780 if (res->caps & IEEE80211_CAP_IBSS) { 781 ret = os_snprintf(pos, end - pos, "[IBSS]"); 782 if (ret < 0 || ret >= end - pos) 783 return -1; 784 pos += ret; 785 } 786 /* Just to make the fields line up nicely when printed */ 787 if (!ie && !ie2) { 788 ret = os_snprintf(pos, end - pos, "\t"); 789 if (ret < 0 || ret >= end - pos) 790 return -1; 791 pos += ret; 792 } 793 ie = wpa_scan_get_ie(res, WLAN_EID_SSID); 794 ret = os_snprintf(pos, end - pos, "\t%s", 795 ie ? wpa_ssid_txt(ie + 2, ie[1]) : ""); 796 if (ret < 0 || ret >= end - pos) 797 return -1; 798 pos += ret; 799 800 ret = os_snprintf(pos, end - pos, "\n"); 801 if (ret < 0 || ret >= end - pos) 802 return -1; 803 pos += ret; 804 805 return pos - buf; 806 } 807 808 809 static int wpa_supplicant_ctrl_iface_scan_results( 810 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 811 { 812 char *pos, *end; 813 struct wpa_scan_res *res; 814 int ret; 815 size_t i; 816 817 if (wpa_s->scan_res == NULL && 818 wpa_supplicant_get_scan_results(wpa_s) < 0) 819 return 0; 820 if (wpa_s->scan_res == NULL) 821 return 0; 822 823 pos = buf; 824 end = buf + buflen; 825 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 826 "flags / ssid\n"); 827 if (ret < 0 || ret >= end - pos) 828 return pos - buf; 829 pos += ret; 830 831 for (i = 0; i < wpa_s->scan_res->num; i++) { 832 res = wpa_s->scan_res->res[i]; 833 ret = wpa_supplicant_ctrl_iface_scan_result(res, pos, 834 end - pos); 835 if (ret < 0 || ret >= end - pos) 836 return pos - buf; 837 pos += ret; 838 } 839 840 return pos - buf; 841 } 842 843 844 static int wpa_supplicant_ctrl_iface_select_network( 845 struct wpa_supplicant *wpa_s, char *cmd) 846 { 847 int id; 848 struct wpa_ssid *ssid; 849 850 /* cmd: "<network id>" or "any" */ 851 if (os_strcmp(cmd, "any") == 0) { 852 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 853 ssid = wpa_s->conf->ssid; 854 while (ssid) { 855 ssid->disabled = 0; 856 ssid = ssid->next; 857 } 858 wpa_s->reassociate = 1; 859 wpa_supplicant_req_scan(wpa_s, 0, 0); 860 return 0; 861 } 862 863 id = atoi(cmd); 864 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 865 866 ssid = wpa_config_get_network(wpa_s->conf, id); 867 if (ssid == NULL) { 868 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 869 "id=%d", id); 870 return -1; 871 } 872 873 if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) 874 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 875 876 /* Mark all other networks disabled and trigger reassociation */ 877 ssid = wpa_s->conf->ssid; 878 while (ssid) { 879 ssid->disabled = id != ssid->id; 880 ssid = ssid->next; 881 } 882 wpa_s->reassociate = 1; 883 wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; 884 wpa_supplicant_req_scan(wpa_s, 0, 0); 885 886 return 0; 887 } 888 889 890 static int wpa_supplicant_ctrl_iface_enable_network( 891 struct wpa_supplicant *wpa_s, char *cmd) 892 { 893 int id; 894 struct wpa_ssid *ssid; 895 896 /* cmd: "<network id>" or "all" */ 897 if (os_strcmp(cmd, "all") == 0) { 898 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 899 ssid = wpa_s->conf->ssid; 900 while (ssid) { 901 if (ssid == wpa_s->current_ssid && ssid->disabled) 902 wpa_s->reassociate = 1; 903 ssid->disabled = 0; 904 ssid = ssid->next; 905 } 906 if (wpa_s->reassociate) 907 #ifdef ANDROID 908 wpa_supplicant_req_scan(wpa_s, 2, 0); 909 #else 910 wpa_supplicant_req_scan(wpa_s, 0, 0); 911 #endif 912 return 0; 913 } 914 915 id = atoi(cmd); 916 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 917 918 ssid = wpa_config_get_network(wpa_s->conf, id); 919 if (ssid == NULL) { 920 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 921 "id=%d", id); 922 return -1; 923 } 924 925 if (wpa_s->current_ssid == NULL && ssid->disabled) { 926 /* 927 * Try to reassociate since there is no current configuration 928 * and a new network was made available. */ 929 wpa_s->reassociate = 1; 930 #ifdef ANDROID 931 wpa_supplicant_req_scan(wpa_s, 2, 0); 932 #else 933 wpa_supplicant_req_scan(wpa_s, 0, 0); 934 #endif 935 } 936 ssid->disabled = 0; 937 938 return 0; 939 } 940 941 942 static int wpa_supplicant_ctrl_iface_disable_network( 943 struct wpa_supplicant *wpa_s, char *cmd) 944 { 945 int id; 946 struct wpa_ssid *ssid; 947 948 /* cmd: "<network id>" or "all" */ 949 if (os_strcmp(cmd, "all") == 0) { 950 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 951 ssid = wpa_s->conf->ssid; 952 while (ssid) { 953 ssid->disabled = 1; 954 ssid = ssid->next; 955 } 956 if (wpa_s->current_ssid) 957 wpa_supplicant_disassociate(wpa_s, 958 WLAN_REASON_DEAUTH_LEAVING); 959 return 0; 960 } 961 962 id = atoi(cmd); 963 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 964 965 ssid = wpa_config_get_network(wpa_s->conf, id); 966 if (ssid == NULL) { 967 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 968 "id=%d", id); 969 return -1; 970 } 971 972 #ifdef ANDROID 973 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 974 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not disable WPS network " 975 "id=%d", id); 976 return -1; 977 } 978 #endif 979 980 if (ssid == wpa_s->current_ssid) 981 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 982 ssid->disabled = 1; 983 984 return 0; 985 } 986 987 988 static int wpa_supplicant_ctrl_iface_add_network( 989 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 990 { 991 struct wpa_ssid *ssid; 992 int ret; 993 994 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 995 996 ssid = wpa_config_add_network(wpa_s->conf); 997 if (ssid == NULL) 998 return -1; 999 ssid->disabled = 1; 1000 wpa_config_set_network_defaults(ssid); 1001 1002 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 1003 if (ret < 0 || (size_t) ret >= buflen) 1004 return -1; 1005 return ret; 1006 } 1007 1008 1009 static int wpa_supplicant_ctrl_iface_remove_network( 1010 struct wpa_supplicant *wpa_s, char *cmd) 1011 { 1012 int id; 1013 struct wpa_ssid *ssid; 1014 1015 /* cmd: "<network id>" or "all" */ 1016 if (os_strcmp(cmd, "all") == 0) { 1017 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 1018 ssid = wpa_s->conf->ssid; 1019 while (ssid) { 1020 id = ssid->id; 1021 ssid = ssid->next; 1022 wpa_config_remove_network(wpa_s->conf, id); 1023 } 1024 if (wpa_s->current_ssid) { 1025 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1026 wpa_supplicant_disassociate(wpa_s, 1027 WLAN_REASON_DEAUTH_LEAVING); 1028 } 1029 return 0; 1030 } 1031 1032 id = atoi(cmd); 1033 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 1034 1035 ssid = wpa_config_get_network(wpa_s->conf, id); 1036 if (ssid == NULL || 1037 wpa_config_remove_network(wpa_s->conf, id) < 0) { 1038 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1039 "id=%d", id); 1040 return -1; 1041 } 1042 1043 if (ssid == wpa_s->current_ssid) { 1044 /* 1045 * Invalidate the EAP session cache if the current network is 1046 * removed. 1047 */ 1048 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1049 1050 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1051 } 1052 1053 return 0; 1054 } 1055 1056 1057 static int wpa_supplicant_ctrl_iface_set_network( 1058 struct wpa_supplicant *wpa_s, char *cmd) 1059 { 1060 int id; 1061 struct wpa_ssid *ssid; 1062 char *name, *value; 1063 1064 /* cmd: "<network id> <variable name> <value>" */ 1065 name = os_strchr(cmd, ' '); 1066 if (name == NULL) 1067 return -1; 1068 *name++ = '\0'; 1069 1070 value = os_strchr(name, ' '); 1071 if (value == NULL) 1072 return -1; 1073 *value++ = '\0'; 1074 1075 id = atoi(cmd); 1076 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 1077 id, name); 1078 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1079 (u8 *) value, os_strlen(value)); 1080 1081 ssid = wpa_config_get_network(wpa_s->conf, id); 1082 if (ssid == NULL) { 1083 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1084 "id=%d", id); 1085 return -1; 1086 } 1087 1088 if (wpa_config_set(ssid, name, value, 0) < 0) { 1089 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 1090 "variable '%s'", name); 1091 return -1; 1092 } else { 1093 if (os_strcmp(name, "priority") == 0) { 1094 wpa_config_update_prio_list(wpa_s->conf); 1095 } 1096 } 1097 1098 if (wpa_s->current_ssid == ssid) { 1099 /* 1100 * Invalidate the EAP session cache if anything in the current 1101 * configuration changes. 1102 */ 1103 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1104 } 1105 1106 if ((os_strcmp(name, "psk") == 0 && 1107 value[0] == '"' && ssid->ssid_len) || 1108 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 1109 wpa_config_update_psk(ssid); 1110 1111 return 0; 1112 } 1113 1114 1115 static int wpa_supplicant_ctrl_iface_get_network( 1116 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1117 { 1118 int id; 1119 size_t res; 1120 struct wpa_ssid *ssid; 1121 char *name, *value; 1122 1123 /* cmd: "<network id> <variable name>" */ 1124 name = os_strchr(cmd, ' '); 1125 if (name == NULL || buflen == 0) 1126 return -1; 1127 *name++ = '\0'; 1128 1129 id = atoi(cmd); 1130 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 1131 id, name); 1132 1133 ssid = wpa_config_get_network(wpa_s->conf, id); 1134 if (ssid == NULL) { 1135 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1136 "id=%d", id); 1137 return -1; 1138 } 1139 1140 value = wpa_config_get_no_key(ssid, name); 1141 if (value == NULL) { 1142 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 1143 "variable '%s'", name); 1144 return -1; 1145 } 1146 1147 res = os_strlcpy(buf, value, buflen); 1148 if (res >= buflen) { 1149 os_free(value); 1150 return -1; 1151 } 1152 1153 os_free(value); 1154 1155 return res; 1156 } 1157 1158 1159 #ifndef CONFIG_NO_CONFIG_WRITE 1160 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 1161 { 1162 int ret; 1163 1164 if (!wpa_s->conf->update_config) { 1165 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 1166 "to update configuration (update_config=0)"); 1167 return -1; 1168 } 1169 1170 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 1171 if (ret) { 1172 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 1173 "update configuration"); 1174 } else { 1175 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 1176 " updated"); 1177 } 1178 1179 return ret; 1180 } 1181 #endif /* CONFIG_NO_CONFIG_WRITE */ 1182 1183 1184 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 1185 struct wpa_driver_capa *capa, 1186 char *buf, size_t buflen) 1187 { 1188 int ret, first = 1; 1189 char *pos, *end; 1190 size_t len; 1191 1192 pos = buf; 1193 end = pos + buflen; 1194 1195 if (res < 0) { 1196 if (strict) 1197 return 0; 1198 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 1199 if (len >= buflen) 1200 return -1; 1201 return len; 1202 } 1203 1204 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1205 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1206 if (ret < 0 || ret >= end - pos) 1207 return pos - buf; 1208 pos += ret; 1209 first = 0; 1210 } 1211 1212 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1213 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1214 if (ret < 0 || ret >= end - pos) 1215 return pos - buf; 1216 pos += ret; 1217 first = 0; 1218 } 1219 1220 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1221 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 1222 if (ret < 0 || ret >= end - pos) 1223 return pos - buf; 1224 pos += ret; 1225 first = 0; 1226 } 1227 1228 return pos - buf; 1229 } 1230 1231 1232 static int ctrl_iface_get_capability_group(int res, char *strict, 1233 struct wpa_driver_capa *capa, 1234 char *buf, size_t buflen) 1235 { 1236 int ret, first = 1; 1237 char *pos, *end; 1238 size_t len; 1239 1240 pos = buf; 1241 end = pos + buflen; 1242 1243 if (res < 0) { 1244 if (strict) 1245 return 0; 1246 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 1247 if (len >= buflen) 1248 return -1; 1249 return len; 1250 } 1251 1252 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1253 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1254 if (ret < 0 || ret >= end - pos) 1255 return pos - buf; 1256 pos += ret; 1257 first = 0; 1258 } 1259 1260 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1261 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1262 if (ret < 0 || ret >= end - pos) 1263 return pos - buf; 1264 pos += ret; 1265 first = 0; 1266 } 1267 1268 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 1269 ret = os_snprintf(pos, end - pos, "%sWEP104", 1270 first ? "" : " "); 1271 if (ret < 0 || ret >= end - pos) 1272 return pos - buf; 1273 pos += ret; 1274 first = 0; 1275 } 1276 1277 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 1278 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 1279 if (ret < 0 || ret >= end - pos) 1280 return pos - buf; 1281 pos += ret; 1282 first = 0; 1283 } 1284 1285 return pos - buf; 1286 } 1287 1288 1289 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 1290 struct wpa_driver_capa *capa, 1291 char *buf, size_t buflen) 1292 { 1293 int ret; 1294 char *pos, *end; 1295 size_t len; 1296 1297 pos = buf; 1298 end = pos + buflen; 1299 1300 if (res < 0) { 1301 if (strict) 1302 return 0; 1303 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 1304 "NONE", buflen); 1305 if (len >= buflen) 1306 return -1; 1307 return len; 1308 } 1309 1310 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 1311 if (ret < 0 || ret >= end - pos) 1312 return pos - buf; 1313 pos += ret; 1314 1315 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1316 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 1317 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 1318 if (ret < 0 || ret >= end - pos) 1319 return pos - buf; 1320 pos += ret; 1321 } 1322 1323 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1324 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1325 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 1326 if (ret < 0 || ret >= end - pos) 1327 return pos - buf; 1328 pos += ret; 1329 } 1330 1331 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1332 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 1333 if (ret < 0 || ret >= end - pos) 1334 return pos - buf; 1335 pos += ret; 1336 } 1337 1338 return pos - buf; 1339 } 1340 1341 1342 static int ctrl_iface_get_capability_proto(int res, char *strict, 1343 struct wpa_driver_capa *capa, 1344 char *buf, size_t buflen) 1345 { 1346 int ret, first = 1; 1347 char *pos, *end; 1348 size_t len; 1349 1350 pos = buf; 1351 end = pos + buflen; 1352 1353 if (res < 0) { 1354 if (strict) 1355 return 0; 1356 len = os_strlcpy(buf, "RSN WPA", buflen); 1357 if (len >= buflen) 1358 return -1; 1359 return len; 1360 } 1361 1362 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1363 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1364 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 1365 if (ret < 0 || ret >= end - pos) 1366 return pos - buf; 1367 pos += ret; 1368 first = 0; 1369 } 1370 1371 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1372 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 1373 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 1374 if (ret < 0 || ret >= end - pos) 1375 return pos - buf; 1376 pos += ret; 1377 first = 0; 1378 } 1379 1380 return pos - buf; 1381 } 1382 1383 1384 static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 1385 struct wpa_driver_capa *capa, 1386 char *buf, size_t buflen) 1387 { 1388 int ret, first = 1; 1389 char *pos, *end; 1390 size_t len; 1391 1392 pos = buf; 1393 end = pos + buflen; 1394 1395 if (res < 0) { 1396 if (strict) 1397 return 0; 1398 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 1399 if (len >= buflen) 1400 return -1; 1401 return len; 1402 } 1403 1404 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 1405 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 1406 if (ret < 0 || ret >= end - pos) 1407 return pos - buf; 1408 pos += ret; 1409 first = 0; 1410 } 1411 1412 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 1413 ret = os_snprintf(pos, end - pos, "%sSHARED", 1414 first ? "" : " "); 1415 if (ret < 0 || ret >= end - pos) 1416 return pos - buf; 1417 pos += ret; 1418 first = 0; 1419 } 1420 1421 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 1422 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 1423 if (ret < 0 || ret >= end - pos) 1424 return pos - buf; 1425 pos += ret; 1426 first = 0; 1427 } 1428 1429 return pos - buf; 1430 } 1431 1432 1433 static int wpa_supplicant_ctrl_iface_get_capability( 1434 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 1435 size_t buflen) 1436 { 1437 struct wpa_driver_capa capa; 1438 int res; 1439 char *strict; 1440 char field[30]; 1441 size_t len; 1442 1443 /* Determine whether or not strict checking was requested */ 1444 len = os_strlcpy(field, _field, sizeof(field)); 1445 if (len >= sizeof(field)) 1446 return -1; 1447 strict = os_strchr(field, ' '); 1448 if (strict != NULL) { 1449 *strict++ = '\0'; 1450 if (os_strcmp(strict, "strict") != 0) 1451 return -1; 1452 } 1453 1454 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 1455 field, strict ? strict : ""); 1456 1457 if (os_strcmp(field, "eap") == 0) { 1458 return eap_get_names(buf, buflen); 1459 } 1460 1461 res = wpa_drv_get_capa(wpa_s, &capa); 1462 1463 if (os_strcmp(field, "pairwise") == 0) 1464 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 1465 buf, buflen); 1466 1467 if (os_strcmp(field, "group") == 0) 1468 return ctrl_iface_get_capability_group(res, strict, &capa, 1469 buf, buflen); 1470 1471 if (os_strcmp(field, "key_mgmt") == 0) 1472 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 1473 buf, buflen); 1474 1475 if (os_strcmp(field, "proto") == 0) 1476 return ctrl_iface_get_capability_proto(res, strict, &capa, 1477 buf, buflen); 1478 1479 if (os_strcmp(field, "auth_alg") == 0) 1480 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 1481 buf, buflen); 1482 1483 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 1484 field); 1485 1486 return -1; 1487 } 1488 1489 1490 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 1491 const char *cmd, char *buf, 1492 size_t buflen) 1493 { 1494 u8 bssid[ETH_ALEN]; 1495 size_t i; 1496 struct wpa_scan_results *results; 1497 struct wpa_scan_res *bss; 1498 int ret; 1499 char *pos, *end; 1500 const u8 *ie, *ie2; 1501 1502 if (wpa_s->scan_res == NULL && 1503 wpa_supplicant_get_scan_results(wpa_s) < 0) 1504 return 0; 1505 1506 results = wpa_s->scan_res; 1507 if (results == NULL) 1508 return 0; 1509 1510 if (hwaddr_aton(cmd, bssid) == 0) { 1511 for (i = 0; i < results->num; i++) { 1512 if (os_memcmp(bssid, results->res[i]->bssid, ETH_ALEN) 1513 == 0) 1514 break; 1515 } 1516 } else 1517 i = atoi(cmd); 1518 1519 if (i >= results->num || results->res[i] == NULL) 1520 return 0; /* no match found */ 1521 1522 bss = results->res[i]; 1523 pos = buf; 1524 end = buf + buflen; 1525 ret = os_snprintf(pos, end - pos, 1526 "bssid=" MACSTR "\n" 1527 "freq=%d\n" 1528 "beacon_int=%d\n" 1529 "capabilities=0x%04x\n" 1530 "qual=%d\n" 1531 "noise=%d\n" 1532 "level=%d\n" 1533 "tsf=%016llu\n" 1534 "ie=", 1535 MAC2STR(bss->bssid), bss->freq, bss->beacon_int, 1536 bss->caps, bss->qual, bss->noise, bss->level, 1537 (unsigned long long) bss->tsf); 1538 if (ret < 0 || ret >= end - pos) 1539 return pos - buf; 1540 pos += ret; 1541 1542 ie = (const u8 *) (bss + 1); 1543 for (i = 0; i < bss->ie_len; i++) { 1544 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 1545 if (ret < 0 || ret >= end - pos) 1546 return pos - buf; 1547 pos += ret; 1548 } 1549 1550 ret = os_snprintf(pos, end - pos, "\n"); 1551 if (ret < 0 || ret >= end - pos) 1552 return pos - buf; 1553 pos += ret; 1554 1555 ret = os_snprintf(pos, end - pos, "flags="); 1556 if (ret < 0 || ret >= end - pos) 1557 return pos - buf; 1558 pos += ret; 1559 1560 ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1561 if (ie) 1562 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1563 ie2 = wpa_scan_get_ie(bss, WLAN_EID_RSN); 1564 if (ie2) 1565 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1566 pos = wpa_supplicant_wps_ie_txt(pos, end, bss); 1567 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1568 ret = os_snprintf(pos, end - pos, "[WEP]"); 1569 if (ret < 0 || ret >= end - pos) 1570 return pos - buf; 1571 pos += ret; 1572 } 1573 if (bss->caps & IEEE80211_CAP_IBSS) { 1574 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1575 if (ret < 0 || ret >= end - pos) 1576 return pos - buf; 1577 pos += ret; 1578 } 1579 1580 ret = os_snprintf(pos, end - pos, "\n"); 1581 if (ret < 0 || ret >= end - pos) 1582 return pos - buf; 1583 pos += ret; 1584 1585 ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); 1586 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 1587 ie ? wpa_ssid_txt(ie + 2, ie[1]) : ""); 1588 if (ret < 0 || ret >= end - pos) 1589 return pos - buf; 1590 pos += ret; 1591 1592 return pos - buf; 1593 } 1594 1595 1596 static int wpa_supplicant_ctrl_iface_ap_scan( 1597 struct wpa_supplicant *wpa_s, char *cmd) 1598 { 1599 int ap_scan = atoi(cmd); 1600 1601 if (ap_scan < 0 || ap_scan > 2) 1602 return -1; 1603 #ifdef ANDROID 1604 if ((ap_scan == 2) && (wpa_s->wpa_state != WPA_COMPLETED)) { 1605 wpa_printf(MSG_DEBUG, "ap_scan = %d", wpa_s->conf->ap_scan); 1606 return 0; 1607 } 1608 wpa_printf(MSG_DEBUG, "ap_scan = %d", ap_scan); 1609 #endif 1610 wpa_s->conf->ap_scan = ap_scan; 1611 return 0; 1612 } 1613 1614 #ifdef ANDROID 1615 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, 1616 char *cmd, char *buf, size_t buflen) 1617 { 1618 int ret; 1619 1620 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 1621 if( ret == 0 ) { 1622 ret = sprintf(buf, "%s\n", "OK"); 1623 } 1624 return( ret ); 1625 } 1626 #endif 1627 1628 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 1629 char *buf, size_t *resp_len) 1630 { 1631 char *reply; 1632 const int reply_size = 4096; 1633 int ctrl_rsp = 0; 1634 int reply_len; 1635 1636 wpa_printf(MSG_DEBUG, "CMD: %s", buf); 1637 1638 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 1639 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1640 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 1641 (const u8 *) buf, os_strlen(buf)); 1642 } else { 1643 if (os_strcmp(buf, "PING") != 0) { 1644 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", 1645 (const u8 *) buf, os_strlen(buf)); 1646 } 1647 } 1648 1649 reply = os_malloc(reply_size); 1650 if (reply == NULL) { 1651 *resp_len = 1; 1652 return NULL; 1653 } 1654 1655 os_memcpy(reply, "OK\n", 3); 1656 reply_len = 3; 1657 1658 if (os_strcmp(buf, "PING") == 0) { 1659 os_memcpy(reply, "PONG\n", 5); 1660 reply_len = 5; 1661 } else if (os_strcmp(buf, "MIB") == 0) { 1662 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 1663 if (reply_len >= 0) { 1664 int res; 1665 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 1666 reply_size - reply_len); 1667 if (res < 0) 1668 reply_len = -1; 1669 else 1670 reply_len += res; 1671 } 1672 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 1673 reply_len = wpa_supplicant_ctrl_iface_status( 1674 wpa_s, buf + 6, reply, reply_size); 1675 } else if (os_strcmp(buf, "PMKSA") == 0) { 1676 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size); 1677 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1678 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 1679 reply_len = -1; 1680 } else if (os_strcmp(buf, "LOGON") == 0) { 1681 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 1682 } else if (os_strcmp(buf, "LOGOFF") == 0) { 1683 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 1684 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 1685 wpa_s->disconnected = 0; 1686 wpa_s->reassociate = 1; 1687 wpa_supplicant_req_scan(wpa_s, 0, 0); 1688 } else if (os_strcmp(buf, "RECONNECT") == 0) { 1689 if (wpa_s->disconnected) { 1690 wpa_s->disconnected = 0; 1691 wpa_s->reassociate = 1; 1692 wpa_supplicant_req_scan(wpa_s, 0, 0); 1693 } 1694 #ifdef IEEE8021X_EAPOL 1695 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 1696 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 1697 reply_len = -1; 1698 #endif /* IEEE8021X_EAPOL */ 1699 #ifdef CONFIG_PEERKEY 1700 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 1701 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 1702 reply_len = -1; 1703 #endif /* CONFIG_PEERKEY */ 1704 #ifdef CONFIG_IEEE80211R 1705 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 1706 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 1707 reply_len = -1; 1708 #endif /* CONFIG_IEEE80211R */ 1709 #ifdef CONFIG_WPS 1710 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1711 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL)) 1712 reply_len = -1; 1713 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 1714 if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8)) 1715 reply_len = -1; 1716 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1717 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 1718 reply, 1719 reply_size); 1720 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 1721 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 1722 reply_len = -1; 1723 #endif /* CONFIG_WPS */ 1724 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 1725 { 1726 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 1727 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 1728 reply_len = -1; 1729 else 1730 ctrl_rsp = 1; 1731 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 1732 if (wpa_supplicant_reload_configuration(wpa_s)) 1733 reply_len = -1; 1734 } else if (os_strcmp(buf, "TERMINATE") == 0) { 1735 eloop_terminate(); 1736 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 1737 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 1738 reply_len = -1; 1739 #ifdef ANDROID 1740 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 1741 reply_len = wpa_supplicant_ctrl_iface_blacklist( 1742 wpa_s, buf + 9, reply, reply_size); 1743 if (os_strlen(buf) > 10 && reply_len == 0) { 1744 struct wpa_blacklist *bl = wpa_s->blacklist; 1745 if (os_strncmp(buf+10, "clear", 5) == 0 || 1746 (bl != NULL && os_memcmp(bl->bssid, wpa_s->bssid, ETH_ALEN) == 0)) { 1747 wpa_s->disconnected = 0; 1748 wpa_s->reassociate = 1; 1749 wpa_supplicant_req_scan(wpa_s, 0, 0); 1750 } 1751 } 1752 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 1753 reply_len = wpa_supplicant_ctrl_iface_log_level( 1754 wpa_s, buf + 9, reply, reply_size); 1755 #endif 1756 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 1757 reply_len = wpa_supplicant_ctrl_iface_list_networks( 1758 wpa_s, reply, reply_size); 1759 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 1760 wpa_s->reassociate = 0; 1761 wpa_s->disconnected = 1; 1762 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1763 } else if (os_strcmp(buf, "SCAN") == 0) { 1764 #ifdef ANDROID 1765 if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) || 1766 (wpa_s->wpa_state >= WPA_COMPLETED))) { 1767 #endif 1768 wpa_s->scan_req = 2; 1769 wpa_supplicant_req_scan(wpa_s, 0, 0); 1770 #ifdef ANDROID 1771 } else { 1772 wpa_printf(MSG_ERROR, "Ongoing Scan action..."); 1773 #endif 1774 } 1775 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 1776 reply_len = wpa_supplicant_ctrl_iface_scan_results( 1777 wpa_s, reply, reply_size); 1778 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 1779 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 1780 reply_len = -1; 1781 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 1782 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 1783 reply_len = -1; 1784 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 1785 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 1786 reply_len = -1; 1787 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 1788 reply_len = wpa_supplicant_ctrl_iface_add_network( 1789 wpa_s, reply, reply_size); 1790 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 1791 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 1792 reply_len = -1; 1793 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 1794 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 1795 reply_len = -1; 1796 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 1797 reply_len = wpa_supplicant_ctrl_iface_get_network( 1798 wpa_s, buf + 12, reply, reply_size); 1799 #ifndef CONFIG_NO_CONFIG_WRITE 1800 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 1801 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 1802 reply_len = -1; 1803 #endif /* CONFIG_NO_CONFIG_WRITE */ 1804 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 1805 reply_len = wpa_supplicant_ctrl_iface_get_capability( 1806 wpa_s, buf + 15, reply, reply_size); 1807 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 1808 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 1809 reply_len = -1; 1810 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 1811 reply_len = wpa_supplicant_global_iface_list( 1812 wpa_s->global, reply, reply_size); 1813 } else if (os_strcmp(buf, "INTERFACES") == 0) { 1814 reply_len = wpa_supplicant_global_iface_interfaces( 1815 wpa_s->global, reply, reply_size); 1816 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 1817 reply_len = wpa_supplicant_ctrl_iface_bss( 1818 wpa_s, buf + 4, reply, reply_size); 1819 #ifdef ANDROID 1820 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 1821 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, reply_size); 1822 #endif 1823 } else { 1824 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1825 reply_len = 16; 1826 } 1827 1828 if (reply_len < 0) { 1829 os_memcpy(reply, "FAIL\n", 5); 1830 reply_len = 5; 1831 } 1832 1833 if (ctrl_rsp) 1834 eapol_sm_notify_ctrl_response(wpa_s->eapol); 1835 1836 *resp_len = reply_len; 1837 return reply; 1838 } 1839 1840 1841 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 1842 char *cmd) 1843 { 1844 struct wpa_interface iface; 1845 char *pos; 1846 1847 /* 1848 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 1849 * TAB<bridge_ifname> 1850 */ 1851 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 1852 1853 os_memset(&iface, 0, sizeof(iface)); 1854 1855 do { 1856 iface.ifname = pos = cmd; 1857 pos = os_strchr(pos, '\t'); 1858 if (pos) 1859 *pos++ = '\0'; 1860 if (iface.ifname[0] == '\0') 1861 return -1; 1862 if (pos == NULL) 1863 break; 1864 1865 iface.confname = pos; 1866 pos = os_strchr(pos, '\t'); 1867 if (pos) 1868 *pos++ = '\0'; 1869 if (iface.confname[0] == '\0') 1870 iface.confname = NULL; 1871 if (pos == NULL) 1872 break; 1873 1874 iface.driver = pos; 1875 pos = os_strchr(pos, '\t'); 1876 if (pos) 1877 *pos++ = '\0'; 1878 if (iface.driver[0] == '\0') 1879 iface.driver = NULL; 1880 if (pos == NULL) 1881 break; 1882 1883 iface.ctrl_interface = pos; 1884 pos = os_strchr(pos, '\t'); 1885 if (pos) 1886 *pos++ = '\0'; 1887 if (iface.ctrl_interface[0] == '\0') 1888 iface.ctrl_interface = NULL; 1889 if (pos == NULL) 1890 break; 1891 1892 iface.driver_param = pos; 1893 pos = os_strchr(pos, '\t'); 1894 if (pos) 1895 *pos++ = '\0'; 1896 if (iface.driver_param[0] == '\0') 1897 iface.driver_param = NULL; 1898 if (pos == NULL) 1899 break; 1900 1901 iface.bridge_ifname = pos; 1902 pos = os_strchr(pos, '\t'); 1903 if (pos) 1904 *pos++ = '\0'; 1905 if (iface.bridge_ifname[0] == '\0') 1906 iface.bridge_ifname = NULL; 1907 if (pos == NULL) 1908 break; 1909 } while (0); 1910 1911 if (wpa_supplicant_get_iface(global, iface.ifname)) 1912 return -1; 1913 1914 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 1915 } 1916 1917 1918 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 1919 char *cmd) 1920 { 1921 struct wpa_supplicant *wpa_s; 1922 1923 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 1924 1925 wpa_s = wpa_supplicant_get_iface(global, cmd); 1926 if (wpa_s == NULL) 1927 return -1; 1928 return wpa_supplicant_remove_iface(global, wpa_s); 1929 } 1930 1931 1932 static void wpa_free_iface_info(struct wpa_interface_info *iface) 1933 { 1934 struct wpa_interface_info *prev; 1935 1936 while (iface) { 1937 prev = iface; 1938 iface = iface->next; 1939 1940 os_free(prev->ifname); 1941 os_free(prev->desc); 1942 os_free(prev); 1943 } 1944 } 1945 1946 1947 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 1948 char *buf, int len) 1949 { 1950 int i, res; 1951 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 1952 char *pos, *end; 1953 1954 for (i = 0; wpa_supplicant_drivers[i]; i++) { 1955 struct wpa_driver_ops *drv = wpa_supplicant_drivers[i]; 1956 if (drv->get_interfaces == NULL) 1957 continue; 1958 tmp = drv->get_interfaces(global->drv_priv); 1959 if (tmp == NULL) 1960 continue; 1961 1962 if (last == NULL) 1963 iface = last = tmp; 1964 else 1965 last->next = tmp; 1966 while (last->next) 1967 last = last->next; 1968 } 1969 1970 pos = buf; 1971 end = buf + len; 1972 for (tmp = iface; tmp; tmp = tmp->next) { 1973 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 1974 tmp->drv_name, tmp->ifname, 1975 tmp->desc ? tmp->desc : ""); 1976 if (res < 0 || res >= end - pos) { 1977 *pos = '\0'; 1978 break; 1979 } 1980 pos += res; 1981 } 1982 1983 wpa_free_iface_info(iface); 1984 1985 return pos - buf; 1986 } 1987 1988 1989 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 1990 char *buf, int len) 1991 { 1992 int res; 1993 char *pos, *end; 1994 struct wpa_supplicant *wpa_s; 1995 1996 wpa_s = global->ifaces; 1997 pos = buf; 1998 end = buf + len; 1999 2000 while (wpa_s) { 2001 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 2002 if (res < 0 || res >= end - pos) { 2003 *pos = '\0'; 2004 break; 2005 } 2006 pos += res; 2007 wpa_s = wpa_s->next; 2008 } 2009 return pos - buf; 2010 } 2011 2012 2013 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 2014 char *buf, size_t *resp_len) 2015 { 2016 char *reply; 2017 const int reply_size = 4096; 2018 int reply_len; 2019 2020 if (os_strcmp(buf, "PING") != 0) { 2021 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", 2022 (const u8 *) buf, os_strlen(buf)); 2023 } 2024 2025 reply = os_malloc(reply_size); 2026 if (reply == NULL) { 2027 *resp_len = 1; 2028 return NULL; 2029 } 2030 2031 os_memcpy(reply, "OK\n", 3); 2032 reply_len = 3; 2033 2034 if (os_strcmp(buf, "PING") == 0) { 2035 os_memcpy(reply, "PONG\n", 5); 2036 reply_len = 5; 2037 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 2038 if (wpa_supplicant_global_iface_add(global, buf + 14)) 2039 reply_len = -1; 2040 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 2041 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 2042 reply_len = -1; 2043 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 2044 reply_len = wpa_supplicant_global_iface_list( 2045 global, reply, reply_size); 2046 } else if (os_strcmp(buf, "INTERFACES") == 0) { 2047 reply_len = wpa_supplicant_global_iface_interfaces( 2048 global, reply, reply_size); 2049 } else if (os_strcmp(buf, "TERMINATE") == 0) { 2050 eloop_terminate(); 2051 } else { 2052 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 2053 reply_len = 16; 2054 } 2055 2056 if (reply_len < 0) { 2057 os_memcpy(reply, "FAIL\n", 5); 2058 reply_len = 5; 2059 } 2060 2061 *resp_len = reply_len; 2062 return reply; 2063 } 2064