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