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 <netinet/ip.h> 12 #endif /* CONFIG_TESTING_OPTIONS */ 13 14 #include <net/ethernet.h> 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 3133 static int wpa_supplicant_ctrl_iface_mesh_link_probe( 3134 struct wpa_supplicant *wpa_s, char *cmd) 3135 { 3136 struct ether_header *eth; 3137 u8 addr[ETH_ALEN]; 3138 u8 *buf; 3139 char *pos; 3140 size_t payload_len = 0, len; 3141 int ret = -1; 3142 3143 if (hwaddr_aton(cmd, addr)) 3144 return -1; 3145 3146 pos = os_strstr(cmd, " payload="); 3147 if (pos) { 3148 pos = pos + 9; 3149 payload_len = os_strlen(pos); 3150 if (payload_len & 1) 3151 return -1; 3152 3153 payload_len /= 2; 3154 } 3155 3156 len = ETH_HLEN + payload_len; 3157 buf = os_malloc(len); 3158 if (!buf) 3159 return -1; 3160 3161 eth = (struct ether_header *) buf; 3162 os_memcpy(eth->ether_dhost, addr, ETH_ALEN); 3163 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN); 3164 eth->ether_type = htons(ETH_P_802_3); 3165 3166 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0) 3167 goto fail; 3168 3169 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len); 3170 fail: 3171 os_free(buf); 3172 return -ret; 3173 } 3174 3175 #endif /* CONFIG_MESH */ 3176 3177 3178 static int wpa_supplicant_ctrl_iface_select_network( 3179 struct wpa_supplicant *wpa_s, char *cmd) 3180 { 3181 int id; 3182 struct wpa_ssid *ssid; 3183 char *pos; 3184 3185 /* cmd: "<network id>" or "any" */ 3186 if (os_strncmp(cmd, "any", 3) == 0) { 3187 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 3188 ssid = NULL; 3189 } else { 3190 id = atoi(cmd); 3191 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 3192 3193 ssid = wpa_config_get_network(wpa_s->conf, id); 3194 if (ssid == NULL) { 3195 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3196 "network id=%d", id); 3197 return -1; 3198 } 3199 if (ssid->disabled == 2) { 3200 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3201 "SELECT_NETWORK with persistent P2P group"); 3202 return -1; 3203 } 3204 } 3205 3206 pos = os_strstr(cmd, " freq="); 3207 if (pos) { 3208 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); 3209 if (freqs) { 3210 os_free(wpa_s->select_network_scan_freqs); 3211 wpa_s->select_network_scan_freqs = freqs; 3212 } 3213 } 3214 3215 wpa_s->scan_min_time.sec = 0; 3216 wpa_s->scan_min_time.usec = 0; 3217 wpa_supplicant_select_network(wpa_s, ssid); 3218 3219 return 0; 3220 } 3221 3222 3223 static int wpa_supplicant_ctrl_iface_enable_network( 3224 struct wpa_supplicant *wpa_s, char *cmd) 3225 { 3226 int id; 3227 struct wpa_ssid *ssid; 3228 3229 /* cmd: "<network id>" or "all" */ 3230 if (os_strcmp(cmd, "all") == 0) { 3231 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 3232 ssid = NULL; 3233 } else { 3234 id = atoi(cmd); 3235 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 3236 3237 ssid = wpa_config_get_network(wpa_s->conf, id); 3238 if (ssid == NULL) { 3239 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3240 "network id=%d", id); 3241 return -1; 3242 } 3243 if (ssid->disabled == 2) { 3244 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3245 "ENABLE_NETWORK with persistent P2P group"); 3246 return -1; 3247 } 3248 3249 if (os_strstr(cmd, " no-connect")) { 3250 ssid->disabled = 0; 3251 return 0; 3252 } 3253 } 3254 wpa_s->scan_min_time.sec = 0; 3255 wpa_s->scan_min_time.usec = 0; 3256 wpa_supplicant_enable_network(wpa_s, ssid); 3257 3258 return 0; 3259 } 3260 3261 3262 static int wpa_supplicant_ctrl_iface_disable_network( 3263 struct wpa_supplicant *wpa_s, char *cmd) 3264 { 3265 int id; 3266 struct wpa_ssid *ssid; 3267 3268 /* cmd: "<network id>" or "all" */ 3269 if (os_strcmp(cmd, "all") == 0) { 3270 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 3271 ssid = NULL; 3272 } else { 3273 id = atoi(cmd); 3274 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 3275 3276 ssid = wpa_config_get_network(wpa_s->conf, id); 3277 if (ssid == NULL) { 3278 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3279 "network id=%d", id); 3280 return -1; 3281 } 3282 if (ssid->disabled == 2) { 3283 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3284 "DISABLE_NETWORK with persistent P2P " 3285 "group"); 3286 return -1; 3287 } 3288 } 3289 wpa_supplicant_disable_network(wpa_s, ssid); 3290 3291 return 0; 3292 } 3293 3294 3295 static int wpa_supplicant_ctrl_iface_add_network( 3296 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3297 { 3298 struct wpa_ssid *ssid; 3299 int ret; 3300 3301 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 3302 3303 ssid = wpa_supplicant_add_network(wpa_s); 3304 if (ssid == NULL) 3305 return -1; 3306 3307 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 3308 if (os_snprintf_error(buflen, ret)) 3309 return -1; 3310 return ret; 3311 } 3312 3313 3314 static int wpa_supplicant_ctrl_iface_remove_network( 3315 struct wpa_supplicant *wpa_s, char *cmd) 3316 { 3317 int id; 3318 struct wpa_ssid *ssid; 3319 int result; 3320 3321 /* cmd: "<network id>" or "all" */ 3322 if (os_strcmp(cmd, "all") == 0) { 3323 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 3324 if (wpa_s->sched_scanning) 3325 wpa_supplicant_cancel_sched_scan(wpa_s); 3326 3327 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3328 if (wpa_s->current_ssid) { 3329 #ifdef CONFIG_SME 3330 wpa_s->sme.prev_bssid_set = 0; 3331 #endif /* CONFIG_SME */ 3332 wpa_sm_set_config(wpa_s->wpa, NULL); 3333 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 3334 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) 3335 wpa_s->own_disconnect_req = 1; 3336 wpa_supplicant_deauthenticate( 3337 wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3338 } 3339 ssid = wpa_s->conf->ssid; 3340 while (ssid) { 3341 struct wpa_ssid *remove_ssid = ssid; 3342 id = ssid->id; 3343 ssid = ssid->next; 3344 if (wpa_s->last_ssid == remove_ssid) 3345 wpa_s->last_ssid = NULL; 3346 wpas_notify_network_removed(wpa_s, remove_ssid); 3347 wpa_config_remove_network(wpa_s->conf, id); 3348 } 3349 return 0; 3350 } 3351 3352 id = atoi(cmd); 3353 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 3354 3355 result = wpa_supplicant_remove_network(wpa_s, id); 3356 if (result == -1) { 3357 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3358 "id=%d", id); 3359 return -1; 3360 } 3361 if (result == -2) { 3362 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 3363 "network id=%d", id); 3364 return -1; 3365 } 3366 return 0; 3367 } 3368 3369 3370 static int wpa_supplicant_ctrl_iface_update_network( 3371 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 3372 char *name, char *value) 3373 { 3374 int ret; 3375 3376 ret = wpa_config_set(ssid, name, value, 0); 3377 if (ret < 0) { 3378 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 3379 "variable '%s'", name); 3380 return -1; 3381 } 3382 if (ret == 1) 3383 return 0; /* No change to the previously configured value */ 3384 3385 if (os_strcmp(name, "bssid") != 0 && 3386 os_strcmp(name, "bssid_hint") != 0 && 3387 os_strcmp(name, "priority") != 0) { 3388 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 3389 3390 if (wpa_s->current_ssid == ssid || 3391 wpa_s->current_ssid == NULL) { 3392 /* 3393 * Invalidate the EAP session cache if anything in the 3394 * current or previously used configuration changes. 3395 */ 3396 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3397 } 3398 } 3399 3400 if ((os_strcmp(name, "psk") == 0 && 3401 value[0] == '"' && ssid->ssid_len) || 3402 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 3403 wpa_config_update_psk(ssid); 3404 else if (os_strcmp(name, "priority") == 0) 3405 wpa_config_update_prio_list(wpa_s->conf); 3406 3407 return 0; 3408 } 3409 3410 3411 static int wpa_supplicant_ctrl_iface_set_network( 3412 struct wpa_supplicant *wpa_s, char *cmd) 3413 { 3414 int id, ret, prev_bssid_set, prev_disabled; 3415 struct wpa_ssid *ssid; 3416 char *name, *value; 3417 u8 prev_bssid[ETH_ALEN]; 3418 3419 /* cmd: "<network id> <variable name> <value>" */ 3420 name = os_strchr(cmd, ' '); 3421 if (name == NULL) 3422 return -1; 3423 *name++ = '\0'; 3424 3425 value = os_strchr(name, ' '); 3426 if (value == NULL) 3427 return -1; 3428 *value++ = '\0'; 3429 3430 id = atoi(cmd); 3431 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 3432 id, name); 3433 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3434 (u8 *) value, os_strlen(value)); 3435 3436 ssid = wpa_config_get_network(wpa_s->conf, id); 3437 if (ssid == NULL) { 3438 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3439 "id=%d", id); 3440 return -1; 3441 } 3442 3443 prev_bssid_set = ssid->bssid_set; 3444 prev_disabled = ssid->disabled; 3445 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN); 3446 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name, 3447 value); 3448 if (ret == 0 && 3449 (ssid->bssid_set != prev_bssid_set || 3450 os_memcmp(ssid->bssid, prev_bssid, ETH_ALEN) != 0)) 3451 wpas_notify_network_bssid_set_changed(wpa_s, ssid); 3452 3453 if (prev_disabled != ssid->disabled && 3454 (prev_disabled == 2 || ssid->disabled == 2)) 3455 wpas_notify_network_type_changed(wpa_s, ssid); 3456 3457 return ret; 3458 } 3459 3460 3461 static int wpa_supplicant_ctrl_iface_get_network( 3462 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 3463 { 3464 int id; 3465 size_t res; 3466 struct wpa_ssid *ssid; 3467 char *name, *value; 3468 3469 /* cmd: "<network id> <variable name>" */ 3470 name = os_strchr(cmd, ' '); 3471 if (name == NULL || buflen == 0) 3472 return -1; 3473 *name++ = '\0'; 3474 3475 id = atoi(cmd); 3476 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 3477 id, name); 3478 3479 ssid = wpa_config_get_network(wpa_s->conf, id); 3480 if (ssid == NULL) { 3481 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network " 3482 "id=%d", id); 3483 return -1; 3484 } 3485 3486 value = wpa_config_get_no_key(ssid, name); 3487 if (value == NULL) { 3488 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network " 3489 "variable '%s'", name); 3490 return -1; 3491 } 3492 3493 res = os_strlcpy(buf, value, buflen); 3494 if (res >= buflen) { 3495 os_free(value); 3496 return -1; 3497 } 3498 3499 os_free(value); 3500 3501 return res; 3502 } 3503 3504 3505 static int wpa_supplicant_ctrl_iface_dup_network( 3506 struct wpa_supplicant *wpa_s, char *cmd, 3507 struct wpa_supplicant *dst_wpa_s) 3508 { 3509 struct wpa_ssid *ssid_s, *ssid_d; 3510 char *name, *id, *value; 3511 int id_s, id_d, ret; 3512 3513 /* cmd: "<src network id> <dst network id> <variable name>" */ 3514 id = os_strchr(cmd, ' '); 3515 if (id == NULL) 3516 return -1; 3517 *id++ = '\0'; 3518 3519 name = os_strchr(id, ' '); 3520 if (name == NULL) 3521 return -1; 3522 *name++ = '\0'; 3523 3524 id_s = atoi(cmd); 3525 id_d = atoi(id); 3526 3527 wpa_printf(MSG_DEBUG, 3528 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'", 3529 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name); 3530 3531 ssid_s = wpa_config_get_network(wpa_s->conf, id_s); 3532 if (ssid_s == NULL) { 3533 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3534 "network id=%d", id_s); 3535 return -1; 3536 } 3537 3538 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d); 3539 if (ssid_d == NULL) { 3540 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3541 "network id=%d", id_d); 3542 return -1; 3543 } 3544 3545 value = wpa_config_get(ssid_s, name); 3546 if (value == NULL) { 3547 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 3548 "variable '%s'", name); 3549 return -1; 3550 } 3551 3552 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name, 3553 value); 3554 3555 os_free(value); 3556 3557 return ret; 3558 } 3559 3560 3561 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 3562 char *buf, size_t buflen) 3563 { 3564 char *pos, *end; 3565 struct wpa_cred *cred; 3566 int ret; 3567 3568 pos = buf; 3569 end = buf + buflen; 3570 ret = os_snprintf(pos, end - pos, 3571 "cred id / realm / username / domain / imsi\n"); 3572 if (os_snprintf_error(end - pos, ret)) 3573 return pos - buf; 3574 pos += ret; 3575 3576 cred = wpa_s->conf->cred; 3577 while (cred) { 3578 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 3579 cred->id, cred->realm ? cred->realm : "", 3580 cred->username ? cred->username : "", 3581 cred->domain ? cred->domain[0] : "", 3582 cred->imsi ? cred->imsi : ""); 3583 if (os_snprintf_error(end - pos, ret)) 3584 return pos - buf; 3585 pos += ret; 3586 3587 cred = cred->next; 3588 } 3589 3590 return pos - buf; 3591 } 3592 3593 3594 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 3595 char *buf, size_t buflen) 3596 { 3597 struct wpa_cred *cred; 3598 int ret; 3599 3600 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 3601 3602 cred = wpa_config_add_cred(wpa_s->conf); 3603 if (cred == NULL) 3604 return -1; 3605 3606 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id); 3607 3608 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 3609 if (os_snprintf_error(buflen, ret)) 3610 return -1; 3611 return ret; 3612 } 3613 3614 3615 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, 3616 struct wpa_cred *cred) 3617 { 3618 struct wpa_ssid *ssid; 3619 char str[20]; 3620 int id; 3621 3622 if (cred == NULL) { 3623 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 3624 return -1; 3625 } 3626 3627 id = cred->id; 3628 if (wpa_config_remove_cred(wpa_s->conf, id) < 0) { 3629 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 3630 return -1; 3631 } 3632 3633 wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id); 3634 3635 /* Remove any network entry created based on the removed credential */ 3636 ssid = wpa_s->conf->ssid; 3637 while (ssid) { 3638 if (ssid->parent_cred == cred) { 3639 int res; 3640 3641 wpa_printf(MSG_DEBUG, "Remove network id %d since it " 3642 "used the removed credential", ssid->id); 3643 res = os_snprintf(str, sizeof(str), "%d", ssid->id); 3644 if (os_snprintf_error(sizeof(str), res)) 3645 str[sizeof(str) - 1] = '\0'; 3646 ssid = ssid->next; 3647 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); 3648 } else 3649 ssid = ssid->next; 3650 } 3651 3652 return 0; 3653 } 3654 3655 3656 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 3657 char *cmd) 3658 { 3659 int id; 3660 struct wpa_cred *cred, *prev; 3661 3662 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or 3663 * "provisioning_sp=<FQDN> */ 3664 if (os_strcmp(cmd, "all") == 0) { 3665 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 3666 cred = wpa_s->conf->cred; 3667 while (cred) { 3668 prev = cred; 3669 cred = cred->next; 3670 wpas_ctrl_remove_cred(wpa_s, prev); 3671 } 3672 return 0; 3673 } 3674 3675 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 3676 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 3677 cmd + 8); 3678 cred = wpa_s->conf->cred; 3679 while (cred) { 3680 prev = cred; 3681 cred = cred->next; 3682 if (prev->domain) { 3683 size_t i; 3684 for (i = 0; i < prev->num_domain; i++) { 3685 if (os_strcmp(prev->domain[i], cmd + 8) 3686 != 0) 3687 continue; 3688 wpas_ctrl_remove_cred(wpa_s, prev); 3689 break; 3690 } 3691 } 3692 } 3693 return 0; 3694 } 3695 3696 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) { 3697 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'", 3698 cmd + 16); 3699 cred = wpa_s->conf->cred; 3700 while (cred) { 3701 prev = cred; 3702 cred = cred->next; 3703 if (prev->provisioning_sp && 3704 os_strcmp(prev->provisioning_sp, cmd + 16) == 0) 3705 wpas_ctrl_remove_cred(wpa_s, prev); 3706 } 3707 return 0; 3708 } 3709 3710 id = atoi(cmd); 3711 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 3712 3713 cred = wpa_config_get_cred(wpa_s->conf, id); 3714 return wpas_ctrl_remove_cred(wpa_s, cred); 3715 } 3716 3717 3718 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 3719 char *cmd) 3720 { 3721 int id; 3722 struct wpa_cred *cred; 3723 char *name, *value; 3724 3725 /* cmd: "<cred id> <variable name> <value>" */ 3726 name = os_strchr(cmd, ' '); 3727 if (name == NULL) 3728 return -1; 3729 *name++ = '\0'; 3730 3731 value = os_strchr(name, ' '); 3732 if (value == NULL) 3733 return -1; 3734 *value++ = '\0'; 3735 3736 id = atoi(cmd); 3737 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 3738 id, name); 3739 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3740 (u8 *) value, os_strlen(value)); 3741 3742 cred = wpa_config_get_cred(wpa_s->conf, id); 3743 if (cred == NULL) { 3744 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3745 id); 3746 return -1; 3747 } 3748 3749 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 3750 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 3751 "variable '%s'", name); 3752 return -1; 3753 } 3754 3755 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name); 3756 3757 return 0; 3758 } 3759 3760 3761 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s, 3762 char *cmd, char *buf, 3763 size_t buflen) 3764 { 3765 int id; 3766 size_t res; 3767 struct wpa_cred *cred; 3768 char *name, *value; 3769 3770 /* cmd: "<cred id> <variable name>" */ 3771 name = os_strchr(cmd, ' '); 3772 if (name == NULL) 3773 return -1; 3774 *name++ = '\0'; 3775 3776 id = atoi(cmd); 3777 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'", 3778 id, name); 3779 3780 cred = wpa_config_get_cred(wpa_s->conf, id); 3781 if (cred == NULL) { 3782 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3783 id); 3784 return -1; 3785 } 3786 3787 value = wpa_config_get_cred_no_key(cred, name); 3788 if (value == NULL) { 3789 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'", 3790 name); 3791 return -1; 3792 } 3793 3794 res = os_strlcpy(buf, value, buflen); 3795 if (res >= buflen) { 3796 os_free(value); 3797 return -1; 3798 } 3799 3800 os_free(value); 3801 3802 return res; 3803 } 3804 3805 3806 #ifndef CONFIG_NO_CONFIG_WRITE 3807 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 3808 { 3809 int ret; 3810 3811 if (!wpa_s->conf->update_config) { 3812 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 3813 "to update configuration (update_config=0)"); 3814 return -1; 3815 } 3816 3817 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 3818 if (ret) { 3819 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 3820 "update configuration"); 3821 } else { 3822 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 3823 " updated"); 3824 } 3825 3826 return ret; 3827 } 3828 #endif /* CONFIG_NO_CONFIG_WRITE */ 3829 3830 3831 struct cipher_info { 3832 unsigned int capa; 3833 const char *name; 3834 int group_only; 3835 }; 3836 3837 static const struct cipher_info ciphers[] = { 3838 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 }, 3839 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, 3840 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, 3841 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, 3842 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, 3843 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, 3844 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, 3845 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } 3846 }; 3847 3848 static const struct cipher_info ciphers_group_mgmt[] = { 3849 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 }, 3850 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 }, 3851 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 }, 3852 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 }, 3853 }; 3854 3855 3856 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 3857 struct wpa_driver_capa *capa, 3858 char *buf, size_t buflen) 3859 { 3860 int ret; 3861 char *pos, *end; 3862 size_t len; 3863 unsigned int i; 3864 3865 pos = buf; 3866 end = pos + buflen; 3867 3868 if (res < 0) { 3869 if (strict) 3870 return 0; 3871 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 3872 if (len >= buflen) 3873 return -1; 3874 return len; 3875 } 3876 3877 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3878 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) { 3879 ret = os_snprintf(pos, end - pos, "%s%s", 3880 pos == buf ? "" : " ", 3881 ciphers[i].name); 3882 if (os_snprintf_error(end - pos, ret)) 3883 return pos - buf; 3884 pos += ret; 3885 } 3886 } 3887 3888 return pos - buf; 3889 } 3890 3891 3892 static int ctrl_iface_get_capability_group(int res, char *strict, 3893 struct wpa_driver_capa *capa, 3894 char *buf, size_t buflen) 3895 { 3896 int ret; 3897 char *pos, *end; 3898 size_t len; 3899 unsigned int i; 3900 3901 pos = buf; 3902 end = pos + buflen; 3903 3904 if (res < 0) { 3905 if (strict) 3906 return 0; 3907 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 3908 if (len >= buflen) 3909 return -1; 3910 return len; 3911 } 3912 3913 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 3914 if (capa->enc & ciphers[i].capa) { 3915 ret = os_snprintf(pos, end - pos, "%s%s", 3916 pos == buf ? "" : " ", 3917 ciphers[i].name); 3918 if (os_snprintf_error(end - pos, ret)) 3919 return pos - buf; 3920 pos += ret; 3921 } 3922 } 3923 3924 return pos - buf; 3925 } 3926 3927 3928 static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, 3929 struct wpa_driver_capa *capa, 3930 char *buf, size_t buflen) 3931 { 3932 int ret; 3933 char *pos, *end; 3934 unsigned int i; 3935 3936 pos = buf; 3937 end = pos + buflen; 3938 3939 if (res < 0) 3940 return 0; 3941 3942 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) { 3943 if (capa->enc & ciphers_group_mgmt[i].capa) { 3944 ret = os_snprintf(pos, end - pos, "%s%s", 3945 pos == buf ? "" : " ", 3946 ciphers_group_mgmt[i].name); 3947 if (os_snprintf_error(end - pos, ret)) 3948 return pos - buf; 3949 pos += ret; 3950 } 3951 } 3952 3953 return pos - buf; 3954 } 3955 3956 3957 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 3958 struct wpa_driver_capa *capa, 3959 char *buf, size_t buflen) 3960 { 3961 int ret; 3962 char *pos, *end; 3963 size_t len; 3964 3965 pos = buf; 3966 end = pos + buflen; 3967 3968 if (res < 0) { 3969 if (strict) 3970 return 0; 3971 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 3972 "NONE", buflen); 3973 if (len >= buflen) 3974 return -1; 3975 return len; 3976 } 3977 3978 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 3979 if (os_snprintf_error(end - pos, ret)) 3980 return pos - buf; 3981 pos += ret; 3982 3983 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3984 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 3985 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 3986 if (os_snprintf_error(end - pos, ret)) 3987 return pos - buf; 3988 pos += ret; 3989 } 3990 3991 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 3992 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 3993 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 3994 if (os_snprintf_error(end - pos, ret)) 3995 return pos - buf; 3996 pos += ret; 3997 } 3998 3999 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 4000 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 4001 if (os_snprintf_error(end - pos, ret)) 4002 return pos - buf; 4003 pos += ret; 4004 } 4005 4006 #ifdef CONFIG_SUITEB 4007 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { 4008 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); 4009 if (os_snprintf_error(end - pos, ret)) 4010 return pos - buf; 4011 pos += ret; 4012 } 4013 #endif /* CONFIG_SUITEB */ 4014 #ifdef CONFIG_SUITEB192 4015 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { 4016 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); 4017 if (os_snprintf_error(end - pos, ret)) 4018 return pos - buf; 4019 pos += ret; 4020 } 4021 #endif /* CONFIG_SUITEB192 */ 4022 #ifdef CONFIG_OWE 4023 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { 4024 ret = os_snprintf(pos, end - pos, " OWE"); 4025 if (os_snprintf_error(end - pos, ret)) 4026 return pos - buf; 4027 pos += ret; 4028 } 4029 #endif /* CONFIG_OWE */ 4030 #ifdef CONFIG_DPP 4031 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { 4032 ret = os_snprintf(pos, end - pos, " DPP"); 4033 if (os_snprintf_error(end - pos, ret)) 4034 return pos - buf; 4035 pos += ret; 4036 } 4037 #endif /* CONFIG_DPP */ 4038 #ifdef CONFIG_FILS 4039 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { 4040 ret = os_snprintf(pos, end - pos, " FILS-SHA256"); 4041 if (os_snprintf_error(end - pos, ret)) 4042 return pos - buf; 4043 pos += ret; 4044 } 4045 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { 4046 ret = os_snprintf(pos, end - pos, " FILS-SHA384"); 4047 if (os_snprintf_error(end - pos, ret)) 4048 return pos - buf; 4049 pos += ret; 4050 } 4051 #ifdef CONFIG_IEEE80211R 4052 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { 4053 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); 4054 if (os_snprintf_error(end - pos, ret)) 4055 return pos - buf; 4056 pos += ret; 4057 } 4058 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { 4059 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); 4060 if (os_snprintf_error(end - pos, ret)) 4061 return pos - buf; 4062 pos += ret; 4063 } 4064 #endif /* CONFIG_IEEE80211R */ 4065 #endif /* CONFIG_FILS */ 4066 #ifdef CONFIG_IEEE80211R 4067 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { 4068 ret = os_snprintf(pos, end - pos, " FT-PSK"); 4069 if (os_snprintf_error(end - pos, ret)) 4070 return pos - buf; 4071 pos += ret; 4072 } 4073 #endif /* CONFIG_IEEE80211R */ 4074 #ifdef CONFIG_SAE 4075 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { 4076 ret = os_snprintf(pos, end - pos, " SAE"); 4077 if (os_snprintf_error(end - pos, ret)) 4078 return pos - buf; 4079 pos += ret; 4080 } 4081 #endif /* CONFIG_SAE */ 4082 4083 return pos - buf; 4084 } 4085 4086 4087 static int ctrl_iface_get_capability_proto(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, "RSN WPA", buflen); 4102 if (len >= buflen) 4103 return -1; 4104 return len; 4105 } 4106 4107 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 4108 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4109 ret = os_snprintf(pos, end - pos, "%sRSN", 4110 pos == buf ? "" : " "); 4111 if (os_snprintf_error(end - pos, ret)) 4112 return pos - buf; 4113 pos += ret; 4114 } 4115 4116 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4117 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 4118 ret = os_snprintf(pos, end - pos, "%sWPA", 4119 pos == buf ? "" : " "); 4120 if (os_snprintf_error(end - pos, ret)) 4121 return pos - buf; 4122 pos += ret; 4123 } 4124 4125 return pos - buf; 4126 } 4127 4128 4129 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, 4130 int res, char *strict, 4131 struct wpa_driver_capa *capa, 4132 char *buf, size_t buflen) 4133 { 4134 int ret; 4135 char *pos, *end; 4136 size_t len; 4137 4138 pos = buf; 4139 end = pos + buflen; 4140 4141 if (res < 0) { 4142 if (strict) 4143 return 0; 4144 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 4145 if (len >= buflen) 4146 return -1; 4147 return len; 4148 } 4149 4150 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 4151 ret = os_snprintf(pos, end - pos, "%sOPEN", 4152 pos == buf ? "" : " "); 4153 if (os_snprintf_error(end - pos, ret)) 4154 return pos - buf; 4155 pos += ret; 4156 } 4157 4158 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 4159 ret = os_snprintf(pos, end - pos, "%sSHARED", 4160 pos == buf ? "" : " "); 4161 if (os_snprintf_error(end - pos, ret)) 4162 return pos - buf; 4163 pos += ret; 4164 } 4165 4166 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 4167 ret = os_snprintf(pos, end - pos, "%sLEAP", 4168 pos == buf ? "" : " "); 4169 if (os_snprintf_error(end - pos, ret)) 4170 return pos - buf; 4171 pos += ret; 4172 } 4173 4174 #ifdef CONFIG_SAE 4175 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) { 4176 ret = os_snprintf(pos, end - pos, "%sSAE", 4177 pos == buf ? "" : " "); 4178 if (os_snprintf_error(end - pos, ret)) 4179 return pos - buf; 4180 pos += ret; 4181 } 4182 #endif /* CONFIG_SAE */ 4183 4184 #ifdef CONFIG_FILS 4185 if (wpa_is_fils_supported(wpa_s)) { 4186 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS", 4187 pos == buf ? "" : " "); 4188 if (os_snprintf_error(end - pos, ret)) 4189 return pos - buf; 4190 pos += ret; 4191 } 4192 4193 #ifdef CONFIG_FILS_SK_PFS 4194 if (wpa_is_fils_sk_pfs_supported(wpa_s)) { 4195 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS", 4196 pos == buf ? "" : " "); 4197 if (os_snprintf_error(end - pos, ret)) 4198 return pos - buf; 4199 pos += ret; 4200 } 4201 #endif /* CONFIG_FILS_SK_PFS */ 4202 #endif /* CONFIG_FILS */ 4203 4204 return pos - buf; 4205 } 4206 4207 4208 static int ctrl_iface_get_capability_modes(int res, char *strict, 4209 struct wpa_driver_capa *capa, 4210 char *buf, size_t buflen) 4211 { 4212 int ret; 4213 char *pos, *end; 4214 size_t len; 4215 4216 pos = buf; 4217 end = pos + buflen; 4218 4219 if (res < 0) { 4220 if (strict) 4221 return 0; 4222 len = os_strlcpy(buf, "IBSS AP", buflen); 4223 if (len >= buflen) 4224 return -1; 4225 return len; 4226 } 4227 4228 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) { 4229 ret = os_snprintf(pos, end - pos, "%sIBSS", 4230 pos == buf ? "" : " "); 4231 if (os_snprintf_error(end - pos, ret)) 4232 return pos - buf; 4233 pos += ret; 4234 } 4235 4236 if (capa->flags & WPA_DRIVER_FLAGS_AP) { 4237 ret = os_snprintf(pos, end - pos, "%sAP", 4238 pos == buf ? "" : " "); 4239 if (os_snprintf_error(end - pos, ret)) 4240 return pos - buf; 4241 pos += ret; 4242 } 4243 4244 #ifdef CONFIG_MESH 4245 if (capa->flags & WPA_DRIVER_FLAGS_MESH) { 4246 ret = os_snprintf(pos, end - pos, "%sMESH", 4247 pos == buf ? "" : " "); 4248 if (os_snprintf_error(end - pos, ret)) 4249 return pos - buf; 4250 pos += ret; 4251 } 4252 #endif /* CONFIG_MESH */ 4253 4254 return pos - buf; 4255 } 4256 4257 4258 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 4259 char *buf, size_t buflen) 4260 { 4261 struct hostapd_channel_data *chnl; 4262 int ret, i, j; 4263 char *pos, *end, *hmode; 4264 4265 pos = buf; 4266 end = pos + buflen; 4267 4268 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4269 switch (wpa_s->hw.modes[j].mode) { 4270 case HOSTAPD_MODE_IEEE80211B: 4271 hmode = "B"; 4272 break; 4273 case HOSTAPD_MODE_IEEE80211G: 4274 hmode = "G"; 4275 break; 4276 case HOSTAPD_MODE_IEEE80211A: 4277 hmode = "A"; 4278 break; 4279 case HOSTAPD_MODE_IEEE80211AD: 4280 hmode = "AD"; 4281 break; 4282 default: 4283 continue; 4284 } 4285 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 4286 if (os_snprintf_error(end - pos, ret)) 4287 return pos - buf; 4288 pos += ret; 4289 chnl = wpa_s->hw.modes[j].channels; 4290 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4291 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4292 continue; 4293 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 4294 if (os_snprintf_error(end - pos, ret)) 4295 return pos - buf; 4296 pos += ret; 4297 } 4298 ret = os_snprintf(pos, end - pos, "\n"); 4299 if (os_snprintf_error(end - pos, ret)) 4300 return pos - buf; 4301 pos += ret; 4302 } 4303 4304 return pos - buf; 4305 } 4306 4307 4308 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s, 4309 char *buf, size_t buflen) 4310 { 4311 struct hostapd_channel_data *chnl; 4312 int ret, i, j; 4313 char *pos, *end, *hmode; 4314 4315 pos = buf; 4316 end = pos + buflen; 4317 4318 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4319 switch (wpa_s->hw.modes[j].mode) { 4320 case HOSTAPD_MODE_IEEE80211B: 4321 hmode = "B"; 4322 break; 4323 case HOSTAPD_MODE_IEEE80211G: 4324 hmode = "G"; 4325 break; 4326 case HOSTAPD_MODE_IEEE80211A: 4327 hmode = "A"; 4328 break; 4329 case HOSTAPD_MODE_IEEE80211AD: 4330 hmode = "AD"; 4331 break; 4332 default: 4333 continue; 4334 } 4335 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n", 4336 hmode); 4337 if (os_snprintf_error(end - pos, ret)) 4338 return pos - buf; 4339 pos += ret; 4340 chnl = wpa_s->hw.modes[j].channels; 4341 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4342 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4343 continue; 4344 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n", 4345 chnl[i].chan, chnl[i].freq, 4346 chnl[i].flag & HOSTAPD_CHAN_NO_IR ? 4347 " (NO_IR)" : "", 4348 chnl[i].flag & HOSTAPD_CHAN_RADAR ? 4349 " (DFS)" : ""); 4350 4351 if (os_snprintf_error(end - pos, ret)) 4352 return pos - buf; 4353 pos += ret; 4354 } 4355 ret = os_snprintf(pos, end - pos, "\n"); 4356 if (os_snprintf_error(end - pos, ret)) 4357 return pos - buf; 4358 pos += ret; 4359 } 4360 4361 return pos - buf; 4362 } 4363 4364 4365 static int wpa_supplicant_ctrl_iface_get_capability( 4366 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 4367 size_t buflen) 4368 { 4369 struct wpa_driver_capa capa; 4370 int res; 4371 char *strict; 4372 char field[30]; 4373 size_t len; 4374 4375 /* Determine whether or not strict checking was requested */ 4376 len = os_strlcpy(field, _field, sizeof(field)); 4377 if (len >= sizeof(field)) 4378 return -1; 4379 strict = os_strchr(field, ' '); 4380 if (strict != NULL) { 4381 *strict++ = '\0'; 4382 if (os_strcmp(strict, "strict") != 0) 4383 return -1; 4384 } 4385 4386 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 4387 field, strict ? strict : ""); 4388 4389 if (os_strcmp(field, "eap") == 0) { 4390 return eap_get_names(buf, buflen); 4391 } 4392 4393 res = wpa_drv_get_capa(wpa_s, &capa); 4394 4395 if (os_strcmp(field, "pairwise") == 0) 4396 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 4397 buf, buflen); 4398 4399 if (os_strcmp(field, "group") == 0) 4400 return ctrl_iface_get_capability_group(res, strict, &capa, 4401 buf, buflen); 4402 4403 if (os_strcmp(field, "group_mgmt") == 0) 4404 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa, 4405 buf, buflen); 4406 4407 if (os_strcmp(field, "key_mgmt") == 0) 4408 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 4409 buf, buflen); 4410 4411 if (os_strcmp(field, "proto") == 0) 4412 return ctrl_iface_get_capability_proto(res, strict, &capa, 4413 buf, buflen); 4414 4415 if (os_strcmp(field, "auth_alg") == 0) 4416 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict, 4417 &capa, buf, buflen); 4418 4419 if (os_strcmp(field, "modes") == 0) 4420 return ctrl_iface_get_capability_modes(res, strict, &capa, 4421 buf, buflen); 4422 4423 if (os_strcmp(field, "channels") == 0) 4424 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 4425 4426 if (os_strcmp(field, "freq") == 0) 4427 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen); 4428 4429 #ifdef CONFIG_TDLS 4430 if (os_strcmp(field, "tdls") == 0) 4431 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen); 4432 #endif /* CONFIG_TDLS */ 4433 4434 #ifdef CONFIG_ERP 4435 if (os_strcmp(field, "erp") == 0) { 4436 res = os_snprintf(buf, buflen, "ERP"); 4437 if (os_snprintf_error(buflen, res)) 4438 return -1; 4439 return res; 4440 } 4441 #endif /* CONFIG_EPR */ 4442 4443 #ifdef CONFIG_FIPS 4444 if (os_strcmp(field, "fips") == 0) { 4445 res = os_snprintf(buf, buflen, "FIPS"); 4446 if (os_snprintf_error(buflen, res)) 4447 return -1; 4448 return res; 4449 } 4450 #endif /* CONFIG_FIPS */ 4451 4452 #ifdef CONFIG_ACS 4453 if (os_strcmp(field, "acs") == 0) { 4454 res = os_snprintf(buf, buflen, "ACS"); 4455 if (os_snprintf_error(buflen, res)) 4456 return -1; 4457 return res; 4458 } 4459 #endif /* CONFIG_ACS */ 4460 4461 #ifdef CONFIG_FILS 4462 if (os_strcmp(field, "fils") == 0) { 4463 #ifdef CONFIG_FILS_SK_PFS 4464 if (wpa_is_fils_supported(wpa_s) && 4465 wpa_is_fils_sk_pfs_supported(wpa_s)) { 4466 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS"); 4467 if (os_snprintf_error(buflen, res)) 4468 return -1; 4469 return res; 4470 } 4471 #endif /* CONFIG_FILS_SK_PFS */ 4472 4473 if (wpa_is_fils_supported(wpa_s)) { 4474 res = os_snprintf(buf, buflen, "FILS"); 4475 if (os_snprintf_error(buflen, res)) 4476 return -1; 4477 return res; 4478 } 4479 } 4480 #endif /* CONFIG_FILS */ 4481 4482 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) { 4483 res = os_snprintf(buf, buflen, "MULTIBSS-STA"); 4484 if (os_snprintf_error(buflen, res)) 4485 return -1; 4486 return res; 4487 } 4488 4489 #ifdef CONFIG_DPP 4490 if (os_strcmp(field, "dpp") == 0) { 4491 #ifdef CONFIG_DPP2 4492 res = os_snprintf(buf, buflen, "DPP=2"); 4493 #else /* CONFIG_DPP2 */ 4494 res = os_snprintf(buf, buflen, "DPP=1"); 4495 #endif /* CONFIG_DPP2 */ 4496 if (os_snprintf_error(buflen, res)) 4497 return -1; 4498 return res; 4499 } 4500 #endif /* CONFIG_DPP */ 4501 4502 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 4503 field); 4504 4505 return -1; 4506 } 4507 4508 4509 #ifdef CONFIG_INTERWORKING 4510 static char * anqp_add_hex(char *pos, char *end, const char *title, 4511 struct wpabuf *data) 4512 { 4513 char *start = pos; 4514 size_t i; 4515 int ret; 4516 const u8 *d; 4517 4518 if (data == NULL) 4519 return start; 4520 4521 ret = os_snprintf(pos, end - pos, "%s=", title); 4522 if (os_snprintf_error(end - pos, ret)) 4523 return start; 4524 pos += ret; 4525 4526 d = wpabuf_head_u8(data); 4527 for (i = 0; i < wpabuf_len(data); i++) { 4528 ret = os_snprintf(pos, end - pos, "%02x", *d++); 4529 if (os_snprintf_error(end - pos, ret)) 4530 return start; 4531 pos += ret; 4532 } 4533 4534 ret = os_snprintf(pos, end - pos, "\n"); 4535 if (os_snprintf_error(end - pos, ret)) 4536 return start; 4537 pos += ret; 4538 4539 return pos; 4540 } 4541 #endif /* CONFIG_INTERWORKING */ 4542 4543 4544 #ifdef CONFIG_FILS 4545 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) 4546 { 4547 char *start = pos; 4548 const u8 *ie, *ie_end; 4549 u16 info, realms; 4550 int ret; 4551 4552 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); 4553 if (!ie) 4554 return 0; 4555 ie_end = ie + 2 + ie[1]; 4556 ie += 2; 4557 if (ie_end - ie < 2) 4558 return -1; 4559 4560 info = WPA_GET_LE16(ie); 4561 ie += 2; 4562 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info); 4563 if (os_snprintf_error(end - pos, ret)) 4564 return 0; 4565 pos += ret; 4566 4567 if (info & BIT(7)) { 4568 /* Cache Identifier Included */ 4569 if (ie_end - ie < 2) 4570 return -1; 4571 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n", 4572 ie[0], ie[1]); 4573 if (os_snprintf_error(end - pos, ret)) 4574 return 0; 4575 pos += ret; 4576 ie += 2; 4577 } 4578 4579 if (info & BIT(8)) { 4580 /* HESSID Included */ 4581 if (ie_end - ie < ETH_ALEN) 4582 return -1; 4583 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n", 4584 MAC2STR(ie)); 4585 if (os_snprintf_error(end - pos, ret)) 4586 return 0; 4587 pos += ret; 4588 ie += ETH_ALEN; 4589 } 4590 4591 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3; 4592 if (realms) { 4593 if (ie_end - ie < realms * 2) 4594 return -1; 4595 ret = os_snprintf(pos, end - pos, "fils_realms="); 4596 if (os_snprintf_error(end - pos, ret)) 4597 return 0; 4598 pos += ret; 4599 4600 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2); 4601 if (ret <= 0) 4602 return 0; 4603 pos += ret; 4604 ie += realms * 2; 4605 ret = os_snprintf(pos, end - pos, "\n"); 4606 if (os_snprintf_error(end - pos, ret)) 4607 return 0; 4608 pos += ret; 4609 } 4610 4611 return pos - start; 4612 } 4613 #endif /* CONFIG_FILS */ 4614 4615 4616 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 4617 unsigned long mask, char *buf, size_t buflen) 4618 { 4619 size_t i; 4620 int ret; 4621 char *pos, *end; 4622 const u8 *ie, *ie2, *osen_ie, *mesh, *owe; 4623 4624 pos = buf; 4625 end = buf + buflen; 4626 4627 if (mask & WPA_BSS_MASK_ID) { 4628 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 4629 if (os_snprintf_error(end - pos, ret)) 4630 return 0; 4631 pos += ret; 4632 } 4633 4634 if (mask & WPA_BSS_MASK_BSSID) { 4635 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 4636 MAC2STR(bss->bssid)); 4637 if (os_snprintf_error(end - pos, ret)) 4638 return 0; 4639 pos += ret; 4640 } 4641 4642 if (mask & WPA_BSS_MASK_FREQ) { 4643 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 4644 if (os_snprintf_error(end - pos, ret)) 4645 return 0; 4646 pos += ret; 4647 } 4648 4649 if (mask & WPA_BSS_MASK_BEACON_INT) { 4650 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 4651 bss->beacon_int); 4652 if (os_snprintf_error(end - pos, ret)) 4653 return 0; 4654 pos += ret; 4655 } 4656 4657 if (mask & WPA_BSS_MASK_CAPABILITIES) { 4658 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 4659 bss->caps); 4660 if (os_snprintf_error(end - pos, ret)) 4661 return 0; 4662 pos += ret; 4663 } 4664 4665 if (mask & WPA_BSS_MASK_QUAL) { 4666 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 4667 if (os_snprintf_error(end - pos, ret)) 4668 return 0; 4669 pos += ret; 4670 } 4671 4672 if (mask & WPA_BSS_MASK_NOISE) { 4673 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 4674 if (os_snprintf_error(end - pos, ret)) 4675 return 0; 4676 pos += ret; 4677 } 4678 4679 if (mask & WPA_BSS_MASK_LEVEL) { 4680 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 4681 if (os_snprintf_error(end - pos, ret)) 4682 return 0; 4683 pos += ret; 4684 } 4685 4686 if (mask & WPA_BSS_MASK_TSF) { 4687 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 4688 (unsigned long long) bss->tsf); 4689 if (os_snprintf_error(end - pos, ret)) 4690 return 0; 4691 pos += ret; 4692 } 4693 4694 if (mask & WPA_BSS_MASK_AGE) { 4695 struct os_reltime now; 4696 4697 os_get_reltime(&now); 4698 ret = os_snprintf(pos, end - pos, "age=%d\n", 4699 (int) (now.sec - bss->last_update.sec)); 4700 if (os_snprintf_error(end - pos, ret)) 4701 return 0; 4702 pos += ret; 4703 } 4704 4705 if (mask & WPA_BSS_MASK_IE) { 4706 ret = os_snprintf(pos, end - pos, "ie="); 4707 if (os_snprintf_error(end - pos, ret)) 4708 return 0; 4709 pos += ret; 4710 4711 ie = (const u8 *) (bss + 1); 4712 for (i = 0; i < bss->ie_len; i++) { 4713 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 4714 if (os_snprintf_error(end - pos, ret)) 4715 return 0; 4716 pos += ret; 4717 } 4718 4719 ret = os_snprintf(pos, end - pos, "\n"); 4720 if (os_snprintf_error(end - pos, ret)) 4721 return 0; 4722 pos += ret; 4723 } 4724 4725 if (mask & WPA_BSS_MASK_FLAGS) { 4726 ret = os_snprintf(pos, end - pos, "flags="); 4727 if (os_snprintf_error(end - pos, ret)) 4728 return 0; 4729 pos += ret; 4730 4731 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 4732 4733 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 4734 if (ie) 4735 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 4736 2 + ie[1]); 4737 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 4738 if (ie2) 4739 pos = wpa_supplicant_ie_txt(pos, end, 4740 mesh ? "RSN" : "WPA2", ie2, 4741 2 + ie2[1]); 4742 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 4743 if (osen_ie) 4744 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 4745 osen_ie, 2 + osen_ie[1]); 4746 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 4747 if (owe) { 4748 ret = os_snprintf( 4749 pos, end - pos, 4750 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 4751 if (os_snprintf_error(end - pos, ret)) 4752 return 0; 4753 pos += ret; 4754 } 4755 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 4756 if (!ie && !ie2 && !osen_ie && 4757 (bss->caps & IEEE80211_CAP_PRIVACY)) { 4758 ret = os_snprintf(pos, end - pos, "[WEP]"); 4759 if (os_snprintf_error(end - pos, ret)) 4760 return 0; 4761 pos += ret; 4762 } 4763 4764 if (mesh) { 4765 ret = os_snprintf(pos, end - pos, "[MESH]"); 4766 if (os_snprintf_error(end - pos, ret)) 4767 return 0; 4768 pos += ret; 4769 } 4770 4771 if (bss_is_dmg(bss)) { 4772 const char *s; 4773 ret = os_snprintf(pos, end - pos, "[DMG]"); 4774 if (os_snprintf_error(end - pos, ret)) 4775 return 0; 4776 pos += ret; 4777 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 4778 case IEEE80211_CAP_DMG_IBSS: 4779 s = "[IBSS]"; 4780 break; 4781 case IEEE80211_CAP_DMG_AP: 4782 s = "[ESS]"; 4783 break; 4784 case IEEE80211_CAP_DMG_PBSS: 4785 s = "[PBSS]"; 4786 break; 4787 default: 4788 s = ""; 4789 break; 4790 } 4791 ret = os_snprintf(pos, end - pos, "%s", s); 4792 if (os_snprintf_error(end - pos, ret)) 4793 return 0; 4794 pos += ret; 4795 } else { 4796 if (bss->caps & IEEE80211_CAP_IBSS) { 4797 ret = os_snprintf(pos, end - pos, "[IBSS]"); 4798 if (os_snprintf_error(end - pos, ret)) 4799 return 0; 4800 pos += ret; 4801 } 4802 if (bss->caps & IEEE80211_CAP_ESS) { 4803 ret = os_snprintf(pos, end - pos, "[ESS]"); 4804 if (os_snprintf_error(end - pos, ret)) 4805 return 0; 4806 pos += ret; 4807 } 4808 } 4809 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || 4810 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { 4811 ret = os_snprintf(pos, end - pos, "[P2P]"); 4812 if (os_snprintf_error(end - pos, ret)) 4813 return 0; 4814 pos += ret; 4815 } 4816 #ifdef CONFIG_HS20 4817 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 4818 ret = os_snprintf(pos, end - pos, "[HS20]"); 4819 if (os_snprintf_error(end - pos, ret)) 4820 return 0; 4821 pos += ret; 4822 } 4823 #endif /* CONFIG_HS20 */ 4824 #ifdef CONFIG_FILS 4825 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 4826 ret = os_snprintf(pos, end - pos, "[FILS]"); 4827 if (os_snprintf_error(end - pos, ret)) 4828 return 0; 4829 pos += ret; 4830 } 4831 #endif /* CONFIG_FILS */ 4832 #ifdef CONFIG_FST 4833 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 4834 ret = os_snprintf(pos, end - pos, "[FST]"); 4835 if (os_snprintf_error(end - pos, ret)) 4836 return 0; 4837 pos += ret; 4838 } 4839 #endif /* CONFIG_FST */ 4840 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 4841 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 4842 if (os_snprintf_error(end - pos, ret)) 4843 return 0; 4844 pos += ret; 4845 } 4846 4847 ret = os_snprintf(pos, end - pos, "\n"); 4848 if (os_snprintf_error(end - pos, ret)) 4849 return 0; 4850 pos += ret; 4851 } 4852 4853 if (mask & WPA_BSS_MASK_SSID) { 4854 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 4855 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 4856 if (os_snprintf_error(end - pos, ret)) 4857 return 0; 4858 pos += ret; 4859 } 4860 4861 #ifdef CONFIG_WPS 4862 if (mask & WPA_BSS_MASK_WPS_SCAN) { 4863 ie = (const u8 *) (bss + 1); 4864 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 4865 if (ret >= end - pos) 4866 return 0; 4867 if (ret > 0) 4868 pos += ret; 4869 } 4870 #endif /* CONFIG_WPS */ 4871 4872 #ifdef CONFIG_P2P 4873 if (mask & WPA_BSS_MASK_P2P_SCAN) { 4874 ie = (const u8 *) (bss + 1); 4875 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 4876 if (ret >= end - pos) 4877 return 0; 4878 if (ret > 0) 4879 pos += ret; 4880 } 4881 #endif /* CONFIG_P2P */ 4882 4883 #ifdef CONFIG_WIFI_DISPLAY 4884 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 4885 struct wpabuf *wfd; 4886 ie = (const u8 *) (bss + 1); 4887 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 4888 WFD_IE_VENDOR_TYPE); 4889 if (wfd) { 4890 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 4891 if (os_snprintf_error(end - pos, ret)) { 4892 wpabuf_free(wfd); 4893 return 0; 4894 } 4895 pos += ret; 4896 4897 pos += wpa_snprintf_hex(pos, end - pos, 4898 wpabuf_head(wfd), 4899 wpabuf_len(wfd)); 4900 wpabuf_free(wfd); 4901 4902 ret = os_snprintf(pos, end - pos, "\n"); 4903 if (os_snprintf_error(end - pos, ret)) 4904 return 0; 4905 pos += ret; 4906 } 4907 } 4908 #endif /* CONFIG_WIFI_DISPLAY */ 4909 4910 #ifdef CONFIG_INTERWORKING 4911 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 4912 struct wpa_bss_anqp *anqp = bss->anqp; 4913 struct wpa_bss_anqp_elem *elem; 4914 4915 pos = anqp_add_hex(pos, end, "anqp_capability_list", 4916 anqp->capability_list); 4917 pos = anqp_add_hex(pos, end, "anqp_venue_name", 4918 anqp->venue_name); 4919 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 4920 anqp->network_auth_type); 4921 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 4922 anqp->roaming_consortium); 4923 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 4924 anqp->ip_addr_type_availability); 4925 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 4926 anqp->nai_realm); 4927 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 4928 pos = anqp_add_hex(pos, end, "anqp_domain_name", 4929 anqp->domain_name); 4930 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info", 4931 anqp->fils_realm_info); 4932 #ifdef CONFIG_HS20 4933 pos = anqp_add_hex(pos, end, "hs20_capability_list", 4934 anqp->hs20_capability_list); 4935 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 4936 anqp->hs20_operator_friendly_name); 4937 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 4938 anqp->hs20_wan_metrics); 4939 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 4940 anqp->hs20_connection_capability); 4941 pos = anqp_add_hex(pos, end, "hs20_operating_class", 4942 anqp->hs20_operating_class); 4943 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", 4944 anqp->hs20_osu_providers_list); 4945 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", 4946 anqp->hs20_operator_icon_metadata); 4947 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", 4948 anqp->hs20_osu_providers_nai_list); 4949 #endif /* CONFIG_HS20 */ 4950 4951 dl_list_for_each(elem, &anqp->anqp_elems, 4952 struct wpa_bss_anqp_elem, list) { 4953 char title[20]; 4954 4955 os_snprintf(title, sizeof(title), "anqp[%u]", 4956 elem->infoid); 4957 pos = anqp_add_hex(pos, end, title, elem->payload); 4958 } 4959 } 4960 #endif /* CONFIG_INTERWORKING */ 4961 4962 #ifdef CONFIG_MESH 4963 if (mask & WPA_BSS_MASK_MESH_SCAN) { 4964 ie = (const u8 *) (bss + 1); 4965 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); 4966 if (ret >= end - pos) 4967 return 0; 4968 if (ret > 0) 4969 pos += ret; 4970 } 4971 #endif /* CONFIG_MESH */ 4972 4973 if (mask & WPA_BSS_MASK_SNR) { 4974 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr); 4975 if (os_snprintf_error(end - pos, ret)) 4976 return 0; 4977 pos += ret; 4978 } 4979 4980 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) { 4981 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n", 4982 bss->est_throughput); 4983 if (os_snprintf_error(end - pos, ret)) 4984 return 0; 4985 pos += ret; 4986 } 4987 4988 #ifdef CONFIG_FST 4989 if (mask & WPA_BSS_MASK_FST) { 4990 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos); 4991 if (ret < 0 || ret >= end - pos) 4992 return 0; 4993 pos += ret; 4994 } 4995 #endif /* CONFIG_FST */ 4996 4997 if (mask & WPA_BSS_MASK_UPDATE_IDX) { 4998 ret = os_snprintf(pos, end - pos, "update_idx=%u\n", 4999 bss->last_update_idx); 5000 if (os_snprintf_error(end - pos, ret)) 5001 return 0; 5002 pos += ret; 5003 } 5004 5005 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) { 5006 ret = os_snprintf(pos, end - pos, "beacon_ie="); 5007 if (os_snprintf_error(end - pos, ret)) 5008 return 0; 5009 pos += ret; 5010 5011 ie = (const u8 *) (bss + 1); 5012 ie += bss->ie_len; 5013 for (i = 0; i < bss->beacon_ie_len; i++) { 5014 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 5015 if (os_snprintf_error(end - pos, ret)) 5016 return 0; 5017 pos += ret; 5018 } 5019 5020 ret = os_snprintf(pos, end - pos, "\n"); 5021 if (os_snprintf_error(end - pos, ret)) 5022 return 0; 5023 pos += ret; 5024 } 5025 5026 #ifdef CONFIG_FILS 5027 if (mask & WPA_BSS_MASK_FILS_INDICATION) { 5028 ret = print_fils_indication(bss, pos, end); 5029 if (ret < 0) 5030 return 0; 5031 pos += ret; 5032 } 5033 #endif /* CONFIG_FILS */ 5034 5035 if (mask & WPA_BSS_MASK_DELIM) { 5036 ret = os_snprintf(pos, end - pos, "====\n"); 5037 if (os_snprintf_error(end - pos, ret)) 5038 return 0; 5039 pos += ret; 5040 } 5041 5042 return pos - buf; 5043 } 5044 5045 5046 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 5047 const char *cmd, char *buf, 5048 size_t buflen) 5049 { 5050 u8 bssid[ETH_ALEN]; 5051 size_t i; 5052 struct wpa_bss *bss; 5053 struct wpa_bss *bsslast = NULL; 5054 struct dl_list *next; 5055 int ret = 0; 5056 int len; 5057 char *ctmp, *end = buf + buflen; 5058 unsigned long mask = WPA_BSS_MASK_ALL; 5059 5060 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 5061 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 5062 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 5063 list_id); 5064 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 5065 list_id); 5066 } else { /* N1-N2 */ 5067 unsigned int id1, id2; 5068 5069 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 5070 wpa_printf(MSG_INFO, "Wrong BSS range " 5071 "format"); 5072 return 0; 5073 } 5074 5075 if (*(cmd + 6) == '-') 5076 id1 = 0; 5077 else 5078 id1 = atoi(cmd + 6); 5079 ctmp++; 5080 if (*ctmp >= '0' && *ctmp <= '9') 5081 id2 = atoi(ctmp); 5082 else 5083 id2 = (unsigned int) -1; 5084 bss = wpa_bss_get_id_range(wpa_s, id1, id2); 5085 if (id2 == (unsigned int) -1) 5086 bsslast = dl_list_last(&wpa_s->bss_id, 5087 struct wpa_bss, 5088 list_id); 5089 else { 5090 bsslast = wpa_bss_get_id(wpa_s, id2); 5091 if (bsslast == NULL && bss && id2 > id1) { 5092 struct wpa_bss *tmp = bss; 5093 for (;;) { 5094 next = tmp->list_id.next; 5095 if (next == &wpa_s->bss_id) 5096 break; 5097 tmp = dl_list_entry( 5098 next, struct wpa_bss, 5099 list_id); 5100 if (tmp->id > id2) 5101 break; 5102 bsslast = tmp; 5103 } 5104 } 5105 } 5106 } 5107 } else if (os_strncmp(cmd, "FIRST", 5) == 0) 5108 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 5109 else if (os_strncmp(cmd, "LAST", 4) == 0) 5110 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id); 5111 else if (os_strncmp(cmd, "ID-", 3) == 0) { 5112 i = atoi(cmd + 3); 5113 bss = wpa_bss_get_id(wpa_s, i); 5114 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 5115 i = atoi(cmd + 5); 5116 bss = wpa_bss_get_id(wpa_s, i); 5117 if (bss) { 5118 next = bss->list_id.next; 5119 if (next == &wpa_s->bss_id) 5120 bss = NULL; 5121 else 5122 bss = dl_list_entry(next, struct wpa_bss, 5123 list_id); 5124 } 5125 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) { 5126 bss = wpa_s->current_bss; 5127 #ifdef CONFIG_P2P 5128 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 5129 if (hwaddr_aton(cmd + 13, bssid) == 0) 5130 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 5131 else 5132 bss = NULL; 5133 #endif /* CONFIG_P2P */ 5134 } else if (hwaddr_aton(cmd, bssid) == 0) 5135 bss = wpa_bss_get_bssid(wpa_s, bssid); 5136 else { 5137 struct wpa_bss *tmp; 5138 i = atoi(cmd); 5139 bss = NULL; 5140 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 5141 { 5142 if (i == 0) { 5143 bss = tmp; 5144 break; 5145 } 5146 i--; 5147 } 5148 } 5149 5150 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 5151 mask = strtoul(ctmp + 5, NULL, 0x10); 5152 if (mask == 0) 5153 mask = WPA_BSS_MASK_ALL; 5154 } 5155 5156 if (bss == NULL) 5157 return 0; 5158 5159 if (bsslast == NULL) 5160 bsslast = bss; 5161 do { 5162 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 5163 ret += len; 5164 buf += len; 5165 buflen -= len; 5166 if (bss == bsslast) { 5167 if ((mask & WPA_BSS_MASK_DELIM) && len && 5168 (bss == dl_list_last(&wpa_s->bss_id, 5169 struct wpa_bss, list_id))) { 5170 int res; 5171 5172 res = os_snprintf(buf - 5, end - buf + 5, 5173 "####\n"); 5174 if (os_snprintf_error(end - buf + 5, res)) { 5175 wpa_printf(MSG_DEBUG, 5176 "Could not add end delim"); 5177 } 5178 } 5179 break; 5180 } 5181 next = bss->list_id.next; 5182 if (next == &wpa_s->bss_id) 5183 break; 5184 bss = dl_list_entry(next, struct wpa_bss, list_id); 5185 } while (bss && len); 5186 5187 return ret; 5188 } 5189 5190 5191 static int wpa_supplicant_ctrl_iface_ap_scan( 5192 struct wpa_supplicant *wpa_s, char *cmd) 5193 { 5194 int ap_scan = atoi(cmd); 5195 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 5196 } 5197 5198 5199 static int wpa_supplicant_ctrl_iface_scan_interval( 5200 struct wpa_supplicant *wpa_s, char *cmd) 5201 { 5202 int scan_int = atoi(cmd); 5203 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 5204 } 5205 5206 5207 static int wpa_supplicant_ctrl_iface_bss_expire_age( 5208 struct wpa_supplicant *wpa_s, char *cmd) 5209 { 5210 int expire_age = atoi(cmd); 5211 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 5212 } 5213 5214 5215 static int wpa_supplicant_ctrl_iface_bss_expire_count( 5216 struct wpa_supplicant *wpa_s, char *cmd) 5217 { 5218 int expire_count = atoi(cmd); 5219 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 5220 } 5221 5222 5223 static void wpa_supplicant_ctrl_iface_bss_flush( 5224 struct wpa_supplicant *wpa_s, char *cmd) 5225 { 5226 int flush_age = atoi(cmd); 5227 5228 if (flush_age == 0) 5229 wpa_bss_flush(wpa_s); 5230 else 5231 wpa_bss_flush_by_age(wpa_s, flush_age); 5232 } 5233 5234 5235 #ifdef CONFIG_TESTING_OPTIONS 5236 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 5237 { 5238 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 5239 /* MLME-DELETEKEYS.request */ 5240 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 5241 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 5242 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 5243 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 5244 #ifdef CONFIG_IEEE80211W 5245 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 5246 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 5247 #endif /* CONFIG_IEEE80211W */ 5248 5249 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 5250 0); 5251 /* MLME-SETPROTECTION.request(None) */ 5252 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 5253 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 5254 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 5255 wpa_sm_drop_sa(wpa_s->wpa); 5256 } 5257 #endif /* CONFIG_TESTING_OPTIONS */ 5258 5259 5260 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 5261 char *addr) 5262 { 5263 #ifdef CONFIG_NO_SCAN_PROCESSING 5264 return -1; 5265 #else /* CONFIG_NO_SCAN_PROCESSING */ 5266 u8 bssid[ETH_ALEN]; 5267 struct wpa_bss *bss; 5268 struct wpa_ssid *ssid = wpa_s->current_ssid; 5269 5270 if (hwaddr_aton(addr, bssid)) { 5271 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 5272 "address '%s'", addr); 5273 return -1; 5274 } 5275 5276 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 5277 5278 if (!ssid) { 5279 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 5280 "configuration known for the target AP"); 5281 return -1; 5282 } 5283 5284 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 5285 if (!bss) { 5286 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 5287 "from BSS table"); 5288 return -1; 5289 } 5290 5291 /* 5292 * TODO: Find best network configuration block from configuration to 5293 * allow roaming to other networks 5294 */ 5295 5296 wpa_s->reassociate = 1; 5297 wpa_supplicant_connect(wpa_s, bss, ssid); 5298 5299 return 0; 5300 #endif /* CONFIG_NO_SCAN_PROCESSING */ 5301 } 5302 5303 5304 #ifdef CONFIG_P2P 5305 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 5306 { 5307 unsigned int timeout = atoi(cmd); 5308 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 5309 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 5310 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL; 5311 char *pos; 5312 unsigned int search_delay; 5313 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL; 5314 u8 seek_count = 0; 5315 int freq = 0; 5316 5317 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 5318 wpa_dbg(wpa_s, MSG_INFO, 5319 "Reject P2P_FIND since interface is disabled"); 5320 return -1; 5321 } 5322 if (os_strstr(cmd, "type=social")) 5323 type = P2P_FIND_ONLY_SOCIAL; 5324 else if (os_strstr(cmd, "type=progressive")) 5325 type = P2P_FIND_PROGRESSIVE; 5326 5327 pos = os_strstr(cmd, "dev_id="); 5328 if (pos) { 5329 pos += 7; 5330 if (hwaddr_aton(pos, dev_id)) 5331 return -1; 5332 _dev_id = dev_id; 5333 } 5334 5335 pos = os_strstr(cmd, "dev_type="); 5336 if (pos) { 5337 pos += 9; 5338 if (wps_dev_type_str2bin(pos, dev_type) < 0) 5339 return -1; 5340 _dev_type = dev_type; 5341 } 5342 5343 pos = os_strstr(cmd, "delay="); 5344 if (pos) { 5345 pos += 6; 5346 search_delay = atoi(pos); 5347 } else 5348 search_delay = wpas_p2p_search_delay(wpa_s); 5349 5350 pos = os_strstr(cmd, "freq="); 5351 if (pos) { 5352 pos += 5; 5353 freq = atoi(pos); 5354 if (freq <= 0) 5355 return -1; 5356 } 5357 5358 /* Must be searched for last, because it adds nul termination */ 5359 pos = os_strstr(cmd, " seek="); 5360 if (pos) 5361 pos += 6; 5362 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) { 5363 char *term; 5364 5365 _seek[seek_count++] = pos; 5366 seek = _seek; 5367 term = os_strchr(pos, ' '); 5368 if (!term) 5369 break; 5370 *term = '\0'; 5371 pos = os_strstr(term + 1, "seek="); 5372 if (pos) 5373 pos += 5; 5374 } 5375 if (seek_count > P2P_MAX_QUERY_HASH) { 5376 seek[0] = NULL; 5377 seek_count = 1; 5378 } 5379 5380 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type, 5381 _dev_id, search_delay, seek_count, seek, freq); 5382 } 5383 5384 5385 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt) 5386 { 5387 const char *last = NULL; 5388 const char *token; 5389 long int token_len; 5390 unsigned int i; 5391 5392 /* Expected predefined CPT names delimited by ':' */ 5393 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) { 5394 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) { 5395 wpa_printf(MSG_ERROR, 5396 "P2PS: CPT name list is too long, expected up to %d names", 5397 P2PS_FEATURE_CAPAB_CPT_MAX); 5398 cpt[0] = 0; 5399 return -1; 5400 } 5401 5402 token_len = last - token; 5403 5404 if (token_len == 3 && 5405 os_memcmp(token, "UDP", token_len) == 0) { 5406 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 5407 } else if (token_len == 3 && 5408 os_memcmp(token, "MAC", token_len) == 0) { 5409 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT; 5410 } else { 5411 wpa_printf(MSG_ERROR, 5412 "P2PS: Unsupported CPT name '%s'", token); 5413 cpt[0] = 0; 5414 return -1; 5415 } 5416 5417 if (isblank((unsigned char) *last)) { 5418 i++; 5419 break; 5420 } 5421 } 5422 cpt[i] = 0; 5423 return 0; 5424 } 5425 5426 5427 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd) 5428 { 5429 struct p2ps_provision *p2ps_prov; 5430 char *pos; 5431 size_t info_len = 0; 5432 char *info = NULL; 5433 u8 role = P2PS_SETUP_NONE; 5434 long long unsigned val; 5435 int i; 5436 5437 pos = os_strstr(cmd, "info="); 5438 if (pos) { 5439 pos += 5; 5440 info_len = os_strlen(pos); 5441 5442 if (info_len) { 5443 info = os_malloc(info_len + 1); 5444 if (info) { 5445 info_len = utf8_unescape(pos, info_len, 5446 info, info_len + 1); 5447 } else 5448 info_len = 0; 5449 } 5450 } 5451 5452 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1); 5453 if (p2ps_prov == NULL) { 5454 os_free(info); 5455 return NULL; 5456 } 5457 5458 if (info) { 5459 os_memcpy(p2ps_prov->info, info, info_len); 5460 p2ps_prov->info[info_len] = '\0'; 5461 os_free(info); 5462 } 5463 5464 pos = os_strstr(cmd, "status="); 5465 if (pos) 5466 p2ps_prov->status = atoi(pos + 7); 5467 else 5468 p2ps_prov->status = -1; 5469 5470 pos = os_strstr(cmd, "adv_id="); 5471 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL) 5472 goto invalid_args; 5473 p2ps_prov->adv_id = val; 5474 5475 pos = os_strstr(cmd, "method="); 5476 if (pos) 5477 p2ps_prov->method = strtol(pos + 7, NULL, 16); 5478 else 5479 p2ps_prov->method = 0; 5480 5481 pos = os_strstr(cmd, "session="); 5482 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL) 5483 goto invalid_args; 5484 p2ps_prov->session_id = val; 5485 5486 pos = os_strstr(cmd, "adv_mac="); 5487 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac)) 5488 goto invalid_args; 5489 5490 pos = os_strstr(cmd, "session_mac="); 5491 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac)) 5492 goto invalid_args; 5493 5494 pos = os_strstr(cmd, "cpt="); 5495 if (pos) { 5496 if (p2ps_ctrl_parse_cpt_priority(pos + 4, 5497 p2ps_prov->cpt_priority)) 5498 goto invalid_args; 5499 } else { 5500 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 5501 } 5502 5503 for (i = 0; p2ps_prov->cpt_priority[i]; i++) 5504 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i]; 5505 5506 /* force conncap with tstCap (no sanity checks) */ 5507 pos = os_strstr(cmd, "tstCap="); 5508 if (pos) { 5509 role = strtol(pos + 7, NULL, 16); 5510 } else { 5511 pos = os_strstr(cmd, "role="); 5512 if (pos) { 5513 role = strtol(pos + 5, NULL, 16); 5514 if (role != P2PS_SETUP_CLIENT && 5515 role != P2PS_SETUP_GROUP_OWNER) 5516 role = P2PS_SETUP_NONE; 5517 } 5518 } 5519 p2ps_prov->role = role; 5520 5521 return p2ps_prov; 5522 5523 invalid_args: 5524 os_free(p2ps_prov); 5525 return NULL; 5526 } 5527 5528 5529 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd) 5530 { 5531 u8 addr[ETH_ALEN]; 5532 struct p2ps_provision *p2ps_prov; 5533 char *pos; 5534 5535 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */ 5536 5537 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 5538 5539 if (hwaddr_aton(cmd, addr)) 5540 return -1; 5541 5542 pos = cmd + 17; 5543 if (*pos != ' ') 5544 return -1; 5545 5546 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 5547 if (!p2ps_prov) 5548 return -1; 5549 5550 if (p2ps_prov->status < 0) { 5551 os_free(p2ps_prov); 5552 return -1; 5553 } 5554 5555 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 5556 p2ps_prov); 5557 } 5558 5559 5560 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd) 5561 { 5562 u8 addr[ETH_ALEN]; 5563 struct p2ps_provision *p2ps_prov; 5564 char *pos; 5565 5566 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap> 5567 * session=<ses_id> mac=<ses_mac> [info=<infodata>] 5568 */ 5569 5570 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 5571 if (hwaddr_aton(cmd, addr)) 5572 return -1; 5573 5574 pos = cmd + 17; 5575 if (*pos != ' ') 5576 return -1; 5577 5578 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 5579 if (!p2ps_prov) 5580 return -1; 5581 5582 p2ps_prov->pd_seeker = 1; 5583 5584 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 5585 p2ps_prov); 5586 } 5587 5588 5589 static int parse_freq(int chwidth, int freq2) 5590 { 5591 if (freq2 < 0) 5592 return -1; 5593 if (freq2) 5594 return CHANWIDTH_80P80MHZ; 5595 5596 switch (chwidth) { 5597 case 0: 5598 case 20: 5599 case 40: 5600 return CHANWIDTH_USE_HT; 5601 case 80: 5602 return CHANWIDTH_80MHZ; 5603 case 160: 5604 return CHANWIDTH_160MHZ; 5605 default: 5606 wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d", 5607 chwidth); 5608 return -1; 5609 } 5610 } 5611 5612 5613 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 5614 char *buf, size_t buflen) 5615 { 5616 u8 addr[ETH_ALEN]; 5617 char *pos, *pos2; 5618 char *pin = NULL; 5619 enum p2p_wps_method wps_method; 5620 int new_pin; 5621 int ret; 5622 int persistent_group, persistent_id = -1; 5623 int join; 5624 int auth; 5625 int automatic; 5626 int go_intent = -1; 5627 int freq = 0; 5628 int pd; 5629 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; 5630 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; 5631 size_t group_ssid_len = 0; 5632 int he; 5633 5634 if (!wpa_s->global->p2p_init_wpa_s) 5635 return -1; 5636 if (wpa_s->global->p2p_init_wpa_s != wpa_s) { 5637 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s", 5638 wpa_s->global->p2p_init_wpa_s->ifname); 5639 wpa_s = wpa_s->global->p2p_init_wpa_s; 5640 } 5641 5642 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] 5643 * [persistent|persistent=<network id>] 5644 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 5645 * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */ 5646 5647 if (hwaddr_aton(cmd, addr)) 5648 return -1; 5649 5650 pos = cmd + 17; 5651 if (*pos != ' ') 5652 return -1; 5653 pos++; 5654 5655 persistent_group = os_strstr(pos, " persistent") != NULL; 5656 pos2 = os_strstr(pos, " persistent="); 5657 if (pos2) { 5658 struct wpa_ssid *ssid; 5659 persistent_id = atoi(pos2 + 12); 5660 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 5661 if (ssid == NULL || ssid->disabled != 2 || 5662 ssid->mode != WPAS_MODE_P2P_GO) { 5663 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 5664 "SSID id=%d for persistent P2P group (GO)", 5665 persistent_id); 5666 return -1; 5667 } 5668 } 5669 join = os_strstr(pos, " join") != NULL; 5670 auth = os_strstr(pos, " auth") != NULL; 5671 automatic = os_strstr(pos, " auto") != NULL; 5672 pd = os_strstr(pos, " provdisc") != NULL; 5673 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 5674 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 5675 vht; 5676 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 5677 5678 pos2 = os_strstr(pos, " go_intent="); 5679 if (pos2) { 5680 pos2 += 11; 5681 go_intent = atoi(pos2); 5682 if (go_intent < 0 || go_intent > 15) 5683 return -1; 5684 } 5685 5686 pos2 = os_strstr(pos, " freq="); 5687 if (pos2) { 5688 pos2 += 6; 5689 freq = atoi(pos2); 5690 if (freq <= 0) 5691 return -1; 5692 } 5693 5694 pos2 = os_strstr(pos, " freq2="); 5695 if (pos2) 5696 freq2 = atoi(pos2 + 7); 5697 5698 pos2 = os_strstr(pos, " max_oper_chwidth="); 5699 if (pos2) 5700 chwidth = atoi(pos2 + 18); 5701 5702 max_oper_chwidth = parse_freq(chwidth, freq2); 5703 if (max_oper_chwidth < 0) 5704 return -1; 5705 5706 pos2 = os_strstr(pos, " ssid="); 5707 if (pos2) { 5708 char *end; 5709 5710 pos2 += 6; 5711 end = os_strchr(pos2, ' '); 5712 if (!end) 5713 group_ssid_len = os_strlen(pos2) / 2; 5714 else 5715 group_ssid_len = (end - pos2) / 2; 5716 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN || 5717 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0) 5718 return -1; 5719 group_ssid = _group_ssid; 5720 } 5721 5722 if (os_strncmp(pos, "pin", 3) == 0) { 5723 /* Request random PIN (to be displayed) and enable the PIN */ 5724 wps_method = WPS_PIN_DISPLAY; 5725 } else if (os_strncmp(pos, "pbc", 3) == 0) { 5726 wps_method = WPS_PBC; 5727 } else if (os_strstr(pos, "p2ps") != NULL) { 5728 wps_method = WPS_P2PS; 5729 } else { 5730 pin = pos; 5731 pos = os_strchr(pin, ' '); 5732 wps_method = WPS_PIN_KEYPAD; 5733 if (pos) { 5734 *pos++ = '\0'; 5735 if (os_strncmp(pos, "display", 7) == 0) 5736 wps_method = WPS_PIN_DISPLAY; 5737 } 5738 if (!wps_pin_str_valid(pin)) { 5739 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 5740 return 17; 5741 } 5742 } 5743 5744 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 5745 persistent_group, automatic, join, 5746 auth, go_intent, freq, freq2, persistent_id, 5747 pd, ht40, vht, max_oper_chwidth, he, 5748 group_ssid, group_ssid_len); 5749 if (new_pin == -2) { 5750 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 5751 return 25; 5752 } 5753 if (new_pin == -3) { 5754 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 5755 return 25; 5756 } 5757 if (new_pin < 0) 5758 return -1; 5759 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 5760 ret = os_snprintf(buf, buflen, "%08d", new_pin); 5761 if (os_snprintf_error(buflen, ret)) 5762 return -1; 5763 return ret; 5764 } 5765 5766 os_memcpy(buf, "OK\n", 3); 5767 return 3; 5768 } 5769 5770 5771 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 5772 { 5773 unsigned int timeout = atoi(cmd); 5774 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 5775 wpa_dbg(wpa_s, MSG_INFO, 5776 "Reject P2P_LISTEN since interface is disabled"); 5777 return -1; 5778 } 5779 return wpas_p2p_listen(wpa_s, timeout); 5780 } 5781 5782 5783 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 5784 { 5785 u8 addr[ETH_ALEN]; 5786 char *pos; 5787 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 5788 5789 /* <addr> <config method> [join|auto] */ 5790 5791 if (hwaddr_aton(cmd, addr)) 5792 return -1; 5793 5794 pos = cmd + 17; 5795 if (*pos != ' ') 5796 return -1; 5797 pos++; 5798 5799 if (os_strstr(pos, " join") != NULL) 5800 use = WPAS_P2P_PD_FOR_JOIN; 5801 else if (os_strstr(pos, " auto") != NULL) 5802 use = WPAS_P2P_PD_AUTO; 5803 5804 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL); 5805 } 5806 5807 5808 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 5809 size_t buflen) 5810 { 5811 struct wpa_ssid *ssid = wpa_s->current_ssid; 5812 5813 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 5814 ssid->passphrase == NULL) 5815 return -1; 5816 5817 os_strlcpy(buf, ssid->passphrase, buflen); 5818 return os_strlen(buf); 5819 } 5820 5821 5822 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 5823 char *buf, size_t buflen) 5824 { 5825 u64 ref; 5826 int res; 5827 u8 dst_buf[ETH_ALEN], *dst; 5828 struct wpabuf *tlvs; 5829 char *pos; 5830 size_t len; 5831 5832 if (hwaddr_aton(cmd, dst_buf)) 5833 return -1; 5834 dst = dst_buf; 5835 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 5836 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 5837 dst = NULL; 5838 pos = cmd + 17; 5839 if (*pos != ' ') 5840 return -1; 5841 pos++; 5842 5843 if (os_strncmp(pos, "upnp ", 5) == 0) { 5844 u8 version; 5845 pos += 5; 5846 if (hexstr2bin(pos, &version, 1) < 0) 5847 return -1; 5848 pos += 2; 5849 if (*pos != ' ') 5850 return -1; 5851 pos++; 5852 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 5853 #ifdef CONFIG_WIFI_DISPLAY 5854 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 5855 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 5856 #endif /* CONFIG_WIFI_DISPLAY */ 5857 } else if (os_strncmp(pos, "asp ", 4) == 0) { 5858 char *svc_str; 5859 char *svc_info = NULL; 5860 u32 id; 5861 5862 pos += 4; 5863 if (sscanf(pos, "%x", &id) != 1 || id > 0xff) 5864 return -1; 5865 5866 pos = os_strchr(pos, ' '); 5867 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ') 5868 return -1; 5869 5870 svc_str = pos + 1; 5871 5872 pos = os_strchr(svc_str, ' '); 5873 5874 if (pos) 5875 *pos++ = '\0'; 5876 5877 /* All remaining data is the svc_info string */ 5878 if (pos && pos[0] && pos[0] != ' ') { 5879 len = os_strlen(pos); 5880 5881 /* Unescape in place */ 5882 len = utf8_unescape(pos, len, pos, len); 5883 if (len > 0xff) 5884 return -1; 5885 5886 svc_info = pos; 5887 } 5888 5889 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id, 5890 svc_str, svc_info); 5891 } else { 5892 len = os_strlen(pos); 5893 if (len & 1) 5894 return -1; 5895 len /= 2; 5896 tlvs = wpabuf_alloc(len); 5897 if (tlvs == NULL) 5898 return -1; 5899 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 5900 wpabuf_free(tlvs); 5901 return -1; 5902 } 5903 5904 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 5905 wpabuf_free(tlvs); 5906 } 5907 if (ref == 0) 5908 return -1; 5909 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 5910 if (os_snprintf_error(buflen, res)) 5911 return -1; 5912 return res; 5913 } 5914 5915 5916 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 5917 char *cmd) 5918 { 5919 long long unsigned val; 5920 u64 req; 5921 if (sscanf(cmd, "%llx", &val) != 1) 5922 return -1; 5923 req = val; 5924 return wpas_p2p_sd_cancel_request(wpa_s, req); 5925 } 5926 5927 5928 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 5929 { 5930 int freq; 5931 u8 dst[ETH_ALEN]; 5932 u8 dialog_token; 5933 struct wpabuf *resp_tlvs; 5934 char *pos, *pos2; 5935 size_t len; 5936 5937 pos = os_strchr(cmd, ' '); 5938 if (pos == NULL) 5939 return -1; 5940 *pos++ = '\0'; 5941 freq = atoi(cmd); 5942 if (freq == 0) 5943 return -1; 5944 5945 if (hwaddr_aton(pos, dst)) 5946 return -1; 5947 pos += 17; 5948 if (*pos != ' ') 5949 return -1; 5950 pos++; 5951 5952 pos2 = os_strchr(pos, ' '); 5953 if (pos2 == NULL) 5954 return -1; 5955 *pos2++ = '\0'; 5956 dialog_token = atoi(pos); 5957 5958 len = os_strlen(pos2); 5959 if (len & 1) 5960 return -1; 5961 len /= 2; 5962 resp_tlvs = wpabuf_alloc(len); 5963 if (resp_tlvs == NULL) 5964 return -1; 5965 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 5966 wpabuf_free(resp_tlvs); 5967 return -1; 5968 } 5969 5970 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 5971 wpabuf_free(resp_tlvs); 5972 return 0; 5973 } 5974 5975 5976 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 5977 char *cmd) 5978 { 5979 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 5980 return -1; 5981 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 5982 return 0; 5983 } 5984 5985 5986 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 5987 char *cmd) 5988 { 5989 char *pos; 5990 size_t len; 5991 struct wpabuf *query, *resp; 5992 5993 pos = os_strchr(cmd, ' '); 5994 if (pos == NULL) 5995 return -1; 5996 *pos++ = '\0'; 5997 5998 len = os_strlen(cmd); 5999 if (len & 1) 6000 return -1; 6001 len /= 2; 6002 query = wpabuf_alloc(len); 6003 if (query == NULL) 6004 return -1; 6005 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 6006 wpabuf_free(query); 6007 return -1; 6008 } 6009 6010 len = os_strlen(pos); 6011 if (len & 1) { 6012 wpabuf_free(query); 6013 return -1; 6014 } 6015 len /= 2; 6016 resp = wpabuf_alloc(len); 6017 if (resp == NULL) { 6018 wpabuf_free(query); 6019 return -1; 6020 } 6021 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 6022 wpabuf_free(query); 6023 wpabuf_free(resp); 6024 return -1; 6025 } 6026 6027 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 6028 wpabuf_free(query); 6029 wpabuf_free(resp); 6030 return -1; 6031 } 6032 return 0; 6033 } 6034 6035 6036 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6037 { 6038 char *pos; 6039 u8 version; 6040 6041 pos = os_strchr(cmd, ' '); 6042 if (pos == NULL) 6043 return -1; 6044 *pos++ = '\0'; 6045 6046 if (hexstr2bin(cmd, &version, 1) < 0) 6047 return -1; 6048 6049 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 6050 } 6051 6052 6053 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s, 6054 u8 replace, char *cmd) 6055 { 6056 char *pos; 6057 char *adv_str; 6058 u32 auto_accept, adv_id, svc_state, config_methods; 6059 char *svc_info = NULL; 6060 char *cpt_prio_str; 6061 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1]; 6062 6063 pos = os_strchr(cmd, ' '); 6064 if (pos == NULL) 6065 return -1; 6066 *pos++ = '\0'; 6067 6068 /* Auto-Accept value is mandatory, and must be one of the 6069 * single values (0, 1, 2, 4) */ 6070 auto_accept = atoi(cmd); 6071 switch (auto_accept) { 6072 case P2PS_SETUP_NONE: /* No auto-accept */ 6073 case P2PS_SETUP_NEW: 6074 case P2PS_SETUP_CLIENT: 6075 case P2PS_SETUP_GROUP_OWNER: 6076 break; 6077 default: 6078 return -1; 6079 } 6080 6081 /* Advertisement ID is mandatory */ 6082 cmd = pos; 6083 pos = os_strchr(cmd, ' '); 6084 if (pos == NULL) 6085 return -1; 6086 *pos++ = '\0'; 6087 6088 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */ 6089 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0) 6090 return -1; 6091 6092 /* Only allow replacements if exist, and adds if not */ 6093 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) { 6094 if (!replace) 6095 return -1; 6096 } else { 6097 if (replace) 6098 return -1; 6099 } 6100 6101 /* svc_state between 0 - 0xff is mandatory */ 6102 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff) 6103 return -1; 6104 6105 pos = os_strchr(pos, ' '); 6106 if (pos == NULL) 6107 return -1; 6108 6109 /* config_methods is mandatory */ 6110 pos++; 6111 if (sscanf(pos, "%x", &config_methods) != 1) 6112 return -1; 6113 6114 if (!(config_methods & 6115 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS))) 6116 return -1; 6117 6118 pos = os_strchr(pos, ' '); 6119 if (pos == NULL) 6120 return -1; 6121 6122 pos++; 6123 adv_str = pos; 6124 6125 /* Advertisement string is mandatory */ 6126 if (!pos[0] || pos[0] == ' ') 6127 return -1; 6128 6129 /* Terminate svc string */ 6130 pos = os_strchr(pos, ' '); 6131 if (pos != NULL) 6132 *pos++ = '\0'; 6133 6134 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL; 6135 if (cpt_prio_str) { 6136 pos = os_strchr(pos, ' '); 6137 if (pos != NULL) 6138 *pos++ = '\0'; 6139 6140 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio)) 6141 return -1; 6142 } else { 6143 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6144 cpt_prio[1] = 0; 6145 } 6146 6147 /* Service and Response Information are optional */ 6148 if (pos && pos[0]) { 6149 size_t len; 6150 6151 /* Note the bare ' included, which cannot exist legally 6152 * in unescaped string. */ 6153 svc_info = os_strstr(pos, "svc_info='"); 6154 6155 if (svc_info) { 6156 svc_info += 9; 6157 len = os_strlen(svc_info); 6158 utf8_unescape(svc_info, len, svc_info, len); 6159 } 6160 } 6161 6162 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str, 6163 (u8) svc_state, (u16) config_methods, 6164 svc_info, cpt_prio); 6165 } 6166 6167 6168 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 6169 { 6170 char *pos; 6171 6172 pos = os_strchr(cmd, ' '); 6173 if (pos == NULL) 6174 return -1; 6175 *pos++ = '\0'; 6176 6177 if (os_strcmp(cmd, "bonjour") == 0) 6178 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 6179 if (os_strcmp(cmd, "upnp") == 0) 6180 return p2p_ctrl_service_add_upnp(wpa_s, pos); 6181 if (os_strcmp(cmd, "asp") == 0) 6182 return p2p_ctrl_service_add_asp(wpa_s, 0, pos); 6183 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6184 return -1; 6185 } 6186 6187 6188 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 6189 char *cmd) 6190 { 6191 size_t len; 6192 struct wpabuf *query; 6193 int ret; 6194 6195 len = os_strlen(cmd); 6196 if (len & 1) 6197 return -1; 6198 len /= 2; 6199 query = wpabuf_alloc(len); 6200 if (query == NULL) 6201 return -1; 6202 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 6203 wpabuf_free(query); 6204 return -1; 6205 } 6206 6207 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 6208 wpabuf_free(query); 6209 return ret; 6210 } 6211 6212 6213 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6214 { 6215 char *pos; 6216 u8 version; 6217 6218 pos = os_strchr(cmd, ' '); 6219 if (pos == NULL) 6220 return -1; 6221 *pos++ = '\0'; 6222 6223 if (hexstr2bin(cmd, &version, 1) < 0) 6224 return -1; 6225 6226 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 6227 } 6228 6229 6230 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd) 6231 { 6232 u32 adv_id; 6233 6234 if (os_strcmp(cmd, "all") == 0) { 6235 wpas_p2p_service_flush_asp(wpa_s); 6236 return 0; 6237 } 6238 6239 if (sscanf(cmd, "%x", &adv_id) != 1) 6240 return -1; 6241 6242 return wpas_p2p_service_del_asp(wpa_s, adv_id); 6243 } 6244 6245 6246 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 6247 { 6248 char *pos; 6249 6250 pos = os_strchr(cmd, ' '); 6251 if (pos == NULL) 6252 return -1; 6253 *pos++ = '\0'; 6254 6255 if (os_strcmp(cmd, "bonjour") == 0) 6256 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 6257 if (os_strcmp(cmd, "upnp") == 0) 6258 return p2p_ctrl_service_del_upnp(wpa_s, pos); 6259 if (os_strcmp(cmd, "asp") == 0) 6260 return p2p_ctrl_service_del_asp(wpa_s, pos); 6261 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6262 return -1; 6263 } 6264 6265 6266 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd) 6267 { 6268 char *pos; 6269 6270 pos = os_strchr(cmd, ' '); 6271 if (pos == NULL) 6272 return -1; 6273 *pos++ = '\0'; 6274 6275 if (os_strcmp(cmd, "asp") == 0) 6276 return p2p_ctrl_service_add_asp(wpa_s, 1, pos); 6277 6278 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6279 return -1; 6280 } 6281 6282 6283 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 6284 { 6285 u8 addr[ETH_ALEN]; 6286 6287 /* <addr> */ 6288 6289 if (hwaddr_aton(cmd, addr)) 6290 return -1; 6291 6292 return wpas_p2p_reject(wpa_s, addr); 6293 } 6294 6295 6296 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 6297 { 6298 char *pos; 6299 int id; 6300 struct wpa_ssid *ssid; 6301 u8 *_peer = NULL, peer[ETH_ALEN]; 6302 int freq = 0, pref_freq = 0; 6303 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; 6304 6305 id = atoi(cmd); 6306 pos = os_strstr(cmd, " peer="); 6307 if (pos) { 6308 pos += 6; 6309 if (hwaddr_aton(pos, peer)) 6310 return -1; 6311 _peer = peer; 6312 } 6313 ssid = wpa_config_get_network(wpa_s->conf, id); 6314 if (ssid == NULL || ssid->disabled != 2) { 6315 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 6316 "for persistent P2P group", 6317 id); 6318 return -1; 6319 } 6320 6321 pos = os_strstr(cmd, " freq="); 6322 if (pos) { 6323 pos += 6; 6324 freq = atoi(pos); 6325 if (freq <= 0) 6326 return -1; 6327 } 6328 6329 pos = os_strstr(cmd, " pref="); 6330 if (pos) { 6331 pos += 6; 6332 pref_freq = atoi(pos); 6333 if (pref_freq <= 0) 6334 return -1; 6335 } 6336 6337 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 6338 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 6339 vht; 6340 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 6341 6342 pos = os_strstr(cmd, "freq2="); 6343 if (pos) 6344 freq2 = atoi(pos + 6); 6345 6346 pos = os_strstr(cmd, " max_oper_chwidth="); 6347 if (pos) 6348 chwidth = atoi(pos + 18); 6349 6350 max_oper_chwidth = parse_freq(chwidth, freq2); 6351 if (max_oper_chwidth < 0) 6352 return -1; 6353 6354 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, 6355 max_oper_chwidth, pref_freq, he); 6356 } 6357 6358 6359 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 6360 { 6361 char *pos; 6362 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 6363 6364 pos = os_strstr(cmd, " peer="); 6365 if (!pos) 6366 return -1; 6367 6368 *pos = '\0'; 6369 pos += 6; 6370 if (hwaddr_aton(pos, peer)) { 6371 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 6372 return -1; 6373 } 6374 6375 pos = os_strstr(pos, " go_dev_addr="); 6376 if (pos) { 6377 pos += 13; 6378 if (hwaddr_aton(pos, go_dev_addr)) { 6379 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 6380 pos); 6381 return -1; 6382 } 6383 go_dev = go_dev_addr; 6384 } 6385 6386 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 6387 } 6388 6389 6390 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 6391 { 6392 if (os_strncmp(cmd, "persistent=", 11) == 0) 6393 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 6394 if (os_strncmp(cmd, "group=", 6) == 0) 6395 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 6396 6397 return -1; 6398 } 6399 6400 6401 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 6402 int id, int freq, int vht_center_freq2, 6403 int ht40, int vht, int vht_chwidth, 6404 int he) 6405 { 6406 struct wpa_ssid *ssid; 6407 6408 ssid = wpa_config_get_network(wpa_s->conf, id); 6409 if (ssid == NULL || ssid->disabled != 2) { 6410 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 6411 "for persistent P2P group", 6412 id); 6413 return -1; 6414 } 6415 6416 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 6417 vht_center_freq2, 0, ht40, vht, 6418 vht_chwidth, he, NULL, 0, 0); 6419 } 6420 6421 6422 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 6423 { 6424 int freq = 0, persistent = 0, group_id = -1; 6425 int vht = wpa_s->conf->p2p_go_vht; 6426 int ht40 = wpa_s->conf->p2p_go_ht40 || vht; 6427 int he = wpa_s->conf->p2p_go_he; 6428 int max_oper_chwidth, chwidth = 0, freq2 = 0; 6429 char *token, *context = NULL; 6430 #ifdef CONFIG_ACS 6431 int acs = 0; 6432 #endif /* CONFIG_ACS */ 6433 6434 while ((token = str_token(cmd, " ", &context))) { 6435 if (sscanf(token, "freq2=%d", &freq2) == 1 || 6436 sscanf(token, "persistent=%d", &group_id) == 1 || 6437 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) { 6438 continue; 6439 #ifdef CONFIG_ACS 6440 } else if (os_strcmp(token, "freq=acs") == 0) { 6441 acs = 1; 6442 #endif /* CONFIG_ACS */ 6443 } else if (sscanf(token, "freq=%d", &freq) == 1) { 6444 continue; 6445 } else if (os_strcmp(token, "ht40") == 0) { 6446 ht40 = 1; 6447 } else if (os_strcmp(token, "vht") == 0) { 6448 vht = 1; 6449 ht40 = 1; 6450 } else if (os_strcmp(token, "he") == 0) { 6451 he = 1; 6452 } else if (os_strcmp(token, "persistent") == 0) { 6453 persistent = 1; 6454 } else { 6455 wpa_printf(MSG_DEBUG, 6456 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'", 6457 token); 6458 return -1; 6459 } 6460 } 6461 6462 #ifdef CONFIG_ACS 6463 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 6464 (acs || freq == 2 || freq == 5)) { 6465 if (freq == 2 && wpa_s->best_24_freq <= 0) { 6466 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G; 6467 wpa_s->p2p_go_do_acs = 1; 6468 freq = 0; 6469 } else if (freq == 5 && wpa_s->best_5_freq <= 0) { 6470 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A; 6471 wpa_s->p2p_go_do_acs = 1; 6472 freq = 0; 6473 } else { 6474 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY; 6475 wpa_s->p2p_go_do_acs = 1; 6476 } 6477 } else { 6478 wpa_s->p2p_go_do_acs = 0; 6479 } 6480 #endif /* CONFIG_ACS */ 6481 6482 max_oper_chwidth = parse_freq(chwidth, freq2); 6483 if (max_oper_chwidth < 0) 6484 return -1; 6485 6486 if (group_id >= 0) 6487 return p2p_ctrl_group_add_persistent(wpa_s, group_id, 6488 freq, freq2, ht40, vht, 6489 max_oper_chwidth, he); 6490 6491 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, 6492 max_oper_chwidth, he); 6493 } 6494 6495 6496 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd, 6497 char *buf, size_t buflen) 6498 { 6499 u8 dev_addr[ETH_ALEN]; 6500 struct wpa_ssid *ssid; 6501 int res; 6502 const u8 *iaddr; 6503 6504 ssid = wpa_s->current_ssid; 6505 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO || 6506 hwaddr_aton(cmd, dev_addr)) 6507 return -1; 6508 6509 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr); 6510 if (!iaddr) 6511 return -1; 6512 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr)); 6513 if (os_snprintf_error(buflen, res)) 6514 return -1; 6515 return res; 6516 } 6517 6518 6519 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global, 6520 const u8 *p2p_dev_addr) 6521 { 6522 struct wpa_supplicant *wpa_s; 6523 6524 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 6525 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr)) 6526 return 1; 6527 } 6528 6529 return 0; 6530 } 6531 6532 6533 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 6534 char *buf, size_t buflen) 6535 { 6536 u8 addr[ETH_ALEN], *addr_ptr, group_capab; 6537 int next, res; 6538 const struct p2p_peer_info *info; 6539 char *pos, *end; 6540 char devtype[WPS_DEV_TYPE_BUFSIZE]; 6541 struct wpa_ssid *ssid; 6542 size_t i; 6543 6544 if (!wpa_s->global->p2p) 6545 return -1; 6546 6547 if (os_strcmp(cmd, "FIRST") == 0) { 6548 addr_ptr = NULL; 6549 next = 0; 6550 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 6551 if (hwaddr_aton(cmd + 5, addr) < 0) 6552 return -1; 6553 addr_ptr = addr; 6554 next = 1; 6555 } else { 6556 if (hwaddr_aton(cmd, addr) < 0) 6557 return -1; 6558 addr_ptr = addr; 6559 next = 0; 6560 } 6561 6562 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 6563 if (info == NULL) 6564 return -1; 6565 group_capab = info->group_capab; 6566 6567 if (group_capab && 6568 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) { 6569 wpa_printf(MSG_DEBUG, 6570 "P2P: Could not find any BSS with p2p_dev_addr " 6571 MACSTR ", hence override group_capab from 0x%x to 0", 6572 MAC2STR(info->p2p_device_addr), group_capab); 6573 group_capab = 0; 6574 } 6575 6576 pos = buf; 6577 end = buf + buflen; 6578 6579 res = os_snprintf(pos, end - pos, MACSTR "\n" 6580 "pri_dev_type=%s\n" 6581 "device_name=%s\n" 6582 "manufacturer=%s\n" 6583 "model_name=%s\n" 6584 "model_number=%s\n" 6585 "serial_number=%s\n" 6586 "config_methods=0x%x\n" 6587 "dev_capab=0x%x\n" 6588 "group_capab=0x%x\n" 6589 "level=%d\n", 6590 MAC2STR(info->p2p_device_addr), 6591 wps_dev_type_bin2str(info->pri_dev_type, 6592 devtype, sizeof(devtype)), 6593 info->device_name, 6594 info->manufacturer, 6595 info->model_name, 6596 info->model_number, 6597 info->serial_number, 6598 info->config_methods, 6599 info->dev_capab, 6600 group_capab, 6601 info->level); 6602 if (os_snprintf_error(end - pos, res)) 6603 return pos - buf; 6604 pos += res; 6605 6606 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 6607 { 6608 const u8 *t; 6609 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 6610 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 6611 wps_dev_type_bin2str(t, devtype, 6612 sizeof(devtype))); 6613 if (os_snprintf_error(end - pos, res)) 6614 return pos - buf; 6615 pos += res; 6616 } 6617 6618 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 6619 if (ssid) { 6620 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 6621 if (os_snprintf_error(end - pos, res)) 6622 return pos - buf; 6623 pos += res; 6624 } 6625 6626 res = p2p_get_peer_info_txt(info, pos, end - pos); 6627 if (res < 0) 6628 return pos - buf; 6629 pos += res; 6630 6631 if (info->vendor_elems) { 6632 res = os_snprintf(pos, end - pos, "vendor_elems="); 6633 if (os_snprintf_error(end - pos, res)) 6634 return pos - buf; 6635 pos += res; 6636 6637 pos += wpa_snprintf_hex(pos, end - pos, 6638 wpabuf_head(info->vendor_elems), 6639 wpabuf_len(info->vendor_elems)); 6640 6641 res = os_snprintf(pos, end - pos, "\n"); 6642 if (os_snprintf_error(end - pos, res)) 6643 return pos - buf; 6644 pos += res; 6645 } 6646 6647 return pos - buf; 6648 } 6649 6650 6651 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 6652 const char *param) 6653 { 6654 unsigned int i; 6655 6656 if (wpa_s->global->p2p == NULL) 6657 return -1; 6658 6659 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0) 6660 return -1; 6661 6662 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) { 6663 struct wpa_freq_range *freq; 6664 freq = &wpa_s->global->p2p_disallow_freq.range[i]; 6665 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 6666 freq->min, freq->max); 6667 } 6668 6669 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW); 6670 return 0; 6671 } 6672 6673 6674 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 6675 { 6676 char *param; 6677 6678 if (wpa_s->global->p2p == NULL) 6679 return -1; 6680 6681 param = os_strchr(cmd, ' '); 6682 if (param == NULL) 6683 return -1; 6684 *param++ = '\0'; 6685 6686 if (os_strcmp(cmd, "discoverability") == 0) { 6687 p2p_set_client_discoverability(wpa_s->global->p2p, 6688 atoi(param)); 6689 return 0; 6690 } 6691 6692 if (os_strcmp(cmd, "managed") == 0) { 6693 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 6694 return 0; 6695 } 6696 6697 if (os_strcmp(cmd, "listen_channel") == 0) { 6698 char *pos; 6699 u8 channel, op_class; 6700 6701 channel = atoi(param); 6702 pos = os_strchr(param, ' '); 6703 op_class = pos ? atoi(pos) : 81; 6704 6705 return p2p_set_listen_channel(wpa_s->global->p2p, op_class, 6706 channel, 1); 6707 } 6708 6709 if (os_strcmp(cmd, "ssid_postfix") == 0) { 6710 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 6711 os_strlen(param)); 6712 } 6713 6714 if (os_strcmp(cmd, "noa") == 0) { 6715 char *pos; 6716 int count, start, duration; 6717 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 6718 count = atoi(param); 6719 pos = os_strchr(param, ','); 6720 if (pos == NULL) 6721 return -1; 6722 pos++; 6723 start = atoi(pos); 6724 pos = os_strchr(pos, ','); 6725 if (pos == NULL) 6726 return -1; 6727 pos++; 6728 duration = atoi(pos); 6729 if (count < 0 || count > 255 || start < 0 || duration < 0) 6730 return -1; 6731 if (count == 0 && duration > 0) 6732 return -1; 6733 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 6734 "start=%d duration=%d", count, start, duration); 6735 return wpas_p2p_set_noa(wpa_s, count, start, duration); 6736 } 6737 6738 if (os_strcmp(cmd, "ps") == 0) 6739 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 6740 6741 if (os_strcmp(cmd, "oppps") == 0) 6742 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 6743 6744 if (os_strcmp(cmd, "ctwindow") == 0) 6745 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 6746 6747 if (os_strcmp(cmd, "disabled") == 0) { 6748 wpa_s->global->p2p_disabled = atoi(param); 6749 wpa_printf(MSG_DEBUG, "P2P functionality %s", 6750 wpa_s->global->p2p_disabled ? 6751 "disabled" : "enabled"); 6752 if (wpa_s->global->p2p_disabled) { 6753 wpas_p2p_stop_find(wpa_s); 6754 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 6755 p2p_flush(wpa_s->global->p2p); 6756 } 6757 return 0; 6758 } 6759 6760 if (os_strcmp(cmd, "conc_pref") == 0) { 6761 if (os_strcmp(param, "sta") == 0) 6762 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 6763 else if (os_strcmp(param, "p2p") == 0) 6764 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 6765 else { 6766 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 6767 return -1; 6768 } 6769 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 6770 "%s", param); 6771 return 0; 6772 } 6773 6774 if (os_strcmp(cmd, "force_long_sd") == 0) { 6775 wpa_s->force_long_sd = atoi(param); 6776 return 0; 6777 } 6778 6779 if (os_strcmp(cmd, "peer_filter") == 0) { 6780 u8 addr[ETH_ALEN]; 6781 if (hwaddr_aton(param, addr)) 6782 return -1; 6783 p2p_set_peer_filter(wpa_s->global->p2p, addr); 6784 return 0; 6785 } 6786 6787 if (os_strcmp(cmd, "cross_connect") == 0) 6788 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 6789 6790 if (os_strcmp(cmd, "go_apsd") == 0) { 6791 if (os_strcmp(param, "disable") == 0) 6792 wpa_s->set_ap_uapsd = 0; 6793 else { 6794 wpa_s->set_ap_uapsd = 1; 6795 wpa_s->ap_uapsd = atoi(param); 6796 } 6797 return 0; 6798 } 6799 6800 if (os_strcmp(cmd, "client_apsd") == 0) { 6801 if (os_strcmp(param, "disable") == 0) 6802 wpa_s->set_sta_uapsd = 0; 6803 else { 6804 int be, bk, vi, vo; 6805 char *pos; 6806 /* format: BE,BK,VI,VO;max SP Length */ 6807 be = atoi(param); 6808 pos = os_strchr(param, ','); 6809 if (pos == NULL) 6810 return -1; 6811 pos++; 6812 bk = atoi(pos); 6813 pos = os_strchr(pos, ','); 6814 if (pos == NULL) 6815 return -1; 6816 pos++; 6817 vi = atoi(pos); 6818 pos = os_strchr(pos, ','); 6819 if (pos == NULL) 6820 return -1; 6821 pos++; 6822 vo = atoi(pos); 6823 /* ignore max SP Length for now */ 6824 6825 wpa_s->set_sta_uapsd = 1; 6826 wpa_s->sta_uapsd = 0; 6827 if (be) 6828 wpa_s->sta_uapsd |= BIT(0); 6829 if (bk) 6830 wpa_s->sta_uapsd |= BIT(1); 6831 if (vi) 6832 wpa_s->sta_uapsd |= BIT(2); 6833 if (vo) 6834 wpa_s->sta_uapsd |= BIT(3); 6835 } 6836 return 0; 6837 } 6838 6839 if (os_strcmp(cmd, "disallow_freq") == 0) 6840 return p2p_ctrl_disallow_freq(wpa_s, param); 6841 6842 if (os_strcmp(cmd, "disc_int") == 0) { 6843 int min_disc_int, max_disc_int, max_disc_tu; 6844 char *pos; 6845 6846 pos = param; 6847 6848 min_disc_int = atoi(pos); 6849 pos = os_strchr(pos, ' '); 6850 if (pos == NULL) 6851 return -1; 6852 *pos++ = '\0'; 6853 6854 max_disc_int = atoi(pos); 6855 pos = os_strchr(pos, ' '); 6856 if (pos == NULL) 6857 return -1; 6858 *pos++ = '\0'; 6859 6860 max_disc_tu = atoi(pos); 6861 6862 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 6863 max_disc_int, max_disc_tu); 6864 } 6865 6866 if (os_strcmp(cmd, "per_sta_psk") == 0) { 6867 wpa_s->global->p2p_per_sta_psk = !!atoi(param); 6868 return 0; 6869 } 6870 6871 #ifdef CONFIG_WPS_NFC 6872 if (os_strcmp(cmd, "nfc_tag") == 0) 6873 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param)); 6874 #endif /* CONFIG_WPS_NFC */ 6875 6876 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) { 6877 wpa_s->p2p_disable_ip_addr_req = !!atoi(param); 6878 return 0; 6879 } 6880 6881 if (os_strcmp(cmd, "override_pref_op_chan") == 0) { 6882 int op_class, chan; 6883 6884 op_class = atoi(param); 6885 param = os_strchr(param, ':'); 6886 if (!param) 6887 return -1; 6888 param++; 6889 chan = atoi(param); 6890 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class, 6891 chan); 6892 return 0; 6893 } 6894 6895 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 6896 cmd); 6897 6898 return -1; 6899 } 6900 6901 6902 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) 6903 { 6904 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 6905 wpa_s->force_long_sd = 0; 6906 6907 #ifdef CONFIG_TESTING_OPTIONS 6908 os_free(wpa_s->get_pref_freq_list_override); 6909 wpa_s->get_pref_freq_list_override = NULL; 6910 #endif /* CONFIG_TESTING_OPTIONS */ 6911 6912 wpas_p2p_stop_find(wpa_s); 6913 wpa_s->parent->p2ps_method_config_any = 0; 6914 if (wpa_s->global->p2p) 6915 p2p_flush(wpa_s->global->p2p); 6916 } 6917 6918 6919 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 6920 { 6921 char *pos, *pos2; 6922 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 6923 6924 if (cmd[0]) { 6925 pos = os_strchr(cmd, ' '); 6926 if (pos == NULL) 6927 return -1; 6928 *pos++ = '\0'; 6929 dur1 = atoi(cmd); 6930 6931 pos2 = os_strchr(pos, ' '); 6932 if (pos2) 6933 *pos2++ = '\0'; 6934 int1 = atoi(pos); 6935 } else 6936 pos2 = NULL; 6937 6938 if (pos2) { 6939 pos = os_strchr(pos2, ' '); 6940 if (pos == NULL) 6941 return -1; 6942 *pos++ = '\0'; 6943 dur2 = atoi(pos2); 6944 int2 = atoi(pos); 6945 } 6946 6947 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 6948 } 6949 6950 6951 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 6952 { 6953 char *pos; 6954 unsigned int period = 0, interval = 0; 6955 6956 if (cmd[0]) { 6957 pos = os_strchr(cmd, ' '); 6958 if (pos == NULL) 6959 return -1; 6960 *pos++ = '\0'; 6961 period = atoi(cmd); 6962 interval = atoi(pos); 6963 } 6964 6965 return wpas_p2p_ext_listen(wpa_s, period, interval); 6966 } 6967 6968 6969 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) 6970 { 6971 const char *pos; 6972 u8 peer[ETH_ALEN]; 6973 int iface_addr = 0; 6974 6975 pos = cmd; 6976 if (os_strncmp(pos, "iface=", 6) == 0) { 6977 iface_addr = 1; 6978 pos += 6; 6979 } 6980 if (hwaddr_aton(pos, peer)) 6981 return -1; 6982 6983 wpas_p2p_remove_client(wpa_s, peer, iface_addr); 6984 return 0; 6985 } 6986 6987 6988 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd) 6989 { 6990 int freq = 0, period = 0, interval = 0, count = 0; 6991 6992 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4) 6993 { 6994 wpa_printf(MSG_DEBUG, 6995 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd); 6996 return -1; 6997 } 6998 6999 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count); 7000 } 7001 7002 #endif /* CONFIG_P2P */ 7003 7004 7005 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val) 7006 { 7007 struct wpa_freq_range_list ranges; 7008 int *freqs = NULL; 7009 struct hostapd_hw_modes *mode; 7010 u16 i; 7011 7012 if (wpa_s->hw.modes == NULL) 7013 return NULL; 7014 7015 os_memset(&ranges, 0, sizeof(ranges)); 7016 if (freq_range_list_parse(&ranges, val) < 0) 7017 return NULL; 7018 7019 for (i = 0; i < wpa_s->hw.num_modes; i++) { 7020 int j; 7021 7022 mode = &wpa_s->hw.modes[i]; 7023 for (j = 0; j < mode->num_channels; j++) { 7024 unsigned int freq; 7025 7026 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED) 7027 continue; 7028 7029 freq = mode->channels[j].freq; 7030 if (!freq_range_list_includes(&ranges, freq)) 7031 continue; 7032 7033 int_array_add_unique(&freqs, freq); 7034 } 7035 } 7036 7037 os_free(ranges.range); 7038 return freqs; 7039 } 7040 7041 7042 #ifdef CONFIG_INTERWORKING 7043 7044 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) 7045 { 7046 int auto_sel = 0; 7047 int *freqs = NULL; 7048 7049 if (param) { 7050 char *pos; 7051 7052 auto_sel = os_strstr(param, "auto") != NULL; 7053 7054 pos = os_strstr(param, "freq="); 7055 if (pos) { 7056 freqs = freq_range_to_channel_list(wpa_s, pos + 5); 7057 if (freqs == NULL) 7058 return -1; 7059 } 7060 7061 } 7062 7063 return interworking_select(wpa_s, auto_sel, freqs); 7064 } 7065 7066 7067 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, 7068 int only_add) 7069 { 7070 u8 bssid[ETH_ALEN]; 7071 struct wpa_bss *bss; 7072 7073 if (hwaddr_aton(dst, bssid)) { 7074 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 7075 return -1; 7076 } 7077 7078 bss = wpa_bss_get_bssid(wpa_s, bssid); 7079 if (bss == NULL) { 7080 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 7081 MAC2STR(bssid)); 7082 return -1; 7083 } 7084 7085 if (bss->ssid_len == 0) { 7086 int found = 0; 7087 7088 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR 7089 " does not have SSID information", MAC2STR(bssid)); 7090 7091 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, 7092 list) { 7093 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && 7094 bss->ssid_len > 0) { 7095 found = 1; 7096 break; 7097 } 7098 } 7099 7100 if (!found) 7101 return -1; 7102 wpa_printf(MSG_DEBUG, 7103 "Found another matching BSS entry with SSID"); 7104 } 7105 7106 return interworking_connect(wpa_s, bss, only_add); 7107 } 7108 7109 7110 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 7111 { 7112 u8 dst_addr[ETH_ALEN]; 7113 int used; 7114 char *pos; 7115 #define MAX_ANQP_INFO_ID 100 7116 u16 id[MAX_ANQP_INFO_ID]; 7117 size_t num_id = 0; 7118 u32 subtypes = 0; 7119 u32 mbo_subtypes = 0; 7120 7121 used = hwaddr_aton2(dst, dst_addr); 7122 if (used < 0) 7123 return -1; 7124 pos = dst + used; 7125 if (*pos == ' ') 7126 pos++; 7127 while (num_id < MAX_ANQP_INFO_ID) { 7128 if (os_strncmp(pos, "hs20:", 5) == 0) { 7129 #ifdef CONFIG_HS20 7130 int num = atoi(pos + 5); 7131 if (num <= 0 || num > 31) 7132 return -1; 7133 subtypes |= BIT(num); 7134 #else /* CONFIG_HS20 */ 7135 return -1; 7136 #endif /* CONFIG_HS20 */ 7137 } else if (os_strncmp(pos, "mbo:", 4) == 0) { 7138 #ifdef CONFIG_MBO 7139 int num = atoi(pos + 4); 7140 7141 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) 7142 return -1; 7143 mbo_subtypes |= BIT(num); 7144 #else /* CONFIG_MBO */ 7145 return -1; 7146 #endif /* CONFIG_MBO */ 7147 } else { 7148 id[num_id] = atoi(pos); 7149 if (id[num_id]) 7150 num_id++; 7151 } 7152 pos = os_strchr(pos + 1, ','); 7153 if (pos == NULL) 7154 break; 7155 pos++; 7156 } 7157 7158 if (num_id == 0 && !subtypes && !mbo_subtypes) 7159 return -1; 7160 7161 return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, 7162 mbo_subtypes); 7163 } 7164 7165 7166 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 7167 { 7168 u8 dst_addr[ETH_ALEN]; 7169 struct wpabuf *advproto, *query = NULL; 7170 int used, ret = -1; 7171 char *pos, *end; 7172 size_t len; 7173 7174 used = hwaddr_aton2(cmd, dst_addr); 7175 if (used < 0) 7176 return -1; 7177 7178 pos = cmd + used; 7179 while (*pos == ' ') 7180 pos++; 7181 7182 /* Advertisement Protocol ID */ 7183 end = os_strchr(pos, ' '); 7184 if (end) 7185 len = end - pos; 7186 else 7187 len = os_strlen(pos); 7188 if (len & 0x01) 7189 return -1; 7190 len /= 2; 7191 if (len == 0) 7192 return -1; 7193 advproto = wpabuf_alloc(len); 7194 if (advproto == NULL) 7195 return -1; 7196 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 7197 goto fail; 7198 7199 if (end) { 7200 /* Optional Query Request */ 7201 pos = end + 1; 7202 while (*pos == ' ') 7203 pos++; 7204 7205 len = os_strlen(pos); 7206 if (len) { 7207 if (len & 0x01) 7208 goto fail; 7209 len /= 2; 7210 if (len == 0) 7211 goto fail; 7212 query = wpabuf_alloc(len); 7213 if (query == NULL) 7214 goto fail; 7215 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 7216 goto fail; 7217 } 7218 } 7219 7220 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 7221 7222 fail: 7223 wpabuf_free(advproto); 7224 wpabuf_free(query); 7225 7226 return ret; 7227 } 7228 7229 7230 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 7231 size_t buflen) 7232 { 7233 u8 addr[ETH_ALEN]; 7234 int dialog_token; 7235 int used; 7236 char *pos; 7237 size_t resp_len, start, requested_len; 7238 struct wpabuf *resp; 7239 int ret; 7240 7241 used = hwaddr_aton2(cmd, addr); 7242 if (used < 0) 7243 return -1; 7244 7245 pos = cmd + used; 7246 while (*pos == ' ') 7247 pos++; 7248 dialog_token = atoi(pos); 7249 7250 if (wpa_s->last_gas_resp && 7251 os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 && 7252 dialog_token == wpa_s->last_gas_dialog_token) 7253 resp = wpa_s->last_gas_resp; 7254 else if (wpa_s->prev_gas_resp && 7255 os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 && 7256 dialog_token == wpa_s->prev_gas_dialog_token) 7257 resp = wpa_s->prev_gas_resp; 7258 else 7259 return -1; 7260 7261 resp_len = wpabuf_len(resp); 7262 start = 0; 7263 requested_len = resp_len; 7264 7265 pos = os_strchr(pos, ' '); 7266 if (pos) { 7267 start = atoi(pos); 7268 if (start > resp_len) 7269 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 7270 pos = os_strchr(pos, ','); 7271 if (pos == NULL) 7272 return -1; 7273 pos++; 7274 requested_len = atoi(pos); 7275 if (start + requested_len > resp_len) 7276 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 7277 } 7278 7279 if (requested_len * 2 + 1 > buflen) 7280 return os_snprintf(buf, buflen, "FAIL-Too long response"); 7281 7282 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start, 7283 requested_len); 7284 7285 if (start + requested_len == resp_len) { 7286 /* 7287 * Free memory by dropping the response after it has been 7288 * fetched. 7289 */ 7290 if (resp == wpa_s->prev_gas_resp) { 7291 wpabuf_free(wpa_s->prev_gas_resp); 7292 wpa_s->prev_gas_resp = NULL; 7293 } else { 7294 wpabuf_free(wpa_s->last_gas_resp); 7295 wpa_s->last_gas_resp = NULL; 7296 } 7297 } 7298 7299 return ret; 7300 } 7301 #endif /* CONFIG_INTERWORKING */ 7302 7303 7304 #ifdef CONFIG_HS20 7305 7306 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 7307 { 7308 u8 dst_addr[ETH_ALEN]; 7309 int used; 7310 char *pos; 7311 u32 subtypes = 0; 7312 7313 used = hwaddr_aton2(dst, dst_addr); 7314 if (used < 0) 7315 return -1; 7316 pos = dst + used; 7317 if (*pos == ' ') 7318 pos++; 7319 for (;;) { 7320 int num = atoi(pos); 7321 if (num <= 0 || num > 31) 7322 return -1; 7323 subtypes |= BIT(num); 7324 pos = os_strchr(pos + 1, ','); 7325 if (pos == NULL) 7326 break; 7327 pos++; 7328 } 7329 7330 if (subtypes == 0) 7331 return -1; 7332 7333 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0); 7334 } 7335 7336 7337 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 7338 const u8 *addr, const char *realm) 7339 { 7340 u8 *buf; 7341 size_t rlen, len; 7342 int ret; 7343 7344 rlen = os_strlen(realm); 7345 len = 3 + rlen; 7346 buf = os_malloc(len); 7347 if (buf == NULL) 7348 return -1; 7349 buf[0] = 1; /* NAI Home Realm Count */ 7350 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 7351 buf[2] = rlen; 7352 os_memcpy(buf + 3, realm, rlen); 7353 7354 ret = hs20_anqp_send_req(wpa_s, addr, 7355 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 7356 buf, len, 0); 7357 7358 os_free(buf); 7359 7360 return ret; 7361 } 7362 7363 7364 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 7365 char *dst) 7366 { 7367 struct wpa_cred *cred = wpa_s->conf->cred; 7368 u8 dst_addr[ETH_ALEN]; 7369 int used; 7370 u8 *buf; 7371 size_t len; 7372 int ret; 7373 7374 used = hwaddr_aton2(dst, dst_addr); 7375 if (used < 0) 7376 return -1; 7377 7378 while (dst[used] == ' ') 7379 used++; 7380 if (os_strncmp(dst + used, "realm=", 6) == 0) 7381 return hs20_nai_home_realm_list(wpa_s, dst_addr, 7382 dst + used + 6); 7383 7384 len = os_strlen(dst + used); 7385 7386 if (len == 0 && cred && cred->realm) 7387 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 7388 7389 if (len & 1) 7390 return -1; 7391 len /= 2; 7392 buf = os_malloc(len); 7393 if (buf == NULL) 7394 return -1; 7395 if (hexstr2bin(dst + used, buf, len) < 0) { 7396 os_free(buf); 7397 return -1; 7398 } 7399 7400 ret = hs20_anqp_send_req(wpa_s, dst_addr, 7401 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 7402 buf, len, 0); 7403 os_free(buf); 7404 7405 return ret; 7406 } 7407 7408 7409 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply, 7410 int buflen) 7411 { 7412 u8 dst_addr[ETH_ALEN]; 7413 int used; 7414 char *ctx = NULL, *icon, *poffset, *psize; 7415 7416 used = hwaddr_aton2(cmd, dst_addr); 7417 if (used < 0) 7418 return -1; 7419 cmd += used; 7420 7421 icon = str_token(cmd, " ", &ctx); 7422 poffset = str_token(cmd, " ", &ctx); 7423 psize = str_token(cmd, " ", &ctx); 7424 if (!icon || !poffset || !psize) 7425 return -1; 7426 7427 wpa_s->fetch_osu_icon_in_progress = 0; 7428 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize), 7429 reply, buflen); 7430 } 7431 7432 7433 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd) 7434 { 7435 u8 dst_addr[ETH_ALEN]; 7436 int used; 7437 char *icon; 7438 7439 if (!cmd[0]) 7440 return hs20_del_icon(wpa_s, NULL, NULL); 7441 7442 used = hwaddr_aton2(cmd, dst_addr); 7443 if (used < 0) 7444 return -1; 7445 7446 while (cmd[used] == ' ') 7447 used++; 7448 icon = cmd[used] ? &cmd[used] : NULL; 7449 7450 return hs20_del_icon(wpa_s, dst_addr, icon); 7451 } 7452 7453 7454 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem) 7455 { 7456 u8 dst_addr[ETH_ALEN]; 7457 int used; 7458 char *icon; 7459 7460 used = hwaddr_aton2(cmd, dst_addr); 7461 if (used < 0) 7462 return -1; 7463 7464 while (cmd[used] == ' ') 7465 used++; 7466 icon = &cmd[used]; 7467 7468 wpa_s->fetch_osu_icon_in_progress = 0; 7469 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST), 7470 (u8 *) icon, os_strlen(icon), inmem); 7471 } 7472 7473 #endif /* CONFIG_HS20 */ 7474 7475 7476 #ifdef CONFIG_AUTOSCAN 7477 7478 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 7479 char *cmd) 7480 { 7481 enum wpa_states state = wpa_s->wpa_state; 7482 char *new_params = NULL; 7483 7484 if (os_strlen(cmd) > 0) { 7485 new_params = os_strdup(cmd); 7486 if (new_params == NULL) 7487 return -1; 7488 } 7489 7490 os_free(wpa_s->conf->autoscan); 7491 wpa_s->conf->autoscan = new_params; 7492 7493 if (wpa_s->conf->autoscan == NULL) 7494 autoscan_deinit(wpa_s); 7495 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 7496 autoscan_init(wpa_s, 1); 7497 else if (state == WPA_SCANNING) 7498 wpa_supplicant_reinit_autoscan(wpa_s); 7499 else 7500 wpa_printf(MSG_DEBUG, "No autoscan update in state %s", 7501 wpa_supplicant_state_txt(state)); 7502 7503 return 0; 7504 } 7505 7506 #endif /* CONFIG_AUTOSCAN */ 7507 7508 7509 #ifdef CONFIG_WNM 7510 7511 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 7512 { 7513 int enter; 7514 int intval = 0; 7515 char *pos; 7516 int ret; 7517 struct wpabuf *tfs_req = NULL; 7518 7519 if (os_strncmp(cmd, "enter", 5) == 0) 7520 enter = 1; 7521 else if (os_strncmp(cmd, "exit", 4) == 0) 7522 enter = 0; 7523 else 7524 return -1; 7525 7526 pos = os_strstr(cmd, " interval="); 7527 if (pos) 7528 intval = atoi(pos + 10); 7529 7530 pos = os_strstr(cmd, " tfs_req="); 7531 if (pos) { 7532 char *end; 7533 size_t len; 7534 pos += 9; 7535 end = os_strchr(pos, ' '); 7536 if (end) 7537 len = end - pos; 7538 else 7539 len = os_strlen(pos); 7540 if (len & 1) 7541 return -1; 7542 len /= 2; 7543 tfs_req = wpabuf_alloc(len); 7544 if (tfs_req == NULL) 7545 return -1; 7546 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 7547 wpabuf_free(tfs_req); 7548 return -1; 7549 } 7550 } 7551 7552 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 7553 WNM_SLEEP_MODE_EXIT, intval, 7554 tfs_req); 7555 wpabuf_free(tfs_req); 7556 7557 return ret; 7558 } 7559 7560 7561 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) 7562 { 7563 int query_reason, list = 0; 7564 char *btm_candidates = NULL; 7565 7566 query_reason = atoi(cmd); 7567 7568 cmd = os_strchr(cmd, ' '); 7569 if (cmd) { 7570 if (os_strncmp(cmd, " list", 5) == 0) 7571 list = 1; 7572 else 7573 btm_candidates = cmd; 7574 } 7575 7576 wpa_printf(MSG_DEBUG, 7577 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s", 7578 query_reason, list ? " candidate list" : ""); 7579 7580 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, 7581 btm_candidates, 7582 list); 7583 } 7584 7585 7586 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s, 7587 char *cmd) 7588 { 7589 struct wpabuf *elems; 7590 int ret; 7591 7592 elems = wpabuf_parse_bin(cmd); 7593 if (!elems) 7594 return -1; 7595 7596 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems); 7597 wpabuf_free(elems); 7598 return ret; 7599 } 7600 7601 #endif /* CONFIG_WNM */ 7602 7603 7604 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 7605 size_t buflen) 7606 { 7607 struct wpa_signal_info si; 7608 int ret; 7609 char *pos, *end; 7610 7611 ret = wpa_drv_signal_poll(wpa_s, &si); 7612 if (ret) 7613 return -1; 7614 7615 pos = buf; 7616 end = buf + buflen; 7617 7618 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%d\n" 7619 "NOISE=%d\nFREQUENCY=%u\n", 7620 si.current_signal, si.current_txrate / 1000, 7621 si.current_noise, si.frequency); 7622 if (os_snprintf_error(end - pos, ret)) 7623 return -1; 7624 pos += ret; 7625 7626 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) { 7627 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 7628 channel_width_to_string(si.chanwidth)); 7629 if (os_snprintf_error(end - pos, ret)) 7630 return -1; 7631 pos += ret; 7632 } 7633 7634 if (si.center_frq1 > 0) { 7635 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 7636 si.center_frq1); 7637 if (os_snprintf_error(end - pos, ret)) 7638 return -1; 7639 pos += ret; 7640 } 7641 7642 if (si.center_frq2 > 0) { 7643 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 7644 si.center_frq2); 7645 if (os_snprintf_error(end - pos, ret)) 7646 return -1; 7647 pos += ret; 7648 } 7649 7650 if (si.avg_signal) { 7651 ret = os_snprintf(pos, end - pos, 7652 "AVG_RSSI=%d\n", si.avg_signal); 7653 if (os_snprintf_error(end - pos, ret)) 7654 return -1; 7655 pos += ret; 7656 } 7657 7658 if (si.avg_beacon_signal) { 7659 ret = os_snprintf(pos, end - pos, 7660 "AVG_BEACON_RSSI=%d\n", si.avg_beacon_signal); 7661 if (os_snprintf_error(end - pos, ret)) 7662 return -1; 7663 pos += ret; 7664 } 7665 7666 return pos - buf; 7667 } 7668 7669 7670 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s, 7671 const char *cmd) 7672 { 7673 const char *pos; 7674 int threshold = 0; 7675 int hysteresis = 0; 7676 7677 if (wpa_s->bgscan && wpa_s->bgscan_priv) { 7678 wpa_printf(MSG_DEBUG, 7679 "Reject SIGNAL_MONITOR command - bgscan is active"); 7680 return -1; 7681 } 7682 pos = os_strstr(cmd, "THRESHOLD="); 7683 if (pos) 7684 threshold = atoi(pos + 10); 7685 pos = os_strstr(cmd, "HYSTERESIS="); 7686 if (pos) 7687 hysteresis = atoi(pos + 11); 7688 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis); 7689 } 7690 7691 7692 #ifdef CONFIG_TESTING_OPTIONS 7693 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, 7694 enum wpa_driver_if_type if_type, 7695 unsigned int *num, 7696 unsigned int *freq_list) 7697 { 7698 char *pos = wpa_s->get_pref_freq_list_override; 7699 char *end; 7700 unsigned int count = 0; 7701 7702 /* Override string format: 7703 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */ 7704 7705 while (pos) { 7706 if (atoi(pos) == (int) if_type) 7707 break; 7708 pos = os_strchr(pos, ' '); 7709 if (pos) 7710 pos++; 7711 } 7712 if (!pos) 7713 return -1; 7714 pos = os_strchr(pos, ':'); 7715 if (!pos) 7716 return -1; 7717 pos++; 7718 end = os_strchr(pos, ' '); 7719 while (pos && (!end || pos < end) && count < *num) { 7720 freq_list[count++] = atoi(pos); 7721 pos = os_strchr(pos, ','); 7722 if (pos) 7723 pos++; 7724 } 7725 7726 *num = count; 7727 return 0; 7728 } 7729 #endif /* CONFIG_TESTING_OPTIONS */ 7730 7731 7732 static int wpas_ctrl_iface_get_pref_freq_list( 7733 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 7734 { 7735 unsigned int freq_list[100], num = 100, i; 7736 int ret; 7737 enum wpa_driver_if_type iface_type; 7738 char *pos, *end; 7739 7740 pos = buf; 7741 end = buf + buflen; 7742 7743 /* buf: "<interface_type>" */ 7744 if (os_strcmp(cmd, "STATION") == 0) 7745 iface_type = WPA_IF_STATION; 7746 else if (os_strcmp(cmd, "AP") == 0) 7747 iface_type = WPA_IF_AP_BSS; 7748 else if (os_strcmp(cmd, "P2P_GO") == 0) 7749 iface_type = WPA_IF_P2P_GO; 7750 else if (os_strcmp(cmd, "P2P_CLIENT") == 0) 7751 iface_type = WPA_IF_P2P_CLIENT; 7752 else if (os_strcmp(cmd, "IBSS") == 0) 7753 iface_type = WPA_IF_IBSS; 7754 else if (os_strcmp(cmd, "TDLS") == 0) 7755 iface_type = WPA_IF_TDLS; 7756 else 7757 return -1; 7758 7759 wpa_printf(MSG_DEBUG, 7760 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", 7761 iface_type, cmd); 7762 7763 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); 7764 if (ret) 7765 return -1; 7766 7767 for (i = 0; i < num; i++) { 7768 ret = os_snprintf(pos, end - pos, "%s%u", 7769 i > 0 ? "," : "", freq_list[i]); 7770 if (os_snprintf_error(end - pos, ret)) 7771 return -1; 7772 pos += ret; 7773 } 7774 7775 return pos - buf; 7776 } 7777 7778 7779 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, 7780 char *buf, size_t buflen) 7781 { 7782 int ret, i; 7783 char *pos, *end; 7784 7785 ret = os_snprintf(buf, buflen, "%016llX:\n", 7786 (long long unsigned) wpa_s->drv_flags); 7787 if (os_snprintf_error(buflen, ret)) 7788 return -1; 7789 7790 pos = buf + ret; 7791 end = buf + buflen; 7792 7793 for (i = 0; i < 64; i++) { 7794 if (wpa_s->drv_flags & (1LLU << i)) { 7795 ret = os_snprintf(pos, end - pos, "%s\n", 7796 driver_flag_to_string(1LLU << i)); 7797 if (os_snprintf_error(end - pos, ret)) 7798 return -1; 7799 pos += ret; 7800 } 7801 } 7802 7803 return pos - buf; 7804 } 7805 7806 7807 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 7808 size_t buflen) 7809 { 7810 struct hostap_sta_driver_data sta; 7811 int ret; 7812 7813 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 7814 if (ret) 7815 return -1; 7816 7817 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 7818 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 7819 if (os_snprintf_error(buflen, ret)) 7820 return -1; 7821 return ret; 7822 } 7823 7824 7825 #ifdef ANDROID 7826 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 7827 char *buf, size_t buflen) 7828 { 7829 int ret; 7830 7831 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 7832 if (ret == 0) { 7833 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { 7834 struct p2p_data *p2p = wpa_s->global->p2p; 7835 if (p2p) { 7836 char country[3]; 7837 country[0] = cmd[8]; 7838 country[1] = cmd[9]; 7839 country[2] = 0x04; 7840 p2p_set_country(p2p, country); 7841 } 7842 } 7843 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 7844 if (os_snprintf_error(buflen, ret)) 7845 ret = -1; 7846 } 7847 return ret; 7848 } 7849 #endif /* ANDROID */ 7850 7851 7852 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, 7853 char *buf, size_t buflen) 7854 { 7855 int ret; 7856 char *pos; 7857 u8 *data = NULL; 7858 unsigned int vendor_id, subcmd; 7859 struct wpabuf *reply; 7860 size_t data_len = 0; 7861 7862 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 7863 vendor_id = strtoul(cmd, &pos, 16); 7864 if (!isblank((unsigned char) *pos)) 7865 return -EINVAL; 7866 7867 subcmd = strtoul(pos, &pos, 10); 7868 7869 if (*pos != '\0') { 7870 if (!isblank((unsigned char) *pos++)) 7871 return -EINVAL; 7872 data_len = os_strlen(pos); 7873 } 7874 7875 if (data_len) { 7876 data_len /= 2; 7877 data = os_malloc(data_len); 7878 if (!data) 7879 return -1; 7880 7881 if (hexstr2bin(pos, data, data_len)) { 7882 wpa_printf(MSG_DEBUG, 7883 "Vendor command: wrong parameter format"); 7884 os_free(data); 7885 return -EINVAL; 7886 } 7887 } 7888 7889 reply = wpabuf_alloc((buflen - 1) / 2); 7890 if (!reply) { 7891 os_free(data); 7892 return -1; 7893 } 7894 7895 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, 7896 reply); 7897 7898 if (ret == 0) 7899 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 7900 wpabuf_len(reply)); 7901 7902 wpabuf_free(reply); 7903 os_free(data); 7904 7905 return ret; 7906 } 7907 7908 7909 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) 7910 { 7911 #ifdef CONFIG_P2P 7912 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ? 7913 wpa_s->global->p2p_init_wpa_s : wpa_s; 7914 #endif /* CONFIG_P2P */ 7915 7916 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); 7917 7918 if (wpas_abort_ongoing_scan(wpa_s) == 0) 7919 wpa_s->ignore_post_flush_scan_res = 1; 7920 7921 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 7922 /* 7923 * Avoid possible auto connect re-connection on getting 7924 * disconnected due to state flush. 7925 */ 7926 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 7927 } 7928 7929 #ifdef CONFIG_P2P 7930 wpas_p2p_group_remove(p2p_wpa_s, "*"); 7931 wpas_p2p_cancel(p2p_wpa_s); 7932 p2p_ctrl_flush(p2p_wpa_s); 7933 wpas_p2p_service_flush(p2p_wpa_s); 7934 p2p_wpa_s->global->p2p_disabled = 0; 7935 p2p_wpa_s->global->p2p_per_sta_psk = 0; 7936 p2p_wpa_s->conf->num_sec_device_types = 0; 7937 p2p_wpa_s->p2p_disable_ip_addr_req = 0; 7938 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range); 7939 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL; 7940 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0; 7941 p2p_wpa_s->global->pending_p2ps_group = 0; 7942 p2p_wpa_s->global->pending_p2ps_group_freq = 0; 7943 #endif /* CONFIG_P2P */ 7944 7945 #ifdef CONFIG_WPS_TESTING 7946 wps_version_number = 0x20; 7947 wps_testing_dummy_cred = 0; 7948 wps_corrupt_pkhash = 0; 7949 wps_force_auth_types_in_use = 0; 7950 wps_force_encr_types_in_use = 0; 7951 #endif /* CONFIG_WPS_TESTING */ 7952 #ifdef CONFIG_WPS 7953 wpa_s->wps_fragment_size = 0; 7954 wpas_wps_cancel(wpa_s); 7955 wps_registrar_flush(wpa_s->wps->registrar); 7956 #endif /* CONFIG_WPS */ 7957 wpa_s->after_wps = 0; 7958 wpa_s->known_wps_freq = 0; 7959 7960 #ifdef CONFIG_DPP 7961 wpas_dpp_deinit(wpa_s); 7962 wpa_s->dpp_init_max_tries = 0; 7963 wpa_s->dpp_init_retry_time = 0; 7964 wpa_s->dpp_resp_wait_time = 0; 7965 wpa_s->dpp_resp_max_tries = 0; 7966 wpa_s->dpp_resp_retry_time = 0; 7967 #ifdef CONFIG_TESTING_OPTIONS 7968 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); 7969 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); 7970 dpp_pkex_ephemeral_key_override_len = 0; 7971 dpp_protocol_key_override_len = 0; 7972 dpp_nonce_override_len = 0; 7973 #endif /* CONFIG_TESTING_OPTIONS */ 7974 #endif /* CONFIG_DPP */ 7975 7976 #ifdef CONFIG_TDLS 7977 #ifdef CONFIG_TDLS_TESTING 7978 tdls_testing = 0; 7979 #endif /* CONFIG_TDLS_TESTING */ 7980 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL); 7981 wpa_tdls_enable(wpa_s->wpa, 1); 7982 #endif /* CONFIG_TDLS */ 7983 7984 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 7985 wpa_supplicant_stop_countermeasures(wpa_s, NULL); 7986 7987 wpa_s->no_keep_alive = 0; 7988 wpa_s->own_disconnect_req = 0; 7989 7990 os_free(wpa_s->disallow_aps_bssid); 7991 wpa_s->disallow_aps_bssid = NULL; 7992 wpa_s->disallow_aps_bssid_count = 0; 7993 os_free(wpa_s->disallow_aps_ssid); 7994 wpa_s->disallow_aps_ssid = NULL; 7995 wpa_s->disallow_aps_ssid_count = 0; 7996 7997 wpa_s->set_sta_uapsd = 0; 7998 wpa_s->sta_uapsd = 0; 7999 8000 wpa_drv_radio_disable(wpa_s, 0); 8001 wpa_blacklist_clear(wpa_s); 8002 wpa_s->extra_blacklist_count = 0; 8003 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); 8004 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); 8005 wpa_config_flush_blobs(wpa_s->conf); 8006 wpa_s->conf->auto_interworking = 0; 8007 wpa_s->conf->okc = 0; 8008 8009 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 8010 rsn_preauth_deinit(wpa_s->wpa); 8011 8012 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); 8013 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); 8014 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); 8015 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 8016 8017 radio_remove_works(wpa_s, NULL, 1); 8018 wpa_s->ext_work_in_progress = 0; 8019 8020 wpa_s->next_ssid = NULL; 8021 8022 #ifdef CONFIG_INTERWORKING 8023 #ifdef CONFIG_HS20 8024 hs20_cancel_fetch_osu(wpa_s); 8025 hs20_del_icon(wpa_s, NULL, NULL); 8026 #endif /* CONFIG_HS20 */ 8027 #endif /* CONFIG_INTERWORKING */ 8028 8029 wpa_s->ext_mgmt_frame_handling = 0; 8030 wpa_s->ext_eapol_frame_io = 0; 8031 #ifdef CONFIG_TESTING_OPTIONS 8032 wpa_s->extra_roc_dur = 0; 8033 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE; 8034 wpa_s->p2p_go_csa_on_inv = 0; 8035 wpa_s->ignore_auth_resp = 0; 8036 wpa_s->ignore_assoc_disallow = 0; 8037 wpa_s->testing_resend_assoc = 0; 8038 wpa_s->reject_btm_req_reason = 0; 8039 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); 8040 os_free(wpa_s->get_pref_freq_list_override); 8041 wpa_s->get_pref_freq_list_override = NULL; 8042 wpabuf_free(wpa_s->sae_commit_override); 8043 wpa_s->sae_commit_override = NULL; 8044 #ifdef CONFIG_DPP 8045 os_free(wpa_s->dpp_config_obj_override); 8046 wpa_s->dpp_config_obj_override = NULL; 8047 os_free(wpa_s->dpp_discovery_override); 8048 wpa_s->dpp_discovery_override = NULL; 8049 os_free(wpa_s->dpp_groups_override); 8050 wpa_s->dpp_groups_override = NULL; 8051 dpp_test = DPP_TEST_DISABLED; 8052 #endif /* CONFIG_DPP */ 8053 #endif /* CONFIG_TESTING_OPTIONS */ 8054 8055 wpa_s->disconnected = 0; 8056 os_free(wpa_s->next_scan_freqs); 8057 wpa_s->next_scan_freqs = NULL; 8058 os_free(wpa_s->select_network_scan_freqs); 8059 wpa_s->select_network_scan_freqs = NULL; 8060 8061 wpa_bss_flush(wpa_s); 8062 if (!dl_list_empty(&wpa_s->bss)) { 8063 wpa_printf(MSG_DEBUG, 8064 "BSS table not empty after flush: %u entries, current_bss=%p bssid=" 8065 MACSTR " pending_bssid=" MACSTR, 8066 dl_list_len(&wpa_s->bss), wpa_s->current_bss, 8067 MAC2STR(wpa_s->bssid), 8068 MAC2STR(wpa_s->pending_bssid)); 8069 } 8070 8071 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); 8072 wpa_s->wnmsleep_used = 0; 8073 8074 #ifdef CONFIG_SME 8075 wpa_s->sme.last_unprot_disconnect.sec = 0; 8076 #endif /* CONFIG_SME */ 8077 8078 wpabuf_free(wpa_s->ric_ies); 8079 wpa_s->ric_ies = NULL; 8080 8081 wpa_supplicant_update_channel_list(wpa_s, NULL); 8082 8083 free_bss_tmp_disallowed(wpa_s); 8084 } 8085 8086 8087 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, 8088 char *buf, size_t buflen) 8089 { 8090 struct wpa_radio_work *work; 8091 char *pos, *end; 8092 struct os_reltime now, diff; 8093 8094 pos = buf; 8095 end = buf + buflen; 8096 8097 os_get_reltime(&now); 8098 8099 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 8100 { 8101 int ret; 8102 8103 os_reltime_sub(&now, &work->time, &diff); 8104 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n", 8105 work->type, work->wpa_s->ifname, work->freq, 8106 work->started, diff.sec, diff.usec); 8107 if (os_snprintf_error(end - pos, ret)) 8108 break; 8109 pos += ret; 8110 } 8111 8112 return pos - buf; 8113 } 8114 8115 8116 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx) 8117 { 8118 struct wpa_radio_work *work = eloop_ctx; 8119 struct wpa_external_work *ework = work->ctx; 8120 8121 wpa_dbg(work->wpa_s, MSG_DEBUG, 8122 "Timing out external radio work %u (%s)", 8123 ework->id, work->type); 8124 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id); 8125 work->wpa_s->ext_work_in_progress = 0; 8126 radio_work_done(work); 8127 os_free(ework); 8128 } 8129 8130 8131 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit) 8132 { 8133 struct wpa_external_work *ework = work->ctx; 8134 8135 if (deinit) { 8136 if (work->started) 8137 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 8138 work, NULL); 8139 8140 /* 8141 * work->type points to a buffer in ework, so need to replace 8142 * that here with a fixed string to avoid use of freed memory 8143 * in debug prints. 8144 */ 8145 work->type = "freed-ext-work"; 8146 work->ctx = NULL; 8147 os_free(ework); 8148 return; 8149 } 8150 8151 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)", 8152 ework->id, ework->type); 8153 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id); 8154 work->wpa_s->ext_work_in_progress = 1; 8155 if (!ework->timeout) 8156 ework->timeout = 10; 8157 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout, 8158 work, NULL); 8159 } 8160 8161 8162 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd, 8163 char *buf, size_t buflen) 8164 { 8165 struct wpa_external_work *ework; 8166 char *pos, *pos2; 8167 size_t type_len; 8168 int ret; 8169 unsigned int freq = 0; 8170 8171 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */ 8172 8173 ework = os_zalloc(sizeof(*ework)); 8174 if (ework == NULL) 8175 return -1; 8176 8177 pos = os_strchr(cmd, ' '); 8178 if (pos) { 8179 type_len = pos - cmd; 8180 pos++; 8181 8182 pos2 = os_strstr(pos, "freq="); 8183 if (pos2) 8184 freq = atoi(pos2 + 5); 8185 8186 pos2 = os_strstr(pos, "timeout="); 8187 if (pos2) 8188 ework->timeout = atoi(pos2 + 8); 8189 } else { 8190 type_len = os_strlen(cmd); 8191 } 8192 if (4 + type_len >= sizeof(ework->type)) 8193 type_len = sizeof(ework->type) - 4 - 1; 8194 os_strlcpy(ework->type, "ext:", sizeof(ework->type)); 8195 os_memcpy(ework->type + 4, cmd, type_len); 8196 ework->type[4 + type_len] = '\0'; 8197 8198 wpa_s->ext_work_id++; 8199 if (wpa_s->ext_work_id == 0) 8200 wpa_s->ext_work_id++; 8201 ework->id = wpa_s->ext_work_id; 8202 8203 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb, 8204 ework) < 0) { 8205 os_free(ework); 8206 return -1; 8207 } 8208 8209 ret = os_snprintf(buf, buflen, "%u", ework->id); 8210 if (os_snprintf_error(buflen, ret)) 8211 return -1; 8212 return ret; 8213 } 8214 8215 8216 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd) 8217 { 8218 struct wpa_radio_work *work; 8219 unsigned int id = atoi(cmd); 8220 8221 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 8222 { 8223 struct wpa_external_work *ework; 8224 8225 if (os_strncmp(work->type, "ext:", 4) != 0) 8226 continue; 8227 ework = work->ctx; 8228 if (id && ework->id != id) 8229 continue; 8230 wpa_dbg(wpa_s, MSG_DEBUG, 8231 "Completed external radio work %u (%s)", 8232 ework->id, ework->type); 8233 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL); 8234 wpa_s->ext_work_in_progress = 0; 8235 radio_work_done(work); 8236 os_free(ework); 8237 return 3; /* "OK\n" */ 8238 } 8239 8240 return -1; 8241 } 8242 8243 8244 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd, 8245 char *buf, size_t buflen) 8246 { 8247 if (os_strcmp(cmd, "show") == 0) 8248 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen); 8249 if (os_strncmp(cmd, "add ", 4) == 0) 8250 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen); 8251 if (os_strncmp(cmd, "done ", 5) == 0) 8252 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4); 8253 return -1; 8254 } 8255 8256 8257 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) 8258 { 8259 struct wpa_radio_work *work, *tmp; 8260 8261 if (!wpa_s || !wpa_s->radio) 8262 return; 8263 8264 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work, 8265 struct wpa_radio_work, list) { 8266 struct wpa_external_work *ework; 8267 8268 if (os_strncmp(work->type, "ext:", 4) != 0) 8269 continue; 8270 ework = work->ctx; 8271 wpa_dbg(wpa_s, MSG_DEBUG, 8272 "Flushing%s external radio work %u (%s)", 8273 work->started ? " started" : "", ework->id, 8274 ework->type); 8275 if (work->started) 8276 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 8277 work, NULL); 8278 radio_work_done(work); 8279 os_free(ework); 8280 } 8281 } 8282 8283 8284 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 8285 { 8286 struct wpa_supplicant *wpa_s = eloop_ctx; 8287 eapol_sm_notify_ctrl_response(wpa_s->eapol); 8288 } 8289 8290 8291 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value, 8292 unsigned int *scan_id_count, int scan_id[]) 8293 { 8294 const char *pos = value; 8295 8296 while (pos) { 8297 if (*pos == ' ' || *pos == '\0') 8298 break; 8299 if (*scan_id_count == MAX_SCAN_ID) 8300 return -1; 8301 scan_id[(*scan_id_count)++] = atoi(pos); 8302 pos = os_strchr(pos, ','); 8303 if (pos) 8304 pos++; 8305 } 8306 8307 return 0; 8308 } 8309 8310 8311 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 8312 char *reply, int reply_size, int *reply_len) 8313 { 8314 char *pos; 8315 unsigned int manual_scan_passive = 0; 8316 unsigned int manual_scan_use_id = 0; 8317 unsigned int manual_scan_only_new = 0; 8318 unsigned int scan_only = 0; 8319 unsigned int scan_id_count = 0; 8320 int scan_id[MAX_SCAN_ID]; 8321 void (*scan_res_handler)(struct wpa_supplicant *wpa_s, 8322 struct wpa_scan_results *scan_res); 8323 int *manual_scan_freqs = NULL; 8324 struct wpa_ssid_value *ssid = NULL, *ns; 8325 unsigned int ssid_count = 0; 8326 8327 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 8328 *reply_len = -1; 8329 return; 8330 } 8331 8332 if (radio_work_pending(wpa_s, "scan")) { 8333 wpa_printf(MSG_DEBUG, 8334 "Pending scan scheduled - reject new request"); 8335 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8336 return; 8337 } 8338 8339 #ifdef CONFIG_INTERWORKING 8340 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) { 8341 wpa_printf(MSG_DEBUG, 8342 "Interworking select in progress - reject new scan"); 8343 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8344 return; 8345 } 8346 #endif /* CONFIG_INTERWORKING */ 8347 8348 if (params) { 8349 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0) 8350 scan_only = 1; 8351 8352 pos = os_strstr(params, "freq="); 8353 if (pos) { 8354 manual_scan_freqs = freq_range_to_channel_list(wpa_s, 8355 pos + 5); 8356 if (manual_scan_freqs == NULL) { 8357 *reply_len = -1; 8358 goto done; 8359 } 8360 } 8361 8362 pos = os_strstr(params, "passive="); 8363 if (pos) 8364 manual_scan_passive = !!atoi(pos + 8); 8365 8366 pos = os_strstr(params, "use_id="); 8367 if (pos) 8368 manual_scan_use_id = atoi(pos + 7); 8369 8370 pos = os_strstr(params, "only_new=1"); 8371 if (pos) 8372 manual_scan_only_new = 1; 8373 8374 pos = os_strstr(params, "scan_id="); 8375 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count, 8376 scan_id) < 0) { 8377 *reply_len = -1; 8378 goto done; 8379 } 8380 8381 pos = os_strstr(params, "bssid="); 8382 if (pos) { 8383 u8 bssid[ETH_ALEN]; 8384 8385 pos += 6; 8386 if (hwaddr_aton(pos, bssid)) { 8387 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos); 8388 *reply_len = -1; 8389 goto done; 8390 } 8391 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); 8392 } 8393 8394 pos = params; 8395 while (pos && *pos != '\0') { 8396 if (os_strncmp(pos, "ssid ", 5) == 0) { 8397 char *end; 8398 8399 pos += 5; 8400 end = pos; 8401 while (*end) { 8402 if (*end == '\0' || *end == ' ') 8403 break; 8404 end++; 8405 } 8406 8407 ns = os_realloc_array( 8408 ssid, ssid_count + 1, 8409 sizeof(struct wpa_ssid_value)); 8410 if (ns == NULL) { 8411 *reply_len = -1; 8412 goto done; 8413 } 8414 ssid = ns; 8415 8416 if ((end - pos) & 0x01 || 8417 end - pos > 2 * SSID_MAX_LEN || 8418 hexstr2bin(pos, ssid[ssid_count].ssid, 8419 (end - pos) / 2) < 0) { 8420 wpa_printf(MSG_DEBUG, 8421 "Invalid SSID value '%s'", 8422 pos); 8423 *reply_len = -1; 8424 goto done; 8425 } 8426 ssid[ssid_count].ssid_len = (end - pos) / 2; 8427 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", 8428 ssid[ssid_count].ssid, 8429 ssid[ssid_count].ssid_len); 8430 ssid_count++; 8431 pos = end; 8432 } 8433 8434 pos = os_strchr(pos, ' '); 8435 if (pos) 8436 pos++; 8437 } 8438 } 8439 8440 wpa_s->num_ssids_from_scan_req = ssid_count; 8441 os_free(wpa_s->ssids_from_scan_req); 8442 if (ssid_count) { 8443 wpa_s->ssids_from_scan_req = ssid; 8444 ssid = NULL; 8445 } else { 8446 wpa_s->ssids_from_scan_req = NULL; 8447 } 8448 8449 if (scan_only) 8450 scan_res_handler = scan_only_handler; 8451 else if (wpa_s->scan_res_handler == scan_only_handler) 8452 scan_res_handler = NULL; 8453 else 8454 scan_res_handler = wpa_s->scan_res_handler; 8455 8456 if (!wpa_s->sched_scanning && !wpa_s->scanning && 8457 ((wpa_s->wpa_state <= WPA_SCANNING) || 8458 (wpa_s->wpa_state == WPA_COMPLETED))) { 8459 wpa_s->manual_scan_passive = manual_scan_passive; 8460 wpa_s->manual_scan_use_id = manual_scan_use_id; 8461 wpa_s->manual_scan_only_new = manual_scan_only_new; 8462 wpa_s->scan_id_count = scan_id_count; 8463 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 8464 wpa_s->scan_res_handler = scan_res_handler; 8465 os_free(wpa_s->manual_scan_freqs); 8466 wpa_s->manual_scan_freqs = manual_scan_freqs; 8467 manual_scan_freqs = NULL; 8468 8469 wpa_s->normal_scans = 0; 8470 wpa_s->scan_req = MANUAL_SCAN_REQ; 8471 wpa_s->after_wps = 0; 8472 wpa_s->known_wps_freq = 0; 8473 wpa_supplicant_req_scan(wpa_s, 0, 0); 8474 if (wpa_s->manual_scan_use_id) { 8475 wpa_s->manual_scan_id++; 8476 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 8477 wpa_s->manual_scan_id); 8478 *reply_len = os_snprintf(reply, reply_size, "%u\n", 8479 wpa_s->manual_scan_id); 8480 } 8481 } else if (wpa_s->sched_scanning) { 8482 wpa_s->manual_scan_passive = manual_scan_passive; 8483 wpa_s->manual_scan_use_id = manual_scan_use_id; 8484 wpa_s->manual_scan_only_new = manual_scan_only_new; 8485 wpa_s->scan_id_count = scan_id_count; 8486 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 8487 wpa_s->scan_res_handler = scan_res_handler; 8488 os_free(wpa_s->manual_scan_freqs); 8489 wpa_s->manual_scan_freqs = manual_scan_freqs; 8490 manual_scan_freqs = NULL; 8491 8492 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed"); 8493 wpa_supplicant_cancel_sched_scan(wpa_s); 8494 wpa_s->scan_req = MANUAL_SCAN_REQ; 8495 wpa_supplicant_req_scan(wpa_s, 0, 0); 8496 if (wpa_s->manual_scan_use_id) { 8497 wpa_s->manual_scan_id++; 8498 *reply_len = os_snprintf(reply, reply_size, "%u\n", 8499 wpa_s->manual_scan_id); 8500 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 8501 wpa_s->manual_scan_id); 8502 } 8503 } else { 8504 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request"); 8505 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 8506 } 8507 8508 done: 8509 os_free(manual_scan_freqs); 8510 os_free(ssid); 8511 } 8512 8513 8514 #ifdef CONFIG_TESTING_OPTIONS 8515 8516 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s, 8517 unsigned int freq, const u8 *dst, 8518 const u8 *src, const u8 *bssid, 8519 const u8 *data, size_t data_len, 8520 enum offchannel_send_action_result 8521 result) 8522 { 8523 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR 8524 " src=" MACSTR " bssid=" MACSTR " result=%s", 8525 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), 8526 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? 8527 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? 8528 "NO_ACK" : "FAILED")); 8529 } 8530 8531 8532 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd) 8533 { 8534 char *pos, *param; 8535 size_t len; 8536 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN]; 8537 int res, used; 8538 int freq = 0, no_cck = 0, wait_time = 0; 8539 8540 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1] 8541 * <action=Action frame payload> */ 8542 8543 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 8544 8545 pos = cmd; 8546 used = hwaddr_aton2(pos, da); 8547 if (used < 0) 8548 return -1; 8549 pos += used; 8550 while (*pos == ' ') 8551 pos++; 8552 used = hwaddr_aton2(pos, bssid); 8553 if (used < 0) 8554 return -1; 8555 pos += used; 8556 8557 param = os_strstr(pos, " freq="); 8558 if (param) { 8559 param += 6; 8560 freq = atoi(param); 8561 } 8562 8563 param = os_strstr(pos, " no_cck="); 8564 if (param) { 8565 param += 8; 8566 no_cck = atoi(param); 8567 } 8568 8569 param = os_strstr(pos, " wait_time="); 8570 if (param) { 8571 param += 11; 8572 wait_time = atoi(param); 8573 } 8574 8575 param = os_strstr(pos, " action="); 8576 if (param == NULL) 8577 return -1; 8578 param += 8; 8579 8580 len = os_strlen(param); 8581 if (len & 1) 8582 return -1; 8583 len /= 2; 8584 8585 buf = os_malloc(len); 8586 if (buf == NULL) 8587 return -1; 8588 8589 if (hexstr2bin(param, buf, len) < 0) { 8590 os_free(buf); 8591 return -1; 8592 } 8593 8594 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid, 8595 buf, len, wait_time, 8596 wpas_ctrl_iface_mgmt_tx_cb, no_cck); 8597 os_free(buf); 8598 return res; 8599 } 8600 8601 8602 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s) 8603 { 8604 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting"); 8605 offchannel_send_action_done(wpa_s); 8606 } 8607 8608 8609 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s, 8610 char *cmd) 8611 { 8612 char *pos, *param; 8613 size_t len; 8614 u8 *buf; 8615 int freq = 0, datarate = 0, ssi_signal = 0; 8616 union wpa_event_data event; 8617 8618 if (!wpa_s->ext_mgmt_frame_handling) 8619 return -1; 8620 8621 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 8622 8623 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 8624 8625 pos = cmd; 8626 param = os_strstr(pos, "freq="); 8627 if (param) { 8628 param += 5; 8629 freq = atoi(param); 8630 } 8631 8632 param = os_strstr(pos, " datarate="); 8633 if (param) { 8634 param += 10; 8635 datarate = atoi(param); 8636 } 8637 8638 param = os_strstr(pos, " ssi_signal="); 8639 if (param) { 8640 param += 12; 8641 ssi_signal = atoi(param); 8642 } 8643 8644 param = os_strstr(pos, " frame="); 8645 if (param == NULL) 8646 return -1; 8647 param += 7; 8648 8649 len = os_strlen(param); 8650 if (len & 1) 8651 return -1; 8652 len /= 2; 8653 8654 buf = os_malloc(len); 8655 if (buf == NULL) 8656 return -1; 8657 8658 if (hexstr2bin(param, buf, len) < 0) { 8659 os_free(buf); 8660 return -1; 8661 } 8662 8663 os_memset(&event, 0, sizeof(event)); 8664 event.rx_mgmt.freq = freq; 8665 event.rx_mgmt.frame = buf; 8666 event.rx_mgmt.frame_len = len; 8667 event.rx_mgmt.ssi_signal = ssi_signal; 8668 event.rx_mgmt.datarate = datarate; 8669 wpa_s->ext_mgmt_frame_handling = 0; 8670 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event); 8671 wpa_s->ext_mgmt_frame_handling = 1; 8672 8673 os_free(buf); 8674 8675 return 0; 8676 } 8677 8678 8679 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s, 8680 char *param) 8681 { 8682 struct wpa_scan_res *res; 8683 struct os_reltime now; 8684 char *pos, *end; 8685 int ret = -1; 8686 8687 if (!param) 8688 return -1; 8689 8690 if (os_strcmp(param, "START") == 0) { 8691 wpa_bss_update_start(wpa_s); 8692 return 0; 8693 } 8694 8695 if (os_strcmp(param, "END") == 0) { 8696 wpa_bss_update_end(wpa_s, NULL, 1); 8697 return 0; 8698 } 8699 8700 if (os_strncmp(param, "BSS ", 4) != 0) 8701 return -1; 8702 param += 3; 8703 8704 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2); 8705 if (!res) 8706 return -1; 8707 8708 pos = os_strstr(param, " flags="); 8709 if (pos) 8710 res->flags = strtol(pos + 7, NULL, 16); 8711 8712 pos = os_strstr(param, " bssid="); 8713 if (pos && hwaddr_aton(pos + 7, res->bssid)) 8714 goto fail; 8715 8716 pos = os_strstr(param, " freq="); 8717 if (pos) 8718 res->freq = atoi(pos + 6); 8719 8720 pos = os_strstr(param, " beacon_int="); 8721 if (pos) 8722 res->beacon_int = atoi(pos + 12); 8723 8724 pos = os_strstr(param, " caps="); 8725 if (pos) 8726 res->caps = strtol(pos + 6, NULL, 16); 8727 8728 pos = os_strstr(param, " qual="); 8729 if (pos) 8730 res->qual = atoi(pos + 6); 8731 8732 pos = os_strstr(param, " noise="); 8733 if (pos) 8734 res->noise = atoi(pos + 7); 8735 8736 pos = os_strstr(param, " level="); 8737 if (pos) 8738 res->level = atoi(pos + 7); 8739 8740 pos = os_strstr(param, " tsf="); 8741 if (pos) 8742 res->tsf = strtoll(pos + 5, NULL, 16); 8743 8744 pos = os_strstr(param, " age="); 8745 if (pos) 8746 res->age = atoi(pos + 5); 8747 8748 pos = os_strstr(param, " est_throughput="); 8749 if (pos) 8750 res->est_throughput = atoi(pos + 16); 8751 8752 pos = os_strstr(param, " snr="); 8753 if (pos) 8754 res->snr = atoi(pos + 5); 8755 8756 pos = os_strstr(param, " parent_tsf="); 8757 if (pos) 8758 res->parent_tsf = strtoll(pos + 7, NULL, 16); 8759 8760 pos = os_strstr(param, " tsf_bssid="); 8761 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid)) 8762 goto fail; 8763 8764 pos = os_strstr(param, " ie="); 8765 if (pos) { 8766 pos += 4; 8767 end = os_strchr(pos, ' '); 8768 if (!end) 8769 end = pos + os_strlen(pos); 8770 res->ie_len = (end - pos) / 2; 8771 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len)) 8772 goto fail; 8773 } 8774 8775 pos = os_strstr(param, " beacon_ie="); 8776 if (pos) { 8777 pos += 11; 8778 end = os_strchr(pos, ' '); 8779 if (!end) 8780 end = pos + os_strlen(pos); 8781 res->beacon_ie_len = (end - pos) / 2; 8782 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len, 8783 res->beacon_ie_len)) 8784 goto fail; 8785 } 8786 8787 os_get_reltime(&now); 8788 wpa_bss_update_scan_res(wpa_s, res, &now); 8789 ret = 0; 8790 fail: 8791 os_free(res); 8792 8793 return ret; 8794 } 8795 8796 8797 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) 8798 { 8799 char *pos, *param; 8800 union wpa_event_data event; 8801 enum wpa_event_type ev; 8802 8803 /* <event name> [parameters..] */ 8804 8805 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd); 8806 8807 pos = cmd; 8808 param = os_strchr(pos, ' '); 8809 if (param) 8810 *param++ = '\0'; 8811 8812 os_memset(&event, 0, sizeof(event)); 8813 8814 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) { 8815 ev = EVENT_INTERFACE_ENABLED; 8816 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) { 8817 ev = EVENT_INTERFACE_DISABLED; 8818 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) { 8819 ev = EVENT_AVOID_FREQUENCIES; 8820 if (param == NULL) 8821 param = ""; 8822 if (freq_range_list_parse(&event.freq_range, param) < 0) 8823 return -1; 8824 wpa_supplicant_event(wpa_s, ev, &event); 8825 os_free(event.freq_range.range); 8826 return 0; 8827 } else if (os_strcmp(cmd, "SCAN_RES") == 0) { 8828 return wpas_ctrl_iface_driver_scan_res(wpa_s, param); 8829 } else { 8830 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", 8831 cmd); 8832 return -1; 8833 } 8834 8835 wpa_supplicant_event(wpa_s, ev, &event); 8836 8837 return 0; 8838 } 8839 8840 8841 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd) 8842 { 8843 char *pos; 8844 u8 src[ETH_ALEN], *buf; 8845 int used; 8846 size_t len; 8847 8848 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 8849 8850 pos = cmd; 8851 used = hwaddr_aton2(pos, src); 8852 if (used < 0) 8853 return -1; 8854 pos += used; 8855 while (*pos == ' ') 8856 pos++; 8857 8858 len = os_strlen(pos); 8859 if (len & 1) 8860 return -1; 8861 len /= 2; 8862 8863 buf = os_malloc(len); 8864 if (buf == NULL) 8865 return -1; 8866 8867 if (hexstr2bin(pos, buf, len) < 0) { 8868 os_free(buf); 8869 return -1; 8870 } 8871 8872 wpa_supplicant_rx_eapol(wpa_s, src, buf, len); 8873 os_free(buf); 8874 8875 return 0; 8876 } 8877 8878 8879 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 8880 { 8881 size_t i; 8882 u32 sum = 0; 8883 const u16 *pos = buf; 8884 8885 for (i = 0; i < len / 2; i++) 8886 sum += *pos++; 8887 8888 while (sum >> 16) 8889 sum = (sum & 0xffff) + (sum >> 16); 8890 8891 return sum ^ 0xffff; 8892 } 8893 8894 8895 #define HWSIM_PACKETLEN 1500 8896 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 8897 8898 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 8899 size_t len) 8900 { 8901 struct wpa_supplicant *wpa_s = ctx; 8902 const struct ether_header *eth; 8903 struct iphdr ip; 8904 const u8 *pos; 8905 unsigned int i; 8906 char extra[30]; 8907 8908 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 8909 wpa_printf(MSG_DEBUG, 8910 "test data: RX - ignore unexpected length %d", 8911 (int) len); 8912 return; 8913 } 8914 8915 eth = (const struct ether_header *) buf; 8916 os_memcpy(&ip, eth + 1, sizeof(ip)); 8917 pos = &buf[sizeof(*eth) + sizeof(ip)]; 8918 8919 if (ip.ihl != 5 || ip.version != 4 || 8920 ntohs(ip.tot_len) > HWSIM_IP_LEN) { 8921 wpa_printf(MSG_DEBUG, 8922 "test data: RX - ignore unexpect IP header"); 8923 return; 8924 } 8925 8926 for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) { 8927 if (*pos != (u8) i) { 8928 wpa_printf(MSG_DEBUG, 8929 "test data: RX - ignore mismatching payload"); 8930 return; 8931 } 8932 pos++; 8933 } 8934 extra[0] = '\0'; 8935 if (ntohs(ip.tot_len) != HWSIM_IP_LEN) 8936 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len)); 8937 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 8938 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 8939 } 8940 8941 8942 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s, 8943 char *cmd) 8944 { 8945 int enabled = atoi(cmd); 8946 char *pos; 8947 const char *ifname; 8948 8949 if (!enabled) { 8950 if (wpa_s->l2_test) { 8951 l2_packet_deinit(wpa_s->l2_test); 8952 wpa_s->l2_test = NULL; 8953 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled"); 8954 } 8955 return 0; 8956 } 8957 8958 if (wpa_s->l2_test) 8959 return 0; 8960 8961 pos = os_strstr(cmd, " ifname="); 8962 if (pos) 8963 ifname = pos + 8; 8964 else 8965 ifname = wpa_s->ifname; 8966 8967 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr, 8968 ETHERTYPE_IP, wpas_data_test_rx, 8969 wpa_s, 1); 8970 if (wpa_s->l2_test == NULL) 8971 return -1; 8972 8973 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled"); 8974 8975 return 0; 8976 } 8977 8978 8979 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) 8980 { 8981 u8 dst[ETH_ALEN], src[ETH_ALEN]; 8982 char *pos, *pos2; 8983 int used; 8984 long int val; 8985 u8 tos; 8986 u8 buf[2 + HWSIM_PACKETLEN]; 8987 struct ether_header *eth; 8988 struct iphdr *ip; 8989 u8 *dpos; 8990 unsigned int i; 8991 size_t send_len = HWSIM_IP_LEN; 8992 8993 if (wpa_s->l2_test == NULL) 8994 return -1; 8995 8996 /* format: <dst> <src> <tos> [len=<length>] */ 8997 8998 pos = cmd; 8999 used = hwaddr_aton2(pos, dst); 9000 if (used < 0) 9001 return -1; 9002 pos += used; 9003 while (*pos == ' ') 9004 pos++; 9005 used = hwaddr_aton2(pos, src); 9006 if (used < 0) 9007 return -1; 9008 pos += used; 9009 9010 val = strtol(pos, &pos2, 0); 9011 if (val < 0 || val > 0xff) 9012 return -1; 9013 tos = val; 9014 9015 pos = os_strstr(pos2, " len="); 9016 if (pos) { 9017 i = atoi(pos + 5); 9018 if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 9019 return -1; 9020 send_len = i; 9021 } 9022 9023 eth = (struct ether_header *) &buf[2]; 9024 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 9025 os_memcpy(eth->ether_shost, src, ETH_ALEN); 9026 eth->ether_type = htons(ETHERTYPE_IP); 9027 ip = (struct iphdr *) (eth + 1); 9028 os_memset(ip, 0, sizeof(*ip)); 9029 ip->ihl = 5; 9030 ip->version = 4; 9031 ip->ttl = 64; 9032 ip->tos = tos; 9033 ip->tot_len = htons(send_len); 9034 ip->protocol = 1; 9035 ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 9036 ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 9037 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 9038 dpos = (u8 *) (ip + 1); 9039 for (i = 0; i < send_len - sizeof(*ip); i++) 9040 *dpos++ = i; 9041 9042 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2], 9043 sizeof(struct ether_header) + send_len) < 0) 9044 return -1; 9045 9046 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR 9047 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 9048 9049 return 0; 9050 } 9051 9052 9053 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s, 9054 char *cmd) 9055 { 9056 u8 *buf; 9057 struct ether_header *eth; 9058 struct l2_packet_data *l2 = NULL; 9059 size_t len; 9060 u16 ethertype; 9061 int res = -1; 9062 9063 len = os_strlen(cmd); 9064 if (len & 1 || len < ETH_HLEN * 2) 9065 return -1; 9066 len /= 2; 9067 9068 buf = os_malloc(len); 9069 if (buf == NULL) 9070 return -1; 9071 9072 if (hexstr2bin(cmd, buf, len) < 0) 9073 goto done; 9074 9075 eth = (struct ether_header *) buf; 9076 ethertype = ntohs(eth->ether_type); 9077 9078 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype, 9079 wpas_data_test_rx, wpa_s, 1); 9080 if (l2 == NULL) 9081 goto done; 9082 9083 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 9084 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res); 9085 done: 9086 if (l2) 9087 l2_packet_deinit(l2); 9088 os_free(buf); 9089 9090 return res < 0 ? -1 : 0; 9091 } 9092 9093 9094 static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd) 9095 { 9096 #ifdef WPA_TRACE_BFD 9097 char *pos; 9098 9099 wpa_trace_fail_after = atoi(cmd); 9100 pos = os_strchr(cmd, ':'); 9101 if (pos) { 9102 pos++; 9103 os_strlcpy(wpa_trace_fail_func, pos, 9104 sizeof(wpa_trace_fail_func)); 9105 } else { 9106 wpa_trace_fail_after = 0; 9107 } 9108 return 0; 9109 #else /* WPA_TRACE_BFD */ 9110 return -1; 9111 #endif /* WPA_TRACE_BFD */ 9112 } 9113 9114 9115 static int wpas_ctrl_get_alloc_fail(struct wpa_supplicant *wpa_s, 9116 char *buf, size_t buflen) 9117 { 9118 #ifdef WPA_TRACE_BFD 9119 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after, 9120 wpa_trace_fail_func); 9121 #else /* WPA_TRACE_BFD */ 9122 return -1; 9123 #endif /* WPA_TRACE_BFD */ 9124 } 9125 9126 9127 static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd) 9128 { 9129 #ifdef WPA_TRACE_BFD 9130 char *pos; 9131 9132 wpa_trace_test_fail_after = atoi(cmd); 9133 pos = os_strchr(cmd, ':'); 9134 if (pos) { 9135 pos++; 9136 os_strlcpy(wpa_trace_test_fail_func, pos, 9137 sizeof(wpa_trace_test_fail_func)); 9138 } else { 9139 wpa_trace_test_fail_after = 0; 9140 } 9141 return 0; 9142 #else /* WPA_TRACE_BFD */ 9143 return -1; 9144 #endif /* WPA_TRACE_BFD */ 9145 } 9146 9147 9148 static int wpas_ctrl_get_fail(struct wpa_supplicant *wpa_s, 9149 char *buf, size_t buflen) 9150 { 9151 #ifdef WPA_TRACE_BFD 9152 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after, 9153 wpa_trace_test_fail_func); 9154 #else /* WPA_TRACE_BFD */ 9155 return -1; 9156 #endif /* WPA_TRACE_BFD */ 9157 } 9158 9159 9160 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx) 9161 { 9162 struct wpa_supplicant *wpa_s = eloop_ctx; 9163 int i, count = (intptr_t) timeout_ctx; 9164 9165 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages", 9166 count); 9167 for (i = 0; i < count; i++) { 9168 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d", 9169 i + 1, count); 9170 } 9171 } 9172 9173 9174 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd) 9175 { 9176 int count; 9177 9178 count = atoi(cmd); 9179 if (count <= 0) 9180 return -1; 9181 9182 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s, 9183 (void *) (intptr_t) count); 9184 } 9185 9186 9187 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s, 9188 const char *cmd) 9189 { 9190 struct wpabuf *buf; 9191 size_t len; 9192 9193 len = os_strlen(cmd); 9194 if (len & 1) 9195 return -1; 9196 len /= 2; 9197 9198 if (len == 0) { 9199 buf = NULL; 9200 } else { 9201 buf = wpabuf_alloc(len); 9202 if (buf == NULL) 9203 return -1; 9204 9205 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 9206 wpabuf_free(buf); 9207 return -1; 9208 } 9209 } 9210 9211 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf); 9212 return 0; 9213 } 9214 9215 9216 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s) 9217 { 9218 u8 zero[WPA_TK_MAX_LEN]; 9219 9220 if (wpa_s->last_tk_alg == WPA_ALG_NONE) 9221 return -1; 9222 9223 wpa_printf(MSG_INFO, "TESTING: Reset PN"); 9224 os_memset(zero, 0, sizeof(zero)); 9225 9226 /* First, use a zero key to avoid any possible duplicate key avoidance 9227 * in the driver. */ 9228 if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 9229 wpa_s->last_tk_key_idx, 1, zero, 6, 9230 zero, wpa_s->last_tk_len) < 0) 9231 return -1; 9232 9233 /* Set the previously configured key to reset its TSC/RSC */ 9234 return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 9235 wpa_s->last_tk_key_idx, 1, zero, 6, 9236 wpa_s->last_tk, wpa_s->last_tk_len); 9237 } 9238 9239 9240 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) 9241 { 9242 const char *pos = cmd; 9243 int error, pairwise; 9244 9245 error = atoi(pos); 9246 pos = os_strchr(pos, ' '); 9247 if (!pos) 9248 return -1; 9249 pairwise = atoi(pos); 9250 wpa_sm_key_request(wpa_s->wpa, error, pairwise); 9251 return 0; 9252 } 9253 9254 9255 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) 9256 { 9257 #ifdef CONFIG_SME 9258 struct wpa_driver_associate_params params; 9259 int ret; 9260 9261 os_memset(¶ms, 0, sizeof(params)); 9262 params.bssid = wpa_s->bssid; 9263 params.ssid = wpa_s->sme.ssid; 9264 params.ssid_len = wpa_s->sme.ssid_len; 9265 params.freq.freq = wpa_s->sme.freq; 9266 if (wpa_s->last_assoc_req_wpa_ie) { 9267 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); 9268 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); 9269 } 9270 params.pairwise_suite = wpa_s->pairwise_cipher; 9271 params.group_suite = wpa_s->group_cipher; 9272 params.mgmt_group_suite = wpa_s->mgmt_group_cipher; 9273 params.key_mgmt_suite = wpa_s->key_mgmt; 9274 params.wpa_proto = wpa_s->wpa_proto; 9275 params.mgmt_frame_protection = wpa_s->sme.mfp; 9276 params.rrm_used = wpa_s->rrm.rrm_used; 9277 if (wpa_s->sme.prev_bssid_set) 9278 params.prev_bssid = wpa_s->sme.prev_bssid; 9279 wpa_printf(MSG_INFO, "TESTING: Resend association request"); 9280 ret = wpa_drv_associate(wpa_s, ¶ms); 9281 wpa_s->testing_resend_assoc = 1; 9282 return ret; 9283 #else /* CONFIG_SME */ 9284 return -1; 9285 #endif /* CONFIG_SME */ 9286 } 9287 9288 #endif /* CONFIG_TESTING_OPTIONS */ 9289 9290 9291 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd) 9292 { 9293 char *pos = cmd; 9294 int frame; 9295 size_t len; 9296 struct wpabuf *buf; 9297 struct ieee802_11_elems elems; 9298 9299 frame = atoi(pos); 9300 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9301 return -1; 9302 wpa_s = wpas_vendor_elem(wpa_s, frame); 9303 9304 pos = os_strchr(pos, ' '); 9305 if (pos == NULL) 9306 return -1; 9307 pos++; 9308 9309 len = os_strlen(pos); 9310 if (len == 0) 9311 return 0; 9312 if (len & 1) 9313 return -1; 9314 len /= 2; 9315 9316 buf = wpabuf_alloc(len); 9317 if (buf == NULL) 9318 return -1; 9319 9320 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 9321 wpabuf_free(buf); 9322 return -1; 9323 } 9324 9325 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) == 9326 ParseFailed) { 9327 wpabuf_free(buf); 9328 return -1; 9329 } 9330 9331 if (wpa_s->vendor_elem[frame] == NULL) { 9332 wpa_s->vendor_elem[frame] = buf; 9333 wpas_vendor_elem_update(wpa_s); 9334 return 0; 9335 } 9336 9337 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) { 9338 wpabuf_free(buf); 9339 return -1; 9340 } 9341 9342 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf); 9343 wpabuf_free(buf); 9344 wpas_vendor_elem_update(wpa_s); 9345 9346 return 0; 9347 } 9348 9349 9350 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd, 9351 char *buf, size_t buflen) 9352 { 9353 int frame = atoi(cmd); 9354 9355 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9356 return -1; 9357 wpa_s = wpas_vendor_elem(wpa_s, frame); 9358 9359 if (wpa_s->vendor_elem[frame] == NULL) 9360 return 0; 9361 9362 return wpa_snprintf_hex(buf, buflen, 9363 wpabuf_head_u8(wpa_s->vendor_elem[frame]), 9364 wpabuf_len(wpa_s->vendor_elem[frame])); 9365 } 9366 9367 9368 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd) 9369 { 9370 char *pos = cmd; 9371 int frame; 9372 size_t len; 9373 u8 *buf; 9374 struct ieee802_11_elems elems; 9375 int res; 9376 9377 frame = atoi(pos); 9378 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 9379 return -1; 9380 wpa_s = wpas_vendor_elem(wpa_s, frame); 9381 9382 pos = os_strchr(pos, ' '); 9383 if (pos == NULL) 9384 return -1; 9385 pos++; 9386 9387 if (*pos == '*') { 9388 wpabuf_free(wpa_s->vendor_elem[frame]); 9389 wpa_s->vendor_elem[frame] = NULL; 9390 wpas_vendor_elem_update(wpa_s); 9391 return 0; 9392 } 9393 9394 if (wpa_s->vendor_elem[frame] == NULL) 9395 return -1; 9396 9397 len = os_strlen(pos); 9398 if (len == 0) 9399 return 0; 9400 if (len & 1) 9401 return -1; 9402 len /= 2; 9403 9404 buf = os_malloc(len); 9405 if (buf == NULL) 9406 return -1; 9407 9408 if (hexstr2bin(pos, buf, len) < 0) { 9409 os_free(buf); 9410 return -1; 9411 } 9412 9413 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) { 9414 os_free(buf); 9415 return -1; 9416 } 9417 9418 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len); 9419 os_free(buf); 9420 return res; 9421 } 9422 9423 9424 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep) 9425 { 9426 struct wpa_supplicant *wpa_s = ctx; 9427 size_t len; 9428 const u8 *data; 9429 9430 /* 9431 * Neighbor Report element (IEEE P802.11-REVmc/D5.0) 9432 * BSSID[6] 9433 * BSSID Information[4] 9434 * Operating Class[1] 9435 * Channel Number[1] 9436 * PHY Type[1] 9437 * Optional Subelements[variable] 9438 */ 9439 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) 9440 9441 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) { 9442 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED); 9443 goto out; 9444 } 9445 9446 data = wpabuf_head_u8(neighbor_rep); 9447 len = wpabuf_len(neighbor_rep); 9448 9449 while (len >= 2 + NR_IE_MIN_LEN) { 9450 const u8 *nr; 9451 char lci[256 * 2 + 1]; 9452 char civic[256 * 2 + 1]; 9453 u8 nr_len = data[1]; 9454 const u8 *pos = data, *end; 9455 9456 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || 9457 nr_len < NR_IE_MIN_LEN) { 9458 wpa_printf(MSG_DEBUG, 9459 "CTRL: Invalid Neighbor Report element: id=%u len=%u", 9460 data[0], nr_len); 9461 goto out; 9462 } 9463 9464 if (2U + nr_len > len) { 9465 wpa_printf(MSG_DEBUG, 9466 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", 9467 data[0], len, nr_len); 9468 goto out; 9469 } 9470 pos += 2; 9471 end = pos + nr_len; 9472 9473 nr = pos; 9474 pos += NR_IE_MIN_LEN; 9475 9476 lci[0] = '\0'; 9477 civic[0] = '\0'; 9478 while (end - pos > 2) { 9479 u8 s_id, s_len; 9480 9481 s_id = *pos++; 9482 s_len = *pos++; 9483 if (s_len > end - pos) 9484 goto out; 9485 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) { 9486 /* Measurement Token[1] */ 9487 /* Measurement Report Mode[1] */ 9488 /* Measurement Type[1] */ 9489 /* Measurement Report[variable] */ 9490 switch (pos[2]) { 9491 case MEASURE_TYPE_LCI: 9492 if (lci[0]) 9493 break; 9494 wpa_snprintf_hex(lci, sizeof(lci), 9495 pos, s_len); 9496 break; 9497 case MEASURE_TYPE_LOCATION_CIVIC: 9498 if (civic[0]) 9499 break; 9500 wpa_snprintf_hex(civic, sizeof(civic), 9501 pos, s_len); 9502 break; 9503 } 9504 } 9505 9506 pos += s_len; 9507 } 9508 9509 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED 9510 "bssid=" MACSTR 9511 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s", 9512 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), 9513 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], 9514 nr[ETH_ALEN + 6], 9515 lci[0] ? " lci=" : "", lci, 9516 civic[0] ? " civic=" : "", civic); 9517 9518 data = end; 9519 len -= 2 + nr_len; 9520 } 9521 9522 out: 9523 wpabuf_free(neighbor_rep); 9524 } 9525 9526 9527 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s, 9528 char *cmd) 9529 { 9530 struct wpa_ssid_value ssid, *ssid_p = NULL; 9531 int ret, lci = 0, civic = 0; 9532 char *ssid_s; 9533 9534 ssid_s = os_strstr(cmd, "ssid="); 9535 if (ssid_s) { 9536 if (ssid_parse(ssid_s + 5, &ssid)) { 9537 wpa_printf(MSG_ERROR, 9538 "CTRL: Send Neighbor Report: bad SSID"); 9539 return -1; 9540 } 9541 9542 ssid_p = &ssid; 9543 9544 /* 9545 * Move cmd after the SSID text that may include "lci" or 9546 * "civic". 9547 */ 9548 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' '); 9549 if (cmd) 9550 cmd++; 9551 9552 } 9553 9554 if (cmd && os_strstr(cmd, "lci")) 9555 lci = 1; 9556 9557 if (cmd && os_strstr(cmd, "civic")) 9558 civic = 1; 9559 9560 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, 9561 wpas_ctrl_neighbor_rep_cb, 9562 wpa_s); 9563 9564 return ret; 9565 } 9566 9567 9568 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s) 9569 { 9570 eapol_sm_erp_flush(wpa_s->eapol); 9571 return 0; 9572 } 9573 9574 9575 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, 9576 char *cmd) 9577 { 9578 char *token, *context = NULL; 9579 unsigned int enable = ~0, type = 0; 9580 u8 _addr[ETH_ALEN], _mask[ETH_ALEN]; 9581 u8 *addr = NULL, *mask = NULL; 9582 9583 while ((token = str_token(cmd, " ", &context))) { 9584 if (os_strcasecmp(token, "scan") == 0) { 9585 type |= MAC_ADDR_RAND_SCAN; 9586 } else if (os_strcasecmp(token, "sched") == 0) { 9587 type |= MAC_ADDR_RAND_SCHED_SCAN; 9588 } else if (os_strcasecmp(token, "pno") == 0) { 9589 type |= MAC_ADDR_RAND_PNO; 9590 } else if (os_strcasecmp(token, "all") == 0) { 9591 type = wpa_s->mac_addr_rand_supported; 9592 } else if (os_strncasecmp(token, "enable=", 7) == 0) { 9593 enable = atoi(token + 7); 9594 } else if (os_strncasecmp(token, "addr=", 5) == 0) { 9595 addr = _addr; 9596 if (hwaddr_aton(token + 5, addr)) { 9597 wpa_printf(MSG_INFO, 9598 "CTRL: Invalid MAC address: %s", 9599 token); 9600 return -1; 9601 } 9602 } else if (os_strncasecmp(token, "mask=", 5) == 0) { 9603 mask = _mask; 9604 if (hwaddr_aton(token + 5, mask)) { 9605 wpa_printf(MSG_INFO, 9606 "CTRL: Invalid MAC address mask: %s", 9607 token); 9608 return -1; 9609 } 9610 } else { 9611 wpa_printf(MSG_INFO, 9612 "CTRL: Invalid MAC_RAND_SCAN parameter: %s", 9613 token); 9614 return -1; 9615 } 9616 } 9617 9618 if (!type) { 9619 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified"); 9620 return -1; 9621 } 9622 9623 if (enable > 1) { 9624 wpa_printf(MSG_INFO, 9625 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified"); 9626 return -1; 9627 } 9628 9629 if (!enable) 9630 return wpas_disable_mac_addr_randomization(wpa_s, type); 9631 9632 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask); 9633 } 9634 9635 9636 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s, 9637 char *buf, size_t buflen) 9638 { 9639 size_t reply_len; 9640 9641 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen); 9642 #ifdef CONFIG_AP 9643 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len], 9644 buflen - reply_len); 9645 #endif /* CONFIG_AP */ 9646 return reply_len; 9647 } 9648 9649 9650 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) 9651 { 9652 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 9653 #ifdef CONFIG_AP 9654 wpas_ap_pmksa_cache_flush(wpa_s); 9655 #endif /* CONFIG_AP */ 9656 } 9657 9658 9659 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 9660 9661 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s, 9662 const char *cmd, char *buf, size_t buflen) 9663 { 9664 struct rsn_pmksa_cache_entry *entry; 9665 struct wpa_ssid *ssid; 9666 char *pos, *pos2, *end; 9667 int ret; 9668 struct os_reltime now; 9669 9670 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 9671 if (!ssid) 9672 return -1; 9673 9674 pos = buf; 9675 end = buf + buflen; 9676 9677 os_get_reltime(&now); 9678 9679 /* 9680 * Entry format: 9681 * <BSSID> <PMKID> <PMK> <reauth_time in seconds> 9682 * <expiration in seconds> <akmp> <opportunistic> 9683 * [FILS Cache Identifier] 9684 */ 9685 9686 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry; 9687 entry = entry->next) { 9688 if (entry->network_ctx != ssid) 9689 continue; 9690 9691 pos2 = pos; 9692 ret = os_snprintf(pos2, end - pos2, MACSTR " ", 9693 MAC2STR(entry->aa)); 9694 if (os_snprintf_error(end - pos2, ret)) 9695 break; 9696 pos2 += ret; 9697 9698 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid, 9699 PMKID_LEN); 9700 9701 ret = os_snprintf(pos2, end - pos2, " "); 9702 if (os_snprintf_error(end - pos2, ret)) 9703 break; 9704 pos2 += ret; 9705 9706 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk, 9707 entry->pmk_len); 9708 9709 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d", 9710 (int) (entry->reauth_time - now.sec), 9711 (int) (entry->expiration - now.sec), 9712 entry->akmp, 9713 entry->opportunistic); 9714 if (os_snprintf_error(end - pos2, ret)) 9715 break; 9716 pos2 += ret; 9717 9718 if (entry->fils_cache_id_set) { 9719 ret = os_snprintf(pos2, end - pos2, " %02x%02x", 9720 entry->fils_cache_id[0], 9721 entry->fils_cache_id[1]); 9722 if (os_snprintf_error(end - pos2, ret)) 9723 break; 9724 pos2 += ret; 9725 } 9726 9727 ret = os_snprintf(pos2, end - pos2, "\n"); 9728 if (os_snprintf_error(end - pos2, ret)) 9729 break; 9730 pos2 += ret; 9731 9732 pos = pos2; 9733 } 9734 9735 return pos - buf; 9736 } 9737 9738 9739 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s, 9740 char *cmd) 9741 { 9742 struct rsn_pmksa_cache_entry *entry; 9743 struct wpa_ssid *ssid; 9744 char *pos, *pos2; 9745 int ret = -1; 9746 struct os_reltime now; 9747 int reauth_time = 0, expiration = 0, i; 9748 9749 /* 9750 * Entry format: 9751 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> 9752 * <expiration in seconds> <akmp> <opportunistic> 9753 * [FILS Cache Identifier] 9754 */ 9755 9756 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 9757 if (!ssid) 9758 return -1; 9759 9760 pos = os_strchr(cmd, ' '); 9761 if (!pos) 9762 return -1; 9763 pos++; 9764 9765 entry = os_zalloc(sizeof(*entry)); 9766 if (!entry) 9767 return -1; 9768 9769 if (hwaddr_aton(pos, entry->aa)) 9770 goto fail; 9771 9772 pos = os_strchr(pos, ' '); 9773 if (!pos) 9774 goto fail; 9775 pos++; 9776 9777 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0) 9778 goto fail; 9779 9780 pos = os_strchr(pos, ' '); 9781 if (!pos) 9782 goto fail; 9783 pos++; 9784 9785 pos2 = os_strchr(pos, ' '); 9786 if (!pos2) 9787 goto fail; 9788 entry->pmk_len = (pos2 - pos) / 2; 9789 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX || 9790 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0) 9791 goto fail; 9792 9793 pos = os_strchr(pos, ' '); 9794 if (!pos) 9795 goto fail; 9796 pos++; 9797 9798 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration, 9799 &entry->akmp, &entry->opportunistic) != 4) 9800 goto fail; 9801 for (i = 0; i < 4; i++) { 9802 pos = os_strchr(pos, ' '); 9803 if (!pos) { 9804 if (i < 3) 9805 goto fail; 9806 break; 9807 } 9808 pos++; 9809 } 9810 if (pos) { 9811 if (hexstr2bin(pos, entry->fils_cache_id, 9812 FILS_CACHE_ID_LEN) < 0) 9813 goto fail; 9814 entry->fils_cache_id_set = 1; 9815 } 9816 os_get_reltime(&now); 9817 entry->expiration = now.sec + expiration; 9818 entry->reauth_time = now.sec + reauth_time; 9819 9820 entry->network_ctx = ssid; 9821 9822 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); 9823 entry = NULL; 9824 ret = 0; 9825 fail: 9826 os_free(entry); 9827 return ret; 9828 } 9829 9830 9831 #ifdef CONFIG_MESH 9832 9833 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, 9834 const char *cmd, char *buf, 9835 size_t buflen) 9836 { 9837 u8 spa[ETH_ALEN]; 9838 9839 if (!wpa_s->ifmsh) 9840 return -1; 9841 9842 if (os_strcasecmp(cmd, "any") == 0) 9843 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); 9844 9845 if (hwaddr_aton(cmd, spa)) 9846 return -1; 9847 9848 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); 9849 } 9850 9851 9852 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, 9853 char *cmd) 9854 { 9855 /* 9856 * We do not check mesh interface existance because PMKSA should be 9857 * stored before wpa_s->ifmsh creation to suppress commit message 9858 * creation. 9859 */ 9860 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); 9861 } 9862 9863 #endif /* CONFIG_MESH */ 9864 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 9865 9866 9867 #ifdef CONFIG_FILS 9868 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s, 9869 const char *cmd) 9870 { 9871 struct fils_hlp_req *req; 9872 const char *pos; 9873 9874 /* format: <dst> <packet starting from ethertype> */ 9875 9876 req = os_zalloc(sizeof(*req)); 9877 if (!req) 9878 return -1; 9879 9880 if (hwaddr_aton(cmd, req->dst)) 9881 goto fail; 9882 9883 pos = os_strchr(cmd, ' '); 9884 if (!pos) 9885 goto fail; 9886 pos++; 9887 req->pkt = wpabuf_parse_bin(pos); 9888 if (!req->pkt) 9889 goto fail; 9890 9891 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list); 9892 return 0; 9893 fail: 9894 wpabuf_free(req->pkt); 9895 os_free(req); 9896 return -1; 9897 } 9898 #endif /* CONFIG_FILS */ 9899 9900 9901 static int wpas_ctrl_cmd_debug_level(const char *cmd) 9902 { 9903 if (os_strcmp(cmd, "PING") == 0 || 9904 os_strncmp(cmd, "BSS ", 4) == 0 || 9905 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 || 9906 os_strncmp(cmd, "STATUS", 6) == 0 || 9907 os_strncmp(cmd, "STA ", 4) == 0 || 9908 os_strncmp(cmd, "STA-", 4) == 0) 9909 return MSG_EXCESSIVE; 9910 return MSG_DEBUG; 9911 } 9912 9913 9914 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 9915 char *buf, size_t *resp_len) 9916 { 9917 char *reply; 9918 const int reply_size = 4096; 9919 int reply_len; 9920 9921 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 9922 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 9923 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 || 9924 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 9925 if (wpa_debug_show_keys) 9926 wpa_dbg(wpa_s, MSG_DEBUG, 9927 "Control interface command '%s'", buf); 9928 else 9929 wpa_dbg(wpa_s, MSG_DEBUG, 9930 "Control interface command '%s [REMOVED]'", 9931 os_strncmp(buf, WPA_CTRL_RSP, 9932 os_strlen(WPA_CTRL_RSP)) == 0 ? 9933 WPA_CTRL_RSP : 9934 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ? 9935 "SET_NETWORK" : "key-add")); 9936 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 9937 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { 9938 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 9939 (const u8 *) buf, os_strlen(buf)); 9940 } else { 9941 int level = wpas_ctrl_cmd_debug_level(buf); 9942 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 9943 } 9944 9945 reply = os_malloc(reply_size); 9946 if (reply == NULL) { 9947 *resp_len = 1; 9948 return NULL; 9949 } 9950 9951 os_memcpy(reply, "OK\n", 3); 9952 reply_len = 3; 9953 9954 if (os_strcmp(buf, "PING") == 0) { 9955 os_memcpy(reply, "PONG\n", 5); 9956 reply_len = 5; 9957 } else if (os_strcmp(buf, "IFNAME") == 0) { 9958 reply_len = os_strlen(wpa_s->ifname); 9959 os_memcpy(reply, wpa_s->ifname, reply_len); 9960 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 9961 if (wpa_debug_reopen_file() < 0) 9962 reply_len = -1; 9963 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 9964 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 9965 } else if (os_strcmp(buf, "MIB") == 0) { 9966 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 9967 if (reply_len >= 0) { 9968 reply_len += eapol_sm_get_mib(wpa_s->eapol, 9969 reply + reply_len, 9970 reply_size - reply_len); 9971 #ifdef CONFIG_MACSEC 9972 reply_len += ieee802_1x_kay_get_mib( 9973 wpa_s->kay, reply + reply_len, 9974 reply_size - reply_len); 9975 #endif /* CONFIG_MACSEC */ 9976 } 9977 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 9978 reply_len = wpa_supplicant_ctrl_iface_status( 9979 wpa_s, buf + 6, reply, reply_size); 9980 } else if (os_strcmp(buf, "PMKSA") == 0) { 9981 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); 9982 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 9983 wpas_ctrl_iface_pmksa_flush(wpa_s); 9984 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 9985 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) { 9986 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10, 9987 reply, reply_size); 9988 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 9989 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) 9990 reply_len = -1; 9991 #ifdef CONFIG_MESH 9992 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { 9993 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, 9994 reply, reply_size); 9995 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 9996 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) 9997 reply_len = -1; 9998 #endif /* CONFIG_MESH */ 9999 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 10000 } else if (os_strncmp(buf, "SET ", 4) == 0) { 10001 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 10002 reply_len = -1; 10003 } else if (os_strncmp(buf, "DUMP", 4) == 0) { 10004 reply_len = wpa_config_dump_values(wpa_s->conf, 10005 reply, reply_size); 10006 } else if (os_strncmp(buf, "GET ", 4) == 0) { 10007 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 10008 reply, reply_size); 10009 } else if (os_strcmp(buf, "LOGON") == 0) { 10010 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 10011 } else if (os_strcmp(buf, "LOGOFF") == 0) { 10012 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 10013 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 10014 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 10015 reply_len = -1; 10016 else 10017 wpas_request_connection(wpa_s); 10018 } else if (os_strcmp(buf, "REATTACH") == 0) { 10019 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || 10020 !wpa_s->current_ssid) 10021 reply_len = -1; 10022 else { 10023 wpa_s->reattach = 1; 10024 wpas_request_connection(wpa_s); 10025 } 10026 } else if (os_strcmp(buf, "RECONNECT") == 0) { 10027 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 10028 reply_len = -1; 10029 else if (wpa_s->disconnected) 10030 wpas_request_connection(wpa_s); 10031 #ifdef IEEE8021X_EAPOL 10032 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 10033 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 10034 reply_len = -1; 10035 #endif /* IEEE8021X_EAPOL */ 10036 #ifdef CONFIG_IEEE80211R 10037 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 10038 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 10039 reply_len = -1; 10040 #endif /* CONFIG_IEEE80211R */ 10041 #ifdef CONFIG_WPS 10042 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 10043 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 10044 if (res == -2) { 10045 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10046 reply_len = 17; 10047 } else if (res) 10048 reply_len = -1; 10049 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 10050 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 10051 if (res == -2) { 10052 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10053 reply_len = 17; 10054 } else if (res) 10055 reply_len = -1; 10056 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 10057 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 10058 reply, 10059 reply_size); 10060 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 10061 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 10062 wpa_s, buf + 14, reply, reply_size); 10063 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 10064 if (wpas_wps_cancel(wpa_s)) 10065 reply_len = -1; 10066 #ifdef CONFIG_WPS_NFC 10067 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 10068 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 10069 reply_len = -1; 10070 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 10071 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 10072 reply_len = -1; 10073 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 10074 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( 10075 wpa_s, buf + 21, reply, reply_size); 10076 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 10077 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 10078 wpa_s, buf + 14, reply, reply_size); 10079 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 10080 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 10081 buf + 17)) 10082 reply_len = -1; 10083 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 10084 reply_len = wpas_ctrl_nfc_get_handover_req( 10085 wpa_s, buf + 21, reply, reply_size); 10086 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 10087 reply_len = wpas_ctrl_nfc_get_handover_sel( 10088 wpa_s, buf + 21, reply, reply_size); 10089 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 10090 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20)) 10091 reply_len = -1; 10092 #endif /* CONFIG_WPS_NFC */ 10093 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 10094 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 10095 reply_len = -1; 10096 #ifdef CONFIG_AP 10097 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 10098 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 10099 wpa_s, buf + 11, reply, reply_size); 10100 #endif /* CONFIG_AP */ 10101 #ifdef CONFIG_WPS_ER 10102 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 10103 if (wpas_wps_er_start(wpa_s, NULL)) 10104 reply_len = -1; 10105 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 10106 if (wpas_wps_er_start(wpa_s, buf + 13)) 10107 reply_len = -1; 10108 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 10109 wpas_wps_er_stop(wpa_s); 10110 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 10111 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 10112 reply_len = -1; 10113 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 10114 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 10115 if (ret == -2) { 10116 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 10117 reply_len = 17; 10118 } else if (ret == -3) { 10119 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 10120 reply_len = 18; 10121 } else if (ret == -4) { 10122 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 10123 reply_len = 20; 10124 } else if (ret) 10125 reply_len = -1; 10126 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 10127 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 10128 reply_len = -1; 10129 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 10130 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 10131 buf + 18)) 10132 reply_len = -1; 10133 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 10134 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 10135 reply_len = -1; 10136 #ifdef CONFIG_WPS_NFC 10137 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 10138 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 10139 wpa_s, buf + 24, reply, reply_size); 10140 #endif /* CONFIG_WPS_NFC */ 10141 #endif /* CONFIG_WPS_ER */ 10142 #endif /* CONFIG_WPS */ 10143 #ifdef CONFIG_IBSS_RSN 10144 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 10145 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 10146 reply_len = -1; 10147 #endif /* CONFIG_IBSS_RSN */ 10148 #ifdef CONFIG_MESH 10149 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) { 10150 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 10151 wpa_s, buf + 19, reply, reply_size); 10152 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) { 10153 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 10154 wpa_s, "", reply, reply_size); 10155 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) { 10156 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15)) 10157 reply_len = -1; 10158 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) { 10159 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s, 10160 buf + 18)) 10161 reply_len = -1; 10162 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) { 10163 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17)) 10164 reply_len = -1; 10165 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) { 10166 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14)) 10167 reply_len = -1; 10168 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) { 10169 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16)) 10170 reply_len = -1; 10171 #endif /* CONFIG_MESH */ 10172 #ifdef CONFIG_P2P 10173 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 10174 if (p2p_ctrl_find(wpa_s, buf + 8)) 10175 reply_len = -1; 10176 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 10177 if (p2p_ctrl_find(wpa_s, "")) 10178 reply_len = -1; 10179 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 10180 wpas_p2p_stop_find(wpa_s); 10181 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) { 10182 if (p2p_ctrl_asp_provision(wpa_s, buf + 18)) 10183 reply_len = -1; 10184 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) { 10185 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23)) 10186 reply_len = -1; 10187 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 10188 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 10189 reply_size); 10190 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 10191 if (p2p_ctrl_listen(wpa_s, buf + 11)) 10192 reply_len = -1; 10193 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 10194 if (p2p_ctrl_listen(wpa_s, "")) 10195 reply_len = -1; 10196 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 10197 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 10198 reply_len = -1; 10199 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 10200 if (p2p_ctrl_group_add(wpa_s, "")) 10201 reply_len = -1; 10202 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 10203 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 10204 reply_len = -1; 10205 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) { 10206 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply, 10207 reply_size); 10208 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 10209 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 10210 reply_len = -1; 10211 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 10212 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 10213 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 10214 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 10215 reply_size); 10216 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 10217 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 10218 reply_len = -1; 10219 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 10220 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 10221 reply_len = -1; 10222 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 10223 wpas_p2p_sd_service_update(wpa_s); 10224 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 10225 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 10226 reply_len = -1; 10227 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 10228 wpas_p2p_service_flush(wpa_s); 10229 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 10230 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 10231 reply_len = -1; 10232 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 10233 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 10234 reply_len = -1; 10235 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) { 10236 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0) 10237 reply_len = -1; 10238 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 10239 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 10240 reply_len = -1; 10241 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 10242 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 10243 reply_len = -1; 10244 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 10245 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 10246 reply_size); 10247 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 10248 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 10249 reply_len = -1; 10250 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 10251 p2p_ctrl_flush(wpa_s); 10252 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 10253 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 10254 reply_len = -1; 10255 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 10256 if (wpas_p2p_cancel(wpa_s)) 10257 reply_len = -1; 10258 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 10259 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 10260 reply_len = -1; 10261 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 10262 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 10263 reply_len = -1; 10264 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 10265 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 10266 reply_len = -1; 10267 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 10268 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 10269 reply_len = -1; 10270 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) { 10271 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0) 10272 reply_len = -1; 10273 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) { 10274 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13)) 10275 reply_len = -1; 10276 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) { 10277 if (wpas_p2p_lo_stop(wpa_s)) 10278 reply_len = -1; 10279 #endif /* CONFIG_P2P */ 10280 #ifdef CONFIG_WIFI_DISPLAY 10281 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 10282 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 10283 reply_len = -1; 10284 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 10285 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 10286 reply, reply_size); 10287 #endif /* CONFIG_WIFI_DISPLAY */ 10288 #ifdef CONFIG_INTERWORKING 10289 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 10290 if (interworking_fetch_anqp(wpa_s) < 0) 10291 reply_len = -1; 10292 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 10293 interworking_stop_fetch_anqp(wpa_s); 10294 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { 10295 if (ctrl_interworking_select(wpa_s, NULL) < 0) 10296 reply_len = -1; 10297 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { 10298 if (ctrl_interworking_select(wpa_s, buf + 20) < 0) 10299 reply_len = -1; 10300 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 10301 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0) 10302 reply_len = -1; 10303 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) { 10304 int id; 10305 10306 id = ctrl_interworking_connect(wpa_s, buf + 25, 1); 10307 if (id < 0) 10308 reply_len = -1; 10309 else { 10310 reply_len = os_snprintf(reply, reply_size, "%d\n", id); 10311 if (os_snprintf_error(reply_size, reply_len)) 10312 reply_len = -1; 10313 } 10314 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 10315 if (get_anqp(wpa_s, buf + 9) < 0) 10316 reply_len = -1; 10317 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 10318 if (gas_request(wpa_s, buf + 12) < 0) 10319 reply_len = -1; 10320 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 10321 reply_len = gas_response_get(wpa_s, buf + 17, reply, 10322 reply_size); 10323 #endif /* CONFIG_INTERWORKING */ 10324 #ifdef CONFIG_HS20 10325 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 10326 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 10327 reply_len = -1; 10328 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 10329 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 10330 reply_len = -1; 10331 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) { 10332 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0) 10333 reply_len = -1; 10334 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) { 10335 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0) 10336 reply_len = -1; 10337 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) { 10338 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size); 10339 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) { 10340 if (del_hs20_icon(wpa_s, buf + 14) < 0) 10341 reply_len = -1; 10342 } else if (os_strcmp(buf, "FETCH_OSU") == 0) { 10343 if (hs20_fetch_osu(wpa_s, 0) < 0) 10344 reply_len = -1; 10345 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) { 10346 if (hs20_fetch_osu(wpa_s, 1) < 0) 10347 reply_len = -1; 10348 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) { 10349 hs20_cancel_fetch_osu(wpa_s); 10350 #endif /* CONFIG_HS20 */ 10351 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 10352 { 10353 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 10354 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 10355 reply_len = -1; 10356 else { 10357 /* 10358 * Notify response from timeout to allow the control 10359 * interface response to be sent first. 10360 */ 10361 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response, 10362 wpa_s, NULL); 10363 } 10364 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 10365 if (wpa_supplicant_reload_configuration(wpa_s)) 10366 reply_len = -1; 10367 } else if (os_strcmp(buf, "TERMINATE") == 0) { 10368 wpa_supplicant_terminate_proc(wpa_s->global); 10369 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 10370 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 10371 reply_len = -1; 10372 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 10373 reply_len = wpa_supplicant_ctrl_iface_blacklist( 10374 wpa_s, buf + 9, reply, reply_size); 10375 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 10376 reply_len = wpa_supplicant_ctrl_iface_log_level( 10377 wpa_s, buf + 9, reply, reply_size); 10378 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) { 10379 reply_len = wpa_supplicant_ctrl_iface_list_networks( 10380 wpa_s, buf + 14, reply, reply_size); 10381 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 10382 reply_len = wpa_supplicant_ctrl_iface_list_networks( 10383 wpa_s, NULL, reply, reply_size); 10384 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 10385 wpas_request_disconnection(wpa_s); 10386 } else if (os_strcmp(buf, "SCAN") == 0) { 10387 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); 10388 } else if (os_strncmp(buf, "SCAN ", 5) == 0) { 10389 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len); 10390 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 10391 reply_len = wpa_supplicant_ctrl_iface_scan_results( 10392 wpa_s, reply, reply_size); 10393 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) { 10394 if (wpas_abort_ongoing_scan(wpa_s) < 0) 10395 reply_len = -1; 10396 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 10397 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 10398 reply_len = -1; 10399 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 10400 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 10401 reply_len = -1; 10402 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 10403 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 10404 reply_len = -1; 10405 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 10406 reply_len = wpa_supplicant_ctrl_iface_add_network( 10407 wpa_s, reply, reply_size); 10408 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 10409 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 10410 reply_len = -1; 10411 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 10412 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 10413 reply_len = -1; 10414 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 10415 reply_len = wpa_supplicant_ctrl_iface_get_network( 10416 wpa_s, buf + 12, reply, reply_size); 10417 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 10418 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12, 10419 wpa_s)) 10420 reply_len = -1; 10421 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 10422 reply_len = wpa_supplicant_ctrl_iface_list_creds( 10423 wpa_s, reply, reply_size); 10424 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 10425 reply_len = wpa_supplicant_ctrl_iface_add_cred( 10426 wpa_s, reply, reply_size); 10427 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 10428 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 10429 reply_len = -1; 10430 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 10431 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 10432 reply_len = -1; 10433 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) { 10434 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9, 10435 reply, 10436 reply_size); 10437 #ifndef CONFIG_NO_CONFIG_WRITE 10438 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 10439 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 10440 reply_len = -1; 10441 #endif /* CONFIG_NO_CONFIG_WRITE */ 10442 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 10443 reply_len = wpa_supplicant_ctrl_iface_get_capability( 10444 wpa_s, buf + 15, reply, reply_size); 10445 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 10446 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 10447 reply_len = -1; 10448 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 10449 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 10450 reply_len = -1; 10451 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 10452 reply_len = wpa_supplicant_global_iface_list( 10453 wpa_s->global, reply, reply_size); 10454 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 10455 reply_len = wpa_supplicant_global_iface_interfaces( 10456 wpa_s->global, buf + 10, reply, reply_size); 10457 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 10458 reply_len = wpa_supplicant_ctrl_iface_bss( 10459 wpa_s, buf + 4, reply, reply_size); 10460 #ifdef CONFIG_AP 10461 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 10462 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 10463 } else if (os_strncmp(buf, "STA ", 4) == 0) { 10464 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 10465 reply_size); 10466 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 10467 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 10468 reply_size); 10469 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 10470 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 10471 reply_len = -1; 10472 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 10473 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 10474 reply_len = -1; 10475 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 10476 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) 10477 reply_len = -1; 10478 } else if (os_strcmp(buf, "STOP_AP") == 0) { 10479 if (wpas_ap_stop_ap(wpa_s)) 10480 reply_len = -1; 10481 #endif /* CONFIG_AP */ 10482 } else if (os_strcmp(buf, "SUSPEND") == 0) { 10483 wpas_notify_suspend(wpa_s->global); 10484 } else if (os_strcmp(buf, "RESUME") == 0) { 10485 wpas_notify_resume(wpa_s->global); 10486 #ifdef CONFIG_TESTING_OPTIONS 10487 } else if (os_strcmp(buf, "DROP_SA") == 0) { 10488 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 10489 #endif /* CONFIG_TESTING_OPTIONS */ 10490 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 10491 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 10492 reply_len = -1; 10493 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 10494 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0; 10495 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 10496 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 10497 reply_len = -1; 10498 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 10499 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 10500 buf + 17)) 10501 reply_len = -1; 10502 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 10503 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10); 10504 #ifdef CONFIG_TDLS 10505 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 10506 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 10507 reply_len = -1; 10508 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 10509 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 10510 reply_len = -1; 10511 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 10512 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 10513 reply_len = -1; 10514 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) { 10515 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s, 10516 buf + 17)) 10517 reply_len = -1; 10518 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) { 10519 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s, 10520 buf + 24)) 10521 reply_len = -1; 10522 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) { 10523 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status( 10524 wpa_s, buf + 17, reply, reply_size); 10525 #endif /* CONFIG_TDLS */ 10526 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) { 10527 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size); 10528 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) { 10529 if (wmm_ac_ctrl_addts(wpa_s, buf + 13)) 10530 reply_len = -1; 10531 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) { 10532 if (wmm_ac_ctrl_delts(wpa_s, buf + 13)) 10533 reply_len = -1; 10534 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 10535 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 10536 reply_size); 10537 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) { 10538 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14)) 10539 reply_len = -1; 10540 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 10541 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 10542 reply_size); 10543 #ifdef CONFIG_AUTOSCAN 10544 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 10545 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 10546 reply_len = -1; 10547 #endif /* CONFIG_AUTOSCAN */ 10548 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 10549 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, 10550 reply_size); 10551 #ifdef ANDROID 10552 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 10553 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 10554 reply_size); 10555 #endif /* ANDROID */ 10556 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 10557 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply, 10558 reply_size); 10559 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 10560 pmksa_cache_clear_current(wpa_s->wpa); 10561 eapol_sm_request_reauth(wpa_s->eapol); 10562 #ifdef CONFIG_WNM 10563 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 10564 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 10565 reply_len = -1; 10566 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) { 10567 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14)) 10568 reply_len = -1; 10569 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) { 10570 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) 10571 reply_len = -1; 10572 #endif /* CONFIG_WNM */ 10573 } else if (os_strcmp(buf, "FLUSH") == 0) { 10574 wpa_supplicant_ctrl_iface_flush(wpa_s); 10575 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { 10576 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply, 10577 reply_size); 10578 #ifdef CONFIG_TESTING_OPTIONS 10579 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 10580 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0) 10581 reply_len = -1; 10582 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) { 10583 wpas_ctrl_iface_mgmt_tx_done(wpa_s); 10584 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 10585 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0) 10586 reply_len = -1; 10587 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) { 10588 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0) 10589 reply_len = -1; 10590 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 10591 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0) 10592 reply_len = -1; 10593 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 10594 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0) 10595 reply_len = -1; 10596 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 10597 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0) 10598 reply_len = -1; 10599 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 10600 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0) 10601 reply_len = -1; 10602 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 10603 if (wpas_ctrl_test_alloc_fail(wpa_s, buf + 16) < 0) 10604 reply_len = -1; 10605 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 10606 reply_len = wpas_ctrl_get_alloc_fail(wpa_s, reply, reply_size); 10607 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 10608 if (wpas_ctrl_test_fail(wpa_s, buf + 10) < 0) 10609 reply_len = -1; 10610 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 10611 reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size); 10612 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) { 10613 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0) 10614 reply_len = -1; 10615 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) { 10616 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0) 10617 reply_len = -1; 10618 } else if (os_strcmp(buf, "RESET_PN") == 0) { 10619 if (wpas_ctrl_reset_pn(wpa_s) < 0) 10620 reply_len = -1; 10621 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { 10622 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) 10623 reply_len = -1; 10624 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { 10625 if (wpas_ctrl_resend_assoc(wpa_s) < 0) 10626 reply_len = -1; 10627 #ifdef CONFIG_IEEE80211W 10628 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) { 10629 sme_event_unprot_disconnect( 10630 wpa_s, wpa_s->bssid, NULL, 10631 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); 10632 #endif /* CONFIG_IEEE80211W */ 10633 #endif /* CONFIG_TESTING_OPTIONS */ 10634 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { 10635 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) 10636 reply_len = -1; 10637 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) { 10638 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply, 10639 reply_size); 10640 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) { 10641 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0) 10642 reply_len = -1; 10643 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) { 10644 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20)) 10645 reply_len = -1; 10646 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 10647 wpas_ctrl_iface_erp_flush(wpa_s); 10648 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) { 10649 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14)) 10650 reply_len = -1; 10651 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { 10652 reply_len = wpas_ctrl_iface_get_pref_freq_list( 10653 wpa_s, buf + 19, reply, reply_size); 10654 #ifdef CONFIG_FILS 10655 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) { 10656 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17)) 10657 reply_len = -1; 10658 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) { 10659 wpas_flush_fils_hlp_req(wpa_s); 10660 #endif /* CONFIG_FILS */ 10661 #ifdef CONFIG_DPP 10662 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 10663 int res; 10664 10665 res = wpas_dpp_qr_code(wpa_s, buf + 12); 10666 if (res < 0) { 10667 reply_len = -1; 10668 } else { 10669 reply_len = os_snprintf(reply, reply_size, "%d", res); 10670 if (os_snprintf_error(reply_size, reply_len)) 10671 reply_len = -1; 10672 } 10673 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 10674 int res; 10675 10676 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); 10677 if (res < 0) { 10678 reply_len = -1; 10679 } else { 10680 reply_len = os_snprintf(reply, reply_size, "%d", res); 10681 if (os_snprintf_error(reply_size, reply_len)) 10682 reply_len = -1; 10683 } 10684 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 10685 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0) 10686 reply_len = -1; 10687 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 10688 const char *uri; 10689 10690 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22)); 10691 if (!uri) { 10692 reply_len = -1; 10693 } else { 10694 reply_len = os_snprintf(reply, reply_size, "%s", uri); 10695 if (os_snprintf_error(reply_size, reply_len)) 10696 reply_len = -1; 10697 } 10698 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 10699 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), 10700 reply, reply_size); 10701 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 10702 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) 10703 reply_len = -1; 10704 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 10705 if (wpas_dpp_listen(wpa_s, buf + 11) < 0) 10706 reply_len = -1; 10707 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 10708 wpas_dpp_stop(wpa_s); 10709 wpas_dpp_listen_stop(wpa_s); 10710 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 10711 int res; 10712 10713 res = dpp_configurator_add(wpa_s->dpp, buf + 20); 10714 if (res < 0) { 10715 reply_len = -1; 10716 } else { 10717 reply_len = os_snprintf(reply, reply_size, "%d", res); 10718 if (os_snprintf_error(reply_size, reply_len)) 10719 reply_len = -1; 10720 } 10721 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 10722 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) 10723 reply_len = -1; 10724 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 10725 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) 10726 reply_len = -1; 10727 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 10728 reply_len = dpp_configurator_get_key_id(wpa_s->dpp, 10729 atoi(buf + 25), 10730 reply, reply_size); 10731 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 10732 int res; 10733 10734 res = wpas_dpp_pkex_add(wpa_s, buf + 12); 10735 if (res < 0) { 10736 reply_len = -1; 10737 } else { 10738 reply_len = os_snprintf(reply, reply_size, "%d", res); 10739 if (os_snprintf_error(reply_size, reply_len)) 10740 reply_len = -1; 10741 } 10742 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 10743 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) 10744 reply_len = -1; 10745 #ifdef CONFIG_DPP2 10746 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { 10747 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0) 10748 reply_len = -1; 10749 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { 10750 if (wpas_dpp_controller_start(wpa_s, NULL) < 0) 10751 reply_len = -1; 10752 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { 10753 dpp_controller_stop(wpa_s->dpp); 10754 #endif /* CONFIG_DPP2 */ 10755 #endif /* CONFIG_DPP */ 10756 } else { 10757 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 10758 reply_len = 16; 10759 } 10760 10761 if (reply_len < 0) { 10762 os_memcpy(reply, "FAIL\n", 5); 10763 reply_len = 5; 10764 } 10765 10766 *resp_len = reply_len; 10767 return reply; 10768 } 10769 10770 10771 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 10772 char *cmd) 10773 { 10774 struct wpa_interface iface; 10775 char *pos, *extra; 10776 struct wpa_supplicant *wpa_s; 10777 unsigned int create_iface = 0; 10778 u8 mac_addr[ETH_ALEN]; 10779 enum wpa_driver_if_type type = WPA_IF_STATION; 10780 10781 /* 10782 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 10783 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]] 10784 */ 10785 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 10786 10787 os_memset(&iface, 0, sizeof(iface)); 10788 10789 do { 10790 iface.ifname = pos = cmd; 10791 pos = os_strchr(pos, '\t'); 10792 if (pos) 10793 *pos++ = '\0'; 10794 if (iface.ifname[0] == '\0') 10795 return -1; 10796 if (pos == NULL) 10797 break; 10798 10799 iface.confname = pos; 10800 pos = os_strchr(pos, '\t'); 10801 if (pos) 10802 *pos++ = '\0'; 10803 if (iface.confname[0] == '\0') 10804 iface.confname = NULL; 10805 if (pos == NULL) 10806 break; 10807 10808 iface.driver = pos; 10809 pos = os_strchr(pos, '\t'); 10810 if (pos) 10811 *pos++ = '\0'; 10812 if (iface.driver[0] == '\0') 10813 iface.driver = NULL; 10814 if (pos == NULL) 10815 break; 10816 10817 iface.ctrl_interface = pos; 10818 pos = os_strchr(pos, '\t'); 10819 if (pos) 10820 *pos++ = '\0'; 10821 if (iface.ctrl_interface[0] == '\0') 10822 iface.ctrl_interface = NULL; 10823 if (pos == NULL) 10824 break; 10825 10826 iface.driver_param = pos; 10827 pos = os_strchr(pos, '\t'); 10828 if (pos) 10829 *pos++ = '\0'; 10830 if (iface.driver_param[0] == '\0') 10831 iface.driver_param = NULL; 10832 if (pos == NULL) 10833 break; 10834 10835 iface.bridge_ifname = pos; 10836 pos = os_strchr(pos, '\t'); 10837 if (pos) 10838 *pos++ = '\0'; 10839 if (iface.bridge_ifname[0] == '\0') 10840 iface.bridge_ifname = NULL; 10841 if (pos == NULL) 10842 break; 10843 10844 extra = pos; 10845 pos = os_strchr(pos, '\t'); 10846 if (pos) 10847 *pos++ = '\0'; 10848 if (!extra[0]) 10849 break; 10850 10851 if (os_strcmp(extra, "create") == 0) { 10852 create_iface = 1; 10853 if (!pos) 10854 break; 10855 10856 if (os_strcmp(pos, "sta") == 0) { 10857 type = WPA_IF_STATION; 10858 } else if (os_strcmp(pos, "ap") == 0) { 10859 type = WPA_IF_AP_BSS; 10860 } else { 10861 wpa_printf(MSG_DEBUG, 10862 "INTERFACE_ADD unsupported interface type: '%s'", 10863 pos); 10864 return -1; 10865 } 10866 } else { 10867 wpa_printf(MSG_DEBUG, 10868 "INTERFACE_ADD unsupported extra parameter: '%s'", 10869 extra); 10870 return -1; 10871 } 10872 } while (0); 10873 10874 if (create_iface) { 10875 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'", 10876 iface.ifname); 10877 if (!global->ifaces) 10878 return -1; 10879 if (wpa_drv_if_add(global->ifaces, type, iface.ifname, 10880 NULL, NULL, NULL, mac_addr, NULL) < 0) { 10881 wpa_printf(MSG_ERROR, 10882 "CTRL_IFACE interface creation failed"); 10883 return -1; 10884 } 10885 10886 wpa_printf(MSG_DEBUG, 10887 "CTRL_IFACE interface '%s' created with MAC addr: " 10888 MACSTR, iface.ifname, MAC2STR(mac_addr)); 10889 } 10890 10891 if (wpa_supplicant_get_iface(global, iface.ifname)) 10892 goto fail; 10893 10894 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); 10895 if (!wpa_s) 10896 goto fail; 10897 wpa_s->added_vif = create_iface; 10898 return 0; 10899 10900 fail: 10901 if (create_iface) 10902 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname); 10903 return -1; 10904 } 10905 10906 10907 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 10908 char *cmd) 10909 { 10910 struct wpa_supplicant *wpa_s; 10911 int ret; 10912 unsigned int delete_iface; 10913 10914 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 10915 10916 wpa_s = wpa_supplicant_get_iface(global, cmd); 10917 if (wpa_s == NULL) 10918 return -1; 10919 delete_iface = wpa_s->added_vif; 10920 ret = wpa_supplicant_remove_iface(global, wpa_s, 0); 10921 if (!ret && delete_iface) { 10922 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'", 10923 cmd); 10924 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd); 10925 } 10926 return ret; 10927 } 10928 10929 10930 static void wpa_free_iface_info(struct wpa_interface_info *iface) 10931 { 10932 struct wpa_interface_info *prev; 10933 10934 while (iface) { 10935 prev = iface; 10936 iface = iface->next; 10937 10938 os_free(prev->ifname); 10939 os_free(prev->desc); 10940 os_free(prev); 10941 } 10942 } 10943 10944 10945 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 10946 char *buf, int len) 10947 { 10948 int i, res; 10949 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 10950 char *pos, *end; 10951 10952 for (i = 0; wpa_drivers[i]; i++) { 10953 const struct wpa_driver_ops *drv = wpa_drivers[i]; 10954 if (drv->get_interfaces == NULL) 10955 continue; 10956 tmp = drv->get_interfaces(global->drv_priv[i]); 10957 if (tmp == NULL) 10958 continue; 10959 10960 if (last == NULL) 10961 iface = last = tmp; 10962 else 10963 last->next = tmp; 10964 while (last->next) 10965 last = last->next; 10966 } 10967 10968 pos = buf; 10969 end = buf + len; 10970 for (tmp = iface; tmp; tmp = tmp->next) { 10971 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 10972 tmp->drv_name, tmp->ifname, 10973 tmp->desc ? tmp->desc : ""); 10974 if (os_snprintf_error(end - pos, res)) { 10975 *pos = '\0'; 10976 break; 10977 } 10978 pos += res; 10979 } 10980 10981 wpa_free_iface_info(iface); 10982 10983 return pos - buf; 10984 } 10985 10986 10987 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 10988 const char *input, 10989 char *buf, int len) 10990 { 10991 int res; 10992 char *pos, *end; 10993 struct wpa_supplicant *wpa_s; 10994 int show_ctrl = 0; 10995 10996 if (input) 10997 show_ctrl = !!os_strstr(input, "ctrl"); 10998 10999 wpa_s = global->ifaces; 11000 pos = buf; 11001 end = buf + len; 11002 11003 while (wpa_s) { 11004 if (show_ctrl) 11005 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n", 11006 wpa_s->ifname, 11007 wpa_s->conf->ctrl_interface ? 11008 wpa_s->conf->ctrl_interface : "N/A"); 11009 else 11010 res = os_snprintf(pos, end - pos, "%s\n", 11011 wpa_s->ifname); 11012 11013 if (os_snprintf_error(end - pos, res)) { 11014 *pos = '\0'; 11015 break; 11016 } 11017 pos += res; 11018 wpa_s = wpa_s->next; 11019 } 11020 return pos - buf; 11021 } 11022 11023 11024 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global, 11025 const char *ifname, 11026 char *cmd, size_t *resp_len) 11027 { 11028 struct wpa_supplicant *wpa_s; 11029 11030 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11031 if (os_strcmp(ifname, wpa_s->ifname) == 0) 11032 break; 11033 } 11034 11035 if (wpa_s == NULL) { 11036 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n"); 11037 if (resp) 11038 *resp_len = os_strlen(resp); 11039 else 11040 *resp_len = 1; 11041 return resp; 11042 } 11043 11044 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len); 11045 } 11046 11047 11048 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, 11049 char *buf, size_t *resp_len) 11050 { 11051 #ifdef CONFIG_P2P 11052 static const char * cmd[] = { 11053 "LIST_NETWORKS", 11054 "P2P_FIND", 11055 "P2P_STOP_FIND", 11056 "P2P_LISTEN", 11057 "P2P_GROUP_ADD", 11058 "P2P_GET_PASSPHRASE", 11059 "P2P_SERVICE_UPDATE", 11060 "P2P_SERVICE_FLUSH", 11061 "P2P_FLUSH", 11062 "P2P_CANCEL", 11063 "P2P_PRESENCE_REQ", 11064 "P2P_EXT_LISTEN", 11065 #ifdef CONFIG_AP 11066 "STA-FIRST", 11067 #endif /* CONFIG_AP */ 11068 NULL 11069 }; 11070 static const char * prefix[] = { 11071 #ifdef ANDROID 11072 "DRIVER ", 11073 #endif /* ANDROID */ 11074 "GET_CAPABILITY ", 11075 "GET_NETWORK ", 11076 "REMOVE_NETWORK ", 11077 "P2P_FIND ", 11078 "P2P_CONNECT ", 11079 "P2P_LISTEN ", 11080 "P2P_GROUP_REMOVE ", 11081 "P2P_GROUP_ADD ", 11082 "P2P_GROUP_MEMBER ", 11083 "P2P_PROV_DISC ", 11084 "P2P_SERV_DISC_REQ ", 11085 "P2P_SERV_DISC_CANCEL_REQ ", 11086 "P2P_SERV_DISC_RESP ", 11087 "P2P_SERV_DISC_EXTERNAL ", 11088 "P2P_SERVICE_ADD ", 11089 "P2P_SERVICE_DEL ", 11090 "P2P_SERVICE_REP ", 11091 "P2P_REJECT ", 11092 "P2P_INVITE ", 11093 "P2P_PEER ", 11094 "P2P_SET ", 11095 "P2P_UNAUTHORIZE ", 11096 "P2P_PRESENCE_REQ ", 11097 "P2P_EXT_LISTEN ", 11098 "P2P_REMOVE_CLIENT ", 11099 "WPS_NFC_TOKEN ", 11100 "WPS_NFC_TAG_READ ", 11101 "NFC_GET_HANDOVER_SEL ", 11102 "NFC_GET_HANDOVER_REQ ", 11103 "NFC_REPORT_HANDOVER ", 11104 "P2P_ASP_PROVISION ", 11105 "P2P_ASP_PROVISION_RESP ", 11106 #ifdef CONFIG_AP 11107 "STA ", 11108 "STA-NEXT ", 11109 #endif /* CONFIG_AP */ 11110 NULL 11111 }; 11112 int found = 0; 11113 int i; 11114 11115 if (global->p2p_init_wpa_s == NULL) 11116 return NULL; 11117 11118 for (i = 0; !found && cmd[i]; i++) { 11119 if (os_strcmp(buf, cmd[i]) == 0) 11120 found = 1; 11121 } 11122 11123 for (i = 0; !found && prefix[i]; i++) { 11124 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0) 11125 found = 1; 11126 } 11127 11128 if (found) 11129 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 11130 buf, resp_len); 11131 #endif /* CONFIG_P2P */ 11132 return NULL; 11133 } 11134 11135 11136 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global, 11137 char *buf, size_t *resp_len) 11138 { 11139 #ifdef CONFIG_WIFI_DISPLAY 11140 if (global->p2p_init_wpa_s == NULL) 11141 return NULL; 11142 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 || 11143 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) 11144 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 11145 buf, resp_len); 11146 #endif /* CONFIG_WIFI_DISPLAY */ 11147 return NULL; 11148 } 11149 11150 11151 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global, 11152 char *buf, size_t *resp_len) 11153 { 11154 char *ret; 11155 11156 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len); 11157 if (ret) 11158 return ret; 11159 11160 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len); 11161 if (ret) 11162 return ret; 11163 11164 return NULL; 11165 } 11166 11167 11168 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd) 11169 { 11170 char *value; 11171 11172 value = os_strchr(cmd, ' '); 11173 if (value == NULL) 11174 return -1; 11175 *value++ = '\0'; 11176 11177 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value); 11178 11179 #ifdef CONFIG_WIFI_DISPLAY 11180 if (os_strcasecmp(cmd, "wifi_display") == 0) { 11181 wifi_display_enable(global, !!atoi(value)); 11182 return 0; 11183 } 11184 #endif /* CONFIG_WIFI_DISPLAY */ 11185 11186 /* Restore cmd to its original value to allow redirection */ 11187 value[-1] = ' '; 11188 11189 return -1; 11190 } 11191 11192 11193 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global, 11194 char *cmd) 11195 { 11196 struct wpa_supplicant *wpa_s[2]; /* src, dst */ 11197 char *p; 11198 unsigned int i; 11199 11200 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id> 11201 * <variable name> */ 11202 11203 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) { 11204 p = os_strchr(cmd, ' '); 11205 if (p == NULL) 11206 return -1; 11207 *p = '\0'; 11208 11209 wpa_s[i] = global->ifaces; 11210 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) { 11211 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0) 11212 break; 11213 } 11214 11215 if (!wpa_s[i]) { 11216 wpa_printf(MSG_DEBUG, 11217 "CTRL_IFACE: Could not find iface=%s", cmd); 11218 return -1; 11219 } 11220 11221 cmd = p + 1; 11222 } 11223 11224 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]); 11225 } 11226 11227 11228 #ifndef CONFIG_NO_CONFIG_WRITE 11229 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global) 11230 { 11231 int ret = 0, saved = 0; 11232 struct wpa_supplicant *wpa_s; 11233 11234 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11235 if (!wpa_s->conf->update_config) { 11236 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)"); 11237 continue; 11238 } 11239 11240 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) { 11241 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration"); 11242 ret = 1; 11243 } else { 11244 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated"); 11245 saved++; 11246 } 11247 } 11248 11249 if (!saved && !ret) { 11250 wpa_dbg(wpa_s, MSG_DEBUG, 11251 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated"); 11252 ret = 1; 11253 } 11254 11255 return ret; 11256 } 11257 #endif /* CONFIG_NO_CONFIG_WRITE */ 11258 11259 11260 static int wpas_global_ctrl_iface_status(struct wpa_global *global, 11261 char *buf, size_t buflen) 11262 { 11263 char *pos, *end; 11264 int ret; 11265 struct wpa_supplicant *wpa_s; 11266 11267 pos = buf; 11268 end = buf + buflen; 11269 11270 #ifdef CONFIG_P2P 11271 if (global->p2p && !global->p2p_disabled) { 11272 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 11273 "\n" 11274 "p2p_state=%s\n", 11275 MAC2STR(global->p2p_dev_addr), 11276 p2p_get_state_txt(global->p2p)); 11277 if (os_snprintf_error(end - pos, ret)) 11278 return pos - buf; 11279 pos += ret; 11280 } else if (global->p2p) { 11281 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n"); 11282 if (os_snprintf_error(end - pos, ret)) 11283 return pos - buf; 11284 pos += ret; 11285 } 11286 #endif /* CONFIG_P2P */ 11287 11288 #ifdef CONFIG_WIFI_DISPLAY 11289 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n", 11290 !!global->wifi_display); 11291 if (os_snprintf_error(end - pos, ret)) 11292 return pos - buf; 11293 pos += ret; 11294 #endif /* CONFIG_WIFI_DISPLAY */ 11295 11296 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 11297 ret = os_snprintf(pos, end - pos, "ifname=%s\n" 11298 "address=" MACSTR "\n", 11299 wpa_s->ifname, MAC2STR(wpa_s->own_addr)); 11300 if (os_snprintf_error(end - pos, ret)) 11301 return pos - buf; 11302 pos += ret; 11303 } 11304 11305 return pos - buf; 11306 } 11307 11308 11309 #ifdef CONFIG_FST 11310 11311 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global, 11312 char *cmd, char *buf, 11313 size_t reply_size) 11314 { 11315 char ifname[IFNAMSIZ + 1]; 11316 struct fst_iface_cfg cfg; 11317 struct wpa_supplicant *wpa_s; 11318 struct fst_wpa_obj iface_obj; 11319 11320 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 11321 wpa_s = wpa_supplicant_get_iface(global, ifname); 11322 if (wpa_s) { 11323 if (wpa_s->fst) { 11324 wpa_printf(MSG_INFO, "FST: Already attached"); 11325 return -1; 11326 } 11327 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj); 11328 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr, 11329 &iface_obj, &cfg); 11330 if (wpa_s->fst) 11331 return os_snprintf(buf, reply_size, "OK\n"); 11332 } 11333 } 11334 11335 return -1; 11336 } 11337 11338 11339 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global, 11340 char *cmd, char *buf, 11341 size_t reply_size) 11342 { 11343 char ifname[IFNAMSIZ + 1]; 11344 struct wpa_supplicant *wpa_s; 11345 11346 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 11347 wpa_s = wpa_supplicant_get_iface(global, ifname); 11348 if (wpa_s) { 11349 if (!fst_iface_detach(ifname)) { 11350 wpa_s->fst = NULL; 11351 return os_snprintf(buf, reply_size, "OK\n"); 11352 } 11353 } 11354 } 11355 11356 return -1; 11357 } 11358 11359 #endif /* CONFIG_FST */ 11360 11361 11362 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 11363 char *buf, size_t *resp_len) 11364 { 11365 char *reply; 11366 const int reply_size = 2048; 11367 int reply_len; 11368 int level = MSG_DEBUG; 11369 11370 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 11371 char *pos = os_strchr(buf + 7, ' '); 11372 if (pos) { 11373 *pos++ = '\0'; 11374 return wpas_global_ctrl_iface_ifname(global, 11375 buf + 7, pos, 11376 resp_len); 11377 } 11378 } 11379 11380 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len); 11381 if (reply) 11382 return reply; 11383 11384 if (os_strcmp(buf, "PING") == 0) 11385 level = MSG_EXCESSIVE; 11386 wpa_hexdump_ascii(level, "RX global ctrl_iface", 11387 (const u8 *) buf, os_strlen(buf)); 11388 11389 reply = os_malloc(reply_size); 11390 if (reply == NULL) { 11391 *resp_len = 1; 11392 return NULL; 11393 } 11394 11395 os_memcpy(reply, "OK\n", 3); 11396 reply_len = 3; 11397 11398 if (os_strcmp(buf, "PING") == 0) { 11399 os_memcpy(reply, "PONG\n", 5); 11400 reply_len = 5; 11401 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 11402 if (wpa_supplicant_global_iface_add(global, buf + 14)) 11403 reply_len = -1; 11404 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 11405 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 11406 reply_len = -1; 11407 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 11408 reply_len = wpa_supplicant_global_iface_list( 11409 global, reply, reply_size); 11410 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 11411 reply_len = wpa_supplicant_global_iface_interfaces( 11412 global, buf + 10, reply, reply_size); 11413 #ifdef CONFIG_FST 11414 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 11415 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11, 11416 reply, 11417 reply_size); 11418 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 11419 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11, 11420 reply, 11421 reply_size); 11422 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 11423 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 11424 #endif /* CONFIG_FST */ 11425 } else if (os_strcmp(buf, "TERMINATE") == 0) { 11426 wpa_supplicant_terminate_proc(global); 11427 } else if (os_strcmp(buf, "SUSPEND") == 0) { 11428 wpas_notify_suspend(global); 11429 } else if (os_strcmp(buf, "RESUME") == 0) { 11430 wpas_notify_resume(global); 11431 } else if (os_strncmp(buf, "SET ", 4) == 0) { 11432 if (wpas_global_ctrl_iface_set(global, buf + 4)) { 11433 #ifdef CONFIG_P2P 11434 if (global->p2p_init_wpa_s) { 11435 os_free(reply); 11436 /* Check if P2P redirection would work for this 11437 * command. */ 11438 return wpa_supplicant_ctrl_iface_process( 11439 global->p2p_init_wpa_s, 11440 buf, resp_len); 11441 } 11442 #endif /* CONFIG_P2P */ 11443 reply_len = -1; 11444 } 11445 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 11446 if (wpas_global_ctrl_iface_dup_network(global, buf + 12)) 11447 reply_len = -1; 11448 #ifndef CONFIG_NO_CONFIG_WRITE 11449 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 11450 if (wpas_global_ctrl_iface_save_config(global)) 11451 reply_len = -1; 11452 #endif /* CONFIG_NO_CONFIG_WRITE */ 11453 } else if (os_strcmp(buf, "STATUS") == 0) { 11454 reply_len = wpas_global_ctrl_iface_status(global, reply, 11455 reply_size); 11456 #ifdef CONFIG_MODULE_TESTS 11457 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 11458 if (wpas_module_tests() < 0) 11459 reply_len = -1; 11460 #endif /* CONFIG_MODULE_TESTS */ 11461 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 11462 if (wpa_debug_reopen_file() < 0) 11463 reply_len = -1; 11464 } else { 11465 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 11466 reply_len = 16; 11467 } 11468 11469 if (reply_len < 0) { 11470 os_memcpy(reply, "FAIL\n", 5); 11471 reply_len = 5; 11472 } 11473 11474 *resp_len = reply_len; 11475 return reply; 11476 } 11477