ctrl_iface.c revision f48e4f901d4b39a4e03210fe0154cdb11112e22e
1/* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "utils/includes.h" 10 11#include "utils/common.h" 12#include "utils/eloop.h" 13#include "common/version.h" 14#include "common/ieee802_11_defs.h" 15#include "common/wpa_ctrl.h" 16#include "eap_peer/eap.h" 17#include "eapol_supp/eapol_supp_sm.h" 18#include "rsn_supp/wpa.h" 19#include "rsn_supp/preauth.h" 20#include "rsn_supp/pmksa_cache.h" 21#include "l2_packet/l2_packet.h" 22#include "wps/wps.h" 23#include "config.h" 24#include "wpa_supplicant_i.h" 25#include "driver_i.h" 26#include "wps_supplicant.h" 27#include "ibss_rsn.h" 28#include "ap.h" 29#include "p2p_supplicant.h" 30#include "p2p/p2p.h" 31#include "hs20_supplicant.h" 32#include "notify.h" 33#include "bss.h" 34#include "scan.h" 35#include "ctrl_iface.h" 36#include "interworking.h" 37#include "blacklist.h" 38#include "wpas_glue.h" 39#include "autoscan.h" 40 41extern struct wpa_driver_ops *wpa_drivers[]; 42 43static int wpa_supplicant_global_iface_list(struct wpa_global *global, 44 char *buf, int len); 45static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 46 char *buf, int len); 47 48 49static int pno_start(struct wpa_supplicant *wpa_s) 50{ 51 int ret; 52 size_t i, num_ssid; 53 struct wpa_ssid *ssid; 54 struct wpa_driver_scan_params params; 55 56 if (wpa_s->pno) 57 return 0; 58 59 os_memset(¶ms, 0, sizeof(params)); 60 61 num_ssid = 0; 62 ssid = wpa_s->conf->ssid; 63 while (ssid) { 64 if (!wpas_network_disabled(wpa_s, ssid)) 65 num_ssid++; 66 ssid = ssid->next; 67 } 68 if (num_ssid > WPAS_MAX_SCAN_SSIDS) { 69 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " 70 "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); 71 num_ssid = WPAS_MAX_SCAN_SSIDS; 72 } 73 74 if (num_ssid == 0) { 75 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); 76 return -1; 77 } 78 79 params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) * 80 num_ssid); 81 if (params.filter_ssids == NULL) 82 return -1; 83 i = 0; 84 ssid = wpa_s->conf->ssid; 85 while (ssid) { 86 if (!wpas_network_disabled(wpa_s, ssid)) { 87 params.ssids[i].ssid = ssid->ssid; 88 params.ssids[i].ssid_len = ssid->ssid_len; 89 params.num_ssids++; 90 os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, 91 ssid->ssid_len); 92 params.filter_ssids[i].ssid_len = ssid->ssid_len; 93 params.num_filter_ssids++; 94 i++; 95 if (i == num_ssid) 96 break; 97 } 98 ssid = ssid->next; 99 } 100 101 ret = wpa_drv_sched_scan(wpa_s, ¶ms, 10 * 1000); 102 os_free(params.filter_ssids); 103 if (ret == 0) 104 wpa_s->pno = 1; 105 return ret; 106} 107 108 109static int pno_stop(struct wpa_supplicant *wpa_s) 110{ 111 if (wpa_s->pno) { 112 wpa_s->pno = 0; 113 return wpa_drv_stop_sched_scan(wpa_s); 114 } 115 return 0; 116} 117 118 119static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 120{ 121 char *pos; 122 u8 addr[ETH_ALEN], *filter = NULL, *n; 123 size_t count = 0; 124 125 pos = val; 126 while (pos) { 127 if (*pos == '\0') 128 break; 129 if (hwaddr_aton(pos, addr)) { 130 os_free(filter); 131 return -1; 132 } 133 n = os_realloc(filter, (count + 1) * ETH_ALEN); 134 if (n == NULL) { 135 os_free(filter); 136 return -1; 137 } 138 filter = n; 139 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 140 count++; 141 142 pos = os_strchr(pos, ' '); 143 if (pos) 144 pos++; 145 } 146 147 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 148 os_free(wpa_s->bssid_filter); 149 wpa_s->bssid_filter = filter; 150 wpa_s->bssid_filter_count = count; 151 152 return 0; 153} 154 155 156static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 157 char *cmd) 158{ 159 char *value; 160 int ret = 0; 161 162 value = os_strchr(cmd, ' '); 163 if (value == NULL) 164 return -1; 165 *value++ = '\0'; 166 167 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 168 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 169 eapol_sm_configure(wpa_s->eapol, 170 atoi(value), -1, -1, -1); 171 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 172 eapol_sm_configure(wpa_s->eapol, 173 -1, atoi(value), -1, -1); 174 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 175 eapol_sm_configure(wpa_s->eapol, 176 -1, -1, atoi(value), -1); 177 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 178 eapol_sm_configure(wpa_s->eapol, 179 -1, -1, -1, atoi(value)); 180 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 181 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 182 atoi(value))) 183 ret = -1; 184 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 185 0) { 186 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 187 atoi(value))) 188 ret = -1; 189 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 190 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 191 ret = -1; 192 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 193 wpa_s->wps_fragment_size = atoi(value); 194#ifdef CONFIG_WPS_TESTING 195 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 196 long int val; 197 val = strtol(value, NULL, 0); 198 if (val < 0 || val > 0xff) { 199 ret = -1; 200 wpa_printf(MSG_DEBUG, "WPS: Invalid " 201 "wps_version_number %ld", val); 202 } else { 203 wps_version_number = val; 204 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 205 "version %u.%u", 206 (wps_version_number & 0xf0) >> 4, 207 wps_version_number & 0x0f); 208 } 209 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 210 wps_testing_dummy_cred = atoi(value); 211 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 212 wps_testing_dummy_cred); 213#endif /* CONFIG_WPS_TESTING */ 214 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 215 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 216 ret = -1; 217#ifdef CONFIG_TDLS_TESTING 218 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 219 extern unsigned int tdls_testing; 220 tdls_testing = strtol(value, NULL, 0); 221 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 222#endif /* CONFIG_TDLS_TESTING */ 223#ifdef CONFIG_TDLS 224 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 225 int disabled = atoi(value); 226 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 227 if (disabled) { 228 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 229 ret = -1; 230 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 231 ret = -1; 232 wpa_tdls_enable(wpa_s->wpa, !disabled); 233#endif /* CONFIG_TDLS */ 234 } else if (os_strcasecmp(cmd, "pno") == 0) { 235 if (atoi(value)) 236 ret = pno_start(wpa_s); 237 else 238 ret = pno_stop(wpa_s); 239 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 240 int disabled = atoi(value); 241 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 242 ret = -1; 243 else if (disabled) 244 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 245 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 246 if (os_strcmp(value, "disable") == 0) 247 wpa_s->set_sta_uapsd = 0; 248 else { 249 int be, bk, vi, vo; 250 char *pos; 251 /* format: BE,BK,VI,VO;max SP Length */ 252 be = atoi(value); 253 pos = os_strchr(value, ','); 254 if (pos == NULL) 255 return -1; 256 pos++; 257 bk = atoi(pos); 258 pos = os_strchr(pos, ','); 259 if (pos == NULL) 260 return -1; 261 pos++; 262 vi = atoi(pos); 263 pos = os_strchr(pos, ','); 264 if (pos == NULL) 265 return -1; 266 pos++; 267 vo = atoi(pos); 268 /* ignore max SP Length for now */ 269 270 wpa_s->set_sta_uapsd = 1; 271 wpa_s->sta_uapsd = 0; 272 if (be) 273 wpa_s->sta_uapsd |= BIT(0); 274 if (bk) 275 wpa_s->sta_uapsd |= BIT(1); 276 if (vi) 277 wpa_s->sta_uapsd |= BIT(2); 278 if (vo) 279 wpa_s->sta_uapsd |= BIT(3); 280 } 281 } else if (os_strcasecmp(cmd, "ps") == 0) { 282 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 283 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 284 ret = set_bssid_filter(wpa_s, value); 285 } else { 286 value[-1] = '='; 287 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 288 if (ret == 0) 289 wpa_supplicant_update_config(wpa_s); 290 } 291 292 return ret; 293} 294 295 296static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 297 char *cmd, char *buf, size_t buflen) 298{ 299 int res = -1; 300 301 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 302 303 if (os_strcmp(cmd, "version") == 0) { 304 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 305 } else if (os_strcasecmp(cmd, "country") == 0) { 306 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 307 res = os_snprintf(buf, buflen, "%c%c", 308 wpa_s->conf->country[0], 309 wpa_s->conf->country[1]); 310 } 311 312 if (res < 0 || (unsigned int) res >= buflen) 313 return -1; 314 return res; 315} 316 317 318#ifdef IEEE8021X_EAPOL 319static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 320 char *addr) 321{ 322 u8 bssid[ETH_ALEN]; 323 struct wpa_ssid *ssid = wpa_s->current_ssid; 324 325 if (hwaddr_aton(addr, bssid)) { 326 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 327 "'%s'", addr); 328 return -1; 329 } 330 331 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 332 rsn_preauth_deinit(wpa_s->wpa); 333 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 334 return -1; 335 336 return 0; 337} 338#endif /* IEEE8021X_EAPOL */ 339 340 341#ifdef CONFIG_PEERKEY 342/* MLME-STKSTART.request(peer) */ 343static int wpa_supplicant_ctrl_iface_stkstart( 344 struct wpa_supplicant *wpa_s, char *addr) 345{ 346 u8 peer[ETH_ALEN]; 347 348 if (hwaddr_aton(addr, peer)) { 349 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 350 "address '%s'", addr); 351 return -1; 352 } 353 354 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 355 MAC2STR(peer)); 356 357 return wpa_sm_stkstart(wpa_s->wpa, peer); 358} 359#endif /* CONFIG_PEERKEY */ 360 361 362#ifdef CONFIG_TDLS 363 364static int wpa_supplicant_ctrl_iface_tdls_discover( 365 struct wpa_supplicant *wpa_s, char *addr) 366{ 367 u8 peer[ETH_ALEN]; 368 int ret; 369 370 if (hwaddr_aton(addr, peer)) { 371 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 372 "address '%s'", addr); 373 return -1; 374 } 375 376 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 377 MAC2STR(peer)); 378 379 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 380 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 381 else 382 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 383 384 return ret; 385} 386 387 388static int wpa_supplicant_ctrl_iface_tdls_setup( 389 struct wpa_supplicant *wpa_s, char *addr) 390{ 391 u8 peer[ETH_ALEN]; 392 int ret; 393 394 if (hwaddr_aton(addr, peer)) { 395 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 396 "address '%s'", addr); 397 return -1; 398 } 399 400 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 401 MAC2STR(peer)); 402 403 ret = wpa_tdls_reneg(wpa_s->wpa, peer); 404 if (ret) { 405 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 406 ret = wpa_tdls_start(wpa_s->wpa, peer); 407 else 408 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 409 } 410 411 return ret; 412} 413 414 415static int wpa_supplicant_ctrl_iface_tdls_teardown( 416 struct wpa_supplicant *wpa_s, char *addr) 417{ 418 u8 peer[ETH_ALEN]; 419 420 if (hwaddr_aton(addr, peer)) { 421 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 422 "address '%s'", addr); 423 return -1; 424 } 425 426 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 427 MAC2STR(peer)); 428 429 return wpa_tdls_teardown_link(wpa_s->wpa, peer, 430 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 431} 432 433#endif /* CONFIG_TDLS */ 434 435 436#ifdef CONFIG_IEEE80211R 437static int wpa_supplicant_ctrl_iface_ft_ds( 438 struct wpa_supplicant *wpa_s, char *addr) 439{ 440 u8 target_ap[ETH_ALEN]; 441 struct wpa_bss *bss; 442 const u8 *mdie; 443 444 if (hwaddr_aton(addr, target_ap)) { 445 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 446 "address '%s'", addr); 447 return -1; 448 } 449 450 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 451 452 bss = wpa_bss_get_bssid(wpa_s, target_ap); 453 if (bss) 454 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 455 else 456 mdie = NULL; 457 458 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 459} 460#endif /* CONFIG_IEEE80211R */ 461 462 463#ifdef CONFIG_WPS 464static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 465 char *cmd) 466{ 467 u8 bssid[ETH_ALEN], *_bssid = bssid; 468#ifdef CONFIG_P2P 469 u8 p2p_dev_addr[ETH_ALEN]; 470#endif /* CONFIG_P2P */ 471#ifdef CONFIG_AP 472 u8 *_p2p_dev_addr = NULL; 473#endif /* CONFIG_AP */ 474 475 if (cmd == NULL || os_strcmp(cmd, "any") == 0) { 476 _bssid = NULL; 477#ifdef CONFIG_P2P 478 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 479 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 480 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 481 "P2P Device Address '%s'", 482 cmd + 13); 483 return -1; 484 } 485 _p2p_dev_addr = p2p_dev_addr; 486#endif /* CONFIG_P2P */ 487 } else if (hwaddr_aton(cmd, bssid)) { 488 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 489 cmd); 490 return -1; 491 } 492 493#ifdef CONFIG_AP 494 if (wpa_s->ap_iface) 495 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 496#endif /* CONFIG_AP */ 497 498 return wpas_wps_start_pbc(wpa_s, _bssid, 0); 499} 500 501 502static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 503 char *cmd, char *buf, 504 size_t buflen) 505{ 506 u8 bssid[ETH_ALEN], *_bssid = bssid; 507 char *pin; 508 int ret; 509 510 pin = os_strchr(cmd, ' '); 511 if (pin) 512 *pin++ = '\0'; 513 514 if (os_strcmp(cmd, "any") == 0) 515 _bssid = NULL; 516 else if (os_strcmp(cmd, "get") == 0) { 517 ret = wps_generate_pin(); 518 goto done; 519 } else if (hwaddr_aton(cmd, bssid)) { 520 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 521 cmd); 522 return -1; 523 } 524 525#ifdef CONFIG_AP 526 if (wpa_s->ap_iface) 527 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 528 buf, buflen); 529#endif /* CONFIG_AP */ 530 531 if (pin) { 532 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 533 DEV_PW_DEFAULT); 534 if (ret < 0) 535 return -1; 536 ret = os_snprintf(buf, buflen, "%s", pin); 537 if (ret < 0 || (size_t) ret >= buflen) 538 return -1; 539 return ret; 540 } 541 542 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 543 if (ret < 0) 544 return -1; 545 546done: 547 /* Return the generated PIN */ 548 ret = os_snprintf(buf, buflen, "%08d", ret); 549 if (ret < 0 || (size_t) ret >= buflen) 550 return -1; 551 return ret; 552} 553 554 555static int wpa_supplicant_ctrl_iface_wps_check_pin( 556 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 557{ 558 char pin[9]; 559 size_t len; 560 char *pos; 561 int ret; 562 563 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 564 (u8 *) cmd, os_strlen(cmd)); 565 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 566 if (*pos < '0' || *pos > '9') 567 continue; 568 pin[len++] = *pos; 569 if (len == 9) { 570 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 571 return -1; 572 } 573 } 574 if (len != 4 && len != 8) { 575 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 576 return -1; 577 } 578 pin[len] = '\0'; 579 580 if (len == 8) { 581 unsigned int pin_val; 582 pin_val = atoi(pin); 583 if (!wps_pin_valid(pin_val)) { 584 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 585 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 586 if (ret < 0 || (size_t) ret >= buflen) 587 return -1; 588 return ret; 589 } 590 } 591 592 ret = os_snprintf(buf, buflen, "%s", pin); 593 if (ret < 0 || (size_t) ret >= buflen) 594 return -1; 595 596 return ret; 597} 598 599 600#ifdef CONFIG_WPS_OOB 601static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s, 602 char *cmd) 603{ 604 char *path, *method, *name; 605 606 path = os_strchr(cmd, ' '); 607 if (path == NULL) 608 return -1; 609 *path++ = '\0'; 610 611 method = os_strchr(path, ' '); 612 if (method == NULL) 613 return -1; 614 *method++ = '\0'; 615 616 name = os_strchr(method, ' '); 617 if (name != NULL) 618 *name++ = '\0'; 619 620 return wpas_wps_start_oob(wpa_s, cmd, path, method, name); 621} 622#endif /* CONFIG_WPS_OOB */ 623 624 625#ifdef CONFIG_WPS_NFC 626 627static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 628 char *cmd) 629{ 630 u8 bssid[ETH_ALEN], *_bssid = bssid; 631 632 if (cmd == NULL || cmd[0] == '\0') 633 _bssid = NULL; 634 else if (hwaddr_aton(cmd, bssid)) 635 return -1; 636 637 return wpas_wps_start_nfc(wpa_s, _bssid); 638} 639 640 641static int wpa_supplicant_ctrl_iface_wps_nfc_token( 642 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 643{ 644 int ndef; 645 struct wpabuf *buf; 646 int res; 647 648 if (os_strcmp(cmd, "WPS") == 0) 649 ndef = 0; 650 else if (os_strcmp(cmd, "NDEF") == 0) 651 ndef = 1; 652 else 653 return -1; 654 655 buf = wpas_wps_nfc_token(wpa_s, ndef); 656 if (buf == NULL) 657 return -1; 658 659 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 660 wpabuf_len(buf)); 661 reply[res++] = '\n'; 662 reply[res] = '\0'; 663 664 wpabuf_free(buf); 665 666 return res; 667} 668 669 670static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 671 struct wpa_supplicant *wpa_s, char *pos) 672{ 673 size_t len; 674 struct wpabuf *buf; 675 int ret; 676 677 len = os_strlen(pos); 678 if (len & 0x01) 679 return -1; 680 len /= 2; 681 682 buf = wpabuf_alloc(len); 683 if (buf == NULL) 684 return -1; 685 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 686 wpabuf_free(buf); 687 return -1; 688 } 689 690 ret = wpas_wps_nfc_tag_read(wpa_s, buf); 691 wpabuf_free(buf); 692 693 return ret; 694} 695 696#endif /* CONFIG_WPS_NFC */ 697 698 699static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 700 char *cmd) 701{ 702 u8 bssid[ETH_ALEN]; 703 char *pin; 704 char *new_ssid; 705 char *new_auth; 706 char *new_encr; 707 char *new_key; 708 struct wps_new_ap_settings ap; 709 710 pin = os_strchr(cmd, ' '); 711 if (pin == NULL) 712 return -1; 713 *pin++ = '\0'; 714 715 if (hwaddr_aton(cmd, bssid)) { 716 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 717 cmd); 718 return -1; 719 } 720 721 new_ssid = os_strchr(pin, ' '); 722 if (new_ssid == NULL) 723 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 724 *new_ssid++ = '\0'; 725 726 new_auth = os_strchr(new_ssid, ' '); 727 if (new_auth == NULL) 728 return -1; 729 *new_auth++ = '\0'; 730 731 new_encr = os_strchr(new_auth, ' '); 732 if (new_encr == NULL) 733 return -1; 734 *new_encr++ = '\0'; 735 736 new_key = os_strchr(new_encr, ' '); 737 if (new_key == NULL) 738 return -1; 739 *new_key++ = '\0'; 740 741 os_memset(&ap, 0, sizeof(ap)); 742 ap.ssid_hex = new_ssid; 743 ap.auth = new_auth; 744 ap.encr = new_encr; 745 ap.key_hex = new_key; 746 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 747} 748 749 750#ifdef CONFIG_AP 751static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 752 char *cmd, char *buf, 753 size_t buflen) 754{ 755 int timeout = 300; 756 char *pos; 757 const char *pin_txt; 758 759 if (!wpa_s->ap_iface) 760 return -1; 761 762 pos = os_strchr(cmd, ' '); 763 if (pos) 764 *pos++ = '\0'; 765 766 if (os_strcmp(cmd, "disable") == 0) { 767 wpas_wps_ap_pin_disable(wpa_s); 768 return os_snprintf(buf, buflen, "OK\n"); 769 } 770 771 if (os_strcmp(cmd, "random") == 0) { 772 if (pos) 773 timeout = atoi(pos); 774 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 775 if (pin_txt == NULL) 776 return -1; 777 return os_snprintf(buf, buflen, "%s", pin_txt); 778 } 779 780 if (os_strcmp(cmd, "get") == 0) { 781 pin_txt = wpas_wps_ap_pin_get(wpa_s); 782 if (pin_txt == NULL) 783 return -1; 784 return os_snprintf(buf, buflen, "%s", pin_txt); 785 } 786 787 if (os_strcmp(cmd, "set") == 0) { 788 char *pin; 789 if (pos == NULL) 790 return -1; 791 pin = pos; 792 pos = os_strchr(pos, ' '); 793 if (pos) { 794 *pos++ = '\0'; 795 timeout = atoi(pos); 796 } 797 if (os_strlen(pin) > buflen) 798 return -1; 799 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 800 return -1; 801 return os_snprintf(buf, buflen, "%s", pin); 802 } 803 804 return -1; 805} 806#endif /* CONFIG_AP */ 807 808 809#ifdef CONFIG_WPS_ER 810static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 811 char *cmd) 812{ 813 char *uuid = cmd, *pin, *pos; 814 u8 addr_buf[ETH_ALEN], *addr = NULL; 815 pin = os_strchr(uuid, ' '); 816 if (pin == NULL) 817 return -1; 818 *pin++ = '\0'; 819 pos = os_strchr(pin, ' '); 820 if (pos) { 821 *pos++ = '\0'; 822 if (hwaddr_aton(pos, addr_buf) == 0) 823 addr = addr_buf; 824 } 825 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 826} 827 828 829static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 830 char *cmd) 831{ 832 char *uuid = cmd, *pin; 833 pin = os_strchr(uuid, ' '); 834 if (pin == NULL) 835 return -1; 836 *pin++ = '\0'; 837 return wpas_wps_er_learn(wpa_s, uuid, pin); 838} 839 840 841static int wpa_supplicant_ctrl_iface_wps_er_set_config( 842 struct wpa_supplicant *wpa_s, char *cmd) 843{ 844 char *uuid = cmd, *id; 845 id = os_strchr(uuid, ' '); 846 if (id == NULL) 847 return -1; 848 *id++ = '\0'; 849 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 850} 851 852 853static int wpa_supplicant_ctrl_iface_wps_er_config( 854 struct wpa_supplicant *wpa_s, char *cmd) 855{ 856 char *pin; 857 char *new_ssid; 858 char *new_auth; 859 char *new_encr; 860 char *new_key; 861 struct wps_new_ap_settings ap; 862 863 pin = os_strchr(cmd, ' '); 864 if (pin == NULL) 865 return -1; 866 *pin++ = '\0'; 867 868 new_ssid = os_strchr(pin, ' '); 869 if (new_ssid == NULL) 870 return -1; 871 *new_ssid++ = '\0'; 872 873 new_auth = os_strchr(new_ssid, ' '); 874 if (new_auth == NULL) 875 return -1; 876 *new_auth++ = '\0'; 877 878 new_encr = os_strchr(new_auth, ' '); 879 if (new_encr == NULL) 880 return -1; 881 *new_encr++ = '\0'; 882 883 new_key = os_strchr(new_encr, ' '); 884 if (new_key == NULL) 885 return -1; 886 *new_key++ = '\0'; 887 888 os_memset(&ap, 0, sizeof(ap)); 889 ap.ssid_hex = new_ssid; 890 ap.auth = new_auth; 891 ap.encr = new_encr; 892 ap.key_hex = new_key; 893 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 894} 895 896 897#ifdef CONFIG_WPS_NFC 898static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 899 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 900{ 901 int ndef; 902 struct wpabuf *buf; 903 int res; 904 char *uuid; 905 906 uuid = os_strchr(cmd, ' '); 907 if (uuid == NULL) 908 return -1; 909 *uuid++ = '\0'; 910 911 if (os_strcmp(cmd, "WPS") == 0) 912 ndef = 0; 913 else if (os_strcmp(cmd, "NDEF") == 0) 914 ndef = 1; 915 else 916 return -1; 917 918 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 919 if (buf == NULL) 920 return -1; 921 922 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 923 wpabuf_len(buf)); 924 reply[res++] = '\n'; 925 reply[res] = '\0'; 926 927 wpabuf_free(buf); 928 929 return res; 930} 931#endif /* CONFIG_WPS_NFC */ 932#endif /* CONFIG_WPS_ER */ 933 934#endif /* CONFIG_WPS */ 935 936 937#ifdef CONFIG_IBSS_RSN 938static int wpa_supplicant_ctrl_iface_ibss_rsn( 939 struct wpa_supplicant *wpa_s, char *addr) 940{ 941 u8 peer[ETH_ALEN]; 942 943 if (hwaddr_aton(addr, peer)) { 944 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 945 "address '%s'", addr); 946 return -1; 947 } 948 949 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 950 MAC2STR(peer)); 951 952 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 953} 954#endif /* CONFIG_IBSS_RSN */ 955 956 957static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 958 char *rsp) 959{ 960#ifdef IEEE8021X_EAPOL 961 char *pos, *id_pos; 962 int id; 963 struct wpa_ssid *ssid; 964 965 pos = os_strchr(rsp, '-'); 966 if (pos == NULL) 967 return -1; 968 *pos++ = '\0'; 969 id_pos = pos; 970 pos = os_strchr(pos, ':'); 971 if (pos == NULL) 972 return -1; 973 *pos++ = '\0'; 974 id = atoi(id_pos); 975 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 976 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 977 (u8 *) pos, os_strlen(pos)); 978 979 ssid = wpa_config_get_network(wpa_s->conf, id); 980 if (ssid == NULL) { 981 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 982 "to update", id); 983 return -1; 984 } 985 986 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 987 pos); 988#else /* IEEE8021X_EAPOL */ 989 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 990 return -1; 991#endif /* IEEE8021X_EAPOL */ 992} 993 994 995static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 996 const char *params, 997 char *buf, size_t buflen) 998{ 999 char *pos, *end, tmp[30]; 1000 int res, verbose, wps, ret; 1001 1002 verbose = os_strcmp(params, "-VERBOSE") == 0; 1003 wps = os_strcmp(params, "-WPS") == 0; 1004 pos = buf; 1005 end = buf + buflen; 1006 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 1007 struct wpa_ssid *ssid = wpa_s->current_ssid; 1008 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 1009 MAC2STR(wpa_s->bssid)); 1010 if (ret < 0 || ret >= end - pos) 1011 return pos - buf; 1012 pos += ret; 1013 if (ssid) { 1014 u8 *_ssid = ssid->ssid; 1015 size_t ssid_len = ssid->ssid_len; 1016 u8 ssid_buf[MAX_SSID_LEN]; 1017 if (ssid_len == 0) { 1018 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 1019 if (_res < 0) 1020 ssid_len = 0; 1021 else 1022 ssid_len = _res; 1023 _ssid = ssid_buf; 1024 } 1025 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 1026 wpa_ssid_txt(_ssid, ssid_len), 1027 ssid->id); 1028 if (ret < 0 || ret >= end - pos) 1029 return pos - buf; 1030 pos += ret; 1031 1032 if (wps && ssid->passphrase && 1033 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 1034 (ssid->mode == WPAS_MODE_AP || 1035 ssid->mode == WPAS_MODE_P2P_GO)) { 1036 ret = os_snprintf(pos, end - pos, 1037 "passphrase=%s\n", 1038 ssid->passphrase); 1039 if (ret < 0 || ret >= end - pos) 1040 return pos - buf; 1041 pos += ret; 1042 } 1043 if (ssid->id_str) { 1044 ret = os_snprintf(pos, end - pos, 1045 "id_str=%s\n", 1046 ssid->id_str); 1047 if (ret < 0 || ret >= end - pos) 1048 return pos - buf; 1049 pos += ret; 1050 } 1051 1052 switch (ssid->mode) { 1053 case WPAS_MODE_INFRA: 1054 ret = os_snprintf(pos, end - pos, 1055 "mode=station\n"); 1056 break; 1057 case WPAS_MODE_IBSS: 1058 ret = os_snprintf(pos, end - pos, 1059 "mode=IBSS\n"); 1060 break; 1061 case WPAS_MODE_AP: 1062 ret = os_snprintf(pos, end - pos, 1063 "mode=AP\n"); 1064 break; 1065 case WPAS_MODE_P2P_GO: 1066 ret = os_snprintf(pos, end - pos, 1067 "mode=P2P GO\n"); 1068 break; 1069 case WPAS_MODE_P2P_GROUP_FORMATION: 1070 ret = os_snprintf(pos, end - pos, 1071 "mode=P2P GO - group " 1072 "formation\n"); 1073 break; 1074 default: 1075 ret = 0; 1076 break; 1077 } 1078 if (ret < 0 || ret >= end - pos) 1079 return pos - buf; 1080 pos += ret; 1081 } 1082 1083#ifdef CONFIG_AP 1084 if (wpa_s->ap_iface) { 1085 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 1086 end - pos, 1087 verbose); 1088 } else 1089#endif /* CONFIG_AP */ 1090 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 1091 } 1092 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 1093 wpa_supplicant_state_txt(wpa_s->wpa_state)); 1094 if (ret < 0 || ret >= end - pos) 1095 return pos - buf; 1096 pos += ret; 1097 1098 if (wpa_s->l2 && 1099 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 1100 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 1101 if (ret < 0 || ret >= end - pos) 1102 return pos - buf; 1103 pos += ret; 1104 } 1105 1106#ifdef CONFIG_P2P 1107 if (wpa_s->global->p2p) { 1108 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 1109 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 1110 if (ret < 0 || ret >= end - pos) 1111 return pos - buf; 1112 pos += ret; 1113 } 1114#endif /* CONFIG_P2P */ 1115 1116 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 1117 MAC2STR(wpa_s->own_addr)); 1118 if (ret < 0 || ret >= end - pos) 1119 return pos - buf; 1120 pos += ret; 1121 1122#ifdef CONFIG_HS20 1123 if (wpa_s->current_bss && 1124 wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE)) { 1125 ret = os_snprintf(pos, end - pos, "hs20=1\n"); 1126 if (ret < 0 || ret >= end - pos) 1127 return pos - buf; 1128 pos += ret; 1129 } 1130#endif /* CONFIG_HS20 */ 1131 1132 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 1133 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1134 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 1135 verbose); 1136 if (res >= 0) 1137 pos += res; 1138 } 1139 1140 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 1141 if (res >= 0) 1142 pos += res; 1143 1144#ifdef ANDROID 1145 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE 1146 "id=%d state=%d BSSID=" MACSTR " SSID=%s", 1147 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, 1148 wpa_s->wpa_state, 1149 MAC2STR(wpa_s->bssid), 1150 wpa_s->current_ssid && wpa_s->current_ssid->ssid ? 1151 wpa_ssid_txt(wpa_s->current_ssid->ssid, 1152 wpa_s->current_ssid->ssid_len) : ""); 1153 if (wpa_s->wpa_state == WPA_COMPLETED) { 1154 struct wpa_ssid *ssid = wpa_s->current_ssid; 1155 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- connection to " 1156 MACSTR " completed %s [id=%d id_str=%s]", 1157 MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ? 1158 "(reauth)" : "(auth)", 1159 ssid ? ssid->id : -1, 1160 ssid && ssid->id_str ? ssid->id_str : ""); 1161 } 1162#endif /* ANDROID */ 1163 1164 return pos - buf; 1165} 1166 1167 1168static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 1169 char *cmd) 1170{ 1171 char *pos; 1172 int id; 1173 struct wpa_ssid *ssid; 1174 u8 bssid[ETH_ALEN]; 1175 1176 /* cmd: "<network id> <BSSID>" */ 1177 pos = os_strchr(cmd, ' '); 1178 if (pos == NULL) 1179 return -1; 1180 *pos++ = '\0'; 1181 id = atoi(cmd); 1182 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 1183 if (hwaddr_aton(pos, bssid)) { 1184 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 1185 return -1; 1186 } 1187 1188 ssid = wpa_config_get_network(wpa_s->conf, id); 1189 if (ssid == NULL) { 1190 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1191 "to update", id); 1192 return -1; 1193 } 1194 1195 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 1196 ssid->bssid_set = !is_zero_ether_addr(bssid); 1197 1198 return 0; 1199} 1200 1201 1202static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 1203 char *cmd, char *buf, 1204 size_t buflen) 1205{ 1206 u8 bssid[ETH_ALEN]; 1207 struct wpa_blacklist *e; 1208 char *pos, *end; 1209 int ret; 1210 1211 /* cmd: "BLACKLIST [<BSSID>]" */ 1212 if (*cmd == '\0') { 1213 pos = buf; 1214 end = buf + buflen; 1215 e = wpa_s->blacklist; 1216 while (e) { 1217 ret = os_snprintf(pos, end - pos, MACSTR "\n", 1218 MAC2STR(e->bssid)); 1219 if (ret < 0 || ret >= end - pos) 1220 return pos - buf; 1221 pos += ret; 1222 e = e->next; 1223 } 1224 return pos - buf; 1225 } 1226 1227 cmd++; 1228 if (os_strncmp(cmd, "clear", 5) == 0) { 1229 wpa_blacklist_clear(wpa_s); 1230 os_memcpy(buf, "OK\n", 3); 1231 return 3; 1232 } 1233 1234 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 1235 if (hwaddr_aton(cmd, bssid)) { 1236 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 1237 return -1; 1238 } 1239 1240 /* 1241 * Add the BSSID twice, so its count will be 2, causing it to be 1242 * skipped when processing scan results. 1243 */ 1244 ret = wpa_blacklist_add(wpa_s, bssid); 1245 if (ret != 0) 1246 return -1; 1247 ret = wpa_blacklist_add(wpa_s, bssid); 1248 if (ret != 0) 1249 return -1; 1250 os_memcpy(buf, "OK\n", 3); 1251 return 3; 1252} 1253 1254 1255extern int wpa_debug_level; 1256extern int wpa_debug_timestamp; 1257 1258static const char * debug_level_str(int level) 1259{ 1260 switch (level) { 1261 case MSG_EXCESSIVE: 1262 return "EXCESSIVE"; 1263 case MSG_MSGDUMP: 1264 return "MSGDUMP"; 1265 case MSG_DEBUG: 1266 return "DEBUG"; 1267 case MSG_INFO: 1268 return "INFO"; 1269 case MSG_WARNING: 1270 return "WARNING"; 1271 case MSG_ERROR: 1272 return "ERROR"; 1273 default: 1274 return "?"; 1275 } 1276} 1277 1278 1279static int str_to_debug_level(const char *s) 1280{ 1281 if (os_strcasecmp(s, "EXCESSIVE") == 0) 1282 return MSG_EXCESSIVE; 1283 if (os_strcasecmp(s, "MSGDUMP") == 0) 1284 return MSG_MSGDUMP; 1285 if (os_strcasecmp(s, "DEBUG") == 0) 1286 return MSG_DEBUG; 1287 if (os_strcasecmp(s, "INFO") == 0) 1288 return MSG_INFO; 1289 if (os_strcasecmp(s, "WARNING") == 0) 1290 return MSG_WARNING; 1291 if (os_strcasecmp(s, "ERROR") == 0) 1292 return MSG_ERROR; 1293 return -1; 1294} 1295 1296 1297static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 1298 char *cmd, char *buf, 1299 size_t buflen) 1300{ 1301 char *pos, *end, *stamp; 1302 int ret; 1303 1304 if (cmd == NULL) { 1305 return -1; 1306 } 1307 1308 /* cmd: "LOG_LEVEL [<level>]" */ 1309 if (*cmd == '\0') { 1310 pos = buf; 1311 end = buf + buflen; 1312 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 1313 "Timestamp: %d\n", 1314 debug_level_str(wpa_debug_level), 1315 wpa_debug_timestamp); 1316 if (ret < 0 || ret >= end - pos) 1317 ret = 0; 1318 1319 return ret; 1320 } 1321 1322 while (*cmd == ' ') 1323 cmd++; 1324 1325 stamp = os_strchr(cmd, ' '); 1326 if (stamp) { 1327 *stamp++ = '\0'; 1328 while (*stamp == ' ') { 1329 stamp++; 1330 } 1331 } 1332 1333 if (cmd && os_strlen(cmd)) { 1334 int level = str_to_debug_level(cmd); 1335 if (level < 0) 1336 return -1; 1337 wpa_debug_level = level; 1338 } 1339 1340 if (stamp && os_strlen(stamp)) 1341 wpa_debug_timestamp = atoi(stamp); 1342 1343 os_memcpy(buf, "OK\n", 3); 1344 return 3; 1345} 1346 1347 1348static int wpa_supplicant_ctrl_iface_list_networks( 1349 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1350{ 1351 char *pos, *end; 1352 struct wpa_ssid *ssid; 1353 int ret; 1354 1355 pos = buf; 1356 end = buf + buflen; 1357 ret = os_snprintf(pos, end - pos, 1358 "network id / ssid / bssid / flags\n"); 1359 if (ret < 0 || ret >= end - pos) 1360 return pos - buf; 1361 pos += ret; 1362 1363 ssid = wpa_s->conf->ssid; 1364 while (ssid) { 1365 ret = os_snprintf(pos, end - pos, "%d\t%s", 1366 ssid->id, 1367 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1368 if (ret < 0 || ret >= end - pos) 1369 return pos - buf; 1370 pos += ret; 1371 if (ssid->bssid_set) { 1372 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 1373 MAC2STR(ssid->bssid)); 1374 } else { 1375 ret = os_snprintf(pos, end - pos, "\tany"); 1376 } 1377 if (ret < 0 || ret >= end - pos) 1378 return pos - buf; 1379 pos += ret; 1380 ret = os_snprintf(pos, end - pos, "\t%s%s%s", 1381 ssid == wpa_s->current_ssid ? 1382 "[CURRENT]" : "", 1383 ssid->disabled ? "[DISABLED]" : "", 1384 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 1385 ""); 1386 if (ret < 0 || ret >= end - pos) 1387 return pos - buf; 1388 pos += ret; 1389 ret = os_snprintf(pos, end - pos, "\n"); 1390 if (ret < 0 || ret >= end - pos) 1391 return pos - buf; 1392 pos += ret; 1393 1394 ssid = ssid->next; 1395 } 1396 1397 return pos - buf; 1398} 1399 1400 1401static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 1402{ 1403 int first = 1, ret; 1404 ret = os_snprintf(pos, end - pos, "-"); 1405 if (ret < 0 || ret >= end - pos) 1406 return pos; 1407 pos += ret; 1408 if (cipher & WPA_CIPHER_NONE) { 1409 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 1410 if (ret < 0 || ret >= end - pos) 1411 return pos; 1412 pos += ret; 1413 first = 0; 1414 } 1415 if (cipher & WPA_CIPHER_WEP40) { 1416 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 1417 if (ret < 0 || ret >= end - pos) 1418 return pos; 1419 pos += ret; 1420 first = 0; 1421 } 1422 if (cipher & WPA_CIPHER_WEP104) { 1423 ret = os_snprintf(pos, end - pos, "%sWEP104", 1424 first ? "" : "+"); 1425 if (ret < 0 || ret >= end - pos) 1426 return pos; 1427 pos += ret; 1428 first = 0; 1429 } 1430 if (cipher & WPA_CIPHER_TKIP) { 1431 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 1432 if (ret < 0 || ret >= end - pos) 1433 return pos; 1434 pos += ret; 1435 first = 0; 1436 } 1437 if (cipher & WPA_CIPHER_CCMP) { 1438 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 1439 if (ret < 0 || ret >= end - pos) 1440 return pos; 1441 pos += ret; 1442 first = 0; 1443 } 1444 return pos; 1445} 1446 1447 1448static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 1449 const u8 *ie, size_t ie_len) 1450{ 1451 struct wpa_ie_data data; 1452 int first, ret; 1453 1454 ret = os_snprintf(pos, end - pos, "[%s-", proto); 1455 if (ret < 0 || ret >= end - pos) 1456 return pos; 1457 pos += ret; 1458 1459 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 1460 ret = os_snprintf(pos, end - pos, "?]"); 1461 if (ret < 0 || ret >= end - pos) 1462 return pos; 1463 pos += ret; 1464 return pos; 1465 } 1466 1467 first = 1; 1468 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1469 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 1470 if (ret < 0 || ret >= end - pos) 1471 return pos; 1472 pos += ret; 1473 first = 0; 1474 } 1475 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 1476 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 1477 if (ret < 0 || ret >= end - pos) 1478 return pos; 1479 pos += ret; 1480 first = 0; 1481 } 1482 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 1483 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 1484 if (ret < 0 || ret >= end - pos) 1485 return pos; 1486 pos += ret; 1487 first = 0; 1488 } 1489#ifdef CONFIG_IEEE80211R 1490 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1491 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 1492 first ? "" : "+"); 1493 if (ret < 0 || ret >= end - pos) 1494 return pos; 1495 pos += ret; 1496 first = 0; 1497 } 1498 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1499 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 1500 first ? "" : "+"); 1501 if (ret < 0 || ret >= end - pos) 1502 return pos; 1503 pos += ret; 1504 first = 0; 1505 } 1506#endif /* CONFIG_IEEE80211R */ 1507#ifdef CONFIG_IEEE80211W 1508 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1509 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 1510 first ? "" : "+"); 1511 if (ret < 0 || ret >= end - pos) 1512 return pos; 1513 pos += ret; 1514 first = 0; 1515 } 1516 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1517 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 1518 first ? "" : "+"); 1519 if (ret < 0 || ret >= end - pos) 1520 return pos; 1521 pos += ret; 1522 first = 0; 1523 } 1524#endif /* CONFIG_IEEE80211W */ 1525 1526 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 1527 1528 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 1529 ret = os_snprintf(pos, end - pos, "-preauth"); 1530 if (ret < 0 || ret >= end - pos) 1531 return pos; 1532 pos += ret; 1533 } 1534 1535 ret = os_snprintf(pos, end - pos, "]"); 1536 if (ret < 0 || ret >= end - pos) 1537 return pos; 1538 pos += ret; 1539 1540 return pos; 1541} 1542 1543 1544#ifdef CONFIG_WPS 1545static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 1546 char *pos, char *end, 1547 struct wpabuf *wps_ie) 1548{ 1549 int ret; 1550 const char *txt; 1551 1552 if (wps_ie == NULL) 1553 return pos; 1554 if (wps_is_selected_pbc_registrar(wps_ie)) 1555 txt = "[WPS-PBC]"; 1556#ifdef CONFIG_WPS2 1557 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 1558 txt = "[WPS-AUTH]"; 1559#endif /* CONFIG_WPS2 */ 1560 else if (wps_is_selected_pin_registrar(wps_ie)) 1561 txt = "[WPS-PIN]"; 1562 else 1563 txt = "[WPS]"; 1564 1565 ret = os_snprintf(pos, end - pos, "%s", txt); 1566 if (ret >= 0 && ret < end - pos) 1567 pos += ret; 1568 wpabuf_free(wps_ie); 1569 return pos; 1570} 1571#endif /* CONFIG_WPS */ 1572 1573 1574static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 1575 char *pos, char *end, 1576 const struct wpa_bss *bss) 1577{ 1578#ifdef CONFIG_WPS 1579 struct wpabuf *wps_ie; 1580 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 1581 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 1582#else /* CONFIG_WPS */ 1583 return pos; 1584#endif /* CONFIG_WPS */ 1585} 1586 1587 1588/* Format one result on one text line into a buffer. */ 1589static int wpa_supplicant_ctrl_iface_scan_result( 1590 struct wpa_supplicant *wpa_s, 1591 const struct wpa_bss *bss, char *buf, size_t buflen) 1592{ 1593 char *pos, *end; 1594 int ret; 1595 const u8 *ie, *ie2, *p2p; 1596 1597 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 1598 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 1599 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 1600 0) 1601 return 0; /* Do not show P2P listen discovery results here */ 1602 1603 pos = buf; 1604 end = buf + buflen; 1605 1606 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 1607 MAC2STR(bss->bssid), bss->freq, bss->level); 1608 if (ret < 0 || ret >= end - pos) 1609 return -1; 1610 pos += ret; 1611 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1612 if (ie) 1613 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1614 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1615 if (ie2) 1616 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1617 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 1618 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1619 ret = os_snprintf(pos, end - pos, "[WEP]"); 1620 if (ret < 0 || ret >= end - pos) 1621 return -1; 1622 pos += ret; 1623 } 1624 if (bss->caps & IEEE80211_CAP_IBSS) { 1625 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1626 if (ret < 0 || ret >= end - pos) 1627 return -1; 1628 pos += ret; 1629 } 1630 if (bss->caps & IEEE80211_CAP_ESS) { 1631 ret = os_snprintf(pos, end - pos, "[ESS]"); 1632 if (ret < 0 || ret >= end - pos) 1633 return -1; 1634 pos += ret; 1635 } 1636 if (p2p) { 1637 ret = os_snprintf(pos, end - pos, "[P2P]"); 1638 if (ret < 0 || ret >= end - pos) 1639 return -1; 1640 pos += ret; 1641 } 1642#ifdef CONFIG_HS20 1643 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 1644 ret = os_snprintf(pos, end - pos, "[HS20]"); 1645 if (ret < 0 || ret >= end - pos) 1646 return -1; 1647 pos += ret; 1648 } 1649#endif /* CONFIG_HS20 */ 1650 1651 ret = os_snprintf(pos, end - pos, "\t%s", 1652 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 1653 if (ret < 0 || ret >= end - pos) 1654 return -1; 1655 pos += ret; 1656 1657 ret = os_snprintf(pos, end - pos, "\n"); 1658 if (ret < 0 || ret >= end - pos) 1659 return -1; 1660 pos += ret; 1661 1662 return pos - buf; 1663} 1664 1665 1666static int wpa_supplicant_ctrl_iface_scan_results( 1667 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1668{ 1669 char *pos, *end; 1670 struct wpa_bss *bss; 1671 int ret; 1672 1673 pos = buf; 1674 end = buf + buflen; 1675 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 1676 "flags / ssid\n"); 1677 if (ret < 0 || ret >= end - pos) 1678 return pos - buf; 1679 pos += ret; 1680 1681 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 1682 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 1683 end - pos); 1684 if (ret < 0 || ret >= end - pos) 1685 return pos - buf; 1686 pos += ret; 1687 } 1688 1689 return pos - buf; 1690} 1691 1692 1693static int wpa_supplicant_ctrl_iface_select_network( 1694 struct wpa_supplicant *wpa_s, char *cmd) 1695{ 1696 int id; 1697 struct wpa_ssid *ssid; 1698 1699 /* cmd: "<network id>" or "any" */ 1700 if (os_strcmp(cmd, "any") == 0) { 1701 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 1702 ssid = NULL; 1703 } else { 1704 id = atoi(cmd); 1705 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 1706 1707 ssid = wpa_config_get_network(wpa_s->conf, id); 1708 if (ssid == NULL) { 1709 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1710 "network id=%d", id); 1711 return -1; 1712 } 1713 if (ssid->disabled == 2) { 1714 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1715 "SELECT_NETWORK with persistent P2P group"); 1716 return -1; 1717 } 1718 } 1719 1720 wpa_supplicant_select_network(wpa_s, ssid); 1721 1722 return 0; 1723} 1724 1725 1726static int wpa_supplicant_ctrl_iface_enable_network( 1727 struct wpa_supplicant *wpa_s, char *cmd) 1728{ 1729 int id; 1730 struct wpa_ssid *ssid; 1731 1732 /* cmd: "<network id>" or "all" */ 1733 if (os_strcmp(cmd, "all") == 0) { 1734 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 1735 ssid = NULL; 1736 } else { 1737 id = atoi(cmd); 1738 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 1739 1740 ssid = wpa_config_get_network(wpa_s->conf, id); 1741 if (ssid == NULL) { 1742 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1743 "network id=%d", id); 1744 return -1; 1745 } 1746 if (ssid->disabled == 2) { 1747 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1748 "ENABLE_NETWORK with persistent P2P group"); 1749 return -1; 1750 } 1751 1752 if (os_strstr(cmd, " no-connect")) { 1753 ssid->disabled = 0; 1754 return 0; 1755 } 1756 } 1757 wpa_supplicant_enable_network(wpa_s, ssid); 1758 1759 return 0; 1760} 1761 1762 1763static int wpa_supplicant_ctrl_iface_disable_network( 1764 struct wpa_supplicant *wpa_s, char *cmd) 1765{ 1766 int id; 1767 struct wpa_ssid *ssid; 1768 1769 /* cmd: "<network id>" or "all" */ 1770 if (os_strcmp(cmd, "all") == 0) { 1771 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 1772 ssid = NULL; 1773 } else { 1774 id = atoi(cmd); 1775 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 1776 1777 ssid = wpa_config_get_network(wpa_s->conf, id); 1778 if (ssid == NULL) { 1779 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1780 "network id=%d", id); 1781 return -1; 1782 } 1783 if (ssid->disabled == 2) { 1784 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1785 "DISABLE_NETWORK with persistent P2P " 1786 "group"); 1787 return -1; 1788 } 1789 } 1790 wpa_supplicant_disable_network(wpa_s, ssid); 1791 1792 return 0; 1793} 1794 1795 1796static int wpa_supplicant_ctrl_iface_add_network( 1797 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1798{ 1799 struct wpa_ssid *ssid; 1800 int ret; 1801 1802 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 1803 1804 ssid = wpa_config_add_network(wpa_s->conf); 1805 if (ssid == NULL) 1806 return -1; 1807 1808 wpas_notify_network_added(wpa_s, ssid); 1809 1810 ssid->disabled = 1; 1811 wpa_config_set_network_defaults(ssid); 1812 1813 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 1814 if (ret < 0 || (size_t) ret >= buflen) 1815 return -1; 1816 return ret; 1817} 1818 1819 1820static int wpa_supplicant_ctrl_iface_remove_network( 1821 struct wpa_supplicant *wpa_s, char *cmd) 1822{ 1823 int id; 1824 struct wpa_ssid *ssid; 1825 1826 /* cmd: "<network id>" or "all" */ 1827 if (os_strcmp(cmd, "all") == 0) { 1828 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 1829 ssid = wpa_s->conf->ssid; 1830 while (ssid) { 1831 struct wpa_ssid *remove_ssid = ssid; 1832 id = ssid->id; 1833 ssid = ssid->next; 1834 wpas_notify_network_removed(wpa_s, remove_ssid); 1835 wpa_config_remove_network(wpa_s->conf, id); 1836 } 1837 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1838 if (wpa_s->current_ssid) { 1839#ifdef CONFIG_SME 1840 wpa_s->sme.prev_bssid_set = 0; 1841#endif /* CONFIG_SME */ 1842 wpa_sm_set_config(wpa_s->wpa, NULL); 1843 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 1844 wpa_supplicant_disassociate(wpa_s, 1845 WLAN_REASON_DEAUTH_LEAVING); 1846 } 1847 return 0; 1848 } 1849 1850 id = atoi(cmd); 1851 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 1852 1853 ssid = wpa_config_get_network(wpa_s->conf, id); 1854 if (ssid) 1855 wpas_notify_network_removed(wpa_s, ssid); 1856 if (ssid == NULL || 1857 wpa_config_remove_network(wpa_s->conf, id) < 0) { 1858 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1859 "id=%d", id); 1860 return -1; 1861 } 1862 1863 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) { 1864#ifdef CONFIG_SME 1865 wpa_s->sme.prev_bssid_set = 0; 1866#endif /* CONFIG_SME */ 1867 /* 1868 * Invalidate the EAP session cache if the current or 1869 * previously used network is removed. 1870 */ 1871 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1872 } 1873 1874 if (ssid == wpa_s->current_ssid) { 1875 wpa_sm_set_config(wpa_s->wpa, NULL); 1876 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 1877 1878 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1879 } 1880 1881 return 0; 1882} 1883 1884 1885static int wpa_supplicant_ctrl_iface_set_network( 1886 struct wpa_supplicant *wpa_s, char *cmd) 1887{ 1888 int id; 1889 struct wpa_ssid *ssid; 1890 char *name, *value; 1891 1892 /* cmd: "<network id> <variable name> <value>" */ 1893 name = os_strchr(cmd, ' '); 1894 if (name == NULL) 1895 return -1; 1896 *name++ = '\0'; 1897 1898 value = os_strchr(name, ' '); 1899 if (value == NULL) 1900 return -1; 1901 *value++ = '\0'; 1902 1903 id = atoi(cmd); 1904 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 1905 id, name); 1906 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1907 (u8 *) value, os_strlen(value)); 1908 1909 ssid = wpa_config_get_network(wpa_s->conf, id); 1910 if (ssid == NULL) { 1911 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1912 "id=%d", id); 1913 return -1; 1914 } 1915 1916 if (wpa_config_set(ssid, name, value, 0) < 0) { 1917 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 1918 "variable '%s'", name); 1919 return -1; 1920 } 1921 1922 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 1923 1924 if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) { 1925 /* 1926 * Invalidate the EAP session cache if anything in the current 1927 * or previously used configuration changes. 1928 */ 1929 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1930 } 1931 1932 if ((os_strcmp(name, "psk") == 0 && 1933 value[0] == '"' && ssid->ssid_len) || 1934 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 1935 wpa_config_update_psk(ssid); 1936 else if (os_strcmp(name, "priority") == 0) 1937 wpa_config_update_prio_list(wpa_s->conf); 1938 1939 return 0; 1940} 1941 1942 1943static int wpa_supplicant_ctrl_iface_get_network( 1944 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1945{ 1946 int id; 1947 size_t res; 1948 struct wpa_ssid *ssid; 1949 char *name, *value; 1950 1951 /* cmd: "<network id> <variable name>" */ 1952 name = os_strchr(cmd, ' '); 1953 if (name == NULL || buflen == 0) 1954 return -1; 1955 *name++ = '\0'; 1956 1957 id = atoi(cmd); 1958 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 1959 id, name); 1960 1961 ssid = wpa_config_get_network(wpa_s->conf, id); 1962 if (ssid == NULL) { 1963 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1964 "id=%d", id); 1965 return -1; 1966 } 1967 1968 value = wpa_config_get_no_key(ssid, name); 1969 if (value == NULL) { 1970 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 1971 "variable '%s'", name); 1972 return -1; 1973 } 1974 1975 res = os_strlcpy(buf, value, buflen); 1976 if (res >= buflen) { 1977 os_free(value); 1978 return -1; 1979 } 1980 1981 os_free(value); 1982 1983 return res; 1984} 1985 1986 1987static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 1988 char *buf, size_t buflen) 1989{ 1990 char *pos, *end; 1991 struct wpa_cred *cred; 1992 int ret; 1993 1994 pos = buf; 1995 end = buf + buflen; 1996 ret = os_snprintf(pos, end - pos, 1997 "cred id / realm / username / domain / imsi\n"); 1998 if (ret < 0 || ret >= end - pos) 1999 return pos - buf; 2000 pos += ret; 2001 2002 cred = wpa_s->conf->cred; 2003 while (cred) { 2004 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 2005 cred->id, cred->realm ? cred->realm : "", 2006 cred->username ? cred->username : "", 2007 cred->domain ? cred->domain : "", 2008 cred->imsi ? cred->imsi : ""); 2009 if (ret < 0 || ret >= end - pos) 2010 return pos - buf; 2011 pos += ret; 2012 2013 cred = cred->next; 2014 } 2015 2016 return pos - buf; 2017} 2018 2019 2020static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 2021 char *buf, size_t buflen) 2022{ 2023 struct wpa_cred *cred; 2024 int ret; 2025 2026 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 2027 2028 cred = wpa_config_add_cred(wpa_s->conf); 2029 if (cred == NULL) 2030 return -1; 2031 2032 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 2033 if (ret < 0 || (size_t) ret >= buflen) 2034 return -1; 2035 return ret; 2036} 2037 2038 2039static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 2040 char *cmd) 2041{ 2042 int id; 2043 struct wpa_cred *cred; 2044 2045 /* cmd: "<cred id>" or "all" */ 2046 if (os_strcmp(cmd, "all") == 0) { 2047 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 2048 cred = wpa_s->conf->cred; 2049 while (cred) { 2050 id = cred->id; 2051 cred = cred->next; 2052 wpa_config_remove_cred(wpa_s->conf, id); 2053 } 2054 return 0; 2055 } 2056 2057 id = atoi(cmd); 2058 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 2059 2060 cred = wpa_config_get_cred(wpa_s->conf, id); 2061 if (cred == NULL || 2062 wpa_config_remove_cred(wpa_s->conf, id) < 0) { 2063 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2064 id); 2065 return -1; 2066 } 2067 2068 return 0; 2069} 2070 2071 2072static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 2073 char *cmd) 2074{ 2075 int id; 2076 struct wpa_cred *cred; 2077 char *name, *value; 2078 2079 /* cmd: "<cred id> <variable name> <value>" */ 2080 name = os_strchr(cmd, ' '); 2081 if (name == NULL) 2082 return -1; 2083 *name++ = '\0'; 2084 2085 value = os_strchr(name, ' '); 2086 if (value == NULL) 2087 return -1; 2088 *value++ = '\0'; 2089 2090 id = atoi(cmd); 2091 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 2092 id, name); 2093 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2094 (u8 *) value, os_strlen(value)); 2095 2096 cred = wpa_config_get_cred(wpa_s->conf, id); 2097 if (cred == NULL) { 2098 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2099 id); 2100 return -1; 2101 } 2102 2103 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 2104 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 2105 "variable '%s'", name); 2106 return -1; 2107 } 2108 2109 return 0; 2110} 2111 2112 2113#ifndef CONFIG_NO_CONFIG_WRITE 2114static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 2115{ 2116 int ret; 2117 2118 if (!wpa_s->conf->update_config) { 2119 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 2120 "to update configuration (update_config=0)"); 2121 return -1; 2122 } 2123 2124 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 2125 if (ret) { 2126 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 2127 "update configuration"); 2128 } else { 2129 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 2130 " updated"); 2131 } 2132 2133 return ret; 2134} 2135#endif /* CONFIG_NO_CONFIG_WRITE */ 2136 2137 2138static int ctrl_iface_get_capability_pairwise(int res, char *strict, 2139 struct wpa_driver_capa *capa, 2140 char *buf, size_t buflen) 2141{ 2142 int ret, first = 1; 2143 char *pos, *end; 2144 size_t len; 2145 2146 pos = buf; 2147 end = pos + buflen; 2148 2149 if (res < 0) { 2150 if (strict) 2151 return 0; 2152 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 2153 if (len >= buflen) 2154 return -1; 2155 return len; 2156 } 2157 2158 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2159 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2160 if (ret < 0 || ret >= end - pos) 2161 return pos - buf; 2162 pos += ret; 2163 first = 0; 2164 } 2165 2166 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2167 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2168 if (ret < 0 || ret >= end - pos) 2169 return pos - buf; 2170 pos += ret; 2171 first = 0; 2172 } 2173 2174 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2175 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 2176 if (ret < 0 || ret >= end - pos) 2177 return pos - buf; 2178 pos += ret; 2179 first = 0; 2180 } 2181 2182 return pos - buf; 2183} 2184 2185 2186static int ctrl_iface_get_capability_group(int res, char *strict, 2187 struct wpa_driver_capa *capa, 2188 char *buf, size_t buflen) 2189{ 2190 int ret, first = 1; 2191 char *pos, *end; 2192 size_t len; 2193 2194 pos = buf; 2195 end = pos + buflen; 2196 2197 if (res < 0) { 2198 if (strict) 2199 return 0; 2200 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 2201 if (len >= buflen) 2202 return -1; 2203 return len; 2204 } 2205 2206 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2207 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2208 if (ret < 0 || ret >= end - pos) 2209 return pos - buf; 2210 pos += ret; 2211 first = 0; 2212 } 2213 2214 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2215 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2216 if (ret < 0 || ret >= end - pos) 2217 return pos - buf; 2218 pos += ret; 2219 first = 0; 2220 } 2221 2222 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 2223 ret = os_snprintf(pos, end - pos, "%sWEP104", 2224 first ? "" : " "); 2225 if (ret < 0 || ret >= end - pos) 2226 return pos - buf; 2227 pos += ret; 2228 first = 0; 2229 } 2230 2231 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 2232 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 2233 if (ret < 0 || ret >= end - pos) 2234 return pos - buf; 2235 pos += ret; 2236 first = 0; 2237 } 2238 2239 return pos - buf; 2240} 2241 2242 2243static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 2244 struct wpa_driver_capa *capa, 2245 char *buf, size_t buflen) 2246{ 2247 int ret; 2248 char *pos, *end; 2249 size_t len; 2250 2251 pos = buf; 2252 end = pos + buflen; 2253 2254 if (res < 0) { 2255 if (strict) 2256 return 0; 2257 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 2258 "NONE", buflen); 2259 if (len >= buflen) 2260 return -1; 2261 return len; 2262 } 2263 2264 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 2265 if (ret < 0 || ret >= end - pos) 2266 return pos - buf; 2267 pos += ret; 2268 2269 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2270 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2271 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 2272 if (ret < 0 || ret >= end - pos) 2273 return pos - buf; 2274 pos += ret; 2275 } 2276 2277 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2278 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2279 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 2280 if (ret < 0 || ret >= end - pos) 2281 return pos - buf; 2282 pos += ret; 2283 } 2284 2285 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2286 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 2287 if (ret < 0 || ret >= end - pos) 2288 return pos - buf; 2289 pos += ret; 2290 } 2291 2292 return pos - buf; 2293} 2294 2295 2296static int ctrl_iface_get_capability_proto(int res, char *strict, 2297 struct wpa_driver_capa *capa, 2298 char *buf, size_t buflen) 2299{ 2300 int ret, first = 1; 2301 char *pos, *end; 2302 size_t len; 2303 2304 pos = buf; 2305 end = pos + buflen; 2306 2307 if (res < 0) { 2308 if (strict) 2309 return 0; 2310 len = os_strlcpy(buf, "RSN WPA", buflen); 2311 if (len >= buflen) 2312 return -1; 2313 return len; 2314 } 2315 2316 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2317 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2318 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 2319 if (ret < 0 || ret >= end - pos) 2320 return pos - buf; 2321 pos += ret; 2322 first = 0; 2323 } 2324 2325 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2326 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 2327 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 2328 if (ret < 0 || ret >= end - pos) 2329 return pos - buf; 2330 pos += ret; 2331 first = 0; 2332 } 2333 2334 return pos - buf; 2335} 2336 2337 2338static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 2339 struct wpa_driver_capa *capa, 2340 char *buf, size_t buflen) 2341{ 2342 int ret, first = 1; 2343 char *pos, *end; 2344 size_t len; 2345 2346 pos = buf; 2347 end = pos + buflen; 2348 2349 if (res < 0) { 2350 if (strict) 2351 return 0; 2352 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 2353 if (len >= buflen) 2354 return -1; 2355 return len; 2356 } 2357 2358 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 2359 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 2360 if (ret < 0 || ret >= end - pos) 2361 return pos - buf; 2362 pos += ret; 2363 first = 0; 2364 } 2365 2366 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 2367 ret = os_snprintf(pos, end - pos, "%sSHARED", 2368 first ? "" : " "); 2369 if (ret < 0 || ret >= end - pos) 2370 return pos - buf; 2371 pos += ret; 2372 first = 0; 2373 } 2374 2375 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 2376 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 2377 if (ret < 0 || ret >= end - pos) 2378 return pos - buf; 2379 pos += ret; 2380 first = 0; 2381 } 2382 2383 return pos - buf; 2384} 2385 2386 2387static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 2388 char *buf, size_t buflen) 2389{ 2390 struct hostapd_channel_data *chnl; 2391 int ret, i, j; 2392 char *pos, *end, *hmode; 2393 2394 pos = buf; 2395 end = pos + buflen; 2396 2397 for (j = 0; j < wpa_s->hw.num_modes; j++) { 2398 switch (wpa_s->hw.modes[j].mode) { 2399 case HOSTAPD_MODE_IEEE80211B: 2400 hmode = "B"; 2401 break; 2402 case HOSTAPD_MODE_IEEE80211G: 2403 hmode = "G"; 2404 break; 2405 case HOSTAPD_MODE_IEEE80211A: 2406 hmode = "A"; 2407 break; 2408 default: 2409 return pos - buf; 2410 } 2411 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 2412 if (ret < 0 || ret >= end - pos) 2413 return pos - buf; 2414 pos += ret; 2415 chnl = wpa_s->hw.modes[j].channels; 2416 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 2417 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 2418 if (ret < 0 || ret >= end - pos) 2419 return pos - buf; 2420 pos += ret; 2421 } 2422 ret = os_snprintf(pos, end - pos, "\n"); 2423 if (ret < 0 || ret >= end - pos) 2424 return pos - buf; 2425 pos += ret; 2426 } 2427 2428 return pos - buf; 2429} 2430 2431 2432static int wpa_supplicant_ctrl_iface_get_capability( 2433 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 2434 size_t buflen) 2435{ 2436 struct wpa_driver_capa capa; 2437 int res; 2438 char *strict; 2439 char field[30]; 2440 size_t len; 2441 2442 /* Determine whether or not strict checking was requested */ 2443 len = os_strlcpy(field, _field, sizeof(field)); 2444 if (len >= sizeof(field)) 2445 return -1; 2446 strict = os_strchr(field, ' '); 2447 if (strict != NULL) { 2448 *strict++ = '\0'; 2449 if (os_strcmp(strict, "strict") != 0) 2450 return -1; 2451 } 2452 2453 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 2454 field, strict ? strict : ""); 2455 2456 if (os_strcmp(field, "eap") == 0) { 2457 return eap_get_names(buf, buflen); 2458 } 2459 2460 res = wpa_drv_get_capa(wpa_s, &capa); 2461 2462 if (os_strcmp(field, "pairwise") == 0) 2463 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 2464 buf, buflen); 2465 2466 if (os_strcmp(field, "group") == 0) 2467 return ctrl_iface_get_capability_group(res, strict, &capa, 2468 buf, buflen); 2469 2470 if (os_strcmp(field, "key_mgmt") == 0) 2471 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 2472 buf, buflen); 2473 2474 if (os_strcmp(field, "proto") == 0) 2475 return ctrl_iface_get_capability_proto(res, strict, &capa, 2476 buf, buflen); 2477 2478 if (os_strcmp(field, "auth_alg") == 0) 2479 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 2480 buf, buflen); 2481 2482 if (os_strcmp(field, "channels") == 0) 2483 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 2484 2485 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 2486 field); 2487 2488 return -1; 2489} 2490 2491 2492#ifdef CONFIG_INTERWORKING 2493static char * anqp_add_hex(char *pos, char *end, const char *title, 2494 struct wpabuf *data) 2495{ 2496 char *start = pos; 2497 size_t i; 2498 int ret; 2499 const u8 *d; 2500 2501 if (data == NULL) 2502 return start; 2503 2504 ret = os_snprintf(pos, end - pos, "%s=", title); 2505 if (ret < 0 || ret >= end - pos) 2506 return start; 2507 pos += ret; 2508 2509 d = wpabuf_head_u8(data); 2510 for (i = 0; i < wpabuf_len(data); i++) { 2511 ret = os_snprintf(pos, end - pos, "%02x", *d++); 2512 if (ret < 0 || ret >= end - pos) 2513 return start; 2514 pos += ret; 2515 } 2516 2517 ret = os_snprintf(pos, end - pos, "\n"); 2518 if (ret < 0 || ret >= end - pos) 2519 return start; 2520 pos += ret; 2521 2522 return pos; 2523} 2524#endif /* CONFIG_INTERWORKING */ 2525 2526 2527static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 2528 unsigned long mask, char *buf, size_t buflen) 2529{ 2530 size_t i; 2531 int ret; 2532 char *pos, *end; 2533 const u8 *ie, *ie2; 2534 2535 pos = buf; 2536 end = buf + buflen; 2537 2538 if (mask & WPA_BSS_MASK_ID) { 2539 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 2540 if (ret < 0 || ret >= end - pos) 2541 return 0; 2542 pos += ret; 2543 } 2544 2545 if (mask & WPA_BSS_MASK_BSSID) { 2546 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2547 MAC2STR(bss->bssid)); 2548 if (ret < 0 || ret >= end - pos) 2549 return 0; 2550 pos += ret; 2551 } 2552 2553 if (mask & WPA_BSS_MASK_FREQ) { 2554 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 2555 if (ret < 0 || ret >= end - pos) 2556 return 0; 2557 pos += ret; 2558 } 2559 2560 if (mask & WPA_BSS_MASK_BEACON_INT) { 2561 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 2562 bss->beacon_int); 2563 if (ret < 0 || ret >= end - pos) 2564 return 0; 2565 pos += ret; 2566 } 2567 2568 if (mask & WPA_BSS_MASK_CAPABILITIES) { 2569 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 2570 bss->caps); 2571 if (ret < 0 || ret >= end - pos) 2572 return 0; 2573 pos += ret; 2574 } 2575 2576 if (mask & WPA_BSS_MASK_QUAL) { 2577 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 2578 if (ret < 0 || ret >= end - pos) 2579 return 0; 2580 pos += ret; 2581 } 2582 2583 if (mask & WPA_BSS_MASK_NOISE) { 2584 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 2585 if (ret < 0 || ret >= end - pos) 2586 return 0; 2587 pos += ret; 2588 } 2589 2590 if (mask & WPA_BSS_MASK_LEVEL) { 2591 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 2592 if (ret < 0 || ret >= end - pos) 2593 return 0; 2594 pos += ret; 2595 } 2596 2597 if (mask & WPA_BSS_MASK_TSF) { 2598 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 2599 (unsigned long long) bss->tsf); 2600 if (ret < 0 || ret >= end - pos) 2601 return 0; 2602 pos += ret; 2603 } 2604 2605 if (mask & WPA_BSS_MASK_AGE) { 2606 struct os_time now; 2607 2608 os_get_time(&now); 2609 ret = os_snprintf(pos, end - pos, "age=%d\n", 2610 (int) (now.sec - bss->last_update.sec)); 2611 if (ret < 0 || ret >= end - pos) 2612 return 0; 2613 pos += ret; 2614 } 2615 2616 if (mask & WPA_BSS_MASK_IE) { 2617 ret = os_snprintf(pos, end - pos, "ie="); 2618 if (ret < 0 || ret >= end - pos) 2619 return 0; 2620 pos += ret; 2621 2622 ie = (const u8 *) (bss + 1); 2623 for (i = 0; i < bss->ie_len; i++) { 2624 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 2625 if (ret < 0 || ret >= end - pos) 2626 return 0; 2627 pos += ret; 2628 } 2629 2630 ret = os_snprintf(pos, end - pos, "\n"); 2631 if (ret < 0 || ret >= end - pos) 2632 return 0; 2633 pos += ret; 2634 } 2635 2636 if (mask & WPA_BSS_MASK_FLAGS) { 2637 ret = os_snprintf(pos, end - pos, "flags="); 2638 if (ret < 0 || ret >= end - pos) 2639 return 0; 2640 pos += ret; 2641 2642 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 2643 if (ie) 2644 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2645 2 + ie[1]); 2646 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 2647 if (ie2) 2648 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2649 2 + ie2[1]); 2650 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 2651 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 2652 ret = os_snprintf(pos, end - pos, "[WEP]"); 2653 if (ret < 0 || ret >= end - pos) 2654 return 0; 2655 pos += ret; 2656 } 2657 if (bss->caps & IEEE80211_CAP_IBSS) { 2658 ret = os_snprintf(pos, end - pos, "[IBSS]"); 2659 if (ret < 0 || ret >= end - pos) 2660 return 0; 2661 pos += ret; 2662 } 2663 if (bss->caps & IEEE80211_CAP_ESS) { 2664 ret = os_snprintf(pos, end - pos, "[ESS]"); 2665 if (ret < 0 || ret >= end - pos) 2666 return 0; 2667 pos += ret; 2668 } 2669 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { 2670 ret = os_snprintf(pos, end - pos, "[P2P]"); 2671 if (ret < 0 || ret >= end - pos) 2672 return 0; 2673 pos += ret; 2674 } 2675#ifdef CONFIG_HS20 2676 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 2677 ret = os_snprintf(pos, end - pos, "[HS20]"); 2678 if (ret < 0 || ret >= end - pos) 2679 return -1; 2680 pos += ret; 2681 } 2682#endif /* CONFIG_HS20 */ 2683 2684 ret = os_snprintf(pos, end - pos, "\n"); 2685 if (ret < 0 || ret >= end - pos) 2686 return 0; 2687 pos += ret; 2688 } 2689 2690 if (mask & WPA_BSS_MASK_SSID) { 2691 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 2692 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 2693 if (ret < 0 || ret >= end - pos) 2694 return 0; 2695 pos += ret; 2696 } 2697 2698#ifdef CONFIG_WPS 2699 if (mask & WPA_BSS_MASK_WPS_SCAN) { 2700 ie = (const u8 *) (bss + 1); 2701 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 2702 if (ret < 0 || ret >= end - pos) 2703 return 0; 2704 pos += ret; 2705 } 2706#endif /* CONFIG_WPS */ 2707 2708#ifdef CONFIG_P2P 2709 if (mask & WPA_BSS_MASK_P2P_SCAN) { 2710 ie = (const u8 *) (bss + 1); 2711 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 2712 if (ret < 0 || ret >= end - pos) 2713 return 0; 2714 pos += ret; 2715 } 2716#endif /* CONFIG_P2P */ 2717 2718#ifdef CONFIG_INTERWORKING 2719 if (mask & WPA_BSS_MASK_INTERNETW) { 2720 pos = anqp_add_hex(pos, end, "anqp_venue_name", 2721 bss->anqp_venue_name); 2722 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 2723 bss->anqp_network_auth_type); 2724 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 2725 bss->anqp_roaming_consortium); 2726 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 2727 bss->anqp_ip_addr_type_availability); 2728 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 2729 bss->anqp_nai_realm); 2730 pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp); 2731 pos = anqp_add_hex(pos, end, "anqp_domain_name", 2732 bss->anqp_domain_name); 2733#ifdef CONFIG_HS20 2734 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 2735 bss->hs20_operator_friendly_name); 2736 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 2737 bss->hs20_wan_metrics); 2738 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 2739 bss->hs20_connection_capability); 2740#endif /* CONFIG_HS20 */ 2741 } 2742#endif /* CONFIG_INTERWORKING */ 2743 2744#ifdef ANDROID 2745 ret = os_snprintf(pos, end - pos, "====\n"); 2746 if (ret < 0 || ret >= end - pos) 2747 return 0; 2748 pos += ret; 2749#endif 2750 2751 return pos - buf; 2752} 2753 2754 2755static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 2756 const char *cmd, char *buf, 2757 size_t buflen) 2758{ 2759 u8 bssid[ETH_ALEN]; 2760 size_t i; 2761 struct wpa_bss *bss; 2762 struct wpa_bss *bsslast = NULL; 2763 struct dl_list *next; 2764 int ret = 0; 2765 int len; 2766 char *ctmp; 2767 unsigned long mask = WPA_BSS_MASK_ALL; 2768 2769 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 2770 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 2771 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 2772 list_id); 2773 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 2774 list_id); 2775 } else { /* N1-N2 */ 2776 unsigned int id1, id2; 2777 2778 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 2779 wpa_printf(MSG_INFO, "Wrong BSS range " 2780 "format"); 2781 return 0; 2782 } 2783 2784 id1 = atoi(cmd + 6); 2785 bss = wpa_bss_get_id(wpa_s, id1); 2786 id2 = atoi(ctmp + 1); 2787 if (id2 == 0) 2788 bsslast = dl_list_last(&wpa_s->bss_id, 2789 struct wpa_bss, 2790 list_id); 2791 else { 2792 bsslast = wpa_bss_get_id(wpa_s, id2); 2793 if (bsslast == NULL && bss && id2 > id1) { 2794 struct wpa_bss *tmp = bss; 2795 for (;;) { 2796 next = tmp->list_id.next; 2797 if (next == &wpa_s->bss_id) 2798 break; 2799 tmp = dl_list_entry( 2800 next, struct wpa_bss, 2801 list_id); 2802 if (tmp->id > id2) 2803 break; 2804 bsslast = tmp; 2805 } 2806 } 2807 } 2808 } 2809 } else if (os_strcmp(cmd, "FIRST") == 0) 2810 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 2811 else if (os_strncmp(cmd, "ID-", 3) == 0) { 2812 i = atoi(cmd + 3); 2813 bss = wpa_bss_get_id(wpa_s, i); 2814 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 2815 i = atoi(cmd + 5); 2816 bss = wpa_bss_get_id(wpa_s, i); 2817 if (bss) { 2818 next = bss->list_id.next; 2819 if (next == &wpa_s->bss_id) 2820 bss = NULL; 2821 else 2822 bss = dl_list_entry(next, struct wpa_bss, 2823 list_id); 2824 } 2825#ifdef CONFIG_P2P 2826 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 2827 if (hwaddr_aton(cmd + 13, bssid) == 0) 2828 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 2829 else 2830 bss = NULL; 2831#endif /* CONFIG_P2P */ 2832 } else if (hwaddr_aton(cmd, bssid) == 0) 2833 bss = wpa_bss_get_bssid(wpa_s, bssid); 2834 else { 2835 struct wpa_bss *tmp; 2836 i = atoi(cmd); 2837 bss = NULL; 2838 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 2839 { 2840 if (i-- == 0) { 2841 bss = tmp; 2842 break; 2843 } 2844 } 2845 } 2846 2847 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 2848 mask = strtoul(ctmp + 5, NULL, 0x10); 2849 if (mask == 0) 2850 mask = WPA_BSS_MASK_ALL; 2851 } 2852 2853 if (bss == NULL) 2854 return 0; 2855 2856 if (bsslast == NULL) 2857 bsslast = bss; 2858 do { 2859 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 2860 ret += len; 2861 buf += len; 2862 buflen -= len; 2863 if (bss == bsslast) 2864 break; 2865 next = bss->list_id.next; 2866 if (next == &wpa_s->bss_id) 2867 break; 2868 bss = dl_list_entry(next, struct wpa_bss, list_id); 2869 } while (bss && len); 2870 2871 return ret; 2872} 2873 2874 2875static int wpa_supplicant_ctrl_iface_ap_scan( 2876 struct wpa_supplicant *wpa_s, char *cmd) 2877{ 2878 int ap_scan = atoi(cmd); 2879 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 2880} 2881 2882 2883static int wpa_supplicant_ctrl_iface_scan_interval( 2884 struct wpa_supplicant *wpa_s, char *cmd) 2885{ 2886 int scan_int = atoi(cmd); 2887 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 2888} 2889 2890 2891static int wpa_supplicant_ctrl_iface_bss_expire_age( 2892 struct wpa_supplicant *wpa_s, char *cmd) 2893{ 2894 int expire_age = atoi(cmd); 2895 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 2896} 2897 2898 2899static int wpa_supplicant_ctrl_iface_bss_expire_count( 2900 struct wpa_supplicant *wpa_s, char *cmd) 2901{ 2902 int expire_count = atoi(cmd); 2903 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 2904} 2905 2906 2907static int wpa_supplicant_ctrl_iface_bss_flush( 2908 struct wpa_supplicant *wpa_s, char *cmd) 2909{ 2910 int flush_age = atoi(cmd); 2911 2912 if (flush_age == 0) 2913 wpa_bss_flush(wpa_s); 2914 else 2915 wpa_bss_flush_by_age(wpa_s, flush_age); 2916 return 0; 2917} 2918 2919 2920static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 2921{ 2922 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 2923 /* MLME-DELETEKEYS.request */ 2924 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 2925 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 2926 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 2927 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 2928#ifdef CONFIG_IEEE80211W 2929 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 2930 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 2931#endif /* CONFIG_IEEE80211W */ 2932 2933 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 2934 0); 2935 /* MLME-SETPROTECTION.request(None) */ 2936 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 2937 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 2938 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 2939 wpa_sm_drop_sa(wpa_s->wpa); 2940} 2941 2942 2943static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 2944 char *addr) 2945{ 2946#ifdef CONFIG_NO_SCAN_PROCESSING 2947 return -1; 2948#else /* CONFIG_NO_SCAN_PROCESSING */ 2949 u8 bssid[ETH_ALEN]; 2950 struct wpa_bss *bss; 2951 struct wpa_ssid *ssid = wpa_s->current_ssid; 2952 2953 if (hwaddr_aton(addr, bssid)) { 2954 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 2955 "address '%s'", addr); 2956 return -1; 2957 } 2958 2959 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 2960 2961 bss = wpa_bss_get_bssid(wpa_s, bssid); 2962 if (!bss) { 2963 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 2964 "from BSS table"); 2965 return -1; 2966 } 2967 2968 /* 2969 * TODO: Find best network configuration block from configuration to 2970 * allow roaming to other networks 2971 */ 2972 2973 if (!ssid) { 2974 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 2975 "configuration known for the target AP"); 2976 return -1; 2977 } 2978 2979 wpa_s->reassociate = 1; 2980 wpa_supplicant_connect(wpa_s, bss, ssid); 2981 2982 return 0; 2983#endif /* CONFIG_NO_SCAN_PROCESSING */ 2984} 2985 2986 2987#ifdef CONFIG_P2P 2988static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 2989{ 2990 unsigned int timeout = atoi(cmd); 2991 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 2992 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 2993 char *pos; 2994 2995 if (os_strstr(cmd, "type=social")) 2996 type = P2P_FIND_ONLY_SOCIAL; 2997 else if (os_strstr(cmd, "type=progressive")) 2998 type = P2P_FIND_PROGRESSIVE; 2999 3000 pos = os_strstr(cmd, "dev_id="); 3001 if (pos) { 3002 pos += 7; 3003 if (hwaddr_aton(pos, dev_id)) 3004 return -1; 3005 _dev_id = dev_id; 3006 } 3007 3008 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id); 3009} 3010 3011 3012static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 3013 char *buf, size_t buflen) 3014{ 3015 u8 addr[ETH_ALEN]; 3016 char *pos, *pos2; 3017 char *pin = NULL; 3018 enum p2p_wps_method wps_method; 3019 int new_pin; 3020 int ret; 3021 int persistent_group, persistent_id = -1; 3022 int join; 3023 int auth; 3024 int automatic; 3025 int go_intent = -1; 3026 int freq = 0; 3027 int pd; 3028 3029 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] 3030 * [persistent|persistent=<network id>] 3031 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] */ 3032 3033 if (hwaddr_aton(cmd, addr)) 3034 return -1; 3035 3036 pos = cmd + 17; 3037 if (*pos != ' ') 3038 return -1; 3039 pos++; 3040 3041 persistent_group = os_strstr(pos, " persistent") != NULL; 3042 pos2 = os_strstr(pos, " persistent="); 3043 if (pos2) { 3044 struct wpa_ssid *ssid; 3045 persistent_id = atoi(pos2 + 12); 3046 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 3047 if (ssid == NULL || ssid->disabled != 2 || 3048 ssid->mode != WPAS_MODE_P2P_GO) { 3049 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3050 "SSID id=%d for persistent P2P group (GO)", 3051 persistent_id); 3052 return -1; 3053 } 3054 } 3055 join = os_strstr(pos, " join") != NULL; 3056 auth = os_strstr(pos, " auth") != NULL; 3057 automatic = os_strstr(pos, " auto") != NULL; 3058 pd = os_strstr(pos, " provdisc") != NULL; 3059 3060 pos2 = os_strstr(pos, " go_intent="); 3061 if (pos2) { 3062 pos2 += 11; 3063 go_intent = atoi(pos2); 3064 if (go_intent < 0 || go_intent > 15) 3065 return -1; 3066 } 3067 3068 pos2 = os_strstr(pos, " freq="); 3069 if (pos2) { 3070 pos2 += 6; 3071 freq = atoi(pos2); 3072 if (freq <= 0) 3073 return -1; 3074 } 3075 3076 if (os_strncmp(pos, "pin", 3) == 0) { 3077 /* Request random PIN (to be displayed) and enable the PIN */ 3078 wps_method = WPS_PIN_DISPLAY; 3079 } else if (os_strncmp(pos, "pbc", 3) == 0) { 3080 wps_method = WPS_PBC; 3081 } else { 3082 pin = pos; 3083 pos = os_strchr(pin, ' '); 3084 wps_method = WPS_PIN_KEYPAD; 3085 if (pos) { 3086 *pos++ = '\0'; 3087 if (os_strncmp(pos, "display", 7) == 0) 3088 wps_method = WPS_PIN_DISPLAY; 3089 } 3090 if (!wps_pin_str_valid(pin)) { 3091 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 3092 return 17; 3093 } 3094 } 3095 3096 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 3097 persistent_group, automatic, join, 3098 auth, go_intent, freq, persistent_id, pd); 3099 if (new_pin == -2) { 3100 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 3101 return 25; 3102 } 3103 if (new_pin == -3) { 3104 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 3105 return 25; 3106 } 3107 if (new_pin < 0) 3108 return -1; 3109 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 3110 ret = os_snprintf(buf, buflen, "%08d", new_pin); 3111 if (ret < 0 || (size_t) ret >= buflen) 3112 return -1; 3113 return ret; 3114 } 3115 3116 os_memcpy(buf, "OK\n", 3); 3117 return 3; 3118} 3119 3120 3121static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 3122{ 3123 unsigned int timeout = atoi(cmd); 3124 return wpas_p2p_listen(wpa_s, timeout); 3125} 3126 3127 3128static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 3129{ 3130 u8 addr[ETH_ALEN]; 3131 char *pos; 3132 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 3133 3134 /* <addr> <config method> [join|auto] */ 3135 3136 if (hwaddr_aton(cmd, addr)) 3137 return -1; 3138 3139 pos = cmd + 17; 3140 if (*pos != ' ') 3141 return -1; 3142 pos++; 3143 3144 if (os_strstr(pos, " join") != NULL) 3145 use = WPAS_P2P_PD_FOR_JOIN; 3146 else if (os_strstr(pos, " auto") != NULL) 3147 use = WPAS_P2P_PD_AUTO; 3148 3149 return wpas_p2p_prov_disc(wpa_s, addr, pos, use); 3150} 3151 3152 3153static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 3154 size_t buflen) 3155{ 3156 struct wpa_ssid *ssid = wpa_s->current_ssid; 3157 3158 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 3159 ssid->passphrase == NULL) 3160 return -1; 3161 3162 os_strlcpy(buf, ssid->passphrase, buflen); 3163 return os_strlen(buf); 3164} 3165 3166 3167static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 3168 char *buf, size_t buflen) 3169{ 3170 u64 ref; 3171 int res; 3172 u8 dst_buf[ETH_ALEN], *dst; 3173 struct wpabuf *tlvs; 3174 char *pos; 3175 size_t len; 3176 3177 if (hwaddr_aton(cmd, dst_buf)) 3178 return -1; 3179 dst = dst_buf; 3180 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 3181 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 3182 dst = NULL; 3183 pos = cmd + 17; 3184 if (*pos != ' ') 3185 return -1; 3186 pos++; 3187 3188 if (os_strncmp(pos, "upnp ", 5) == 0) { 3189 u8 version; 3190 pos += 5; 3191 if (hexstr2bin(pos, &version, 1) < 0) 3192 return -1; 3193 pos += 2; 3194 if (*pos != ' ') 3195 return -1; 3196 pos++; 3197 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 3198 } else { 3199 len = os_strlen(pos); 3200 if (len & 1) 3201 return -1; 3202 len /= 2; 3203 tlvs = wpabuf_alloc(len); 3204 if (tlvs == NULL) 3205 return -1; 3206 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 3207 wpabuf_free(tlvs); 3208 return -1; 3209 } 3210 3211 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 3212 wpabuf_free(tlvs); 3213 } 3214 if (ref == 0) 3215 return -1; 3216 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 3217 if (res < 0 || (unsigned) res >= buflen) 3218 return -1; 3219 return res; 3220} 3221 3222 3223static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 3224 char *cmd) 3225{ 3226 long long unsigned val; 3227 u64 req; 3228 if (sscanf(cmd, "%llx", &val) != 1) 3229 return -1; 3230 req = val; 3231 return wpas_p2p_sd_cancel_request(wpa_s, req); 3232} 3233 3234 3235static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 3236{ 3237 int freq; 3238 u8 dst[ETH_ALEN]; 3239 u8 dialog_token; 3240 struct wpabuf *resp_tlvs; 3241 char *pos, *pos2; 3242 size_t len; 3243 3244 pos = os_strchr(cmd, ' '); 3245 if (pos == NULL) 3246 return -1; 3247 *pos++ = '\0'; 3248 freq = atoi(cmd); 3249 if (freq == 0) 3250 return -1; 3251 3252 if (hwaddr_aton(pos, dst)) 3253 return -1; 3254 pos += 17; 3255 if (*pos != ' ') 3256 return -1; 3257 pos++; 3258 3259 pos2 = os_strchr(pos, ' '); 3260 if (pos2 == NULL) 3261 return -1; 3262 *pos2++ = '\0'; 3263 dialog_token = atoi(pos); 3264 3265 len = os_strlen(pos2); 3266 if (len & 1) 3267 return -1; 3268 len /= 2; 3269 resp_tlvs = wpabuf_alloc(len); 3270 if (resp_tlvs == NULL) 3271 return -1; 3272 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 3273 wpabuf_free(resp_tlvs); 3274 return -1; 3275 } 3276 3277 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 3278 wpabuf_free(resp_tlvs); 3279 return 0; 3280} 3281 3282 3283static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 3284 char *cmd) 3285{ 3286 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 3287 return -1; 3288 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 3289 return 0; 3290} 3291 3292 3293static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 3294 char *cmd) 3295{ 3296 char *pos; 3297 size_t len; 3298 struct wpabuf *query, *resp; 3299 3300 pos = os_strchr(cmd, ' '); 3301 if (pos == NULL) 3302 return -1; 3303 *pos++ = '\0'; 3304 3305 len = os_strlen(cmd); 3306 if (len & 1) 3307 return -1; 3308 len /= 2; 3309 query = wpabuf_alloc(len); 3310 if (query == NULL) 3311 return -1; 3312 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3313 wpabuf_free(query); 3314 return -1; 3315 } 3316 3317 len = os_strlen(pos); 3318 if (len & 1) { 3319 wpabuf_free(query); 3320 return -1; 3321 } 3322 len /= 2; 3323 resp = wpabuf_alloc(len); 3324 if (resp == NULL) { 3325 wpabuf_free(query); 3326 return -1; 3327 } 3328 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 3329 wpabuf_free(query); 3330 wpabuf_free(resp); 3331 return -1; 3332 } 3333 3334 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 3335 wpabuf_free(query); 3336 wpabuf_free(resp); 3337 return -1; 3338 } 3339 return 0; 3340} 3341 3342 3343static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3344{ 3345 char *pos; 3346 u8 version; 3347 3348 pos = os_strchr(cmd, ' '); 3349 if (pos == NULL) 3350 return -1; 3351 *pos++ = '\0'; 3352 3353 if (hexstr2bin(cmd, &version, 1) < 0) 3354 return -1; 3355 3356 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 3357} 3358 3359 3360static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 3361{ 3362 char *pos; 3363 3364 pos = os_strchr(cmd, ' '); 3365 if (pos == NULL) 3366 return -1; 3367 *pos++ = '\0'; 3368 3369 if (os_strcmp(cmd, "bonjour") == 0) 3370 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 3371 if (os_strcmp(cmd, "upnp") == 0) 3372 return p2p_ctrl_service_add_upnp(wpa_s, pos); 3373 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3374 return -1; 3375} 3376 3377 3378static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 3379 char *cmd) 3380{ 3381 size_t len; 3382 struct wpabuf *query; 3383 int ret; 3384 3385 len = os_strlen(cmd); 3386 if (len & 1) 3387 return -1; 3388 len /= 2; 3389 query = wpabuf_alloc(len); 3390 if (query == NULL) 3391 return -1; 3392 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3393 wpabuf_free(query); 3394 return -1; 3395 } 3396 3397 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 3398 wpabuf_free(query); 3399 return ret; 3400} 3401 3402 3403static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3404{ 3405 char *pos; 3406 u8 version; 3407 3408 pos = os_strchr(cmd, ' '); 3409 if (pos == NULL) 3410 return -1; 3411 *pos++ = '\0'; 3412 3413 if (hexstr2bin(cmd, &version, 1) < 0) 3414 return -1; 3415 3416 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 3417} 3418 3419 3420static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 3421{ 3422 char *pos; 3423 3424 pos = os_strchr(cmd, ' '); 3425 if (pos == NULL) 3426 return -1; 3427 *pos++ = '\0'; 3428 3429 if (os_strcmp(cmd, "bonjour") == 0) 3430 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 3431 if (os_strcmp(cmd, "upnp") == 0) 3432 return p2p_ctrl_service_del_upnp(wpa_s, pos); 3433 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3434 return -1; 3435} 3436 3437 3438static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 3439{ 3440 u8 addr[ETH_ALEN]; 3441 3442 /* <addr> */ 3443 3444 if (hwaddr_aton(cmd, addr)) 3445 return -1; 3446 3447 return wpas_p2p_reject(wpa_s, addr); 3448} 3449 3450 3451static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 3452{ 3453 char *pos; 3454 int id; 3455 struct wpa_ssid *ssid; 3456 u8 peer[ETH_ALEN]; 3457 3458 id = atoi(cmd); 3459 pos = os_strstr(cmd, " peer="); 3460 if (pos) { 3461 pos += 6; 3462 if (hwaddr_aton(pos, peer)) 3463 return -1; 3464 } 3465 ssid = wpa_config_get_network(wpa_s->conf, id); 3466 if (ssid == NULL || ssid->disabled != 2) { 3467 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3468 "for persistent P2P group", 3469 id); 3470 return -1; 3471 } 3472 3473 return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL); 3474} 3475 3476 3477static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 3478{ 3479 char *pos; 3480 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 3481 3482 pos = os_strstr(cmd, " peer="); 3483 if (!pos) 3484 return -1; 3485 3486 *pos = '\0'; 3487 pos += 6; 3488 if (hwaddr_aton(pos, peer)) { 3489 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 3490 return -1; 3491 } 3492 3493 pos = os_strstr(pos, " go_dev_addr="); 3494 if (pos) { 3495 pos += 13; 3496 if (hwaddr_aton(pos, go_dev_addr)) { 3497 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 3498 pos); 3499 return -1; 3500 } 3501 go_dev = go_dev_addr; 3502 } 3503 3504 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 3505} 3506 3507 3508static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 3509{ 3510 if (os_strncmp(cmd, "persistent=", 11) == 0) 3511 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 3512 if (os_strncmp(cmd, "group=", 6) == 0) 3513 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 3514 3515 return -1; 3516} 3517 3518 3519static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 3520 char *cmd, int freq) 3521{ 3522 int id; 3523 struct wpa_ssid *ssid; 3524 3525 id = atoi(cmd); 3526 ssid = wpa_config_get_network(wpa_s->conf, id); 3527 if (ssid == NULL || ssid->disabled != 2) { 3528 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3529 "for persistent P2P group", 3530 id); 3531 return -1; 3532 } 3533 3534 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq); 3535} 3536 3537 3538static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 3539{ 3540 int freq = 0; 3541 char *pos; 3542 3543 pos = os_strstr(cmd, "freq="); 3544 if (pos) 3545 freq = atoi(pos + 5); 3546 3547 if (os_strncmp(cmd, "persistent=", 11) == 0) 3548 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq); 3549 if (os_strcmp(cmd, "persistent") == 0 || 3550 os_strncmp(cmd, "persistent ", 11) == 0) 3551 return wpas_p2p_group_add(wpa_s, 1, freq); 3552 if (os_strncmp(cmd, "freq=", 5) == 0) 3553 return wpas_p2p_group_add(wpa_s, 0, freq); 3554 3555 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'", 3556 cmd); 3557 return -1; 3558} 3559 3560 3561static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 3562 char *buf, size_t buflen) 3563{ 3564 u8 addr[ETH_ALEN], *addr_ptr; 3565 int next, res; 3566 const struct p2p_peer_info *info; 3567 char *pos, *end; 3568 char devtype[WPS_DEV_TYPE_BUFSIZE]; 3569 struct wpa_ssid *ssid; 3570 3571 if (!wpa_s->global->p2p) 3572 return -1; 3573 3574 if (os_strcmp(cmd, "FIRST") == 0) { 3575 addr_ptr = NULL; 3576 next = 0; 3577 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 3578 if (hwaddr_aton(cmd + 5, addr) < 0) 3579 return -1; 3580 addr_ptr = addr; 3581 next = 1; 3582 } else { 3583 if (hwaddr_aton(cmd, addr) < 0) 3584 return -1; 3585 addr_ptr = addr; 3586 next = 0; 3587 } 3588 3589 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 3590 if (info == NULL) 3591 return -1; 3592 3593 pos = buf; 3594 end = buf + buflen; 3595 3596 res = os_snprintf(pos, end - pos, MACSTR "\n" 3597 "pri_dev_type=%s\n" 3598 "device_name=%s\n" 3599 "manufacturer=%s\n" 3600 "model_name=%s\n" 3601 "model_number=%s\n" 3602 "serial_number=%s\n" 3603 "config_methods=0x%x\n" 3604 "dev_capab=0x%x\n" 3605 "group_capab=0x%x\n" 3606 "level=%d\n", 3607 MAC2STR(info->p2p_device_addr), 3608 wps_dev_type_bin2str(info->pri_dev_type, 3609 devtype, sizeof(devtype)), 3610 info->device_name, 3611 info->manufacturer, 3612 info->model_name, 3613 info->model_number, 3614 info->serial_number, 3615 info->config_methods, 3616 info->dev_capab, 3617 info->group_capab, 3618 info->level); 3619 if (res < 0 || res >= end - pos) 3620 return pos - buf; 3621 pos += res; 3622 3623 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 3624 if (ssid) { 3625 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 3626 if (res < 0 || res >= end - pos) 3627 return pos - buf; 3628 pos += res; 3629 } 3630 3631 res = p2p_get_peer_info_txt(info, pos, end - pos); 3632 if (res < 0) 3633 return pos - buf; 3634 pos += res; 3635 3636 return pos - buf; 3637} 3638 3639 3640static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 3641 const char *param) 3642{ 3643 struct wpa_freq_range *freq = NULL, *n; 3644 unsigned int count = 0, i; 3645 const char *pos, *pos2, *pos3; 3646 3647 if (wpa_s->global->p2p == NULL) 3648 return -1; 3649 3650 /* 3651 * param includes comma separated frequency range. 3652 * For example: 2412-2432,2462,5000-6000 3653 */ 3654 pos = param; 3655 while (pos && pos[0]) { 3656 n = os_realloc(freq, 3657 (count + 1) * sizeof(struct wpa_freq_range)); 3658 if (n == NULL) { 3659 os_free(freq); 3660 return -1; 3661 } 3662 freq = n; 3663 freq[count].min = atoi(pos); 3664 pos2 = os_strchr(pos, '-'); 3665 pos3 = os_strchr(pos, ','); 3666 if (pos2 && (!pos3 || pos2 < pos3)) { 3667 pos2++; 3668 freq[count].max = atoi(pos2); 3669 } else 3670 freq[count].max = freq[count].min; 3671 pos = pos3; 3672 if (pos) 3673 pos++; 3674 count++; 3675 } 3676 3677 for (i = 0; i < count; i++) { 3678 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 3679 freq[i].min, freq[i].max); 3680 } 3681 3682 os_free(wpa_s->global->p2p_disallow_freq); 3683 wpa_s->global->p2p_disallow_freq = freq; 3684 wpa_s->global->num_p2p_disallow_freq = count; 3685 wpas_p2p_update_channel_list(wpa_s); 3686 return 0; 3687} 3688 3689 3690static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 3691{ 3692 char *param; 3693 3694 if (wpa_s->global->p2p == NULL) 3695 return -1; 3696 3697 param = os_strchr(cmd, ' '); 3698 if (param == NULL) 3699 return -1; 3700 *param++ = '\0'; 3701 3702 if (os_strcmp(cmd, "discoverability") == 0) { 3703 p2p_set_client_discoverability(wpa_s->global->p2p, 3704 atoi(param)); 3705 return 0; 3706 } 3707 3708 if (os_strcmp(cmd, "managed") == 0) { 3709 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 3710 return 0; 3711 } 3712 3713 if (os_strcmp(cmd, "listen_channel") == 0) { 3714 return p2p_set_listen_channel(wpa_s->global->p2p, 81, 3715 atoi(param)); 3716 } 3717 3718 if (os_strcmp(cmd, "ssid_postfix") == 0) { 3719 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 3720 os_strlen(param)); 3721 } 3722 3723 if (os_strcmp(cmd, "noa") == 0) { 3724 char *pos; 3725 int count, start, duration; 3726 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 3727 count = atoi(param); 3728 pos = os_strchr(param, ','); 3729 if (pos == NULL) 3730 return -1; 3731 pos++; 3732 start = atoi(pos); 3733 pos = os_strchr(pos, ','); 3734 if (pos == NULL) 3735 return -1; 3736 pos++; 3737 duration = atoi(pos); 3738 if (count < 0 || count > 255 || start < 0 || duration < 0) 3739 return -1; 3740 if (count == 0 && duration > 0) 3741 return -1; 3742 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 3743 "start=%d duration=%d", count, start, duration); 3744 return wpas_p2p_set_noa(wpa_s, count, start, duration); 3745 } 3746 3747 if (os_strcmp(cmd, "ps") == 0) 3748 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 3749 3750 if (os_strcmp(cmd, "oppps") == 0) 3751 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 3752 3753 if (os_strcmp(cmd, "ctwindow") == 0) 3754 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 3755 3756 if (os_strcmp(cmd, "disabled") == 0) { 3757 wpa_s->global->p2p_disabled = atoi(param); 3758 wpa_printf(MSG_DEBUG, "P2P functionality %s", 3759 wpa_s->global->p2p_disabled ? 3760 "disabled" : "enabled"); 3761 if (wpa_s->global->p2p_disabled) { 3762 wpas_p2p_stop_find(wpa_s); 3763 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 3764 p2p_flush(wpa_s->global->p2p); 3765 } 3766 return 0; 3767 } 3768 3769 if (os_strcmp(cmd, "conc_pref") == 0) { 3770 if (os_strcmp(param, "sta") == 0) 3771 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 3772 else if (os_strcmp(param, "p2p") == 0) 3773 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 3774 else { 3775 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 3776 return -1; 3777 } 3778 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 3779 "%s", param); 3780 return 0; 3781 } 3782 3783 if (os_strcmp(cmd, "force_long_sd") == 0) { 3784 wpa_s->force_long_sd = atoi(param); 3785 return 0; 3786 } 3787 3788 if (os_strcmp(cmd, "peer_filter") == 0) { 3789 u8 addr[ETH_ALEN]; 3790 if (hwaddr_aton(param, addr)) 3791 return -1; 3792 p2p_set_peer_filter(wpa_s->global->p2p, addr); 3793 return 0; 3794 } 3795 3796 if (os_strcmp(cmd, "cross_connect") == 0) 3797 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 3798 3799 if (os_strcmp(cmd, "go_apsd") == 0) { 3800 if (os_strcmp(param, "disable") == 0) 3801 wpa_s->set_ap_uapsd = 0; 3802 else { 3803 wpa_s->set_ap_uapsd = 1; 3804 wpa_s->ap_uapsd = atoi(param); 3805 } 3806 return 0; 3807 } 3808 3809 if (os_strcmp(cmd, "client_apsd") == 0) { 3810 if (os_strcmp(param, "disable") == 0) 3811 wpa_s->set_sta_uapsd = 0; 3812 else { 3813 int be, bk, vi, vo; 3814 char *pos; 3815 /* format: BE,BK,VI,VO;max SP Length */ 3816 be = atoi(param); 3817 pos = os_strchr(param, ','); 3818 if (pos == NULL) 3819 return -1; 3820 pos++; 3821 bk = atoi(pos); 3822 pos = os_strchr(pos, ','); 3823 if (pos == NULL) 3824 return -1; 3825 pos++; 3826 vi = atoi(pos); 3827 pos = os_strchr(pos, ','); 3828 if (pos == NULL) 3829 return -1; 3830 pos++; 3831 vo = atoi(pos); 3832 /* ignore max SP Length for now */ 3833 3834 wpa_s->set_sta_uapsd = 1; 3835 wpa_s->sta_uapsd = 0; 3836 if (be) 3837 wpa_s->sta_uapsd |= BIT(0); 3838 if (bk) 3839 wpa_s->sta_uapsd |= BIT(1); 3840 if (vi) 3841 wpa_s->sta_uapsd |= BIT(2); 3842 if (vo) 3843 wpa_s->sta_uapsd |= BIT(3); 3844 } 3845 return 0; 3846 } 3847 3848 if (os_strcmp(cmd, "disallow_freq") == 0) 3849 return p2p_ctrl_disallow_freq(wpa_s, param); 3850 3851 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 3852 cmd); 3853 3854 return -1; 3855} 3856 3857 3858static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 3859{ 3860 char *pos, *pos2; 3861 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 3862 3863 if (cmd[0]) { 3864 pos = os_strchr(cmd, ' '); 3865 if (pos == NULL) 3866 return -1; 3867 *pos++ = '\0'; 3868 dur1 = atoi(cmd); 3869 3870 pos2 = os_strchr(pos, ' '); 3871 if (pos2) 3872 *pos2++ = '\0'; 3873 int1 = atoi(pos); 3874 } else 3875 pos2 = NULL; 3876 3877 if (pos2) { 3878 pos = os_strchr(pos2, ' '); 3879 if (pos == NULL) 3880 return -1; 3881 *pos++ = '\0'; 3882 dur2 = atoi(pos2); 3883 int2 = atoi(pos); 3884 } 3885 3886 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 3887} 3888 3889 3890static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 3891{ 3892 char *pos; 3893 unsigned int period = 0, interval = 0; 3894 3895 if (cmd[0]) { 3896 pos = os_strchr(cmd, ' '); 3897 if (pos == NULL) 3898 return -1; 3899 *pos++ = '\0'; 3900 period = atoi(cmd); 3901 interval = atoi(pos); 3902 } 3903 3904 return wpas_p2p_ext_listen(wpa_s, period, interval); 3905} 3906 3907#endif /* CONFIG_P2P */ 3908 3909 3910#ifdef CONFIG_INTERWORKING 3911static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst) 3912{ 3913 u8 bssid[ETH_ALEN]; 3914 struct wpa_bss *bss; 3915 3916 if (hwaddr_aton(dst, bssid)) { 3917 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 3918 return -1; 3919 } 3920 3921 bss = wpa_bss_get_bssid(wpa_s, bssid); 3922 if (bss == NULL) { 3923 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 3924 MAC2STR(bssid)); 3925 return -1; 3926 } 3927 3928 return interworking_connect(wpa_s, bss); 3929} 3930 3931 3932static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 3933{ 3934 u8 dst_addr[ETH_ALEN]; 3935 int used; 3936 char *pos; 3937#define MAX_ANQP_INFO_ID 100 3938 u16 id[MAX_ANQP_INFO_ID]; 3939 size_t num_id = 0; 3940 3941 used = hwaddr_aton2(dst, dst_addr); 3942 if (used < 0) 3943 return -1; 3944 pos = dst + used; 3945 while (num_id < MAX_ANQP_INFO_ID) { 3946 id[num_id] = atoi(pos); 3947 if (id[num_id]) 3948 num_id++; 3949 pos = os_strchr(pos + 1, ','); 3950 if (pos == NULL) 3951 break; 3952 pos++; 3953 } 3954 3955 if (num_id == 0) 3956 return -1; 3957 3958 return anqp_send_req(wpa_s, dst_addr, id, num_id); 3959} 3960#endif /* CONFIG_INTERWORKING */ 3961 3962 3963#ifdef CONFIG_HS20 3964 3965static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 3966{ 3967 u8 dst_addr[ETH_ALEN]; 3968 int used; 3969 char *pos; 3970 u32 subtypes = 0; 3971 3972 used = hwaddr_aton2(dst, dst_addr); 3973 if (used < 0) 3974 return -1; 3975 pos = dst + used; 3976 for (;;) { 3977 int num = atoi(pos); 3978 if (num <= 0 || num > 31) 3979 return -1; 3980 subtypes |= BIT(num); 3981 pos = os_strchr(pos + 1, ','); 3982 if (pos == NULL) 3983 break; 3984 pos++; 3985 } 3986 3987 if (subtypes == 0) 3988 return -1; 3989 3990 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0); 3991} 3992 3993 3994static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 3995 const u8 *addr, const char *realm) 3996{ 3997 u8 *buf; 3998 size_t rlen, len; 3999 int ret; 4000 4001 rlen = os_strlen(realm); 4002 len = 3 + rlen; 4003 buf = os_malloc(len); 4004 if (buf == NULL) 4005 return -1; 4006 buf[0] = 1; /* NAI Home Realm Count */ 4007 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 4008 buf[2] = rlen; 4009 os_memcpy(buf + 3, realm, rlen); 4010 4011 ret = hs20_anqp_send_req(wpa_s, addr, 4012 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4013 buf, len); 4014 4015 os_free(buf); 4016 4017 return ret; 4018} 4019 4020 4021static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 4022 char *dst) 4023{ 4024 struct wpa_cred *cred = wpa_s->conf->cred; 4025 u8 dst_addr[ETH_ALEN]; 4026 int used; 4027 u8 *buf; 4028 size_t len; 4029 int ret; 4030 4031 used = hwaddr_aton2(dst, dst_addr); 4032 if (used < 0) 4033 return -1; 4034 4035 while (dst[used] == ' ') 4036 used++; 4037 if (os_strncmp(dst + used, "realm=", 6) == 0) 4038 return hs20_nai_home_realm_list(wpa_s, dst_addr, 4039 dst + used + 6); 4040 4041 len = os_strlen(dst + used); 4042 4043 if (len == 0 && cred && cred->realm) 4044 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 4045 4046 if (len % 1) 4047 return -1; 4048 len /= 2; 4049 buf = os_malloc(len); 4050 if (buf == NULL) 4051 return -1; 4052 if (hexstr2bin(dst + used, buf, len) < 0) { 4053 os_free(buf); 4054 return -1; 4055 } 4056 4057 ret = hs20_anqp_send_req(wpa_s, dst_addr, 4058 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4059 buf, len); 4060 os_free(buf); 4061 4062 return ret; 4063} 4064 4065#endif /* CONFIG_HS20 */ 4066 4067 4068static int wpa_supplicant_ctrl_iface_sta_autoconnect( 4069 struct wpa_supplicant *wpa_s, char *cmd) 4070{ 4071 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0; 4072 return 0; 4073} 4074 4075 4076#ifdef CONFIG_AUTOSCAN 4077 4078static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 4079 char *cmd) 4080{ 4081 enum wpa_states state = wpa_s->wpa_state; 4082 char *new_params = NULL; 4083 4084 if (os_strlen(cmd) > 0) { 4085 new_params = os_strdup(cmd); 4086 if (new_params == NULL) 4087 return -1; 4088 } 4089 4090 os_free(wpa_s->conf->autoscan); 4091 wpa_s->conf->autoscan = new_params; 4092 4093 if (wpa_s->conf->autoscan == NULL) 4094 autoscan_deinit(wpa_s); 4095 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 4096 autoscan_init(wpa_s, 1); 4097 else if (state == WPA_SCANNING) 4098 wpa_supplicant_reinit_autoscan(wpa_s); 4099 4100 return 0; 4101} 4102 4103#endif /* CONFIG_AUTOSCAN */ 4104 4105 4106static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 4107 size_t buflen) 4108{ 4109 struct wpa_signal_info si; 4110 int ret; 4111 4112 ret = wpa_drv_signal_poll(wpa_s, &si); 4113 if (ret) 4114 return -1; 4115 4116 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n" 4117 "NOISE=%d\nFREQUENCY=%u\n", 4118 si.current_signal, si.current_txrate / 1000, 4119 si.current_noise, si.frequency); 4120 if (ret < 0 || (unsigned int) ret > buflen) 4121 return -1; 4122 return ret; 4123} 4124 4125static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 4126 size_t buflen) 4127{ 4128 struct hostap_sta_driver_data sta; 4129 int ret; 4130 4131 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 4132 if (ret) 4133 return -1; 4134 4135 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 4136 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 4137 if (ret < 0 || (unsigned int) ret > buflen) 4138 return -1; 4139 return ret; 4140} 4141 4142 4143#ifdef ANDROID 4144static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 4145 char *buf, size_t buflen) 4146{ 4147 int ret; 4148 4149 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 4150 if (ret == 0) 4151 ret = sprintf(buf, "%s\n", "OK"); 4152 return ret; 4153} 4154#endif 4155 4156char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 4157 char *buf, size_t *resp_len) 4158{ 4159 char *reply; 4160 const int reply_size = 4096; 4161 int ctrl_rsp = 0; 4162 int reply_len; 4163 4164 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 4165 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 4166 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 4167 (const u8 *) buf, os_strlen(buf)); 4168 } else { 4169 int level = MSG_DEBUG; 4170 if (os_strcmp(buf, "PING") == 0) 4171 level = MSG_EXCESSIVE; 4172 wpa_hexdump_ascii(level, "RX ctrl_iface", 4173 (const u8 *) buf, os_strlen(buf)); 4174 } 4175 4176 reply = os_malloc(reply_size); 4177 if (reply == NULL) { 4178 *resp_len = 1; 4179 return NULL; 4180 } 4181 4182 os_memcpy(reply, "OK\n", 3); 4183 reply_len = 3; 4184 4185 if (os_strcmp(buf, "PING") == 0) { 4186 os_memcpy(reply, "PONG\n", 5); 4187 reply_len = 5; 4188 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 4189 if (wpa_debug_reopen_file() < 0) 4190 reply_len = -1; 4191 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 4192 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 4193 } else if (os_strcmp(buf, "MIB") == 0) { 4194 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 4195 if (reply_len >= 0) { 4196 int res; 4197 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 4198 reply_size - reply_len); 4199 if (res < 0) 4200 reply_len = -1; 4201 else 4202 reply_len += res; 4203 } 4204 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 4205 reply_len = wpa_supplicant_ctrl_iface_status( 4206 wpa_s, buf + 6, reply, reply_size); 4207 } else if (os_strcmp(buf, "PMKSA") == 0) { 4208 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 4209 reply_size); 4210 } else if (os_strncmp(buf, "SET ", 4) == 0) { 4211 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 4212 reply_len = -1; 4213 } else if (os_strncmp(buf, "GET ", 4) == 0) { 4214 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 4215 reply, reply_size); 4216 } else if (os_strcmp(buf, "LOGON") == 0) { 4217 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 4218 } else if (os_strcmp(buf, "LOGOFF") == 0) { 4219 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 4220 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 4221 wpa_s->normal_scans = 0; 4222 wpa_supplicant_reinit_autoscan(wpa_s); 4223 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4224 reply_len = -1; 4225 else { 4226 wpa_s->disconnected = 0; 4227 wpa_s->reassociate = 1; 4228 wpa_supplicant_req_scan(wpa_s, 0, 0); 4229 } 4230 } else if (os_strcmp(buf, "RECONNECT") == 0) { 4231 wpa_s->normal_scans = 0; 4232 wpa_supplicant_reinit_autoscan(wpa_s); 4233 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4234 reply_len = -1; 4235 else if (wpa_s->disconnected) { 4236 wpa_s->disconnected = 0; 4237 wpa_s->reassociate = 1; 4238 wpa_supplicant_req_scan(wpa_s, 0, 0); 4239 } 4240#ifdef IEEE8021X_EAPOL 4241 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 4242 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 4243 reply_len = -1; 4244#endif /* IEEE8021X_EAPOL */ 4245#ifdef CONFIG_PEERKEY 4246 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 4247 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 4248 reply_len = -1; 4249#endif /* CONFIG_PEERKEY */ 4250#ifdef CONFIG_IEEE80211R 4251 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 4252 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 4253 reply_len = -1; 4254#endif /* CONFIG_IEEE80211R */ 4255#ifdef CONFIG_WPS 4256 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 4257 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 4258 if (res == -2) { 4259 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4260 reply_len = 17; 4261 } else if (res) 4262 reply_len = -1; 4263 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 4264 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 4265 if (res == -2) { 4266 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4267 reply_len = 17; 4268 } else if (res) 4269 reply_len = -1; 4270 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 4271 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 4272 reply, 4273 reply_size); 4274 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 4275 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 4276 wpa_s, buf + 14, reply, reply_size); 4277 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 4278 if (wpas_wps_cancel(wpa_s)) 4279 reply_len = -1; 4280#ifdef CONFIG_WPS_OOB 4281 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 4282 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8)) 4283 reply_len = -1; 4284#endif /* CONFIG_WPS_OOB */ 4285#ifdef CONFIG_WPS_NFC 4286 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 4287 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 4288 reply_len = -1; 4289 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 4290 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 4291 reply_len = -1; 4292 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 4293 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 4294 wpa_s, buf + 14, reply, reply_size); 4295 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 4296 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 4297 buf + 17)) 4298 reply_len = -1; 4299#endif /* CONFIG_WPS_NFC */ 4300 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 4301 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 4302 reply_len = -1; 4303#ifdef CONFIG_AP 4304 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 4305 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 4306 wpa_s, buf + 11, reply, reply_size); 4307#endif /* CONFIG_AP */ 4308#ifdef CONFIG_WPS_ER 4309 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 4310 if (wpas_wps_er_start(wpa_s, NULL)) 4311 reply_len = -1; 4312 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 4313 if (wpas_wps_er_start(wpa_s, buf + 13)) 4314 reply_len = -1; 4315 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 4316 if (wpas_wps_er_stop(wpa_s)) 4317 reply_len = -1; 4318 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 4319 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 4320 reply_len = -1; 4321 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 4322 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 4323 if (ret == -2) { 4324 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4325 reply_len = 17; 4326 } else if (ret == -3) { 4327 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 4328 reply_len = 18; 4329 } else if (ret == -4) { 4330 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 4331 reply_len = 20; 4332 } else if (ret) 4333 reply_len = -1; 4334 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 4335 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 4336 reply_len = -1; 4337 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 4338 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 4339 buf + 18)) 4340 reply_len = -1; 4341 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 4342 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 4343 reply_len = -1; 4344#ifdef CONFIG_WPS_NFC 4345 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 4346 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 4347 wpa_s, buf + 24, reply, reply_size); 4348#endif /* CONFIG_WPS_NFC */ 4349#endif /* CONFIG_WPS_ER */ 4350#endif /* CONFIG_WPS */ 4351#ifdef CONFIG_IBSS_RSN 4352 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 4353 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 4354 reply_len = -1; 4355#endif /* CONFIG_IBSS_RSN */ 4356#ifdef CONFIG_P2P 4357 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 4358 if (p2p_ctrl_find(wpa_s, buf + 9)) 4359 reply_len = -1; 4360 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 4361 if (p2p_ctrl_find(wpa_s, "")) 4362 reply_len = -1; 4363 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 4364 wpas_p2p_stop_find(wpa_s); 4365 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 4366 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 4367 reply_size); 4368 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 4369 if (p2p_ctrl_listen(wpa_s, buf + 11)) 4370 reply_len = -1; 4371 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 4372 if (p2p_ctrl_listen(wpa_s, "")) 4373 reply_len = -1; 4374 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 4375 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 4376 reply_len = -1; 4377 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 4378 if (wpas_p2p_group_add(wpa_s, 0, 0)) 4379 reply_len = -1; 4380 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 4381 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 4382 reply_len = -1; 4383 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 4384 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 4385 reply_len = -1; 4386 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 4387 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 4388 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 4389 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 4390 reply_size); 4391 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 4392 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 4393 reply_len = -1; 4394 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 4395 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 4396 reply_len = -1; 4397 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 4398#ifdef ANDROID_P2P 4399 wpas_p2p_sd_service_update(wpa_s, SRV_UPDATE); 4400#else 4401 wpas_p2p_sd_service_update(wpa_s); 4402#endif 4403 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 4404 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 4405 reply_len = -1; 4406 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 4407 wpas_p2p_service_flush(wpa_s); 4408 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 4409 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 4410 reply_len = -1; 4411 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 4412 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 4413 reply_len = -1; 4414 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 4415 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 4416 reply_len = -1; 4417 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 4418 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 4419 reply_len = -1; 4420 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 4421 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 4422 reply_size); 4423 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 4424 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 4425 reply_len = -1; 4426 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 4427 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 4428 wpa_s->force_long_sd = 0; 4429 if (wpa_s->global->p2p) 4430 p2p_flush(wpa_s->global->p2p); 4431 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 4432 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 4433 reply_len = -1; 4434 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 4435 if (wpas_p2p_cancel(wpa_s)) 4436 reply_len = -1; 4437 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 4438 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 4439 reply_len = -1; 4440 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 4441 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 4442 reply_len = -1; 4443 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 4444 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 4445 reply_len = -1; 4446 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 4447 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 4448 reply_len = -1; 4449#endif /* CONFIG_P2P */ 4450#ifdef CONFIG_INTERWORKING 4451 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 4452 if (interworking_fetch_anqp(wpa_s) < 0) 4453 reply_len = -1; 4454 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 4455 interworking_stop_fetch_anqp(wpa_s); 4456 } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) { 4457 if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") != 4458 NULL) < 0) 4459 reply_len = -1; 4460 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 4461 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0) 4462 reply_len = -1; 4463 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 4464 if (get_anqp(wpa_s, buf + 9) < 0) 4465 reply_len = -1; 4466#endif /* CONFIG_INTERWORKING */ 4467#ifdef CONFIG_HS20 4468 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 4469 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 4470 reply_len = -1; 4471 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 4472 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 4473 reply_len = -1; 4474#endif /* CONFIG_HS20 */ 4475 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 4476 { 4477 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 4478 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 4479 reply_len = -1; 4480 else 4481 ctrl_rsp = 1; 4482 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 4483 if (wpa_supplicant_reload_configuration(wpa_s)) 4484 reply_len = -1; 4485 } else if (os_strcmp(buf, "TERMINATE") == 0) { 4486 wpa_supplicant_terminate_proc(wpa_s->global); 4487 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 4488 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 4489 reply_len = -1; 4490 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 4491 reply_len = wpa_supplicant_ctrl_iface_blacklist( 4492 wpa_s, buf + 9, reply, reply_size); 4493 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 4494 reply_len = wpa_supplicant_ctrl_iface_log_level( 4495 wpa_s, buf + 9, reply, reply_size); 4496 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 4497 reply_len = wpa_supplicant_ctrl_iface_list_networks( 4498 wpa_s, reply, reply_size); 4499 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 4500#ifdef CONFIG_SME 4501 wpa_s->sme.prev_bssid_set = 0; 4502#endif /* CONFIG_SME */ 4503 wpa_s->reassociate = 0; 4504 wpa_s->disconnected = 1; 4505 wpa_supplicant_cancel_sched_scan(wpa_s); 4506 wpa_supplicant_cancel_scan(wpa_s); 4507 wpa_supplicant_deauthenticate(wpa_s, 4508 WLAN_REASON_DEAUTH_LEAVING); 4509 } else if (os_strcmp(buf, "SCAN") == 0) { 4510 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4511 reply_len = -1; 4512 else { 4513 if (!wpa_s->scanning && 4514 ((wpa_s->wpa_state <= WPA_SCANNING) || 4515 (wpa_s->wpa_state == WPA_COMPLETED))) { 4516 wpa_s->normal_scans = 0; 4517 wpa_s->scan_req = 2; 4518 wpa_supplicant_req_scan(wpa_s, 0, 0); 4519 } else if (wpa_s->sched_scanning) { 4520 wpa_printf(MSG_DEBUG, "Stop ongoing " 4521 "sched_scan to allow requested " 4522 "full scan to proceed"); 4523 wpa_supplicant_cancel_sched_scan(wpa_s); 4524 wpa_s->scan_req = 2; 4525 wpa_supplicant_req_scan(wpa_s, 0, 0); 4526 } else { 4527 wpa_printf(MSG_DEBUG, "Ongoing scan action - " 4528 "reject new request"); 4529 reply_len = os_snprintf(reply, reply_size, 4530 "FAIL-BUSY\n"); 4531 } 4532 } 4533 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 4534 reply_len = wpa_supplicant_ctrl_iface_scan_results( 4535 wpa_s, reply, reply_size); 4536 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 4537 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 4538 reply_len = -1; 4539 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 4540 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 4541 reply_len = -1; 4542 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 4543 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 4544 reply_len = -1; 4545 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 4546 reply_len = wpa_supplicant_ctrl_iface_add_network( 4547 wpa_s, reply, reply_size); 4548 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 4549 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 4550 reply_len = -1; 4551 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 4552 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 4553 reply_len = -1; 4554 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 4555 reply_len = wpa_supplicant_ctrl_iface_get_network( 4556 wpa_s, buf + 12, reply, reply_size); 4557 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 4558 reply_len = wpa_supplicant_ctrl_iface_list_creds( 4559 wpa_s, reply, reply_size); 4560 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 4561 reply_len = wpa_supplicant_ctrl_iface_add_cred( 4562 wpa_s, reply, reply_size); 4563 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 4564 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 4565 reply_len = -1; 4566 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 4567 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 4568 reply_len = -1; 4569#ifndef CONFIG_NO_CONFIG_WRITE 4570 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 4571 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 4572 reply_len = -1; 4573#endif /* CONFIG_NO_CONFIG_WRITE */ 4574 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 4575 reply_len = wpa_supplicant_ctrl_iface_get_capability( 4576 wpa_s, buf + 15, reply, reply_size); 4577 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 4578 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 4579 reply_len = -1; 4580 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 4581 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 4582 reply_len = -1; 4583 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 4584 reply_len = wpa_supplicant_global_iface_list( 4585 wpa_s->global, reply, reply_size); 4586 } else if (os_strcmp(buf, "INTERFACES") == 0) { 4587 reply_len = wpa_supplicant_global_iface_interfaces( 4588 wpa_s->global, reply, reply_size); 4589 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 4590 reply_len = wpa_supplicant_ctrl_iface_bss( 4591 wpa_s, buf + 4, reply, reply_size); 4592#ifdef CONFIG_AP 4593 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 4594 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 4595 } else if (os_strncmp(buf, "STA ", 4) == 0) { 4596 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 4597 reply_size); 4598 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 4599 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 4600 reply_size); 4601 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 4602 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 4603 reply_len = -1; 4604 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 4605 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 4606 reply_len = -1; 4607#endif /* CONFIG_AP */ 4608 } else if (os_strcmp(buf, "SUSPEND") == 0) { 4609 wpas_notify_suspend(wpa_s->global); 4610 } else if (os_strcmp(buf, "RESUME") == 0) { 4611 wpas_notify_resume(wpa_s->global); 4612 } else if (os_strcmp(buf, "DROP_SA") == 0) { 4613 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 4614 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 4615 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 4616 reply_len = -1; 4617 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 4618 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16)) 4619 reply_len = -1; 4620 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 4621 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 4622 reply_len = -1; 4623 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 4624 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 4625 buf + 17)) 4626 reply_len = -1; 4627 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 4628 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10)) 4629 reply_len = -1; 4630#ifdef CONFIG_TDLS 4631 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 4632 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 4633 reply_len = -1; 4634 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 4635 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 4636 reply_len = -1; 4637 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 4638 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 4639 reply_len = -1; 4640#endif /* CONFIG_TDLS */ 4641 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 4642 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 4643 reply_size); 4644 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 4645 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 4646 reply_size); 4647#ifdef CONFIG_AUTOSCAN 4648 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 4649 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 4650 reply_len = -1; 4651#endif /* CONFIG_AUTOSCAN */ 4652#ifdef ANDROID 4653 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 4654 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 4655 reply_size); 4656#endif 4657 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 4658 eapol_sm_request_reauth(wpa_s->eapol); 4659 } else { 4660 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 4661 reply_len = 16; 4662 } 4663 4664 if (reply_len < 0) { 4665 os_memcpy(reply, "FAIL\n", 5); 4666 reply_len = 5; 4667 } 4668 4669 if (ctrl_rsp) 4670 eapol_sm_notify_ctrl_response(wpa_s->eapol); 4671 4672 *resp_len = reply_len; 4673 return reply; 4674} 4675 4676 4677static int wpa_supplicant_global_iface_add(struct wpa_global *global, 4678 char *cmd) 4679{ 4680 struct wpa_interface iface; 4681 char *pos; 4682 4683 /* 4684 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 4685 * TAB<bridge_ifname> 4686 */ 4687 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 4688 4689 os_memset(&iface, 0, sizeof(iface)); 4690 4691 do { 4692 iface.ifname = pos = cmd; 4693 pos = os_strchr(pos, '\t'); 4694 if (pos) 4695 *pos++ = '\0'; 4696 if (iface.ifname[0] == '\0') 4697 return -1; 4698 if (pos == NULL) 4699 break; 4700 4701 iface.confname = pos; 4702 pos = os_strchr(pos, '\t'); 4703 if (pos) 4704 *pos++ = '\0'; 4705 if (iface.confname[0] == '\0') 4706 iface.confname = NULL; 4707 if (pos == NULL) 4708 break; 4709 4710 iface.driver = pos; 4711 pos = os_strchr(pos, '\t'); 4712 if (pos) 4713 *pos++ = '\0'; 4714 if (iface.driver[0] == '\0') 4715 iface.driver = NULL; 4716 if (pos == NULL) 4717 break; 4718 4719 iface.ctrl_interface = pos; 4720 pos = os_strchr(pos, '\t'); 4721 if (pos) 4722 *pos++ = '\0'; 4723 if (iface.ctrl_interface[0] == '\0') 4724 iface.ctrl_interface = NULL; 4725 if (pos == NULL) 4726 break; 4727 4728 iface.driver_param = pos; 4729 pos = os_strchr(pos, '\t'); 4730 if (pos) 4731 *pos++ = '\0'; 4732 if (iface.driver_param[0] == '\0') 4733 iface.driver_param = NULL; 4734 if (pos == NULL) 4735 break; 4736 4737 iface.bridge_ifname = pos; 4738 pos = os_strchr(pos, '\t'); 4739 if (pos) 4740 *pos++ = '\0'; 4741 if (iface.bridge_ifname[0] == '\0') 4742 iface.bridge_ifname = NULL; 4743 if (pos == NULL) 4744 break; 4745 } while (0); 4746 4747 if (wpa_supplicant_get_iface(global, iface.ifname)) 4748 return -1; 4749 4750 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 4751} 4752 4753 4754static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 4755 char *cmd) 4756{ 4757 struct wpa_supplicant *wpa_s; 4758 4759 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 4760 4761 wpa_s = wpa_supplicant_get_iface(global, cmd); 4762 if (wpa_s == NULL) 4763 return -1; 4764 return wpa_supplicant_remove_iface(global, wpa_s, 0); 4765} 4766 4767 4768static void wpa_free_iface_info(struct wpa_interface_info *iface) 4769{ 4770 struct wpa_interface_info *prev; 4771 4772 while (iface) { 4773 prev = iface; 4774 iface = iface->next; 4775 4776 os_free(prev->ifname); 4777 os_free(prev->desc); 4778 os_free(prev); 4779 } 4780} 4781 4782 4783static int wpa_supplicant_global_iface_list(struct wpa_global *global, 4784 char *buf, int len) 4785{ 4786 int i, res; 4787 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 4788 char *pos, *end; 4789 4790 for (i = 0; wpa_drivers[i]; i++) { 4791 struct wpa_driver_ops *drv = wpa_drivers[i]; 4792 if (drv->get_interfaces == NULL) 4793 continue; 4794 tmp = drv->get_interfaces(global->drv_priv[i]); 4795 if (tmp == NULL) 4796 continue; 4797 4798 if (last == NULL) 4799 iface = last = tmp; 4800 else 4801 last->next = tmp; 4802 while (last->next) 4803 last = last->next; 4804 } 4805 4806 pos = buf; 4807 end = buf + len; 4808 for (tmp = iface; tmp; tmp = tmp->next) { 4809 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 4810 tmp->drv_name, tmp->ifname, 4811 tmp->desc ? tmp->desc : ""); 4812 if (res < 0 || res >= end - pos) { 4813 *pos = '\0'; 4814 break; 4815 } 4816 pos += res; 4817 } 4818 4819 wpa_free_iface_info(iface); 4820 4821 return pos - buf; 4822} 4823 4824 4825static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 4826 char *buf, int len) 4827{ 4828 int res; 4829 char *pos, *end; 4830 struct wpa_supplicant *wpa_s; 4831 4832 wpa_s = global->ifaces; 4833 pos = buf; 4834 end = buf + len; 4835 4836 while (wpa_s) { 4837 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 4838 if (res < 0 || res >= end - pos) { 4839 *pos = '\0'; 4840 break; 4841 } 4842 pos += res; 4843 wpa_s = wpa_s->next; 4844 } 4845 return pos - buf; 4846} 4847 4848 4849char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 4850 char *buf, size_t *resp_len) 4851{ 4852 char *reply; 4853 const int reply_size = 2048; 4854 int reply_len; 4855 int level = MSG_DEBUG; 4856 4857 if (os_strcmp(buf, "PING") == 0) 4858 level = MSG_EXCESSIVE; 4859 wpa_hexdump_ascii(level, "RX global ctrl_iface", 4860 (const u8 *) buf, os_strlen(buf)); 4861 4862 reply = os_malloc(reply_size); 4863 if (reply == NULL) { 4864 *resp_len = 1; 4865 return NULL; 4866 } 4867 4868 os_memcpy(reply, "OK\n", 3); 4869 reply_len = 3; 4870 4871 if (os_strcmp(buf, "PING") == 0) { 4872 os_memcpy(reply, "PONG\n", 5); 4873 reply_len = 5; 4874 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 4875 if (wpa_supplicant_global_iface_add(global, buf + 14)) 4876 reply_len = -1; 4877 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 4878 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 4879 reply_len = -1; 4880 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 4881 reply_len = wpa_supplicant_global_iface_list( 4882 global, reply, reply_size); 4883 } else if (os_strcmp(buf, "INTERFACES") == 0) { 4884 reply_len = wpa_supplicant_global_iface_interfaces( 4885 global, reply, reply_size); 4886 } else if (os_strcmp(buf, "TERMINATE") == 0) { 4887 wpa_supplicant_terminate_proc(global); 4888 } else if (os_strcmp(buf, "SUSPEND") == 0) { 4889 wpas_notify_suspend(global); 4890 } else if (os_strcmp(buf, "RESUME") == 0) { 4891 wpas_notify_resume(global); 4892 } else { 4893 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 4894 reply_len = 16; 4895 } 4896 4897 if (reply_len < 0) { 4898 os_memcpy(reply, "FAIL\n", 5); 4899 reply_len = 5; 4900 } 4901 4902 *resp_len = reply_len; 4903 return reply; 4904} 4905