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