1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2024, 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/nan_de.h" 26 #include "common/ptksa_cache.h" 27 #include "crypto/tls.h" 28 #include "ap/hostapd.h" 29 #include "eap_peer/eap.h" 30 #include "eapol_supp/eapol_supp_sm.h" 31 #include "rsn_supp/wpa.h" 32 #include "rsn_supp/preauth.h" 33 #include "rsn_supp/pmksa_cache.h" 34 #include "l2_packet/l2_packet.h" 35 #include "wps/wps.h" 36 #include "fst/fst.h" 37 #include "fst/fst_ctrl_iface.h" 38 #include "config.h" 39 #include "wpa_supplicant_i.h" 40 #include "driver_i.h" 41 #include "wps_supplicant.h" 42 #include "ibss_rsn.h" 43 #include "wpas_glue.h" 44 #include "ap.h" 45 #include "p2p_supplicant.h" 46 #include "p2p/p2p.h" 47 #include "hs20_supplicant.h" 48 #include "wifi_display.h" 49 #include "notify.h" 50 #include "bss.h" 51 #include "scan.h" 52 #include "ctrl_iface.h" 53 #include "interworking.h" 54 #include "bssid_ignore.h" 55 #include "autoscan.h" 56 #include "wnm_sta.h" 57 #include "offchannel.h" 58 #include "drivers/driver.h" 59 #include "mesh.h" 60 #include "dpp_supplicant.h" 61 #include "sme.h" 62 #include "nan_usd.h" 63 64 #ifdef __NetBSD__ 65 #include <net/if_ether.h> 66 #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS) 67 #include <net/ethernet.h> 68 #endif 69 70 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 71 char *buf, int len); 72 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 73 const char *input, 74 char *buf, int len); 75 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, 76 char *val); 77 78 79 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 80 { 81 char *pos; 82 u8 addr[ETH_ALEN], *filter = NULL, *n; 83 size_t count = 0; 84 85 pos = val; 86 while (pos) { 87 if (*pos == '\0') 88 break; 89 if (hwaddr_aton(pos, addr)) { 90 os_free(filter); 91 return -1; 92 } 93 n = os_realloc_array(filter, count + 1, ETH_ALEN); 94 if (n == NULL) { 95 os_free(filter); 96 return -1; 97 } 98 filter = n; 99 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 100 count++; 101 102 pos = os_strchr(pos, ' '); 103 if (pos) 104 pos++; 105 } 106 107 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 108 os_free(wpa_s->bssid_filter); 109 wpa_s->bssid_filter = filter; 110 wpa_s->bssid_filter_count = count; 111 112 return 0; 113 } 114 115 116 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 117 { 118 char *pos; 119 u8 addr[ETH_ALEN], *bssid = NULL, *n; 120 struct wpa_ssid_value *ssid = NULL, *ns; 121 size_t count = 0, ssid_count = 0; 122 struct wpa_ssid *c; 123 124 /* 125 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | "" 126 * SSID_SPEC ::= ssid <SSID_HEX> 127 * BSSID_SPEC ::= bssid <BSSID_HEX> 128 */ 129 130 pos = val; 131 while (pos) { 132 if (*pos == '\0') 133 break; 134 if (os_strncmp(pos, "bssid ", 6) == 0) { 135 int res; 136 pos += 6; 137 res = hwaddr_aton2(pos, addr); 138 if (res < 0) { 139 os_free(ssid); 140 os_free(bssid); 141 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 142 "BSSID value '%s'", pos); 143 return -1; 144 } 145 pos += res; 146 n = os_realloc_array(bssid, count + 1, ETH_ALEN); 147 if (n == NULL) { 148 os_free(ssid); 149 os_free(bssid); 150 return -1; 151 } 152 bssid = n; 153 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 154 count++; 155 } else if (os_strncmp(pos, "ssid ", 5) == 0) { 156 char *end; 157 pos += 5; 158 159 end = pos; 160 while (*end) { 161 if (*end == '\0' || *end == ' ') 162 break; 163 end++; 164 } 165 166 ns = os_realloc_array(ssid, ssid_count + 1, 167 sizeof(struct wpa_ssid_value)); 168 if (ns == NULL) { 169 os_free(ssid); 170 os_free(bssid); 171 return -1; 172 } 173 ssid = ns; 174 175 if ((end - pos) & 0x01 || 176 end - pos > 2 * SSID_MAX_LEN || 177 hexstr2bin(pos, ssid[ssid_count].ssid, 178 (end - pos) / 2) < 0) { 179 os_free(ssid); 180 os_free(bssid); 181 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 182 "SSID value '%s'", pos); 183 return -1; 184 } 185 ssid[ssid_count].ssid_len = (end - pos) / 2; 186 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 187 ssid[ssid_count].ssid, 188 ssid[ssid_count].ssid_len); 189 ssid_count++; 190 pos = end; 191 } else { 192 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 193 "'%s'", pos); 194 os_free(ssid); 195 os_free(bssid); 196 return -1; 197 } 198 199 pos = os_strchr(pos, ' '); 200 if (pos) 201 pos++; 202 } 203 204 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 205 os_free(wpa_s->disallow_aps_bssid); 206 wpa_s->disallow_aps_bssid = bssid; 207 wpa_s->disallow_aps_bssid_count = count; 208 209 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 210 os_free(wpa_s->disallow_aps_ssid); 211 wpa_s->disallow_aps_ssid = ssid; 212 wpa_s->disallow_aps_ssid_count = ssid_count; 213 214 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 215 return 0; 216 217 c = wpa_s->current_ssid; 218 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 219 return 0; 220 221 if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 222 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 223 return 0; 224 225 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 226 "because current AP was marked disallowed"); 227 228 #ifdef CONFIG_SME 229 wpa_s->sme.prev_bssid_set = 0; 230 #endif /* CONFIG_SME */ 231 wpa_s->reassociate = 1; 232 wpa_s->own_disconnect_req = 1; 233 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 234 wpa_supplicant_req_scan(wpa_s, 0, 0); 235 236 return 0; 237 } 238 239 240 #ifndef CONFIG_NO_CONFIG_BLOBS 241 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos) 242 { 243 char *name = pos; 244 struct wpa_config_blob *blob; 245 size_t len; 246 247 pos = os_strchr(pos, ' '); 248 if (pos == NULL) 249 return -1; 250 *pos++ = '\0'; 251 len = os_strlen(pos); 252 if (len & 1) 253 return -1; 254 255 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name); 256 blob = os_zalloc(sizeof(*blob)); 257 if (blob == NULL) 258 return -1; 259 blob->name = os_strdup(name); 260 blob->data = os_malloc(len / 2); 261 if (blob->name == NULL || blob->data == NULL) { 262 wpa_config_free_blob(blob); 263 return -1; 264 } 265 266 if (hexstr2bin(pos, blob->data, len / 2) < 0) { 267 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data"); 268 wpa_config_free_blob(blob); 269 return -1; 270 } 271 blob->len = len / 2; 272 273 wpa_config_set_blob(wpa_s->conf, blob); 274 275 return 0; 276 } 277 #endif /* CONFIG_NO_CONFIG_BLOBS */ 278 279 280 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) 281 { 282 char *params; 283 char *pos; 284 int *freqs = NULL; 285 int ret; 286 287 if (atoi(cmd)) { 288 params = os_strchr(cmd, ' '); 289 os_free(wpa_s->manual_sched_scan_freqs); 290 if (params) { 291 params++; 292 pos = os_strstr(params, "freq="); 293 if (pos) 294 freqs = freq_range_to_channel_list(wpa_s, 295 pos + 5); 296 } 297 wpa_s->manual_sched_scan_freqs = freqs; 298 ret = wpas_start_pno(wpa_s); 299 } else { 300 ret = wpas_stop_pno(wpa_s); 301 } 302 return ret; 303 } 304 305 306 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands) 307 { 308 union wpa_event_data event; 309 u32 setband_mask = WPA_SETBAND_AUTO; 310 311 /* 312 * For example: 313 * SET setband 2G,6G 314 * SET setband 5G 315 * SET setband AUTO 316 */ 317 if (!os_strstr(bands, "AUTO")) { 318 if (os_strstr(bands, "5G")) 319 setband_mask |= WPA_SETBAND_5G; 320 if (os_strstr(bands, "6G")) 321 setband_mask |= WPA_SETBAND_6G; 322 if (os_strstr(bands, "2G")) 323 setband_mask |= WPA_SETBAND_2G; 324 if (setband_mask == WPA_SETBAND_AUTO) 325 return -1; 326 } 327 328 wpa_s->setband_mask = setband_mask; 329 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) { 330 os_memset(&event, 0, sizeof(event)); 331 event.channel_list_changed.initiator = REGDOM_SET_BY_USER; 332 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; 333 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event); 334 } 335 336 return 0; 337 } 338 339 340 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s, 341 const char *cmd) 342 { 343 struct wpabuf *lci; 344 345 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 346 wpabuf_free(wpa_s->lci); 347 wpa_s->lci = NULL; 348 return 0; 349 } 350 351 lci = wpabuf_parse_bin(cmd); 352 if (!lci) 353 return -1; 354 355 if (os_get_reltime(&wpa_s->lci_time)) { 356 wpabuf_free(lci); 357 return -1; 358 } 359 360 wpabuf_free(wpa_s->lci); 361 wpa_s->lci = lci; 362 363 return 0; 364 } 365 366 367 static int 368 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd) 369 { 370 int relative_rssi; 371 372 if (os_strcmp(cmd, "disable") == 0) { 373 wpa_s->srp.relative_rssi_set = 0; 374 return 0; 375 } 376 377 relative_rssi = atoi(cmd); 378 if (relative_rssi < 0 || relative_rssi > 100) 379 return -1; 380 wpa_s->srp.relative_rssi = relative_rssi; 381 wpa_s->srp.relative_rssi_set = 1; 382 return 0; 383 } 384 385 386 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s, 387 const char *cmd) 388 { 389 char *pos; 390 int adjust_rssi; 391 392 /* <band>:adjust_value */ 393 pos = os_strchr(cmd, ':'); 394 if (!pos) 395 return -1; 396 pos++; 397 adjust_rssi = atoi(pos); 398 if (adjust_rssi < -100 || adjust_rssi > 100) 399 return -1; 400 401 if (os_strncmp(cmd, "2G", 2) == 0) 402 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G; 403 else if (os_strncmp(cmd, "5G", 2) == 0) 404 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G; 405 else 406 return -1; 407 408 wpa_s->srp.relative_adjust_rssi = adjust_rssi; 409 410 return 0; 411 } 412 413 414 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s, 415 const char *cmd) 416 { 417 struct wpabuf *ric_ies; 418 419 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 420 wpabuf_free(wpa_s->ric_ies); 421 wpa_s->ric_ies = NULL; 422 return 0; 423 } 424 425 ric_ies = wpabuf_parse_bin(cmd); 426 if (!ric_ies) 427 return -1; 428 429 wpabuf_free(wpa_s->ric_ies); 430 wpa_s->ric_ies = ric_ies; 431 432 return 0; 433 } 434 435 436 #ifdef CONFIG_TESTING_OPTIONS 437 static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s, 438 const char *val) 439 { 440 u8 bssid[ETH_ALEN]; 441 const char *pos = val; 442 struct driver_signal_override *dso = NULL, *tmp, parsed; 443 444 if (hwaddr_aton(pos, bssid)) 445 return -1; 446 pos = os_strchr(pos, ' '); 447 448 dl_list_for_each(tmp, &wpa_s->drv_signal_override, 449 struct driver_signal_override, list) { 450 if (ether_addr_equal(bssid, tmp->bssid)) { 451 dso = tmp; 452 break; 453 } 454 } 455 456 if (!pos) { 457 /* Remove existing entry */ 458 if (dso) { 459 dl_list_del(&dso->list); 460 os_free(dso); 461 } 462 return 0; 463 } 464 pos++; 465 466 /* Update an existing entry or add a new one */ 467 os_memset(&parsed, 0, sizeof(parsed)); 468 if (sscanf(pos, "%d %d %d %d %d", 469 &parsed.si_current_signal, 470 &parsed.si_avg_signal, 471 &parsed.si_avg_beacon_signal, 472 &parsed.si_current_noise, 473 &parsed.scan_level) != 5) 474 return -1; 475 476 if (!dso) { 477 dso = os_zalloc(sizeof(*dso)); 478 if (!dso) 479 return -1; 480 os_memcpy(dso->bssid, bssid, ETH_ALEN); 481 dl_list_add(&wpa_s->drv_signal_override, &dso->list); 482 } 483 dso->si_current_signal = parsed.si_current_signal; 484 dso->si_avg_signal = parsed.si_avg_signal; 485 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal; 486 dso->si_current_noise = parsed.si_current_noise; 487 dso->scan_level = parsed.scan_level; 488 489 return 0; 490 } 491 #endif /* CONFIG_TESTING_OPTIONS */ 492 493 494 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 495 char *cmd) 496 { 497 char *value; 498 int ret = 0; 499 500 value = os_strchr(cmd, ' '); 501 if (value == NULL) 502 return -1; 503 *value++ = '\0'; 504 505 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 506 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 507 eapol_sm_configure(wpa_s->eapol, 508 atoi(value), -1, -1, -1); 509 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 510 eapol_sm_configure(wpa_s->eapol, 511 -1, atoi(value), -1, -1); 512 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 513 eapol_sm_configure(wpa_s->eapol, 514 -1, -1, atoi(value), -1); 515 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 516 eapol_sm_configure(wpa_s->eapol, 517 -1, -1, -1, atoi(value)); 518 #ifdef CONFIG_TESTING_OPTIONS 519 } else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) { 520 if (os_strcmp(value, "Auto") == 0) 521 eapol_sm_notify_portControl(wpa_s->eapol, Auto); 522 else if (os_strcmp(value, "ForceUnauthorized") == 0) 523 eapol_sm_notify_portControl(wpa_s->eapol, 524 ForceUnauthorized); 525 else if (os_strcmp(value, "ForceAuthorized") == 0) 526 eapol_sm_notify_portControl(wpa_s->eapol, 527 ForceAuthorized); 528 else 529 ret = -1; 530 #endif /* CONFIG_TESTING_OPTIONS */ 531 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 532 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 533 atoi(value))) { 534 ret = -1; 535 } else { 536 value[-1] = '='; 537 wpa_config_process_global(wpa_s->conf, cmd, -1); 538 } 539 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 540 0) { 541 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 542 atoi(value))) { 543 ret = -1; 544 } else { 545 value[-1] = '='; 546 wpa_config_process_global(wpa_s->conf, cmd, -1); 547 } 548 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 549 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 550 atoi(value))) { 551 ret = -1; 552 } else { 553 value[-1] = '='; 554 wpa_config_process_global(wpa_s->conf, cmd, -1); 555 } 556 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 557 wpa_s->wps_fragment_size = atoi(value); 558 #ifdef CONFIG_WPS_TESTING 559 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 560 long int val; 561 val = strtol(value, NULL, 0); 562 if (val < 0 || val > 0xff) { 563 ret = -1; 564 wpa_printf(MSG_DEBUG, "WPS: Invalid " 565 "wps_version_number %ld", val); 566 } else { 567 wps_version_number = val; 568 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 569 "version %u.%u", 570 (wps_version_number & 0xf0) >> 4, 571 wps_version_number & 0x0f); 572 } 573 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) { 574 wps_testing_stub_cred = atoi(value); 575 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d", 576 wps_testing_stub_cred); 577 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 578 wps_corrupt_pkhash = atoi(value); 579 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 580 wps_corrupt_pkhash); 581 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) { 582 if (value[0] == '\0') { 583 wps_force_auth_types_in_use = 0; 584 } else { 585 wps_force_auth_types = strtol(value, NULL, 0); 586 wps_force_auth_types_in_use = 1; 587 } 588 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) { 589 if (value[0] == '\0') { 590 wps_force_encr_types_in_use = 0; 591 } else { 592 wps_force_encr_types = strtol(value, NULL, 0); 593 wps_force_encr_types_in_use = 1; 594 } 595 #endif /* CONFIG_WPS_TESTING */ 596 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 597 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 598 ret = -1; 599 #ifdef CONFIG_TDLS 600 #ifdef CONFIG_TDLS_TESTING 601 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 602 tdls_testing = strtol(value, NULL, 0); 603 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 604 #endif /* CONFIG_TDLS_TESTING */ 605 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 606 int disabled = atoi(value); 607 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 608 if (disabled) { 609 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 610 ret = -1; 611 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 612 ret = -1; 613 wpa_tdls_enable(wpa_s->wpa, !disabled); 614 #endif /* CONFIG_TDLS */ 615 } else if (os_strcasecmp(cmd, "pno") == 0) { 616 ret = wpas_ctrl_pno(wpa_s, value); 617 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 618 int disabled = atoi(value); 619 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 620 ret = -1; 621 else if (disabled) 622 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 623 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 624 if (os_strcmp(value, "disable") == 0) 625 wpa_s->set_sta_uapsd = 0; 626 else { 627 int be, bk, vi, vo; 628 char *pos; 629 /* format: BE,BK,VI,VO;max SP Length */ 630 be = atoi(value); 631 pos = os_strchr(value, ','); 632 if (pos == NULL) 633 return -1; 634 pos++; 635 bk = atoi(pos); 636 pos = os_strchr(pos, ','); 637 if (pos == NULL) 638 return -1; 639 pos++; 640 vi = atoi(pos); 641 pos = os_strchr(pos, ','); 642 if (pos == NULL) 643 return -1; 644 pos++; 645 vo = atoi(pos); 646 /* ignore max SP Length for now */ 647 648 wpa_s->set_sta_uapsd = 1; 649 wpa_s->sta_uapsd = 0; 650 if (be) 651 wpa_s->sta_uapsd |= BIT(0); 652 if (bk) 653 wpa_s->sta_uapsd |= BIT(1); 654 if (vi) 655 wpa_s->sta_uapsd |= BIT(2); 656 if (vo) 657 wpa_s->sta_uapsd |= BIT(3); 658 } 659 } else if (os_strcasecmp(cmd, "ps") == 0) { 660 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 661 #ifdef CONFIG_WIFI_DISPLAY 662 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 663 int enabled = !!atoi(value); 664 if (enabled && !wpa_s->global->p2p) 665 ret = -1; 666 else 667 wifi_display_enable(wpa_s->global, enabled); 668 #endif /* CONFIG_WIFI_DISPLAY */ 669 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 670 ret = set_bssid_filter(wpa_s, value); 671 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 672 ret = set_disallow_aps(wpa_s, value); 673 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 674 wpa_s->no_keep_alive = !!atoi(value); 675 #ifdef CONFIG_DPP 676 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { 677 os_free(wpa_s->dpp_configurator_params); 678 wpa_s->dpp_configurator_params = os_strdup(value); 679 #ifdef CONFIG_DPP2 680 dpp_controller_set_params(wpa_s->dpp, value); 681 #endif /* CONFIG_DPP2 */ 682 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { 683 wpa_s->dpp_init_max_tries = atoi(value); 684 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { 685 wpa_s->dpp_init_retry_time = atoi(value); 686 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { 687 wpa_s->dpp_resp_wait_time = atoi(value); 688 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { 689 wpa_s->dpp_resp_max_tries = atoi(value); 690 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { 691 wpa_s->dpp_resp_retry_time = atoi(value); 692 #ifdef CONFIG_TESTING_OPTIONS 693 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) { 694 if (hwaddr_aton(value, dpp_pkex_own_mac_override)) 695 ret = -1; 696 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) { 697 if (hwaddr_aton(value, dpp_pkex_peer_mac_override)) 698 ret = -1; 699 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) { 700 size_t hex_len = os_strlen(value); 701 702 if (hex_len > 703 2 * sizeof(dpp_pkex_ephemeral_key_override)) 704 ret = -1; 705 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override, 706 hex_len / 2)) 707 ret = -1; 708 else 709 dpp_pkex_ephemeral_key_override_len = hex_len / 2; 710 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) { 711 size_t hex_len = os_strlen(value); 712 713 if (hex_len > 2 * sizeof(dpp_protocol_key_override)) 714 ret = -1; 715 else if (hexstr2bin(value, dpp_protocol_key_override, 716 hex_len / 2)) 717 ret = -1; 718 else 719 dpp_protocol_key_override_len = hex_len / 2; 720 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) { 721 size_t hex_len = os_strlen(value); 722 723 if (hex_len > 2 * sizeof(dpp_nonce_override)) 724 ret = -1; 725 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2)) 726 ret = -1; 727 else 728 dpp_nonce_override_len = hex_len / 2; 729 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { 730 dpp_version_override = atoi(value); 731 #endif /* CONFIG_TESTING_OPTIONS */ 732 #endif /* CONFIG_DPP */ 733 #ifdef CONFIG_TESTING_OPTIONS 734 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 735 wpa_s->ext_mgmt_frame_handling = !!atoi(value); 736 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 737 wpa_s->ext_eapol_frame_io = !!atoi(value); 738 #ifdef CONFIG_AP 739 if (wpa_s->ap_iface) { 740 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io = 741 wpa_s->ext_eapol_frame_io; 742 } 743 #endif /* CONFIG_AP */ 744 } else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) { 745 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 746 !!atoi(value)); 747 } else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) { 748 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 749 !!atoi(value)); 750 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) { 751 wpa_s->extra_roc_dur = atoi(value); 752 } else if (os_strcasecmp(cmd, "test_failure") == 0) { 753 wpa_s->test_failure = atoi(value); 754 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) { 755 wpa_s->p2p_go_csa_on_inv = !!atoi(value); 756 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) { 757 wpa_s->ignore_auth_resp = !!atoi(value); 758 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) { 759 wpa_s->ignore_assoc_disallow = !!atoi(value); 760 wpa_drv_ignore_assoc_disallow(wpa_s, 761 wpa_s->ignore_assoc_disallow); 762 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) { 763 wpa_s->disable_sa_query = !!atoi(value); 764 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) { 765 wpa_s->ignore_sae_h2e_only = !!atoi(value); 766 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) { 767 char *pos; 768 769 os_free(wpa_s->extra_sae_rejected_groups); 770 wpa_s->extra_sae_rejected_groups = NULL; 771 pos = value; 772 while (pos && pos[0]) { 773 int group; 774 775 group = atoi(pos); 776 wpa_printf(MSG_DEBUG, 777 "TESTING: Extra rejection of SAE group %d", 778 group); 779 if (group) 780 int_array_add_unique( 781 &wpa_s->extra_sae_rejected_groups, 782 group); 783 pos = os_strchr(pos, ' '); 784 if (!pos) 785 break; 786 pos++; 787 } 788 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) { 789 wpa_s->ft_rsnxe_used = atoi(value); 790 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) { 791 wpa_s->oci_freq_override_eapol = atoi(value); 792 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) { 793 wpa_s->oci_freq_override_saquery_req = atoi(value); 794 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) { 795 wpa_s->oci_freq_override_saquery_resp = atoi(value); 796 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) { 797 wpa_s->oci_freq_override_eapol_g2 = atoi(value); 798 /* Populate value to wpa_sm if already associated. */ 799 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, 800 wpa_s->oci_freq_override_eapol_g2); 801 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) { 802 wpa_s->oci_freq_override_ft_assoc = atoi(value); 803 /* Populate value to wpa_sm if already associated. */ 804 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, 805 wpa_s->oci_freq_override_ft_assoc); 806 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) { 807 wpa_s->oci_freq_override_fils_assoc = atoi(value); 808 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) { 809 wpa_s->oci_freq_override_wnm_sleep = atoi(value); 810 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { 811 wpabuf_free(wpa_s->rsne_override_eapol); 812 if (os_strcmp(value, "NULL") == 0) 813 wpa_s->rsne_override_eapol = NULL; 814 else 815 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value); 816 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) { 817 wpabuf_free(wpa_s->rsnxe_override_assoc); 818 if (os_strcmp(value, "NULL") == 0) 819 wpa_s->rsnxe_override_assoc = NULL; 820 else 821 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value); 822 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) { 823 wpabuf_free(wpa_s->rsnxe_override_eapol); 824 if (os_strcmp(value, "NULL") == 0) 825 wpa_s->rsnxe_override_eapol = NULL; 826 else 827 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value); 828 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) { 829 wpa_s->reject_btm_req_reason = atoi(value); 830 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) { 831 os_free(wpa_s->get_pref_freq_list_override); 832 if (!value[0]) 833 wpa_s->get_pref_freq_list_override = NULL; 834 else 835 wpa_s->get_pref_freq_list_override = os_strdup(value); 836 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) { 837 wpabuf_free(wpa_s->sae_commit_override); 838 if (value[0] == '\0') 839 wpa_s->sae_commit_override = NULL; 840 else 841 wpa_s->sae_commit_override = wpabuf_parse_bin(value); 842 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) { 843 ret = wpas_ctrl_iface_set_dso(wpa_s, value); 844 #ifndef CONFIG_NO_ROBUST_AV 845 } else if (os_strcasecmp(cmd, "disable_scs_support") == 0) { 846 wpa_s->disable_scs_support = !!atoi(value); 847 } else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) { 848 wpa_s->disable_mscs_support = !!atoi(value); 849 #endif /* CONFIG_NO_ROBUST_AV */ 850 } else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) { 851 wpa_s->disable_eapol_g2_tx = !!atoi(value); 852 /* Populate value to wpa_sm if already associated. */ 853 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX, 854 wpa_s->disable_eapol_g2_tx); 855 } else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) { 856 wpa_s->test_assoc_comeback_type = atoi(value); 857 #ifdef CONFIG_DPP 858 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { 859 os_free(wpa_s->dpp_config_obj_override); 860 if (value[0] == '\0') 861 wpa_s->dpp_config_obj_override = NULL; 862 else 863 wpa_s->dpp_config_obj_override = os_strdup(value); 864 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { 865 os_free(wpa_s->dpp_discovery_override); 866 if (value[0] == '\0') 867 wpa_s->dpp_discovery_override = NULL; 868 else 869 wpa_s->dpp_discovery_override = os_strdup(value); 870 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { 871 os_free(wpa_s->dpp_groups_override); 872 if (value[0] == '\0') 873 wpa_s->dpp_groups_override = NULL; 874 else 875 wpa_s->dpp_groups_override = os_strdup(value); 876 } else if (os_strcasecmp(cmd, 877 "dpp_ignore_netaccesskey_mismatch") == 0) { 878 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value); 879 } else if (os_strcasecmp(cmd, "dpp_discard_public_action") == 0) { 880 wpa_s->dpp_discard_public_action = atoi(value); 881 } else if (os_strcasecmp(cmd, "dpp_test") == 0) { 882 dpp_test = atoi(value); 883 #endif /* CONFIG_DPP */ 884 #endif /* CONFIG_TESTING_OPTIONS */ 885 #ifdef CONFIG_FILS 886 } else if (os_strcasecmp(cmd, "disable_fils") == 0) { 887 wpa_s->disable_fils = !!atoi(value); 888 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils); 889 wpa_supplicant_set_default_scan_ies(wpa_s); 890 #endif /* CONFIG_FILS */ 891 #ifndef CONFIG_NO_CONFIG_BLOBS 892 } else if (os_strcmp(cmd, "blob") == 0) { 893 ret = wpas_ctrl_set_blob(wpa_s, value); 894 #endif /* CONFIG_NO_CONFIG_BLOBS */ 895 } else if (os_strcasecmp(cmd, "setband") == 0) { 896 ret = wpas_ctrl_set_band(wpa_s, value); 897 #ifdef CONFIG_MBO 898 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) { 899 ret = wpas_mbo_update_non_pref_chan(wpa_s, value); 900 if (ret == 0) { 901 value[-1] = '='; 902 wpa_config_process_global(wpa_s->conf, cmd, -1); 903 } 904 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { 905 int val = atoi(value); 906 907 if (val < MBO_CELL_CAPA_AVAILABLE || 908 val > MBO_CELL_CAPA_NOT_SUPPORTED) 909 return -1; 910 911 wpas_mbo_update_cell_capa(wpa_s, val); 912 } else if (os_strcasecmp(cmd, "oce") == 0) { 913 int val = atoi(value); 914 915 if (val < 0 || val > 3) 916 return -1; 917 918 wpa_s->conf->oce = val; 919 if (wpa_s->conf->oce) { 920 if ((wpa_s->conf->oce & OCE_STA) && 921 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) 922 wpa_s->enable_oce = OCE_STA; 923 924 if ((wpa_s->conf->oce & OCE_STA_CFON) && 925 (wpa_s->drv_flags & 926 WPA_DRIVER_FLAGS_OCE_STA_CFON)) { 927 /* TODO: Need to add STA-CFON support */ 928 wpa_printf(MSG_ERROR, 929 "OCE STA-CFON feature is not yet supported"); 930 return -1; 931 } 932 } else { 933 wpa_s->enable_oce = 0; 934 } 935 wpa_supplicant_set_default_scan_ies(wpa_s); 936 #endif /* CONFIG_MBO */ 937 } else if (os_strcasecmp(cmd, "lci") == 0) { 938 ret = wpas_ctrl_iface_set_lci(wpa_s, value); 939 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) { 940 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value)); 941 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) { 942 ret = wpas_ctrl_set_relative_rssi(wpa_s, value); 943 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) { 944 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value); 945 } else if (os_strcasecmp(cmd, "ric_ies") == 0) { 946 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value); 947 } else if (os_strcasecmp(cmd, "roaming") == 0) { 948 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL); 949 #ifdef CONFIG_WNM 950 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) { 951 struct wpabuf *elems; 952 953 elems = wpabuf_parse_bin(value); 954 if (!elems) 955 return -1; 956 wnm_set_coloc_intf_elems(wpa_s, elems); 957 #endif /* CONFIG_WNM */ 958 #ifndef CONFIG_NO_ROBUST_AV 959 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) { 960 wpa_s->enable_dscp_policy_capa = !!atoi(value); 961 #endif /* CONFIG_NO_ROBUST_AV */ 962 } else { 963 value[-1] = '='; 964 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 965 if (ret == 0) 966 wpa_supplicant_update_config(wpa_s); 967 else if (ret == 1) 968 ret = 0; 969 } 970 971 return ret; 972 } 973 974 975 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 976 char *cmd, char *buf, size_t buflen) 977 { 978 int res = -1; 979 980 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 981 982 if (os_strcmp(cmd, "version") == 0) { 983 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 984 } else if (os_strcasecmp(cmd, "max_command_len") == 0) { 985 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN); 986 } else if (os_strcasecmp(cmd, "country") == 0) { 987 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 988 res = os_snprintf(buf, buflen, "%c%c", 989 wpa_s->conf->country[0], 990 wpa_s->conf->country[1]); 991 #ifdef CONFIG_WIFI_DISPLAY 992 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 993 int enabled; 994 if (wpa_s->global->p2p == NULL || 995 wpa_s->global->p2p_disabled) 996 enabled = 0; 997 else 998 enabled = wpa_s->global->wifi_display; 999 res = os_snprintf(buf, buflen, "%d", enabled); 1000 #endif /* CONFIG_WIFI_DISPLAY */ 1001 #ifdef CONFIG_TESTING_GET_GTK 1002 } else if (os_strcmp(cmd, "gtk") == 0) { 1003 if (wpa_s->last_gtk_len == 0) 1004 return -1; 1005 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk, 1006 wpa_s->last_gtk_len); 1007 return res; 1008 #endif /* CONFIG_TESTING_GET_GTK */ 1009 } else if (os_strcmp(cmd, "tls_library") == 0) { 1010 res = tls_get_library_version(buf, buflen); 1011 #ifdef CONFIG_TESTING_OPTIONS 1012 } else if (os_strcmp(cmd, "anonce") == 0) { 1013 return wpa_snprintf_hex(buf, buflen, 1014 wpa_sm_get_anonce(wpa_s->wpa), 1015 WPA_NONCE_LEN); 1016 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) { 1017 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx); 1018 #endif /* CONFIG_TESTING_OPTIONS */ 1019 } else { 1020 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); 1021 } 1022 1023 if (os_snprintf_error(buflen, res)) 1024 return -1; 1025 return res; 1026 } 1027 1028 1029 #ifdef IEEE8021X_EAPOL 1030 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 1031 char *addr) 1032 { 1033 u8 bssid[ETH_ALEN]; 1034 struct wpa_ssid *ssid = wpa_s->current_ssid; 1035 1036 if (hwaddr_aton(addr, bssid)) { 1037 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 1038 "'%s'", addr); 1039 return -1; 1040 } 1041 1042 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 1043 rsn_preauth_deinit(wpa_s->wpa); 1044 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 1045 return -1; 1046 1047 return 0; 1048 } 1049 #endif /* IEEE8021X_EAPOL */ 1050 1051 1052 #ifdef CONFIG_TDLS 1053 1054 static int wpa_supplicant_ctrl_iface_tdls_discover( 1055 struct wpa_supplicant *wpa_s, char *addr) 1056 { 1057 u8 peer[ETH_ALEN]; 1058 int ret; 1059 1060 if (hwaddr_aton(addr, peer)) { 1061 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 1062 "address '%s'", addr); 1063 return -1; 1064 } 1065 1066 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 1067 MAC2STR(peer)); 1068 1069 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1070 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 1071 else 1072 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 1073 1074 return ret; 1075 } 1076 1077 1078 static int wpa_supplicant_ctrl_iface_tdls_setup( 1079 struct wpa_supplicant *wpa_s, char *addr) 1080 { 1081 u8 peer[ETH_ALEN]; 1082 int ret; 1083 1084 if (hwaddr_aton(addr, peer)) { 1085 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 1086 "address '%s'", addr); 1087 return -1; 1088 } 1089 1090 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 1091 MAC2STR(peer)); 1092 1093 if ((wpa_s->conf->tdls_external_control) && 1094 wpa_tdls_is_external_setup(wpa_s->wpa)) 1095 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 1096 1097 wpa_tdls_remove(wpa_s->wpa, peer); 1098 1099 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1100 ret = wpa_tdls_start(wpa_s->wpa, peer); 1101 else 1102 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 1103 1104 return ret; 1105 } 1106 1107 1108 static int wpa_supplicant_ctrl_iface_tdls_teardown( 1109 struct wpa_supplicant *wpa_s, char *addr) 1110 { 1111 u8 peer[ETH_ALEN]; 1112 int ret; 1113 1114 if (os_strcmp(addr, "*") == 0) { 1115 /* remove everyone */ 1116 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *"); 1117 wpa_tdls_teardown_peers(wpa_s->wpa); 1118 return 0; 1119 } 1120 1121 if (hwaddr_aton(addr, peer)) { 1122 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 1123 "address '%s'", addr); 1124 return -1; 1125 } 1126 1127 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 1128 MAC2STR(peer)); 1129 1130 if ((wpa_s->conf->tdls_external_control) && 1131 wpa_tdls_is_external_setup(wpa_s->wpa)) 1132 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 1133 1134 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1135 ret = wpa_tdls_teardown_link( 1136 wpa_s->wpa, peer, 1137 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 1138 else 1139 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 1140 1141 return ret; 1142 } 1143 1144 1145 static int ctrl_iface_get_capability_tdls( 1146 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1147 { 1148 int ret; 1149 1150 ret = os_snprintf(buf, buflen, "%s\n", 1151 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ? 1152 (wpa_s->drv_flags & 1153 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ? 1154 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED"); 1155 if (os_snprintf_error(buflen, ret)) 1156 return -1; 1157 return ret; 1158 } 1159 1160 1161 static int wpa_supplicant_ctrl_iface_tdls_chan_switch( 1162 struct wpa_supplicant *wpa_s, char *cmd) 1163 { 1164 u8 peer[ETH_ALEN]; 1165 struct hostapd_freq_params freq_params; 1166 u8 oper_class; 1167 char *pos, *end; 1168 1169 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 1170 wpa_printf(MSG_INFO, 1171 "tdls_chanswitch: Only supported with external setup"); 1172 return -1; 1173 } 1174 1175 os_memset(&freq_params, 0, sizeof(freq_params)); 1176 1177 pos = os_strchr(cmd, ' '); 1178 if (pos == NULL) 1179 return -1; 1180 *pos++ = '\0'; 1181 1182 oper_class = strtol(pos, &end, 10); 1183 if (pos == end) { 1184 wpa_printf(MSG_INFO, 1185 "tdls_chanswitch: Invalid op class provided"); 1186 return -1; 1187 } 1188 1189 pos = end; 1190 freq_params.freq = atoi(pos); 1191 if (freq_params.freq == 0) { 1192 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided"); 1193 return -1; 1194 } 1195 1196 #define SET_FREQ_SETTING(str) \ 1197 do { \ 1198 const char *pos2 = os_strstr(pos, " " #str "="); \ 1199 if (pos2) { \ 1200 pos2 += sizeof(" " #str "=") - 1; \ 1201 freq_params.str = atoi(pos2); \ 1202 } \ 1203 } while (0) 1204 1205 SET_FREQ_SETTING(center_freq1); 1206 SET_FREQ_SETTING(center_freq2); 1207 SET_FREQ_SETTING(bandwidth); 1208 SET_FREQ_SETTING(sec_channel_offset); 1209 #undef SET_FREQ_SETTING 1210 1211 freq_params.ht_enabled = !!os_strstr(pos, " ht"); 1212 freq_params.vht_enabled = !!os_strstr(pos, " vht"); 1213 1214 if (hwaddr_aton(cmd, peer)) { 1215 wpa_printf(MSG_DEBUG, 1216 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'", 1217 cmd); 1218 return -1; 1219 } 1220 1221 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR 1222 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s", 1223 MAC2STR(peer), oper_class, freq_params.freq, 1224 freq_params.center_freq1, freq_params.center_freq2, 1225 freq_params.bandwidth, freq_params.sec_channel_offset, 1226 freq_params.ht_enabled ? " HT" : "", 1227 freq_params.vht_enabled ? " VHT" : ""); 1228 1229 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class, 1230 &freq_params); 1231 } 1232 1233 1234 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch( 1235 struct wpa_supplicant *wpa_s, char *cmd) 1236 { 1237 u8 peer[ETH_ALEN]; 1238 1239 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 1240 wpa_printf(MSG_INFO, 1241 "tdls_chanswitch: Only supported with external setup"); 1242 return -1; 1243 } 1244 1245 if (hwaddr_aton(cmd, peer)) { 1246 wpa_printf(MSG_DEBUG, 1247 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'", 1248 cmd); 1249 return -1; 1250 } 1251 1252 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR, 1253 MAC2STR(peer)); 1254 1255 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer); 1256 } 1257 1258 1259 static int wpa_supplicant_ctrl_iface_tdls_link_status( 1260 struct wpa_supplicant *wpa_s, const char *addr, 1261 char *buf, size_t buflen) 1262 { 1263 u8 peer[ETH_ALEN]; 1264 const char *tdls_status; 1265 int ret; 1266 1267 if (hwaddr_aton(addr, peer)) { 1268 wpa_printf(MSG_DEBUG, 1269 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'", 1270 addr); 1271 return -1; 1272 } 1273 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR, 1274 MAC2STR(peer)); 1275 1276 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 1277 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status); 1278 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status); 1279 if (os_snprintf_error(buflen, ret)) 1280 return -1; 1281 1282 return ret; 1283 } 1284 1285 #endif /* CONFIG_TDLS */ 1286 1287 1288 #ifndef CONFIG_NO_WMM_AC 1289 1290 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd) 1291 { 1292 char *token, *context = NULL; 1293 struct wmm_ac_ts_setup_params params = { 1294 .tsid = 0xff, 1295 .direction = 0xff, 1296 }; 1297 1298 while ((token = str_token(cmd, " ", &context))) { 1299 if (sscanf(token, "tsid=%i", ¶ms.tsid) == 1 || 1300 sscanf(token, "up=%i", ¶ms.user_priority) == 1 || 1301 sscanf(token, "nominal_msdu_size=%i", 1302 ¶ms.nominal_msdu_size) == 1 || 1303 sscanf(token, "mean_data_rate=%i", 1304 ¶ms.mean_data_rate) == 1 || 1305 sscanf(token, "min_phy_rate=%i", 1306 ¶ms.minimum_phy_rate) == 1 || 1307 sscanf(token, "sba=%i", 1308 ¶ms.surplus_bandwidth_allowance) == 1) 1309 continue; 1310 1311 if (os_strcasecmp(token, "downlink") == 0) { 1312 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK; 1313 } else if (os_strcasecmp(token, "uplink") == 0) { 1314 params.direction = WMM_TSPEC_DIRECTION_UPLINK; 1315 } else if (os_strcasecmp(token, "bidi") == 0) { 1316 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL; 1317 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) { 1318 params.fixed_nominal_msdu = 1; 1319 } else { 1320 wpa_printf(MSG_DEBUG, 1321 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'", 1322 token); 1323 return -1; 1324 } 1325 1326 } 1327 1328 return wpas_wmm_ac_addts(wpa_s, ¶ms); 1329 } 1330 1331 1332 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd) 1333 { 1334 u8 tsid = atoi(cmd); 1335 1336 return wpas_wmm_ac_delts(wpa_s, tsid); 1337 } 1338 1339 #endif /* CONFIG_NO_WMM_AC */ 1340 1341 1342 #ifdef CONFIG_IEEE80211R 1343 static int wpa_supplicant_ctrl_iface_ft_ds( 1344 struct wpa_supplicant *wpa_s, char *addr) 1345 { 1346 u8 target_ap[ETH_ALEN]; 1347 struct wpa_bss *bss; 1348 const u8 *mdie; 1349 bool force = os_strstr(addr, " force") != NULL; 1350 1351 if (hwaddr_aton(addr, target_ap)) { 1352 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 1353 "address '%s'", addr); 1354 return -1; 1355 } 1356 1357 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 1358 1359 bss = wpa_bss_get_bssid(wpa_s, target_ap); 1360 if (bss) 1361 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 1362 else 1363 mdie = NULL; 1364 1365 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force); 1366 } 1367 #endif /* CONFIG_IEEE80211R */ 1368 1369 1370 #ifdef CONFIG_WPS 1371 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 1372 char *cmd) 1373 { 1374 u8 bssid[ETH_ALEN], *_bssid = bssid; 1375 #ifdef CONFIG_P2P 1376 u8 p2p_dev_addr[ETH_ALEN]; 1377 #endif /* CONFIG_P2P */ 1378 #ifdef CONFIG_AP 1379 u8 *_p2p_dev_addr = NULL; 1380 #endif /* CONFIG_AP */ 1381 char *pos; 1382 int multi_ap = 0; 1383 1384 if (!cmd || os_strcmp(cmd, "any") == 0 || 1385 os_strncmp(cmd, "any ", 4) == 0) { 1386 _bssid = NULL; 1387 #ifdef CONFIG_P2P 1388 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 1389 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 1390 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 1391 "P2P Device Address '%s'", 1392 cmd + 13); 1393 return -1; 1394 } 1395 _p2p_dev_addr = p2p_dev_addr; 1396 #endif /* CONFIG_P2P */ 1397 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) { 1398 _bssid = NULL; 1399 multi_ap = atoi(cmd + 9); 1400 } else if (hwaddr_aton(cmd, bssid)) { 1401 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 1402 cmd); 1403 return -1; 1404 } 1405 1406 if (cmd) { 1407 pos = os_strstr(cmd, " multi_ap="); 1408 if (pos) { 1409 pos += 10; 1410 multi_ap = atoi(pos); 1411 } 1412 } 1413 1414 #ifdef CONFIG_AP 1415 if (wpa_s->ap_iface) 1416 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 1417 #endif /* CONFIG_AP */ 1418 1419 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap); 1420 } 1421 1422 1423 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 1424 char *cmd, char *buf, 1425 size_t buflen) 1426 { 1427 u8 bssid[ETH_ALEN], *_bssid = bssid; 1428 char *pin; 1429 int ret; 1430 1431 pin = os_strchr(cmd, ' '); 1432 if (pin) 1433 *pin++ = '\0'; 1434 1435 if (os_strcmp(cmd, "any") == 0) 1436 _bssid = NULL; 1437 else if (os_strcmp(cmd, "get") == 0) { 1438 if (wps_generate_pin((unsigned int *) &ret) < 0) 1439 return -1; 1440 goto done; 1441 } else if (hwaddr_aton(cmd, bssid)) { 1442 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 1443 cmd); 1444 return -1; 1445 } 1446 1447 #ifdef CONFIG_AP 1448 if (wpa_s->ap_iface) { 1449 int timeout = 0; 1450 char *pos; 1451 1452 if (pin) { 1453 pos = os_strchr(pin, ' '); 1454 if (pos) { 1455 *pos++ = '\0'; 1456 timeout = atoi(pos); 1457 } 1458 } 1459 1460 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 1461 buf, buflen, timeout); 1462 } 1463 #endif /* CONFIG_AP */ 1464 1465 if (pin) { 1466 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 1467 DEV_PW_DEFAULT); 1468 if (ret < 0) 1469 return -1; 1470 ret = os_snprintf(buf, buflen, "%s", pin); 1471 if (os_snprintf_error(buflen, ret)) 1472 return -1; 1473 return ret; 1474 } 1475 1476 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 1477 if (ret < 0) 1478 return -1; 1479 1480 done: 1481 /* Return the generated PIN */ 1482 ret = os_snprintf(buf, buflen, "%08d", ret); 1483 if (os_snprintf_error(buflen, ret)) 1484 return -1; 1485 return ret; 1486 } 1487 1488 1489 static int wpa_supplicant_ctrl_iface_wps_check_pin( 1490 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1491 { 1492 char pin[9]; 1493 size_t len; 1494 char *pos; 1495 int ret; 1496 1497 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 1498 (u8 *) cmd, os_strlen(cmd)); 1499 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 1500 if (*pos < '0' || *pos > '9') 1501 continue; 1502 pin[len++] = *pos; 1503 if (len == 9) { 1504 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 1505 return -1; 1506 } 1507 } 1508 if (len != 4 && len != 8) { 1509 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 1510 return -1; 1511 } 1512 pin[len] = '\0'; 1513 1514 if (len == 8) { 1515 unsigned int pin_val; 1516 pin_val = atoi(pin); 1517 if (!wps_pin_valid(pin_val)) { 1518 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 1519 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 1520 if (os_snprintf_error(buflen, ret)) 1521 return -1; 1522 return ret; 1523 } 1524 } 1525 1526 ret = os_snprintf(buf, buflen, "%s", pin); 1527 if (os_snprintf_error(buflen, ret)) 1528 return -1; 1529 1530 return ret; 1531 } 1532 1533 1534 #ifdef CONFIG_WPS_NFC 1535 1536 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 1537 char *cmd) 1538 { 1539 u8 bssid[ETH_ALEN], *_bssid = bssid; 1540 1541 if (cmd == NULL || cmd[0] == '\0') 1542 _bssid = NULL; 1543 else if (hwaddr_aton(cmd, bssid)) 1544 return -1; 1545 1546 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL, 1547 0, 0); 1548 } 1549 1550 1551 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( 1552 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1553 { 1554 int ndef; 1555 struct wpabuf *buf; 1556 int res; 1557 char *pos; 1558 1559 pos = os_strchr(cmd, ' '); 1560 if (pos) 1561 *pos++ = '\0'; 1562 if (os_strcmp(cmd, "WPS") == 0) 1563 ndef = 0; 1564 else if (os_strcmp(cmd, "NDEF") == 0) 1565 ndef = 1; 1566 else 1567 return -1; 1568 1569 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos); 1570 if (buf == NULL) 1571 return -1; 1572 1573 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1574 wpabuf_len(buf)); 1575 reply[res++] = '\n'; 1576 reply[res] = '\0'; 1577 1578 wpabuf_free(buf); 1579 1580 return res; 1581 } 1582 1583 1584 static int wpa_supplicant_ctrl_iface_wps_nfc_token( 1585 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1586 { 1587 int ndef; 1588 struct wpabuf *buf; 1589 int res; 1590 1591 if (os_strcmp(cmd, "WPS") == 0) 1592 ndef = 0; 1593 else if (os_strcmp(cmd, "NDEF") == 0) 1594 ndef = 1; 1595 else 1596 return -1; 1597 1598 buf = wpas_wps_nfc_token(wpa_s, ndef); 1599 if (buf == NULL) 1600 return -1; 1601 1602 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1603 wpabuf_len(buf)); 1604 reply[res++] = '\n'; 1605 reply[res] = '\0'; 1606 1607 wpabuf_free(buf); 1608 1609 return res; 1610 } 1611 1612 1613 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 1614 struct wpa_supplicant *wpa_s, char *pos) 1615 { 1616 size_t len; 1617 struct wpabuf *buf; 1618 int ret; 1619 char *freq; 1620 int forced_freq = 0; 1621 1622 freq = strstr(pos, " freq="); 1623 if (freq) { 1624 *freq = '\0'; 1625 freq += 6; 1626 forced_freq = atoi(freq); 1627 } 1628 1629 len = os_strlen(pos); 1630 if (len & 0x01) 1631 return -1; 1632 len /= 2; 1633 1634 buf = wpabuf_alloc(len); 1635 if (buf == NULL) 1636 return -1; 1637 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 1638 wpabuf_free(buf); 1639 return -1; 1640 } 1641 1642 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq); 1643 wpabuf_free(buf); 1644 1645 return ret; 1646 } 1647 1648 1649 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 1650 char *reply, size_t max_len, 1651 int ndef) 1652 { 1653 struct wpabuf *buf; 1654 int res; 1655 1656 buf = wpas_wps_nfc_handover_req(wpa_s, ndef); 1657 if (buf == NULL) 1658 return -1; 1659 1660 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1661 wpabuf_len(buf)); 1662 reply[res++] = '\n'; 1663 reply[res] = '\0'; 1664 1665 wpabuf_free(buf); 1666 1667 return res; 1668 } 1669 1670 1671 #ifdef CONFIG_P2P 1672 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s, 1673 char *reply, size_t max_len, 1674 int ndef) 1675 { 1676 struct wpabuf *buf; 1677 int res; 1678 1679 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef); 1680 if (buf == NULL) { 1681 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request"); 1682 return -1; 1683 } 1684 1685 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1686 wpabuf_len(buf)); 1687 reply[res++] = '\n'; 1688 reply[res] = '\0'; 1689 1690 wpabuf_free(buf); 1691 1692 return res; 1693 } 1694 #endif /* CONFIG_P2P */ 1695 1696 1697 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 1698 char *cmd, char *reply, 1699 size_t max_len) 1700 { 1701 char *pos; 1702 int ndef; 1703 1704 pos = os_strchr(cmd, ' '); 1705 if (pos == NULL) 1706 return -1; 1707 *pos++ = '\0'; 1708 1709 if (os_strcmp(cmd, "WPS") == 0) 1710 ndef = 0; 1711 else if (os_strcmp(cmd, "NDEF") == 0) 1712 ndef = 1; 1713 else 1714 return -1; 1715 1716 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1717 if (!ndef) 1718 return -1; 1719 return wpas_ctrl_nfc_get_handover_req_wps( 1720 wpa_s, reply, max_len, ndef); 1721 } 1722 1723 #ifdef CONFIG_P2P 1724 if (os_strcmp(pos, "P2P-CR") == 0) { 1725 return wpas_ctrl_nfc_get_handover_req_p2p( 1726 wpa_s, reply, max_len, ndef); 1727 } 1728 #endif /* CONFIG_P2P */ 1729 1730 return -1; 1731 } 1732 1733 1734 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 1735 char *reply, size_t max_len, 1736 int ndef, int cr, char *uuid) 1737 { 1738 struct wpabuf *buf; 1739 int res; 1740 1741 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid); 1742 if (buf == NULL) 1743 return -1; 1744 1745 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1746 wpabuf_len(buf)); 1747 reply[res++] = '\n'; 1748 reply[res] = '\0'; 1749 1750 wpabuf_free(buf); 1751 1752 return res; 1753 } 1754 1755 1756 #ifdef CONFIG_P2P 1757 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s, 1758 char *reply, size_t max_len, 1759 int ndef, int tag) 1760 { 1761 struct wpabuf *buf; 1762 int res; 1763 1764 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag); 1765 if (buf == NULL) 1766 return -1; 1767 1768 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1769 wpabuf_len(buf)); 1770 reply[res++] = '\n'; 1771 reply[res] = '\0'; 1772 1773 wpabuf_free(buf); 1774 1775 return res; 1776 } 1777 #endif /* CONFIG_P2P */ 1778 1779 1780 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 1781 char *cmd, char *reply, 1782 size_t max_len) 1783 { 1784 char *pos, *pos2; 1785 int ndef; 1786 1787 pos = os_strchr(cmd, ' '); 1788 if (pos == NULL) 1789 return -1; 1790 *pos++ = '\0'; 1791 1792 if (os_strcmp(cmd, "WPS") == 0) 1793 ndef = 0; 1794 else if (os_strcmp(cmd, "NDEF") == 0) 1795 ndef = 1; 1796 else 1797 return -1; 1798 1799 pos2 = os_strchr(pos, ' '); 1800 if (pos2) 1801 *pos2++ = '\0'; 1802 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1803 if (!ndef) 1804 return -1; 1805 return wpas_ctrl_nfc_get_handover_sel_wps( 1806 wpa_s, reply, max_len, ndef, 1807 os_strcmp(pos, "WPS-CR") == 0, pos2); 1808 } 1809 1810 #ifdef CONFIG_P2P 1811 if (os_strcmp(pos, "P2P-CR") == 0) { 1812 return wpas_ctrl_nfc_get_handover_sel_p2p( 1813 wpa_s, reply, max_len, ndef, 0); 1814 } 1815 1816 if (os_strcmp(pos, "P2P-CR-TAG") == 0) { 1817 return wpas_ctrl_nfc_get_handover_sel_p2p( 1818 wpa_s, reply, max_len, ndef, 1); 1819 } 1820 #endif /* CONFIG_P2P */ 1821 1822 return -1; 1823 } 1824 1825 1826 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s, 1827 char *cmd) 1828 { 1829 size_t len; 1830 struct wpabuf *req, *sel; 1831 int ret; 1832 char *pos, *role, *type, *pos2; 1833 #ifdef CONFIG_P2P 1834 char *freq; 1835 int forced_freq = 0; 1836 1837 freq = strstr(cmd, " freq="); 1838 if (freq) { 1839 *freq = '\0'; 1840 freq += 6; 1841 forced_freq = atoi(freq); 1842 } 1843 #endif /* CONFIG_P2P */ 1844 1845 role = cmd; 1846 pos = os_strchr(role, ' '); 1847 if (pos == NULL) { 1848 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report"); 1849 return -1; 1850 } 1851 *pos++ = '\0'; 1852 1853 type = pos; 1854 pos = os_strchr(type, ' '); 1855 if (pos == NULL) { 1856 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report"); 1857 return -1; 1858 } 1859 *pos++ = '\0'; 1860 1861 pos2 = os_strchr(pos, ' '); 1862 if (pos2 == NULL) { 1863 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report"); 1864 return -1; 1865 } 1866 *pos2++ = '\0'; 1867 1868 len = os_strlen(pos); 1869 if (len & 0x01) { 1870 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report"); 1871 return -1; 1872 } 1873 len /= 2; 1874 1875 req = wpabuf_alloc(len); 1876 if (req == NULL) { 1877 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message"); 1878 return -1; 1879 } 1880 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 1881 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report"); 1882 wpabuf_free(req); 1883 return -1; 1884 } 1885 1886 len = os_strlen(pos2); 1887 if (len & 0x01) { 1888 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report"); 1889 wpabuf_free(req); 1890 return -1; 1891 } 1892 len /= 2; 1893 1894 sel = wpabuf_alloc(len); 1895 if (sel == NULL) { 1896 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message"); 1897 wpabuf_free(req); 1898 return -1; 1899 } 1900 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 1901 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report"); 1902 wpabuf_free(req); 1903 wpabuf_free(sel); 1904 return -1; 1905 } 1906 1907 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d", 1908 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel)); 1909 1910 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) { 1911 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel); 1912 #ifdef CONFIG_AP 1913 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) 1914 { 1915 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel); 1916 if (ret < 0) 1917 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel); 1918 #endif /* CONFIG_AP */ 1919 #ifdef CONFIG_P2P 1920 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0) 1921 { 1922 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0); 1923 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0) 1924 { 1925 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel, 1926 forced_freq); 1927 #endif /* CONFIG_P2P */ 1928 } else { 1929 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 1930 "reported: role=%s type=%s", role, type); 1931 ret = -1; 1932 } 1933 wpabuf_free(req); 1934 wpabuf_free(sel); 1935 1936 if (ret) 1937 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages"); 1938 1939 return ret; 1940 } 1941 1942 #endif /* CONFIG_WPS_NFC */ 1943 1944 1945 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 1946 char *cmd) 1947 { 1948 u8 bssid[ETH_ALEN]; 1949 char *pin; 1950 char *new_ssid; 1951 char *new_auth; 1952 char *new_encr; 1953 char *new_key; 1954 struct wps_new_ap_settings ap; 1955 1956 pin = os_strchr(cmd, ' '); 1957 if (pin == NULL) 1958 return -1; 1959 *pin++ = '\0'; 1960 1961 if (hwaddr_aton(cmd, bssid)) { 1962 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1963 cmd); 1964 return -1; 1965 } 1966 1967 new_ssid = os_strchr(pin, ' '); 1968 if (new_ssid == NULL) 1969 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1970 *new_ssid++ = '\0'; 1971 1972 new_auth = os_strchr(new_ssid, ' '); 1973 if (new_auth == NULL) 1974 return -1; 1975 *new_auth++ = '\0'; 1976 1977 new_encr = os_strchr(new_auth, ' '); 1978 if (new_encr == NULL) 1979 return -1; 1980 *new_encr++ = '\0'; 1981 1982 new_key = os_strchr(new_encr, ' '); 1983 if (new_key == NULL) 1984 return -1; 1985 *new_key++ = '\0'; 1986 1987 os_memset(&ap, 0, sizeof(ap)); 1988 ap.ssid_hex = new_ssid; 1989 ap.auth = new_auth; 1990 ap.encr = new_encr; 1991 ap.key_hex = new_key; 1992 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1993 } 1994 1995 1996 #ifdef CONFIG_AP 1997 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 1998 char *cmd, char *buf, 1999 size_t buflen) 2000 { 2001 int timeout = 300; 2002 char *pos; 2003 const char *pin_txt; 2004 2005 if (!wpa_s->ap_iface) 2006 return -1; 2007 2008 pos = os_strchr(cmd, ' '); 2009 if (pos) 2010 *pos++ = '\0'; 2011 2012 if (os_strcmp(cmd, "disable") == 0) { 2013 wpas_wps_ap_pin_disable(wpa_s); 2014 return os_snprintf(buf, buflen, "OK\n"); 2015 } 2016 2017 if (os_strcmp(cmd, "random") == 0) { 2018 if (pos) 2019 timeout = atoi(pos); 2020 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 2021 if (pin_txt == NULL) 2022 return -1; 2023 return os_snprintf(buf, buflen, "%s", pin_txt); 2024 } 2025 2026 if (os_strcmp(cmd, "get") == 0) { 2027 pin_txt = wpas_wps_ap_pin_get(wpa_s); 2028 if (pin_txt == NULL) 2029 return -1; 2030 return os_snprintf(buf, buflen, "%s", pin_txt); 2031 } 2032 2033 if (os_strcmp(cmd, "set") == 0) { 2034 char *pin; 2035 if (pos == NULL) 2036 return -1; 2037 pin = pos; 2038 pos = os_strchr(pos, ' '); 2039 if (pos) { 2040 *pos++ = '\0'; 2041 timeout = atoi(pos); 2042 } 2043 if (os_strlen(pin) > buflen) 2044 return -1; 2045 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 2046 return -1; 2047 return os_snprintf(buf, buflen, "%s", pin); 2048 } 2049 2050 return -1; 2051 } 2052 #endif /* CONFIG_AP */ 2053 2054 2055 #ifdef CONFIG_WPS_ER 2056 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 2057 char *cmd) 2058 { 2059 char *uuid = cmd, *pin, *pos; 2060 u8 addr_buf[ETH_ALEN], *addr = NULL; 2061 pin = os_strchr(uuid, ' '); 2062 if (pin == NULL) 2063 return -1; 2064 *pin++ = '\0'; 2065 pos = os_strchr(pin, ' '); 2066 if (pos) { 2067 *pos++ = '\0'; 2068 if (hwaddr_aton(pos, addr_buf) == 0) 2069 addr = addr_buf; 2070 } 2071 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 2072 } 2073 2074 2075 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 2076 char *cmd) 2077 { 2078 char *uuid = cmd, *pin; 2079 pin = os_strchr(uuid, ' '); 2080 if (pin == NULL) 2081 return -1; 2082 *pin++ = '\0'; 2083 return wpas_wps_er_learn(wpa_s, uuid, pin); 2084 } 2085 2086 2087 static int wpa_supplicant_ctrl_iface_wps_er_set_config( 2088 struct wpa_supplicant *wpa_s, char *cmd) 2089 { 2090 char *uuid = cmd, *id; 2091 id = os_strchr(uuid, ' '); 2092 if (id == NULL) 2093 return -1; 2094 *id++ = '\0'; 2095 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 2096 } 2097 2098 2099 static int wpa_supplicant_ctrl_iface_wps_er_config( 2100 struct wpa_supplicant *wpa_s, char *cmd) 2101 { 2102 char *pin; 2103 char *new_ssid; 2104 char *new_auth; 2105 char *new_encr; 2106 char *new_key; 2107 struct wps_new_ap_settings ap; 2108 2109 pin = os_strchr(cmd, ' '); 2110 if (pin == NULL) 2111 return -1; 2112 *pin++ = '\0'; 2113 2114 new_ssid = os_strchr(pin, ' '); 2115 if (new_ssid == NULL) 2116 return -1; 2117 *new_ssid++ = '\0'; 2118 2119 new_auth = os_strchr(new_ssid, ' '); 2120 if (new_auth == NULL) 2121 return -1; 2122 *new_auth++ = '\0'; 2123 2124 new_encr = os_strchr(new_auth, ' '); 2125 if (new_encr == NULL) 2126 return -1; 2127 *new_encr++ = '\0'; 2128 2129 new_key = os_strchr(new_encr, ' '); 2130 if (new_key == NULL) 2131 return -1; 2132 *new_key++ = '\0'; 2133 2134 os_memset(&ap, 0, sizeof(ap)); 2135 ap.ssid_hex = new_ssid; 2136 ap.auth = new_auth; 2137 ap.encr = new_encr; 2138 ap.key_hex = new_key; 2139 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 2140 } 2141 2142 2143 #ifdef CONFIG_WPS_NFC 2144 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 2145 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 2146 { 2147 int ndef; 2148 struct wpabuf *buf; 2149 int res; 2150 char *uuid; 2151 2152 uuid = os_strchr(cmd, ' '); 2153 if (uuid == NULL) 2154 return -1; 2155 *uuid++ = '\0'; 2156 2157 if (os_strcmp(cmd, "WPS") == 0) 2158 ndef = 0; 2159 else if (os_strcmp(cmd, "NDEF") == 0) 2160 ndef = 1; 2161 else 2162 return -1; 2163 2164 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 2165 if (buf == NULL) 2166 return -1; 2167 2168 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 2169 wpabuf_len(buf)); 2170 reply[res++] = '\n'; 2171 reply[res] = '\0'; 2172 2173 wpabuf_free(buf); 2174 2175 return res; 2176 } 2177 #endif /* CONFIG_WPS_NFC */ 2178 #endif /* CONFIG_WPS_ER */ 2179 2180 #endif /* CONFIG_WPS */ 2181 2182 2183 #ifdef CONFIG_IBSS_RSN 2184 static int wpa_supplicant_ctrl_iface_ibss_rsn( 2185 struct wpa_supplicant *wpa_s, char *addr) 2186 { 2187 u8 peer[ETH_ALEN]; 2188 2189 if (hwaddr_aton(addr, peer)) { 2190 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 2191 "address '%s'", addr); 2192 return -1; 2193 } 2194 2195 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 2196 MAC2STR(peer)); 2197 2198 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 2199 } 2200 #endif /* CONFIG_IBSS_RSN */ 2201 2202 2203 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 2204 char *rsp) 2205 { 2206 #ifdef IEEE8021X_EAPOL 2207 char *pos, *id_pos; 2208 int id; 2209 struct wpa_ssid *ssid; 2210 2211 pos = os_strchr(rsp, '-'); 2212 if (pos == NULL) 2213 return -1; 2214 *pos++ = '\0'; 2215 id_pos = pos; 2216 pos = os_strchr(pos, ':'); 2217 if (pos == NULL) 2218 return -1; 2219 *pos++ = '\0'; 2220 id = atoi(id_pos); 2221 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 2222 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2223 (u8 *) pos, os_strlen(pos)); 2224 2225 ssid = wpa_config_get_network(wpa_s->conf, id); 2226 if (ssid == NULL) { 2227 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2228 "to update", id); 2229 return -1; 2230 } 2231 2232 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 2233 pos); 2234 #else /* IEEE8021X_EAPOL */ 2235 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 2236 return -1; 2237 #endif /* IEEE8021X_EAPOL */ 2238 } 2239 2240 2241 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 2242 const char *params, 2243 char *buf, size_t buflen) 2244 { 2245 char *pos, *end, tmp[30]; 2246 int res, verbose, wps, ret; 2247 #ifdef CONFIG_HS20 2248 const u8 *hs20; 2249 #endif /* CONFIG_HS20 */ 2250 const u8 *sess_id; 2251 size_t sess_id_len; 2252 2253 if (os_strcmp(params, "-DRIVER") == 0) 2254 return wpa_drv_status(wpa_s, buf, buflen); 2255 verbose = os_strcmp(params, "-VERBOSE") == 0; 2256 wps = os_strcmp(params, "-WPS") == 0; 2257 pos = buf; 2258 end = buf + buflen; 2259 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 2260 struct wpa_ssid *ssid = wpa_s->current_ssid; 2261 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2262 MAC2STR(wpa_s->bssid)); 2263 if (os_snprintf_error(end - pos, ret)) 2264 return pos - buf; 2265 pos += ret; 2266 ret = os_snprintf(pos, end - pos, "freq=%u\n", 2267 wpa_s->assoc_freq); 2268 if (os_snprintf_error(end - pos, ret)) 2269 return pos - buf; 2270 pos += ret; 2271 if (ssid) { 2272 u8 *_ssid = ssid->ssid; 2273 size_t ssid_len = ssid->ssid_len; 2274 u8 ssid_buf[SSID_MAX_LEN]; 2275 if (ssid_len == 0) { 2276 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 2277 if (_res < 0) 2278 ssid_len = 0; 2279 else 2280 ssid_len = _res; 2281 _ssid = ssid_buf; 2282 } 2283 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 2284 wpa_ssid_txt(_ssid, ssid_len), 2285 ssid->id); 2286 if (os_snprintf_error(end - pos, ret)) 2287 return pos - buf; 2288 pos += ret; 2289 2290 if (wps && ssid->passphrase && 2291 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 2292 (ssid->mode == WPAS_MODE_AP || 2293 ssid->mode == WPAS_MODE_P2P_GO)) { 2294 ret = os_snprintf(pos, end - pos, 2295 "passphrase=%s\n", 2296 ssid->passphrase); 2297 if (os_snprintf_error(end - pos, ret)) 2298 return pos - buf; 2299 pos += ret; 2300 } 2301 if (ssid->id_str) { 2302 ret = os_snprintf(pos, end - pos, 2303 "id_str=%s\n", 2304 ssid->id_str); 2305 if (os_snprintf_error(end - pos, ret)) 2306 return pos - buf; 2307 pos += ret; 2308 } 2309 2310 switch (ssid->mode) { 2311 case WPAS_MODE_INFRA: 2312 ret = os_snprintf(pos, end - pos, 2313 "mode=station\n"); 2314 break; 2315 case WPAS_MODE_IBSS: 2316 ret = os_snprintf(pos, end - pos, 2317 "mode=IBSS\n"); 2318 break; 2319 case WPAS_MODE_AP: 2320 ret = os_snprintf(pos, end - pos, 2321 "mode=AP\n"); 2322 break; 2323 case WPAS_MODE_P2P_GO: 2324 ret = os_snprintf(pos, end - pos, 2325 "mode=P2P GO\n"); 2326 break; 2327 case WPAS_MODE_P2P_GROUP_FORMATION: 2328 ret = os_snprintf(pos, end - pos, 2329 "mode=P2P GO - group " 2330 "formation\n"); 2331 break; 2332 case WPAS_MODE_MESH: 2333 ret = os_snprintf(pos, end - pos, 2334 "mode=mesh\n"); 2335 break; 2336 default: 2337 ret = 0; 2338 break; 2339 } 2340 if (os_snprintf_error(end - pos, ret)) 2341 return pos - buf; 2342 pos += ret; 2343 } 2344 2345 if (wpa_s->connection_set && 2346 (wpa_s->connection_ht || wpa_s->connection_vht || 2347 wpa_s->connection_he || wpa_s->connection_eht)) { 2348 ret = os_snprintf(pos, end - pos, 2349 "wifi_generation=%u\n", 2350 wpa_s->connection_eht ? 7 : 2351 (wpa_s->connection_he ? 6 : 2352 (wpa_s->connection_vht ? 5 : 4))); 2353 if (os_snprintf_error(end - pos, ret)) 2354 return pos - buf; 2355 pos += ret; 2356 } 2357 2358 #ifdef CONFIG_AP 2359 if (wpa_s->ap_iface) { 2360 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 2361 end - pos, 2362 verbose); 2363 } else 2364 #endif /* CONFIG_AP */ 2365 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 2366 } 2367 #ifdef CONFIG_SME 2368 #ifdef CONFIG_SAE 2369 if (wpa_s->wpa_state >= WPA_ASSOCIATED && 2370 #ifdef CONFIG_AP 2371 !wpa_s->ap_iface && 2372 #endif /* CONFIG_AP */ 2373 wpa_s->sme.sae.state == SAE_ACCEPTED) { 2374 ret = os_snprintf(pos, end - pos, "sae_group=%d\n" 2375 "sae_h2e=%d\n" 2376 "sae_pk=%d\n", 2377 wpa_s->sme.sae.group, 2378 wpa_s->sme.sae.h2e, 2379 wpa_s->sme.sae.pk); 2380 if (os_snprintf_error(end - pos, ret)) 2381 return pos - buf; 2382 pos += ret; 2383 } 2384 #endif /* CONFIG_SAE */ 2385 #endif /* CONFIG_SME */ 2386 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 2387 wpa_supplicant_state_txt(wpa_s->wpa_state)); 2388 if (os_snprintf_error(end - pos, ret)) 2389 return pos - buf; 2390 pos += ret; 2391 2392 if (wpa_s->l2 && 2393 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 2394 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 2395 if (os_snprintf_error(end - pos, ret)) 2396 return pos - buf; 2397 pos += ret; 2398 } 2399 2400 #ifdef CONFIG_P2P 2401 if (wpa_s->global->p2p) { 2402 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 2403 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 2404 if (os_snprintf_error(end - pos, ret)) 2405 return pos - buf; 2406 pos += ret; 2407 } 2408 #endif /* CONFIG_P2P */ 2409 2410 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 2411 MAC2STR(wpa_s->own_addr)); 2412 if (os_snprintf_error(end - pos, ret)) 2413 return pos - buf; 2414 pos += ret; 2415 2416 if (wpa_s->valid_links) { 2417 ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n", 2418 MAC2STR(wpa_s->ap_mld_addr)); 2419 if (os_snprintf_error(end - pos, ret)) 2420 return pos - buf; 2421 pos += ret; 2422 } 2423 2424 #ifdef CONFIG_HS20 2425 if (wpa_s->current_bss && 2426 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss, 2427 HS20_IE_VENDOR_TYPE)) && 2428 wpa_s->wpa_proto == WPA_PROTO_RSN && 2429 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 2430 int release = 1; 2431 if (hs20[1] >= 5) { 2432 u8 rel_num = (hs20[6] & 0xf0) >> 4; 2433 release = rel_num + 1; 2434 } 2435 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release); 2436 if (os_snprintf_error(end - pos, ret)) 2437 return pos - buf; 2438 pos += ret; 2439 } 2440 2441 if (wpa_s->current_ssid) { 2442 struct wpa_cred *cred; 2443 char *type; 2444 2445 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2446 size_t i; 2447 2448 if (wpa_s->current_ssid->parent_cred != cred) 2449 continue; 2450 2451 if (cred->provisioning_sp) { 2452 ret = os_snprintf(pos, end - pos, 2453 "provisioning_sp=%s\n", 2454 cred->provisioning_sp); 2455 if (os_snprintf_error(end - pos, ret)) 2456 return pos - buf; 2457 pos += ret; 2458 } 2459 2460 if (!cred->domain) 2461 goto no_domain; 2462 2463 i = 0; 2464 if (wpa_s->current_bss && wpa_s->current_bss->anqp) { 2465 struct wpabuf *names = 2466 wpa_s->current_bss->anqp->domain_name; 2467 for (i = 0; names && i < cred->num_domain; i++) 2468 { 2469 if (domain_name_list_contains( 2470 names, cred->domain[i], 1)) 2471 break; 2472 } 2473 if (i == cred->num_domain) 2474 i = 0; /* show first entry by default */ 2475 } 2476 ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 2477 cred->domain[i]); 2478 if (os_snprintf_error(end - pos, ret)) 2479 return pos - buf; 2480 pos += ret; 2481 2482 no_domain: 2483 if (wpa_s->current_bss == NULL || 2484 wpa_s->current_bss->anqp == NULL) 2485 res = -1; 2486 else 2487 res = interworking_home_sp_cred( 2488 wpa_s, cred, 2489 wpa_s->current_bss->anqp->domain_name); 2490 if (res > 0) 2491 type = "home"; 2492 else if (res == 0) 2493 type = "roaming"; 2494 else 2495 type = "unknown"; 2496 2497 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 2498 if (os_snprintf_error(end - pos, ret)) 2499 return pos - buf; 2500 pos += ret; 2501 2502 break; 2503 } 2504 } 2505 #endif /* CONFIG_HS20 */ 2506 2507 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 2508 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 2509 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 2510 verbose); 2511 if (res >= 0) 2512 pos += res; 2513 } 2514 2515 #ifdef CONFIG_MACSEC 2516 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos); 2517 if (res > 0) 2518 pos += res; 2519 #endif /* CONFIG_MACSEC */ 2520 2521 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len); 2522 if (sess_id) { 2523 char *start = pos; 2524 2525 ret = os_snprintf(pos, end - pos, "eap_session_id="); 2526 if (os_snprintf_error(end - pos, ret)) 2527 return start - buf; 2528 pos += ret; 2529 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len); 2530 if (ret <= 0) 2531 return start - buf; 2532 pos += ret; 2533 ret = os_snprintf(pos, end - pos, "\n"); 2534 if (os_snprintf_error(end - pos, ret)) 2535 return start - buf; 2536 pos += ret; 2537 } 2538 2539 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 2540 if (res >= 0) 2541 pos += res; 2542 2543 #ifdef CONFIG_WPS 2544 { 2545 char uuid_str[100]; 2546 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str)); 2547 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str); 2548 if (os_snprintf_error(end - pos, ret)) 2549 return pos - buf; 2550 pos += ret; 2551 } 2552 #endif /* CONFIG_WPS */ 2553 2554 if (wpa_s->ieee80211ac) { 2555 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n"); 2556 if (os_snprintf_error(end - pos, ret)) 2557 return pos - buf; 2558 pos += ret; 2559 } 2560 2561 #ifdef CONFIG_SME 2562 if (wpa_s->sme.bss_max_idle_period) { 2563 ret = os_snprintf(pos, end - pos, "bss_max_idle_period=%d\n", 2564 wpa_s->sme.bss_max_idle_period); 2565 if (os_snprintf_error(end - pos, ret)) 2566 return pos - buf; 2567 pos += ret; 2568 } 2569 #endif /* CONFIG_SME */ 2570 2571 if (wpa_s->ssid_verified) { 2572 ret = os_snprintf(pos, end - pos, "ssid_verified=1\n"); 2573 if (os_snprintf_error(end - pos, ret)) 2574 return pos - buf; 2575 pos += ret; 2576 } 2577 2578 if (wpa_s->bigtk_set) { 2579 ret = os_snprintf(pos, end - pos, "bigtk_set=1\n"); 2580 if (os_snprintf_error(end - pos, ret)) 2581 return pos - buf; 2582 pos += ret; 2583 } 2584 2585 #ifdef ANDROID 2586 /* 2587 * Allow using the STATUS command with default behavior, say for debug, 2588 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE 2589 * events with STATUS-NO_EVENTS. 2590 */ 2591 if (os_strcmp(params, "-NO_EVENTS")) { 2592 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE 2593 "id=%d state=%d BSSID=" MACSTR " SSID=%s", 2594 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, 2595 wpa_s->wpa_state, 2596 MAC2STR(wpa_s->bssid), 2597 wpa_s->current_ssid && wpa_s->current_ssid->ssid ? 2598 wpa_ssid_txt(wpa_s->current_ssid->ssid, 2599 wpa_s->current_ssid->ssid_len) : ""); 2600 if (wpa_s->wpa_state == WPA_COMPLETED) { 2601 struct wpa_ssid *ssid = wpa_s->current_ssid; 2602 char mld_addr[50]; 2603 2604 mld_addr[0] = '\0'; 2605 if (wpa_s->valid_links) 2606 os_snprintf(mld_addr, sizeof(mld_addr), 2607 " ap_mld_addr=" MACSTR, 2608 MAC2STR(wpa_s->ap_mld_addr)); 2609 2610 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED 2611 "- connection to " MACSTR 2612 " completed %s [id=%d id_str=%s]%s", 2613 MAC2STR(wpa_s->bssid), "(auth)", 2614 ssid ? ssid->id : -1, 2615 ssid && ssid->id_str ? ssid->id_str : "", 2616 mld_addr); 2617 } 2618 } 2619 #endif /* ANDROID */ 2620 2621 return pos - buf; 2622 } 2623 2624 2625 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 2626 char *cmd) 2627 { 2628 char *pos; 2629 int id; 2630 struct wpa_ssid *ssid; 2631 u8 bssid[ETH_ALEN]; 2632 2633 /* cmd: "<network id> <BSSID>" */ 2634 pos = os_strchr(cmd, ' '); 2635 if (pos == NULL) 2636 return -1; 2637 *pos++ = '\0'; 2638 id = atoi(cmd); 2639 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 2640 if (hwaddr_aton(pos, bssid)) { 2641 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 2642 return -1; 2643 } 2644 2645 ssid = wpa_config_get_network(wpa_s->conf, id); 2646 if (ssid == NULL) { 2647 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2648 "to update", id); 2649 return -1; 2650 } 2651 2652 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 2653 ssid->bssid_set = !is_zero_ether_addr(bssid); 2654 2655 return 0; 2656 } 2657 2658 2659 static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s, 2660 char *cmd, char *buf, 2661 size_t buflen) 2662 { 2663 u8 bssid[ETH_ALEN]; 2664 struct wpa_bssid_ignore *e; 2665 char *pos, *end; 2666 int ret; 2667 2668 /* cmd: "BSSID_IGNORE [<BSSID>]" */ 2669 if (*cmd == '\0') { 2670 pos = buf; 2671 end = buf + buflen; 2672 e = wpa_s->bssid_ignore; 2673 while (e) { 2674 ret = os_snprintf(pos, end - pos, MACSTR "\n", 2675 MAC2STR(e->bssid)); 2676 if (os_snprintf_error(end - pos, ret)) 2677 return pos - buf; 2678 pos += ret; 2679 e = e->next; 2680 } 2681 return pos - buf; 2682 } 2683 2684 cmd++; 2685 if (os_strncmp(cmd, "clear", 5) == 0) { 2686 wpa_bssid_ignore_clear(wpa_s); 2687 os_memcpy(buf, "OK\n", 3); 2688 return 3; 2689 } 2690 2691 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd); 2692 if (hwaddr_aton(cmd, bssid)) { 2693 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 2694 return -1; 2695 } 2696 2697 /* 2698 * Add the BSSID twice, so its count will be 2, causing it to be 2699 * skipped when processing scan results. 2700 */ 2701 ret = wpa_bssid_ignore_add(wpa_s, bssid); 2702 if (ret < 0) 2703 return -1; 2704 ret = wpa_bssid_ignore_add(wpa_s, bssid); 2705 if (ret < 0) 2706 return -1; 2707 os_memcpy(buf, "OK\n", 3); 2708 return 3; 2709 } 2710 2711 2712 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 2713 char *cmd, char *buf, 2714 size_t buflen) 2715 { 2716 char *pos, *end, *stamp; 2717 int ret; 2718 2719 /* cmd: "LOG_LEVEL [<level>]" */ 2720 if (*cmd == '\0') { 2721 pos = buf; 2722 end = buf + buflen; 2723 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 2724 "Timestamp: %d\n", 2725 debug_level_str(wpa_debug_level), 2726 wpa_debug_timestamp); 2727 if (os_snprintf_error(end - pos, ret)) 2728 ret = 0; 2729 2730 return ret; 2731 } 2732 2733 while (*cmd == ' ') 2734 cmd++; 2735 2736 stamp = os_strchr(cmd, ' '); 2737 if (stamp) { 2738 *stamp++ = '\0'; 2739 while (*stamp == ' ') { 2740 stamp++; 2741 } 2742 } 2743 2744 if (os_strlen(cmd)) { 2745 int level = str_to_debug_level(cmd); 2746 if (level < 0) 2747 return -1; 2748 wpa_debug_level = level; 2749 } 2750 2751 if (stamp && os_strlen(stamp)) 2752 wpa_debug_timestamp = atoi(stamp); 2753 2754 os_memcpy(buf, "OK\n", 3); 2755 return 3; 2756 } 2757 2758 2759 static int wpa_supplicant_ctrl_iface_list_networks( 2760 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2761 { 2762 char *pos, *end, *prev; 2763 struct wpa_ssid *ssid; 2764 int ret; 2765 2766 pos = buf; 2767 end = buf + buflen; 2768 ret = os_snprintf(pos, end - pos, 2769 "network id / ssid / bssid / flags\n"); 2770 if (os_snprintf_error(end - pos, ret)) 2771 return pos - buf; 2772 pos += ret; 2773 2774 ssid = wpa_s->conf->ssid; 2775 2776 /* skip over ssids until we find next one */ 2777 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) { 2778 int last_id = atoi(cmd + 8); 2779 if (last_id != -1) { 2780 while (ssid != NULL && ssid->id <= last_id) { 2781 ssid = ssid->next; 2782 } 2783 } 2784 } 2785 2786 while (ssid) { 2787 prev = pos; 2788 ret = os_snprintf(pos, end - pos, "%d\t%s", 2789 ssid->id, 2790 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2791 if (os_snprintf_error(end - pos, ret)) 2792 return prev - buf; 2793 pos += ret; 2794 if (ssid->bssid_set) { 2795 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 2796 MAC2STR(ssid->bssid)); 2797 } else { 2798 ret = os_snprintf(pos, end - pos, "\tany"); 2799 } 2800 if (os_snprintf_error(end - pos, ret)) 2801 return prev - buf; 2802 pos += ret; 2803 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 2804 ssid == wpa_s->current_ssid ? 2805 "[CURRENT]" : "", 2806 ssid->disabled ? "[DISABLED]" : "", 2807 ssid->disabled_until.sec ? 2808 "[TEMP-DISABLED]" : "", 2809 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 2810 ""); 2811 if (os_snprintf_error(end - pos, ret)) 2812 return prev - buf; 2813 pos += ret; 2814 ret = os_snprintf(pos, end - pos, "\n"); 2815 if (os_snprintf_error(end - pos, ret)) 2816 return prev - buf; 2817 pos += ret; 2818 2819 ssid = ssid->next; 2820 } 2821 2822 return pos - buf; 2823 } 2824 2825 2826 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 2827 { 2828 int ret; 2829 ret = os_snprintf(pos, end - pos, "-"); 2830 if (os_snprintf_error(end - pos, ret)) 2831 return pos; 2832 pos += ret; 2833 ret = wpa_write_ciphers(pos, end, cipher, "+"); 2834 if (ret < 0) 2835 return pos; 2836 pos += ret; 2837 return pos; 2838 } 2839 2840 2841 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 2842 const u8 *ie, size_t ie_len) 2843 { 2844 struct wpa_ie_data data; 2845 char *start; 2846 int ret; 2847 2848 ret = os_snprintf(pos, end - pos, "[%s-", proto); 2849 if (os_snprintf_error(end - pos, ret)) 2850 return pos; 2851 pos += ret; 2852 2853 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 2854 ret = os_snprintf(pos, end - pos, "?]"); 2855 if (os_snprintf_error(end - pos, ret)) 2856 return pos; 2857 pos += ret; 2858 return pos; 2859 } 2860 2861 start = pos; 2862 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 2863 ret = os_snprintf(pos, end - pos, "%sEAP", 2864 pos == start ? "" : "+"); 2865 if (os_snprintf_error(end - pos, ret)) 2866 return pos; 2867 pos += ret; 2868 } 2869 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 2870 ret = os_snprintf(pos, end - pos, "%sPSK", 2871 pos == start ? "" : "+"); 2872 if (os_snprintf_error(end - pos, ret)) 2873 return pos; 2874 pos += ret; 2875 } 2876 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 2877 ret = os_snprintf(pos, end - pos, "%sNone", 2878 pos == start ? "" : "+"); 2879 if (os_snprintf_error(end - pos, ret)) 2880 return pos; 2881 pos += ret; 2882 } 2883 if (data.key_mgmt & WPA_KEY_MGMT_SAE) { 2884 ret = os_snprintf(pos, end - pos, "%sSAE", 2885 pos == start ? "" : "+"); 2886 if (os_snprintf_error(end - pos, ret)) 2887 return pos; 2888 pos += ret; 2889 } 2890 if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) { 2891 ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY", 2892 pos == start ? "" : "+"); 2893 if (os_snprintf_error(end - pos, ret)) 2894 return pos; 2895 pos += ret; 2896 } 2897 #ifdef CONFIG_IEEE80211R 2898 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 2899 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 2900 pos == start ? "" : "+"); 2901 if (os_snprintf_error(end - pos, ret)) 2902 return pos; 2903 pos += ret; 2904 } 2905 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 2906 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 2907 pos == start ? "" : "+"); 2908 if (os_snprintf_error(end - pos, ret)) 2909 return pos; 2910 pos += ret; 2911 } 2912 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) { 2913 ret = os_snprintf(pos, end - pos, "%sFT/SAE", 2914 pos == start ? "" : "+"); 2915 if (os_snprintf_error(end - pos, ret)) 2916 return pos; 2917 pos += ret; 2918 } 2919 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) { 2920 ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY", 2921 pos == start ? "" : "+"); 2922 if (os_snprintf_error(end - pos, ret)) 2923 return pos; 2924 pos += ret; 2925 } 2926 #endif /* CONFIG_IEEE80211R */ 2927 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 2928 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 2929 pos == start ? "" : "+"); 2930 if (os_snprintf_error(end - pos, ret)) 2931 return pos; 2932 pos += ret; 2933 } 2934 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 2935 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 2936 pos == start ? "" : "+"); 2937 if (os_snprintf_error(end - pos, ret)) 2938 return pos; 2939 pos += ret; 2940 } 2941 2942 #ifdef CONFIG_SUITEB 2943 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 2944 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B", 2945 pos == start ? "" : "+"); 2946 if (os_snprintf_error(end - pos, ret)) 2947 return pos; 2948 pos += ret; 2949 } 2950 #endif /* CONFIG_SUITEB */ 2951 2952 #ifdef CONFIG_SUITEB192 2953 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 2954 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192", 2955 pos == start ? "" : "+"); 2956 if (os_snprintf_error(end - pos, ret)) 2957 return pos; 2958 pos += ret; 2959 } 2960 #endif /* CONFIG_SUITEB192 */ 2961 2962 #ifdef CONFIG_FILS 2963 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 2964 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256", 2965 pos == start ? "" : "+"); 2966 if (os_snprintf_error(end - pos, ret)) 2967 return pos; 2968 pos += ret; 2969 } 2970 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 2971 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384", 2972 pos == start ? "" : "+"); 2973 if (os_snprintf_error(end - pos, ret)) 2974 return pos; 2975 pos += ret; 2976 } 2977 #ifdef CONFIG_IEEE80211R 2978 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 2979 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256", 2980 pos == start ? "" : "+"); 2981 if (os_snprintf_error(end - pos, ret)) 2982 return pos; 2983 pos += ret; 2984 } 2985 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 2986 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384", 2987 pos == start ? "" : "+"); 2988 if (os_snprintf_error(end - pos, ret)) 2989 return pos; 2990 pos += ret; 2991 } 2992 #endif /* CONFIG_IEEE80211R */ 2993 #endif /* CONFIG_FILS */ 2994 2995 #ifdef CONFIG_OWE 2996 if (data.key_mgmt & WPA_KEY_MGMT_OWE) { 2997 ret = os_snprintf(pos, end - pos, "%sOWE", 2998 pos == start ? "" : "+"); 2999 if (os_snprintf_error(end - pos, ret)) 3000 return pos; 3001 pos += ret; 3002 } 3003 #endif /* CONFIG_OWE */ 3004 3005 #ifdef CONFIG_DPP 3006 if (data.key_mgmt & WPA_KEY_MGMT_DPP) { 3007 ret = os_snprintf(pos, end - pos, "%sDPP", 3008 pos == start ? "" : "+"); 3009 if (os_snprintf_error(end - pos, ret)) 3010 return pos; 3011 pos += ret; 3012 } 3013 #endif /* CONFIG_DPP */ 3014 3015 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) { 3016 ret = os_snprintf(pos, end - pos, "%sOSEN", 3017 pos == start ? "" : "+"); 3018 if (os_snprintf_error(end - pos, ret)) 3019 return pos; 3020 pos += ret; 3021 } 3022 3023 #ifdef CONFIG_SHA384 3024 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { 3025 ret = os_snprintf(pos, end - pos, "%sEAP-SHA384", 3026 pos == start ? "" : "+"); 3027 if (os_snprintf_error(end - pos, ret)) 3028 return pos; 3029 pos += ret; 3030 } 3031 #endif /* CONFIG_SHA384 */ 3032 3033 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 3034 3035 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 3036 ret = os_snprintf(pos, end - pos, "-preauth"); 3037 if (os_snprintf_error(end - pos, ret)) 3038 return pos; 3039 pos += ret; 3040 } 3041 3042 ret = os_snprintf(pos, end - pos, "]"); 3043 if (os_snprintf_error(end - pos, ret)) 3044 return pos; 3045 pos += ret; 3046 3047 return pos; 3048 } 3049 3050 3051 #ifdef CONFIG_WPS 3052 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 3053 char *pos, char *end, 3054 struct wpabuf *wps_ie) 3055 { 3056 int ret; 3057 const char *txt; 3058 3059 if (wps_ie == NULL) 3060 return pos; 3061 if (wps_is_selected_pbc_registrar(wps_ie)) 3062 txt = "[WPS-PBC]"; 3063 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 3064 txt = "[WPS-AUTH]"; 3065 else if (wps_is_selected_pin_registrar(wps_ie)) 3066 txt = "[WPS-PIN]"; 3067 else 3068 txt = "[WPS]"; 3069 3070 ret = os_snprintf(pos, end - pos, "%s", txt); 3071 if (!os_snprintf_error(end - pos, ret)) 3072 pos += ret; 3073 wpabuf_free(wps_ie); 3074 return pos; 3075 } 3076 #endif /* CONFIG_WPS */ 3077 3078 3079 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 3080 char *pos, char *end, 3081 const struct wpa_bss *bss) 3082 { 3083 #ifdef CONFIG_WPS 3084 struct wpabuf *wps_ie; 3085 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 3086 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 3087 #else /* CONFIG_WPS */ 3088 return pos; 3089 #endif /* CONFIG_WPS */ 3090 } 3091 3092 3093 /* Format one result on one text line into a buffer. */ 3094 static int wpa_supplicant_ctrl_iface_scan_result( 3095 struct wpa_supplicant *wpa_s, 3096 const struct wpa_bss *bss, char *buf, size_t buflen) 3097 { 3098 char *pos, *end; 3099 int ret; 3100 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe; 3101 3102 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 3103 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 3104 if (!p2p) 3105 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); 3106 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 3107 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 3108 0) 3109 return 0; /* Do not show P2P listen discovery results here */ 3110 3111 pos = buf; 3112 end = buf + buflen; 3113 3114 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 3115 MAC2STR(bss->bssid), bss->freq, bss->level); 3116 if (os_snprintf_error(end - pos, ret)) 3117 return -1; 3118 pos += ret; 3119 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 3120 if (ie) 3121 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 3122 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3123 if (ie2) { 3124 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", 3125 ie2, 2 + ie2[1]); 3126 } 3127 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); 3128 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) { 3129 ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); 3130 if (os_snprintf_error(end - pos, ret)) 3131 return -1; 3132 pos += ret; 3133 } 3134 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) { 3135 ret = os_snprintf(pos, end - pos, "[SAE-PK]"); 3136 if (os_snprintf_error(end - pos, ret)) 3137 return -1; 3138 pos += ret; 3139 } 3140 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 3141 if (osen_ie) 3142 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 3143 osen_ie, 2 + osen_ie[1]); 3144 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 3145 if (owe) { 3146 ret = os_snprintf(pos, end - pos, 3147 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 3148 if (os_snprintf_error(end - pos, ret)) 3149 return -1; 3150 pos += ret; 3151 } 3152 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 3153 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { 3154 ret = os_snprintf(pos, end - pos, "[WEP]"); 3155 if (os_snprintf_error(end - pos, ret)) 3156 return -1; 3157 pos += ret; 3158 } 3159 if (mesh) { 3160 ret = os_snprintf(pos, end - pos, "[MESH]"); 3161 if (os_snprintf_error(end - pos, ret)) 3162 return -1; 3163 pos += ret; 3164 } 3165 if (bss_is_dmg(bss)) { 3166 const char *s; 3167 3168 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) { 3169 ret = os_snprintf(pos, end - pos, "[EDMG]"); 3170 if (os_snprintf_error(end - pos, ret)) 3171 return -1; 3172 pos += ret; 3173 } 3174 3175 ret = os_snprintf(pos, end - pos, "[DMG]"); 3176 if (os_snprintf_error(end - pos, ret)) 3177 return -1; 3178 pos += ret; 3179 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 3180 case IEEE80211_CAP_DMG_IBSS: 3181 s = "[IBSS]"; 3182 break; 3183 case IEEE80211_CAP_DMG_AP: 3184 s = "[ESS]"; 3185 break; 3186 case IEEE80211_CAP_DMG_PBSS: 3187 s = "[PBSS]"; 3188 break; 3189 default: 3190 s = ""; 3191 break; 3192 } 3193 ret = os_snprintf(pos, end - pos, "%s", s); 3194 if (os_snprintf_error(end - pos, ret)) 3195 return -1; 3196 pos += ret; 3197 } else { 3198 if (bss->caps & IEEE80211_CAP_IBSS) { 3199 ret = os_snprintf(pos, end - pos, "[IBSS]"); 3200 if (os_snprintf_error(end - pos, ret)) 3201 return -1; 3202 pos += ret; 3203 } 3204 if (bss->caps & IEEE80211_CAP_ESS) { 3205 ret = os_snprintf(pos, end - pos, "[ESS]"); 3206 if (os_snprintf_error(end - pos, ret)) 3207 return -1; 3208 pos += ret; 3209 } 3210 } 3211 if (p2p) { 3212 ret = os_snprintf(pos, end - pos, "[P2P]"); 3213 if (os_snprintf_error(end - pos, ret)) 3214 return -1; 3215 pos += ret; 3216 } 3217 #ifdef CONFIG_HS20 3218 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 3219 ret = os_snprintf(pos, end - pos, "[HS20]"); 3220 if (os_snprintf_error(end - pos, ret)) 3221 return -1; 3222 pos += ret; 3223 } 3224 #endif /* CONFIG_HS20 */ 3225 #ifdef CONFIG_FILS 3226 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 3227 ret = os_snprintf(pos, end - pos, "[FILS]"); 3228 if (os_snprintf_error(end - pos, ret)) 3229 return -1; 3230 pos += ret; 3231 } 3232 #endif /* CONFIG_FILS */ 3233 #ifdef CONFIG_FST 3234 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 3235 ret = os_snprintf(pos, end - pos, "[FST]"); 3236 if (os_snprintf_error(end - pos, ret)) 3237 return -1; 3238 pos += ret; 3239 } 3240 #endif /* CONFIG_FST */ 3241 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 3242 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 3243 if (os_snprintf_error(end - pos, ret)) 3244 return -1; 3245 pos += ret; 3246 } 3247 3248 ret = os_snprintf(pos, end - pos, "\t%s", 3249 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 3250 if (os_snprintf_error(end - pos, ret)) 3251 return -1; 3252 pos += ret; 3253 3254 ret = os_snprintf(pos, end - pos, "\n"); 3255 if (os_snprintf_error(end - pos, ret)) 3256 return -1; 3257 pos += ret; 3258 3259 return pos - buf; 3260 } 3261 3262 3263 static int wpa_supplicant_ctrl_iface_scan_results( 3264 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3265 { 3266 char *pos, *end; 3267 struct wpa_bss *bss; 3268 int ret; 3269 3270 pos = buf; 3271 end = buf + buflen; 3272 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 3273 "flags / ssid\n"); 3274 if (os_snprintf_error(end - pos, ret)) 3275 return pos - buf; 3276 pos += ret; 3277 3278 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 3279 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 3280 end - pos); 3281 if (ret < 0 || ret >= end - pos) 3282 return pos - buf; 3283 pos += ret; 3284 } 3285 3286 return pos - buf; 3287 } 3288 3289 3290 #ifdef CONFIG_MESH 3291 3292 static int wpa_supplicant_ctrl_iface_mesh_interface_add( 3293 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 3294 { 3295 char *pos, ifname[IFNAMSIZ + 1]; 3296 3297 ifname[0] = '\0'; 3298 3299 pos = os_strstr(cmd, "ifname="); 3300 if (pos) { 3301 pos += 7; 3302 os_strlcpy(ifname, pos, sizeof(ifname)); 3303 } 3304 3305 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0) 3306 return -1; 3307 3308 os_strlcpy(reply, ifname, max_len); 3309 return os_strlen(ifname); 3310 } 3311 3312 3313 static int wpa_supplicant_ctrl_iface_mesh_group_add( 3314 struct wpa_supplicant *wpa_s, char *cmd) 3315 { 3316 int id; 3317 struct wpa_ssid *ssid; 3318 3319 id = atoi(cmd); 3320 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id); 3321 3322 ssid = wpa_config_get_network(wpa_s->conf, id); 3323 if (ssid == NULL) { 3324 wpa_printf(MSG_DEBUG, 3325 "CTRL_IFACE: Could not find network id=%d", id); 3326 return -1; 3327 } 3328 if (ssid->mode != WPAS_MODE_MESH) { 3329 wpa_printf(MSG_DEBUG, 3330 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network"); 3331 return -1; 3332 } 3333 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE && 3334 ssid->key_mgmt != WPA_KEY_MGMT_SAE && 3335 ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) { 3336 wpa_printf(MSG_ERROR, 3337 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE"); 3338 return -1; 3339 } 3340 3341 /* 3342 * TODO: If necessary write our own group_add function, 3343 * for now we can reuse select_network 3344 */ 3345 wpa_supplicant_select_network(wpa_s, ssid); 3346 3347 return 0; 3348 } 3349 3350 3351 static int wpa_supplicant_ctrl_iface_mesh_group_remove( 3352 struct wpa_supplicant *wpa_s, char *cmd) 3353 { 3354 struct wpa_supplicant *orig; 3355 struct wpa_global *global; 3356 int found = 0; 3357 3358 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd); 3359 3360 global = wpa_s->global; 3361 orig = wpa_s; 3362 3363 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 3364 if (os_strcmp(wpa_s->ifname, cmd) == 0) { 3365 found = 1; 3366 break; 3367 } 3368 } 3369 if (!found) { 3370 wpa_printf(MSG_ERROR, 3371 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found", 3372 cmd); 3373 return -1; 3374 } 3375 if (wpa_s->mesh_if_created && wpa_s == orig) { 3376 wpa_printf(MSG_ERROR, 3377 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself"); 3378 return -1; 3379 } 3380 3381 wpa_s->reassociate = 0; 3382 wpa_s->disconnected = 1; 3383 wpa_supplicant_cancel_sched_scan(wpa_s); 3384 wpa_supplicant_cancel_scan(wpa_s); 3385 3386 /* 3387 * TODO: If necessary write our own group_remove function, 3388 * for now we can reuse deauthenticate 3389 */ 3390 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3391 3392 if (wpa_s->mesh_if_created) 3393 wpa_supplicant_remove_iface(global, wpa_s, 0); 3394 3395 return 0; 3396 } 3397 3398 3399 static int wpa_supplicant_ctrl_iface_mesh_peer_remove( 3400 struct wpa_supplicant *wpa_s, char *cmd) 3401 { 3402 u8 addr[ETH_ALEN]; 3403 3404 if (hwaddr_aton(cmd, addr) < 0) 3405 return -1; 3406 3407 return wpas_mesh_peer_remove(wpa_s, addr); 3408 } 3409 3410 3411 static int wpa_supplicant_ctrl_iface_mesh_peer_add( 3412 struct wpa_supplicant *wpa_s, char *cmd) 3413 { 3414 u8 addr[ETH_ALEN]; 3415 int duration; 3416 char *pos; 3417 3418 pos = os_strstr(cmd, " duration="); 3419 if (pos) { 3420 *pos = '\0'; 3421 duration = atoi(pos + 10); 3422 } else { 3423 duration = -1; 3424 } 3425 3426 if (hwaddr_aton(cmd, addr)) 3427 return -1; 3428 3429 return wpas_mesh_peer_add(wpa_s, addr, duration); 3430 } 3431 3432 3433 static int wpa_supplicant_ctrl_iface_mesh_link_probe( 3434 struct wpa_supplicant *wpa_s, char *cmd) 3435 { 3436 struct ether_header *eth; 3437 u8 addr[ETH_ALEN]; 3438 u8 *buf; 3439 char *pos; 3440 size_t payload_len = 0, len; 3441 int ret = -1; 3442 3443 if (hwaddr_aton(cmd, addr)) 3444 return -1; 3445 3446 pos = os_strstr(cmd, " payload="); 3447 if (pos) { 3448 pos = pos + 9; 3449 payload_len = os_strlen(pos); 3450 if (payload_len & 1) 3451 return -1; 3452 3453 payload_len /= 2; 3454 } 3455 3456 len = ETH_HLEN + payload_len; 3457 buf = os_malloc(len); 3458 if (!buf) 3459 return -1; 3460 3461 eth = (struct ether_header *) buf; 3462 os_memcpy(eth->ether_dhost, addr, ETH_ALEN); 3463 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN); 3464 eth->ether_type = htons(ETH_P_802_3); 3465 3466 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0) 3467 goto fail; 3468 3469 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len); 3470 fail: 3471 os_free(buf); 3472 return -ret; 3473 } 3474 3475 #endif /* CONFIG_MESH */ 3476 3477 3478 static int wpa_supplicant_ctrl_iface_select_network( 3479 struct wpa_supplicant *wpa_s, char *cmd) 3480 { 3481 int id; 3482 struct wpa_ssid *ssid; 3483 char *pos; 3484 3485 /* cmd: "<network id>" or "any" */ 3486 if (os_strncmp(cmd, "any", 3) == 0) { 3487 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 3488 ssid = NULL; 3489 } else { 3490 id = atoi(cmd); 3491 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 3492 3493 ssid = wpa_config_get_network(wpa_s->conf, id); 3494 if (ssid == NULL) { 3495 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3496 "network id=%d", id); 3497 return -1; 3498 } 3499 if (ssid->disabled == 2) { 3500 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3501 "SELECT_NETWORK with persistent P2P group"); 3502 return -1; 3503 } 3504 } 3505 3506 pos = os_strstr(cmd, " freq="); 3507 if (pos) { 3508 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); 3509 if (freqs) { 3510 os_free(wpa_s->select_network_scan_freqs); 3511 wpa_s->select_network_scan_freqs = freqs; 3512 } 3513 } 3514 3515 wpa_s->scan_min_time.sec = 0; 3516 wpa_s->scan_min_time.usec = 0; 3517 wpa_supplicant_select_network(wpa_s, ssid); 3518 3519 return 0; 3520 } 3521 3522 3523 static int wpa_supplicant_ctrl_iface_enable_network( 3524 struct wpa_supplicant *wpa_s, char *cmd) 3525 { 3526 int id; 3527 struct wpa_ssid *ssid; 3528 3529 /* cmd: "<network id>" or "all" */ 3530 if (os_strcmp(cmd, "all") == 0) { 3531 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 3532 ssid = NULL; 3533 } else { 3534 id = atoi(cmd); 3535 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 3536 3537 ssid = wpa_config_get_network(wpa_s->conf, id); 3538 if (ssid == NULL) { 3539 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3540 "network id=%d", id); 3541 return -1; 3542 } 3543 if (ssid->disabled == 2) { 3544 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3545 "ENABLE_NETWORK with persistent P2P group"); 3546 return -1; 3547 } 3548 3549 if (os_strstr(cmd, " no-connect")) { 3550 ssid->disabled = 0; 3551 return 0; 3552 } 3553 } 3554 wpa_s->scan_min_time.sec = 0; 3555 wpa_s->scan_min_time.usec = 0; 3556 wpa_supplicant_enable_network(wpa_s, ssid); 3557 3558 return 0; 3559 } 3560 3561 3562 static int wpa_supplicant_ctrl_iface_disable_network( 3563 struct wpa_supplicant *wpa_s, char *cmd) 3564 { 3565 int id; 3566 struct wpa_ssid *ssid; 3567 3568 /* cmd: "<network id>" or "all" */ 3569 if (os_strcmp(cmd, "all") == 0) { 3570 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 3571 ssid = NULL; 3572 } else { 3573 id = atoi(cmd); 3574 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 3575 3576 ssid = wpa_config_get_network(wpa_s->conf, id); 3577 if (ssid == NULL) { 3578 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3579 "network id=%d", id); 3580 return -1; 3581 } 3582 if (ssid->disabled == 2) { 3583 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3584 "DISABLE_NETWORK with persistent P2P " 3585 "group"); 3586 return -1; 3587 } 3588 } 3589 wpa_supplicant_disable_network(wpa_s, ssid); 3590 3591 return 0; 3592 } 3593 3594 3595 static int wpa_supplicant_ctrl_iface_add_network( 3596 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3597 { 3598 struct wpa_ssid *ssid; 3599 int ret; 3600 3601 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 3602 3603 ssid = wpa_supplicant_add_network(wpa_s); 3604 if (ssid == NULL) 3605 return -1; 3606 3607 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 3608 if (os_snprintf_error(buflen, ret)) 3609 return -1; 3610 return ret; 3611 } 3612 3613 3614 static int wpa_supplicant_ctrl_iface_remove_network( 3615 struct wpa_supplicant *wpa_s, char *cmd) 3616 { 3617 int id; 3618 int result; 3619 3620 /* cmd: "<network id>" or "all" */ 3621 if (os_strcmp(cmd, "all") == 0) { 3622 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 3623 return wpa_supplicant_remove_all_networks(wpa_s); 3624 } 3625 3626 id = atoi(cmd); 3627 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 3628 3629 result = wpa_supplicant_remove_network(wpa_s, id); 3630 if (result == -1) { 3631 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3632 "id=%d", id); 3633 return -1; 3634 } 3635 if (result == -2) { 3636 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 3637 "network id=%d", id); 3638 return -1; 3639 } 3640 return 0; 3641 } 3642 3643 3644 static int wpa_supplicant_ctrl_iface_update_network( 3645 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 3646 char *name, char *value) 3647 { 3648 int ret; 3649 3650 ret = wpa_config_set(ssid, name, value, 0); 3651 if (ret < 0) { 3652 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 3653 "variable '%s'", name); 3654 return -1; 3655 } 3656 if (ret == 1) 3657 return 0; /* No change to the previously configured value */ 3658 3659 #ifdef CONFIG_BGSCAN 3660 if (os_strcmp(name, "bgscan") == 0) { 3661 /* 3662 * Reset the bgscan parameters for the current network and 3663 * return. There's no need to flush caches for bgscan parameter 3664 * changes. 3665 */ 3666 if (wpa_s->current_ssid == ssid && 3667 wpa_s->wpa_state == WPA_COMPLETED) 3668 wpa_supplicant_reset_bgscan(wpa_s); 3669 return 0; 3670 } 3671 #endif /* CONFIG_BGSCAN */ 3672 3673 if (os_strcmp(name, "bssid") != 0 && 3674 os_strncmp(name, "bssid_", 6) != 0 && 3675 os_strcmp(name, "scan_freq") != 0 && 3676 os_strcmp(name, "priority") != 0) { 3677 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 3678 3679 if (wpa_s->current_ssid == ssid || 3680 wpa_s->current_ssid == NULL) { 3681 /* 3682 * Invalidate the EAP session cache if anything in the 3683 * current or previously used configuration changes. 3684 */ 3685 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3686 } 3687 } 3688 3689 if ((os_strcmp(name, "psk") == 0 && 3690 value[0] == '"' && ssid->ssid_len) || 3691 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 3692 wpa_config_update_psk(ssid); 3693 else if (os_strcmp(name, "priority") == 0) 3694 wpa_config_update_prio_list(wpa_s->conf); 3695 3696 return 0; 3697 } 3698 3699 3700 static int wpa_supplicant_ctrl_iface_set_network( 3701 struct wpa_supplicant *wpa_s, char *cmd) 3702 { 3703 int id, ret, prev_bssid_set, prev_disabled; 3704 struct wpa_ssid *ssid; 3705 char *name, *value; 3706 u8 prev_bssid[ETH_ALEN]; 3707 3708 /* cmd: "<network id> <variable name> <value>" */ 3709 name = os_strchr(cmd, ' '); 3710 if (name == NULL) 3711 return -1; 3712 *name++ = '\0'; 3713 3714 value = os_strchr(name, ' '); 3715 if (value == NULL) 3716 return -1; 3717 *value++ = '\0'; 3718 3719 id = atoi(cmd); 3720 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 3721 id, name); 3722 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3723 (u8 *) value, os_strlen(value)); 3724 3725 ssid = wpa_config_get_network(wpa_s->conf, id); 3726 if (ssid == NULL) { 3727 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3728 "id=%d", id); 3729 return -1; 3730 } 3731 3732 prev_bssid_set = ssid->bssid_set; 3733 prev_disabled = ssid->disabled; 3734 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN); 3735 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name, 3736 value); 3737 if (ret == 0 && 3738 (ssid->bssid_set != prev_bssid_set || 3739 !ether_addr_equal(ssid->bssid, prev_bssid))) 3740 wpas_notify_network_bssid_set_changed(wpa_s, ssid); 3741 3742 if (prev_disabled != ssid->disabled && 3743 (prev_disabled == 2 || ssid->disabled == 2)) 3744 wpas_notify_network_type_changed(wpa_s, ssid); 3745 3746 return ret; 3747 } 3748 3749 3750 static int wpa_supplicant_ctrl_iface_get_network( 3751 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 3752 { 3753 int id; 3754 size_t res; 3755 struct wpa_ssid *ssid; 3756 char *name, *value; 3757 3758 /* cmd: "<network id> <variable name>" */ 3759 name = os_strchr(cmd, ' '); 3760 if (name == NULL || buflen == 0) 3761 return -1; 3762 *name++ = '\0'; 3763 3764 id = atoi(cmd); 3765 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 3766 id, name); 3767 3768 ssid = wpa_config_get_network(wpa_s->conf, id); 3769 if (ssid == NULL) { 3770 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network " 3771 "id=%d", id); 3772 return -1; 3773 } 3774 3775 value = wpa_config_get_no_key(ssid, name); 3776 if (value == NULL) { 3777 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network " 3778 "variable '%s'", name); 3779 return -1; 3780 } 3781 3782 res = os_strlcpy(buf, value, buflen); 3783 if (res >= buflen) { 3784 os_free(value); 3785 return -1; 3786 } 3787 3788 os_free(value); 3789 3790 return res; 3791 } 3792 3793 3794 static int wpa_supplicant_ctrl_iface_dup_network( 3795 struct wpa_supplicant *wpa_s, char *cmd, 3796 struct wpa_supplicant *dst_wpa_s) 3797 { 3798 struct wpa_ssid *ssid_s, *ssid_d; 3799 char *name, *id, *value; 3800 int id_s, id_d, ret; 3801 3802 /* cmd: "<src network id> <dst network id> <variable name>" */ 3803 id = os_strchr(cmd, ' '); 3804 if (id == NULL) 3805 return -1; 3806 *id++ = '\0'; 3807 3808 name = os_strchr(id, ' '); 3809 if (name == NULL) 3810 return -1; 3811 *name++ = '\0'; 3812 3813 id_s = atoi(cmd); 3814 id_d = atoi(id); 3815 3816 wpa_printf(MSG_DEBUG, 3817 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'", 3818 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name); 3819 3820 ssid_s = wpa_config_get_network(wpa_s->conf, id_s); 3821 if (ssid_s == NULL) { 3822 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3823 "network id=%d", id_s); 3824 return -1; 3825 } 3826 3827 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d); 3828 if (ssid_d == NULL) { 3829 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3830 "network id=%d", id_d); 3831 return -1; 3832 } 3833 3834 value = wpa_config_get(ssid_s, name); 3835 if (value == NULL) { 3836 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 3837 "variable '%s'", name); 3838 return -1; 3839 } 3840 3841 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name, 3842 value); 3843 3844 os_free(value); 3845 3846 return ret; 3847 } 3848 3849 3850 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 3851 char *buf, size_t buflen) 3852 { 3853 char *pos, *end; 3854 struct wpa_cred *cred; 3855 int ret; 3856 3857 pos = buf; 3858 end = buf + buflen; 3859 ret = os_snprintf(pos, end - pos, 3860 "cred id / realm / username / domain / imsi\n"); 3861 if (os_snprintf_error(end - pos, ret)) 3862 return pos - buf; 3863 pos += ret; 3864 3865 cred = wpa_s->conf->cred; 3866 while (cred) { 3867 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 3868 cred->id, cred->realm ? cred->realm : "", 3869 cred->username ? cred->username : "", 3870 cred->domain ? cred->domain[0] : "", 3871 cred->imsi ? cred->imsi : ""); 3872 if (os_snprintf_error(end - pos, ret)) 3873 return pos - buf; 3874 pos += ret; 3875 3876 cred = cred->next; 3877 } 3878 3879 return pos - buf; 3880 } 3881 3882 3883 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 3884 char *buf, size_t buflen) 3885 { 3886 struct wpa_cred *cred; 3887 int ret; 3888 3889 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 3890 3891 cred = wpa_config_add_cred(wpa_s->conf); 3892 if (cred == NULL) 3893 return -1; 3894 3895 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id); 3896 3897 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 3898 if (os_snprintf_error(buflen, ret)) 3899 return -1; 3900 return ret; 3901 } 3902 3903 3904 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 3905 char *cmd) 3906 { 3907 int id; 3908 struct wpa_cred *cred, *prev; 3909 3910 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or 3911 * "provisioning_sp=<FQDN> */ 3912 if (os_strcmp(cmd, "all") == 0) { 3913 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 3914 return wpas_remove_all_creds(wpa_s); 3915 } 3916 3917 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 3918 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 3919 cmd + 8); 3920 cred = wpa_s->conf->cred; 3921 while (cred) { 3922 prev = cred; 3923 cred = cred->next; 3924 if (prev->domain) { 3925 size_t i; 3926 for (i = 0; i < prev->num_domain; i++) { 3927 if (os_strcmp(prev->domain[i], cmd + 8) 3928 != 0) 3929 continue; 3930 wpas_remove_cred(wpa_s, prev); 3931 break; 3932 } 3933 } 3934 } 3935 return 0; 3936 } 3937 3938 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) { 3939 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'", 3940 cmd + 16); 3941 cred = wpa_s->conf->cred; 3942 while (cred) { 3943 prev = cred; 3944 cred = cred->next; 3945 if (prev->provisioning_sp && 3946 os_strcmp(prev->provisioning_sp, cmd + 16) == 0) 3947 wpas_remove_cred(wpa_s, prev); 3948 } 3949 return 0; 3950 } 3951 3952 id = atoi(cmd); 3953 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 3954 3955 cred = wpa_config_get_cred(wpa_s->conf, id); 3956 return wpas_remove_cred(wpa_s, cred); 3957 } 3958 3959 3960 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 3961 char *cmd) 3962 { 3963 int id; 3964 struct wpa_cred *cred; 3965 char *name, *value; 3966 3967 /* cmd: "<cred id> <variable name> <value>" */ 3968 name = os_strchr(cmd, ' '); 3969 if (name == NULL) 3970 return -1; 3971 *name++ = '\0'; 3972 3973 value = os_strchr(name, ' '); 3974 if (value == NULL) 3975 return -1; 3976 *value++ = '\0'; 3977 3978 id = atoi(cmd); 3979 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 3980 id, name); 3981 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3982 (u8 *) value, os_strlen(value)); 3983 3984 cred = wpa_config_get_cred(wpa_s->conf, id); 3985 if (cred == NULL) { 3986 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3987 id); 3988 return -1; 3989 } 3990 3991 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 3992 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 3993 "variable '%s'", name); 3994 return -1; 3995 } 3996 3997 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name); 3998 3999 return 0; 4000 } 4001 4002 4003 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s, 4004 char *cmd, char *buf, 4005 size_t buflen) 4006 { 4007 int id; 4008 size_t res; 4009 struct wpa_cred *cred; 4010 char *name, *value; 4011 4012 /* cmd: "<cred id> <variable name>" */ 4013 name = os_strchr(cmd, ' '); 4014 if (name == NULL) 4015 return -1; 4016 *name++ = '\0'; 4017 4018 id = atoi(cmd); 4019 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'", 4020 id, name); 4021 4022 cred = wpa_config_get_cred(wpa_s->conf, id); 4023 if (cred == NULL) { 4024 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 4025 id); 4026 return -1; 4027 } 4028 4029 value = wpa_config_get_cred_no_key(cred, name); 4030 if (value == NULL) { 4031 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'", 4032 name); 4033 return -1; 4034 } 4035 4036 res = os_strlcpy(buf, value, buflen); 4037 if (res >= buflen) { 4038 os_free(value); 4039 return -1; 4040 } 4041 4042 os_free(value); 4043 4044 return res; 4045 } 4046 4047 4048 #ifndef CONFIG_NO_CONFIG_WRITE 4049 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 4050 { 4051 int ret; 4052 4053 if (!wpa_s->conf->update_config) { 4054 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 4055 "to update configuration (update_config=0)"); 4056 return -1; 4057 } 4058 4059 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 4060 if (ret) { 4061 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 4062 "update configuration"); 4063 } else { 4064 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 4065 " updated"); 4066 } 4067 4068 return ret; 4069 } 4070 #endif /* CONFIG_NO_CONFIG_WRITE */ 4071 4072 4073 struct cipher_info { 4074 unsigned int capa; 4075 const char *name; 4076 int group_only; 4077 }; 4078 4079 static const struct cipher_info ciphers[] = { 4080 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 }, 4081 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, 4082 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, 4083 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, 4084 #ifndef CONFIG_NO_TKIP 4085 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, 4086 #endif /* CONFIG_NO_TKIP */ 4087 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, 4088 #ifdef CONFIG_WEP 4089 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, 4090 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } 4091 #endif /* CONFIG_WEP */ 4092 }; 4093 4094 static const struct cipher_info ciphers_group_mgmt[] = { 4095 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 }, 4096 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 }, 4097 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 }, 4098 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 }, 4099 }; 4100 4101 4102 static int ctrl_iface_get_capability_pairwise(int res, bool strict, 4103 struct wpa_driver_capa *capa, 4104 char *buf, size_t buflen) 4105 { 4106 int ret; 4107 char *pos, *end; 4108 size_t len; 4109 unsigned int i; 4110 4111 pos = buf; 4112 end = pos + buflen; 4113 4114 if (res < 0) { 4115 if (strict) 4116 return 0; 4117 #ifdef CONFIG_NO_TKIP 4118 len = os_strlcpy(buf, "CCMP NONE", buflen); 4119 #else /* CONFIG_NO_TKIP */ 4120 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 4121 #endif /* CONFIG_NO_TKIP */ 4122 if (len >= buflen) 4123 return -1; 4124 return len; 4125 } 4126 4127 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 4128 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) { 4129 ret = os_snprintf(pos, end - pos, "%s%s", 4130 pos == buf ? "" : " ", 4131 ciphers[i].name); 4132 if (os_snprintf_error(end - pos, ret)) 4133 return pos - buf; 4134 pos += ret; 4135 } 4136 } 4137 4138 return pos - buf; 4139 } 4140 4141 4142 static int ctrl_iface_get_capability_group(int res, bool strict, 4143 struct wpa_driver_capa *capa, 4144 char *buf, size_t buflen) 4145 { 4146 int ret; 4147 char *pos, *end; 4148 size_t len; 4149 unsigned int i; 4150 4151 pos = buf; 4152 end = pos + buflen; 4153 4154 if (res < 0) { 4155 if (strict) 4156 return 0; 4157 #ifdef CONFIG_WEP 4158 #ifdef CONFIG_NO_TKIP 4159 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen); 4160 #else /* CONFIG_NO_TKIP */ 4161 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 4162 #endif /* CONFIG_NO_TKIP */ 4163 #else /* CONFIG_WEP */ 4164 #ifdef CONFIG_NO_TKIP 4165 len = os_strlcpy(buf, "CCMP", buflen); 4166 #else /* CONFIG_NO_TKIP */ 4167 len = os_strlcpy(buf, "CCMP TKIP", buflen); 4168 #endif /* CONFIG_NO_TKIP */ 4169 #endif /* CONFIG_WEP */ 4170 if (len >= buflen) 4171 return -1; 4172 return len; 4173 } 4174 4175 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 4176 if (capa->enc & ciphers[i].capa) { 4177 ret = os_snprintf(pos, end - pos, "%s%s", 4178 pos == buf ? "" : " ", 4179 ciphers[i].name); 4180 if (os_snprintf_error(end - pos, ret)) 4181 return pos - buf; 4182 pos += ret; 4183 } 4184 } 4185 4186 return pos - buf; 4187 } 4188 4189 4190 static int ctrl_iface_get_capability_group_mgmt(int res, bool strict, 4191 struct wpa_driver_capa *capa, 4192 char *buf, size_t buflen) 4193 { 4194 int ret; 4195 char *pos, *end; 4196 unsigned int i; 4197 4198 pos = buf; 4199 end = pos + buflen; 4200 4201 if (res < 0) 4202 return 0; 4203 4204 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) { 4205 if (capa->enc & ciphers_group_mgmt[i].capa) { 4206 ret = os_snprintf(pos, end - pos, "%s%s", 4207 pos == buf ? "" : " ", 4208 ciphers_group_mgmt[i].name); 4209 if (os_snprintf_error(end - pos, ret)) 4210 return pos - buf; 4211 pos += ret; 4212 } 4213 } 4214 4215 return pos - buf; 4216 } 4217 4218 4219 static int iftype_str_to_index(const char *iftype_str) 4220 { 4221 if (!iftype_str) 4222 return WPA_IF_MAX; 4223 4224 if (os_strcmp(iftype_str, "STATION") == 0) 4225 return WPA_IF_STATION; 4226 4227 if (os_strcmp(iftype_str, "AP_VLAN") == 0) 4228 return WPA_IF_AP_VLAN; 4229 4230 if (os_strcmp(iftype_str, "AP") == 0) 4231 return WPA_IF_AP_BSS; 4232 4233 if (os_strcmp(iftype_str, "P2P_GO") == 0) 4234 return WPA_IF_P2P_GO; 4235 4236 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0) 4237 return WPA_IF_P2P_CLIENT; 4238 4239 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0) 4240 return WPA_IF_P2P_DEVICE; 4241 4242 if (os_strcmp(iftype_str, "MESH") == 0) 4243 return WPA_IF_MESH; 4244 4245 if (os_strcmp(iftype_str, "IBSS") == 0) 4246 return WPA_IF_IBSS; 4247 4248 if (os_strcmp(iftype_str, "NAN") == 0) 4249 return WPA_IF_NAN; 4250 4251 return WPA_IF_MAX; 4252 } 4253 4254 4255 static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, 4256 struct wpa_driver_capa *capa, 4257 const char *iftype_str, 4258 char *buf, size_t buflen) 4259 { 4260 int ret; 4261 unsigned int key_mgmt; 4262 char *pos, *end; 4263 size_t len; 4264 4265 pos = buf; 4266 end = pos + buflen; 4267 4268 if (res < 0) { 4269 if (strict) 4270 return 0; 4271 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 4272 "NONE", buflen); 4273 if (len >= buflen) 4274 return -1; 4275 return len; 4276 } 4277 4278 if (iftype_str) { 4279 enum wpa_driver_if_type iftype; 4280 4281 iftype = iftype_str_to_index(iftype_str); 4282 if (iftype == WPA_IF_MAX) 4283 return -1; 4284 key_mgmt = capa->key_mgmt_iftype[iftype]; 4285 } else { 4286 key_mgmt = capa->key_mgmt; 4287 } 4288 4289 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 4290 if (os_snprintf_error(end - pos, ret)) 4291 return pos - buf; 4292 pos += ret; 4293 4294 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4295 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 4296 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 4297 if (os_snprintf_error(end - pos, ret)) 4298 return pos - buf; 4299 pos += ret; 4300 } 4301 4302 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 4303 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4304 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 4305 if (os_snprintf_error(end - pos, ret)) 4306 return pos - buf; 4307 pos += ret; 4308 } 4309 4310 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 4311 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 4312 if (os_snprintf_error(end - pos, ret)) 4313 return pos - buf; 4314 pos += ret; 4315 } 4316 4317 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) { 4318 ret = os_snprintf(pos, end - pos, " WAPI-PSK"); 4319 if (os_snprintf_error(end - pos, ret)) 4320 return pos - buf; 4321 pos += ret; 4322 } 4323 4324 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) { 4325 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE"); 4326 if (os_snprintf_error(end - pos, ret)) 4327 return pos - buf; 4328 pos += ret; 4329 } 4330 4331 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) { 4332 ret = os_snprintf(pos, end - pos, " CCKM"); 4333 if (os_snprintf_error(end - pos, ret)) 4334 return pos - buf; 4335 pos += ret; 4336 } 4337 4338 #ifdef CONFIG_SUITEB 4339 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { 4340 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); 4341 if (os_snprintf_error(end - pos, ret)) 4342 return pos - buf; 4343 pos += ret; 4344 } 4345 #endif /* CONFIG_SUITEB */ 4346 #ifdef CONFIG_SUITEB192 4347 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { 4348 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); 4349 if (os_snprintf_error(end - pos, ret)) 4350 return pos - buf; 4351 pos += ret; 4352 } 4353 #endif /* CONFIG_SUITEB192 */ 4354 #ifdef CONFIG_OWE 4355 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { 4356 ret = os_snprintf(pos, end - pos, " OWE"); 4357 if (os_snprintf_error(end - pos, ret)) 4358 return pos - buf; 4359 pos += ret; 4360 } 4361 #endif /* CONFIG_OWE */ 4362 #ifdef CONFIG_DPP 4363 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { 4364 ret = os_snprintf(pos, end - pos, " DPP"); 4365 if (os_snprintf_error(end - pos, ret)) 4366 return pos - buf; 4367 pos += ret; 4368 } 4369 #endif /* CONFIG_DPP */ 4370 #ifdef CONFIG_FILS 4371 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { 4372 ret = os_snprintf(pos, end - pos, " FILS-SHA256"); 4373 if (os_snprintf_error(end - pos, ret)) 4374 return pos - buf; 4375 pos += ret; 4376 } 4377 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { 4378 ret = os_snprintf(pos, end - pos, " FILS-SHA384"); 4379 if (os_snprintf_error(end - pos, ret)) 4380 return pos - buf; 4381 pos += ret; 4382 } 4383 #ifdef CONFIG_IEEE80211R 4384 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { 4385 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); 4386 if (os_snprintf_error(end - pos, ret)) 4387 return pos - buf; 4388 pos += ret; 4389 } 4390 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { 4391 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); 4392 if (os_snprintf_error(end - pos, ret)) 4393 return pos - buf; 4394 pos += ret; 4395 } 4396 #endif /* CONFIG_IEEE80211R */ 4397 #endif /* CONFIG_FILS */ 4398 #ifdef CONFIG_IEEE80211R 4399 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { 4400 ret = os_snprintf(pos, end - pos, " FT-PSK"); 4401 if (os_snprintf_error(end - pos, ret)) 4402 return pos - buf; 4403 pos += ret; 4404 } 4405 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 4406 ret = os_snprintf(pos, end - pos, " FT-EAP"); 4407 if (os_snprintf_error(end - pos, ret)) 4408 return pos - buf; 4409 pos += ret; 4410 } 4411 #ifdef CONFIG_SAE 4412 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) { 4413 ret = os_snprintf(pos, end - pos, " FT-SAE"); 4414 if (os_snprintf_error(end - pos, ret)) 4415 return pos - buf; 4416 pos += ret; 4417 } 4418 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) { 4419 ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY"); 4420 if (os_snprintf_error(end - pos, ret)) 4421 return pos - buf; 4422 pos += ret; 4423 } 4424 #endif /* CONFIG_SAE */ 4425 #ifdef CONFIG_SHA384 4426 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) { 4427 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384"); 4428 if (os_snprintf_error(end - pos, ret)) 4429 return pos - buf; 4430 pos += ret; 4431 } 4432 #endif /* CONFIG_SHA384 */ 4433 #endif /* CONFIG_IEEE80211R */ 4434 #ifdef CONFIG_SAE 4435 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { 4436 ret = os_snprintf(pos, end - pos, " SAE"); 4437 if (os_snprintf_error(end - pos, ret)) 4438 return pos - buf; 4439 pos += ret; 4440 } 4441 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) { 4442 ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY"); 4443 if (os_snprintf_error(end - pos, ret)) 4444 return pos - buf; 4445 pos += ret; 4446 } 4447 #endif /* CONFIG_SAE */ 4448 #ifdef CONFIG_SHA256 4449 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) { 4450 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256"); 4451 if (os_snprintf_error(end - pos, ret)) 4452 return pos - buf; 4453 pos += ret; 4454 } 4455 4456 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) { 4457 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256"); 4458 if (os_snprintf_error(end - pos, ret)) 4459 return pos - buf; 4460 pos += ret; 4461 } 4462 #endif /* CONFIG_SHA256 */ 4463 #ifdef CONFIG_HS20 4464 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) { 4465 ret = os_snprintf(pos, end - pos, " OSEN"); 4466 if (os_snprintf_error(end - pos, ret)) 4467 return pos - buf; 4468 pos += ret; 4469 } 4470 #endif /* CONFIG_HS20 */ 4471 4472 return pos - buf; 4473 } 4474 4475 4476 static int ctrl_iface_get_capability_proto(int res, bool strict, 4477 struct wpa_driver_capa *capa, 4478 char *buf, size_t buflen) 4479 { 4480 int ret; 4481 char *pos, *end; 4482 size_t len; 4483 4484 pos = buf; 4485 end = pos + buflen; 4486 4487 if (res < 0) { 4488 if (strict) 4489 return 0; 4490 len = os_strlcpy(buf, "RSN WPA", buflen); 4491 if (len >= buflen) 4492 return -1; 4493 return len; 4494 } 4495 4496 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 4497 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4498 ret = os_snprintf(pos, end - pos, "%sRSN", 4499 pos == buf ? "" : " "); 4500 if (os_snprintf_error(end - pos, ret)) 4501 return pos - buf; 4502 pos += ret; 4503 } 4504 4505 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4506 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 4507 ret = os_snprintf(pos, end - pos, "%sWPA", 4508 pos == buf ? "" : " "); 4509 if (os_snprintf_error(end - pos, ret)) 4510 return pos - buf; 4511 pos += ret; 4512 } 4513 4514 return pos - buf; 4515 } 4516 4517 4518 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, 4519 int res, bool strict, 4520 struct wpa_driver_capa *capa, 4521 char *buf, size_t buflen) 4522 { 4523 int ret; 4524 char *pos, *end; 4525 size_t len; 4526 4527 pos = buf; 4528 end = pos + buflen; 4529 4530 if (res < 0) { 4531 if (strict) 4532 return 0; 4533 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 4534 if (len >= buflen) 4535 return -1; 4536 return len; 4537 } 4538 4539 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 4540 ret = os_snprintf(pos, end - pos, "%sOPEN", 4541 pos == buf ? "" : " "); 4542 if (os_snprintf_error(end - pos, ret)) 4543 return pos - buf; 4544 pos += ret; 4545 } 4546 4547 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 4548 ret = os_snprintf(pos, end - pos, "%sSHARED", 4549 pos == buf ? "" : " "); 4550 if (os_snprintf_error(end - pos, ret)) 4551 return pos - buf; 4552 pos += ret; 4553 } 4554 4555 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 4556 ret = os_snprintf(pos, end - pos, "%sLEAP", 4557 pos == buf ? "" : " "); 4558 if (os_snprintf_error(end - pos, ret)) 4559 return pos - buf; 4560 pos += ret; 4561 } 4562 4563 #ifdef CONFIG_SAE 4564 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) { 4565 ret = os_snprintf(pos, end - pos, "%sSAE", 4566 pos == buf ? "" : " "); 4567 if (os_snprintf_error(end - pos, ret)) 4568 return pos - buf; 4569 pos += ret; 4570 } 4571 #endif /* CONFIG_SAE */ 4572 4573 #ifdef CONFIG_FILS 4574 if (wpa_is_fils_supported(wpa_s)) { 4575 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS", 4576 pos == buf ? "" : " "); 4577 if (os_snprintf_error(end - pos, ret)) 4578 return pos - buf; 4579 pos += ret; 4580 } 4581 4582 #ifdef CONFIG_FILS_SK_PFS 4583 if (wpa_is_fils_sk_pfs_supported(wpa_s)) { 4584 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS", 4585 pos == buf ? "" : " "); 4586 if (os_snprintf_error(end - pos, ret)) 4587 return pos - buf; 4588 pos += ret; 4589 } 4590 #endif /* CONFIG_FILS_SK_PFS */ 4591 #endif /* CONFIG_FILS */ 4592 4593 #ifdef CONFIG_PASN 4594 ret = os_snprintf(pos, end - pos, "%sPASN", 4595 pos == buf ? "" : " "); 4596 if (os_snprintf_error(end - pos, ret)) 4597 return pos - buf; 4598 pos += ret; 4599 4600 #endif /* CONFIG_PASN */ 4601 4602 return pos - buf; 4603 } 4604 4605 4606 static int ctrl_iface_get_capability_modes(int res, bool strict, 4607 struct wpa_driver_capa *capa, 4608 char *buf, size_t buflen) 4609 { 4610 int ret; 4611 char *pos, *end; 4612 size_t len; 4613 4614 pos = buf; 4615 end = pos + buflen; 4616 4617 if (res < 0) { 4618 if (strict) 4619 return 0; 4620 len = os_strlcpy(buf, "IBSS AP", buflen); 4621 if (len >= buflen) 4622 return -1; 4623 return len; 4624 } 4625 4626 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) { 4627 ret = os_snprintf(pos, end - pos, "%sIBSS", 4628 pos == buf ? "" : " "); 4629 if (os_snprintf_error(end - pos, ret)) 4630 return pos - buf; 4631 pos += ret; 4632 } 4633 4634 if (capa->flags & WPA_DRIVER_FLAGS_AP) { 4635 ret = os_snprintf(pos, end - pos, "%sAP", 4636 pos == buf ? "" : " "); 4637 if (os_snprintf_error(end - pos, ret)) 4638 return pos - buf; 4639 pos += ret; 4640 } 4641 4642 #ifdef CONFIG_MESH 4643 if (capa->flags & WPA_DRIVER_FLAGS_MESH) { 4644 ret = os_snprintf(pos, end - pos, "%sMESH", 4645 pos == buf ? "" : " "); 4646 if (os_snprintf_error(end - pos, ret)) 4647 return pos - buf; 4648 pos += ret; 4649 } 4650 #endif /* CONFIG_MESH */ 4651 4652 return pos - buf; 4653 } 4654 4655 4656 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 4657 char *buf, size_t buflen) 4658 { 4659 struct hostapd_channel_data *chnl; 4660 int ret, i, j; 4661 char *pos, *end, *hmode; 4662 4663 pos = buf; 4664 end = pos + buflen; 4665 4666 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4667 switch (wpa_s->hw.modes[j].mode) { 4668 case HOSTAPD_MODE_IEEE80211B: 4669 hmode = "B"; 4670 break; 4671 case HOSTAPD_MODE_IEEE80211G: 4672 hmode = "G"; 4673 break; 4674 case HOSTAPD_MODE_IEEE80211A: 4675 hmode = "A"; 4676 break; 4677 case HOSTAPD_MODE_IEEE80211AD: 4678 hmode = "AD"; 4679 break; 4680 default: 4681 continue; 4682 } 4683 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 4684 if (os_snprintf_error(end - pos, ret)) 4685 return pos - buf; 4686 pos += ret; 4687 chnl = wpa_s->hw.modes[j].channels; 4688 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4689 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4690 continue; 4691 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 4692 if (os_snprintf_error(end - pos, ret)) 4693 return pos - buf; 4694 pos += ret; 4695 } 4696 ret = os_snprintf(pos, end - pos, "\n"); 4697 if (os_snprintf_error(end - pos, ret)) 4698 return pos - buf; 4699 pos += ret; 4700 } 4701 4702 return pos - buf; 4703 } 4704 4705 4706 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s, 4707 char *buf, size_t buflen) 4708 { 4709 struct hostapd_channel_data *chnl; 4710 int ret, i, j; 4711 char *pos, *end, *hmode; 4712 4713 pos = buf; 4714 end = pos + buflen; 4715 4716 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4717 switch (wpa_s->hw.modes[j].mode) { 4718 case HOSTAPD_MODE_IEEE80211B: 4719 hmode = "B"; 4720 break; 4721 case HOSTAPD_MODE_IEEE80211G: 4722 hmode = "G"; 4723 break; 4724 case HOSTAPD_MODE_IEEE80211A: 4725 hmode = "A"; 4726 break; 4727 case HOSTAPD_MODE_IEEE80211AD: 4728 hmode = "AD"; 4729 break; 4730 default: 4731 continue; 4732 } 4733 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n", 4734 hmode); 4735 if (os_snprintf_error(end - pos, ret)) 4736 return pos - buf; 4737 pos += ret; 4738 chnl = wpa_s->hw.modes[j].channels; 4739 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4740 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4741 continue; 4742 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n", 4743 chnl[i].chan, chnl[i].freq, 4744 chnl[i].flag & HOSTAPD_CHAN_NO_IR ? 4745 " (NO_IR)" : "", 4746 chnl[i].flag & HOSTAPD_CHAN_RADAR ? 4747 " (DFS)" : ""); 4748 4749 if (os_snprintf_error(end - pos, ret)) 4750 return pos - buf; 4751 pos += ret; 4752 } 4753 ret = os_snprintf(pos, end - pos, "\n"); 4754 if (os_snprintf_error(end - pos, ret)) 4755 return pos - buf; 4756 pos += ret; 4757 } 4758 4759 return pos - buf; 4760 } 4761 4762 4763 static int wpa_supplicant_ctrl_iface_get_capability( 4764 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 4765 size_t buflen) 4766 { 4767 struct wpa_driver_capa capa; 4768 int res; 4769 char *next_param, *curr_param, *iftype = NULL; 4770 bool strict = false; 4771 char field[50]; 4772 size_t len; 4773 4774 /* Determine whether or not strict checking was requested */ 4775 len = os_strlcpy(field, _field, sizeof(field)); 4776 if (len >= sizeof(field)) 4777 return -1; 4778 4779 next_param = os_strchr(field, ' '); 4780 while (next_param) { 4781 *next_param++ = '\0'; 4782 curr_param = next_param; 4783 next_param = os_strchr(next_param, ' '); 4784 4785 if (next_param) 4786 *next_param = '\0'; 4787 4788 if (os_strcmp(curr_param, "strict") == 0) 4789 strict = true; 4790 else if (os_strncmp(curr_param, "iftype=", 7) == 0) 4791 iftype = curr_param + 7; 4792 else 4793 return -1; 4794 } 4795 4796 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s", 4797 field, iftype ? " iftype=" : "", iftype ? iftype : "", 4798 strict ? " strict" : ""); 4799 4800 if (os_strcmp(field, "eap") == 0) { 4801 return eap_get_names(buf, buflen); 4802 } 4803 4804 res = wpa_drv_get_capa(wpa_s, &capa); 4805 4806 if (os_strcmp(field, "pairwise") == 0) 4807 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 4808 buf, buflen); 4809 4810 if (os_strcmp(field, "group") == 0) 4811 return ctrl_iface_get_capability_group(res, strict, &capa, 4812 buf, buflen); 4813 4814 if (os_strcmp(field, "group_mgmt") == 0) 4815 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa, 4816 buf, buflen); 4817 4818 if (os_strcmp(field, "key_mgmt") == 0) 4819 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 4820 iftype, buf, buflen); 4821 4822 if (os_strcmp(field, "proto") == 0) 4823 return ctrl_iface_get_capability_proto(res, strict, &capa, 4824 buf, buflen); 4825 4826 if (os_strcmp(field, "auth_alg") == 0) 4827 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict, 4828 &capa, buf, buflen); 4829 4830 if (os_strcmp(field, "modes") == 0) 4831 return ctrl_iface_get_capability_modes(res, strict, &capa, 4832 buf, buflen); 4833 4834 if (os_strcmp(field, "channels") == 0) 4835 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 4836 4837 if (os_strcmp(field, "freq") == 0) 4838 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen); 4839 4840 #ifdef CONFIG_TDLS 4841 if (os_strcmp(field, "tdls") == 0) 4842 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen); 4843 #endif /* CONFIG_TDLS */ 4844 4845 #ifdef CONFIG_ERP 4846 if (os_strcmp(field, "erp") == 0) { 4847 res = os_snprintf(buf, buflen, "ERP"); 4848 if (os_snprintf_error(buflen, res)) 4849 return -1; 4850 return res; 4851 } 4852 #endif /* CONFIG_EPR */ 4853 4854 #ifdef CONFIG_FIPS 4855 if (os_strcmp(field, "fips") == 0) { 4856 res = os_snprintf(buf, buflen, "FIPS"); 4857 if (os_snprintf_error(buflen, res)) 4858 return -1; 4859 return res; 4860 } 4861 #endif /* CONFIG_FIPS */ 4862 4863 #ifdef CONFIG_ACS 4864 if (os_strcmp(field, "acs") == 0) { 4865 res = os_snprintf(buf, buflen, "ACS"); 4866 if (os_snprintf_error(buflen, res)) 4867 return -1; 4868 return res; 4869 } 4870 #endif /* CONFIG_ACS */ 4871 4872 #ifdef CONFIG_FILS 4873 if (os_strcmp(field, "fils") == 0) { 4874 #ifdef CONFIG_FILS_SK_PFS 4875 if (wpa_is_fils_supported(wpa_s) && 4876 wpa_is_fils_sk_pfs_supported(wpa_s)) { 4877 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS"); 4878 if (os_snprintf_error(buflen, res)) 4879 return -1; 4880 return res; 4881 } 4882 #endif /* CONFIG_FILS_SK_PFS */ 4883 4884 if (wpa_is_fils_supported(wpa_s)) { 4885 res = os_snprintf(buf, buflen, "FILS"); 4886 if (os_snprintf_error(buflen, res)) 4887 return -1; 4888 return res; 4889 } 4890 } 4891 #endif /* CONFIG_FILS */ 4892 4893 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) { 4894 res = os_snprintf(buf, buflen, "MULTIBSS-STA"); 4895 if (os_snprintf_error(buflen, res)) 4896 return -1; 4897 return res; 4898 } 4899 4900 #ifdef CONFIG_DPP 4901 if (os_strcmp(field, "dpp") == 0) { 4902 #ifdef CONFIG_DPP3 4903 res = os_snprintf(buf, buflen, "DPP=3"); 4904 #elif defined(CONFIG_DPP2) 4905 res = os_snprintf(buf, buflen, "DPP=2"); 4906 #else /* CONFIG_DPP2 */ 4907 res = os_snprintf(buf, buflen, "DPP=1"); 4908 #endif /* CONFIG_DPP2 */ 4909 if (os_snprintf_error(buflen, res)) 4910 return -1; 4911 return res; 4912 } 4913 #endif /* CONFIG_DPP */ 4914 4915 #ifdef CONFIG_NAN_USD 4916 if (os_strcmp(field, "nan") == 0) { 4917 res = os_snprintf(buf, buflen, "USD"); 4918 if (os_snprintf_error(buflen, res)) 4919 return -1; 4920 return res; 4921 } 4922 #endif /* CONFIG_NAN_USD */ 4923 4924 #ifdef CONFIG_SAE 4925 if (os_strcmp(field, "sae") == 0 && 4926 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { 4927 #ifdef CONFIG_SAE_PK 4928 res = os_snprintf(buf, buflen, "H2E PK"); 4929 #else /* CONFIG_SAE_PK */ 4930 res = os_snprintf(buf, buflen, "H2E"); 4931 #endif /* CONFIG_SAE_PK */ 4932 if (os_snprintf_error(buflen, res)) 4933 return -1; 4934 return res; 4935 } 4936 #endif /* CONFIG_SAE */ 4937 4938 #ifdef CONFIG_OCV 4939 if (os_strcmp(field, "ocv") == 0) { 4940 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) || 4941 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV)) 4942 res = os_snprintf(buf, buflen, "supported"); 4943 else 4944 res = os_snprintf(buf, buflen, "not supported"); 4945 if (os_snprintf_error(buflen, res)) 4946 return -1; 4947 return res; 4948 } 4949 #endif /* CONFIG_OCV */ 4950 4951 if (os_strcmp(field, "beacon_prot") == 0) { 4952 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) || 4953 (wpa_s->drv_flags2 & 4954 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT)) 4955 res = os_snprintf(buf, buflen, "supported"); 4956 else 4957 res = os_snprintf(buf, buflen, "not supported"); 4958 if (os_snprintf_error(buflen, res)) 4959 return -1; 4960 return res; 4961 } 4962 4963 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 4964 field); 4965 4966 return -1; 4967 } 4968 4969 4970 #ifdef CONFIG_INTERWORKING 4971 static char * anqp_add_hex(char *pos, char *end, const char *title, 4972 struct wpabuf *data) 4973 { 4974 char *start = pos; 4975 size_t i; 4976 int ret; 4977 const u8 *d; 4978 4979 if (data == NULL) 4980 return start; 4981 4982 ret = os_snprintf(pos, end - pos, "%s=", title); 4983 if (os_snprintf_error(end - pos, ret)) 4984 return start; 4985 pos += ret; 4986 4987 d = wpabuf_head_u8(data); 4988 for (i = 0; i < wpabuf_len(data); i++) { 4989 ret = os_snprintf(pos, end - pos, "%02x", *d++); 4990 if (os_snprintf_error(end - pos, ret)) 4991 return start; 4992 pos += ret; 4993 } 4994 4995 ret = os_snprintf(pos, end - pos, "\n"); 4996 if (os_snprintf_error(end - pos, ret)) 4997 return start; 4998 pos += ret; 4999 5000 return pos; 5001 } 5002 #endif /* CONFIG_INTERWORKING */ 5003 5004 5005 #ifdef CONFIG_FILS 5006 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) 5007 { 5008 char *start = pos; 5009 const u8 *ie, *ie_end; 5010 u16 info, realms; 5011 int ret; 5012 5013 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); 5014 if (!ie) 5015 return 0; 5016 ie_end = ie + 2 + ie[1]; 5017 ie += 2; 5018 if (ie_end - ie < 2) 5019 return 0; 5020 5021 info = WPA_GET_LE16(ie); 5022 ie += 2; 5023 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info); 5024 if (os_snprintf_error(end - pos, ret)) 5025 return 0; 5026 pos += ret; 5027 5028 if (info & BIT(7)) { 5029 /* Cache Identifier Included */ 5030 if (ie_end - ie < 2) 5031 return 0; 5032 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n", 5033 ie[0], ie[1]); 5034 if (os_snprintf_error(end - pos, ret)) 5035 return 0; 5036 pos += ret; 5037 ie += 2; 5038 } 5039 5040 if (info & BIT(8)) { 5041 /* HESSID Included */ 5042 if (ie_end - ie < ETH_ALEN) 5043 return 0; 5044 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n", 5045 MAC2STR(ie)); 5046 if (os_snprintf_error(end - pos, ret)) 5047 return 0; 5048 pos += ret; 5049 ie += ETH_ALEN; 5050 } 5051 5052 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3; 5053 if (realms) { 5054 if (ie_end - ie < realms * 2) 5055 return 0; 5056 ret = os_snprintf(pos, end - pos, "fils_realms="); 5057 if (os_snprintf_error(end - pos, ret)) 5058 return 0; 5059 pos += ret; 5060 5061 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2); 5062 if (ret <= 0) 5063 return 0; 5064 pos += ret; 5065 ie += realms * 2; 5066 ret = os_snprintf(pos, end - pos, "\n"); 5067 if (os_snprintf_error(end - pos, ret)) 5068 return 0; 5069 pos += ret; 5070 } 5071 5072 return pos - start; 5073 } 5074 #endif /* CONFIG_FILS */ 5075 5076 5077 static int print_rnr(struct wpa_bss *bss, char *pos, char *end) 5078 { 5079 char *start = pos; 5080 const u8 *ie, *ie_end; 5081 unsigned int n = 0; 5082 int ret; 5083 5084 ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT); 5085 if (!ie) 5086 return 0; 5087 5088 ie_end = ie + 2 + ie[1]; 5089 ie += 2; 5090 5091 while (ie < ie_end) { 5092 const struct ieee80211_neighbor_ap_info *info = 5093 (const struct ieee80211_neighbor_ap_info *) ie; 5094 const u8 *tbtt_start; 5095 size_t left = ie_end - ie; 5096 5097 if (left < sizeof(struct ieee80211_neighbor_ap_info)) 5098 return 0; 5099 5100 left -= sizeof(struct ieee80211_neighbor_ap_info); 5101 if (left < info->tbtt_info_len) 5102 return 0; 5103 5104 ret = os_snprintf(pos, end - pos, 5105 "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ", 5106 n, *ie, info->tbtt_info_len, 5107 info->op_class, info->channel); 5108 if (os_snprintf_error(end - pos, ret)) 5109 return 0; 5110 pos += ret; 5111 5112 ie += sizeof(struct ieee80211_neighbor_ap_info); 5113 tbtt_start = ie; 5114 if (info->tbtt_info_len >= 1) { 5115 ret = os_snprintf(pos, end - pos, 5116 "tbtt_offset=%u, ", *ie); 5117 if (os_snprintf_error(end - pos, ret)) 5118 return 0; 5119 5120 ie++; 5121 pos += ret; 5122 } 5123 5124 if (info->tbtt_info_len >= 7) { 5125 ret = os_snprintf(pos, end - pos, 5126 "bssid=" MACSTR ", ", 5127 MAC2STR(ie)); 5128 if (os_snprintf_error(end - pos, ret)) 5129 return 0; 5130 5131 ie += ETH_ALEN; 5132 pos += ret; 5133 } 5134 5135 if (info->tbtt_info_len >= 11) { 5136 ret = os_snprintf(pos, end - pos, 5137 "short SSID=0x%x, ", 5138 WPA_GET_LE32(ie)); 5139 if (os_snprintf_error(end - pos, ret)) 5140 return 0; 5141 5142 ie += 4; 5143 pos += ret; 5144 } 5145 5146 if (info->tbtt_info_len >= 12) { 5147 ret = os_snprintf(pos, end - pos, 5148 "bss_params=0x%x, ", *ie); 5149 if (os_snprintf_error(end - pos, ret)) 5150 return 0; 5151 5152 ie++; 5153 pos += ret; 5154 } 5155 5156 if (info->tbtt_info_len >= 13) { 5157 ret = os_snprintf(pos, end - pos, 5158 "PSD=0x%x, ", *ie); 5159 if (os_snprintf_error(end - pos, ret)) 5160 return 0; 5161 5162 ie++; 5163 pos += ret; 5164 } 5165 5166 if (info->tbtt_info_len >= 16) { 5167 ret = os_snprintf(pos, end - pos, 5168 "mld ID=%u, link ID=%u", 5169 *ie, *(ie + 1) & 0xF); 5170 if (os_snprintf_error(end - pos, ret)) 5171 return 0; 5172 5173 ie += 3; 5174 pos += ret; 5175 } 5176 5177 ie = tbtt_start + info->tbtt_info_len; 5178 5179 ret = os_snprintf(pos, end - pos, "\n"); 5180 if (os_snprintf_error(end - pos, ret)) 5181 return 0; 5182 pos += ret; 5183 5184 n++; 5185 } 5186 5187 return pos - start; 5188 } 5189 5190 5191 static int print_ml(struct wpa_bss *bss, char *pos, char *end) 5192 { 5193 const struct ieee80211_eht_ml *ml; 5194 char *start = pos; 5195 const u8 *ie, *ie_end; 5196 u16 ml_control; 5197 u8 common_info_length; 5198 int ret; 5199 5200 ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len, 5201 MULTI_LINK_CONTROL_TYPE_BASIC); 5202 if (!ie) 5203 return 0; 5204 5205 ie_end = ie + 2 + ie[1]; 5206 ie += 3; 5207 ml = (const struct ieee80211_eht_ml *) ie; 5208 5209 /* control + common info length + MLD MAC Address */ 5210 if (ie_end - ie < 2 + 1 + ETH_ALEN) 5211 return 0; 5212 5213 ml_control = le_to_host16(ml->ml_control); 5214 5215 common_info_length = *(ie + 2); 5216 ret = os_snprintf(pos, end - pos, 5217 "multi-link: control=0x%x, common info len=%u", 5218 ml_control, common_info_length); 5219 if (os_snprintf_error(end - pos, ret)) 5220 return 0; 5221 pos += ret; 5222 5223 ie += 2; 5224 if (ie_end - ie < common_info_length) 5225 return 0; 5226 5227 ie++; 5228 common_info_length--; 5229 5230 if (common_info_length < ETH_ALEN) 5231 return 0; 5232 5233 ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie)); 5234 if (os_snprintf_error(end - pos, ret)) 5235 return 0; 5236 pos += ret; 5237 5238 ie += ETH_ALEN; 5239 common_info_length -= ETH_ALEN; 5240 5241 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) { 5242 if (common_info_length < 1) 5243 return 0; 5244 5245 ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f); 5246 if (os_snprintf_error(end - pos, ret)) 5247 return 0; 5248 pos += ret; 5249 ie++; 5250 common_info_length--; 5251 } 5252 5253 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) { 5254 if (common_info_length < 1) 5255 return 0; 5256 5257 ret = os_snprintf(pos, end - pos, 5258 ", BSS change parameters=0x%x", *ie); 5259 if (os_snprintf_error(end - pos, ret)) 5260 return 0; 5261 pos += ret; 5262 ie++; 5263 common_info_length--; 5264 } 5265 5266 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) { 5267 if (common_info_length < 2) 5268 return 0; 5269 5270 ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x", 5271 WPA_GET_LE16(ie)); 5272 if (os_snprintf_error(end - pos, ret)) 5273 return 0; 5274 pos += ret; 5275 ie += 2; 5276 common_info_length -= 2; 5277 } 5278 5279 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) { 5280 if (common_info_length < 2) 5281 return 0; 5282 5283 ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x", 5284 WPA_GET_LE16(ie)); 5285 if (os_snprintf_error(end - pos, ret)) 5286 return 0; 5287 pos += ret; 5288 ie += 2; 5289 common_info_length -= 2; 5290 } 5291 5292 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) { 5293 if (common_info_length < 2) 5294 return 0; 5295 5296 ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x", 5297 WPA_GET_LE16(ie)); 5298 if (os_snprintf_error(end - pos, ret)) 5299 return 0; 5300 pos += ret; 5301 ie += 2; 5302 common_info_length -= 2; 5303 } 5304 5305 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) { 5306 if (common_info_length < 1) 5307 return 0; 5308 5309 ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie); 5310 if (os_snprintf_error(end - pos, ret)) 5311 return 0; 5312 pos += ret; 5313 ie += 1; 5314 common_info_length--; 5315 } 5316 5317 ret = os_snprintf(pos, end - pos, "\n"); 5318 if (os_snprintf_error(end - pos, ret)) 5319 return 0; 5320 pos += ret; 5321 5322 return pos - start; 5323 } 5324 5325 5326 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 5327 unsigned long mask, char *buf, size_t buflen) 5328 { 5329 size_t i; 5330 int ret; 5331 char *pos, *end; 5332 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe; 5333 5334 pos = buf; 5335 end = buf + buflen; 5336 5337 if (mask & WPA_BSS_MASK_ID) { 5338 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 5339 if (os_snprintf_error(end - pos, ret)) 5340 return 0; 5341 pos += ret; 5342 } 5343 5344 if (mask & WPA_BSS_MASK_BSSID) { 5345 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 5346 MAC2STR(bss->bssid)); 5347 if (os_snprintf_error(end - pos, ret)) 5348 return 0; 5349 pos += ret; 5350 } 5351 5352 if (mask & WPA_BSS_MASK_FREQ) { 5353 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 5354 if (os_snprintf_error(end - pos, ret)) 5355 return 0; 5356 pos += ret; 5357 } 5358 5359 if (mask & WPA_BSS_MASK_BEACON_INT) { 5360 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 5361 bss->beacon_int); 5362 if (os_snprintf_error(end - pos, ret)) 5363 return 0; 5364 pos += ret; 5365 } 5366 5367 if (mask & WPA_BSS_MASK_CAPABILITIES) { 5368 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 5369 bss->caps); 5370 if (os_snprintf_error(end - pos, ret)) 5371 return 0; 5372 pos += ret; 5373 } 5374 5375 if (mask & WPA_BSS_MASK_QUAL) { 5376 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 5377 if (os_snprintf_error(end - pos, ret)) 5378 return 0; 5379 pos += ret; 5380 } 5381 5382 if (mask & WPA_BSS_MASK_NOISE) { 5383 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 5384 if (os_snprintf_error(end - pos, ret)) 5385 return 0; 5386 pos += ret; 5387 } 5388 5389 if (mask & WPA_BSS_MASK_LEVEL) { 5390 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 5391 if (os_snprintf_error(end - pos, ret)) 5392 return 0; 5393 pos += ret; 5394 } 5395 5396 if (mask & WPA_BSS_MASK_TSF) { 5397 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 5398 (unsigned long long) bss->tsf); 5399 if (os_snprintf_error(end - pos, ret)) 5400 return 0; 5401 pos += ret; 5402 } 5403 5404 if (mask & WPA_BSS_MASK_AGE) { 5405 struct os_reltime now; 5406 5407 os_get_reltime(&now); 5408 ret = os_snprintf(pos, end - pos, "age=%d\n", 5409 (int) (now.sec - bss->last_update.sec)); 5410 if (os_snprintf_error(end - pos, ret)) 5411 return 0; 5412 pos += ret; 5413 } 5414 5415 if (mask & WPA_BSS_MASK_IE) { 5416 ret = os_snprintf(pos, end - pos, "ie="); 5417 if (os_snprintf_error(end - pos, ret)) 5418 return 0; 5419 pos += ret; 5420 5421 ie = wpa_bss_ie_ptr(bss); 5422 for (i = 0; i < bss->ie_len; i++) { 5423 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 5424 if (os_snprintf_error(end - pos, ret)) 5425 return 0; 5426 pos += ret; 5427 } 5428 5429 ret = os_snprintf(pos, end - pos, "\n"); 5430 if (os_snprintf_error(end - pos, ret)) 5431 return 0; 5432 pos += ret; 5433 } 5434 5435 if (mask & WPA_BSS_MASK_FLAGS) { 5436 ret = os_snprintf(pos, end - pos, "flags="); 5437 if (os_snprintf_error(end - pos, ret)) 5438 return 0; 5439 pos += ret; 5440 5441 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 5442 5443 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 5444 if (ie) 5445 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 5446 2 + ie[1]); 5447 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 5448 if (ie2) 5449 pos = wpa_supplicant_ie_txt(pos, end, 5450 mesh ? "RSN" : "WPA2", ie2, 5451 2 + ie2[1]); 5452 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); 5453 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) { 5454 ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); 5455 if (os_snprintf_error(end - pos, ret)) 5456 return 0; 5457 pos += ret; 5458 } 5459 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) { 5460 ret = os_snprintf(pos, end - pos, "[SAE-PK]"); 5461 if (os_snprintf_error(end - pos, ret)) 5462 return 0; 5463 pos += ret; 5464 } 5465 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 5466 if (osen_ie) 5467 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 5468 osen_ie, 2 + osen_ie[1]); 5469 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 5470 if (owe) { 5471 ret = os_snprintf( 5472 pos, end - pos, 5473 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 5474 if (os_snprintf_error(end - pos, ret)) 5475 return 0; 5476 pos += ret; 5477 } 5478 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 5479 if (!ie && !ie2 && !osen_ie && 5480 (bss->caps & IEEE80211_CAP_PRIVACY)) { 5481 ret = os_snprintf(pos, end - pos, "[WEP]"); 5482 if (os_snprintf_error(end - pos, ret)) 5483 return 0; 5484 pos += ret; 5485 } 5486 5487 if (mesh) { 5488 ret = os_snprintf(pos, end - pos, "[MESH]"); 5489 if (os_snprintf_error(end - pos, ret)) 5490 return 0; 5491 pos += ret; 5492 } 5493 5494 if (bss_is_dmg(bss)) { 5495 const char *s; 5496 ret = os_snprintf(pos, end - pos, "[DMG]"); 5497 if (os_snprintf_error(end - pos, ret)) 5498 return 0; 5499 pos += ret; 5500 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 5501 case IEEE80211_CAP_DMG_IBSS: 5502 s = "[IBSS]"; 5503 break; 5504 case IEEE80211_CAP_DMG_AP: 5505 s = "[ESS]"; 5506 break; 5507 case IEEE80211_CAP_DMG_PBSS: 5508 s = "[PBSS]"; 5509 break; 5510 default: 5511 s = ""; 5512 break; 5513 } 5514 ret = os_snprintf(pos, end - pos, "%s", s); 5515 if (os_snprintf_error(end - pos, ret)) 5516 return 0; 5517 pos += ret; 5518 } else { 5519 if (bss->caps & IEEE80211_CAP_IBSS) { 5520 ret = os_snprintf(pos, end - pos, "[IBSS]"); 5521 if (os_snprintf_error(end - pos, ret)) 5522 return 0; 5523 pos += ret; 5524 } 5525 if (bss->caps & IEEE80211_CAP_ESS) { 5526 ret = os_snprintf(pos, end - pos, "[ESS]"); 5527 if (os_snprintf_error(end - pos, ret)) 5528 return 0; 5529 pos += ret; 5530 } 5531 } 5532 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || 5533 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { 5534 ret = os_snprintf(pos, end - pos, "[P2P]"); 5535 if (os_snprintf_error(end - pos, ret)) 5536 return 0; 5537 pos += ret; 5538 } 5539 #ifdef CONFIG_HS20 5540 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 5541 ret = os_snprintf(pos, end - pos, "[HS20]"); 5542 if (os_snprintf_error(end - pos, ret)) 5543 return 0; 5544 pos += ret; 5545 } 5546 #endif /* CONFIG_HS20 */ 5547 #ifdef CONFIG_FILS 5548 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 5549 ret = os_snprintf(pos, end - pos, "[FILS]"); 5550 if (os_snprintf_error(end - pos, ret)) 5551 return 0; 5552 pos += ret; 5553 } 5554 #endif /* CONFIG_FILS */ 5555 #ifdef CONFIG_FST 5556 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 5557 ret = os_snprintf(pos, end - pos, "[FST]"); 5558 if (os_snprintf_error(end - pos, ret)) 5559 return 0; 5560 pos += ret; 5561 } 5562 #endif /* CONFIG_FST */ 5563 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 5564 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 5565 if (os_snprintf_error(end - pos, ret)) 5566 return 0; 5567 pos += ret; 5568 } 5569 5570 ret = os_snprintf(pos, end - pos, "\n"); 5571 if (os_snprintf_error(end - pos, ret)) 5572 return 0; 5573 pos += ret; 5574 } 5575 5576 if (mask & WPA_BSS_MASK_SSID) { 5577 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 5578 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 5579 if (os_snprintf_error(end - pos, ret)) 5580 return 0; 5581 pos += ret; 5582 } 5583 5584 #ifdef CONFIG_WPS 5585 if (mask & WPA_BSS_MASK_WPS_SCAN) { 5586 ie = wpa_bss_ie_ptr(bss); 5587 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 5588 if (ret >= end - pos) 5589 return 0; 5590 if (ret > 0) 5591 pos += ret; 5592 } 5593 #endif /* CONFIG_WPS */ 5594 5595 #ifdef CONFIG_P2P 5596 if (mask & WPA_BSS_MASK_P2P_SCAN) { 5597 ie = wpa_bss_ie_ptr(bss); 5598 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 5599 if (ret >= end - pos) 5600 return 0; 5601 if (ret > 0) 5602 pos += ret; 5603 } 5604 #endif /* CONFIG_P2P */ 5605 5606 #ifdef CONFIG_WIFI_DISPLAY 5607 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 5608 struct wpabuf *wfd; 5609 5610 ie = wpa_bss_ie_ptr(bss); 5611 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 5612 WFD_IE_VENDOR_TYPE); 5613 if (wfd) { 5614 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 5615 if (os_snprintf_error(end - pos, ret)) { 5616 wpabuf_free(wfd); 5617 return 0; 5618 } 5619 pos += ret; 5620 5621 pos += wpa_snprintf_hex(pos, end - pos, 5622 wpabuf_head(wfd), 5623 wpabuf_len(wfd)); 5624 wpabuf_free(wfd); 5625 5626 ret = os_snprintf(pos, end - pos, "\n"); 5627 if (os_snprintf_error(end - pos, ret)) 5628 return 0; 5629 pos += ret; 5630 } 5631 } 5632 #endif /* CONFIG_WIFI_DISPLAY */ 5633 5634 #ifdef CONFIG_INTERWORKING 5635 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 5636 struct wpa_bss_anqp *anqp = bss->anqp; 5637 struct wpa_bss_anqp_elem *elem; 5638 5639 pos = anqp_add_hex(pos, end, "anqp_capability_list", 5640 anqp->capability_list); 5641 pos = anqp_add_hex(pos, end, "anqp_venue_name", 5642 anqp->venue_name); 5643 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 5644 anqp->network_auth_type); 5645 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 5646 anqp->roaming_consortium); 5647 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 5648 anqp->ip_addr_type_availability); 5649 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 5650 anqp->nai_realm); 5651 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 5652 pos = anqp_add_hex(pos, end, "anqp_domain_name", 5653 anqp->domain_name); 5654 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info", 5655 anqp->fils_realm_info); 5656 #ifdef CONFIG_HS20 5657 pos = anqp_add_hex(pos, end, "hs20_capability_list", 5658 anqp->hs20_capability_list); 5659 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 5660 anqp->hs20_operator_friendly_name); 5661 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 5662 anqp->hs20_wan_metrics); 5663 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 5664 anqp->hs20_connection_capability); 5665 pos = anqp_add_hex(pos, end, "hs20_operating_class", 5666 anqp->hs20_operating_class); 5667 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", 5668 anqp->hs20_osu_providers_list); 5669 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", 5670 anqp->hs20_operator_icon_metadata); 5671 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", 5672 anqp->hs20_osu_providers_nai_list); 5673 #endif /* CONFIG_HS20 */ 5674 5675 dl_list_for_each(elem, &anqp->anqp_elems, 5676 struct wpa_bss_anqp_elem, list) { 5677 char title[20]; 5678 5679 os_snprintf(title, sizeof(title), "anqp[%u]", 5680 elem->infoid); 5681 pos = anqp_add_hex(pos, end, title, elem->payload); 5682 if (elem->protected_response) { 5683 ret = os_snprintf(pos, end - pos, 5684 "protected-anqp-info[%u]=1\n", 5685 elem->infoid); 5686 if (os_snprintf_error(end - pos, ret)) 5687 return 0; 5688 pos += ret; 5689 } 5690 } 5691 } 5692 #endif /* CONFIG_INTERWORKING */ 5693 5694 #ifdef CONFIG_MESH 5695 if (mask & WPA_BSS_MASK_MESH_SCAN) { 5696 ie = wpa_bss_ie_ptr(bss); 5697 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); 5698 if (ret >= end - pos) 5699 return 0; 5700 if (ret > 0) 5701 pos += ret; 5702 } 5703 #endif /* CONFIG_MESH */ 5704 5705 if (mask & WPA_BSS_MASK_SNR) { 5706 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr); 5707 if (os_snprintf_error(end - pos, ret)) 5708 return 0; 5709 pos += ret; 5710 } 5711 5712 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) { 5713 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n", 5714 bss->est_throughput); 5715 if (os_snprintf_error(end - pos, ret)) 5716 return 0; 5717 pos += ret; 5718 } 5719 5720 #ifdef CONFIG_FST 5721 if (mask & WPA_BSS_MASK_FST) { 5722 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos); 5723 if (ret < 0 || ret >= end - pos) 5724 return 0; 5725 pos += ret; 5726 } 5727 #endif /* CONFIG_FST */ 5728 5729 if (mask & WPA_BSS_MASK_UPDATE_IDX) { 5730 ret = os_snprintf(pos, end - pos, "update_idx=%u\n", 5731 bss->last_update_idx); 5732 if (os_snprintf_error(end - pos, ret)) 5733 return 0; 5734 pos += ret; 5735 } 5736 5737 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) { 5738 ret = os_snprintf(pos, end - pos, "beacon_ie="); 5739 if (os_snprintf_error(end - pos, ret)) 5740 return 0; 5741 pos += ret; 5742 5743 ie = wpa_bss_ie_ptr(bss); 5744 ie += bss->ie_len; 5745 for (i = 0; i < bss->beacon_ie_len; i++) { 5746 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 5747 if (os_snprintf_error(end - pos, ret)) 5748 return 0; 5749 pos += ret; 5750 } 5751 5752 ret = os_snprintf(pos, end - pos, "\n"); 5753 if (os_snprintf_error(end - pos, ret)) 5754 return 0; 5755 pos += ret; 5756 } 5757 5758 #ifdef CONFIG_FILS 5759 if (mask & WPA_BSS_MASK_FILS_INDICATION) { 5760 ret = print_fils_indication(bss, pos, end); 5761 pos += ret; 5762 } 5763 #endif /* CONFIG_FILS */ 5764 5765 if (!is_zero_ether_addr(bss->mld_addr) && 5766 (mask & WPA_BSS_MASK_AP_MLD_ADDR)) { 5767 ret = os_snprintf(pos, end - pos, 5768 "ap_mld_addr=" MACSTR "\n", 5769 MAC2STR(bss->mld_addr)); 5770 if (os_snprintf_error(end - pos, ret)) 5771 return 0; 5772 pos += ret; 5773 } 5774 5775 if (mask & WPA_BSS_MASK_RNR) 5776 pos += print_rnr(bss, pos, end); 5777 5778 if (mask & WPA_BSS_MASK_ML) 5779 pos += print_ml(bss, pos, end); 5780 5781 if (mask & WPA_BSS_MASK_DELIM) { 5782 ret = os_snprintf(pos, end - pos, "====\n"); 5783 if (os_snprintf_error(end - pos, ret)) 5784 return 0; 5785 pos += ret; 5786 } 5787 5788 return pos - buf; 5789 } 5790 5791 5792 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 5793 const char *cmd, char *buf, 5794 size_t buflen) 5795 { 5796 u8 bssid[ETH_ALEN]; 5797 size_t i; 5798 struct wpa_bss *bss; 5799 struct wpa_bss *bsslast = NULL; 5800 struct dl_list *next; 5801 int ret = 0; 5802 int len; 5803 char *ctmp, *end = buf + buflen; 5804 unsigned long mask = WPA_BSS_MASK_ALL; 5805 5806 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 5807 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 5808 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 5809 list_id); 5810 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 5811 list_id); 5812 } else { /* N1-N2 */ 5813 unsigned int id1, id2; 5814 5815 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 5816 wpa_printf(MSG_INFO, "Wrong BSS range " 5817 "format"); 5818 return 0; 5819 } 5820 5821 if (*(cmd + 6) == '-') 5822 id1 = 0; 5823 else 5824 id1 = atoi(cmd + 6); 5825 ctmp++; 5826 if (*ctmp >= '0' && *ctmp <= '9') 5827 id2 = atoi(ctmp); 5828 else 5829 id2 = (unsigned int) -1; 5830 bss = wpa_bss_get_id_range(wpa_s, id1, id2); 5831 if (id2 == (unsigned int) -1) 5832 bsslast = dl_list_last(&wpa_s->bss_id, 5833 struct wpa_bss, 5834 list_id); 5835 else { 5836 bsslast = wpa_bss_get_id(wpa_s, id2); 5837 if (bsslast == NULL && bss && id2 > id1) { 5838 struct wpa_bss *tmp = bss; 5839 for (;;) { 5840 next = tmp->list_id.next; 5841 if (next == &wpa_s->bss_id) 5842 break; 5843 tmp = dl_list_entry( 5844 next, struct wpa_bss, 5845 list_id); 5846 if (tmp->id > id2) 5847 break; 5848 bsslast = tmp; 5849 } 5850 } 5851 } 5852 } 5853 } else if (os_strncmp(cmd, "FIRST", 5) == 0) 5854 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 5855 else if (os_strncmp(cmd, "LAST", 4) == 0) 5856 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id); 5857 else if (os_strncmp(cmd, "ID-", 3) == 0) { 5858 i = atoi(cmd + 3); 5859 bss = wpa_bss_get_id(wpa_s, i); 5860 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 5861 i = atoi(cmd + 5); 5862 bss = wpa_bss_get_id(wpa_s, i); 5863 if (bss) { 5864 next = bss->list_id.next; 5865 if (next == &wpa_s->bss_id) 5866 bss = NULL; 5867 else 5868 bss = dl_list_entry(next, struct wpa_bss, 5869 list_id); 5870 } 5871 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) { 5872 bss = wpa_s->current_bss; 5873 #ifdef CONFIG_P2P 5874 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 5875 if (hwaddr_aton(cmd + 13, bssid) == 0) 5876 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 5877 else 5878 bss = NULL; 5879 #endif /* CONFIG_P2P */ 5880 } else if (hwaddr_aton(cmd, bssid) == 0) 5881 bss = wpa_bss_get_bssid(wpa_s, bssid); 5882 else { 5883 struct wpa_bss *tmp; 5884 i = atoi(cmd); 5885 bss = NULL; 5886 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 5887 { 5888 if (i == 0) { 5889 bss = tmp; 5890 break; 5891 } 5892 i--; 5893 } 5894 } 5895 5896 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 5897 mask = strtoul(ctmp + 5, NULL, 0x10); 5898 if (mask == 0) 5899 mask = WPA_BSS_MASK_ALL; 5900 } 5901 5902 if (bss == NULL) 5903 return 0; 5904 5905 if (bsslast == NULL) 5906 bsslast = bss; 5907 do { 5908 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 5909 ret += len; 5910 buf += len; 5911 buflen -= len; 5912 if (bss == bsslast) { 5913 if ((mask & WPA_BSS_MASK_DELIM) && len && 5914 (bss == dl_list_last(&wpa_s->bss_id, 5915 struct wpa_bss, list_id))) { 5916 int res; 5917 5918 res = os_snprintf(buf - 5, end - buf + 5, 5919 "####\n"); 5920 if (os_snprintf_error(end - buf + 5, res)) { 5921 wpa_printf(MSG_DEBUG, 5922 "Could not add end delim"); 5923 } 5924 } 5925 break; 5926 } 5927 next = bss->list_id.next; 5928 if (next == &wpa_s->bss_id) 5929 break; 5930 bss = dl_list_entry(next, struct wpa_bss, list_id); 5931 } while (bss && len); 5932 5933 return ret; 5934 } 5935 5936 5937 static int wpa_supplicant_ctrl_iface_ap_scan( 5938 struct wpa_supplicant *wpa_s, char *cmd) 5939 { 5940 int ap_scan = atoi(cmd); 5941 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 5942 } 5943 5944 5945 static int wpa_supplicant_ctrl_iface_scan_interval( 5946 struct wpa_supplicant *wpa_s, char *cmd) 5947 { 5948 int scan_int = atoi(cmd); 5949 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 5950 } 5951 5952 5953 static int wpa_supplicant_ctrl_iface_bss_expire_age( 5954 struct wpa_supplicant *wpa_s, char *cmd) 5955 { 5956 int expire_age = atoi(cmd); 5957 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 5958 } 5959 5960 5961 static int wpa_supplicant_ctrl_iface_bss_expire_count( 5962 struct wpa_supplicant *wpa_s, char *cmd) 5963 { 5964 int expire_count = atoi(cmd); 5965 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 5966 } 5967 5968 5969 static void wpa_supplicant_ctrl_iface_bss_flush( 5970 struct wpa_supplicant *wpa_s, char *cmd) 5971 { 5972 int flush_age = atoi(cmd); 5973 5974 if (flush_age == 0) 5975 wpa_bss_flush(wpa_s); 5976 else 5977 wpa_bss_flush_by_age(wpa_s, flush_age); 5978 } 5979 5980 5981 #ifdef CONFIG_TESTING_OPTIONS 5982 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 5983 { 5984 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 5985 /* MLME-DELETEKEYS.request */ 5986 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 5987 0, KEY_FLAG_GROUP); 5988 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 5989 0, KEY_FLAG_GROUP); 5990 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 5991 0, KEY_FLAG_GROUP); 5992 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 5993 0, KEY_FLAG_GROUP); 5994 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 5995 0, KEY_FLAG_GROUP); 5996 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 5997 0, KEY_FLAG_GROUP); 5998 5999 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, 6000 NULL, 0, KEY_FLAG_PAIRWISE); 6001 if (wpa_sm_ext_key_id(wpa_s->wpa)) 6002 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0, 6003 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); 6004 /* MLME-SETPROTECTION.request(None) */ 6005 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 6006 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 6007 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 6008 wpa_sm_drop_sa(wpa_s->wpa); 6009 } 6010 #endif /* CONFIG_TESTING_OPTIONS */ 6011 6012 6013 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 6014 char *addr) 6015 { 6016 #ifdef CONFIG_NO_SCAN_PROCESSING 6017 return -1; 6018 #else /* CONFIG_NO_SCAN_PROCESSING */ 6019 u8 bssid[ETH_ALEN]; 6020 struct wpa_bss *bss; 6021 struct wpa_ssid *ssid = wpa_s->current_ssid; 6022 struct wpa_radio_work *already_connecting; 6023 6024 if (hwaddr_aton(addr, bssid)) { 6025 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 6026 "address '%s'", addr); 6027 return -1; 6028 } 6029 6030 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 6031 6032 if (!ssid) { 6033 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 6034 "configuration known for the target AP"); 6035 return -1; 6036 } 6037 6038 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 6039 if (!bss) { 6040 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 6041 "from BSS table"); 6042 return -1; 6043 } 6044 6045 /* 6046 * TODO: Find best network configuration block from configuration to 6047 * allow roaming to other networks 6048 */ 6049 6050 already_connecting = radio_work_pending(wpa_s, "sme-connect"); 6051 wpa_s->reassociate = 1; 6052 wpa_supplicant_connect(wpa_s, bss, ssid); 6053 6054 /* 6055 * Indicate that an explicitly requested roam is in progress so scan 6056 * results that come in before the 'sme-connect' radio work gets 6057 * executed do not override the original connection attempt. 6058 */ 6059 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) 6060 wpa_s->roam_in_progress = true; 6061 6062 return 0; 6063 #endif /* CONFIG_NO_SCAN_PROCESSING */ 6064 } 6065 6066 6067 #ifdef CONFIG_P2P 6068 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 6069 { 6070 unsigned int timeout = atoi(cmd); 6071 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 6072 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 6073 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL; 6074 char *pos; 6075 unsigned int search_delay; 6076 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL; 6077 u8 seek_count = 0; 6078 int freq = 0; 6079 bool include_6ghz = false; 6080 6081 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6082 wpa_dbg(wpa_s, MSG_INFO, 6083 "Reject P2P_FIND since interface is disabled"); 6084 return -1; 6085 } 6086 6087 if (os_strstr(cmd, " include_6ghz")) 6088 include_6ghz = true; 6089 if (os_strstr(cmd, "type=social")) 6090 type = P2P_FIND_ONLY_SOCIAL; 6091 else if (os_strstr(cmd, "type=progressive")) 6092 type = P2P_FIND_PROGRESSIVE; 6093 6094 pos = os_strstr(cmd, "dev_id="); 6095 if (pos) { 6096 pos += 7; 6097 if (hwaddr_aton(pos, dev_id)) 6098 return -1; 6099 _dev_id = dev_id; 6100 } 6101 6102 pos = os_strstr(cmd, "dev_type="); 6103 if (pos) { 6104 pos += 9; 6105 if (wps_dev_type_str2bin(pos, dev_type) < 0) 6106 return -1; 6107 _dev_type = dev_type; 6108 } 6109 6110 pos = os_strstr(cmd, "delay="); 6111 if (pos) { 6112 pos += 6; 6113 search_delay = atoi(pos); 6114 } else 6115 search_delay = wpas_p2p_search_delay(wpa_s); 6116 6117 pos = os_strstr(cmd, "freq="); 6118 if (pos) { 6119 pos += 5; 6120 freq = atoi(pos); 6121 if (freq <= 0) 6122 return -1; 6123 } 6124 6125 /* Must be searched for last, because it adds nul termination */ 6126 pos = os_strstr(cmd, " seek="); 6127 if (pos) 6128 pos += 6; 6129 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) { 6130 char *term; 6131 6132 _seek[seek_count++] = pos; 6133 seek = _seek; 6134 term = os_strchr(pos, ' '); 6135 if (!term) 6136 break; 6137 *term = '\0'; 6138 pos = os_strstr(term + 1, "seek="); 6139 if (pos) 6140 pos += 5; 6141 } 6142 if (seek_count > P2P_MAX_QUERY_HASH) { 6143 seek[0] = NULL; 6144 seek_count = 1; 6145 } 6146 6147 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type, 6148 _dev_id, search_delay, seek_count, seek, freq, 6149 include_6ghz); 6150 } 6151 6152 6153 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt) 6154 { 6155 const char *last = NULL; 6156 const char *token; 6157 long int token_len; 6158 unsigned int i; 6159 6160 /* Expected predefined CPT names delimited by ':' */ 6161 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) { 6162 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) { 6163 wpa_printf(MSG_ERROR, 6164 "P2PS: CPT name list is too long, expected up to %d names", 6165 P2PS_FEATURE_CAPAB_CPT_MAX); 6166 cpt[0] = 0; 6167 return -1; 6168 } 6169 6170 token_len = last - token; 6171 6172 if (token_len == 3 && 6173 os_memcmp(token, "UDP", token_len) == 0) { 6174 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6175 } else if (token_len == 3 && 6176 os_memcmp(token, "MAC", token_len) == 0) { 6177 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT; 6178 } else { 6179 wpa_printf(MSG_ERROR, 6180 "P2PS: Unsupported CPT name '%s'", token); 6181 cpt[0] = 0; 6182 return -1; 6183 } 6184 6185 if (isblank((unsigned char) *last)) { 6186 i++; 6187 break; 6188 } 6189 } 6190 cpt[i] = 0; 6191 return 0; 6192 } 6193 6194 6195 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd) 6196 { 6197 struct p2ps_provision *p2ps_prov; 6198 char *pos; 6199 size_t info_len = 0; 6200 char *info = NULL; 6201 u8 role = P2PS_SETUP_NONE; 6202 long long unsigned val; 6203 int i; 6204 6205 pos = os_strstr(cmd, "info="); 6206 if (pos) { 6207 pos += 5; 6208 info_len = os_strlen(pos); 6209 6210 if (info_len) { 6211 info = os_malloc(info_len + 1); 6212 if (info) { 6213 info_len = utf8_unescape(pos, info_len, 6214 info, info_len + 1); 6215 } else 6216 info_len = 0; 6217 } 6218 } 6219 6220 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1); 6221 if (p2ps_prov == NULL) { 6222 os_free(info); 6223 return NULL; 6224 } 6225 6226 if (info) { 6227 os_memcpy(p2ps_prov->info, info, info_len); 6228 p2ps_prov->info[info_len] = '\0'; 6229 os_free(info); 6230 } 6231 6232 pos = os_strstr(cmd, "status="); 6233 if (pos) 6234 p2ps_prov->status = atoi(pos + 7); 6235 else 6236 p2ps_prov->status = -1; 6237 6238 pos = os_strstr(cmd, "adv_id="); 6239 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL) 6240 goto invalid_args; 6241 p2ps_prov->adv_id = val; 6242 6243 pos = os_strstr(cmd, "method="); 6244 if (pos) 6245 p2ps_prov->method = strtol(pos + 7, NULL, 16); 6246 else 6247 p2ps_prov->method = 0; 6248 6249 pos = os_strstr(cmd, "session="); 6250 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL) 6251 goto invalid_args; 6252 p2ps_prov->session_id = val; 6253 6254 pos = os_strstr(cmd, "adv_mac="); 6255 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac)) 6256 goto invalid_args; 6257 6258 pos = os_strstr(cmd, "session_mac="); 6259 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac)) 6260 goto invalid_args; 6261 6262 pos = os_strstr(cmd, "cpt="); 6263 if (pos) { 6264 if (p2ps_ctrl_parse_cpt_priority(pos + 4, 6265 p2ps_prov->cpt_priority)) 6266 goto invalid_args; 6267 } else { 6268 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6269 } 6270 6271 for (i = 0; p2ps_prov->cpt_priority[i]; i++) 6272 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i]; 6273 6274 /* force conncap with tstCap (no validity checks) */ 6275 pos = os_strstr(cmd, "tstCap="); 6276 if (pos) { 6277 role = strtol(pos + 7, NULL, 16); 6278 } else { 6279 pos = os_strstr(cmd, "role="); 6280 if (pos) { 6281 role = strtol(pos + 5, NULL, 16); 6282 if (role != P2PS_SETUP_CLIENT && 6283 role != P2PS_SETUP_GROUP_OWNER) 6284 role = P2PS_SETUP_NONE; 6285 } 6286 } 6287 p2ps_prov->role = role; 6288 6289 return p2ps_prov; 6290 6291 invalid_args: 6292 os_free(p2ps_prov); 6293 return NULL; 6294 } 6295 6296 6297 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd) 6298 { 6299 u8 addr[ETH_ALEN]; 6300 struct p2ps_provision *p2ps_prov; 6301 char *pos; 6302 6303 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */ 6304 6305 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 6306 6307 if (hwaddr_aton(cmd, addr)) 6308 return -1; 6309 6310 pos = cmd + 17; 6311 if (*pos != ' ') 6312 return -1; 6313 6314 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 6315 if (!p2ps_prov) 6316 return -1; 6317 6318 if (p2ps_prov->status < 0) { 6319 os_free(p2ps_prov); 6320 return -1; 6321 } 6322 6323 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 6324 p2ps_prov); 6325 } 6326 6327 6328 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd) 6329 { 6330 u8 addr[ETH_ALEN]; 6331 struct p2ps_provision *p2ps_prov; 6332 char *pos; 6333 6334 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap> 6335 * session=<ses_id> mac=<ses_mac> [info=<infodata>] 6336 */ 6337 6338 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 6339 if (hwaddr_aton(cmd, addr)) 6340 return -1; 6341 6342 pos = cmd + 17; 6343 if (*pos != ' ') 6344 return -1; 6345 6346 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 6347 if (!p2ps_prov) 6348 return -1; 6349 6350 p2ps_prov->pd_seeker = 1; 6351 6352 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 6353 p2ps_prov); 6354 } 6355 6356 6357 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 6358 char *buf, size_t buflen) 6359 { 6360 u8 addr[ETH_ALEN]; 6361 char *pos, *pos2; 6362 char *pin = NULL; 6363 enum p2p_wps_method wps_method; 6364 int new_pin; 6365 int ret; 6366 int persistent_group, persistent_id = -1; 6367 int join; 6368 int auth; 6369 int automatic; 6370 int go_intent = -1; 6371 int freq = 0; 6372 int pd; 6373 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; 6374 int edmg; 6375 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; 6376 size_t group_ssid_len = 0; 6377 int he; 6378 bool allow_6ghz; 6379 6380 if (!wpa_s->global->p2p_init_wpa_s) 6381 return -1; 6382 if (wpa_s->global->p2p_init_wpa_s != wpa_s) { 6383 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s", 6384 wpa_s->global->p2p_init_wpa_s->ifname); 6385 wpa_s = wpa_s->global->p2p_init_wpa_s; 6386 } 6387 6388 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] 6389 * [persistent|persistent=<network id>] 6390 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 6391 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */ 6392 6393 if (hwaddr_aton(cmd, addr)) 6394 return -1; 6395 6396 pos = cmd + 17; 6397 if (*pos != ' ') 6398 return -1; 6399 pos++; 6400 6401 persistent_group = os_strstr(pos, " persistent") != NULL; 6402 pos2 = os_strstr(pos, " persistent="); 6403 if (pos2) { 6404 struct wpa_ssid *ssid; 6405 persistent_id = atoi(pos2 + 12); 6406 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 6407 if (ssid == NULL || ssid->disabled != 2 || 6408 ssid->mode != WPAS_MODE_P2P_GO) { 6409 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 6410 "SSID id=%d for persistent P2P group (GO)", 6411 persistent_id); 6412 return -1; 6413 } 6414 } 6415 join = os_strstr(pos, " join") != NULL; 6416 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL; 6417 auth = os_strstr(pos, " auth") != NULL; 6418 automatic = os_strstr(pos, " auto") != NULL; 6419 pd = os_strstr(pos, " provdisc") != NULL; 6420 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 6421 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 6422 vht; 6423 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 6424 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; 6425 6426 pos2 = os_strstr(pos, " go_intent="); 6427 if (pos2) { 6428 pos2 += 11; 6429 go_intent = atoi(pos2); 6430 if (go_intent < 0 || go_intent > 15) 6431 return -1; 6432 } 6433 6434 pos2 = os_strstr(pos, " freq="); 6435 if (pos2) { 6436 pos2 += 6; 6437 freq = atoi(pos2); 6438 if (freq <= 0) 6439 return -1; 6440 } 6441 6442 pos2 = os_strstr(pos, " freq2="); 6443 if (pos2) 6444 freq2 = atoi(pos2 + 7); 6445 6446 pos2 = os_strstr(pos, " max_oper_chwidth="); 6447 if (pos2) 6448 chwidth = atoi(pos2 + 18); 6449 6450 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 6451 if (max_oper_chwidth < 0) 6452 return -1; 6453 6454 if (allow_6ghz && chwidth == 40) 6455 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 6456 6457 pos2 = os_strstr(pos, " ssid="); 6458 if (pos2) { 6459 char *end; 6460 6461 pos2 += 6; 6462 end = os_strchr(pos2, ' '); 6463 if (!end) 6464 group_ssid_len = os_strlen(pos2) / 2; 6465 else 6466 group_ssid_len = (end - pos2) / 2; 6467 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN || 6468 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0) 6469 return -1; 6470 group_ssid = _group_ssid; 6471 } 6472 6473 if (os_strncmp(pos, "pin", 3) == 0) { 6474 /* Request random PIN (to be displayed) and enable the PIN */ 6475 wps_method = WPS_PIN_DISPLAY; 6476 } else if (os_strncmp(pos, "pbc", 3) == 0) { 6477 wps_method = WPS_PBC; 6478 } else if (os_strstr(pos, "p2ps") != NULL) { 6479 wps_method = WPS_P2PS; 6480 } else { 6481 pin = pos; 6482 pos = os_strchr(pin, ' '); 6483 wps_method = WPS_PIN_KEYPAD; 6484 if (pos) { 6485 *pos++ = '\0'; 6486 if (os_strncmp(pos, "display", 7) == 0) 6487 wps_method = WPS_PIN_DISPLAY; 6488 } 6489 if (!wps_pin_str_valid(pin)) { 6490 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 6491 return 17; 6492 } 6493 } 6494 6495 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 6496 persistent_group, automatic, join, 6497 auth, go_intent, freq, freq2, persistent_id, 6498 pd, ht40, vht, max_oper_chwidth, he, edmg, 6499 group_ssid, group_ssid_len, allow_6ghz); 6500 if (new_pin == -2) { 6501 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 6502 return 25; 6503 } 6504 if (new_pin == -3) { 6505 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 6506 return 25; 6507 } 6508 if (new_pin < 0) 6509 return -1; 6510 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 6511 ret = os_snprintf(buf, buflen, "%08d", new_pin); 6512 if (os_snprintf_error(buflen, ret)) 6513 return -1; 6514 return ret; 6515 } 6516 6517 os_memcpy(buf, "OK\n", 3); 6518 return 3; 6519 } 6520 6521 6522 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 6523 { 6524 unsigned int timeout = atoi(cmd); 6525 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6526 wpa_dbg(wpa_s, MSG_INFO, 6527 "Reject P2P_LISTEN since interface is disabled"); 6528 return -1; 6529 } 6530 return wpas_p2p_listen(wpa_s, timeout); 6531 } 6532 6533 6534 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 6535 { 6536 u8 addr[ETH_ALEN]; 6537 char *pos; 6538 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 6539 6540 /* <addr> <config method> [join|auto] */ 6541 6542 if (hwaddr_aton(cmd, addr)) 6543 return -1; 6544 6545 pos = cmd + 17; 6546 if (*pos != ' ') 6547 return -1; 6548 pos++; 6549 6550 if (os_strstr(pos, " join") != NULL) 6551 use = WPAS_P2P_PD_FOR_JOIN; 6552 else if (os_strstr(pos, " auto") != NULL) 6553 use = WPAS_P2P_PD_AUTO; 6554 6555 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL); 6556 } 6557 6558 6559 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 6560 size_t buflen) 6561 { 6562 struct wpa_ssid *ssid = wpa_s->current_ssid; 6563 6564 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 6565 ssid->passphrase == NULL) 6566 return -1; 6567 6568 os_strlcpy(buf, ssid->passphrase, buflen); 6569 return os_strlen(buf); 6570 } 6571 6572 6573 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 6574 char *buf, size_t buflen) 6575 { 6576 u64 ref; 6577 int res; 6578 u8 dst_buf[ETH_ALEN], *dst; 6579 struct wpabuf *tlvs; 6580 char *pos; 6581 size_t len; 6582 6583 if (hwaddr_aton(cmd, dst_buf)) 6584 return -1; 6585 dst = dst_buf; 6586 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 6587 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 6588 dst = NULL; 6589 pos = cmd + 17; 6590 if (*pos != ' ') 6591 return -1; 6592 pos++; 6593 6594 if (os_strncmp(pos, "upnp ", 5) == 0) { 6595 u8 version; 6596 pos += 5; 6597 if (hexstr2bin(pos, &version, 1) < 0) 6598 return -1; 6599 pos += 2; 6600 if (*pos != ' ') 6601 return -1; 6602 pos++; 6603 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 6604 #ifdef CONFIG_WIFI_DISPLAY 6605 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 6606 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 6607 #endif /* CONFIG_WIFI_DISPLAY */ 6608 } else if (os_strncmp(pos, "asp ", 4) == 0) { 6609 char *svc_str; 6610 char *svc_info = NULL; 6611 u32 id; 6612 6613 pos += 4; 6614 if (sscanf(pos, "%x", &id) != 1 || id > 0xff) 6615 return -1; 6616 6617 pos = os_strchr(pos, ' '); 6618 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ') 6619 return -1; 6620 6621 svc_str = pos + 1; 6622 6623 pos = os_strchr(svc_str, ' '); 6624 6625 if (pos) 6626 *pos++ = '\0'; 6627 6628 /* All remaining data is the svc_info string */ 6629 if (pos && pos[0] && pos[0] != ' ') { 6630 len = os_strlen(pos); 6631 6632 /* Unescape in place */ 6633 len = utf8_unescape(pos, len, pos, len); 6634 if (len > 0xff) 6635 return -1; 6636 6637 svc_info = pos; 6638 } 6639 6640 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id, 6641 svc_str, svc_info); 6642 } else { 6643 len = os_strlen(pos); 6644 if (len & 1) 6645 return -1; 6646 len /= 2; 6647 tlvs = wpabuf_alloc(len); 6648 if (tlvs == NULL) 6649 return -1; 6650 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 6651 wpabuf_free(tlvs); 6652 return -1; 6653 } 6654 6655 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 6656 wpabuf_free(tlvs); 6657 } 6658 if (ref == 0) 6659 return -1; 6660 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 6661 if (os_snprintf_error(buflen, res)) 6662 return -1; 6663 return res; 6664 } 6665 6666 6667 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 6668 char *cmd) 6669 { 6670 long long unsigned val; 6671 u64 req; 6672 if (sscanf(cmd, "%llx", &val) != 1) 6673 return -1; 6674 req = val; 6675 return wpas_p2p_sd_cancel_request(wpa_s, req); 6676 } 6677 6678 6679 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 6680 { 6681 int freq; 6682 u8 dst[ETH_ALEN]; 6683 u8 dialog_token; 6684 struct wpabuf *resp_tlvs; 6685 char *pos, *pos2; 6686 size_t len; 6687 6688 pos = os_strchr(cmd, ' '); 6689 if (pos == NULL) 6690 return -1; 6691 *pos++ = '\0'; 6692 freq = atoi(cmd); 6693 if (freq == 0) 6694 return -1; 6695 6696 if (hwaddr_aton(pos, dst)) 6697 return -1; 6698 pos += 17; 6699 if (*pos != ' ') 6700 return -1; 6701 pos++; 6702 6703 pos2 = os_strchr(pos, ' '); 6704 if (pos2 == NULL) 6705 return -1; 6706 *pos2++ = '\0'; 6707 dialog_token = atoi(pos); 6708 6709 len = os_strlen(pos2); 6710 if (len & 1) 6711 return -1; 6712 len /= 2; 6713 resp_tlvs = wpabuf_alloc(len); 6714 if (resp_tlvs == NULL) 6715 return -1; 6716 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 6717 wpabuf_free(resp_tlvs); 6718 return -1; 6719 } 6720 6721 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 6722 wpabuf_free(resp_tlvs); 6723 return 0; 6724 } 6725 6726 6727 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 6728 char *cmd) 6729 { 6730 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 6731 return -1; 6732 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 6733 return 0; 6734 } 6735 6736 6737 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 6738 char *cmd) 6739 { 6740 char *pos; 6741 size_t len; 6742 struct wpabuf *query, *resp; 6743 int ret; 6744 6745 pos = os_strchr(cmd, ' '); 6746 if (pos == NULL) 6747 return -1; 6748 *pos++ = '\0'; 6749 6750 len = os_strlen(cmd); 6751 if (len & 1) 6752 return -1; 6753 len /= 2; 6754 query = wpabuf_alloc(len); 6755 if (query == NULL) 6756 return -1; 6757 ret = hexstr2bin(cmd, wpabuf_put(query, len), len); 6758 if (ret < 0) 6759 goto err_query; 6760 ret = -1; 6761 len = os_strlen(pos); 6762 if (len & 1) 6763 goto err_query; 6764 len /= 2; 6765 resp = wpabuf_alloc(len); 6766 if (!resp) 6767 goto err_query; 6768 ret = hexstr2bin(pos, wpabuf_put(resp, len), len); 6769 if (ret < 0) 6770 goto err_resp; 6771 6772 ret = wpas_p2p_service_add_bonjour(wpa_s, query, resp); 6773 6774 err_resp: 6775 wpabuf_free(resp); 6776 err_query: 6777 wpabuf_free(query); 6778 return ret; 6779 } 6780 6781 6782 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6783 { 6784 char *pos; 6785 u8 version; 6786 6787 pos = os_strchr(cmd, ' '); 6788 if (pos == NULL) 6789 return -1; 6790 *pos++ = '\0'; 6791 6792 if (hexstr2bin(cmd, &version, 1) < 0) 6793 return -1; 6794 6795 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 6796 } 6797 6798 6799 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s, 6800 u8 replace, char *cmd) 6801 { 6802 char *pos; 6803 char *adv_str; 6804 u32 auto_accept, adv_id, svc_state, config_methods; 6805 char *svc_info = NULL; 6806 char *cpt_prio_str; 6807 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1]; 6808 6809 pos = os_strchr(cmd, ' '); 6810 if (pos == NULL) 6811 return -1; 6812 *pos++ = '\0'; 6813 6814 /* Auto-Accept value is mandatory, and must be one of the 6815 * single values (0, 1, 2, 4) */ 6816 auto_accept = atoi(cmd); 6817 switch (auto_accept) { 6818 case P2PS_SETUP_NONE: /* No auto-accept */ 6819 case P2PS_SETUP_NEW: 6820 case P2PS_SETUP_CLIENT: 6821 case P2PS_SETUP_GROUP_OWNER: 6822 break; 6823 default: 6824 return -1; 6825 } 6826 6827 /* Advertisement ID is mandatory */ 6828 cmd = pos; 6829 pos = os_strchr(cmd, ' '); 6830 if (pos == NULL) 6831 return -1; 6832 *pos++ = '\0'; 6833 6834 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */ 6835 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0) 6836 return -1; 6837 6838 /* Only allow replacements if exist, and adds if not */ 6839 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) { 6840 if (!replace) 6841 return -1; 6842 } else { 6843 if (replace) 6844 return -1; 6845 } 6846 6847 /* svc_state between 0 - 0xff is mandatory */ 6848 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff) 6849 return -1; 6850 6851 pos = os_strchr(pos, ' '); 6852 if (pos == NULL) 6853 return -1; 6854 6855 /* config_methods is mandatory */ 6856 pos++; 6857 if (sscanf(pos, "%x", &config_methods) != 1) 6858 return -1; 6859 6860 if (!(config_methods & 6861 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS))) 6862 return -1; 6863 6864 pos = os_strchr(pos, ' '); 6865 if (pos == NULL) 6866 return -1; 6867 6868 pos++; 6869 adv_str = pos; 6870 6871 /* Advertisement string is mandatory */ 6872 if (!pos[0] || pos[0] == ' ') 6873 return -1; 6874 6875 /* Terminate svc string */ 6876 pos = os_strchr(pos, ' '); 6877 if (pos != NULL) 6878 *pos++ = '\0'; 6879 6880 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL; 6881 if (cpt_prio_str) { 6882 pos = os_strchr(pos, ' '); 6883 if (pos != NULL) 6884 *pos++ = '\0'; 6885 6886 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio)) 6887 return -1; 6888 } else { 6889 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6890 cpt_prio[1] = 0; 6891 } 6892 6893 /* Service and Response Information are optional */ 6894 if (pos && pos[0]) { 6895 size_t len; 6896 6897 /* Note the bare ' included, which cannot exist legally 6898 * in unescaped string. */ 6899 svc_info = os_strstr(pos, "svc_info='"); 6900 6901 if (svc_info) { 6902 svc_info += 9; 6903 len = os_strlen(svc_info); 6904 utf8_unescape(svc_info, len, svc_info, len); 6905 } 6906 } 6907 6908 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str, 6909 (u8) svc_state, (u16) config_methods, 6910 svc_info, cpt_prio); 6911 } 6912 6913 6914 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 6915 { 6916 char *pos; 6917 6918 pos = os_strchr(cmd, ' '); 6919 if (pos == NULL) 6920 return -1; 6921 *pos++ = '\0'; 6922 6923 if (os_strcmp(cmd, "bonjour") == 0) 6924 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 6925 if (os_strcmp(cmd, "upnp") == 0) 6926 return p2p_ctrl_service_add_upnp(wpa_s, pos); 6927 if (os_strcmp(cmd, "asp") == 0) 6928 return p2p_ctrl_service_add_asp(wpa_s, 0, pos); 6929 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6930 return -1; 6931 } 6932 6933 6934 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 6935 char *cmd) 6936 { 6937 size_t len; 6938 struct wpabuf *query; 6939 int ret; 6940 6941 len = os_strlen(cmd); 6942 if (len & 1) 6943 return -1; 6944 len /= 2; 6945 query = wpabuf_alloc(len); 6946 if (query == NULL) 6947 return -1; 6948 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 6949 wpabuf_free(query); 6950 return -1; 6951 } 6952 6953 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 6954 wpabuf_free(query); 6955 return ret; 6956 } 6957 6958 6959 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6960 { 6961 char *pos; 6962 u8 version; 6963 6964 pos = os_strchr(cmd, ' '); 6965 if (pos == NULL) 6966 return -1; 6967 *pos++ = '\0'; 6968 6969 if (hexstr2bin(cmd, &version, 1) < 0) 6970 return -1; 6971 6972 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 6973 } 6974 6975 6976 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd) 6977 { 6978 u32 adv_id; 6979 6980 if (os_strcmp(cmd, "all") == 0) { 6981 wpas_p2p_service_flush_asp(wpa_s); 6982 return 0; 6983 } 6984 6985 if (sscanf(cmd, "%x", &adv_id) != 1) 6986 return -1; 6987 6988 return wpas_p2p_service_del_asp(wpa_s, adv_id); 6989 } 6990 6991 6992 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 6993 { 6994 char *pos; 6995 6996 pos = os_strchr(cmd, ' '); 6997 if (pos == NULL) 6998 return -1; 6999 *pos++ = '\0'; 7000 7001 if (os_strcmp(cmd, "bonjour") == 0) 7002 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 7003 if (os_strcmp(cmd, "upnp") == 0) 7004 return p2p_ctrl_service_del_upnp(wpa_s, pos); 7005 if (os_strcmp(cmd, "asp") == 0) 7006 return p2p_ctrl_service_del_asp(wpa_s, pos); 7007 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 7008 return -1; 7009 } 7010 7011 7012 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd) 7013 { 7014 char *pos; 7015 7016 pos = os_strchr(cmd, ' '); 7017 if (pos == NULL) 7018 return -1; 7019 *pos++ = '\0'; 7020 7021 if (os_strcmp(cmd, "asp") == 0) 7022 return p2p_ctrl_service_add_asp(wpa_s, 1, pos); 7023 7024 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 7025 return -1; 7026 } 7027 7028 7029 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 7030 { 7031 u8 addr[ETH_ALEN]; 7032 7033 /* <addr> */ 7034 7035 if (hwaddr_aton(cmd, addr)) 7036 return -1; 7037 7038 return wpas_p2p_reject(wpa_s, addr); 7039 } 7040 7041 7042 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 7043 { 7044 char *pos; 7045 int id; 7046 struct wpa_ssid *ssid; 7047 u8 *_peer = NULL, peer[ETH_ALEN]; 7048 int freq = 0, pref_freq = 0; 7049 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; 7050 int edmg; 7051 bool allow_6ghz; 7052 7053 id = atoi(cmd); 7054 pos = os_strstr(cmd, " peer="); 7055 if (pos) { 7056 pos += 6; 7057 if (hwaddr_aton(pos, peer)) 7058 return -1; 7059 _peer = peer; 7060 } 7061 ssid = wpa_config_get_network(wpa_s->conf, id); 7062 if (ssid == NULL || ssid->disabled != 2) { 7063 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 7064 "for persistent P2P group", 7065 id); 7066 return -1; 7067 } 7068 7069 pos = os_strstr(cmd, " freq="); 7070 if (pos) { 7071 pos += 6; 7072 freq = atoi(pos); 7073 if (freq <= 0) 7074 return -1; 7075 } 7076 7077 pos = os_strstr(cmd, " pref="); 7078 if (pos) { 7079 pos += 6; 7080 pref_freq = atoi(pos); 7081 if (pref_freq <= 0) 7082 return -1; 7083 } 7084 7085 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 7086 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 7087 vht; 7088 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 7089 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; 7090 7091 pos = os_strstr(cmd, "freq2="); 7092 if (pos) 7093 freq2 = atoi(pos + 6); 7094 7095 pos = os_strstr(cmd, " max_oper_chwidth="); 7096 if (pos) 7097 chwidth = atoi(pos + 18); 7098 7099 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 7100 if (max_oper_chwidth < 0) 7101 return -1; 7102 7103 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL; 7104 7105 if (allow_6ghz && chwidth == 40) 7106 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 7107 7108 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, 7109 max_oper_chwidth, pref_freq, he, edmg, 7110 allow_6ghz); 7111 } 7112 7113 7114 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 7115 { 7116 char *pos; 7117 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 7118 bool allow_6ghz; 7119 7120 pos = os_strstr(cmd, " peer="); 7121 if (!pos) 7122 return -1; 7123 7124 *pos = '\0'; 7125 pos += 6; 7126 if (hwaddr_aton(pos, peer)) { 7127 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 7128 return -1; 7129 } 7130 7131 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL; 7132 7133 pos = os_strstr(pos, " go_dev_addr="); 7134 if (pos) { 7135 pos += 13; 7136 if (hwaddr_aton(pos, go_dev_addr)) { 7137 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 7138 pos); 7139 return -1; 7140 } 7141 go_dev = go_dev_addr; 7142 } 7143 7144 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz); 7145 } 7146 7147 7148 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 7149 { 7150 if (os_strncmp(cmd, "persistent=", 11) == 0) 7151 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 7152 if (os_strncmp(cmd, "group=", 6) == 0) 7153 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 7154 7155 return -1; 7156 } 7157 7158 7159 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 7160 int id, int freq, int vht_center_freq2, 7161 int ht40, int vht, int vht_chwidth, 7162 int he, int edmg, bool allow_6ghz, 7163 const u8 *go_bssid) 7164 { 7165 struct wpa_ssid *ssid; 7166 7167 ssid = wpa_config_get_network(wpa_s->conf, id); 7168 if (ssid == NULL || ssid->disabled != 2) { 7169 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 7170 "for persistent P2P group", 7171 id); 7172 return -1; 7173 } 7174 7175 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 7176 vht_center_freq2, ht40, vht, 7177 vht_chwidth, he, edmg, 7178 NULL, 0, 0, allow_6ghz, 0, 7179 go_bssid); 7180 } 7181 7182 7183 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 7184 { 7185 int freq = 0, persistent = 0, group_id = -1; 7186 bool allow_6ghz = false; 7187 int vht = wpa_s->conf->p2p_go_vht; 7188 int ht40 = wpa_s->conf->p2p_go_ht40 || vht; 7189 int he = wpa_s->conf->p2p_go_he; 7190 int edmg = wpa_s->conf->p2p_go_edmg; 7191 int max_oper_chwidth, chwidth = 0, freq2 = 0; 7192 char *token, *context = NULL; 7193 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL; 7194 #ifdef CONFIG_ACS 7195 int acs = 0; 7196 #endif /* CONFIG_ACS */ 7197 7198 while ((token = str_token(cmd, " ", &context))) { 7199 if (sscanf(token, "freq2=%d", &freq2) == 1 || 7200 sscanf(token, "persistent=%d", &group_id) == 1 || 7201 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) { 7202 continue; 7203 #ifdef CONFIG_ACS 7204 } else if (os_strcmp(token, "freq=acs") == 0) { 7205 acs = 1; 7206 #endif /* CONFIG_ACS */ 7207 } else if (sscanf(token, "freq=%d", &freq) == 1) { 7208 continue; 7209 } else if (os_strcmp(token, "ht40") == 0) { 7210 ht40 = 1; 7211 } else if (os_strcmp(token, "vht") == 0) { 7212 vht = 1; 7213 ht40 = 1; 7214 } else if (os_strcmp(token, "he") == 0) { 7215 he = 1; 7216 } else if (os_strcmp(token, "edmg") == 0) { 7217 edmg = 1; 7218 } else if (os_strcmp(token, "persistent") == 0) { 7219 persistent = 1; 7220 } else if (os_strcmp(token, "allow_6ghz") == 0) { 7221 allow_6ghz = true; 7222 } else if (os_strncmp(token, "go_bssid=", 9) == 0) { 7223 if (hwaddr_aton(token + 9, go_bssid_buf)) 7224 return -1; 7225 go_bssid = go_bssid_buf; 7226 } else { 7227 wpa_printf(MSG_DEBUG, 7228 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'", 7229 token); 7230 return -1; 7231 } 7232 } 7233 7234 #ifdef CONFIG_ACS 7235 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 7236 (acs || freq == 2 || freq == 5)) { 7237 if (freq == 2 && wpa_s->best_24_freq <= 0) { 7238 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G; 7239 wpa_s->p2p_go_do_acs = 1; 7240 freq = 0; 7241 } else if (freq == 5 && wpa_s->best_5_freq <= 0) { 7242 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A; 7243 wpa_s->p2p_go_do_acs = 1; 7244 freq = 0; 7245 } else { 7246 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY; 7247 wpa_s->p2p_go_do_acs = 1; 7248 } 7249 } else { 7250 wpa_s->p2p_go_do_acs = 0; 7251 } 7252 #endif /* CONFIG_ACS */ 7253 7254 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 7255 if (max_oper_chwidth < 0) 7256 return -1; 7257 7258 if (allow_6ghz && chwidth == 40) 7259 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 7260 7261 /* Allow DFS to be used for Autonomous GO */ 7262 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags & 7263 WPA_DRIVER_FLAGS_DFS_OFFLOAD); 7264 7265 if (group_id >= 0) 7266 return p2p_ctrl_group_add_persistent(wpa_s, group_id, 7267 freq, freq2, ht40, vht, 7268 max_oper_chwidth, he, 7269 edmg, allow_6ghz, 7270 go_bssid); 7271 7272 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, 7273 max_oper_chwidth, he, edmg, allow_6ghz); 7274 } 7275 7276 7277 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd, 7278 char *buf, size_t buflen) 7279 { 7280 u8 dev_addr[ETH_ALEN]; 7281 struct wpa_ssid *ssid; 7282 int res; 7283 const u8 *iaddr; 7284 7285 ssid = wpa_s->current_ssid; 7286 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO || 7287 hwaddr_aton(cmd, dev_addr)) 7288 return -1; 7289 7290 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr); 7291 if (!iaddr) 7292 return -1; 7293 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr)); 7294 if (os_snprintf_error(buflen, res)) 7295 return -1; 7296 return res; 7297 } 7298 7299 7300 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global, 7301 const u8 *p2p_dev_addr) 7302 { 7303 struct wpa_supplicant *wpa_s; 7304 7305 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 7306 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr)) 7307 return 1; 7308 } 7309 7310 return 0; 7311 } 7312 7313 7314 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 7315 char *buf, size_t buflen) 7316 { 7317 u8 addr[ETH_ALEN], *addr_ptr, group_capab; 7318 int next, res; 7319 const struct p2p_peer_info *info; 7320 char *pos, *end; 7321 char devtype[WPS_DEV_TYPE_BUFSIZE]; 7322 struct wpa_ssid *ssid; 7323 size_t i; 7324 7325 if (!wpa_s->global->p2p) 7326 return -1; 7327 7328 if (os_strcmp(cmd, "FIRST") == 0) { 7329 addr_ptr = NULL; 7330 next = 0; 7331 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 7332 if (hwaddr_aton(cmd + 5, addr) < 0) 7333 return -1; 7334 addr_ptr = addr; 7335 next = 1; 7336 } else { 7337 if (hwaddr_aton(cmd, addr) < 0) 7338 return -1; 7339 addr_ptr = addr; 7340 next = 0; 7341 } 7342 7343 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 7344 if (info == NULL) 7345 return -1; 7346 group_capab = info->group_capab; 7347 7348 if (group_capab && 7349 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) { 7350 wpa_printf(MSG_DEBUG, 7351 "P2P: Could not find any BSS with p2p_dev_addr " 7352 MACSTR ", hence override group_capab from 0x%x to 0", 7353 MAC2STR(info->p2p_device_addr), group_capab); 7354 group_capab = 0; 7355 } 7356 7357 pos = buf; 7358 end = buf + buflen; 7359 7360 res = os_snprintf(pos, end - pos, MACSTR "\n" 7361 "pri_dev_type=%s\n" 7362 "device_name=%s\n" 7363 "manufacturer=%s\n" 7364 "model_name=%s\n" 7365 "model_number=%s\n" 7366 "serial_number=%s\n" 7367 "config_methods=0x%x\n" 7368 "dev_capab=0x%x\n" 7369 "group_capab=0x%x\n" 7370 "level=%d\n", 7371 MAC2STR(info->p2p_device_addr), 7372 wps_dev_type_bin2str(info->pri_dev_type, 7373 devtype, sizeof(devtype)), 7374 info->device_name, 7375 info->manufacturer, 7376 info->model_name, 7377 info->model_number, 7378 info->serial_number, 7379 info->config_methods, 7380 info->dev_capab, 7381 group_capab, 7382 info->level); 7383 if (os_snprintf_error(end - pos, res)) 7384 return pos - buf; 7385 pos += res; 7386 7387 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 7388 { 7389 const u8 *t; 7390 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 7391 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 7392 wps_dev_type_bin2str(t, devtype, 7393 sizeof(devtype))); 7394 if (os_snprintf_error(end - pos, res)) 7395 return pos - buf; 7396 pos += res; 7397 } 7398 7399 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 7400 if (ssid) { 7401 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 7402 if (os_snprintf_error(end - pos, res)) 7403 return pos - buf; 7404 pos += res; 7405 } 7406 7407 res = p2p_get_peer_info_txt(info, pos, end - pos); 7408 if (res < 0) 7409 return pos - buf; 7410 pos += res; 7411 7412 if (info->vendor_elems) { 7413 res = os_snprintf(pos, end - pos, "vendor_elems="); 7414 if (os_snprintf_error(end - pos, res)) 7415 return pos - buf; 7416 pos += res; 7417 7418 pos += wpa_snprintf_hex(pos, end - pos, 7419 wpabuf_head(info->vendor_elems), 7420 wpabuf_len(info->vendor_elems)); 7421 7422 res = os_snprintf(pos, end - pos, "\n"); 7423 if (os_snprintf_error(end - pos, res)) 7424 return pos - buf; 7425 pos += res; 7426 } 7427 7428 return pos - buf; 7429 } 7430 7431 7432 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 7433 const char *param) 7434 { 7435 unsigned int i; 7436 7437 if (wpa_s->global->p2p == NULL) 7438 return -1; 7439 7440 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0) 7441 return -1; 7442 7443 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) { 7444 struct wpa_freq_range *freq; 7445 freq = &wpa_s->global->p2p_disallow_freq.range[i]; 7446 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 7447 freq->min, freq->max); 7448 } 7449 7450 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW); 7451 return 0; 7452 } 7453 7454 7455 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 7456 { 7457 char *param; 7458 7459 if (wpa_s->global->p2p == NULL) 7460 return -1; 7461 7462 param = os_strchr(cmd, ' '); 7463 if (param == NULL) 7464 return -1; 7465 *param++ = '\0'; 7466 7467 if (os_strcmp(cmd, "discoverability") == 0) { 7468 p2p_set_client_discoverability(wpa_s->global->p2p, 7469 atoi(param)); 7470 return 0; 7471 } 7472 7473 if (os_strcmp(cmd, "managed") == 0) { 7474 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 7475 return 0; 7476 } 7477 7478 if (os_strcmp(cmd, "listen_channel") == 0) { 7479 char *pos; 7480 u8 channel, op_class; 7481 7482 channel = atoi(param); 7483 pos = os_strchr(param, ' '); 7484 op_class = pos ? atoi(pos) : 81; 7485 7486 return p2p_set_listen_channel(wpa_s->global->p2p, op_class, 7487 channel, 1); 7488 } 7489 7490 if (os_strcmp(cmd, "ssid_postfix") == 0) { 7491 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 7492 os_strlen(param)); 7493 } 7494 7495 if (os_strcmp(cmd, "noa") == 0) { 7496 char *pos; 7497 int count, start, duration; 7498 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 7499 count = atoi(param); 7500 pos = os_strchr(param, ','); 7501 if (pos == NULL) 7502 return -1; 7503 pos++; 7504 start = atoi(pos); 7505 pos = os_strchr(pos, ','); 7506 if (pos == NULL) 7507 return -1; 7508 pos++; 7509 duration = atoi(pos); 7510 if (count < 0 || count > 255 || start < 0 || duration < 0) 7511 return -1; 7512 if (count == 0 && duration > 0) 7513 return -1; 7514 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 7515 "start=%d duration=%d", count, start, duration); 7516 return wpas_p2p_set_noa(wpa_s, count, start, duration); 7517 } 7518 7519 if (os_strcmp(cmd, "ps") == 0) 7520 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 7521 7522 if (os_strcmp(cmd, "oppps") == 0) 7523 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 7524 7525 if (os_strcmp(cmd, "ctwindow") == 0) 7526 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 7527 7528 if (os_strcmp(cmd, "disabled") == 0) { 7529 wpa_s->global->p2p_disabled = atoi(param); 7530 wpa_printf(MSG_DEBUG, "P2P functionality %s", 7531 wpa_s->global->p2p_disabled ? 7532 "disabled" : "enabled"); 7533 if (wpa_s->global->p2p_disabled) { 7534 wpas_p2p_stop_find(wpa_s); 7535 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 7536 p2p_flush(wpa_s->global->p2p); 7537 } 7538 return 0; 7539 } 7540 7541 if (os_strcmp(cmd, "conc_pref") == 0) { 7542 if (os_strcmp(param, "sta") == 0) 7543 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 7544 else if (os_strcmp(param, "p2p") == 0) 7545 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 7546 else { 7547 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 7548 return -1; 7549 } 7550 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 7551 "%s", param); 7552 return 0; 7553 } 7554 7555 if (os_strcmp(cmd, "force_long_sd") == 0) { 7556 wpa_s->force_long_sd = atoi(param); 7557 return 0; 7558 } 7559 7560 if (os_strcmp(cmd, "peer_filter") == 0) { 7561 u8 addr[ETH_ALEN]; 7562 if (hwaddr_aton(param, addr)) 7563 return -1; 7564 p2p_set_peer_filter(wpa_s->global->p2p, addr); 7565 return 0; 7566 } 7567 7568 if (os_strcmp(cmd, "cross_connect") == 0) 7569 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 7570 7571 if (os_strcmp(cmd, "go_apsd") == 0) { 7572 if (os_strcmp(param, "disable") == 0) 7573 wpa_s->set_ap_uapsd = 0; 7574 else { 7575 wpa_s->set_ap_uapsd = 1; 7576 wpa_s->ap_uapsd = atoi(param); 7577 } 7578 return 0; 7579 } 7580 7581 if (os_strcmp(cmd, "client_apsd") == 0) { 7582 if (os_strcmp(param, "disable") == 0) 7583 wpa_s->set_sta_uapsd = 0; 7584 else { 7585 int be, bk, vi, vo; 7586 char *pos; 7587 /* format: BE,BK,VI,VO;max SP Length */ 7588 be = atoi(param); 7589 pos = os_strchr(param, ','); 7590 if (pos == NULL) 7591 return -1; 7592 pos++; 7593 bk = atoi(pos); 7594 pos = os_strchr(pos, ','); 7595 if (pos == NULL) 7596 return -1; 7597 pos++; 7598 vi = atoi(pos); 7599 pos = os_strchr(pos, ','); 7600 if (pos == NULL) 7601 return -1; 7602 pos++; 7603 vo = atoi(pos); 7604 /* ignore max SP Length for now */ 7605 7606 wpa_s->set_sta_uapsd = 1; 7607 wpa_s->sta_uapsd = 0; 7608 if (be) 7609 wpa_s->sta_uapsd |= BIT(0); 7610 if (bk) 7611 wpa_s->sta_uapsd |= BIT(1); 7612 if (vi) 7613 wpa_s->sta_uapsd |= BIT(2); 7614 if (vo) 7615 wpa_s->sta_uapsd |= BIT(3); 7616 } 7617 return 0; 7618 } 7619 7620 if (os_strcmp(cmd, "disallow_freq") == 0) 7621 return p2p_ctrl_disallow_freq(wpa_s, param); 7622 7623 if (os_strcmp(cmd, "disc_int") == 0) { 7624 int min_disc_int, max_disc_int, max_disc_tu; 7625 char *pos; 7626 7627 pos = param; 7628 7629 min_disc_int = atoi(pos); 7630 pos = os_strchr(pos, ' '); 7631 if (pos == NULL) 7632 return -1; 7633 *pos++ = '\0'; 7634 7635 max_disc_int = atoi(pos); 7636 pos = os_strchr(pos, ' '); 7637 if (pos == NULL) 7638 return -1; 7639 *pos++ = '\0'; 7640 7641 max_disc_tu = atoi(pos); 7642 7643 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 7644 max_disc_int, max_disc_tu); 7645 } 7646 7647 if (os_strcmp(cmd, "per_sta_psk") == 0) { 7648 wpa_s->global->p2p_per_sta_psk = !!atoi(param); 7649 return 0; 7650 } 7651 7652 #ifdef CONFIG_WPS_NFC 7653 if (os_strcmp(cmd, "nfc_tag") == 0) 7654 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param)); 7655 #endif /* CONFIG_WPS_NFC */ 7656 7657 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) { 7658 wpa_s->p2p_disable_ip_addr_req = !!atoi(param); 7659 return 0; 7660 } 7661 7662 if (os_strcmp(cmd, "override_pref_op_chan") == 0) { 7663 int op_class, chan; 7664 7665 op_class = atoi(param); 7666 param = os_strchr(param, ':'); 7667 if (!param) 7668 return -1; 7669 param++; 7670 chan = atoi(param); 7671 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class, 7672 chan); 7673 return 0; 7674 } 7675 7676 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 7677 cmd); 7678 7679 return -1; 7680 } 7681 7682 7683 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) 7684 { 7685 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 7686 wpa_s->force_long_sd = 0; 7687 7688 #ifdef CONFIG_TESTING_OPTIONS 7689 os_free(wpa_s->get_pref_freq_list_override); 7690 wpa_s->get_pref_freq_list_override = NULL; 7691 #endif /* CONFIG_TESTING_OPTIONS */ 7692 7693 wpas_p2p_stop_find(wpa_s); 7694 wpa_s->parent->p2ps_method_config_any = 0; 7695 if (wpa_s->global->p2p) 7696 p2p_flush(wpa_s->global->p2p); 7697 } 7698 7699 7700 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 7701 { 7702 char *pos, *pos2; 7703 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 7704 7705 if (cmd[0]) { 7706 pos = os_strchr(cmd, ' '); 7707 if (pos == NULL) 7708 return -1; 7709 *pos++ = '\0'; 7710 dur1 = atoi(cmd); 7711 7712 pos2 = os_strchr(pos, ' '); 7713 if (pos2) 7714 *pos2++ = '\0'; 7715 int1 = atoi(pos); 7716 } else 7717 pos2 = NULL; 7718 7719 if (pos2) { 7720 pos = os_strchr(pos2, ' '); 7721 if (pos == NULL) 7722 return -1; 7723 *pos++ = '\0'; 7724 dur2 = atoi(pos2); 7725 int2 = atoi(pos); 7726 } 7727 7728 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 7729 } 7730 7731 7732 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 7733 { 7734 char *pos; 7735 unsigned int period = 0, interval = 0; 7736 7737 if (cmd[0]) { 7738 pos = os_strchr(cmd, ' '); 7739 if (pos == NULL) 7740 return -1; 7741 *pos++ = '\0'; 7742 period = atoi(cmd); 7743 interval = atoi(pos); 7744 } 7745 7746 return wpas_p2p_ext_listen(wpa_s, period, interval); 7747 } 7748 7749 7750 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) 7751 { 7752 const char *pos; 7753 u8 peer[ETH_ALEN]; 7754 int iface_addr = 0; 7755 7756 pos = cmd; 7757 if (os_strncmp(pos, "iface=", 6) == 0) { 7758 iface_addr = 1; 7759 pos += 6; 7760 } 7761 if (hwaddr_aton(pos, peer)) 7762 return -1; 7763 7764 wpas_p2p_remove_client(wpa_s, peer, iface_addr); 7765 return 0; 7766 } 7767 7768 7769 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd) 7770 { 7771 int freq = 0, period = 0, interval = 0, count = 0; 7772 7773 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4) 7774 { 7775 wpa_printf(MSG_DEBUG, 7776 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd); 7777 return -1; 7778 } 7779 7780 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count); 7781 } 7782 7783 #endif /* CONFIG_P2P */ 7784 7785 7786 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val) 7787 { 7788 struct wpa_freq_range_list ranges; 7789 int *freqs = NULL; 7790 struct hostapd_hw_modes *mode; 7791 u16 i; 7792 7793 if (wpa_s->hw.modes == NULL) 7794 return NULL; 7795 7796 os_memset(&ranges, 0, sizeof(ranges)); 7797 if (freq_range_list_parse(&ranges, val) < 0) 7798 return NULL; 7799 7800 for (i = 0; i < wpa_s->hw.num_modes; i++) { 7801 int j; 7802 7803 mode = &wpa_s->hw.modes[i]; 7804 for (j = 0; j < mode->num_channels; j++) { 7805 unsigned int freq; 7806 7807 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED) 7808 continue; 7809 7810 freq = mode->channels[j].freq; 7811 if (!freq_range_list_includes(&ranges, freq)) 7812 continue; 7813 7814 int_array_add_unique(&freqs, freq); 7815 } 7816 } 7817 7818 os_free(ranges.range); 7819 return freqs; 7820 } 7821 7822 7823 #ifdef CONFIG_INTERWORKING 7824 7825 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) 7826 { 7827 int auto_sel = 0; 7828 int *freqs = NULL; 7829 7830 if (param) { 7831 char *pos; 7832 7833 auto_sel = os_strstr(param, "auto") != NULL; 7834 7835 pos = os_strstr(param, "freq="); 7836 if (pos) { 7837 freqs = freq_range_to_channel_list(wpa_s, pos + 5); 7838 if (freqs == NULL) 7839 return -1; 7840 } 7841 7842 } 7843 7844 return interworking_select(wpa_s, auto_sel, freqs); 7845 } 7846 7847 7848 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, 7849 int only_add) 7850 { 7851 u8 bssid[ETH_ALEN]; 7852 struct wpa_bss *bss; 7853 7854 if (hwaddr_aton(dst, bssid)) { 7855 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 7856 return -1; 7857 } 7858 7859 bss = wpa_bss_get_bssid_latest(wpa_s, bssid); 7860 if (bss == NULL) { 7861 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 7862 MAC2STR(bssid)); 7863 return -1; 7864 } 7865 7866 if (bss->ssid_len == 0) { 7867 int found = 0; 7868 7869 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR 7870 " does not have SSID information", MAC2STR(bssid)); 7871 7872 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, 7873 list) { 7874 if (ether_addr_equal(bss->bssid, bssid) && 7875 bss->ssid_len > 0) { 7876 found = 1; 7877 break; 7878 } 7879 } 7880 7881 if (!found) 7882 return -1; 7883 wpa_printf(MSG_DEBUG, 7884 "Found another matching BSS entry with SSID"); 7885 } 7886 7887 return interworking_connect(wpa_s, bss, only_add); 7888 } 7889 7890 7891 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 7892 { 7893 u8 dst_addr[ETH_ALEN]; 7894 int used, freq = 0; 7895 char *pos; 7896 #define MAX_ANQP_INFO_ID 100 7897 u16 id[MAX_ANQP_INFO_ID]; 7898 size_t num_id = 0; 7899 u32 subtypes = 0; 7900 u32 mbo_subtypes = 0; 7901 7902 used = hwaddr_aton2(dst, dst_addr); 7903 if (used < 0) 7904 return -1; 7905 pos = dst + used; 7906 if (*pos == ' ') 7907 pos++; 7908 7909 if (os_strncmp(pos, "freq=", 5) == 0) { 7910 freq = atoi(pos + 5); 7911 pos = os_strchr(pos, ' '); 7912 if (!pos) 7913 return -1; 7914 pos++; 7915 } 7916 7917 while (num_id < MAX_ANQP_INFO_ID) { 7918 if (os_strncmp(pos, "hs20:", 5) == 0) { 7919 #ifdef CONFIG_HS20 7920 int num = atoi(pos + 5); 7921 if (num <= 0 || num > 31) 7922 return -1; 7923 subtypes |= BIT(num); 7924 #else /* CONFIG_HS20 */ 7925 return -1; 7926 #endif /* CONFIG_HS20 */ 7927 } else if (os_strncmp(pos, "mbo:", 4) == 0) { 7928 #ifdef CONFIG_MBO 7929 int num = atoi(pos + 4); 7930 7931 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) 7932 return -1; 7933 mbo_subtypes |= BIT(num); 7934 #else /* CONFIG_MBO */ 7935 return -1; 7936 #endif /* CONFIG_MBO */ 7937 } else { 7938 id[num_id] = atoi(pos); 7939 if (id[num_id]) 7940 num_id++; 7941 } 7942 pos = os_strchr(pos + 1, ','); 7943 if (pos == NULL) 7944 break; 7945 pos++; 7946 } 7947 7948 if (num_id == 0 && !subtypes && !mbo_subtypes) 7949 return -1; 7950 7951 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes, 7952 mbo_subtypes); 7953 } 7954 7955 7956 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 7957 { 7958 u8 dst_addr[ETH_ALEN]; 7959 struct wpabuf *advproto, *query = NULL; 7960 int used, ret = -1; 7961 char *pos, *end; 7962 size_t len; 7963 7964 used = hwaddr_aton2(cmd, dst_addr); 7965 if (used < 0) 7966 return -1; 7967 7968 pos = cmd + used; 7969 while (*pos == ' ') 7970 pos++; 7971 7972 /* Advertisement Protocol ID */ 7973 end = os_strchr(pos, ' '); 7974 if (end) 7975 len = end - pos; 7976 else 7977 len = os_strlen(pos); 7978 if (len & 0x01) 7979 return -1; 7980 len /= 2; 7981 if (len == 0) 7982 return -1; 7983 advproto = wpabuf_alloc(len); 7984 if (advproto == NULL) 7985 return -1; 7986 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 7987 goto fail; 7988 7989 if (end) { 7990 /* Optional Query Request */ 7991 pos = end + 1; 7992 while (*pos == ' ') 7993 pos++; 7994 7995 len = os_strlen(pos); 7996 if (len) { 7997 if (len & 0x01) 7998 goto fail; 7999 len /= 2; 8000 if (len == 0) 8001 goto fail; 8002 query = wpabuf_alloc(len); 8003 if (query == NULL) 8004 goto fail; 8005 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 8006 goto fail; 8007 } 8008 } 8009 8010 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 8011 8012 fail: 8013 wpabuf_free(advproto); 8014 wpabuf_free(query); 8015 8016 return ret; 8017 } 8018 8019 8020 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 8021 size_t buflen) 8022 { 8023 u8 addr[ETH_ALEN]; 8024 int dialog_token; 8025 int used; 8026 char *pos; 8027 size_t resp_len, start, requested_len; 8028 struct wpabuf *resp; 8029 int ret; 8030 8031 used = hwaddr_aton2(cmd, addr); 8032 if (used < 0) 8033 return -1; 8034 8035 pos = cmd + used; 8036 while (*pos == ' ') 8037 pos++; 8038 dialog_token = atoi(pos); 8039 8040 if (wpa_s->last_gas_resp && 8041 ether_addr_equal(addr, wpa_s->last_gas_addr) && 8042 dialog_token == wpa_s->last_gas_dialog_token) 8043 resp = wpa_s->last_gas_resp; 8044 else if (wpa_s->prev_gas_resp && 8045 ether_addr_equal(addr, wpa_s->prev_gas_addr) && 8046 dialog_token == wpa_s->prev_gas_dialog_token) 8047 resp = wpa_s->prev_gas_resp; 8048 else 8049 return -1; 8050 8051 resp_len = wpabuf_len(resp); 8052 start = 0; 8053 requested_len = resp_len; 8054 8055 pos = os_strchr(pos, ' '); 8056 if (pos) { 8057 start = atoi(pos); 8058 if (start > resp_len) 8059 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 8060 pos = os_strchr(pos, ','); 8061 if (pos == NULL) 8062 return -1; 8063 pos++; 8064 requested_len = atoi(pos); 8065 if (start + requested_len > resp_len) 8066 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 8067 } 8068 8069 if (requested_len * 2 + 1 > buflen) 8070 return os_snprintf(buf, buflen, "FAIL-Too long response"); 8071 8072 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start, 8073 requested_len); 8074 8075 if (start + requested_len == resp_len) { 8076 /* 8077 * Free memory by dropping the response after it has been 8078 * fetched. 8079 */ 8080 if (resp == wpa_s->prev_gas_resp) { 8081 wpabuf_free(wpa_s->prev_gas_resp); 8082 wpa_s->prev_gas_resp = NULL; 8083 } else { 8084 wpabuf_free(wpa_s->last_gas_resp); 8085 wpa_s->last_gas_resp = NULL; 8086 } 8087 } 8088 8089 return ret; 8090 } 8091 #endif /* CONFIG_INTERWORKING */ 8092 8093 8094 #ifdef CONFIG_HS20 8095 8096 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 8097 { 8098 u8 dst_addr[ETH_ALEN]; 8099 int used; 8100 char *pos; 8101 u32 subtypes = 0; 8102 8103 used = hwaddr_aton2(dst, dst_addr); 8104 if (used < 0) 8105 return -1; 8106 pos = dst + used; 8107 if (*pos == ' ') 8108 pos++; 8109 for (;;) { 8110 int num = atoi(pos); 8111 if (num <= 0 || num > 31) 8112 return -1; 8113 subtypes |= BIT(num); 8114 pos = os_strchr(pos + 1, ','); 8115 if (pos == NULL) 8116 break; 8117 pos++; 8118 } 8119 8120 if (subtypes == 0) 8121 return -1; 8122 8123 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0); 8124 } 8125 8126 8127 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 8128 const u8 *addr, const char *realm) 8129 { 8130 u8 *buf; 8131 size_t rlen, len; 8132 int ret; 8133 8134 rlen = os_strlen(realm); 8135 len = 3 + rlen; 8136 buf = os_malloc(len); 8137 if (buf == NULL) 8138 return -1; 8139 buf[0] = 1; /* NAI Home Realm Count */ 8140 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 8141 buf[2] = rlen; 8142 os_memcpy(buf + 3, realm, rlen); 8143 8144 ret = hs20_anqp_send_req(wpa_s, addr, 8145 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 8146 buf, len, 0); 8147 8148 os_free(buf); 8149 8150 return ret; 8151 } 8152 8153 8154 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 8155 char *dst) 8156 { 8157 struct wpa_cred *cred = wpa_s->conf->cred; 8158 u8 dst_addr[ETH_ALEN]; 8159 int used; 8160 u8 *buf; 8161 size_t len; 8162 int ret; 8163 8164 used = hwaddr_aton2(dst, dst_addr); 8165 if (used < 0) 8166 return -1; 8167 8168 while (dst[used] == ' ') 8169 used++; 8170 if (os_strncmp(dst + used, "realm=", 6) == 0) 8171 return hs20_nai_home_realm_list(wpa_s, dst_addr, 8172 dst + used + 6); 8173 8174 len = os_strlen(dst + used); 8175 8176 if (len == 0 && cred && cred->realm) 8177 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 8178 8179 if (len & 1) 8180 return -1; 8181 len /= 2; 8182 buf = os_malloc(len); 8183 if (buf == NULL) 8184 return -1; 8185 if (hexstr2bin(dst + used, buf, len) < 0) { 8186 os_free(buf); 8187 return -1; 8188 } 8189 8190 ret = hs20_anqp_send_req(wpa_s, dst_addr, 8191 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 8192 buf, len, 0); 8193 os_free(buf); 8194 8195 return ret; 8196 } 8197 8198 8199 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply, 8200 int buflen) 8201 { 8202 u8 dst_addr[ETH_ALEN]; 8203 int used; 8204 char *ctx = NULL, *icon, *poffset, *psize; 8205 8206 used = hwaddr_aton2(cmd, dst_addr); 8207 if (used < 0) 8208 return -1; 8209 cmd += used; 8210 8211 icon = str_token(cmd, " ", &ctx); 8212 poffset = str_token(cmd, " ", &ctx); 8213 psize = str_token(cmd, " ", &ctx); 8214 if (!icon || !poffset || !psize) 8215 return -1; 8216 8217 wpa_s->fetch_osu_icon_in_progress = 0; 8218 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize), 8219 reply, buflen); 8220 } 8221 8222 8223 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd) 8224 { 8225 u8 dst_addr[ETH_ALEN]; 8226 int used; 8227 char *icon; 8228 8229 if (!cmd[0]) 8230 return hs20_del_icon(wpa_s, NULL, NULL); 8231 8232 used = hwaddr_aton2(cmd, dst_addr); 8233 if (used < 0) 8234 return -1; 8235 8236 while (cmd[used] == ' ') 8237 used++; 8238 icon = cmd[used] ? &cmd[used] : NULL; 8239 8240 return hs20_del_icon(wpa_s, dst_addr, icon); 8241 } 8242 8243 8244 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem) 8245 { 8246 u8 dst_addr[ETH_ALEN]; 8247 int used; 8248 char *icon; 8249 8250 used = hwaddr_aton2(cmd, dst_addr); 8251 if (used < 0) 8252 return -1; 8253 8254 while (cmd[used] == ' ') 8255 used++; 8256 icon = &cmd[used]; 8257 8258 wpa_s->fetch_osu_icon_in_progress = 0; 8259 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST), 8260 (u8 *) icon, os_strlen(icon), inmem); 8261 } 8262 8263 #endif /* CONFIG_HS20 */ 8264 8265 8266 #ifdef CONFIG_AUTOSCAN 8267 8268 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 8269 char *cmd) 8270 { 8271 enum wpa_states state = wpa_s->wpa_state; 8272 char *new_params = NULL; 8273 8274 if (os_strlen(cmd) > 0) { 8275 new_params = os_strdup(cmd); 8276 if (new_params == NULL) 8277 return -1; 8278 } 8279 8280 os_free(wpa_s->conf->autoscan); 8281 wpa_s->conf->autoscan = new_params; 8282 8283 if (wpa_s->conf->autoscan == NULL) 8284 autoscan_deinit(wpa_s); 8285 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 8286 autoscan_init(wpa_s, 1); 8287 else if (state == WPA_SCANNING) 8288 wpa_supplicant_reinit_autoscan(wpa_s); 8289 else 8290 wpa_printf(MSG_DEBUG, "No autoscan update in state %s", 8291 wpa_supplicant_state_txt(state)); 8292 8293 return 0; 8294 } 8295 8296 #endif /* CONFIG_AUTOSCAN */ 8297 8298 8299 #ifdef CONFIG_WNM 8300 8301 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 8302 { 8303 int enter; 8304 int intval = 0; 8305 char *pos; 8306 int ret; 8307 struct wpabuf *tfs_req = NULL; 8308 8309 if (os_strncmp(cmd, "enter", 5) == 0) 8310 enter = 1; 8311 else if (os_strncmp(cmd, "exit", 4) == 0) 8312 enter = 0; 8313 else 8314 return -1; 8315 8316 pos = os_strstr(cmd, " interval="); 8317 if (pos) 8318 intval = atoi(pos + 10); 8319 8320 pos = os_strstr(cmd, " tfs_req="); 8321 if (pos) { 8322 char *end; 8323 size_t len; 8324 pos += 9; 8325 end = os_strchr(pos, ' '); 8326 if (end) 8327 len = end - pos; 8328 else 8329 len = os_strlen(pos); 8330 if (len & 1) 8331 return -1; 8332 len /= 2; 8333 tfs_req = wpabuf_alloc(len); 8334 if (tfs_req == NULL) 8335 return -1; 8336 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 8337 wpabuf_free(tfs_req); 8338 return -1; 8339 } 8340 } 8341 8342 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 8343 WNM_SLEEP_MODE_EXIT, intval, 8344 tfs_req); 8345 wpabuf_free(tfs_req); 8346 8347 return ret; 8348 } 8349 8350 8351 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) 8352 { 8353 int query_reason, list = 0; 8354 char *btm_candidates = NULL; 8355 8356 query_reason = atoi(cmd); 8357 8358 cmd = os_strchr(cmd, ' '); 8359 if (cmd) { 8360 if (os_strncmp(cmd, " list", 5) == 0) 8361 list = 1; 8362 else 8363 btm_candidates = cmd; 8364 } 8365 8366 wpa_printf(MSG_DEBUG, 8367 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s", 8368 query_reason, list ? " candidate list" : ""); 8369 8370 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, 8371 btm_candidates, 8372 list); 8373 } 8374 8375 8376 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s, 8377 char *cmd) 8378 { 8379 struct wpabuf *elems; 8380 int ret; 8381 8382 elems = wpabuf_parse_bin(cmd); 8383 if (!elems) 8384 return -1; 8385 8386 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems); 8387 wpabuf_free(elems); 8388 return ret; 8389 } 8390 8391 #endif /* CONFIG_WNM */ 8392 8393 8394 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 8395 size_t buflen) 8396 { 8397 struct wpa_signal_info si; 8398 int ret; 8399 char *pos, *end; 8400 8401 ret = wpa_drv_signal_poll(wpa_s, &si); 8402 if (ret) 8403 return -1; 8404 8405 pos = buf; 8406 end = buf + buflen; 8407 8408 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n" 8409 "NOISE=%d\nFREQUENCY=%u\n", 8410 si.data.signal, si.data.current_tx_rate / 1000, 8411 si.current_noise, si.frequency); 8412 if (os_snprintf_error(end - pos, ret)) 8413 return -1; 8414 pos += ret; 8415 8416 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) { 8417 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 8418 channel_width_to_string(si.chanwidth)); 8419 if (os_snprintf_error(end - pos, ret)) 8420 return -1; 8421 pos += ret; 8422 } 8423 8424 if (si.center_frq1 > 0) { 8425 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 8426 si.center_frq1); 8427 if (os_snprintf_error(end - pos, ret)) 8428 return -1; 8429 pos += ret; 8430 } 8431 8432 if (si.center_frq2 > 0) { 8433 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 8434 si.center_frq2); 8435 if (os_snprintf_error(end - pos, ret)) 8436 return -1; 8437 pos += ret; 8438 } 8439 8440 if (si.data.avg_signal) { 8441 ret = os_snprintf(pos, end - pos, 8442 "AVG_RSSI=%d\n", si.data.avg_signal); 8443 if (os_snprintf_error(end - pos, ret)) 8444 return -1; 8445 pos += ret; 8446 } 8447 8448 if (si.data.avg_beacon_signal) { 8449 ret = os_snprintf(pos, end - pos, 8450 "AVG_BEACON_RSSI=%d\n", 8451 si.data.avg_beacon_signal); 8452 if (os_snprintf_error(end - pos, ret)) 8453 return -1; 8454 pos += ret; 8455 } 8456 8457 return pos - buf; 8458 } 8459 8460 8461 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s, 8462 const char *cmd) 8463 { 8464 const char *pos; 8465 int threshold = 0; 8466 int hysteresis = 0; 8467 8468 if (wpa_s->bgscan && wpa_s->bgscan_priv) { 8469 wpa_printf(MSG_DEBUG, 8470 "Reject SIGNAL_MONITOR command - bgscan is active"); 8471 return -1; 8472 } 8473 pos = os_strstr(cmd, "THRESHOLD="); 8474 if (pos) 8475 threshold = atoi(pos + 10); 8476 pos = os_strstr(cmd, "HYSTERESIS="); 8477 if (pos) 8478 hysteresis = atoi(pos + 11); 8479 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis); 8480 } 8481 8482 8483 #ifdef CONFIG_TESTING_OPTIONS 8484 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, 8485 enum wpa_driver_if_type if_type, 8486 unsigned int *num, 8487 struct weighted_pcl *freq_list) 8488 { 8489 char *pos = wpa_s->get_pref_freq_list_override; 8490 char *end; 8491 unsigned int count = 0; 8492 8493 /* Override string format: 8494 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */ 8495 8496 while (pos) { 8497 if (atoi(pos) == (int) if_type) 8498 break; 8499 pos = os_strchr(pos, ' '); 8500 if (pos) 8501 pos++; 8502 } 8503 if (!pos) 8504 return -1; 8505 pos = os_strchr(pos, ':'); 8506 if (!pos) 8507 return -1; 8508 pos++; 8509 end = os_strchr(pos, ' '); 8510 while (pos && (!end || pos < end) && count < *num) { 8511 freq_list[count].freq = atoi(pos); 8512 freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI; 8513 pos = os_strchr(pos, ','); 8514 if (pos) 8515 pos++; 8516 } 8517 8518 *num = count; 8519 return 0; 8520 } 8521 #endif /* CONFIG_TESTING_OPTIONS */ 8522 8523 8524 static int wpas_ctrl_iface_get_pref_freq_list( 8525 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 8526 { 8527 unsigned int num = 100, i; 8528 int ret; 8529 enum wpa_driver_if_type iface_type; 8530 char *pos, *end; 8531 struct weighted_pcl freq_list[100]; 8532 8533 pos = buf; 8534 end = buf + buflen; 8535 8536 /* buf: "<interface_type>" */ 8537 if (os_strcmp(cmd, "STATION") == 0) 8538 iface_type = WPA_IF_STATION; 8539 else if (os_strcmp(cmd, "AP") == 0) 8540 iface_type = WPA_IF_AP_BSS; 8541 else if (os_strcmp(cmd, "P2P_GO") == 0) 8542 iface_type = WPA_IF_P2P_GO; 8543 else if (os_strcmp(cmd, "P2P_CLIENT") == 0) 8544 iface_type = WPA_IF_P2P_CLIENT; 8545 else if (os_strcmp(cmd, "IBSS") == 0) 8546 iface_type = WPA_IF_IBSS; 8547 else if (os_strcmp(cmd, "TDLS") == 0) 8548 iface_type = WPA_IF_TDLS; 8549 else 8550 return -1; 8551 8552 wpa_printf(MSG_DEBUG, 8553 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", 8554 iface_type, cmd); 8555 8556 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); 8557 if (ret) 8558 return -1; 8559 8560 for (i = 0; i < num; i++) { 8561 ret = os_snprintf(pos, end - pos, "%s%u", 8562 i > 0 ? "," : "", freq_list[i].freq); 8563 if (os_snprintf_error(end - pos, ret)) 8564 return -1; 8565 pos += ret; 8566 } 8567 8568 return pos - buf; 8569 } 8570 8571 8572 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, 8573 char *buf, size_t buflen) 8574 { 8575 int ret, i; 8576 char *pos, *end; 8577 8578 ret = os_snprintf(buf, buflen, "%016llX:\n", 8579 (long long unsigned) wpa_s->drv_flags); 8580 if (os_snprintf_error(buflen, ret)) 8581 return -1; 8582 8583 pos = buf + ret; 8584 end = buf + buflen; 8585 8586 for (i = 0; i < 64; i++) { 8587 if (wpa_s->drv_flags & (1LLU << i)) { 8588 ret = os_snprintf(pos, end - pos, "%s\n", 8589 driver_flag_to_string(1LLU << i)); 8590 if (os_snprintf_error(end - pos, ret)) 8591 return -1; 8592 pos += ret; 8593 } 8594 } 8595 8596 return pos - buf; 8597 } 8598 8599 8600 static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s, 8601 char *buf, size_t buflen) 8602 { 8603 int ret, i; 8604 char *pos, *end; 8605 8606 ret = os_snprintf(buf, buflen, "%016llX:\n", 8607 (long long unsigned) wpa_s->drv_flags2); 8608 if (os_snprintf_error(buflen, ret)) 8609 return -1; 8610 8611 pos = buf + ret; 8612 end = buf + buflen; 8613 8614 for (i = 0; i < 64; i++) { 8615 if (wpa_s->drv_flags2 & (1LLU << i)) { 8616 ret = os_snprintf(pos, end - pos, "%s\n", 8617 driver_flag2_to_string(1LLU << i)); 8618 if (os_snprintf_error(end - pos, ret)) 8619 return -1; 8620 pos += ret; 8621 } 8622 } 8623 8624 return pos - buf; 8625 } 8626 8627 8628 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 8629 size_t buflen) 8630 { 8631 struct hostap_sta_driver_data sta; 8632 int ret; 8633 8634 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 8635 if (ret) 8636 return -1; 8637 8638 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 8639 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 8640 if (os_snprintf_error(buflen, ret)) 8641 return -1; 8642 return ret; 8643 } 8644 8645 8646 #ifdef ANDROID 8647 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 8648 char *buf, size_t buflen) 8649 { 8650 int ret; 8651 8652 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 8653 if (ret == 0) { 8654 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { 8655 struct p2p_data *p2p = wpa_s->global->p2p; 8656 if (p2p) { 8657 char country[3]; 8658 country[0] = cmd[8]; 8659 country[1] = cmd[9]; 8660 country[2] = 0x04; 8661 p2p_set_country(p2p, country); 8662 } 8663 } 8664 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 8665 if (os_snprintf_error(buflen, ret)) 8666 ret = -1; 8667 } 8668 return ret; 8669 } 8670 #endif /* ANDROID */ 8671 8672 8673 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, 8674 char *buf, size_t buflen) 8675 { 8676 int ret; 8677 char *pos, *temp = NULL; 8678 u8 *data = NULL; 8679 unsigned int vendor_id, subcmd; 8680 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; 8681 struct wpabuf *reply; 8682 size_t data_len = 0; 8683 8684 /** 8685 * cmd: <vendor id> <subcommand id> [<hex formatted data>] 8686 * [nested=<0|1>] 8687 */ 8688 vendor_id = strtoul(cmd, &pos, 16); 8689 if (!isblank((unsigned char) *pos)) 8690 return -EINVAL; 8691 8692 subcmd = strtoul(pos, &pos, 10); 8693 8694 if (*pos != '\0') { 8695 if (!isblank((unsigned char) *pos++)) 8696 return -EINVAL; 8697 8698 temp = os_strchr(pos, ' '); 8699 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); 8700 } 8701 8702 if (data_len) { 8703 data_len /= 2; 8704 data = os_malloc(data_len); 8705 if (!data) 8706 return -1; 8707 8708 if (hexstr2bin(pos, data, data_len)) { 8709 wpa_printf(MSG_DEBUG, 8710 "Vendor command: wrong parameter format"); 8711 os_free(data); 8712 return -EINVAL; 8713 } 8714 } 8715 8716 pos = os_strstr(cmd, "nested="); 8717 if (pos) 8718 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : 8719 NESTED_ATTR_NOT_USED; 8720 8721 reply = wpabuf_alloc((buflen - 1) / 2); 8722 if (!reply) { 8723 os_free(data); 8724 return -1; 8725 } 8726 8727 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, 8728 nested_attr_flag, reply); 8729 8730 if (ret == 0) 8731 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 8732 wpabuf_len(reply)); 8733 8734 wpabuf_free(reply); 8735 os_free(data); 8736 8737 return ret; 8738 } 8739 8740 8741 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) 8742 { 8743 #ifdef CONFIG_P2P 8744 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ? 8745 wpa_s->global->p2p_init_wpa_s : wpa_s; 8746 #endif /* CONFIG_P2P */ 8747 8748 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); 8749 8750 if (wpas_abort_ongoing_scan(wpa_s) == 0) 8751 wpa_s->ignore_post_flush_scan_res = 1; 8752 8753 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 8754 /* 8755 * Avoid possible auto connect re-connection on getting 8756 * disconnected due to state flush. 8757 */ 8758 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 8759 } 8760 8761 #ifdef CONFIG_P2P 8762 wpas_p2p_group_remove(p2p_wpa_s, "*"); 8763 wpas_p2p_cancel(p2p_wpa_s); 8764 p2p_ctrl_flush(p2p_wpa_s); 8765 wpas_p2p_service_flush(p2p_wpa_s); 8766 p2p_wpa_s->global->p2p_disabled = 0; 8767 p2p_wpa_s->global->p2p_per_sta_psk = 0; 8768 p2p_wpa_s->conf->num_sec_device_types = 0; 8769 p2p_wpa_s->p2p_disable_ip_addr_req = 0; 8770 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range); 8771 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL; 8772 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0; 8773 p2p_wpa_s->global->pending_p2ps_group = 0; 8774 p2p_wpa_s->global->pending_p2ps_group_freq = 0; 8775 #endif /* CONFIG_P2P */ 8776 8777 #ifdef CONFIG_WPS_TESTING 8778 wps_version_number = 0x20; 8779 wps_testing_stub_cred = 0; 8780 wps_corrupt_pkhash = 0; 8781 wps_force_auth_types_in_use = 0; 8782 wps_force_encr_types_in_use = 0; 8783 #endif /* CONFIG_WPS_TESTING */ 8784 #ifdef CONFIG_WPS 8785 wpa_s->wps_fragment_size = 0; 8786 wpas_wps_cancel(wpa_s); 8787 wps_registrar_flush(wpa_s->wps->registrar); 8788 #endif /* CONFIG_WPS */ 8789 wpa_s->after_wps = 0; 8790 wpa_s->known_wps_freq = 0; 8791 8792 #ifdef CONFIG_DPP 8793 wpas_dpp_deinit(wpa_s); 8794 wpa_s->dpp_init_max_tries = 0; 8795 wpa_s->dpp_init_retry_time = 0; 8796 wpa_s->dpp_resp_wait_time = 0; 8797 wpa_s->dpp_resp_max_tries = 0; 8798 wpa_s->dpp_resp_retry_time = 0; 8799 #ifdef CONFIG_DPP2 8800 wpas_dpp_chirp_stop(wpa_s); 8801 wpa_s->dpp_pfs_fallback = 0; 8802 #endif /* CONFIG_DPP2 */ 8803 #ifdef CONFIG_DPP3 8804 { 8805 int i; 8806 8807 for (i = 0; i < DPP_PB_INFO_COUNT; i++) { 8808 struct dpp_pb_info *info; 8809 8810 info = &wpa_s->dpp_pb[i]; 8811 info->rx_time.sec = 0; 8812 info->rx_time.usec = 0; 8813 } 8814 } 8815 #endif /* CONFIG_DPP3 */ 8816 #ifdef CONFIG_TESTING_OPTIONS 8817 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); 8818 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); 8819 dpp_pkex_ephemeral_key_override_len = 0; 8820 dpp_protocol_key_override_len = 0; 8821 dpp_nonce_override_len = 0; 8822 #ifdef CONFIG_DPP3 8823 dpp_version_override = 3; 8824 #elif defined(CONFIG_DPP2) 8825 dpp_version_override = 2; 8826 #else /* CONFIG_DPP2 */ 8827 dpp_version_override = 1; 8828 #endif /* CONFIG_DPP2 */ 8829 #endif /* CONFIG_TESTING_OPTIONS */ 8830 #endif /* CONFIG_DPP */ 8831 8832 #ifdef CONFIG_TDLS 8833 #ifdef CONFIG_TDLS_TESTING 8834 tdls_testing = 0; 8835 #endif /* CONFIG_TDLS_TESTING */ 8836 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL); 8837 wpa_tdls_enable(wpa_s->wpa, 1); 8838 #endif /* CONFIG_TDLS */ 8839 8840 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 8841 wpa_supplicant_stop_countermeasures(wpa_s, NULL); 8842 wpa_s->last_michael_mic_error.sec = 0; 8843 8844 wpa_s->no_keep_alive = 0; 8845 wpa_s->own_disconnect_req = 0; 8846 wpa_s->own_reconnect_req = 0; 8847 wpa_s->deny_ptk0_rekey = 0; 8848 8849 os_free(wpa_s->disallow_aps_bssid); 8850 wpa_s->disallow_aps_bssid = NULL; 8851 wpa_s->disallow_aps_bssid_count = 0; 8852 os_free(wpa_s->disallow_aps_ssid); 8853 wpa_s->disallow_aps_ssid = NULL; 8854 wpa_s->disallow_aps_ssid_count = 0; 8855 8856 wpa_s->set_sta_uapsd = 0; 8857 wpa_s->sta_uapsd = 0; 8858 8859 wpa_s->consecutive_conn_failures = 0; 8860 8861 wpa_drv_radio_disable(wpa_s, 0); 8862 wpa_bssid_ignore_clear(wpa_s); 8863 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); 8864 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); 8865 wpa_config_flush_blobs(wpa_s->conf); 8866 wpa_s->conf->auto_interworking = 0; 8867 wpa_s->conf->okc = 0; 8868 8869 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE); 8870 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 8871 rsn_preauth_deinit(wpa_s->wpa); 8872 8873 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); 8874 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); 8875 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); 8876 eapol_sm_notify_logoff(wpa_s->eapol, false); 8877 8878 radio_remove_works(wpa_s, NULL, 1); 8879 wpa_s->ext_work_in_progress = 0; 8880 8881 wpa_s->next_ssid = NULL; 8882 8883 wnm_btm_reset(wpa_s); 8884 8885 #ifdef CONFIG_INTERWORKING 8886 #ifdef CONFIG_HS20 8887 hs20_cancel_fetch_osu(wpa_s); 8888 hs20_del_icon(wpa_s, NULL, NULL); 8889 #endif /* CONFIG_HS20 */ 8890 #endif /* CONFIG_INTERWORKING */ 8891 8892 wpa_s->ext_mgmt_frame_handling = 0; 8893 wpa_s->ext_eapol_frame_io = 0; 8894 #ifdef CONFIG_TESTING_OPTIONS 8895 wpa_s->extra_roc_dur = 0; 8896 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE; 8897 wpa_s->p2p_go_csa_on_inv = 0; 8898 wpa_s->ignore_auth_resp = 0; 8899 wpa_s->ignore_assoc_disallow = 0; 8900 wpa_s->disable_sa_query = 0; 8901 wpa_s->testing_resend_assoc = 0; 8902 wpa_s->ignore_sae_h2e_only = 0; 8903 wpa_s->ft_rsnxe_used = 0; 8904 wpa_s->reject_btm_req_reason = 0; 8905 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); 8906 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL); 8907 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL); 8908 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0); 8909 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0); 8910 os_free(wpa_s->get_pref_freq_list_override); 8911 wpa_s->get_pref_freq_list_override = NULL; 8912 wpabuf_free(wpa_s->sae_commit_override); 8913 wpa_s->sae_commit_override = NULL; 8914 os_free(wpa_s->extra_sae_rejected_groups); 8915 wpa_s->extra_sae_rejected_groups = NULL; 8916 wpabuf_free(wpa_s->rsne_override_eapol); 8917 wpa_s->rsne_override_eapol = NULL; 8918 wpabuf_free(wpa_s->rsnxe_override_assoc); 8919 wpa_s->rsnxe_override_assoc = NULL; 8920 wpabuf_free(wpa_s->rsnxe_override_eapol); 8921 wpa_s->rsnxe_override_eapol = NULL; 8922 wpas_clear_driver_signal_override(wpa_s); 8923 #ifndef CONFIG_NO_ROBUST_AV 8924 wpa_s->disable_scs_support = 0; 8925 wpa_s->disable_mscs_support = 0; 8926 wpa_s->enable_dscp_policy_capa = 0; 8927 #endif /* CONFIG_NO_ROBUST_AV */ 8928 wpa_s->oci_freq_override_eapol = 0; 8929 wpa_s->oci_freq_override_saquery_req = 0; 8930 wpa_s->oci_freq_override_saquery_resp = 0; 8931 wpa_s->oci_freq_override_eapol_g2 = 0; 8932 wpa_s->oci_freq_override_ft_assoc = 0; 8933 wpa_s->oci_freq_override_fils_assoc = 0; 8934 wpa_s->oci_freq_override_wnm_sleep = 0; 8935 wpa_s->disable_eapol_g2_tx = 0; 8936 wpa_s->test_assoc_comeback_type = -1; 8937 #ifdef CONFIG_DPP 8938 os_free(wpa_s->dpp_config_obj_override); 8939 wpa_s->dpp_config_obj_override = NULL; 8940 os_free(wpa_s->dpp_discovery_override); 8941 wpa_s->dpp_discovery_override = NULL; 8942 os_free(wpa_s->dpp_groups_override); 8943 wpa_s->dpp_groups_override = NULL; 8944 wpa_s->dpp_ignore_netaccesskey_mismatch = 0; 8945 wpa_s->dpp_discard_public_action = 0; 8946 dpp_test = DPP_TEST_DISABLED; 8947 #endif /* CONFIG_DPP */ 8948 #endif /* CONFIG_TESTING_OPTIONS */ 8949 8950 wpa_s->disconnected = 0; 8951 os_free(wpa_s->next_scan_freqs); 8952 wpa_s->next_scan_freqs = NULL; 8953 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); 8954 wpa_s->next_scan_bssid_wildcard_ssid = 0; 8955 os_free(wpa_s->select_network_scan_freqs); 8956 wpa_s->select_network_scan_freqs = NULL; 8957 #ifndef CONFIG_NO_ROBUST_AV 8958 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); 8959 #endif /* CONFIG_NO_ROBUST_AV */ 8960 8961 wpa_bss_flush(wpa_s); 8962 if (!dl_list_empty(&wpa_s->bss)) { 8963 wpa_printf(MSG_DEBUG, 8964 "BSS table not empty after flush: %u entries, current_bss=%p bssid=" 8965 MACSTR " pending_bssid=" MACSTR, 8966 dl_list_len(&wpa_s->bss), wpa_s->current_bss, 8967 MAC2STR(wpa_s->bssid), 8968 MAC2STR(wpa_s->pending_bssid)); 8969 } 8970 8971 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); 8972 wpa_s->wnmsleep_used = 0; 8973 8974 #ifdef CONFIG_SME 8975 wpa_s->sme.last_unprot_disconnect.sec = 0; 8976 wpa_s->sme.auth_alg = 0; 8977 #endif /* CONFIG_SME */ 8978 8979 wpabuf_free(wpa_s->ric_ies); 8980 wpa_s->ric_ies = NULL; 8981 8982 wpa_supplicant_update_channel_list(wpa_s, NULL); 8983 8984 free_bss_tmp_disallowed(wpa_s); 8985 8986 #ifndef CONFIG_NO_ROBUST_AV 8987 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); 8988 #endif /* CONFIG_NO_ROBUST_AV */ 8989 8990 #ifdef CONFIG_PASN 8991 wpas_pasn_auth_stop(wpa_s); 8992 #endif /* CONFIG_PASN */ 8993 8994 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0) 8995 wpas_restore_permanent_mac_addr(wpa_s); 8996 8997 wpa_s->conf->ignore_old_scan_res = 0; 8998 8999 #ifdef CONFIG_NAN_USD 9000 wpas_nan_usd_flush(wpa_s); 9001 #endif /* CONFIG_NAN_USD */ 9002 } 9003 9004 9005 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, 9006 char *buf, size_t buflen) 9007 { 9008 struct wpa_radio_work *work; 9009 char *pos, *end; 9010 struct os_reltime now, diff; 9011 9012 pos = buf; 9013 end = buf + buflen; 9014 9015 os_get_reltime(&now); 9016 9017 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 9018 { 9019 int ret; 9020 9021 os_reltime_sub(&now, &work->time, &diff); 9022 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n", 9023 work->type, work->wpa_s->ifname, work->freq, 9024 work->started, diff.sec, diff.usec); 9025 if (os_snprintf_error(end - pos, ret)) 9026 break; 9027 pos += ret; 9028 } 9029 9030 return pos - buf; 9031 } 9032 9033 9034 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx) 9035 { 9036 struct wpa_radio_work *work = eloop_ctx; 9037 struct wpa_external_work *ework = work->ctx; 9038 9039 wpa_dbg(work->wpa_s, MSG_DEBUG, 9040 "Timing out external radio work %u (%s)", 9041 ework->id, work->type); 9042 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id); 9043 work->wpa_s->ext_work_in_progress = 0; 9044 radio_work_done(work); 9045 os_free(ework); 9046 } 9047 9048 9049 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit) 9050 { 9051 struct wpa_external_work *ework = work->ctx; 9052 9053 if (deinit) { 9054 if (work->started) 9055 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 9056 work, NULL); 9057 9058 /* 9059 * work->type points to a buffer in ework, so need to replace 9060 * that here with a fixed string to avoid use of freed memory 9061 * in debug prints. 9062 */ 9063 work->type = "freed-ext-work"; 9064 work->ctx = NULL; 9065 os_free(ework); 9066 return; 9067 } 9068 9069 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)", 9070 ework->id, ework->type); 9071 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id); 9072 work->wpa_s->ext_work_in_progress = 1; 9073 if (!ework->timeout) 9074 ework->timeout = 10; 9075 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout, 9076 work, NULL); 9077 } 9078 9079 9080 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd, 9081 char *buf, size_t buflen) 9082 { 9083 struct wpa_external_work *ework; 9084 char *pos, *pos2; 9085 size_t type_len; 9086 int ret; 9087 unsigned int freq = 0; 9088 9089 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */ 9090 9091 ework = os_zalloc(sizeof(*ework)); 9092 if (ework == NULL) 9093 return -1; 9094 9095 pos = os_strchr(cmd, ' '); 9096 if (pos) { 9097 type_len = pos - cmd; 9098 pos++; 9099 9100 pos2 = os_strstr(pos, "freq="); 9101 if (pos2) 9102 freq = atoi(pos2 + 5); 9103 9104 pos2 = os_strstr(pos, "timeout="); 9105 if (pos2) 9106 ework->timeout = atoi(pos2 + 8); 9107 } else { 9108 type_len = os_strlen(cmd); 9109 } 9110 if (4 + type_len >= sizeof(ework->type)) 9111 type_len = sizeof(ework->type) - 4 - 1; 9112 os_strlcpy(ework->type, "ext:", sizeof(ework->type)); 9113 os_memcpy(ework->type + 4, cmd, type_len); 9114 ework->type[4 + type_len] = '\0'; 9115 9116 wpa_s->ext_work_id++; 9117 if (wpa_s->ext_work_id == 0) 9118 wpa_s->ext_work_id++; 9119 ework->id = wpa_s->ext_work_id; 9120 9121 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb, 9122 ework) < 0) { 9123 os_free(ework); 9124 return -1; 9125 } 9126 9127 ret = os_snprintf(buf, buflen, "%u", ework->id); 9128 if (os_snprintf_error(buflen, ret)) 9129 return -1; 9130 return ret; 9131 } 9132 9133 9134 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd) 9135 { 9136 struct wpa_radio_work *work; 9137 unsigned int id = atoi(cmd); 9138 9139 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 9140 { 9141 struct wpa_external_work *ework; 9142 9143 if (os_strncmp(work->type, "ext:", 4) != 0) 9144 continue; 9145 ework = work->ctx; 9146 if (id && ework->id != id) 9147 continue; 9148 wpa_dbg(wpa_s, MSG_DEBUG, 9149 "Completed external radio work %u (%s)", 9150 ework->id, ework->type); 9151 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL); 9152 wpa_s->ext_work_in_progress = 0; 9153 radio_work_done(work); 9154 os_free(ework); 9155 return 3; /* "OK\n" */ 9156 } 9157 9158 return -1; 9159 } 9160 9161 9162 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd, 9163 char *buf, size_t buflen) 9164 { 9165 if (os_strcmp(cmd, "show") == 0) 9166 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen); 9167 if (os_strncmp(cmd, "add ", 4) == 0) 9168 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen); 9169 if (os_strncmp(cmd, "done ", 5) == 0) 9170 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4); 9171 return -1; 9172 } 9173 9174 9175 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) 9176 { 9177 struct wpa_radio_work *work, *tmp; 9178 9179 if (!wpa_s || !wpa_s->radio) 9180 return; 9181 9182 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work, 9183 struct wpa_radio_work, list) { 9184 struct wpa_external_work *ework; 9185 9186 if (os_strncmp(work->type, "ext:", 4) != 0) 9187 continue; 9188 ework = work->ctx; 9189 wpa_dbg(wpa_s, MSG_DEBUG, 9190 "Flushing%s external radio work %u (%s)", 9191 work->started ? " started" : "", ework->id, 9192 ework->type); 9193 if (work->started) 9194 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 9195 work, NULL); 9196 radio_work_done(work); 9197 os_free(ework); 9198 } 9199 } 9200 9201 9202 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 9203 { 9204 struct wpa_supplicant *wpa_s = eloop_ctx; 9205 eapol_sm_notify_ctrl_response(wpa_s->eapol); 9206 } 9207 9208 9209 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value, 9210 unsigned int *scan_id_count, int scan_id[]) 9211 { 9212 const char *pos = value; 9213 9214 while (pos) { 9215 if (*pos == ' ' || *pos == '\0') 9216 break; 9217 if (*scan_id_count == MAX_SCAN_ID) 9218 return -1; 9219 scan_id[(*scan_id_count)++] = atoi(pos); 9220 pos = os_strchr(pos, ','); 9221 if (pos) 9222 pos++; 9223 } 9224 9225 return 0; 9226 } 9227 9228 9229 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 9230 char *reply, int reply_size, int *reply_len) 9231 { 9232 char *pos; 9233 unsigned int manual_scan_passive = 0; 9234 unsigned int manual_scan_use_id = 0; 9235 unsigned int manual_scan_only_new = 0; 9236 unsigned int scan_only = 0; 9237 unsigned int scan_id_count = 0; 9238 unsigned int manual_non_coloc_6ghz = 0; 9239 int scan_id[MAX_SCAN_ID]; 9240 void (*scan_res_handler)(struct wpa_supplicant *wpa_s, 9241 struct wpa_scan_results *scan_res); 9242 int *manual_scan_freqs = NULL; 9243 struct wpa_ssid_value *ssid = NULL, *ns; 9244 unsigned int ssid_count = 0; 9245 9246 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 9247 *reply_len = -1; 9248 return; 9249 } 9250 9251 if (radio_work_pending(wpa_s, "scan")) { 9252 wpa_printf(MSG_DEBUG, 9253 "Pending scan scheduled - reject new request"); 9254 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9255 return; 9256 } 9257 9258 #ifdef CONFIG_INTERWORKING 9259 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) { 9260 wpa_printf(MSG_DEBUG, 9261 "Interworking select in progress - reject new scan"); 9262 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9263 return; 9264 } 9265 #endif /* CONFIG_INTERWORKING */ 9266 9267 if (params) { 9268 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0) 9269 scan_only = 1; 9270 9271 pos = os_strstr(params, "freq="); 9272 if (pos) { 9273 manual_scan_freqs = freq_range_to_channel_list(wpa_s, 9274 pos + 5); 9275 if (manual_scan_freqs == NULL) { 9276 *reply_len = -1; 9277 goto done; 9278 } 9279 } 9280 9281 pos = os_strstr(params, "passive="); 9282 if (pos) 9283 manual_scan_passive = !!atoi(pos + 8); 9284 9285 pos = os_strstr(params, "use_id="); 9286 if (pos) 9287 manual_scan_use_id = atoi(pos + 7); 9288 9289 pos = os_strstr(params, "only_new=1"); 9290 if (pos) 9291 manual_scan_only_new = 1; 9292 9293 pos = os_strstr(params, "scan_id="); 9294 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count, 9295 scan_id) < 0) { 9296 *reply_len = -1; 9297 goto done; 9298 } 9299 9300 pos = os_strstr(params, "bssid="); 9301 if (pos) { 9302 u8 bssid[ETH_ALEN]; 9303 9304 pos += 6; 9305 if (hwaddr_aton(pos, bssid)) { 9306 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos); 9307 *reply_len = -1; 9308 goto done; 9309 } 9310 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); 9311 9312 wpa_s->next_scan_bssid_wildcard_ssid = 9313 os_strstr(params, "wildcard_ssid=1") != NULL; 9314 } 9315 9316 pos = os_strstr(params, "non_coloc_6ghz="); 9317 if (pos) 9318 manual_non_coloc_6ghz = !!atoi(pos + 15); 9319 9320 pos = params; 9321 while (pos && *pos != '\0') { 9322 if (os_strncmp(pos, "ssid ", 5) == 0) { 9323 char *end; 9324 9325 pos += 5; 9326 end = pos; 9327 while (*end) { 9328 if (*end == '\0' || *end == ' ') 9329 break; 9330 end++; 9331 } 9332 9333 ns = os_realloc_array( 9334 ssid, ssid_count + 1, 9335 sizeof(struct wpa_ssid_value)); 9336 if (ns == NULL) { 9337 *reply_len = -1; 9338 goto done; 9339 } 9340 ssid = ns; 9341 9342 if ((end - pos) & 0x01 || 9343 end - pos > 2 * SSID_MAX_LEN || 9344 hexstr2bin(pos, ssid[ssid_count].ssid, 9345 (end - pos) / 2) < 0) { 9346 wpa_printf(MSG_DEBUG, 9347 "Invalid SSID value '%s'", 9348 pos); 9349 *reply_len = -1; 9350 goto done; 9351 } 9352 ssid[ssid_count].ssid_len = (end - pos) / 2; 9353 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", 9354 ssid[ssid_count].ssid, 9355 ssid[ssid_count].ssid_len); 9356 ssid_count++; 9357 pos = end; 9358 } 9359 9360 pos = os_strchr(pos, ' '); 9361 if (pos) 9362 pos++; 9363 } 9364 } 9365 9366 wpa_s->num_ssids_from_scan_req = ssid_count; 9367 os_free(wpa_s->ssids_from_scan_req); 9368 if (ssid_count) { 9369 wpa_s->ssids_from_scan_req = ssid; 9370 ssid = NULL; 9371 } else { 9372 wpa_s->ssids_from_scan_req = NULL; 9373 } 9374 9375 if (scan_only) 9376 scan_res_handler = scan_only_handler; 9377 else if (wpa_s->scan_res_handler == scan_only_handler) 9378 scan_res_handler = NULL; 9379 else 9380 scan_res_handler = wpa_s->scan_res_handler; 9381 9382 if (!wpa_s->sched_scanning && !wpa_s->scanning && 9383 ((wpa_s->wpa_state <= WPA_SCANNING) || 9384 (wpa_s->wpa_state == WPA_COMPLETED))) { 9385 wpa_s->manual_scan_passive = manual_scan_passive; 9386 wpa_s->manual_scan_use_id = manual_scan_use_id; 9387 wpa_s->manual_scan_only_new = manual_scan_only_new; 9388 wpa_s->scan_id_count = scan_id_count; 9389 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz; 9390 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 9391 wpa_s->scan_res_handler = scan_res_handler; 9392 os_free(wpa_s->manual_scan_freqs); 9393 wpa_s->manual_scan_freqs = manual_scan_freqs; 9394 manual_scan_freqs = NULL; 9395 9396 wpa_s->normal_scans = 0; 9397 wpa_s->scan_req = MANUAL_SCAN_REQ; 9398 wpa_s->after_wps = 0; 9399 wpa_s->known_wps_freq = 0; 9400 wpa_supplicant_req_scan(wpa_s, 0, 0); 9401 if (wpa_s->manual_scan_use_id) { 9402 wpa_s->manual_scan_id++; 9403 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 9404 wpa_s->manual_scan_id); 9405 *reply_len = os_snprintf(reply, reply_size, "%u\n", 9406 wpa_s->manual_scan_id); 9407 } 9408 } else if (wpa_s->sched_scanning) { 9409 wpa_s->manual_scan_passive = manual_scan_passive; 9410 wpa_s->manual_scan_use_id = manual_scan_use_id; 9411 wpa_s->manual_scan_only_new = manual_scan_only_new; 9412 wpa_s->scan_id_count = scan_id_count; 9413 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz; 9414 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 9415 wpa_s->scan_res_handler = scan_res_handler; 9416 os_free(wpa_s->manual_scan_freqs); 9417 wpa_s->manual_scan_freqs = manual_scan_freqs; 9418 manual_scan_freqs = NULL; 9419 9420 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed"); 9421 wpa_supplicant_cancel_sched_scan(wpa_s); 9422 wpa_s->scan_req = MANUAL_SCAN_REQ; 9423 wpa_supplicant_req_scan(wpa_s, 0, 0); 9424 if (wpa_s->manual_scan_use_id) { 9425 wpa_s->manual_scan_id++; 9426 *reply_len = os_snprintf(reply, reply_size, "%u\n", 9427 wpa_s->manual_scan_id); 9428 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 9429 wpa_s->manual_scan_id); 9430 } 9431 } else { 9432 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request"); 9433 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9434 } 9435 9436 done: 9437 os_free(manual_scan_freqs); 9438 os_free(ssid); 9439 } 9440 9441 9442 #ifdef CONFIG_TESTING_OPTIONS 9443 9444 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s, 9445 unsigned int freq, const u8 *dst, 9446 const u8 *src, const u8 *bssid, 9447 const u8 *data, size_t data_len, 9448 enum offchannel_send_action_result 9449 result) 9450 { 9451 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR 9452 " src=" MACSTR " bssid=" MACSTR " result=%s", 9453 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), 9454 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? 9455 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? 9456 "NO_ACK" : "FAILED")); 9457 } 9458 9459 9460 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd) 9461 { 9462 char *pos, *param; 9463 size_t len; 9464 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN]; 9465 int res, used; 9466 int freq = 0, no_cck = 0, wait_time = 0; 9467 9468 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1] 9469 * <action=Action frame payload> */ 9470 9471 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 9472 9473 pos = cmd; 9474 used = hwaddr_aton2(pos, da); 9475 if (used < 0) 9476 return -1; 9477 pos += used; 9478 while (*pos == ' ') 9479 pos++; 9480 used = hwaddr_aton2(pos, bssid); 9481 if (used < 0) 9482 return -1; 9483 pos += used; 9484 9485 param = os_strstr(pos, " freq="); 9486 if (param) { 9487 param += 6; 9488 freq = atoi(param); 9489 } 9490 9491 param = os_strstr(pos, " no_cck="); 9492 if (param) { 9493 param += 8; 9494 no_cck = atoi(param); 9495 } 9496 9497 param = os_strstr(pos, " wait_time="); 9498 if (param) { 9499 param += 11; 9500 wait_time = atoi(param); 9501 } 9502 9503 param = os_strstr(pos, " action="); 9504 if (param == NULL) 9505 return -1; 9506 param += 8; 9507 9508 len = os_strlen(param); 9509 if (len & 1) 9510 return -1; 9511 len /= 2; 9512 9513 buf = os_malloc(len); 9514 if (buf == NULL) 9515 return -1; 9516 9517 if (hexstr2bin(param, buf, len) < 0) { 9518 os_free(buf); 9519 return -1; 9520 } 9521 9522 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid, 9523 buf, len, wait_time, 9524 wpas_ctrl_iface_mgmt_tx_cb, no_cck); 9525 os_free(buf); 9526 return res; 9527 } 9528 9529 9530 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s) 9531 { 9532 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting"); 9533 offchannel_send_action_done(wpa_s); 9534 } 9535 9536 9537 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s, 9538 char *cmd) 9539 { 9540 char *pos, *param; 9541 size_t len; 9542 u8 *buf; 9543 int freq = 0, datarate = 0, ssi_signal = 0; 9544 union wpa_event_data event; 9545 9546 if (!wpa_s->ext_mgmt_frame_handling) 9547 return -1; 9548 9549 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 9550 9551 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 9552 9553 pos = cmd; 9554 param = os_strstr(pos, "freq="); 9555 if (param) { 9556 param += 5; 9557 freq = atoi(param); 9558 } 9559 9560 param = os_strstr(pos, " datarate="); 9561 if (param) { 9562 param += 10; 9563 datarate = atoi(param); 9564 } 9565 9566 param = os_strstr(pos, " ssi_signal="); 9567 if (param) { 9568 param += 12; 9569 ssi_signal = atoi(param); 9570 } 9571 9572 param = os_strstr(pos, " frame="); 9573 if (param == NULL) 9574 return -1; 9575 param += 7; 9576 9577 len = os_strlen(param); 9578 if (len & 1) 9579 return -1; 9580 len /= 2; 9581 9582 buf = os_malloc(len); 9583 if (buf == NULL) 9584 return -1; 9585 9586 if (hexstr2bin(param, buf, len) < 0) { 9587 os_free(buf); 9588 return -1; 9589 } 9590 9591 os_memset(&event, 0, sizeof(event)); 9592 event.rx_mgmt.freq = freq; 9593 event.rx_mgmt.frame = buf; 9594 event.rx_mgmt.frame_len = len; 9595 event.rx_mgmt.ssi_signal = ssi_signal; 9596 event.rx_mgmt.datarate = datarate; 9597 wpa_s->ext_mgmt_frame_handling = 0; 9598 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event); 9599 wpa_s->ext_mgmt_frame_handling = 1; 9600 9601 os_free(buf); 9602 9603 return 0; 9604 } 9605 9606 9607 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s, 9608 char *param) 9609 { 9610 struct wpa_scan_res *res; 9611 struct os_reltime now; 9612 char *pos, *end; 9613 int ret = -1; 9614 9615 if (!param) 9616 return -1; 9617 9618 if (os_strcmp(param, "START") == 0) { 9619 wpa_bss_update_start(wpa_s); 9620 return 0; 9621 } 9622 9623 if (os_strcmp(param, "END") == 0) { 9624 wpa_bss_update_end(wpa_s, NULL, 1); 9625 return 0; 9626 } 9627 9628 if (os_strncmp(param, "BSS ", 4) != 0) 9629 return -1; 9630 param += 3; 9631 9632 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2); 9633 if (!res) 9634 return -1; 9635 9636 pos = os_strstr(param, " flags="); 9637 if (pos) 9638 res->flags = strtol(pos + 7, NULL, 16); 9639 9640 pos = os_strstr(param, " bssid="); 9641 if (pos && hwaddr_aton(pos + 7, res->bssid)) 9642 goto fail; 9643 9644 pos = os_strstr(param, " freq="); 9645 if (pos) 9646 res->freq = atoi(pos + 6); 9647 9648 pos = os_strstr(param, " beacon_int="); 9649 if (pos) 9650 res->beacon_int = atoi(pos + 12); 9651 9652 pos = os_strstr(param, " caps="); 9653 if (pos) 9654 res->caps = strtol(pos + 6, NULL, 16); 9655 9656 pos = os_strstr(param, " qual="); 9657 if (pos) 9658 res->qual = atoi(pos + 6); 9659 9660 pos = os_strstr(param, " noise="); 9661 if (pos) 9662 res->noise = atoi(pos + 7); 9663 9664 pos = os_strstr(param, " level="); 9665 if (pos) 9666 res->level = atoi(pos + 7); 9667 9668 pos = os_strstr(param, " tsf="); 9669 if (pos) 9670 res->tsf = strtoll(pos + 5, NULL, 16); 9671 9672 pos = os_strstr(param, " age="); 9673 if (pos) 9674 res->age = atoi(pos + 5); 9675 9676 pos = os_strstr(param, " est_throughput="); 9677 if (pos) 9678 res->est_throughput = atoi(pos + 16); 9679 9680 pos = os_strstr(param, " snr="); 9681 if (pos) 9682 res->snr = atoi(pos + 5); 9683 9684 pos = os_strstr(param, " parent_tsf="); 9685 if (pos) 9686 res->parent_tsf = strtoll(pos + 7, NULL, 16); 9687 9688 pos = os_strstr(param, " tsf_bssid="); 9689 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid)) 9690 goto fail; 9691 9692 pos = os_strstr(param, " ie="); 9693 if (pos) { 9694 pos += 4; 9695 end = os_strchr(pos, ' '); 9696 if (!end) 9697 end = pos + os_strlen(pos); 9698 res->ie_len = (end - pos) / 2; 9699 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len)) 9700 goto fail; 9701 } 9702 9703 pos = os_strstr(param, " beacon_ie="); 9704 if (pos) { 9705 pos += 11; 9706 end = os_strchr(pos, ' '); 9707 if (!end) 9708 end = pos + os_strlen(pos); 9709 res->beacon_ie_len = (end - pos) / 2; 9710 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len, 9711 res->beacon_ie_len)) 9712 goto fail; 9713 } 9714 9715 os_get_reltime(&now); 9716 wpa_bss_update_scan_res(wpa_s, res, &now); 9717 ret = 0; 9718 fail: 9719 os_free(res); 9720 9721 return ret; 9722 } 9723 9724 9725 static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s, 9726 char *param) 9727 { 9728 union wpa_event_data event; 9729 struct assoc_info *ai; 9730 char *ctx = NULL; 9731 int ret = -1; 9732 struct wpabuf *req_ies = NULL; 9733 struct wpabuf *resp_ies = NULL; 9734 struct wpabuf *resp_frame = NULL; 9735 struct wpabuf *beacon_ies = NULL; 9736 struct wpabuf *key_replay_ctr = NULL; 9737 struct wpabuf *ptk_kck = NULL; 9738 struct wpabuf *ptk_kek = NULL; 9739 struct wpabuf *fils_pmk = NULL; 9740 char *str, *pos; 9741 u8 addr[ETH_ALEN]; 9742 u8 fils_pmkid[PMKID_LEN]; 9743 9744 os_memset(&event, 0, sizeof(event)); 9745 ai = &event.assoc_info; 9746 9747 while ((str = str_token(param, " ", &ctx))) { 9748 pos = os_strchr(str, '='); 9749 if (!pos) 9750 goto fail; 9751 *pos++ = '\0'; 9752 9753 if (os_strcmp(str, "reassoc") == 0) { 9754 ai->reassoc = atoi(pos); 9755 } else if (os_strcmp(str, "req_ies") == 0) { 9756 wpabuf_free(req_ies); 9757 req_ies = wpabuf_parse_bin(pos); 9758 if (!req_ies) 9759 goto fail; 9760 ai->req_ies = wpabuf_head(req_ies); 9761 ai->req_ies_len = wpabuf_len(req_ies); 9762 } else if (os_strcmp(str, "resp_ies") == 0) { 9763 wpabuf_free(resp_ies); 9764 resp_ies = wpabuf_parse_bin(pos); 9765 if (!resp_ies) 9766 goto fail; 9767 ai->resp_ies = wpabuf_head(resp_ies); 9768 ai->resp_ies_len = wpabuf_len(resp_ies); 9769 } else if (os_strcmp(str, "resp_frame") == 0) { 9770 wpabuf_free(resp_frame); 9771 resp_frame = wpabuf_parse_bin(pos); 9772 if (!resp_frame) 9773 goto fail; 9774 ai->resp_frame = wpabuf_head(resp_frame); 9775 ai->resp_frame_len = wpabuf_len(resp_frame); 9776 } else if (os_strcmp(str, "beacon_ies") == 0) { 9777 wpabuf_free(beacon_ies); 9778 beacon_ies = wpabuf_parse_bin(pos); 9779 if (!beacon_ies) 9780 goto fail; 9781 ai->beacon_ies = wpabuf_head(beacon_ies); 9782 ai->beacon_ies_len = wpabuf_len(beacon_ies); 9783 } else if (os_strcmp(str, "freq") == 0) { 9784 ai->freq = atoi(pos); 9785 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) { 9786 ai->wmm_params.info_bitmap = atoi(pos); 9787 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) { 9788 ai->wmm_params.uapsd_queues = atoi(pos); 9789 } else if (os_strcmp(str, "addr") == 0) { 9790 if (hwaddr_aton(pos, addr)) 9791 goto fail; 9792 ai->addr = addr; 9793 } else if (os_strcmp(str, "authorized") == 0) { 9794 ai->authorized = atoi(pos); 9795 } else if (os_strcmp(str, "key_replay_ctr") == 0) { 9796 wpabuf_free(key_replay_ctr); 9797 key_replay_ctr = wpabuf_parse_bin(pos); 9798 if (!key_replay_ctr) 9799 goto fail; 9800 ai->key_replay_ctr = wpabuf_head(key_replay_ctr); 9801 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr); 9802 } else if (os_strcmp(str, "ptk_kck") == 0) { 9803 wpabuf_free(ptk_kck); 9804 ptk_kck = wpabuf_parse_bin(pos); 9805 if (!ptk_kck) 9806 goto fail; 9807 ai->ptk_kck = wpabuf_head(ptk_kck); 9808 ai->ptk_kck_len = wpabuf_len(ptk_kck); 9809 } else if (os_strcmp(str, "ptk_kek") == 0) { 9810 wpabuf_free(ptk_kek); 9811 ptk_kek = wpabuf_parse_bin(pos); 9812 if (!ptk_kek) 9813 goto fail; 9814 ai->ptk_kek = wpabuf_head(ptk_kek); 9815 ai->ptk_kek_len = wpabuf_len(ptk_kek); 9816 } else if (os_strcmp(str, "subnet_status") == 0) { 9817 ai->subnet_status = atoi(pos); 9818 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) { 9819 ai->fils_erp_next_seq_num = atoi(pos); 9820 } else if (os_strcmp(str, "fils_pmk") == 0) { 9821 wpabuf_free(fils_pmk); 9822 fils_pmk = wpabuf_parse_bin(pos); 9823 if (!fils_pmk) 9824 goto fail; 9825 ai->fils_pmk = wpabuf_head(fils_pmk); 9826 ai->fils_pmk_len = wpabuf_len(fils_pmk); 9827 } else if (os_strcmp(str, "fils_pmkid") == 0) { 9828 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0) 9829 goto fail; 9830 ai->fils_pmkid = fils_pmkid; 9831 } else { 9832 goto fail; 9833 } 9834 } 9835 9836 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event); 9837 ret = 0; 9838 fail: 9839 wpabuf_free(req_ies); 9840 wpabuf_free(resp_ies); 9841 wpabuf_free(resp_frame); 9842 wpabuf_free(beacon_ies); 9843 wpabuf_free(key_replay_ctr); 9844 wpabuf_free(ptk_kck); 9845 wpabuf_free(ptk_kek); 9846 wpabuf_free(fils_pmk); 9847 return ret; 9848 } 9849 9850 9851 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) 9852 { 9853 char *pos, *param; 9854 union wpa_event_data event; 9855 enum wpa_event_type ev; 9856 9857 /* <event name> [parameters..] */ 9858 9859 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd); 9860 9861 pos = cmd; 9862 param = os_strchr(pos, ' '); 9863 if (param) 9864 *param++ = '\0'; 9865 9866 os_memset(&event, 0, sizeof(event)); 9867 9868 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) { 9869 ev = EVENT_INTERFACE_ENABLED; 9870 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) { 9871 ev = EVENT_INTERFACE_DISABLED; 9872 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) { 9873 ev = EVENT_AVOID_FREQUENCIES; 9874 if (param == NULL) 9875 param = ""; 9876 if (freq_range_list_parse(&event.freq_range, param) < 0) 9877 return -1; 9878 wpa_supplicant_event(wpa_s, ev, &event); 9879 os_free(event.freq_range.range); 9880 return 0; 9881 } else if (os_strcmp(cmd, "SCAN_RES") == 0) { 9882 return wpas_ctrl_iface_driver_scan_res(wpa_s, param); 9883 } else if (os_strcmp(cmd, "ASSOC") == 0) { 9884 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param); 9885 } else { 9886 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", 9887 cmd); 9888 return -1; 9889 } 9890 9891 wpa_supplicant_event(wpa_s, ev, &event); 9892 9893 return 0; 9894 } 9895 9896 9897 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd) 9898 { 9899 char *pos; 9900 u8 src[ETH_ALEN], *buf; 9901 int used; 9902 size_t len; 9903 9904 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 9905 9906 pos = cmd; 9907 used = hwaddr_aton2(pos, src); 9908 if (used < 0) 9909 return -1; 9910 pos += used; 9911 while (*pos == ' ') 9912 pos++; 9913 9914 len = os_strlen(pos); 9915 if (len & 1) 9916 return -1; 9917 len /= 2; 9918 9919 buf = os_malloc(len); 9920 if (buf == NULL) 9921 return -1; 9922 9923 if (hexstr2bin(pos, buf, len) < 0) { 9924 os_free(buf); 9925 return -1; 9926 } 9927 9928 wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN); 9929 os_free(buf); 9930 9931 return 0; 9932 } 9933 9934 9935 static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd) 9936 { 9937 char *pos; 9938 u8 dst[ETH_ALEN], *buf; 9939 int used, ret; 9940 size_t len; 9941 unsigned int prev; 9942 9943 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd); 9944 9945 pos = cmd; 9946 used = hwaddr_aton2(pos, dst); 9947 if (used < 0) 9948 return -1; 9949 pos += used; 9950 while (*pos == ' ') 9951 pos++; 9952 9953 len = os_strlen(pos); 9954 if (len & 1) 9955 return -1; 9956 len /= 2; 9957 9958 buf = os_malloc(len); 9959 if (!buf || hexstr2bin(pos, buf, len) < 0) { 9960 os_free(buf); 9961 return -1; 9962 } 9963 9964 prev = wpa_s->ext_eapol_frame_io; 9965 wpa_s->ext_eapol_frame_io = 0; 9966 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len); 9967 wpa_s->ext_eapol_frame_io = prev; 9968 os_free(buf); 9969 9970 return ret; 9971 } 9972 9973 9974 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 9975 { 9976 size_t i; 9977 u32 sum = 0; 9978 const u16 *pos = buf; 9979 9980 for (i = 0; i < len / 2; i++) 9981 sum += *pos++; 9982 9983 while (sum >> 16) 9984 sum = (sum & 0xffff) + (sum >> 16); 9985 9986 return sum ^ 0xffff; 9987 } 9988 9989 9990 #define HWSIM_PACKETLEN 1500 9991 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 9992 9993 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 9994 size_t len) 9995 { 9996 struct wpa_supplicant *wpa_s = ctx; 9997 const struct ether_header *eth; 9998 struct ip ip; 9999 const u8 *pos; 10000 unsigned int i; 10001 char extra[30]; 10002 10003 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 10004 wpa_printf(MSG_DEBUG, 10005 "test data: RX - ignore unexpected length %d", 10006 (int) len); 10007 return; 10008 } 10009 10010 eth = (const struct ether_header *) buf; 10011 os_memcpy(&ip, eth + 1, sizeof(ip)); 10012 pos = &buf[sizeof(*eth) + sizeof(ip)]; 10013 10014 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { 10015 wpa_printf(MSG_DEBUG, 10016 "test data: RX - ignore unexpected IP header"); 10017 return; 10018 } 10019 10020 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) { 10021 if (*pos != (u8) i) { 10022 wpa_printf(MSG_DEBUG, 10023 "test data: RX - ignore mismatching payload"); 10024 return; 10025 } 10026 pos++; 10027 } 10028 extra[0] = '\0'; 10029 if (ntohs(ip.ip_len) != HWSIM_IP_LEN) 10030 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len)); 10031 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 10032 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 10033 } 10034 10035 10036 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s, 10037 char *cmd) 10038 { 10039 int enabled = atoi(cmd); 10040 char *pos; 10041 const char *ifname; 10042 10043 if (!enabled) { 10044 if (wpa_s->l2_test) { 10045 l2_packet_deinit(wpa_s->l2_test); 10046 wpa_s->l2_test = NULL; 10047 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled"); 10048 } 10049 return 0; 10050 } 10051 10052 if (wpa_s->l2_test) 10053 return 0; 10054 10055 pos = os_strstr(cmd, " ifname="); 10056 if (pos) 10057 ifname = pos + 8; 10058 else 10059 ifname = wpa_s->ifname; 10060 10061 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr, 10062 ETHERTYPE_IP, wpas_data_test_rx, 10063 wpa_s, 1); 10064 if (wpa_s->l2_test == NULL) 10065 return -1; 10066 10067 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled"); 10068 10069 return 0; 10070 } 10071 10072 10073 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) 10074 { 10075 u8 dst[ETH_ALEN], src[ETH_ALEN]; 10076 char *pos, *pos2; 10077 int used; 10078 long int val; 10079 u8 tos; 10080 u8 buf[2 + HWSIM_PACKETLEN]; 10081 struct ether_header *eth; 10082 struct ip *ip; 10083 u8 *dpos; 10084 unsigned int i; 10085 size_t send_len = HWSIM_IP_LEN; 10086 10087 if (wpa_s->l2_test == NULL) 10088 return -1; 10089 10090 /* format: <dst> <src> <tos> [len=<length>] */ 10091 10092 pos = cmd; 10093 used = hwaddr_aton2(pos, dst); 10094 if (used < 0) 10095 return -1; 10096 pos += used; 10097 while (*pos == ' ') 10098 pos++; 10099 used = hwaddr_aton2(pos, src); 10100 if (used < 0) 10101 return -1; 10102 pos += used; 10103 10104 val = strtol(pos, &pos2, 0); 10105 if (val < 0 || val > 0xff) 10106 return -1; 10107 tos = val; 10108 10109 pos = os_strstr(pos2, " len="); 10110 if (pos) { 10111 i = atoi(pos + 5); 10112 if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 10113 return -1; 10114 send_len = i; 10115 } 10116 10117 eth = (struct ether_header *) &buf[2]; 10118 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 10119 os_memcpy(eth->ether_shost, src, ETH_ALEN); 10120 eth->ether_type = htons(ETHERTYPE_IP); 10121 ip = (struct ip *) (eth + 1); 10122 os_memset(ip, 0, sizeof(*ip)); 10123 ip->ip_hl = 5; 10124 ip->ip_v = 4; 10125 ip->ip_ttl = 64; 10126 ip->ip_tos = tos; 10127 ip->ip_len = htons(send_len); 10128 ip->ip_p = 1; 10129 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 10130 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 10131 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip)); 10132 dpos = (u8 *) (ip + 1); 10133 for (i = 0; i < send_len - sizeof(*ip); i++) 10134 *dpos++ = i; 10135 10136 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2], 10137 sizeof(struct ether_header) + send_len) < 0) 10138 return -1; 10139 10140 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR 10141 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 10142 10143 return 0; 10144 } 10145 10146 10147 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s, 10148 char *cmd) 10149 { 10150 u8 *buf; 10151 struct ether_header *eth; 10152 struct l2_packet_data *l2 = NULL; 10153 size_t len; 10154 u16 ethertype; 10155 int res = -1; 10156 10157 len = os_strlen(cmd); 10158 if (len & 1 || len < ETH_HLEN * 2) 10159 return -1; 10160 len /= 2; 10161 10162 buf = os_malloc(len); 10163 if (buf == NULL) 10164 return -1; 10165 10166 if (hexstr2bin(cmd, buf, len) < 0) 10167 goto done; 10168 10169 eth = (struct ether_header *) buf; 10170 ethertype = ntohs(eth->ether_type); 10171 10172 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype, 10173 wpas_data_test_rx, wpa_s, 1); 10174 if (l2 == NULL) 10175 goto done; 10176 10177 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 10178 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res); 10179 done: 10180 if (l2) 10181 l2_packet_deinit(l2); 10182 os_free(buf); 10183 10184 return res < 0 ? -1 : 0; 10185 } 10186 10187 10188 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx) 10189 { 10190 struct wpa_supplicant *wpa_s = eloop_ctx; 10191 int i, count = (intptr_t) timeout_ctx; 10192 10193 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages", 10194 count); 10195 for (i = 0; i < count; i++) { 10196 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d", 10197 i + 1, count); 10198 } 10199 } 10200 10201 10202 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd) 10203 { 10204 int count; 10205 10206 count = atoi(cmd); 10207 if (count <= 0) 10208 return -1; 10209 10210 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s, 10211 (void *) (intptr_t) count); 10212 } 10213 10214 10215 static int wpas_get_hex_buf(const char *val, struct wpabuf **ret) 10216 { 10217 struct wpabuf *buf; 10218 size_t len; 10219 10220 len = os_strlen(val); 10221 if (len & 1) 10222 return -1; 10223 len /= 2; 10224 10225 if (len == 0) { 10226 buf = NULL; 10227 } else { 10228 buf = wpabuf_alloc(len); 10229 if (!buf) 10230 return -1; 10231 10232 if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) { 10233 wpabuf_free(buf); 10234 return -1; 10235 } 10236 } 10237 10238 *ret = buf; 10239 return 0; 10240 } 10241 10242 10243 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s, 10244 const char *cmd) 10245 { 10246 struct wpabuf *buf; 10247 10248 if (wpas_get_hex_buf(cmd, &buf) < 0) 10249 return -1; 10250 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf); 10251 return 0; 10252 } 10253 10254 10255 static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s, 10256 const char *cmd) 10257 { 10258 struct wpabuf *buf; 10259 10260 if (wpas_get_hex_buf(cmd, &buf) < 0) 10261 return -1; 10262 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf); 10263 return 0; 10264 } 10265 10266 10267 static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s, 10268 const char *cmd) 10269 { 10270 struct wpabuf *buf; 10271 10272 if (wpas_get_hex_buf(cmd, &buf) < 0) 10273 return -1; 10274 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf); 10275 return 0; 10276 } 10277 10278 10279 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s) 10280 { 10281 u8 zero[WPA_TK_MAX_LEN]; 10282 10283 if (wpa_s->last_tk_alg == WPA_ALG_NONE) 10284 return -1; 10285 10286 wpa_printf(MSG_INFO, "TESTING: Reset PN"); 10287 os_memset(zero, 0, sizeof(zero)); 10288 10289 /* First, use a zero key to avoid any possible duplicate key avoidance 10290 * in the driver. */ 10291 if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 10292 wpa_s->last_tk_key_idx, 1, zero, 6, 10293 zero, wpa_s->last_tk_len, 10294 KEY_FLAG_PAIRWISE_RX_TX) < 0) 10295 return -1; 10296 10297 /* Set the previously configured key to reset its TSC/RSC */ 10298 return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, 10299 wpa_s->last_tk_addr, 10300 wpa_s->last_tk_key_idx, 1, zero, 6, 10301 wpa_s->last_tk, wpa_s->last_tk_len, 10302 KEY_FLAG_PAIRWISE_RX_TX); 10303 } 10304 10305 10306 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) 10307 { 10308 const char *pos = cmd; 10309 int error, pairwise; 10310 10311 error = atoi(pos); 10312 pos = os_strchr(pos, ' '); 10313 if (!pos) 10314 return -1; 10315 pairwise = atoi(pos); 10316 wpa_sm_key_request(wpa_s->wpa, error, pairwise); 10317 return 0; 10318 } 10319 10320 10321 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) 10322 { 10323 #ifdef CONFIG_SME 10324 struct wpa_driver_associate_params params; 10325 int ret; 10326 10327 os_memset(¶ms, 0, sizeof(params)); 10328 params.bssid = wpa_s->bssid; 10329 params.ssid = wpa_s->sme.ssid; 10330 params.ssid_len = wpa_s->sme.ssid_len; 10331 params.freq.freq = wpa_s->sme.freq; 10332 if (wpa_s->last_assoc_req_wpa_ie) { 10333 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); 10334 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); 10335 } 10336 params.pairwise_suite = wpa_s->pairwise_cipher; 10337 params.group_suite = wpa_s->group_cipher; 10338 params.mgmt_group_suite = wpa_s->mgmt_group_cipher; 10339 params.key_mgmt_suite = wpa_s->key_mgmt; 10340 params.wpa_proto = wpa_s->wpa_proto; 10341 params.mgmt_frame_protection = wpa_s->sme.mfp; 10342 params.rrm_used = wpa_s->rrm.rrm_used; 10343 if (wpa_s->sme.prev_bssid_set) 10344 params.prev_bssid = wpa_s->sme.prev_bssid; 10345 wpa_printf(MSG_INFO, "TESTING: Resend association request"); 10346 ret = wpa_drv_associate(wpa_s, ¶ms); 10347 wpa_s->testing_resend_assoc = 1; 10348 return ret; 10349 #else /* CONFIG_SME */ 10350 return -1; 10351 #endif /* CONFIG_SME */ 10352 } 10353 10354 10355 static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s, 10356 const char *cmd) 10357 { 10358 u8 dtok = 1; 10359 int exponent = 10; 10360 int mantissa = 8192; 10361 u8 min_twt = 255; 10362 unsigned long long twt = 0; 10363 bool requestor = true; 10364 int setup_cmd = 0; 10365 bool trigger = true; 10366 bool implicit = true; 10367 bool flow_type = true; 10368 int flow_id = 0; 10369 bool protection = false; 10370 u8 twt_channel = 0; 10371 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021, 10372 * Figure 9-687 - Control field format): 10373 * B4 = TWT Information Frame Disabled */ 10374 const char *tok_s; 10375 10376 tok_s = os_strstr(cmd, " dialog="); 10377 if (tok_s) 10378 dtok = atoi(tok_s + os_strlen(" dialog=")); 10379 10380 tok_s = os_strstr(cmd, " exponent="); 10381 if (tok_s) 10382 exponent = atoi(tok_s + os_strlen(" exponent=")); 10383 10384 tok_s = os_strstr(cmd, " mantissa="); 10385 if (tok_s) 10386 mantissa = atoi(tok_s + os_strlen(" mantissa=")); 10387 10388 tok_s = os_strstr(cmd, " min_twt="); 10389 if (tok_s) 10390 min_twt = atoi(tok_s + os_strlen(" min_twt=")); 10391 10392 tok_s = os_strstr(cmd, " setup_cmd="); 10393 if (tok_s) 10394 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd=")); 10395 10396 tok_s = os_strstr(cmd, " twt="); 10397 if (tok_s && 10398 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1) 10399 return -1; 10400 10401 tok_s = os_strstr(cmd, " requestor="); 10402 if (tok_s) 10403 requestor = atoi(tok_s + os_strlen(" requestor=")); 10404 10405 tok_s = os_strstr(cmd, " trigger="); 10406 if (tok_s) 10407 trigger = atoi(tok_s + os_strlen(" trigger=")); 10408 10409 tok_s = os_strstr(cmd, " implicit="); 10410 if (tok_s) 10411 implicit = atoi(tok_s + os_strlen(" implicit=")); 10412 10413 tok_s = os_strstr(cmd, " flow_type="); 10414 if (tok_s) 10415 flow_type = atoi(tok_s + os_strlen(" flow_type=")); 10416 10417 tok_s = os_strstr(cmd, " flow_id="); 10418 if (tok_s) 10419 flow_id = atoi(tok_s + os_strlen(" flow_id=")); 10420 10421 tok_s = os_strstr(cmd, " protection="); 10422 if (tok_s) 10423 protection = atoi(tok_s + os_strlen(" protection=")); 10424 10425 tok_s = os_strstr(cmd, " twt_channel="); 10426 if (tok_s) 10427 twt_channel = atoi(tok_s + os_strlen(" twt_channel=")); 10428 10429 tok_s = os_strstr(cmd, " control="); 10430 if (tok_s) 10431 control = atoi(tok_s + os_strlen(" control=")); 10432 10433 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt, 10434 setup_cmd, twt, requestor, trigger, implicit, 10435 flow_type, flow_id, protection, twt_channel, 10436 control); 10437 } 10438 10439 10440 static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s, 10441 const char *cmd) 10442 { 10443 u8 flags = 0x1; 10444 const char *tok_s; 10445 10446 tok_s = os_strstr(cmd, " flags="); 10447 if (tok_s) 10448 flags = atoi(tok_s + os_strlen(" flags=")); 10449 10450 return wpas_twt_send_teardown(wpa_s, flags); 10451 } 10452 10453 #endif /* CONFIG_TESTING_OPTIONS */ 10454 10455 10456 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd) 10457 { 10458 char *pos = cmd; 10459 int frame; 10460 size_t len; 10461 struct wpabuf *buf; 10462 struct ieee802_11_elems elems; 10463 10464 frame = atoi(pos); 10465 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10466 return -1; 10467 wpa_s = wpas_vendor_elem(wpa_s, frame); 10468 10469 pos = os_strchr(pos, ' '); 10470 if (pos == NULL) 10471 return -1; 10472 pos++; 10473 10474 len = os_strlen(pos); 10475 if (len == 0) 10476 return 0; 10477 if (len & 1) 10478 return -1; 10479 len /= 2; 10480 10481 buf = wpabuf_alloc(len); 10482 if (buf == NULL) 10483 return -1; 10484 10485 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 10486 wpabuf_free(buf); 10487 return -1; 10488 } 10489 10490 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) == 10491 ParseFailed) { 10492 wpabuf_free(buf); 10493 return -1; 10494 } 10495 10496 if (wpa_s->vendor_elem[frame] == NULL) { 10497 wpa_s->vendor_elem[frame] = buf; 10498 goto update_ies; 10499 } 10500 10501 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) { 10502 wpabuf_free(buf); 10503 return -1; 10504 } 10505 10506 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf); 10507 wpabuf_free(buf); 10508 10509 update_ies: 10510 wpas_vendor_elem_update(wpa_s); 10511 10512 if (frame == VENDOR_ELEM_PROBE_REQ || 10513 frame == VENDOR_ELEM_PROBE_REQ_P2P) 10514 wpa_supplicant_set_default_scan_ies(wpa_s); 10515 10516 return 0; 10517 } 10518 10519 10520 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd, 10521 char *buf, size_t buflen) 10522 { 10523 int frame = atoi(cmd); 10524 10525 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10526 return -1; 10527 wpa_s = wpas_vendor_elem(wpa_s, frame); 10528 10529 if (wpa_s->vendor_elem[frame] == NULL) 10530 return 0; 10531 10532 return wpa_snprintf_hex(buf, buflen, 10533 wpabuf_head_u8(wpa_s->vendor_elem[frame]), 10534 wpabuf_len(wpa_s->vendor_elem[frame])); 10535 } 10536 10537 10538 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd) 10539 { 10540 char *pos = cmd; 10541 int frame; 10542 size_t len; 10543 u8 *buf; 10544 struct ieee802_11_elems elems; 10545 int res; 10546 10547 frame = atoi(pos); 10548 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10549 return -1; 10550 wpa_s = wpas_vendor_elem(wpa_s, frame); 10551 10552 pos = os_strchr(pos, ' '); 10553 if (pos == NULL) 10554 return -1; 10555 pos++; 10556 10557 if (*pos == '*') { 10558 wpabuf_free(wpa_s->vendor_elem[frame]); 10559 wpa_s->vendor_elem[frame] = NULL; 10560 wpas_vendor_elem_update(wpa_s); 10561 return 0; 10562 } 10563 10564 if (wpa_s->vendor_elem[frame] == NULL) 10565 return -1; 10566 10567 len = os_strlen(pos); 10568 if (len == 0) 10569 return 0; 10570 if (len & 1) 10571 return -1; 10572 len /= 2; 10573 10574 buf = os_malloc(len); 10575 if (buf == NULL) 10576 return -1; 10577 10578 if (hexstr2bin(pos, buf, len) < 0) { 10579 os_free(buf); 10580 return -1; 10581 } 10582 10583 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) { 10584 os_free(buf); 10585 return -1; 10586 } 10587 10588 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len); 10589 os_free(buf); 10590 return res; 10591 } 10592 10593 10594 #ifndef CONFIG_NO_RRM 10595 10596 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep) 10597 { 10598 struct wpa_supplicant *wpa_s = ctx; 10599 size_t len; 10600 const u8 *data; 10601 10602 /* 10603 * Neighbor Report element (IEEE P802.11-REVmc/D5.0) 10604 * BSSID[6] 10605 * BSSID Information[4] 10606 * Operating Class[1] 10607 * Channel Number[1] 10608 * PHY Type[1] 10609 * Optional Subelements[variable] 10610 */ 10611 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) 10612 10613 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) { 10614 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED); 10615 goto out; 10616 } 10617 10618 data = wpabuf_head_u8(neighbor_rep); 10619 len = wpabuf_len(neighbor_rep); 10620 10621 while (len >= 2 + NR_IE_MIN_LEN) { 10622 const u8 *nr; 10623 char lci[256 * 2 + 1]; 10624 char civic[256 * 2 + 1]; 10625 u8 nr_len = data[1]; 10626 const u8 *pos = data, *end; 10627 10628 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || 10629 nr_len < NR_IE_MIN_LEN) { 10630 wpa_dbg(wpa_s, MSG_DEBUG, 10631 "CTRL: Invalid Neighbor Report element: id=%u len=%u", 10632 data[0], nr_len); 10633 goto out; 10634 } 10635 10636 if (2U + nr_len > len) { 10637 wpa_dbg(wpa_s, MSG_DEBUG, 10638 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", 10639 data[0], len, nr_len); 10640 goto out; 10641 } 10642 pos += 2; 10643 end = pos + nr_len; 10644 10645 nr = pos; 10646 pos += NR_IE_MIN_LEN; 10647 10648 lci[0] = '\0'; 10649 civic[0] = '\0'; 10650 while (end - pos > 2) { 10651 u8 s_id, s_len; 10652 10653 s_id = *pos++; 10654 s_len = *pos++; 10655 if (s_len > end - pos) 10656 goto out; 10657 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) { 10658 /* Measurement Token[1] */ 10659 /* Measurement Report Mode[1] */ 10660 /* Measurement Type[1] */ 10661 /* Measurement Report[variable] */ 10662 switch (pos[2]) { 10663 case MEASURE_TYPE_LCI: 10664 if (lci[0]) 10665 break; 10666 wpa_snprintf_hex(lci, sizeof(lci), 10667 pos, s_len); 10668 break; 10669 case MEASURE_TYPE_LOCATION_CIVIC: 10670 if (civic[0]) 10671 break; 10672 wpa_snprintf_hex(civic, sizeof(civic), 10673 pos, s_len); 10674 break; 10675 } 10676 } 10677 10678 pos += s_len; 10679 } 10680 10681 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED 10682 "bssid=" MACSTR 10683 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s", 10684 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), 10685 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], 10686 nr[ETH_ALEN + 6], 10687 lci[0] ? " lci=" : "", lci, 10688 civic[0] ? " civic=" : "", civic); 10689 10690 data = end; 10691 len -= 2 + nr_len; 10692 } 10693 10694 out: 10695 wpabuf_free(neighbor_rep); 10696 } 10697 10698 10699 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s, 10700 char *cmd) 10701 { 10702 struct wpa_ssid_value ssid, *ssid_p = NULL; 10703 int ret, lci = 0, civic = 0; 10704 char *ssid_s; 10705 10706 ssid_s = os_strstr(cmd, "ssid="); 10707 if (ssid_s) { 10708 if (ssid_parse(ssid_s + 5, &ssid)) { 10709 wpa_msg(wpa_s, MSG_INFO, 10710 "CTRL: Send Neighbor Report: bad SSID"); 10711 return -1; 10712 } 10713 10714 ssid_p = &ssid; 10715 10716 /* 10717 * Move cmd after the SSID text that may include "lci" or 10718 * "civic". 10719 */ 10720 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' '); 10721 if (cmd) 10722 cmd++; 10723 10724 } 10725 10726 if (cmd && os_strstr(cmd, "lci")) 10727 lci = 1; 10728 10729 if (cmd && os_strstr(cmd, "civic")) 10730 civic = 1; 10731 10732 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, 10733 wpas_ctrl_neighbor_rep_cb, 10734 wpa_s); 10735 10736 return ret; 10737 } 10738 10739 #endif /* CONFIG_NO_RRM */ 10740 10741 10742 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s) 10743 { 10744 eapol_sm_erp_flush(wpa_s->eapol); 10745 return 0; 10746 } 10747 10748 10749 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, 10750 char *cmd) 10751 { 10752 char *token, *context = NULL; 10753 unsigned int enable = ~0, type = 0; 10754 u8 _addr[ETH_ALEN], _mask[ETH_ALEN]; 10755 u8 *addr = NULL, *mask = NULL; 10756 10757 while ((token = str_token(cmd, " ", &context))) { 10758 if (os_strcasecmp(token, "scan") == 0) { 10759 type |= MAC_ADDR_RAND_SCAN; 10760 } else if (os_strcasecmp(token, "sched") == 0) { 10761 type |= MAC_ADDR_RAND_SCHED_SCAN; 10762 } else if (os_strcasecmp(token, "pno") == 0) { 10763 type |= MAC_ADDR_RAND_PNO; 10764 } else if (os_strcasecmp(token, "all") == 0) { 10765 type = wpa_s->mac_addr_rand_supported; 10766 } else if (os_strncasecmp(token, "enable=", 7) == 0) { 10767 enable = atoi(token + 7); 10768 } else if (os_strncasecmp(token, "addr=", 5) == 0) { 10769 addr = _addr; 10770 if (hwaddr_aton(token + 5, addr)) { 10771 wpa_printf(MSG_INFO, 10772 "CTRL: Invalid MAC address: %s", 10773 token); 10774 return -1; 10775 } 10776 } else if (os_strncasecmp(token, "mask=", 5) == 0) { 10777 mask = _mask; 10778 if (hwaddr_aton(token + 5, mask)) { 10779 wpa_printf(MSG_INFO, 10780 "CTRL: Invalid MAC address mask: %s", 10781 token); 10782 return -1; 10783 } 10784 } else { 10785 wpa_printf(MSG_INFO, 10786 "CTRL: Invalid MAC_RAND_SCAN parameter: %s", 10787 token); 10788 return -1; 10789 } 10790 } 10791 10792 if (!type) { 10793 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified"); 10794 return -1; 10795 } 10796 10797 if (enable > 1) { 10798 wpa_printf(MSG_INFO, 10799 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified"); 10800 return -1; 10801 } 10802 10803 if (!enable) 10804 return wpas_disable_mac_addr_randomization(wpa_s, type); 10805 10806 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask); 10807 } 10808 10809 10810 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s, 10811 char *buf, size_t buflen) 10812 { 10813 size_t reply_len; 10814 10815 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen); 10816 #ifdef CONFIG_AP 10817 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len], 10818 buflen - reply_len); 10819 #endif /* CONFIG_AP */ 10820 return reply_len; 10821 } 10822 10823 10824 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) 10825 { 10826 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE); 10827 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 10828 #ifdef CONFIG_AP 10829 wpas_ap_pmksa_cache_flush(wpa_s); 10830 #endif /* CONFIG_AP */ 10831 } 10832 10833 10834 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 10835 10836 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s, 10837 const char *cmd, char *buf, size_t buflen) 10838 { 10839 struct rsn_pmksa_cache_entry *entry; 10840 struct wpa_ssid *ssid; 10841 char *pos, *pos2, *end; 10842 int ret; 10843 struct os_reltime now; 10844 10845 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 10846 if (!ssid) 10847 return -1; 10848 10849 pos = buf; 10850 end = buf + buflen; 10851 10852 os_get_reltime(&now); 10853 10854 /* 10855 * Entry format: 10856 * <BSSID> <PMKID> <PMK> <reauth_time in seconds> 10857 * <expiration in seconds> <akmp> <opportunistic> 10858 * [FILS Cache Identifier] 10859 */ 10860 10861 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry; 10862 entry = entry->next) { 10863 if (entry->network_ctx != ssid) 10864 continue; 10865 10866 pos2 = pos; 10867 ret = os_snprintf(pos2, end - pos2, MACSTR " ", 10868 MAC2STR(entry->aa)); 10869 if (os_snprintf_error(end - pos2, ret)) 10870 break; 10871 pos2 += ret; 10872 10873 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid, 10874 PMKID_LEN); 10875 10876 ret = os_snprintf(pos2, end - pos2, " "); 10877 if (os_snprintf_error(end - pos2, ret)) 10878 break; 10879 pos2 += ret; 10880 10881 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk, 10882 entry->pmk_len); 10883 10884 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d", 10885 (int) (entry->reauth_time - now.sec), 10886 (int) (entry->expiration - now.sec), 10887 entry->akmp, 10888 entry->opportunistic); 10889 if (os_snprintf_error(end - pos2, ret)) 10890 break; 10891 pos2 += ret; 10892 10893 if (entry->fils_cache_id_set) { 10894 ret = os_snprintf(pos2, end - pos2, " %02x%02x", 10895 entry->fils_cache_id[0], 10896 entry->fils_cache_id[1]); 10897 if (os_snprintf_error(end - pos2, ret)) 10898 break; 10899 pos2 += ret; 10900 } 10901 10902 ret = os_snprintf(pos2, end - pos2, "\n"); 10903 if (os_snprintf_error(end - pos2, ret)) 10904 break; 10905 pos2 += ret; 10906 10907 pos = pos2; 10908 } 10909 10910 return pos - buf; 10911 } 10912 10913 10914 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s, 10915 char *cmd) 10916 { 10917 struct rsn_pmksa_cache_entry *entry; 10918 struct wpa_ssid *ssid; 10919 char *pos, *pos2; 10920 int ret = -1; 10921 struct os_reltime now; 10922 int reauth_time = 0, expiration = 0, i; 10923 10924 /* 10925 * Entry format: 10926 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> 10927 * <expiration in seconds> <akmp> <opportunistic> 10928 * [FILS Cache Identifier] 10929 */ 10930 10931 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 10932 if (!ssid) 10933 return -1; 10934 10935 pos = os_strchr(cmd, ' '); 10936 if (!pos) 10937 return -1; 10938 pos++; 10939 10940 entry = os_zalloc(sizeof(*entry)); 10941 if (!entry) 10942 return -1; 10943 10944 if (hwaddr_aton(pos, entry->aa)) 10945 goto fail; 10946 10947 pos = os_strchr(pos, ' '); 10948 if (!pos) 10949 goto fail; 10950 pos++; 10951 10952 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0) 10953 goto fail; 10954 10955 pos = os_strchr(pos, ' '); 10956 if (!pos) 10957 goto fail; 10958 pos++; 10959 10960 pos2 = os_strchr(pos, ' '); 10961 if (!pos2) 10962 goto fail; 10963 entry->pmk_len = (pos2 - pos) / 2; 10964 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX || 10965 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0) 10966 goto fail; 10967 10968 pos = os_strchr(pos, ' '); 10969 if (!pos) 10970 goto fail; 10971 pos++; 10972 10973 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration, 10974 &entry->akmp, &entry->opportunistic) != 4) 10975 goto fail; 10976 if (reauth_time > expiration) 10977 goto fail; 10978 for (i = 0; i < 4; i++) { 10979 pos = os_strchr(pos, ' '); 10980 if (!pos) { 10981 if (i < 3) 10982 goto fail; 10983 break; 10984 } 10985 pos++; 10986 } 10987 if (pos) { 10988 if (hexstr2bin(pos, entry->fils_cache_id, 10989 FILS_CACHE_ID_LEN) < 0) 10990 goto fail; 10991 entry->fils_cache_id_set = 1; 10992 } 10993 os_get_reltime(&now); 10994 entry->expiration = now.sec + expiration; 10995 entry->reauth_time = now.sec + reauth_time; 10996 10997 entry->network_ctx = ssid; 10998 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN); 10999 11000 entry->external = true; 11001 11002 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); 11003 entry = NULL; 11004 ret = 0; 11005 fail: 11006 os_free(entry); 11007 return ret; 11008 } 11009 11010 11011 #ifdef CONFIG_MESH 11012 11013 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, 11014 const char *cmd, char *buf, 11015 size_t buflen) 11016 { 11017 u8 spa[ETH_ALEN]; 11018 11019 if (!wpa_s->ifmsh) 11020 return -1; 11021 11022 if (os_strcasecmp(cmd, "any") == 0) 11023 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); 11024 11025 if (hwaddr_aton(cmd, spa)) 11026 return -1; 11027 11028 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); 11029 } 11030 11031 11032 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, 11033 char *cmd) 11034 { 11035 /* 11036 * We do not check mesh interface existence because PMKSA should be 11037 * stored before wpa_s->ifmsh creation to suppress commit message 11038 * creation. 11039 */ 11040 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); 11041 } 11042 11043 #endif /* CONFIG_MESH */ 11044 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 11045 11046 11047 #ifdef CONFIG_FILS 11048 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s, 11049 const char *cmd) 11050 { 11051 struct fils_hlp_req *req; 11052 const char *pos; 11053 11054 /* format: <dst> <packet starting from ethertype> */ 11055 11056 req = os_zalloc(sizeof(*req)); 11057 if (!req) 11058 return -1; 11059 11060 if (hwaddr_aton(cmd, req->dst)) 11061 goto fail; 11062 11063 pos = os_strchr(cmd, ' '); 11064 if (!pos) 11065 goto fail; 11066 pos++; 11067 req->pkt = wpabuf_parse_bin(pos); 11068 if (!req->pkt) 11069 goto fail; 11070 11071 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list); 11072 return 0; 11073 fail: 11074 wpabuf_free(req->pkt); 11075 os_free(req); 11076 return -1; 11077 } 11078 #endif /* CONFIG_FILS */ 11079 11080 11081 int wpas_ctrl_cmd_debug_level(const char *cmd) 11082 { 11083 if (os_strcmp(cmd, "PING") == 0 || 11084 os_strncmp(cmd, "BSS ", 4) == 0 || 11085 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 || 11086 os_strncmp(cmd, "STATUS", 6) == 0 || 11087 os_strncmp(cmd, "STA ", 4) == 0 || 11088 os_strncmp(cmd, "STA-", 4) == 0) 11089 return MSG_EXCESSIVE; 11090 return MSG_DEBUG; 11091 } 11092 11093 11094 #ifndef CONFIG_NO_ROBUST_AV 11095 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s, 11096 const char *cmd) 11097 { 11098 size_t frame_classifier_len; 11099 const char *pos, *end; 11100 struct robust_av_data *robust_av = &wpa_s->robust_av; 11101 int val; 11102 11103 /* 11104 * format: 11105 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>] 11106 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>] 11107 */ 11108 os_memset(robust_av, 0, sizeof(struct robust_av_data)); 11109 if (os_strncmp(cmd, "add ", 4) == 0) { 11110 robust_av->request_type = SCS_REQ_ADD; 11111 } else if (os_strcmp(cmd, "remove") == 0) { 11112 robust_av->request_type = SCS_REQ_REMOVE; 11113 robust_av->valid_config = false; 11114 return wpas_send_mscs_req(wpa_s); 11115 } else if (os_strncmp(cmd, "change ", 7) == 0) { 11116 robust_av->request_type = SCS_REQ_CHANGE; 11117 } else { 11118 return -1; 11119 } 11120 11121 pos = os_strstr(cmd, "up_bitmap="); 11122 if (!pos) 11123 return -1; 11124 11125 val = hex2byte(pos + 10); 11126 if (val < 0) 11127 return -1; 11128 robust_av->up_bitmap = val; 11129 11130 pos = os_strstr(cmd, "up_limit="); 11131 if (!pos) 11132 return -1; 11133 11134 robust_av->up_limit = atoi(pos + 9); 11135 11136 pos = os_strstr(cmd, "stream_timeout="); 11137 if (!pos) 11138 return -1; 11139 11140 robust_av->stream_timeout = atoi(pos + 15); 11141 if (robust_av->stream_timeout == 0) 11142 return -1; 11143 11144 pos = os_strstr(cmd, "frame_classifier="); 11145 if (!pos) 11146 return -1; 11147 11148 pos += 17; 11149 end = os_strchr(pos, ' '); 11150 if (!end) 11151 end = pos + os_strlen(pos); 11152 11153 frame_classifier_len = (end - pos) / 2; 11154 if (frame_classifier_len > sizeof(robust_av->frame_classifier) || 11155 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len)) 11156 return -1; 11157 11158 robust_av->frame_classifier_len = frame_classifier_len; 11159 robust_av->valid_config = true; 11160 11161 return wpas_send_mscs_req(wpa_s); 11162 } 11163 #endif /* CONFIG_NO_ROBUST_AV */ 11164 11165 11166 #ifdef CONFIG_PASN 11167 static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd) 11168 { 11169 char *token, *context = NULL; 11170 u8 bssid[ETH_ALEN]; 11171 int akmp = -1, cipher = -1, got_bssid = 0; 11172 u16 group = 0xFFFF; 11173 u8 *comeback = NULL; 11174 size_t comeback_len = 0; 11175 int id = 0, ret = -1; 11176 11177 /* 11178 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group> 11179 * [comeback=<hexdump>] 11180 */ 11181 while ((token = str_token(cmd, " ", &context))) { 11182 if (os_strncmp(token, "bssid=", 6) == 0) { 11183 if (hwaddr_aton(token + 6, bssid)) 11184 goto out; 11185 got_bssid = 1; 11186 } else if (os_strcmp(token, "akmp=PASN") == 0) { 11187 akmp = WPA_KEY_MGMT_PASN; 11188 #ifdef CONFIG_IEEE80211R 11189 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) { 11190 akmp = WPA_KEY_MGMT_FT_PSK; 11191 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) { 11192 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; 11193 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) { 11194 akmp = WPA_KEY_MGMT_FT_IEEE8021X; 11195 #endif /* CONFIG_IEEE80211R */ 11196 #ifdef CONFIG_SAE 11197 } else if (os_strcmp(token, "akmp=SAE") == 0) { 11198 akmp = WPA_KEY_MGMT_SAE; 11199 } else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) { 11200 akmp = WPA_KEY_MGMT_SAE_EXT_KEY; 11201 #endif /* CONFIG_SAE */ 11202 #ifdef CONFIG_FILS 11203 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) { 11204 akmp = WPA_KEY_MGMT_FILS_SHA256; 11205 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) { 11206 akmp = WPA_KEY_MGMT_FILS_SHA384; 11207 #endif /* CONFIG_FILS */ 11208 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) { 11209 cipher = WPA_CIPHER_CCMP_256; 11210 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) { 11211 cipher = WPA_CIPHER_GCMP_256; 11212 } else if (os_strcmp(token, "cipher=CCMP") == 0) { 11213 cipher = WPA_CIPHER_CCMP; 11214 } else if (os_strcmp(token, "cipher=GCMP") == 0) { 11215 cipher = WPA_CIPHER_GCMP; 11216 } else if (os_strncmp(token, "group=", 6) == 0) { 11217 group = atoi(token + 6); 11218 } else if (os_strncmp(token, "nid=", 4) == 0) { 11219 id = atoi(token + 4); 11220 } else if (os_strncmp(token, "comeback=", 9) == 0) { 11221 comeback_len = os_strlen(token + 9); 11222 if (comeback || !comeback_len || comeback_len % 2) 11223 goto out; 11224 11225 comeback_len /= 2; 11226 comeback = os_malloc(comeback_len); 11227 if (!comeback || 11228 hexstr2bin(token + 9, comeback, comeback_len)) 11229 goto out; 11230 } else { 11231 wpa_printf(MSG_DEBUG, 11232 "CTRL: PASN Invalid parameter: '%s'", 11233 token); 11234 goto out; 11235 } 11236 } 11237 11238 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) { 11239 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter"); 11240 goto out; 11241 } 11242 11243 ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher, 11244 group, id, comeback, comeback_len); 11245 out: 11246 os_free(comeback); 11247 return ret; 11248 } 11249 11250 11251 static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s, 11252 const char *cmd) 11253 { 11254 u8 bssid[ETH_ALEN]; 11255 11256 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) { 11257 wpa_printf(MSG_DEBUG, 11258 "CTRL: PASN_DEAUTH without valid BSSID"); 11259 return -1; 11260 } 11261 11262 return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid); 11263 } 11264 11265 11266 #ifdef CONFIG_TESTING_OPTIONS 11267 static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s, 11268 const char *cmd) 11269 { 11270 union wpa_event_data event; 11271 const char *pos = cmd; 11272 u8 addr[ETH_ALEN]; 11273 11274 os_memset(&event, 0, sizeof(event)); 11275 11276 if (os_strncmp(pos, "auth ", 5) == 0) 11277 event.pasn_auth.action = PASN_ACTION_AUTH; 11278 else if (os_strncmp(pos, "del ", 4) == 0) 11279 event.pasn_auth.action = 11280 PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT; 11281 else 11282 return -1; 11283 11284 pos = os_strchr(pos, ' '); 11285 if (!pos) 11286 return -1; 11287 pos++; 11288 while (hwaddr_aton(pos, addr) == 0) { 11289 struct pasn_peer *peer; 11290 11291 if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS) 11292 return -1; 11293 peer = &event.pasn_auth.peer[event.pasn_auth.num_peers]; 11294 os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN); 11295 os_memcpy(peer->peer_addr, addr, ETH_ALEN); 11296 event.pasn_auth.num_peers++; 11297 11298 pos = os_strchr(pos, ' '); 11299 if (!pos) 11300 break; 11301 pos++; 11302 } 11303 11304 wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event); 11305 return 0; 11306 } 11307 #endif /* CONFIG_TESTING_OPTIONS */ 11308 11309 #endif /* CONFIG_PASN */ 11310 11311 11312 #ifndef CONFIG_NO_ROBUST_AV 11313 11314 static int set_type4_frame_classifier(const char *cmd, 11315 struct type4_params *param) 11316 { 11317 const char *pos, *end; 11318 u8 classifier_mask = 0; 11319 int ret; 11320 char addr[INET6_ADDRSTRLEN]; 11321 size_t alen; 11322 11323 if (os_strstr(cmd, "ip_version=ipv4")) { 11324 param->ip_version = IPV4; 11325 } else if (os_strstr(cmd, "ip_version=ipv6")) { 11326 param->ip_version = IPV6; 11327 } else { 11328 wpa_printf(MSG_ERROR, "IP version missing/invalid"); 11329 return -1; 11330 } 11331 11332 classifier_mask |= BIT(0); 11333 11334 pos = os_strstr(cmd, "src_ip="); 11335 if (pos) { 11336 pos += 7; 11337 end = os_strchr(pos, ' '); 11338 if (!end) 11339 end = pos + os_strlen(pos); 11340 11341 alen = end - pos; 11342 if (alen >= INET6_ADDRSTRLEN) 11343 return -1; 11344 os_memcpy(addr, pos, alen); 11345 addr[alen] = '\0'; 11346 if (param->ip_version == IPV4) 11347 ret = inet_pton(AF_INET, addr, 11348 ¶m->ip_params.v4.src_ip); 11349 else 11350 ret = inet_pton(AF_INET6, addr, 11351 ¶m->ip_params.v6.src_ip); 11352 11353 if (ret != 1) { 11354 wpa_printf(MSG_ERROR, 11355 "Error converting src IP address to binary ret=%d", 11356 ret); 11357 return -1; 11358 } 11359 11360 classifier_mask |= BIT(1); 11361 } 11362 11363 pos = os_strstr(cmd, "dst_ip="); 11364 if (pos) { 11365 pos += 7; 11366 end = os_strchr(pos, ' '); 11367 if (!end) 11368 end = pos + os_strlen(pos); 11369 11370 alen = end - pos; 11371 if (alen >= INET6_ADDRSTRLEN) 11372 return -1; 11373 os_memcpy(addr, pos, alen); 11374 addr[alen] = '\0'; 11375 if (param->ip_version == IPV4) 11376 ret = inet_pton(AF_INET, addr, 11377 ¶m->ip_params.v4.dst_ip); 11378 else 11379 ret = inet_pton(AF_INET6, addr, 11380 ¶m->ip_params.v6.dst_ip); 11381 11382 if (ret != 1) { 11383 wpa_printf(MSG_ERROR, 11384 "Error converting dst IP address to binary ret=%d", 11385 ret); 11386 return -1; 11387 } 11388 11389 classifier_mask |= BIT(2); 11390 } 11391 11392 pos = os_strstr(cmd, "src_port="); 11393 if (pos && atoi(pos + 9) > 0) { 11394 if (param->ip_version == IPV4) 11395 param->ip_params.v4.src_port = atoi(pos + 9); 11396 else 11397 param->ip_params.v6.src_port = atoi(pos + 9); 11398 classifier_mask |= BIT(3); 11399 } 11400 11401 pos = os_strstr(cmd, "dst_port="); 11402 if (pos && atoi(pos + 9) > 0) { 11403 if (param->ip_version == IPV4) 11404 param->ip_params.v4.dst_port = atoi(pos + 9); 11405 else 11406 param->ip_params.v6.dst_port = atoi(pos + 9); 11407 classifier_mask |= BIT(4); 11408 } 11409 11410 pos = os_strstr(cmd, "dscp="); 11411 if (pos && atoi(pos + 5) > 0) { 11412 if (param->ip_version == IPV4) 11413 param->ip_params.v4.dscp = atoi(pos + 5); 11414 else 11415 param->ip_params.v6.dscp = atoi(pos + 5); 11416 classifier_mask |= BIT(5); 11417 } 11418 11419 if (param->ip_version == IPV4) { 11420 pos = os_strstr(cmd, "protocol="); 11421 if (pos) { 11422 if (os_strstr(pos, "udp")) { 11423 param->ip_params.v4.protocol = 17; 11424 } else if (os_strstr(pos, "tcp")) { 11425 param->ip_params.v4.protocol = 6; 11426 } else if (os_strstr(pos, "esp")) { 11427 param->ip_params.v4.protocol = 50; 11428 } else { 11429 wpa_printf(MSG_ERROR, "Invalid protocol"); 11430 return -1; 11431 } 11432 classifier_mask |= BIT(6); 11433 } 11434 } else { 11435 pos = os_strstr(cmd, "next_header="); 11436 if (pos) { 11437 if (os_strstr(pos, "udp")) { 11438 param->ip_params.v6.next_header = 17; 11439 } else if (os_strstr(pos, "tcp")) { 11440 param->ip_params.v6.next_header = 6; 11441 } else if (os_strstr(pos, "esp")) { 11442 param->ip_params.v6.next_header = 50; 11443 } else { 11444 wpa_printf(MSG_ERROR, "Invalid next header"); 11445 return -1; 11446 } 11447 11448 classifier_mask |= BIT(6); 11449 } 11450 11451 pos = os_strstr(cmd, "flow_label="); 11452 if (pos) { 11453 pos += 11; 11454 end = os_strchr(pos, ' '); 11455 if (!end) 11456 end = pos + os_strlen(pos); 11457 11458 if (end - pos != 6 || 11459 hexstr2bin(pos, param->ip_params.v6.flow_label, 11460 3) || 11461 param->ip_params.v6.flow_label[0] > 0x0F) { 11462 wpa_printf(MSG_ERROR, "Invalid flow label"); 11463 return -1; 11464 } 11465 11466 classifier_mask |= BIT(7); 11467 } 11468 } 11469 11470 param->classifier_mask = classifier_mask; 11471 return 0; 11472 } 11473 11474 11475 static int set_type10_frame_classifier(const char *cmd, 11476 struct type10_params *param) 11477 { 11478 const char *pos, *end; 11479 size_t filter_len; 11480 11481 pos = os_strstr(cmd, "prot_instance="); 11482 if (!pos) { 11483 wpa_printf(MSG_ERROR, "Protocol instance missing"); 11484 return -1; 11485 } 11486 param->prot_instance = atoi(pos + 14); 11487 11488 pos = os_strstr(cmd, "prot_number="); 11489 if (!pos) { 11490 wpa_printf(MSG_ERROR, "Protocol number missing"); 11491 return -1; 11492 } 11493 if (os_strstr(pos, "udp")) { 11494 param->prot_number = 17; 11495 } else if (os_strstr(pos, "tcp")) { 11496 param->prot_number = 6; 11497 } else if (os_strstr(pos, "esp")) { 11498 param->prot_number = 50; 11499 } else { 11500 wpa_printf(MSG_ERROR, "Invalid protocol number"); 11501 return -1; 11502 } 11503 11504 pos = os_strstr(cmd, "filter_value="); 11505 if (!pos) { 11506 wpa_printf(MSG_ERROR, 11507 "Classifier parameter filter_value missing"); 11508 return -1; 11509 } 11510 11511 pos += 13; 11512 end = os_strchr(pos, ' '); 11513 if (!end) 11514 end = pos + os_strlen(pos); 11515 11516 filter_len = (end - pos) / 2; 11517 param->filter_value = os_malloc(filter_len); 11518 if (!param->filter_value) 11519 return -1; 11520 11521 if (hexstr2bin(pos, param->filter_value, filter_len)) { 11522 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos); 11523 goto free; 11524 } 11525 11526 pos = os_strstr(cmd, "filter_mask="); 11527 if (!pos) { 11528 wpa_printf(MSG_ERROR, 11529 "Classifier parameter filter_mask missing"); 11530 goto free; 11531 } 11532 11533 pos += 12; 11534 end = os_strchr(pos, ' '); 11535 if (!end) 11536 end = pos + os_strlen(pos); 11537 11538 if (filter_len != (size_t) (end - pos) / 2) { 11539 wpa_printf(MSG_ERROR, 11540 "Filter mask length mismatch expected=%zu received=%zu", 11541 filter_len, (size_t) (end - pos) / 2); 11542 goto free; 11543 } 11544 11545 param->filter_mask = os_malloc(filter_len); 11546 if (!param->filter_mask) 11547 goto free; 11548 11549 if (hexstr2bin(pos, param->filter_mask, filter_len)) { 11550 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos); 11551 os_free(param->filter_mask); 11552 param->filter_mask = NULL; 11553 goto free; 11554 } 11555 11556 param->filter_len = filter_len; 11557 return 0; 11558 free: 11559 os_free(param->filter_value); 11560 param->filter_value = NULL; 11561 return -1; 11562 } 11563 11564 11565 static int scs_parse_type4(struct tclas_element *elem, const char *pos) 11566 { 11567 struct type4_params type4_param = { 0 }; 11568 11569 if (set_type4_frame_classifier(pos, &type4_param) == -1) { 11570 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4"); 11571 return -1; 11572 } 11573 11574 os_memcpy(&elem->frame_classifier.type4_param, 11575 &type4_param, sizeof(struct type4_params)); 11576 return 0; 11577 } 11578 11579 11580 static int scs_parse_type10(struct tclas_element *elem, const char *pos) 11581 { 11582 struct type10_params type10_param = { 0 }; 11583 11584 if (set_type10_frame_classifier(pos, &type10_param) == -1) { 11585 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10"); 11586 return -1; 11587 } 11588 11589 os_memcpy(&elem->frame_classifier.type10_param, 11590 &type10_param, sizeof(struct type10_params)); 11591 return 0; 11592 } 11593 11594 11595 static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s, 11596 char *cmd) 11597 { 11598 char *pos1, *pos; 11599 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req; 11600 struct scs_desc_elem desc_elem = { 0 }; 11601 int val; 11602 unsigned int num_scs_desc = 0; 11603 11604 if (wpa_s->ongoing_scs_req) { 11605 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue", 11606 __func__); 11607 return -1; 11608 } 11609 11610 /** 11611 * format: 11612 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>] 11613 * [classifier_type=<4|10>] 11614 * [classifier params based on classifier type] 11615 * [tclas_processing=<0|1>] 11616 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>] 11617 * [max_si=<decimal number>] [min_data_rate=<decimal number>] 11618 * [delay_bound=<decimal number>] [max_msdu=<decimal number>] 11619 * [service_start_time=<decimal number>] 11620 * [service_start_time_link_id=<decimal number>] 11621 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>] 11622 * [msdu_lifetime=<decimal number>] 11623 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>] 11624 * [scs_id=<decimal number>] ... 11625 */ 11626 pos1 = os_strstr(cmd, "scs_id="); 11627 if (!pos1) { 11628 wpa_printf(MSG_ERROR, "SCSID not present"); 11629 return -1; 11630 } 11631 11632 free_up_scs_desc(scs_data); 11633 11634 while (pos1) { 11635 struct scs_desc_elem *n1; 11636 struct active_scs_elem *active_scs_desc; 11637 char *next_scs_desc, *pos2; 11638 unsigned int num_tclas_elem = 0; 11639 bool scsid_active = false, tclas_present = false; 11640 struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem; 11641 11642 desc_elem.scs_id = atoi(pos1 + 7); 11643 pos1 += 7; 11644 11645 next_scs_desc = os_strstr(pos1, "scs_id="); 11646 if (next_scs_desc) { 11647 char temp[20]; 11648 11649 os_snprintf(temp, sizeof(temp), "scs_id=%d ", 11650 desc_elem.scs_id); 11651 if (os_strstr(next_scs_desc, temp)) { 11652 wpa_printf(MSG_ERROR, 11653 "Multiple SCS descriptors configured with same SCSID(=%d)", 11654 desc_elem.scs_id); 11655 goto free_scs_desc; 11656 } 11657 pos1[next_scs_desc - pos1 - 1] = '\0'; 11658 } 11659 11660 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids, 11661 struct active_scs_elem, list) { 11662 if (desc_elem.scs_id == active_scs_desc->scs_id) { 11663 scsid_active = true; 11664 break; 11665 } 11666 } 11667 11668 if (os_strstr(pos1, "add ")) { 11669 desc_elem.request_type = SCS_REQ_ADD; 11670 if (scsid_active) { 11671 wpa_printf(MSG_ERROR, "SCSID %d already active", 11672 desc_elem.scs_id); 11673 return -1; 11674 } 11675 } else if (os_strstr(pos1, "remove")) { 11676 desc_elem.request_type = SCS_REQ_REMOVE; 11677 if (!scsid_active) { 11678 wpa_printf(MSG_ERROR, "SCSID %d not active", 11679 desc_elem.scs_id); 11680 return -1; 11681 } 11682 goto scs_desc_end; 11683 } else if (os_strstr(pos1, "change ")) { 11684 desc_elem.request_type = SCS_REQ_CHANGE; 11685 if (!scsid_active) { 11686 wpa_printf(MSG_ERROR, "SCSID %d not active", 11687 desc_elem.scs_id); 11688 return -1; 11689 } 11690 } else { 11691 wpa_printf(MSG_ERROR, "SCS Request type invalid"); 11692 goto free_scs_desc; 11693 } 11694 11695 pos1 = os_strstr(pos1, "scs_up="); 11696 if (!pos1) { 11697 wpa_printf(MSG_ERROR, 11698 "Intra-Access user priority not present"); 11699 goto free_scs_desc; 11700 } 11701 11702 val = atoi(pos1 + 7); 11703 if (val < 0 || val > 7) { 11704 wpa_printf(MSG_ERROR, 11705 "Intra-Access user priority invalid %d", 11706 val); 11707 goto free_scs_desc; 11708 } 11709 11710 desc_elem.intra_access_priority = val; 11711 desc_elem.scs_up_avail = true; 11712 11713 pos = os_strstr(pos1, "classifier_type="); 11714 if (!pos) { 11715 wpa_printf(MSG_ERROR, "classifier type empty"); 11716 goto qos_characteristics; 11717 } 11718 tclas_present = true; 11719 11720 while (pos) { 11721 struct tclas_element elem = { 0 }, *n; 11722 char *next_tclas_elem; 11723 11724 val = atoi(pos + 16); 11725 if (val != 4 && val != 10) { 11726 wpa_printf(MSG_ERROR, 11727 "classifier type invalid %d", val); 11728 goto free_scs_desc; 11729 } 11730 11731 elem.classifier_type = val; 11732 pos += 16; 11733 11734 next_tclas_elem = os_strstr(pos, "classifier_type="); 11735 if (next_tclas_elem) { 11736 pos1 = next_tclas_elem; 11737 pos[next_tclas_elem - pos - 1] = '\0'; 11738 } 11739 11740 switch (val) { 11741 case 4: 11742 if (scs_parse_type4(&elem, pos) < 0) 11743 goto free_scs_desc; 11744 break; 11745 case 10: 11746 if (scs_parse_type10(&elem, pos) < 0) 11747 goto free_scs_desc; 11748 break; 11749 } 11750 11751 n = os_realloc(desc_elem.tclas_elems, 11752 (num_tclas_elem + 1) * sizeof(elem)); 11753 if (!n) 11754 goto free_scs_desc; 11755 11756 desc_elem.tclas_elems = n; 11757 os_memcpy((u8 *) desc_elem.tclas_elems + 11758 num_tclas_elem * sizeof(elem), 11759 &elem, sizeof(elem)); 11760 num_tclas_elem++; 11761 desc_elem.num_tclas_elem = num_tclas_elem; 11762 pos = next_tclas_elem; 11763 } 11764 11765 if (desc_elem.num_tclas_elem > 1) { 11766 pos1 = os_strstr(pos1, "tclas_processing="); 11767 if (!pos1) { 11768 wpa_printf(MSG_ERROR, "tclas_processing empty"); 11769 goto free_scs_desc; 11770 } 11771 11772 val = atoi(pos1 + 17); 11773 if (val != 0 && val != 1) { 11774 wpa_printf(MSG_ERROR, 11775 "tclas_processing invalid"); 11776 goto free_scs_desc; 11777 } 11778 11779 desc_elem.tclas_processing = val; 11780 } 11781 11782 qos_characteristics: 11783 pos1 = os_strstr(pos1, "qos_characteristics"); 11784 if (!pos1 && !tclas_present) 11785 goto free_scs_desc; 11786 if (!pos1) 11787 goto scs_desc_end; 11788 11789 qos_elem->available = true; 11790 if (os_strstr(pos1, "up ")) { 11791 qos_elem->direction = SCS_DIRECTION_UP; 11792 if (tclas_present) { 11793 wpa_printf(MSG_ERROR, 11794 "TCLAS with direction:UP not allowed"); 11795 goto free_scs_desc; 11796 } 11797 } else if (os_strstr(pos1, "down ")) { 11798 qos_elem->direction = SCS_DIRECTION_DOWN; 11799 } else if (os_strstr(pos1, "direct ")) { 11800 qos_elem->direction = SCS_DIRECTION_DIRECT; 11801 } 11802 11803 pos1 = os_strstr(pos1, "min_si="); 11804 if (!pos1) { 11805 wpa_printf(MSG_ERROR, "Min SI is required"); 11806 goto free_scs_desc; 11807 } 11808 qos_elem->min_si = atoi(pos1 + 7); 11809 11810 pos1 = os_strstr(pos1, "max_si="); 11811 if (!pos1) { 11812 wpa_printf(MSG_ERROR, "Max SI is required"); 11813 goto free_scs_desc; 11814 } 11815 qos_elem->max_si = atoi(pos1 + 7); 11816 11817 if (qos_elem->min_si && qos_elem->max_si && 11818 qos_elem->max_si < qos_elem->min_si) { 11819 wpa_printf(MSG_ERROR, "Invalid Max SI"); 11820 goto free_scs_desc; 11821 } 11822 11823 pos1 = os_strstr(pos1, "min_data_rate="); 11824 if (!pos1) { 11825 wpa_printf(MSG_ERROR, "Min data rate is required"); 11826 goto free_scs_desc; 11827 } 11828 qos_elem->min_data_rate = atoi(pos1 + 14); 11829 11830 pos1 = os_strstr(pos1, "delay_bound="); 11831 if (!pos1) { 11832 wpa_printf(MSG_ERROR, "Delay Bound is required"); 11833 goto free_scs_desc; 11834 } 11835 qos_elem->delay_bound = atoi(pos1 + 12); 11836 11837 if (qos_elem->min_data_rate >= BIT(24) || 11838 qos_elem->delay_bound >= BIT(24)) { 11839 wpa_printf(MSG_ERROR, 11840 "Invalid min_data_rate or delay_bound"); 11841 goto free_scs_desc; 11842 } 11843 11844 pos2 = os_strstr(pos1, "max_msdu="); 11845 if (pos2) { 11846 qos_elem->max_msdu_size = atoi(pos2 + 9); 11847 qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE; 11848 } 11849 11850 pos2 = os_strstr(pos1, "service_start_time="); 11851 if (pos2) { 11852 qos_elem->service_start_time = atoi(pos2 + 19); 11853 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME; 11854 } 11855 11856 pos2 = os_strstr(pos1, "service_start_time_link_id="); 11857 if (pos2) { 11858 qos_elem->service_start_time_link_id = atoi(pos2 + 27); 11859 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID; 11860 } 11861 11862 pos2 = os_strstr(pos1, "mean_data_rate="); 11863 if (pos2) { 11864 qos_elem->mean_data_rate = atoi(pos2 + 15); 11865 qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE; 11866 } 11867 11868 pos2 = os_strstr(pos1, "burst_size="); 11869 if (pos2) { 11870 qos_elem->burst_size = atoi(pos2 + 11); 11871 qos_elem->mask |= 11872 SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE; 11873 } 11874 11875 pos2 = os_strstr(pos1, "msdu_lifetime="); 11876 if (pos2) { 11877 qos_elem->msdu_lifetime = atoi(pos2 + 14); 11878 qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME; 11879 } 11880 11881 pos2 = os_strstr(pos1, "msdu_delivery_info="); 11882 if (pos2) { 11883 qos_elem->msdu_delivery_info = atoi(pos2 + 19); 11884 qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO; 11885 } 11886 11887 pos2 = os_strstr(pos1, "medium_time="); 11888 if (pos2) { 11889 qos_elem->medium_time = atoi(pos2 + 12); 11890 qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME; 11891 } 11892 11893 scs_desc_end: 11894 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) * 11895 sizeof(struct scs_desc_elem)); 11896 if (!n1) 11897 goto free_scs_desc; 11898 11899 scs_data->scs_desc_elems = n1; 11900 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc * 11901 sizeof(desc_elem), &desc_elem, sizeof(desc_elem)); 11902 num_scs_desc++; 11903 scs_data->num_scs_desc = num_scs_desc; 11904 pos1 = next_scs_desc; 11905 os_memset(&desc_elem, 0, sizeof(desc_elem)); 11906 } 11907 11908 return wpas_send_scs_req(wpa_s); 11909 11910 free_scs_desc: 11911 free_up_tclas_elem(&desc_elem); 11912 free_up_scs_desc(scs_data); 11913 return -1; 11914 } 11915 11916 11917 static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s, 11918 const char *cmd) 11919 { 11920 char *pos; 11921 struct dscp_policy_status *policy = NULL, *n; 11922 int num_policies = 0, ret = -1; 11923 struct dscp_resp_data resp_data; 11924 11925 /* 11926 * format: 11927 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more] 11928 */ 11929 11930 os_memset(&resp_data, 0, sizeof(resp_data)); 11931 11932 resp_data.more = os_strstr(cmd, "more") != NULL; 11933 11934 if (os_strstr(cmd, "reset")) { 11935 resp_data.reset = true; 11936 resp_data.solicited = false; 11937 goto send_resp; 11938 } 11939 11940 resp_data.solicited = os_strstr(cmd, "solicited") != NULL; 11941 11942 pos = os_strstr(cmd, "policy_id="); 11943 while (pos) { 11944 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy)); 11945 if (!n) 11946 goto fail; 11947 11948 policy = n; 11949 pos += 10; 11950 policy[num_policies].id = atoi(pos); 11951 if (policy[num_policies].id == 0) { 11952 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id"); 11953 goto fail; 11954 } 11955 11956 pos = os_strstr(pos, "status="); 11957 if (!pos) { 11958 wpa_printf(MSG_ERROR, 11959 "DSCP: Status is not found for a policy"); 11960 goto fail; 11961 } 11962 11963 pos += 7; 11964 policy[num_policies].status = atoi(pos); 11965 num_policies++; 11966 11967 pos = os_strstr(pos, "policy_id"); 11968 } 11969 11970 resp_data.policy = policy; 11971 resp_data.num_policies = num_policies; 11972 send_resp: 11973 ret = wpas_send_dscp_response(wpa_s, &resp_data); 11974 if (ret) 11975 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response"); 11976 fail: 11977 os_free(policy); 11978 return ret; 11979 } 11980 11981 11982 static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s, 11983 const char *cmd) 11984 { 11985 char *pos; 11986 11987 /* 11988 * format: 11989 * Wildcard DSCP query 11990 * <wildcard> 11991 * 11992 * DSCP query with a domain name attribute: 11993 * [domain_name=<string>] 11994 */ 11995 11996 if (os_strstr(cmd, "wildcard")) { 11997 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query"); 11998 return wpas_send_dscp_query(wpa_s, NULL, 0); 11999 } 12000 12001 pos = os_strstr(cmd, "domain_name="); 12002 if (!pos || !os_strlen(pos + 12)) { 12003 wpa_printf(MSG_ERROR, "QM: Domain name not preset"); 12004 return -1; 12005 } 12006 12007 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12)); 12008 } 12009 12010 #endif /* CONFIG_NO_ROBUST_AV */ 12011 12012 12013 static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s, 12014 char *buf, size_t buflen) 12015 { 12016 int ret, i; 12017 char *pos, *end; 12018 struct wpa_mlo_signal_info mlo_si; 12019 12020 if (!wpa_s->valid_links) 12021 return -1; 12022 12023 ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si); 12024 if (ret) 12025 return -1; 12026 12027 pos = buf; 12028 end = buf + buflen; 12029 12030 for_each_link(mlo_si.valid_links, i) { 12031 ret = os_snprintf(pos, end - pos, 12032 "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n" 12033 "NOISE=%d\nFREQUENCY=%u\n", 12034 i, mlo_si.links[i].data.signal, 12035 mlo_si.links[i].data.current_tx_rate / 1000, 12036 mlo_si.links[i].current_noise, 12037 mlo_si.links[i].frequency); 12038 if (os_snprintf_error(end - pos, ret)) 12039 return -1; 12040 pos += ret; 12041 12042 if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) { 12043 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 12044 channel_width_to_string( 12045 mlo_si.links[i].chanwidth)); 12046 if (os_snprintf_error(end - pos, ret)) 12047 return -1; 12048 pos += ret; 12049 } 12050 12051 if (mlo_si.links[i].center_frq1 > 0) { 12052 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 12053 mlo_si.links[i].center_frq1); 12054 if (os_snprintf_error(end - pos, ret)) 12055 return -1; 12056 pos += ret; 12057 } 12058 12059 if (mlo_si.links[i].center_frq2 > 0) { 12060 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 12061 mlo_si.links[i].center_frq2); 12062 if (os_snprintf_error(end - pos, ret)) 12063 return -1; 12064 pos += ret; 12065 } 12066 12067 if (mlo_si.links[i].data.avg_signal) { 12068 ret = os_snprintf(pos, end - pos, 12069 "AVG_RSSI=%d\n", 12070 mlo_si.links[i].data.avg_signal); 12071 if (os_snprintf_error(end - pos, ret)) 12072 return -1; 12073 pos += ret; 12074 } 12075 12076 if (mlo_si.links[i].data.avg_beacon_signal) { 12077 ret = os_snprintf( 12078 pos, end - pos, "AVG_BEACON_RSSI=%d\n", 12079 mlo_si.links[i].data.avg_beacon_signal); 12080 if (os_snprintf_error(end - pos, ret)) 12081 return -1; 12082 pos += ret; 12083 } 12084 } 12085 12086 return pos - buf; 12087 } 12088 12089 12090 static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s, 12091 char *buf, size_t buflen) 12092 { 12093 int ret, i; 12094 char *pos, *end; 12095 12096 if (!wpa_s->valid_links) 12097 return -1; 12098 12099 pos = buf; 12100 end = buf + buflen; 12101 12102 for_each_link(wpa_s->valid_links, i) { 12103 ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n" 12104 "ap_link_addr=" MACSTR 12105 "\nsta_link_addr=" MACSTR "\n", 12106 i, wpa_s->links[i].freq, 12107 MAC2STR(wpa_s->links[i].bssid), 12108 MAC2STR(wpa_s->links[i].addr)); 12109 if (os_snprintf_error(end - pos, ret)) 12110 return pos - buf; 12111 pos += ret; 12112 } 12113 12114 return pos - buf; 12115 } 12116 12117 12118 #ifdef CONFIG_TESTING_OPTIONS 12119 static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd) 12120 { 12121 char *token, *context = NULL; 12122 u8 bssid[ETH_ALEN]; 12123 int mld_id = -1, link_id = -1; 12124 struct wpa_bss *bss; 12125 int *freqs; 12126 12127 os_memset(bssid, 0, sizeof(bssid)); 12128 12129 while ((token = str_token(cmd, " ", &context))) { 12130 if (os_strncmp(token, "bssid=", 6) == 0) { 12131 if (hwaddr_aton(token + 6, bssid)) 12132 return -1; 12133 } else if (os_strncmp(token, "mld_id=", 7) == 0) { 12134 mld_id = atoi(token + 7); 12135 } else if (os_strncmp(token, "link_id=", 8) == 0) { 12136 link_id = atoi(token + 8); 12137 } 12138 } 12139 12140 if (is_zero_ether_addr(bssid)) { 12141 wpa_printf(MSG_DEBUG, 12142 "MLD: Failed parsing ML probe request arguments"); 12143 return -1; 12144 } 12145 12146 bss = wpa_bss_get_bssid(wpa_s, bssid); 12147 if (!bss) { 12148 wpa_printf(MSG_DEBUG, 12149 "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid)); 12150 return -1; 12151 } 12152 12153 if (wpa_s->sched_scanning || wpa_s->scanning || 12154 (wpa_s->wpa_state > WPA_SCANNING && 12155 wpa_s->wpa_state != WPA_COMPLETED)) { 12156 wpa_printf(MSG_DEBUG, 12157 "MLO: Ongoing scan: Reject ML probe request"); 12158 return -1; 12159 } 12160 12161 freqs = os_malloc(sizeof(int) * 2); 12162 if (!freqs) 12163 return -1; 12164 12165 freqs[0] = bss->freq; 12166 freqs[1] = 0; 12167 12168 wpa_s->manual_scan_passive = 0; 12169 wpa_s->manual_scan_use_id = 0; 12170 wpa_s->manual_scan_only_new = 0; 12171 wpa_s->scan_id_count = 0; 12172 wpa_s->scan_res_handler = scan_only_handler; 12173 os_free(wpa_s->manual_scan_freqs); 12174 wpa_s->manual_scan_freqs = freqs; 12175 12176 os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN); 12177 wpa_s->ml_probe_mld_id = mld_id; 12178 if (link_id >= 0) 12179 wpa_s->ml_probe_links = BIT(link_id); 12180 12181 wpa_s->normal_scans = 0; 12182 wpa_s->scan_req = MANUAL_SCAN_REQ; 12183 wpa_s->after_wps = 0; 12184 wpa_s->known_wps_freq = 0; 12185 wpa_supplicant_req_scan(wpa_s, 0, 0); 12186 12187 return 0; 12188 } 12189 #endif /* CONFIG_TESTING_OPTIONS */ 12190 12191 12192 #ifdef CONFIG_NAN_USD 12193 12194 static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd, 12195 char *buf, size_t buflen) 12196 { 12197 char *token, *context = NULL; 12198 int publish_id; 12199 struct nan_publish_params params; 12200 const char *service_name = NULL; 12201 struct wpabuf *ssi = NULL; 12202 int ret = -1; 12203 enum nan_service_protocol_type srv_proto_type = 0; 12204 int *freq_list = NULL; 12205 12206 os_memset(¶ms, 0, sizeof(params)); 12207 /* USD shall use both solicited and unsolicited transmissions */ 12208 params.unsolicited = true; 12209 params.solicited = true; 12210 /* USD shall require FSD without GAS */ 12211 params.fsd = true; 12212 params.freq = NAN_USD_DEFAULT_FREQ; 12213 12214 while ((token = str_token(cmd, " ", &context))) { 12215 if (os_strncmp(token, "service_name=", 13) == 0) { 12216 service_name = token + 13; 12217 continue; 12218 } 12219 12220 if (os_strncmp(token, "ttl=", 4) == 0) { 12221 params.ttl = atoi(token + 4); 12222 continue; 12223 } 12224 12225 if (os_strncmp(token, "freq=", 5) == 0) { 12226 params.freq = atoi(token + 5); 12227 continue; 12228 } 12229 12230 if (os_strncmp(token, "freq_list=", 10) == 0) { 12231 char *pos = token + 10; 12232 12233 if (os_strcmp(pos, "all") == 0) { 12234 os_free(freq_list); 12235 freq_list = wpas_nan_usd_all_freqs(wpa_s); 12236 params.freq_list = freq_list; 12237 continue; 12238 } 12239 12240 while (pos && pos[0]) { 12241 int_array_add_unique(&freq_list, atoi(pos)); 12242 pos = os_strchr(pos, ','); 12243 if (pos) 12244 pos++; 12245 } 12246 12247 params.freq_list = freq_list; 12248 continue; 12249 } 12250 12251 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 12252 srv_proto_type = atoi(token + 15); 12253 continue; 12254 } 12255 12256 if (os_strncmp(token, "ssi=", 4) == 0) { 12257 if (ssi) 12258 goto fail; 12259 ssi = wpabuf_parse_bin(token + 4); 12260 if (!ssi) 12261 goto fail; 12262 continue; 12263 } 12264 12265 if (os_strcmp(token, "solicited=0") == 0) { 12266 params.solicited = false; 12267 continue; 12268 } 12269 12270 if (os_strcmp(token, "unsolicited=0") == 0) { 12271 params.unsolicited = false; 12272 continue; 12273 } 12274 12275 if (os_strcmp(token, "fsd=0") == 0) { 12276 params.fsd = false; 12277 continue; 12278 } 12279 12280 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s", 12281 token); 12282 goto fail; 12283 } 12284 12285 publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type, 12286 ssi, ¶ms); 12287 if (publish_id > 0) 12288 ret = os_snprintf(buf, buflen, "%d", publish_id); 12289 fail: 12290 wpabuf_free(ssi); 12291 os_free(freq_list); 12292 return ret; 12293 } 12294 12295 12296 static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s, 12297 char *cmd) 12298 { 12299 char *token, *context = NULL; 12300 int publish_id = 0; 12301 12302 while ((token = str_token(cmd, " ", &context))) { 12303 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 12304 continue; 12305 wpa_printf(MSG_INFO, 12306 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s", 12307 token); 12308 return -1; 12309 } 12310 12311 if (publish_id <= 0) { 12312 wpa_printf(MSG_INFO, 12313 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id"); 12314 return -1; 12315 } 12316 12317 wpas_nan_usd_cancel_publish(wpa_s, publish_id); 12318 return 0; 12319 } 12320 12321 12322 static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s, 12323 char *cmd) 12324 { 12325 char *token, *context = NULL; 12326 int publish_id = 0; 12327 struct wpabuf *ssi = NULL; 12328 int ret = -1; 12329 12330 while ((token = str_token(cmd, " ", &context))) { 12331 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 12332 continue; 12333 if (os_strncmp(token, "ssi=", 4) == 0) { 12334 if (ssi) 12335 goto fail; 12336 ssi = wpabuf_parse_bin(token + 4); 12337 if (!ssi) 12338 goto fail; 12339 continue; 12340 } 12341 wpa_printf(MSG_INFO, 12342 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s", 12343 token); 12344 goto fail; 12345 } 12346 12347 if (publish_id <= 0) { 12348 wpa_printf(MSG_INFO, 12349 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id"); 12350 goto fail; 12351 } 12352 12353 ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi); 12354 fail: 12355 wpabuf_free(ssi); 12356 return ret; 12357 } 12358 12359 12360 static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd, 12361 char *buf, size_t buflen) 12362 { 12363 char *token, *context = NULL; 12364 int subscribe_id; 12365 struct nan_subscribe_params params; 12366 const char *service_name = NULL; 12367 struct wpabuf *ssi = NULL; 12368 int ret = -1; 12369 enum nan_service_protocol_type srv_proto_type = 0; 12370 12371 os_memset(¶ms, 0, sizeof(params)); 12372 params.freq = NAN_USD_DEFAULT_FREQ; 12373 12374 while ((token = str_token(cmd, " ", &context))) { 12375 if (os_strncmp(token, "service_name=", 13) == 0) { 12376 service_name = token + 13; 12377 continue; 12378 } 12379 12380 if (os_strcmp(token, "active=1") == 0) { 12381 params.active = true; 12382 continue; 12383 } 12384 12385 if (os_strncmp(token, "ttl=", 4) == 0) { 12386 params.ttl = atoi(token + 4); 12387 continue; 12388 } 12389 12390 if (os_strncmp(token, "freq=", 5) == 0) { 12391 params.freq = atoi(token + 5); 12392 continue; 12393 } 12394 12395 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 12396 srv_proto_type = atoi(token + 15); 12397 continue; 12398 } 12399 12400 if (os_strncmp(token, "ssi=", 4) == 0) { 12401 if (ssi) 12402 goto fail; 12403 ssi = wpabuf_parse_bin(token + 4); 12404 if (!ssi) 12405 goto fail; 12406 continue; 12407 } 12408 12409 wpa_printf(MSG_INFO, 12410 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s", 12411 token); 12412 goto fail; 12413 } 12414 12415 subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name, 12416 srv_proto_type, ssi, 12417 ¶ms); 12418 if (subscribe_id > 0) 12419 ret = os_snprintf(buf, buflen, "%d", subscribe_id); 12420 fail: 12421 wpabuf_free(ssi); 12422 return ret; 12423 } 12424 12425 12426 static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s, 12427 char *cmd) 12428 { 12429 char *token, *context = NULL; 12430 int subscribe_id = 0; 12431 12432 while ((token = str_token(cmd, " ", &context))) { 12433 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1) 12434 continue; 12435 wpa_printf(MSG_INFO, 12436 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s", 12437 token); 12438 return -1; 12439 } 12440 12441 if (subscribe_id <= 0) { 12442 wpa_printf(MSG_INFO, 12443 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id"); 12444 return -1; 12445 } 12446 12447 wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id); 12448 return 0; 12449 } 12450 12451 12452 static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd) 12453 { 12454 char *token, *context = NULL; 12455 int handle = 0; 12456 int req_instance_id = 0; 12457 struct wpabuf *ssi = NULL; 12458 u8 peer_addr[ETH_ALEN]; 12459 int ret = -1; 12460 12461 os_memset(peer_addr, 0, ETH_ALEN); 12462 12463 while ((token = str_token(cmd, " ", &context))) { 12464 if (sscanf(token, "handle=%i", &handle) == 1) 12465 continue; 12466 12467 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1) 12468 continue; 12469 12470 if (os_strncmp(token, "address=", 8) == 0) { 12471 if (hwaddr_aton(token + 8, peer_addr) < 0) 12472 return -1; 12473 continue; 12474 } 12475 12476 if (os_strncmp(token, "ssi=", 4) == 0) { 12477 if (ssi) 12478 goto fail; 12479 ssi = wpabuf_parse_bin(token + 4); 12480 if (!ssi) 12481 goto fail; 12482 continue; 12483 } 12484 12485 wpa_printf(MSG_INFO, 12486 "CTRL: Invalid NAN_TRANSMIT parameter: %s", 12487 token); 12488 goto fail; 12489 } 12490 12491 if (handle <= 0) { 12492 wpa_printf(MSG_INFO, 12493 "CTRL: Invalid or missing NAN_TRANSMIT handle"); 12494 goto fail; 12495 } 12496 12497 if (is_zero_ether_addr(peer_addr)) { 12498 wpa_printf(MSG_INFO, 12499 "CTRL: Invalid or missing NAN_TRANSMIT address"); 12500 goto fail; 12501 } 12502 12503 ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr, 12504 req_instance_id); 12505 fail: 12506 wpabuf_free(ssi); 12507 return ret; 12508 } 12509 12510 #endif /* CONFIG_NAN_USD */ 12511 12512 12513 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 12514 char *buf, size_t *resp_len) 12515 { 12516 char *reply; 12517 const int reply_size = 4096; 12518 int reply_len; 12519 12520 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 12521 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 12522 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 || 12523 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 12524 if (wpa_debug_show_keys) 12525 wpa_dbg(wpa_s, MSG_DEBUG, 12526 "Control interface command '%s'", buf); 12527 else 12528 wpa_dbg(wpa_s, MSG_DEBUG, 12529 "Control interface command '%s [REMOVED]'", 12530 os_strncmp(buf, WPA_CTRL_RSP, 12531 os_strlen(WPA_CTRL_RSP)) == 0 ? 12532 WPA_CTRL_RSP : 12533 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ? 12534 "SET_NETWORK" : "key-add")); 12535 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 12536 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { 12537 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 12538 (const u8 *) buf, os_strlen(buf)); 12539 } else { 12540 int level = wpas_ctrl_cmd_debug_level(buf); 12541 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 12542 } 12543 12544 reply = os_malloc(reply_size); 12545 if (reply == NULL) { 12546 *resp_len = 1; 12547 return NULL; 12548 } 12549 12550 os_memcpy(reply, "OK\n", 3); 12551 reply_len = 3; 12552 12553 if (os_strcmp(buf, "PING") == 0) { 12554 os_memcpy(reply, "PONG\n", 5); 12555 reply_len = 5; 12556 } else if (os_strcmp(buf, "IFNAME") == 0) { 12557 reply_len = os_strlen(wpa_s->ifname); 12558 os_memcpy(reply, wpa_s->ifname, reply_len); 12559 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 12560 if (wpa_debug_reopen_file() < 0) 12561 reply_len = -1; 12562 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 12563 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 12564 } else if (os_strcmp(buf, "MIB") == 0) { 12565 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 12566 if (reply_len >= 0) { 12567 reply_len += eapol_sm_get_mib(wpa_s->eapol, 12568 reply + reply_len, 12569 reply_size - reply_len); 12570 #ifdef CONFIG_MACSEC 12571 reply_len += ieee802_1x_kay_get_mib( 12572 wpa_s->kay, reply + reply_len, 12573 reply_size - reply_len); 12574 #endif /* CONFIG_MACSEC */ 12575 } 12576 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 12577 reply_len = wpa_supplicant_ctrl_iface_status( 12578 wpa_s, buf + 6, reply, reply_size); 12579 } else if (os_strcmp(buf, "PMKSA") == 0) { 12580 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); 12581 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 12582 wpas_ctrl_iface_pmksa_flush(wpa_s); 12583 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 12584 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) { 12585 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10, 12586 reply, reply_size); 12587 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 12588 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) 12589 reply_len = -1; 12590 #ifdef CONFIG_MESH 12591 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { 12592 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, 12593 reply, reply_size); 12594 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 12595 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) 12596 reply_len = -1; 12597 #endif /* CONFIG_MESH */ 12598 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 12599 } else if (os_strncmp(buf, "SET ", 4) == 0) { 12600 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 12601 reply_len = -1; 12602 } else if (os_strncmp(buf, "DUMP", 4) == 0) { 12603 reply_len = wpa_config_dump_values(wpa_s->conf, 12604 reply, reply_size); 12605 } else if (os_strncmp(buf, "GET ", 4) == 0) { 12606 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 12607 reply, reply_size); 12608 } else if (os_strcmp(buf, "LOGON") == 0) { 12609 eapol_sm_notify_logoff(wpa_s->eapol, false); 12610 } else if (os_strcmp(buf, "LOGOFF") == 0) { 12611 eapol_sm_notify_logoff(wpa_s->eapol, true); 12612 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 12613 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 12614 reply_len = -1; 12615 else 12616 wpas_request_connection(wpa_s); 12617 } else if (os_strcmp(buf, "REATTACH") == 0) { 12618 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || 12619 !wpa_s->current_ssid) 12620 reply_len = -1; 12621 else { 12622 wpa_s->reattach = 1; 12623 wpas_request_connection(wpa_s); 12624 } 12625 } else if (os_strcmp(buf, "RECONNECT") == 0) { 12626 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 12627 reply_len = -1; 12628 else if (wpa_s->disconnected) 12629 wpas_request_connection(wpa_s); 12630 #ifdef IEEE8021X_EAPOL 12631 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 12632 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 12633 reply_len = -1; 12634 #endif /* IEEE8021X_EAPOL */ 12635 #ifdef CONFIG_IEEE80211R 12636 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 12637 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 12638 reply_len = -1; 12639 #endif /* CONFIG_IEEE80211R */ 12640 #ifdef CONFIG_WPS 12641 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 12642 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 12643 if (res == -2) { 12644 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12645 reply_len = 17; 12646 } else if (res) 12647 reply_len = -1; 12648 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 12649 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 12650 if (res == -2) { 12651 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12652 reply_len = 17; 12653 } else if (res) 12654 reply_len = -1; 12655 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 12656 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 12657 reply, 12658 reply_size); 12659 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 12660 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 12661 wpa_s, buf + 14, reply, reply_size); 12662 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 12663 if (wpas_wps_cancel(wpa_s)) 12664 reply_len = -1; 12665 #ifdef CONFIG_WPS_NFC 12666 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 12667 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 12668 reply_len = -1; 12669 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 12670 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 12671 reply_len = -1; 12672 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 12673 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( 12674 wpa_s, buf + 21, reply, reply_size); 12675 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 12676 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 12677 wpa_s, buf + 14, reply, reply_size); 12678 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 12679 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 12680 buf + 17)) 12681 reply_len = -1; 12682 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 12683 reply_len = wpas_ctrl_nfc_get_handover_req( 12684 wpa_s, buf + 21, reply, reply_size); 12685 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 12686 reply_len = wpas_ctrl_nfc_get_handover_sel( 12687 wpa_s, buf + 21, reply, reply_size); 12688 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 12689 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20)) 12690 reply_len = -1; 12691 #endif /* CONFIG_WPS_NFC */ 12692 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 12693 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 12694 reply_len = -1; 12695 #ifdef CONFIG_AP 12696 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 12697 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 12698 wpa_s, buf + 11, reply, reply_size); 12699 #endif /* CONFIG_AP */ 12700 #ifdef CONFIG_WPS_ER 12701 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 12702 if (wpas_wps_er_start(wpa_s, NULL)) 12703 reply_len = -1; 12704 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 12705 if (wpas_wps_er_start(wpa_s, buf + 13)) 12706 reply_len = -1; 12707 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 12708 wpas_wps_er_stop(wpa_s); 12709 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 12710 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 12711 reply_len = -1; 12712 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 12713 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 12714 if (ret == -2) { 12715 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12716 reply_len = 17; 12717 } else if (ret == -3) { 12718 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 12719 reply_len = 18; 12720 } else if (ret == -4) { 12721 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 12722 reply_len = 20; 12723 } else if (ret) 12724 reply_len = -1; 12725 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 12726 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 12727 reply_len = -1; 12728 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 12729 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 12730 buf + 18)) 12731 reply_len = -1; 12732 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 12733 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 12734 reply_len = -1; 12735 #ifdef CONFIG_WPS_NFC 12736 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 12737 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 12738 wpa_s, buf + 24, reply, reply_size); 12739 #endif /* CONFIG_WPS_NFC */ 12740 #endif /* CONFIG_WPS_ER */ 12741 #endif /* CONFIG_WPS */ 12742 #ifdef CONFIG_IBSS_RSN 12743 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 12744 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 12745 reply_len = -1; 12746 #endif /* CONFIG_IBSS_RSN */ 12747 #ifdef CONFIG_MESH 12748 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) { 12749 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 12750 wpa_s, buf + 19, reply, reply_size); 12751 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) { 12752 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 12753 wpa_s, "", reply, reply_size); 12754 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) { 12755 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15)) 12756 reply_len = -1; 12757 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) { 12758 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s, 12759 buf + 18)) 12760 reply_len = -1; 12761 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) { 12762 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17)) 12763 reply_len = -1; 12764 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) { 12765 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14)) 12766 reply_len = -1; 12767 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) { 12768 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16)) 12769 reply_len = -1; 12770 #endif /* CONFIG_MESH */ 12771 #ifdef CONFIG_P2P 12772 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 12773 if (p2p_ctrl_find(wpa_s, buf + 8)) 12774 reply_len = -1; 12775 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 12776 if (p2p_ctrl_find(wpa_s, "")) 12777 reply_len = -1; 12778 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 12779 wpas_p2p_stop_find(wpa_s); 12780 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) { 12781 if (p2p_ctrl_asp_provision(wpa_s, buf + 18)) 12782 reply_len = -1; 12783 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) { 12784 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23)) 12785 reply_len = -1; 12786 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 12787 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 12788 reply_size); 12789 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 12790 if (p2p_ctrl_listen(wpa_s, buf + 11)) 12791 reply_len = -1; 12792 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 12793 if (p2p_ctrl_listen(wpa_s, "")) 12794 reply_len = -1; 12795 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 12796 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 12797 reply_len = -1; 12798 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 12799 if (p2p_ctrl_group_add(wpa_s, "")) 12800 reply_len = -1; 12801 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 12802 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 12803 reply_len = -1; 12804 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) { 12805 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply, 12806 reply_size); 12807 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 12808 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 12809 reply_len = -1; 12810 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 12811 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 12812 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 12813 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 12814 reply_size); 12815 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 12816 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 12817 reply_len = -1; 12818 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 12819 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 12820 reply_len = -1; 12821 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 12822 wpas_p2p_sd_service_update(wpa_s); 12823 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 12824 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 12825 reply_len = -1; 12826 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 12827 wpas_p2p_service_flush(wpa_s); 12828 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 12829 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 12830 reply_len = -1; 12831 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 12832 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 12833 reply_len = -1; 12834 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) { 12835 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0) 12836 reply_len = -1; 12837 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 12838 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 12839 reply_len = -1; 12840 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 12841 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 12842 reply_len = -1; 12843 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 12844 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 12845 reply_size); 12846 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 12847 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 12848 reply_len = -1; 12849 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 12850 p2p_ctrl_flush(wpa_s); 12851 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 12852 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 12853 reply_len = -1; 12854 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 12855 if (wpas_p2p_cancel(wpa_s)) 12856 reply_len = -1; 12857 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 12858 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 12859 reply_len = -1; 12860 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 12861 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 12862 reply_len = -1; 12863 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 12864 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 12865 reply_len = -1; 12866 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 12867 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 12868 reply_len = -1; 12869 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) { 12870 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0) 12871 reply_len = -1; 12872 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) { 12873 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13)) 12874 reply_len = -1; 12875 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) { 12876 if (wpas_p2p_lo_stop(wpa_s)) 12877 reply_len = -1; 12878 #endif /* CONFIG_P2P */ 12879 #ifdef CONFIG_WIFI_DISPLAY 12880 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 12881 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 12882 reply_len = -1; 12883 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 12884 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 12885 reply, reply_size); 12886 #endif /* CONFIG_WIFI_DISPLAY */ 12887 #ifdef CONFIG_INTERWORKING 12888 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 12889 if (interworking_fetch_anqp(wpa_s) < 0) 12890 reply_len = -1; 12891 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 12892 interworking_stop_fetch_anqp(wpa_s); 12893 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { 12894 if (ctrl_interworking_select(wpa_s, NULL) < 0) 12895 reply_len = -1; 12896 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { 12897 if (ctrl_interworking_select(wpa_s, buf + 20) < 0) 12898 reply_len = -1; 12899 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 12900 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0) 12901 reply_len = -1; 12902 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) { 12903 int id; 12904 12905 id = ctrl_interworking_connect(wpa_s, buf + 25, 1); 12906 if (id < 0) 12907 reply_len = -1; 12908 else { 12909 reply_len = os_snprintf(reply, reply_size, "%d\n", id); 12910 if (os_snprintf_error(reply_size, reply_len)) 12911 reply_len = -1; 12912 } 12913 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 12914 if (get_anqp(wpa_s, buf + 9) < 0) 12915 reply_len = -1; 12916 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 12917 if (gas_request(wpa_s, buf + 12) < 0) 12918 reply_len = -1; 12919 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 12920 reply_len = gas_response_get(wpa_s, buf + 17, reply, 12921 reply_size); 12922 #endif /* CONFIG_INTERWORKING */ 12923 #ifdef CONFIG_HS20 12924 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 12925 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 12926 reply_len = -1; 12927 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 12928 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 12929 reply_len = -1; 12930 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) { 12931 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0) 12932 reply_len = -1; 12933 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) { 12934 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0) 12935 reply_len = -1; 12936 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) { 12937 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size); 12938 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) { 12939 if (del_hs20_icon(wpa_s, buf + 14) < 0) 12940 reply_len = -1; 12941 } else if (os_strcmp(buf, "FETCH_OSU") == 0) { 12942 if (hs20_fetch_osu(wpa_s, 0) < 0) 12943 reply_len = -1; 12944 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) { 12945 if (hs20_fetch_osu(wpa_s, 1) < 0) 12946 reply_len = -1; 12947 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) { 12948 hs20_cancel_fetch_osu(wpa_s); 12949 #endif /* CONFIG_HS20 */ 12950 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 12951 { 12952 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 12953 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 12954 reply_len = -1; 12955 else { 12956 /* 12957 * Notify response from timeout to allow the control 12958 * interface response to be sent first. 12959 */ 12960 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response, 12961 wpa_s, NULL); 12962 } 12963 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 12964 if (wpa_supplicant_reload_configuration(wpa_s)) 12965 reply_len = -1; 12966 } else if (os_strcmp(buf, "TERMINATE") == 0) { 12967 wpa_supplicant_terminate_proc(wpa_s->global); 12968 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 12969 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 12970 reply_len = -1; 12971 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) { 12972 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore( 12973 wpa_s, buf + 12, reply, reply_size); 12974 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 12975 /* deprecated backwards compatibility alias for BSSID_IGNORE */ 12976 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore( 12977 wpa_s, buf + 9, reply, reply_size); 12978 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 12979 reply_len = wpa_supplicant_ctrl_iface_log_level( 12980 wpa_s, buf + 9, reply, reply_size); 12981 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) { 12982 reply_len = wpa_supplicant_ctrl_iface_list_networks( 12983 wpa_s, buf + 14, reply, reply_size); 12984 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 12985 reply_len = wpa_supplicant_ctrl_iface_list_networks( 12986 wpa_s, NULL, reply, reply_size); 12987 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 12988 wpas_request_disconnection(wpa_s); 12989 } else if (os_strcmp(buf, "SCAN") == 0) { 12990 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); 12991 } else if (os_strncmp(buf, "SCAN ", 5) == 0) { 12992 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len); 12993 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 12994 reply_len = wpa_supplicant_ctrl_iface_scan_results( 12995 wpa_s, reply, reply_size); 12996 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) { 12997 if (wpas_abort_ongoing_scan(wpa_s) < 0) 12998 reply_len = -1; 12999 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 13000 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 13001 reply_len = -1; 13002 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 13003 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 13004 reply_len = -1; 13005 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 13006 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 13007 reply_len = -1; 13008 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 13009 reply_len = wpa_supplicant_ctrl_iface_add_network( 13010 wpa_s, reply, reply_size); 13011 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 13012 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 13013 reply_len = -1; 13014 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 13015 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 13016 reply_len = -1; 13017 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 13018 reply_len = wpa_supplicant_ctrl_iface_get_network( 13019 wpa_s, buf + 12, reply, reply_size); 13020 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 13021 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12, 13022 wpa_s)) 13023 reply_len = -1; 13024 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 13025 reply_len = wpa_supplicant_ctrl_iface_list_creds( 13026 wpa_s, reply, reply_size); 13027 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 13028 reply_len = wpa_supplicant_ctrl_iface_add_cred( 13029 wpa_s, reply, reply_size); 13030 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 13031 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 13032 reply_len = -1; 13033 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 13034 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 13035 reply_len = -1; 13036 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) { 13037 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9, 13038 reply, 13039 reply_size); 13040 #ifndef CONFIG_NO_CONFIG_WRITE 13041 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 13042 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 13043 reply_len = -1; 13044 #endif /* CONFIG_NO_CONFIG_WRITE */ 13045 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 13046 reply_len = wpa_supplicant_ctrl_iface_get_capability( 13047 wpa_s, buf + 15, reply, reply_size); 13048 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 13049 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 13050 reply_len = -1; 13051 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 13052 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 13053 reply_len = -1; 13054 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 13055 reply_len = wpa_supplicant_global_iface_list( 13056 wpa_s->global, reply, reply_size); 13057 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 13058 reply_len = wpa_supplicant_global_iface_interfaces( 13059 wpa_s->global, buf + 10, reply, reply_size); 13060 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 13061 reply_len = wpa_supplicant_ctrl_iface_bss( 13062 wpa_s, buf + 4, reply, reply_size); 13063 #ifdef CONFIG_AP 13064 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 13065 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 13066 } else if (os_strncmp(buf, "STA ", 4) == 0) { 13067 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 13068 reply_size); 13069 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 13070 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 13071 reply_size); 13072 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 13073 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 13074 reply_len = -1; 13075 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 13076 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 13077 reply_len = -1; 13078 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 13079 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) 13080 reply_len = -1; 13081 } else if (os_strcmp(buf, "STOP_AP") == 0) { 13082 if (wpas_ap_stop_ap(wpa_s)) 13083 reply_len = -1; 13084 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 13085 if (wpas_ap_update_beacon(wpa_s)) 13086 reply_len = -1; 13087 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { 13088 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { 13089 if (ap_ctrl_iface_acl_add_mac(wpa_s, 13090 DENY_UNLESS_ACCEPTED, 13091 buf + 19) || 13092 ap_ctrl_iface_set_acl(wpa_s)) 13093 reply_len = -1; 13094 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { 13095 if (ap_ctrl_iface_acl_del_mac(wpa_s, 13096 DENY_UNLESS_ACCEPTED, 13097 buf + 19) || 13098 ap_ctrl_iface_set_acl(wpa_s) || 13099 ap_ctrl_iface_disassoc_accept_mac(wpa_s)) 13100 reply_len = -1; 13101 } else if (os_strcmp(buf + 11, "SHOW") == 0) { 13102 reply_len = ap_ctrl_iface_acl_show_mac( 13103 wpa_s, DENY_UNLESS_ACCEPTED, 13104 reply, reply_size); 13105 } else if (os_strcmp(buf + 11, "CLEAR") == 0) { 13106 ap_ctrl_iface_acl_clear_list(wpa_s, 13107 DENY_UNLESS_ACCEPTED); 13108 if (ap_ctrl_iface_set_acl(wpa_s) || 13109 ap_ctrl_iface_disassoc_accept_mac(wpa_s)) 13110 reply_len = -1; 13111 } else { 13112 reply_len = -1; 13113 } 13114 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { 13115 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { 13116 if (ap_ctrl_iface_acl_add_mac(wpa_s, 13117 ACCEPT_UNLESS_DENIED, 13118 buf + 17) || 13119 ap_ctrl_iface_set_acl(wpa_s) || 13120 ap_ctrl_iface_disassoc_deny_mac(wpa_s)) 13121 reply_len = -1; 13122 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { 13123 if (ap_ctrl_iface_acl_del_mac(wpa_s, 13124 ACCEPT_UNLESS_DENIED, 13125 buf + 17) || 13126 ap_ctrl_iface_set_acl(wpa_s)) 13127 reply_len = -1; 13128 } else if (os_strcmp(buf + 9, "SHOW") == 0) { 13129 reply_len = ap_ctrl_iface_acl_show_mac( 13130 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size); 13131 } else if (os_strcmp(buf + 9, "CLEAR") == 0) { 13132 ap_ctrl_iface_acl_clear_list(wpa_s, 13133 ACCEPT_UNLESS_DENIED); 13134 if (ap_ctrl_iface_set_acl(wpa_s)) 13135 reply_len = -1; 13136 } else { 13137 reply_len = -1; 13138 } 13139 #endif /* CONFIG_AP */ 13140 } else if (os_strcmp(buf, "SUSPEND") == 0) { 13141 wpas_notify_suspend(wpa_s->global); 13142 } else if (os_strcmp(buf, "RESUME") == 0) { 13143 wpas_notify_resume(wpa_s->global); 13144 #ifdef CONFIG_TESTING_OPTIONS 13145 } else if (os_strcmp(buf, "DROP_SA") == 0) { 13146 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 13147 #endif /* CONFIG_TESTING_OPTIONS */ 13148 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 13149 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 13150 reply_len = -1; 13151 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 13152 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0; 13153 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 13154 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 13155 reply_len = -1; 13156 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 13157 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 13158 buf + 17)) 13159 reply_len = -1; 13160 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 13161 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10); 13162 #ifdef CONFIG_TDLS 13163 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 13164 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 13165 reply_len = -1; 13166 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 13167 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 13168 reply_len = -1; 13169 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 13170 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 13171 reply_len = -1; 13172 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) { 13173 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s, 13174 buf + 17)) 13175 reply_len = -1; 13176 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) { 13177 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s, 13178 buf + 24)) 13179 reply_len = -1; 13180 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) { 13181 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status( 13182 wpa_s, buf + 17, reply, reply_size); 13183 #endif /* CONFIG_TDLS */ 13184 #ifndef CONFIG_NO_WMM_AC 13185 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) { 13186 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size); 13187 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) { 13188 if (wmm_ac_ctrl_addts(wpa_s, buf + 13)) 13189 reply_len = -1; 13190 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) { 13191 if (wmm_ac_ctrl_delts(wpa_s, buf + 13)) 13192 reply_len = -1; 13193 #endif /* CONFIG_NO_WMM_AC */ 13194 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 13195 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 13196 reply_size); 13197 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) { 13198 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14)) 13199 reply_len = -1; 13200 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 13201 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 13202 reply_size); 13203 #ifdef CONFIG_AUTOSCAN 13204 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 13205 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 13206 reply_len = -1; 13207 #endif /* CONFIG_AUTOSCAN */ 13208 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 13209 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, 13210 reply_size); 13211 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { 13212 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply, 13213 reply_size); 13214 #ifdef ANDROID 13215 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 13216 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 13217 reply_size); 13218 #endif /* ANDROID */ 13219 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 13220 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply, 13221 reply_size); 13222 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 13223 pmksa_cache_clear_current(wpa_s->wpa); 13224 eapol_sm_request_reauth(wpa_s->eapol); 13225 #ifdef CONFIG_WNM 13226 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 13227 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 13228 reply_len = -1; 13229 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) { 13230 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14)) 13231 reply_len = -1; 13232 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) { 13233 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) 13234 reply_len = -1; 13235 #endif /* CONFIG_WNM */ 13236 #ifdef CONFIG_WNM_AP 13237 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 13238 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18)) 13239 reply_len = -1; 13240 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 13241 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13)) 13242 reply_len = -1; 13243 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 13244 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11)) 13245 reply_len = -1; 13246 #endif /* CONFIG_WNM_AP */ 13247 } else if (os_strcmp(buf, "FLUSH") == 0) { 13248 wpa_supplicant_ctrl_iface_flush(wpa_s); 13249 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { 13250 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply, 13251 reply_size); 13252 #ifdef CONFIG_TESTING_OPTIONS 13253 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 13254 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0) 13255 reply_len = -1; 13256 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) { 13257 wpas_ctrl_iface_mgmt_tx_done(wpa_s); 13258 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 13259 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0) 13260 reply_len = -1; 13261 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) { 13262 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0) 13263 reply_len = -1; 13264 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 13265 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0) 13266 reply_len = -1; 13267 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) { 13268 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0) 13269 reply_len = -1; 13270 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 13271 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0) 13272 reply_len = -1; 13273 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 13274 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0) 13275 reply_len = -1; 13276 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 13277 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0) 13278 reply_len = -1; 13279 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 13280 if (testing_set_fail_pattern(true, buf + 16) < 0) 13281 reply_len = -1; 13282 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 13283 reply_len = testing_get_fail_pattern(true, reply, reply_size); 13284 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 13285 if (testing_set_fail_pattern(false, buf + 10) < 0) 13286 reply_len = -1; 13287 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 13288 reply_len = testing_get_fail_pattern(false, reply, reply_size); 13289 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) { 13290 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0) 13291 reply_len = -1; 13292 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) { 13293 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0) 13294 reply_len = -1; 13295 } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) { 13296 if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0) 13297 reply_len = -1; 13298 } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) { 13299 if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0) 13300 reply_len = -1; 13301 } else if (os_strcmp(buf, "RESET_PN") == 0) { 13302 if (wpas_ctrl_reset_pn(wpa_s) < 0) 13303 reply_len = -1; 13304 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { 13305 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) 13306 reply_len = -1; 13307 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { 13308 if (wpas_ctrl_resend_assoc(wpa_s) < 0) 13309 reply_len = -1; 13310 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) { 13311 sme_event_unprot_disconnect( 13312 wpa_s, wpa_s->bssid, NULL, 13313 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); 13314 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) { 13315 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9)) 13316 reply_len = -1; 13317 } else if (os_strcmp(buf, "TWT_SETUP") == 0) { 13318 if (wpas_ctrl_iface_send_twt_setup(wpa_s, "")) 13319 reply_len = -1; 13320 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) { 13321 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12)) 13322 reply_len = -1; 13323 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) { 13324 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, "")) 13325 reply_len = -1; 13326 } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) { 13327 if (wpas_ctrl_ml_probe(wpa_s, buf + 13)) 13328 reply_len = -1; 13329 #endif /* CONFIG_TESTING_OPTIONS */ 13330 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { 13331 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) 13332 reply_len = -1; 13333 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) { 13334 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply, 13335 reply_size); 13336 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) { 13337 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0) 13338 reply_len = -1; 13339 #ifndef CONFIG_NO_RRM 13340 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) { 13341 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20)) 13342 reply_len = -1; 13343 #endif /* CONFIG_NO_RRM */ 13344 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 13345 wpas_ctrl_iface_erp_flush(wpa_s); 13346 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) { 13347 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14)) 13348 reply_len = -1; 13349 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { 13350 reply_len = wpas_ctrl_iface_get_pref_freq_list( 13351 wpa_s, buf + 19, reply, reply_size); 13352 #ifdef CONFIG_FILS 13353 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) { 13354 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17)) 13355 reply_len = -1; 13356 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) { 13357 wpas_flush_fils_hlp_req(wpa_s); 13358 #endif /* CONFIG_FILS */ 13359 #ifdef CONFIG_DPP 13360 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 13361 int res; 13362 13363 res = wpas_dpp_qr_code(wpa_s, buf + 12); 13364 if (res < 0) { 13365 reply_len = -1; 13366 } else { 13367 reply_len = os_snprintf(reply, reply_size, "%d", res); 13368 if (os_snprintf_error(reply_size, reply_len)) 13369 reply_len = -1; 13370 } 13371 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) { 13372 int res; 13373 13374 res = wpas_dpp_nfc_uri(wpa_s, buf + 12); 13375 if (res < 0) { 13376 reply_len = -1; 13377 } else { 13378 reply_len = os_snprintf(reply, reply_size, "%d", res); 13379 if (os_snprintf_error(reply_size, reply_len)) 13380 reply_len = -1; 13381 } 13382 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) { 13383 int res; 13384 13385 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20); 13386 if (res < 0) { 13387 reply_len = -1; 13388 } else { 13389 reply_len = os_snprintf(reply, reply_size, "%d", res); 13390 if (os_snprintf_error(reply_size, reply_len)) 13391 reply_len = -1; 13392 } 13393 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) { 13394 int res; 13395 13396 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20); 13397 if (res < 0) { 13398 reply_len = -1; 13399 } else { 13400 reply_len = os_snprintf(reply, reply_size, "%d", res); 13401 if (os_snprintf_error(reply_size, reply_len)) 13402 reply_len = -1; 13403 } 13404 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 13405 int res; 13406 13407 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); 13408 if (res < 0) { 13409 reply_len = -1; 13410 } else { 13411 reply_len = os_snprintf(reply, reply_size, "%d", res); 13412 if (os_snprintf_error(reply_size, reply_len)) 13413 reply_len = -1; 13414 } 13415 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 13416 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0) 13417 reply_len = -1; 13418 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 13419 const char *uri; 13420 13421 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22)); 13422 if (!uri) { 13423 reply_len = -1; 13424 } else { 13425 reply_len = os_snprintf(reply, reply_size, "%s", uri); 13426 if (os_snprintf_error(reply_size, reply_len)) 13427 reply_len = -1; 13428 } 13429 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 13430 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), 13431 reply, reply_size); 13432 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { 13433 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18), 13434 os_strchr(buf + 18, ' ')) < 0) 13435 reply_len = -1; 13436 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 13437 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) 13438 reply_len = -1; 13439 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 13440 if (wpas_dpp_listen(wpa_s, buf + 11) < 0) 13441 reply_len = -1; 13442 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 13443 wpas_dpp_stop(wpa_s); 13444 wpas_dpp_listen_stop(wpa_s); 13445 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 13446 int res; 13447 13448 res = dpp_configurator_add(wpa_s->dpp, buf + 20); 13449 if (res < 0) { 13450 reply_len = -1; 13451 } else { 13452 reply_len = os_snprintf(reply, reply_size, "%d", res); 13453 if (os_snprintf_error(reply_size, reply_len)) 13454 reply_len = -1; 13455 } 13456 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) { 13457 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0) 13458 reply_len = -1; 13459 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 13460 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) 13461 reply_len = -1; 13462 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 13463 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) 13464 reply_len = -1; 13465 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 13466 reply_len = dpp_configurator_get_key_id(wpa_s->dpp, 13467 atoi(buf + 25), 13468 reply, reply_size); 13469 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 13470 int res; 13471 13472 res = wpas_dpp_pkex_add(wpa_s, buf + 12); 13473 if (res < 0) { 13474 reply_len = -1; 13475 } else { 13476 reply_len = os_snprintf(reply, reply_size, "%d", res); 13477 if (os_snprintf_error(reply_size, reply_len)) 13478 reply_len = -1; 13479 } 13480 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 13481 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) 13482 reply_len = -1; 13483 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) { 13484 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0) 13485 reply_len = -1; 13486 #ifdef CONFIG_DPP2 13487 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { 13488 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0) 13489 reply_len = -1; 13490 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { 13491 if (wpas_dpp_controller_start(wpa_s, NULL) < 0) 13492 reply_len = -1; 13493 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { 13494 dpp_controller_stop(wpa_s->dpp); 13495 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { 13496 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0) 13497 reply_len = -1; 13498 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { 13499 wpas_dpp_chirp_stop(wpa_s); 13500 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) { 13501 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0) 13502 reply_len = -1; 13503 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) { 13504 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0) 13505 reply_len = -1; 13506 #endif /* CONFIG_DPP2 */ 13507 #ifdef CONFIG_DPP3 13508 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) { 13509 if (wpas_dpp_push_button(wpa_s, NULL) < 0) 13510 reply_len = -1; 13511 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) { 13512 if (wpas_dpp_push_button(wpa_s, buf + 15) < 0) 13513 reply_len = -1; 13514 #endif /* CONFIG_DPP3 */ 13515 #endif /* CONFIG_DPP */ 13516 #ifdef CONFIG_NAN_USD 13517 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) { 13518 reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply, 13519 reply_size); 13520 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) { 13521 if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0) 13522 reply_len = -1; 13523 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) { 13524 if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0) 13525 reply_len = -1; 13526 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) { 13527 reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply, 13528 reply_size); 13529 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) { 13530 if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0) 13531 reply_len = -1; 13532 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) { 13533 if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0) 13534 reply_len = -1; 13535 #endif /* CONFIG_NAN_USD */ 13536 #ifdef CONFIG_PASN 13537 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) { 13538 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0) 13539 reply_len = -1; 13540 } else if (os_strcmp(buf, "PASN_STOP") == 0) { 13541 wpas_pasn_auth_stop(wpa_s); 13542 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) { 13543 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size); 13544 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) { 13545 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0) 13546 reply_len = -1; 13547 #ifdef CONFIG_TESTING_OPTIONS 13548 } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) { 13549 if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0) 13550 reply_len = -1; 13551 #endif /* CONFIG_TESTING_OPTIONS */ 13552 #endif /* CONFIG_PASN */ 13553 #ifndef CONFIG_NO_ROBUST_AV 13554 } else if (os_strncmp(buf, "MSCS ", 5) == 0) { 13555 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5)) 13556 reply_len = -1; 13557 } else if (os_strncmp(buf, "SCS ", 4) == 0) { 13558 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4)) 13559 reply_len = -1; 13560 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) { 13561 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10)) 13562 reply_len = -1; 13563 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) { 13564 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11)) 13565 reply_len = -1; 13566 #endif /* CONFIG_NO_ROBUST_AV */ 13567 } else if (os_strcmp(buf, "MLO_STATUS") == 0) { 13568 reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply, 13569 reply_size); 13570 } else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) { 13571 reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply, 13572 reply_size); 13573 } else { 13574 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 13575 reply_len = 16; 13576 } 13577 13578 if (reply_len < 0) { 13579 os_memcpy(reply, "FAIL\n", 5); 13580 reply_len = 5; 13581 } 13582 13583 *resp_len = reply_len; 13584 return reply; 13585 } 13586 13587 13588 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 13589 char *cmd) 13590 { 13591 struct wpa_interface iface; 13592 char *pos, *extra; 13593 struct wpa_supplicant *wpa_s; 13594 unsigned int create_iface = 0; 13595 u8 mac_addr[ETH_ALEN]; 13596 enum wpa_driver_if_type type = WPA_IF_STATION; 13597 13598 /* 13599 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 13600 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]] 13601 */ 13602 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 13603 13604 os_memset(&iface, 0, sizeof(iface)); 13605 13606 do { 13607 iface.ifname = pos = cmd; 13608 pos = os_strchr(pos, '\t'); 13609 if (pos) 13610 *pos++ = '\0'; 13611 if (iface.ifname[0] == '\0') 13612 return -1; 13613 if (pos == NULL) 13614 break; 13615 13616 iface.confname = pos; 13617 pos = os_strchr(pos, '\t'); 13618 if (pos) 13619 *pos++ = '\0'; 13620 if (iface.confname[0] == '\0') 13621 iface.confname = NULL; 13622 if (pos == NULL) 13623 break; 13624 13625 iface.driver = pos; 13626 pos = os_strchr(pos, '\t'); 13627 if (pos) 13628 *pos++ = '\0'; 13629 if (iface.driver[0] == '\0') 13630 iface.driver = NULL; 13631 if (pos == NULL) 13632 break; 13633 13634 iface.ctrl_interface = pos; 13635 pos = os_strchr(pos, '\t'); 13636 if (pos) 13637 *pos++ = '\0'; 13638 if (iface.ctrl_interface[0] == '\0') 13639 iface.ctrl_interface = NULL; 13640 if (pos == NULL) 13641 break; 13642 13643 iface.driver_param = pos; 13644 pos = os_strchr(pos, '\t'); 13645 if (pos) 13646 *pos++ = '\0'; 13647 if (iface.driver_param[0] == '\0') 13648 iface.driver_param = NULL; 13649 if (pos == NULL) 13650 break; 13651 13652 iface.bridge_ifname = pos; 13653 pos = os_strchr(pos, '\t'); 13654 if (pos) 13655 *pos++ = '\0'; 13656 if (iface.bridge_ifname[0] == '\0') 13657 iface.bridge_ifname = NULL; 13658 if (pos == NULL) 13659 break; 13660 13661 extra = pos; 13662 pos = os_strchr(pos, '\t'); 13663 if (pos) 13664 *pos++ = '\0'; 13665 if (!extra[0]) 13666 break; 13667 13668 if (os_strcmp(extra, "create") == 0) { 13669 create_iface = 1; 13670 if (!pos) 13671 break; 13672 13673 if (os_strcmp(pos, "sta") == 0) { 13674 type = WPA_IF_STATION; 13675 } else if (os_strcmp(pos, "ap") == 0) { 13676 type = WPA_IF_AP_BSS; 13677 } else { 13678 wpa_printf(MSG_DEBUG, 13679 "INTERFACE_ADD unsupported interface type: '%s'", 13680 pos); 13681 return -1; 13682 } 13683 } else { 13684 wpa_printf(MSG_DEBUG, 13685 "INTERFACE_ADD unsupported extra parameter: '%s'", 13686 extra); 13687 return -1; 13688 } 13689 } while (0); 13690 13691 if (create_iface) { 13692 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'", 13693 iface.ifname); 13694 if (!global->ifaces) 13695 return -1; 13696 if (wpa_drv_if_add(global->ifaces, type, iface.ifname, 13697 NULL, NULL, NULL, mac_addr, NULL) < 0) { 13698 wpa_printf(MSG_ERROR, 13699 "CTRL_IFACE interface creation failed"); 13700 return -1; 13701 } 13702 13703 wpa_printf(MSG_DEBUG, 13704 "CTRL_IFACE interface '%s' created with MAC addr: " 13705 MACSTR, iface.ifname, MAC2STR(mac_addr)); 13706 } 13707 13708 if (wpa_supplicant_get_iface(global, iface.ifname)) 13709 goto fail; 13710 13711 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); 13712 if (!wpa_s) 13713 goto fail; 13714 wpa_s->added_vif = create_iface; 13715 return 0; 13716 13717 fail: 13718 if (create_iface) { 13719 /* wpa_supplicant does not create multi-BSS AP, so collapse to 13720 * WPA_IF_STATION to avoid unwanted clean up in the driver. */ 13721 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname); 13722 } 13723 return -1; 13724 } 13725 13726 13727 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 13728 char *cmd) 13729 { 13730 struct wpa_supplicant *wpa_s; 13731 int ret; 13732 unsigned int delete_iface; 13733 13734 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 13735 13736 wpa_s = wpa_supplicant_get_iface(global, cmd); 13737 if (wpa_s == NULL) 13738 return -1; 13739 delete_iface = wpa_s->added_vif; 13740 ret = wpa_supplicant_remove_iface(global, wpa_s, 0); 13741 if (!ret && delete_iface) { 13742 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'", 13743 cmd); 13744 /* wpa_supplicant does not create multi-BSS AP, so collapse to 13745 * WPA_IF_STATION to avoid unwanted clean up in the driver. */ 13746 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd); 13747 } 13748 return ret; 13749 } 13750 13751 13752 static void wpa_free_iface_info(struct wpa_interface_info *iface) 13753 { 13754 struct wpa_interface_info *prev; 13755 13756 while (iface) { 13757 prev = iface; 13758 iface = iface->next; 13759 13760 os_free(prev->ifname); 13761 os_free(prev->desc); 13762 os_free(prev); 13763 } 13764 } 13765 13766 13767 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 13768 char *buf, int len) 13769 { 13770 int i, res; 13771 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 13772 char *pos, *end; 13773 13774 for (i = 0; wpa_drivers[i]; i++) { 13775 const struct wpa_driver_ops *drv = wpa_drivers[i]; 13776 if (drv->get_interfaces == NULL) 13777 continue; 13778 tmp = drv->get_interfaces(global->drv_priv[i]); 13779 if (tmp == NULL) 13780 continue; 13781 13782 if (last == NULL) 13783 iface = last = tmp; 13784 else 13785 last->next = tmp; 13786 while (last->next) 13787 last = last->next; 13788 } 13789 13790 pos = buf; 13791 end = buf + len; 13792 for (tmp = iface; tmp; tmp = tmp->next) { 13793 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 13794 tmp->drv_name, tmp->ifname, 13795 tmp->desc ? tmp->desc : ""); 13796 if (os_snprintf_error(end - pos, res)) { 13797 *pos = '\0'; 13798 break; 13799 } 13800 pos += res; 13801 } 13802 13803 wpa_free_iface_info(iface); 13804 13805 return pos - buf; 13806 } 13807 13808 13809 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 13810 const char *input, 13811 char *buf, int len) 13812 { 13813 int res; 13814 char *pos, *end; 13815 struct wpa_supplicant *wpa_s; 13816 int show_ctrl = 0; 13817 13818 if (input) 13819 show_ctrl = !!os_strstr(input, "ctrl"); 13820 13821 wpa_s = global->ifaces; 13822 pos = buf; 13823 end = buf + len; 13824 13825 while (wpa_s) { 13826 if (show_ctrl) 13827 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n", 13828 wpa_s->ifname, 13829 wpa_s->conf->ctrl_interface ? 13830 wpa_s->conf->ctrl_interface : "N/A"); 13831 else 13832 res = os_snprintf(pos, end - pos, "%s\n", 13833 wpa_s->ifname); 13834 13835 if (os_snprintf_error(end - pos, res)) { 13836 *pos = '\0'; 13837 break; 13838 } 13839 pos += res; 13840 wpa_s = wpa_s->next; 13841 } 13842 return pos - buf; 13843 } 13844 13845 13846 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global, 13847 const char *ifname, 13848 char *cmd, size_t *resp_len) 13849 { 13850 struct wpa_supplicant *wpa_s; 13851 13852 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 13853 if (os_strcmp(ifname, wpa_s->ifname) == 0) 13854 break; 13855 } 13856 13857 if (wpa_s == NULL) { 13858 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n"); 13859 if (resp) 13860 *resp_len = os_strlen(resp); 13861 else 13862 *resp_len = 1; 13863 return resp; 13864 } 13865 13866 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len); 13867 } 13868 13869 13870 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, 13871 char *buf, size_t *resp_len) 13872 { 13873 #ifdef CONFIG_P2P 13874 static const char * cmd[] = { 13875 "LIST_NETWORKS", 13876 "P2P_FIND", 13877 "P2P_STOP_FIND", 13878 "P2P_LISTEN", 13879 "P2P_GROUP_ADD", 13880 "P2P_GET_PASSPHRASE", 13881 "P2P_SERVICE_UPDATE", 13882 "P2P_SERVICE_FLUSH", 13883 "P2P_FLUSH", 13884 "P2P_CANCEL", 13885 "P2P_PRESENCE_REQ", 13886 "P2P_EXT_LISTEN", 13887 #ifdef CONFIG_AP 13888 "STA-FIRST", 13889 #endif /* CONFIG_AP */ 13890 NULL 13891 }; 13892 static const char * prefix[] = { 13893 #ifdef ANDROID 13894 "DRIVER ", 13895 #endif /* ANDROID */ 13896 "GET_CAPABILITY ", 13897 "GET_NETWORK ", 13898 "REMOVE_NETWORK ", 13899 "P2P_FIND ", 13900 "P2P_CONNECT ", 13901 "P2P_LISTEN ", 13902 "P2P_GROUP_REMOVE ", 13903 "P2P_GROUP_ADD ", 13904 "P2P_GROUP_MEMBER ", 13905 "P2P_PROV_DISC ", 13906 "P2P_SERV_DISC_REQ ", 13907 "P2P_SERV_DISC_CANCEL_REQ ", 13908 "P2P_SERV_DISC_RESP ", 13909 "P2P_SERV_DISC_EXTERNAL ", 13910 "P2P_SERVICE_ADD ", 13911 "P2P_SERVICE_DEL ", 13912 "P2P_SERVICE_REP ", 13913 "P2P_REJECT ", 13914 "P2P_INVITE ", 13915 "P2P_PEER ", 13916 "P2P_SET ", 13917 "P2P_UNAUTHORIZE ", 13918 "P2P_PRESENCE_REQ ", 13919 "P2P_EXT_LISTEN ", 13920 "P2P_REMOVE_CLIENT ", 13921 "WPS_NFC_TOKEN ", 13922 "WPS_NFC_TAG_READ ", 13923 "NFC_GET_HANDOVER_SEL ", 13924 "NFC_GET_HANDOVER_REQ ", 13925 "NFC_REPORT_HANDOVER ", 13926 "P2P_ASP_PROVISION ", 13927 "P2P_ASP_PROVISION_RESP ", 13928 #ifdef CONFIG_AP 13929 "STA ", 13930 "STA-NEXT ", 13931 #endif /* CONFIG_AP */ 13932 NULL 13933 }; 13934 int found = 0; 13935 int i; 13936 13937 if (global->p2p_init_wpa_s == NULL) 13938 return NULL; 13939 13940 for (i = 0; !found && cmd[i]; i++) { 13941 if (os_strcmp(buf, cmd[i]) == 0) 13942 found = 1; 13943 } 13944 13945 for (i = 0; !found && prefix[i]; i++) { 13946 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0) 13947 found = 1; 13948 } 13949 13950 if (found) 13951 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 13952 buf, resp_len); 13953 #endif /* CONFIG_P2P */ 13954 return NULL; 13955 } 13956 13957 13958 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global, 13959 char *buf, size_t *resp_len) 13960 { 13961 #ifdef CONFIG_WIFI_DISPLAY 13962 if (global->p2p_init_wpa_s == NULL) 13963 return NULL; 13964 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 || 13965 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) 13966 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 13967 buf, resp_len); 13968 #endif /* CONFIG_WIFI_DISPLAY */ 13969 return NULL; 13970 } 13971 13972 13973 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global, 13974 char *buf, size_t *resp_len) 13975 { 13976 char *ret; 13977 13978 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len); 13979 if (ret) 13980 return ret; 13981 13982 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len); 13983 if (ret) 13984 return ret; 13985 13986 return NULL; 13987 } 13988 13989 13990 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd) 13991 { 13992 char *value; 13993 13994 value = os_strchr(cmd, ' '); 13995 if (value == NULL) 13996 return -1; 13997 *value++ = '\0'; 13998 13999 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value); 14000 14001 #ifdef CONFIG_WIFI_DISPLAY 14002 if (os_strcasecmp(cmd, "wifi_display") == 0) { 14003 wifi_display_enable(global, !!atoi(value)); 14004 return 0; 14005 } 14006 #endif /* CONFIG_WIFI_DISPLAY */ 14007 14008 /* Restore cmd to its original value to allow redirection */ 14009 value[-1] = ' '; 14010 14011 return -1; 14012 } 14013 14014 14015 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global, 14016 char *cmd) 14017 { 14018 struct wpa_supplicant *wpa_s[2]; /* src, dst */ 14019 char *p; 14020 unsigned int i; 14021 14022 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id> 14023 * <variable name> */ 14024 14025 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) { 14026 p = os_strchr(cmd, ' '); 14027 if (p == NULL) 14028 return -1; 14029 *p = '\0'; 14030 14031 wpa_s[i] = global->ifaces; 14032 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) { 14033 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0) 14034 break; 14035 } 14036 14037 if (!wpa_s[i]) { 14038 wpa_printf(MSG_DEBUG, 14039 "CTRL_IFACE: Could not find iface=%s", cmd); 14040 return -1; 14041 } 14042 14043 cmd = p + 1; 14044 } 14045 14046 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]); 14047 } 14048 14049 14050 #ifndef CONFIG_NO_CONFIG_WRITE 14051 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global) 14052 { 14053 int ret = 0, saved = 0; 14054 struct wpa_supplicant *wpa_s; 14055 14056 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 14057 if (!wpa_s->conf->update_config) { 14058 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)"); 14059 continue; 14060 } 14061 14062 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) { 14063 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration"); 14064 ret = 1; 14065 } else { 14066 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated"); 14067 saved++; 14068 } 14069 } 14070 14071 if (!saved && !ret) { 14072 wpa_dbg(wpa_s, MSG_DEBUG, 14073 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated"); 14074 ret = 1; 14075 } 14076 14077 return ret; 14078 } 14079 #endif /* CONFIG_NO_CONFIG_WRITE */ 14080 14081 14082 static int wpas_global_ctrl_iface_status(struct wpa_global *global, 14083 char *buf, size_t buflen) 14084 { 14085 char *pos, *end; 14086 int ret; 14087 struct wpa_supplicant *wpa_s; 14088 14089 pos = buf; 14090 end = buf + buflen; 14091 14092 #ifdef CONFIG_P2P 14093 if (global->p2p && !global->p2p_disabled) { 14094 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 14095 "\n" 14096 "p2p_state=%s\n", 14097 MAC2STR(global->p2p_dev_addr), 14098 p2p_get_state_txt(global->p2p)); 14099 if (os_snprintf_error(end - pos, ret)) 14100 return pos - buf; 14101 pos += ret; 14102 } else if (global->p2p) { 14103 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n"); 14104 if (os_snprintf_error(end - pos, ret)) 14105 return pos - buf; 14106 pos += ret; 14107 } 14108 #endif /* CONFIG_P2P */ 14109 14110 #ifdef CONFIG_WIFI_DISPLAY 14111 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n", 14112 !!global->wifi_display); 14113 if (os_snprintf_error(end - pos, ret)) 14114 return pos - buf; 14115 pos += ret; 14116 #endif /* CONFIG_WIFI_DISPLAY */ 14117 14118 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 14119 ret = os_snprintf(pos, end - pos, "ifname=%s\n" 14120 "address=" MACSTR "\n", 14121 wpa_s->ifname, MAC2STR(wpa_s->own_addr)); 14122 if (os_snprintf_error(end - pos, ret)) 14123 return pos - buf; 14124 pos += ret; 14125 } 14126 14127 return pos - buf; 14128 } 14129 14130 14131 #ifdef CONFIG_FST 14132 14133 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global, 14134 char *cmd, char *buf, 14135 size_t reply_size) 14136 { 14137 char ifname[IFNAMSIZ + 1]; 14138 struct fst_iface_cfg cfg; 14139 struct wpa_supplicant *wpa_s; 14140 struct fst_wpa_obj iface_obj; 14141 14142 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 14143 wpa_s = wpa_supplicant_get_iface(global, ifname); 14144 if (wpa_s) { 14145 if (wpa_s->fst) { 14146 wpa_printf(MSG_INFO, "FST: Already attached"); 14147 return -1; 14148 } 14149 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj); 14150 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr, 14151 &iface_obj, &cfg); 14152 if (wpa_s->fst) 14153 return os_snprintf(buf, reply_size, "OK\n"); 14154 } 14155 } 14156 14157 return -1; 14158 } 14159 14160 14161 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global, 14162 char *cmd, char *buf, 14163 size_t reply_size) 14164 { 14165 char ifname[IFNAMSIZ + 1]; 14166 struct wpa_supplicant *wpa_s; 14167 14168 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 14169 wpa_s = wpa_supplicant_get_iface(global, ifname); 14170 if (wpa_s) { 14171 if (!fst_iface_detach(ifname)) { 14172 wpa_s->fst = NULL; 14173 return os_snprintf(buf, reply_size, "OK\n"); 14174 } 14175 } 14176 } 14177 14178 return -1; 14179 } 14180 14181 #endif /* CONFIG_FST */ 14182 14183 14184 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 14185 char *buf, size_t *resp_len) 14186 { 14187 char *reply; 14188 const int reply_size = 2048; 14189 int reply_len; 14190 int level = MSG_DEBUG; 14191 14192 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 14193 char *pos = os_strchr(buf + 7, ' '); 14194 if (pos) { 14195 *pos++ = '\0'; 14196 return wpas_global_ctrl_iface_ifname(global, 14197 buf + 7, pos, 14198 resp_len); 14199 } 14200 } 14201 14202 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len); 14203 if (reply) 14204 return reply; 14205 14206 if (os_strcmp(buf, "PING") == 0) 14207 level = MSG_EXCESSIVE; 14208 wpa_hexdump_ascii(level, "RX global ctrl_iface", 14209 (const u8 *) buf, os_strlen(buf)); 14210 14211 reply = os_malloc(reply_size); 14212 if (reply == NULL) { 14213 *resp_len = 1; 14214 return NULL; 14215 } 14216 14217 os_memcpy(reply, "OK\n", 3); 14218 reply_len = 3; 14219 14220 if (os_strcmp(buf, "PING") == 0) { 14221 os_memcpy(reply, "PONG\n", 5); 14222 reply_len = 5; 14223 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 14224 if (wpa_supplicant_global_iface_add(global, buf + 14)) 14225 reply_len = -1; 14226 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 14227 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 14228 reply_len = -1; 14229 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 14230 reply_len = wpa_supplicant_global_iface_list( 14231 global, reply, reply_size); 14232 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 14233 reply_len = wpa_supplicant_global_iface_interfaces( 14234 global, buf + 10, reply, reply_size); 14235 #ifdef CONFIG_FST 14236 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 14237 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11, 14238 reply, 14239 reply_size); 14240 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 14241 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11, 14242 reply, 14243 reply_size); 14244 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 14245 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 14246 #endif /* CONFIG_FST */ 14247 } else if (os_strcmp(buf, "TERMINATE") == 0) { 14248 wpa_supplicant_terminate_proc(global); 14249 } else if (os_strcmp(buf, "SUSPEND") == 0) { 14250 wpas_notify_suspend(global); 14251 } else if (os_strcmp(buf, "RESUME") == 0) { 14252 wpas_notify_resume(global); 14253 } else if (os_strncmp(buf, "SET ", 4) == 0) { 14254 if (wpas_global_ctrl_iface_set(global, buf + 4)) { 14255 #ifdef CONFIG_P2P 14256 if (global->p2p_init_wpa_s) { 14257 os_free(reply); 14258 /* Check if P2P redirection would work for this 14259 * command. */ 14260 return wpa_supplicant_ctrl_iface_process( 14261 global->p2p_init_wpa_s, 14262 buf, resp_len); 14263 } 14264 #endif /* CONFIG_P2P */ 14265 reply_len = -1; 14266 } 14267 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 14268 if (wpas_global_ctrl_iface_dup_network(global, buf + 12)) 14269 reply_len = -1; 14270 #ifndef CONFIG_NO_CONFIG_WRITE 14271 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 14272 if (wpas_global_ctrl_iface_save_config(global)) 14273 reply_len = -1; 14274 #endif /* CONFIG_NO_CONFIG_WRITE */ 14275 } else if (os_strcmp(buf, "STATUS") == 0) { 14276 reply_len = wpas_global_ctrl_iface_status(global, reply, 14277 reply_size); 14278 #ifdef CONFIG_MODULE_TESTS 14279 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 14280 if (wpas_module_tests() < 0) 14281 reply_len = -1; 14282 #endif /* CONFIG_MODULE_TESTS */ 14283 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 14284 if (wpa_debug_reopen_file() < 0) 14285 reply_len = -1; 14286 } else { 14287 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 14288 reply_len = 16; 14289 } 14290 14291 if (reply_len < 0) { 14292 os_memcpy(reply, "FAIL\n", 5); 14293 reply_len = 5; 14294 } 14295 14296 *resp_len = reply_len; 14297 return reply; 14298 } 14299