1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2019, 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 #ifdef CONFIG_TESTING_OPTIONS 11 #include <net/ethernet.h> 12 #include <netinet/ip.h> 13 #endif /* CONFIG_TESTING_OPTIONS */ 14 15 #include "utils/common.h" 16 #include "utils/eloop.h" 17 #include "utils/uuid.h" 18 #include "utils/module_tests.h" 19 #include "common/version.h" 20 #include "common/ieee802_11_defs.h" 21 #include "common/ieee802_11_common.h" 22 #include "common/wpa_ctrl.h" 23 #ifdef CONFIG_DPP 24 #include "common/dpp.h" 25 #endif /* CONFIG_DPP */ 26 #include "crypto/tls.h" 27 #include "ap/hostapd.h" 28 #include "eap_peer/eap.h" 29 #include "eapol_supp/eapol_supp_sm.h" 30 #include "rsn_supp/wpa.h" 31 #include "rsn_supp/preauth.h" 32 #include "rsn_supp/pmksa_cache.h" 33 #include "l2_packet/l2_packet.h" 34 #include "wps/wps.h" 35 #include "fst/fst.h" 36 #include "fst/fst_ctrl_iface.h" 37 #include "config.h" 38 #include "wpa_supplicant_i.h" 39 #include "driver_i.h" 40 #include "wps_supplicant.h" 41 #include "ibss_rsn.h" 42 #include "ap.h" 43 #include "p2p_supplicant.h" 44 #include "p2p/p2p.h" 45 #include "hs20_supplicant.h" 46 #include "wifi_display.h" 47 #include "notify.h" 48 #include "bss.h" 49 #include "scan.h" 50 #include "ctrl_iface.h" 51 #include "interworking.h" 52 #include "blacklist.h" 53 #include "autoscan.h" 54 #include "wnm_sta.h" 55 #include "offchannel.h" 56 #include "drivers/driver.h" 57 #include "mesh.h" 58 #include "dpp_supplicant.h" 59 #include "sme.h" 60 61 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 62 char *buf, int len); 63 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 64 const char *input, 65 char *buf, int len); 66 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, 67 char *val); 68 69 70 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 71 { 72 char *pos; 73 u8 addr[ETH_ALEN], *filter = NULL, *n; 74 size_t count = 0; 75 76 pos = val; 77 while (pos) { 78 if (*pos == '\0') 79 break; 80 if (hwaddr_aton(pos, addr)) { 81 os_free(filter); 82 return -1; 83 } 84 n = os_realloc_array(filter, count + 1, ETH_ALEN); 85 if (n == NULL) { 86 os_free(filter); 87 return -1; 88 } 89 filter = n; 90 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 91 count++; 92 93 pos = os_strchr(pos, ' '); 94 if (pos) 95 pos++; 96 } 97 98 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 99 os_free(wpa_s->bssid_filter); 100 wpa_s->bssid_filter = filter; 101 wpa_s->bssid_filter_count = count; 102 103 return 0; 104 } 105 106 107 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 108 { 109 char *pos; 110 u8 addr[ETH_ALEN], *bssid = NULL, *n; 111 struct wpa_ssid_value *ssid = NULL, *ns; 112 size_t count = 0, ssid_count = 0; 113 struct wpa_ssid *c; 114 115 /* 116 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | "" 117 * SSID_SPEC ::= ssid <SSID_HEX> 118 * BSSID_SPEC ::= bssid <BSSID_HEX> 119 */ 120 121 pos = val; 122 while (pos) { 123 if (*pos == '\0') 124 break; 125 if (os_strncmp(pos, "bssid ", 6) == 0) { 126 int res; 127 pos += 6; 128 res = hwaddr_aton2(pos, addr); 129 if (res < 0) { 130 os_free(ssid); 131 os_free(bssid); 132 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 133 "BSSID value '%s'", pos); 134 return -1; 135 } 136 pos += res; 137 n = os_realloc_array(bssid, count + 1, ETH_ALEN); 138 if (n == NULL) { 139 os_free(ssid); 140 os_free(bssid); 141 return -1; 142 } 143 bssid = n; 144 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 145 count++; 146 } else if (os_strncmp(pos, "ssid ", 5) == 0) { 147 char *end; 148 pos += 5; 149 150 end = pos; 151 while (*end) { 152 if (*end == '\0' || *end == ' ') 153 break; 154 end++; 155 } 156 157 ns = os_realloc_array(ssid, ssid_count + 1, 158 sizeof(struct wpa_ssid_value)); 159 if (ns == NULL) { 160 os_free(ssid); 161 os_free(bssid); 162 return -1; 163 } 164 ssid = ns; 165 166 if ((end - pos) & 0x01 || 167 end - pos > 2 * SSID_MAX_LEN || 168 hexstr2bin(pos, ssid[ssid_count].ssid, 169 (end - pos) / 2) < 0) { 170 os_free(ssid); 171 os_free(bssid); 172 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 173 "SSID value '%s'", pos); 174 return -1; 175 } 176 ssid[ssid_count].ssid_len = (end - pos) / 2; 177 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 178 ssid[ssid_count].ssid, 179 ssid[ssid_count].ssid_len); 180 ssid_count++; 181 pos = end; 182 } else { 183 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 184 "'%s'", pos); 185 os_free(ssid); 186 os_free(bssid); 187 return -1; 188 } 189 190 pos = os_strchr(pos, ' '); 191 if (pos) 192 pos++; 193 } 194 195 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 196 os_free(wpa_s->disallow_aps_bssid); 197 wpa_s->disallow_aps_bssid = bssid; 198 wpa_s->disallow_aps_bssid_count = count; 199 200 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 201 os_free(wpa_s->disallow_aps_ssid); 202 wpa_s->disallow_aps_ssid = ssid; 203 wpa_s->disallow_aps_ssid_count = ssid_count; 204 205 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 206 return 0; 207 208 c = wpa_s->current_ssid; 209 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 210 return 0; 211 212 if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 213 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 214 return 0; 215 216 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 217 "because current AP was marked disallowed"); 218 219 #ifdef CONFIG_SME 220 wpa_s->sme.prev_bssid_set = 0; 221 #endif /* CONFIG_SME */ 222 wpa_s->reassociate = 1; 223 wpa_s->own_disconnect_req = 1; 224 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 225 wpa_supplicant_req_scan(wpa_s, 0, 0); 226 227 return 0; 228 } 229 230 231 #ifndef CONFIG_NO_CONFIG_BLOBS 232 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos) 233 { 234 char *name = pos; 235 struct wpa_config_blob *blob; 236 size_t len; 237 238 pos = os_strchr(pos, ' '); 239 if (pos == NULL) 240 return -1; 241 *pos++ = '\0'; 242 len = os_strlen(pos); 243 if (len & 1) 244 return -1; 245 246 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name); 247 blob = os_zalloc(sizeof(*blob)); 248 if (blob == NULL) 249 return -1; 250 blob->name = os_strdup(name); 251 blob->data = os_malloc(len / 2); 252 if (blob->name == NULL || blob->data == NULL) { 253 wpa_config_free_blob(blob); 254 return -1; 255 } 256 257 if (hexstr2bin(pos, blob->data, len / 2) < 0) { 258 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data"); 259 wpa_config_free_blob(blob); 260 return -1; 261 } 262 blob->len = len / 2; 263 264 wpa_config_set_blob(wpa_s->conf, blob); 265 266 return 0; 267 } 268 #endif /* CONFIG_NO_CONFIG_BLOBS */ 269 270 271 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) 272 { 273 char *params; 274 char *pos; 275 int *freqs = NULL; 276 int ret; 277 278 if (atoi(cmd)) { 279 params = os_strchr(cmd, ' '); 280 os_free(wpa_s->manual_sched_scan_freqs); 281 if (params) { 282 params++; 283 pos = os_strstr(params, "freq="); 284 if (pos) 285 freqs = freq_range_to_channel_list(wpa_s, 286 pos + 5); 287 } 288 wpa_s->manual_sched_scan_freqs = freqs; 289 ret = wpas_start_pno(wpa_s); 290 } else { 291 ret = wpas_stop_pno(wpa_s); 292 } 293 return ret; 294 } 295 296 297 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band) 298 { 299 union wpa_event_data event; 300 301 if (os_strcmp(band, "AUTO") == 0) 302 wpa_s->setband = WPA_SETBAND_AUTO; 303 else if (os_strcmp(band, "5G") == 0) 304 wpa_s->setband = WPA_SETBAND_5G; 305 else if (os_strcmp(band, "2G") == 0) 306 wpa_s->setband = WPA_SETBAND_2G; 307 else 308 return -1; 309 310 if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) { 311 os_memset(&event, 0, sizeof(event)); 312 event.channel_list_changed.initiator = REGDOM_SET_BY_USER; 313 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; 314 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event); 315 } 316 317 return 0; 318 } 319 320 321 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s, 322 const char *cmd) 323 { 324 struct wpabuf *lci; 325 326 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 327 wpabuf_free(wpa_s->lci); 328 wpa_s->lci = NULL; 329 return 0; 330 } 331 332 lci = wpabuf_parse_bin(cmd); 333 if (!lci) 334 return -1; 335 336 if (os_get_reltime(&wpa_s->lci_time)) { 337 wpabuf_free(lci); 338 return -1; 339 } 340 341 wpabuf_free(wpa_s->lci); 342 wpa_s->lci = lci; 343 344 return 0; 345 } 346 347 348 static int 349 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd) 350 { 351 int relative_rssi; 352 353 if (os_strcmp(cmd, "disable") == 0) { 354 wpa_s->srp.relative_rssi_set = 0; 355 return 0; 356 } 357 358 relative_rssi = atoi(cmd); 359 if (relative_rssi < 0 || relative_rssi > 100) 360 return -1; 361 wpa_s->srp.relative_rssi = relative_rssi; 362 wpa_s->srp.relative_rssi_set = 1; 363 return 0; 364 } 365 366 367 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s, 368 const char *cmd) 369 { 370 char *pos; 371 int adjust_rssi; 372 373 /* <band>:adjust_value */ 374 pos = os_strchr(cmd, ':'); 375 if (!pos) 376 return -1; 377 pos++; 378 adjust_rssi = atoi(pos); 379 if (adjust_rssi < -100 || adjust_rssi > 100) 380 return -1; 381 382 if (os_strncmp(cmd, "2G", 2) == 0) 383 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G; 384 else if (os_strncmp(cmd, "5G", 2) == 0) 385 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G; 386 else 387 return -1; 388 389 wpa_s->srp.relative_adjust_rssi = adjust_rssi; 390 391 return 0; 392 } 393 394 395 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s, 396 const char *cmd) 397 { 398 struct wpabuf *ric_ies; 399 400 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 401 wpabuf_free(wpa_s->ric_ies); 402 wpa_s->ric_ies = NULL; 403 return 0; 404 } 405 406 ric_ies = wpabuf_parse_bin(cmd); 407 if (!ric_ies) 408 return -1; 409 410 wpabuf_free(wpa_s->ric_ies); 411 wpa_s->ric_ies = ric_ies; 412 413 return 0; 414 } 415 416 417 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 418 char *cmd) 419 { 420 char *value; 421 int ret = 0; 422 423 value = os_strchr(cmd, ' '); 424 if (value == NULL) 425 return -1; 426 *value++ = '\0'; 427 428 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 429 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 430 eapol_sm_configure(wpa_s->eapol, 431 atoi(value), -1, -1, -1); 432 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 433 eapol_sm_configure(wpa_s->eapol, 434 -1, atoi(value), -1, -1); 435 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 436 eapol_sm_configure(wpa_s->eapol, 437 -1, -1, atoi(value), -1); 438 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 439 eapol_sm_configure(wpa_s->eapol, 440 -1, -1, -1, atoi(value)); 441 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 442 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 443 atoi(value))) { 444 ret = -1; 445 } else { 446 value[-1] = '='; 447 wpa_config_process_global(wpa_s->conf, cmd, -1); 448 } 449 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 450 0) { 451 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 452 atoi(value))) { 453 ret = -1; 454 } else { 455 value[-1] = '='; 456 wpa_config_process_global(wpa_s->conf, cmd, -1); 457 } 458 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 459 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 460 atoi(value))) { 461 ret = -1; 462 } else { 463 value[-1] = '='; 464 wpa_config_process_global(wpa_s->conf, cmd, -1); 465 } 466 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 467 wpa_s->wps_fragment_size = atoi(value); 468 #ifdef CONFIG_WPS_TESTING 469 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 470 long int val; 471 val = strtol(value, NULL, 0); 472 if (val < 0 || val > 0xff) { 473 ret = -1; 474 wpa_printf(MSG_DEBUG, "WPS: Invalid " 475 "wps_version_number %ld", val); 476 } else { 477 wps_version_number = val; 478 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 479 "version %u.%u", 480 (wps_version_number & 0xf0) >> 4, 481 wps_version_number & 0x0f); 482 } 483 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 484 wps_testing_dummy_cred = atoi(value); 485 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 486 wps_testing_dummy_cred); 487 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 488 wps_corrupt_pkhash = atoi(value); 489 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 490 wps_corrupt_pkhash); 491 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) { 492 if (value[0] == '\0') { 493 wps_force_auth_types_in_use = 0; 494 } else { 495 wps_force_auth_types = strtol(value, NULL, 0); 496 wps_force_auth_types_in_use = 1; 497 } 498 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) { 499 if (value[0] == '\0') { 500 wps_force_encr_types_in_use = 0; 501 } else { 502 wps_force_encr_types = strtol(value, NULL, 0); 503 wps_force_encr_types_in_use = 1; 504 } 505 #endif /* CONFIG_WPS_TESTING */ 506 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 507 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 508 ret = -1; 509 #ifdef CONFIG_TDLS 510 #ifdef CONFIG_TDLS_TESTING 511 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 512 tdls_testing = strtol(value, NULL, 0); 513 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 514 #endif /* CONFIG_TDLS_TESTING */ 515 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 516 int disabled = atoi(value); 517 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 518 if (disabled) { 519 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 520 ret = -1; 521 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 522 ret = -1; 523 wpa_tdls_enable(wpa_s->wpa, !disabled); 524 #endif /* CONFIG_TDLS */ 525 } else if (os_strcasecmp(cmd, "pno") == 0) { 526 ret = wpas_ctrl_pno(wpa_s, value); 527 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 528 int disabled = atoi(value); 529 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 530 ret = -1; 531 else if (disabled) 532 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 533 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 534 if (os_strcmp(value, "disable") == 0) 535 wpa_s->set_sta_uapsd = 0; 536 else { 537 int be, bk, vi, vo; 538 char *pos; 539 /* format: BE,BK,VI,VO;max SP Length */ 540 be = atoi(value); 541 pos = os_strchr(value, ','); 542 if (pos == NULL) 543 return -1; 544 pos++; 545 bk = atoi(pos); 546 pos = os_strchr(pos, ','); 547 if (pos == NULL) 548 return -1; 549 pos++; 550 vi = atoi(pos); 551 pos = os_strchr(pos, ','); 552 if (pos == NULL) 553 return -1; 554 pos++; 555 vo = atoi(pos); 556 /* ignore max SP Length for now */ 557 558 wpa_s->set_sta_uapsd = 1; 559 wpa_s->sta_uapsd = 0; 560 if (be) 561 wpa_s->sta_uapsd |= BIT(0); 562 if (bk) 563 wpa_s->sta_uapsd |= BIT(1); 564 if (vi) 565 wpa_s->sta_uapsd |= BIT(2); 566 if (vo) 567 wpa_s->sta_uapsd |= BIT(3); 568 } 569 } else if (os_strcasecmp(cmd, "ps") == 0) { 570 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 571 #ifdef CONFIG_WIFI_DISPLAY 572 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 573 int enabled = !!atoi(value); 574 if (enabled && !wpa_s->global->p2p) 575 ret = -1; 576 else 577 wifi_display_enable(wpa_s->global, enabled); 578 #endif /* CONFIG_WIFI_DISPLAY */ 579 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 580 ret = set_bssid_filter(wpa_s, value); 581 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 582 ret = set_disallow_aps(wpa_s, value); 583 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 584 wpa_s->no_keep_alive = !!atoi(value); 585 #ifdef CONFIG_DPP 586 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { 587 os_free(wpa_s->dpp_configurator_params); 588 wpa_s->dpp_configurator_params = os_strdup(value); 589 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { 590 wpa_s->dpp_init_max_tries = atoi(value); 591 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { 592 wpa_s->dpp_init_retry_time = atoi(value); 593 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { 594 wpa_s->dpp_resp_wait_time = atoi(value); 595 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { 596 wpa_s->dpp_resp_max_tries = atoi(value); 597 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { 598 wpa_s->dpp_resp_retry_time = atoi(value); 599 #ifdef CONFIG_TESTING_OPTIONS 600 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) { 601 if (hwaddr_aton(value, dpp_pkex_own_mac_override)) 602 ret = -1; 603 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) { 604 if (hwaddr_aton(value, dpp_pkex_peer_mac_override)) 605 ret = -1; 606 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) { 607 size_t hex_len = os_strlen(value); 608 609 if (hex_len > 610 2 * sizeof(dpp_pkex_ephemeral_key_override)) 611 ret = -1; 612 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override, 613 hex_len / 2)) 614 ret = -1; 615 else 616 dpp_pkex_ephemeral_key_override_len = hex_len / 2; 617 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) { 618 size_t hex_len = os_strlen(value); 619 620 if (hex_len > 2 * sizeof(dpp_protocol_key_override)) 621 ret = -1; 622 else if (hexstr2bin(value, dpp_protocol_key_override, 623 hex_len / 2)) 624 ret = -1; 625 else 626 dpp_protocol_key_override_len = hex_len / 2; 627 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) { 628 size_t hex_len = os_strlen(value); 629 630 if (hex_len > 2 * sizeof(dpp_nonce_override)) 631 ret = -1; 632 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2)) 633 ret = -1; 634 else 635 dpp_nonce_override_len = hex_len / 2; 636 #endif /* CONFIG_TESTING_OPTIONS */ 637 #endif /* CONFIG_DPP */ 638 #ifdef CONFIG_TESTING_OPTIONS 639 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 640 wpa_s->ext_mgmt_frame_handling = !!atoi(value); 641 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 642 wpa_s->ext_eapol_frame_io = !!atoi(value); 643 #ifdef CONFIG_AP 644 if (wpa_s->ap_iface) { 645 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io = 646 wpa_s->ext_eapol_frame_io; 647 } 648 #endif /* CONFIG_AP */ 649 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) { 650 wpa_s->extra_roc_dur = atoi(value); 651 } else if (os_strcasecmp(cmd, "test_failure") == 0) { 652 wpa_s->test_failure = atoi(value); 653 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) { 654 wpa_s->p2p_go_csa_on_inv = !!atoi(value); 655 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) { 656 wpa_s->ignore_auth_resp = !!atoi(value); 657 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) { 658 wpa_s->ignore_assoc_disallow = !!atoi(value); 659 wpa_drv_ignore_assoc_disallow(wpa_s, 660 wpa_s->ignore_assoc_disallow); 661 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) { 662 wpa_s->reject_btm_req_reason = atoi(value); 663 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) { 664 os_free(wpa_s->get_pref_freq_list_override); 665 if (!value[0]) 666 wpa_s->get_pref_freq_list_override = NULL; 667 else 668 wpa_s->get_pref_freq_list_override = os_strdup(value); 669 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) { 670 wpabuf_free(wpa_s->sae_commit_override); 671 if (value[0] == '\0') 672 wpa_s->sae_commit_override = NULL; 673 else 674 wpa_s->sae_commit_override = wpabuf_parse_bin(value); 675 #ifdef CONFIG_DPP 676 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { 677 os_free(wpa_s->dpp_config_obj_override); 678 if (value[0] == '\0') 679 wpa_s->dpp_config_obj_override = NULL; 680 else 681 wpa_s->dpp_config_obj_override = os_strdup(value); 682 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { 683 os_free(wpa_s->dpp_discovery_override); 684 if (value[0] == '\0') 685 wpa_s->dpp_discovery_override = NULL; 686 else 687 wpa_s->dpp_discovery_override = os_strdup(value); 688 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { 689 os_free(wpa_s->dpp_groups_override); 690 if (value[0] == '\0') 691 wpa_s->dpp_groups_override = NULL; 692 else 693 wpa_s->dpp_groups_override = os_strdup(value); 694 } else if (os_strcasecmp(cmd, 695 "dpp_ignore_netaccesskey_mismatch") == 0) { 696 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value); 697 } else if (os_strcasecmp(cmd, "dpp_test") == 0) { 698 dpp_test = atoi(value); 699 #endif /* CONFIG_DPP */ 700 #endif /* CONFIG_TESTING_OPTIONS */ 701 #ifdef CONFIG_FILS 702 } else if (os_strcasecmp(cmd, "disable_fils") == 0) { 703 wpa_s->disable_fils = !!atoi(value); 704 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils); 705 wpa_supplicant_set_default_scan_ies(wpa_s); 706 #endif /* CONFIG_FILS */ 707 #ifndef CONFIG_NO_CONFIG_BLOBS 708 } else if (os_strcmp(cmd, "blob") == 0) { 709 ret = wpas_ctrl_set_blob(wpa_s, value); 710 #endif /* CONFIG_NO_CONFIG_BLOBS */ 711 } else if (os_strcasecmp(cmd, "setband") == 0) { 712 ret = wpas_ctrl_set_band(wpa_s, value); 713 #ifdef CONFIG_MBO 714 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) { 715 ret = wpas_mbo_update_non_pref_chan(wpa_s, value); 716 if (ret == 0) { 717 value[-1] = '='; 718 wpa_config_process_global(wpa_s->conf, cmd, -1); 719 } 720 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { 721 wpas_mbo_update_cell_capa(wpa_s, atoi(value)); 722 } else if (os_strcasecmp(cmd, "oce") == 0) { 723 wpa_s->conf->oce = atoi(value); 724 if (wpa_s->conf->oce) { 725 if ((wpa_s->conf->oce & OCE_STA) && 726 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) 727 wpa_s->enable_oce = OCE_STA; 728 729 if ((wpa_s->conf->oce & OCE_STA_CFON) && 730 (wpa_s->drv_flags & 731 WPA_DRIVER_FLAGS_OCE_STA_CFON)) { 732 /* TODO: Need to add STA-CFON support */ 733 wpa_printf(MSG_ERROR, 734 "OCE STA-CFON feature is not yet supported"); 735 return -1; 736 } 737 } else { 738 wpa_s->enable_oce = 0; 739 } 740 wpa_supplicant_set_default_scan_ies(wpa_s); 741 #endif /* CONFIG_MBO */ 742 } else if (os_strcasecmp(cmd, "lci") == 0) { 743 ret = wpas_ctrl_iface_set_lci(wpa_s, value); 744 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) { 745 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value)); 746 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) { 747 ret = wpas_ctrl_set_relative_rssi(wpa_s, value); 748 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) { 749 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value); 750 } else if (os_strcasecmp(cmd, "ric_ies") == 0) { 751 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value); 752 } else if (os_strcasecmp(cmd, "roaming") == 0) { 753 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL); 754 #ifdef CONFIG_WNM 755 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) { 756 struct wpabuf *elems; 757 758 elems = wpabuf_parse_bin(value); 759 if (!elems) 760 return -1; 761 wnm_set_coloc_intf_elems(wpa_s, elems); 762 #endif /* CONFIG_WNM */ 763 } else { 764 value[-1] = '='; 765 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 766 if (ret == 0) 767 wpa_supplicant_update_config(wpa_s); 768 } 769 770 return ret; 771 } 772 773 774 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 775 char *cmd, char *buf, size_t buflen) 776 { 777 int res = -1; 778 779 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 780 781 if (os_strcmp(cmd, "version") == 0) { 782 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 783 } else if (os_strcasecmp(cmd, "country") == 0) { 784 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 785 res = os_snprintf(buf, buflen, "%c%c", 786 wpa_s->conf->country[0], 787 wpa_s->conf->country[1]); 788 #ifdef CONFIG_WIFI_DISPLAY 789 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 790 int enabled; 791 if (wpa_s->global->p2p == NULL || 792 wpa_s->global->p2p_disabled) 793 enabled = 0; 794 else 795 enabled = wpa_s->global->wifi_display; 796 res = os_snprintf(buf, buflen, "%d", enabled); 797 #endif /* CONFIG_WIFI_DISPLAY */ 798 #ifdef CONFIG_TESTING_GET_GTK 799 } else if (os_strcmp(cmd, "gtk") == 0) { 800 if (wpa_s->last_gtk_len == 0) 801 return -1; 802 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk, 803 wpa_s->last_gtk_len); 804 return res; 805 #endif /* CONFIG_TESTING_GET_GTK */ 806 } else if (os_strcmp(cmd, "tls_library") == 0) { 807 res = tls_get_library_version(buf, buflen); 808 #ifdef CONFIG_TESTING_OPTIONS 809 } else if (os_strcmp(cmd, "anonce") == 0) { 810 return wpa_snprintf_hex(buf, buflen, 811 wpa_sm_get_anonce(wpa_s->wpa), 812 WPA_NONCE_LEN); 813 #endif /* CONFIG_TESTING_OPTIONS */ 814 } else { 815 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); 816 } 817 818 if (os_snprintf_error(buflen, res)) 819 return -1; 820 return res; 821 } 822 823 824 #ifdef IEEE8021X_EAPOL 825 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 826 char *addr) 827 { 828 u8 bssid[ETH_ALEN]; 829 struct wpa_ssid *ssid = wpa_s->current_ssid; 830 831 if (hwaddr_aton(addr, bssid)) { 832 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 833 "'%s'", addr); 834 return -1; 835 } 836 837 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 838 rsn_preauth_deinit(wpa_s->wpa); 839 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 840 return -1; 841 842 return 0; 843 } 844 #endif /* IEEE8021X_EAPOL */ 845 846 847 #ifdef CONFIG_TDLS 848 849 static int wpa_supplicant_ctrl_iface_tdls_discover( 850 struct wpa_supplicant *wpa_s, char *addr) 851 { 852 u8 peer[ETH_ALEN]; 853 int ret; 854 855 if (hwaddr_aton(addr, peer)) { 856 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 857 "address '%s'", addr); 858 return -1; 859 } 860 861 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 862 MAC2STR(peer)); 863 864 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 865 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 866 else 867 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 868 869 return ret; 870 } 871 872 873 static int wpa_supplicant_ctrl_iface_tdls_setup( 874 struct wpa_supplicant *wpa_s, char *addr) 875 { 876 u8 peer[ETH_ALEN]; 877 int ret; 878 879 if (hwaddr_aton(addr, peer)) { 880 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 881 "address '%s'", addr); 882 return -1; 883 } 884 885 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 886 MAC2STR(peer)); 887 888 if ((wpa_s->conf->tdls_external_control) && 889 wpa_tdls_is_external_setup(wpa_s->wpa)) 890 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 891 892 wpa_tdls_remove(wpa_s->wpa, peer); 893 894 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 895 ret = wpa_tdls_start(wpa_s->wpa, peer); 896 else 897 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 898 899 return ret; 900 } 901 902 903 static int wpa_supplicant_ctrl_iface_tdls_teardown( 904 struct wpa_supplicant *wpa_s, char *addr) 905 { 906 u8 peer[ETH_ALEN]; 907 int ret; 908 909 if (os_strcmp(addr, "*") == 0) { 910 /* remove everyone */ 911 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *"); 912 wpa_tdls_teardown_peers(wpa_s->wpa); 913 return 0; 914 } 915 916 if (hwaddr_aton(addr, peer)) { 917 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 918 "address '%s'", addr); 919 return -1; 920 } 921 922 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 923 MAC2STR(peer)); 924 925 if ((wpa_s->conf->tdls_external_control) && 926 wpa_tdls_is_external_setup(wpa_s->wpa)) 927 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 928 929 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 930 ret = wpa_tdls_teardown_link( 931 wpa_s->wpa, peer, 932 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 933 else 934 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 935 936 return ret; 937 } 938 939 940 static int ctrl_iface_get_capability_tdls( 941 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 942 { 943 int ret; 944 945 ret = os_snprintf(buf, buflen, "%s\n", 946 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ? 947 (wpa_s->drv_flags & 948 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ? 949 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED"); 950 if (os_snprintf_error(buflen, ret)) 951 return -1; 952 return ret; 953 } 954 955 956 static int wpa_supplicant_ctrl_iface_tdls_chan_switch( 957 struct wpa_supplicant *wpa_s, char *cmd) 958 { 959 u8 peer[ETH_ALEN]; 960 struct hostapd_freq_params freq_params; 961 u8 oper_class; 962 char *pos, *end; 963 964 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 965 wpa_printf(MSG_INFO, 966 "tdls_chanswitch: Only supported with external setup"); 967 return -1; 968 } 969 970 os_memset(&freq_params, 0, sizeof(freq_params)); 971 972 pos = os_strchr(cmd, ' '); 973 if (pos == NULL) 974 return -1; 975 *pos++ = '\0'; 976 977 oper_class = strtol(pos, &end, 10); 978 if (pos == end) { 979 wpa_printf(MSG_INFO, 980 "tdls_chanswitch: Invalid op class provided"); 981 return -1; 982 } 983 984 pos = end; 985 freq_params.freq = atoi(pos); 986 if (freq_params.freq == 0) { 987 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided"); 988 return -1; 989 } 990 991 #define SET_FREQ_SETTING(str) \ 992 do { \ 993 const char *pos2 = os_strstr(pos, " " #str "="); \ 994 if (pos2) { \ 995 pos2 += sizeof(" " #str "=") - 1; \ 996 freq_params.str = atoi(pos2); \ 997 } \ 998 } while (0) 999 1000 SET_FREQ_SETTING(center_freq1); 1001 SET_FREQ_SETTING(center_freq2); 1002 SET_FREQ_SETTING(bandwidth); 1003 SET_FREQ_SETTING(sec_channel_offset); 1004 #undef SET_FREQ_SETTING 1005 1006 freq_params.ht_enabled = !!os_strstr(pos, " ht"); 1007 freq_params.vht_enabled = !!os_strstr(pos, " vht"); 1008 1009 if (hwaddr_aton(cmd, peer)) { 1010 wpa_printf(MSG_DEBUG, 1011 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'", 1012 cmd); 1013 return -1; 1014 } 1015 1016 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR 1017 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s", 1018 MAC2STR(peer), oper_class, freq_params.freq, 1019 freq_params.center_freq1, freq_params.center_freq2, 1020 freq_params.bandwidth, freq_params.sec_channel_offset, 1021 freq_params.ht_enabled ? " HT" : "", 1022 freq_params.vht_enabled ? " VHT" : ""); 1023 1024 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class, 1025 &freq_params); 1026 } 1027 1028 1029 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch( 1030 struct wpa_supplicant *wpa_s, char *cmd) 1031 { 1032 u8 peer[ETH_ALEN]; 1033 1034 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 1035 wpa_printf(MSG_INFO, 1036 "tdls_chanswitch: Only supported with external setup"); 1037 return -1; 1038 } 1039 1040 if (hwaddr_aton(cmd, peer)) { 1041 wpa_printf(MSG_DEBUG, 1042 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'", 1043 cmd); 1044 return -1; 1045 } 1046 1047 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR, 1048 MAC2STR(peer)); 1049 1050 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer); 1051 } 1052 1053 1054 static int wpa_supplicant_ctrl_iface_tdls_link_status( 1055 struct wpa_supplicant *wpa_s, const char *addr, 1056 char *buf, size_t buflen) 1057 { 1058 u8 peer[ETH_ALEN]; 1059 const char *tdls_status; 1060 int ret; 1061 1062 if (hwaddr_aton(addr, peer)) { 1063 wpa_printf(MSG_DEBUG, 1064 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'", 1065 addr); 1066 return -1; 1067 } 1068 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR, 1069 MAC2STR(peer)); 1070 1071 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 1072 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status); 1073 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status); 1074 if (os_snprintf_error(buflen, ret)) 1075 return -1; 1076 1077 return ret; 1078 } 1079 1080 #endif /* CONFIG_TDLS */ 1081 1082 1083 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd) 1084 { 1085 char *token, *context = NULL; 1086 struct wmm_ac_ts_setup_params params = { 1087 .tsid = 0xff, 1088 .direction = 0xff, 1089 }; 1090 1091 while ((token = str_token(cmd, " ", &context))) { 1092 if (sscanf(token, "tsid=%i", ¶ms.tsid) == 1 || 1093 sscanf(token, "up=%i", ¶ms.user_priority) == 1 || 1094 sscanf(token, "nominal_msdu_size=%i", 1095 ¶ms.nominal_msdu_size) == 1 || 1096 sscanf(token, "mean_data_rate=%i", 1097 ¶ms.mean_data_rate) == 1 || 1098 sscanf(token, "min_phy_rate=%i", 1099 ¶ms.minimum_phy_rate) == 1 || 1100 sscanf(token, "sba=%i", 1101 ¶ms.surplus_bandwidth_allowance) == 1) 1102 continue; 1103 1104 if (os_strcasecmp(token, "downlink") == 0) { 1105 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK; 1106 } else if (os_strcasecmp(token, "uplink") == 0) { 1107 params.direction = WMM_TSPEC_DIRECTION_UPLINK; 1108 } else if (os_strcasecmp(token, "bidi") == 0) { 1109 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL; 1110 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) { 1111 params.fixed_nominal_msdu = 1; 1112 } else { 1113 wpa_printf(MSG_DEBUG, 1114 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'", 1115 token); 1116 return -1; 1117 } 1118 1119 } 1120 1121 return wpas_wmm_ac_addts(wpa_s, ¶ms); 1122 } 1123 1124 1125 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd) 1126 { 1127 u8 tsid = atoi(cmd); 1128 1129 return wpas_wmm_ac_delts(wpa_s, tsid); 1130 } 1131 1132 1133 #ifdef CONFIG_IEEE80211R 1134 static int wpa_supplicant_ctrl_iface_ft_ds( 1135 struct wpa_supplicant *wpa_s, char *addr) 1136 { 1137 u8 target_ap[ETH_ALEN]; 1138 struct wpa_bss *bss; 1139 const u8 *mdie; 1140 1141 if (hwaddr_aton(addr, target_ap)) { 1142 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 1143 "address '%s'", addr); 1144 return -1; 1145 } 1146 1147 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 1148 1149 bss = wpa_bss_get_bssid(wpa_s, target_ap); 1150 if (bss) 1151 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 1152 else 1153 mdie = NULL; 1154 1155 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 1156 } 1157 #endif /* CONFIG_IEEE80211R */ 1158 1159 1160 #ifdef CONFIG_WPS 1161 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 1162 char *cmd) 1163 { 1164 u8 bssid[ETH_ALEN], *_bssid = bssid; 1165 #ifdef CONFIG_P2P 1166 u8 p2p_dev_addr[ETH_ALEN]; 1167 #endif /* CONFIG_P2P */ 1168 #ifdef CONFIG_AP 1169 u8 *_p2p_dev_addr = NULL; 1170 #endif /* CONFIG_AP */ 1171 char *pos; 1172 int multi_ap = 0; 1173 1174 if (!cmd || os_strcmp(cmd, "any") == 0 || 1175 os_strncmp(cmd, "any ", 4) == 0) { 1176 _bssid = NULL; 1177 #ifdef CONFIG_P2P 1178 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 1179 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 1180 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 1181 "P2P Device Address '%s'", 1182 cmd + 13); 1183 return -1; 1184 } 1185 _p2p_dev_addr = p2p_dev_addr; 1186 #endif /* CONFIG_P2P */ 1187 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) { 1188 _bssid = NULL; 1189 multi_ap = atoi(cmd + 9); 1190 } else if (hwaddr_aton(cmd, bssid)) { 1191 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 1192 cmd); 1193 return -1; 1194 } 1195 1196 if (cmd) { 1197 pos = os_strstr(cmd, " multi_ap="); 1198 if (pos) { 1199 pos += 10; 1200 multi_ap = atoi(pos); 1201 } 1202 } 1203 1204 #ifdef CONFIG_AP 1205 if (wpa_s->ap_iface) 1206 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 1207 #endif /* CONFIG_AP */ 1208 1209 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap); 1210 } 1211 1212 1213 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 1214 char *cmd, char *buf, 1215 size_t buflen) 1216 { 1217 u8 bssid[ETH_ALEN], *_bssid = bssid; 1218 char *pin; 1219 int ret; 1220 1221 pin = os_strchr(cmd, ' '); 1222 if (pin) 1223 *pin++ = '\0'; 1224 1225 if (os_strcmp(cmd, "any") == 0) 1226 _bssid = NULL; 1227 else if (os_strcmp(cmd, "get") == 0) { 1228 if (wps_generate_pin((unsigned int *) &ret) < 0) 1229 return -1; 1230 goto done; 1231 } else if (hwaddr_aton(cmd, bssid)) { 1232 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 1233 cmd); 1234 return -1; 1235 } 1236 1237 #ifdef CONFIG_AP 1238 if (wpa_s->ap_iface) { 1239 int timeout = 0; 1240 char *pos; 1241 1242 if (pin) { 1243 pos = os_strchr(pin, ' '); 1244 if (pos) { 1245 *pos++ = '\0'; 1246 timeout = atoi(pos); 1247 } 1248 } 1249 1250 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 1251 buf, buflen, timeout); 1252 } 1253 #endif /* CONFIG_AP */ 1254 1255 if (pin) { 1256 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 1257 DEV_PW_DEFAULT); 1258 if (ret < 0) 1259 return -1; 1260 ret = os_snprintf(buf, buflen, "%s", pin); 1261 if (os_snprintf_error(buflen, ret)) 1262 return -1; 1263 return ret; 1264 } 1265 1266 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 1267 if (ret < 0) 1268 return -1; 1269 1270 done: 1271 /* Return the generated PIN */ 1272 ret = os_snprintf(buf, buflen, "%08d", ret); 1273 if (os_snprintf_error(buflen, ret)) 1274 return -1; 1275 return ret; 1276 } 1277 1278 1279 static int wpa_supplicant_ctrl_iface_wps_check_pin( 1280 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1281 { 1282 char pin[9]; 1283 size_t len; 1284 char *pos; 1285 int ret; 1286 1287 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 1288 (u8 *) cmd, os_strlen(cmd)); 1289 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 1290 if (*pos < '0' || *pos > '9') 1291 continue; 1292 pin[len++] = *pos; 1293 if (len == 9) { 1294 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 1295 return -1; 1296 } 1297 } 1298 if (len != 4 && len != 8) { 1299 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 1300 return -1; 1301 } 1302 pin[len] = '\0'; 1303 1304 if (len == 8) { 1305 unsigned int pin_val; 1306 pin_val = atoi(pin); 1307 if (!wps_pin_valid(pin_val)) { 1308 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 1309 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 1310 if (os_snprintf_error(buflen, ret)) 1311 return -1; 1312 return ret; 1313 } 1314 } 1315 1316 ret = os_snprintf(buf, buflen, "%s", pin); 1317 if (os_snprintf_error(buflen, ret)) 1318 return -1; 1319 1320 return ret; 1321 } 1322 1323 1324 #ifdef CONFIG_WPS_NFC 1325 1326 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 1327 char *cmd) 1328 { 1329 u8 bssid[ETH_ALEN], *_bssid = bssid; 1330 1331 if (cmd == NULL || cmd[0] == '\0') 1332 _bssid = NULL; 1333 else if (hwaddr_aton(cmd, bssid)) 1334 return -1; 1335 1336 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL, 1337 0, 0); 1338 } 1339 1340 1341 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( 1342 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1343 { 1344 int ndef; 1345 struct wpabuf *buf; 1346 int res; 1347 char *pos; 1348 1349 pos = os_strchr(cmd, ' '); 1350 if (pos) 1351 *pos++ = '\0'; 1352 if (os_strcmp(cmd, "WPS") == 0) 1353 ndef = 0; 1354 else if (os_strcmp(cmd, "NDEF") == 0) 1355 ndef = 1; 1356 else 1357 return -1; 1358 1359 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos); 1360 if (buf == NULL) 1361 return -1; 1362 1363 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1364 wpabuf_len(buf)); 1365 reply[res++] = '\n'; 1366 reply[res] = '\0'; 1367 1368 wpabuf_free(buf); 1369 1370 return res; 1371 } 1372 1373 1374 static int wpa_supplicant_ctrl_iface_wps_nfc_token( 1375 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1376 { 1377 int ndef; 1378 struct wpabuf *buf; 1379 int res; 1380 1381 if (os_strcmp(cmd, "WPS") == 0) 1382 ndef = 0; 1383 else if (os_strcmp(cmd, "NDEF") == 0) 1384 ndef = 1; 1385 else 1386 return -1; 1387 1388 buf = wpas_wps_nfc_token(wpa_s, ndef); 1389 if (buf == NULL) 1390 return -1; 1391 1392 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1393 wpabuf_len(buf)); 1394 reply[res++] = '\n'; 1395 reply[res] = '\0'; 1396 1397 wpabuf_free(buf); 1398 1399 return res; 1400 } 1401 1402 1403 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 1404 struct wpa_supplicant *wpa_s, char *pos) 1405 { 1406 size_t len; 1407 struct wpabuf *buf; 1408 int ret; 1409 char *freq; 1410 int forced_freq = 0; 1411 1412 freq = strstr(pos, " freq="); 1413 if (freq) { 1414 *freq = '\0'; 1415 freq += 6; 1416 forced_freq = atoi(freq); 1417 } 1418 1419 len = os_strlen(pos); 1420 if (len & 0x01) 1421 return -1; 1422 len /= 2; 1423 1424 buf = wpabuf_alloc(len); 1425 if (buf == NULL) 1426 return -1; 1427 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 1428 wpabuf_free(buf); 1429 return -1; 1430 } 1431 1432 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq); 1433 wpabuf_free(buf); 1434 1435 return ret; 1436 } 1437 1438 1439 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 1440 char *reply, size_t max_len, 1441 int ndef) 1442 { 1443 struct wpabuf *buf; 1444 int res; 1445 1446 buf = wpas_wps_nfc_handover_req(wpa_s, ndef); 1447 if (buf == NULL) 1448 return -1; 1449 1450 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1451 wpabuf_len(buf)); 1452 reply[res++] = '\n'; 1453 reply[res] = '\0'; 1454 1455 wpabuf_free(buf); 1456 1457 return res; 1458 } 1459 1460 1461 #ifdef CONFIG_P2P 1462 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s, 1463 char *reply, size_t max_len, 1464 int ndef) 1465 { 1466 struct wpabuf *buf; 1467 int res; 1468 1469 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef); 1470 if (buf == NULL) { 1471 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request"); 1472 return -1; 1473 } 1474 1475 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1476 wpabuf_len(buf)); 1477 reply[res++] = '\n'; 1478 reply[res] = '\0'; 1479 1480 wpabuf_free(buf); 1481 1482 return res; 1483 } 1484 #endif /* CONFIG_P2P */ 1485 1486 1487 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 1488 char *cmd, char *reply, 1489 size_t max_len) 1490 { 1491 char *pos; 1492 int ndef; 1493 1494 pos = os_strchr(cmd, ' '); 1495 if (pos == NULL) 1496 return -1; 1497 *pos++ = '\0'; 1498 1499 if (os_strcmp(cmd, "WPS") == 0) 1500 ndef = 0; 1501 else if (os_strcmp(cmd, "NDEF") == 0) 1502 ndef = 1; 1503 else 1504 return -1; 1505 1506 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1507 if (!ndef) 1508 return -1; 1509 return wpas_ctrl_nfc_get_handover_req_wps( 1510 wpa_s, reply, max_len, ndef); 1511 } 1512 1513 #ifdef CONFIG_P2P 1514 if (os_strcmp(pos, "P2P-CR") == 0) { 1515 return wpas_ctrl_nfc_get_handover_req_p2p( 1516 wpa_s, reply, max_len, ndef); 1517 } 1518 #endif /* CONFIG_P2P */ 1519 1520 return -1; 1521 } 1522 1523 1524 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 1525 char *reply, size_t max_len, 1526 int ndef, int cr, char *uuid) 1527 { 1528 struct wpabuf *buf; 1529 int res; 1530 1531 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid); 1532 if (buf == NULL) 1533 return -1; 1534 1535 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1536 wpabuf_len(buf)); 1537 reply[res++] = '\n'; 1538 reply[res] = '\0'; 1539 1540 wpabuf_free(buf); 1541 1542 return res; 1543 } 1544 1545 1546 #ifdef CONFIG_P2P 1547 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s, 1548 char *reply, size_t max_len, 1549 int ndef, int tag) 1550 { 1551 struct wpabuf *buf; 1552 int res; 1553 1554 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag); 1555 if (buf == NULL) 1556 return -1; 1557 1558 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1559 wpabuf_len(buf)); 1560 reply[res++] = '\n'; 1561 reply[res] = '\0'; 1562 1563 wpabuf_free(buf); 1564 1565 return res; 1566 } 1567 #endif /* CONFIG_P2P */ 1568 1569 1570 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 1571 char *cmd, char *reply, 1572 size_t max_len) 1573 { 1574 char *pos, *pos2; 1575 int ndef; 1576 1577 pos = os_strchr(cmd, ' '); 1578 if (pos == NULL) 1579 return -1; 1580 *pos++ = '\0'; 1581 1582 if (os_strcmp(cmd, "WPS") == 0) 1583 ndef = 0; 1584 else if (os_strcmp(cmd, "NDEF") == 0) 1585 ndef = 1; 1586 else 1587 return -1; 1588 1589 pos2 = os_strchr(pos, ' '); 1590 if (pos2) 1591 *pos2++ = '\0'; 1592 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1593 if (!ndef) 1594 return -1; 1595 return wpas_ctrl_nfc_get_handover_sel_wps( 1596 wpa_s, reply, max_len, ndef, 1597 os_strcmp(pos, "WPS-CR") == 0, pos2); 1598 } 1599 1600 #ifdef CONFIG_P2P 1601 if (os_strcmp(pos, "P2P-CR") == 0) { 1602 return wpas_ctrl_nfc_get_handover_sel_p2p( 1603 wpa_s, reply, max_len, ndef, 0); 1604 } 1605 1606 if (os_strcmp(pos, "P2P-CR-TAG") == 0) { 1607 return wpas_ctrl_nfc_get_handover_sel_p2p( 1608 wpa_s, reply, max_len, ndef, 1); 1609 } 1610 #endif /* CONFIG_P2P */ 1611 1612 return -1; 1613 } 1614 1615 1616 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s, 1617 char *cmd) 1618 { 1619 size_t len; 1620 struct wpabuf *req, *sel; 1621 int ret; 1622 char *pos, *role, *type, *pos2; 1623 #ifdef CONFIG_P2P 1624 char *freq; 1625 int forced_freq = 0; 1626 1627 freq = strstr(cmd, " freq="); 1628 if (freq) { 1629 *freq = '\0'; 1630 freq += 6; 1631 forced_freq = atoi(freq); 1632 } 1633 #endif /* CONFIG_P2P */ 1634 1635 role = cmd; 1636 pos = os_strchr(role, ' '); 1637 if (pos == NULL) { 1638 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report"); 1639 return -1; 1640 } 1641 *pos++ = '\0'; 1642 1643 type = pos; 1644 pos = os_strchr(type, ' '); 1645 if (pos == NULL) { 1646 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report"); 1647 return -1; 1648 } 1649 *pos++ = '\0'; 1650 1651 pos2 = os_strchr(pos, ' '); 1652 if (pos2 == NULL) { 1653 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report"); 1654 return -1; 1655 } 1656 *pos2++ = '\0'; 1657 1658 len = os_strlen(pos); 1659 if (len & 0x01) { 1660 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report"); 1661 return -1; 1662 } 1663 len /= 2; 1664 1665 req = wpabuf_alloc(len); 1666 if (req == NULL) { 1667 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message"); 1668 return -1; 1669 } 1670 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 1671 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report"); 1672 wpabuf_free(req); 1673 return -1; 1674 } 1675 1676 len = os_strlen(pos2); 1677 if (len & 0x01) { 1678 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report"); 1679 wpabuf_free(req); 1680 return -1; 1681 } 1682 len /= 2; 1683 1684 sel = wpabuf_alloc(len); 1685 if (sel == NULL) { 1686 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message"); 1687 wpabuf_free(req); 1688 return -1; 1689 } 1690 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 1691 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report"); 1692 wpabuf_free(req); 1693 wpabuf_free(sel); 1694 return -1; 1695 } 1696 1697 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d", 1698 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel)); 1699 1700 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) { 1701 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel); 1702 #ifdef CONFIG_AP 1703 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) 1704 { 1705 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel); 1706 if (ret < 0) 1707 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel); 1708 #endif /* CONFIG_AP */ 1709 #ifdef CONFIG_P2P 1710 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0) 1711 { 1712 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0); 1713 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0) 1714 { 1715 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel, 1716 forced_freq); 1717 #endif /* CONFIG_P2P */ 1718 } else { 1719 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 1720 "reported: role=%s type=%s", role, type); 1721 ret = -1; 1722 } 1723 wpabuf_free(req); 1724 wpabuf_free(sel); 1725 1726 if (ret) 1727 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages"); 1728 1729 return ret; 1730 } 1731 1732 #endif /* CONFIG_WPS_NFC */ 1733 1734 1735 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 1736 char *cmd) 1737 { 1738 u8 bssid[ETH_ALEN]; 1739 char *pin; 1740 char *new_ssid; 1741 char *new_auth; 1742 char *new_encr; 1743 char *new_key; 1744 struct wps_new_ap_settings ap; 1745 1746 pin = os_strchr(cmd, ' '); 1747 if (pin == NULL) 1748 return -1; 1749 *pin++ = '\0'; 1750 1751 if (hwaddr_aton(cmd, bssid)) { 1752 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1753 cmd); 1754 return -1; 1755 } 1756 1757 new_ssid = os_strchr(pin, ' '); 1758 if (new_ssid == NULL) 1759 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1760 *new_ssid++ = '\0'; 1761 1762 new_auth = os_strchr(new_ssid, ' '); 1763 if (new_auth == NULL) 1764 return -1; 1765 *new_auth++ = '\0'; 1766 1767 new_encr = os_strchr(new_auth, ' '); 1768 if (new_encr == NULL) 1769 return -1; 1770 *new_encr++ = '\0'; 1771 1772 new_key = os_strchr(new_encr, ' '); 1773 if (new_key == NULL) 1774 return -1; 1775 *new_key++ = '\0'; 1776 1777 os_memset(&ap, 0, sizeof(ap)); 1778 ap.ssid_hex = new_ssid; 1779 ap.auth = new_auth; 1780 ap.encr = new_encr; 1781 ap.key_hex = new_key; 1782 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1783 } 1784 1785 1786 #ifdef CONFIG_AP 1787 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 1788 char *cmd, char *buf, 1789 size_t buflen) 1790 { 1791 int timeout = 300; 1792 char *pos; 1793 const char *pin_txt; 1794 1795 if (!wpa_s->ap_iface) 1796 return -1; 1797 1798 pos = os_strchr(cmd, ' '); 1799 if (pos) 1800 *pos++ = '\0'; 1801 1802 if (os_strcmp(cmd, "disable") == 0) { 1803 wpas_wps_ap_pin_disable(wpa_s); 1804 return os_snprintf(buf, buflen, "OK\n"); 1805 } 1806 1807 if (os_strcmp(cmd, "random") == 0) { 1808 if (pos) 1809 timeout = atoi(pos); 1810 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 1811 if (pin_txt == NULL) 1812 return -1; 1813 return os_snprintf(buf, buflen, "%s", pin_txt); 1814 } 1815 1816 if (os_strcmp(cmd, "get") == 0) { 1817 pin_txt = wpas_wps_ap_pin_get(wpa_s); 1818 if (pin_txt == NULL) 1819 return -1; 1820 return os_snprintf(buf, buflen, "%s", pin_txt); 1821 } 1822 1823 if (os_strcmp(cmd, "set") == 0) { 1824 char *pin; 1825 if (pos == NULL) 1826 return -1; 1827 pin = pos; 1828 pos = os_strchr(pos, ' '); 1829 if (pos) { 1830 *pos++ = '\0'; 1831 timeout = atoi(pos); 1832 } 1833 if (os_strlen(pin) > buflen) 1834 return -1; 1835 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 1836 return -1; 1837 return os_snprintf(buf, buflen, "%s", pin); 1838 } 1839 1840 return -1; 1841 } 1842 #endif /* CONFIG_AP */ 1843 1844 1845 #ifdef CONFIG_WPS_ER 1846 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 1847 char *cmd) 1848 { 1849 char *uuid = cmd, *pin, *pos; 1850 u8 addr_buf[ETH_ALEN], *addr = NULL; 1851 pin = os_strchr(uuid, ' '); 1852 if (pin == NULL) 1853 return -1; 1854 *pin++ = '\0'; 1855 pos = os_strchr(pin, ' '); 1856 if (pos) { 1857 *pos++ = '\0'; 1858 if (hwaddr_aton(pos, addr_buf) == 0) 1859 addr = addr_buf; 1860 } 1861 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 1862 } 1863 1864 1865 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 1866 char *cmd) 1867 { 1868 char *uuid = cmd, *pin; 1869 pin = os_strchr(uuid, ' '); 1870 if (pin == NULL) 1871 return -1; 1872 *pin++ = '\0'; 1873 return wpas_wps_er_learn(wpa_s, uuid, pin); 1874 } 1875 1876 1877 static int wpa_supplicant_ctrl_iface_wps_er_set_config( 1878 struct wpa_supplicant *wpa_s, char *cmd) 1879 { 1880 char *uuid = cmd, *id; 1881 id = os_strchr(uuid, ' '); 1882 if (id == NULL) 1883 return -1; 1884 *id++ = '\0'; 1885 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 1886 } 1887 1888 1889 static int wpa_supplicant_ctrl_iface_wps_er_config( 1890 struct wpa_supplicant *wpa_s, char *cmd) 1891 { 1892 char *pin; 1893 char *new_ssid; 1894 char *new_auth; 1895 char *new_encr; 1896 char *new_key; 1897 struct wps_new_ap_settings ap; 1898 1899 pin = os_strchr(cmd, ' '); 1900 if (pin == NULL) 1901 return -1; 1902 *pin++ = '\0'; 1903 1904 new_ssid = os_strchr(pin, ' '); 1905 if (new_ssid == NULL) 1906 return -1; 1907 *new_ssid++ = '\0'; 1908 1909 new_auth = os_strchr(new_ssid, ' '); 1910 if (new_auth == NULL) 1911 return -1; 1912 *new_auth++ = '\0'; 1913 1914 new_encr = os_strchr(new_auth, ' '); 1915 if (new_encr == NULL) 1916 return -1; 1917 *new_encr++ = '\0'; 1918 1919 new_key = os_strchr(new_encr, ' '); 1920 if (new_key == NULL) 1921 return -1; 1922 *new_key++ = '\0'; 1923 1924 os_memset(&ap, 0, sizeof(ap)); 1925 ap.ssid_hex = new_ssid; 1926 ap.auth = new_auth; 1927 ap.encr = new_encr; 1928 ap.key_hex = new_key; 1929 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 1930 } 1931 1932 1933 #ifdef CONFIG_WPS_NFC 1934 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 1935 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1936 { 1937 int ndef; 1938 struct wpabuf *buf; 1939 int res; 1940 char *uuid; 1941 1942 uuid = os_strchr(cmd, ' '); 1943 if (uuid == NULL) 1944 return -1; 1945 *uuid++ = '\0'; 1946 1947 if (os_strcmp(cmd, "WPS") == 0) 1948 ndef = 0; 1949 else if (os_strcmp(cmd, "NDEF") == 0) 1950 ndef = 1; 1951 else 1952 return -1; 1953 1954 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 1955 if (buf == NULL) 1956 return -1; 1957 1958 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1959 wpabuf_len(buf)); 1960 reply[res++] = '\n'; 1961 reply[res] = '\0'; 1962 1963 wpabuf_free(buf); 1964 1965 return res; 1966 } 1967 #endif /* CONFIG_WPS_NFC */ 1968 #endif /* CONFIG_WPS_ER */ 1969 1970 #endif /* CONFIG_WPS */ 1971 1972 1973 #ifdef CONFIG_IBSS_RSN 1974 static int wpa_supplicant_ctrl_iface_ibss_rsn( 1975 struct wpa_supplicant *wpa_s, char *addr) 1976 { 1977 u8 peer[ETH_ALEN]; 1978 1979 if (hwaddr_aton(addr, peer)) { 1980 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 1981 "address '%s'", addr); 1982 return -1; 1983 } 1984 1985 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 1986 MAC2STR(peer)); 1987 1988 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 1989 } 1990 #endif /* CONFIG_IBSS_RSN */ 1991 1992 1993 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 1994 char *rsp) 1995 { 1996 #ifdef IEEE8021X_EAPOL 1997 char *pos, *id_pos; 1998 int id; 1999 struct wpa_ssid *ssid; 2000 2001 pos = os_strchr(rsp, '-'); 2002 if (pos == NULL) 2003 return -1; 2004 *pos++ = '\0'; 2005 id_pos = pos; 2006 pos = os_strchr(pos, ':'); 2007 if (pos == NULL) 2008 return -1; 2009 *pos++ = '\0'; 2010 id = atoi(id_pos); 2011 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 2012 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2013 (u8 *) pos, os_strlen(pos)); 2014 2015 ssid = wpa_config_get_network(wpa_s->conf, id); 2016 if (ssid == NULL) { 2017 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2018 "to update", id); 2019 return -1; 2020 } 2021 2022 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 2023 pos); 2024 #else /* IEEE8021X_EAPOL */ 2025 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 2026 return -1; 2027 #endif /* IEEE8021X_EAPOL */ 2028 } 2029 2030 2031 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 2032 const char *params, 2033 char *buf, size_t buflen) 2034 { 2035 char *pos, *end, tmp[30]; 2036 int res, verbose, wps, ret; 2037 #ifdef CONFIG_HS20 2038 const u8 *hs20; 2039 #endif /* CONFIG_HS20 */ 2040 const u8 *sess_id; 2041 size_t sess_id_len; 2042 2043 if (os_strcmp(params, "-DRIVER") == 0) 2044 return wpa_drv_status(wpa_s, buf, buflen); 2045 verbose = os_strcmp(params, "-VERBOSE") == 0; 2046 wps = os_strcmp(params, "-WPS") == 0; 2047 pos = buf; 2048 end = buf + buflen; 2049 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 2050 struct wpa_ssid *ssid = wpa_s->current_ssid; 2051 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2052 MAC2STR(wpa_s->bssid)); 2053 if (os_snprintf_error(end - pos, ret)) 2054 return pos - buf; 2055 pos += ret; 2056 ret = os_snprintf(pos, end - pos, "freq=%u\n", 2057 wpa_s->assoc_freq); 2058 if (os_snprintf_error(end - pos, ret)) 2059 return pos - buf; 2060 pos += ret; 2061 if (ssid) { 2062 u8 *_ssid = ssid->ssid; 2063 size_t ssid_len = ssid->ssid_len; 2064 u8 ssid_buf[SSID_MAX_LEN]; 2065 if (ssid_len == 0) { 2066 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 2067 if (_res < 0) 2068 ssid_len = 0; 2069 else 2070 ssid_len = _res; 2071 _ssid = ssid_buf; 2072 } 2073 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 2074 wpa_ssid_txt(_ssid, ssid_len), 2075 ssid->id); 2076 if (os_snprintf_error(end - pos, ret)) 2077 return pos - buf; 2078 pos += ret; 2079 2080 if (wps && ssid->passphrase && 2081 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 2082 (ssid->mode == WPAS_MODE_AP || 2083 ssid->mode == WPAS_MODE_P2P_GO)) { 2084 ret = os_snprintf(pos, end - pos, 2085 "passphrase=%s\n", 2086 ssid->passphrase); 2087 if (os_snprintf_error(end - pos, ret)) 2088 return pos - buf; 2089 pos += ret; 2090 } 2091 if (ssid->id_str) { 2092 ret = os_snprintf(pos, end - pos, 2093 "id_str=%s\n", 2094 ssid->id_str); 2095 if (os_snprintf_error(end - pos, ret)) 2096 return pos - buf; 2097 pos += ret; 2098 } 2099 2100 switch (ssid->mode) { 2101 case WPAS_MODE_INFRA: 2102 ret = os_snprintf(pos, end - pos, 2103 "mode=station\n"); 2104 break; 2105 case WPAS_MODE_IBSS: 2106 ret = os_snprintf(pos, end - pos, 2107 "mode=IBSS\n"); 2108 break; 2109 case WPAS_MODE_AP: 2110 ret = os_snprintf(pos, end - pos, 2111 "mode=AP\n"); 2112 break; 2113 case WPAS_MODE_P2P_GO: 2114 ret = os_snprintf(pos, end - pos, 2115 "mode=P2P GO\n"); 2116 break; 2117 case WPAS_MODE_P2P_GROUP_FORMATION: 2118 ret = os_snprintf(pos, end - pos, 2119 "mode=P2P GO - group " 2120 "formation\n"); 2121 break; 2122 case WPAS_MODE_MESH: 2123 ret = os_snprintf(pos, end - pos, 2124 "mode=mesh\n"); 2125 break; 2126 default: 2127 ret = 0; 2128 break; 2129 } 2130 if (os_snprintf_error(end - pos, ret)) 2131 return pos - buf; 2132 pos += ret; 2133 } 2134 2135 if (wpa_s->connection_set && 2136 (wpa_s->connection_ht || wpa_s->connection_vht || 2137 wpa_s->connection_he)) { 2138 ret = os_snprintf(pos, end - pos, 2139 "wifi_generation=%u\n", 2140 wpa_s->connection_he ? 6 : 2141 (wpa_s->connection_vht ? 5 : 4)); 2142 if (os_snprintf_error(end - pos, ret)) 2143 return pos - buf; 2144 pos += ret; 2145 } 2146 2147 #ifdef CONFIG_AP 2148 if (wpa_s->ap_iface) { 2149 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 2150 end - pos, 2151 verbose); 2152 } else 2153 #endif /* CONFIG_AP */ 2154 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 2155 } 2156 #ifdef CONFIG_SME 2157 #ifdef CONFIG_SAE 2158 if (wpa_s->wpa_state >= WPA_ASSOCIATED && 2159 #ifdef CONFIG_AP 2160 !wpa_s->ap_iface && 2161 #endif /* CONFIG_AP */ 2162 wpa_s->sme.sae.state == SAE_ACCEPTED) { 2163 ret = os_snprintf(pos, end - pos, "sae_group=%d\n", 2164 wpa_s->sme.sae.group); 2165 if (os_snprintf_error(end - pos, ret)) 2166 return pos - buf; 2167 pos += ret; 2168 } 2169 #endif /* CONFIG_SAE */ 2170 #endif /* CONFIG_SME */ 2171 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 2172 wpa_supplicant_state_txt(wpa_s->wpa_state)); 2173 if (os_snprintf_error(end - pos, ret)) 2174 return pos - buf; 2175 pos += ret; 2176 2177 if (wpa_s->l2 && 2178 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 2179 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 2180 if (os_snprintf_error(end - pos, ret)) 2181 return pos - buf; 2182 pos += ret; 2183 } 2184 2185 #ifdef CONFIG_P2P 2186 if (wpa_s->global->p2p) { 2187 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 2188 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 2189 if (os_snprintf_error(end - pos, ret)) 2190 return pos - buf; 2191 pos += ret; 2192 } 2193 #endif /* CONFIG_P2P */ 2194 2195 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 2196 MAC2STR(wpa_s->own_addr)); 2197 if (os_snprintf_error(end - pos, ret)) 2198 return pos - buf; 2199 pos += ret; 2200 2201 #ifdef CONFIG_HS20 2202 if (wpa_s->current_bss && 2203 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss, 2204 HS20_IE_VENDOR_TYPE)) && 2205 wpa_s->wpa_proto == WPA_PROTO_RSN && 2206 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 2207 int release = 1; 2208 if (hs20[1] >= 5) { 2209 u8 rel_num = (hs20[6] & 0xf0) >> 4; 2210 release = rel_num + 1; 2211 } 2212 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release); 2213 if (os_snprintf_error(end - pos, ret)) 2214 return pos - buf; 2215 pos += ret; 2216 } 2217 2218 if (wpa_s->current_ssid) { 2219 struct wpa_cred *cred; 2220 char *type; 2221 2222 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2223 size_t i; 2224 2225 if (wpa_s->current_ssid->parent_cred != cred) 2226 continue; 2227 2228 if (cred->provisioning_sp) { 2229 ret = os_snprintf(pos, end - pos, 2230 "provisioning_sp=%s\n", 2231 cred->provisioning_sp); 2232 if (os_snprintf_error(end - pos, ret)) 2233 return pos - buf; 2234 pos += ret; 2235 } 2236 2237 if (!cred->domain) 2238 goto no_domain; 2239 2240 i = 0; 2241 if (wpa_s->current_bss && wpa_s->current_bss->anqp) { 2242 struct wpabuf *names = 2243 wpa_s->current_bss->anqp->domain_name; 2244 for (i = 0; names && i < cred->num_domain; i++) 2245 { 2246 if (domain_name_list_contains( 2247 names, cred->domain[i], 1)) 2248 break; 2249 } 2250 if (i == cred->num_domain) 2251 i = 0; /* show first entry by default */ 2252 } 2253 ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 2254 cred->domain[i]); 2255 if (os_snprintf_error(end - pos, ret)) 2256 return pos - buf; 2257 pos += ret; 2258 2259 no_domain: 2260 if (wpa_s->current_bss == NULL || 2261 wpa_s->current_bss->anqp == NULL) 2262 res = -1; 2263 else 2264 res = interworking_home_sp_cred( 2265 wpa_s, cred, 2266 wpa_s->current_bss->anqp->domain_name); 2267 if (res > 0) 2268 type = "home"; 2269 else if (res == 0) 2270 type = "roaming"; 2271 else 2272 type = "unknown"; 2273 2274 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 2275 if (os_snprintf_error(end - pos, ret)) 2276 return pos - buf; 2277 pos += ret; 2278 2279 break; 2280 } 2281 } 2282 #endif /* CONFIG_HS20 */ 2283 2284 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 2285 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 2286 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 2287 verbose); 2288 if (res >= 0) 2289 pos += res; 2290 } 2291 2292 #ifdef CONFIG_MACSEC 2293 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos); 2294 if (res > 0) 2295 pos += res; 2296 #endif /* CONFIG_MACSEC */ 2297 2298 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len); 2299 if (sess_id) { 2300 char *start = pos; 2301 2302 ret = os_snprintf(pos, end - pos, "eap_session_id="); 2303 if (os_snprintf_error(end - pos, ret)) 2304 return start - buf; 2305 pos += ret; 2306 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len); 2307 if (ret <= 0) 2308 return start - buf; 2309 pos += ret; 2310 ret = os_snprintf(pos, end - pos, "\n"); 2311 if (os_snprintf_error(end - pos, ret)) 2312 return start - buf; 2313 pos += ret; 2314 } 2315 2316 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 2317 if (res >= 0) 2318 pos += res; 2319 2320 #ifdef CONFIG_WPS 2321 { 2322 char uuid_str[100]; 2323 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str)); 2324 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str); 2325 if (os_snprintf_error(end - pos, ret)) 2326 return pos - buf; 2327 pos += ret; 2328 } 2329 #endif /* CONFIG_WPS */ 2330 2331 if (wpa_s->ieee80211ac) { 2332 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n"); 2333 if (os_snprintf_error(end - pos, ret)) 2334 return pos - buf; 2335 pos += ret; 2336 } 2337 2338 #ifdef ANDROID 2339 /* 2340 * Allow using the STATUS command with default behavior, say for debug, 2341 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE 2342 * events with STATUS-NO_EVENTS. 2343 */ 2344 if (os_strcmp(params, "-NO_EVENTS")) { 2345 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE 2346 "id=%d state=%d BSSID=" MACSTR " SSID=%s", 2347 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, 2348 wpa_s->wpa_state, 2349 MAC2STR(wpa_s->bssid), 2350 wpa_s->current_ssid && wpa_s->current_ssid->ssid ? 2351 wpa_ssid_txt(wpa_s->current_ssid->ssid, 2352 wpa_s->current_ssid->ssid_len) : ""); 2353 if (wpa_s->wpa_state == WPA_COMPLETED) { 2354 struct wpa_ssid *ssid = wpa_s->current_ssid; 2355 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED 2356 "- connection to " MACSTR 2357 " completed %s [id=%d id_str=%s]", 2358 MAC2STR(wpa_s->bssid), "(auth)", 2359 ssid ? ssid->id : -1, 2360 ssid && ssid->id_str ? ssid->id_str : ""); 2361 } 2362 } 2363 #endif /* ANDROID */ 2364 2365 return pos - buf; 2366 } 2367 2368 2369 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 2370 char *cmd) 2371 { 2372 char *pos; 2373 int id; 2374 struct wpa_ssid *ssid; 2375 u8 bssid[ETH_ALEN]; 2376 2377 /* cmd: "<network id> <BSSID>" */ 2378 pos = os_strchr(cmd, ' '); 2379 if (pos == NULL) 2380 return -1; 2381 *pos++ = '\0'; 2382 id = atoi(cmd); 2383 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 2384 if (hwaddr_aton(pos, bssid)) { 2385 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 2386 return -1; 2387 } 2388 2389 ssid = wpa_config_get_network(wpa_s->conf, id); 2390 if (ssid == NULL) { 2391 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2392 "to update", id); 2393 return -1; 2394 } 2395 2396 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 2397 ssid->bssid_set = !is_zero_ether_addr(bssid); 2398 2399 return 0; 2400 } 2401 2402 2403 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 2404 char *cmd, char *buf, 2405 size_t buflen) 2406 { 2407 u8 bssid[ETH_ALEN]; 2408 struct wpa_blacklist *e; 2409 char *pos, *end; 2410 int ret; 2411 2412 /* cmd: "BLACKLIST [<BSSID>]" */ 2413 if (*cmd == '\0') { 2414 pos = buf; 2415 end = buf + buflen; 2416 e = wpa_s->blacklist; 2417 while (e) { 2418 ret = os_snprintf(pos, end - pos, MACSTR "\n", 2419 MAC2STR(e->bssid)); 2420 if (os_snprintf_error(end - pos, ret)) 2421 return pos - buf; 2422 pos += ret; 2423 e = e->next; 2424 } 2425 return pos - buf; 2426 } 2427 2428 cmd++; 2429 if (os_strncmp(cmd, "clear", 5) == 0) { 2430 wpa_blacklist_clear(wpa_s); 2431 os_memcpy(buf, "OK\n", 3); 2432 return 3; 2433 } 2434 2435 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 2436 if (hwaddr_aton(cmd, bssid)) { 2437 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 2438 return -1; 2439 } 2440 2441 /* 2442 * Add the BSSID twice, so its count will be 2, causing it to be 2443 * skipped when processing scan results. 2444 */ 2445 ret = wpa_blacklist_add(wpa_s, bssid); 2446 if (ret < 0) 2447 return -1; 2448 ret = wpa_blacklist_add(wpa_s, bssid); 2449 if (ret < 0) 2450 return -1; 2451 os_memcpy(buf, "OK\n", 3); 2452 return 3; 2453 } 2454 2455 2456 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 2457 char *cmd, char *buf, 2458 size_t buflen) 2459 { 2460 char *pos, *end, *stamp; 2461 int ret; 2462 2463 /* cmd: "LOG_LEVEL [<level>]" */ 2464 if (*cmd == '\0') { 2465 pos = buf; 2466 end = buf + buflen; 2467 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 2468 "Timestamp: %d\n", 2469 debug_level_str(wpa_debug_level), 2470 wpa_debug_timestamp); 2471 if (os_snprintf_error(end - pos, ret)) 2472 ret = 0; 2473 2474 return ret; 2475 } 2476 2477 while (*cmd == ' ') 2478 cmd++; 2479 2480 stamp = os_strchr(cmd, ' '); 2481 if (stamp) { 2482 *stamp++ = '\0'; 2483 while (*stamp == ' ') { 2484 stamp++; 2485 } 2486 } 2487 2488 if (os_strlen(cmd)) { 2489 int level = str_to_debug_level(cmd); 2490 if (level < 0) 2491 return -1; 2492 wpa_debug_level = level; 2493 } 2494 2495 if (stamp && os_strlen(stamp)) 2496 wpa_debug_timestamp = atoi(stamp); 2497 2498 os_memcpy(buf, "OK\n", 3); 2499 return 3; 2500 } 2501 2502 2503 static int wpa_supplicant_ctrl_iface_list_networks( 2504 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2505 { 2506 char *pos, *end, *prev; 2507 struct wpa_ssid *ssid; 2508 int ret; 2509 2510 pos = buf; 2511 end = buf + buflen; 2512 ret = os_snprintf(pos, end - pos, 2513 "network id / ssid / bssid / flags\n"); 2514 if (os_snprintf_error(end - pos, ret)) 2515 return pos - buf; 2516 pos += ret; 2517 2518 ssid = wpa_s->conf->ssid; 2519 2520 /* skip over ssids until we find next one */ 2521 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) { 2522 int last_id = atoi(cmd + 8); 2523 if (last_id != -1) { 2524 while (ssid != NULL && ssid->id <= last_id) { 2525 ssid = ssid->next; 2526 } 2527 } 2528 } 2529 2530 while (ssid) { 2531 prev = pos; 2532 ret = os_snprintf(pos, end - pos, "%d\t%s", 2533 ssid->id, 2534 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2535 if (os_snprintf_error(end - pos, ret)) 2536 return prev - buf; 2537 pos += ret; 2538 if (ssid->bssid_set) { 2539 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 2540 MAC2STR(ssid->bssid)); 2541 } else { 2542 ret = os_snprintf(pos, end - pos, "\tany"); 2543 } 2544 if (os_snprintf_error(end - pos, ret)) 2545 return prev - buf; 2546 pos += ret; 2547 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 2548 ssid == wpa_s->current_ssid ? 2549 "[CURRENT]" : "", 2550 ssid->disabled ? "[DISABLED]" : "", 2551 ssid->disabled_until.sec ? 2552 "[TEMP-DISABLED]" : "", 2553 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 2554 ""); 2555 if (os_snprintf_error(end - pos, ret)) 2556 return prev - buf; 2557 pos += ret; 2558 ret = os_snprintf(pos, end - pos, "\n"); 2559 if (os_snprintf_error(end - pos, ret)) 2560 return prev - buf; 2561 pos += ret; 2562 2563 ssid = ssid->next; 2564 } 2565 2566 return pos - buf; 2567 } 2568 2569 2570 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 2571 { 2572 int ret; 2573 ret = os_snprintf(pos, end - pos, "-"); 2574 if (os_snprintf_error(end - pos, ret)) 2575 return pos; 2576 pos += ret; 2577 ret = wpa_write_ciphers(pos, end, cipher, "+"); 2578 if (ret < 0) 2579 return pos; 2580 pos += ret; 2581 return pos; 2582 } 2583 2584 2585 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 2586 const u8 *ie, size_t ie_len) 2587 { 2588 struct wpa_ie_data data; 2589 char *start; 2590 int ret; 2591 2592 ret = os_snprintf(pos, end - pos, "[%s-", proto); 2593 if (os_snprintf_error(end - pos, ret)) 2594 return pos; 2595 pos += ret; 2596 2597 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 2598 ret = os_snprintf(pos, end - pos, "?]"); 2599 if (os_snprintf_error(end - pos, ret)) 2600 return pos; 2601 pos += ret; 2602 return pos; 2603 } 2604 2605 start = pos; 2606 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 2607 ret = os_snprintf(pos, end - pos, "%sEAP", 2608 pos == start ? "" : "+"); 2609 if (os_snprintf_error(end - pos, ret)) 2610 return pos; 2611 pos += ret; 2612 } 2613 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 2614 ret = os_snprintf(pos, end - pos, "%sPSK", 2615 pos == start ? "" : "+"); 2616 if (os_snprintf_error(end - pos, ret)) 2617 return pos; 2618 pos += ret; 2619 } 2620 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 2621 ret = os_snprintf(pos, end - pos, "%sNone", 2622 pos == start ? "" : "+"); 2623 if (os_snprintf_error(end - pos, ret)) 2624 return pos; 2625 pos += ret; 2626 } 2627 if (data.key_mgmt & WPA_KEY_MGMT_SAE) { 2628 ret = os_snprintf(pos, end - pos, "%sSAE", 2629 pos == start ? "" : "+"); 2630 if (os_snprintf_error(end - pos, ret)) 2631 return pos; 2632 pos += ret; 2633 } 2634 #ifdef CONFIG_IEEE80211R 2635 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 2636 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 2637 pos == start ? "" : "+"); 2638 if (os_snprintf_error(end - pos, ret)) 2639 return pos; 2640 pos += ret; 2641 } 2642 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 2643 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 2644 pos == start ? "" : "+"); 2645 if (os_snprintf_error(end - pos, ret)) 2646 return pos; 2647 pos += ret; 2648 } 2649 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) { 2650 ret = os_snprintf(pos, end - pos, "%sFT/SAE", 2651 pos == start ? "" : "+"); 2652 if (os_snprintf_error(end - pos, ret)) 2653 return pos; 2654 pos += ret; 2655 } 2656 #endif /* CONFIG_IEEE80211R */ 2657 #ifdef CONFIG_IEEE80211W 2658 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 2659 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 2660 pos == start ? "" : "+"); 2661 if (os_snprintf_error(end - pos, ret)) 2662 return pos; 2663 pos += ret; 2664 } 2665 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 2666 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 2667 pos == start ? "" : "+"); 2668 if (os_snprintf_error(end - pos, ret)) 2669 return pos; 2670 pos += ret; 2671 } 2672 #endif /* CONFIG_IEEE80211W */ 2673 2674 #ifdef CONFIG_SUITEB 2675 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 2676 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B", 2677 pos == start ? "" : "+"); 2678 if (os_snprintf_error(end - pos, ret)) 2679 return pos; 2680 pos += ret; 2681 } 2682 #endif /* CONFIG_SUITEB */ 2683 2684 #ifdef CONFIG_SUITEB192 2685 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 2686 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192", 2687 pos == start ? "" : "+"); 2688 if (os_snprintf_error(end - pos, ret)) 2689 return pos; 2690 pos += ret; 2691 } 2692 #endif /* CONFIG_SUITEB192 */ 2693 2694 #ifdef CONFIG_FILS 2695 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 2696 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256", 2697 pos == start ? "" : "+"); 2698 if (os_snprintf_error(end - pos, ret)) 2699 return pos; 2700 pos += ret; 2701 } 2702 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 2703 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384", 2704 pos == start ? "" : "+"); 2705 if (os_snprintf_error(end - pos, ret)) 2706 return pos; 2707 pos += ret; 2708 } 2709 #ifdef CONFIG_IEEE80211R 2710 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 2711 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256", 2712 pos == start ? "" : "+"); 2713 if (os_snprintf_error(end - pos, ret)) 2714 return pos; 2715 pos += ret; 2716 } 2717 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 2718 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384", 2719 pos == start ? "" : "+"); 2720 if (os_snprintf_error(end - pos, ret)) 2721 return pos; 2722 pos += ret; 2723 } 2724 #endif /* CONFIG_IEEE80211R */ 2725 #endif /* CONFIG_FILS */ 2726 2727 #ifdef CONFIG_OWE 2728 if (data.key_mgmt & WPA_KEY_MGMT_OWE) { 2729 ret = os_snprintf(pos, end - pos, "%sOWE", 2730 pos == start ? "" : "+"); 2731 if (os_snprintf_error(end - pos, ret)) 2732 return pos; 2733 pos += ret; 2734 } 2735 #endif /* CONFIG_OWE */ 2736 2737 #ifdef CONFIG_DPP 2738 if (data.key_mgmt & WPA_KEY_MGMT_DPP) { 2739 ret = os_snprintf(pos, end - pos, "%sDPP", 2740 pos == start ? "" : "+"); 2741 if (os_snprintf_error(end - pos, ret)) 2742 return pos; 2743 pos += ret; 2744 } 2745 #endif /* CONFIG_DPP */ 2746 2747 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) { 2748 ret = os_snprintf(pos, end - pos, "%sOSEN", 2749 pos == start ? "" : "+"); 2750 if (os_snprintf_error(end - pos, ret)) 2751 return pos; 2752 pos += ret; 2753 } 2754 2755 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 2756 2757 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 2758 ret = os_snprintf(pos, end - pos, "-preauth"); 2759 if (os_snprintf_error(end - pos, ret)) 2760 return pos; 2761 pos += ret; 2762 } 2763 2764 ret = os_snprintf(pos, end - pos, "]"); 2765 if (os_snprintf_error(end - pos, ret)) 2766 return pos; 2767 pos += ret; 2768 2769 return pos; 2770 } 2771 2772 2773 #ifdef CONFIG_WPS 2774 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 2775 char *pos, char *end, 2776 struct wpabuf *wps_ie) 2777 { 2778 int ret; 2779 const char *txt; 2780 2781 if (wps_ie == NULL) 2782 return pos; 2783 if (wps_is_selected_pbc_registrar(wps_ie)) 2784 txt = "[WPS-PBC]"; 2785 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 2786 txt = "[WPS-AUTH]"; 2787 else if (wps_is_selected_pin_registrar(wps_ie)) 2788 txt = "[WPS-PIN]"; 2789 else 2790 txt = "[WPS]"; 2791 2792 ret = os_snprintf(pos, end - pos, "%s", txt); 2793 if (!os_snprintf_error(end - pos, ret)) 2794 pos += ret; 2795 wpabuf_free(wps_ie); 2796 return pos; 2797 } 2798 #endif /* CONFIG_WPS */ 2799 2800 2801 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 2802 char *pos, char *end, 2803 const struct wpa_bss *bss) 2804 { 2805 #ifdef CONFIG_WPS 2806 struct wpabuf *wps_ie; 2807 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 2808 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 2809 #else /* CONFIG_WPS */ 2810 return pos; 2811 #endif /* CONFIG_WPS */ 2812 } 2813 2814 2815 /* Format one result on one text line into a buffer. */ 2816 static int wpa_supplicant_ctrl_iface_scan_result( 2817 struct wpa_supplicant *wpa_s, 2818 const struct wpa_bss *bss, char *buf, size_t buflen) 2819 { 2820 char *pos, *end; 2821 int ret; 2822 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe; 2823 2824 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 2825 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 2826 if (!p2p) 2827 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); 2828 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 2829 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 2830 0) 2831 return 0; /* Do not show P2P listen discovery results here */ 2832 2833 pos = buf; 2834 end = buf + buflen; 2835 2836 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 2837 MAC2STR(bss->bssid), bss->freq, bss->level); 2838 if (os_snprintf_error(end - pos, ret)) 2839 return -1; 2840 pos += ret; 2841 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 2842 if (ie) 2843 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 2844 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 2845 if (ie2) { 2846 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", 2847 ie2, 2 + ie2[1]); 2848 } 2849 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 2850 if (osen_ie) 2851 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 2852 osen_ie, 2 + osen_ie[1]); 2853 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 2854 if (owe) { 2855 ret = os_snprintf(pos, end - pos, 2856 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 2857 if (os_snprintf_error(end - pos, ret)) 2858 return -1; 2859 pos += ret; 2860 } 2861 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 2862 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { 2863 ret = os_snprintf(pos, end - pos, "[WEP]"); 2864 if (os_snprintf_error(end - pos, ret)) 2865 return -1; 2866 pos += ret; 2867 } 2868 if (mesh) { 2869 ret = os_snprintf(pos, end - pos, "[MESH]"); 2870 if (os_snprintf_error(end - pos, ret)) 2871 return -1; 2872 pos += ret; 2873 } 2874 if (bss_is_dmg(bss)) { 2875 const char *s; 2876 ret = os_snprintf(pos, end - pos, "[DMG]"); 2877 if (os_snprintf_error(end - pos, ret)) 2878 return -1; 2879 pos += ret; 2880 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 2881 case IEEE80211_CAP_DMG_IBSS: 2882 s = "[IBSS]"; 2883 break; 2884 case IEEE80211_CAP_DMG_AP: 2885 s = "[ESS]"; 2886 break; 2887 case IEEE80211_CAP_DMG_PBSS: 2888 s = "[PBSS]"; 2889 break; 2890 default: 2891 s = ""; 2892 break; 2893 } 2894 ret = os_snprintf(pos, end - pos, "%s", s); 2895 if (os_snprintf_error(end - pos, ret)) 2896 return -1; 2897 pos += ret; 2898 } else { 2899 if (bss->caps & IEEE80211_CAP_IBSS) { 2900 ret = os_snprintf(pos, end - pos, "[IBSS]"); 2901 if (os_snprintf_error(end - pos, ret)) 2902 return -1; 2903 pos += ret; 2904 } 2905 if (bss->caps & IEEE80211_CAP_ESS) { 2906 ret = os_snprintf(pos, end - pos, "[ESS]"); 2907 if (os_snprintf_error(end - pos, ret)) 2908 return -1; 2909 pos += ret; 2910 } 2911 } 2912 if (p2p) { 2913 ret = os_snprintf(pos, end - pos, "[P2P]"); 2914 if (os_snprintf_error(end - pos, ret)) 2915 return -1; 2916 pos += ret; 2917 } 2918 #ifdef CONFIG_HS20 2919 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 2920 ret = os_snprintf(pos, end - pos, "[HS20]"); 2921 if (os_snprintf_error(end - pos, ret)) 2922 return -1; 2923 pos += ret; 2924 } 2925 #endif /* CONFIG_HS20 */ 2926 #ifdef CONFIG_FILS 2927 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 2928 ret = os_snprintf(pos, end - pos, "[FILS]"); 2929 if (os_snprintf_error(end - pos, ret)) 2930 return -1; 2931 pos += ret; 2932 } 2933 #endif /* CONFIG_FILS */ 2934 #ifdef CONFIG_FST 2935 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 2936 ret = os_snprintf(pos, end - pos, "[FST]"); 2937 if (os_snprintf_error(end - pos, ret)) 2938 return -1; 2939 pos += ret; 2940 } 2941 #endif /* CONFIG_FST */ 2942 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 2943 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 2944 if (os_snprintf_error(end - pos, ret)) 2945 return -1; 2946 pos += ret; 2947 } 2948 2949 ret = os_snprintf(pos, end - pos, "\t%s", 2950 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 2951 if (os_snprintf_error(end - pos, ret)) 2952 return -1; 2953 pos += ret; 2954 2955 ret = os_snprintf(pos, end - pos, "\n"); 2956 if (os_snprintf_error(end - pos, ret)) 2957 return -1; 2958 pos += ret; 2959 2960 return pos - buf; 2961 } 2962 2963 2964 static int wpa_supplicant_ctrl_iface_scan_results( 2965 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 2966 { 2967 char *pos, *end; 2968 struct wpa_bss *bss; 2969 int ret; 2970 2971 pos = buf; 2972 end = buf + buflen; 2973 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 2974 "flags / ssid\n"); 2975 if (os_snprintf_error(end - pos, ret)) 2976 return pos - buf; 2977 pos += ret; 2978 2979 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 2980 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 2981 end - pos); 2982 if (ret < 0 || ret >= end - pos) 2983 return pos - buf; 2984 pos += ret; 2985 } 2986 2987 return pos - buf; 2988 } 2989 2990 2991 #ifdef CONFIG_MESH 2992 2993 static int wpa_supplicant_ctrl_iface_mesh_interface_add( 2994 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 2995 { 2996 char *pos, ifname[IFNAMSIZ + 1]; 2997 2998 ifname[0] = '\0'; 2999 3000 pos = os_strstr(cmd, "ifname="); 3001 if (pos) { 3002 pos += 7; 3003 os_strlcpy(ifname, pos, sizeof(ifname)); 3004 } 3005 3006 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0) 3007 return -1; 3008 3009 os_strlcpy(reply, ifname, max_len); 3010 return os_strlen(ifname); 3011 } 3012 3013 3014 static int wpa_supplicant_ctrl_iface_mesh_group_add( 3015 struct wpa_supplicant *wpa_s, char *cmd) 3016 { 3017 int id; 3018 struct wpa_ssid *ssid; 3019 3020 id = atoi(cmd); 3021 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id); 3022 3023 ssid = wpa_config_get_network(wpa_s->conf, id); 3024 if (ssid == NULL) { 3025 wpa_printf(MSG_DEBUG, 3026 "CTRL_IFACE: Could not find network id=%d", id); 3027 return -1; 3028 } 3029 if (ssid->mode != WPAS_MODE_MESH) { 3030 wpa_printf(MSG_DEBUG, 3031 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network"); 3032 return -1; 3033 } 3034 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE && 3035 ssid->key_mgmt != WPA_KEY_MGMT_SAE) { 3036 wpa_printf(MSG_ERROR, 3037 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE"); 3038 return -1; 3039 } 3040 3041 /* 3042 * TODO: If necessary write our own group_add function, 3043 * for now we can reuse select_network 3044 */ 3045 wpa_supplicant_select_network(wpa_s, ssid); 3046 3047 return 0; 3048 } 3049 3050 3051 static int wpa_supplicant_ctrl_iface_mesh_group_remove( 3052 struct wpa_supplicant *wpa_s, char *cmd) 3053 { 3054 struct wpa_supplicant *orig; 3055 struct wpa_global *global; 3056 int found = 0; 3057 3058 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd); 3059 3060 global = wpa_s->global; 3061 orig = wpa_s; 3062 3063 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 3064 if (os_strcmp(wpa_s->ifname, cmd) == 0) { 3065 found = 1; 3066 break; 3067 } 3068 } 3069 if (!found) { 3070 wpa_printf(MSG_ERROR, 3071 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found", 3072 cmd); 3073 return -1; 3074 } 3075 if (wpa_s->mesh_if_created && wpa_s == orig) { 3076 wpa_printf(MSG_ERROR, 3077 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself"); 3078 return -1; 3079 } 3080 3081 wpa_s->reassociate = 0; 3082 wpa_s->disconnected = 1; 3083 wpa_supplicant_cancel_sched_scan(wpa_s); 3084 wpa_supplicant_cancel_scan(wpa_s); 3085 3086 /* 3087 * TODO: If necessary write our own group_remove function, 3088 * for now we can reuse deauthenticate 3089 */ 3090 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3091 3092 if (wpa_s->mesh_if_created) 3093 wpa_supplicant_remove_iface(global, wpa_s, 0); 3094 3095 return 0; 3096 } 3097 3098 3099 static int wpa_supplicant_ctrl_iface_mesh_peer_remove( 3100 struct wpa_supplicant *wpa_s, char *cmd) 3101 { 3102 u8 addr[ETH_ALEN]; 3103 3104 if (hwaddr_aton(cmd, addr) < 0) 3105 return -1; 3106 3107 return wpas_mesh_peer_remove(wpa_s, addr); 3108 } 3109 3110 3111 static int wpa_supplicant_ctrl_iface_mesh_peer_add( 3112 struct wpa_supplicant *wpa_s, char *cmd) 3113 { 3114 u8 addr[ETH_ALEN]; 3115 int duration; 3116 char *pos; 3117 3118 pos = os_strstr(cmd, " duration="); 3119 if (pos) { 3120 *pos = '\0'; 3121 duration = atoi(pos + 10); 3122 } else { 3123 duration = -1; 3124 } 3125 3126 if (hwaddr_aton(cmd, addr)) 3127 return -1; 3128 3129 return wpas_mesh_peer_add(wpa_s, addr, duration); 3130 } 3131 3132 #endif /* CONFIG_MESH */ 3133 3134 3135 static int wpa_supplicant_ctrl_iface_select_network( 3136 struct wpa_supplicant *wpa_s, char *cmd) 3137 { 3138 int id; 3139 struct wpa_ssid *ssid; 3140 char *pos; 3141 3142 /* cmd: "<network id>" or "any" */ 3143 if (os_strncmp(cmd, "any", 3) == 0) { 3144 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 3145 ssid = NULL; 3146 } else { 3147 id = atoi(cmd); 3148 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 3149 3150 ssid = wpa_config_get_network(wpa_s->conf, id); 3151 if (ssid == NULL) { 3152 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3153 "network id=%d", id); 3154 return -1; 3155 } 3156 if (ssid->disabled == 2) { 3157 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3158 "SELECT_NETWORK with persistent P2P group"); 3159 return -1; 3160 } 3161 } 3162 3163 pos = os_strstr(cmd, " freq="); 3164 if (pos) { 3165 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); 3166 if (freqs) { 3167 os_free(wpa_s->select_network_scan_freqs); 3168 wpa_s->select_network_scan_freqs = freqs; 3169 } 3170 } 3171 3172 wpa_s->scan_min_time.sec = 0; 3173 wpa_s->scan_min_time.usec = 0; 3174 wpa_supplicant_select_network(wpa_s, ssid); 3175 3176 return 0; 3177 } 3178 3179 3180 static int wpa_supplicant_ctrl_iface_enable_network( 3181 struct wpa_supplicant *wpa_s, char *cmd) 3182 { 3183 int id; 3184 struct wpa_ssid *ssid; 3185 3186 /* cmd: "<network id>" or "all" */ 3187 if (os_strcmp(cmd, "all") == 0) { 3188 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 3189 ssid = NULL; 3190 } else { 3191 id = atoi(cmd); 3192 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 3193 3194 ssid = wpa_config_get_network(wpa_s->conf, id); 3195 if (ssid == NULL) { 3196 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3197 "network id=%d", id); 3198 return -1; 3199 } 3200 if (ssid->disabled == 2) { 3201 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3202 "ENABLE_NETWORK with persistent P2P group"); 3203 return -1; 3204 } 3205 3206 if (os_strstr(cmd, " no-connect")) { 3207 ssid->disabled = 0; 3208 return 0; 3209 } 3210 } 3211 wpa_s->scan_min_time.sec = 0; 3212 wpa_s->scan_min_time.usec = 0; 3213 wpa_supplicant_enable_network(wpa_s, ssid); 3214 3215 return 0; 3216 } 3217 3218 3219 static int wpa_supplicant_ctrl_iface_disable_network( 3220 struct wpa_supplicant *wpa_s, char *cmd) 3221 { 3222 int id; 3223 struct wpa_ssid *ssid; 3224 3225 /* cmd: "<network id>" or "all" */ 3226 if (os_strcmp(cmd, "all") == 0) { 3227 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 3228 ssid = NULL; 3229 } else { 3230 id = atoi(cmd); 3231 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 3232 3233 ssid = wpa_config_get_network(wpa_s->conf, id); 3234 if (ssid == NULL) { 3235 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3236 "network id=%d", id); 3237 return -1; 3238 } 3239 if (ssid->disabled == 2) { 3240 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3241 "DISABLE_NETWORK with persistent P2P " 3242 "group"); 3243 return -1; 3244 } 3245 } 3246 wpa_supplicant_disable_network(wpa_s, ssid); 3247 3248 return 0; 3249 } 3250 3251 3252 static int wpa_supplicant_ctrl_iface_add_network( 3253 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3254 { 3255 struct wpa_ssid *ssid; 3256 int ret; 3257 3258 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 3259 3260 ssid = wpa_supplicant_add_network(wpa_s); 3261 if (ssid == NULL) 3262 return -1; 3263 3264 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 3265 if (os_snprintf_error(buflen, ret)) 3266 return -1; 3267 return ret; 3268 } 3269 3270 3271 static int wpa_supplicant_ctrl_iface_remove_network( 3272 struct wpa_supplicant *wpa_s, char *cmd) 3273 { 3274 int id; 3275 struct wpa_ssid *ssid; 3276 int result; 3277 3278 /* cmd: "<network id>" or "all" */ 3279 if (os_strcmp(cmd, "all") == 0) { 3280 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 3281 if (wpa_s->sched_scanning) 3282 wpa_supplicant_cancel_sched_scan(wpa_s); 3283 3284 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3285 if (wpa_s->current_ssid) { 3286 #ifdef CONFIG_SME 3287 wpa_s->sme.prev_bssid_set = 0; 3288 #endif /* CONFIG_SME */ 3289 wpa_sm_set_config(wpa_s->wpa, NULL); 3290 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 3291 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) 3292 wpa_s->own_disconnect_req = 1; 3293 wpa_supplicant_deauthenticate( 3294 wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3295 } 3296 ssid = wpa_s->conf->ssid; 3297 while (ssid) { 3298 struct wpa_ssid *remove_ssid = ssid; 3299 id = ssid->id; 3300 ssid = ssid->next; 3301 if (wpa_s->last_ssid == remove_ssid) 3302 wpa_s->last_ssid = NULL; 3303 wpas_notify_network_removed(wpa_s, remove_ssid); 3304 wpa_config_remove_network(wpa_s->conf, id); 3305 } 3306 return 0; 3307 } 3308 3309 id = atoi(cmd); 3310 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 3311 3312 result = wpa_supplicant_remove_network(wpa_s, id); 3313 if (result == -1) { 3314 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3315 "id=%d", id); 3316 return -1; 3317 } 3318 if (result == -2) { 3319 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 3320 "network id=%d", id); 3321 return -1; 3322 } 3323 return 0; 3324 } 3325 3326 3327 static int wpa_supplicant_ctrl_iface_update_network( 3328 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 3329 char *name, char *value) 3330 { 3331 int ret; 3332 3333 ret = wpa_config_set(ssid, name, value, 0); 3334 if (ret < 0) { 3335 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 3336 "variable '%s'", name); 3337 return -1; 3338 } 3339 if (ret == 1) 3340 return 0; /* No change to the previously configured value */ 3341 3342 if (os_strcmp(name, "bssid") != 0 && 3343 os_strcmp(name, "bssid_hint") != 0 && 3344 os_strcmp(name, "priority") != 0) { 3345 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 3346 3347 if (wpa_s->current_ssid == ssid || 3348 wpa_s->current_ssid == NULL) { 3349 /* 3350 * Invalidate the EAP session cache if anything in the 3351 * current or previously used configuration changes. 3352 */ 3353 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3354 } 3355 } 3356 3357 if ((os_strcmp(name, "psk") == 0 && 3358 value[0] == '"' && ssid->ssid_len) || 3359 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 3360 wpa_config_update_psk(ssid); 3361 else if (os_strcmp(name, "priority") == 0) 3362 wpa_config_update_prio_list(wpa_s->conf); 3363 3364 return 0; 3365 } 3366 3367 3368 static int wpa_supplicant_ctrl_iface_set_network( 3369 struct wpa_supplicant *wpa_s, char *cmd) 3370 { 3371 int id, ret, prev_bssid_set, prev_disabled; 3372 struct wpa_ssid *ssid; 3373 char *name, *value; 3374 u8 prev_bssid[ETH_ALEN]; 3375 3376 /* cmd: "<network id> <variable name> <value>" */ 3377 name = os_strchr(cmd, ' '); 3378 if (name == NULL) 3379 return -1; 3380 *name++ = '\0'; 3381 3382 value = os_strchr(name, ' '); 3383 if (value == NULL) 3384 return -1; 3385 *value++ = '\0'; 3386 3387 id = atoi(cmd); 3388 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 3389 id, name); 3390 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3391 (u8 *) value, os_strlen(value)); 3392 3393 ssid = wpa_config_get_network(wpa_s->conf, id); 3394 if (ssid == NULL) { 3395 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3396 "id=%d", id); 3397 return -1; 3398 } 3399 3400 prev_bssid_set = ssid->bssid_set; 3401 prev_disabled = ssid->disabled; 3402 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN); 3403 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name, 3404 value); 3405 if (ret == 0 && 3406 (ssid->bssid_set != prev_bssid_set || 3407 os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0)) 3408 wpas_notify_network_bssid_set_changed(wpa_s, ssid); 3409 3410 if (prev_disabled != ssid->disabled && 3411 (prev_disabled == 2 || ssid->disabled == 2)) 3412 wpas_notify_network_type_changed(wpa_s, ssid); 3413 3414 return ret; 3415 } 3416 3417 3418 static int wpa_supplicant_ctrl_iface_get_network( 3419 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 3420 { 3421 int id; 3422 size_t res; 3423 struct wpa_ssid *ssid; 3424 char *name, *value; 3425 3426 /* cmd: "<network id> <variable name>" */ 3427 name = os_strchr(cmd, ' '); 3428 if (name == NULL || buflen == 0) 3429 return -1; 3430 *name++ = '\0'; 3431 3432 id = atoi(cmd); 3433 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 3434 id, name); 3435 3436 ssid = wpa_config_get_network(wpa_s->conf, id); 3437 if (ssid == NULL) { 3438 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network " 3439 "id=%d", id); 3440 return -1; 3441 } 3442 3443 value = wpa_config_get_no_key(ssid, name); 3444 if (value == NULL) { 3445 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network " 3446 "variable '%s'", name); 3447 return -1; 3448 } 3449 3450 res = os_strlcpy(buf, value, buflen); 3451 if (res >= buflen) { 3452 os_free(value); 3453 return -1; 3454 } 3455 3456 os_free(value); 3457 3458 return res; 3459 } 3460 3461 3462 static int wpa_supplicant_ctrl_iface_dup_network( 3463 struct wpa_supplicant *wpa_s, char *cmd, 3464 struct wpa_supplicant *dst_wpa_s) 3465 { 3466 struct wpa_ssid *ssid_s, *ssid_d; 3467 char *name, *id, *value; 3468 int id_s, id_d, ret; 3469 3470 /* cmd: "<src network id> <dst network id> <variable name>" */ 3471 id = os_strchr(cmd, ' '); 3472 if (id == NULL) 3473 return -1; 3474 *id++ = '\0'; 3475 3476 name = os_strchr(id, ' '); 3477 if (name == NULL) 3478 return -1; 3479 *name++ = '\0'; 3480 3481 id_s = atoi(cmd); 3482 id_d = atoi(id); 3483 3484 wpa_printf(MSG_DEBUG, 3485 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'", 3486 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name); 3487 3488 ssid_s = wpa_config_get_network(wpa_s->conf, id_s); 3489 if (ssid_s == NULL) { 3490 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3491 "network id=%d", id_s); 3492 return -1; 3493 } 3494 3495 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d); 3496 if (ssid_d == NULL) { 3497 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3498 "network id=%d", id_d); 3499 return -1; 3500 } 3501 3502 value = wpa_config_get(ssid_s, name); 3503 if (value == NULL) { 3504 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 3505 "variable '%s'", name); 3506 return -1; 3507 } 3508 3509 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name, 3510 value); 3511 3512 os_free(value); 3513 3514 return ret; 3515 } 3516 3517 3518 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 3519 char *buf, size_t buflen) 3520 { 3521 char *pos, *end; 3522 struct wpa_cred *cred; 3523 int ret; 3524 3525 pos = buf; 3526 end = buf + buflen; 3527 ret = os_snprintf(pos, end - pos, 3528 "cred id / realm / username / domain / imsi\n"); 3529 if (os_snprintf_error(end - pos, ret)) 3530 return pos - buf; 3531 pos += ret; 3532 3533 cred = wpa_s->conf->cred; 3534 while (cred) { 3535 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 3536 cred->id, cred->realm ? cred->realm : "", 3537 cred->username ? cred->username : "", 3538 cred->domain ? cred->domain[0] : "", 3539 cred->imsi ? cred->imsi : ""); 3540 if (os_snprintf_error(end - pos, ret)) 3541 return pos - buf; 3542 pos += ret; 3543 3544 cred = cred->next; 3545 } 3546 3547 return pos - buf; 3548 } 3549 3550 3551 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 3552 char *buf, size_t buflen) 3553 { 3554 struct wpa_cred *cred; 3555 int ret; 3556 3557 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 3558 3559 cred = wpa_config_add_cred(wpa_s->conf); 3560 if (cred == NULL) 3561 return -1; 3562 3563 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id); 3564 3565 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 3566 if (os_snprintf_error(buflen, ret)) 3567 return -1; 3568 return ret; 3569 } 3570 3571 3572 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, 3573 struct wpa_cred *cred) 3574 { 3575 struct wpa_ssid *ssid; 3576 char str[20]; 3577 int id; 3578 3579 if (cred == NULL) { 3580 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 3581 return -1; 3582 } 3583 3584 id = cred->id; 3585 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) { 3586 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 3587 return -1; 3588 } 3589 3590 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id); 3591 3592 /* Remove any network entry created based on the removed credential */ 3593 ssid = wpa_s->conf->ssid; 3594 while (ssid) { 3595 if (ssid->parent_cred == cred) { 3596 int res; 3597 3598 wpa_printf(MSG_DEBUG, "Remove network id %d since it " 3599 "used the removed credential", ssid->id); 3600 res = os_snprintf(str, sizeof(str), "%d", ssid->id); 3601 if (os_snprintf_error(sizeof(str), res)) 3602 str[sizeof(str) - 1] = '\0'; 3603 ssid = ssid->next; 3604 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); 3605 } else 3606 ssid = ssid->next; 3607 } 3608 3609 return 0; 3610 } 3611 3612 3613 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 3614 char *cmd) 3615 { 3616 int id; 3617 struct wpa_cred *cred, *prev; 3618 3619 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or 3620 * "provisioning_sp=<FQDN> */ 3621 if (os_strcmp(cmd, "all") == 0) { 3622 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 3623 cred = wpa_s->conf->cred; 3624 while (cred) { 3625 prev = cred; 3626 cred = cred->next; 3627 wpas_ctrl_remove_cred(wpa_s, prev); 3628 } 3629 return 0; 3630 } 3631 3632 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 3633 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 3634 cmd + 8); 3635 cred = wpa_s->conf->cred; 3636 while (cred) { 3637 prev = cred; 3638 cred = cred->next; 3639 if (prev->domain) { 3640 size_t i; 3641 for (i = 0; i < prev->num_domain; i++) { 3642 if (os_strcmp(prev->domain[i], cmd + 8) 3643 != 0) 3644 continue; 3645 wpas_ctrl_remove_cred(wpa_s, prev); 3646 break; 3647 } 3648 } 3649 } 3650 return 0; 3651 } 3652 3653 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) { 3654 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'", 3655 cmd + 16); 3656 cred = wpa_s->conf->cred; 3657 while (cred) { 3658 prev = cred; 3659 cred = cred->next; 3660 if (prev->provisioning_sp && 3661 os_strcmp(prev->provisioning_sp, cmd + 16) == 0) 3662 wpas_ctrl_remove_cred(wpa_s, prev); 3663 } 3664 return 0; 3665 } 3666 3667 id = atoi(cmd); 3668 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 3669 3670 cred = wpa_config_get_cred(wpa_s->conf, id); 3671 return wpas_ctrl_remove_cred(wpa_s, cred); 3672 } 3673 3674 3675 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 3676 char *cmd) 3677 { 3678 int id; 3679 struct wpa_cred *cred; 3680 char *name, *value; 3681 3682 /* cmd: "<cred id> <variable name> <value>" */ 3683 name = os_strchr(cmd, ' '); 3684 if (name == NULL) 3685 return -1; 3686 *name++ = '\0'; 3687 3688 value = os_strchr(name, ' '); 3689 if (value == NULL) 3690 return -1; 3691 *value++ = '\0'; 3692 3693 id = atoi(cmd); 3694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 3695 id, name); 3696 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3697 (u8 *) value, os_strlen(value)); 3698 3699 cred = wpa_config_get_cred(wpa_s->conf, id); 3700 if (cred == NULL) { 3701 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3702 id); 3703 return -1; 3704 } 3705 3706 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 3707 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 3708 "variable '%s'", name); 3709 return -1; 3710 } 3711 3712 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name); 3713 3714 return 0; 3715 } 3716 3717 3718 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s, 3719 char *cmd, char *buf, 3720 size_t buflen) 3721 { 3722 int id; 3723 size_t res; 3724 struct wpa_cred *cred; 3725 char *name, *value; 3726 3727 /* cmd: "<cred id> <variable name>" */ 3728 name = os_strchr(cmd, ' '); 3729 if (name == NULL) 3730 return -1; 3731 *name++ = '\0'; 3732 3733 id = atoi(cmd); 3734 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'", 3735 id, name); 3736 3737 cred = wpa_config_get_cred(wpa_s->conf, id); 3738 if (cred == NULL) { 3739 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3740 id); 3741 return -1; 3742 } 3743 3744 value = wpa_config_get_cred_no_key(cred, name); 3745 if (value == NULL) { 3746 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'", 3747 name); 3748 return -1; 3749 } 3750 3751 res = os_strlcpy(buf, value, buflen); 3752 if (res >= buflen) { 3753 os_free(value); 3754 return -1; 3755 } 3756 3757 os_free(value); 3758 3759 return res; 3760 } 3761 3762 3763 #ifndef CONFIG_NO_CONFIG_WRITE 3764 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 3765 { 3766 int ret; 3767 3768 if (!wpa_s->conf->update_config) { 3769 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 3770 "to update configuration (update_config=0)"); 3771 return -1; 3772 } 3773 3774 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 3775 if (ret) { 3776 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 3777 "update configuration"); 3778 } else { 3779 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 3780 " updated"); 3781 } 3782 3783 return ret; 3784 } 3785 #endif /* CONFIG_NO_CONFIG_WRITE */ 3786 3787 3788 struct cipher_info { 3789 unsigned int capa; 3790 const char *name; 3791 int group_only; 3792 }; 3793 3794 static const struct cipher_info ciphers[] = { 3795 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 }, 3796 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, 3797 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, 3798 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, 3799 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, 3800 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, 3801 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, 3802 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } 3803 }; 3804 3805 static const struct cipher_info ciphers_group_mgmt[] = { 3806 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 }, 3807 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 }, 3808 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 }, 3809 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 }, 3810 }; 3811 3812 3813 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 3814 struct wpa_driver_capa *capa, 3815 char *buf, size_t buflen) 3816 { 3817 int ret; 3818 char *pos, *end; 3819 size_t len; 3820 unsigned int i; 3821 3822 pos = buf; 3823 end = pos + buflen; 3824 3825 if (res < 0) { 3826 if (strict) 3827 return 0; 3828 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 3829 if (len >= buflen) 3830 return -1; 3831 return len; 3832 } 3833 3834 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3835 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) { 3836 ret = os_snprintf(pos, end - pos, "%s%s", 3837 pos == buf ? "" : " ", 3838 ciphers[i].name); 3839 if (os_snprintf_error(end - pos, ret)) 3840 return pos - buf; 3841 pos += ret; 3842 } 3843 } 3844 3845 return pos - buf; 3846 } 3847 3848 3849 static int ctrl_iface_get_capability_group(int res, char *strict, 3850 struct wpa_driver_capa *capa, 3851 char *buf, size_t buflen) 3852 { 3853 int ret; 3854 char *pos, *end; 3855 size_t len; 3856 unsigned int i; 3857 3858 pos = buf; 3859 end = pos + buflen; 3860 3861 if (res < 0) { 3862 if (strict) 3863 return 0; 3864 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 3865 if (len >= buflen) 3866 return -1; 3867 return len; 3868 } 3869 3870 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3871 if (capa->enc & ciphers[i].capa) { 3872 ret = os_snprintf(pos, end - pos, "%s%s", 3873 pos == buf ? "" : " ", 3874 ciphers[i].name); 3875 if (os_snprintf_error(end - pos, ret)) 3876 return pos - buf; 3877 pos += ret; 3878 } 3879 } 3880 3881 return pos - buf; 3882 } 3883 3884 3885 static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, 3886 struct wpa_driver_capa *capa, 3887 char *buf, size_t buflen) 3888 { 3889 int ret; 3890 char *pos, *end; 3891 unsigned int i; 3892 3893 pos = buf; 3894 end = pos + buflen; 3895 3896 if (res < 0) 3897 return 0; 3898 3899 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) { 3900 if (capa->enc & ciphers_group_mgmt[i].capa) { 3901 ret = os_snprintf(pos, end - pos, "%s%s", 3902 pos == buf ? "" : " ", 3903 ciphers_group_mgmt[i].name); 3904 if (os_snprintf_error(end - pos, ret)) 3905 return pos - buf; 3906 pos += ret; 3907 } 3908 } 3909 3910 return pos - buf; 3911 } 3912 3913 3914 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 3915 struct wpa_driver_capa *capa, 3916 char *buf, size_t buflen) 3917 { 3918 int ret; 3919 char *pos, *end; 3920 size_t len; 3921 3922 pos = buf; 3923 end = pos + buflen; 3924 3925 if (res < 0) { 3926 if (strict) 3927 return 0; 3928 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 3929 "NONE", buflen); 3930 if (len >= buflen) 3931 return -1; 3932 return len; 3933 } 3934 3935 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 3936 if (os_snprintf_error(end - pos, ret)) 3937 return pos - buf; 3938 pos += ret; 3939 3940 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3941 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 3942 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 3943 if (os_snprintf_error(end - pos, ret)) 3944 return pos - buf; 3945 pos += ret; 3946 } 3947 3948 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 3949 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 3950 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 3951 if (os_snprintf_error(end - pos, ret)) 3952 return pos - buf; 3953 pos += ret; 3954 } 3955 3956 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 3957 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 3958 if (os_snprintf_error(end - pos, ret)) 3959 return pos - buf; 3960 pos += ret; 3961 } 3962 3963 #ifdef CONFIG_SUITEB 3964 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { 3965 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); 3966 if (os_snprintf_error(end - pos, ret)) 3967 return pos - buf; 3968 pos += ret; 3969 } 3970 #endif /* CONFIG_SUITEB */ 3971 #ifdef CONFIG_SUITEB192 3972 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { 3973 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); 3974 if (os_snprintf_error(end - pos, ret)) 3975 return pos - buf; 3976 pos += ret; 3977 } 3978 #endif /* CONFIG_SUITEB192 */ 3979 #ifdef CONFIG_OWE 3980 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { 3981 ret = os_snprintf(pos, end - pos, " OWE"); 3982 if (os_snprintf_error(end - pos, ret)) 3983 return pos - buf; 3984 pos += ret; 3985 } 3986 #endif /* CONFIG_OWE */ 3987 #ifdef CONFIG_DPP 3988 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { 3989 ret = os_snprintf(pos, end - pos, " DPP"); 3990 if (os_snprintf_error(end - pos, ret)) 3991 return pos - buf; 3992 pos += ret; 3993 } 3994 #endif /* CONFIG_DPP */ 3995 #ifdef CONFIG_FILS 3996 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { 3997 ret = os_snprintf(pos, end - pos, " FILS-SHA256"); 3998 if (os_snprintf_error(end - pos, ret)) 3999 return pos - buf; 4000 pos += ret; 4001 } 4002 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { 4003 ret = os_snprintf(pos, end - pos, " FILS-SHA384"); 4004 if (os_snprintf_error(end - pos, ret)) 4005 return pos - buf; 4006 pos += ret; 4007 } 4008 #ifdef CONFIG_IEEE80211R 4009 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { 4010 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); 4011 if (os_snprintf_error(end - pos, ret)) 4012 return pos - buf; 4013 pos += ret; 4014 } 4015 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { 4016 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); 4017 if (os_snprintf_error(end - pos, ret)) 4018 return pos - buf; 4019 pos += ret; 4020 } 4021 #endif /* CONFIG_IEEE80211R */ 4022 #endif /* CONFIG_FILS */ 4023 #ifdef CONFIG_IEEE80211R 4024 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { 4025 ret = os_snprintf(pos, end - pos, " FT-PSK"); 4026 if (os_snprintf_error(end - pos, ret)) 4027 return pos - buf; 4028 pos += ret; 4029 } 4030 #endif /* CONFIG_IEEE80211R */ 4031 #ifdef CONFIG_SAE 4032 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { 4033 ret = os_snprintf(pos, end - pos, " SAE"); 4034 if (os_snprintf_error(end - pos, ret)) 4035 return pos - buf; 4036 pos += ret; 4037 } 4038 #endif /* CONFIG_SAE */ 4039 4040 return pos - buf; 4041 } 4042 4043 4044 static int ctrl_iface_get_capability_proto(int res, char *strict, 4045 struct wpa_driver_capa *capa, 4046 char *buf, size_t buflen) 4047 { 4048 int ret; 4049 char *pos, *end; 4050 size_t len; 4051 4052 pos = buf; 4053 end = pos + buflen; 4054 4055 if (res < 0) { 4056 if (strict) 4057 return 0; 4058 len = os_strlcpy(buf, "RSN WPA", buflen); 4059 if (len >= buflen) 4060 return -1; 4061 return len; 4062 } 4063 4064 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 4065 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4066 ret = os_snprintf(pos, end - pos, "%sRSN", 4067 pos == buf ? "" : " "); 4068 if (os_snprintf_error(end - pos, ret)) 4069 return pos - buf; 4070 pos += ret; 4071 } 4072 4073 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4074 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 4075 ret = os_snprintf(pos, end - pos, "%sWPA", 4076 pos == buf ? "" : " "); 4077 if (os_snprintf_error(end - pos, ret)) 4078 return pos - buf; 4079 pos += ret; 4080 } 4081 4082 return pos - buf; 4083 } 4084 4085 4086 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, 4087 int res, char *strict, 4088 struct wpa_driver_capa *capa, 4089 char *buf, size_t buflen) 4090 { 4091 int ret; 4092 char *pos, *end; 4093 size_t len; 4094 4095 pos = buf; 4096 end = pos + buflen; 4097 4098 if (res < 0) { 4099 if (strict) 4100 return 0; 4101 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 4102 if (len >= buflen) 4103 return -1; 4104 return len; 4105 } 4106 4107 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 4108 ret = os_snprintf(pos, end - pos, "%sOPEN", 4109 pos == buf ? "" : " "); 4110 if (os_snprintf_error(end - pos, ret)) 4111 return pos - buf; 4112 pos += ret; 4113 } 4114 4115 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 4116 ret = os_snprintf(pos, end - pos, "%sSHARED", 4117 pos == buf ? "" : " "); 4118 if (os_snprintf_error(end - pos, ret)) 4119 return pos - buf; 4120 pos += ret; 4121 } 4122 4123 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 4124 ret = os_snprintf(pos, end - pos, "%sLEAP", 4125 pos == buf ? "" : " "); 4126 if (os_snprintf_error(end - pos, ret)) 4127 return pos - buf; 4128 pos += ret; 4129 } 4130 4131 #ifdef CONFIG_SAE 4132 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) { 4133 ret = os_snprintf(pos, end - pos, "%sSAE", 4134 pos == buf ? "" : " "); 4135 if (os_snprintf_error(end - pos, ret)) 4136 return pos - buf; 4137 pos += ret; 4138 } 4139 #endif /* CONFIG_SAE */ 4140 4141 #ifdef CONFIG_FILS 4142 if (wpa_is_fils_supported(wpa_s)) { 4143 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS", 4144 pos == buf ? "" : " "); 4145 if (os_snprintf_error(end - pos, ret)) 4146 return pos - buf; 4147 pos += ret; 4148 } 4149 4150 #ifdef CONFIG_FILS_SK_PFS 4151 if (wpa_is_fils_sk_pfs_supported(wpa_s)) { 4152 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS", 4153 pos == buf ? "" : " "); 4154 if (os_snprintf_error(end - pos, ret)) 4155 return pos - buf; 4156 pos += ret; 4157 } 4158 #endif /* CONFIG_FILS_SK_PFS */ 4159 #endif /* CONFIG_FILS */ 4160 4161 return pos - buf; 4162 } 4163 4164 4165 static int ctrl_iface_get_capability_modes(int res, char *strict, 4166 struct wpa_driver_capa *capa, 4167 char *buf, size_t buflen) 4168 { 4169 int ret; 4170 char *pos, *end; 4171 size_t len; 4172 4173 pos = buf; 4174 end = pos + buflen; 4175 4176 if (res < 0) { 4177 if (strict) 4178 return 0; 4179 len = os_strlcpy(buf, "IBSS AP", buflen); 4180 if (len >= buflen) 4181 return -1; 4182 return len; 4183 } 4184 4185 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) { 4186 ret = os_snprintf(pos, end - pos, "%sIBSS", 4187 pos == buf ? "" : " "); 4188 if (os_snprintf_error(end - pos, ret)) 4189 return pos - buf; 4190 pos += ret; 4191 } 4192 4193 if (capa->flags & WPA_DRIVER_FLAGS_AP) { 4194 ret = os_snprintf(pos, end - pos, "%sAP", 4195 pos == buf ? "" : " "); 4196 if (os_snprintf_error(end - pos, ret)) 4197 return pos - buf; 4198 pos += ret; 4199 } 4200 4201 #ifdef CONFIG_MESH 4202 if (capa->flags & WPA_DRIVER_FLAGS_MESH) { 4203 ret = os_snprintf(pos, end - pos, "%sMESH", 4204 pos == buf ? "" : " "); 4205 if (os_snprintf_error(end - pos, ret)) 4206 return pos - buf; 4207 pos += ret; 4208 } 4209 #endif /* CONFIG_MESH */ 4210 4211 return pos - buf; 4212 } 4213 4214 4215 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 4216 char *buf, size_t buflen) 4217 { 4218 struct hostapd_channel_data *chnl; 4219 int ret, i, j; 4220 char *pos, *end, *hmode; 4221 4222 pos = buf; 4223 end = pos + buflen; 4224 4225 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4226 switch (wpa_s->hw.modes[j].mode) { 4227 case HOSTAPD_MODE_IEEE80211B: 4228 hmode = "B"; 4229 break; 4230 case HOSTAPD_MODE_IEEE80211G: 4231 hmode = "G"; 4232 break; 4233 case HOSTAPD_MODE_IEEE80211A: 4234 hmode = "A"; 4235 break; 4236 case HOSTAPD_MODE_IEEE80211AD: 4237 hmode = "AD"; 4238 break; 4239 default: 4240 continue; 4241 } 4242 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 4243 if (os_snprintf_error(end - pos, ret)) 4244 return pos - buf; 4245 pos += ret; 4246 chnl = wpa_s->hw.modes[j].channels; 4247 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4248 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4249 continue; 4250 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 4251 if (os_snprintf_error(end - pos, ret)) 4252 return pos - buf; 4253 pos += ret; 4254 } 4255 ret = os_snprintf(pos, end - pos, "\n"); 4256 if (os_snprintf_error(end - pos, ret)) 4257 return pos - buf; 4258 pos += ret; 4259 } 4260 4261 return pos - buf; 4262 } 4263 4264 4265 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s, 4266 char *buf, size_t buflen) 4267 { 4268 struct hostapd_channel_data *chnl; 4269 int ret, i, j; 4270 char *pos, *end, *hmode; 4271 4272 pos = buf; 4273 end = pos + buflen; 4274 4275 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4276 switch (wpa_s->hw.modes[j].mode) { 4277 case HOSTAPD_MODE_IEEE80211B: 4278 hmode = "B"; 4279 break; 4280 case HOSTAPD_MODE_IEEE80211G: 4281 hmode = "G"; 4282 break; 4283 case HOSTAPD_MODE_IEEE80211A: 4284 hmode = "A"; 4285 break; 4286 case HOSTAPD_MODE_IEEE80211AD: 4287 hmode = "AD"; 4288 break; 4289 default: 4290 continue; 4291 } 4292 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n", 4293 hmode); 4294 if (os_snprintf_error(end - pos, ret)) 4295 return pos - buf; 4296 pos += ret; 4297 chnl = wpa_s->hw.modes[j].channels; 4298 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4299 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4300 continue; 4301 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n", 4302 chnl[i].chan, chnl[i].freq, 4303 chnl[i].flag & HOSTAPD_CHAN_NO_IR ? 4304 " (NO_IR)" : "", 4305 chnl[i].flag & HOSTAPD_CHAN_RADAR ? 4306 " (DFS)" : ""); 4307 4308 if (os_snprintf_error(end - pos, ret)) 4309 return pos - buf; 4310 pos += ret; 4311 } 4312 ret = os_snprintf(pos, end - pos, "\n"); 4313 if (os_snprintf_error(end - pos, ret)) 4314 return pos - buf; 4315 pos += ret; 4316 } 4317 4318 return pos - buf; 4319 } 4320 4321 4322 static int wpa_supplicant_ctrl_iface_get_capability( 4323 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 4324 size_t buflen) 4325 { 4326 struct wpa_driver_capa capa; 4327 int res; 4328 char *strict; 4329 char field[30]; 4330 size_t len; 4331 4332 /* Determine whether or not strict checking was requested */ 4333 len = os_strlcpy(field, _field, sizeof(field)); 4334 if (len >= sizeof(field)) 4335 return -1; 4336 strict = os_strchr(field, ' '); 4337 if (strict != NULL) { 4338 *strict++ = '\0'; 4339 if (os_strcmp(strict, "strict") != 0) 4340 return -1; 4341 } 4342 4343 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 4344 field, strict ? strict : ""); 4345 4346 if (os_strcmp(field, "eap") == 0) { 4347 return eap_get_names(buf, buflen); 4348 } 4349 4350 res = wpa_drv_get_capa(wpa_s, &capa); 4351 4352 if (os_strcmp(field, "pairwise") == 0) 4353 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 4354 buf, buflen); 4355 4356 if (os_strcmp(field, "group") == 0) 4357 return ctrl_iface_get_capability_group(res, strict, &capa, 4358 buf, buflen); 4359 4360 if (os_strcmp(field, "group_mgmt") == 0) 4361 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa, 4362 buf, buflen); 4363 4364 if (os_strcmp(field, "key_mgmt") == 0) 4365 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 4366 buf, buflen); 4367 4368 if (os_strcmp(field, "proto") == 0) 4369 return ctrl_iface_get_capability_proto(res, strict, &capa, 4370 buf, buflen); 4371 4372 if (os_strcmp(field, "auth_alg") == 0) 4373 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict, 4374 &capa, buf, buflen); 4375 4376 if (os_strcmp(field, "modes") == 0) 4377 return ctrl_iface_get_capability_modes(res, strict, &capa, 4378 buf, buflen); 4379 4380 if (os_strcmp(field, "channels") == 0) 4381 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 4382 4383 if (os_strcmp(field, "freq") == 0) 4384 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen); 4385 4386 #ifdef CONFIG_TDLS 4387 if (os_strcmp(field, "tdls") == 0) 4388 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen); 4389 #endif /* CONFIG_TDLS */ 4390 4391 #ifdef CONFIG_ERP 4392 if (os_strcmp(field, "erp") == 0) { 4393 res = os_snprintf(buf, buflen, "ERP"); 4394 if (os_snprintf_error(buflen, res)) 4395 return -1; 4396 return res; 4397 } 4398 #endif /* CONFIG_EPR */ 4399 4400 #ifdef CONFIG_FIPS 4401 if (os_strcmp(field, "fips") == 0) { 4402 res = os_snprintf(buf, buflen, "FIPS"); 4403 if (os_snprintf_error(buflen, res)) 4404 return -1; 4405 return res; 4406 } 4407 #endif /* CONFIG_FIPS */ 4408 4409 #ifdef CONFIG_ACS 4410 if (os_strcmp(field, "acs") == 0) { 4411 res = os_snprintf(buf, buflen, "ACS"); 4412 if (os_snprintf_error(buflen, res)) 4413 return -1; 4414 return res; 4415 } 4416 #endif /* CONFIG_ACS */ 4417 4418 #ifdef CONFIG_FILS 4419 if (os_strcmp(field, "fils") == 0) { 4420 #ifdef CONFIG_FILS_SK_PFS 4421 if (wpa_is_fils_supported(wpa_s) && 4422 wpa_is_fils_sk_pfs_supported(wpa_s)) { 4423 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS"); 4424 if (os_snprintf_error(buflen, res)) 4425 return -1; 4426 return res; 4427 } 4428 #endif /* CONFIG_FILS_SK_PFS */ 4429 4430 if (wpa_is_fils_supported(wpa_s)) { 4431 res = os_snprintf(buf, buflen, "FILS"); 4432 if (os_snprintf_error(buflen, res)) 4433 return -1; 4434 return res; 4435 } 4436 } 4437 #endif /* CONFIG_FILS */ 4438 4439 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) { 4440 res = os_snprintf(buf, buflen, "MULTIBSS-STA"); 4441 if (os_snprintf_error(buflen, res)) 4442 return -1; 4443 return res; 4444 } 4445 4446 #ifdef CONFIG_DPP 4447 if (os_strcmp(field, "dpp") == 0) { 4448 #ifdef CONFIG_DPP2 4449 res = os_snprintf(buf, buflen, "DPP=2"); 4450 #else /* CONFIG_DPP2 */ 4451 res = os_snprintf(buf, buflen, "DPP=1"); 4452 #endif /* CONFIG_DPP2 */ 4453 if (os_snprintf_error(buflen, res)) 4454 return -1; 4455 return res; 4456 } 4457 #endif /* CONFIG_DPP */ 4458 4459 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 4460 field); 4461 4462 return -1; 4463 } 4464 4465 4466 #ifdef CONFIG_INTERWORKING 4467 static char * anqp_add_hex(char *pos, char *end, const char *title, 4468 struct wpabuf *data) 4469 { 4470 char *start = pos; 4471 size_t i; 4472 int ret; 4473 const u8 *d; 4474 4475 if (data == NULL) 4476 return start; 4477 4478 ret = os_snprintf(pos, end - pos, "%s=", title); 4479 if (os_snprintf_error(end - pos, ret)) 4480 return start; 4481 pos += ret; 4482 4483 d = wpabuf_head_u8(data); 4484 for (i = 0; i < wpabuf_len(data); i++) { 4485 ret = os_snprintf(pos, end - pos, "%02x", *d++); 4486 if (os_snprintf_error(end - pos, ret)) 4487 return start; 4488 pos += ret; 4489 } 4490 4491 ret = os_snprintf(pos, end - pos, "\n"); 4492 if (os_snprintf_error(end - pos, ret)) 4493 return start; 4494 pos += ret; 4495 4496 return pos; 4497 } 4498 #endif /* CONFIG_INTERWORKING */ 4499 4500 4501 #ifdef CONFIG_FILS 4502 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) 4503 { 4504 char *start = pos; 4505 const u8 *ie, *ie_end; 4506 u16 info, realms; 4507 int ret; 4508 4509 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); 4510 if (!ie) 4511 return 0; 4512 ie_end = ie + 2 + ie[1]; 4513 ie += 2; 4514 if (ie_end - ie < 2) 4515 return -1; 4516 4517 info = WPA_GET_LE16(ie); 4518 ie += 2; 4519 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info); 4520 if (os_snprintf_error(end - pos, ret)) 4521 return 0; 4522 pos += ret; 4523 4524 if (info & BIT(7)) { 4525 /* Cache Identifier Included */ 4526 if (ie_end - ie < 2) 4527 return -1; 4528 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n", 4529 ie[0], ie[1]); 4530 if (os_snprintf_error(end - pos, ret)) 4531 return 0; 4532 pos += ret; 4533 ie += 2; 4534 } 4535 4536 if (info & BIT(8)) { 4537 /* HESSID Included */ 4538 if (ie_end - ie < ETH_ALEN) 4539 return -1; 4540 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n", 4541 MAC2STR(ie)); 4542 if (os_snprintf_error(end - pos, ret)) 4543 return 0; 4544 pos += ret; 4545 ie += ETH_ALEN; 4546 } 4547 4548 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3; 4549 if (realms) { 4550 if (ie_end - ie < realms * 2) 4551 return -1; 4552 ret = os_snprintf(pos, end - pos, "fils_realms="); 4553 if (os_snprintf_error(end - pos, ret)) 4554 return 0; 4555 pos += ret; 4556 4557 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2); 4558 if (ret <= 0) 4559 return 0; 4560 pos += ret; 4561 ie += realms * 2; 4562 ret = os_snprintf(pos, end - pos, "\n"); 4563 if (os_snprintf_error(end - pos, ret)) 4564 return 0; 4565 pos += ret; 4566 } 4567 4568 return pos - start; 4569 } 4570 #endif /* CONFIG_FILS */ 4571 4572 4573 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 4574 unsigned long mask, char *buf, size_t buflen) 4575 { 4576 size_t i; 4577 int ret; 4578 char *pos, *end; 4579 const u8 *ie, *ie2, *osen_ie, *mesh, *owe; 4580 4581 pos = buf; 4582 end = buf + buflen; 4583 4584 if (mask & WPA_BSS_MASK_ID) { 4585 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 4586 if (os_snprintf_error(end - pos, ret)) 4587 return 0; 4588 pos += ret; 4589 } 4590 4591 if (mask & WPA_BSS_MASK_BSSID) { 4592 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 4593 MAC2STR(bss->bssid)); 4594 if (os_snprintf_error(end - pos, ret)) 4595 return 0; 4596 pos += ret; 4597 } 4598 4599 if (mask & WPA_BSS_MASK_FREQ) { 4600 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 4601 if (os_snprintf_error(end - pos, ret)) 4602 return 0; 4603 pos += ret; 4604 } 4605 4606 if (mask & WPA_BSS_MASK_BEACON_INT) { 4607 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 4608 bss->beacon_int); 4609 if (os_snprintf_error(end - pos, ret)) 4610 return 0; 4611 pos += ret; 4612 } 4613 4614 if (mask & WPA_BSS_MASK_CAPABILITIES) { 4615 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 4616 bss->caps); 4617 if (os_snprintf_error(end - pos, ret)) 4618 return 0; 4619 pos += ret; 4620 } 4621 4622 if (mask & WPA_BSS_MASK_QUAL) { 4623 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 4624 if (os_snprintf_error(end - pos, ret)) 4625 return 0; 4626 pos += ret; 4627 } 4628 4629 if (mask & WPA_BSS_MASK_NOISE) { 4630 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 4631 if (os_snprintf_error(end - pos, ret)) 4632 return 0; 4633 pos += ret; 4634 } 4635 4636 if (mask & WPA_BSS_MASK_LEVEL) { 4637 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 4638 if (os_snprintf_error(end - pos, ret)) 4639 return 0; 4640 pos += ret; 4641 } 4642 4643 if (mask & WPA_BSS_MASK_TSF) { 4644 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 4645 (unsigned long long) bss->tsf); 4646 if (os_snprintf_error(end - pos, ret)) 4647 return 0; 4648 pos += ret; 4649 } 4650 4651 if (mask & WPA_BSS_MASK_AGE) { 4652 struct os_reltime now; 4653 4654 os_get_reltime(&now); 4655 ret = os_snprintf(pos, end - pos, "age=%d\n", 4656 (int) (now.sec - bss->last_update.sec)); 4657 if (os_snprintf_error(end - pos, ret)) 4658 return 0; 4659 pos += ret; 4660 } 4661 4662 if (mask & WPA_BSS_MASK_IE) { 4663 ret = os_snprintf(pos, end - pos, "ie="); 4664 if (os_snprintf_error(end - pos, ret)) 4665 return 0; 4666 pos += ret; 4667 4668 ie = (const u8 *) (bss + 1); 4669 for (i = 0; i < bss->ie_len; i++) { 4670 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 4671 if (os_snprintf_error(end - pos, ret)) 4672 return 0; 4673 pos += ret; 4674 } 4675 4676 ret = os_snprintf(pos, end - pos, "\n"); 4677 if (os_snprintf_error(end - pos, ret)) 4678 return 0; 4679 pos += ret; 4680 } 4681 4682 if (mask & WPA_BSS_MASK_FLAGS) { 4683 ret = os_snprintf(pos, end - pos, "flags="); 4684 if (os_snprintf_error(end - pos, ret)) 4685 return 0; 4686 pos += ret; 4687 4688 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 4689 4690 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 4691 if (ie) 4692 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 4693 2 + ie[1]); 4694 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 4695 if (ie2) 4696 pos = wpa_supplicant_ie_txt(pos, end, 4697 mesh ? "RSN" : "WPA2", ie2, 4698 2 + ie2[1]); 4699 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 4700 if (osen_ie) 4701 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 4702 osen_ie, 2 + osen_ie[1]); 4703 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 4704 if (owe) { 4705 ret = os_snprintf( 4706 pos, end - pos, 4707 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 4708 if (os_snprintf_error(end - pos, ret)) 4709 return 0; 4710 pos += ret; 4711 } 4712 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 4713 if (!ie && !ie2 && !osen_ie && 4714 (bss->caps & IEEE80211_CAP_PRIVACY)) { 4715 ret = os_snprintf(pos, end - pos, "[WEP]"); 4716 if (os_snprintf_error(end - pos, ret)) 4717 return 0; 4718 pos += ret; 4719 } 4720 4721 if (mesh) { 4722 ret = os_snprintf(pos, end - pos, "[MESH]"); 4723 if (os_snprintf_error(end - pos, ret)) 4724 return 0; 4725 pos += ret; 4726 } 4727 4728 if (bss_is_dmg(bss)) { 4729 const char *s; 4730 ret = os_snprintf(pos, end - pos, "[DMG]"); 4731 if (os_snprintf_error(end - pos, ret)) 4732 return 0; 4733 pos += ret; 4734 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 4735 case IEEE80211_CAP_DMG_IBSS: 4736 s = "[IBSS]"; 4737 break; 4738 case IEEE80211_CAP_DMG_AP: 4739 s = "[ESS]"; 4740 break; 4741 case IEEE80211_CAP_DMG_PBSS: 4742 s = "[PBSS]"; 4743 break; 4744 default: 4745 s = ""; 4746 break; 4747 } 4748 ret = os_snprintf(pos, end - pos, "%s", s); 4749 if (os_snprintf_error(end - pos, ret)) 4750 return 0; 4751 pos += ret; 4752 } else { 4753 if (bss->caps & IEEE80211_CAP_IBSS) { 4754 ret = os_snprintf(pos, end - pos, "[IBSS]"); 4755 if (os_snprintf_error(end - pos, ret)) 4756 return 0; 4757 pos += ret; 4758 } 4759 if (bss->caps & IEEE80211_CAP_ESS) { 4760 ret = os_snprintf(pos, end - pos, "[ESS]"); 4761 if (os_snprintf_error(end - pos, ret)) 4762 return 0; 4763 pos += ret; 4764 } 4765 } 4766 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || 4767 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { 4768 ret = os_snprintf(pos, end - pos, "[P2P]"); 4769 if (os_snprintf_error(end - pos, ret)) 4770 return 0; 4771 pos += ret; 4772 } 4773 #ifdef CONFIG_HS20 4774 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 4775 ret = os_snprintf(pos, end - pos, "[HS20]"); 4776 if (os_snprintf_error(end - pos, ret)) 4777 return 0; 4778 pos += ret; 4779 } 4780 #endif /* CONFIG_HS20 */ 4781 #ifdef CONFIG_FILS 4782 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 4783 ret = os_snprintf(pos, end - pos, "[FILS]"); 4784 if (os_snprintf_error(end - pos, ret)) 4785 return 0; 4786 pos += ret; 4787 } 4788 #endif /* CONFIG_FILS */ 4789 #ifdef CONFIG_FST 4790 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 4791 ret = os_snprintf(pos, end - pos, "[FST]"); 4792 if (os_snprintf_error(end - pos, ret)) 4793 return 0; 4794 pos += ret; 4795 } 4796 #endif /* CONFIG_FST */ 4797 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 4798 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 4799 if (os_snprintf_error(end - pos, ret)) 4800 return 0; 4801 pos += ret; 4802 } 4803 4804 ret = os_snprintf(pos, end - pos, "\n"); 4805 if (os_snprintf_error(end - pos, ret)) 4806 return 0; 4807 pos += ret; 4808 } 4809 4810 if (mask & WPA_BSS_MASK_SSID) { 4811 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 4812 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 4813 if (os_snprintf_error(end - pos, ret)) 4814 return 0; 4815 pos += ret; 4816 } 4817 4818 #ifdef CONFIG_WPS 4819 if (mask & WPA_BSS_MASK_WPS_SCAN) { 4820 ie = (const u8 *) (bss + 1); 4821 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 4822 if (ret >= end - pos) 4823 return 0; 4824 if (ret > 0) 4825 pos += ret; 4826 } 4827 #endif /* CONFIG_WPS */ 4828 4829 #ifdef CONFIG_P2P 4830 if (mask & WPA_BSS_MASK_P2P_SCAN) { 4831 ie = (const u8 *) (bss + 1); 4832 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 4833 if (ret >= end - pos) 4834 return 0; 4835 if (ret > 0) 4836 pos += ret; 4837 } 4838 #endif /* CONFIG_P2P */ 4839 4840 #ifdef CONFIG_WIFI_DISPLAY 4841 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 4842 struct wpabuf *wfd; 4843 ie = (const u8 *) (bss + 1); 4844 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 4845 WFD_IE_VENDOR_TYPE); 4846 if (wfd) { 4847 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 4848 if (os_snprintf_error(end - pos, ret)) { 4849 wpabuf_free(wfd); 4850 return 0; 4851 } 4852 pos += ret; 4853 4854 pos += wpa_snprintf_hex(pos, end - pos, 4855 wpabuf_head(wfd), 4856 wpabuf_len(wfd)); 4857 wpabuf_free(wfd); 4858 4859 ret = os_snprintf(pos, end - pos, "\n"); 4860 if (os_snprintf_error(end - pos, ret)) 4861 return 0; 4862 pos += ret; 4863 } 4864 } 4865 #endif /* CONFIG_WIFI_DISPLAY */ 4866 4867 #ifdef CONFIG_INTERWORKING 4868 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 4869 struct wpa_bss_anqp *anqp = bss->anqp; 4870 struct wpa_bss_anqp_elem *elem; 4871 4872 pos = anqp_add_hex(pos, end, "anqp_capability_list", 4873 anqp->capability_list); 4874 pos = anqp_add_hex(pos, end, "anqp_venue_name", 4875 anqp->venue_name); 4876 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 4877 anqp->network_auth_type); 4878 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 4879 anqp->roaming_consortium); 4880 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 4881 anqp->ip_addr_type_availability); 4882 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 4883 anqp->nai_realm); 4884 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 4885 pos = anqp_add_hex(pos, end, "anqp_domain_name", 4886 anqp->domain_name); 4887 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info", 4888 anqp->fils_realm_info); 4889 #ifdef CONFIG_HS20 4890 pos = anqp_add_hex(pos, end, "hs20_capability_list", 4891 anqp->hs20_capability_list); 4892 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 4893 anqp->hs20_operator_friendly_name); 4894 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 4895 anqp->hs20_wan_metrics); 4896 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 4897 anqp->hs20_connection_capability); 4898 pos = anqp_add_hex(pos, end, "hs20_operating_class", 4899 anqp->hs20_operating_class); 4900 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", 4901 anqp->hs20_osu_providers_list); 4902 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", 4903 anqp->hs20_operator_icon_metadata); 4904 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", 4905 anqp->hs20_osu_providers_nai_list); 4906 #endif /* CONFIG_HS20 */ 4907 4908 dl_list_for_each(elem, &anqp->anqp_elems, 4909 struct wpa_bss_anqp_elem, list) { 4910 char title[20]; 4911 4912 os_snprintf(title, sizeof(title), "anqp[%u]", 4913 elem->infoid); 4914 pos = anqp_add_hex(pos, end, title, elem->payload); 4915 } 4916 } 4917 #endif /* CONFIG_INTERWORKING */ 4918 4919 #ifdef CONFIG_MESH 4920 if (mask & WPA_BSS_MASK_MESH_SCAN) { 4921 ie = (const u8 *) (bss + 1); 4922 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); 4923 if (ret >= end - pos) 4924 return 0; 4925 if (ret > 0) 4926 pos += ret; 4927 } 4928 #endif /* CONFIG_MESH */ 4929 4930 if (mask & WPA_BSS_MASK_SNR) { 4931 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr); 4932 if (os_snprintf_error(end - pos, ret)) 4933 return 0; 4934 pos += ret; 4935 } 4936 4937 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) { 4938 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n", 4939 bss->est_throughput); 4940 if (os_snprintf_error(end - pos, ret)) 4941 return 0; 4942 pos += ret; 4943 } 4944 4945 #ifdef CONFIG_FST 4946 if (mask & WPA_BSS_MASK_FST) { 4947 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos); 4948 if (ret < 0 || ret >= end - pos) 4949 return 0; 4950 pos += ret; 4951 } 4952 #endif /* CONFIG_FST */ 4953 4954 if (mask & WPA_BSS_MASK_UPDATE_IDX) { 4955 ret = os_snprintf(pos, end - pos, "update_idx=%u\n", 4956 bss->last_update_idx); 4957 if (os_snprintf_error(end - pos, ret)) 4958 return 0; 4959 pos += ret; 4960 } 4961 4962 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) { 4963 ret = os_snprintf(pos, end - pos, "beacon_ie="); 4964 if (os_snprintf_error(end - pos, ret)) 4965 return 0; 4966 pos += ret; 4967 4968 ie = (const u8 *) (bss + 1); 4969 ie += bss->ie_len; 4970 for (i = 0; i < bss->beacon_ie_len; i++) { 4971 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 4972 if (os_snprintf_error(end - pos, ret)) 4973 return 0; 4974 pos += ret; 4975 } 4976 4977 ret = os_snprintf(pos, end - pos, "\n"); 4978 if (os_snprintf_error(end - pos, ret)) 4979 return 0; 4980 pos += ret; 4981 } 4982 4983 #ifdef CONFIG_FILS 4984 if (mask & WPA_BSS_MASK_FILS_INDICATION) { 4985 ret = print_fils_indication(bss, pos, end); 4986 if (ret < 0) 4987 return 0; 4988 pos += ret; 4989 } 4990 #endif /* CONFIG_FILS */ 4991 4992 if (mask & WPA_BSS_MASK_DELIM) { 4993 ret = os_snprintf(pos, end - pos, "====\n"); 4994 if (os_snprintf_error(end - pos, ret)) 4995 return 0; 4996 pos += ret; 4997 } 4998 4999 return pos - buf; 5000 } 5001 5002 5003 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 5004 const char *cmd, char *buf, 5005 size_t buflen) 5006 { 5007 u8 bssid[ETH_ALEN]; 5008 size_t i; 5009 struct wpa_bss *bss; 5010 struct wpa_bss *bsslast = NULL; 5011 struct dl_list *next; 5012 int ret = 0; 5013 int len; 5014 char *ctmp, *end = buf + buflen; 5015 unsigned long mask = WPA_BSS_MASK_ALL; 5016 5017 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 5018 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 5019 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 5020 list_id); 5021 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 5022 list_id); 5023 } else { /* N1-N2 */ 5024 unsigned int id1, id2; 5025 5026 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 5027 wpa_printf(MSG_INFO, "Wrong BSS range " 5028 "format"); 5029 return 0; 5030 } 5031 5032 if (*(cmd + 6) == '-') 5033 id1 = 0; 5034 else 5035 id1 = atoi(cmd + 6); 5036 ctmp++; 5037 if (*ctmp >= '0' && *ctmp <= '9') 5038 id2 = atoi(ctmp); 5039 else 5040 id2 = (unsigned int) -1; 5041 bss = wpa_bss_get_id_range(wpa_s, id1, id2); 5042 if (id2 == (unsigned int) -1) 5043 bsslast = dl_list_last(&wpa_s->bss_id, 5044 struct wpa_bss, 5045 list_id); 5046 else { 5047 bsslast = wpa_bss_get_id(wpa_s, id2); 5048 if (bsslast == NULL && bss && id2 > id1) { 5049 struct wpa_bss *tmp = bss; 5050 for (;;) { 5051 next = tmp->list_id.next; 5052 if (next == &wpa_s->bss_id) 5053 break; 5054 tmp = dl_list_entry( 5055 next, struct wpa_bss, 5056 list_id); 5057 if (tmp->id > id2) 5058 break; 5059 bsslast = tmp; 5060 } 5061 } 5062 } 5063 } 5064 } else if (os_strncmp(cmd, "FIRST", 5) == 0) 5065 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 5066 else if (os_strncmp(cmd, "LAST", 4) == 0) 5067 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id); 5068 else if (os_strncmp(cmd, "ID-", 3) == 0) { 5069 i = atoi(cmd + 3); 5070 bss = wpa_bss_get_id(wpa_s, i); 5071 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 5072 i = atoi(cmd + 5); 5073 bss = wpa_bss_get_id(wpa_s, i); 5074 if (bss) { 5075 next = bss->list_id.next; 5076 if (next == &wpa_s->bss_id) 5077 bss = NULL; 5078 else 5079 bss = dl_list_entry(next, struct wpa_bss, 5080 list_id); 5081 } 5082 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) { 5083 bss = wpa_s->current_bss; 5084 #ifdef CONFIG_P2P 5085 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 5086 if (hwaddr_aton(cmd + 13, bssid) == 0) 5087 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 5088 else 5089 bss = NULL; 5090 #endif /* CONFIG_P2P */ 5091 } else if (hwaddr_aton(cmd, bssid) == 0) 5092 bss = wpa_bss_get_bssid(wpa_s, bssid); 5093 else { 5094 struct wpa_bss *tmp; 5095 i = atoi(cmd); 5096 bss = NULL; 5097 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 5098 { 5099 if (i == 0) { 5100 bss = tmp; 5101 break; 5102 } 5103 i--; 5104 } 5105 } 5106 5107 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 5108 mask = strtoul(ctmp + 5, NULL, 0x10); 5109 if (mask == 0) 5110 mask = WPA_BSS_MASK_ALL; 5111 } 5112 5113 if (bss == NULL) 5114 return 0; 5115 5116 if (bsslast == NULL) 5117 bsslast = bss; 5118 do { 5119 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 5120 ret += len; 5121 buf += len; 5122 buflen -= len; 5123 if (bss == bsslast) { 5124 if ((mask & WPA_BSS_MASK_DELIM) && len && 5125 (bss == dl_list_last(&wpa_s->bss_id, 5126 struct wpa_bss, list_id))) { 5127 int res; 5128 5129 res = os_snprintf(buf - 5, end - buf + 5, 5130 "####\n"); 5131 if (os_snprintf_error(end - buf + 5, res)) { 5132 wpa_printf(MSG_DEBUG, 5133 "Could not add end delim"); 5134 } 5135 } 5136 break; 5137 } 5138 next = bss->list_id.next; 5139 if (next == &wpa_s->bss_id) 5140 break; 5141 bss = dl_list_entry(next, struct wpa_bss, list_id); 5142 } while (bss && len); 5143 5144 return ret; 5145 } 5146 5147 5148 static int wpa_supplicant_ctrl_iface_ap_scan( 5149 struct wpa_supplicant *wpa_s, char *cmd) 5150 { 5151 int ap_scan = atoi(cmd); 5152 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 5153 } 5154 5155 5156 static int wpa_supplicant_ctrl_iface_scan_interval( 5157 struct wpa_supplicant *wpa_s, char *cmd) 5158 { 5159 int scan_int = atoi(cmd); 5160 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 5161 } 5162 5163 5164 static int wpa_supplicant_ctrl_iface_bss_expire_age( 5165 struct wpa_supplicant *wpa_s, char *cmd) 5166 { 5167 int expire_age = atoi(cmd); 5168 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 5169 } 5170 5171 5172 static int wpa_supplicant_ctrl_iface_bss_expire_count( 5173 struct wpa_supplicant *wpa_s, char *cmd) 5174 { 5175 int expire_count = atoi(cmd); 5176 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 5177 } 5178 5179 5180 static void wpa_supplicant_ctrl_iface_bss_flush( 5181 struct wpa_supplicant *wpa_s, char *cmd) 5182 { 5183 int flush_age = atoi(cmd); 5184 5185 if (flush_age == 0) 5186 wpa_bss_flush(wpa_s); 5187 else 5188 wpa_bss_flush_by_age(wpa_s, flush_age); 5189 } 5190 5191 5192 #ifdef CONFIG_TESTING_OPTIONS 5193 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 5194 { 5195 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 5196 /* MLME-DELETEKEYS.request */ 5197 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 5198 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 5199 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 5200 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 5201 #ifdef CONFIG_IEEE80211W 5202 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 5203 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 5204 #endif /* CONFIG_IEEE80211W */ 5205 5206 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 5207 0); 5208 /* MLME-SETPROTECTION.request(None) */ 5209 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 5210 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 5211 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 5212 wpa_sm_drop_sa(wpa_s->wpa); 5213 } 5214 #endif /* CONFIG_TESTING_OPTIONS */ 5215 5216 5217 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 5218 char *addr) 5219 { 5220 #ifdef CONFIG_NO_SCAN_PROCESSING 5221 return -1; 5222 #else /* CONFIG_NO_SCAN_PROCESSING */ 5223 u8 bssid[ETH_ALEN]; 5224 struct wpa_bss *bss; 5225 struct wpa_ssid *ssid = wpa_s->current_ssid; 5226 5227 if (hwaddr_aton(addr, bssid)) { 5228 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 5229 "address '%s'", addr); 5230 return -1; 5231 } 5232 5233 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 5234 5235 if (!ssid) { 5236 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 5237 "configuration known for the target AP"); 5238 return -1; 5239 } 5240 5241 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 5242 if (!bss) { 5243 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 5244 "from BSS table"); 5245 return -1; 5246 } 5247 5248 /* 5249 * TODO: Find best network configuration block from configuration to 5250 * allow roaming to other networks 5251 */ 5252 5253 wpa_s->reassociate = 1; 5254 wpa_supplicant_connect(wpa_s, bss, ssid); 5255 5256 return 0; 5257 #endif /* CONFIG_NO_SCAN_PROCESSING */ 5258 } 5259 5260 5261 #ifdef CONFIG_P2P 5262 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 5263 { 5264 unsigned int timeout = atoi(cmd); 5265 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 5266 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 5267 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL; 5268 char *pos; 5269 unsigned int search_delay; 5270 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL; 5271 u8 seek_count = 0; 5272 int freq = 0; 5273 5274 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 5275 wpa_dbg(wpa_s, MSG_INFO, 5276 "Reject P2P_FIND since interface is disabled"); 5277 return -1; 5278 } 5279 if (os_strstr(cmd, "type=social")) 5280 type = P2P_FIND_ONLY_SOCIAL; 5281 else if (os_strstr(cmd, "type=progressive")) 5282 type = P2P_FIND_PROGRESSIVE; 5283 5284 pos = os_strstr(cmd, "dev_id="); 5285 if (pos) { 5286 pos += 7; 5287 if (hwaddr_aton(pos, dev_id)) 5288 return -1; 5289 _dev_id = dev_id; 5290 } 5291 5292 pos = os_strstr(cmd, "dev_type="); 5293 if (pos) { 5294 pos += 9; 5295 if (wps_dev_type_str2bin(pos, dev_type) < 0) 5296 return -1; 5297 _dev_type = dev_type; 5298 } 5299 5300 pos = os_strstr(cmd, "delay="); 5301 if (pos) { 5302 pos += 6; 5303 search_delay = atoi(pos); 5304 } else 5305 search_delay = wpas_p2p_search_delay(wpa_s); 5306 5307 pos = os_strstr(cmd, "freq="); 5308 if (pos) { 5309 pos += 5; 5310 freq = atoi(pos); 5311 if (freq <= 0) 5312 return -1; 5313 } 5314 5315 /* Must be searched for last, because it adds nul termination */ 5316 pos = os_strstr(cmd, " seek="); 5317 if (pos) 5318 pos += 6; 5319 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) { 5320 char *term; 5321 5322 _seek[seek_count++] = pos; 5323 seek = _seek; 5324 term = os_strchr(pos, ' '); 5325 if (!term) 5326 break; 5327 *term = '\0'; 5328 pos = os_strstr(term + 1, "seek="); 5329 if (pos) 5330 pos += 5; 5331 } 5332 if (seek_count > P2P_MAX_QUERY_HASH) { 5333 seek[0] = NULL; 5334 seek_count = 1; 5335 } 5336 5337 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type, 5338 _dev_id, search_delay, seek_count, seek, freq); 5339 } 5340 5341 5342 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt) 5343 { 5344 const char *last = NULL; 5345 const char *token; 5346 long int token_len; 5347 unsigned int i; 5348 5349 /* Expected predefined CPT names delimited by ':' */ 5350 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) { 5351 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) { 5352 wpa_printf(MSG_ERROR, 5353 "P2PS: CPT name list is too long, expected up to %d names", 5354 P2PS_FEATURE_CAPAB_CPT_MAX); 5355 cpt[0] = 0; 5356 return -1; 5357 } 5358 5359 token_len = last - token; 5360 5361 if (token_len == 3 && 5362 os_memcmp(token, "UDP", token_len) == 0) { 5363 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 5364 } else if (token_len == 3 && 5365 os_memcmp(token, "MAC", token_len) == 0) { 5366 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT; 5367 } else { 5368 wpa_printf(MSG_ERROR, 5369 "P2PS: Unsupported CPT name '%s'", token); 5370 cpt[0] = 0; 5371 return -1; 5372 } 5373 5374 if (isblank((unsigned char) *last)) { 5375 i++; 5376 break; 5377 } 5378 } 5379 cpt[i] = 0; 5380 return 0; 5381 } 5382 5383 5384 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd) 5385 { 5386 struct p2ps_provision *p2ps_prov; 5387 char *pos; 5388 size_t info_len = 0; 5389 char *info = NULL; 5390 u8 role = P2PS_SETUP_NONE; 5391 long long unsigned val; 5392 int i; 5393 5394 pos = os_strstr(cmd, "info="); 5395 if (pos) { 5396 pos += 5; 5397 info_len = os_strlen(pos); 5398 5399 if (info_len) { 5400 info = os_malloc(info_len + 1); 5401 if (info) { 5402 info_len = utf8_unescape(pos, info_len, 5403 info, info_len + 1); 5404 } else 5405 info_len = 0; 5406 } 5407 } 5408 5409 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1); 5410 if (p2ps_prov == NULL) { 5411 os_free(info); 5412 return NULL; 5413 } 5414 5415 if (info) { 5416 os_memcpy(p2ps_prov->info, info, info_len); 5417 p2ps_prov->info[info_len] = '\0'; 5418 os_free(info); 5419 } 5420 5421 pos = os_strstr(cmd, "status="); 5422 if (pos) 5423 p2ps_prov->status = atoi(pos + 7); 5424 else 5425 p2ps_prov->status = -1; 5426 5427 pos = os_strstr(cmd, "adv_id="); 5428 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL) 5429 goto invalid_args; 5430 p2ps_prov->adv_id = val; 5431 5432 pos = os_strstr(cmd, "method="); 5433 if (pos) 5434 p2ps_prov->method = strtol(pos + 7, NULL, 16); 5435 else 5436 p2ps_prov->method = 0; 5437 5438 pos = os_strstr(cmd, "session="); 5439 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL) 5440 goto invalid_args; 5441 p2ps_prov->session_id = val; 5442 5443 pos = os_strstr(cmd, "adv_mac="); 5444 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac)) 5445 goto invalid_args; 5446 5447 pos = os_strstr(cmd, "session_mac="); 5448 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac)) 5449 goto invalid_args; 5450 5451 pos = os_strstr(cmd, "cpt="); 5452 if (pos) { 5453 if (p2ps_ctrl_parse_cpt_priority(pos + 4, 5454 p2ps_prov->cpt_priority)) 5455 goto invalid_args; 5456 } else { 5457 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 5458 } 5459 5460 for (i = 0; p2ps_prov->cpt_priority[i]; i++) 5461 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i]; 5462 5463 /* force conncap with tstCap (no sanity checks) */ 5464 pos = os_strstr(cmd, "tstCap="); 5465 if (pos) { 5466 role = strtol(pos + 7, NULL, 16); 5467 } else { 5468 pos = os_strstr(cmd, "role="); 5469 if (pos) { 5470 role = strtol(pos + 5, NULL, 16); 5471 if (role != P2PS_SETUP_CLIENT && 5472 role != P2PS_SETUP_GROUP_OWNER) 5473 role = P2PS_SETUP_NONE; 5474 } 5475 } 5476 p2ps_prov->role = role; 5477 5478 return p2ps_prov; 5479 5480 invalid_args: 5481 os_free(p2ps_prov); 5482 return NULL; 5483 } 5484 5485 5486 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd) 5487 { 5488 u8 addr[ETH_ALEN]; 5489 struct p2ps_provision *p2ps_prov; 5490 char *pos; 5491 5492 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */ 5493 5494 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 5495 5496 if (hwaddr_aton(cmd, addr)) 5497 return -1; 5498 5499 pos = cmd + 17; 5500 if (*pos != ' ') 5501 return -1; 5502 5503 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 5504 if (!p2ps_prov) 5505 return -1; 5506 5507 if (p2ps_prov->status < 0) { 5508 os_free(p2ps_prov); 5509 return -1; 5510 } 5511 5512 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 5513 p2ps_prov); 5514 } 5515 5516 5517 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd) 5518 { 5519 u8 addr[ETH_ALEN]; 5520 struct p2ps_provision *p2ps_prov; 5521 char *pos; 5522 5523 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap> 5524 * session=<ses_id> mac=<ses_mac> [info=<infodata>] 5525 */ 5526 5527 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 5528 if (hwaddr_aton(cmd, addr)) 5529 return -1; 5530 5531 pos = cmd + 17; 5532 if (*pos != ' ') 5533 return -1; 5534 5535 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 5536 if (!p2ps_prov) 5537 return -1; 5538 5539 p2ps_prov->pd_seeker = 1; 5540 5541 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 5542 p2ps_prov); 5543 } 5544 5545 5546 static int parse_freq(int chwidth, int freq2) 5547 { 5548 if (freq2 < 0) 5549 return -1; 5550 if (freq2) 5551 return VHT_CHANWIDTH_80P80MHZ; 5552 5553 switch (chwidth) { 5554 case 0: 5555 case 20: 5556 case 40: 5557 return VHT_CHANWIDTH_USE_HT; 5558 case 80: 5559 return VHT_CHANWIDTH_80MHZ; 5560 case 160: 5561 return VHT_CHANWIDTH_160MHZ; 5562 default: 5563 wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d", 5564 chwidth); 5565 return -1; 5566 } 5567 } 5568 5569 5570 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 5571 char *buf, size_t buflen) 5572 { 5573 u8 addr[ETH_ALEN]; 5574 char *pos, *pos2; 5575 char *pin = NULL; 5576 enum p2p_wps_method wps_method; 5577 int new_pin; 5578 int ret; 5579 int persistent_group, persistent_id = -1; 5580 int join; 5581 int auth; 5582 int automatic; 5583 int go_intent = -1; 5584 int freq = 0; 5585 int pd; 5586 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; 5587 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; 5588 size_t group_ssid_len = 0; 5589 int he; 5590 5591 if (!wpa_s->global->p2p_init_wpa_s) 5592 return -1; 5593 if (wpa_s->global->p2p_init_wpa_s != wpa_s) { 5594 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s", 5595 wpa_s->global->p2p_init_wpa_s->ifname); 5596 wpa_s = wpa_s->global->p2p_init_wpa_s; 5597 } 5598 5599 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] 5600 * [persistent|persistent=<network id>] 5601 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 5602 * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */ 5603 5604 if (hwaddr_aton(cmd, addr)) 5605 return -1; 5606 5607 pos = cmd + 17; 5608 if (*pos != ' ') 5609 return -1; 5610 pos++; 5611 5612 persistent_group = os_strstr(pos, " persistent") != NULL; 5613 pos2 = os_strstr(pos, " persistent="); 5614 if (pos2) { 5615 struct wpa_ssid *ssid; 5616 persistent_id = atoi(pos2 + 12); 5617 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 5618 if (ssid == NULL || ssid->disabled != 2 || 5619 ssid->mode != WPAS_MODE_P2P_GO) { 5620 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 5621 "SSID id=%d for persistent P2P group (GO)", 5622 persistent_id); 5623 return -1; 5624 } 5625 } 5626 join = os_strstr(pos, " join") != NULL; 5627 auth = os_strstr(pos, " auth") != NULL; 5628 automatic = os_strstr(pos, " auto") != NULL; 5629 pd = os_strstr(pos, " provdisc") != NULL; 5630 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 5631 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 5632 vht; 5633 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 5634 5635 pos2 = os_strstr(pos, " go_intent="); 5636 if (pos2) { 5637 pos2 += 11; 5638 go_intent = atoi(pos2); 5639 if (go_intent < 0 || go_intent > 15) 5640 return -1; 5641 } 5642 5643 pos2 = os_strstr(pos, " freq="); 5644 if (pos2) { 5645 pos2 += 6; 5646 freq = atoi(pos2); 5647 if (freq <= 0) 5648 return -1; 5649 } 5650 5651 pos2 = os_strstr(pos, " freq2="); 5652 if (pos2) 5653 freq2 = atoi(pos2 + 7); 5654 5655 pos2 = os_strstr(pos, " max_oper_chwidth="); 5656 if (pos2) 5657 chwidth = atoi(pos2 + 18); 5658 5659 max_oper_chwidth = parse_freq(chwidth, freq2); 5660 if (max_oper_chwidth < 0) 5661 return -1; 5662 5663 pos2 = os_strstr(pos, " ssid="); 5664 if (pos2) { 5665 char *end; 5666 5667 pos2 += 6; 5668 end = os_strchr(pos2, ' '); 5669 if (!end) 5670 group_ssid_len = os_strlen(pos2) / 2; 5671 else 5672 group_ssid_len = (end - pos2) / 2; 5673 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN || 5674 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0) 5675 return -1; 5676 group_ssid = _group_ssid; 5677 } 5678 5679 if (os_strncmp(pos, "pin", 3) == 0) { 5680 /* Request random PIN (to be displayed) and enable the PIN */ 5681 wps_method = WPS_PIN_DISPLAY; 5682 } else if (os_strncmp(pos, "pbc", 3) == 0) { 5683 wps_method = WPS_PBC; 5684 } else if (os_strstr(pos, "p2ps") != NULL) { 5685 wps_method = WPS_P2PS; 5686 } else { 5687 pin = pos; 5688 pos = os_strchr(pin, ' '); 5689 wps_method = WPS_PIN_KEYPAD; 5690 if (pos) { 5691 *pos++ = '\0'; 5692 if (os_strncmp(pos, "display", 7) == 0) 5693 wps_method = WPS_PIN_DISPLAY; 5694 } 5695 if (!wps_pin_str_valid(pin)) { 5696 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 5697 return 17; 5698 } 5699 } 5700 5701 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 5702 persistent_group, automatic, join, 5703 auth, go_intent, freq, freq2, persistent_id, 5704 pd, ht40, vht, max_oper_chwidth, he, 5705 group_ssid, group_ssid_len); 5706 if (new_pin == -2) { 5707 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 5708 return 25; 5709 } 5710 if (new_pin == -3) { 5711 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 5712 return 25; 5713 } 5714 if (new_pin < 0) 5715 return -1; 5716 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 5717 ret = os_snprintf(buf, buflen, "%08d", new_pin); 5718 if (os_snprintf_error(buflen, ret)) 5719 return -1; 5720 return ret; 5721 } 5722 5723 os_memcpy(buf, "OK\n", 3); 5724 return 3; 5725 } 5726 5727 5728 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 5729 { 5730 unsigned int timeout = atoi(cmd); 5731 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 5732 wpa_dbg(wpa_s, MSG_INFO, 5733 "Reject P2P_LISTEN since interface is disabled"); 5734 return -1; 5735 } 5736 return wpas_p2p_listen(wpa_s, timeout); 5737 } 5738 5739 5740 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 5741 { 5742 u8 addr[ETH_ALEN]; 5743 char *pos; 5744 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 5745 5746 /* <addr> <config method> [join|auto] */ 5747 5748 if (hwaddr_aton(cmd, addr)) 5749 return -1; 5750 5751 pos = cmd + 17; 5752 if (*pos != ' ') 5753 return -1; 5754 pos++; 5755 5756 if (os_strstr(pos, " join") != NULL) 5757 use = WPAS_P2P_PD_FOR_JOIN; 5758 else if (os_strstr(pos, " auto") != NULL) 5759 use = WPAS_P2P_PD_AUTO; 5760 5761 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL); 5762 } 5763 5764 5765 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 5766 size_t buflen) 5767 { 5768 struct wpa_ssid *ssid = wpa_s->current_ssid; 5769 5770 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 5771 ssid->passphrase == NULL) 5772 return -1; 5773 5774 os_strlcpy(buf, ssid->passphrase, buflen); 5775 return os_strlen(buf); 5776 } 5777 5778 5779 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 5780 char *buf, size_t buflen) 5781 { 5782 u64 ref; 5783 int res; 5784 u8 dst_buf[ETH_ALEN], *dst; 5785 struct wpabuf *tlvs; 5786 char *pos; 5787 size_t len; 5788 5789 if (hwaddr_aton(cmd, dst_buf)) 5790 return -1; 5791 dst = dst_buf; 5792 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 5793 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 5794 dst = NULL; 5795 pos = cmd + 17; 5796 if (*pos != ' ') 5797 return -1; 5798 pos++; 5799 5800 if (os_strncmp(pos, "upnp ", 5) == 0) { 5801 u8 version; 5802 pos += 5; 5803 if (hexstr2bin(pos, &version, 1) < 0) 5804 return -1; 5805 pos += 2; 5806 if (*pos != ' ') 5807 return -1; 5808 pos++; 5809 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 5810 #ifdef CONFIG_WIFI_DISPLAY 5811 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 5812 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 5813 #endif /* CONFIG_WIFI_DISPLAY */ 5814 } else if (os_strncmp(pos, "asp ", 4) == 0) { 5815 char *svc_str; 5816 char *svc_info = NULL; 5817 u32 id; 5818 5819 pos += 4; 5820 if (sscanf(pos, "%x", &id) != 1 || id > 0xff) 5821 return -1; 5822 5823 pos = os_strchr(pos, ' '); 5824 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ') 5825 return -1; 5826 5827 svc_str = pos + 1; 5828 5829 pos = os_strchr(svc_str, ' '); 5830 5831 if (pos) 5832 *pos++ = '\0'; 5833 5834 /* All remaining data is the svc_info string */ 5835 if (pos && pos[0] && pos[0] != ' ') { 5836 len = os_strlen(pos); 5837 5838 /* Unescape in place */ 5839 len = utf8_unescape(pos, len, pos, len); 5840 if (len > 0xff) 5841 return -1; 5842 5843 svc_info = pos; 5844 } 5845 5846 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id, 5847 svc_str, svc_info); 5848 } else { 5849 len = os_strlen(pos); 5850 if (len & 1) 5851 return -1; 5852 len /= 2; 5853 tlvs = wpabuf_alloc(len); 5854 if (tlvs == NULL) 5855 return -1; 5856 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 5857 wpabuf_free(tlvs); 5858 return -1; 5859 } 5860 5861 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 5862 wpabuf_free(tlvs); 5863 } 5864 if (ref == 0) 5865 return -1; 5866 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 5867 if (os_snprintf_error(buflen, res)) 5868 return -1; 5869 return res; 5870 } 5871 5872 5873 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 5874 char *cmd) 5875 { 5876 long long unsigned val; 5877 u64 req; 5878 if (sscanf(cmd, "%llx", &val) != 1) 5879 return -1; 5880 req = val; 5881 return wpas_p2p_sd_cancel_request(wpa_s, req); 5882 } 5883 5884 5885 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 5886 { 5887 int freq; 5888 u8 dst[ETH_ALEN]; 5889 u8 dialog_token; 5890 struct wpabuf *resp_tlvs; 5891 char *pos, *pos2; 5892 size_t len; 5893 5894 pos = os_strchr(cmd, ' '); 5895 if (pos == NULL) 5896 return -1; 5897 *pos++ = '\0'; 5898 freq = atoi(cmd); 5899 if (freq == 0) 5900 return -1; 5901 5902 if (hwaddr_aton(pos, dst)) 5903 return -1; 5904 pos += 17; 5905 if (*pos != ' ') 5906 return -1; 5907 pos++; 5908 5909 pos2 = os_strchr(pos, ' '); 5910 if (pos2 == NULL) 5911 return -1; 5912 *pos2++ = '\0'; 5913 dialog_token = atoi(pos); 5914 5915 len = os_strlen(pos2); 5916 if (len & 1) 5917 return -1; 5918 len /= 2; 5919 resp_tlvs = wpabuf_alloc(len); 5920 if (resp_tlvs == NULL) 5921 return -1; 5922 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 5923 wpabuf_free(resp_tlvs); 5924 return -1; 5925 } 5926 5927 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 5928 wpabuf_free(resp_tlvs); 5929 return 0; 5930 } 5931 5932 5933 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 5934 char *cmd) 5935 { 5936 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 5937 return -1; 5938 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 5939 return 0; 5940 } 5941 5942 5943 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 5944 char *cmd) 5945 { 5946 char *pos; 5947 size_t len; 5948 struct wpabuf *query, *resp; 5949 5950 pos = os_strchr(cmd, ' '); 5951 if (pos == NULL) 5952 return -1; 5953 *pos++ = '\0'; 5954 5955 len = os_strlen(cmd); 5956 if (len & 1) 5957 return -1; 5958 len /= 2; 5959 query = wpabuf_alloc(len); 5960 if (query == NULL) 5961 return -1; 5962 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 5963 wpabuf_free(query); 5964 return -1; 5965 } 5966 5967 len = os_strlen(pos); 5968 if (len & 1) { 5969 wpabuf_free(query); 5970 return -1; 5971 } 5972 len /= 2; 5973 resp = wpabuf_alloc(len); 5974 if (resp == NULL) { 5975 wpabuf_free(query); 5976 return -1; 5977 } 5978 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 5979 wpabuf_free(query); 5980 wpabuf_free(resp); 5981 return -1; 5982 } 5983 5984 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 5985 wpabuf_free(query); 5986 wpabuf_free(resp); 5987 return -1; 5988 } 5989 return 0; 5990 } 5991 5992 5993 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 5994 { 5995 char *pos; 5996 u8 version; 5997 5998 pos = os_strchr(cmd, ' '); 5999 if (pos == NULL) 6000 return -1; 6001 *pos++ = '\0'; 6002 6003 if (hexstr2bin(cmd, &version, 1) < 0) 6004 return -1; 6005 6006 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 6007 } 6008 6009 6010 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s, 6011 u8 replace, char *cmd) 6012 { 6013 char *pos; 6014 char *adv_str; 6015 u32 auto_accept, adv_id, svc_state, config_methods; 6016 char *svc_info = NULL; 6017 char *cpt_prio_str; 6018 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1]; 6019 6020 pos = os_strchr(cmd, ' '); 6021 if (pos == NULL) 6022 return -1; 6023 *pos++ = '\0'; 6024 6025 /* Auto-Accept value is mandatory, and must be one of the 6026 * single values (0, 1, 2, 4) */ 6027 auto_accept = atoi(cmd); 6028 switch (auto_accept) { 6029 case P2PS_SETUP_NONE: /* No auto-accept */ 6030 case P2PS_SETUP_NEW: 6031 case P2PS_SETUP_CLIENT: 6032 case P2PS_SETUP_GROUP_OWNER: 6033 break; 6034 default: 6035 return -1; 6036 } 6037 6038 /* Advertisement ID is mandatory */ 6039 cmd = pos; 6040 pos = os_strchr(cmd, ' '); 6041 if (pos == NULL) 6042 return -1; 6043 *pos++ = '\0'; 6044 6045 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */ 6046 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0) 6047 return -1; 6048 6049 /* Only allow replacements if exist, and adds if not */ 6050 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) { 6051 if (!replace) 6052 return -1; 6053 } else { 6054 if (replace) 6055 return -1; 6056 } 6057 6058 /* svc_state between 0 - 0xff is mandatory */ 6059 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff) 6060 return -1; 6061 6062 pos = os_strchr(pos, ' '); 6063 if (pos == NULL) 6064 return -1; 6065 6066 /* config_methods is mandatory */ 6067 pos++; 6068 if (sscanf(pos, "%x", &config_methods) != 1) 6069 return -1; 6070 6071 if (!(config_methods & 6072 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS))) 6073 return -1; 6074 6075 pos = os_strchr(pos, ' '); 6076 if (pos == NULL) 6077 return -1; 6078 6079 pos++; 6080 adv_str = pos; 6081 6082 /* Advertisement string is mandatory */ 6083 if (!pos[0] || pos[0] == ' ') 6084 return -1; 6085 6086 /* Terminate svc string */ 6087 pos = os_strchr(pos, ' '); 6088 if (pos != NULL) 6089 *pos++ = '\0'; 6090 6091 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL; 6092 if (cpt_prio_str) { 6093 pos = os_strchr(pos, ' '); 6094 if (pos != NULL) 6095 *pos++ = '\0'; 6096 6097 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio)) 6098 return -1; 6099 } else { 6100 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6101 cpt_prio[1] = 0; 6102 } 6103 6104 /* Service and Response Information are optional */ 6105 if (pos && pos[0]) { 6106 size_t len; 6107 6108 /* Note the bare ' included, which cannot exist legally 6109 * in unescaped string. */ 6110 svc_info = os_strstr(pos, "svc_info='"); 6111 6112 if (svc_info) { 6113 svc_info += 9; 6114 len = os_strlen(svc_info); 6115 utf8_unescape(svc_info, len, svc_info, len); 6116 } 6117 } 6118 6119 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str, 6120 (u8) svc_state, (u16) config_methods, 6121 svc_info, cpt_prio); 6122 } 6123 6124 6125 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 6126 { 6127 char *pos; 6128 6129 pos = os_strchr(cmd, ' '); 6130 if (pos == NULL) 6131 return -1; 6132 *pos++ = '\0'; 6133 6134 if (os_strcmp(cmd, "bonjour") == 0) 6135 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 6136 if (os_strcmp(cmd, "upnp") == 0) 6137 return p2p_ctrl_service_add_upnp(wpa_s, pos); 6138 if (os_strcmp(cmd, "asp") == 0) 6139 return p2p_ctrl_service_add_asp(wpa_s, 0, pos); 6140 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6141 return -1; 6142 } 6143 6144 6145 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 6146 char *cmd) 6147 { 6148 size_t len; 6149 struct wpabuf *query; 6150 int ret; 6151 6152 len = os_strlen(cmd); 6153 if (len & 1) 6154 return -1; 6155 len /= 2; 6156 query = wpabuf_alloc(len); 6157 if (query == NULL) 6158 return -1; 6159 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 6160 wpabuf_free(query); 6161 return -1; 6162 } 6163 6164 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 6165 wpabuf_free(query); 6166 return ret; 6167 } 6168 6169 6170 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6171 { 6172 char *pos; 6173 u8 version; 6174 6175 pos = os_strchr(cmd, ' '); 6176 if (pos == NULL) 6177 return -1; 6178 *pos++ = '\0'; 6179 6180 if (hexstr2bin(cmd, &version, 1) < 0) 6181 return -1; 6182 6183 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 6184 } 6185 6186 6187 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd) 6188 { 6189 u32 adv_id; 6190 6191 if (os_strcmp(cmd, "all") == 0) { 6192 wpas_p2p_service_flush_asp(wpa_s); 6193 return 0; 6194 } 6195 6196 if (sscanf(cmd, "%x", &adv_id) != 1) 6197 return -1; 6198 6199 return wpas_p2p_service_del_asp(wpa_s, adv_id); 6200 } 6201 6202 6203 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 6204 { 6205 char *pos; 6206 6207 pos = os_strchr(cmd, ' '); 6208 if (pos == NULL) 6209 return -1; 6210 *pos++ = '\0'; 6211 6212 if (os_strcmp(cmd, "bonjour") == 0) 6213 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 6214 if (os_strcmp(cmd, "upnp") == 0) 6215 return p2p_ctrl_service_del_upnp(wpa_s, pos); 6216 if (os_strcmp(cmd, "asp") == 0) 6217 return p2p_ctrl_service_del_asp(wpa_s, pos); 6218 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6219 return -1; 6220 } 6221 6222 6223 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd) 6224 { 6225 char *pos; 6226 6227 pos = os_strchr(cmd, ' '); 6228 if (pos == NULL) 6229 return -1; 6230 *pos++ = '\0'; 6231 6232 if (os_strcmp(cmd, "asp") == 0) 6233 return p2p_ctrl_service_add_asp(wpa_s, 1, pos); 6234 6235 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6236 return -1; 6237 } 6238 6239 6240 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 6241 { 6242 u8 addr[ETH_ALEN]; 6243 6244 /* <addr> */ 6245 6246 if (hwaddr_aton(cmd, addr)) 6247 return -1; 6248 6249 return wpas_p2p_reject(wpa_s, addr); 6250 } 6251 6252 6253 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 6254 { 6255 char *pos; 6256 int id; 6257 struct wpa_ssid *ssid; 6258 u8 *_peer = NULL, peer[ETH_ALEN]; 6259 int freq = 0, pref_freq = 0; 6260 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; 6261 6262 id = atoi(cmd); 6263 pos = os_strstr(cmd, " peer="); 6264 if (pos) { 6265 pos += 6; 6266 if (hwaddr_aton(pos, peer)) 6267 return -1; 6268 _peer = peer; 6269 } 6270 ssid = wpa_config_get_network(wpa_s->conf, id); 6271 if (ssid == NULL || ssid->disabled != 2) { 6272 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 6273 "for persistent P2P group", 6274 id); 6275 return -1; 6276 } 6277 6278 pos = os_strstr(cmd, " freq="); 6279 if (pos) { 6280 pos += 6; 6281 freq = atoi(pos); 6282 if (freq <= 0) 6283 return -1; 6284 } 6285 6286 pos = os_strstr(cmd, " pref="); 6287 if (pos) { 6288 pos += 6; 6289 pref_freq = atoi(pos); 6290 if (pref_freq <= 0) 6291 return -1; 6292 } 6293 6294 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 6295 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 6296 vht; 6297 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 6298 6299 pos = os_strstr(cmd, "freq2="); 6300 if (pos) 6301 freq2 = atoi(pos + 6); 6302 6303 pos = os_strstr(cmd, " max_oper_chwidth="); 6304 if (pos) 6305 chwidth = atoi(pos + 18); 6306 6307 max_oper_chwidth = parse_freq(chwidth, freq2); 6308 if (max_oper_chwidth < 0) 6309 return -1; 6310 6311 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, 6312 max_oper_chwidth, pref_freq, he); 6313 } 6314 6315 6316 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 6317 { 6318 char *pos; 6319 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 6320 6321 pos = os_strstr(cmd, " peer="); 6322 if (!pos) 6323 return -1; 6324 6325 *pos = '\0'; 6326 pos += 6; 6327 if (hwaddr_aton(pos, peer)) { 6328 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 6329 return -1; 6330 } 6331 6332 pos = os_strstr(pos, " go_dev_addr="); 6333 if (pos) { 6334 pos += 13; 6335 if (hwaddr_aton(pos, go_dev_addr)) { 6336 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 6337 pos); 6338 return -1; 6339 } 6340 go_dev = go_dev_addr; 6341 } 6342 6343 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 6344 } 6345 6346 6347 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 6348 { 6349 if (os_strncmp(cmd, "persistent=", 11) == 0) 6350 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 6351 if (os_strncmp(cmd, "group=", 6) == 0) 6352 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 6353 6354 return -1; 6355 } 6356 6357 6358 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 6359 int id, int freq, int vht_center_freq2, 6360 int ht40, int vht, int vht_chwidth, 6361 int he) 6362 { 6363 struct wpa_ssid *ssid; 6364 6365 ssid = wpa_config_get_network(wpa_s->conf, id); 6366 if (ssid == NULL || ssid->disabled != 2) { 6367 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 6368 "for persistent P2P group", 6369 id); 6370 return -1; 6371 } 6372 6373 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 6374 vht_center_freq2, 0, ht40, vht, 6375 vht_chwidth, he, NULL, 0, 0); 6376 } 6377 6378 6379 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 6380 { 6381 int freq = 0, persistent = 0, group_id = -1; 6382 int vht = wpa_s->conf->p2p_go_vht; 6383 int ht40 = wpa_s->conf->p2p_go_ht40 || vht; 6384 int he = wpa_s->conf->p2p_go_he; 6385 int max_oper_chwidth, chwidth = 0, freq2 = 0; 6386 char *token, *context = NULL; 6387 #ifdef CONFIG_ACS 6388 int acs = 0; 6389 #endif /* CONFIG_ACS */ 6390 6391 while ((token = str_token(cmd, " ", &context))) { 6392 if (sscanf(token, "freq2=%d", &freq2) == 1 || 6393 sscanf(token, "persistent=%d", &group_id) == 1 || 6394 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) { 6395 continue; 6396 #ifdef CONFIG_ACS 6397 } else if (os_strcmp(token, "freq=acs") == 0) { 6398 acs = 1; 6399 #endif /* CONFIG_ACS */ 6400 } else if (sscanf(token, "freq=%d", &freq) == 1) { 6401 continue; 6402 } else if (os_strcmp(token, "ht40") == 0) { 6403 ht40 = 1; 6404 } else if (os_strcmp(token, "vht") == 0) { 6405 vht = 1; 6406 ht40 = 1; 6407 } else if (os_strcmp(token, "he") == 0) { 6408 he = 1; 6409 } else if (os_strcmp(token, "persistent") == 0) { 6410 persistent = 1; 6411 } else { 6412 wpa_printf(MSG_DEBUG, 6413 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'", 6414 token); 6415 return -1; 6416 } 6417 } 6418 6419 #ifdef CONFIG_ACS 6420 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 6421 (acs || freq == 2 || freq == 5)) { 6422 if (freq == 2 && wpa_s->best_24_freq <= 0) { 6423 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G; 6424 wpa_s->p2p_go_do_acs = 1; 6425 freq = 0; 6426 } else if (freq == 5 && wpa_s->best_5_freq <= 0) { 6427 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A; 6428 wpa_s->p2p_go_do_acs = 1; 6429 freq = 0; 6430 } else { 6431 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY; 6432 wpa_s->p2p_go_do_acs = 1; 6433 } 6434 } else { 6435 wpa_s->p2p_go_do_acs = 0; 6436 } 6437 #endif /* CONFIG_ACS */ 6438 6439 max_oper_chwidth = parse_freq(chwidth, freq2); 6440 if (max_oper_chwidth < 0) 6441 return -1; 6442 6443 if (group_id >= 0) 6444 return p2p_ctrl_group_add_persistent(wpa_s, group_id, 6445 freq, freq2, ht40, vht, 6446 max_oper_chwidth, he); 6447 6448 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, 6449 max_oper_chwidth, he); 6450 } 6451 6452 6453 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd, 6454 char *buf, size_t buflen) 6455 { 6456 u8 dev_addr[ETH_ALEN]; 6457 struct wpa_ssid *ssid; 6458 int res; 6459 const u8 *iaddr; 6460 6461 ssid = wpa_s->current_ssid; 6462 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO || 6463 hwaddr_aton(cmd, dev_addr)) 6464 return -1; 6465 6466 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr); 6467 if (!iaddr) 6468 return -1; 6469 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr)); 6470 if (os_snprintf_error(buflen, res)) 6471 return -1; 6472 return res; 6473 } 6474 6475 6476 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global, 6477 const u8 *p2p_dev_addr) 6478 { 6479 struct wpa_supplicant *wpa_s; 6480 6481 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 6482 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr)) 6483 return 1; 6484 } 6485 6486 return 0; 6487 } 6488 6489 6490 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 6491 char *buf, size_t buflen) 6492 { 6493 u8 addr[ETH_ALEN], *addr_ptr, group_capab; 6494 int next, res; 6495 const struct p2p_peer_info *info; 6496 char *pos, *end; 6497 char devtype[WPS_DEV_TYPE_BUFSIZE]; 6498 struct wpa_ssid *ssid; 6499 size_t i; 6500 6501 if (!wpa_s->global->p2p) 6502 return -1; 6503 6504 if (os_strcmp(cmd, "FIRST") == 0) { 6505 addr_ptr = NULL; 6506 next = 0; 6507 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 6508 if (hwaddr_aton(cmd + 5, addr) < 0) 6509 return -1; 6510 addr_ptr = addr; 6511 next = 1; 6512 } else { 6513 if (hwaddr_aton(cmd, addr) < 0) 6514 return -1; 6515 addr_ptr = addr; 6516 next = 0; 6517 } 6518 6519 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 6520 if (info == NULL) 6521 return -1; 6522 group_capab = info->group_capab; 6523 6524 if (group_capab && 6525 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) { 6526 wpa_printf(MSG_DEBUG, 6527 "P2P: Could not find any BSS with p2p_dev_addr " 6528 MACSTR ", hence override group_capab from 0x%x to 0", 6529 MAC2STR(info->p2p_device_addr), group_capab); 6530 group_capab = 0; 6531 } 6532 6533 pos = buf; 6534 end = buf + buflen; 6535 6536 res = os_snprintf(pos, end - pos, MACSTR "\n" 6537 "pri_dev_type=%s\n" 6538 "device_name=%s\n" 6539 "manufacturer=%s\n" 6540 "model_name=%s\n" 6541 "model_number=%s\n" 6542 "serial_number=%s\n" 6543 "config_methods=0x%x\n" 6544 "dev_capab=0x%x\n" 6545 "group_capab=0x%x\n" 6546 "level=%d\n", 6547 MAC2STR(info->p2p_device_addr), 6548 wps_dev_type_bin2str(info->pri_dev_type, 6549 devtype, sizeof(devtype)), 6550 info->device_name, 6551 info->manufacturer, 6552 info->model_name, 6553 info->model_number, 6554 info->serial_number, 6555 info->config_methods, 6556 info->dev_capab, 6557 group_capab, 6558 info->level); 6559 if (os_snprintf_error(end - pos, res)) 6560 return pos - buf; 6561 pos += res; 6562 6563 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 6564 { 6565 const u8 *t; 6566 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 6567 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 6568 wps_dev_type_bin2str(t, devtype, 6569 sizeof(devtype))); 6570 if (os_snprintf_error(end - pos, res)) 6571 return pos - buf; 6572 pos += res; 6573 } 6574 6575 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 6576 if (ssid) { 6577 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 6578 if (os_snprintf_error(end - pos, res)) 6579 return pos - buf; 6580 pos += res; 6581 } 6582 6583 res = p2p_get_peer_info_txt(info, pos, end - pos); 6584 if (res < 0) 6585 return pos - buf; 6586 pos += res; 6587 6588 if (info->vendor_elems) { 6589 res = os_snprintf(pos, end - pos, "vendor_elems="); 6590 if (os_snprintf_error(end - pos, res)) 6591 return pos - buf; 6592 pos += res; 6593 6594 pos += wpa_snprintf_hex(pos, end - pos, 6595 wpabuf_head(info->vendor_elems), 6596 wpabuf_len(info->vendor_elems)); 6597 6598 res = os_snprintf(pos, end - pos, "\n"); 6599 if (os_snprintf_error(end - pos, res)) 6600 return pos - buf; 6601 pos += res; 6602 } 6603 6604 return pos - buf; 6605 } 6606 6607 6608 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 6609 const char *param) 6610 { 6611 unsigned int i; 6612 6613 if (wpa_s->global->p2p == NULL) 6614 return -1; 6615 6616 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0) 6617 return -1; 6618 6619 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) { 6620 struct wpa_freq_range *freq; 6621 freq = &wpa_s->global->p2p_disallow_freq.range[i]; 6622 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 6623 freq->min, freq->max); 6624 } 6625 6626 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW); 6627 return 0; 6628 } 6629 6630 6631 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 6632 { 6633 char *param; 6634 6635 if (wpa_s->global->p2p == NULL) 6636 return -1; 6637 6638 param = os_strchr(cmd, ' '); 6639 if (param == NULL) 6640 return -1; 6641 *param++ = '\0'; 6642 6643 if (os_strcmp(cmd, "discoverability") == 0) { 6644 p2p_set_client_discoverability(wpa_s->global->p2p, 6645 atoi(param)); 6646 return 0; 6647 } 6648 6649 if (os_strcmp(cmd, "managed") == 0) { 6650 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 6651 return 0; 6652 } 6653 6654 if (os_strcmp(cmd, "listen_channel") == 0) { 6655 char *pos; 6656 u8 channel, op_class; 6657 6658 channel = atoi(param); 6659 pos = os_strchr(param, ' '); 6660 op_class = pos ? atoi(pos) : 81; 6661 6662 return p2p_set_listen_channel(wpa_s->global->p2p, op_class, 6663 channel, 1); 6664 } 6665 6666 if (os_strcmp(cmd, "ssid_postfix") == 0) { 6667 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 6668 os_strlen(param)); 6669 } 6670 6671 if (os_strcmp(cmd, "noa") == 0) { 6672 char *pos; 6673 int count, start, duration; 6674 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 6675 count = atoi(param); 6676 pos = os_strchr(param, ','); 6677 if (pos == NULL) 6678 return -1; 6679 pos++; 6680 start = atoi(pos); 6681 pos = os_strchr(pos, ','); 6682 if (pos == NULL) 6683 return -1; 6684 pos++; 6685 duration = atoi(pos); 6686 if (count < 0 || count > 255 || start < 0 || duration < 0) 6687 return -1; 6688 if (count == 0 && duration > 0) 6689 return -1; 6690 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 6691 "start=%d duration=%d", count, start, duration); 6692 return wpas_p2p_set_noa(wpa_s, count, start, duration); 6693 } 6694 6695 if (os_strcmp(cmd, "ps") == 0) 6696 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 6697 6698 if (os_strcmp(cmd, "oppps") == 0) 6699 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 6700 6701 if (os_strcmp(cmd, "ctwindow") == 0) 6702 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 6703 6704 if (os_strcmp(cmd, "disabled") == 0) { 6705 wpa_s->global->p2p_disabled = atoi(param); 6706 wpa_printf(MSG_DEBUG, "P2P functionality %s", 6707 wpa_s->global->p2p_disabled ? 6708 "disabled" : "enabled"); 6709 if (wpa_s->global->p2p_disabled) { 6710 wpas_p2p_stop_find(wpa_s); 6711 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 6712 p2p_flush(wpa_s->global->p2p); 6713 } 6714 return 0; 6715 } 6716 6717 if (os_strcmp(cmd, "conc_pref") == 0) { 6718 if (os_strcmp(param, "sta") == 0) 6719 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 6720 else if (os_strcmp(param, "p2p") == 0) 6721 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 6722 else { 6723 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 6724 return -1; 6725 } 6726 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 6727 "%s", param); 6728 return 0; 6729 } 6730 6731 if (os_strcmp(cmd, "force_long_sd") == 0) { 6732 wpa_s->force_long_sd = atoi(param); 6733 return 0; 6734 } 6735 6736 if (os_strcmp(cmd, "peer_filter") == 0) { 6737 u8 addr[ETH_ALEN]; 6738 if (hwaddr_aton(param, addr)) 6739 return -1; 6740 p2p_set_peer_filter(wpa_s->global->p2p, addr); 6741 return 0; 6742 } 6743 6744 if (os_strcmp(cmd, "cross_connect") == 0) 6745 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 6746 6747 if (os_strcmp(cmd, "go_apsd") == 0) { 6748 if (os_strcmp(param, "disable") == 0) 6749 wpa_s->set_ap_uapsd = 0; 6750 else { 6751 wpa_s->set_ap_uapsd = 1; 6752 wpa_s->ap_uapsd = atoi(param); 6753 } 6754 return 0; 6755 } 6756 6757 if (os_strcmp(cmd, "client_apsd") == 0) { 6758 if (os_strcmp(param, "disable") == 0) 6759 wpa_s->set_sta_uapsd = 0; 6760 else { 6761 int be, bk, vi, vo; 6762 char *pos; 6763 /* format: BE,BK,VI,VO;max SP Length */ 6764 be = atoi(param); 6765 pos = os_strchr(param, ','); 6766 if (pos == NULL) 6767 return -1; 6768 pos++; 6769 bk = atoi(pos); 6770 pos = os_strchr(pos, ','); 6771 if (pos == NULL) 6772 return -1; 6773 pos++; 6774 vi = atoi(pos); 6775 pos = os_strchr(pos, ','); 6776 if (pos == NULL) 6777 return -1; 6778 pos++; 6779 vo = atoi(pos); 6780 /* ignore max SP Length for now */ 6781 6782 wpa_s->set_sta_uapsd = 1; 6783 wpa_s->sta_uapsd = 0; 6784 if (be) 6785 wpa_s->sta_uapsd |= BIT(0); 6786 if (bk) 6787 wpa_s->sta_uapsd |= BIT(1); 6788 if (vi) 6789 wpa_s->sta_uapsd |= BIT(2); 6790 if (vo) 6791 wpa_s->sta_uapsd |= BIT(3); 6792 } 6793 return 0; 6794 } 6795 6796 if (os_strcmp(cmd, "disallow_freq") == 0) 6797 return p2p_ctrl_disallow_freq(wpa_s, param); 6798 6799 if (os_strcmp(cmd, "disc_int") == 0) { 6800 int min_disc_int, max_disc_int, max_disc_tu; 6801 char *pos; 6802 6803 pos = param; 6804 6805 min_disc_int = atoi(pos); 6806 pos = os_strchr(pos, ' '); 6807 if (pos == NULL) 6808 return -1; 6809 *pos++ = '\0'; 6810 6811 max_disc_int = atoi(pos); 6812 pos = os_strchr(pos, ' '); 6813 if (pos == NULL) 6814 return -1; 6815 *pos++ = '\0'; 6816 6817 max_disc_tu = atoi(pos); 6818 6819 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 6820 max_disc_int, max_disc_tu); 6821 } 6822 6823 if (os_strcmp(cmd, "per_sta_psk") == 0) { 6824 wpa_s->global->p2p_per_sta_psk = !!atoi(param); 6825 return 0; 6826 } 6827 6828 #ifdef CONFIG_WPS_NFC 6829 if (os_strcmp(cmd, "nfc_tag") == 0) 6830 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param)); 6831 #endif /* CONFIG_WPS_NFC */ 6832 6833 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) { 6834 wpa_s->p2p_disable_ip_addr_req = !!atoi(param); 6835 return 0; 6836 } 6837 6838 if (os_strcmp(cmd, "override_pref_op_chan") == 0) { 6839 int op_class, chan; 6840 6841 op_class = atoi(param); 6842 param = os_strchr(param, ':'); 6843 if (!param) 6844 return -1; 6845 param++; 6846 chan = atoi(param); 6847 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class, 6848 chan); 6849 return 0; 6850 } 6851 6852 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 6853 cmd); 6854 6855 return -1; 6856 } 6857 6858 6859 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) 6860 { 6861 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 6862 wpa_s->force_long_sd = 0; 6863 6864 #ifdef CONFIG_TESTING_OPTIONS 6865 os_free(wpa_s->get_pref_freq_list_override); 6866 wpa_s->get_pref_freq_list_override = NULL; 6867 #endif /* CONFIG_TESTING_OPTIONS */ 6868 6869 wpas_p2p_stop_find(wpa_s); 6870 wpa_s->parent->p2ps_method_config_any = 0; 6871 if (wpa_s->global->p2p) 6872 p2p_flush(wpa_s->global->p2p); 6873 } 6874 6875 6876 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 6877 { 6878 char *pos, *pos2; 6879 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 6880 6881 if (cmd[0]) { 6882 pos = os_strchr(cmd, ' '); 6883 if (pos == NULL) 6884 return -1; 6885 *pos++ = '\0'; 6886 dur1 = atoi(cmd); 6887 6888 pos2 = os_strchr(pos, ' '); 6889 if (pos2) 6890 *pos2++ = '\0'; 6891 int1 = atoi(pos); 6892 } else 6893 pos2 = NULL; 6894 6895 if (pos2) { 6896 pos = os_strchr(pos2, ' '); 6897 if (pos == NULL) 6898 return -1; 6899 *pos++ = '\0'; 6900 dur2 = atoi(pos2); 6901 int2 = atoi(pos); 6902 } 6903 6904 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 6905 } 6906 6907 6908 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 6909 { 6910 char *pos; 6911 unsigned int period = 0, interval = 0; 6912 6913 if (cmd[0]) { 6914 pos = os_strchr(cmd, ' '); 6915 if (pos == NULL) 6916 return -1; 6917 *pos++ = '\0'; 6918 period = atoi(cmd); 6919 interval = atoi(pos); 6920 } 6921 6922 return wpas_p2p_ext_listen(wpa_s, period, interval); 6923 } 6924 6925 6926 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) 6927 { 6928 const char *pos; 6929 u8 peer[ETH_ALEN]; 6930 int iface_addr = 0; 6931 6932 pos = cmd; 6933 if (os_strncmp(pos, "iface=", 6) == 0) { 6934 iface_addr = 1; 6935 pos += 6; 6936 } 6937 if (hwaddr_aton(pos, peer)) 6938 return -1; 6939 6940 wpas_p2p_remove_client(wpa_s, peer, iface_addr); 6941 return 0; 6942 } 6943 6944 6945 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd) 6946 { 6947 int freq = 0, period = 0, interval = 0, count = 0; 6948 6949 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4) 6950 { 6951 wpa_printf(MSG_DEBUG, 6952 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd); 6953 return -1; 6954 } 6955 6956 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count); 6957 } 6958 6959 #endif /* CONFIG_P2P */ 6960 6961 6962 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val) 6963 { 6964 struct wpa_freq_range_list ranges; 6965 int *freqs = NULL; 6966 struct hostapd_hw_modes *mode; 6967 u16 i; 6968 6969 if (wpa_s->hw.modes == NULL) 6970 return NULL; 6971 6972 os_memset(&ranges, 0, sizeof(ranges)); 6973 if (freq_range_list_parse(&ranges, val) < 0) 6974 return NULL; 6975 6976 for (i = 0; i < wpa_s->hw.num_modes; i++) { 6977 int j; 6978 6979 mode = &wpa_s->hw.modes[i]; 6980 for (j = 0; j < mode->num_channels; j++) { 6981 unsigned int freq; 6982 6983 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED) 6984 continue; 6985 6986 freq = mode->channels[j].freq; 6987 if (!freq_range_list_includes(&ranges, freq)) 6988 continue; 6989 6990 int_array_add_unique(&freqs, freq); 6991 } 6992 } 6993 6994 os_free(ranges.range); 6995 return freqs; 6996 } 6997 6998 6999 #ifdef CONFIG_INTERWORKING 7000 7001 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) 7002 { 7003 int auto_sel = 0; 7004 int *freqs = NULL; 7005 7006 if (param) { 7007 char *pos; 7008 7009 auto_sel = os_strstr(param, "auto") != NULL; 7010 7011 pos = os_strstr(param, "freq="); 7012 if (pos) { 7013 freqs = freq_range_to_channel_list(wpa_s, pos + 5); 7014 if (freqs == NULL) 7015 return -1; 7016 } 7017 7018 } 7019 7020 return interworking_select(wpa_s, auto_sel, freqs); 7021 } 7022 7023 7024 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, 7025 int only_add) 7026 { 7027 u8 bssid[ETH_ALEN]; 7028 struct wpa_bss *bss; 7029 7030 if (hwaddr_aton(dst, bssid)) { 7031 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 7032 return -1; 7033 } 7034 7035 bss = wpa_bss_get_bssid(wpa_s, bssid); 7036 if (bss == NULL) { 7037 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 7038 MAC2STR(bssid)); 7039 return -1; 7040 } 7041 7042 if (bss->ssid_len == 0) { 7043 int found = 0; 7044 7045 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR 7046 " does not have SSID information", MAC2STR(bssid)); 7047 7048 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, 7049 list) { 7050 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && 7051 bss->ssid_len > 0) { 7052 found = 1; 7053 break; 7054 } 7055 } 7056 7057 if (!found) 7058 return -1; 7059 wpa_printf(MSG_DEBUG, 7060 "Found another matching BSS entry with SSID"); 7061 } 7062 7063 return interworking_connect(wpa_s, bss, only_add); 7064 } 7065 7066 7067 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 7068 { 7069 u8 dst_addr[ETH_ALEN]; 7070 int used; 7071 char *pos; 7072 #define MAX_ANQP_INFO_ID 100 7073 u16 id[MAX_ANQP_INFO_ID]; 7074 size_t num_id = 0; 7075 u32 subtypes = 0; 7076 u32 mbo_subtypes = 0; 7077 7078 used = hwaddr_aton2(dst, dst_addr); 7079 if (used < 0) 7080 return -1; 7081 pos = dst + used; 7082 if (*pos == ' ') 7083 pos++; 7084 while (num_id < MAX_ANQP_INFO_ID) { 7085 if (os_strncmp(pos, "hs20:", 5) == 0) { 7086 #ifdef CONFIG_HS20 7087 int num = atoi(pos + 5); 7088 if (num <= 0 || num > 31) 7089 return -1; 7090 subtypes |= BIT(num); 7091 #else /* CONFIG_HS20 */ 7092 return -1; 7093 #endif /* CONFIG_HS20 */ 7094 } else if (os_strncmp(pos, "mbo:", 4) == 0) { 7095 #ifdef CONFIG_MBO 7096 int num = atoi(pos + 4); 7097 7098 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) 7099 return -1; 7100 mbo_subtypes |= BIT(num); 7101 #else /* CONFIG_MBO */ 7102 return -1; 7103 #endif /* CONFIG_MBO */ 7104 } else { 7105 id[num_id] = atoi(pos); 7106 if (id[num_id]) 7107 num_id++; 7108 } 7109 pos = os_strchr(pos + 1, ','); 7110 if (pos == NULL) 7111 break; 7112 pos++; 7113 } 7114 7115 if (num_id == 0 && !subtypes && !mbo_subtypes) 7116 return -1; 7117 7118 return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, 7119 mbo_subtypes); 7120 } 7121 7122 7123 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 7124 { 7125 u8 dst_addr[ETH_ALEN]; 7126 struct wpabuf *advproto, *query = NULL; 7127 int used, ret = -1; 7128 char *pos, *end; 7129 size_t len; 7130 7131 used = hwaddr_aton2(cmd, dst_addr); 7132 if (used < 0) 7133 return -1; 7134 7135 pos = cmd + used; 7136 while (*pos == ' ') 7137 pos++; 7138 7139 /* Advertisement Protocol ID */ 7140 end = os_strchr(pos, ' '); 7141 if (end) 7142 len = end - pos; 7143 else 7144 len = os_strlen(pos); 7145 if (len & 0x01) 7146 return -1; 7147 len /= 2; 7148 if (len == 0) 7149 return -1; 7150 advproto = wpabuf_alloc(len); 7151 if (advproto == NULL) 7152 return -1; 7153 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 7154 goto fail; 7155 7156 if (end) { 7157 /* Optional Query Request */ 7158 pos = end + 1; 7159 while (*pos == ' ') 7160 pos++; 7161 7162 len = os_strlen(pos); 7163 if (len) { 7164 if (len & 0x01) 7165 goto fail; 7166 len /= 2; 7167 if (len == 0) 7168 goto fail; 7169 query = wpabuf_alloc(len); 7170 if (query == NULL) 7171 goto fail; 7172 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 7173 goto fail; 7174 } 7175 } 7176 7177 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 7178 7179 fail: 7180 wpabuf_free(advproto); 7181 wpabuf_free(query); 7182 7183 return ret; 7184 } 7185 7186 7187 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 7188 size_t buflen) 7189 { 7190 u8 addr[ETH_ALEN]; 7191 int dialog_token; 7192 int used; 7193 char *pos; 7194 size_t resp_len, start, requested_len; 7195 struct wpabuf *resp; 7196 int ret; 7197 7198 used = hwaddr_aton2(cmd, addr); 7199 if (used < 0) 7200 return -1; 7201 7202 pos = cmd + used; 7203 while (*pos == ' ') 7204 pos++; 7205 dialog_token = atoi(pos); 7206 7207 if (wpa_s->last_gas_resp && 7208 os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 && 7209 dialog_token == wpa_s->last_gas_dialog_token) 7210 resp = wpa_s->last_gas_resp; 7211 else if (wpa_s->prev_gas_resp && 7212 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 && 7213 dialog_token == wpa_s->prev_gas_dialog_token) 7214 resp = wpa_s->prev_gas_resp; 7215 else 7216 return -1; 7217 7218 resp_len = wpabuf_len(resp); 7219 start = 0; 7220 requested_len = resp_len; 7221 7222 pos = os_strchr(pos, ' '); 7223 if (pos) { 7224 start = atoi(pos); 7225 if (start > resp_len) 7226 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 7227 pos = os_strchr(pos, ','); 7228 if (pos == NULL) 7229 return -1; 7230 pos++; 7231 requested_len = atoi(pos); 7232 if (start + requested_len > resp_len) 7233 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 7234 } 7235 7236 if (requested_len * 2 + 1 > buflen) 7237 return os_snprintf(buf, buflen, "FAIL-Too long response"); 7238 7239 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start, 7240 requested_len); 7241 7242 if (start + requested_len == resp_len) { 7243 /* 7244 * Free memory by dropping the response after it has been 7245 * fetched. 7246 */ 7247 if (resp == wpa_s->prev_gas_resp) { 7248 wpabuf_free(wpa_s->prev_gas_resp); 7249 wpa_s->prev_gas_resp = NULL; 7250 } else { 7251 wpabuf_free(wpa_s->last_gas_resp); 7252 wpa_s->last_gas_resp = NULL; 7253 } 7254 } 7255 7256 return ret; 7257 } 7258 #endif /* CONFIG_INTERWORKING */ 7259 7260 7261 #ifdef CONFIG_HS20 7262 7263 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 7264 { 7265 u8 dst_addr[ETH_ALEN]; 7266 int used; 7267 char *pos; 7268 u32 subtypes = 0; 7269 7270 used = hwaddr_aton2(dst, dst_addr); 7271 if (used < 0) 7272 return -1; 7273 pos = dst + used; 7274 if (*pos == ' ') 7275 pos++; 7276 for (;;) { 7277 int num = atoi(pos); 7278 if (num <= 0 || num > 31) 7279 return -1; 7280 subtypes |= BIT(num); 7281 pos = os_strchr(pos + 1, ','); 7282 if (pos == NULL) 7283 break; 7284 pos++; 7285 } 7286 7287 if (subtypes == 0) 7288 return -1; 7289 7290 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0); 7291 } 7292 7293 7294 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 7295 const u8 *addr, const char *realm) 7296 { 7297 u8 *buf; 7298 size_t rlen, len; 7299 int ret; 7300 7301 rlen = os_strlen(realm); 7302 len = 3 + rlen; 7303 buf = os_malloc(len); 7304 if (buf == NULL) 7305 return -1; 7306 buf[0] = 1; /* NAI Home Realm Count */ 7307 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 7308 buf[2] = rlen; 7309 os_memcpy(buf + 3, realm, rlen); 7310 7311 ret = hs20_anqp_send_req(wpa_s, addr, 7312 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 7313 buf, len, 0); 7314 7315 os_free(buf); 7316 7317 return ret; 7318 } 7319 7320 7321 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 7322 char *dst) 7323 { 7324 struct wpa_cred *cred = wpa_s->conf->cred; 7325 u8 dst_addr[ETH_ALEN]; 7326 int used; 7327 u8 *buf; 7328 size_t len; 7329 int ret; 7330 7331 used = hwaddr_aton2(dst, dst_addr); 7332 if (used < 0) 7333 return -1; 7334 7335 while (dst[used] == ' ') 7336 used++; 7337 if (os_strncmp(dst + used, "realm=", 6) == 0) 7338 return hs20_nai_home_realm_list(wpa_s, dst_addr, 7339 dst + used + 6); 7340 7341 len = os_strlen(dst + used); 7342 7343 if (len == 0 && cred && cred->realm) 7344 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 7345 7346 if (len & 1) 7347 return -1; 7348 len /= 2; 7349 buf = os_malloc(len); 7350 if (buf == NULL) 7351 return -1; 7352 if (hexstr2bin(dst + used, buf, len) < 0) { 7353 os_free(buf); 7354 return -1; 7355 } 7356 7357 ret = hs20_anqp_send_req(wpa_s, dst_addr, 7358 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 7359 buf, len, 0); 7360 os_free(buf); 7361 7362 return ret; 7363 } 7364 7365 7366 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply, 7367 int buflen) 7368 { 7369 u8 dst_addr[ETH_ALEN]; 7370 int used; 7371 char *ctx = NULL, *icon, *poffset, *psize; 7372 7373 used = hwaddr_aton2(cmd, dst_addr); 7374 if (used < 0) 7375 return -1; 7376 cmd += used; 7377 7378 icon = str_token(cmd, " ", &ctx); 7379 poffset = str_token(cmd, " ", &ctx); 7380 psize = str_token(cmd, " ", &ctx); 7381 if (!icon || !poffset || !psize) 7382 return -1; 7383 7384 wpa_s->fetch_osu_icon_in_progress = 0; 7385 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize), 7386 reply, buflen); 7387 } 7388 7389 7390 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd) 7391 { 7392 u8 dst_addr[ETH_ALEN]; 7393 int used; 7394 char *icon; 7395 7396 if (!cmd[0]) 7397 return hs20_del_icon(wpa_s, NULL, NULL); 7398 7399 used = hwaddr_aton2(cmd, dst_addr); 7400 if (used < 0) 7401 return -1; 7402 7403 while (cmd[used] == ' ') 7404 used++; 7405 icon = cmd[used] ? &cmd[used] : NULL; 7406 7407 return hs20_del_icon(wpa_s, dst_addr, icon); 7408 } 7409 7410 7411 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem) 7412 { 7413 u8 dst_addr[ETH_ALEN]; 7414 int used; 7415 char *icon; 7416 7417 used = hwaddr_aton2(cmd, dst_addr); 7418 if (used < 0) 7419 return -1; 7420 7421 while (cmd[used] == ' ') 7422 used++; 7423 icon = &cmd[used]; 7424 7425 wpa_s->fetch_osu_icon_in_progress = 0; 7426 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST), 7427 (u8 *) icon, os_strlen(icon), inmem); 7428 } 7429 7430 #endif /* CONFIG_HS20 */ 7431 7432 7433 #ifdef CONFIG_AUTOSCAN 7434 7435 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 7436 char *cmd) 7437 { 7438 enum wpa_states state = wpa_s->wpa_state; 7439 char *new_params = NULL; 7440 7441 if (os_strlen(cmd) > 0) { 7442 new_params = os_strdup(cmd); 7443 if (new_params == NULL) 7444 return -1; 7445 } 7446 7447 os_free(wpa_s->conf->autoscan); 7448 wpa_s->conf->autoscan = new_params; 7449 7450 if (wpa_s->conf->autoscan == NULL) 7451 autoscan_deinit(wpa_s); 7452 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 7453 autoscan_init(wpa_s, 1); 7454 else if (state == WPA_SCANNING) 7455 wpa_supplicant_reinit_autoscan(wpa_s); 7456 else 7457 wpa_printf(MSG_DEBUG, "No autoscan update in state %s", 7458 wpa_supplicant_state_txt(state)); 7459 7460 return 0; 7461 } 7462 7463 #endif /* CONFIG_AUTOSCAN */ 7464 7465 7466 #ifdef CONFIG_WNM 7467 7468 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 7469 { 7470 int enter; 7471 int intval = 0; 7472 char *pos; 7473 int ret; 7474 struct wpabuf *tfs_req = NULL; 7475 7476 if (os_strncmp(cmd, "enter", 5) == 0) 7477 enter = 1; 7478 else if (os_strncmp(cmd, "exit", 4) == 0) 7479 enter = 0; 7480 else 7481 return -1; 7482 7483 pos = os_strstr(cmd, " interval="); 7484 if (pos) 7485 intval = atoi(pos + 10); 7486 7487 pos = os_strstr(cmd, " tfs_req="); 7488 if (pos) { 7489 char *end; 7490 size_t len; 7491 pos += 9; 7492 end = os_strchr(pos, ' '); 7493 if (end) 7494 len = end - pos; 7495 else 7496 len = os_strlen(pos); 7497 if (len & 1) 7498 return -1; 7499 len /= 2; 7500 tfs_req = wpabuf_alloc(len); 7501 if (tfs_req == NULL) 7502 return -1; 7503 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 7504 wpabuf_free(tfs_req); 7505 return -1; 7506 } 7507 } 7508 7509 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 7510 WNM_SLEEP_MODE_EXIT, intval, 7511 tfs_req); 7512 wpabuf_free(tfs_req); 7513 7514 return ret; 7515 } 7516 7517 7518 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) 7519 { 7520 int query_reason, list = 0; 7521 char *btm_candidates = NULL; 7522 7523 query_reason = atoi(cmd); 7524 7525 cmd = os_strchr(cmd, ' '); 7526 if (cmd) { 7527 if (os_strncmp(cmd, " list", 5) == 0) 7528 list = 1; 7529 else 7530 btm_candidates = cmd; 7531 } 7532 7533 wpa_printf(MSG_DEBUG, 7534 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s", 7535 query_reason, list ? " candidate list" : ""); 7536 7537 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, 7538 btm_candidates, 7539 list); 7540 } 7541 7542 7543 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s, 7544 char *cmd) 7545 { 7546 struct wpabuf *elems; 7547 int ret; 7548 7549 elems = wpabuf_parse_bin(cmd); 7550 if (!elems) 7551 return -1; 7552 7553 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems); 7554 wpabuf_free(elems); 7555 return ret; 7556 } 7557 7558 #endif /* CONFIG_WNM */ 7559 7560 7561 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 7562 size_t buflen) 7563 { 7564 struct wpa_signal_info si; 7565 int ret; 7566 char *pos, *end; 7567 7568 ret = wpa_drv_signal_poll(wpa_s, &si); 7569 if (ret) 7570 return -1; 7571 7572 pos = buf; 7573 end = buf + buflen; 7574 7575 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n" 7576 "NOISE=%d\nFREQUENCY=%u\n", 7577 si.current_signal, si.current_txrate / 1000, 7578 si.current_noise, si.frequency); 7579 if (os_snprintf_error(end - pos, ret)) 7580 return -1; 7581 pos += ret; 7582 7583 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) { 7584 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 7585 channel_width_to_string(si.chanwidth)); 7586 if (os_snprintf_error(end - pos, ret)) 7587 return -1; 7588 pos += ret; 7589 } 7590 7591 if (si.center_frq1 > 0) { 7592 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 7593 si.center_frq1); 7594 if (os_snprintf_error(end - pos, ret)) 7595 return -1; 7596 pos += ret; 7597 } 7598 7599 if (si.center_frq2 > 0) { 7600 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 7601 si.center_frq2); 7602 if (os_snprintf_error(end - pos, ret)) 7603 return -1; 7604 pos += ret; 7605 } 7606 7607 if (si.avg_signal) { 7608 ret = os_snprintf(pos, end - pos, 7609 "AVG_RSSI=%d\n", si.avg_signal); 7610 if (os_snprintf_error(end - pos, ret)) 7611 return -1; 7612 pos += ret; 7613 } 7614 7615 if (si.avg_beacon_signal) { 7616 ret = os_snprintf(pos, end - pos, 7617 "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal); 7618 if (os_snprintf_error(end - pos, ret)) 7619 return -1; 7620 pos += ret; 7621 } 7622 7623 return pos - buf; 7624 } 7625 7626 7627 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s, 7628 const char *cmd) 7629 { 7630 const char *pos; 7631 int threshold = 0; 7632 int hysteresis = 0; 7633 7634 if (wpa_s->bgscan && wpa_s->bgscan_priv) { 7635 wpa_printf(MSG_DEBUG, 7636 "Reject SIGNAL_MONITOR command - bgscan is active"); 7637 return -1; 7638 } 7639 pos = os_strstr(cmd, "THRESHOLD="); 7640 if (pos) 7641 threshold = atoi(pos + 10); 7642 pos = os_strstr(cmd, "HYSTERESIS="); 7643 if (pos) 7644 hysteresis = atoi(pos + 11); 7645 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis); 7646 } 7647 7648 7649 #ifdef CONFIG_TESTING_OPTIONS 7650 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, 7651 enum wpa_driver_if_type if_type, 7652 unsigned int *num, 7653 unsigned int *freq_list) 7654 { 7655 char *pos = wpa_s->get_pref_freq_list_override; 7656 char *end; 7657 unsigned int count = 0; 7658 7659 /* Override string format: 7660 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */ 7661 7662 while (pos) { 7663 if (atoi(pos) == (int) if_type) 7664 break; 7665 pos = os_strchr(pos, ' '); 7666 if (pos) 7667 pos++; 7668 } 7669 if (!pos) 7670 return -1; 7671 pos = os_strchr(pos, ':'); 7672 if (!pos) 7673 return -1; 7674 pos++; 7675 end = os_strchr(pos, ' '); 7676 while (pos && (!end || pos < end) && count < *num) { 7677 freq_list[count++] = atoi(pos); 7678 pos = os_strchr(pos, ','); 7679 if (pos) 7680 pos++; 7681 } 7682 7683 *num = count; 7684 return 0; 7685 } 7686 #endif /* CONFIG_TESTING_OPTIONS */ 7687 7688 7689 static int wpas_ctrl_iface_get_pref_freq_list( 7690 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 7691 { 7692 unsigned int freq_list[100], num = 100, i; 7693 int ret; 7694 enum wpa_driver_if_type iface_type; 7695 char *pos, *end; 7696 7697 pos = buf; 7698 end = buf + buflen; 7699 7700 /* buf: "<interface_type>" */ 7701 if (os_strcmp(cmd, "STATION") == 0) 7702 iface_type = WPA_IF_STATION; 7703 else if (os_strcmp(cmd, "AP") == 0) 7704 iface_type = WPA_IF_AP_BSS; 7705 else if (os_strcmp(cmd, "P2P_GO") == 0) 7706 iface_type = WPA_IF_P2P_GO; 7707 else if (os_strcmp(cmd, "P2P_CLIENT") == 0) 7708 iface_type = WPA_IF_P2P_CLIENT; 7709 else if (os_strcmp(cmd, "IBSS") == 0) 7710 iface_type = WPA_IF_IBSS; 7711 else if (os_strcmp(cmd, "TDLS") == 0) 7712 iface_type = WPA_IF_TDLS; 7713 else 7714 return -1; 7715 7716 wpa_printf(MSG_DEBUG, 7717 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", 7718 iface_type, cmd); 7719 7720 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); 7721 if (ret) 7722 return -1; 7723 7724 for (i = 0; i < num; i++) { 7725 ret = os_snprintf(pos, end - pos, "%s%u", 7726 i > 0 ? "," : "", freq_list[i]); 7727 if (os_snprintf_error(end - pos, ret)) 7728 return -1; 7729 pos += ret; 7730 } 7731 7732 return pos - buf; 7733 } 7734 7735 7736 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, 7737 char *buf, size_t buflen) 7738 { 7739 int ret, i; 7740 char *pos, *end; 7741 7742 ret = os_snprintf(buf, buflen, "%016llX:\n", 7743 (long long unsigned) wpa_s->drv_flags); 7744 if (os_snprintf_error(buflen, ret)) 7745 return -1; 7746 7747 pos = buf + ret; 7748 end = buf + buflen; 7749 7750 for (i = 0; i < 64; i++) { 7751 if (wpa_s->drv_flags & (1LLU << i)) { 7752 ret = os_snprintf(pos, end - pos, "%s\n", 7753 driver_flag_to_string(1LLU << i)); 7754 if (os_snprintf_error(end - pos, ret)) 7755 return -1; 7756 pos += ret; 7757 } 7758 } 7759 7760 return pos - buf; 7761 } 7762 7763 7764 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 7765 size_t buflen) 7766 { 7767 struct hostap_sta_driver_data sta; 7768 int ret; 7769 7770 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 7771 if (ret) 7772 return -1; 7773 7774 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 7775 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 7776 if (os_snprintf_error(buflen, ret)) 7777 return -1; 7778 return ret; 7779 } 7780 7781 7782 #ifdef ANDROID 7783 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 7784 char *buf, size_t buflen) 7785 { 7786 int ret; 7787 7788 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 7789 if (ret == 0) { 7790 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { 7791 struct p2p_data *p2p = wpa_s->global->p2p; 7792 if (p2p) { 7793 char country[3]; 7794 country[0] = cmd[8]; 7795 country[1] = cmd[9]; 7796 country[2] = 0x04; 7797 p2p_set_country(p2p, country); 7798 } 7799 } 7800 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 7801 if (os_snprintf_error(buflen, ret)) 7802 ret = -1; 7803 } 7804 return ret; 7805 } 7806 #endif /* ANDROID */ 7807 7808 7809 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, 7810 char *buf, size_t buflen) 7811 { 7812 int ret; 7813 char *pos; 7814 u8 *data = NULL; 7815 unsigned int vendor_id, subcmd; 7816 struct wpabuf *reply; 7817 size_t data_len = 0; 7818 7819 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 7820 vendor_id = strtoul(cmd, &pos, 16); 7821 if (!isblank((unsigned char) *pos)) 7822 return -EINVAL; 7823 7824 subcmd = strtoul(pos, &pos, 10); 7825 7826 if (*pos != '\0') { 7827 if (!isblank((unsigned char) *pos++)) 7828 return -EINVAL; 7829 data_len = os_strlen(pos); 7830 } 7831 7832 if (data_len) { 7833 data_len /= 2; 7834 data = os_malloc(data_len); 7835 if (!data) 7836 return -1; 7837 7838 if (hexstr2bin(pos, data, data_len)) { 7839 wpa_printf(MSG_DEBUG, 7840 "Vendor command: wrong parameter format"); 7841 os_free(data); 7842 return -EINVAL; 7843 } 7844 } 7845 7846 reply = wpabuf_alloc((buflen - 1) / 2); 7847 if (!reply) { 7848 os_free(data); 7849 return -1; 7850 } 7851 7852 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, 7853 reply); 7854 7855 if (ret == 0) 7856 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 7857 wpabuf_len(reply)); 7858 7859 wpabuf_free(reply); 7860 os_free(data); 7861 7862 return ret; 7863 } 7864 7865 7866 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) 7867 { 7868 #ifdef CONFIG_P2P 7869 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ? 7870 wpa_s->global->p2p_init_wpa_s : wpa_s; 7871 #endif /* CONFIG_P2P */ 7872 7873 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); 7874 7875 if (wpas_abort_ongoing_scan(wpa_s) == 0) 7876 wpa_s->ignore_post_flush_scan_res = 1; 7877 7878 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 7879 /* 7880 * Avoid possible auto connect re-connection on getting 7881 * disconnected due to state flush. 7882 */ 7883 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 7884 } 7885 7886 #ifdef CONFIG_P2P 7887 wpas_p2p_group_remove(p2p_wpa_s, "*"); 7888 wpas_p2p_cancel(p2p_wpa_s); 7889 p2p_ctrl_flush(p2p_wpa_s); 7890 wpas_p2p_service_flush(p2p_wpa_s); 7891 p2p_wpa_s->global->p2p_disabled = 0; 7892 p2p_wpa_s->global->p2p_per_sta_psk = 0; 7893 p2p_wpa_s->conf->num_sec_device_types = 0; 7894 p2p_wpa_s->p2p_disable_ip_addr_req = 0; 7895 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range); 7896 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL; 7897 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0; 7898 p2p_wpa_s->global->pending_p2ps_group = 0; 7899 p2p_wpa_s->global->pending_p2ps_group_freq = 0; 7900 #endif /* CONFIG_P2P */ 7901 7902 #ifdef CONFIG_WPS_TESTING 7903 wps_version_number = 0x20; 7904 wps_testing_dummy_cred = 0; 7905 wps_corrupt_pkhash = 0; 7906 wps_force_auth_types_in_use = 0; 7907 wps_force_encr_types_in_use = 0; 7908 #endif /* CONFIG_WPS_TESTING */ 7909 #ifdef CONFIG_WPS 7910 wpa_s->wps_fragment_size = 0; 7911 wpas_wps_cancel(wpa_s); 7912 wps_registrar_flush(wpa_s->wps->registrar); 7913 #endif /* CONFIG_WPS */ 7914 wpa_s->after_wps = 0; 7915 wpa_s->known_wps_freq = 0; 7916 7917 #ifdef CONFIG_DPP 7918 wpas_dpp_deinit(wpa_s); 7919 wpa_s->dpp_init_max_tries = 0; 7920 wpa_s->dpp_init_retry_time = 0; 7921 wpa_s->dpp_resp_wait_time = 0; 7922 wpa_s->dpp_resp_max_tries = 0; 7923 wpa_s->dpp_resp_retry_time = 0; 7924 #ifdef CONFIG_TESTING_OPTIONS 7925 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); 7926 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); 7927 dpp_pkex_ephemeral_key_override_len = 0; 7928 dpp_protocol_key_override_len = 0; 7929 dpp_nonce_override_len = 0; 7930 #endif /* CONFIG_TESTING_OPTIONS */ 7931 #endif /* CONFIG_DPP */ 7932 7933 #ifdef CONFIG_TDLS 7934 #ifdef CONFIG_TDLS_TESTING 7935 tdls_testing = 0; 7936 #endif /* CONFIG_TDLS_TESTING */ 7937 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL); 7938 wpa_tdls_enable(wpa_s->wpa, 1); 7939 #endif /* CONFIG_TDLS */ 7940 7941 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 7942 wpa_supplicant_stop_countermeasures(wpa_s, NULL); 7943 7944 wpa_s->no_keep_alive = 0; 7945 wpa_s->own_disconnect_req = 0; 7946 7947 os_free(wpa_s->disallow_aps_bssid); 7948 wpa_s->disallow_aps_bssid = NULL; 7949 wpa_s->disallow_aps_bssid_count = 0; 7950 os_free(wpa_s->disallow_aps_ssid); 7951 wpa_s->disallow_aps_ssid = NULL; 7952 wpa_s->disallow_aps_ssid_count = 0; 7953 7954 wpa_s->set_sta_uapsd = 0; 7955 wpa_s->sta_uapsd = 0; 7956 7957 wpa_drv_radio_disable(wpa_s, 0); 7958 wpa_blacklist_clear(wpa_s); 7959 wpa_s->extra_blacklist_count = 0; 7960 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); 7961 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); 7962 wpa_config_flush_blobs(wpa_s->conf); 7963 wpa_s->conf->auto_interworking = 0; 7964 wpa_s->conf->okc = 0; 7965 7966 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 7967 rsn_preauth_deinit(wpa_s->wpa); 7968 7969 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); 7970 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); 7971 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); 7972 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 7973 7974 radio_remove_works(wpa_s, NULL, 1); 7975 wpa_s->ext_work_in_progress = 0; 7976 7977 wpa_s->next_ssid = NULL; 7978 7979 #ifdef CONFIG_INTERWORKING 7980 #ifdef CONFIG_HS20 7981 hs20_cancel_fetch_osu(wpa_s); 7982 hs20_del_icon(wpa_s, NULL, NULL); 7983 #endif /* CONFIG_HS20 */ 7984 #endif /* CONFIG_INTERWORKING */ 7985 7986 wpa_s->ext_mgmt_frame_handling = 0; 7987 wpa_s->ext_eapol_frame_io = 0; 7988 #ifdef CONFIG_TESTING_OPTIONS 7989 wpa_s->extra_roc_dur = 0; 7990 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE; 7991 wpa_s->p2p_go_csa_on_inv = 0; 7992 wpa_s->ignore_auth_resp = 0; 7993 wpa_s->ignore_assoc_disallow = 0; 7994 wpa_s->testing_resend_assoc = 0; 7995 wpa_s->reject_btm_req_reason = 0; 7996 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); 7997 os_free(wpa_s->get_pref_freq_list_override); 7998 wpa_s->get_pref_freq_list_override = NULL; 7999 wpabuf_free(wpa_s->sae_commit_override); 8000 wpa_s->sae_commit_override = NULL; 8001 #ifdef CONFIG_DPP 8002 os_free(wpa_s->dpp_config_obj_override); 8003 wpa_s->dpp_config_obj_override = NULL; 8004 os_free(wpa_s->dpp_discovery_override); 8005 wpa_s->dpp_discovery_override = NULL; 8006 os_free(wpa_s->dpp_groups_override); 8007 wpa_s->dpp_groups_override = NULL; 8008 dpp_test = DPP_TEST_DISABLED; 8009 #endif /* CONFIG_DPP */ 8010 #endif /* CONFIG_TESTING_OPTIONS */ 8011 8012 wpa_s->disconnected = 0; 8013 os_free(wpa_s->next_scan_freqs); 8014 wpa_s->next_scan_freqs = NULL; 8015 os_free(wpa_s->select_network_scan_freqs); 8016 wpa_s->select_network_scan_freqs = NULL; 8017 8018 wpa_bss_flush(wpa_s); 8019 if (!dl_list_empty(&wpa_s->bss)) { 8020 wpa_printf(MSG_DEBUG, 8021 "BSS table not empty after flush: %u entries, current_bss=%p bssid=" 8022 MACSTR " pending_bssid=" MACSTR, 8023 dl_list_len(&wpa_s->bss), wpa_s->current_bss, 8024 MAC2STR(wpa_s->bssid), 8025 MAC2STR(wpa_s->pending_bssid)); 8026 } 8027 8028 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); 8029 wpa_s->wnmsleep_used = 0; 8030 8031 #ifdef CONFIG_SME 8032 wpa_s->sme.last_unprot_disconnect.sec = 0; 8033 #endif /* CONFIG_SME */ 8034 8035 wpabuf_free(wpa_s->ric_ies); 8036 wpa_s->ric_ies = NULL; 8037 8038 wpa_supplicant_update_channel_list(wpa_s, NULL); 8039 8040 free_bss_tmp_disallowed(wpa_s); 8041 } 8042 8043 8044 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, 8045 char *buf, size_t buflen) 8046 { 8047 struct wpa_radio_work *work; 8048 char *pos, *end; 8049 struct os_reltime now, diff; 8050 8051 pos = buf; 8052 end = buf + buflen; 8053 8054 os_get_reltime(&now); 8055 8056 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 8057 { 8058 int ret; 8059 8060 os_reltime_sub(&now, &work->time, &diff); 8061 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n", 8062 work->type, work->wpa_s->ifname, work->freq, 8063 work->started, diff.sec, diff.usec); 8064 if (os_snprintf_error(end - pos, ret)) 8065 break; 8066 pos += ret; 8067 } 8068 8069 return pos - buf; 8070 } 8071 8072 8073 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx) 8074 { 8075 struct wpa_radio_work *work = eloop_ctx; 8076 struct wpa_external_work *ework = work->ctx; 8077 8078 wpa_dbg(work->wpa_s, MSG_DEBUG, 8079 "Timing out external radio work %u (%s)", 8080 ework->id, work->type); 8081 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id); 8082 work->wpa_s->ext_work_in_progress = 0; 8083 radio_work_done(work); 8084 os_free(ework); 8085 } 8086 8087 8088 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit) 8089 { 8090 struct wpa_external_work *ework = work->ctx; 8091 8092 if (deinit) { 8093 if (work->started) 8094 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 8095 work, NULL); 8096 8097 /* 8098 * work->type points to a buffer in ework, so need to replace 8099 * that here with a fixed string to avoid use of freed memory 8100 * in debug prints. 8101 */ 8102 work->type = "freed-ext-work"; 8103 work->ctx = NULL; 8104 os_free(ework); 8105 return; 8106 } 8107 8108 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)", 8109 ework->id, ework->type); 8110 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id); 8111 work->wpa_s->ext_work_in_progress = 1; 8112 if (!ework->timeout) 8113 ework->timeout = 10; 8114 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout, 8115 work, NULL); 8116 } 8117 8118 8119 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd, 8120 char *buf, size_t buflen) 8121 { 8122 struct wpa_external_work *ework; 8123 char *pos, *pos2; 8124 size_t type_len; 8125 int ret; 8126 unsigned int freq = 0; 8127 8128 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */ 8129 8130 ework = os_zalloc(sizeof(*ework)); 8131 if (ework == NULL) 8132 return -1; 8133 8134 pos = os_strchr(cmd, ' '); 8135 if (pos) { 8136 type_len = pos - cmd; 8137 pos++; 8138 8139 pos2 = os_strstr(pos, "freq="); 8140 if (pos2) 8141 freq = atoi(pos2 + 5); 8142 8143 pos2 = os_strstr(pos, "timeout="); 8144 if (pos2) 8145 ework->timeout = atoi(pos2 + 8); 8146 } else { 8147 type_len = os_strlen(cmd); 8148 } 8149 if (4 + type_len >= sizeof(ework->type)) 8150 type_len = sizeof(ework->type) - 4 - 1; 8151 os_strlcpy(ework->type, "ext:", sizeof(ework->type)); 8152 os_memcpy(ework->type + 4, cmd, type_len); 8153 ework->type[4 + type_len] = '\0'; 8154 8155 wpa_s->ext_work_id++; 8156 if (wpa_s->ext_work_id == 0) 8157 wpa_s->ext_work_id++; 8158 ework->id = wpa_s->ext_work_id; 8159 8160 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb, 8161 ework) < 0) { 8162 os_free(ework); 8163 return -1; 8164 } 8165 8166 ret = os_snprintf(buf, buflen, "%u", ework->id); 8167 if (os_snprintf_error(buflen, ret)) 8168 return -1; 8169 return ret; 8170 } 8171 8172 8173 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd) 8174 { 8175 struct wpa_radio_work *work; 8176 unsigned int id = atoi(cmd); 8177 8178 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 8179 { 8180 struct wpa_external_work *ework; 8181 8182 if (os_strncmp(work->type, "ext:", 4) != 0) 8183 continue; 8184 ework = work->ctx; 8185 if (id && ework->id != id) 8186 continue; 8187 wpa_dbg(wpa_s, MSG_DEBUG, 8188 "Completed external radio work %u (%s)", 8189 ework->id, ework->type); 8190 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL); 8191 wpa_s->ext_work_in_progress = 0; 8192 radio_work_done(work); 8193 os_free(ework); 8194 return 3; /* "OK\n" */ 8195 } 8196 8197 return -1; 8198 } 8199 8200 8201 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd, 8202 char *buf, size_t buflen) 8203 { 8204 if (os_strcmp(cmd, "show") == 0) 8205 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen); 8206 if (os_strncmp(cmd, "add ", 4) == 0) 8207 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen); 8208 if (os_strncmp(cmd, "done ", 5) == 0) 8209 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4); 8210 return -1; 8211 } 8212 8213 8214 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) 8215 { 8216 struct wpa_radio_work *work, *tmp; 8217 8218 if (!wpa_s || !wpa_s->radio) 8219 return; 8220 8221 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work, 8222 struct wpa_radio_work, list) { 8223 struct wpa_external_work *ework; 8224 8225 if (os_strncmp(work->type, "ext:", 4) != 0) 8226 continue; 8227 ework = work->ctx; 8228 wpa_dbg(wpa_s, MSG_DEBUG, 8229 "Flushing%s external radio work %u (%s)", 8230 work->started ? " started" : "", ework->id, 8231 ework->type); 8232 if (work->started) 8233 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 8234 work, NULL); 8235 radio_work_done(work); 8236 os_free(ework); 8237 } 8238 } 8239 8240 8241 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 8242 { 8243 struct wpa_supplicant *wpa_s = eloop_ctx; 8244 eapol_sm_notify_ctrl_response(wpa_s->eapol); 8245 } 8246 8247 8248 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value, 8249 unsigned int *scan_id_count, int scan_id[]) 8250 { 8251 const char *pos = value; 8252 8253 while (pos) { 8254 if (*pos == ' ' || *pos == '\0') 8255 break; 8256 if (*scan_id_count == MAX_SCAN_ID) 8257 return -1; 8258 scan_id[(*scan_id_count)++] = atoi(pos); 8259 pos = os_strchr(pos, ','); 8260 if (pos) 8261 pos++; 8262 } 8263 8264 return 0; 8265 } 8266 8267 8268 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 8269 char *reply, int reply_size, int *reply_len) 8270 { 8271 char *pos; 8272 unsigned int manual_scan_passive = 0; 8273 unsigned int manual_scan_use_id = 0; 8274 unsigned int manual_scan_only_new = 0; 8275 unsigned int scan_only = 0; 8276 unsigned int scan_id_count = 0; 8277 int scan_id[MAX_SCAN_ID]; 8278 void (*scan_res_handler)(struct wpa_supplicant *wpa_s, 8279 struct wpa_scan_results *scan_res); 8280 int *manual_scan_freqs = NULL; 8281 struct wpa_ssid_value *ssid = NULL, *ns; 8282 unsigned int ssid_count = 0; 8283 8284 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 8285 *reply_len = -1; 8286 return; 8287 } 8288 8289 if (radio_work_pending(wpa_s, "scan")) { 8290 wpa_printf(MSG_DEBUG, 8291 "Pending scan scheduled - reject new request"); 8292 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8293 return; 8294 } 8295 8296 #ifdef CONFIG_INTERWORKING 8297 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) { 8298 wpa_printf(MSG_DEBUG, 8299 "Interworking select in progress - reject new scan"); 8300 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8301 return; 8302 } 8303 #endif /* CONFIG_INTERWORKING */ 8304 8305 if (params) { 8306 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0) 8307 scan_only = 1; 8308 8309 pos = os_strstr(params, "freq="); 8310 if (pos) { 8311 manual_scan_freqs = freq_range_to_channel_list(wpa_s, 8312 pos + 5); 8313 if (manual_scan_freqs == NULL) { 8314 *reply_len = -1; 8315 goto done; 8316 } 8317 } 8318 8319 pos = os_strstr(params, "passive="); 8320 if (pos) 8321 manual_scan_passive = !!atoi(pos + 8); 8322 8323 pos = os_strstr(params, "use_id="); 8324 if (pos) 8325 manual_scan_use_id = atoi(pos + 7); 8326 8327 pos = os_strstr(params, "only_new=1"); 8328 if (pos) 8329 manual_scan_only_new = 1; 8330 8331 pos = os_strstr(params, "scan_id="); 8332 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count, 8333 scan_id) < 0) { 8334 *reply_len = -1; 8335 goto done; 8336 } 8337 8338 pos = os_strstr(params, "bssid="); 8339 if (pos) { 8340 u8 bssid[ETH_ALEN]; 8341 8342 pos += 6; 8343 if (hwaddr_aton(pos, bssid)) { 8344 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos); 8345 *reply_len = -1; 8346 goto done; 8347 } 8348 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); 8349 } 8350 8351 pos = params; 8352 while (pos && *pos != '\0') { 8353 if (os_strncmp(pos, "ssid ", 5) == 0) { 8354 char *end; 8355 8356 pos += 5; 8357 end = pos; 8358 while (*end) { 8359 if (*end == '\0' || *end == ' ') 8360 break; 8361 end++; 8362 } 8363 8364 ns = os_realloc_array( 8365 ssid, ssid_count + 1, 8366 sizeof(struct wpa_ssid_value)); 8367 if (ns == NULL) { 8368 *reply_len = -1; 8369 goto done; 8370 } 8371 ssid = ns; 8372 8373 if ((end - pos) & 0x01 || 8374 end - pos > 2 * SSID_MAX_LEN || 8375 hexstr2bin(pos, ssid[ssid_count].ssid, 8376 (end - pos) / 2) < 0) { 8377 wpa_printf(MSG_DEBUG, 8378 "Invalid SSID value '%s'", 8379 pos); 8380 *reply_len = -1; 8381 goto done; 8382 } 8383 ssid[ssid_count].ssid_len = (end - pos) / 2; 8384 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", 8385 ssid[ssid_count].ssid, 8386 ssid[ssid_count].ssid_len); 8387 ssid_count++; 8388 pos = end; 8389 } 8390 8391 pos = os_strchr(pos, ' '); 8392 if (pos) 8393 pos++; 8394 } 8395 } 8396 8397 wpa_s->num_ssids_from_scan_req = ssid_count; 8398 os_free(wpa_s->ssids_from_scan_req); 8399 if (ssid_count) { 8400 wpa_s->ssids_from_scan_req = ssid; 8401 ssid = NULL; 8402 } else { 8403 wpa_s->ssids_from_scan_req = NULL; 8404 } 8405 8406 if (scan_only) 8407 scan_res_handler = scan_only_handler; 8408 else if (wpa_s->scan_res_handler == scan_only_handler) 8409 scan_res_handler = NULL; 8410 else 8411 scan_res_handler = wpa_s->scan_res_handler; 8412 8413 if (!wpa_s->sched_scanning && !wpa_s->scanning && 8414 ((wpa_s->wpa_state <= WPA_SCANNING) || 8415 (wpa_s->wpa_state == WPA_COMPLETED))) { 8416 wpa_s->manual_scan_passive = manual_scan_passive; 8417 wpa_s->manual_scan_use_id = manual_scan_use_id; 8418 wpa_s->manual_scan_only_new = manual_scan_only_new; 8419 wpa_s->scan_id_count = scan_id_count; 8420 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 8421 wpa_s->scan_res_handler = scan_res_handler; 8422 os_free(wpa_s->manual_scan_freqs); 8423 wpa_s->manual_scan_freqs = manual_scan_freqs; 8424 manual_scan_freqs = NULL; 8425 8426 wpa_s->normal_scans = 0; 8427 wpa_s->scan_req = MANUAL_SCAN_REQ; 8428 wpa_s->after_wps = 0; 8429 wpa_s->known_wps_freq = 0; 8430 wpa_supplicant_req_scan(wpa_s, 0, 0); 8431 if (wpa_s->manual_scan_use_id) { 8432 wpa_s->manual_scan_id++; 8433 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 8434 wpa_s->manual_scan_id); 8435 *reply_len = os_snprintf(reply, reply_size, "%u\n", 8436 wpa_s->manual_scan_id); 8437 } 8438 } else if (wpa_s->sched_scanning) { 8439 wpa_s->manual_scan_passive = manual_scan_passive; 8440 wpa_s->manual_scan_use_id = manual_scan_use_id; 8441 wpa_s->manual_scan_only_new = manual_scan_only_new; 8442 wpa_s->scan_id_count = scan_id_count; 8443 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 8444 wpa_s->scan_res_handler = scan_res_handler; 8445 os_free(wpa_s->manual_scan_freqs); 8446 wpa_s->manual_scan_freqs = manual_scan_freqs; 8447 manual_scan_freqs = NULL; 8448 8449 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed"); 8450 wpa_supplicant_cancel_sched_scan(wpa_s); 8451 wpa_s->scan_req = MANUAL_SCAN_REQ; 8452 wpa_supplicant_req_scan(wpa_s, 0, 0); 8453 if (wpa_s->manual_scan_use_id) { 8454 wpa_s->manual_scan_id++; 8455 *reply_len = os_snprintf(reply, reply_size, "%u\n", 8456 wpa_s->manual_scan_id); 8457 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 8458 wpa_s->manual_scan_id); 8459 } 8460 } else { 8461 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request"); 8462 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8463 } 8464 8465 done: 8466 os_free(manual_scan_freqs); 8467 os_free(ssid); 8468 } 8469 8470 8471 #ifdef CONFIG_TESTING_OPTIONS 8472 8473 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s, 8474 unsigned int freq, const u8 *dst, 8475 const u8 *src, const u8 *bssid, 8476 const u8 *data, size_t data_len, 8477 enum offchannel_send_action_result 8478 result) 8479 { 8480 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR 8481 " src=" MACSTR " bssid=" MACSTR " result=%s", 8482 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), 8483 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? 8484 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? 8485 "NO_ACK" : "FAILED")); 8486 } 8487 8488 8489 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd) 8490 { 8491 char *pos, *param; 8492 size_t len; 8493 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN]; 8494 int res, used; 8495 int freq = 0, no_cck = 0, wait_time = 0; 8496 8497 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1] 8498 * <action=Action frame payload> */ 8499 8500 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 8501 8502 pos = cmd; 8503 used = hwaddr_aton2(pos, da); 8504 if (used < 0) 8505 return -1; 8506 pos += used; 8507 while (*pos == ' ') 8508 pos++; 8509 used = hwaddr_aton2(pos, bssid); 8510 if (used < 0) 8511 return -1; 8512 pos += used; 8513 8514 param = os_strstr(pos, " freq="); 8515 if (param) { 8516 param += 6; 8517 freq = atoi(param); 8518 } 8519 8520 param = os_strstr(pos, " no_cck="); 8521 if (param) { 8522 param += 8; 8523 no_cck = atoi(param); 8524 } 8525 8526 param = os_strstr(pos, " wait_time="); 8527 if (param) { 8528 param += 11; 8529 wait_time = atoi(param); 8530 } 8531 8532 param = os_strstr(pos, " action="); 8533 if (param == NULL) 8534 return -1; 8535 param += 8; 8536 8537 len = os_strlen(param); 8538 if (len & 1) 8539 return -1; 8540 len /= 2; 8541 8542 buf = os_malloc(len); 8543 if (buf == NULL) 8544 return -1; 8545 8546 if (hexstr2bin(param, buf, len) < 0) { 8547 os_free(buf); 8548 return -1; 8549 } 8550 8551 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid, 8552 buf, len, wait_time, 8553 wpas_ctrl_iface_mgmt_tx_cb, no_cck); 8554 os_free(buf); 8555 return res; 8556 } 8557 8558 8559 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s) 8560 { 8561 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting"); 8562 offchannel_send_action_done(wpa_s); 8563 } 8564 8565 8566 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s, 8567 char *cmd) 8568 { 8569 char *pos, *param; 8570 size_t len; 8571 u8 *buf; 8572 int freq = 0, datarate = 0, ssi_signal = 0; 8573 union wpa_event_data event; 8574 8575 if (!wpa_s->ext_mgmt_frame_handling) 8576 return -1; 8577 8578 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 8579 8580 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 8581 8582 pos = cmd; 8583 param = os_strstr(pos, "freq="); 8584 if (param) { 8585 param += 5; 8586 freq = atoi(param); 8587 } 8588 8589 param = os_strstr(pos, " datarate="); 8590 if (param) { 8591 param += 10; 8592 datarate = atoi(param); 8593 } 8594 8595 param = os_strstr(pos, " ssi_signal="); 8596 if (param) { 8597 param += 12; 8598 ssi_signal = atoi(param); 8599 } 8600 8601 param = os_strstr(pos, " frame="); 8602 if (param == NULL) 8603 return -1; 8604 param += 7; 8605 8606 len = os_strlen(param); 8607 if (len & 1) 8608 return -1; 8609 len /= 2; 8610 8611 buf = os_malloc(len); 8612 if (buf == NULL) 8613 return -1; 8614 8615 if (hexstr2bin(param, buf, len) < 0) { 8616 os_free(buf); 8617 return -1; 8618 } 8619 8620 os_memset(&event, 0, sizeof(event)); 8621 event.rx_mgmt.freq = freq; 8622 event.rx_mgmt.frame = buf; 8623 event.rx_mgmt.frame_len = len; 8624 event.rx_mgmt.ssi_signal = ssi_signal; 8625 event.rx_mgmt.datarate = datarate; 8626 wpa_s->ext_mgmt_frame_handling = 0; 8627 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event); 8628 wpa_s->ext_mgmt_frame_handling = 1; 8629 8630 os_free(buf); 8631 8632 return 0; 8633 } 8634 8635 8636 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s, 8637 char *param) 8638 { 8639 struct wpa_scan_res *res; 8640 struct os_reltime now; 8641 char *pos, *end; 8642 int ret = -1; 8643 8644 if (!param) 8645 return -1; 8646 8647 if (os_strcmp(param, "START") == 0) { 8648 wpa_bss_update_start(wpa_s); 8649 return 0; 8650 } 8651 8652 if (os_strcmp(param, "END") == 0) { 8653 wpa_bss_update_end(wpa_s, NULL, 1); 8654 return 0; 8655 } 8656 8657 if (os_strncmp(param, "BSS ", 4) != 0) 8658 return -1; 8659 param += 3; 8660 8661 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2); 8662 if (!res) 8663 return -1; 8664 8665 pos = os_strstr(param, " flags="); 8666 if (pos) 8667 res->flags = strtol(pos + 7, NULL, 16); 8668 8669 pos = os_strstr(param, " bssid="); 8670 if (pos && hwaddr_aton(pos + 7, res->bssid)) 8671 goto fail; 8672 8673 pos = os_strstr(param, " freq="); 8674 if (pos) 8675 res->freq = atoi(pos + 6); 8676 8677 pos = os_strstr(param, " beacon_int="); 8678 if (pos) 8679 res->beacon_int = atoi(pos + 12); 8680 8681 pos = os_strstr(param, " caps="); 8682 if (pos) 8683 res->caps = strtol(pos + 6, NULL, 16); 8684 8685 pos = os_strstr(param, " qual="); 8686 if (pos) 8687 res->qual = atoi(pos + 6); 8688 8689 pos = os_strstr(param, " noise="); 8690 if (pos) 8691 res->noise = atoi(pos + 7); 8692 8693 pos = os_strstr(param, " level="); 8694 if (pos) 8695 res->level = atoi(pos + 7); 8696 8697 pos = os_strstr(param, " tsf="); 8698 if (pos) 8699 res->tsf = strtoll(pos + 5, NULL, 16); 8700 8701 pos = os_strstr(param, " age="); 8702 if (pos) 8703 res->age = atoi(pos + 5); 8704 8705 pos = os_strstr(param, " est_throughput="); 8706 if (pos) 8707 res->est_throughput = atoi(pos + 16); 8708 8709 pos = os_strstr(param, " snr="); 8710 if (pos) 8711 res->snr = atoi(pos + 5); 8712 8713 pos = os_strstr(param, " parent_tsf="); 8714 if (pos) 8715 res->parent_tsf = strtoll(pos + 7, NULL, 16); 8716 8717 pos = os_strstr(param, " tsf_bssid="); 8718 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid)) 8719 goto fail; 8720 8721 pos = os_strstr(param, " ie="); 8722 if (pos) { 8723 pos += 4; 8724 end = os_strchr(pos, ' '); 8725 if (!end) 8726 end = pos + os_strlen(pos); 8727 res->ie_len = (end - pos) / 2; 8728 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len)) 8729 goto fail; 8730 } 8731 8732 pos = os_strstr(param, " beacon_ie="); 8733 if (pos) { 8734 pos += 11; 8735 end = os_strchr(pos, ' '); 8736 if (!end) 8737 end = pos + os_strlen(pos); 8738 res->beacon_ie_len = (end - pos) / 2; 8739 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len, 8740 res->beacon_ie_len)) 8741 goto fail; 8742 } 8743 8744 os_get_reltime(&now); 8745 wpa_bss_update_scan_res(wpa_s, res, &now); 8746 ret = 0; 8747 fail: 8748 os_free(res); 8749 8750 return ret; 8751 } 8752 8753 8754 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) 8755 { 8756 char *pos, *param; 8757 union wpa_event_data event; 8758 enum wpa_event_type ev; 8759 8760 /* <event name> [parameters..] */ 8761 8762 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd); 8763 8764 pos = cmd; 8765 param = os_strchr(pos, ' '); 8766 if (param) 8767 *param++ = '\0'; 8768 8769 os_memset(&event, 0, sizeof(event)); 8770 8771 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) { 8772 ev = EVENT_INTERFACE_ENABLED; 8773 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) { 8774 ev = EVENT_INTERFACE_DISABLED; 8775 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) { 8776 ev = EVENT_AVOID_FREQUENCIES; 8777 if (param == NULL) 8778 param = ""; 8779 if (freq_range_list_parse(&event.freq_range, param) < 0) 8780 return -1; 8781 wpa_supplicant_event(wpa_s, ev, &event); 8782 os_free(event.freq_range.range); 8783 return 0; 8784 } else if (os_strcmp(cmd, "SCAN_RES") == 0) { 8785 return wpas_ctrl_iface_driver_scan_res(wpa_s, param); 8786 } else { 8787 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", 8788 cmd); 8789 return -1; 8790 } 8791 8792 wpa_supplicant_event(wpa_s, ev, &event); 8793 8794 return 0; 8795 } 8796 8797 8798 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd) 8799 { 8800 char *pos; 8801 u8 src[ETH_ALEN], *buf; 8802 int used; 8803 size_t len; 8804 8805 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 8806 8807 pos = cmd; 8808 used = hwaddr_aton2(pos, src); 8809 if (used < 0) 8810 return -1; 8811 pos += used; 8812 while (*pos == ' ') 8813 pos++; 8814 8815 len = os_strlen(pos); 8816 if (len & 1) 8817 return -1; 8818 len /= 2; 8819 8820 buf = os_malloc(len); 8821 if (buf == NULL) 8822 return -1; 8823 8824 if (hexstr2bin(pos, buf, len) < 0) { 8825 os_free(buf); 8826 return -1; 8827 } 8828 8829 wpa_supplicant_rx_eapol(wpa_s, src, buf, len); 8830 os_free(buf); 8831 8832 return 0; 8833 } 8834 8835 8836 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 8837 { 8838 size_t i; 8839 u32 sum = 0; 8840 const u16 *pos = buf; 8841 8842 for (i = 0; i < len / 2; i++) 8843 sum += *pos++; 8844 8845 while (sum >> 16) 8846 sum = (sum & 0xffff) + (sum >> 16); 8847 8848 return sum ^ 0xffff; 8849 } 8850 8851 8852 #define HWSIM_PACKETLEN 1500 8853 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 8854 8855 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 8856 size_t len) 8857 { 8858 struct wpa_supplicant *wpa_s = ctx; 8859 const struct ether_header *eth; 8860 struct iphdr ip; 8861 const u8 *pos; 8862 unsigned int i; 8863 char extra[30]; 8864 8865 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 8866 wpa_printf(MSG_DEBUG, 8867 "test data: RX - ignore unexpected length %d", 8868 (int) len); 8869 return; 8870 } 8871 8872 eth = (const struct ether_header *) buf; 8873 os_memcpy(&ip, eth + 1, sizeof(ip)); 8874 pos = &buf[sizeof(*eth) + sizeof(ip)]; 8875 8876 if (ip.ihl != 5 || ip.version != 4 || 8877 ntohs(ip.tot_len) > HWSIM_IP_LEN) { 8878 wpa_printf(MSG_DEBUG, 8879 "test data: RX - ignore unexpect IP header"); 8880 return; 8881 } 8882 8883 for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) { 8884 if (*pos != (u8) i) { 8885 wpa_printf(MSG_DEBUG, 8886 "test data: RX - ignore mismatching payload"); 8887 return; 8888 } 8889 pos++; 8890 } 8891 extra[0] = '\0'; 8892 if (ntohs(ip.tot_len) != HWSIM_IP_LEN) 8893 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len)); 8894 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 8895 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 8896 } 8897 8898 8899 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s, 8900 char *cmd) 8901 { 8902 int enabled = atoi(cmd); 8903 char *pos; 8904 const char *ifname; 8905 8906 if (!enabled) { 8907 if (wpa_s->l2_test) { 8908 l2_packet_deinit(wpa_s->l2_test); 8909 wpa_s->l2_test = NULL; 8910 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled"); 8911 } 8912 return 0; 8913 } 8914 8915 if (wpa_s->l2_test) 8916 return 0; 8917 8918 pos = os_strstr(cmd, " ifname="); 8919 if (pos) 8920 ifname = pos + 8; 8921 else 8922 ifname = wpa_s->ifname; 8923 8924 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr, 8925 ETHERTYPE_IP, wpas_data_test_rx, 8926 wpa_s, 1); 8927 if (wpa_s->l2_test == NULL) 8928 return -1; 8929 8930 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled"); 8931 8932 return 0; 8933 } 8934 8935 8936 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) 8937 { 8938 u8 dst[ETH_ALEN], src[ETH_ALEN]; 8939 char *pos, *pos2; 8940 int used; 8941 long int val; 8942 u8 tos; 8943 u8 buf[2 + HWSIM_PACKETLEN]; 8944 struct ether_header *eth; 8945 struct iphdr *ip; 8946 u8 *dpos; 8947 unsigned int i; 8948 size_t send_len = HWSIM_IP_LEN; 8949 8950 if (wpa_s->l2_test == NULL) 8951 return -1; 8952 8953 /* format: <dst> <src> <tos> [len=<length>] */ 8954 8955 pos = cmd; 8956 used = hwaddr_aton2(pos, dst); 8957 if (used < 0) 8958 return -1; 8959 pos += used; 8960 while (*pos == ' ') 8961 pos++; 8962 used = hwaddr_aton2(pos, src); 8963 if (used < 0) 8964 return -1; 8965 pos += used; 8966 8967 val = strtol(pos, &pos2, 0); 8968 if (val < 0 || val > 0xff) 8969 return -1; 8970 tos = val; 8971 8972 pos = os_strstr(pos2, " len="); 8973 if (pos) { 8974 i = atoi(pos + 5); 8975 if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 8976 return -1; 8977 send_len = i; 8978 } 8979 8980 eth = (struct ether_header *) &buf[2]; 8981 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 8982 os_memcpy(eth->ether_shost, src, ETH_ALEN); 8983 eth->ether_type = htons(ETHERTYPE_IP); 8984 ip = (struct iphdr *) (eth + 1); 8985 os_memset(ip, 0, sizeof(*ip)); 8986 ip->ihl = 5; 8987 ip->version = 4; 8988 ip->ttl = 64; 8989 ip->tos = tos; 8990 ip->tot_len = htons(send_len); 8991 ip->protocol = 1; 8992 ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 8993 ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 8994 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 8995 dpos = (u8 *) (ip + 1); 8996 for (i = 0; i < send_len - sizeof(*ip); i++) 8997 *dpos++ = i; 8998 8999 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2], 9000 sizeof(struct ether_header) + send_len) < 0) 9001 return -1; 9002 9003 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR 9004 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 9005 9006 return 0; 9007 } 9008 9009 9010 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s, 9011 char *cmd) 9012 { 9013 u8 *buf; 9014 struct ether_header *eth; 9015 struct l2_packet_data *l2 = NULL; 9016 size_t len; 9017 u16 ethertype; 9018 int res = -1; 9019 9020 len = os_strlen(cmd); 9021 if (len & 1 || len < ETH_HLEN * 2) 9022 return -1; 9023 len /= 2; 9024 9025 buf = os_malloc(len); 9026 if (buf == NULL) 9027 return -1; 9028 9029 if (hexstr2bin(cmd, buf, len) < 0) 9030 goto done; 9031 9032 eth = (struct ether_header *) buf; 9033 ethertype = ntohs(eth->ether_type); 9034 9035 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype, 9036 wpas_data_test_rx, wpa_s, 1); 9037 if (l2 == NULL) 9038 goto done; 9039 9040 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 9041 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res); 9042 done: 9043 if (l2) 9044 l2_packet_deinit(l2); 9045 os_free(buf); 9046 9047 return res < 0 ? -1 : 0; 9048 } 9049 9050 9051 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd) 9052 { 9053 #ifdef WPA_TRACE_BFD 9054 char *pos; 9055 9056 wpa_trace_fail_after = atoi(cmd); 9057 pos = os_strchr(cmd, ':'); 9058 if (pos) { 9059 pos++; 9060 os_strlcpy(wpa_trace_fail_func, pos, 9061 sizeof(wpa_trace_fail_func)); 9062 } else { 9063 wpa_trace_fail_after = 0; 9064 } 9065 return 0; 9066 #else /* WPA_TRACE_BFD */ 9067 return -1; 9068 #endif /* WPA_TRACE_BFD */ 9069 } 9070 9071 9072 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s, 9073 char *buf, size_t buflen) 9074 { 9075 #ifdef WPA_TRACE_BFD 9076 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after, 9077 wpa_trace_fail_func); 9078 #else /* WPA_TRACE_BFD */ 9079 return -1; 9080 #endif /* WPA_TRACE_BFD */ 9081 } 9082 9083 9084 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd) 9085 { 9086 #ifdef WPA_TRACE_BFD 9087 char *pos; 9088 9089 wpa_trace_test_fail_after = atoi(cmd); 9090 pos = os_strchr(cmd, ':'); 9091 if (pos) { 9092 pos++; 9093 os_strlcpy(wpa_trace_test_fail_func, pos, 9094 sizeof(wpa_trace_test_fail_func)); 9095 } else { 9096 wpa_trace_test_fail_after = 0; 9097 } 9098 return 0; 9099 #else /* WPA_TRACE_BFD */ 9100 return -1; 9101 #endif /* WPA_TRACE_BFD */ 9102 } 9103 9104 9105 static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s, 9106 char *buf, size_t buflen) 9107 { 9108 #ifdef WPA_TRACE_BFD 9109 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after, 9110 wpa_trace_test_fail_func); 9111 #else /* WPA_TRACE_BFD */ 9112 return -1; 9113 #endif /* WPA_TRACE_BFD */ 9114 } 9115 9116 9117 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx) 9118 { 9119 struct wpa_supplicant *wpa_s = eloop_ctx; 9120 int i, count = (intptr_t) timeout_ctx; 9121 9122 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages", 9123 count); 9124 for (i = 0; i < count; i++) { 9125 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d", 9126 i + 1, count); 9127 } 9128 } 9129 9130 9131 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd) 9132 { 9133 int count; 9134 9135 count = atoi(cmd); 9136 if (count <= 0) 9137 return -1; 9138 9139 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s, 9140 (void *) (intptr_t) count); 9141 } 9142 9143 9144 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s, 9145 const char *cmd) 9146 { 9147 struct wpabuf *buf; 9148 size_t len; 9149 9150 len = os_strlen(cmd); 9151 if (len & 1) 9152 return -1; 9153 len /= 2; 9154 9155 if (len == 0) { 9156 buf = NULL; 9157 } else { 9158 buf = wpabuf_alloc(len); 9159 if (buf == NULL) 9160 return -1; 9161 9162 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 9163 wpabuf_free(buf); 9164 return -1; 9165 } 9166 } 9167 9168 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf); 9169 return 0; 9170 } 9171 9172 9173 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s) 9174 { 9175 u8 zero[WPA_TK_MAX_LEN]; 9176 9177 if (wpa_s->last_tk_alg == WPA_ALG_NONE) 9178 return -1; 9179 9180 wpa_printf(MSG_INFO, "TESTING: Reset PN"); 9181 os_memset(zero, 0, sizeof(zero)); 9182 9183 /* First, use a zero key to avoid any possible duplicate key avoidance 9184 * in the driver. */ 9185 if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 9186 wpa_s->last_tk_key_idx, 1, zero, 6, 9187 zero, wpa_s->last_tk_len) < 0) 9188 return -1; 9189 9190 /* Set the previously configured key to reset its TSC/RSC */ 9191 return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 9192 wpa_s->last_tk_key_idx, 1, zero, 6, 9193 wpa_s->last_tk, wpa_s->last_tk_len); 9194 } 9195 9196 9197 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) 9198 { 9199 const char *pos = cmd; 9200 int error, pairwise; 9201 9202 error = atoi(pos); 9203 pos = os_strchr(pos, ' '); 9204 if (!pos) 9205 return -1; 9206 pairwise = atoi(pos); 9207 wpa_sm_key_request(wpa_s->wpa, error, pairwise); 9208 return 0; 9209 } 9210 9211 9212 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) 9213 { 9214 #ifdef CONFIG_SME 9215 struct wpa_driver_associate_params params; 9216 int ret; 9217 9218 os_memset(¶ms, 0, sizeof(params)); 9219 params.bssid = wpa_s->bssid; 9220 params.ssid = wpa_s->sme.ssid; 9221 params.ssid_len = wpa_s->sme.ssid_len; 9222 params.freq.freq = wpa_s->sme.freq; 9223 if (wpa_s->last_assoc_req_wpa_ie) { 9224 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); 9225 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); 9226 } 9227 params.pairwise_suite = wpa_s->pairwise_cipher; 9228 params.group_suite = wpa_s->group_cipher; 9229 params.mgmt_group_suite = wpa_s->mgmt_group_cipher; 9230 params.key_mgmt_suite = wpa_s->key_mgmt; 9231 params.wpa_proto = wpa_s->wpa_proto; 9232 params.mgmt_frame_protection = wpa_s->sme.mfp; 9233 params.rrm_used = wpa_s->rrm.rrm_used; 9234 if (wpa_s->sme.prev_bssid_set) 9235 params.prev_bssid = wpa_s->sme.prev_bssid; 9236 wpa_printf(MSG_INFO, "TESTING: Resend association request"); 9237 ret = wpa_drv_associate(wpa_s, ¶ms); 9238 wpa_s->testing_resend_assoc = 1; 9239 return ret; 9240 #else /* CONFIG_SME */ 9241 return -1; 9242 #endif /* CONFIG_SME */ 9243 } 9244 9245 #endif /* CONFIG_TESTING_OPTIONS */ 9246 9247 9248 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd) 9249 { 9250 char *pos = cmd; 9251 int frame; 9252 size_t len; 9253 struct wpabuf *buf; 9254 struct ieee802_11_elems elems; 9255 9256 frame = atoi(pos); 9257 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9258 return -1; 9259 wpa_s = wpas_vendor_elem(wpa_s, frame); 9260 9261 pos = os_strchr(pos, ' '); 9262 if (pos == NULL) 9263 return -1; 9264 pos++; 9265 9266 len = os_strlen(pos); 9267 if (len == 0) 9268 return 0; 9269 if (len & 1) 9270 return -1; 9271 len /= 2; 9272 9273 buf = wpabuf_alloc(len); 9274 if (buf == NULL) 9275 return -1; 9276 9277 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 9278 wpabuf_free(buf); 9279 return -1; 9280 } 9281 9282 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) == 9283 ParseFailed) { 9284 wpabuf_free(buf); 9285 return -1; 9286 } 9287 9288 if (wpa_s->vendor_elem[frame] == NULL) { 9289 wpa_s->vendor_elem[frame] = buf; 9290 wpas_vendor_elem_update(wpa_s); 9291 return 0; 9292 } 9293 9294 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) { 9295 wpabuf_free(buf); 9296 return -1; 9297 } 9298 9299 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf); 9300 wpabuf_free(buf); 9301 wpas_vendor_elem_update(wpa_s); 9302 9303 return 0; 9304 } 9305 9306 9307 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd, 9308 char *buf, size_t buflen) 9309 { 9310 int frame = atoi(cmd); 9311 9312 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9313 return -1; 9314 wpa_s = wpas_vendor_elem(wpa_s, frame); 9315 9316 if (wpa_s->vendor_elem[frame] == NULL) 9317 return 0; 9318 9319 return wpa_snprintf_hex(buf, buflen, 9320 wpabuf_head_u8(wpa_s->vendor_elem[frame]), 9321 wpabuf_len(wpa_s->vendor_elem[frame])); 9322 } 9323 9324 9325 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd) 9326 { 9327 char *pos = cmd; 9328 int frame; 9329 size_t len; 9330 u8 *buf; 9331 struct ieee802_11_elems elems; 9332 int res; 9333 9334 frame = atoi(pos); 9335 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9336 return -1; 9337 wpa_s = wpas_vendor_elem(wpa_s, frame); 9338 9339 pos = os_strchr(pos, ' '); 9340 if (pos == NULL) 9341 return -1; 9342 pos++; 9343 9344 if (*pos == '*') { 9345 wpabuf_free(wpa_s->vendor_elem[frame]); 9346 wpa_s->vendor_elem[frame] = NULL; 9347 wpas_vendor_elem_update(wpa_s); 9348 return 0; 9349 } 9350 9351 if (wpa_s->vendor_elem[frame] == NULL) 9352 return -1; 9353 9354 len = os_strlen(pos); 9355 if (len == 0) 9356 return 0; 9357 if (len & 1) 9358 return -1; 9359 len /= 2; 9360 9361 buf = os_malloc(len); 9362 if (buf == NULL) 9363 return -1; 9364 9365 if (hexstr2bin(pos, buf, len) < 0) { 9366 os_free(buf); 9367 return -1; 9368 } 9369 9370 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) { 9371 os_free(buf); 9372 return -1; 9373 } 9374 9375 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len); 9376 os_free(buf); 9377 return res; 9378 } 9379 9380 9381 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep) 9382 { 9383 struct wpa_supplicant *wpa_s = ctx; 9384 size_t len; 9385 const u8 *data; 9386 9387 /* 9388 * Neighbor Report element (IEEE P802.11-REVmc/D5.0) 9389 * BSSID[6] 9390 * BSSID Information[4] 9391 * Operating Class[1] 9392 * Channel Number[1] 9393 * PHY Type[1] 9394 * Optional Subelements[variable] 9395 */ 9396 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) 9397 9398 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) { 9399 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED); 9400 goto out; 9401 } 9402 9403 data = wpabuf_head_u8(neighbor_rep); 9404 len = wpabuf_len(neighbor_rep); 9405 9406 while (len >= 2 + NR_IE_MIN_LEN) { 9407 const u8 *nr; 9408 char lci[256 * 2 + 1]; 9409 char civic[256 * 2 + 1]; 9410 u8 nr_len = data[1]; 9411 const u8 *pos = data, *end; 9412 9413 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || 9414 nr_len < NR_IE_MIN_LEN) { 9415 wpa_printf(MSG_DEBUG, 9416 "CTRL: Invalid Neighbor Report element: id=%u len=%u", 9417 data[0], nr_len); 9418 goto out; 9419 } 9420 9421 if (2U + nr_len > len) { 9422 wpa_printf(MSG_DEBUG, 9423 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", 9424 data[0], len, nr_len); 9425 goto out; 9426 } 9427 pos += 2; 9428 end = pos + nr_len; 9429 9430 nr = pos; 9431 pos += NR_IE_MIN_LEN; 9432 9433 lci[0] = '\0'; 9434 civic[0] = '\0'; 9435 while (end - pos > 2) { 9436 u8 s_id, s_len; 9437 9438 s_id = *pos++; 9439 s_len = *pos++; 9440 if (s_len > end - pos) 9441 goto out; 9442 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) { 9443 /* Measurement Token[1] */ 9444 /* Measurement Report Mode[1] */ 9445 /* Measurement Type[1] */ 9446 /* Measurement Report[variable] */ 9447 switch (pos[2]) { 9448 case MEASURE_TYPE_LCI: 9449 if (lci[0]) 9450 break; 9451 wpa_snprintf_hex(lci, sizeof(lci), 9452 pos, s_len); 9453 break; 9454 case MEASURE_TYPE_LOCATION_CIVIC: 9455 if (civic[0]) 9456 break; 9457 wpa_snprintf_hex(civic, sizeof(civic), 9458 pos, s_len); 9459 break; 9460 } 9461 } 9462 9463 pos += s_len; 9464 } 9465 9466 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED 9467 "bssid=" MACSTR 9468 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s", 9469 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), 9470 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], 9471 nr[ETH_ALEN + 6], 9472 lci[0] ? " lci=" : "", lci, 9473 civic[0] ? " civic=" : "", civic); 9474 9475 data = end; 9476 len -= 2 + nr_len; 9477 } 9478 9479 out: 9480 wpabuf_free(neighbor_rep); 9481 } 9482 9483 9484 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s, 9485 char *cmd) 9486 { 9487 struct wpa_ssid_value ssid, *ssid_p = NULL; 9488 int ret, lci = 0, civic = 0; 9489 char *ssid_s; 9490 9491 ssid_s = os_strstr(cmd, "ssid="); 9492 if (ssid_s) { 9493 if (ssid_parse(ssid_s + 5, &ssid)) { 9494 wpa_printf(MSG_ERROR, 9495 "CTRL: Send Neighbor Report: bad SSID"); 9496 return -1; 9497 } 9498 9499 ssid_p = &ssid; 9500 9501 /* 9502 * Move cmd after the SSID text that may include "lci" or 9503 * "civic". 9504 */ 9505 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' '); 9506 if (cmd) 9507 cmd++; 9508 9509 } 9510 9511 if (cmd && os_strstr(cmd, "lci")) 9512 lci = 1; 9513 9514 if (cmd && os_strstr(cmd, "civic")) 9515 civic = 1; 9516 9517 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, 9518 wpas_ctrl_neighbor_rep_cb, 9519 wpa_s); 9520 9521 return ret; 9522 } 9523 9524 9525 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s) 9526 { 9527 eapol_sm_erp_flush(wpa_s->eapol); 9528 return 0; 9529 } 9530 9531 9532 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, 9533 char *cmd) 9534 { 9535 char *token, *context = NULL; 9536 unsigned int enable = ~0, type = 0; 9537 u8 _addr[ETH_ALEN], _mask[ETH_ALEN]; 9538 u8 *addr = NULL, *mask = NULL; 9539 9540 while ((token = str_token(cmd, " ", &context))) { 9541 if (os_strcasecmp(token, "scan") == 0) { 9542 type |= MAC_ADDR_RAND_SCAN; 9543 } else if (os_strcasecmp(token, "sched") == 0) { 9544 type |= MAC_ADDR_RAND_SCHED_SCAN; 9545 } else if (os_strcasecmp(token, "pno") == 0) { 9546 type |= MAC_ADDR_RAND_PNO; 9547 } else if (os_strcasecmp(token, "all") == 0) { 9548 type = wpa_s->mac_addr_rand_supported; 9549 } else if (os_strncasecmp(token, "enable=", 7) == 0) { 9550 enable = atoi(token + 7); 9551 } else if (os_strncasecmp(token, "addr=", 5) == 0) { 9552 addr = _addr; 9553 if (hwaddr_aton(token + 5, addr)) { 9554 wpa_printf(MSG_INFO, 9555 "CTRL: Invalid MAC address: %s", 9556 token); 9557 return -1; 9558 } 9559 } else if (os_strncasecmp(token, "mask=", 5) == 0) { 9560 mask = _mask; 9561 if (hwaddr_aton(token + 5, mask)) { 9562 wpa_printf(MSG_INFO, 9563 "CTRL: Invalid MAC address mask: %s", 9564 token); 9565 return -1; 9566 } 9567 } else { 9568 wpa_printf(MSG_INFO, 9569 "CTRL: Invalid MAC_RAND_SCAN parameter: %s", 9570 token); 9571 return -1; 9572 } 9573 } 9574 9575 if (!type) { 9576 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified"); 9577 return -1; 9578 } 9579 9580 if (enable > 1) { 9581 wpa_printf(MSG_INFO, 9582 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified"); 9583 return -1; 9584 } 9585 9586 if (!enable) { 9587 wpas_mac_addr_rand_scan_clear(wpa_s, type); 9588 if (wpa_s->pno) { 9589 if (type & MAC_ADDR_RAND_PNO) { 9590 wpas_stop_pno(wpa_s); 9591 wpas_start_pno(wpa_s); 9592 } 9593 } else if (wpa_s->sched_scanning && 9594 (type & MAC_ADDR_RAND_SCHED_SCAN)) { 9595 wpas_scan_restart_sched_scan(wpa_s); 9596 } 9597 return 0; 9598 } 9599 9600 if ((addr && !mask) || (!addr && mask)) { 9601 wpa_printf(MSG_INFO, 9602 "CTRL: MAC_RAND_SCAN invalid addr/mask combination"); 9603 return -1; 9604 } 9605 9606 if (addr && mask && (!(mask[0] & 0x01) || (addr[0] & 0x01))) { 9607 wpa_printf(MSG_INFO, 9608 "CTRL: MAC_RAND_SCAN cannot allow multicast address"); 9609 return -1; 9610 } 9611 9612 if (type & MAC_ADDR_RAND_SCAN) { 9613 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN, 9614 addr, mask)) 9615 return -1; 9616 } 9617 9618 if (type & MAC_ADDR_RAND_SCHED_SCAN) { 9619 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN, 9620 addr, mask)) 9621 return -1; 9622 9623 if (wpa_s->sched_scanning && !wpa_s->pno) 9624 wpas_scan_restart_sched_scan(wpa_s); 9625 } 9626 9627 if (type & MAC_ADDR_RAND_PNO) { 9628 if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO, 9629 addr, mask)) 9630 return -1; 9631 9632 if (wpa_s->pno) { 9633 wpas_stop_pno(wpa_s); 9634 wpas_start_pno(wpa_s); 9635 } 9636 } 9637 9638 return 0; 9639 } 9640 9641 9642 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s, 9643 char *buf, size_t buflen) 9644 { 9645 size_t reply_len; 9646 9647 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen); 9648 #ifdef CONFIG_AP 9649 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len], 9650 buflen - reply_len); 9651 #endif /* CONFIG_AP */ 9652 return reply_len; 9653 } 9654 9655 9656 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) 9657 { 9658 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 9659 #ifdef CONFIG_AP 9660 wpas_ap_pmksa_cache_flush(wpa_s); 9661 #endif /* CONFIG_AP */ 9662 } 9663 9664 9665 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 9666 9667 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s, 9668 const char *cmd, char *buf, size_t buflen) 9669 { 9670 struct rsn_pmksa_cache_entry *entry; 9671 struct wpa_ssid *ssid; 9672 char *pos, *pos2, *end; 9673 int ret; 9674 struct os_reltime now; 9675 9676 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 9677 if (!ssid) 9678 return -1; 9679 9680 pos = buf; 9681 end = buf + buflen; 9682 9683 os_get_reltime(&now); 9684 9685 /* 9686 * Entry format: 9687 * <BSSID> <PMKID> <PMK> <reauth_time in seconds> 9688 * <expiration in seconds> <akmp> <opportunistic> 9689 * [FILS Cache Identifier] 9690 */ 9691 9692 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry; 9693 entry = entry->next) { 9694 if (entry->network_ctx != ssid) 9695 continue; 9696 9697 pos2 = pos; 9698 ret = os_snprintf(pos2, end - pos2, MACSTR " ", 9699 MAC2STR(entry->aa)); 9700 if (os_snprintf_error(end - pos2, ret)) 9701 break; 9702 pos2 += ret; 9703 9704 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid, 9705 PMKID_LEN); 9706 9707 ret = os_snprintf(pos2, end - pos2, " "); 9708 if (os_snprintf_error(end - pos2, ret)) 9709 break; 9710 pos2 += ret; 9711 9712 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk, 9713 entry->pmk_len); 9714 9715 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d", 9716 (int) (entry->reauth_time - now.sec), 9717 (int) (entry->expiration - now.sec), 9718 entry->akmp, 9719 entry->opportunistic); 9720 if (os_snprintf_error(end - pos2, ret)) 9721 break; 9722 pos2 += ret; 9723 9724 if (entry->fils_cache_id_set) { 9725 ret = os_snprintf(pos2, end - pos2, " %02x%02x", 9726 entry->fils_cache_id[0], 9727 entry->fils_cache_id[1]); 9728 if (os_snprintf_error(end - pos2, ret)) 9729 break; 9730 pos2 += ret; 9731 } 9732 9733 ret = os_snprintf(pos2, end - pos2, "\n"); 9734 if (os_snprintf_error(end - pos2, ret)) 9735 break; 9736 pos2 += ret; 9737 9738 pos = pos2; 9739 } 9740 9741 return pos - buf; 9742 } 9743 9744 9745 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s, 9746 char *cmd) 9747 { 9748 struct rsn_pmksa_cache_entry *entry; 9749 struct wpa_ssid *ssid; 9750 char *pos, *pos2; 9751 int ret = -1; 9752 struct os_reltime now; 9753 int reauth_time = 0, expiration = 0, i; 9754 9755 /* 9756 * Entry format: 9757 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> 9758 * <expiration in seconds> <akmp> <opportunistic> 9759 * [FILS Cache Identifier] 9760 */ 9761 9762 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 9763 if (!ssid) 9764 return -1; 9765 9766 pos = os_strchr(cmd, ' '); 9767 if (!pos) 9768 return -1; 9769 pos++; 9770 9771 entry = os_zalloc(sizeof(*entry)); 9772 if (!entry) 9773 return -1; 9774 9775 if (hwaddr_aton(pos, entry->aa)) 9776 goto fail; 9777 9778 pos = os_strchr(pos, ' '); 9779 if (!pos) 9780 goto fail; 9781 pos++; 9782 9783 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0) 9784 goto fail; 9785 9786 pos = os_strchr(pos, ' '); 9787 if (!pos) 9788 goto fail; 9789 pos++; 9790 9791 pos2 = os_strchr(pos, ' '); 9792 if (!pos2) 9793 goto fail; 9794 entry->pmk_len = (pos2 - pos) / 2; 9795 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX || 9796 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0) 9797 goto fail; 9798 9799 pos = os_strchr(pos, ' '); 9800 if (!pos) 9801 goto fail; 9802 pos++; 9803 9804 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration, 9805 &entry->akmp, &entry->opportunistic) != 4) 9806 goto fail; 9807 for (i = 0; i < 4; i++) { 9808 pos = os_strchr(pos, ' '); 9809 if (!pos) { 9810 if (i < 3) 9811 goto fail; 9812 break; 9813 } 9814 pos++; 9815 } 9816 if (pos) { 9817 if (hexstr2bin(pos, entry->fils_cache_id, 9818 FILS_CACHE_ID_LEN) < 0) 9819 goto fail; 9820 entry->fils_cache_id_set = 1; 9821 } 9822 os_get_reltime(&now); 9823 entry->expiration = now.sec + expiration; 9824 entry->reauth_time = now.sec + reauth_time; 9825 9826 entry->network_ctx = ssid; 9827 9828 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); 9829 entry = NULL; 9830 ret = 0; 9831 fail: 9832 os_free(entry); 9833 return ret; 9834 } 9835 9836 9837 #ifdef CONFIG_MESH 9838 9839 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, 9840 const char *cmd, char *buf, 9841 size_t buflen) 9842 { 9843 u8 spa[ETH_ALEN]; 9844 9845 if (!wpa_s->ifmsh) 9846 return -1; 9847 9848 if (os_strcasecmp(cmd, "any") == 0) 9849 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); 9850 9851 if (hwaddr_aton(cmd, spa)) 9852 return -1; 9853 9854 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); 9855 } 9856 9857 9858 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, 9859 char *cmd) 9860 { 9861 /* 9862 * We do not check mesh interface existance because PMKSA should be 9863 * stored before wpa_s->ifmsh creation to suppress commit message 9864 * creation. 9865 */ 9866 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); 9867 } 9868 9869 #endif /* CONFIG_MESH */ 9870 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 9871 9872 9873 #ifdef CONFIG_FILS 9874 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s, 9875 const char *cmd) 9876 { 9877 struct fils_hlp_req *req; 9878 const char *pos; 9879 9880 /* format: <dst> <packet starting from ethertype> */ 9881 9882 req = os_zalloc(sizeof(*req)); 9883 if (!req) 9884 return -1; 9885 9886 if (hwaddr_aton(cmd, req->dst)) 9887 goto fail; 9888 9889 pos = os_strchr(cmd, ' '); 9890 if (!pos) 9891 goto fail; 9892 pos++; 9893 req->pkt = wpabuf_parse_bin(pos); 9894 if (!req->pkt) 9895 goto fail; 9896 9897 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list); 9898 return 0; 9899 fail: 9900 wpabuf_free(req->pkt); 9901 os_free(req); 9902 return -1; 9903 } 9904 #endif /* CONFIG_FILS */ 9905 9906 9907 static int wpas_ctrl_cmd_debug_level(const char *cmd) 9908 { 9909 if (os_strcmp(cmd, "PING") == 0 || 9910 os_strncmp(cmd, "BSS ", 4) == 0 || 9911 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 || 9912 os_strncmp(cmd, "STATUS", 6) == 0 || 9913 os_strncmp(cmd, "STA ", 4) == 0 || 9914 os_strncmp(cmd, "STA-", 4) == 0) 9915 return MSG_EXCESSIVE; 9916 return MSG_DEBUG; 9917 } 9918 9919 9920 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 9921 char *buf, size_t *resp_len) 9922 { 9923 char *reply; 9924 const int reply_size = 4096; 9925 int reply_len; 9926 9927 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 9928 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 9929 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 || 9930 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 9931 if (wpa_debug_show_keys) 9932 wpa_dbg(wpa_s, MSG_DEBUG, 9933 "Control interface command '%s'", buf); 9934 else 9935 wpa_dbg(wpa_s, MSG_DEBUG, 9936 "Control interface command '%s [REMOVED]'", 9937 os_strncmp(buf, WPA_CTRL_RSP, 9938 os_strlen(WPA_CTRL_RSP)) == 0 ? 9939 WPA_CTRL_RSP : 9940 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ? 9941 "SET_NETWORK" : "key-add")); 9942 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 9943 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { 9944 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 9945 (const u8 *) buf, os_strlen(buf)); 9946 } else { 9947 int level = wpas_ctrl_cmd_debug_level(buf); 9948 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 9949 } 9950 9951 reply = os_malloc(reply_size); 9952 if (reply == NULL) { 9953 *resp_len = 1; 9954 return NULL; 9955 } 9956 9957 os_memcpy(reply, "OK\n", 3); 9958 reply_len = 3; 9959 9960 if (os_strcmp(buf, "PING") == 0) { 9961 os_memcpy(reply, "PONG\n", 5); 9962 reply_len = 5; 9963 } else if (os_strcmp(buf, "IFNAME") == 0) { 9964 reply_len = os_strlen(wpa_s->ifname); 9965 os_memcpy(reply, wpa_s->ifname, reply_len); 9966 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 9967 if (wpa_debug_reopen_file() < 0) 9968 reply_len = -1; 9969 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 9970 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 9971 } else if (os_strcmp(buf, "MIB") == 0) { 9972 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 9973 if (reply_len >= 0) { 9974 reply_len += eapol_sm_get_mib(wpa_s->eapol, 9975 reply + reply_len, 9976 reply_size - reply_len); 9977 #ifdef CONFIG_MACSEC 9978 reply_len += ieee802_1x_kay_get_mib( 9979 wpa_s->kay, reply + reply_len, 9980 reply_size - reply_len); 9981 #endif /* CONFIG_MACSEC */ 9982 } 9983 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 9984 reply_len = wpa_supplicant_ctrl_iface_status( 9985 wpa_s, buf + 6, reply, reply_size); 9986 } else if (os_strcmp(buf, "PMKSA") == 0) { 9987 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); 9988 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 9989 wpas_ctrl_iface_pmksa_flush(wpa_s); 9990 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 9991 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) { 9992 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10, 9993 reply, reply_size); 9994 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 9995 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) 9996 reply_len = -1; 9997 #ifdef CONFIG_MESH 9998 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { 9999 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, 10000 reply, reply_size); 10001 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 10002 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) 10003 reply_len = -1; 10004 #endif /* CONFIG_MESH */ 10005 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 10006 } else if (os_strncmp(buf, "SET ", 4) == 0) { 10007 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 10008 reply_len = -1; 10009 } else if (os_strncmp(buf, "DUMP", 4) == 0) { 10010 reply_len = wpa_config_dump_values(wpa_s->conf, 10011 reply, reply_size); 10012 } else if (os_strncmp(buf, "GET ", 4) == 0) { 10013 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 10014 reply, reply_size); 10015 } else if (os_strcmp(buf, "LOGON") == 0) { 10016 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 10017 } else if (os_strcmp(buf, "LOGOFF") == 0) { 10018 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 10019 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 10020 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 10021 reply_len = -1; 10022 else 10023 wpas_request_connection(wpa_s); 10024 } else if (os_strcmp(buf, "REATTACH") == 0) { 10025 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || 10026 !wpa_s->current_ssid) 10027 reply_len = -1; 10028 else { 10029 wpa_s->reattach = 1; 10030 wpas_request_connection(wpa_s); 10031 } 10032 } else if (os_strcmp(buf, "RECONNECT") == 0) { 10033 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 10034 reply_len = -1; 10035 else if (wpa_s->disconnected) 10036 wpas_request_connection(wpa_s); 10037 #ifdef IEEE8021X_EAPOL 10038 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 10039 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 10040 reply_len = -1; 10041 #endif /* IEEE8021X_EAPOL */ 10042 #ifdef CONFIG_IEEE80211R 10043 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 10044 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 10045 reply_len = -1; 10046 #endif /* CONFIG_IEEE80211R */ 10047 #ifdef CONFIG_WPS 10048 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 10049 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 10050 if (res == -2) { 10051 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10052 reply_len = 17; 10053 } else if (res) 10054 reply_len = -1; 10055 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 10056 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 10057 if (res == -2) { 10058 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10059 reply_len = 17; 10060 } else if (res) 10061 reply_len = -1; 10062 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 10063 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 10064 reply, 10065 reply_size); 10066 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 10067 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 10068 wpa_s, buf + 14, reply, reply_size); 10069 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 10070 if (wpas_wps_cancel(wpa_s)) 10071 reply_len = -1; 10072 #ifdef CONFIG_WPS_NFC 10073 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 10074 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 10075 reply_len = -1; 10076 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 10077 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 10078 reply_len = -1; 10079 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 10080 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( 10081 wpa_s, buf + 21, reply, reply_size); 10082 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 10083 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 10084 wpa_s, buf + 14, reply, reply_size); 10085 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 10086 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 10087 buf + 17)) 10088 reply_len = -1; 10089 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 10090 reply_len = wpas_ctrl_nfc_get_handover_req( 10091 wpa_s, buf + 21, reply, reply_size); 10092 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 10093 reply_len = wpas_ctrl_nfc_get_handover_sel( 10094 wpa_s, buf + 21, reply, reply_size); 10095 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 10096 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20)) 10097 reply_len = -1; 10098 #endif /* CONFIG_WPS_NFC */ 10099 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 10100 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 10101 reply_len = -1; 10102 #ifdef CONFIG_AP 10103 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 10104 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 10105 wpa_s, buf + 11, reply, reply_size); 10106 #endif /* CONFIG_AP */ 10107 #ifdef CONFIG_WPS_ER 10108 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 10109 if (wpas_wps_er_start(wpa_s, NULL)) 10110 reply_len = -1; 10111 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 10112 if (wpas_wps_er_start(wpa_s, buf + 13)) 10113 reply_len = -1; 10114 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 10115 wpas_wps_er_stop(wpa_s); 10116 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 10117 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 10118 reply_len = -1; 10119 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 10120 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 10121 if (ret == -2) { 10122 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10123 reply_len = 17; 10124 } else if (ret == -3) { 10125 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 10126 reply_len = 18; 10127 } else if (ret == -4) { 10128 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 10129 reply_len = 20; 10130 } else if (ret) 10131 reply_len = -1; 10132 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 10133 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 10134 reply_len = -1; 10135 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 10136 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 10137 buf + 18)) 10138 reply_len = -1; 10139 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 10140 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 10141 reply_len = -1; 10142 #ifdef CONFIG_WPS_NFC 10143 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 10144 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 10145 wpa_s, buf + 24, reply, reply_size); 10146 #endif /* CONFIG_WPS_NFC */ 10147 #endif /* CONFIG_WPS_ER */ 10148 #endif /* CONFIG_WPS */ 10149 #ifdef CONFIG_IBSS_RSN 10150 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 10151 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 10152 reply_len = -1; 10153 #endif /* CONFIG_IBSS_RSN */ 10154 #ifdef CONFIG_MESH 10155 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) { 10156 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 10157 wpa_s, buf + 19, reply, reply_size); 10158 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) { 10159 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 10160 wpa_s, "", reply, reply_size); 10161 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) { 10162 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15)) 10163 reply_len = -1; 10164 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) { 10165 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s, 10166 buf + 18)) 10167 reply_len = -1; 10168 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) { 10169 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17)) 10170 reply_len = -1; 10171 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) { 10172 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14)) 10173 reply_len = -1; 10174 #endif /* CONFIG_MESH */ 10175 #ifdef CONFIG_P2P 10176 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 10177 if (p2p_ctrl_find(wpa_s, buf + 8)) 10178 reply_len = -1; 10179 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 10180 if (p2p_ctrl_find(wpa_s, "")) 10181 reply_len = -1; 10182 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 10183 wpas_p2p_stop_find(wpa_s); 10184 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) { 10185 if (p2p_ctrl_asp_provision(wpa_s, buf + 18)) 10186 reply_len = -1; 10187 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) { 10188 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23)) 10189 reply_len = -1; 10190 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 10191 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 10192 reply_size); 10193 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 10194 if (p2p_ctrl_listen(wpa_s, buf + 11)) 10195 reply_len = -1; 10196 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 10197 if (p2p_ctrl_listen(wpa_s, "")) 10198 reply_len = -1; 10199 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 10200 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 10201 reply_len = -1; 10202 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 10203 if (p2p_ctrl_group_add(wpa_s, "")) 10204 reply_len = -1; 10205 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 10206 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 10207 reply_len = -1; 10208 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) { 10209 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply, 10210 reply_size); 10211 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 10212 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 10213 reply_len = -1; 10214 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 10215 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 10216 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 10217 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 10218 reply_size); 10219 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 10220 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 10221 reply_len = -1; 10222 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 10223 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 10224 reply_len = -1; 10225 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 10226 wpas_p2p_sd_service_update(wpa_s); 10227 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 10228 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 10229 reply_len = -1; 10230 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 10231 wpas_p2p_service_flush(wpa_s); 10232 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 10233 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 10234 reply_len = -1; 10235 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 10236 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 10237 reply_len = -1; 10238 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) { 10239 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0) 10240 reply_len = -1; 10241 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 10242 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 10243 reply_len = -1; 10244 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 10245 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 10246 reply_len = -1; 10247 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 10248 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 10249 reply_size); 10250 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 10251 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 10252 reply_len = -1; 10253 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 10254 p2p_ctrl_flush(wpa_s); 10255 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 10256 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 10257 reply_len = -1; 10258 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 10259 if (wpas_p2p_cancel(wpa_s)) 10260 reply_len = -1; 10261 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 10262 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 10263 reply_len = -1; 10264 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 10265 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 10266 reply_len = -1; 10267 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 10268 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 10269 reply_len = -1; 10270 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 10271 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 10272 reply_len = -1; 10273 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) { 10274 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0) 10275 reply_len = -1; 10276 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) { 10277 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13)) 10278 reply_len = -1; 10279 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) { 10280 if (wpas_p2p_lo_stop(wpa_s)) 10281 reply_len = -1; 10282 #endif /* CONFIG_P2P */ 10283 #ifdef CONFIG_WIFI_DISPLAY 10284 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 10285 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 10286 reply_len = -1; 10287 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 10288 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 10289 reply, reply_size); 10290 #endif /* CONFIG_WIFI_DISPLAY */ 10291 #ifdef CONFIG_INTERWORKING 10292 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 10293 if (interworking_fetch_anqp(wpa_s) < 0) 10294 reply_len = -1; 10295 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 10296 interworking_stop_fetch_anqp(wpa_s); 10297 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { 10298 if (ctrl_interworking_select(wpa_s, NULL) < 0) 10299 reply_len = -1; 10300 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { 10301 if (ctrl_interworking_select(wpa_s, buf + 20) < 0) 10302 reply_len = -1; 10303 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 10304 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0) 10305 reply_len = -1; 10306 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) { 10307 int id; 10308 10309 id = ctrl_interworking_connect(wpa_s, buf + 25, 1); 10310 if (id < 0) 10311 reply_len = -1; 10312 else { 10313 reply_len = os_snprintf(reply, reply_size, "%d\n", id); 10314 if (os_snprintf_error(reply_size, reply_len)) 10315 reply_len = -1; 10316 } 10317 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 10318 if (get_anqp(wpa_s, buf + 9) < 0) 10319 reply_len = -1; 10320 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 10321 if (gas_request(wpa_s, buf + 12) < 0) 10322 reply_len = -1; 10323 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 10324 reply_len = gas_response_get(wpa_s, buf + 17, reply, 10325 reply_size); 10326 #endif /* CONFIG_INTERWORKING */ 10327 #ifdef CONFIG_HS20 10328 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 10329 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 10330 reply_len = -1; 10331 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 10332 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 10333 reply_len = -1; 10334 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) { 10335 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0) 10336 reply_len = -1; 10337 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) { 10338 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0) 10339 reply_len = -1; 10340 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) { 10341 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size); 10342 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) { 10343 if (del_hs20_icon(wpa_s, buf + 14) < 0) 10344 reply_len = -1; 10345 } else if (os_strcmp(buf, "FETCH_OSU") == 0) { 10346 if (hs20_fetch_osu(wpa_s, 0) < 0) 10347 reply_len = -1; 10348 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) { 10349 if (hs20_fetch_osu(wpa_s, 1) < 0) 10350 reply_len = -1; 10351 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) { 10352 hs20_cancel_fetch_osu(wpa_s); 10353 #endif /* CONFIG_HS20 */ 10354 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 10355 { 10356 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 10357 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 10358 reply_len = -1; 10359 else { 10360 /* 10361 * Notify response from timeout to allow the control 10362 * interface response to be sent first. 10363 */ 10364 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response, 10365 wpa_s, NULL); 10366 } 10367 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 10368 if (wpa_supplicant_reload_configuration(wpa_s)) 10369 reply_len = -1; 10370 } else if (os_strcmp(buf, "TERMINATE") == 0) { 10371 wpa_supplicant_terminate_proc(wpa_s->global); 10372 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 10373 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 10374 reply_len = -1; 10375 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 10376 reply_len = wpa_supplicant_ctrl_iface_blacklist( 10377 wpa_s, buf + 9, reply, reply_size); 10378 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 10379 reply_len = wpa_supplicant_ctrl_iface_log_level( 10380 wpa_s, buf + 9, reply, reply_size); 10381 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) { 10382 reply_len = wpa_supplicant_ctrl_iface_list_networks( 10383 wpa_s, buf + 14, reply, reply_size); 10384 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 10385 reply_len = wpa_supplicant_ctrl_iface_list_networks( 10386 wpa_s, NULL, reply, reply_size); 10387 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 10388 wpas_request_disconnection(wpa_s); 10389 } else if (os_strcmp(buf, "SCAN") == 0) { 10390 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); 10391 } else if (os_strncmp(buf, "SCAN ", 5) == 0) { 10392 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len); 10393 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 10394 reply_len = wpa_supplicant_ctrl_iface_scan_results( 10395 wpa_s, reply, reply_size); 10396 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) { 10397 if (wpas_abort_ongoing_scan(wpa_s) < 0) 10398 reply_len = -1; 10399 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 10400 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 10401 reply_len = -1; 10402 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 10403 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 10404 reply_len = -1; 10405 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 10406 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 10407 reply_len = -1; 10408 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 10409 reply_len = wpa_supplicant_ctrl_iface_add_network( 10410 wpa_s, reply, reply_size); 10411 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 10412 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 10413 reply_len = -1; 10414 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 10415 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 10416 reply_len = -1; 10417 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 10418 reply_len = wpa_supplicant_ctrl_iface_get_network( 10419 wpa_s, buf + 12, reply, reply_size); 10420 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 10421 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12, 10422 wpa_s)) 10423 reply_len = -1; 10424 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 10425 reply_len = wpa_supplicant_ctrl_iface_list_creds( 10426 wpa_s, reply, reply_size); 10427 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 10428 reply_len = wpa_supplicant_ctrl_iface_add_cred( 10429 wpa_s, reply, reply_size); 10430 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 10431 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 10432 reply_len = -1; 10433 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 10434 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 10435 reply_len = -1; 10436 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) { 10437 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9, 10438 reply, 10439 reply_size); 10440 #ifndef CONFIG_NO_CONFIG_WRITE 10441 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 10442 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 10443 reply_len = -1; 10444 #endif /* CONFIG_NO_CONFIG_WRITE */ 10445 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 10446 reply_len = wpa_supplicant_ctrl_iface_get_capability( 10447 wpa_s, buf + 15, reply, reply_size); 10448 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 10449 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 10450 reply_len = -1; 10451 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 10452 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 10453 reply_len = -1; 10454 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 10455 reply_len = wpa_supplicant_global_iface_list( 10456 wpa_s->global, reply, reply_size); 10457 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 10458 reply_len = wpa_supplicant_global_iface_interfaces( 10459 wpa_s->global, buf + 10, reply, reply_size); 10460 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 10461 reply_len = wpa_supplicant_ctrl_iface_bss( 10462 wpa_s, buf + 4, reply, reply_size); 10463 #ifdef CONFIG_AP 10464 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 10465 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 10466 } else if (os_strncmp(buf, "STA ", 4) == 0) { 10467 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 10468 reply_size); 10469 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 10470 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 10471 reply_size); 10472 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 10473 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 10474 reply_len = -1; 10475 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 10476 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 10477 reply_len = -1; 10478 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 10479 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) 10480 reply_len = -1; 10481 } else if (os_strcmp(buf, "STOP_AP") == 0) { 10482 if (wpas_ap_stop_ap(wpa_s)) 10483 reply_len = -1; 10484 #endif /* CONFIG_AP */ 10485 } else if (os_strcmp(buf, "SUSPEND") == 0) { 10486 wpas_notify_suspend(wpa_s->global); 10487 } else if (os_strcmp(buf, "RESUME") == 0) { 10488 wpas_notify_resume(wpa_s->global); 10489 #ifdef CONFIG_TESTING_OPTIONS 10490 } else if (os_strcmp(buf, "DROP_SA") == 0) { 10491 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 10492 #endif /* CONFIG_TESTING_OPTIONS */ 10493 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 10494 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 10495 reply_len = -1; 10496 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 10497 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0; 10498 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 10499 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 10500 reply_len = -1; 10501 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 10502 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 10503 buf + 17)) 10504 reply_len = -1; 10505 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 10506 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10); 10507 #ifdef CONFIG_TDLS 10508 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 10509 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 10510 reply_len = -1; 10511 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 10512 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 10513 reply_len = -1; 10514 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 10515 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 10516 reply_len = -1; 10517 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) { 10518 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s, 10519 buf + 17)) 10520 reply_len = -1; 10521 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) { 10522 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s, 10523 buf + 24)) 10524 reply_len = -1; 10525 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) { 10526 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status( 10527 wpa_s, buf + 17, reply, reply_size); 10528 #endif /* CONFIG_TDLS */ 10529 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) { 10530 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size); 10531 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) { 10532 if (wmm_ac_ctrl_addts(wpa_s, buf + 13)) 10533 reply_len = -1; 10534 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) { 10535 if (wmm_ac_ctrl_delts(wpa_s, buf + 13)) 10536 reply_len = -1; 10537 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 10538 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 10539 reply_size); 10540 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) { 10541 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14)) 10542 reply_len = -1; 10543 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 10544 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 10545 reply_size); 10546 #ifdef CONFIG_AUTOSCAN 10547 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 10548 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 10549 reply_len = -1; 10550 #endif /* CONFIG_AUTOSCAN */ 10551 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 10552 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, 10553 reply_size); 10554 #ifdef ANDROID 10555 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 10556 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 10557 reply_size); 10558 #endif /* ANDROID */ 10559 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 10560 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply, 10561 reply_size); 10562 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 10563 pmksa_cache_clear_current(wpa_s->wpa); 10564 eapol_sm_request_reauth(wpa_s->eapol); 10565 #ifdef CONFIG_WNM 10566 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 10567 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 10568 reply_len = -1; 10569 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) { 10570 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14)) 10571 reply_len = -1; 10572 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) { 10573 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) 10574 reply_len = -1; 10575 #endif /* CONFIG_WNM */ 10576 } else if (os_strcmp(buf, "FLUSH") == 0) { 10577 wpa_supplicant_ctrl_iface_flush(wpa_s); 10578 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { 10579 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply, 10580 reply_size); 10581 #ifdef CONFIG_TESTING_OPTIONS 10582 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 10583 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0) 10584 reply_len = -1; 10585 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) { 10586 wpas_ctrl_iface_mgmt_tx_done(wpa_s); 10587 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 10588 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0) 10589 reply_len = -1; 10590 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) { 10591 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0) 10592 reply_len = -1; 10593 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 10594 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0) 10595 reply_len = -1; 10596 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 10597 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0) 10598 reply_len = -1; 10599 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 10600 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0) 10601 reply_len = -1; 10602 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 10603 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0) 10604 reply_len = -1; 10605 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 10606 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0) 10607 reply_len = -1; 10608 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 10609 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size); 10610 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 10611 if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0) 10612 reply_len = -1; 10613 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 10614 reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size); 10615 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) { 10616 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0) 10617 reply_len = -1; 10618 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) { 10619 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0) 10620 reply_len = -1; 10621 } else if (os_strcmp(buf, "RESET_PN") == 0) { 10622 if (wpas_ctrl_reset_pn(wpa_s) < 0) 10623 reply_len = -1; 10624 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { 10625 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) 10626 reply_len = -1; 10627 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { 10628 if (wpas_ctrl_resend_assoc(wpa_s) < 0) 10629 reply_len = -1; 10630 #ifdef CONFIG_IEEE80211W 10631 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) { 10632 sme_event_unprot_disconnect( 10633 wpa_s, wpa_s->bssid, NULL, 10634 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); 10635 #endif /* CONFIG_IEEE80211W */ 10636 #endif /* CONFIG_TESTING_OPTIONS */ 10637 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { 10638 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) 10639 reply_len = -1; 10640 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) { 10641 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply, 10642 reply_size); 10643 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) { 10644 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0) 10645 reply_len = -1; 10646 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) { 10647 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20)) 10648 reply_len = -1; 10649 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 10650 wpas_ctrl_iface_erp_flush(wpa_s); 10651 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) { 10652 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14)) 10653 reply_len = -1; 10654 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { 10655 reply_len = wpas_ctrl_iface_get_pref_freq_list( 10656 wpa_s, buf + 19, reply, reply_size); 10657 #ifdef CONFIG_FILS 10658 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) { 10659 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17)) 10660 reply_len = -1; 10661 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) { 10662 wpas_flush_fils_hlp_req(wpa_s); 10663 #endif /* CONFIG_FILS */ 10664 #ifdef CONFIG_DPP 10665 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 10666 int res; 10667 10668 res = wpas_dpp_qr_code(wpa_s, buf + 12); 10669 if (res < 0) { 10670 reply_len = -1; 10671 } else { 10672 reply_len = os_snprintf(reply, reply_size, "%d", res); 10673 if (os_snprintf_error(reply_size, reply_len)) 10674 reply_len = -1; 10675 } 10676 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 10677 int res; 10678 10679 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); 10680 if (res < 0) { 10681 reply_len = -1; 10682 } else { 10683 reply_len = os_snprintf(reply, reply_size, "%d", res); 10684 if (os_snprintf_error(reply_size, reply_len)) 10685 reply_len = -1; 10686 } 10687 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 10688 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0) 10689 reply_len = -1; 10690 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 10691 const char *uri; 10692 10693 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22)); 10694 if (!uri) { 10695 reply_len = -1; 10696 } else { 10697 reply_len = os_snprintf(reply, reply_size, "%s", uri); 10698 if (os_snprintf_error(reply_size, reply_len)) 10699 reply_len = -1; 10700 } 10701 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 10702 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), 10703 reply, reply_size); 10704 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 10705 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) 10706 reply_len = -1; 10707 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 10708 if (wpas_dpp_listen(wpa_s, buf + 11) < 0) 10709 reply_len = -1; 10710 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 10711 wpas_dpp_stop(wpa_s); 10712 wpas_dpp_listen_stop(wpa_s); 10713 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 10714 int res; 10715 10716 res = dpp_configurator_add(wpa_s->dpp, buf + 20); 10717 if (res < 0) { 10718 reply_len = -1; 10719 } else { 10720 reply_len = os_snprintf(reply, reply_size, "%d", res); 10721 if (os_snprintf_error(reply_size, reply_len)) 10722 reply_len = -1; 10723 } 10724 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 10725 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) 10726 reply_len = -1; 10727 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 10728 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) 10729 reply_len = -1; 10730 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 10731 reply_len = dpp_configurator_get_key_id(wpa_s->dpp, 10732 atoi(buf + 25), 10733 reply, reply_size); 10734 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 10735 int res; 10736 10737 res = wpas_dpp_pkex_add(wpa_s, buf + 12); 10738 if (res < 0) { 10739 reply_len = -1; 10740 } else { 10741 reply_len = os_snprintf(reply, reply_size, "%d", res); 10742 if (os_snprintf_error(reply_size, reply_len)) 10743 reply_len = -1; 10744 } 10745 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 10746 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) 10747 reply_len = -1; 10748 #endif /* CONFIG_DPP */ 10749 } else { 10750 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 10751 reply_len = 16; 10752 } 10753 10754 if (reply_len < 0) { 10755 os_memcpy(reply, "FAIL\n", 5); 10756 reply_len = 5; 10757 } 10758 10759 *resp_len = reply_len; 10760 return reply; 10761 } 10762 10763 10764 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 10765 char *cmd) 10766 { 10767 struct wpa_interface iface; 10768 char *pos, *extra; 10769 struct wpa_supplicant *wpa_s; 10770 unsigned int create_iface = 0; 10771 u8 mac_addr[ETH_ALEN]; 10772 enum wpa_driver_if_type type = WPA_IF_STATION; 10773 10774 /* 10775 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 10776 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]] 10777 */ 10778 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 10779 10780 os_memset(&iface, 0, sizeof(iface)); 10781 10782 do { 10783 iface.ifname = pos = cmd; 10784 pos = os_strchr(pos, '\t'); 10785 if (pos) 10786 *pos++ = '\0'; 10787 if (iface.ifname[0] == '\0') 10788 return -1; 10789 if (pos == NULL) 10790 break; 10791 10792 iface.confname = pos; 10793 pos = os_strchr(pos, '\t'); 10794 if (pos) 10795 *pos++ = '\0'; 10796 if (iface.confname[0] == '\0') 10797 iface.confname = NULL; 10798 if (pos == NULL) 10799 break; 10800 10801 iface.driver = pos; 10802 pos = os_strchr(pos, '\t'); 10803 if (pos) 10804 *pos++ = '\0'; 10805 if (iface.driver[0] == '\0') 10806 iface.driver = NULL; 10807 if (pos == NULL) 10808 break; 10809 10810 iface.ctrl_interface = pos; 10811 pos = os_strchr(pos, '\t'); 10812 if (pos) 10813 *pos++ = '\0'; 10814 if (iface.ctrl_interface[0] == '\0') 10815 iface.ctrl_interface = NULL; 10816 if (pos == NULL) 10817 break; 10818 10819 iface.driver_param = pos; 10820 pos = os_strchr(pos, '\t'); 10821 if (pos) 10822 *pos++ = '\0'; 10823 if (iface.driver_param[0] == '\0') 10824 iface.driver_param = NULL; 10825 if (pos == NULL) 10826 break; 10827 10828 iface.bridge_ifname = pos; 10829 pos = os_strchr(pos, '\t'); 10830 if (pos) 10831 *pos++ = '\0'; 10832 if (iface.bridge_ifname[0] == '\0') 10833 iface.bridge_ifname = NULL; 10834 if (pos == NULL) 10835 break; 10836 10837 extra = pos; 10838 pos = os_strchr(pos, '\t'); 10839 if (pos) 10840 *pos++ = '\0'; 10841 if (!extra[0]) 10842 break; 10843 10844 if (os_strcmp(extra, "create") == 0) { 10845 create_iface = 1; 10846 if (!pos) 10847 break; 10848 10849 if (os_strcmp(pos, "sta") == 0) { 10850 type = WPA_IF_STATION; 10851 } else if (os_strcmp(pos, "ap") == 0) { 10852 type = WPA_IF_AP_BSS; 10853 } else { 10854 wpa_printf(MSG_DEBUG, 10855 "INTERFACE_ADD unsupported interface type: '%s'", 10856 pos); 10857 return -1; 10858 } 10859 } else { 10860 wpa_printf(MSG_DEBUG, 10861 "INTERFACE_ADD unsupported extra parameter: '%s'", 10862 extra); 10863 return -1; 10864 } 10865 } while (0); 10866 10867 if (create_iface) { 10868 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'", 10869 iface.ifname); 10870 if (!global->ifaces) 10871 return -1; 10872 if (wpa_drv_if_add(global->ifaces, type, iface.ifname, 10873 NULL, NULL, NULL, mac_addr, NULL) < 0) { 10874 wpa_printf(MSG_ERROR, 10875 "CTRL_IFACE interface creation failed"); 10876 return -1; 10877 } 10878 10879 wpa_printf(MSG_DEBUG, 10880 "CTRL_IFACE interface '%s' created with MAC addr: " 10881 MACSTR, iface.ifname, MAC2STR(mac_addr)); 10882 } 10883 10884 if (wpa_supplicant_get_iface(global, iface.ifname)) 10885 goto fail; 10886 10887 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); 10888 if (!wpa_s) 10889 goto fail; 10890 wpa_s->added_vif = create_iface; 10891 return 0; 10892 10893 fail: 10894 if (create_iface) 10895 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname); 10896 return -1; 10897 } 10898 10899 10900 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 10901 char *cmd) 10902 { 10903 struct wpa_supplicant *wpa_s; 10904 int ret; 10905 unsigned int delete_iface; 10906 10907 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 10908 10909 wpa_s = wpa_supplicant_get_iface(global, cmd); 10910 if (wpa_s == NULL) 10911 return -1; 10912 delete_iface = wpa_s->added_vif; 10913 ret = wpa_supplicant_remove_iface(global, wpa_s, 0); 10914 if (!ret && delete_iface) { 10915 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'", 10916 cmd); 10917 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd); 10918 } 10919 return ret; 10920 } 10921 10922 10923 static void wpa_free_iface_info(struct wpa_interface_info *iface) 10924 { 10925 struct wpa_interface_info *prev; 10926 10927 while (iface) { 10928 prev = iface; 10929 iface = iface->next; 10930 10931 os_free(prev->ifname); 10932 os_free(prev->desc); 10933 os_free(prev); 10934 } 10935 } 10936 10937 10938 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 10939 char *buf, int len) 10940 { 10941 int i, res; 10942 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 10943 char *pos, *end; 10944 10945 for (i = 0; wpa_drivers[i]; i++) { 10946 const struct wpa_driver_ops *drv = wpa_drivers[i]; 10947 if (drv->get_interfaces == NULL) 10948 continue; 10949 tmp = drv->get_interfaces(global->drv_priv[i]); 10950 if (tmp == NULL) 10951 continue; 10952 10953 if (last == NULL) 10954 iface = last = tmp; 10955 else 10956 last->next = tmp; 10957 while (last->next) 10958 last = last->next; 10959 } 10960 10961 pos = buf; 10962 end = buf + len; 10963 for (tmp = iface; tmp; tmp = tmp->next) { 10964 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 10965 tmp->drv_name, tmp->ifname, 10966 tmp->desc ? tmp->desc : ""); 10967 if (os_snprintf_error(end - pos, res)) { 10968 *pos = '\0'; 10969 break; 10970 } 10971 pos += res; 10972 } 10973 10974 wpa_free_iface_info(iface); 10975 10976 return pos - buf; 10977 } 10978 10979 10980 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 10981 const char *input, 10982 char *buf, int len) 10983 { 10984 int res; 10985 char *pos, *end; 10986 struct wpa_supplicant *wpa_s; 10987 int show_ctrl = 0; 10988 10989 if (input) 10990 show_ctrl = !!os_strstr(input, "ctrl"); 10991 10992 wpa_s = global->ifaces; 10993 pos = buf; 10994 end = buf + len; 10995 10996 while (wpa_s) { 10997 if (show_ctrl) 10998 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n", 10999 wpa_s->ifname, 11000 wpa_s->conf->ctrl_interface ? 11001 wpa_s->conf->ctrl_interface : "N/A"); 11002 else 11003 res = os_snprintf(pos, end - pos, "%s\n", 11004 wpa_s->ifname); 11005 11006 if (os_snprintf_error(end - pos, res)) { 11007 *pos = '\0'; 11008 break; 11009 } 11010 pos += res; 11011 wpa_s = wpa_s->next; 11012 } 11013 return pos - buf; 11014 } 11015 11016 11017 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global, 11018 const char *ifname, 11019 char *cmd, size_t *resp_len) 11020 { 11021 struct wpa_supplicant *wpa_s; 11022 11023 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11024 if (os_strcmp(ifname, wpa_s->ifname) == 0) 11025 break; 11026 } 11027 11028 if (wpa_s == NULL) { 11029 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n"); 11030 if (resp) 11031 *resp_len = os_strlen(resp); 11032 else 11033 *resp_len = 1; 11034 return resp; 11035 } 11036 11037 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len); 11038 } 11039 11040 11041 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, 11042 char *buf, size_t *resp_len) 11043 { 11044 #ifdef CONFIG_P2P 11045 static const char * cmd[] = { 11046 "LIST_NETWORKS", 11047 "P2P_FIND", 11048 "P2P_STOP_FIND", 11049 "P2P_LISTEN", 11050 "P2P_GROUP_ADD", 11051 "P2P_GET_PASSPHRASE", 11052 "P2P_SERVICE_UPDATE", 11053 "P2P_SERVICE_FLUSH", 11054 "P2P_FLUSH", 11055 "P2P_CANCEL", 11056 "P2P_PRESENCE_REQ", 11057 "P2P_EXT_LISTEN", 11058 #ifdef CONFIG_AP 11059 "STA-FIRST", 11060 #endif /* CONFIG_AP */ 11061 NULL 11062 }; 11063 static const char * prefix[] = { 11064 #ifdef ANDROID 11065 "DRIVER ", 11066 #endif /* ANDROID */ 11067 "GET_CAPABILITY ", 11068 "GET_NETWORK ", 11069 "REMOVE_NETWORK ", 11070 "P2P_FIND ", 11071 "P2P_CONNECT ", 11072 "P2P_LISTEN ", 11073 "P2P_GROUP_REMOVE ", 11074 "P2P_GROUP_ADD ", 11075 "P2P_GROUP_MEMBER ", 11076 "P2P_PROV_DISC ", 11077 "P2P_SERV_DISC_REQ ", 11078 "P2P_SERV_DISC_CANCEL_REQ ", 11079 "P2P_SERV_DISC_RESP ", 11080 "P2P_SERV_DISC_EXTERNAL ", 11081 "P2P_SERVICE_ADD ", 11082 "P2P_SERVICE_DEL ", 11083 "P2P_SERVICE_REP ", 11084 "P2P_REJECT ", 11085 "P2P_INVITE ", 11086 "P2P_PEER ", 11087 "P2P_SET ", 11088 "P2P_UNAUTHORIZE ", 11089 "P2P_PRESENCE_REQ ", 11090 "P2P_EXT_LISTEN ", 11091 "P2P_REMOVE_CLIENT ", 11092 "WPS_NFC_TOKEN ", 11093 "WPS_NFC_TAG_READ ", 11094 "NFC_GET_HANDOVER_SEL ", 11095 "NFC_GET_HANDOVER_REQ ", 11096 "NFC_REPORT_HANDOVER ", 11097 "P2P_ASP_PROVISION ", 11098 "P2P_ASP_PROVISION_RESP ", 11099 #ifdef CONFIG_AP 11100 "STA ", 11101 "STA-NEXT ", 11102 #endif /* CONFIG_AP */ 11103 NULL 11104 }; 11105 int found = 0; 11106 int i; 11107 11108 if (global->p2p_init_wpa_s == NULL) 11109 return NULL; 11110 11111 for (i = 0; !found && cmd[i]; i++) { 11112 if (os_strcmp(buf, cmd[i]) == 0) 11113 found = 1; 11114 } 11115 11116 for (i = 0; !found && prefix[i]; i++) { 11117 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0) 11118 found = 1; 11119 } 11120 11121 if (found) 11122 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 11123 buf, resp_len); 11124 #endif /* CONFIG_P2P */ 11125 return NULL; 11126 } 11127 11128 11129 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global, 11130 char *buf, size_t *resp_len) 11131 { 11132 #ifdef CONFIG_WIFI_DISPLAY 11133 if (global->p2p_init_wpa_s == NULL) 11134 return NULL; 11135 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 || 11136 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) 11137 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 11138 buf, resp_len); 11139 #endif /* CONFIG_WIFI_DISPLAY */ 11140 return NULL; 11141 } 11142 11143 11144 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global, 11145 char *buf, size_t *resp_len) 11146 { 11147 char *ret; 11148 11149 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len); 11150 if (ret) 11151 return ret; 11152 11153 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len); 11154 if (ret) 11155 return ret; 11156 11157 return NULL; 11158 } 11159 11160 11161 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd) 11162 { 11163 char *value; 11164 11165 value = os_strchr(cmd, ' '); 11166 if (value == NULL) 11167 return -1; 11168 *value++ = '\0'; 11169 11170 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value); 11171 11172 #ifdef CONFIG_WIFI_DISPLAY 11173 if (os_strcasecmp(cmd, "wifi_display") == 0) { 11174 wifi_display_enable(global, !!atoi(value)); 11175 return 0; 11176 } 11177 #endif /* CONFIG_WIFI_DISPLAY */ 11178 11179 /* Restore cmd to its original value to allow redirection */ 11180 value[-1] = ' '; 11181 11182 return -1; 11183 } 11184 11185 11186 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global, 11187 char *cmd) 11188 { 11189 struct wpa_supplicant *wpa_s[2]; /* src, dst */ 11190 char *p; 11191 unsigned int i; 11192 11193 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id> 11194 * <variable name> */ 11195 11196 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) { 11197 p = os_strchr(cmd, ' '); 11198 if (p == NULL) 11199 return -1; 11200 *p = '\0'; 11201 11202 wpa_s[i] = global->ifaces; 11203 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) { 11204 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0) 11205 break; 11206 } 11207 11208 if (!wpa_s[i]) { 11209 wpa_printf(MSG_DEBUG, 11210 "CTRL_IFACE: Could not find iface=%s", cmd); 11211 return -1; 11212 } 11213 11214 cmd = p + 1; 11215 } 11216 11217 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]); 11218 } 11219 11220 11221 #ifndef CONFIG_NO_CONFIG_WRITE 11222 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global) 11223 { 11224 int ret = 0, saved = 0; 11225 struct wpa_supplicant *wpa_s; 11226 11227 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11228 if (!wpa_s->conf->update_config) { 11229 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)"); 11230 continue; 11231 } 11232 11233 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) { 11234 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration"); 11235 ret = 1; 11236 } else { 11237 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated"); 11238 saved++; 11239 } 11240 } 11241 11242 if (!saved && !ret) { 11243 wpa_dbg(wpa_s, MSG_DEBUG, 11244 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated"); 11245 ret = 1; 11246 } 11247 11248 return ret; 11249 } 11250 #endif /* CONFIG_NO_CONFIG_WRITE */ 11251 11252 11253 static int wpas_global_ctrl_iface_status(struct wpa_global *global, 11254 char *buf, size_t buflen) 11255 { 11256 char *pos, *end; 11257 int ret; 11258 struct wpa_supplicant *wpa_s; 11259 11260 pos = buf; 11261 end = buf + buflen; 11262 11263 #ifdef CONFIG_P2P 11264 if (global->p2p && !global->p2p_disabled) { 11265 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 11266 "\n" 11267 "p2p_state=%s\n", 11268 MAC2STR(global->p2p_dev_addr), 11269 p2p_get_state_txt(global->p2p)); 11270 if (os_snprintf_error(end - pos, ret)) 11271 return pos - buf; 11272 pos += ret; 11273 } else if (global->p2p) { 11274 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n"); 11275 if (os_snprintf_error(end - pos, ret)) 11276 return pos - buf; 11277 pos += ret; 11278 } 11279 #endif /* CONFIG_P2P */ 11280 11281 #ifdef CONFIG_WIFI_DISPLAY 11282 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n", 11283 !!global->wifi_display); 11284 if (os_snprintf_error(end - pos, ret)) 11285 return pos - buf; 11286 pos += ret; 11287 #endif /* CONFIG_WIFI_DISPLAY */ 11288 11289 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11290 ret = os_snprintf(pos, end - pos, "ifname=%s\n" 11291 "address=" MACSTR "\n", 11292 wpa_s->ifname, MAC2STR(wpa_s->own_addr)); 11293 if (os_snprintf_error(end - pos, ret)) 11294 return pos - buf; 11295 pos += ret; 11296 } 11297 11298 return pos - buf; 11299 } 11300 11301 11302 #ifdef CONFIG_FST 11303 11304 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global, 11305 char *cmd, char *buf, 11306 size_t reply_size) 11307 { 11308 char ifname[IFNAMSIZ + 1]; 11309 struct fst_iface_cfg cfg; 11310 struct wpa_supplicant *wpa_s; 11311 struct fst_wpa_obj iface_obj; 11312 11313 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 11314 wpa_s = wpa_supplicant_get_iface(global, ifname); 11315 if (wpa_s) { 11316 if (wpa_s->fst) { 11317 wpa_printf(MSG_INFO, "FST: Already attached"); 11318 return -1; 11319 } 11320 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj); 11321 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr, 11322 &iface_obj, &cfg); 11323 if (wpa_s->fst) 11324 return os_snprintf(buf, reply_size, "OK\n"); 11325 } 11326 } 11327 11328 return -1; 11329 } 11330 11331 11332 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global, 11333 char *cmd, char *buf, 11334 size_t reply_size) 11335 { 11336 char ifname[IFNAMSIZ + 1]; 11337 struct wpa_supplicant *wpa_s; 11338 11339 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 11340 wpa_s = wpa_supplicant_get_iface(global, ifname); 11341 if (wpa_s) { 11342 if (!fst_iface_detach(ifname)) { 11343 wpa_s->fst = NULL; 11344 return os_snprintf(buf, reply_size, "OK\n"); 11345 } 11346 } 11347 } 11348 11349 return -1; 11350 } 11351 11352 #endif /* CONFIG_FST */ 11353 11354 11355 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 11356 char *buf, size_t *resp_len) 11357 { 11358 char *reply; 11359 const int reply_size = 2048; 11360 int reply_len; 11361 int level = MSG_DEBUG; 11362 11363 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 11364 char *pos = os_strchr(buf + 7, ' '); 11365 if (pos) { 11366 *pos++ = '\0'; 11367 return wpas_global_ctrl_iface_ifname(global, 11368 buf + 7, pos, 11369 resp_len); 11370 } 11371 } 11372 11373 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len); 11374 if (reply) 11375 return reply; 11376 11377 if (os_strcmp(buf, "PING") == 0) 11378 level = MSG_EXCESSIVE; 11379 wpa_hexdump_ascii(level, "RX global ctrl_iface", 11380 (const u8 *) buf, os_strlen(buf)); 11381 11382 reply = os_malloc(reply_size); 11383 if (reply == NULL) { 11384 *resp_len = 1; 11385 return NULL; 11386 } 11387 11388 os_memcpy(reply, "OK\n", 3); 11389 reply_len = 3; 11390 11391 if (os_strcmp(buf, "PING") == 0) { 11392 os_memcpy(reply, "PONG\n", 5); 11393 reply_len = 5; 11394 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 11395 if (wpa_supplicant_global_iface_add(global, buf + 14)) 11396 reply_len = -1; 11397 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 11398 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 11399 reply_len = -1; 11400 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 11401 reply_len = wpa_supplicant_global_iface_list( 11402 global, reply, reply_size); 11403 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 11404 reply_len = wpa_supplicant_global_iface_interfaces( 11405 global, buf + 10, reply, reply_size); 11406 #ifdef CONFIG_FST 11407 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 11408 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11, 11409 reply, 11410 reply_size); 11411 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 11412 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11, 11413 reply, 11414 reply_size); 11415 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 11416 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 11417 #endif /* CONFIG_FST */ 11418 } else if (os_strcmp(buf, "TERMINATE") == 0) { 11419 wpa_supplicant_terminate_proc(global); 11420 } else if (os_strcmp(buf, "SUSPEND") == 0) { 11421 wpas_notify_suspend(global); 11422 } else if (os_strcmp(buf, "RESUME") == 0) { 11423 wpas_notify_resume(global); 11424 } else if (os_strncmp(buf, "SET ", 4) == 0) { 11425 if (wpas_global_ctrl_iface_set(global, buf + 4)) { 11426 #ifdef CONFIG_P2P 11427 if (global->p2p_init_wpa_s) { 11428 os_free(reply); 11429 /* Check if P2P redirection would work for this 11430 * command. */ 11431 return wpa_supplicant_ctrl_iface_process( 11432 global->p2p_init_wpa_s, 11433 buf, resp_len); 11434 } 11435 #endif /* CONFIG_P2P */ 11436 reply_len = -1; 11437 } 11438 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 11439 if (wpas_global_ctrl_iface_dup_network(global, buf + 12)) 11440 reply_len = -1; 11441 #ifndef CONFIG_NO_CONFIG_WRITE 11442 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 11443 if (wpas_global_ctrl_iface_save_config(global)) 11444 reply_len = -1; 11445 #endif /* CONFIG_NO_CONFIG_WRITE */ 11446 } else if (os_strcmp(buf, "STATUS") == 0) { 11447 reply_len = wpas_global_ctrl_iface_status(global, reply, 11448 reply_size); 11449 #ifdef CONFIG_MODULE_TESTS 11450 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 11451 if (wpas_module_tests() < 0) 11452 reply_len = -1; 11453 #endif /* CONFIG_MODULE_TESTS */ 11454 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 11455 if (wpa_debug_reopen_file() < 0) 11456 reply_len = -1; 11457 } else { 11458 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 11459 reply_len = 16; 11460 } 11461 11462 if (reply_len < 0) { 11463 os_memcpy(reply, "FAIL\n", 5); 11464 reply_len = 5; 11465 } 11466 11467 *resp_len = reply_len; 11468 return reply; 11469 } 11470