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