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