1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2024, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 #ifdef CONFIG_TESTING_OPTIONS 11 #include <netinet/ip.h> 12 #endif /* CONFIG_TESTING_OPTIONS */ 13 14 #ifndef __NetBSD__ 15 #include <net/ethernet.h> 16 #endif 17 #include "utils/common.h" 18 #include "utils/eloop.h" 19 #include "utils/uuid.h" 20 #include "utils/module_tests.h" 21 #include "common/version.h" 22 #include "common/ieee802_11_defs.h" 23 #include "common/ieee802_11_common.h" 24 #include "common/wpa_ctrl.h" 25 #ifdef CONFIG_DPP 26 #include "common/dpp.h" 27 #endif /* CONFIG_DPP */ 28 #include "common/nan_de.h" 29 #include "common/ptksa_cache.h" 30 #include "crypto/tls.h" 31 #include "ap/hostapd.h" 32 #include "eap_peer/eap.h" 33 #include "eapol_supp/eapol_supp_sm.h" 34 #include "rsn_supp/wpa.h" 35 #include "rsn_supp/preauth.h" 36 #include "rsn_supp/pmksa_cache.h" 37 #include "l2_packet/l2_packet.h" 38 #include "wps/wps.h" 39 #include "fst/fst.h" 40 #include "fst/fst_ctrl_iface.h" 41 #include "config.h" 42 #include "wpa_supplicant_i.h" 43 #include "driver_i.h" 44 #include "wps_supplicant.h" 45 #include "ibss_rsn.h" 46 #include "wpas_glue.h" 47 #include "ap.h" 48 #include "p2p_supplicant.h" 49 #include "p2p/p2p.h" 50 #include "hs20_supplicant.h" 51 #include "wifi_display.h" 52 #include "notify.h" 53 #include "bss.h" 54 #include "scan.h" 55 #include "ctrl_iface.h" 56 #include "interworking.h" 57 #include "bssid_ignore.h" 58 #include "autoscan.h" 59 #include "wnm_sta.h" 60 #include "offchannel.h" 61 #include "drivers/driver.h" 62 #include "mesh.h" 63 #include "dpp_supplicant.h" 64 #include "sme.h" 65 #include "nan_usd.h" 66 67 #ifdef __NetBSD__ 68 #include <net/if_ether.h> 69 #elif !defined(__CYGWIN__) && !defined(CONFIG_NATIVE_WINDOWS) 70 #include <net/ethernet.h> 71 #endif 72 73 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 74 char *buf, int len); 75 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 76 const char *input, 77 char *buf, int len); 78 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, 79 char *val); 80 81 82 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 83 { 84 char *pos; 85 u8 addr[ETH_ALEN], *filter = NULL, *n; 86 size_t count = 0; 87 88 pos = val; 89 while (pos) { 90 if (*pos == '\0') 91 break; 92 if (hwaddr_aton(pos, addr)) { 93 os_free(filter); 94 return -1; 95 } 96 n = os_realloc_array(filter, count + 1, ETH_ALEN); 97 if (n == NULL) { 98 os_free(filter); 99 return -1; 100 } 101 filter = n; 102 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 103 count++; 104 105 pos = os_strchr(pos, ' '); 106 if (pos) 107 pos++; 108 } 109 110 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 111 os_free(wpa_s->bssid_filter); 112 wpa_s->bssid_filter = filter; 113 wpa_s->bssid_filter_count = count; 114 115 return 0; 116 } 117 118 119 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 120 { 121 char *pos; 122 u8 addr[ETH_ALEN], *bssid = NULL, *n; 123 struct wpa_ssid_value *ssid = NULL, *ns; 124 size_t count = 0, ssid_count = 0; 125 struct wpa_ssid *c; 126 127 /* 128 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | "" 129 * SSID_SPEC ::= ssid <SSID_HEX> 130 * BSSID_SPEC ::= bssid <BSSID_HEX> 131 */ 132 133 pos = val; 134 while (pos) { 135 if (*pos == '\0') 136 break; 137 if (os_strncmp(pos, "bssid ", 6) == 0) { 138 int res; 139 pos += 6; 140 res = hwaddr_aton2(pos, addr); 141 if (res < 0) { 142 os_free(ssid); 143 os_free(bssid); 144 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 145 "BSSID value '%s'", pos); 146 return -1; 147 } 148 pos += res; 149 n = os_realloc_array(bssid, count + 1, ETH_ALEN); 150 if (n == NULL) { 151 os_free(ssid); 152 os_free(bssid); 153 return -1; 154 } 155 bssid = n; 156 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 157 count++; 158 } else if (os_strncmp(pos, "ssid ", 5) == 0) { 159 char *end; 160 pos += 5; 161 162 end = pos; 163 while (*end) { 164 if (*end == '\0' || *end == ' ') 165 break; 166 end++; 167 } 168 169 ns = os_realloc_array(ssid, ssid_count + 1, 170 sizeof(struct wpa_ssid_value)); 171 if (ns == NULL) { 172 os_free(ssid); 173 os_free(bssid); 174 return -1; 175 } 176 ssid = ns; 177 178 if ((end - pos) & 0x01 || 179 end - pos > 2 * SSID_MAX_LEN || 180 hexstr2bin(pos, ssid[ssid_count].ssid, 181 (end - pos) / 2) < 0) { 182 os_free(ssid); 183 os_free(bssid); 184 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 185 "SSID value '%s'", pos); 186 return -1; 187 } 188 ssid[ssid_count].ssid_len = (end - pos) / 2; 189 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 190 ssid[ssid_count].ssid, 191 ssid[ssid_count].ssid_len); 192 ssid_count++; 193 pos = end; 194 } else { 195 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 196 "'%s'", pos); 197 os_free(ssid); 198 os_free(bssid); 199 return -1; 200 } 201 202 pos = os_strchr(pos, ' '); 203 if (pos) 204 pos++; 205 } 206 207 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 208 os_free(wpa_s->disallow_aps_bssid); 209 wpa_s->disallow_aps_bssid = bssid; 210 wpa_s->disallow_aps_bssid_count = count; 211 212 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 213 os_free(wpa_s->disallow_aps_ssid); 214 wpa_s->disallow_aps_ssid = ssid; 215 wpa_s->disallow_aps_ssid_count = ssid_count; 216 217 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 218 return 0; 219 220 c = wpa_s->current_ssid; 221 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 222 return 0; 223 224 if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 225 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 226 return 0; 227 228 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 229 "because current AP was marked disallowed"); 230 231 #ifdef CONFIG_SME 232 wpa_s->sme.prev_bssid_set = 0; 233 #endif /* CONFIG_SME */ 234 wpa_s->reassociate = 1; 235 wpa_s->own_disconnect_req = 1; 236 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 237 wpa_supplicant_req_scan(wpa_s, 0, 0); 238 239 return 0; 240 } 241 242 243 #ifndef CONFIG_NO_CONFIG_BLOBS 244 static int wpas_ctrl_set_blob(struct wpa_supplicant *wpa_s, char *pos) 245 { 246 char *name = pos; 247 struct wpa_config_blob *blob; 248 size_t len; 249 250 pos = os_strchr(pos, ' '); 251 if (pos == NULL) 252 return -1; 253 *pos++ = '\0'; 254 len = os_strlen(pos); 255 if (len & 1) 256 return -1; 257 258 wpa_printf(MSG_DEBUG, "CTRL: Set blob '%s'", name); 259 blob = os_zalloc(sizeof(*blob)); 260 if (blob == NULL) 261 return -1; 262 blob->name = os_strdup(name); 263 blob->data = os_malloc(len / 2); 264 if (blob->name == NULL || blob->data == NULL) { 265 wpa_config_free_blob(blob); 266 return -1; 267 } 268 269 if (hexstr2bin(pos, blob->data, len / 2) < 0) { 270 wpa_printf(MSG_DEBUG, "CTRL: Invalid blob hex data"); 271 wpa_config_free_blob(blob); 272 return -1; 273 } 274 blob->len = len / 2; 275 276 wpa_config_set_blob(wpa_s->conf, blob); 277 278 return 0; 279 } 280 #endif /* CONFIG_NO_CONFIG_BLOBS */ 281 282 283 static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) 284 { 285 char *params; 286 char *pos; 287 int *freqs = NULL; 288 int ret; 289 290 if (atoi(cmd)) { 291 params = os_strchr(cmd, ' '); 292 os_free(wpa_s->manual_sched_scan_freqs); 293 if (params) { 294 params++; 295 pos = os_strstr(params, "freq="); 296 if (pos) 297 freqs = freq_range_to_channel_list(wpa_s, 298 pos + 5); 299 } 300 wpa_s->manual_sched_scan_freqs = freqs; 301 ret = wpas_start_pno(wpa_s); 302 } else { 303 ret = wpas_stop_pno(wpa_s); 304 } 305 return ret; 306 } 307 308 309 static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands) 310 { 311 union wpa_event_data event; 312 u32 setband_mask = WPA_SETBAND_AUTO; 313 314 /* 315 * For example: 316 * SET setband 2G,6G 317 * SET setband 5G 318 * SET setband AUTO 319 */ 320 if (!os_strstr(bands, "AUTO")) { 321 if (os_strstr(bands, "5G")) 322 setband_mask |= WPA_SETBAND_5G; 323 if (os_strstr(bands, "6G")) 324 setband_mask |= WPA_SETBAND_6G; 325 if (os_strstr(bands, "2G")) 326 setband_mask |= WPA_SETBAND_2G; 327 if (setband_mask == WPA_SETBAND_AUTO) 328 return -1; 329 } 330 331 wpa_s->setband_mask = setband_mask; 332 if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) { 333 os_memset(&event, 0, sizeof(event)); 334 event.channel_list_changed.initiator = REGDOM_SET_BY_USER; 335 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; 336 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event); 337 } 338 339 return 0; 340 } 341 342 343 static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s, 344 const char *cmd) 345 { 346 struct wpabuf *lci; 347 348 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 349 wpabuf_free(wpa_s->lci); 350 wpa_s->lci = NULL; 351 return 0; 352 } 353 354 lci = wpabuf_parse_bin(cmd); 355 if (!lci) 356 return -1; 357 358 if (os_get_reltime(&wpa_s->lci_time)) { 359 wpabuf_free(lci); 360 return -1; 361 } 362 363 wpabuf_free(wpa_s->lci); 364 wpa_s->lci = lci; 365 366 return 0; 367 } 368 369 370 static int 371 wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd) 372 { 373 int relative_rssi; 374 375 if (os_strcmp(cmd, "disable") == 0) { 376 wpa_s->srp.relative_rssi_set = 0; 377 return 0; 378 } 379 380 relative_rssi = atoi(cmd); 381 if (relative_rssi < 0 || relative_rssi > 100) 382 return -1; 383 wpa_s->srp.relative_rssi = relative_rssi; 384 wpa_s->srp.relative_rssi_set = 1; 385 return 0; 386 } 387 388 389 static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s, 390 const char *cmd) 391 { 392 char *pos; 393 int adjust_rssi; 394 395 /* <band>:adjust_value */ 396 pos = os_strchr(cmd, ':'); 397 if (!pos) 398 return -1; 399 pos++; 400 adjust_rssi = atoi(pos); 401 if (adjust_rssi < -100 || adjust_rssi > 100) 402 return -1; 403 404 if (os_strncmp(cmd, "2G", 2) == 0) 405 wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G; 406 else if (os_strncmp(cmd, "5G", 2) == 0) 407 wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G; 408 else 409 return -1; 410 411 wpa_s->srp.relative_adjust_rssi = adjust_rssi; 412 413 return 0; 414 } 415 416 417 static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s, 418 const char *cmd) 419 { 420 struct wpabuf *ric_ies; 421 422 if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { 423 wpabuf_free(wpa_s->ric_ies); 424 wpa_s->ric_ies = NULL; 425 return 0; 426 } 427 428 ric_ies = wpabuf_parse_bin(cmd); 429 if (!ric_ies) 430 return -1; 431 432 wpabuf_free(wpa_s->ric_ies); 433 wpa_s->ric_ies = ric_ies; 434 435 return 0; 436 } 437 438 439 #ifdef CONFIG_TESTING_OPTIONS 440 static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s, 441 const char *val) 442 { 443 u8 bssid[ETH_ALEN]; 444 const char *pos = val; 445 struct driver_signal_override *dso = NULL, *tmp, parsed; 446 447 if (hwaddr_aton(pos, bssid)) 448 return -1; 449 pos = os_strchr(pos, ' '); 450 451 dl_list_for_each(tmp, &wpa_s->drv_signal_override, 452 struct driver_signal_override, list) { 453 if (ether_addr_equal(bssid, tmp->bssid)) { 454 dso = tmp; 455 break; 456 } 457 } 458 459 if (!pos) { 460 /* Remove existing entry */ 461 if (dso) { 462 dl_list_del(&dso->list); 463 os_free(dso); 464 } 465 return 0; 466 } 467 pos++; 468 469 /* Update an existing entry or add a new one */ 470 os_memset(&parsed, 0, sizeof(parsed)); 471 if (sscanf(pos, "%d %d %d %d %d", 472 &parsed.si_current_signal, 473 &parsed.si_avg_signal, 474 &parsed.si_avg_beacon_signal, 475 &parsed.si_current_noise, 476 &parsed.scan_level) != 5) 477 return -1; 478 479 if (!dso) { 480 dso = os_zalloc(sizeof(*dso)); 481 if (!dso) 482 return -1; 483 os_memcpy(dso->bssid, bssid, ETH_ALEN); 484 dl_list_add(&wpa_s->drv_signal_override, &dso->list); 485 } 486 dso->si_current_signal = parsed.si_current_signal; 487 dso->si_avg_signal = parsed.si_avg_signal; 488 dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal; 489 dso->si_current_noise = parsed.si_current_noise; 490 dso->scan_level = parsed.scan_level; 491 492 return 0; 493 } 494 #endif /* CONFIG_TESTING_OPTIONS */ 495 496 497 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 498 char *cmd) 499 { 500 char *value; 501 int ret = 0; 502 503 value = os_strchr(cmd, ' '); 504 if (value == NULL) 505 return -1; 506 *value++ = '\0'; 507 508 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 509 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 510 eapol_sm_configure(wpa_s->eapol, 511 atoi(value), -1, -1, -1); 512 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 513 eapol_sm_configure(wpa_s->eapol, 514 -1, atoi(value), -1, -1); 515 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 516 eapol_sm_configure(wpa_s->eapol, 517 -1, -1, atoi(value), -1); 518 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 519 eapol_sm_configure(wpa_s->eapol, 520 -1, -1, -1, atoi(value)); 521 #ifdef CONFIG_TESTING_OPTIONS 522 } else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) { 523 if (os_strcmp(value, "Auto") == 0) 524 eapol_sm_notify_portControl(wpa_s->eapol, Auto); 525 else if (os_strcmp(value, "ForceUnauthorized") == 0) 526 eapol_sm_notify_portControl(wpa_s->eapol, 527 ForceUnauthorized); 528 else if (os_strcmp(value, "ForceAuthorized") == 0) 529 eapol_sm_notify_portControl(wpa_s->eapol, 530 ForceAuthorized); 531 else 532 ret = -1; 533 #endif /* CONFIG_TESTING_OPTIONS */ 534 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 535 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 536 atoi(value))) { 537 ret = -1; 538 } else { 539 value[-1] = '='; 540 wpa_config_process_global(wpa_s->conf, cmd, -1); 541 } 542 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 543 0) { 544 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 545 atoi(value))) { 546 ret = -1; 547 } else { 548 value[-1] = '='; 549 wpa_config_process_global(wpa_s->conf, cmd, -1); 550 } 551 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 552 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 553 atoi(value))) { 554 ret = -1; 555 } else { 556 value[-1] = '='; 557 wpa_config_process_global(wpa_s->conf, cmd, -1); 558 } 559 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 560 wpa_s->wps_fragment_size = atoi(value); 561 #ifdef CONFIG_WPS_TESTING 562 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 563 long int val; 564 val = strtol(value, NULL, 0); 565 if (val < 0 || val > 0xff) { 566 ret = -1; 567 wpa_printf(MSG_DEBUG, "WPS: Invalid " 568 "wps_version_number %ld", val); 569 } else { 570 wps_version_number = val; 571 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 572 "version %u.%u", 573 (wps_version_number & 0xf0) >> 4, 574 wps_version_number & 0x0f); 575 } 576 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) { 577 wps_testing_stub_cred = atoi(value); 578 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d", 579 wps_testing_stub_cred); 580 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 581 wps_corrupt_pkhash = atoi(value); 582 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 583 wps_corrupt_pkhash); 584 } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) { 585 if (value[0] == '\0') { 586 wps_force_auth_types_in_use = 0; 587 } else { 588 wps_force_auth_types = strtol(value, NULL, 0); 589 wps_force_auth_types_in_use = 1; 590 } 591 } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) { 592 if (value[0] == '\0') { 593 wps_force_encr_types_in_use = 0; 594 } else { 595 wps_force_encr_types = strtol(value, NULL, 0); 596 wps_force_encr_types_in_use = 1; 597 } 598 #endif /* CONFIG_WPS_TESTING */ 599 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 600 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 601 ret = -1; 602 #ifdef CONFIG_TDLS 603 #ifdef CONFIG_TDLS_TESTING 604 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 605 tdls_testing = strtol(value, NULL, 0); 606 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 607 #endif /* CONFIG_TDLS_TESTING */ 608 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 609 int disabled = atoi(value); 610 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 611 if (disabled) { 612 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 613 ret = -1; 614 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 615 ret = -1; 616 wpa_tdls_enable(wpa_s->wpa, !disabled); 617 #endif /* CONFIG_TDLS */ 618 } else if (os_strcasecmp(cmd, "pno") == 0) { 619 ret = wpas_ctrl_pno(wpa_s, value); 620 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 621 int disabled = atoi(value); 622 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 623 ret = -1; 624 else if (disabled) 625 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 626 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 627 if (os_strcmp(value, "disable") == 0) 628 wpa_s->set_sta_uapsd = 0; 629 else { 630 int be, bk, vi, vo; 631 char *pos; 632 /* format: BE,BK,VI,VO;max SP Length */ 633 be = atoi(value); 634 pos = os_strchr(value, ','); 635 if (pos == NULL) 636 return -1; 637 pos++; 638 bk = atoi(pos); 639 pos = os_strchr(pos, ','); 640 if (pos == NULL) 641 return -1; 642 pos++; 643 vi = atoi(pos); 644 pos = os_strchr(pos, ','); 645 if (pos == NULL) 646 return -1; 647 pos++; 648 vo = atoi(pos); 649 /* ignore max SP Length for now */ 650 651 wpa_s->set_sta_uapsd = 1; 652 wpa_s->sta_uapsd = 0; 653 if (be) 654 wpa_s->sta_uapsd |= BIT(0); 655 if (bk) 656 wpa_s->sta_uapsd |= BIT(1); 657 if (vi) 658 wpa_s->sta_uapsd |= BIT(2); 659 if (vo) 660 wpa_s->sta_uapsd |= BIT(3); 661 } 662 } else if (os_strcasecmp(cmd, "ps") == 0) { 663 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 664 #ifdef CONFIG_WIFI_DISPLAY 665 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 666 int enabled = !!atoi(value); 667 if (enabled && !wpa_s->global->p2p) 668 ret = -1; 669 else 670 wifi_display_enable(wpa_s->global, enabled); 671 #endif /* CONFIG_WIFI_DISPLAY */ 672 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 673 ret = set_bssid_filter(wpa_s, value); 674 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 675 ret = set_disallow_aps(wpa_s, value); 676 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 677 wpa_s->no_keep_alive = !!atoi(value); 678 #ifdef CONFIG_DPP 679 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { 680 os_free(wpa_s->dpp_configurator_params); 681 wpa_s->dpp_configurator_params = os_strdup(value); 682 #ifdef CONFIG_DPP2 683 dpp_controller_set_params(wpa_s->dpp, value); 684 #endif /* CONFIG_DPP2 */ 685 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { 686 wpa_s->dpp_init_max_tries = atoi(value); 687 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { 688 wpa_s->dpp_init_retry_time = atoi(value); 689 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { 690 wpa_s->dpp_resp_wait_time = atoi(value); 691 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { 692 wpa_s->dpp_resp_max_tries = atoi(value); 693 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { 694 wpa_s->dpp_resp_retry_time = atoi(value); 695 #ifdef CONFIG_TESTING_OPTIONS 696 } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) { 697 if (hwaddr_aton(value, dpp_pkex_own_mac_override)) 698 ret = -1; 699 } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) { 700 if (hwaddr_aton(value, dpp_pkex_peer_mac_override)) 701 ret = -1; 702 } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) { 703 size_t hex_len = os_strlen(value); 704 705 if (hex_len > 706 2 * sizeof(dpp_pkex_ephemeral_key_override)) 707 ret = -1; 708 else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override, 709 hex_len / 2)) 710 ret = -1; 711 else 712 dpp_pkex_ephemeral_key_override_len = hex_len / 2; 713 } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) { 714 size_t hex_len = os_strlen(value); 715 716 if (hex_len > 2 * sizeof(dpp_protocol_key_override)) 717 ret = -1; 718 else if (hexstr2bin(value, dpp_protocol_key_override, 719 hex_len / 2)) 720 ret = -1; 721 else 722 dpp_protocol_key_override_len = hex_len / 2; 723 } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) { 724 size_t hex_len = os_strlen(value); 725 726 if (hex_len > 2 * sizeof(dpp_nonce_override)) 727 ret = -1; 728 else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2)) 729 ret = -1; 730 else 731 dpp_nonce_override_len = hex_len / 2; 732 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { 733 dpp_version_override = atoi(value); 734 #endif /* CONFIG_TESTING_OPTIONS */ 735 #endif /* CONFIG_DPP */ 736 #ifdef CONFIG_TESTING_OPTIONS 737 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 738 wpa_s->ext_mgmt_frame_handling = !!atoi(value); 739 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 740 wpa_s->ext_eapol_frame_io = !!atoi(value); 741 #ifdef CONFIG_AP 742 if (wpa_s->ap_iface) { 743 wpa_s->ap_iface->bss[0]->ext_eapol_frame_io = 744 wpa_s->ext_eapol_frame_io; 745 } 746 #endif /* CONFIG_AP */ 747 } else if (os_strcasecmp(cmd, "encrypt_eapol_m2") == 0) { 748 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 749 !!atoi(value)); 750 } else if (os_strcasecmp(cmd, "encrypt_eapol_m4") == 0) { 751 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 752 !!atoi(value)); 753 } else if (os_strcasecmp(cmd, "extra_roc_dur") == 0) { 754 wpa_s->extra_roc_dur = atoi(value); 755 } else if (os_strcasecmp(cmd, "test_failure") == 0) { 756 wpa_s->test_failure = atoi(value); 757 } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) { 758 wpa_s->p2p_go_csa_on_inv = !!atoi(value); 759 } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) { 760 wpa_s->ignore_auth_resp = !!atoi(value); 761 } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) { 762 wpa_s->ignore_assoc_disallow = !!atoi(value); 763 wpa_drv_ignore_assoc_disallow(wpa_s, 764 wpa_s->ignore_assoc_disallow); 765 } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) { 766 wpa_s->disable_sa_query = !!atoi(value); 767 } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) { 768 wpa_s->ignore_sae_h2e_only = !!atoi(value); 769 } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) { 770 char *pos; 771 772 os_free(wpa_s->extra_sae_rejected_groups); 773 wpa_s->extra_sae_rejected_groups = NULL; 774 pos = value; 775 while (pos && pos[0]) { 776 int group; 777 778 group = atoi(pos); 779 wpa_printf(MSG_DEBUG, 780 "TESTING: Extra rejection of SAE group %d", 781 group); 782 if (group) 783 int_array_add_unique( 784 &wpa_s->extra_sae_rejected_groups, 785 group); 786 pos = os_strchr(pos, ' '); 787 if (!pos) 788 break; 789 pos++; 790 } 791 } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) { 792 wpa_s->ft_rsnxe_used = atoi(value); 793 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) { 794 wpa_s->oci_freq_override_eapol = atoi(value); 795 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) { 796 wpa_s->oci_freq_override_saquery_req = atoi(value); 797 } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) { 798 wpa_s->oci_freq_override_saquery_resp = atoi(value); 799 } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) { 800 wpa_s->oci_freq_override_eapol_g2 = atoi(value); 801 /* Populate value to wpa_sm if already associated. */ 802 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, 803 wpa_s->oci_freq_override_eapol_g2); 804 } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) { 805 wpa_s->oci_freq_override_ft_assoc = atoi(value); 806 /* Populate value to wpa_sm if already associated. */ 807 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, 808 wpa_s->oci_freq_override_ft_assoc); 809 } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) { 810 wpa_s->oci_freq_override_fils_assoc = atoi(value); 811 } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) { 812 wpa_s->oci_freq_override_wnm_sleep = atoi(value); 813 } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { 814 wpabuf_free(wpa_s->rsne_override_eapol); 815 if (os_strcmp(value, "NULL") == 0) 816 wpa_s->rsne_override_eapol = NULL; 817 else 818 wpa_s->rsne_override_eapol = wpabuf_parse_bin(value); 819 } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) { 820 wpabuf_free(wpa_s->rsnxe_override_assoc); 821 if (os_strcmp(value, "NULL") == 0) 822 wpa_s->rsnxe_override_assoc = NULL; 823 else 824 wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value); 825 } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) { 826 wpabuf_free(wpa_s->rsnxe_override_eapol); 827 if (os_strcmp(value, "NULL") == 0) 828 wpa_s->rsnxe_override_eapol = NULL; 829 else 830 wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value); 831 } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) { 832 wpa_s->reject_btm_req_reason = atoi(value); 833 } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) { 834 os_free(wpa_s->get_pref_freq_list_override); 835 if (!value[0]) 836 wpa_s->get_pref_freq_list_override = NULL; 837 else 838 wpa_s->get_pref_freq_list_override = os_strdup(value); 839 } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) { 840 wpabuf_free(wpa_s->sae_commit_override); 841 if (value[0] == '\0') 842 wpa_s->sae_commit_override = NULL; 843 else 844 wpa_s->sae_commit_override = wpabuf_parse_bin(value); 845 } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) { 846 ret = wpas_ctrl_iface_set_dso(wpa_s, value); 847 #ifndef CONFIG_NO_ROBUST_AV 848 } else if (os_strcasecmp(cmd, "disable_scs_support") == 0) { 849 wpa_s->disable_scs_support = !!atoi(value); 850 } else if (os_strcasecmp(cmd, "disable_mscs_support") == 0) { 851 wpa_s->disable_mscs_support = !!atoi(value); 852 #endif /* CONFIG_NO_ROBUST_AV */ 853 } else if (os_strcasecmp(cmd, "disable_eapol_g2_tx") == 0) { 854 wpa_s->disable_eapol_g2_tx = !!atoi(value); 855 /* Populate value to wpa_sm if already associated. */ 856 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DISABLE_EAPOL_G2_TX, 857 wpa_s->disable_eapol_g2_tx); 858 } else if (os_strcasecmp(cmd, "test_assoc_comeback_type") == 0) { 859 wpa_s->test_assoc_comeback_type = atoi(value); 860 #ifdef CONFIG_DPP 861 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { 862 os_free(wpa_s->dpp_config_obj_override); 863 if (value[0] == '\0') 864 wpa_s->dpp_config_obj_override = NULL; 865 else 866 wpa_s->dpp_config_obj_override = os_strdup(value); 867 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { 868 os_free(wpa_s->dpp_discovery_override); 869 if (value[0] == '\0') 870 wpa_s->dpp_discovery_override = NULL; 871 else 872 wpa_s->dpp_discovery_override = os_strdup(value); 873 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { 874 os_free(wpa_s->dpp_groups_override); 875 if (value[0] == '\0') 876 wpa_s->dpp_groups_override = NULL; 877 else 878 wpa_s->dpp_groups_override = os_strdup(value); 879 } else if (os_strcasecmp(cmd, 880 "dpp_ignore_netaccesskey_mismatch") == 0) { 881 wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value); 882 } else if (os_strcasecmp(cmd, "dpp_discard_public_action") == 0) { 883 wpa_s->dpp_discard_public_action = atoi(value); 884 } else if (os_strcasecmp(cmd, "dpp_test") == 0) { 885 dpp_test = atoi(value); 886 #endif /* CONFIG_DPP */ 887 #endif /* CONFIG_TESTING_OPTIONS */ 888 #ifdef CONFIG_FILS 889 } else if (os_strcasecmp(cmd, "disable_fils") == 0) { 890 wpa_s->disable_fils = !!atoi(value); 891 wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils); 892 wpa_supplicant_set_default_scan_ies(wpa_s); 893 #endif /* CONFIG_FILS */ 894 #ifndef CONFIG_NO_CONFIG_BLOBS 895 } else if (os_strcmp(cmd, "blob") == 0) { 896 ret = wpas_ctrl_set_blob(wpa_s, value); 897 #endif /* CONFIG_NO_CONFIG_BLOBS */ 898 } else if (os_strcasecmp(cmd, "setband") == 0) { 899 ret = wpas_ctrl_set_band(wpa_s, value); 900 #ifdef CONFIG_MBO 901 } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) { 902 ret = wpas_mbo_update_non_pref_chan(wpa_s, value); 903 if (ret == 0) { 904 value[-1] = '='; 905 wpa_config_process_global(wpa_s->conf, cmd, -1); 906 } 907 } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { 908 int val = atoi(value); 909 910 if (val < MBO_CELL_CAPA_AVAILABLE || 911 val > MBO_CELL_CAPA_NOT_SUPPORTED) 912 return -1; 913 914 wpas_mbo_update_cell_capa(wpa_s, val); 915 } else if (os_strcasecmp(cmd, "oce") == 0) { 916 int val = atoi(value); 917 918 if (val < 0 || val > 3) 919 return -1; 920 921 wpa_s->conf->oce = val; 922 if (wpa_s->conf->oce) { 923 if ((wpa_s->conf->oce & OCE_STA) && 924 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) 925 wpa_s->enable_oce = OCE_STA; 926 927 if ((wpa_s->conf->oce & OCE_STA_CFON) && 928 (wpa_s->drv_flags & 929 WPA_DRIVER_FLAGS_OCE_STA_CFON)) { 930 /* TODO: Need to add STA-CFON support */ 931 wpa_printf(MSG_ERROR, 932 "OCE STA-CFON feature is not yet supported"); 933 return -1; 934 } 935 } else { 936 wpa_s->enable_oce = 0; 937 } 938 wpa_supplicant_set_default_scan_ies(wpa_s); 939 #endif /* CONFIG_MBO */ 940 } else if (os_strcasecmp(cmd, "lci") == 0) { 941 ret = wpas_ctrl_iface_set_lci(wpa_s, value); 942 } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) { 943 ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value)); 944 } else if (os_strcasecmp(cmd, "relative_rssi") == 0) { 945 ret = wpas_ctrl_set_relative_rssi(wpa_s, value); 946 } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) { 947 ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value); 948 } else if (os_strcasecmp(cmd, "ric_ies") == 0) { 949 ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value); 950 } else if (os_strcasecmp(cmd, "roaming") == 0) { 951 ret = wpa_drv_roaming(wpa_s, atoi(value), NULL); 952 #ifdef CONFIG_WNM 953 } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) { 954 struct wpabuf *elems; 955 956 elems = wpabuf_parse_bin(value); 957 if (!elems) 958 return -1; 959 wnm_set_coloc_intf_elems(wpa_s, elems); 960 #endif /* CONFIG_WNM */ 961 #ifndef CONFIG_NO_ROBUST_AV 962 } else if (os_strcasecmp(cmd, "enable_dscp_policy_capa") == 0) { 963 wpa_s->enable_dscp_policy_capa = !!atoi(value); 964 #endif /* CONFIG_NO_ROBUST_AV */ 965 } else { 966 value[-1] = '='; 967 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 968 if (ret == 0) 969 wpa_supplicant_update_config(wpa_s); 970 else if (ret == 1) 971 ret = 0; 972 } 973 974 return ret; 975 } 976 977 978 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 979 char *cmd, char *buf, size_t buflen) 980 { 981 int res = -1; 982 983 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 984 985 if (os_strcmp(cmd, "version") == 0) { 986 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 987 } else if (os_strcasecmp(cmd, "max_command_len") == 0) { 988 res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN); 989 } else if (os_strcasecmp(cmd, "country") == 0) { 990 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 991 res = os_snprintf(buf, buflen, "%c%c", 992 wpa_s->conf->country[0], 993 wpa_s->conf->country[1]); 994 #ifdef CONFIG_WIFI_DISPLAY 995 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 996 int enabled; 997 if (wpa_s->global->p2p == NULL || 998 wpa_s->global->p2p_disabled) 999 enabled = 0; 1000 else 1001 enabled = wpa_s->global->wifi_display; 1002 res = os_snprintf(buf, buflen, "%d", enabled); 1003 #endif /* CONFIG_WIFI_DISPLAY */ 1004 #ifdef CONFIG_TESTING_GET_GTK 1005 } else if (os_strcmp(cmd, "gtk") == 0) { 1006 if (wpa_s->last_gtk_len == 0) 1007 return -1; 1008 res = wpa_snprintf_hex(buf, buflen, wpa_s->last_gtk, 1009 wpa_s->last_gtk_len); 1010 return res; 1011 #endif /* CONFIG_TESTING_GET_GTK */ 1012 } else if (os_strcmp(cmd, "tls_library") == 0) { 1013 res = tls_get_library_version(buf, buflen); 1014 #ifdef CONFIG_TESTING_OPTIONS 1015 } else if (os_strcmp(cmd, "anonce") == 0) { 1016 return wpa_snprintf_hex(buf, buflen, 1017 wpa_sm_get_anonce(wpa_s->wpa), 1018 WPA_NONCE_LEN); 1019 } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) { 1020 res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx); 1021 #endif /* CONFIG_TESTING_OPTIONS */ 1022 } else { 1023 res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); 1024 } 1025 1026 if (os_snprintf_error(buflen, res)) 1027 return -1; 1028 return res; 1029 } 1030 1031 1032 #ifdef IEEE8021X_EAPOL 1033 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 1034 char *addr) 1035 { 1036 u8 bssid[ETH_ALEN]; 1037 struct wpa_ssid *ssid = wpa_s->current_ssid; 1038 1039 if (hwaddr_aton(addr, bssid)) { 1040 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 1041 "'%s'", addr); 1042 return -1; 1043 } 1044 1045 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 1046 rsn_preauth_deinit(wpa_s->wpa); 1047 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 1048 return -1; 1049 1050 return 0; 1051 } 1052 #endif /* IEEE8021X_EAPOL */ 1053 1054 1055 #ifdef CONFIG_TDLS 1056 1057 static int wpa_supplicant_ctrl_iface_tdls_discover( 1058 struct wpa_supplicant *wpa_s, char *addr) 1059 { 1060 u8 peer[ETH_ALEN]; 1061 int ret; 1062 1063 if (hwaddr_aton(addr, peer)) { 1064 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 1065 "address '%s'", addr); 1066 return -1; 1067 } 1068 1069 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 1070 MAC2STR(peer)); 1071 1072 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1073 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 1074 else 1075 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 1076 1077 return ret; 1078 } 1079 1080 1081 static int wpa_supplicant_ctrl_iface_tdls_setup( 1082 struct wpa_supplicant *wpa_s, char *addr) 1083 { 1084 u8 peer[ETH_ALEN]; 1085 int ret; 1086 1087 if (hwaddr_aton(addr, peer)) { 1088 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 1089 "address '%s'", addr); 1090 return -1; 1091 } 1092 1093 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 1094 MAC2STR(peer)); 1095 1096 if ((wpa_s->conf->tdls_external_control) && 1097 wpa_tdls_is_external_setup(wpa_s->wpa)) 1098 return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 1099 1100 wpa_tdls_remove(wpa_s->wpa, peer); 1101 1102 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1103 ret = wpa_tdls_start(wpa_s->wpa, peer); 1104 else 1105 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 1106 1107 return ret; 1108 } 1109 1110 1111 static int wpa_supplicant_ctrl_iface_tdls_teardown( 1112 struct wpa_supplicant *wpa_s, char *addr) 1113 { 1114 u8 peer[ETH_ALEN]; 1115 int ret; 1116 1117 if (os_strcmp(addr, "*") == 0) { 1118 /* remove everyone */ 1119 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN *"); 1120 wpa_tdls_teardown_peers(wpa_s->wpa); 1121 return 0; 1122 } 1123 1124 if (hwaddr_aton(addr, peer)) { 1125 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 1126 "address '%s'", addr); 1127 return -1; 1128 } 1129 1130 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 1131 MAC2STR(peer)); 1132 1133 if ((wpa_s->conf->tdls_external_control) && 1134 wpa_tdls_is_external_setup(wpa_s->wpa)) 1135 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 1136 1137 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 1138 ret = wpa_tdls_teardown_link( 1139 wpa_s->wpa, peer, 1140 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 1141 else 1142 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 1143 1144 return ret; 1145 } 1146 1147 1148 static int ctrl_iface_get_capability_tdls( 1149 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1150 { 1151 int ret; 1152 1153 ret = os_snprintf(buf, buflen, "%s\n", 1154 wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT ? 1155 (wpa_s->drv_flags & 1156 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP ? 1157 "EXTERNAL" : "INTERNAL") : "UNSUPPORTED"); 1158 if (os_snprintf_error(buflen, ret)) 1159 return -1; 1160 return ret; 1161 } 1162 1163 1164 static int wpa_supplicant_ctrl_iface_tdls_chan_switch( 1165 struct wpa_supplicant *wpa_s, char *cmd) 1166 { 1167 u8 peer[ETH_ALEN]; 1168 struct hostapd_freq_params freq_params; 1169 u8 oper_class; 1170 char *pos, *end; 1171 1172 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 1173 wpa_printf(MSG_INFO, 1174 "tdls_chanswitch: Only supported with external setup"); 1175 return -1; 1176 } 1177 1178 os_memset(&freq_params, 0, sizeof(freq_params)); 1179 1180 pos = os_strchr(cmd, ' '); 1181 if (pos == NULL) 1182 return -1; 1183 *pos++ = '\0'; 1184 1185 oper_class = strtol(pos, &end, 10); 1186 if (pos == end) { 1187 wpa_printf(MSG_INFO, 1188 "tdls_chanswitch: Invalid op class provided"); 1189 return -1; 1190 } 1191 1192 pos = end; 1193 freq_params.freq = atoi(pos); 1194 if (freq_params.freq == 0) { 1195 wpa_printf(MSG_INFO, "tdls_chanswitch: Invalid freq provided"); 1196 return -1; 1197 } 1198 1199 #define SET_FREQ_SETTING(str) \ 1200 do { \ 1201 const char *pos2 = os_strstr(pos, " " #str "="); \ 1202 if (pos2) { \ 1203 pos2 += sizeof(" " #str "=") - 1; \ 1204 freq_params.str = atoi(pos2); \ 1205 } \ 1206 } while (0) 1207 1208 SET_FREQ_SETTING(center_freq1); 1209 SET_FREQ_SETTING(center_freq2); 1210 SET_FREQ_SETTING(bandwidth); 1211 SET_FREQ_SETTING(sec_channel_offset); 1212 #undef SET_FREQ_SETTING 1213 1214 freq_params.ht_enabled = !!os_strstr(pos, " ht"); 1215 freq_params.vht_enabled = !!os_strstr(pos, " vht"); 1216 1217 if (hwaddr_aton(cmd, peer)) { 1218 wpa_printf(MSG_DEBUG, 1219 "CTRL_IFACE TDLS_CHAN_SWITCH: Invalid address '%s'", 1220 cmd); 1221 return -1; 1222 } 1223 1224 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CHAN_SWITCH " MACSTR 1225 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s", 1226 MAC2STR(peer), oper_class, freq_params.freq, 1227 freq_params.center_freq1, freq_params.center_freq2, 1228 freq_params.bandwidth, freq_params.sec_channel_offset, 1229 freq_params.ht_enabled ? " HT" : "", 1230 freq_params.vht_enabled ? " VHT" : ""); 1231 1232 return wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class, 1233 &freq_params); 1234 } 1235 1236 1237 static int wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch( 1238 struct wpa_supplicant *wpa_s, char *cmd) 1239 { 1240 u8 peer[ETH_ALEN]; 1241 1242 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 1243 wpa_printf(MSG_INFO, 1244 "tdls_chanswitch: Only supported with external setup"); 1245 return -1; 1246 } 1247 1248 if (hwaddr_aton(cmd, peer)) { 1249 wpa_printf(MSG_DEBUG, 1250 "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH: Invalid address '%s'", 1251 cmd); 1252 return -1; 1253 } 1254 1255 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_CANCEL_CHAN_SWITCH " MACSTR, 1256 MAC2STR(peer)); 1257 1258 return wpa_tdls_disable_chan_switch(wpa_s->wpa, peer); 1259 } 1260 1261 1262 static int wpa_supplicant_ctrl_iface_tdls_link_status( 1263 struct wpa_supplicant *wpa_s, const char *addr, 1264 char *buf, size_t buflen) 1265 { 1266 u8 peer[ETH_ALEN]; 1267 const char *tdls_status; 1268 int ret; 1269 1270 if (hwaddr_aton(addr, peer)) { 1271 wpa_printf(MSG_DEBUG, 1272 "CTRL_IFACE TDLS_LINK_STATUS: Invalid address '%s'", 1273 addr); 1274 return -1; 1275 } 1276 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS " MACSTR, 1277 MAC2STR(peer)); 1278 1279 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 1280 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_LINK_STATUS: %s", tdls_status); 1281 ret = os_snprintf(buf, buflen, "TDLS link status: %s\n", tdls_status); 1282 if (os_snprintf_error(buflen, ret)) 1283 return -1; 1284 1285 return ret; 1286 } 1287 1288 #endif /* CONFIG_TDLS */ 1289 1290 1291 #ifndef CONFIG_NO_WMM_AC 1292 1293 static int wmm_ac_ctrl_addts(struct wpa_supplicant *wpa_s, char *cmd) 1294 { 1295 char *token, *context = NULL; 1296 struct wmm_ac_ts_setup_params params = { 1297 .tsid = 0xff, 1298 .direction = 0xff, 1299 }; 1300 1301 while ((token = str_token(cmd, " ", &context))) { 1302 if (sscanf(token, "tsid=%i", ¶ms.tsid) == 1 || 1303 sscanf(token, "up=%i", ¶ms.user_priority) == 1 || 1304 sscanf(token, "nominal_msdu_size=%i", 1305 ¶ms.nominal_msdu_size) == 1 || 1306 sscanf(token, "mean_data_rate=%i", 1307 ¶ms.mean_data_rate) == 1 || 1308 sscanf(token, "min_phy_rate=%i", 1309 ¶ms.minimum_phy_rate) == 1 || 1310 sscanf(token, "sba=%i", 1311 ¶ms.surplus_bandwidth_allowance) == 1) 1312 continue; 1313 1314 if (os_strcasecmp(token, "downlink") == 0) { 1315 params.direction = WMM_TSPEC_DIRECTION_DOWNLINK; 1316 } else if (os_strcasecmp(token, "uplink") == 0) { 1317 params.direction = WMM_TSPEC_DIRECTION_UPLINK; 1318 } else if (os_strcasecmp(token, "bidi") == 0) { 1319 params.direction = WMM_TSPEC_DIRECTION_BI_DIRECTIONAL; 1320 } else if (os_strcasecmp(token, "fixed_nominal_msdu") == 0) { 1321 params.fixed_nominal_msdu = 1; 1322 } else { 1323 wpa_printf(MSG_DEBUG, 1324 "CTRL: Invalid WMM_AC_ADDTS parameter: '%s'", 1325 token); 1326 return -1; 1327 } 1328 1329 } 1330 1331 return wpas_wmm_ac_addts(wpa_s, ¶ms); 1332 } 1333 1334 1335 static int wmm_ac_ctrl_delts(struct wpa_supplicant *wpa_s, char *cmd) 1336 { 1337 u8 tsid = atoi(cmd); 1338 1339 return wpas_wmm_ac_delts(wpa_s, tsid); 1340 } 1341 1342 #endif /* CONFIG_NO_WMM_AC */ 1343 1344 1345 #ifdef CONFIG_IEEE80211R 1346 static int wpa_supplicant_ctrl_iface_ft_ds( 1347 struct wpa_supplicant *wpa_s, char *addr) 1348 { 1349 u8 target_ap[ETH_ALEN]; 1350 struct wpa_bss *bss; 1351 const u8 *mdie; 1352 bool force = os_strstr(addr, " force") != NULL; 1353 1354 if (hwaddr_aton(addr, target_ap)) { 1355 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 1356 "address '%s'", addr); 1357 return -1; 1358 } 1359 1360 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 1361 1362 bss = wpa_bss_get_bssid(wpa_s, target_ap); 1363 if (bss) 1364 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 1365 else 1366 mdie = NULL; 1367 1368 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie, force); 1369 } 1370 #endif /* CONFIG_IEEE80211R */ 1371 1372 1373 #ifdef CONFIG_WPS 1374 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 1375 char *cmd) 1376 { 1377 u8 bssid[ETH_ALEN], *_bssid = bssid; 1378 #ifdef CONFIG_P2P 1379 u8 p2p_dev_addr[ETH_ALEN]; 1380 #endif /* CONFIG_P2P */ 1381 #ifdef CONFIG_AP 1382 u8 *_p2p_dev_addr = NULL; 1383 #endif /* CONFIG_AP */ 1384 char *pos; 1385 int multi_ap = 0; 1386 1387 if (!cmd || os_strcmp(cmd, "any") == 0 || 1388 os_strncmp(cmd, "any ", 4) == 0) { 1389 _bssid = NULL; 1390 #ifdef CONFIG_P2P 1391 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 1392 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 1393 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 1394 "P2P Device Address '%s'", 1395 cmd + 13); 1396 return -1; 1397 } 1398 _p2p_dev_addr = p2p_dev_addr; 1399 #endif /* CONFIG_P2P */ 1400 } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) { 1401 _bssid = NULL; 1402 multi_ap = atoi(cmd + 9); 1403 } else if (hwaddr_aton(cmd, bssid)) { 1404 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 1405 cmd); 1406 return -1; 1407 } 1408 1409 if (cmd) { 1410 pos = os_strstr(cmd, " multi_ap="); 1411 if (pos) { 1412 pos += 10; 1413 multi_ap = atoi(pos); 1414 } 1415 } 1416 1417 #ifdef CONFIG_AP 1418 if (wpa_s->ap_iface) 1419 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 1420 #endif /* CONFIG_AP */ 1421 1422 return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap); 1423 } 1424 1425 1426 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 1427 char *cmd, char *buf, 1428 size_t buflen) 1429 { 1430 u8 bssid[ETH_ALEN], *_bssid = bssid; 1431 char *pin; 1432 int ret; 1433 1434 pin = os_strchr(cmd, ' '); 1435 if (pin) 1436 *pin++ = '\0'; 1437 1438 if (os_strcmp(cmd, "any") == 0) 1439 _bssid = NULL; 1440 else if (os_strcmp(cmd, "get") == 0) { 1441 if (wps_generate_pin((unsigned int *) &ret) < 0) 1442 return -1; 1443 goto done; 1444 } else if (hwaddr_aton(cmd, bssid)) { 1445 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 1446 cmd); 1447 return -1; 1448 } 1449 1450 #ifdef CONFIG_AP 1451 if (wpa_s->ap_iface) { 1452 int timeout = 0; 1453 char *pos; 1454 1455 if (pin) { 1456 pos = os_strchr(pin, ' '); 1457 if (pos) { 1458 *pos++ = '\0'; 1459 timeout = atoi(pos); 1460 } 1461 } 1462 1463 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 1464 buf, buflen, timeout); 1465 } 1466 #endif /* CONFIG_AP */ 1467 1468 if (pin) { 1469 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 1470 DEV_PW_DEFAULT); 1471 if (ret < 0) 1472 return -1; 1473 ret = os_snprintf(buf, buflen, "%s", pin); 1474 if (os_snprintf_error(buflen, ret)) 1475 return -1; 1476 return ret; 1477 } 1478 1479 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 1480 if (ret < 0) 1481 return -1; 1482 1483 done: 1484 /* Return the generated PIN */ 1485 ret = os_snprintf(buf, buflen, "%08d", ret); 1486 if (os_snprintf_error(buflen, ret)) 1487 return -1; 1488 return ret; 1489 } 1490 1491 1492 static int wpa_supplicant_ctrl_iface_wps_check_pin( 1493 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1494 { 1495 char pin[9]; 1496 size_t len; 1497 char *pos; 1498 int ret; 1499 1500 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 1501 (u8 *) cmd, os_strlen(cmd)); 1502 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 1503 if (*pos < '0' || *pos > '9') 1504 continue; 1505 pin[len++] = *pos; 1506 if (len == 9) { 1507 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 1508 return -1; 1509 } 1510 } 1511 if (len != 4 && len != 8) { 1512 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 1513 return -1; 1514 } 1515 pin[len] = '\0'; 1516 1517 if (len == 8) { 1518 unsigned int pin_val; 1519 pin_val = atoi(pin); 1520 if (!wps_pin_valid(pin_val)) { 1521 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 1522 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 1523 if (os_snprintf_error(buflen, ret)) 1524 return -1; 1525 return ret; 1526 } 1527 } 1528 1529 ret = os_snprintf(buf, buflen, "%s", pin); 1530 if (os_snprintf_error(buflen, ret)) 1531 return -1; 1532 1533 return ret; 1534 } 1535 1536 1537 #ifdef CONFIG_WPS_NFC 1538 1539 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 1540 char *cmd) 1541 { 1542 u8 bssid[ETH_ALEN], *_bssid = bssid; 1543 1544 if (cmd == NULL || cmd[0] == '\0') 1545 _bssid = NULL; 1546 else if (hwaddr_aton(cmd, bssid)) 1547 return -1; 1548 1549 return wpas_wps_start_nfc(wpa_s, NULL, _bssid, NULL, 0, 0, NULL, NULL, 1550 0, 0); 1551 } 1552 1553 1554 static int wpa_supplicant_ctrl_iface_wps_nfc_config_token( 1555 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1556 { 1557 int ndef; 1558 struct wpabuf *buf; 1559 int res; 1560 char *pos; 1561 1562 pos = os_strchr(cmd, ' '); 1563 if (pos) 1564 *pos++ = '\0'; 1565 if (os_strcmp(cmd, "WPS") == 0) 1566 ndef = 0; 1567 else if (os_strcmp(cmd, "NDEF") == 0) 1568 ndef = 1; 1569 else 1570 return -1; 1571 1572 buf = wpas_wps_nfc_config_token(wpa_s, ndef, pos); 1573 if (buf == NULL) 1574 return -1; 1575 1576 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1577 wpabuf_len(buf)); 1578 reply[res++] = '\n'; 1579 reply[res] = '\0'; 1580 1581 wpabuf_free(buf); 1582 1583 return res; 1584 } 1585 1586 1587 static int wpa_supplicant_ctrl_iface_wps_nfc_token( 1588 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1589 { 1590 int ndef; 1591 struct wpabuf *buf; 1592 int res; 1593 1594 if (os_strcmp(cmd, "WPS") == 0) 1595 ndef = 0; 1596 else if (os_strcmp(cmd, "NDEF") == 0) 1597 ndef = 1; 1598 else 1599 return -1; 1600 1601 buf = wpas_wps_nfc_token(wpa_s, ndef); 1602 if (buf == NULL) 1603 return -1; 1604 1605 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1606 wpabuf_len(buf)); 1607 reply[res++] = '\n'; 1608 reply[res] = '\0'; 1609 1610 wpabuf_free(buf); 1611 1612 return res; 1613 } 1614 1615 1616 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 1617 struct wpa_supplicant *wpa_s, char *pos) 1618 { 1619 size_t len; 1620 struct wpabuf *buf; 1621 int ret; 1622 char *freq; 1623 int forced_freq = 0; 1624 1625 freq = strstr(pos, " freq="); 1626 if (freq) { 1627 *freq = '\0'; 1628 freq += 6; 1629 forced_freq = atoi(freq); 1630 } 1631 1632 len = os_strlen(pos); 1633 if (len & 0x01) 1634 return -1; 1635 len /= 2; 1636 1637 buf = wpabuf_alloc(len); 1638 if (buf == NULL) 1639 return -1; 1640 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 1641 wpabuf_free(buf); 1642 return -1; 1643 } 1644 1645 ret = wpas_wps_nfc_tag_read(wpa_s, buf, forced_freq); 1646 wpabuf_free(buf); 1647 1648 return ret; 1649 } 1650 1651 1652 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 1653 char *reply, size_t max_len, 1654 int ndef) 1655 { 1656 struct wpabuf *buf; 1657 int res; 1658 1659 buf = wpas_wps_nfc_handover_req(wpa_s, ndef); 1660 if (buf == NULL) 1661 return -1; 1662 1663 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1664 wpabuf_len(buf)); 1665 reply[res++] = '\n'; 1666 reply[res] = '\0'; 1667 1668 wpabuf_free(buf); 1669 1670 return res; 1671 } 1672 1673 1674 #ifdef CONFIG_P2P 1675 static int wpas_ctrl_nfc_get_handover_req_p2p(struct wpa_supplicant *wpa_s, 1676 char *reply, size_t max_len, 1677 int ndef) 1678 { 1679 struct wpabuf *buf; 1680 int res; 1681 1682 buf = wpas_p2p_nfc_handover_req(wpa_s, ndef); 1683 if (buf == NULL) { 1684 wpa_printf(MSG_DEBUG, "P2P: Could not generate NFC handover request"); 1685 return -1; 1686 } 1687 1688 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1689 wpabuf_len(buf)); 1690 reply[res++] = '\n'; 1691 reply[res] = '\0'; 1692 1693 wpabuf_free(buf); 1694 1695 return res; 1696 } 1697 #endif /* CONFIG_P2P */ 1698 1699 1700 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 1701 char *cmd, char *reply, 1702 size_t max_len) 1703 { 1704 char *pos; 1705 int ndef; 1706 1707 pos = os_strchr(cmd, ' '); 1708 if (pos == NULL) 1709 return -1; 1710 *pos++ = '\0'; 1711 1712 if (os_strcmp(cmd, "WPS") == 0) 1713 ndef = 0; 1714 else if (os_strcmp(cmd, "NDEF") == 0) 1715 ndef = 1; 1716 else 1717 return -1; 1718 1719 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1720 if (!ndef) 1721 return -1; 1722 return wpas_ctrl_nfc_get_handover_req_wps( 1723 wpa_s, reply, max_len, ndef); 1724 } 1725 1726 #ifdef CONFIG_P2P 1727 if (os_strcmp(pos, "P2P-CR") == 0) { 1728 return wpas_ctrl_nfc_get_handover_req_p2p( 1729 wpa_s, reply, max_len, ndef); 1730 } 1731 #endif /* CONFIG_P2P */ 1732 1733 return -1; 1734 } 1735 1736 1737 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 1738 char *reply, size_t max_len, 1739 int ndef, int cr, char *uuid) 1740 { 1741 struct wpabuf *buf; 1742 int res; 1743 1744 buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid); 1745 if (buf == NULL) 1746 return -1; 1747 1748 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1749 wpabuf_len(buf)); 1750 reply[res++] = '\n'; 1751 reply[res] = '\0'; 1752 1753 wpabuf_free(buf); 1754 1755 return res; 1756 } 1757 1758 1759 #ifdef CONFIG_P2P 1760 static int wpas_ctrl_nfc_get_handover_sel_p2p(struct wpa_supplicant *wpa_s, 1761 char *reply, size_t max_len, 1762 int ndef, int tag) 1763 { 1764 struct wpabuf *buf; 1765 int res; 1766 1767 buf = wpas_p2p_nfc_handover_sel(wpa_s, ndef, tag); 1768 if (buf == NULL) 1769 return -1; 1770 1771 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1772 wpabuf_len(buf)); 1773 reply[res++] = '\n'; 1774 reply[res] = '\0'; 1775 1776 wpabuf_free(buf); 1777 1778 return res; 1779 } 1780 #endif /* CONFIG_P2P */ 1781 1782 1783 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 1784 char *cmd, char *reply, 1785 size_t max_len) 1786 { 1787 char *pos, *pos2; 1788 int ndef; 1789 1790 pos = os_strchr(cmd, ' '); 1791 if (pos == NULL) 1792 return -1; 1793 *pos++ = '\0'; 1794 1795 if (os_strcmp(cmd, "WPS") == 0) 1796 ndef = 0; 1797 else if (os_strcmp(cmd, "NDEF") == 0) 1798 ndef = 1; 1799 else 1800 return -1; 1801 1802 pos2 = os_strchr(pos, ' '); 1803 if (pos2) 1804 *pos2++ = '\0'; 1805 if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) { 1806 if (!ndef) 1807 return -1; 1808 return wpas_ctrl_nfc_get_handover_sel_wps( 1809 wpa_s, reply, max_len, ndef, 1810 os_strcmp(pos, "WPS-CR") == 0, pos2); 1811 } 1812 1813 #ifdef CONFIG_P2P 1814 if (os_strcmp(pos, "P2P-CR") == 0) { 1815 return wpas_ctrl_nfc_get_handover_sel_p2p( 1816 wpa_s, reply, max_len, ndef, 0); 1817 } 1818 1819 if (os_strcmp(pos, "P2P-CR-TAG") == 0) { 1820 return wpas_ctrl_nfc_get_handover_sel_p2p( 1821 wpa_s, reply, max_len, ndef, 1); 1822 } 1823 #endif /* CONFIG_P2P */ 1824 1825 return -1; 1826 } 1827 1828 1829 static int wpas_ctrl_nfc_report_handover(struct wpa_supplicant *wpa_s, 1830 char *cmd) 1831 { 1832 size_t len; 1833 struct wpabuf *req, *sel; 1834 int ret; 1835 char *pos, *role, *type, *pos2; 1836 #ifdef CONFIG_P2P 1837 char *freq; 1838 int forced_freq = 0; 1839 1840 freq = strstr(cmd, " freq="); 1841 if (freq) { 1842 *freq = '\0'; 1843 freq += 6; 1844 forced_freq = atoi(freq); 1845 } 1846 #endif /* CONFIG_P2P */ 1847 1848 role = cmd; 1849 pos = os_strchr(role, ' '); 1850 if (pos == NULL) { 1851 wpa_printf(MSG_DEBUG, "NFC: Missing type in handover report"); 1852 return -1; 1853 } 1854 *pos++ = '\0'; 1855 1856 type = pos; 1857 pos = os_strchr(type, ' '); 1858 if (pos == NULL) { 1859 wpa_printf(MSG_DEBUG, "NFC: Missing request message in handover report"); 1860 return -1; 1861 } 1862 *pos++ = '\0'; 1863 1864 pos2 = os_strchr(pos, ' '); 1865 if (pos2 == NULL) { 1866 wpa_printf(MSG_DEBUG, "NFC: Missing select message in handover report"); 1867 return -1; 1868 } 1869 *pos2++ = '\0'; 1870 1871 len = os_strlen(pos); 1872 if (len & 0x01) { 1873 wpa_printf(MSG_DEBUG, "NFC: Invalid request message length in handover report"); 1874 return -1; 1875 } 1876 len /= 2; 1877 1878 req = wpabuf_alloc(len); 1879 if (req == NULL) { 1880 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for request message"); 1881 return -1; 1882 } 1883 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 1884 wpa_printf(MSG_DEBUG, "NFC: Invalid request message hexdump in handover report"); 1885 wpabuf_free(req); 1886 return -1; 1887 } 1888 1889 len = os_strlen(pos2); 1890 if (len & 0x01) { 1891 wpa_printf(MSG_DEBUG, "NFC: Invalid select message length in handover report"); 1892 wpabuf_free(req); 1893 return -1; 1894 } 1895 len /= 2; 1896 1897 sel = wpabuf_alloc(len); 1898 if (sel == NULL) { 1899 wpa_printf(MSG_DEBUG, "NFC: Failed to allocate memory for select message"); 1900 wpabuf_free(req); 1901 return -1; 1902 } 1903 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 1904 wpa_printf(MSG_DEBUG, "NFC: Invalid select message hexdump in handover report"); 1905 wpabuf_free(req); 1906 wpabuf_free(sel); 1907 return -1; 1908 } 1909 1910 wpa_printf(MSG_DEBUG, "NFC: Connection handover reported - role=%s type=%s req_len=%d sel_len=%d", 1911 role, type, (int) wpabuf_len(req), (int) wpabuf_len(sel)); 1912 1913 if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "WPS") == 0) { 1914 ret = wpas_wps_nfc_report_handover(wpa_s, req, sel); 1915 #ifdef CONFIG_AP 1916 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) 1917 { 1918 ret = wpas_ap_wps_nfc_report_handover(wpa_s, req, sel); 1919 if (ret < 0) 1920 ret = wpas_er_wps_nfc_report_handover(wpa_s, req, sel); 1921 #endif /* CONFIG_AP */ 1922 #ifdef CONFIG_P2P 1923 } else if (os_strcmp(role, "INIT") == 0 && os_strcmp(type, "P2P") == 0) 1924 { 1925 ret = wpas_p2p_nfc_report_handover(wpa_s, 1, req, sel, 0); 1926 } else if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "P2P") == 0) 1927 { 1928 ret = wpas_p2p_nfc_report_handover(wpa_s, 0, req, sel, 1929 forced_freq); 1930 #endif /* CONFIG_P2P */ 1931 } else { 1932 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 1933 "reported: role=%s type=%s", role, type); 1934 ret = -1; 1935 } 1936 wpabuf_free(req); 1937 wpabuf_free(sel); 1938 1939 if (ret) 1940 wpa_printf(MSG_DEBUG, "NFC: Failed to process reported handover messages"); 1941 1942 return ret; 1943 } 1944 1945 #endif /* CONFIG_WPS_NFC */ 1946 1947 1948 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 1949 char *cmd) 1950 { 1951 u8 bssid[ETH_ALEN]; 1952 char *pin; 1953 char *new_ssid; 1954 char *new_auth; 1955 char *new_encr; 1956 char *new_key; 1957 struct wps_new_ap_settings ap; 1958 1959 pin = os_strchr(cmd, ' '); 1960 if (pin == NULL) 1961 return -1; 1962 *pin++ = '\0'; 1963 1964 if (hwaddr_aton(cmd, bssid)) { 1965 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1966 cmd); 1967 return -1; 1968 } 1969 1970 new_ssid = os_strchr(pin, ' '); 1971 if (new_ssid == NULL) 1972 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1973 *new_ssid++ = '\0'; 1974 1975 new_auth = os_strchr(new_ssid, ' '); 1976 if (new_auth == NULL) 1977 return -1; 1978 *new_auth++ = '\0'; 1979 1980 new_encr = os_strchr(new_auth, ' '); 1981 if (new_encr == NULL) 1982 return -1; 1983 *new_encr++ = '\0'; 1984 1985 new_key = os_strchr(new_encr, ' '); 1986 if (new_key == NULL) 1987 return -1; 1988 *new_key++ = '\0'; 1989 1990 os_memset(&ap, 0, sizeof(ap)); 1991 ap.ssid_hex = new_ssid; 1992 ap.auth = new_auth; 1993 ap.encr = new_encr; 1994 ap.key_hex = new_key; 1995 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1996 } 1997 1998 1999 #ifdef CONFIG_AP 2000 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 2001 char *cmd, char *buf, 2002 size_t buflen) 2003 { 2004 int timeout = 300; 2005 char *pos; 2006 const char *pin_txt; 2007 2008 if (!wpa_s->ap_iface) 2009 return -1; 2010 2011 pos = os_strchr(cmd, ' '); 2012 if (pos) 2013 *pos++ = '\0'; 2014 2015 if (os_strcmp(cmd, "disable") == 0) { 2016 wpas_wps_ap_pin_disable(wpa_s); 2017 return os_snprintf(buf, buflen, "OK\n"); 2018 } 2019 2020 if (os_strcmp(cmd, "random") == 0) { 2021 if (pos) 2022 timeout = atoi(pos); 2023 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 2024 if (pin_txt == NULL) 2025 return -1; 2026 return os_snprintf(buf, buflen, "%s", pin_txt); 2027 } 2028 2029 if (os_strcmp(cmd, "get") == 0) { 2030 pin_txt = wpas_wps_ap_pin_get(wpa_s); 2031 if (pin_txt == NULL) 2032 return -1; 2033 return os_snprintf(buf, buflen, "%s", pin_txt); 2034 } 2035 2036 if (os_strcmp(cmd, "set") == 0) { 2037 char *pin; 2038 if (pos == NULL) 2039 return -1; 2040 pin = pos; 2041 pos = os_strchr(pos, ' '); 2042 if (pos) { 2043 *pos++ = '\0'; 2044 timeout = atoi(pos); 2045 } 2046 if (os_strlen(pin) > buflen) 2047 return -1; 2048 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 2049 return -1; 2050 return os_snprintf(buf, buflen, "%s", pin); 2051 } 2052 2053 return -1; 2054 } 2055 #endif /* CONFIG_AP */ 2056 2057 2058 #ifdef CONFIG_WPS_ER 2059 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 2060 char *cmd) 2061 { 2062 char *uuid = cmd, *pin, *pos; 2063 u8 addr_buf[ETH_ALEN], *addr = NULL; 2064 pin = os_strchr(uuid, ' '); 2065 if (pin == NULL) 2066 return -1; 2067 *pin++ = '\0'; 2068 pos = os_strchr(pin, ' '); 2069 if (pos) { 2070 *pos++ = '\0'; 2071 if (hwaddr_aton(pos, addr_buf) == 0) 2072 addr = addr_buf; 2073 } 2074 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 2075 } 2076 2077 2078 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 2079 char *cmd) 2080 { 2081 char *uuid = cmd, *pin; 2082 pin = os_strchr(uuid, ' '); 2083 if (pin == NULL) 2084 return -1; 2085 *pin++ = '\0'; 2086 return wpas_wps_er_learn(wpa_s, uuid, pin); 2087 } 2088 2089 2090 static int wpa_supplicant_ctrl_iface_wps_er_set_config( 2091 struct wpa_supplicant *wpa_s, char *cmd) 2092 { 2093 char *uuid = cmd, *id; 2094 id = os_strchr(uuid, ' '); 2095 if (id == NULL) 2096 return -1; 2097 *id++ = '\0'; 2098 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 2099 } 2100 2101 2102 static int wpa_supplicant_ctrl_iface_wps_er_config( 2103 struct wpa_supplicant *wpa_s, char *cmd) 2104 { 2105 char *pin; 2106 char *new_ssid; 2107 char *new_auth; 2108 char *new_encr; 2109 char *new_key; 2110 struct wps_new_ap_settings ap; 2111 2112 pin = os_strchr(cmd, ' '); 2113 if (pin == NULL) 2114 return -1; 2115 *pin++ = '\0'; 2116 2117 new_ssid = os_strchr(pin, ' '); 2118 if (new_ssid == NULL) 2119 return -1; 2120 *new_ssid++ = '\0'; 2121 2122 new_auth = os_strchr(new_ssid, ' '); 2123 if (new_auth == NULL) 2124 return -1; 2125 *new_auth++ = '\0'; 2126 2127 new_encr = os_strchr(new_auth, ' '); 2128 if (new_encr == NULL) 2129 return -1; 2130 *new_encr++ = '\0'; 2131 2132 new_key = os_strchr(new_encr, ' '); 2133 if (new_key == NULL) 2134 return -1; 2135 *new_key++ = '\0'; 2136 2137 os_memset(&ap, 0, sizeof(ap)); 2138 ap.ssid_hex = new_ssid; 2139 ap.auth = new_auth; 2140 ap.encr = new_encr; 2141 ap.key_hex = new_key; 2142 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 2143 } 2144 2145 2146 #ifdef CONFIG_WPS_NFC 2147 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 2148 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 2149 { 2150 int ndef; 2151 struct wpabuf *buf; 2152 int res; 2153 char *uuid; 2154 2155 uuid = os_strchr(cmd, ' '); 2156 if (uuid == NULL) 2157 return -1; 2158 *uuid++ = '\0'; 2159 2160 if (os_strcmp(cmd, "WPS") == 0) 2161 ndef = 0; 2162 else if (os_strcmp(cmd, "NDEF") == 0) 2163 ndef = 1; 2164 else 2165 return -1; 2166 2167 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 2168 if (buf == NULL) 2169 return -1; 2170 2171 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 2172 wpabuf_len(buf)); 2173 reply[res++] = '\n'; 2174 reply[res] = '\0'; 2175 2176 wpabuf_free(buf); 2177 2178 return res; 2179 } 2180 #endif /* CONFIG_WPS_NFC */ 2181 #endif /* CONFIG_WPS_ER */ 2182 2183 #endif /* CONFIG_WPS */ 2184 2185 2186 #ifdef CONFIG_IBSS_RSN 2187 static int wpa_supplicant_ctrl_iface_ibss_rsn( 2188 struct wpa_supplicant *wpa_s, char *addr) 2189 { 2190 u8 peer[ETH_ALEN]; 2191 2192 if (hwaddr_aton(addr, peer)) { 2193 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 2194 "address '%s'", addr); 2195 return -1; 2196 } 2197 2198 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 2199 MAC2STR(peer)); 2200 2201 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 2202 } 2203 #endif /* CONFIG_IBSS_RSN */ 2204 2205 2206 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 2207 char *rsp) 2208 { 2209 #ifdef IEEE8021X_EAPOL 2210 char *pos, *id_pos; 2211 int id; 2212 struct wpa_ssid *ssid; 2213 2214 pos = os_strchr(rsp, '-'); 2215 if (pos == NULL) 2216 return -1; 2217 *pos++ = '\0'; 2218 id_pos = pos; 2219 pos = os_strchr(pos, ':'); 2220 if (pos == NULL) 2221 return -1; 2222 *pos++ = '\0'; 2223 id = atoi(id_pos); 2224 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 2225 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2226 (u8 *) pos, os_strlen(pos)); 2227 2228 ssid = wpa_config_get_network(wpa_s->conf, id); 2229 if (ssid == NULL) { 2230 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2231 "to update", id); 2232 return -1; 2233 } 2234 2235 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 2236 pos); 2237 #else /* IEEE8021X_EAPOL */ 2238 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 2239 return -1; 2240 #endif /* IEEE8021X_EAPOL */ 2241 } 2242 2243 2244 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 2245 const char *params, 2246 char *buf, size_t buflen) 2247 { 2248 char *pos, *end, tmp[30]; 2249 int res, verbose, wps, ret; 2250 #ifdef CONFIG_HS20 2251 const u8 *hs20; 2252 #endif /* CONFIG_HS20 */ 2253 const u8 *sess_id; 2254 size_t sess_id_len; 2255 2256 if (os_strcmp(params, "-DRIVER") == 0) 2257 return wpa_drv_status(wpa_s, buf, buflen); 2258 verbose = os_strcmp(params, "-VERBOSE") == 0; 2259 wps = os_strcmp(params, "-WPS") == 0; 2260 pos = buf; 2261 end = buf + buflen; 2262 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 2263 struct wpa_ssid *ssid = wpa_s->current_ssid; 2264 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2265 MAC2STR(wpa_s->bssid)); 2266 if (os_snprintf_error(end - pos, ret)) 2267 return pos - buf; 2268 pos += ret; 2269 ret = os_snprintf(pos, end - pos, "freq=%u\n", 2270 wpa_s->assoc_freq); 2271 if (os_snprintf_error(end - pos, ret)) 2272 return pos - buf; 2273 pos += ret; 2274 if (ssid) { 2275 u8 *_ssid = ssid->ssid; 2276 size_t ssid_len = ssid->ssid_len; 2277 u8 ssid_buf[SSID_MAX_LEN]; 2278 if (ssid_len == 0) { 2279 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 2280 if (_res < 0) 2281 ssid_len = 0; 2282 else 2283 ssid_len = _res; 2284 _ssid = ssid_buf; 2285 } 2286 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 2287 wpa_ssid_txt(_ssid, ssid_len), 2288 ssid->id); 2289 if (os_snprintf_error(end - pos, ret)) 2290 return pos - buf; 2291 pos += ret; 2292 2293 if (wps && ssid->passphrase && 2294 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 2295 (ssid->mode == WPAS_MODE_AP || 2296 ssid->mode == WPAS_MODE_P2P_GO)) { 2297 ret = os_snprintf(pos, end - pos, 2298 "passphrase=%s\n", 2299 ssid->passphrase); 2300 if (os_snprintf_error(end - pos, ret)) 2301 return pos - buf; 2302 pos += ret; 2303 } 2304 if (ssid->id_str) { 2305 ret = os_snprintf(pos, end - pos, 2306 "id_str=%s\n", 2307 ssid->id_str); 2308 if (os_snprintf_error(end - pos, ret)) 2309 return pos - buf; 2310 pos += ret; 2311 } 2312 2313 switch (ssid->mode) { 2314 case WPAS_MODE_INFRA: 2315 ret = os_snprintf(pos, end - pos, 2316 "mode=station\n"); 2317 break; 2318 case WPAS_MODE_IBSS: 2319 ret = os_snprintf(pos, end - pos, 2320 "mode=IBSS\n"); 2321 break; 2322 case WPAS_MODE_AP: 2323 ret = os_snprintf(pos, end - pos, 2324 "mode=AP\n"); 2325 break; 2326 case WPAS_MODE_P2P_GO: 2327 ret = os_snprintf(pos, end - pos, 2328 "mode=P2P GO\n"); 2329 break; 2330 case WPAS_MODE_P2P_GROUP_FORMATION: 2331 ret = os_snprintf(pos, end - pos, 2332 "mode=P2P GO - group " 2333 "formation\n"); 2334 break; 2335 case WPAS_MODE_MESH: 2336 ret = os_snprintf(pos, end - pos, 2337 "mode=mesh\n"); 2338 break; 2339 default: 2340 ret = 0; 2341 break; 2342 } 2343 if (os_snprintf_error(end - pos, ret)) 2344 return pos - buf; 2345 pos += ret; 2346 } 2347 2348 if (wpa_s->connection_set && 2349 (wpa_s->connection_ht || wpa_s->connection_vht || 2350 wpa_s->connection_he || wpa_s->connection_eht)) { 2351 ret = os_snprintf(pos, end - pos, 2352 "wifi_generation=%u\n", 2353 wpa_s->connection_eht ? 7 : 2354 (wpa_s->connection_he ? 6 : 2355 (wpa_s->connection_vht ? 5 : 4))); 2356 if (os_snprintf_error(end - pos, ret)) 2357 return pos - buf; 2358 pos += ret; 2359 } 2360 2361 #ifdef CONFIG_AP 2362 if (wpa_s->ap_iface) { 2363 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 2364 end - pos, 2365 verbose); 2366 } else 2367 #endif /* CONFIG_AP */ 2368 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 2369 } 2370 #ifdef CONFIG_SME 2371 #ifdef CONFIG_SAE 2372 if (wpa_s->wpa_state >= WPA_ASSOCIATED && 2373 #ifdef CONFIG_AP 2374 !wpa_s->ap_iface && 2375 #endif /* CONFIG_AP */ 2376 wpa_s->sme.sae.state == SAE_ACCEPTED) { 2377 ret = os_snprintf(pos, end - pos, "sae_group=%d\n" 2378 "sae_h2e=%d\n" 2379 "sae_pk=%d\n", 2380 wpa_s->sme.sae.group, 2381 wpa_s->sme.sae.h2e, 2382 wpa_s->sme.sae.pk); 2383 if (os_snprintf_error(end - pos, ret)) 2384 return pos - buf; 2385 pos += ret; 2386 } 2387 #endif /* CONFIG_SAE */ 2388 #endif /* CONFIG_SME */ 2389 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 2390 wpa_supplicant_state_txt(wpa_s->wpa_state)); 2391 if (os_snprintf_error(end - pos, ret)) 2392 return pos - buf; 2393 pos += ret; 2394 2395 if (wpa_s->l2 && 2396 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 2397 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 2398 if (os_snprintf_error(end - pos, ret)) 2399 return pos - buf; 2400 pos += ret; 2401 } 2402 2403 #ifdef CONFIG_P2P 2404 if (wpa_s->global->p2p) { 2405 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 2406 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 2407 if (os_snprintf_error(end - pos, ret)) 2408 return pos - buf; 2409 pos += ret; 2410 } 2411 #endif /* CONFIG_P2P */ 2412 2413 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 2414 MAC2STR(wpa_s->own_addr)); 2415 if (os_snprintf_error(end - pos, ret)) 2416 return pos - buf; 2417 pos += ret; 2418 2419 if (wpa_s->valid_links) { 2420 ret = os_snprintf(pos, end - pos, "ap_mld_addr=" MACSTR "\n", 2421 MAC2STR(wpa_s->ap_mld_addr)); 2422 if (os_snprintf_error(end - pos, ret)) 2423 return pos - buf; 2424 pos += ret; 2425 } 2426 2427 #ifdef CONFIG_HS20 2428 if (wpa_s->current_bss && 2429 (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss, 2430 HS20_IE_VENDOR_TYPE)) && 2431 wpa_s->wpa_proto == WPA_PROTO_RSN && 2432 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 2433 int release = 1; 2434 if (hs20[1] >= 5) { 2435 u8 rel_num = (hs20[6] & 0xf0) >> 4; 2436 release = rel_num + 1; 2437 } 2438 ret = os_snprintf(pos, end - pos, "hs20=%d\n", release); 2439 if (os_snprintf_error(end - pos, ret)) 2440 return pos - buf; 2441 pos += ret; 2442 } 2443 2444 if (wpa_s->current_ssid) { 2445 struct wpa_cred *cred; 2446 char *type; 2447 2448 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 2449 size_t i; 2450 2451 if (wpa_s->current_ssid->parent_cred != cred) 2452 continue; 2453 2454 if (cred->provisioning_sp) { 2455 ret = os_snprintf(pos, end - pos, 2456 "provisioning_sp=%s\n", 2457 cred->provisioning_sp); 2458 if (os_snprintf_error(end - pos, ret)) 2459 return pos - buf; 2460 pos += ret; 2461 } 2462 2463 if (!cred->domain) 2464 goto no_domain; 2465 2466 i = 0; 2467 if (wpa_s->current_bss && wpa_s->current_bss->anqp) { 2468 struct wpabuf *names = 2469 wpa_s->current_bss->anqp->domain_name; 2470 for (i = 0; names && i < cred->num_domain; i++) 2471 { 2472 if (domain_name_list_contains( 2473 names, cred->domain[i], 1)) 2474 break; 2475 } 2476 if (i == cred->num_domain) 2477 i = 0; /* show first entry by default */ 2478 } 2479 ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 2480 cred->domain[i]); 2481 if (os_snprintf_error(end - pos, ret)) 2482 return pos - buf; 2483 pos += ret; 2484 2485 no_domain: 2486 if (wpa_s->current_bss == NULL || 2487 wpa_s->current_bss->anqp == NULL) 2488 res = -1; 2489 else 2490 res = interworking_home_sp_cred( 2491 wpa_s, cred, 2492 wpa_s->current_bss->anqp->domain_name); 2493 if (res > 0) 2494 type = "home"; 2495 else if (res == 0) 2496 type = "roaming"; 2497 else 2498 type = "unknown"; 2499 2500 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 2501 if (os_snprintf_error(end - pos, ret)) 2502 return pos - buf; 2503 pos += ret; 2504 2505 break; 2506 } 2507 } 2508 #endif /* CONFIG_HS20 */ 2509 2510 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 2511 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 2512 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 2513 verbose); 2514 if (res >= 0) 2515 pos += res; 2516 } 2517 2518 #ifdef CONFIG_MACSEC 2519 res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos); 2520 if (res > 0) 2521 pos += res; 2522 #endif /* CONFIG_MACSEC */ 2523 2524 sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len); 2525 if (sess_id) { 2526 char *start = pos; 2527 2528 ret = os_snprintf(pos, end - pos, "eap_session_id="); 2529 if (os_snprintf_error(end - pos, ret)) 2530 return start - buf; 2531 pos += ret; 2532 ret = wpa_snprintf_hex(pos, end - pos, sess_id, sess_id_len); 2533 if (ret <= 0) 2534 return start - buf; 2535 pos += ret; 2536 ret = os_snprintf(pos, end - pos, "\n"); 2537 if (os_snprintf_error(end - pos, ret)) 2538 return start - buf; 2539 pos += ret; 2540 } 2541 2542 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 2543 if (res >= 0) 2544 pos += res; 2545 2546 #ifdef CONFIG_WPS 2547 { 2548 char uuid_str[100]; 2549 uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str)); 2550 ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str); 2551 if (os_snprintf_error(end - pos, ret)) 2552 return pos - buf; 2553 pos += ret; 2554 } 2555 #endif /* CONFIG_WPS */ 2556 2557 if (wpa_s->ieee80211ac) { 2558 ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n"); 2559 if (os_snprintf_error(end - pos, ret)) 2560 return pos - buf; 2561 pos += ret; 2562 } 2563 2564 #ifdef CONFIG_SME 2565 if (wpa_s->sme.bss_max_idle_period) { 2566 ret = os_snprintf(pos, end - pos, "bss_max_idle_period=%d\n", 2567 wpa_s->sme.bss_max_idle_period); 2568 if (os_snprintf_error(end - pos, ret)) 2569 return pos - buf; 2570 pos += ret; 2571 } 2572 #endif /* CONFIG_SME */ 2573 2574 if (wpa_s->ssid_verified) { 2575 ret = os_snprintf(pos, end - pos, "ssid_verified=1\n"); 2576 if (os_snprintf_error(end - pos, ret)) 2577 return pos - buf; 2578 pos += ret; 2579 } 2580 2581 if (wpa_s->bigtk_set) { 2582 ret = os_snprintf(pos, end - pos, "bigtk_set=1\n"); 2583 if (os_snprintf_error(end - pos, ret)) 2584 return pos - buf; 2585 pos += ret; 2586 } 2587 2588 #ifdef ANDROID 2589 /* 2590 * Allow using the STATUS command with default behavior, say for debug, 2591 * i.e., don't generate a "fake" CONNECTION and SUPPLICANT_STATE_CHANGE 2592 * events with STATUS-NO_EVENTS. 2593 */ 2594 if (os_strcmp(params, "-NO_EVENTS")) { 2595 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE 2596 "id=%d state=%d BSSID=" MACSTR " SSID=%s", 2597 wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, 2598 wpa_s->wpa_state, 2599 MAC2STR(wpa_s->bssid), 2600 wpa_s->current_ssid && wpa_s->current_ssid->ssid ? 2601 wpa_ssid_txt(wpa_s->current_ssid->ssid, 2602 wpa_s->current_ssid->ssid_len) : ""); 2603 if (wpa_s->wpa_state == WPA_COMPLETED) { 2604 struct wpa_ssid *ssid = wpa_s->current_ssid; 2605 char mld_addr[50]; 2606 2607 mld_addr[0] = '\0'; 2608 if (wpa_s->valid_links) 2609 os_snprintf(mld_addr, sizeof(mld_addr), 2610 " ap_mld_addr=" MACSTR, 2611 MAC2STR(wpa_s->ap_mld_addr)); 2612 2613 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED 2614 "- connection to " MACSTR 2615 " completed %s [id=%d id_str=%s]%s", 2616 MAC2STR(wpa_s->bssid), "(auth)", 2617 ssid ? ssid->id : -1, 2618 ssid && ssid->id_str ? ssid->id_str : "", 2619 mld_addr); 2620 } 2621 } 2622 #endif /* ANDROID */ 2623 2624 return pos - buf; 2625 } 2626 2627 2628 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 2629 char *cmd) 2630 { 2631 char *pos; 2632 int id; 2633 struct wpa_ssid *ssid; 2634 u8 bssid[ETH_ALEN]; 2635 2636 /* cmd: "<network id> <BSSID>" */ 2637 pos = os_strchr(cmd, ' '); 2638 if (pos == NULL) 2639 return -1; 2640 *pos++ = '\0'; 2641 id = atoi(cmd); 2642 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 2643 if (hwaddr_aton(pos, bssid)) { 2644 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 2645 return -1; 2646 } 2647 2648 ssid = wpa_config_get_network(wpa_s->conf, id); 2649 if (ssid == NULL) { 2650 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2651 "to update", id); 2652 return -1; 2653 } 2654 2655 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 2656 ssid->bssid_set = !is_zero_ether_addr(bssid); 2657 2658 return 0; 2659 } 2660 2661 2662 static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s, 2663 char *cmd, char *buf, 2664 size_t buflen) 2665 { 2666 u8 bssid[ETH_ALEN]; 2667 struct wpa_bssid_ignore *e; 2668 char *pos, *end; 2669 int ret; 2670 2671 /* cmd: "BSSID_IGNORE [<BSSID>]" */ 2672 if (*cmd == '\0') { 2673 pos = buf; 2674 end = buf + buflen; 2675 e = wpa_s->bssid_ignore; 2676 while (e) { 2677 ret = os_snprintf(pos, end - pos, MACSTR "\n", 2678 MAC2STR(e->bssid)); 2679 if (os_snprintf_error(end - pos, ret)) 2680 return pos - buf; 2681 pos += ret; 2682 e = e->next; 2683 } 2684 return pos - buf; 2685 } 2686 2687 cmd++; 2688 if (os_strncmp(cmd, "clear", 5) == 0) { 2689 wpa_bssid_ignore_clear(wpa_s); 2690 os_memcpy(buf, "OK\n", 3); 2691 return 3; 2692 } 2693 2694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd); 2695 if (hwaddr_aton(cmd, bssid)) { 2696 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 2697 return -1; 2698 } 2699 2700 /* 2701 * Add the BSSID twice, so its count will be 2, causing it to be 2702 * skipped when processing scan results. 2703 */ 2704 ret = wpa_bssid_ignore_add(wpa_s, bssid); 2705 if (ret < 0) 2706 return -1; 2707 ret = wpa_bssid_ignore_add(wpa_s, bssid); 2708 if (ret < 0) 2709 return -1; 2710 os_memcpy(buf, "OK\n", 3); 2711 return 3; 2712 } 2713 2714 2715 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 2716 char *cmd, char *buf, 2717 size_t buflen) 2718 { 2719 char *pos, *end, *stamp; 2720 int ret; 2721 2722 /* cmd: "LOG_LEVEL [<level>]" */ 2723 if (*cmd == '\0') { 2724 pos = buf; 2725 end = buf + buflen; 2726 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 2727 "Timestamp: %d\n", 2728 debug_level_str(wpa_debug_level), 2729 wpa_debug_timestamp); 2730 if (os_snprintf_error(end - pos, ret)) 2731 ret = 0; 2732 2733 return ret; 2734 } 2735 2736 while (*cmd == ' ') 2737 cmd++; 2738 2739 stamp = os_strchr(cmd, ' '); 2740 if (stamp) { 2741 *stamp++ = '\0'; 2742 while (*stamp == ' ') { 2743 stamp++; 2744 } 2745 } 2746 2747 if (os_strlen(cmd)) { 2748 int level = str_to_debug_level(cmd); 2749 if (level < 0) 2750 return -1; 2751 wpa_debug_level = level; 2752 } 2753 2754 if (stamp && os_strlen(stamp)) 2755 wpa_debug_timestamp = atoi(stamp); 2756 2757 os_memcpy(buf, "OK\n", 3); 2758 return 3; 2759 } 2760 2761 2762 static int wpa_supplicant_ctrl_iface_list_networks( 2763 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2764 { 2765 char *pos, *end, *prev; 2766 struct wpa_ssid *ssid; 2767 int ret; 2768 2769 pos = buf; 2770 end = buf + buflen; 2771 ret = os_snprintf(pos, end - pos, 2772 "network id / ssid / bssid / flags\n"); 2773 if (os_snprintf_error(end - pos, ret)) 2774 return pos - buf; 2775 pos += ret; 2776 2777 ssid = wpa_s->conf->ssid; 2778 2779 /* skip over ssids until we find next one */ 2780 if (cmd != NULL && os_strncmp(cmd, "LAST_ID=", 8) == 0) { 2781 int last_id = atoi(cmd + 8); 2782 if (last_id != -1) { 2783 while (ssid != NULL && ssid->id <= last_id) { 2784 ssid = ssid->next; 2785 } 2786 } 2787 } 2788 2789 while (ssid) { 2790 prev = pos; 2791 ret = os_snprintf(pos, end - pos, "%d\t%s", 2792 ssid->id, 2793 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 2794 if (os_snprintf_error(end - pos, ret)) 2795 return prev - buf; 2796 pos += ret; 2797 if (ssid->bssid_set) { 2798 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 2799 MAC2STR(ssid->bssid)); 2800 } else { 2801 ret = os_snprintf(pos, end - pos, "\tany"); 2802 } 2803 if (os_snprintf_error(end - pos, ret)) 2804 return prev - buf; 2805 pos += ret; 2806 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 2807 ssid == wpa_s->current_ssid ? 2808 "[CURRENT]" : "", 2809 ssid->disabled ? "[DISABLED]" : "", 2810 ssid->disabled_until.sec ? 2811 "[TEMP-DISABLED]" : "", 2812 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 2813 ""); 2814 if (os_snprintf_error(end - pos, ret)) 2815 return prev - buf; 2816 pos += ret; 2817 ret = os_snprintf(pos, end - pos, "\n"); 2818 if (os_snprintf_error(end - pos, ret)) 2819 return prev - buf; 2820 pos += ret; 2821 2822 ssid = ssid->next; 2823 } 2824 2825 return pos - buf; 2826 } 2827 2828 2829 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 2830 { 2831 int ret; 2832 ret = os_snprintf(pos, end - pos, "-"); 2833 if (os_snprintf_error(end - pos, ret)) 2834 return pos; 2835 pos += ret; 2836 ret = wpa_write_ciphers(pos, end, cipher, "+"); 2837 if (ret < 0) 2838 return pos; 2839 pos += ret; 2840 return pos; 2841 } 2842 2843 2844 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 2845 const u8 *ie, size_t ie_len) 2846 { 2847 struct wpa_ie_data data; 2848 char *start; 2849 int ret; 2850 2851 ret = os_snprintf(pos, end - pos, "[%s-", proto); 2852 if (os_snprintf_error(end - pos, ret)) 2853 return pos; 2854 pos += ret; 2855 2856 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 2857 ret = os_snprintf(pos, end - pos, "?]"); 2858 if (os_snprintf_error(end - pos, ret)) 2859 return pos; 2860 pos += ret; 2861 return pos; 2862 } 2863 2864 start = pos; 2865 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 2866 ret = os_snprintf(pos, end - pos, "%sEAP", 2867 pos == start ? "" : "+"); 2868 if (os_snprintf_error(end - pos, ret)) 2869 return pos; 2870 pos += ret; 2871 } 2872 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 2873 ret = os_snprintf(pos, end - pos, "%sPSK", 2874 pos == start ? "" : "+"); 2875 if (os_snprintf_error(end - pos, ret)) 2876 return pos; 2877 pos += ret; 2878 } 2879 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 2880 ret = os_snprintf(pos, end - pos, "%sNone", 2881 pos == start ? "" : "+"); 2882 if (os_snprintf_error(end - pos, ret)) 2883 return pos; 2884 pos += ret; 2885 } 2886 if (data.key_mgmt & WPA_KEY_MGMT_SAE) { 2887 ret = os_snprintf(pos, end - pos, "%sSAE", 2888 pos == start ? "" : "+"); 2889 if (os_snprintf_error(end - pos, ret)) 2890 return pos; 2891 pos += ret; 2892 } 2893 if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) { 2894 ret = os_snprintf(pos, end - pos, "%sSAE-EXT-KEY", 2895 pos == start ? "" : "+"); 2896 if (os_snprintf_error(end - pos, ret)) 2897 return pos; 2898 pos += ret; 2899 } 2900 #ifdef CONFIG_IEEE80211R 2901 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 2902 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 2903 pos == start ? "" : "+"); 2904 if (os_snprintf_error(end - pos, ret)) 2905 return pos; 2906 pos += ret; 2907 } 2908 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 2909 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 2910 pos == start ? "" : "+"); 2911 if (os_snprintf_error(end - pos, ret)) 2912 return pos; 2913 pos += ret; 2914 } 2915 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) { 2916 ret = os_snprintf(pos, end - pos, "%sFT/SAE", 2917 pos == start ? "" : "+"); 2918 if (os_snprintf_error(end - pos, ret)) 2919 return pos; 2920 pos += ret; 2921 } 2922 if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) { 2923 ret = os_snprintf(pos, end - pos, "%sFT/SAE-EXT-KEY", 2924 pos == start ? "" : "+"); 2925 if (os_snprintf_error(end - pos, ret)) 2926 return pos; 2927 pos += ret; 2928 } 2929 #endif /* CONFIG_IEEE80211R */ 2930 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 2931 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 2932 pos == start ? "" : "+"); 2933 if (os_snprintf_error(end - pos, ret)) 2934 return pos; 2935 pos += ret; 2936 } 2937 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 2938 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 2939 pos == start ? "" : "+"); 2940 if (os_snprintf_error(end - pos, ret)) 2941 return pos; 2942 pos += ret; 2943 } 2944 2945 #ifdef CONFIG_SUITEB 2946 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 2947 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B", 2948 pos == start ? "" : "+"); 2949 if (os_snprintf_error(end - pos, ret)) 2950 return pos; 2951 pos += ret; 2952 } 2953 #endif /* CONFIG_SUITEB */ 2954 2955 #ifdef CONFIG_SUITEB192 2956 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 2957 ret = os_snprintf(pos, end - pos, "%sEAP-SUITE-B-192", 2958 pos == start ? "" : "+"); 2959 if (os_snprintf_error(end - pos, ret)) 2960 return pos; 2961 pos += ret; 2962 } 2963 #endif /* CONFIG_SUITEB192 */ 2964 2965 #ifdef CONFIG_FILS 2966 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 2967 ret = os_snprintf(pos, end - pos, "%sFILS-SHA256", 2968 pos == start ? "" : "+"); 2969 if (os_snprintf_error(end - pos, ret)) 2970 return pos; 2971 pos += ret; 2972 } 2973 if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 2974 ret = os_snprintf(pos, end - pos, "%sFILS-SHA384", 2975 pos == start ? "" : "+"); 2976 if (os_snprintf_error(end - pos, ret)) 2977 return pos; 2978 pos += ret; 2979 } 2980 #ifdef CONFIG_IEEE80211R 2981 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 2982 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256", 2983 pos == start ? "" : "+"); 2984 if (os_snprintf_error(end - pos, ret)) 2985 return pos; 2986 pos += ret; 2987 } 2988 if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 2989 ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384", 2990 pos == start ? "" : "+"); 2991 if (os_snprintf_error(end - pos, ret)) 2992 return pos; 2993 pos += ret; 2994 } 2995 #endif /* CONFIG_IEEE80211R */ 2996 #endif /* CONFIG_FILS */ 2997 2998 #ifdef CONFIG_OWE 2999 if (data.key_mgmt & WPA_KEY_MGMT_OWE) { 3000 ret = os_snprintf(pos, end - pos, "%sOWE", 3001 pos == start ? "" : "+"); 3002 if (os_snprintf_error(end - pos, ret)) 3003 return pos; 3004 pos += ret; 3005 } 3006 #endif /* CONFIG_OWE */ 3007 3008 #ifdef CONFIG_DPP 3009 if (data.key_mgmt & WPA_KEY_MGMT_DPP) { 3010 ret = os_snprintf(pos, end - pos, "%sDPP", 3011 pos == start ? "" : "+"); 3012 if (os_snprintf_error(end - pos, ret)) 3013 return pos; 3014 pos += ret; 3015 } 3016 #endif /* CONFIG_DPP */ 3017 3018 if (data.key_mgmt & WPA_KEY_MGMT_OSEN) { 3019 ret = os_snprintf(pos, end - pos, "%sOSEN", 3020 pos == start ? "" : "+"); 3021 if (os_snprintf_error(end - pos, ret)) 3022 return pos; 3023 pos += ret; 3024 } 3025 3026 #ifdef CONFIG_SHA384 3027 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { 3028 ret = os_snprintf(pos, end - pos, "%sEAP-SHA384", 3029 pos == start ? "" : "+"); 3030 if (os_snprintf_error(end - pos, ret)) 3031 return pos; 3032 pos += ret; 3033 } 3034 #endif /* CONFIG_SHA384 */ 3035 3036 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 3037 3038 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 3039 ret = os_snprintf(pos, end - pos, "-preauth"); 3040 if (os_snprintf_error(end - pos, ret)) 3041 return pos; 3042 pos += ret; 3043 } 3044 3045 ret = os_snprintf(pos, end - pos, "]"); 3046 if (os_snprintf_error(end - pos, ret)) 3047 return pos; 3048 pos += ret; 3049 3050 return pos; 3051 } 3052 3053 3054 #ifdef CONFIG_WPS 3055 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 3056 char *pos, char *end, 3057 struct wpabuf *wps_ie) 3058 { 3059 int ret; 3060 const char *txt; 3061 3062 if (wps_ie == NULL) 3063 return pos; 3064 if (wps_is_selected_pbc_registrar(wps_ie)) 3065 txt = "[WPS-PBC]"; 3066 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 3067 txt = "[WPS-AUTH]"; 3068 else if (wps_is_selected_pin_registrar(wps_ie)) 3069 txt = "[WPS-PIN]"; 3070 else 3071 txt = "[WPS]"; 3072 3073 ret = os_snprintf(pos, end - pos, "%s", txt); 3074 if (!os_snprintf_error(end - pos, ret)) 3075 pos += ret; 3076 wpabuf_free(wps_ie); 3077 return pos; 3078 } 3079 #endif /* CONFIG_WPS */ 3080 3081 3082 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 3083 char *pos, char *end, 3084 const struct wpa_bss *bss) 3085 { 3086 #ifdef CONFIG_WPS 3087 struct wpabuf *wps_ie; 3088 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 3089 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 3090 #else /* CONFIG_WPS */ 3091 return pos; 3092 #endif /* CONFIG_WPS */ 3093 } 3094 3095 3096 /* Format one result on one text line into a buffer. */ 3097 static int wpa_supplicant_ctrl_iface_scan_result( 3098 struct wpa_supplicant *wpa_s, 3099 const struct wpa_bss *bss, char *buf, size_t buflen) 3100 { 3101 char *pos, *end; 3102 int ret; 3103 const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe; 3104 3105 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 3106 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 3107 if (!p2p) 3108 p2p = wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE); 3109 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 3110 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 3111 0) 3112 return 0; /* Do not show P2P listen discovery results here */ 3113 3114 pos = buf; 3115 end = buf + buflen; 3116 3117 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 3118 MAC2STR(bss->bssid), bss->freq, bss->level); 3119 if (os_snprintf_error(end - pos, ret)) 3120 return -1; 3121 pos += ret; 3122 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 3123 if (ie) 3124 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 3125 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3126 if (ie2) { 3127 pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", 3128 ie2, 2 + ie2[1]); 3129 } 3130 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); 3131 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) { 3132 ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); 3133 if (os_snprintf_error(end - pos, ret)) 3134 return -1; 3135 pos += ret; 3136 } 3137 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) { 3138 ret = os_snprintf(pos, end - pos, "[SAE-PK]"); 3139 if (os_snprintf_error(end - pos, ret)) 3140 return -1; 3141 pos += ret; 3142 } 3143 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 3144 if (osen_ie) 3145 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 3146 osen_ie, 2 + osen_ie[1]); 3147 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 3148 if (owe) { 3149 ret = os_snprintf(pos, end - pos, 3150 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 3151 if (os_snprintf_error(end - pos, ret)) 3152 return -1; 3153 pos += ret; 3154 } 3155 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 3156 if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { 3157 ret = os_snprintf(pos, end - pos, "[WEP]"); 3158 if (os_snprintf_error(end - pos, ret)) 3159 return -1; 3160 pos += ret; 3161 } 3162 if (mesh) { 3163 ret = os_snprintf(pos, end - pos, "[MESH]"); 3164 if (os_snprintf_error(end - pos, ret)) 3165 return -1; 3166 pos += ret; 3167 } 3168 if (bss_is_dmg(bss)) { 3169 const char *s; 3170 3171 if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) { 3172 ret = os_snprintf(pos, end - pos, "[EDMG]"); 3173 if (os_snprintf_error(end - pos, ret)) 3174 return -1; 3175 pos += ret; 3176 } 3177 3178 ret = os_snprintf(pos, end - pos, "[DMG]"); 3179 if (os_snprintf_error(end - pos, ret)) 3180 return -1; 3181 pos += ret; 3182 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 3183 case IEEE80211_CAP_DMG_IBSS: 3184 s = "[IBSS]"; 3185 break; 3186 case IEEE80211_CAP_DMG_AP: 3187 s = "[ESS]"; 3188 break; 3189 case IEEE80211_CAP_DMG_PBSS: 3190 s = "[PBSS]"; 3191 break; 3192 default: 3193 s = ""; 3194 break; 3195 } 3196 ret = os_snprintf(pos, end - pos, "%s", s); 3197 if (os_snprintf_error(end - pos, ret)) 3198 return -1; 3199 pos += ret; 3200 } else { 3201 if (bss->caps & IEEE80211_CAP_IBSS) { 3202 ret = os_snprintf(pos, end - pos, "[IBSS]"); 3203 if (os_snprintf_error(end - pos, ret)) 3204 return -1; 3205 pos += ret; 3206 } 3207 if (bss->caps & IEEE80211_CAP_ESS) { 3208 ret = os_snprintf(pos, end - pos, "[ESS]"); 3209 if (os_snprintf_error(end - pos, ret)) 3210 return -1; 3211 pos += ret; 3212 } 3213 } 3214 if (p2p) { 3215 ret = os_snprintf(pos, end - pos, "[P2P]"); 3216 if (os_snprintf_error(end - pos, ret)) 3217 return -1; 3218 pos += ret; 3219 } 3220 #ifdef CONFIG_HS20 3221 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 3222 ret = os_snprintf(pos, end - pos, "[HS20]"); 3223 if (os_snprintf_error(end - pos, ret)) 3224 return -1; 3225 pos += ret; 3226 } 3227 #endif /* CONFIG_HS20 */ 3228 #ifdef CONFIG_FILS 3229 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 3230 ret = os_snprintf(pos, end - pos, "[FILS]"); 3231 if (os_snprintf_error(end - pos, ret)) 3232 return -1; 3233 pos += ret; 3234 } 3235 #endif /* CONFIG_FILS */ 3236 #ifdef CONFIG_FST 3237 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 3238 ret = os_snprintf(pos, end - pos, "[FST]"); 3239 if (os_snprintf_error(end - pos, ret)) 3240 return -1; 3241 pos += ret; 3242 } 3243 #endif /* CONFIG_FST */ 3244 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 3245 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 3246 if (os_snprintf_error(end - pos, ret)) 3247 return -1; 3248 pos += ret; 3249 } 3250 3251 ret = os_snprintf(pos, end - pos, "\t%s", 3252 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 3253 if (os_snprintf_error(end - pos, ret)) 3254 return -1; 3255 pos += ret; 3256 3257 ret = os_snprintf(pos, end - pos, "\n"); 3258 if (os_snprintf_error(end - pos, ret)) 3259 return -1; 3260 pos += ret; 3261 3262 return pos - buf; 3263 } 3264 3265 3266 static int wpa_supplicant_ctrl_iface_scan_results( 3267 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3268 { 3269 char *pos, *end; 3270 struct wpa_bss *bss; 3271 int ret; 3272 3273 pos = buf; 3274 end = buf + buflen; 3275 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 3276 "flags / ssid\n"); 3277 if (os_snprintf_error(end - pos, ret)) 3278 return pos - buf; 3279 pos += ret; 3280 3281 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 3282 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 3283 end - pos); 3284 if (ret < 0 || ret >= end - pos) 3285 return pos - buf; 3286 pos += ret; 3287 } 3288 3289 return pos - buf; 3290 } 3291 3292 3293 #ifdef CONFIG_MESH 3294 3295 static int wpa_supplicant_ctrl_iface_mesh_interface_add( 3296 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 3297 { 3298 char *pos, ifname[IFNAMSIZ + 1]; 3299 3300 ifname[0] = '\0'; 3301 3302 pos = os_strstr(cmd, "ifname="); 3303 if (pos) { 3304 pos += 7; 3305 os_strlcpy(ifname, pos, sizeof(ifname)); 3306 } 3307 3308 if (wpas_mesh_add_interface(wpa_s, ifname, sizeof(ifname)) < 0) 3309 return -1; 3310 3311 os_strlcpy(reply, ifname, max_len); 3312 return os_strlen(ifname); 3313 } 3314 3315 3316 static int wpa_supplicant_ctrl_iface_mesh_group_add( 3317 struct wpa_supplicant *wpa_s, char *cmd) 3318 { 3319 int id; 3320 struct wpa_ssid *ssid; 3321 3322 id = atoi(cmd); 3323 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id); 3324 3325 ssid = wpa_config_get_network(wpa_s->conf, id); 3326 if (ssid == NULL) { 3327 wpa_printf(MSG_DEBUG, 3328 "CTRL_IFACE: Could not find network id=%d", id); 3329 return -1; 3330 } 3331 if (ssid->mode != WPAS_MODE_MESH) { 3332 wpa_printf(MSG_DEBUG, 3333 "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network"); 3334 return -1; 3335 } 3336 if (ssid->key_mgmt != WPA_KEY_MGMT_NONE && 3337 ssid->key_mgmt != WPA_KEY_MGMT_SAE && 3338 ssid->key_mgmt != WPA_KEY_MGMT_SAE_EXT_KEY) { 3339 wpa_printf(MSG_ERROR, 3340 "CTRL_IFACE: key_mgmt for mesh network should be open or SAE"); 3341 return -1; 3342 } 3343 3344 /* 3345 * TODO: If necessary write our own group_add function, 3346 * for now we can reuse select_network 3347 */ 3348 wpa_supplicant_select_network(wpa_s, ssid); 3349 3350 return 0; 3351 } 3352 3353 3354 static int wpa_supplicant_ctrl_iface_mesh_group_remove( 3355 struct wpa_supplicant *wpa_s, char *cmd) 3356 { 3357 struct wpa_supplicant *orig; 3358 struct wpa_global *global; 3359 int found = 0; 3360 3361 wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd); 3362 3363 global = wpa_s->global; 3364 orig = wpa_s; 3365 3366 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 3367 if (os_strcmp(wpa_s->ifname, cmd) == 0) { 3368 found = 1; 3369 break; 3370 } 3371 } 3372 if (!found) { 3373 wpa_printf(MSG_ERROR, 3374 "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s not found", 3375 cmd); 3376 return -1; 3377 } 3378 if (wpa_s->mesh_if_created && wpa_s == orig) { 3379 wpa_printf(MSG_ERROR, 3380 "CTRL_IFACE: MESH_GROUP_REMOVE can't remove itself"); 3381 return -1; 3382 } 3383 3384 wpa_s->reassociate = 0; 3385 wpa_s->disconnected = 1; 3386 wpa_supplicant_cancel_sched_scan(wpa_s); 3387 wpa_supplicant_cancel_scan(wpa_s); 3388 3389 /* 3390 * TODO: If necessary write our own group_remove function, 3391 * for now we can reuse deauthenticate 3392 */ 3393 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 3394 3395 if (wpa_s->mesh_if_created) 3396 wpa_supplicant_remove_iface(global, wpa_s, 0); 3397 3398 return 0; 3399 } 3400 3401 3402 static int wpa_supplicant_ctrl_iface_mesh_peer_remove( 3403 struct wpa_supplicant *wpa_s, char *cmd) 3404 { 3405 u8 addr[ETH_ALEN]; 3406 3407 if (hwaddr_aton(cmd, addr) < 0) 3408 return -1; 3409 3410 return wpas_mesh_peer_remove(wpa_s, addr); 3411 } 3412 3413 3414 static int wpa_supplicant_ctrl_iface_mesh_peer_add( 3415 struct wpa_supplicant *wpa_s, char *cmd) 3416 { 3417 u8 addr[ETH_ALEN]; 3418 int duration; 3419 char *pos; 3420 3421 pos = os_strstr(cmd, " duration="); 3422 if (pos) { 3423 *pos = '\0'; 3424 duration = atoi(pos + 10); 3425 } else { 3426 duration = -1; 3427 } 3428 3429 if (hwaddr_aton(cmd, addr)) 3430 return -1; 3431 3432 return wpas_mesh_peer_add(wpa_s, addr, duration); 3433 } 3434 3435 3436 static int wpa_supplicant_ctrl_iface_mesh_link_probe( 3437 struct wpa_supplicant *wpa_s, char *cmd) 3438 { 3439 struct ether_header *eth; 3440 u8 addr[ETH_ALEN]; 3441 u8 *buf; 3442 char *pos; 3443 size_t payload_len = 0, len; 3444 int ret = -1; 3445 3446 if (hwaddr_aton(cmd, addr)) 3447 return -1; 3448 3449 pos = os_strstr(cmd, " payload="); 3450 if (pos) { 3451 pos = pos + 9; 3452 payload_len = os_strlen(pos); 3453 if (payload_len & 1) 3454 return -1; 3455 3456 payload_len /= 2; 3457 } 3458 3459 len = ETH_HLEN + payload_len; 3460 buf = os_malloc(len); 3461 if (!buf) 3462 return -1; 3463 3464 eth = (struct ether_header *) buf; 3465 os_memcpy(eth->ether_dhost, addr, ETH_ALEN); 3466 os_memcpy(eth->ether_shost, wpa_s->own_addr, ETH_ALEN); 3467 eth->ether_type = htons(ETH_P_802_3); 3468 3469 if (payload_len && hexstr2bin(pos, buf + ETH_HLEN, payload_len) < 0) 3470 goto fail; 3471 3472 ret = wpa_drv_mesh_link_probe(wpa_s, addr, buf, len); 3473 fail: 3474 os_free(buf); 3475 return -ret; 3476 } 3477 3478 #endif /* CONFIG_MESH */ 3479 3480 3481 static int wpa_supplicant_ctrl_iface_select_network( 3482 struct wpa_supplicant *wpa_s, char *cmd) 3483 { 3484 int id; 3485 struct wpa_ssid *ssid; 3486 char *pos; 3487 3488 /* cmd: "<network id>" or "any" */ 3489 if (os_strncmp(cmd, "any", 3) == 0) { 3490 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 3491 ssid = NULL; 3492 } else { 3493 id = atoi(cmd); 3494 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 3495 3496 ssid = wpa_config_get_network(wpa_s->conf, id); 3497 if (ssid == NULL) { 3498 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3499 "network id=%d", id); 3500 return -1; 3501 } 3502 if (ssid->disabled == 2) { 3503 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3504 "SELECT_NETWORK with persistent P2P group"); 3505 return -1; 3506 } 3507 } 3508 3509 pos = os_strstr(cmd, " freq="); 3510 if (pos) { 3511 int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); 3512 if (freqs) { 3513 os_free(wpa_s->select_network_scan_freqs); 3514 wpa_s->select_network_scan_freqs = freqs; 3515 } 3516 } 3517 3518 wpa_s->scan_min_time.sec = 0; 3519 wpa_s->scan_min_time.usec = 0; 3520 wpa_supplicant_select_network(wpa_s, ssid); 3521 3522 return 0; 3523 } 3524 3525 3526 static int wpa_supplicant_ctrl_iface_enable_network( 3527 struct wpa_supplicant *wpa_s, char *cmd) 3528 { 3529 int id; 3530 struct wpa_ssid *ssid; 3531 3532 /* cmd: "<network id>" or "all" */ 3533 if (os_strcmp(cmd, "all") == 0) { 3534 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 3535 ssid = NULL; 3536 } else { 3537 id = atoi(cmd); 3538 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 3539 3540 ssid = wpa_config_get_network(wpa_s->conf, id); 3541 if (ssid == NULL) { 3542 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3543 "network id=%d", id); 3544 return -1; 3545 } 3546 if (ssid->disabled == 2) { 3547 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3548 "ENABLE_NETWORK with persistent P2P group"); 3549 return -1; 3550 } 3551 3552 if (os_strstr(cmd, " no-connect")) { 3553 ssid->disabled = 0; 3554 return 0; 3555 } 3556 } 3557 wpa_s->scan_min_time.sec = 0; 3558 wpa_s->scan_min_time.usec = 0; 3559 wpa_supplicant_enable_network(wpa_s, ssid); 3560 3561 return 0; 3562 } 3563 3564 3565 static int wpa_supplicant_ctrl_iface_disable_network( 3566 struct wpa_supplicant *wpa_s, char *cmd) 3567 { 3568 int id; 3569 struct wpa_ssid *ssid; 3570 3571 /* cmd: "<network id>" or "all" */ 3572 if (os_strcmp(cmd, "all") == 0) { 3573 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 3574 ssid = NULL; 3575 } else { 3576 id = atoi(cmd); 3577 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 3578 3579 ssid = wpa_config_get_network(wpa_s->conf, id); 3580 if (ssid == NULL) { 3581 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3582 "network id=%d", id); 3583 return -1; 3584 } 3585 if (ssid->disabled == 2) { 3586 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 3587 "DISABLE_NETWORK with persistent P2P " 3588 "group"); 3589 return -1; 3590 } 3591 } 3592 wpa_supplicant_disable_network(wpa_s, ssid); 3593 3594 return 0; 3595 } 3596 3597 3598 static int wpa_supplicant_ctrl_iface_add_network( 3599 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 3600 { 3601 struct wpa_ssid *ssid; 3602 int ret; 3603 3604 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 3605 3606 ssid = wpa_supplicant_add_network(wpa_s); 3607 if (ssid == NULL) 3608 return -1; 3609 3610 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 3611 if (os_snprintf_error(buflen, ret)) 3612 return -1; 3613 return ret; 3614 } 3615 3616 3617 static int wpa_supplicant_ctrl_iface_remove_network( 3618 struct wpa_supplicant *wpa_s, char *cmd) 3619 { 3620 int id; 3621 int result; 3622 3623 /* cmd: "<network id>" or "all" */ 3624 if (os_strcmp(cmd, "all") == 0) { 3625 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 3626 return wpa_supplicant_remove_all_networks(wpa_s); 3627 } 3628 3629 id = atoi(cmd); 3630 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 3631 3632 result = wpa_supplicant_remove_network(wpa_s, id); 3633 if (result == -1) { 3634 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3635 "id=%d", id); 3636 return -1; 3637 } 3638 if (result == -2) { 3639 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 3640 "network id=%d", id); 3641 return -1; 3642 } 3643 return 0; 3644 } 3645 3646 3647 static int wpa_supplicant_ctrl_iface_update_network( 3648 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 3649 char *name, char *value) 3650 { 3651 int ret; 3652 3653 ret = wpa_config_set(ssid, name, value, 0); 3654 if (ret < 0) { 3655 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 3656 "variable '%s'", name); 3657 return -1; 3658 } 3659 if (ret == 1) 3660 return 0; /* No change to the previously configured value */ 3661 3662 #ifdef CONFIG_BGSCAN 3663 if (os_strcmp(name, "bgscan") == 0) { 3664 /* 3665 * Reset the bgscan parameters for the current network and 3666 * return. There's no need to flush caches for bgscan parameter 3667 * changes. 3668 */ 3669 if (wpa_s->current_ssid == ssid && 3670 wpa_s->wpa_state == WPA_COMPLETED) 3671 wpa_supplicant_reset_bgscan(wpa_s); 3672 return 0; 3673 } 3674 #endif /* CONFIG_BGSCAN */ 3675 3676 if (os_strcmp(name, "bssid") != 0 && 3677 os_strncmp(name, "bssid_", 6) != 0 && 3678 os_strcmp(name, "scan_freq") != 0 && 3679 os_strcmp(name, "priority") != 0) { 3680 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 3681 3682 if (wpa_s->current_ssid == ssid || 3683 wpa_s->current_ssid == NULL) { 3684 /* 3685 * Invalidate the EAP session cache if anything in the 3686 * current or previously used configuration changes. 3687 */ 3688 eapol_sm_invalidate_cached_session(wpa_s->eapol); 3689 } 3690 } 3691 3692 if ((os_strcmp(name, "psk") == 0 && 3693 value[0] == '"' && ssid->ssid_len) || 3694 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 3695 wpa_config_update_psk(ssid); 3696 else if (os_strcmp(name, "priority") == 0) 3697 wpa_config_update_prio_list(wpa_s->conf); 3698 3699 return 0; 3700 } 3701 3702 3703 static int wpa_supplicant_ctrl_iface_set_network( 3704 struct wpa_supplicant *wpa_s, char *cmd) 3705 { 3706 int id, ret, prev_bssid_set, prev_disabled; 3707 struct wpa_ssid *ssid; 3708 char *name, *value; 3709 u8 prev_bssid[ETH_ALEN]; 3710 3711 /* cmd: "<network id> <variable name> <value>" */ 3712 name = os_strchr(cmd, ' '); 3713 if (name == NULL) 3714 return -1; 3715 *name++ = '\0'; 3716 3717 value = os_strchr(name, ' '); 3718 if (value == NULL) 3719 return -1; 3720 *value++ = '\0'; 3721 3722 id = atoi(cmd); 3723 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 3724 id, name); 3725 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3726 (u8 *) value, os_strlen(value)); 3727 3728 ssid = wpa_config_get_network(wpa_s->conf, id); 3729 if (ssid == NULL) { 3730 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 3731 "id=%d", id); 3732 return -1; 3733 } 3734 3735 prev_bssid_set = ssid->bssid_set; 3736 prev_disabled = ssid->disabled; 3737 os_memcpy(prev_bssid, ssid->bssid, ETH_ALEN); 3738 ret = wpa_supplicant_ctrl_iface_update_network(wpa_s, ssid, name, 3739 value); 3740 if (ret == 0 && 3741 (ssid->bssid_set != prev_bssid_set || 3742 !ether_addr_equal(ssid->bssid, prev_bssid))) 3743 wpas_notify_network_bssid_set_changed(wpa_s, ssid); 3744 3745 if (prev_disabled != ssid->disabled && 3746 (prev_disabled == 2 || ssid->disabled == 2)) 3747 wpas_notify_network_type_changed(wpa_s, ssid); 3748 3749 return ret; 3750 } 3751 3752 3753 static int wpa_supplicant_ctrl_iface_get_network( 3754 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 3755 { 3756 int id; 3757 size_t res; 3758 struct wpa_ssid *ssid; 3759 char *name, *value; 3760 3761 /* cmd: "<network id> <variable name>" */ 3762 name = os_strchr(cmd, ' '); 3763 if (name == NULL || buflen == 0) 3764 return -1; 3765 *name++ = '\0'; 3766 3767 id = atoi(cmd); 3768 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 3769 id, name); 3770 3771 ssid = wpa_config_get_network(wpa_s->conf, id); 3772 if (ssid == NULL) { 3773 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Could not find network " 3774 "id=%d", id); 3775 return -1; 3776 } 3777 3778 value = wpa_config_get_no_key(ssid, name); 3779 if (value == NULL) { 3780 wpa_printf(MSG_EXCESSIVE, "CTRL_IFACE: Failed to get network " 3781 "variable '%s'", name); 3782 return -1; 3783 } 3784 3785 res = os_strlcpy(buf, value, buflen); 3786 if (res >= buflen) { 3787 os_free(value); 3788 return -1; 3789 } 3790 3791 os_free(value); 3792 3793 return res; 3794 } 3795 3796 3797 static int wpa_supplicant_ctrl_iface_dup_network( 3798 struct wpa_supplicant *wpa_s, char *cmd, 3799 struct wpa_supplicant *dst_wpa_s) 3800 { 3801 struct wpa_ssid *ssid_s, *ssid_d; 3802 char *name, *id, *value; 3803 int id_s, id_d, ret; 3804 3805 /* cmd: "<src network id> <dst network id> <variable name>" */ 3806 id = os_strchr(cmd, ' '); 3807 if (id == NULL) 3808 return -1; 3809 *id++ = '\0'; 3810 3811 name = os_strchr(id, ' '); 3812 if (name == NULL) 3813 return -1; 3814 *name++ = '\0'; 3815 3816 id_s = atoi(cmd); 3817 id_d = atoi(id); 3818 3819 wpa_printf(MSG_DEBUG, 3820 "CTRL_IFACE: DUP_NETWORK ifname=%s->%s id=%d->%d name='%s'", 3821 wpa_s->ifname, dst_wpa_s->ifname, id_s, id_d, name); 3822 3823 ssid_s = wpa_config_get_network(wpa_s->conf, id_s); 3824 if (ssid_s == NULL) { 3825 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3826 "network id=%d", id_s); 3827 return -1; 3828 } 3829 3830 ssid_d = wpa_config_get_network(dst_wpa_s->conf, id_d); 3831 if (ssid_d == NULL) { 3832 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3833 "network id=%d", id_d); 3834 return -1; 3835 } 3836 3837 value = wpa_config_get(ssid_s, name); 3838 if (value == NULL) { 3839 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 3840 "variable '%s'", name); 3841 return -1; 3842 } 3843 3844 ret = wpa_supplicant_ctrl_iface_update_network(dst_wpa_s, ssid_d, name, 3845 value); 3846 3847 os_free(value); 3848 3849 return ret; 3850 } 3851 3852 3853 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 3854 char *buf, size_t buflen) 3855 { 3856 char *pos, *end; 3857 struct wpa_cred *cred; 3858 int ret; 3859 3860 pos = buf; 3861 end = buf + buflen; 3862 ret = os_snprintf(pos, end - pos, 3863 "cred id / realm / username / domain / imsi\n"); 3864 if (os_snprintf_error(end - pos, ret)) 3865 return pos - buf; 3866 pos += ret; 3867 3868 cred = wpa_s->conf->cred; 3869 while (cred) { 3870 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 3871 cred->id, cred->realm ? cred->realm : "", 3872 cred->username ? cred->username : "", 3873 cred->domain ? cred->domain[0] : "", 3874 cred->imsi ? cred->imsi : ""); 3875 if (os_snprintf_error(end - pos, ret)) 3876 return pos - buf; 3877 pos += ret; 3878 3879 cred = cred->next; 3880 } 3881 3882 return pos - buf; 3883 } 3884 3885 3886 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 3887 char *buf, size_t buflen) 3888 { 3889 struct wpa_cred *cred; 3890 int ret; 3891 3892 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 3893 3894 cred = wpa_config_add_cred(wpa_s->conf); 3895 if (cred == NULL) 3896 return -1; 3897 3898 wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id); 3899 3900 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 3901 if (os_snprintf_error(buflen, ret)) 3902 return -1; 3903 return ret; 3904 } 3905 3906 3907 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 3908 char *cmd) 3909 { 3910 int id; 3911 struct wpa_cred *cred, *prev; 3912 3913 /* cmd: "<cred id>", "all", "sp_fqdn=<FQDN>", or 3914 * "provisioning_sp=<FQDN> */ 3915 if (os_strcmp(cmd, "all") == 0) { 3916 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 3917 return wpas_remove_all_creds(wpa_s); 3918 } 3919 3920 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 3921 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 3922 cmd + 8); 3923 cred = wpa_s->conf->cred; 3924 while (cred) { 3925 prev = cred; 3926 cred = cred->next; 3927 if (prev->domain) { 3928 size_t i; 3929 for (i = 0; i < prev->num_domain; i++) { 3930 if (os_strcmp(prev->domain[i], cmd + 8) 3931 != 0) 3932 continue; 3933 wpas_remove_cred(wpa_s, prev); 3934 break; 3935 } 3936 } 3937 } 3938 return 0; 3939 } 3940 3941 if (os_strncmp(cmd, "provisioning_sp=", 16) == 0) { 3942 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED provisioning SP FQDN '%s'", 3943 cmd + 16); 3944 cred = wpa_s->conf->cred; 3945 while (cred) { 3946 prev = cred; 3947 cred = cred->next; 3948 if (prev->provisioning_sp && 3949 os_strcmp(prev->provisioning_sp, cmd + 16) == 0) 3950 wpas_remove_cred(wpa_s, prev); 3951 } 3952 return 0; 3953 } 3954 3955 id = atoi(cmd); 3956 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 3957 3958 cred = wpa_config_get_cred(wpa_s->conf, id); 3959 return wpas_remove_cred(wpa_s, cred); 3960 } 3961 3962 3963 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 3964 char *cmd) 3965 { 3966 int id; 3967 struct wpa_cred *cred; 3968 char *name, *value; 3969 3970 /* cmd: "<cred id> <variable name> <value>" */ 3971 name = os_strchr(cmd, ' '); 3972 if (name == NULL) 3973 return -1; 3974 *name++ = '\0'; 3975 3976 value = os_strchr(name, ' '); 3977 if (value == NULL) 3978 return -1; 3979 *value++ = '\0'; 3980 3981 id = atoi(cmd); 3982 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 3983 id, name); 3984 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 3985 (u8 *) value, os_strlen(value)); 3986 3987 cred = wpa_config_get_cred(wpa_s->conf, id); 3988 if (cred == NULL) { 3989 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 3990 id); 3991 return -1; 3992 } 3993 3994 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 3995 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 3996 "variable '%s'", name); 3997 return -1; 3998 } 3999 4000 wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name); 4001 4002 return 0; 4003 } 4004 4005 4006 static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s, 4007 char *cmd, char *buf, 4008 size_t buflen) 4009 { 4010 int id; 4011 size_t res; 4012 struct wpa_cred *cred; 4013 char *name, *value; 4014 4015 /* cmd: "<cred id> <variable name>" */ 4016 name = os_strchr(cmd, ' '); 4017 if (name == NULL) 4018 return -1; 4019 *name++ = '\0'; 4020 4021 id = atoi(cmd); 4022 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'", 4023 id, name); 4024 4025 cred = wpa_config_get_cred(wpa_s->conf, id); 4026 if (cred == NULL) { 4027 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 4028 id); 4029 return -1; 4030 } 4031 4032 value = wpa_config_get_cred_no_key(cred, name); 4033 if (value == NULL) { 4034 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'", 4035 name); 4036 return -1; 4037 } 4038 4039 res = os_strlcpy(buf, value, buflen); 4040 if (res >= buflen) { 4041 os_free(value); 4042 return -1; 4043 } 4044 4045 os_free(value); 4046 4047 return res; 4048 } 4049 4050 4051 #ifndef CONFIG_NO_CONFIG_WRITE 4052 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 4053 { 4054 int ret; 4055 4056 if (!wpa_s->conf->update_config) { 4057 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 4058 "to update configuration (update_config=0)"); 4059 return -1; 4060 } 4061 4062 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 4063 if (ret) { 4064 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 4065 "update configuration"); 4066 } else { 4067 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 4068 " updated"); 4069 } 4070 4071 return ret; 4072 } 4073 #endif /* CONFIG_NO_CONFIG_WRITE */ 4074 4075 4076 struct cipher_info { 4077 unsigned int capa; 4078 const char *name; 4079 int group_only; 4080 }; 4081 4082 static const struct cipher_info ciphers[] = { 4083 { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 }, 4084 { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, 4085 { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, 4086 { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, 4087 #ifndef CONFIG_NO_TKIP 4088 { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, 4089 #endif /* CONFIG_NO_TKIP */ 4090 { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, 4091 #ifdef CONFIG_WEP 4092 { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, 4093 { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } 4094 #endif /* CONFIG_WEP */ 4095 }; 4096 4097 static const struct cipher_info ciphers_group_mgmt[] = { 4098 { WPA_DRIVER_CAPA_ENC_BIP, "AES-128-CMAC", 1 }, 4099 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_128, "BIP-GMAC-128", 1 }, 4100 { WPA_DRIVER_CAPA_ENC_BIP_GMAC_256, "BIP-GMAC-256", 1 }, 4101 { WPA_DRIVER_CAPA_ENC_BIP_CMAC_256, "BIP-CMAC-256", 1 }, 4102 }; 4103 4104 4105 static int ctrl_iface_get_capability_pairwise(int res, bool strict, 4106 struct wpa_driver_capa *capa, 4107 char *buf, size_t buflen) 4108 { 4109 int ret; 4110 char *pos, *end; 4111 size_t len; 4112 unsigned int i; 4113 4114 pos = buf; 4115 end = pos + buflen; 4116 4117 if (res < 0) { 4118 if (strict) 4119 return 0; 4120 #ifdef CONFIG_NO_TKIP 4121 len = os_strlcpy(buf, "CCMP NONE", buflen); 4122 #else /* CONFIG_NO_TKIP */ 4123 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 4124 #endif /* CONFIG_NO_TKIP */ 4125 if (len >= buflen) 4126 return -1; 4127 return len; 4128 } 4129 4130 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 4131 if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) { 4132 ret = os_snprintf(pos, end - pos, "%s%s", 4133 pos == buf ? "" : " ", 4134 ciphers[i].name); 4135 if (os_snprintf_error(end - pos, ret)) 4136 return pos - buf; 4137 pos += ret; 4138 } 4139 } 4140 4141 return pos - buf; 4142 } 4143 4144 4145 static int ctrl_iface_get_capability_group(int res, bool strict, 4146 struct wpa_driver_capa *capa, 4147 char *buf, size_t buflen) 4148 { 4149 int ret; 4150 char *pos, *end; 4151 size_t len; 4152 unsigned int i; 4153 4154 pos = buf; 4155 end = pos + buflen; 4156 4157 if (res < 0) { 4158 if (strict) 4159 return 0; 4160 #ifdef CONFIG_WEP 4161 #ifdef CONFIG_NO_TKIP 4162 len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen); 4163 #else /* CONFIG_NO_TKIP */ 4164 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 4165 #endif /* CONFIG_NO_TKIP */ 4166 #else /* CONFIG_WEP */ 4167 #ifdef CONFIG_NO_TKIP 4168 len = os_strlcpy(buf, "CCMP", buflen); 4169 #else /* CONFIG_NO_TKIP */ 4170 len = os_strlcpy(buf, "CCMP TKIP", buflen); 4171 #endif /* CONFIG_NO_TKIP */ 4172 #endif /* CONFIG_WEP */ 4173 if (len >= buflen) 4174 return -1; 4175 return len; 4176 } 4177 4178 for (i = 0; i < ARRAY_SIZE(ciphers); i++) { 4179 if (capa->enc & ciphers[i].capa) { 4180 ret = os_snprintf(pos, end - pos, "%s%s", 4181 pos == buf ? "" : " ", 4182 ciphers[i].name); 4183 if (os_snprintf_error(end - pos, ret)) 4184 return pos - buf; 4185 pos += ret; 4186 } 4187 } 4188 4189 return pos - buf; 4190 } 4191 4192 4193 static int ctrl_iface_get_capability_group_mgmt(int res, bool strict, 4194 struct wpa_driver_capa *capa, 4195 char *buf, size_t buflen) 4196 { 4197 int ret; 4198 char *pos, *end; 4199 unsigned int i; 4200 4201 pos = buf; 4202 end = pos + buflen; 4203 4204 if (res < 0) 4205 return 0; 4206 4207 for (i = 0; i < ARRAY_SIZE(ciphers_group_mgmt); i++) { 4208 if (capa->enc & ciphers_group_mgmt[i].capa) { 4209 ret = os_snprintf(pos, end - pos, "%s%s", 4210 pos == buf ? "" : " ", 4211 ciphers_group_mgmt[i].name); 4212 if (os_snprintf_error(end - pos, ret)) 4213 return pos - buf; 4214 pos += ret; 4215 } 4216 } 4217 4218 return pos - buf; 4219 } 4220 4221 4222 static int iftype_str_to_index(const char *iftype_str) 4223 { 4224 if (!iftype_str) 4225 return WPA_IF_MAX; 4226 4227 if (os_strcmp(iftype_str, "STATION") == 0) 4228 return WPA_IF_STATION; 4229 4230 if (os_strcmp(iftype_str, "AP_VLAN") == 0) 4231 return WPA_IF_AP_VLAN; 4232 4233 if (os_strcmp(iftype_str, "AP") == 0) 4234 return WPA_IF_AP_BSS; 4235 4236 if (os_strcmp(iftype_str, "P2P_GO") == 0) 4237 return WPA_IF_P2P_GO; 4238 4239 if (os_strcmp(iftype_str, "P2P_CLIENT") == 0) 4240 return WPA_IF_P2P_CLIENT; 4241 4242 if (os_strcmp(iftype_str, "P2P_DEVICE") == 0) 4243 return WPA_IF_P2P_DEVICE; 4244 4245 if (os_strcmp(iftype_str, "MESH") == 0) 4246 return WPA_IF_MESH; 4247 4248 if (os_strcmp(iftype_str, "IBSS") == 0) 4249 return WPA_IF_IBSS; 4250 4251 if (os_strcmp(iftype_str, "NAN") == 0) 4252 return WPA_IF_NAN; 4253 4254 return WPA_IF_MAX; 4255 } 4256 4257 4258 static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, 4259 struct wpa_driver_capa *capa, 4260 const char *iftype_str, 4261 char *buf, size_t buflen) 4262 { 4263 int ret; 4264 unsigned int key_mgmt; 4265 char *pos, *end; 4266 size_t len; 4267 4268 pos = buf; 4269 end = pos + buflen; 4270 4271 if (res < 0) { 4272 if (strict) 4273 return 0; 4274 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 4275 "NONE", buflen); 4276 if (len >= buflen) 4277 return -1; 4278 return len; 4279 } 4280 4281 if (iftype_str) { 4282 enum wpa_driver_if_type iftype; 4283 4284 iftype = iftype_str_to_index(iftype_str); 4285 if (iftype == WPA_IF_MAX) 4286 return -1; 4287 key_mgmt = capa->key_mgmt_iftype[iftype]; 4288 } else { 4289 key_mgmt = capa->key_mgmt; 4290 } 4291 4292 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 4293 if (os_snprintf_error(end - pos, ret)) 4294 return pos - buf; 4295 pos += ret; 4296 4297 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4298 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 4299 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 4300 if (os_snprintf_error(end - pos, ret)) 4301 return pos - buf; 4302 pos += ret; 4303 } 4304 4305 if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 4306 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4307 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 4308 if (os_snprintf_error(end - pos, ret)) 4309 return pos - buf; 4310 pos += ret; 4311 } 4312 4313 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 4314 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 4315 if (os_snprintf_error(end - pos, ret)) 4316 return pos - buf; 4317 pos += ret; 4318 } 4319 4320 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) { 4321 ret = os_snprintf(pos, end - pos, " WAPI-PSK"); 4322 if (os_snprintf_error(end - pos, ret)) 4323 return pos - buf; 4324 pos += ret; 4325 } 4326 4327 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) { 4328 ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE"); 4329 if (os_snprintf_error(end - pos, ret)) 4330 return pos - buf; 4331 pos += ret; 4332 } 4333 4334 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) { 4335 ret = os_snprintf(pos, end - pos, " CCKM"); 4336 if (os_snprintf_error(end - pos, ret)) 4337 return pos - buf; 4338 pos += ret; 4339 } 4340 4341 #ifdef CONFIG_SUITEB 4342 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { 4343 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); 4344 if (os_snprintf_error(end - pos, ret)) 4345 return pos - buf; 4346 pos += ret; 4347 } 4348 #endif /* CONFIG_SUITEB */ 4349 #ifdef CONFIG_SUITEB192 4350 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { 4351 ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); 4352 if (os_snprintf_error(end - pos, ret)) 4353 return pos - buf; 4354 pos += ret; 4355 } 4356 #endif /* CONFIG_SUITEB192 */ 4357 #ifdef CONFIG_OWE 4358 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { 4359 ret = os_snprintf(pos, end - pos, " OWE"); 4360 if (os_snprintf_error(end - pos, ret)) 4361 return pos - buf; 4362 pos += ret; 4363 } 4364 #endif /* CONFIG_OWE */ 4365 #ifdef CONFIG_DPP 4366 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { 4367 ret = os_snprintf(pos, end - pos, " DPP"); 4368 if (os_snprintf_error(end - pos, ret)) 4369 return pos - buf; 4370 pos += ret; 4371 } 4372 #endif /* CONFIG_DPP */ 4373 #ifdef CONFIG_FILS 4374 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { 4375 ret = os_snprintf(pos, end - pos, " FILS-SHA256"); 4376 if (os_snprintf_error(end - pos, ret)) 4377 return pos - buf; 4378 pos += ret; 4379 } 4380 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { 4381 ret = os_snprintf(pos, end - pos, " FILS-SHA384"); 4382 if (os_snprintf_error(end - pos, ret)) 4383 return pos - buf; 4384 pos += ret; 4385 } 4386 #ifdef CONFIG_IEEE80211R 4387 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { 4388 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); 4389 if (os_snprintf_error(end - pos, ret)) 4390 return pos - buf; 4391 pos += ret; 4392 } 4393 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { 4394 ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); 4395 if (os_snprintf_error(end - pos, ret)) 4396 return pos - buf; 4397 pos += ret; 4398 } 4399 #endif /* CONFIG_IEEE80211R */ 4400 #endif /* CONFIG_FILS */ 4401 #ifdef CONFIG_IEEE80211R 4402 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { 4403 ret = os_snprintf(pos, end - pos, " FT-PSK"); 4404 if (os_snprintf_error(end - pos, ret)) 4405 return pos - buf; 4406 pos += ret; 4407 } 4408 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { 4409 ret = os_snprintf(pos, end - pos, " FT-EAP"); 4410 if (os_snprintf_error(end - pos, ret)) 4411 return pos - buf; 4412 pos += ret; 4413 } 4414 #ifdef CONFIG_SAE 4415 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) { 4416 ret = os_snprintf(pos, end - pos, " FT-SAE"); 4417 if (os_snprintf_error(end - pos, ret)) 4418 return pos - buf; 4419 pos += ret; 4420 } 4421 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY) { 4422 ret = os_snprintf(pos, end - pos, " FT-SAE-EXT-KEY"); 4423 if (os_snprintf_error(end - pos, ret)) 4424 return pos - buf; 4425 pos += ret; 4426 } 4427 #endif /* CONFIG_SAE */ 4428 #ifdef CONFIG_SHA384 4429 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) { 4430 ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384"); 4431 if (os_snprintf_error(end - pos, ret)) 4432 return pos - buf; 4433 pos += ret; 4434 } 4435 #endif /* CONFIG_SHA384 */ 4436 #endif /* CONFIG_IEEE80211R */ 4437 #ifdef CONFIG_SAE 4438 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { 4439 ret = os_snprintf(pos, end - pos, " SAE"); 4440 if (os_snprintf_error(end - pos, ret)) 4441 return pos - buf; 4442 pos += ret; 4443 } 4444 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY) { 4445 ret = os_snprintf(pos, end - pos, " SAE-EXT-KEY"); 4446 if (os_snprintf_error(end - pos, ret)) 4447 return pos - buf; 4448 pos += ret; 4449 } 4450 #endif /* CONFIG_SAE */ 4451 #ifdef CONFIG_SHA256 4452 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) { 4453 ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256"); 4454 if (os_snprintf_error(end - pos, ret)) 4455 return pos - buf; 4456 pos += ret; 4457 } 4458 4459 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) { 4460 ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256"); 4461 if (os_snprintf_error(end - pos, ret)) 4462 return pos - buf; 4463 pos += ret; 4464 } 4465 #endif /* CONFIG_SHA256 */ 4466 #ifdef CONFIG_HS20 4467 if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) { 4468 ret = os_snprintf(pos, end - pos, " OSEN"); 4469 if (os_snprintf_error(end - pos, ret)) 4470 return pos - buf; 4471 pos += ret; 4472 } 4473 #endif /* CONFIG_HS20 */ 4474 4475 return pos - buf; 4476 } 4477 4478 4479 static int ctrl_iface_get_capability_proto(int res, bool strict, 4480 struct wpa_driver_capa *capa, 4481 char *buf, size_t buflen) 4482 { 4483 int ret; 4484 char *pos, *end; 4485 size_t len; 4486 4487 pos = buf; 4488 end = pos + buflen; 4489 4490 if (res < 0) { 4491 if (strict) 4492 return 0; 4493 len = os_strlcpy(buf, "RSN WPA", buflen); 4494 if (len >= buflen) 4495 return -1; 4496 return len; 4497 } 4498 4499 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 4500 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 4501 ret = os_snprintf(pos, end - pos, "%sRSN", 4502 pos == buf ? "" : " "); 4503 if (os_snprintf_error(end - pos, ret)) 4504 return pos - buf; 4505 pos += ret; 4506 } 4507 4508 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 4509 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 4510 ret = os_snprintf(pos, end - pos, "%sWPA", 4511 pos == buf ? "" : " "); 4512 if (os_snprintf_error(end - pos, ret)) 4513 return pos - buf; 4514 pos += ret; 4515 } 4516 4517 return pos - buf; 4518 } 4519 4520 4521 static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, 4522 int res, bool strict, 4523 struct wpa_driver_capa *capa, 4524 char *buf, size_t buflen) 4525 { 4526 int ret; 4527 char *pos, *end; 4528 size_t len; 4529 4530 pos = buf; 4531 end = pos + buflen; 4532 4533 if (res < 0) { 4534 if (strict) 4535 return 0; 4536 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 4537 if (len >= buflen) 4538 return -1; 4539 return len; 4540 } 4541 4542 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 4543 ret = os_snprintf(pos, end - pos, "%sOPEN", 4544 pos == buf ? "" : " "); 4545 if (os_snprintf_error(end - pos, ret)) 4546 return pos - buf; 4547 pos += ret; 4548 } 4549 4550 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 4551 ret = os_snprintf(pos, end - pos, "%sSHARED", 4552 pos == buf ? "" : " "); 4553 if (os_snprintf_error(end - pos, ret)) 4554 return pos - buf; 4555 pos += ret; 4556 } 4557 4558 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 4559 ret = os_snprintf(pos, end - pos, "%sLEAP", 4560 pos == buf ? "" : " "); 4561 if (os_snprintf_error(end - pos, ret)) 4562 return pos - buf; 4563 pos += ret; 4564 } 4565 4566 #ifdef CONFIG_SAE 4567 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) { 4568 ret = os_snprintf(pos, end - pos, "%sSAE", 4569 pos == buf ? "" : " "); 4570 if (os_snprintf_error(end - pos, ret)) 4571 return pos - buf; 4572 pos += ret; 4573 } 4574 #endif /* CONFIG_SAE */ 4575 4576 #ifdef CONFIG_FILS 4577 if (wpa_is_fils_supported(wpa_s)) { 4578 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS", 4579 pos == buf ? "" : " "); 4580 if (os_snprintf_error(end - pos, ret)) 4581 return pos - buf; 4582 pos += ret; 4583 } 4584 4585 #ifdef CONFIG_FILS_SK_PFS 4586 if (wpa_is_fils_sk_pfs_supported(wpa_s)) { 4587 ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS", 4588 pos == buf ? "" : " "); 4589 if (os_snprintf_error(end - pos, ret)) 4590 return pos - buf; 4591 pos += ret; 4592 } 4593 #endif /* CONFIG_FILS_SK_PFS */ 4594 #endif /* CONFIG_FILS */ 4595 4596 #ifdef CONFIG_PASN 4597 ret = os_snprintf(pos, end - pos, "%sPASN", 4598 pos == buf ? "" : " "); 4599 if (os_snprintf_error(end - pos, ret)) 4600 return pos - buf; 4601 pos += ret; 4602 4603 #endif /* CONFIG_PASN */ 4604 4605 return pos - buf; 4606 } 4607 4608 4609 static int ctrl_iface_get_capability_modes(int res, bool strict, 4610 struct wpa_driver_capa *capa, 4611 char *buf, size_t buflen) 4612 { 4613 int ret; 4614 char *pos, *end; 4615 size_t len; 4616 4617 pos = buf; 4618 end = pos + buflen; 4619 4620 if (res < 0) { 4621 if (strict) 4622 return 0; 4623 len = os_strlcpy(buf, "IBSS AP", buflen); 4624 if (len >= buflen) 4625 return -1; 4626 return len; 4627 } 4628 4629 if (capa->flags & WPA_DRIVER_FLAGS_IBSS) { 4630 ret = os_snprintf(pos, end - pos, "%sIBSS", 4631 pos == buf ? "" : " "); 4632 if (os_snprintf_error(end - pos, ret)) 4633 return pos - buf; 4634 pos += ret; 4635 } 4636 4637 if (capa->flags & WPA_DRIVER_FLAGS_AP) { 4638 ret = os_snprintf(pos, end - pos, "%sAP", 4639 pos == buf ? "" : " "); 4640 if (os_snprintf_error(end - pos, ret)) 4641 return pos - buf; 4642 pos += ret; 4643 } 4644 4645 #ifdef CONFIG_MESH 4646 if (capa->flags & WPA_DRIVER_FLAGS_MESH) { 4647 ret = os_snprintf(pos, end - pos, "%sMESH", 4648 pos == buf ? "" : " "); 4649 if (os_snprintf_error(end - pos, ret)) 4650 return pos - buf; 4651 pos += ret; 4652 } 4653 #endif /* CONFIG_MESH */ 4654 4655 return pos - buf; 4656 } 4657 4658 4659 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 4660 char *buf, size_t buflen) 4661 { 4662 struct hostapd_channel_data *chnl; 4663 int ret, i, j; 4664 char *pos, *end, *hmode; 4665 4666 pos = buf; 4667 end = pos + buflen; 4668 4669 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4670 switch (wpa_s->hw.modes[j].mode) { 4671 case HOSTAPD_MODE_IEEE80211B: 4672 hmode = "B"; 4673 break; 4674 case HOSTAPD_MODE_IEEE80211G: 4675 hmode = "G"; 4676 break; 4677 case HOSTAPD_MODE_IEEE80211A: 4678 hmode = "A"; 4679 break; 4680 case HOSTAPD_MODE_IEEE80211AD: 4681 hmode = "AD"; 4682 break; 4683 default: 4684 continue; 4685 } 4686 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 4687 if (os_snprintf_error(end - pos, ret)) 4688 return pos - buf; 4689 pos += ret; 4690 chnl = wpa_s->hw.modes[j].channels; 4691 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4692 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4693 continue; 4694 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 4695 if (os_snprintf_error(end - pos, ret)) 4696 return pos - buf; 4697 pos += ret; 4698 } 4699 ret = os_snprintf(pos, end - pos, "\n"); 4700 if (os_snprintf_error(end - pos, ret)) 4701 return pos - buf; 4702 pos += ret; 4703 } 4704 4705 return pos - buf; 4706 } 4707 4708 4709 static int ctrl_iface_get_capability_freq(struct wpa_supplicant *wpa_s, 4710 char *buf, size_t buflen) 4711 { 4712 struct hostapd_channel_data *chnl; 4713 int ret, i, j; 4714 char *pos, *end, *hmode; 4715 4716 pos = buf; 4717 end = pos + buflen; 4718 4719 for (j = 0; j < wpa_s->hw.num_modes; j++) { 4720 switch (wpa_s->hw.modes[j].mode) { 4721 case HOSTAPD_MODE_IEEE80211B: 4722 hmode = "B"; 4723 break; 4724 case HOSTAPD_MODE_IEEE80211G: 4725 hmode = "G"; 4726 break; 4727 case HOSTAPD_MODE_IEEE80211A: 4728 hmode = "A"; 4729 break; 4730 case HOSTAPD_MODE_IEEE80211AD: 4731 hmode = "AD"; 4732 break; 4733 default: 4734 continue; 4735 } 4736 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:\n", 4737 hmode); 4738 if (os_snprintf_error(end - pos, ret)) 4739 return pos - buf; 4740 pos += ret; 4741 chnl = wpa_s->hw.modes[j].channels; 4742 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 4743 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 4744 continue; 4745 ret = os_snprintf(pos, end - pos, " %d = %d MHz%s%s\n", 4746 chnl[i].chan, chnl[i].freq, 4747 chnl[i].flag & HOSTAPD_CHAN_NO_IR ? 4748 " (NO_IR)" : "", 4749 chnl[i].flag & HOSTAPD_CHAN_RADAR ? 4750 " (DFS)" : ""); 4751 4752 if (os_snprintf_error(end - pos, ret)) 4753 return pos - buf; 4754 pos += ret; 4755 } 4756 ret = os_snprintf(pos, end - pos, "\n"); 4757 if (os_snprintf_error(end - pos, ret)) 4758 return pos - buf; 4759 pos += ret; 4760 } 4761 4762 return pos - buf; 4763 } 4764 4765 4766 static int wpa_supplicant_ctrl_iface_get_capability( 4767 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 4768 size_t buflen) 4769 { 4770 struct wpa_driver_capa capa; 4771 int res; 4772 char *next_param, *curr_param, *iftype = NULL; 4773 bool strict = false; 4774 char field[50]; 4775 size_t len; 4776 4777 /* Determine whether or not strict checking was requested */ 4778 len = os_strlcpy(field, _field, sizeof(field)); 4779 if (len >= sizeof(field)) 4780 return -1; 4781 4782 next_param = os_strchr(field, ' '); 4783 while (next_param) { 4784 *next_param++ = '\0'; 4785 curr_param = next_param; 4786 next_param = os_strchr(next_param, ' '); 4787 4788 if (next_param) 4789 *next_param = '\0'; 4790 4791 if (os_strcmp(curr_param, "strict") == 0) 4792 strict = true; 4793 else if (os_strncmp(curr_param, "iftype=", 7) == 0) 4794 iftype = curr_param + 7; 4795 else 4796 return -1; 4797 } 4798 4799 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s", 4800 field, iftype ? " iftype=" : "", iftype ? iftype : "", 4801 strict ? " strict" : ""); 4802 4803 if (os_strcmp(field, "eap") == 0) { 4804 return eap_get_names(buf, buflen); 4805 } 4806 4807 res = wpa_drv_get_capa(wpa_s, &capa); 4808 4809 if (os_strcmp(field, "pairwise") == 0) 4810 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 4811 buf, buflen); 4812 4813 if (os_strcmp(field, "group") == 0) 4814 return ctrl_iface_get_capability_group(res, strict, &capa, 4815 buf, buflen); 4816 4817 if (os_strcmp(field, "group_mgmt") == 0) 4818 return ctrl_iface_get_capability_group_mgmt(res, strict, &capa, 4819 buf, buflen); 4820 4821 if (os_strcmp(field, "key_mgmt") == 0) 4822 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 4823 iftype, buf, buflen); 4824 4825 if (os_strcmp(field, "proto") == 0) 4826 return ctrl_iface_get_capability_proto(res, strict, &capa, 4827 buf, buflen); 4828 4829 if (os_strcmp(field, "auth_alg") == 0) 4830 return ctrl_iface_get_capability_auth_alg(wpa_s, res, strict, 4831 &capa, buf, buflen); 4832 4833 if (os_strcmp(field, "modes") == 0) 4834 return ctrl_iface_get_capability_modes(res, strict, &capa, 4835 buf, buflen); 4836 4837 if (os_strcmp(field, "channels") == 0) 4838 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 4839 4840 if (os_strcmp(field, "freq") == 0) 4841 return ctrl_iface_get_capability_freq(wpa_s, buf, buflen); 4842 4843 #ifdef CONFIG_TDLS 4844 if (os_strcmp(field, "tdls") == 0) 4845 return ctrl_iface_get_capability_tdls(wpa_s, buf, buflen); 4846 #endif /* CONFIG_TDLS */ 4847 4848 #ifdef CONFIG_ERP 4849 if (os_strcmp(field, "erp") == 0) { 4850 res = os_snprintf(buf, buflen, "ERP"); 4851 if (os_snprintf_error(buflen, res)) 4852 return -1; 4853 return res; 4854 } 4855 #endif /* CONFIG_EPR */ 4856 4857 #ifdef CONFIG_FIPS 4858 if (os_strcmp(field, "fips") == 0) { 4859 res = os_snprintf(buf, buflen, "FIPS"); 4860 if (os_snprintf_error(buflen, res)) 4861 return -1; 4862 return res; 4863 } 4864 #endif /* CONFIG_FIPS */ 4865 4866 #ifdef CONFIG_ACS 4867 if (os_strcmp(field, "acs") == 0) { 4868 res = os_snprintf(buf, buflen, "ACS"); 4869 if (os_snprintf_error(buflen, res)) 4870 return -1; 4871 return res; 4872 } 4873 #endif /* CONFIG_ACS */ 4874 4875 #ifdef CONFIG_FILS 4876 if (os_strcmp(field, "fils") == 0) { 4877 #ifdef CONFIG_FILS_SK_PFS 4878 if (wpa_is_fils_supported(wpa_s) && 4879 wpa_is_fils_sk_pfs_supported(wpa_s)) { 4880 res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS"); 4881 if (os_snprintf_error(buflen, res)) 4882 return -1; 4883 return res; 4884 } 4885 #endif /* CONFIG_FILS_SK_PFS */ 4886 4887 if (wpa_is_fils_supported(wpa_s)) { 4888 res = os_snprintf(buf, buflen, "FILS"); 4889 if (os_snprintf_error(buflen, res)) 4890 return -1; 4891 return res; 4892 } 4893 } 4894 #endif /* CONFIG_FILS */ 4895 4896 if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) { 4897 res = os_snprintf(buf, buflen, "MULTIBSS-STA"); 4898 if (os_snprintf_error(buflen, res)) 4899 return -1; 4900 return res; 4901 } 4902 4903 #ifdef CONFIG_DPP 4904 if (os_strcmp(field, "dpp") == 0) { 4905 #ifdef CONFIG_DPP3 4906 res = os_snprintf(buf, buflen, "DPP=3"); 4907 #elif defined(CONFIG_DPP2) 4908 res = os_snprintf(buf, buflen, "DPP=2"); 4909 #else /* CONFIG_DPP2 */ 4910 res = os_snprintf(buf, buflen, "DPP=1"); 4911 #endif /* CONFIG_DPP2 */ 4912 if (os_snprintf_error(buflen, res)) 4913 return -1; 4914 return res; 4915 } 4916 #endif /* CONFIG_DPP */ 4917 4918 #ifdef CONFIG_NAN_USD 4919 if (os_strcmp(field, "nan") == 0) { 4920 res = os_snprintf(buf, buflen, "USD"); 4921 if (os_snprintf_error(buflen, res)) 4922 return -1; 4923 return res; 4924 } 4925 #endif /* CONFIG_NAN_USD */ 4926 4927 #ifdef CONFIG_SAE 4928 if (os_strcmp(field, "sae") == 0 && 4929 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { 4930 #ifdef CONFIG_SAE_PK 4931 res = os_snprintf(buf, buflen, "H2E PK"); 4932 #else /* CONFIG_SAE_PK */ 4933 res = os_snprintf(buf, buflen, "H2E"); 4934 #endif /* CONFIG_SAE_PK */ 4935 if (os_snprintf_error(buflen, res)) 4936 return -1; 4937 return res; 4938 } 4939 #endif /* CONFIG_SAE */ 4940 4941 #ifdef CONFIG_OCV 4942 if (os_strcmp(field, "ocv") == 0) { 4943 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) || 4944 (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV)) 4945 res = os_snprintf(buf, buflen, "supported"); 4946 else 4947 res = os_snprintf(buf, buflen, "not supported"); 4948 if (os_snprintf_error(buflen, res)) 4949 return -1; 4950 return res; 4951 } 4952 #endif /* CONFIG_OCV */ 4953 4954 if (os_strcmp(field, "beacon_prot") == 0) { 4955 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) || 4956 (wpa_s->drv_flags2 & 4957 WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT)) 4958 res = os_snprintf(buf, buflen, "supported"); 4959 else 4960 res = os_snprintf(buf, buflen, "not supported"); 4961 if (os_snprintf_error(buflen, res)) 4962 return -1; 4963 return res; 4964 } 4965 4966 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 4967 field); 4968 4969 return -1; 4970 } 4971 4972 4973 #ifdef CONFIG_INTERWORKING 4974 static char * anqp_add_hex(char *pos, char *end, const char *title, 4975 struct wpabuf *data) 4976 { 4977 char *start = pos; 4978 size_t i; 4979 int ret; 4980 const u8 *d; 4981 4982 if (data == NULL) 4983 return start; 4984 4985 ret = os_snprintf(pos, end - pos, "%s=", title); 4986 if (os_snprintf_error(end - pos, ret)) 4987 return start; 4988 pos += ret; 4989 4990 d = wpabuf_head_u8(data); 4991 for (i = 0; i < wpabuf_len(data); i++) { 4992 ret = os_snprintf(pos, end - pos, "%02x", *d++); 4993 if (os_snprintf_error(end - pos, ret)) 4994 return start; 4995 pos += ret; 4996 } 4997 4998 ret = os_snprintf(pos, end - pos, "\n"); 4999 if (os_snprintf_error(end - pos, ret)) 5000 return start; 5001 pos += ret; 5002 5003 return pos; 5004 } 5005 #endif /* CONFIG_INTERWORKING */ 5006 5007 5008 #ifdef CONFIG_FILS 5009 static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) 5010 { 5011 char *start = pos; 5012 const u8 *ie, *ie_end; 5013 u16 info, realms; 5014 int ret; 5015 5016 ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); 5017 if (!ie) 5018 return 0; 5019 ie_end = ie + 2 + ie[1]; 5020 ie += 2; 5021 if (ie_end - ie < 2) 5022 return 0; 5023 5024 info = WPA_GET_LE16(ie); 5025 ie += 2; 5026 ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info); 5027 if (os_snprintf_error(end - pos, ret)) 5028 return 0; 5029 pos += ret; 5030 5031 if (info & BIT(7)) { 5032 /* Cache Identifier Included */ 5033 if (ie_end - ie < 2) 5034 return 0; 5035 ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n", 5036 ie[0], ie[1]); 5037 if (os_snprintf_error(end - pos, ret)) 5038 return 0; 5039 pos += ret; 5040 ie += 2; 5041 } 5042 5043 if (info & BIT(8)) { 5044 /* HESSID Included */ 5045 if (ie_end - ie < ETH_ALEN) 5046 return 0; 5047 ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n", 5048 MAC2STR(ie)); 5049 if (os_snprintf_error(end - pos, ret)) 5050 return 0; 5051 pos += ret; 5052 ie += ETH_ALEN; 5053 } 5054 5055 realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3; 5056 if (realms) { 5057 if (ie_end - ie < realms * 2) 5058 return 0; 5059 ret = os_snprintf(pos, end - pos, "fils_realms="); 5060 if (os_snprintf_error(end - pos, ret)) 5061 return 0; 5062 pos += ret; 5063 5064 ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2); 5065 if (ret <= 0) 5066 return 0; 5067 pos += ret; 5068 ie += realms * 2; 5069 ret = os_snprintf(pos, end - pos, "\n"); 5070 if (os_snprintf_error(end - pos, ret)) 5071 return 0; 5072 pos += ret; 5073 } 5074 5075 return pos - start; 5076 } 5077 #endif /* CONFIG_FILS */ 5078 5079 5080 static int print_rnr(struct wpa_bss *bss, char *pos, char *end) 5081 { 5082 char *start = pos; 5083 const u8 *ie, *ie_end; 5084 unsigned int n = 0; 5085 int ret; 5086 5087 ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT); 5088 if (!ie) 5089 return 0; 5090 5091 ie_end = ie + 2 + ie[1]; 5092 ie += 2; 5093 5094 while (ie < ie_end) { 5095 const struct ieee80211_neighbor_ap_info *info = 5096 (const struct ieee80211_neighbor_ap_info *) ie; 5097 const u8 *tbtt_start; 5098 size_t left = ie_end - ie; 5099 5100 if (left < sizeof(struct ieee80211_neighbor_ap_info)) 5101 return 0; 5102 5103 left -= sizeof(struct ieee80211_neighbor_ap_info); 5104 if (left < info->tbtt_info_len) 5105 return 0; 5106 5107 ret = os_snprintf(pos, end - pos, 5108 "ap_info[%u]: tbtt_info: hdr=0x%x, len=%u, op_c=%u, channel=%u, ", 5109 n, *ie, info->tbtt_info_len, 5110 info->op_class, info->channel); 5111 if (os_snprintf_error(end - pos, ret)) 5112 return 0; 5113 pos += ret; 5114 5115 ie += sizeof(struct ieee80211_neighbor_ap_info); 5116 tbtt_start = ie; 5117 if (info->tbtt_info_len >= 1) { 5118 ret = os_snprintf(pos, end - pos, 5119 "tbtt_offset=%u, ", *ie); 5120 if (os_snprintf_error(end - pos, ret)) 5121 return 0; 5122 5123 ie++; 5124 pos += ret; 5125 } 5126 5127 if (info->tbtt_info_len >= 7) { 5128 ret = os_snprintf(pos, end - pos, 5129 "bssid=" MACSTR ", ", 5130 MAC2STR(ie)); 5131 if (os_snprintf_error(end - pos, ret)) 5132 return 0; 5133 5134 ie += ETH_ALEN; 5135 pos += ret; 5136 } 5137 5138 if (info->tbtt_info_len >= 11) { 5139 ret = os_snprintf(pos, end - pos, 5140 "short SSID=0x%x, ", 5141 WPA_GET_LE32(ie)); 5142 if (os_snprintf_error(end - pos, ret)) 5143 return 0; 5144 5145 ie += 4; 5146 pos += ret; 5147 } 5148 5149 if (info->tbtt_info_len >= 12) { 5150 ret = os_snprintf(pos, end - pos, 5151 "bss_params=0x%x, ", *ie); 5152 if (os_snprintf_error(end - pos, ret)) 5153 return 0; 5154 5155 ie++; 5156 pos += ret; 5157 } 5158 5159 if (info->tbtt_info_len >= 13) { 5160 ret = os_snprintf(pos, end - pos, 5161 "PSD=0x%x, ", *ie); 5162 if (os_snprintf_error(end - pos, ret)) 5163 return 0; 5164 5165 ie++; 5166 pos += ret; 5167 } 5168 5169 if (info->tbtt_info_len >= 16) { 5170 ret = os_snprintf(pos, end - pos, 5171 "mld ID=%u, link ID=%u", 5172 *ie, *(ie + 1) & 0xF); 5173 if (os_snprintf_error(end - pos, ret)) 5174 return 0; 5175 5176 ie += 3; 5177 pos += ret; 5178 } 5179 5180 ie = tbtt_start + info->tbtt_info_len; 5181 5182 ret = os_snprintf(pos, end - pos, "\n"); 5183 if (os_snprintf_error(end - pos, ret)) 5184 return 0; 5185 pos += ret; 5186 5187 n++; 5188 } 5189 5190 return pos - start; 5191 } 5192 5193 5194 static int print_ml(struct wpa_bss *bss, char *pos, char *end) 5195 { 5196 const struct ieee80211_eht_ml *ml; 5197 char *start = pos; 5198 const u8 *ie, *ie_end; 5199 u16 ml_control; 5200 u8 common_info_length; 5201 int ret; 5202 5203 ie = get_ml_ie(wpa_bss_ie_ptr(bss), bss->ie_len, 5204 MULTI_LINK_CONTROL_TYPE_BASIC); 5205 if (!ie) 5206 return 0; 5207 5208 ie_end = ie + 2 + ie[1]; 5209 ie += 3; 5210 ml = (const struct ieee80211_eht_ml *) ie; 5211 5212 /* control + common info length + MLD MAC Address */ 5213 if (ie_end - ie < 2 + 1 + ETH_ALEN) 5214 return 0; 5215 5216 ml_control = le_to_host16(ml->ml_control); 5217 5218 common_info_length = *(ie + 2); 5219 ret = os_snprintf(pos, end - pos, 5220 "multi-link: control=0x%x, common info len=%u", 5221 ml_control, common_info_length); 5222 if (os_snprintf_error(end - pos, ret)) 5223 return 0; 5224 pos += ret; 5225 5226 ie += 2; 5227 if (ie_end - ie < common_info_length) 5228 return 0; 5229 5230 ie++; 5231 common_info_length--; 5232 5233 if (common_info_length < ETH_ALEN) 5234 return 0; 5235 5236 ret = os_snprintf(pos, end - pos, ", MLD addr=" MACSTR, MAC2STR(ie)); 5237 if (os_snprintf_error(end - pos, ret)) 5238 return 0; 5239 pos += ret; 5240 5241 ie += ETH_ALEN; 5242 common_info_length -= ETH_ALEN; 5243 5244 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) { 5245 if (common_info_length < 1) 5246 return 0; 5247 5248 ret = os_snprintf(pos, end - pos, ", link ID=%u", *ie & 0x0f); 5249 if (os_snprintf_error(end - pos, ret)) 5250 return 0; 5251 pos += ret; 5252 ie++; 5253 common_info_length--; 5254 } 5255 5256 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) { 5257 if (common_info_length < 1) 5258 return 0; 5259 5260 ret = os_snprintf(pos, end - pos, 5261 ", BSS change parameters=0x%x", *ie); 5262 if (os_snprintf_error(end - pos, ret)) 5263 return 0; 5264 pos += ret; 5265 ie++; 5266 common_info_length--; 5267 } 5268 5269 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) { 5270 if (common_info_length < 2) 5271 return 0; 5272 5273 ret = os_snprintf(pos, end - pos, ", MSD Info=0x%x", 5274 WPA_GET_LE16(ie)); 5275 if (os_snprintf_error(end - pos, ret)) 5276 return 0; 5277 pos += ret; 5278 ie += 2; 5279 common_info_length -= 2; 5280 } 5281 5282 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) { 5283 if (common_info_length < 2) 5284 return 0; 5285 5286 ret = os_snprintf(pos, end - pos, ", EML capabilities=0x%x", 5287 WPA_GET_LE16(ie)); 5288 if (os_snprintf_error(end - pos, ret)) 5289 return 0; 5290 pos += ret; 5291 ie += 2; 5292 common_info_length -= 2; 5293 } 5294 5295 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) { 5296 if (common_info_length < 2) 5297 return 0; 5298 5299 ret = os_snprintf(pos, end - pos, ", MLD capabilities=0x%x", 5300 WPA_GET_LE16(ie)); 5301 if (os_snprintf_error(end - pos, ret)) 5302 return 0; 5303 pos += ret; 5304 ie += 2; 5305 common_info_length -= 2; 5306 } 5307 5308 if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) { 5309 if (common_info_length < 1) 5310 return 0; 5311 5312 ret = os_snprintf(pos, end - pos, ", MLD ID=0x%x", *ie); 5313 if (os_snprintf_error(end - pos, ret)) 5314 return 0; 5315 pos += ret; 5316 ie += 1; 5317 common_info_length--; 5318 } 5319 5320 ret = os_snprintf(pos, end - pos, "\n"); 5321 if (os_snprintf_error(end - pos, ret)) 5322 return 0; 5323 pos += ret; 5324 5325 return pos - start; 5326 } 5327 5328 5329 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 5330 unsigned long mask, char *buf, size_t buflen) 5331 { 5332 size_t i; 5333 int ret; 5334 char *pos, *end; 5335 const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe; 5336 5337 pos = buf; 5338 end = buf + buflen; 5339 5340 if (mask & WPA_BSS_MASK_ID) { 5341 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 5342 if (os_snprintf_error(end - pos, ret)) 5343 return 0; 5344 pos += ret; 5345 } 5346 5347 if (mask & WPA_BSS_MASK_BSSID) { 5348 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 5349 MAC2STR(bss->bssid)); 5350 if (os_snprintf_error(end - pos, ret)) 5351 return 0; 5352 pos += ret; 5353 } 5354 5355 if (mask & WPA_BSS_MASK_FREQ) { 5356 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 5357 if (os_snprintf_error(end - pos, ret)) 5358 return 0; 5359 pos += ret; 5360 } 5361 5362 if (mask & WPA_BSS_MASK_BEACON_INT) { 5363 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 5364 bss->beacon_int); 5365 if (os_snprintf_error(end - pos, ret)) 5366 return 0; 5367 pos += ret; 5368 } 5369 5370 if (mask & WPA_BSS_MASK_CAPABILITIES) { 5371 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 5372 bss->caps); 5373 if (os_snprintf_error(end - pos, ret)) 5374 return 0; 5375 pos += ret; 5376 } 5377 5378 if (mask & WPA_BSS_MASK_QUAL) { 5379 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 5380 if (os_snprintf_error(end - pos, ret)) 5381 return 0; 5382 pos += ret; 5383 } 5384 5385 if (mask & WPA_BSS_MASK_NOISE) { 5386 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 5387 if (os_snprintf_error(end - pos, ret)) 5388 return 0; 5389 pos += ret; 5390 } 5391 5392 if (mask & WPA_BSS_MASK_LEVEL) { 5393 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 5394 if (os_snprintf_error(end - pos, ret)) 5395 return 0; 5396 pos += ret; 5397 } 5398 5399 if (mask & WPA_BSS_MASK_TSF) { 5400 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 5401 (unsigned long long) bss->tsf); 5402 if (os_snprintf_error(end - pos, ret)) 5403 return 0; 5404 pos += ret; 5405 } 5406 5407 if (mask & WPA_BSS_MASK_AGE) { 5408 struct os_reltime now; 5409 5410 os_get_reltime(&now); 5411 ret = os_snprintf(pos, end - pos, "age=%d\n", 5412 (int) (now.sec - bss->last_update.sec)); 5413 if (os_snprintf_error(end - pos, ret)) 5414 return 0; 5415 pos += ret; 5416 } 5417 5418 if (mask & WPA_BSS_MASK_IE) { 5419 ret = os_snprintf(pos, end - pos, "ie="); 5420 if (os_snprintf_error(end - pos, ret)) 5421 return 0; 5422 pos += ret; 5423 5424 ie = wpa_bss_ie_ptr(bss); 5425 for (i = 0; i < bss->ie_len; i++) { 5426 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 5427 if (os_snprintf_error(end - pos, ret)) 5428 return 0; 5429 pos += ret; 5430 } 5431 5432 ret = os_snprintf(pos, end - pos, "\n"); 5433 if (os_snprintf_error(end - pos, ret)) 5434 return 0; 5435 pos += ret; 5436 } 5437 5438 if (mask & WPA_BSS_MASK_FLAGS) { 5439 ret = os_snprintf(pos, end - pos, "flags="); 5440 if (os_snprintf_error(end - pos, ret)) 5441 return 0; 5442 pos += ret; 5443 5444 mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); 5445 5446 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 5447 if (ie) 5448 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 5449 2 + ie[1]); 5450 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 5451 if (ie2) 5452 pos = wpa_supplicant_ie_txt(pos, end, 5453 mesh ? "RSN" : "WPA2", ie2, 5454 2 + ie2[1]); 5455 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); 5456 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) { 5457 ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); 5458 if (os_snprintf_error(end - pos, ret)) 5459 return 0; 5460 pos += ret; 5461 } 5462 if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) { 5463 ret = os_snprintf(pos, end - pos, "[SAE-PK]"); 5464 if (os_snprintf_error(end - pos, ret)) 5465 return 0; 5466 pos += ret; 5467 } 5468 osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); 5469 if (osen_ie) 5470 pos = wpa_supplicant_ie_txt(pos, end, "OSEN", 5471 osen_ie, 2 + osen_ie[1]); 5472 owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); 5473 if (owe) { 5474 ret = os_snprintf( 5475 pos, end - pos, 5476 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); 5477 if (os_snprintf_error(end - pos, ret)) 5478 return 0; 5479 pos += ret; 5480 } 5481 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 5482 if (!ie && !ie2 && !osen_ie && 5483 (bss->caps & IEEE80211_CAP_PRIVACY)) { 5484 ret = os_snprintf(pos, end - pos, "[WEP]"); 5485 if (os_snprintf_error(end - pos, ret)) 5486 return 0; 5487 pos += ret; 5488 } 5489 5490 if (mesh) { 5491 ret = os_snprintf(pos, end - pos, "[MESH]"); 5492 if (os_snprintf_error(end - pos, ret)) 5493 return 0; 5494 pos += ret; 5495 } 5496 5497 if (bss_is_dmg(bss)) { 5498 const char *s; 5499 ret = os_snprintf(pos, end - pos, "[DMG]"); 5500 if (os_snprintf_error(end - pos, ret)) 5501 return 0; 5502 pos += ret; 5503 switch (bss->caps & IEEE80211_CAP_DMG_MASK) { 5504 case IEEE80211_CAP_DMG_IBSS: 5505 s = "[IBSS]"; 5506 break; 5507 case IEEE80211_CAP_DMG_AP: 5508 s = "[ESS]"; 5509 break; 5510 case IEEE80211_CAP_DMG_PBSS: 5511 s = "[PBSS]"; 5512 break; 5513 default: 5514 s = ""; 5515 break; 5516 } 5517 ret = os_snprintf(pos, end - pos, "%s", s); 5518 if (os_snprintf_error(end - pos, ret)) 5519 return 0; 5520 pos += ret; 5521 } else { 5522 if (bss->caps & IEEE80211_CAP_IBSS) { 5523 ret = os_snprintf(pos, end - pos, "[IBSS]"); 5524 if (os_snprintf_error(end - pos, ret)) 5525 return 0; 5526 pos += ret; 5527 } 5528 if (bss->caps & IEEE80211_CAP_ESS) { 5529 ret = os_snprintf(pos, end - pos, "[ESS]"); 5530 if (os_snprintf_error(end - pos, ret)) 5531 return 0; 5532 pos += ret; 5533 } 5534 } 5535 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || 5536 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { 5537 ret = os_snprintf(pos, end - pos, "[P2P]"); 5538 if (os_snprintf_error(end - pos, ret)) 5539 return 0; 5540 pos += ret; 5541 } 5542 #ifdef CONFIG_HS20 5543 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 5544 ret = os_snprintf(pos, end - pos, "[HS20]"); 5545 if (os_snprintf_error(end - pos, ret)) 5546 return 0; 5547 pos += ret; 5548 } 5549 #endif /* CONFIG_HS20 */ 5550 #ifdef CONFIG_FILS 5551 if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { 5552 ret = os_snprintf(pos, end - pos, "[FILS]"); 5553 if (os_snprintf_error(end - pos, ret)) 5554 return 0; 5555 pos += ret; 5556 } 5557 #endif /* CONFIG_FILS */ 5558 #ifdef CONFIG_FST 5559 if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { 5560 ret = os_snprintf(pos, end - pos, "[FST]"); 5561 if (os_snprintf_error(end - pos, ret)) 5562 return 0; 5563 pos += ret; 5564 } 5565 #endif /* CONFIG_FST */ 5566 if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { 5567 ret = os_snprintf(pos, end - pos, "[UTF-8]"); 5568 if (os_snprintf_error(end - pos, ret)) 5569 return 0; 5570 pos += ret; 5571 } 5572 5573 ret = os_snprintf(pos, end - pos, "\n"); 5574 if (os_snprintf_error(end - pos, ret)) 5575 return 0; 5576 pos += ret; 5577 } 5578 5579 if (mask & WPA_BSS_MASK_SSID) { 5580 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 5581 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 5582 if (os_snprintf_error(end - pos, ret)) 5583 return 0; 5584 pos += ret; 5585 } 5586 5587 #ifdef CONFIG_WPS 5588 if (mask & WPA_BSS_MASK_WPS_SCAN) { 5589 ie = wpa_bss_ie_ptr(bss); 5590 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 5591 if (ret >= end - pos) 5592 return 0; 5593 if (ret > 0) 5594 pos += ret; 5595 } 5596 #endif /* CONFIG_WPS */ 5597 5598 #ifdef CONFIG_P2P 5599 if (mask & WPA_BSS_MASK_P2P_SCAN) { 5600 ie = wpa_bss_ie_ptr(bss); 5601 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 5602 if (ret >= end - pos) 5603 return 0; 5604 if (ret > 0) 5605 pos += ret; 5606 } 5607 #endif /* CONFIG_P2P */ 5608 5609 #ifdef CONFIG_WIFI_DISPLAY 5610 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 5611 struct wpabuf *wfd; 5612 5613 ie = wpa_bss_ie_ptr(bss); 5614 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 5615 WFD_IE_VENDOR_TYPE); 5616 if (wfd) { 5617 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 5618 if (os_snprintf_error(end - pos, ret)) { 5619 wpabuf_free(wfd); 5620 return 0; 5621 } 5622 pos += ret; 5623 5624 pos += wpa_snprintf_hex(pos, end - pos, 5625 wpabuf_head(wfd), 5626 wpabuf_len(wfd)); 5627 wpabuf_free(wfd); 5628 5629 ret = os_snprintf(pos, end - pos, "\n"); 5630 if (os_snprintf_error(end - pos, ret)) 5631 return 0; 5632 pos += ret; 5633 } 5634 } 5635 #endif /* CONFIG_WIFI_DISPLAY */ 5636 5637 #ifdef CONFIG_INTERWORKING 5638 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 5639 struct wpa_bss_anqp *anqp = bss->anqp; 5640 struct wpa_bss_anqp_elem *elem; 5641 5642 pos = anqp_add_hex(pos, end, "anqp_capability_list", 5643 anqp->capability_list); 5644 pos = anqp_add_hex(pos, end, "anqp_venue_name", 5645 anqp->venue_name); 5646 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 5647 anqp->network_auth_type); 5648 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 5649 anqp->roaming_consortium); 5650 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 5651 anqp->ip_addr_type_availability); 5652 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 5653 anqp->nai_realm); 5654 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 5655 pos = anqp_add_hex(pos, end, "anqp_domain_name", 5656 anqp->domain_name); 5657 pos = anqp_add_hex(pos, end, "anqp_fils_realm_info", 5658 anqp->fils_realm_info); 5659 #ifdef CONFIG_HS20 5660 pos = anqp_add_hex(pos, end, "hs20_capability_list", 5661 anqp->hs20_capability_list); 5662 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 5663 anqp->hs20_operator_friendly_name); 5664 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 5665 anqp->hs20_wan_metrics); 5666 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 5667 anqp->hs20_connection_capability); 5668 pos = anqp_add_hex(pos, end, "hs20_operating_class", 5669 anqp->hs20_operating_class); 5670 pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", 5671 anqp->hs20_osu_providers_list); 5672 pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", 5673 anqp->hs20_operator_icon_metadata); 5674 pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", 5675 anqp->hs20_osu_providers_nai_list); 5676 #endif /* CONFIG_HS20 */ 5677 5678 dl_list_for_each(elem, &anqp->anqp_elems, 5679 struct wpa_bss_anqp_elem, list) { 5680 char title[20]; 5681 5682 os_snprintf(title, sizeof(title), "anqp[%u]", 5683 elem->infoid); 5684 pos = anqp_add_hex(pos, end, title, elem->payload); 5685 if (elem->protected_response) { 5686 ret = os_snprintf(pos, end - pos, 5687 "protected-anqp-info[%u]=1\n", 5688 elem->infoid); 5689 if (os_snprintf_error(end - pos, ret)) 5690 return 0; 5691 pos += ret; 5692 } 5693 } 5694 } 5695 #endif /* CONFIG_INTERWORKING */ 5696 5697 #ifdef CONFIG_MESH 5698 if (mask & WPA_BSS_MASK_MESH_SCAN) { 5699 ie = wpa_bss_ie_ptr(bss); 5700 ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); 5701 if (ret >= end - pos) 5702 return 0; 5703 if (ret > 0) 5704 pos += ret; 5705 } 5706 #endif /* CONFIG_MESH */ 5707 5708 if (mask & WPA_BSS_MASK_SNR) { 5709 ret = os_snprintf(pos, end - pos, "snr=%d\n", bss->snr); 5710 if (os_snprintf_error(end - pos, ret)) 5711 return 0; 5712 pos += ret; 5713 } 5714 5715 if (mask & WPA_BSS_MASK_EST_THROUGHPUT) { 5716 ret = os_snprintf(pos, end - pos, "est_throughput=%d\n", 5717 bss->est_throughput); 5718 if (os_snprintf_error(end - pos, ret)) 5719 return 0; 5720 pos += ret; 5721 } 5722 5723 #ifdef CONFIG_FST 5724 if (mask & WPA_BSS_MASK_FST) { 5725 ret = fst_ctrl_iface_mb_info(bss->bssid, pos, end - pos); 5726 if (ret < 0 || ret >= end - pos) 5727 return 0; 5728 pos += ret; 5729 } 5730 #endif /* CONFIG_FST */ 5731 5732 if (mask & WPA_BSS_MASK_UPDATE_IDX) { 5733 ret = os_snprintf(pos, end - pos, "update_idx=%u\n", 5734 bss->last_update_idx); 5735 if (os_snprintf_error(end - pos, ret)) 5736 return 0; 5737 pos += ret; 5738 } 5739 5740 if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) { 5741 ret = os_snprintf(pos, end - pos, "beacon_ie="); 5742 if (os_snprintf_error(end - pos, ret)) 5743 return 0; 5744 pos += ret; 5745 5746 ie = wpa_bss_ie_ptr(bss); 5747 ie += bss->ie_len; 5748 for (i = 0; i < bss->beacon_ie_len; i++) { 5749 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 5750 if (os_snprintf_error(end - pos, ret)) 5751 return 0; 5752 pos += ret; 5753 } 5754 5755 ret = os_snprintf(pos, end - pos, "\n"); 5756 if (os_snprintf_error(end - pos, ret)) 5757 return 0; 5758 pos += ret; 5759 } 5760 5761 #ifdef CONFIG_FILS 5762 if (mask & WPA_BSS_MASK_FILS_INDICATION) { 5763 ret = print_fils_indication(bss, pos, end); 5764 pos += ret; 5765 } 5766 #endif /* CONFIG_FILS */ 5767 5768 if (!is_zero_ether_addr(bss->mld_addr) && 5769 (mask & WPA_BSS_MASK_AP_MLD_ADDR)) { 5770 ret = os_snprintf(pos, end - pos, 5771 "ap_mld_addr=" MACSTR "\n", 5772 MAC2STR(bss->mld_addr)); 5773 if (os_snprintf_error(end - pos, ret)) 5774 return 0; 5775 pos += ret; 5776 } 5777 5778 if (mask & WPA_BSS_MASK_RNR) 5779 pos += print_rnr(bss, pos, end); 5780 5781 if (mask & WPA_BSS_MASK_ML) 5782 pos += print_ml(bss, pos, end); 5783 5784 if (mask & WPA_BSS_MASK_DELIM) { 5785 ret = os_snprintf(pos, end - pos, "====\n"); 5786 if (os_snprintf_error(end - pos, ret)) 5787 return 0; 5788 pos += ret; 5789 } 5790 5791 return pos - buf; 5792 } 5793 5794 5795 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 5796 const char *cmd, char *buf, 5797 size_t buflen) 5798 { 5799 u8 bssid[ETH_ALEN]; 5800 size_t i; 5801 struct wpa_bss *bss; 5802 struct wpa_bss *bsslast = NULL; 5803 struct dl_list *next; 5804 int ret = 0; 5805 int len; 5806 char *ctmp, *end = buf + buflen; 5807 unsigned long mask = WPA_BSS_MASK_ALL; 5808 5809 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 5810 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 5811 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 5812 list_id); 5813 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 5814 list_id); 5815 } else { /* N1-N2 */ 5816 unsigned int id1, id2; 5817 5818 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 5819 wpa_printf(MSG_INFO, "Wrong BSS range " 5820 "format"); 5821 return 0; 5822 } 5823 5824 if (*(cmd + 6) == '-') 5825 id1 = 0; 5826 else 5827 id1 = atoi(cmd + 6); 5828 ctmp++; 5829 if (*ctmp >= '0' && *ctmp <= '9') 5830 id2 = atoi(ctmp); 5831 else 5832 id2 = (unsigned int) -1; 5833 bss = wpa_bss_get_id_range(wpa_s, id1, id2); 5834 if (id2 == (unsigned int) -1) 5835 bsslast = dl_list_last(&wpa_s->bss_id, 5836 struct wpa_bss, 5837 list_id); 5838 else { 5839 bsslast = wpa_bss_get_id(wpa_s, id2); 5840 if (bsslast == NULL && bss && id2 > id1) { 5841 struct wpa_bss *tmp = bss; 5842 for (;;) { 5843 next = tmp->list_id.next; 5844 if (next == &wpa_s->bss_id) 5845 break; 5846 tmp = dl_list_entry( 5847 next, struct wpa_bss, 5848 list_id); 5849 if (tmp->id > id2) 5850 break; 5851 bsslast = tmp; 5852 } 5853 } 5854 } 5855 } 5856 } else if (os_strncmp(cmd, "FIRST", 5) == 0) 5857 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 5858 else if (os_strncmp(cmd, "LAST", 4) == 0) 5859 bss = dl_list_last(&wpa_s->bss_id, struct wpa_bss, list_id); 5860 else if (os_strncmp(cmd, "ID-", 3) == 0) { 5861 i = atoi(cmd + 3); 5862 bss = wpa_bss_get_id(wpa_s, i); 5863 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 5864 i = atoi(cmd + 5); 5865 bss = wpa_bss_get_id(wpa_s, i); 5866 if (bss) { 5867 next = bss->list_id.next; 5868 if (next == &wpa_s->bss_id) 5869 bss = NULL; 5870 else 5871 bss = dl_list_entry(next, struct wpa_bss, 5872 list_id); 5873 } 5874 } else if (os_strncmp(cmd, "CURRENT", 7) == 0) { 5875 bss = wpa_s->current_bss; 5876 #ifdef CONFIG_P2P 5877 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 5878 if (hwaddr_aton(cmd + 13, bssid) == 0) 5879 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 5880 else 5881 bss = NULL; 5882 #endif /* CONFIG_P2P */ 5883 } else if (hwaddr_aton(cmd, bssid) == 0) 5884 bss = wpa_bss_get_bssid(wpa_s, bssid); 5885 else { 5886 struct wpa_bss *tmp; 5887 i = atoi(cmd); 5888 bss = NULL; 5889 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 5890 { 5891 if (i == 0) { 5892 bss = tmp; 5893 break; 5894 } 5895 i--; 5896 } 5897 } 5898 5899 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 5900 mask = strtoul(ctmp + 5, NULL, 0x10); 5901 if (mask == 0) 5902 mask = WPA_BSS_MASK_ALL; 5903 } 5904 5905 if (bss == NULL) 5906 return 0; 5907 5908 if (bsslast == NULL) 5909 bsslast = bss; 5910 do { 5911 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 5912 ret += len; 5913 buf += len; 5914 buflen -= len; 5915 if (bss == bsslast) { 5916 if ((mask & WPA_BSS_MASK_DELIM) && len && 5917 (bss == dl_list_last(&wpa_s->bss_id, 5918 struct wpa_bss, list_id))) { 5919 int res; 5920 5921 res = os_snprintf(buf - 5, end - buf + 5, 5922 "####\n"); 5923 if (os_snprintf_error(end - buf + 5, res)) { 5924 wpa_printf(MSG_DEBUG, 5925 "Could not add end delim"); 5926 } 5927 } 5928 break; 5929 } 5930 next = bss->list_id.next; 5931 if (next == &wpa_s->bss_id) 5932 break; 5933 bss = dl_list_entry(next, struct wpa_bss, list_id); 5934 } while (bss && len); 5935 5936 return ret; 5937 } 5938 5939 5940 static int wpa_supplicant_ctrl_iface_ap_scan( 5941 struct wpa_supplicant *wpa_s, char *cmd) 5942 { 5943 int ap_scan = atoi(cmd); 5944 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 5945 } 5946 5947 5948 static int wpa_supplicant_ctrl_iface_scan_interval( 5949 struct wpa_supplicant *wpa_s, char *cmd) 5950 { 5951 int scan_int = atoi(cmd); 5952 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 5953 } 5954 5955 5956 static int wpa_supplicant_ctrl_iface_bss_expire_age( 5957 struct wpa_supplicant *wpa_s, char *cmd) 5958 { 5959 int expire_age = atoi(cmd); 5960 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 5961 } 5962 5963 5964 static int wpa_supplicant_ctrl_iface_bss_expire_count( 5965 struct wpa_supplicant *wpa_s, char *cmd) 5966 { 5967 int expire_count = atoi(cmd); 5968 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 5969 } 5970 5971 5972 static void wpa_supplicant_ctrl_iface_bss_flush( 5973 struct wpa_supplicant *wpa_s, char *cmd) 5974 { 5975 int flush_age = atoi(cmd); 5976 5977 if (flush_age == 0) 5978 wpa_bss_flush(wpa_s); 5979 else 5980 wpa_bss_flush_by_age(wpa_s, flush_age); 5981 } 5982 5983 5984 #ifdef CONFIG_TESTING_OPTIONS 5985 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 5986 { 5987 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 5988 /* MLME-DELETEKEYS.request */ 5989 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 5990 0, KEY_FLAG_GROUP); 5991 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 5992 0, KEY_FLAG_GROUP); 5993 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 5994 0, KEY_FLAG_GROUP); 5995 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 5996 0, KEY_FLAG_GROUP); 5997 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 5998 0, KEY_FLAG_GROUP); 5999 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 6000 0, KEY_FLAG_GROUP); 6001 6002 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, 6003 NULL, 0, KEY_FLAG_PAIRWISE); 6004 if (wpa_sm_ext_key_id(wpa_s->wpa)) 6005 wpa_drv_set_key(wpa_s, -1, WPA_ALG_NONE, wpa_s->bssid, 1, 0, 6006 NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); 6007 /* MLME-SETPROTECTION.request(None) */ 6008 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 6009 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 6010 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 6011 wpa_sm_drop_sa(wpa_s->wpa); 6012 } 6013 #endif /* CONFIG_TESTING_OPTIONS */ 6014 6015 6016 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 6017 char *addr) 6018 { 6019 #ifdef CONFIG_NO_SCAN_PROCESSING 6020 return -1; 6021 #else /* CONFIG_NO_SCAN_PROCESSING */ 6022 u8 bssid[ETH_ALEN]; 6023 struct wpa_bss *bss; 6024 struct wpa_ssid *ssid = wpa_s->current_ssid; 6025 struct wpa_radio_work *already_connecting; 6026 6027 if (hwaddr_aton(addr, bssid)) { 6028 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 6029 "address '%s'", addr); 6030 return -1; 6031 } 6032 6033 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 6034 6035 if (!ssid) { 6036 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 6037 "configuration known for the target AP"); 6038 return -1; 6039 } 6040 6041 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 6042 if (!bss) { 6043 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 6044 "from BSS table"); 6045 return -1; 6046 } 6047 6048 /* 6049 * TODO: Find best network configuration block from configuration to 6050 * allow roaming to other networks 6051 */ 6052 6053 already_connecting = radio_work_pending(wpa_s, "sme-connect"); 6054 wpa_s->reassociate = 1; 6055 wpa_supplicant_connect(wpa_s, bss, ssid); 6056 6057 /* 6058 * Indicate that an explicitly requested roam is in progress so scan 6059 * results that come in before the 'sme-connect' radio work gets 6060 * executed do not override the original connection attempt. 6061 */ 6062 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) 6063 wpa_s->roam_in_progress = true; 6064 6065 return 0; 6066 #endif /* CONFIG_NO_SCAN_PROCESSING */ 6067 } 6068 6069 6070 #ifdef CONFIG_P2P 6071 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 6072 { 6073 unsigned int timeout = atoi(cmd); 6074 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 6075 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 6076 u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL; 6077 char *pos; 6078 unsigned int search_delay; 6079 const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL; 6080 u8 seek_count = 0; 6081 int freq = 0; 6082 bool include_6ghz = false; 6083 6084 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6085 wpa_dbg(wpa_s, MSG_INFO, 6086 "Reject P2P_FIND since interface is disabled"); 6087 return -1; 6088 } 6089 6090 if (os_strstr(cmd, " include_6ghz")) 6091 include_6ghz = true; 6092 if (os_strstr(cmd, "type=social")) 6093 type = P2P_FIND_ONLY_SOCIAL; 6094 else if (os_strstr(cmd, "type=progressive")) 6095 type = P2P_FIND_PROGRESSIVE; 6096 6097 pos = os_strstr(cmd, "dev_id="); 6098 if (pos) { 6099 pos += 7; 6100 if (hwaddr_aton(pos, dev_id)) 6101 return -1; 6102 _dev_id = dev_id; 6103 } 6104 6105 pos = os_strstr(cmd, "dev_type="); 6106 if (pos) { 6107 pos += 9; 6108 if (wps_dev_type_str2bin(pos, dev_type) < 0) 6109 return -1; 6110 _dev_type = dev_type; 6111 } 6112 6113 pos = os_strstr(cmd, "delay="); 6114 if (pos) { 6115 pos += 6; 6116 search_delay = atoi(pos); 6117 } else 6118 search_delay = wpas_p2p_search_delay(wpa_s); 6119 6120 pos = os_strstr(cmd, "freq="); 6121 if (pos) { 6122 pos += 5; 6123 freq = atoi(pos); 6124 if (freq <= 0) 6125 return -1; 6126 } 6127 6128 /* Must be searched for last, because it adds nul termination */ 6129 pos = os_strstr(cmd, " seek="); 6130 if (pos) 6131 pos += 6; 6132 while (pos && seek_count < P2P_MAX_QUERY_HASH + 1) { 6133 char *term; 6134 6135 _seek[seek_count++] = pos; 6136 seek = _seek; 6137 term = os_strchr(pos, ' '); 6138 if (!term) 6139 break; 6140 *term = '\0'; 6141 pos = os_strstr(term + 1, "seek="); 6142 if (pos) 6143 pos += 5; 6144 } 6145 if (seek_count > P2P_MAX_QUERY_HASH) { 6146 seek[0] = NULL; 6147 seek_count = 1; 6148 } 6149 6150 return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type, 6151 _dev_id, search_delay, seek_count, seek, freq, 6152 include_6ghz); 6153 } 6154 6155 6156 static int p2ps_ctrl_parse_cpt_priority(const char *pos, u8 *cpt) 6157 { 6158 const char *last = NULL; 6159 const char *token; 6160 long int token_len; 6161 unsigned int i; 6162 6163 /* Expected predefined CPT names delimited by ':' */ 6164 for (i = 0; (token = cstr_token(pos, ": \t", &last)); i++) { 6165 if (i >= P2PS_FEATURE_CAPAB_CPT_MAX) { 6166 wpa_printf(MSG_ERROR, 6167 "P2PS: CPT name list is too long, expected up to %d names", 6168 P2PS_FEATURE_CAPAB_CPT_MAX); 6169 cpt[0] = 0; 6170 return -1; 6171 } 6172 6173 token_len = last - token; 6174 6175 if (token_len == 3 && 6176 os_memcmp(token, "UDP", token_len) == 0) { 6177 cpt[i] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6178 } else if (token_len == 3 && 6179 os_memcmp(token, "MAC", token_len) == 0) { 6180 cpt[i] = P2PS_FEATURE_CAPAB_MAC_TRANSPORT; 6181 } else { 6182 wpa_printf(MSG_ERROR, 6183 "P2PS: Unsupported CPT name '%s'", token); 6184 cpt[0] = 0; 6185 return -1; 6186 } 6187 6188 if (isblank((unsigned char) *last)) { 6189 i++; 6190 break; 6191 } 6192 } 6193 cpt[i] = 0; 6194 return 0; 6195 } 6196 6197 6198 static struct p2ps_provision * p2p_parse_asp_provision_cmd(const char *cmd) 6199 { 6200 struct p2ps_provision *p2ps_prov; 6201 char *pos; 6202 size_t info_len = 0; 6203 char *info = NULL; 6204 u8 role = P2PS_SETUP_NONE; 6205 long long unsigned val; 6206 int i; 6207 6208 pos = os_strstr(cmd, "info="); 6209 if (pos) { 6210 pos += 5; 6211 info_len = os_strlen(pos); 6212 6213 if (info_len) { 6214 info = os_malloc(info_len + 1); 6215 if (info) { 6216 info_len = utf8_unescape(pos, info_len, 6217 info, info_len + 1); 6218 } else 6219 info_len = 0; 6220 } 6221 } 6222 6223 p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + info_len + 1); 6224 if (p2ps_prov == NULL) { 6225 os_free(info); 6226 return NULL; 6227 } 6228 6229 if (info) { 6230 os_memcpy(p2ps_prov->info, info, info_len); 6231 p2ps_prov->info[info_len] = '\0'; 6232 os_free(info); 6233 } 6234 6235 pos = os_strstr(cmd, "status="); 6236 if (pos) 6237 p2ps_prov->status = atoi(pos + 7); 6238 else 6239 p2ps_prov->status = -1; 6240 6241 pos = os_strstr(cmd, "adv_id="); 6242 if (!pos || sscanf(pos + 7, "%llx", &val) != 1 || val > 0xffffffffULL) 6243 goto invalid_args; 6244 p2ps_prov->adv_id = val; 6245 6246 pos = os_strstr(cmd, "method="); 6247 if (pos) 6248 p2ps_prov->method = strtol(pos + 7, NULL, 16); 6249 else 6250 p2ps_prov->method = 0; 6251 6252 pos = os_strstr(cmd, "session="); 6253 if (!pos || sscanf(pos + 8, "%llx", &val) != 1 || val > 0xffffffffULL) 6254 goto invalid_args; 6255 p2ps_prov->session_id = val; 6256 6257 pos = os_strstr(cmd, "adv_mac="); 6258 if (!pos || hwaddr_aton(pos + 8, p2ps_prov->adv_mac)) 6259 goto invalid_args; 6260 6261 pos = os_strstr(cmd, "session_mac="); 6262 if (!pos || hwaddr_aton(pos + 12, p2ps_prov->session_mac)) 6263 goto invalid_args; 6264 6265 pos = os_strstr(cmd, "cpt="); 6266 if (pos) { 6267 if (p2ps_ctrl_parse_cpt_priority(pos + 4, 6268 p2ps_prov->cpt_priority)) 6269 goto invalid_args; 6270 } else { 6271 p2ps_prov->cpt_priority[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6272 } 6273 6274 for (i = 0; p2ps_prov->cpt_priority[i]; i++) 6275 p2ps_prov->cpt_mask |= p2ps_prov->cpt_priority[i]; 6276 6277 /* force conncap with tstCap (no validity checks) */ 6278 pos = os_strstr(cmd, "tstCap="); 6279 if (pos) { 6280 role = strtol(pos + 7, NULL, 16); 6281 } else { 6282 pos = os_strstr(cmd, "role="); 6283 if (pos) { 6284 role = strtol(pos + 5, NULL, 16); 6285 if (role != P2PS_SETUP_CLIENT && 6286 role != P2PS_SETUP_GROUP_OWNER) 6287 role = P2PS_SETUP_NONE; 6288 } 6289 } 6290 p2ps_prov->role = role; 6291 6292 return p2ps_prov; 6293 6294 invalid_args: 6295 os_free(p2ps_prov); 6296 return NULL; 6297 } 6298 6299 6300 static int p2p_ctrl_asp_provision_resp(struct wpa_supplicant *wpa_s, char *cmd) 6301 { 6302 u8 addr[ETH_ALEN]; 6303 struct p2ps_provision *p2ps_prov; 6304 char *pos; 6305 6306 /* <addr> id=<adv_id> [role=<conncap>] [info=<infodata>] */ 6307 6308 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 6309 6310 if (hwaddr_aton(cmd, addr)) 6311 return -1; 6312 6313 pos = cmd + 17; 6314 if (*pos != ' ') 6315 return -1; 6316 6317 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 6318 if (!p2ps_prov) 6319 return -1; 6320 6321 if (p2ps_prov->status < 0) { 6322 os_free(p2ps_prov); 6323 return -1; 6324 } 6325 6326 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 6327 p2ps_prov); 6328 } 6329 6330 6331 static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd) 6332 { 6333 u8 addr[ETH_ALEN]; 6334 struct p2ps_provision *p2ps_prov; 6335 char *pos; 6336 6337 /* <addr> id=<adv_id> adv_mac=<adv_mac> conncap=<conncap> 6338 * session=<ses_id> mac=<ses_mac> [info=<infodata>] 6339 */ 6340 6341 wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd); 6342 if (hwaddr_aton(cmd, addr)) 6343 return -1; 6344 6345 pos = cmd + 17; 6346 if (*pos != ' ') 6347 return -1; 6348 6349 p2ps_prov = p2p_parse_asp_provision_cmd(pos); 6350 if (!p2ps_prov) 6351 return -1; 6352 6353 p2ps_prov->pd_seeker = 1; 6354 6355 return wpas_p2p_prov_disc(wpa_s, addr, NULL, WPAS_P2P_PD_FOR_ASP, 6356 p2ps_prov); 6357 } 6358 6359 6360 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 6361 char *buf, size_t buflen) 6362 { 6363 u8 addr[ETH_ALEN]; 6364 char *pos, *pos2; 6365 char *pin = NULL; 6366 enum p2p_wps_method wps_method; 6367 int new_pin; 6368 int ret; 6369 int persistent_group, persistent_id = -1; 6370 int join; 6371 int auth; 6372 int automatic; 6373 int go_intent = -1; 6374 int freq = 0; 6375 int pd; 6376 int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; 6377 int edmg; 6378 u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; 6379 size_t group_ssid_len = 0; 6380 int he; 6381 bool allow_6ghz; 6382 6383 if (!wpa_s->global->p2p_init_wpa_s) 6384 return -1; 6385 if (wpa_s->global->p2p_init_wpa_s != wpa_s) { 6386 wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s", 6387 wpa_s->global->p2p_init_wpa_s->ifname); 6388 wpa_s = wpa_s->global->p2p_init_wpa_s; 6389 } 6390 6391 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] 6392 * [persistent|persistent=<network id>] 6393 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 6394 * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */ 6395 6396 if (hwaddr_aton(cmd, addr)) 6397 return -1; 6398 6399 pos = cmd + 17; 6400 if (*pos != ' ') 6401 return -1; 6402 pos++; 6403 6404 persistent_group = os_strstr(pos, " persistent") != NULL; 6405 pos2 = os_strstr(pos, " persistent="); 6406 if (pos2) { 6407 struct wpa_ssid *ssid; 6408 persistent_id = atoi(pos2 + 12); 6409 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 6410 if (ssid == NULL || ssid->disabled != 2 || 6411 ssid->mode != WPAS_MODE_P2P_GO) { 6412 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 6413 "SSID id=%d for persistent P2P group (GO)", 6414 persistent_id); 6415 return -1; 6416 } 6417 } 6418 join = os_strstr(pos, " join") != NULL; 6419 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL; 6420 auth = os_strstr(pos, " auth") != NULL; 6421 automatic = os_strstr(pos, " auto") != NULL; 6422 pd = os_strstr(pos, " provdisc") != NULL; 6423 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 6424 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 6425 vht; 6426 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 6427 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; 6428 6429 pos2 = os_strstr(pos, " go_intent="); 6430 if (pos2) { 6431 pos2 += 11; 6432 go_intent = atoi(pos2); 6433 if (go_intent < 0 || go_intent > 15) 6434 return -1; 6435 } 6436 6437 pos2 = os_strstr(pos, " freq="); 6438 if (pos2) { 6439 pos2 += 6; 6440 freq = atoi(pos2); 6441 if (freq <= 0) 6442 return -1; 6443 } 6444 6445 pos2 = os_strstr(pos, " freq2="); 6446 if (pos2) 6447 freq2 = atoi(pos2 + 7); 6448 6449 pos2 = os_strstr(pos, " max_oper_chwidth="); 6450 if (pos2) 6451 chwidth = atoi(pos2 + 18); 6452 6453 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 6454 if (max_oper_chwidth < 0) 6455 return -1; 6456 6457 if (allow_6ghz && chwidth == 40) 6458 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 6459 6460 pos2 = os_strstr(pos, " ssid="); 6461 if (pos2) { 6462 char *end; 6463 6464 pos2 += 6; 6465 end = os_strchr(pos2, ' '); 6466 if (!end) 6467 group_ssid_len = os_strlen(pos2) / 2; 6468 else 6469 group_ssid_len = (end - pos2) / 2; 6470 if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN || 6471 hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0) 6472 return -1; 6473 group_ssid = _group_ssid; 6474 } 6475 6476 if (os_strncmp(pos, "pin", 3) == 0) { 6477 /* Request random PIN (to be displayed) and enable the PIN */ 6478 wps_method = WPS_PIN_DISPLAY; 6479 } else if (os_strncmp(pos, "pbc", 3) == 0) { 6480 wps_method = WPS_PBC; 6481 } else if (os_strstr(pos, "p2ps") != NULL) { 6482 wps_method = WPS_P2PS; 6483 } else { 6484 pin = pos; 6485 pos = os_strchr(pin, ' '); 6486 wps_method = WPS_PIN_KEYPAD; 6487 if (pos) { 6488 *pos++ = '\0'; 6489 if (os_strncmp(pos, "display", 7) == 0) 6490 wps_method = WPS_PIN_DISPLAY; 6491 } 6492 if (!wps_pin_str_valid(pin)) { 6493 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 6494 return 17; 6495 } 6496 } 6497 6498 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 6499 persistent_group, automatic, join, 6500 auth, go_intent, freq, freq2, persistent_id, 6501 pd, ht40, vht, max_oper_chwidth, he, edmg, 6502 group_ssid, group_ssid_len, allow_6ghz); 6503 if (new_pin == -2) { 6504 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 6505 return 25; 6506 } 6507 if (new_pin == -3) { 6508 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 6509 return 25; 6510 } 6511 if (new_pin < 0) 6512 return -1; 6513 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 6514 ret = os_snprintf(buf, buflen, "%08d", new_pin); 6515 if (os_snprintf_error(buflen, ret)) 6516 return -1; 6517 return ret; 6518 } 6519 6520 os_memcpy(buf, "OK\n", 3); 6521 return 3; 6522 } 6523 6524 6525 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 6526 { 6527 unsigned int timeout = atoi(cmd); 6528 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 6529 wpa_dbg(wpa_s, MSG_INFO, 6530 "Reject P2P_LISTEN since interface is disabled"); 6531 return -1; 6532 } 6533 return wpas_p2p_listen(wpa_s, timeout); 6534 } 6535 6536 6537 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 6538 { 6539 u8 addr[ETH_ALEN]; 6540 char *pos; 6541 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 6542 6543 /* <addr> <config method> [join|auto] */ 6544 6545 if (hwaddr_aton(cmd, addr)) 6546 return -1; 6547 6548 pos = cmd + 17; 6549 if (*pos != ' ') 6550 return -1; 6551 pos++; 6552 6553 if (os_strstr(pos, " join") != NULL) 6554 use = WPAS_P2P_PD_FOR_JOIN; 6555 else if (os_strstr(pos, " auto") != NULL) 6556 use = WPAS_P2P_PD_AUTO; 6557 6558 return wpas_p2p_prov_disc(wpa_s, addr, pos, use, NULL); 6559 } 6560 6561 6562 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 6563 size_t buflen) 6564 { 6565 struct wpa_ssid *ssid = wpa_s->current_ssid; 6566 6567 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 6568 ssid->passphrase == NULL) 6569 return -1; 6570 6571 os_strlcpy(buf, ssid->passphrase, buflen); 6572 return os_strlen(buf); 6573 } 6574 6575 6576 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 6577 char *buf, size_t buflen) 6578 { 6579 u64 ref; 6580 int res; 6581 u8 dst_buf[ETH_ALEN], *dst; 6582 struct wpabuf *tlvs; 6583 char *pos; 6584 size_t len; 6585 6586 if (hwaddr_aton(cmd, dst_buf)) 6587 return -1; 6588 dst = dst_buf; 6589 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 6590 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 6591 dst = NULL; 6592 pos = cmd + 17; 6593 if (*pos != ' ') 6594 return -1; 6595 pos++; 6596 6597 if (os_strncmp(pos, "upnp ", 5) == 0) { 6598 u8 version; 6599 pos += 5; 6600 if (hexstr2bin(pos, &version, 1) < 0) 6601 return -1; 6602 pos += 2; 6603 if (*pos != ' ') 6604 return -1; 6605 pos++; 6606 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 6607 #ifdef CONFIG_WIFI_DISPLAY 6608 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 6609 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 6610 #endif /* CONFIG_WIFI_DISPLAY */ 6611 } else if (os_strncmp(pos, "asp ", 4) == 0) { 6612 char *svc_str; 6613 char *svc_info = NULL; 6614 u32 id; 6615 6616 pos += 4; 6617 if (sscanf(pos, "%x", &id) != 1 || id > 0xff) 6618 return -1; 6619 6620 pos = os_strchr(pos, ' '); 6621 if (pos == NULL || pos[1] == '\0' || pos[1] == ' ') 6622 return -1; 6623 6624 svc_str = pos + 1; 6625 6626 pos = os_strchr(svc_str, ' '); 6627 6628 if (pos) 6629 *pos++ = '\0'; 6630 6631 /* All remaining data is the svc_info string */ 6632 if (pos && pos[0] && pos[0] != ' ') { 6633 len = os_strlen(pos); 6634 6635 /* Unescape in place */ 6636 len = utf8_unescape(pos, len, pos, len); 6637 if (len > 0xff) 6638 return -1; 6639 6640 svc_info = pos; 6641 } 6642 6643 ref = wpas_p2p_sd_request_asp(wpa_s, dst, (u8) id, 6644 svc_str, svc_info); 6645 } else { 6646 len = os_strlen(pos); 6647 if (len & 1) 6648 return -1; 6649 len /= 2; 6650 tlvs = wpabuf_alloc(len); 6651 if (tlvs == NULL) 6652 return -1; 6653 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 6654 wpabuf_free(tlvs); 6655 return -1; 6656 } 6657 6658 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 6659 wpabuf_free(tlvs); 6660 } 6661 if (ref == 0) 6662 return -1; 6663 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 6664 if (os_snprintf_error(buflen, res)) 6665 return -1; 6666 return res; 6667 } 6668 6669 6670 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 6671 char *cmd) 6672 { 6673 long long unsigned val; 6674 u64 req; 6675 if (sscanf(cmd, "%llx", &val) != 1) 6676 return -1; 6677 req = val; 6678 return wpas_p2p_sd_cancel_request(wpa_s, req); 6679 } 6680 6681 6682 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 6683 { 6684 int freq; 6685 u8 dst[ETH_ALEN]; 6686 u8 dialog_token; 6687 struct wpabuf *resp_tlvs; 6688 char *pos, *pos2; 6689 size_t len; 6690 6691 pos = os_strchr(cmd, ' '); 6692 if (pos == NULL) 6693 return -1; 6694 *pos++ = '\0'; 6695 freq = atoi(cmd); 6696 if (freq == 0) 6697 return -1; 6698 6699 if (hwaddr_aton(pos, dst)) 6700 return -1; 6701 pos += 17; 6702 if (*pos != ' ') 6703 return -1; 6704 pos++; 6705 6706 pos2 = os_strchr(pos, ' '); 6707 if (pos2 == NULL) 6708 return -1; 6709 *pos2++ = '\0'; 6710 dialog_token = atoi(pos); 6711 6712 len = os_strlen(pos2); 6713 if (len & 1) 6714 return -1; 6715 len /= 2; 6716 resp_tlvs = wpabuf_alloc(len); 6717 if (resp_tlvs == NULL) 6718 return -1; 6719 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 6720 wpabuf_free(resp_tlvs); 6721 return -1; 6722 } 6723 6724 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 6725 wpabuf_free(resp_tlvs); 6726 return 0; 6727 } 6728 6729 6730 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 6731 char *cmd) 6732 { 6733 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 6734 return -1; 6735 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 6736 return 0; 6737 } 6738 6739 6740 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 6741 char *cmd) 6742 { 6743 char *pos; 6744 size_t len; 6745 struct wpabuf *query, *resp; 6746 int ret; 6747 6748 pos = os_strchr(cmd, ' '); 6749 if (pos == NULL) 6750 return -1; 6751 *pos++ = '\0'; 6752 6753 len = os_strlen(cmd); 6754 if (len & 1) 6755 return -1; 6756 len /= 2; 6757 query = wpabuf_alloc(len); 6758 if (query == NULL) 6759 return -1; 6760 ret = hexstr2bin(cmd, wpabuf_put(query, len), len); 6761 if (ret < 0) 6762 goto err_query; 6763 ret = -1; 6764 len = os_strlen(pos); 6765 if (len & 1) 6766 goto err_query; 6767 len /= 2; 6768 resp = wpabuf_alloc(len); 6769 if (!resp) 6770 goto err_query; 6771 ret = hexstr2bin(pos, wpabuf_put(resp, len), len); 6772 if (ret < 0) 6773 goto err_resp; 6774 6775 ret = wpas_p2p_service_add_bonjour(wpa_s, query, resp); 6776 6777 err_resp: 6778 wpabuf_free(resp); 6779 err_query: 6780 wpabuf_free(query); 6781 return ret; 6782 } 6783 6784 6785 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6786 { 6787 char *pos; 6788 u8 version; 6789 6790 pos = os_strchr(cmd, ' '); 6791 if (pos == NULL) 6792 return -1; 6793 *pos++ = '\0'; 6794 6795 if (hexstr2bin(cmd, &version, 1) < 0) 6796 return -1; 6797 6798 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 6799 } 6800 6801 6802 static int p2p_ctrl_service_add_asp(struct wpa_supplicant *wpa_s, 6803 u8 replace, char *cmd) 6804 { 6805 char *pos; 6806 char *adv_str; 6807 u32 auto_accept, adv_id, svc_state, config_methods; 6808 char *svc_info = NULL; 6809 char *cpt_prio_str; 6810 u8 cpt_prio[P2PS_FEATURE_CAPAB_CPT_MAX + 1]; 6811 6812 pos = os_strchr(cmd, ' '); 6813 if (pos == NULL) 6814 return -1; 6815 *pos++ = '\0'; 6816 6817 /* Auto-Accept value is mandatory, and must be one of the 6818 * single values (0, 1, 2, 4) */ 6819 auto_accept = atoi(cmd); 6820 switch (auto_accept) { 6821 case P2PS_SETUP_NONE: /* No auto-accept */ 6822 case P2PS_SETUP_NEW: 6823 case P2PS_SETUP_CLIENT: 6824 case P2PS_SETUP_GROUP_OWNER: 6825 break; 6826 default: 6827 return -1; 6828 } 6829 6830 /* Advertisement ID is mandatory */ 6831 cmd = pos; 6832 pos = os_strchr(cmd, ' '); 6833 if (pos == NULL) 6834 return -1; 6835 *pos++ = '\0'; 6836 6837 /* Handle Adv_ID == 0 (wildcard "org.wi-fi.wfds") internally. */ 6838 if (sscanf(cmd, "%x", &adv_id) != 1 || adv_id == 0) 6839 return -1; 6840 6841 /* Only allow replacements if exist, and adds if not */ 6842 if (wpas_p2p_service_p2ps_id_exists(wpa_s, adv_id)) { 6843 if (!replace) 6844 return -1; 6845 } else { 6846 if (replace) 6847 return -1; 6848 } 6849 6850 /* svc_state between 0 - 0xff is mandatory */ 6851 if (sscanf(pos, "%x", &svc_state) != 1 || svc_state > 0xff) 6852 return -1; 6853 6854 pos = os_strchr(pos, ' '); 6855 if (pos == NULL) 6856 return -1; 6857 6858 /* config_methods is mandatory */ 6859 pos++; 6860 if (sscanf(pos, "%x", &config_methods) != 1) 6861 return -1; 6862 6863 if (!(config_methods & 6864 (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS))) 6865 return -1; 6866 6867 pos = os_strchr(pos, ' '); 6868 if (pos == NULL) 6869 return -1; 6870 6871 pos++; 6872 adv_str = pos; 6873 6874 /* Advertisement string is mandatory */ 6875 if (!pos[0] || pos[0] == ' ') 6876 return -1; 6877 6878 /* Terminate svc string */ 6879 pos = os_strchr(pos, ' '); 6880 if (pos != NULL) 6881 *pos++ = '\0'; 6882 6883 cpt_prio_str = (pos && pos[0]) ? os_strstr(pos, "cpt=") : NULL; 6884 if (cpt_prio_str) { 6885 pos = os_strchr(pos, ' '); 6886 if (pos != NULL) 6887 *pos++ = '\0'; 6888 6889 if (p2ps_ctrl_parse_cpt_priority(cpt_prio_str + 4, cpt_prio)) 6890 return -1; 6891 } else { 6892 cpt_prio[0] = P2PS_FEATURE_CAPAB_UDP_TRANSPORT; 6893 cpt_prio[1] = 0; 6894 } 6895 6896 /* Service and Response Information are optional */ 6897 if (pos && pos[0]) { 6898 size_t len; 6899 6900 /* Note the bare ' included, which cannot exist legally 6901 * in unescaped string. */ 6902 svc_info = os_strstr(pos, "svc_info='"); 6903 6904 if (svc_info) { 6905 svc_info += 9; 6906 len = os_strlen(svc_info); 6907 utf8_unescape(svc_info, len, svc_info, len); 6908 } 6909 } 6910 6911 return wpas_p2p_service_add_asp(wpa_s, auto_accept, adv_id, adv_str, 6912 (u8) svc_state, (u16) config_methods, 6913 svc_info, cpt_prio); 6914 } 6915 6916 6917 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 6918 { 6919 char *pos; 6920 6921 pos = os_strchr(cmd, ' '); 6922 if (pos == NULL) 6923 return -1; 6924 *pos++ = '\0'; 6925 6926 if (os_strcmp(cmd, "bonjour") == 0) 6927 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 6928 if (os_strcmp(cmd, "upnp") == 0) 6929 return p2p_ctrl_service_add_upnp(wpa_s, pos); 6930 if (os_strcmp(cmd, "asp") == 0) 6931 return p2p_ctrl_service_add_asp(wpa_s, 0, pos); 6932 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 6933 return -1; 6934 } 6935 6936 6937 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 6938 char *cmd) 6939 { 6940 size_t len; 6941 struct wpabuf *query; 6942 int ret; 6943 6944 len = os_strlen(cmd); 6945 if (len & 1) 6946 return -1; 6947 len /= 2; 6948 query = wpabuf_alloc(len); 6949 if (query == NULL) 6950 return -1; 6951 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 6952 wpabuf_free(query); 6953 return -1; 6954 } 6955 6956 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 6957 wpabuf_free(query); 6958 return ret; 6959 } 6960 6961 6962 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 6963 { 6964 char *pos; 6965 u8 version; 6966 6967 pos = os_strchr(cmd, ' '); 6968 if (pos == NULL) 6969 return -1; 6970 *pos++ = '\0'; 6971 6972 if (hexstr2bin(cmd, &version, 1) < 0) 6973 return -1; 6974 6975 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 6976 } 6977 6978 6979 static int p2p_ctrl_service_del_asp(struct wpa_supplicant *wpa_s, char *cmd) 6980 { 6981 u32 adv_id; 6982 6983 if (os_strcmp(cmd, "all") == 0) { 6984 wpas_p2p_service_flush_asp(wpa_s); 6985 return 0; 6986 } 6987 6988 if (sscanf(cmd, "%x", &adv_id) != 1) 6989 return -1; 6990 6991 return wpas_p2p_service_del_asp(wpa_s, adv_id); 6992 } 6993 6994 6995 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 6996 { 6997 char *pos; 6998 6999 pos = os_strchr(cmd, ' '); 7000 if (pos == NULL) 7001 return -1; 7002 *pos++ = '\0'; 7003 7004 if (os_strcmp(cmd, "bonjour") == 0) 7005 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 7006 if (os_strcmp(cmd, "upnp") == 0) 7007 return p2p_ctrl_service_del_upnp(wpa_s, pos); 7008 if (os_strcmp(cmd, "asp") == 0) 7009 return p2p_ctrl_service_del_asp(wpa_s, pos); 7010 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 7011 return -1; 7012 } 7013 7014 7015 static int p2p_ctrl_service_replace(struct wpa_supplicant *wpa_s, char *cmd) 7016 { 7017 char *pos; 7018 7019 pos = os_strchr(cmd, ' '); 7020 if (pos == NULL) 7021 return -1; 7022 *pos++ = '\0'; 7023 7024 if (os_strcmp(cmd, "asp") == 0) 7025 return p2p_ctrl_service_add_asp(wpa_s, 1, pos); 7026 7027 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 7028 return -1; 7029 } 7030 7031 7032 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 7033 { 7034 u8 addr[ETH_ALEN]; 7035 7036 /* <addr> */ 7037 7038 if (hwaddr_aton(cmd, addr)) 7039 return -1; 7040 7041 return wpas_p2p_reject(wpa_s, addr); 7042 } 7043 7044 7045 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 7046 { 7047 char *pos; 7048 int id; 7049 struct wpa_ssid *ssid; 7050 u8 *_peer = NULL, peer[ETH_ALEN]; 7051 int freq = 0, pref_freq = 0; 7052 int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; 7053 int edmg; 7054 bool allow_6ghz; 7055 7056 id = atoi(cmd); 7057 pos = os_strstr(cmd, " peer="); 7058 if (pos) { 7059 pos += 6; 7060 if (hwaddr_aton(pos, peer)) 7061 return -1; 7062 _peer = peer; 7063 } 7064 ssid = wpa_config_get_network(wpa_s->conf, id); 7065 if (ssid == NULL || ssid->disabled != 2) { 7066 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 7067 "for persistent P2P group", 7068 id); 7069 return -1; 7070 } 7071 7072 pos = os_strstr(cmd, " freq="); 7073 if (pos) { 7074 pos += 6; 7075 freq = atoi(pos); 7076 if (freq <= 0) 7077 return -1; 7078 } 7079 7080 pos = os_strstr(cmd, " pref="); 7081 if (pos) { 7082 pos += 6; 7083 pref_freq = atoi(pos); 7084 if (pref_freq <= 0) 7085 return -1; 7086 } 7087 7088 vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; 7089 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || 7090 vht; 7091 he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; 7092 edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg; 7093 7094 pos = os_strstr(cmd, "freq2="); 7095 if (pos) 7096 freq2 = atoi(pos + 6); 7097 7098 pos = os_strstr(cmd, " max_oper_chwidth="); 7099 if (pos) 7100 chwidth = atoi(pos + 18); 7101 7102 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 7103 if (max_oper_chwidth < 0) 7104 return -1; 7105 7106 allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL; 7107 7108 if (allow_6ghz && chwidth == 40) 7109 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 7110 7111 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, 7112 max_oper_chwidth, pref_freq, he, edmg, 7113 allow_6ghz); 7114 } 7115 7116 7117 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 7118 { 7119 char *pos; 7120 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 7121 bool allow_6ghz; 7122 7123 pos = os_strstr(cmd, " peer="); 7124 if (!pos) 7125 return -1; 7126 7127 *pos = '\0'; 7128 pos += 6; 7129 if (hwaddr_aton(pos, peer)) { 7130 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 7131 return -1; 7132 } 7133 7134 allow_6ghz = os_strstr(pos, " allow_6ghz") != NULL; 7135 7136 pos = os_strstr(pos, " go_dev_addr="); 7137 if (pos) { 7138 pos += 13; 7139 if (hwaddr_aton(pos, go_dev_addr)) { 7140 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 7141 pos); 7142 return -1; 7143 } 7144 go_dev = go_dev_addr; 7145 } 7146 7147 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev, allow_6ghz); 7148 } 7149 7150 7151 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 7152 { 7153 if (os_strncmp(cmd, "persistent=", 11) == 0) 7154 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 7155 if (os_strncmp(cmd, "group=", 6) == 0) 7156 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 7157 7158 return -1; 7159 } 7160 7161 7162 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 7163 int id, int freq, int vht_center_freq2, 7164 int ht40, int vht, int vht_chwidth, 7165 int he, int edmg, bool allow_6ghz, 7166 const u8 *go_bssid) 7167 { 7168 struct wpa_ssid *ssid; 7169 7170 ssid = wpa_config_get_network(wpa_s->conf, id); 7171 if (ssid == NULL || ssid->disabled != 2) { 7172 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 7173 "for persistent P2P group", 7174 id); 7175 return -1; 7176 } 7177 7178 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 7179 vht_center_freq2, ht40, vht, 7180 vht_chwidth, he, edmg, 7181 NULL, 0, 0, allow_6ghz, 0, 7182 go_bssid); 7183 } 7184 7185 7186 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 7187 { 7188 int freq = 0, persistent = 0, group_id = -1; 7189 bool allow_6ghz = false; 7190 int vht = wpa_s->conf->p2p_go_vht; 7191 int ht40 = wpa_s->conf->p2p_go_ht40 || vht; 7192 int he = wpa_s->conf->p2p_go_he; 7193 int edmg = wpa_s->conf->p2p_go_edmg; 7194 int max_oper_chwidth, chwidth = 0, freq2 = 0; 7195 char *token, *context = NULL; 7196 u8 go_bssid_buf[ETH_ALEN], *go_bssid = NULL; 7197 #ifdef CONFIG_ACS 7198 int acs = 0; 7199 #endif /* CONFIG_ACS */ 7200 7201 while ((token = str_token(cmd, " ", &context))) { 7202 if (sscanf(token, "freq2=%d", &freq2) == 1 || 7203 sscanf(token, "persistent=%d", &group_id) == 1 || 7204 sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) { 7205 continue; 7206 #ifdef CONFIG_ACS 7207 } else if (os_strcmp(token, "freq=acs") == 0) { 7208 acs = 1; 7209 #endif /* CONFIG_ACS */ 7210 } else if (sscanf(token, "freq=%d", &freq) == 1) { 7211 continue; 7212 } else if (os_strcmp(token, "ht40") == 0) { 7213 ht40 = 1; 7214 } else if (os_strcmp(token, "vht") == 0) { 7215 vht = 1; 7216 ht40 = 1; 7217 } else if (os_strcmp(token, "he") == 0) { 7218 he = 1; 7219 } else if (os_strcmp(token, "edmg") == 0) { 7220 edmg = 1; 7221 } else if (os_strcmp(token, "persistent") == 0) { 7222 persistent = 1; 7223 } else if (os_strcmp(token, "allow_6ghz") == 0) { 7224 allow_6ghz = true; 7225 } else if (os_strncmp(token, "go_bssid=", 9) == 0) { 7226 if (hwaddr_aton(token + 9, go_bssid_buf)) 7227 return -1; 7228 go_bssid = go_bssid_buf; 7229 } else { 7230 wpa_printf(MSG_DEBUG, 7231 "CTRL: Invalid P2P_GROUP_ADD parameter: '%s'", 7232 token); 7233 return -1; 7234 } 7235 } 7236 7237 #ifdef CONFIG_ACS 7238 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && 7239 (acs || freq == 2 || freq == 5)) { 7240 if (freq == 2 && wpa_s->best_24_freq <= 0) { 7241 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G; 7242 wpa_s->p2p_go_do_acs = 1; 7243 freq = 0; 7244 } else if (freq == 5 && wpa_s->best_5_freq <= 0) { 7245 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A; 7246 wpa_s->p2p_go_do_acs = 1; 7247 freq = 0; 7248 } else { 7249 wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY; 7250 wpa_s->p2p_go_do_acs = 1; 7251 } 7252 } else { 7253 wpa_s->p2p_go_do_acs = 0; 7254 } 7255 #endif /* CONFIG_ACS */ 7256 7257 max_oper_chwidth = chwidth_freq2_to_ch_width(chwidth, freq2); 7258 if (max_oper_chwidth < 0) 7259 return -1; 7260 7261 if (allow_6ghz && chwidth == 40) 7262 max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ; 7263 7264 /* Allow DFS to be used for Autonomous GO */ 7265 wpa_s->p2p_go_allow_dfs = !!(wpa_s->drv_flags & 7266 WPA_DRIVER_FLAGS_DFS_OFFLOAD); 7267 7268 if (group_id >= 0) 7269 return p2p_ctrl_group_add_persistent(wpa_s, group_id, 7270 freq, freq2, ht40, vht, 7271 max_oper_chwidth, he, 7272 edmg, allow_6ghz, 7273 go_bssid); 7274 7275 return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, 7276 max_oper_chwidth, he, edmg, allow_6ghz); 7277 } 7278 7279 7280 static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd, 7281 char *buf, size_t buflen) 7282 { 7283 u8 dev_addr[ETH_ALEN]; 7284 struct wpa_ssid *ssid; 7285 int res; 7286 const u8 *iaddr; 7287 7288 ssid = wpa_s->current_ssid; 7289 if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO || 7290 hwaddr_aton(cmd, dev_addr)) 7291 return -1; 7292 7293 iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr); 7294 if (!iaddr) 7295 return -1; 7296 res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr)); 7297 if (os_snprintf_error(buflen, res)) 7298 return -1; 7299 return res; 7300 } 7301 7302 7303 static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global, 7304 const u8 *p2p_dev_addr) 7305 { 7306 struct wpa_supplicant *wpa_s; 7307 7308 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 7309 if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr)) 7310 return 1; 7311 } 7312 7313 return 0; 7314 } 7315 7316 7317 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 7318 char *buf, size_t buflen) 7319 { 7320 u8 addr[ETH_ALEN], *addr_ptr, group_capab; 7321 int next, res; 7322 const struct p2p_peer_info *info; 7323 char *pos, *end; 7324 char devtype[WPS_DEV_TYPE_BUFSIZE]; 7325 struct wpa_ssid *ssid; 7326 size_t i; 7327 7328 if (!wpa_s->global->p2p) 7329 return -1; 7330 7331 if (os_strcmp(cmd, "FIRST") == 0) { 7332 addr_ptr = NULL; 7333 next = 0; 7334 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 7335 if (hwaddr_aton(cmd + 5, addr) < 0) 7336 return -1; 7337 addr_ptr = addr; 7338 next = 1; 7339 } else { 7340 if (hwaddr_aton(cmd, addr) < 0) 7341 return -1; 7342 addr_ptr = addr; 7343 next = 0; 7344 } 7345 7346 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 7347 if (info == NULL) 7348 return -1; 7349 group_capab = info->group_capab; 7350 7351 if (group_capab && 7352 !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) { 7353 wpa_printf(MSG_DEBUG, 7354 "P2P: Could not find any BSS with p2p_dev_addr " 7355 MACSTR ", hence override group_capab from 0x%x to 0", 7356 MAC2STR(info->p2p_device_addr), group_capab); 7357 group_capab = 0; 7358 } 7359 7360 pos = buf; 7361 end = buf + buflen; 7362 7363 res = os_snprintf(pos, end - pos, MACSTR "\n" 7364 "pri_dev_type=%s\n" 7365 "device_name=%s\n" 7366 "manufacturer=%s\n" 7367 "model_name=%s\n" 7368 "model_number=%s\n" 7369 "serial_number=%s\n" 7370 "config_methods=0x%x\n" 7371 "dev_capab=0x%x\n" 7372 "group_capab=0x%x\n" 7373 "level=%d\n", 7374 MAC2STR(info->p2p_device_addr), 7375 wps_dev_type_bin2str(info->pri_dev_type, 7376 devtype, sizeof(devtype)), 7377 info->device_name, 7378 info->manufacturer, 7379 info->model_name, 7380 info->model_number, 7381 info->serial_number, 7382 info->config_methods, 7383 info->dev_capab, 7384 group_capab, 7385 info->level); 7386 if (os_snprintf_error(end - pos, res)) 7387 return pos - buf; 7388 pos += res; 7389 7390 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 7391 { 7392 const u8 *t; 7393 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 7394 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 7395 wps_dev_type_bin2str(t, devtype, 7396 sizeof(devtype))); 7397 if (os_snprintf_error(end - pos, res)) 7398 return pos - buf; 7399 pos += res; 7400 } 7401 7402 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 7403 if (ssid) { 7404 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 7405 if (os_snprintf_error(end - pos, res)) 7406 return pos - buf; 7407 pos += res; 7408 } 7409 7410 res = p2p_get_peer_info_txt(info, pos, end - pos); 7411 if (res < 0) 7412 return pos - buf; 7413 pos += res; 7414 7415 if (info->vendor_elems) { 7416 res = os_snprintf(pos, end - pos, "vendor_elems="); 7417 if (os_snprintf_error(end - pos, res)) 7418 return pos - buf; 7419 pos += res; 7420 7421 pos += wpa_snprintf_hex(pos, end - pos, 7422 wpabuf_head(info->vendor_elems), 7423 wpabuf_len(info->vendor_elems)); 7424 7425 res = os_snprintf(pos, end - pos, "\n"); 7426 if (os_snprintf_error(end - pos, res)) 7427 return pos - buf; 7428 pos += res; 7429 } 7430 7431 return pos - buf; 7432 } 7433 7434 7435 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 7436 const char *param) 7437 { 7438 unsigned int i; 7439 7440 if (wpa_s->global->p2p == NULL) 7441 return -1; 7442 7443 if (freq_range_list_parse(&wpa_s->global->p2p_disallow_freq, param) < 0) 7444 return -1; 7445 7446 for (i = 0; i < wpa_s->global->p2p_disallow_freq.num; i++) { 7447 struct wpa_freq_range *freq; 7448 freq = &wpa_s->global->p2p_disallow_freq.range[i]; 7449 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 7450 freq->min, freq->max); 7451 } 7452 7453 wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW); 7454 return 0; 7455 } 7456 7457 7458 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 7459 { 7460 char *param; 7461 7462 if (wpa_s->global->p2p == NULL) 7463 return -1; 7464 7465 param = os_strchr(cmd, ' '); 7466 if (param == NULL) 7467 return -1; 7468 *param++ = '\0'; 7469 7470 if (os_strcmp(cmd, "discoverability") == 0) { 7471 p2p_set_client_discoverability(wpa_s->global->p2p, 7472 atoi(param)); 7473 return 0; 7474 } 7475 7476 if (os_strcmp(cmd, "managed") == 0) { 7477 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 7478 return 0; 7479 } 7480 7481 if (os_strcmp(cmd, "listen_channel") == 0) { 7482 char *pos; 7483 u8 channel, op_class; 7484 7485 channel = atoi(param); 7486 pos = os_strchr(param, ' '); 7487 op_class = pos ? atoi(pos) : 81; 7488 7489 return p2p_set_listen_channel(wpa_s->global->p2p, op_class, 7490 channel, 1); 7491 } 7492 7493 if (os_strcmp(cmd, "ssid_postfix") == 0) { 7494 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 7495 os_strlen(param)); 7496 } 7497 7498 if (os_strcmp(cmd, "noa") == 0) { 7499 char *pos; 7500 int count, start, duration; 7501 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 7502 count = atoi(param); 7503 pos = os_strchr(param, ','); 7504 if (pos == NULL) 7505 return -1; 7506 pos++; 7507 start = atoi(pos); 7508 pos = os_strchr(pos, ','); 7509 if (pos == NULL) 7510 return -1; 7511 pos++; 7512 duration = atoi(pos); 7513 if (count < 0 || count > 255 || start < 0 || duration < 0) 7514 return -1; 7515 if (count == 0 && duration > 0) 7516 return -1; 7517 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 7518 "start=%d duration=%d", count, start, duration); 7519 return wpas_p2p_set_noa(wpa_s, count, start, duration); 7520 } 7521 7522 if (os_strcmp(cmd, "ps") == 0) 7523 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 7524 7525 if (os_strcmp(cmd, "oppps") == 0) 7526 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 7527 7528 if (os_strcmp(cmd, "ctwindow") == 0) 7529 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 7530 7531 if (os_strcmp(cmd, "disabled") == 0) { 7532 wpa_s->global->p2p_disabled = atoi(param); 7533 wpa_printf(MSG_DEBUG, "P2P functionality %s", 7534 wpa_s->global->p2p_disabled ? 7535 "disabled" : "enabled"); 7536 if (wpa_s->global->p2p_disabled) { 7537 wpas_p2p_stop_find(wpa_s); 7538 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 7539 p2p_flush(wpa_s->global->p2p); 7540 } 7541 return 0; 7542 } 7543 7544 if (os_strcmp(cmd, "conc_pref") == 0) { 7545 if (os_strcmp(param, "sta") == 0) 7546 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 7547 else if (os_strcmp(param, "p2p") == 0) 7548 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 7549 else { 7550 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 7551 return -1; 7552 } 7553 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 7554 "%s", param); 7555 return 0; 7556 } 7557 7558 if (os_strcmp(cmd, "force_long_sd") == 0) { 7559 wpa_s->force_long_sd = atoi(param); 7560 return 0; 7561 } 7562 7563 if (os_strcmp(cmd, "peer_filter") == 0) { 7564 u8 addr[ETH_ALEN]; 7565 if (hwaddr_aton(param, addr)) 7566 return -1; 7567 p2p_set_peer_filter(wpa_s->global->p2p, addr); 7568 return 0; 7569 } 7570 7571 if (os_strcmp(cmd, "cross_connect") == 0) 7572 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 7573 7574 if (os_strcmp(cmd, "go_apsd") == 0) { 7575 if (os_strcmp(param, "disable") == 0) 7576 wpa_s->set_ap_uapsd = 0; 7577 else { 7578 wpa_s->set_ap_uapsd = 1; 7579 wpa_s->ap_uapsd = atoi(param); 7580 } 7581 return 0; 7582 } 7583 7584 if (os_strcmp(cmd, "client_apsd") == 0) { 7585 if (os_strcmp(param, "disable") == 0) 7586 wpa_s->set_sta_uapsd = 0; 7587 else { 7588 int be, bk, vi, vo; 7589 char *pos; 7590 /* format: BE,BK,VI,VO;max SP Length */ 7591 be = atoi(param); 7592 pos = os_strchr(param, ','); 7593 if (pos == NULL) 7594 return -1; 7595 pos++; 7596 bk = atoi(pos); 7597 pos = os_strchr(pos, ','); 7598 if (pos == NULL) 7599 return -1; 7600 pos++; 7601 vi = atoi(pos); 7602 pos = os_strchr(pos, ','); 7603 if (pos == NULL) 7604 return -1; 7605 pos++; 7606 vo = atoi(pos); 7607 /* ignore max SP Length for now */ 7608 7609 wpa_s->set_sta_uapsd = 1; 7610 wpa_s->sta_uapsd = 0; 7611 if (be) 7612 wpa_s->sta_uapsd |= BIT(0); 7613 if (bk) 7614 wpa_s->sta_uapsd |= BIT(1); 7615 if (vi) 7616 wpa_s->sta_uapsd |= BIT(2); 7617 if (vo) 7618 wpa_s->sta_uapsd |= BIT(3); 7619 } 7620 return 0; 7621 } 7622 7623 if (os_strcmp(cmd, "disallow_freq") == 0) 7624 return p2p_ctrl_disallow_freq(wpa_s, param); 7625 7626 if (os_strcmp(cmd, "disc_int") == 0) { 7627 int min_disc_int, max_disc_int, max_disc_tu; 7628 char *pos; 7629 7630 pos = param; 7631 7632 min_disc_int = atoi(pos); 7633 pos = os_strchr(pos, ' '); 7634 if (pos == NULL) 7635 return -1; 7636 *pos++ = '\0'; 7637 7638 max_disc_int = atoi(pos); 7639 pos = os_strchr(pos, ' '); 7640 if (pos == NULL) 7641 return -1; 7642 *pos++ = '\0'; 7643 7644 max_disc_tu = atoi(pos); 7645 7646 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 7647 max_disc_int, max_disc_tu); 7648 } 7649 7650 if (os_strcmp(cmd, "per_sta_psk") == 0) { 7651 wpa_s->global->p2p_per_sta_psk = !!atoi(param); 7652 return 0; 7653 } 7654 7655 #ifdef CONFIG_WPS_NFC 7656 if (os_strcmp(cmd, "nfc_tag") == 0) 7657 return wpas_p2p_nfc_tag_enabled(wpa_s, !!atoi(param)); 7658 #endif /* CONFIG_WPS_NFC */ 7659 7660 if (os_strcmp(cmd, "disable_ip_addr_req") == 0) { 7661 wpa_s->p2p_disable_ip_addr_req = !!atoi(param); 7662 return 0; 7663 } 7664 7665 if (os_strcmp(cmd, "override_pref_op_chan") == 0) { 7666 int op_class, chan; 7667 7668 op_class = atoi(param); 7669 param = os_strchr(param, ':'); 7670 if (!param) 7671 return -1; 7672 param++; 7673 chan = atoi(param); 7674 p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class, 7675 chan); 7676 return 0; 7677 } 7678 7679 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 7680 cmd); 7681 7682 return -1; 7683 } 7684 7685 7686 static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) 7687 { 7688 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 7689 wpa_s->force_long_sd = 0; 7690 7691 #ifdef CONFIG_TESTING_OPTIONS 7692 os_free(wpa_s->get_pref_freq_list_override); 7693 wpa_s->get_pref_freq_list_override = NULL; 7694 #endif /* CONFIG_TESTING_OPTIONS */ 7695 7696 wpas_p2p_stop_find(wpa_s); 7697 wpa_s->parent->p2ps_method_config_any = 0; 7698 if (wpa_s->global->p2p) 7699 p2p_flush(wpa_s->global->p2p); 7700 } 7701 7702 7703 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 7704 { 7705 char *pos, *pos2; 7706 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 7707 7708 if (cmd[0]) { 7709 pos = os_strchr(cmd, ' '); 7710 if (pos == NULL) 7711 return -1; 7712 *pos++ = '\0'; 7713 dur1 = atoi(cmd); 7714 7715 pos2 = os_strchr(pos, ' '); 7716 if (pos2) 7717 *pos2++ = '\0'; 7718 int1 = atoi(pos); 7719 } else 7720 pos2 = NULL; 7721 7722 if (pos2) { 7723 pos = os_strchr(pos2, ' '); 7724 if (pos == NULL) 7725 return -1; 7726 *pos++ = '\0'; 7727 dur2 = atoi(pos2); 7728 int2 = atoi(pos); 7729 } 7730 7731 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 7732 } 7733 7734 7735 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 7736 { 7737 char *pos; 7738 unsigned int period = 0, interval = 0; 7739 7740 if (cmd[0]) { 7741 pos = os_strchr(cmd, ' '); 7742 if (pos == NULL) 7743 return -1; 7744 *pos++ = '\0'; 7745 period = atoi(cmd); 7746 interval = atoi(pos); 7747 } 7748 7749 return wpas_p2p_ext_listen(wpa_s, period, interval); 7750 } 7751 7752 7753 static int p2p_ctrl_remove_client(struct wpa_supplicant *wpa_s, const char *cmd) 7754 { 7755 const char *pos; 7756 u8 peer[ETH_ALEN]; 7757 int iface_addr = 0; 7758 7759 pos = cmd; 7760 if (os_strncmp(pos, "iface=", 6) == 0) { 7761 iface_addr = 1; 7762 pos += 6; 7763 } 7764 if (hwaddr_aton(pos, peer)) 7765 return -1; 7766 7767 wpas_p2p_remove_client(wpa_s, peer, iface_addr); 7768 return 0; 7769 } 7770 7771 7772 static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd) 7773 { 7774 int freq = 0, period = 0, interval = 0, count = 0; 7775 7776 if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4) 7777 { 7778 wpa_printf(MSG_DEBUG, 7779 "CTRL: Invalid P2P LO Start parameter: '%s'", cmd); 7780 return -1; 7781 } 7782 7783 return wpas_p2p_lo_start(wpa_s, freq, period, interval, count); 7784 } 7785 7786 #endif /* CONFIG_P2P */ 7787 7788 7789 static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val) 7790 { 7791 struct wpa_freq_range_list ranges; 7792 int *freqs = NULL; 7793 struct hostapd_hw_modes *mode; 7794 u16 i; 7795 7796 if (wpa_s->hw.modes == NULL) 7797 return NULL; 7798 7799 os_memset(&ranges, 0, sizeof(ranges)); 7800 if (freq_range_list_parse(&ranges, val) < 0) 7801 return NULL; 7802 7803 for (i = 0; i < wpa_s->hw.num_modes; i++) { 7804 int j; 7805 7806 mode = &wpa_s->hw.modes[i]; 7807 for (j = 0; j < mode->num_channels; j++) { 7808 unsigned int freq; 7809 7810 if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED) 7811 continue; 7812 7813 freq = mode->channels[j].freq; 7814 if (!freq_range_list_includes(&ranges, freq)) 7815 continue; 7816 7817 int_array_add_unique(&freqs, freq); 7818 } 7819 } 7820 7821 os_free(ranges.range); 7822 return freqs; 7823 } 7824 7825 7826 #ifdef CONFIG_INTERWORKING 7827 7828 static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param) 7829 { 7830 int auto_sel = 0; 7831 int *freqs = NULL; 7832 7833 if (param) { 7834 char *pos; 7835 7836 auto_sel = os_strstr(param, "auto") != NULL; 7837 7838 pos = os_strstr(param, "freq="); 7839 if (pos) { 7840 freqs = freq_range_to_channel_list(wpa_s, pos + 5); 7841 if (freqs == NULL) 7842 return -1; 7843 } 7844 7845 } 7846 7847 return interworking_select(wpa_s, auto_sel, freqs); 7848 } 7849 7850 7851 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, 7852 int only_add) 7853 { 7854 u8 bssid[ETH_ALEN]; 7855 struct wpa_bss *bss; 7856 7857 if (hwaddr_aton(dst, bssid)) { 7858 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 7859 return -1; 7860 } 7861 7862 bss = wpa_bss_get_bssid_latest(wpa_s, bssid); 7863 if (bss == NULL) { 7864 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 7865 MAC2STR(bssid)); 7866 return -1; 7867 } 7868 7869 if (bss->ssid_len == 0) { 7870 int found = 0; 7871 7872 wpa_printf(MSG_DEBUG, "Selected BSS entry for " MACSTR 7873 " does not have SSID information", MAC2STR(bssid)); 7874 7875 dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, 7876 list) { 7877 if (ether_addr_equal(bss->bssid, bssid) && 7878 bss->ssid_len > 0) { 7879 found = 1; 7880 break; 7881 } 7882 } 7883 7884 if (!found) 7885 return -1; 7886 wpa_printf(MSG_DEBUG, 7887 "Found another matching BSS entry with SSID"); 7888 } 7889 7890 return interworking_connect(wpa_s, bss, only_add); 7891 } 7892 7893 7894 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 7895 { 7896 u8 dst_addr[ETH_ALEN]; 7897 int used, freq = 0; 7898 char *pos; 7899 #define MAX_ANQP_INFO_ID 100 7900 u16 id[MAX_ANQP_INFO_ID]; 7901 size_t num_id = 0; 7902 u32 subtypes = 0; 7903 u32 mbo_subtypes = 0; 7904 7905 used = hwaddr_aton2(dst, dst_addr); 7906 if (used < 0) 7907 return -1; 7908 pos = dst + used; 7909 if (*pos == ' ') 7910 pos++; 7911 7912 if (os_strncmp(pos, "freq=", 5) == 0) { 7913 freq = atoi(pos + 5); 7914 pos = os_strchr(pos, ' '); 7915 if (!pos) 7916 return -1; 7917 pos++; 7918 } 7919 7920 while (num_id < MAX_ANQP_INFO_ID) { 7921 if (os_strncmp(pos, "hs20:", 5) == 0) { 7922 #ifdef CONFIG_HS20 7923 int num = atoi(pos + 5); 7924 if (num <= 0 || num > 31) 7925 return -1; 7926 subtypes |= BIT(num); 7927 #else /* CONFIG_HS20 */ 7928 return -1; 7929 #endif /* CONFIG_HS20 */ 7930 } else if (os_strncmp(pos, "mbo:", 4) == 0) { 7931 #ifdef CONFIG_MBO 7932 int num = atoi(pos + 4); 7933 7934 if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) 7935 return -1; 7936 mbo_subtypes |= BIT(num); 7937 #else /* CONFIG_MBO */ 7938 return -1; 7939 #endif /* CONFIG_MBO */ 7940 } else { 7941 id[num_id] = atoi(pos); 7942 if (id[num_id]) 7943 num_id++; 7944 } 7945 pos = os_strchr(pos + 1, ','); 7946 if (pos == NULL) 7947 break; 7948 pos++; 7949 } 7950 7951 if (num_id == 0 && !subtypes && !mbo_subtypes) 7952 return -1; 7953 7954 return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes, 7955 mbo_subtypes); 7956 } 7957 7958 7959 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 7960 { 7961 u8 dst_addr[ETH_ALEN]; 7962 struct wpabuf *advproto, *query = NULL; 7963 int used, ret = -1; 7964 char *pos, *end; 7965 size_t len; 7966 7967 used = hwaddr_aton2(cmd, dst_addr); 7968 if (used < 0) 7969 return -1; 7970 7971 pos = cmd + used; 7972 while (*pos == ' ') 7973 pos++; 7974 7975 /* Advertisement Protocol ID */ 7976 end = os_strchr(pos, ' '); 7977 if (end) 7978 len = end - pos; 7979 else 7980 len = os_strlen(pos); 7981 if (len & 0x01) 7982 return -1; 7983 len /= 2; 7984 if (len == 0) 7985 return -1; 7986 advproto = wpabuf_alloc(len); 7987 if (advproto == NULL) 7988 return -1; 7989 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 7990 goto fail; 7991 7992 if (end) { 7993 /* Optional Query Request */ 7994 pos = end + 1; 7995 while (*pos == ' ') 7996 pos++; 7997 7998 len = os_strlen(pos); 7999 if (len) { 8000 if (len & 0x01) 8001 goto fail; 8002 len /= 2; 8003 if (len == 0) 8004 goto fail; 8005 query = wpabuf_alloc(len); 8006 if (query == NULL) 8007 goto fail; 8008 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 8009 goto fail; 8010 } 8011 } 8012 8013 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 8014 8015 fail: 8016 wpabuf_free(advproto); 8017 wpabuf_free(query); 8018 8019 return ret; 8020 } 8021 8022 8023 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 8024 size_t buflen) 8025 { 8026 u8 addr[ETH_ALEN]; 8027 int dialog_token; 8028 int used; 8029 char *pos; 8030 size_t resp_len, start, requested_len; 8031 struct wpabuf *resp; 8032 int ret; 8033 8034 used = hwaddr_aton2(cmd, addr); 8035 if (used < 0) 8036 return -1; 8037 8038 pos = cmd + used; 8039 while (*pos == ' ') 8040 pos++; 8041 dialog_token = atoi(pos); 8042 8043 if (wpa_s->last_gas_resp && 8044 ether_addr_equal(addr, wpa_s->last_gas_addr) && 8045 dialog_token == wpa_s->last_gas_dialog_token) 8046 resp = wpa_s->last_gas_resp; 8047 else if (wpa_s->prev_gas_resp && 8048 ether_addr_equal(addr, wpa_s->prev_gas_addr) && 8049 dialog_token == wpa_s->prev_gas_dialog_token) 8050 resp = wpa_s->prev_gas_resp; 8051 else 8052 return -1; 8053 8054 resp_len = wpabuf_len(resp); 8055 start = 0; 8056 requested_len = resp_len; 8057 8058 pos = os_strchr(pos, ' '); 8059 if (pos) { 8060 start = atoi(pos); 8061 if (start > resp_len) 8062 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 8063 pos = os_strchr(pos, ','); 8064 if (pos == NULL) 8065 return -1; 8066 pos++; 8067 requested_len = atoi(pos); 8068 if (start + requested_len > resp_len) 8069 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 8070 } 8071 8072 if (requested_len * 2 + 1 > buflen) 8073 return os_snprintf(buf, buflen, "FAIL-Too long response"); 8074 8075 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start, 8076 requested_len); 8077 8078 if (start + requested_len == resp_len) { 8079 /* 8080 * Free memory by dropping the response after it has been 8081 * fetched. 8082 */ 8083 if (resp == wpa_s->prev_gas_resp) { 8084 wpabuf_free(wpa_s->prev_gas_resp); 8085 wpa_s->prev_gas_resp = NULL; 8086 } else { 8087 wpabuf_free(wpa_s->last_gas_resp); 8088 wpa_s->last_gas_resp = NULL; 8089 } 8090 } 8091 8092 return ret; 8093 } 8094 #endif /* CONFIG_INTERWORKING */ 8095 8096 8097 #ifdef CONFIG_HS20 8098 8099 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 8100 { 8101 u8 dst_addr[ETH_ALEN]; 8102 int used; 8103 char *pos; 8104 u32 subtypes = 0; 8105 8106 used = hwaddr_aton2(dst, dst_addr); 8107 if (used < 0) 8108 return -1; 8109 pos = dst + used; 8110 if (*pos == ' ') 8111 pos++; 8112 for (;;) { 8113 int num = atoi(pos); 8114 if (num <= 0 || num > 31) 8115 return -1; 8116 subtypes |= BIT(num); 8117 pos = os_strchr(pos + 1, ','); 8118 if (pos == NULL) 8119 break; 8120 pos++; 8121 } 8122 8123 if (subtypes == 0) 8124 return -1; 8125 8126 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0); 8127 } 8128 8129 8130 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 8131 const u8 *addr, const char *realm) 8132 { 8133 u8 *buf; 8134 size_t rlen, len; 8135 int ret; 8136 8137 rlen = os_strlen(realm); 8138 len = 3 + rlen; 8139 buf = os_malloc(len); 8140 if (buf == NULL) 8141 return -1; 8142 buf[0] = 1; /* NAI Home Realm Count */ 8143 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 8144 buf[2] = rlen; 8145 os_memcpy(buf + 3, realm, rlen); 8146 8147 ret = hs20_anqp_send_req(wpa_s, addr, 8148 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 8149 buf, len, 0); 8150 8151 os_free(buf); 8152 8153 return ret; 8154 } 8155 8156 8157 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 8158 char *dst) 8159 { 8160 struct wpa_cred *cred = wpa_s->conf->cred; 8161 u8 dst_addr[ETH_ALEN]; 8162 int used; 8163 u8 *buf; 8164 size_t len; 8165 int ret; 8166 8167 used = hwaddr_aton2(dst, dst_addr); 8168 if (used < 0) 8169 return -1; 8170 8171 while (dst[used] == ' ') 8172 used++; 8173 if (os_strncmp(dst + used, "realm=", 6) == 0) 8174 return hs20_nai_home_realm_list(wpa_s, dst_addr, 8175 dst + used + 6); 8176 8177 len = os_strlen(dst + used); 8178 8179 if (len == 0 && cred && cred->realm) 8180 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 8181 8182 if (len & 1) 8183 return -1; 8184 len /= 2; 8185 buf = os_malloc(len); 8186 if (buf == NULL) 8187 return -1; 8188 if (hexstr2bin(dst + used, buf, len) < 0) { 8189 os_free(buf); 8190 return -1; 8191 } 8192 8193 ret = hs20_anqp_send_req(wpa_s, dst_addr, 8194 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 8195 buf, len, 0); 8196 os_free(buf); 8197 8198 return ret; 8199 } 8200 8201 8202 static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply, 8203 int buflen) 8204 { 8205 u8 dst_addr[ETH_ALEN]; 8206 int used; 8207 char *ctx = NULL, *icon, *poffset, *psize; 8208 8209 used = hwaddr_aton2(cmd, dst_addr); 8210 if (used < 0) 8211 return -1; 8212 cmd += used; 8213 8214 icon = str_token(cmd, " ", &ctx); 8215 poffset = str_token(cmd, " ", &ctx); 8216 psize = str_token(cmd, " ", &ctx); 8217 if (!icon || !poffset || !psize) 8218 return -1; 8219 8220 wpa_s->fetch_osu_icon_in_progress = 0; 8221 return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize), 8222 reply, buflen); 8223 } 8224 8225 8226 static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd) 8227 { 8228 u8 dst_addr[ETH_ALEN]; 8229 int used; 8230 char *icon; 8231 8232 if (!cmd[0]) 8233 return hs20_del_icon(wpa_s, NULL, NULL); 8234 8235 used = hwaddr_aton2(cmd, dst_addr); 8236 if (used < 0) 8237 return -1; 8238 8239 while (cmd[used] == ' ') 8240 used++; 8241 icon = cmd[used] ? &cmd[used] : NULL; 8242 8243 return hs20_del_icon(wpa_s, dst_addr, icon); 8244 } 8245 8246 8247 static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem) 8248 { 8249 u8 dst_addr[ETH_ALEN]; 8250 int used; 8251 char *icon; 8252 8253 used = hwaddr_aton2(cmd, dst_addr); 8254 if (used < 0) 8255 return -1; 8256 8257 while (cmd[used] == ' ') 8258 used++; 8259 icon = &cmd[used]; 8260 8261 wpa_s->fetch_osu_icon_in_progress = 0; 8262 return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST), 8263 (u8 *) icon, os_strlen(icon), inmem); 8264 } 8265 8266 #endif /* CONFIG_HS20 */ 8267 8268 8269 #ifdef CONFIG_AUTOSCAN 8270 8271 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 8272 char *cmd) 8273 { 8274 enum wpa_states state = wpa_s->wpa_state; 8275 char *new_params = NULL; 8276 8277 if (os_strlen(cmd) > 0) { 8278 new_params = os_strdup(cmd); 8279 if (new_params == NULL) 8280 return -1; 8281 } 8282 8283 os_free(wpa_s->conf->autoscan); 8284 wpa_s->conf->autoscan = new_params; 8285 8286 if (wpa_s->conf->autoscan == NULL) 8287 autoscan_deinit(wpa_s); 8288 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 8289 autoscan_init(wpa_s, 1); 8290 else if (state == WPA_SCANNING) 8291 wpa_supplicant_reinit_autoscan(wpa_s); 8292 else 8293 wpa_printf(MSG_DEBUG, "No autoscan update in state %s", 8294 wpa_supplicant_state_txt(state)); 8295 8296 return 0; 8297 } 8298 8299 #endif /* CONFIG_AUTOSCAN */ 8300 8301 8302 #ifdef CONFIG_WNM 8303 8304 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 8305 { 8306 int enter; 8307 int intval = 0; 8308 char *pos; 8309 int ret; 8310 struct wpabuf *tfs_req = NULL; 8311 8312 if (os_strncmp(cmd, "enter", 5) == 0) 8313 enter = 1; 8314 else if (os_strncmp(cmd, "exit", 4) == 0) 8315 enter = 0; 8316 else 8317 return -1; 8318 8319 pos = os_strstr(cmd, " interval="); 8320 if (pos) 8321 intval = atoi(pos + 10); 8322 8323 pos = os_strstr(cmd, " tfs_req="); 8324 if (pos) { 8325 char *end; 8326 size_t len; 8327 pos += 9; 8328 end = os_strchr(pos, ' '); 8329 if (end) 8330 len = end - pos; 8331 else 8332 len = os_strlen(pos); 8333 if (len & 1) 8334 return -1; 8335 len /= 2; 8336 tfs_req = wpabuf_alloc(len); 8337 if (tfs_req == NULL) 8338 return -1; 8339 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 8340 wpabuf_free(tfs_req); 8341 return -1; 8342 } 8343 } 8344 8345 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 8346 WNM_SLEEP_MODE_EXIT, intval, 8347 tfs_req); 8348 wpabuf_free(tfs_req); 8349 8350 return ret; 8351 } 8352 8353 8354 static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) 8355 { 8356 int query_reason, list = 0; 8357 char *btm_candidates = NULL; 8358 8359 query_reason = atoi(cmd); 8360 8361 cmd = os_strchr(cmd, ' '); 8362 if (cmd) { 8363 if (os_strncmp(cmd, " list", 5) == 0) 8364 list = 1; 8365 else 8366 btm_candidates = cmd; 8367 } 8368 8369 wpa_printf(MSG_DEBUG, 8370 "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s", 8371 query_reason, list ? " candidate list" : ""); 8372 8373 return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, 8374 btm_candidates, 8375 list); 8376 } 8377 8378 8379 static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s, 8380 char *cmd) 8381 { 8382 struct wpabuf *elems; 8383 int ret; 8384 8385 elems = wpabuf_parse_bin(cmd); 8386 if (!elems) 8387 return -1; 8388 8389 ret = wnm_send_coloc_intf_report(wpa_s, 0, elems); 8390 wpabuf_free(elems); 8391 return ret; 8392 } 8393 8394 #endif /* CONFIG_WNM */ 8395 8396 8397 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 8398 size_t buflen) 8399 { 8400 struct wpa_signal_info si; 8401 int ret; 8402 char *pos, *end; 8403 8404 ret = wpa_drv_signal_poll(wpa_s, &si); 8405 if (ret) 8406 return -1; 8407 8408 pos = buf; 8409 end = buf + buflen; 8410 8411 ret = os_snprintf(pos, end - pos, "RSSI=%d\nLINKSPEED=%lu\n" 8412 "NOISE=%d\nFREQUENCY=%u\n", 8413 si.data.signal, si.data.current_tx_rate / 1000, 8414 si.current_noise, si.frequency); 8415 if (os_snprintf_error(end - pos, ret)) 8416 return -1; 8417 pos += ret; 8418 8419 if (si.chanwidth != CHAN_WIDTH_UNKNOWN) { 8420 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 8421 channel_width_to_string(si.chanwidth)); 8422 if (os_snprintf_error(end - pos, ret)) 8423 return -1; 8424 pos += ret; 8425 } 8426 8427 if (si.center_frq1 > 0) { 8428 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 8429 si.center_frq1); 8430 if (os_snprintf_error(end - pos, ret)) 8431 return -1; 8432 pos += ret; 8433 } 8434 8435 if (si.center_frq2 > 0) { 8436 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 8437 si.center_frq2); 8438 if (os_snprintf_error(end - pos, ret)) 8439 return -1; 8440 pos += ret; 8441 } 8442 8443 if (si.data.avg_signal) { 8444 ret = os_snprintf(pos, end - pos, 8445 "AVG_RSSI=%d\n", si.data.avg_signal); 8446 if (os_snprintf_error(end - pos, ret)) 8447 return -1; 8448 pos += ret; 8449 } 8450 8451 if (si.data.avg_beacon_signal) { 8452 ret = os_snprintf(pos, end - pos, 8453 "AVG_BEACON_RSSI=%d\n", 8454 si.data.avg_beacon_signal); 8455 if (os_snprintf_error(end - pos, ret)) 8456 return -1; 8457 pos += ret; 8458 } 8459 8460 return pos - buf; 8461 } 8462 8463 8464 static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s, 8465 const char *cmd) 8466 { 8467 const char *pos; 8468 int threshold = 0; 8469 int hysteresis = 0; 8470 8471 if (wpa_s->bgscan && wpa_s->bgscan_priv) { 8472 wpa_printf(MSG_DEBUG, 8473 "Reject SIGNAL_MONITOR command - bgscan is active"); 8474 return -1; 8475 } 8476 pos = os_strstr(cmd, "THRESHOLD="); 8477 if (pos) 8478 threshold = atoi(pos + 10); 8479 pos = os_strstr(cmd, "HYSTERESIS="); 8480 if (pos) 8481 hysteresis = atoi(pos + 11); 8482 return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis); 8483 } 8484 8485 8486 #ifdef CONFIG_TESTING_OPTIONS 8487 int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, 8488 enum wpa_driver_if_type if_type, 8489 unsigned int *num, 8490 struct weighted_pcl *freq_list) 8491 { 8492 char *pos = wpa_s->get_pref_freq_list_override; 8493 char *end; 8494 unsigned int count = 0; 8495 8496 /* Override string format: 8497 * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */ 8498 8499 while (pos) { 8500 if (atoi(pos) == (int) if_type) 8501 break; 8502 pos = os_strchr(pos, ' '); 8503 if (pos) 8504 pos++; 8505 } 8506 if (!pos) 8507 return -1; 8508 pos = os_strchr(pos, ':'); 8509 if (!pos) 8510 return -1; 8511 pos++; 8512 end = os_strchr(pos, ' '); 8513 while (pos && (!end || pos < end) && count < *num) { 8514 freq_list[count].freq = atoi(pos); 8515 freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI; 8516 pos = os_strchr(pos, ','); 8517 if (pos) 8518 pos++; 8519 } 8520 8521 *num = count; 8522 return 0; 8523 } 8524 #endif /* CONFIG_TESTING_OPTIONS */ 8525 8526 8527 static int wpas_ctrl_iface_get_pref_freq_list( 8528 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 8529 { 8530 unsigned int num = 100, i; 8531 int ret; 8532 enum wpa_driver_if_type iface_type; 8533 char *pos, *end; 8534 struct weighted_pcl freq_list[100]; 8535 8536 pos = buf; 8537 end = buf + buflen; 8538 8539 /* buf: "<interface_type>" */ 8540 if (os_strcmp(cmd, "STATION") == 0) 8541 iface_type = WPA_IF_STATION; 8542 else if (os_strcmp(cmd, "AP") == 0) 8543 iface_type = WPA_IF_AP_BSS; 8544 else if (os_strcmp(cmd, "P2P_GO") == 0) 8545 iface_type = WPA_IF_P2P_GO; 8546 else if (os_strcmp(cmd, "P2P_CLIENT") == 0) 8547 iface_type = WPA_IF_P2P_CLIENT; 8548 else if (os_strcmp(cmd, "IBSS") == 0) 8549 iface_type = WPA_IF_IBSS; 8550 else if (os_strcmp(cmd, "TDLS") == 0) 8551 iface_type = WPA_IF_TDLS; 8552 else 8553 return -1; 8554 8555 wpa_printf(MSG_DEBUG, 8556 "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", 8557 iface_type, cmd); 8558 8559 ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); 8560 if (ret) 8561 return -1; 8562 8563 for (i = 0; i < num; i++) { 8564 ret = os_snprintf(pos, end - pos, "%s%u", 8565 i > 0 ? "," : "", freq_list[i].freq); 8566 if (os_snprintf_error(end - pos, ret)) 8567 return -1; 8568 pos += ret; 8569 } 8570 8571 return pos - buf; 8572 } 8573 8574 8575 static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, 8576 char *buf, size_t buflen) 8577 { 8578 int ret, i; 8579 char *pos, *end; 8580 8581 ret = os_snprintf(buf, buflen, "%016llX:\n", 8582 (long long unsigned) wpa_s->drv_flags); 8583 if (os_snprintf_error(buflen, ret)) 8584 return -1; 8585 8586 pos = buf + ret; 8587 end = buf + buflen; 8588 8589 for (i = 0; i < 64; i++) { 8590 if (wpa_s->drv_flags & (1LLU << i)) { 8591 ret = os_snprintf(pos, end - pos, "%s\n", 8592 driver_flag_to_string(1LLU << i)); 8593 if (os_snprintf_error(end - pos, ret)) 8594 return -1; 8595 pos += ret; 8596 } 8597 } 8598 8599 return pos - buf; 8600 } 8601 8602 8603 static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s, 8604 char *buf, size_t buflen) 8605 { 8606 int ret, i; 8607 char *pos, *end; 8608 8609 ret = os_snprintf(buf, buflen, "%016llX:\n", 8610 (long long unsigned) wpa_s->drv_flags2); 8611 if (os_snprintf_error(buflen, ret)) 8612 return -1; 8613 8614 pos = buf + ret; 8615 end = buf + buflen; 8616 8617 for (i = 0; i < 64; i++) { 8618 if (wpa_s->drv_flags2 & (1LLU << i)) { 8619 ret = os_snprintf(pos, end - pos, "%s\n", 8620 driver_flag2_to_string(1LLU << i)); 8621 if (os_snprintf_error(end - pos, ret)) 8622 return -1; 8623 pos += ret; 8624 } 8625 } 8626 8627 return pos - buf; 8628 } 8629 8630 8631 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 8632 size_t buflen) 8633 { 8634 struct hostap_sta_driver_data sta; 8635 int ret; 8636 8637 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 8638 if (ret) 8639 return -1; 8640 8641 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 8642 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 8643 if (os_snprintf_error(buflen, ret)) 8644 return -1; 8645 return ret; 8646 } 8647 8648 8649 #ifdef ANDROID 8650 static int wpa_supplicant_driver_cmd(struct wpa_supplicant *wpa_s, char *cmd, 8651 char *buf, size_t buflen) 8652 { 8653 int ret; 8654 8655 ret = wpa_drv_driver_cmd(wpa_s, cmd, buf, buflen); 8656 if (ret == 0) { 8657 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) { 8658 struct p2p_data *p2p = wpa_s->global->p2p; 8659 if (p2p) { 8660 char country[3]; 8661 country[0] = cmd[8]; 8662 country[1] = cmd[9]; 8663 country[2] = 0x04; 8664 p2p_set_country(p2p, country); 8665 } 8666 } 8667 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 8668 if (os_snprintf_error(buflen, ret)) 8669 ret = -1; 8670 } 8671 return ret; 8672 } 8673 #endif /* ANDROID */ 8674 8675 8676 static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, 8677 char *buf, size_t buflen) 8678 { 8679 int ret; 8680 char *pos, *temp = NULL; 8681 u8 *data = NULL; 8682 unsigned int vendor_id, subcmd; 8683 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; 8684 struct wpabuf *reply; 8685 size_t data_len = 0; 8686 8687 /** 8688 * cmd: <vendor id> <subcommand id> [<hex formatted data>] 8689 * [nested=<0|1>] 8690 */ 8691 vendor_id = strtoul(cmd, &pos, 16); 8692 if (!isblank((unsigned char) *pos)) 8693 return -EINVAL; 8694 8695 subcmd = strtoul(pos, &pos, 10); 8696 8697 if (*pos != '\0') { 8698 if (!isblank((unsigned char) *pos++)) 8699 return -EINVAL; 8700 8701 temp = os_strchr(pos, ' '); 8702 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); 8703 } 8704 8705 if (data_len) { 8706 data_len /= 2; 8707 data = os_malloc(data_len); 8708 if (!data) 8709 return -1; 8710 8711 if (hexstr2bin(pos, data, data_len)) { 8712 wpa_printf(MSG_DEBUG, 8713 "Vendor command: wrong parameter format"); 8714 os_free(data); 8715 return -EINVAL; 8716 } 8717 } 8718 8719 pos = os_strstr(cmd, "nested="); 8720 if (pos) 8721 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : 8722 NESTED_ATTR_NOT_USED; 8723 8724 reply = wpabuf_alloc((buflen - 1) / 2); 8725 if (!reply) { 8726 os_free(data); 8727 return -1; 8728 } 8729 8730 ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, 8731 nested_attr_flag, reply); 8732 8733 if (ret == 0) 8734 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 8735 wpabuf_len(reply)); 8736 8737 wpabuf_free(reply); 8738 os_free(data); 8739 8740 return ret; 8741 } 8742 8743 8744 static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) 8745 { 8746 #ifdef CONFIG_P2P 8747 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s ? 8748 wpa_s->global->p2p_init_wpa_s : wpa_s; 8749 #endif /* CONFIG_P2P */ 8750 8751 wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); 8752 8753 if (wpas_abort_ongoing_scan(wpa_s) == 0) 8754 wpa_s->ignore_post_flush_scan_res = 1; 8755 8756 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { 8757 /* 8758 * Avoid possible auto connect re-connection on getting 8759 * disconnected due to state flush. 8760 */ 8761 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 8762 } 8763 8764 #ifdef CONFIG_P2P 8765 wpas_p2p_group_remove(p2p_wpa_s, "*"); 8766 wpas_p2p_cancel(p2p_wpa_s); 8767 p2p_ctrl_flush(p2p_wpa_s); 8768 wpas_p2p_service_flush(p2p_wpa_s); 8769 p2p_wpa_s->global->p2p_disabled = 0; 8770 p2p_wpa_s->global->p2p_per_sta_psk = 0; 8771 p2p_wpa_s->conf->num_sec_device_types = 0; 8772 p2p_wpa_s->p2p_disable_ip_addr_req = 0; 8773 os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range); 8774 p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL; 8775 p2p_wpa_s->global->p2p_go_avoid_freq.num = 0; 8776 p2p_wpa_s->global->pending_p2ps_group = 0; 8777 p2p_wpa_s->global->pending_p2ps_group_freq = 0; 8778 #endif /* CONFIG_P2P */ 8779 8780 #ifdef CONFIG_WPS_TESTING 8781 wps_version_number = 0x20; 8782 wps_testing_stub_cred = 0; 8783 wps_corrupt_pkhash = 0; 8784 wps_force_auth_types_in_use = 0; 8785 wps_force_encr_types_in_use = 0; 8786 #endif /* CONFIG_WPS_TESTING */ 8787 #ifdef CONFIG_WPS 8788 wpa_s->wps_fragment_size = 0; 8789 wpas_wps_cancel(wpa_s); 8790 wps_registrar_flush(wpa_s->wps->registrar); 8791 #endif /* CONFIG_WPS */ 8792 wpa_s->after_wps = 0; 8793 wpa_s->known_wps_freq = 0; 8794 8795 #ifdef CONFIG_DPP 8796 wpas_dpp_deinit(wpa_s); 8797 wpa_s->dpp_init_max_tries = 0; 8798 wpa_s->dpp_init_retry_time = 0; 8799 wpa_s->dpp_resp_wait_time = 0; 8800 wpa_s->dpp_resp_max_tries = 0; 8801 wpa_s->dpp_resp_retry_time = 0; 8802 #ifdef CONFIG_DPP2 8803 wpas_dpp_chirp_stop(wpa_s); 8804 wpa_s->dpp_pfs_fallback = 0; 8805 #endif /* CONFIG_DPP2 */ 8806 #ifdef CONFIG_DPP3 8807 { 8808 int i; 8809 8810 for (i = 0; i < DPP_PB_INFO_COUNT; i++) { 8811 struct dpp_pb_info *info; 8812 8813 info = &wpa_s->dpp_pb[i]; 8814 info->rx_time.sec = 0; 8815 info->rx_time.usec = 0; 8816 } 8817 } 8818 #endif /* CONFIG_DPP3 */ 8819 #ifdef CONFIG_TESTING_OPTIONS 8820 os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); 8821 os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); 8822 dpp_pkex_ephemeral_key_override_len = 0; 8823 dpp_protocol_key_override_len = 0; 8824 dpp_nonce_override_len = 0; 8825 #ifdef CONFIG_DPP3 8826 dpp_version_override = 3; 8827 #elif defined(CONFIG_DPP2) 8828 dpp_version_override = 2; 8829 #else /* CONFIG_DPP2 */ 8830 dpp_version_override = 1; 8831 #endif /* CONFIG_DPP2 */ 8832 #endif /* CONFIG_TESTING_OPTIONS */ 8833 #endif /* CONFIG_DPP */ 8834 8835 #ifdef CONFIG_TDLS 8836 #ifdef CONFIG_TDLS_TESTING 8837 tdls_testing = 0; 8838 #endif /* CONFIG_TDLS_TESTING */ 8839 wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL); 8840 wpa_tdls_enable(wpa_s->wpa, 1); 8841 #endif /* CONFIG_TDLS */ 8842 8843 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); 8844 wpa_supplicant_stop_countermeasures(wpa_s, NULL); 8845 wpa_s->last_michael_mic_error.sec = 0; 8846 8847 wpa_s->no_keep_alive = 0; 8848 wpa_s->own_disconnect_req = 0; 8849 wpa_s->own_reconnect_req = 0; 8850 wpa_s->deny_ptk0_rekey = 0; 8851 8852 os_free(wpa_s->disallow_aps_bssid); 8853 wpa_s->disallow_aps_bssid = NULL; 8854 wpa_s->disallow_aps_bssid_count = 0; 8855 os_free(wpa_s->disallow_aps_ssid); 8856 wpa_s->disallow_aps_ssid = NULL; 8857 wpa_s->disallow_aps_ssid_count = 0; 8858 8859 wpa_s->set_sta_uapsd = 0; 8860 wpa_s->sta_uapsd = 0; 8861 8862 wpa_s->consecutive_conn_failures = 0; 8863 8864 wpa_drv_radio_disable(wpa_s, 0); 8865 wpa_bssid_ignore_clear(wpa_s); 8866 wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); 8867 wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); 8868 wpa_config_flush_blobs(wpa_s->conf); 8869 wpa_s->conf->auto_interworking = 0; 8870 wpa_s->conf->okc = 0; 8871 8872 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE); 8873 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 8874 rsn_preauth_deinit(wpa_s->wpa); 8875 8876 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); 8877 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); 8878 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); 8879 eapol_sm_notify_logoff(wpa_s->eapol, false); 8880 8881 radio_remove_works(wpa_s, NULL, 1); 8882 wpa_s->ext_work_in_progress = 0; 8883 8884 wpa_s->next_ssid = NULL; 8885 8886 wnm_btm_reset(wpa_s); 8887 8888 #ifdef CONFIG_INTERWORKING 8889 #ifdef CONFIG_HS20 8890 hs20_cancel_fetch_osu(wpa_s); 8891 hs20_del_icon(wpa_s, NULL, NULL); 8892 #endif /* CONFIG_HS20 */ 8893 #endif /* CONFIG_INTERWORKING */ 8894 8895 wpa_s->ext_mgmt_frame_handling = 0; 8896 wpa_s->ext_eapol_frame_io = 0; 8897 #ifdef CONFIG_TESTING_OPTIONS 8898 wpa_s->extra_roc_dur = 0; 8899 wpa_s->test_failure = WPAS_TEST_FAILURE_NONE; 8900 wpa_s->p2p_go_csa_on_inv = 0; 8901 wpa_s->ignore_auth_resp = 0; 8902 wpa_s->ignore_assoc_disallow = 0; 8903 wpa_s->disable_sa_query = 0; 8904 wpa_s->testing_resend_assoc = 0; 8905 wpa_s->ignore_sae_h2e_only = 0; 8906 wpa_s->ft_rsnxe_used = 0; 8907 wpa_s->reject_btm_req_reason = 0; 8908 wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); 8909 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, NULL); 8910 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, NULL); 8911 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M2, 0); 8912 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_ENCRYPT_EAPOL_M4, 0); 8913 os_free(wpa_s->get_pref_freq_list_override); 8914 wpa_s->get_pref_freq_list_override = NULL; 8915 wpabuf_free(wpa_s->sae_commit_override); 8916 wpa_s->sae_commit_override = NULL; 8917 os_free(wpa_s->extra_sae_rejected_groups); 8918 wpa_s->extra_sae_rejected_groups = NULL; 8919 wpabuf_free(wpa_s->rsne_override_eapol); 8920 wpa_s->rsne_override_eapol = NULL; 8921 wpabuf_free(wpa_s->rsnxe_override_assoc); 8922 wpa_s->rsnxe_override_assoc = NULL; 8923 wpabuf_free(wpa_s->rsnxe_override_eapol); 8924 wpa_s->rsnxe_override_eapol = NULL; 8925 wpas_clear_driver_signal_override(wpa_s); 8926 #ifndef CONFIG_NO_ROBUST_AV 8927 wpa_s->disable_scs_support = 0; 8928 wpa_s->disable_mscs_support = 0; 8929 wpa_s->enable_dscp_policy_capa = 0; 8930 #endif /* CONFIG_NO_ROBUST_AV */ 8931 wpa_s->oci_freq_override_eapol = 0; 8932 wpa_s->oci_freq_override_saquery_req = 0; 8933 wpa_s->oci_freq_override_saquery_resp = 0; 8934 wpa_s->oci_freq_override_eapol_g2 = 0; 8935 wpa_s->oci_freq_override_ft_assoc = 0; 8936 wpa_s->oci_freq_override_fils_assoc = 0; 8937 wpa_s->oci_freq_override_wnm_sleep = 0; 8938 wpa_s->disable_eapol_g2_tx = 0; 8939 wpa_s->test_assoc_comeback_type = -1; 8940 #ifdef CONFIG_DPP 8941 os_free(wpa_s->dpp_config_obj_override); 8942 wpa_s->dpp_config_obj_override = NULL; 8943 os_free(wpa_s->dpp_discovery_override); 8944 wpa_s->dpp_discovery_override = NULL; 8945 os_free(wpa_s->dpp_groups_override); 8946 wpa_s->dpp_groups_override = NULL; 8947 wpa_s->dpp_ignore_netaccesskey_mismatch = 0; 8948 wpa_s->dpp_discard_public_action = 0; 8949 dpp_test = DPP_TEST_DISABLED; 8950 #endif /* CONFIG_DPP */ 8951 #endif /* CONFIG_TESTING_OPTIONS */ 8952 8953 wpa_s->disconnected = 0; 8954 os_free(wpa_s->next_scan_freqs); 8955 wpa_s->next_scan_freqs = NULL; 8956 os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); 8957 wpa_s->next_scan_bssid_wildcard_ssid = 0; 8958 os_free(wpa_s->select_network_scan_freqs); 8959 wpa_s->select_network_scan_freqs = NULL; 8960 #ifndef CONFIG_NO_ROBUST_AV 8961 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); 8962 #endif /* CONFIG_NO_ROBUST_AV */ 8963 8964 wpa_bss_flush(wpa_s); 8965 if (!dl_list_empty(&wpa_s->bss)) { 8966 wpa_printf(MSG_DEBUG, 8967 "BSS table not empty after flush: %u entries, current_bss=%p bssid=" 8968 MACSTR " pending_bssid=" MACSTR, 8969 dl_list_len(&wpa_s->bss), wpa_s->current_bss, 8970 MAC2STR(wpa_s->bssid), 8971 MAC2STR(wpa_s->pending_bssid)); 8972 } 8973 8974 eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); 8975 wpa_s->wnmsleep_used = 0; 8976 8977 #ifdef CONFIG_SME 8978 wpa_s->sme.last_unprot_disconnect.sec = 0; 8979 wpa_s->sme.auth_alg = 0; 8980 #endif /* CONFIG_SME */ 8981 8982 wpabuf_free(wpa_s->ric_ies); 8983 wpa_s->ric_ies = NULL; 8984 8985 wpa_supplicant_update_channel_list(wpa_s, NULL); 8986 8987 free_bss_tmp_disallowed(wpa_s); 8988 8989 #ifndef CONFIG_NO_ROBUST_AV 8990 os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); 8991 #endif /* CONFIG_NO_ROBUST_AV */ 8992 8993 #ifdef CONFIG_PASN 8994 wpas_pasn_auth_stop(wpa_s); 8995 #endif /* CONFIG_PASN */ 8996 8997 if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0) 8998 wpas_restore_permanent_mac_addr(wpa_s); 8999 9000 wpa_s->conf->ignore_old_scan_res = 0; 9001 9002 #ifdef CONFIG_NAN_USD 9003 wpas_nan_usd_flush(wpa_s); 9004 #endif /* CONFIG_NAN_USD */ 9005 } 9006 9007 9008 static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s, 9009 char *buf, size_t buflen) 9010 { 9011 struct wpa_radio_work *work; 9012 char *pos, *end; 9013 struct os_reltime now, diff; 9014 9015 pos = buf; 9016 end = buf + buflen; 9017 9018 os_get_reltime(&now); 9019 9020 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 9021 { 9022 int ret; 9023 9024 os_reltime_sub(&now, &work->time, &diff); 9025 ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%jd.%06ld\n", 9026 work->type, work->wpa_s->ifname, work->freq, 9027 work->started, (intmax_t)diff.sec, 9028 (long)diff.usec); 9029 if (os_snprintf_error(end - pos, ret)) 9030 break; 9031 pos += ret; 9032 } 9033 9034 return pos - buf; 9035 } 9036 9037 9038 static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx) 9039 { 9040 struct wpa_radio_work *work = eloop_ctx; 9041 struct wpa_external_work *ework = work->ctx; 9042 9043 wpa_dbg(work->wpa_s, MSG_DEBUG, 9044 "Timing out external radio work %u (%s)", 9045 ework->id, work->type); 9046 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id); 9047 work->wpa_s->ext_work_in_progress = 0; 9048 radio_work_done(work); 9049 os_free(ework); 9050 } 9051 9052 9053 static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit) 9054 { 9055 struct wpa_external_work *ework = work->ctx; 9056 9057 if (deinit) { 9058 if (work->started) 9059 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 9060 work, NULL); 9061 9062 /* 9063 * work->type points to a buffer in ework, so need to replace 9064 * that here with a fixed string to avoid use of freed memory 9065 * in debug prints. 9066 */ 9067 work->type = "freed-ext-work"; 9068 work->ctx = NULL; 9069 os_free(ework); 9070 return; 9071 } 9072 9073 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)", 9074 ework->id, ework->type); 9075 wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id); 9076 work->wpa_s->ext_work_in_progress = 1; 9077 if (!ework->timeout) 9078 ework->timeout = 10; 9079 eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout, 9080 work, NULL); 9081 } 9082 9083 9084 static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd, 9085 char *buf, size_t buflen) 9086 { 9087 struct wpa_external_work *ework; 9088 char *pos, *pos2; 9089 size_t type_len; 9090 int ret; 9091 unsigned int freq = 0; 9092 9093 /* format: <name> [freq=<MHz>] [timeout=<seconds>] */ 9094 9095 ework = os_zalloc(sizeof(*ework)); 9096 if (ework == NULL) 9097 return -1; 9098 9099 pos = os_strchr(cmd, ' '); 9100 if (pos) { 9101 type_len = pos - cmd; 9102 pos++; 9103 9104 pos2 = os_strstr(pos, "freq="); 9105 if (pos2) 9106 freq = atoi(pos2 + 5); 9107 9108 pos2 = os_strstr(pos, "timeout="); 9109 if (pos2) 9110 ework->timeout = atoi(pos2 + 8); 9111 } else { 9112 type_len = os_strlen(cmd); 9113 } 9114 if (4 + type_len >= sizeof(ework->type)) 9115 type_len = sizeof(ework->type) - 4 - 1; 9116 os_strlcpy(ework->type, "ext:", sizeof(ework->type)); 9117 os_memcpy(ework->type + 4, cmd, type_len); 9118 ework->type[4 + type_len] = '\0'; 9119 9120 wpa_s->ext_work_id++; 9121 if (wpa_s->ext_work_id == 0) 9122 wpa_s->ext_work_id++; 9123 ework->id = wpa_s->ext_work_id; 9124 9125 if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb, 9126 ework) < 0) { 9127 os_free(ework); 9128 return -1; 9129 } 9130 9131 ret = os_snprintf(buf, buflen, "%u", ework->id); 9132 if (os_snprintf_error(buflen, ret)) 9133 return -1; 9134 return ret; 9135 } 9136 9137 9138 static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd) 9139 { 9140 struct wpa_radio_work *work; 9141 unsigned int id = atoi(cmd); 9142 9143 dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list) 9144 { 9145 struct wpa_external_work *ework; 9146 9147 if (os_strncmp(work->type, "ext:", 4) != 0) 9148 continue; 9149 ework = work->ctx; 9150 if (id && ework->id != id) 9151 continue; 9152 wpa_dbg(wpa_s, MSG_DEBUG, 9153 "Completed external radio work %u (%s)", 9154 ework->id, ework->type); 9155 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL); 9156 wpa_s->ext_work_in_progress = 0; 9157 radio_work_done(work); 9158 os_free(ework); 9159 return 3; /* "OK\n" */ 9160 } 9161 9162 return -1; 9163 } 9164 9165 9166 static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd, 9167 char *buf, size_t buflen) 9168 { 9169 if (os_strcmp(cmd, "show") == 0) 9170 return wpas_ctrl_radio_work_show(wpa_s, buf, buflen); 9171 if (os_strncmp(cmd, "add ", 4) == 0) 9172 return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen); 9173 if (os_strncmp(cmd, "done ", 5) == 0) 9174 return wpas_ctrl_radio_work_done(wpa_s, cmd + 4); 9175 return -1; 9176 } 9177 9178 9179 void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) 9180 { 9181 struct wpa_radio_work *work, *tmp; 9182 9183 if (!wpa_s || !wpa_s->radio) 9184 return; 9185 9186 dl_list_for_each_safe(work, tmp, &wpa_s->radio->work, 9187 struct wpa_radio_work, list) { 9188 struct wpa_external_work *ework; 9189 9190 if (os_strncmp(work->type, "ext:", 4) != 0) 9191 continue; 9192 ework = work->ctx; 9193 wpa_dbg(wpa_s, MSG_DEBUG, 9194 "Flushing%s external radio work %u (%s)", 9195 work->started ? " started" : "", ework->id, 9196 ework->type); 9197 if (work->started) 9198 eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, 9199 work, NULL); 9200 radio_work_done(work); 9201 os_free(ework); 9202 } 9203 } 9204 9205 9206 static void wpas_ctrl_eapol_response(void *eloop_ctx, void *timeout_ctx) 9207 { 9208 struct wpa_supplicant *wpa_s = eloop_ctx; 9209 eapol_sm_notify_ctrl_response(wpa_s->eapol); 9210 } 9211 9212 9213 static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value, 9214 unsigned int *scan_id_count, int scan_id[]) 9215 { 9216 const char *pos = value; 9217 9218 while (pos) { 9219 if (*pos == ' ' || *pos == '\0') 9220 break; 9221 if (*scan_id_count == MAX_SCAN_ID) 9222 return -1; 9223 scan_id[(*scan_id_count)++] = atoi(pos); 9224 pos = os_strchr(pos, ','); 9225 if (pos) 9226 pos++; 9227 } 9228 9229 return 0; 9230 } 9231 9232 9233 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, 9234 char *reply, int reply_size, int *reply_len) 9235 { 9236 char *pos; 9237 unsigned int manual_scan_passive = 0; 9238 unsigned int manual_scan_use_id = 0; 9239 unsigned int manual_scan_only_new = 0; 9240 unsigned int scan_only = 0; 9241 unsigned int scan_id_count = 0; 9242 unsigned int manual_non_coloc_6ghz = 0; 9243 int scan_id[MAX_SCAN_ID]; 9244 void (*scan_res_handler)(struct wpa_supplicant *wpa_s, 9245 struct wpa_scan_results *scan_res); 9246 int *manual_scan_freqs = NULL; 9247 struct wpa_ssid_value *ssid = NULL, *ns; 9248 unsigned int ssid_count = 0; 9249 9250 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 9251 *reply_len = -1; 9252 return; 9253 } 9254 9255 if (radio_work_pending(wpa_s, "scan")) { 9256 wpa_printf(MSG_DEBUG, 9257 "Pending scan scheduled - reject new request"); 9258 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9259 return; 9260 } 9261 9262 #ifdef CONFIG_INTERWORKING 9263 if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) { 9264 wpa_printf(MSG_DEBUG, 9265 "Interworking select in progress - reject new scan"); 9266 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9267 return; 9268 } 9269 #endif /* CONFIG_INTERWORKING */ 9270 9271 if (params) { 9272 if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0) 9273 scan_only = 1; 9274 9275 pos = os_strstr(params, "freq="); 9276 if (pos) { 9277 manual_scan_freqs = freq_range_to_channel_list(wpa_s, 9278 pos + 5); 9279 if (manual_scan_freqs == NULL) { 9280 *reply_len = -1; 9281 goto done; 9282 } 9283 } 9284 9285 pos = os_strstr(params, "passive="); 9286 if (pos) 9287 manual_scan_passive = !!atoi(pos + 8); 9288 9289 pos = os_strstr(params, "use_id="); 9290 if (pos) 9291 manual_scan_use_id = atoi(pos + 7); 9292 9293 pos = os_strstr(params, "only_new=1"); 9294 if (pos) 9295 manual_scan_only_new = 1; 9296 9297 pos = os_strstr(params, "scan_id="); 9298 if (pos && scan_id_list_parse(wpa_s, pos + 8, &scan_id_count, 9299 scan_id) < 0) { 9300 *reply_len = -1; 9301 goto done; 9302 } 9303 9304 pos = os_strstr(params, "bssid="); 9305 if (pos) { 9306 u8 bssid[ETH_ALEN]; 9307 9308 pos += 6; 9309 if (hwaddr_aton(pos, bssid)) { 9310 wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos); 9311 *reply_len = -1; 9312 goto done; 9313 } 9314 os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); 9315 9316 wpa_s->next_scan_bssid_wildcard_ssid = 9317 os_strstr(params, "wildcard_ssid=1") != NULL; 9318 } 9319 9320 pos = os_strstr(params, "non_coloc_6ghz="); 9321 if (pos) 9322 manual_non_coloc_6ghz = !!atoi(pos + 15); 9323 9324 pos = params; 9325 while (pos && *pos != '\0') { 9326 if (os_strncmp(pos, "ssid ", 5) == 0) { 9327 char *end; 9328 9329 pos += 5; 9330 end = pos; 9331 while (*end) { 9332 if (*end == '\0' || *end == ' ') 9333 break; 9334 end++; 9335 } 9336 9337 ns = os_realloc_array( 9338 ssid, ssid_count + 1, 9339 sizeof(struct wpa_ssid_value)); 9340 if (ns == NULL) { 9341 *reply_len = -1; 9342 goto done; 9343 } 9344 ssid = ns; 9345 9346 if ((end - pos) & 0x01 || 9347 end - pos > 2 * SSID_MAX_LEN || 9348 hexstr2bin(pos, ssid[ssid_count].ssid, 9349 (end - pos) / 2) < 0) { 9350 wpa_printf(MSG_DEBUG, 9351 "Invalid SSID value '%s'", 9352 pos); 9353 *reply_len = -1; 9354 goto done; 9355 } 9356 ssid[ssid_count].ssid_len = (end - pos) / 2; 9357 wpa_hexdump_ascii(MSG_DEBUG, "scan SSID", 9358 ssid[ssid_count].ssid, 9359 ssid[ssid_count].ssid_len); 9360 ssid_count++; 9361 pos = end; 9362 } 9363 9364 pos = os_strchr(pos, ' '); 9365 if (pos) 9366 pos++; 9367 } 9368 } 9369 9370 wpa_s->num_ssids_from_scan_req = ssid_count; 9371 os_free(wpa_s->ssids_from_scan_req); 9372 if (ssid_count) { 9373 wpa_s->ssids_from_scan_req = ssid; 9374 ssid = NULL; 9375 } else { 9376 wpa_s->ssids_from_scan_req = NULL; 9377 } 9378 9379 if (scan_only) 9380 scan_res_handler = scan_only_handler; 9381 else if (wpa_s->scan_res_handler == scan_only_handler) 9382 scan_res_handler = NULL; 9383 else 9384 scan_res_handler = wpa_s->scan_res_handler; 9385 9386 if (!wpa_s->sched_scanning && !wpa_s->scanning && 9387 ((wpa_s->wpa_state <= WPA_SCANNING) || 9388 (wpa_s->wpa_state == WPA_COMPLETED))) { 9389 wpa_s->manual_scan_passive = manual_scan_passive; 9390 wpa_s->manual_scan_use_id = manual_scan_use_id; 9391 wpa_s->manual_scan_only_new = manual_scan_only_new; 9392 wpa_s->scan_id_count = scan_id_count; 9393 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz; 9394 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 9395 wpa_s->scan_res_handler = scan_res_handler; 9396 os_free(wpa_s->manual_scan_freqs); 9397 wpa_s->manual_scan_freqs = manual_scan_freqs; 9398 manual_scan_freqs = NULL; 9399 9400 wpa_s->normal_scans = 0; 9401 wpa_s->scan_req = MANUAL_SCAN_REQ; 9402 wpa_s->after_wps = 0; 9403 wpa_s->known_wps_freq = 0; 9404 wpa_supplicant_req_scan(wpa_s, 0, 0); 9405 if (wpa_s->manual_scan_use_id) { 9406 wpa_s->manual_scan_id++; 9407 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 9408 wpa_s->manual_scan_id); 9409 *reply_len = os_snprintf(reply, reply_size, "%u\n", 9410 wpa_s->manual_scan_id); 9411 } 9412 } else if (wpa_s->sched_scanning) { 9413 wpa_s->manual_scan_passive = manual_scan_passive; 9414 wpa_s->manual_scan_use_id = manual_scan_use_id; 9415 wpa_s->manual_scan_only_new = manual_scan_only_new; 9416 wpa_s->scan_id_count = scan_id_count; 9417 wpa_s->manual_non_coloc_6ghz = manual_non_coloc_6ghz; 9418 os_memcpy(wpa_s->scan_id, scan_id, scan_id_count * sizeof(int)); 9419 wpa_s->scan_res_handler = scan_res_handler; 9420 os_free(wpa_s->manual_scan_freqs); 9421 wpa_s->manual_scan_freqs = manual_scan_freqs; 9422 manual_scan_freqs = NULL; 9423 9424 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed"); 9425 wpa_supplicant_cancel_sched_scan(wpa_s); 9426 wpa_s->scan_req = MANUAL_SCAN_REQ; 9427 wpa_supplicant_req_scan(wpa_s, 0, 0); 9428 if (wpa_s->manual_scan_use_id) { 9429 wpa_s->manual_scan_id++; 9430 *reply_len = os_snprintf(reply, reply_size, "%u\n", 9431 wpa_s->manual_scan_id); 9432 wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u", 9433 wpa_s->manual_scan_id); 9434 } 9435 } else { 9436 wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request"); 9437 *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n"); 9438 } 9439 9440 done: 9441 os_free(manual_scan_freqs); 9442 os_free(ssid); 9443 } 9444 9445 9446 #ifdef CONFIG_TESTING_OPTIONS 9447 9448 static void wpas_ctrl_iface_mgmt_tx_cb(struct wpa_supplicant *wpa_s, 9449 unsigned int freq, const u8 *dst, 9450 const u8 *src, const u8 *bssid, 9451 const u8 *data, size_t data_len, 9452 enum offchannel_send_action_result 9453 result) 9454 { 9455 wpa_msg(wpa_s, MSG_INFO, "MGMT-TX-STATUS freq=%u dst=" MACSTR 9456 " src=" MACSTR " bssid=" MACSTR " result=%s", 9457 freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), 9458 result == OFFCHANNEL_SEND_ACTION_SUCCESS ? 9459 "SUCCESS" : (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? 9460 "NO_ACK" : "FAILED")); 9461 } 9462 9463 9464 static int wpas_ctrl_iface_mgmt_tx(struct wpa_supplicant *wpa_s, char *cmd) 9465 { 9466 char *pos, *param; 9467 size_t len; 9468 u8 *buf, da[ETH_ALEN], bssid[ETH_ALEN]; 9469 int res, used; 9470 int freq = 0, no_cck = 0, wait_time = 0; 9471 9472 /* <DA> <BSSID> [freq=<MHz>] [wait_time=<ms>] [no_cck=1] 9473 * <action=Action frame payload> */ 9474 9475 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 9476 9477 pos = cmd; 9478 used = hwaddr_aton2(pos, da); 9479 if (used < 0) 9480 return -1; 9481 pos += used; 9482 while (*pos == ' ') 9483 pos++; 9484 used = hwaddr_aton2(pos, bssid); 9485 if (used < 0) 9486 return -1; 9487 pos += used; 9488 9489 param = os_strstr(pos, " freq="); 9490 if (param) { 9491 param += 6; 9492 freq = atoi(param); 9493 } 9494 9495 param = os_strstr(pos, " no_cck="); 9496 if (param) { 9497 param += 8; 9498 no_cck = atoi(param); 9499 } 9500 9501 param = os_strstr(pos, " wait_time="); 9502 if (param) { 9503 param += 11; 9504 wait_time = atoi(param); 9505 } 9506 9507 param = os_strstr(pos, " action="); 9508 if (param == NULL) 9509 return -1; 9510 param += 8; 9511 9512 len = os_strlen(param); 9513 if (len & 1) 9514 return -1; 9515 len /= 2; 9516 9517 buf = os_malloc(len); 9518 if (buf == NULL) 9519 return -1; 9520 9521 if (hexstr2bin(param, buf, len) < 0) { 9522 os_free(buf); 9523 return -1; 9524 } 9525 9526 res = offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, bssid, 9527 buf, len, wait_time, 9528 wpas_ctrl_iface_mgmt_tx_cb, no_cck); 9529 os_free(buf); 9530 return res; 9531 } 9532 9533 9534 static void wpas_ctrl_iface_mgmt_tx_done(struct wpa_supplicant *wpa_s) 9535 { 9536 wpa_printf(MSG_DEBUG, "External MGMT TX - done waiting"); 9537 offchannel_send_action_done(wpa_s); 9538 } 9539 9540 9541 static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s, 9542 char *cmd) 9543 { 9544 char *pos, *param; 9545 size_t len; 9546 u8 *buf; 9547 int freq = 0, datarate = 0, ssi_signal = 0; 9548 union wpa_event_data event; 9549 9550 if (!wpa_s->ext_mgmt_frame_handling) 9551 return -1; 9552 9553 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 9554 9555 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 9556 9557 pos = cmd; 9558 param = os_strstr(pos, "freq="); 9559 if (param) { 9560 param += 5; 9561 freq = atoi(param); 9562 } 9563 9564 param = os_strstr(pos, " datarate="); 9565 if (param) { 9566 param += 10; 9567 datarate = atoi(param); 9568 } 9569 9570 param = os_strstr(pos, " ssi_signal="); 9571 if (param) { 9572 param += 12; 9573 ssi_signal = atoi(param); 9574 } 9575 9576 param = os_strstr(pos, " frame="); 9577 if (param == NULL) 9578 return -1; 9579 param += 7; 9580 9581 len = os_strlen(param); 9582 if (len & 1) 9583 return -1; 9584 len /= 2; 9585 9586 buf = os_malloc(len); 9587 if (buf == NULL) 9588 return -1; 9589 9590 if (hexstr2bin(param, buf, len) < 0) { 9591 os_free(buf); 9592 return -1; 9593 } 9594 9595 os_memset(&event, 0, sizeof(event)); 9596 event.rx_mgmt.freq = freq; 9597 event.rx_mgmt.frame = buf; 9598 event.rx_mgmt.frame_len = len; 9599 event.rx_mgmt.ssi_signal = ssi_signal; 9600 event.rx_mgmt.datarate = datarate; 9601 wpa_s->ext_mgmt_frame_handling = 0; 9602 wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event); 9603 wpa_s->ext_mgmt_frame_handling = 1; 9604 9605 os_free(buf); 9606 9607 return 0; 9608 } 9609 9610 9611 static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s, 9612 char *param) 9613 { 9614 struct wpa_scan_res *res; 9615 struct os_reltime now; 9616 char *pos, *end; 9617 int ret = -1; 9618 9619 if (!param) 9620 return -1; 9621 9622 if (os_strcmp(param, "START") == 0) { 9623 wpa_bss_update_start(wpa_s); 9624 return 0; 9625 } 9626 9627 if (os_strcmp(param, "END") == 0) { 9628 wpa_bss_update_end(wpa_s, NULL, 1); 9629 return 0; 9630 } 9631 9632 if (os_strncmp(param, "BSS ", 4) != 0) 9633 return -1; 9634 param += 3; 9635 9636 res = os_zalloc(sizeof(*res) + os_strlen(param) / 2); 9637 if (!res) 9638 return -1; 9639 9640 pos = os_strstr(param, " flags="); 9641 if (pos) 9642 res->flags = strtol(pos + 7, NULL, 16); 9643 9644 pos = os_strstr(param, " bssid="); 9645 if (pos && hwaddr_aton(pos + 7, res->bssid)) 9646 goto fail; 9647 9648 pos = os_strstr(param, " freq="); 9649 if (pos) 9650 res->freq = atoi(pos + 6); 9651 9652 pos = os_strstr(param, " beacon_int="); 9653 if (pos) 9654 res->beacon_int = atoi(pos + 12); 9655 9656 pos = os_strstr(param, " caps="); 9657 if (pos) 9658 res->caps = strtol(pos + 6, NULL, 16); 9659 9660 pos = os_strstr(param, " qual="); 9661 if (pos) 9662 res->qual = atoi(pos + 6); 9663 9664 pos = os_strstr(param, " noise="); 9665 if (pos) 9666 res->noise = atoi(pos + 7); 9667 9668 pos = os_strstr(param, " level="); 9669 if (pos) 9670 res->level = atoi(pos + 7); 9671 9672 pos = os_strstr(param, " tsf="); 9673 if (pos) 9674 res->tsf = strtoll(pos + 5, NULL, 16); 9675 9676 pos = os_strstr(param, " age="); 9677 if (pos) 9678 res->age = atoi(pos + 5); 9679 9680 pos = os_strstr(param, " est_throughput="); 9681 if (pos) 9682 res->est_throughput = atoi(pos + 16); 9683 9684 pos = os_strstr(param, " snr="); 9685 if (pos) 9686 res->snr = atoi(pos + 5); 9687 9688 pos = os_strstr(param, " parent_tsf="); 9689 if (pos) 9690 res->parent_tsf = strtoll(pos + 7, NULL, 16); 9691 9692 pos = os_strstr(param, " tsf_bssid="); 9693 if (pos && hwaddr_aton(pos + 11, res->tsf_bssid)) 9694 goto fail; 9695 9696 pos = os_strstr(param, " ie="); 9697 if (pos) { 9698 pos += 4; 9699 end = os_strchr(pos, ' '); 9700 if (!end) 9701 end = pos + os_strlen(pos); 9702 res->ie_len = (end - pos) / 2; 9703 if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len)) 9704 goto fail; 9705 } 9706 9707 pos = os_strstr(param, " beacon_ie="); 9708 if (pos) { 9709 pos += 11; 9710 end = os_strchr(pos, ' '); 9711 if (!end) 9712 end = pos + os_strlen(pos); 9713 res->beacon_ie_len = (end - pos) / 2; 9714 if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len, 9715 res->beacon_ie_len)) 9716 goto fail; 9717 } 9718 9719 os_get_reltime(&now); 9720 wpa_bss_update_scan_res(wpa_s, res, &now); 9721 ret = 0; 9722 fail: 9723 os_free(res); 9724 9725 return ret; 9726 } 9727 9728 9729 static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s, 9730 char *param) 9731 { 9732 union wpa_event_data event; 9733 struct assoc_info *ai; 9734 char *ctx = NULL; 9735 int ret = -1; 9736 struct wpabuf *req_ies = NULL; 9737 struct wpabuf *resp_ies = NULL; 9738 struct wpabuf *resp_frame = NULL; 9739 struct wpabuf *beacon_ies = NULL; 9740 struct wpabuf *key_replay_ctr = NULL; 9741 struct wpabuf *ptk_kck = NULL; 9742 struct wpabuf *ptk_kek = NULL; 9743 struct wpabuf *fils_pmk = NULL; 9744 char *str, *pos; 9745 u8 addr[ETH_ALEN]; 9746 u8 fils_pmkid[PMKID_LEN]; 9747 9748 os_memset(&event, 0, sizeof(event)); 9749 ai = &event.assoc_info; 9750 9751 while ((str = str_token(param, " ", &ctx))) { 9752 pos = os_strchr(str, '='); 9753 if (!pos) 9754 goto fail; 9755 *pos++ = '\0'; 9756 9757 if (os_strcmp(str, "reassoc") == 0) { 9758 ai->reassoc = atoi(pos); 9759 } else if (os_strcmp(str, "req_ies") == 0) { 9760 wpabuf_free(req_ies); 9761 req_ies = wpabuf_parse_bin(pos); 9762 if (!req_ies) 9763 goto fail; 9764 ai->req_ies = wpabuf_head(req_ies); 9765 ai->req_ies_len = wpabuf_len(req_ies); 9766 } else if (os_strcmp(str, "resp_ies") == 0) { 9767 wpabuf_free(resp_ies); 9768 resp_ies = wpabuf_parse_bin(pos); 9769 if (!resp_ies) 9770 goto fail; 9771 ai->resp_ies = wpabuf_head(resp_ies); 9772 ai->resp_ies_len = wpabuf_len(resp_ies); 9773 } else if (os_strcmp(str, "resp_frame") == 0) { 9774 wpabuf_free(resp_frame); 9775 resp_frame = wpabuf_parse_bin(pos); 9776 if (!resp_frame) 9777 goto fail; 9778 ai->resp_frame = wpabuf_head(resp_frame); 9779 ai->resp_frame_len = wpabuf_len(resp_frame); 9780 } else if (os_strcmp(str, "beacon_ies") == 0) { 9781 wpabuf_free(beacon_ies); 9782 beacon_ies = wpabuf_parse_bin(pos); 9783 if (!beacon_ies) 9784 goto fail; 9785 ai->beacon_ies = wpabuf_head(beacon_ies); 9786 ai->beacon_ies_len = wpabuf_len(beacon_ies); 9787 } else if (os_strcmp(str, "freq") == 0) { 9788 ai->freq = atoi(pos); 9789 } else if (os_strcmp(str, "wmm::info_bitmap") == 0) { 9790 ai->wmm_params.info_bitmap = atoi(pos); 9791 } else if (os_strcmp(str, "wmm::uapsd_queues") == 0) { 9792 ai->wmm_params.uapsd_queues = atoi(pos); 9793 } else if (os_strcmp(str, "addr") == 0) { 9794 if (hwaddr_aton(pos, addr)) 9795 goto fail; 9796 ai->addr = addr; 9797 } else if (os_strcmp(str, "authorized") == 0) { 9798 ai->authorized = atoi(pos); 9799 } else if (os_strcmp(str, "key_replay_ctr") == 0) { 9800 wpabuf_free(key_replay_ctr); 9801 key_replay_ctr = wpabuf_parse_bin(pos); 9802 if (!key_replay_ctr) 9803 goto fail; 9804 ai->key_replay_ctr = wpabuf_head(key_replay_ctr); 9805 ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr); 9806 } else if (os_strcmp(str, "ptk_kck") == 0) { 9807 wpabuf_free(ptk_kck); 9808 ptk_kck = wpabuf_parse_bin(pos); 9809 if (!ptk_kck) 9810 goto fail; 9811 ai->ptk_kck = wpabuf_head(ptk_kck); 9812 ai->ptk_kck_len = wpabuf_len(ptk_kck); 9813 } else if (os_strcmp(str, "ptk_kek") == 0) { 9814 wpabuf_free(ptk_kek); 9815 ptk_kek = wpabuf_parse_bin(pos); 9816 if (!ptk_kek) 9817 goto fail; 9818 ai->ptk_kek = wpabuf_head(ptk_kek); 9819 ai->ptk_kek_len = wpabuf_len(ptk_kek); 9820 } else if (os_strcmp(str, "subnet_status") == 0) { 9821 ai->subnet_status = atoi(pos); 9822 } else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) { 9823 ai->fils_erp_next_seq_num = atoi(pos); 9824 } else if (os_strcmp(str, "fils_pmk") == 0) { 9825 wpabuf_free(fils_pmk); 9826 fils_pmk = wpabuf_parse_bin(pos); 9827 if (!fils_pmk) 9828 goto fail; 9829 ai->fils_pmk = wpabuf_head(fils_pmk); 9830 ai->fils_pmk_len = wpabuf_len(fils_pmk); 9831 } else if (os_strcmp(str, "fils_pmkid") == 0) { 9832 if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0) 9833 goto fail; 9834 ai->fils_pmkid = fils_pmkid; 9835 } else { 9836 goto fail; 9837 } 9838 } 9839 9840 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event); 9841 ret = 0; 9842 fail: 9843 wpabuf_free(req_ies); 9844 wpabuf_free(resp_ies); 9845 wpabuf_free(resp_frame); 9846 wpabuf_free(beacon_ies); 9847 wpabuf_free(key_replay_ctr); 9848 wpabuf_free(ptk_kck); 9849 wpabuf_free(ptk_kek); 9850 wpabuf_free(fils_pmk); 9851 return ret; 9852 } 9853 9854 9855 static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) 9856 { 9857 char *pos, *param; 9858 union wpa_event_data event; 9859 enum wpa_event_type ev; 9860 9861 /* <event name> [parameters..] */ 9862 9863 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - external driver event: %s", cmd); 9864 9865 pos = cmd; 9866 param = os_strchr(pos, ' '); 9867 if (param) 9868 *param++ = '\0'; 9869 9870 os_memset(&event, 0, sizeof(event)); 9871 9872 if (os_strcmp(cmd, "INTERFACE_ENABLED") == 0) { 9873 ev = EVENT_INTERFACE_ENABLED; 9874 } else if (os_strcmp(cmd, "INTERFACE_DISABLED") == 0) { 9875 ev = EVENT_INTERFACE_DISABLED; 9876 } else if (os_strcmp(cmd, "AVOID_FREQUENCIES") == 0) { 9877 ev = EVENT_AVOID_FREQUENCIES; 9878 if (param == NULL) 9879 param = ""; 9880 if (freq_range_list_parse(&event.freq_range, param) < 0) 9881 return -1; 9882 wpa_supplicant_event(wpa_s, ev, &event); 9883 os_free(event.freq_range.range); 9884 return 0; 9885 } else if (os_strcmp(cmd, "SCAN_RES") == 0) { 9886 return wpas_ctrl_iface_driver_scan_res(wpa_s, param); 9887 } else if (os_strcmp(cmd, "ASSOC") == 0) { 9888 return wpas_ctrl_iface_driver_event_assoc(wpa_s, param); 9889 } else { 9890 wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", 9891 cmd); 9892 return -1; 9893 } 9894 9895 wpa_supplicant_event(wpa_s, ev, &event); 9896 9897 return 0; 9898 } 9899 9900 9901 static int wpas_ctrl_iface_eapol_rx(struct wpa_supplicant *wpa_s, char *cmd) 9902 { 9903 char *pos; 9904 u8 src[ETH_ALEN], *buf; 9905 int used; 9906 size_t len; 9907 9908 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 9909 9910 pos = cmd; 9911 used = hwaddr_aton2(pos, src); 9912 if (used < 0) 9913 return -1; 9914 pos += used; 9915 while (*pos == ' ') 9916 pos++; 9917 9918 len = os_strlen(pos); 9919 if (len & 1) 9920 return -1; 9921 len /= 2; 9922 9923 buf = os_malloc(len); 9924 if (buf == NULL) 9925 return -1; 9926 9927 if (hexstr2bin(pos, buf, len) < 0) { 9928 os_free(buf); 9929 return -1; 9930 } 9931 9932 wpa_supplicant_rx_eapol(wpa_s, src, buf, len, FRAME_ENCRYPTION_UNKNOWN); 9933 os_free(buf); 9934 9935 return 0; 9936 } 9937 9938 9939 static int wpas_ctrl_iface_eapol_tx(struct wpa_supplicant *wpa_s, char *cmd) 9940 { 9941 char *pos; 9942 u8 dst[ETH_ALEN], *buf; 9943 int used, ret; 9944 size_t len; 9945 unsigned int prev; 9946 9947 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd); 9948 9949 pos = cmd; 9950 used = hwaddr_aton2(pos, dst); 9951 if (used < 0) 9952 return -1; 9953 pos += used; 9954 while (*pos == ' ') 9955 pos++; 9956 9957 len = os_strlen(pos); 9958 if (len & 1) 9959 return -1; 9960 len /= 2; 9961 9962 buf = os_malloc(len); 9963 if (!buf || hexstr2bin(pos, buf, len) < 0) { 9964 os_free(buf); 9965 return -1; 9966 } 9967 9968 prev = wpa_s->ext_eapol_frame_io; 9969 wpa_s->ext_eapol_frame_io = 0; 9970 ret = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, buf, len); 9971 wpa_s->ext_eapol_frame_io = prev; 9972 os_free(buf); 9973 9974 return ret; 9975 } 9976 9977 9978 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 9979 { 9980 size_t i; 9981 u32 sum = 0; 9982 const u16 *pos = buf; 9983 9984 for (i = 0; i < len / 2; i++) 9985 sum += *pos++; 9986 9987 while (sum >> 16) 9988 sum = (sum & 0xffff) + (sum >> 16); 9989 9990 return sum ^ 0xffff; 9991 } 9992 9993 9994 #define HWSIM_PACKETLEN 1500 9995 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 9996 9997 static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 9998 size_t len) 9999 { 10000 struct wpa_supplicant *wpa_s = ctx; 10001 const struct ether_header *eth; 10002 struct ip ip; 10003 const u8 *pos; 10004 unsigned int i; 10005 char extra[30]; 10006 10007 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 10008 wpa_printf(MSG_DEBUG, 10009 "test data: RX - ignore unexpected length %d", 10010 (int) len); 10011 return; 10012 } 10013 10014 eth = (const struct ether_header *) buf; 10015 os_memcpy(&ip, eth + 1, sizeof(ip)); 10016 pos = &buf[sizeof(*eth) + sizeof(ip)]; 10017 10018 if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { 10019 wpa_printf(MSG_DEBUG, 10020 "test data: RX - ignore unexpected IP header"); 10021 return; 10022 } 10023 10024 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) { 10025 if (*pos != (u8) i) { 10026 wpa_printf(MSG_DEBUG, 10027 "test data: RX - ignore mismatching payload"); 10028 return; 10029 } 10030 pos++; 10031 } 10032 extra[0] = '\0'; 10033 if (ntohs(ip.ip_len) != HWSIM_IP_LEN) 10034 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len)); 10035 wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 10036 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 10037 } 10038 10039 10040 static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s, 10041 char *cmd) 10042 { 10043 int enabled = atoi(cmd); 10044 char *pos; 10045 const char *ifname; 10046 10047 if (!enabled) { 10048 if (wpa_s->l2_test) { 10049 l2_packet_deinit(wpa_s->l2_test); 10050 wpa_s->l2_test = NULL; 10051 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Disabled"); 10052 } 10053 return 0; 10054 } 10055 10056 if (wpa_s->l2_test) 10057 return 0; 10058 10059 pos = os_strstr(cmd, " ifname="); 10060 if (pos) 10061 ifname = pos + 8; 10062 else 10063 ifname = wpa_s->ifname; 10064 10065 wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr, 10066 ETHERTYPE_IP, wpas_data_test_rx, 10067 wpa_s, 1); 10068 if (wpa_s->l2_test == NULL) 10069 return -1; 10070 10071 wpa_dbg(wpa_s, MSG_DEBUG, "test data: Enabled"); 10072 10073 return 0; 10074 } 10075 10076 10077 static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) 10078 { 10079 u8 dst[ETH_ALEN], src[ETH_ALEN]; 10080 char *pos, *pos2; 10081 int used; 10082 long int val; 10083 u8 tos; 10084 u8 buf[2 + HWSIM_PACKETLEN]; 10085 struct ether_header *eth; 10086 struct ip *ip; 10087 u8 *dpos; 10088 unsigned int i; 10089 size_t send_len = HWSIM_IP_LEN; 10090 10091 if (wpa_s->l2_test == NULL) 10092 return -1; 10093 10094 /* format: <dst> <src> <tos> [len=<length>] */ 10095 10096 pos = cmd; 10097 used = hwaddr_aton2(pos, dst); 10098 if (used < 0) 10099 return -1; 10100 pos += used; 10101 while (*pos == ' ') 10102 pos++; 10103 used = hwaddr_aton2(pos, src); 10104 if (used < 0) 10105 return -1; 10106 pos += used; 10107 10108 val = strtol(pos, &pos2, 0); 10109 if (val < 0 || val > 0xff) 10110 return -1; 10111 tos = val; 10112 10113 pos = os_strstr(pos2, " len="); 10114 if (pos) { 10115 i = atoi(pos + 5); 10116 if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 10117 return -1; 10118 send_len = i; 10119 } 10120 10121 eth = (struct ether_header *) &buf[2]; 10122 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 10123 os_memcpy(eth->ether_shost, src, ETH_ALEN); 10124 eth->ether_type = htons(ETHERTYPE_IP); 10125 ip = (struct ip *) (eth + 1); 10126 os_memset(ip, 0, sizeof(*ip)); 10127 ip->ip_hl = 5; 10128 ip->ip_v = 4; 10129 ip->ip_ttl = 64; 10130 ip->ip_tos = tos; 10131 ip->ip_len = htons(send_len); 10132 ip->ip_p = 1; 10133 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 10134 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 10135 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip)); 10136 dpos = (u8 *) (ip + 1); 10137 for (i = 0; i < send_len - sizeof(*ip); i++) 10138 *dpos++ = i; 10139 10140 if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2], 10141 sizeof(struct ether_header) + send_len) < 0) 10142 return -1; 10143 10144 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR 10145 " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 10146 10147 return 0; 10148 } 10149 10150 10151 static int wpas_ctrl_iface_data_test_frame(struct wpa_supplicant *wpa_s, 10152 char *cmd) 10153 { 10154 u8 *buf; 10155 struct ether_header *eth; 10156 struct l2_packet_data *l2 = NULL; 10157 size_t len; 10158 u16 ethertype; 10159 int res = -1; 10160 10161 len = os_strlen(cmd); 10162 if (len & 1 || len < ETH_HLEN * 2) 10163 return -1; 10164 len /= 2; 10165 10166 buf = os_malloc(len); 10167 if (buf == NULL) 10168 return -1; 10169 10170 if (hexstr2bin(cmd, buf, len) < 0) 10171 goto done; 10172 10173 eth = (struct ether_header *) buf; 10174 ethertype = ntohs(eth->ether_type); 10175 10176 l2 = l2_packet_init(wpa_s->ifname, wpa_s->own_addr, ethertype, 10177 wpas_data_test_rx, wpa_s, 1); 10178 if (l2 == NULL) 10179 goto done; 10180 10181 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 10182 wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX frame res=%d", res); 10183 done: 10184 if (l2) 10185 l2_packet_deinit(l2); 10186 os_free(buf); 10187 10188 return res < 0 ? -1 : 0; 10189 } 10190 10191 10192 static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx) 10193 { 10194 struct wpa_supplicant *wpa_s = eloop_ctx; 10195 int i, count = (intptr_t) timeout_ctx; 10196 10197 wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages", 10198 count); 10199 for (i = 0; i < count; i++) { 10200 wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d", 10201 i + 1, count); 10202 } 10203 } 10204 10205 10206 static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd) 10207 { 10208 int count; 10209 10210 count = atoi(cmd); 10211 if (count <= 0) 10212 return -1; 10213 10214 return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s, 10215 (void *) (intptr_t) count); 10216 } 10217 10218 10219 static int wpas_get_hex_buf(const char *val, struct wpabuf **ret) 10220 { 10221 struct wpabuf *buf; 10222 size_t len; 10223 10224 len = os_strlen(val); 10225 if (len & 1) 10226 return -1; 10227 len /= 2; 10228 10229 if (len == 0) { 10230 buf = NULL; 10231 } else { 10232 buf = wpabuf_alloc(len); 10233 if (!buf) 10234 return -1; 10235 10236 if (hexstr2bin(val, wpabuf_put(buf, len), len) < 0) { 10237 wpabuf_free(buf); 10238 return -1; 10239 } 10240 } 10241 10242 *ret = buf; 10243 return 0; 10244 } 10245 10246 10247 static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s, 10248 const char *cmd) 10249 { 10250 struct wpabuf *buf; 10251 10252 if (wpas_get_hex_buf(cmd, &buf) < 0) 10253 return -1; 10254 wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf); 10255 return 0; 10256 } 10257 10258 10259 static int wpas_ctrl_test_eapol_m2_elems(struct wpa_supplicant *wpa_s, 10260 const char *cmd) 10261 { 10262 struct wpabuf *buf; 10263 10264 if (wpas_get_hex_buf(cmd, &buf) < 0) 10265 return -1; 10266 wpa_sm_set_test_eapol_m2_elems(wpa_s->wpa, buf); 10267 return 0; 10268 } 10269 10270 10271 static int wpas_ctrl_test_eapol_m4_elems(struct wpa_supplicant *wpa_s, 10272 const char *cmd) 10273 { 10274 struct wpabuf *buf; 10275 10276 if (wpas_get_hex_buf(cmd, &buf) < 0) 10277 return -1; 10278 wpa_sm_set_test_eapol_m4_elems(wpa_s->wpa, buf); 10279 return 0; 10280 } 10281 10282 10283 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s) 10284 { 10285 u8 zero[WPA_TK_MAX_LEN]; 10286 10287 if (wpa_s->last_tk_alg == WPA_ALG_NONE) 10288 return -1; 10289 10290 wpa_printf(MSG_INFO, "TESTING: Reset PN"); 10291 os_memset(zero, 0, sizeof(zero)); 10292 10293 /* First, use a zero key to avoid any possible duplicate key avoidance 10294 * in the driver. */ 10295 if (wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, wpa_s->last_tk_addr, 10296 wpa_s->last_tk_key_idx, 1, zero, 6, 10297 zero, wpa_s->last_tk_len, 10298 KEY_FLAG_PAIRWISE_RX_TX) < 0) 10299 return -1; 10300 10301 /* Set the previously configured key to reset its TSC/RSC */ 10302 return wpa_drv_set_key(wpa_s, -1, wpa_s->last_tk_alg, 10303 wpa_s->last_tk_addr, 10304 wpa_s->last_tk_key_idx, 1, zero, 6, 10305 wpa_s->last_tk, wpa_s->last_tk_len, 10306 KEY_FLAG_PAIRWISE_RX_TX); 10307 } 10308 10309 10310 static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) 10311 { 10312 const char *pos = cmd; 10313 int error, pairwise; 10314 10315 error = atoi(pos); 10316 pos = os_strchr(pos, ' '); 10317 if (!pos) 10318 return -1; 10319 pairwise = atoi(pos); 10320 wpa_sm_key_request(wpa_s->wpa, error, pairwise); 10321 return 0; 10322 } 10323 10324 10325 static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) 10326 { 10327 #ifdef CONFIG_SME 10328 struct wpa_driver_associate_params params; 10329 int ret; 10330 10331 os_memset(¶ms, 0, sizeof(params)); 10332 params.bssid = wpa_s->bssid; 10333 params.ssid = wpa_s->sme.ssid; 10334 params.ssid_len = wpa_s->sme.ssid_len; 10335 params.freq.freq = wpa_s->sme.freq; 10336 if (wpa_s->last_assoc_req_wpa_ie) { 10337 params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); 10338 params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); 10339 } 10340 params.pairwise_suite = wpa_s->pairwise_cipher; 10341 params.group_suite = wpa_s->group_cipher; 10342 params.mgmt_group_suite = wpa_s->mgmt_group_cipher; 10343 params.key_mgmt_suite = wpa_s->key_mgmt; 10344 params.wpa_proto = wpa_s->wpa_proto; 10345 params.mgmt_frame_protection = wpa_s->sme.mfp; 10346 params.rrm_used = wpa_s->rrm.rrm_used; 10347 if (wpa_s->sme.prev_bssid_set) 10348 params.prev_bssid = wpa_s->sme.prev_bssid; 10349 wpa_printf(MSG_INFO, "TESTING: Resend association request"); 10350 ret = wpa_drv_associate(wpa_s, ¶ms); 10351 wpa_s->testing_resend_assoc = 1; 10352 return ret; 10353 #else /* CONFIG_SME */ 10354 return -1; 10355 #endif /* CONFIG_SME */ 10356 } 10357 10358 10359 static int wpas_ctrl_iface_send_twt_setup(struct wpa_supplicant *wpa_s, 10360 const char *cmd) 10361 { 10362 u8 dtok = 1; 10363 int exponent = 10; 10364 int mantissa = 8192; 10365 u8 min_twt = 255; 10366 unsigned long long twt = 0; 10367 bool requestor = true; 10368 int setup_cmd = 0; 10369 bool trigger = true; 10370 bool implicit = true; 10371 bool flow_type = true; 10372 int flow_id = 0; 10373 bool protection = false; 10374 u8 twt_channel = 0; 10375 u8 control = BIT(4); /* Control field (IEEE Std 802.11ax-2021, 10376 * Figure 9-687 - Control field format): 10377 * B4 = TWT Information Frame Disabled */ 10378 const char *tok_s; 10379 10380 tok_s = os_strstr(cmd, " dialog="); 10381 if (tok_s) 10382 dtok = atoi(tok_s + os_strlen(" dialog=")); 10383 10384 tok_s = os_strstr(cmd, " exponent="); 10385 if (tok_s) 10386 exponent = atoi(tok_s + os_strlen(" exponent=")); 10387 10388 tok_s = os_strstr(cmd, " mantissa="); 10389 if (tok_s) 10390 mantissa = atoi(tok_s + os_strlen(" mantissa=")); 10391 10392 tok_s = os_strstr(cmd, " min_twt="); 10393 if (tok_s) 10394 min_twt = atoi(tok_s + os_strlen(" min_twt=")); 10395 10396 tok_s = os_strstr(cmd, " setup_cmd="); 10397 if (tok_s) 10398 setup_cmd = atoi(tok_s + os_strlen(" setup_cmd=")); 10399 10400 tok_s = os_strstr(cmd, " twt="); 10401 if (tok_s && 10402 sscanf(tok_s + os_strlen(" twt="), "%llu", &twt) != 1) 10403 return -1; 10404 10405 tok_s = os_strstr(cmd, " requestor="); 10406 if (tok_s) 10407 requestor = atoi(tok_s + os_strlen(" requestor=")); 10408 10409 tok_s = os_strstr(cmd, " trigger="); 10410 if (tok_s) 10411 trigger = atoi(tok_s + os_strlen(" trigger=")); 10412 10413 tok_s = os_strstr(cmd, " implicit="); 10414 if (tok_s) 10415 implicit = atoi(tok_s + os_strlen(" implicit=")); 10416 10417 tok_s = os_strstr(cmd, " flow_type="); 10418 if (tok_s) 10419 flow_type = atoi(tok_s + os_strlen(" flow_type=")); 10420 10421 tok_s = os_strstr(cmd, " flow_id="); 10422 if (tok_s) 10423 flow_id = atoi(tok_s + os_strlen(" flow_id=")); 10424 10425 tok_s = os_strstr(cmd, " protection="); 10426 if (tok_s) 10427 protection = atoi(tok_s + os_strlen(" protection=")); 10428 10429 tok_s = os_strstr(cmd, " twt_channel="); 10430 if (tok_s) 10431 twt_channel = atoi(tok_s + os_strlen(" twt_channel=")); 10432 10433 tok_s = os_strstr(cmd, " control="); 10434 if (tok_s) 10435 control = atoi(tok_s + os_strlen(" control=")); 10436 10437 return wpas_twt_send_setup(wpa_s, dtok, exponent, mantissa, min_twt, 10438 setup_cmd, twt, requestor, trigger, implicit, 10439 flow_type, flow_id, protection, twt_channel, 10440 control); 10441 } 10442 10443 10444 static int wpas_ctrl_iface_send_twt_teardown(struct wpa_supplicant *wpa_s, 10445 const char *cmd) 10446 { 10447 u8 flags = 0x1; 10448 const char *tok_s; 10449 10450 tok_s = os_strstr(cmd, " flags="); 10451 if (tok_s) 10452 flags = atoi(tok_s + os_strlen(" flags=")); 10453 10454 return wpas_twt_send_teardown(wpa_s, flags); 10455 } 10456 10457 #endif /* CONFIG_TESTING_OPTIONS */ 10458 10459 10460 static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd) 10461 { 10462 char *pos = cmd; 10463 int frame; 10464 size_t len; 10465 struct wpabuf *buf; 10466 struct ieee802_11_elems elems; 10467 10468 frame = atoi(pos); 10469 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10470 return -1; 10471 wpa_s = wpas_vendor_elem(wpa_s, frame); 10472 10473 pos = os_strchr(pos, ' '); 10474 if (pos == NULL) 10475 return -1; 10476 pos++; 10477 10478 len = os_strlen(pos); 10479 if (len == 0) 10480 return 0; 10481 if (len & 1) 10482 return -1; 10483 len /= 2; 10484 10485 buf = wpabuf_alloc(len); 10486 if (buf == NULL) 10487 return -1; 10488 10489 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 10490 wpabuf_free(buf); 10491 return -1; 10492 } 10493 10494 if (ieee802_11_parse_elems(wpabuf_head_u8(buf), len, &elems, 0) == 10495 ParseFailed) { 10496 wpabuf_free(buf); 10497 return -1; 10498 } 10499 10500 if (wpa_s->vendor_elem[frame] == NULL) { 10501 wpa_s->vendor_elem[frame] = buf; 10502 goto update_ies; 10503 } 10504 10505 if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) { 10506 wpabuf_free(buf); 10507 return -1; 10508 } 10509 10510 wpabuf_put_buf(wpa_s->vendor_elem[frame], buf); 10511 wpabuf_free(buf); 10512 10513 update_ies: 10514 wpas_vendor_elem_update(wpa_s); 10515 10516 if (frame == VENDOR_ELEM_PROBE_REQ || 10517 frame == VENDOR_ELEM_PROBE_REQ_P2P) 10518 wpa_supplicant_set_default_scan_ies(wpa_s); 10519 10520 return 0; 10521 } 10522 10523 10524 static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd, 10525 char *buf, size_t buflen) 10526 { 10527 int frame = atoi(cmd); 10528 10529 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10530 return -1; 10531 wpa_s = wpas_vendor_elem(wpa_s, frame); 10532 10533 if (wpa_s->vendor_elem[frame] == NULL) 10534 return 0; 10535 10536 return wpa_snprintf_hex(buf, buflen, 10537 wpabuf_head_u8(wpa_s->vendor_elem[frame]), 10538 wpabuf_len(wpa_s->vendor_elem[frame])); 10539 } 10540 10541 10542 static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd) 10543 { 10544 char *pos = cmd; 10545 int frame; 10546 size_t len; 10547 u8 *buf; 10548 struct ieee802_11_elems elems; 10549 int res; 10550 10551 frame = atoi(pos); 10552 if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES) 10553 return -1; 10554 wpa_s = wpas_vendor_elem(wpa_s, frame); 10555 10556 pos = os_strchr(pos, ' '); 10557 if (pos == NULL) 10558 return -1; 10559 pos++; 10560 10561 if (*pos == '*') { 10562 wpabuf_free(wpa_s->vendor_elem[frame]); 10563 wpa_s->vendor_elem[frame] = NULL; 10564 wpas_vendor_elem_update(wpa_s); 10565 return 0; 10566 } 10567 10568 if (wpa_s->vendor_elem[frame] == NULL) 10569 return -1; 10570 10571 len = os_strlen(pos); 10572 if (len == 0) 10573 return 0; 10574 if (len & 1) 10575 return -1; 10576 len /= 2; 10577 10578 buf = os_malloc(len); 10579 if (buf == NULL) 10580 return -1; 10581 10582 if (hexstr2bin(pos, buf, len) < 0) { 10583 os_free(buf); 10584 return -1; 10585 } 10586 10587 if (ieee802_11_parse_elems(buf, len, &elems, 0) == ParseFailed) { 10588 os_free(buf); 10589 return -1; 10590 } 10591 10592 res = wpas_vendor_elem_remove(wpa_s, frame, buf, len); 10593 os_free(buf); 10594 return res; 10595 } 10596 10597 10598 #ifndef CONFIG_NO_RRM 10599 10600 static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep) 10601 { 10602 struct wpa_supplicant *wpa_s = ctx; 10603 size_t len; 10604 const u8 *data; 10605 10606 /* 10607 * Neighbor Report element (IEEE P802.11-REVmc/D5.0) 10608 * BSSID[6] 10609 * BSSID Information[4] 10610 * Operating Class[1] 10611 * Channel Number[1] 10612 * PHY Type[1] 10613 * Optional Subelements[variable] 10614 */ 10615 #define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1) 10616 10617 if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) { 10618 wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED); 10619 goto out; 10620 } 10621 10622 data = wpabuf_head_u8(neighbor_rep); 10623 len = wpabuf_len(neighbor_rep); 10624 10625 while (len >= 2 + NR_IE_MIN_LEN) { 10626 const u8 *nr; 10627 char lci[256 * 2 + 1]; 10628 char civic[256 * 2 + 1]; 10629 u8 nr_len = data[1]; 10630 const u8 *pos = data, *end; 10631 10632 if (pos[0] != WLAN_EID_NEIGHBOR_REPORT || 10633 nr_len < NR_IE_MIN_LEN) { 10634 wpa_dbg(wpa_s, MSG_DEBUG, 10635 "CTRL: Invalid Neighbor Report element: id=%u len=%u", 10636 data[0], nr_len); 10637 goto out; 10638 } 10639 10640 if (2U + nr_len > len) { 10641 wpa_dbg(wpa_s, MSG_DEBUG, 10642 "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u", 10643 data[0], len, nr_len); 10644 goto out; 10645 } 10646 pos += 2; 10647 end = pos + nr_len; 10648 10649 nr = pos; 10650 pos += NR_IE_MIN_LEN; 10651 10652 lci[0] = '\0'; 10653 civic[0] = '\0'; 10654 while (end - pos > 2) { 10655 u8 s_id, s_len; 10656 10657 s_id = *pos++; 10658 s_len = *pos++; 10659 if (s_len > end - pos) 10660 goto out; 10661 if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) { 10662 /* Measurement Token[1] */ 10663 /* Measurement Report Mode[1] */ 10664 /* Measurement Type[1] */ 10665 /* Measurement Report[variable] */ 10666 switch (pos[2]) { 10667 case MEASURE_TYPE_LCI: 10668 if (lci[0]) 10669 break; 10670 wpa_snprintf_hex(lci, sizeof(lci), 10671 pos, s_len); 10672 break; 10673 case MEASURE_TYPE_LOCATION_CIVIC: 10674 if (civic[0]) 10675 break; 10676 wpa_snprintf_hex(civic, sizeof(civic), 10677 pos, s_len); 10678 break; 10679 } 10680 } 10681 10682 pos += s_len; 10683 } 10684 10685 wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED 10686 "bssid=" MACSTR 10687 " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s", 10688 MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN), 10689 nr[ETH_ALEN + 4], nr[ETH_ALEN + 5], 10690 nr[ETH_ALEN + 6], 10691 lci[0] ? " lci=" : "", lci, 10692 civic[0] ? " civic=" : "", civic); 10693 10694 data = end; 10695 len -= 2 + nr_len; 10696 } 10697 10698 out: 10699 wpabuf_free(neighbor_rep); 10700 } 10701 10702 10703 static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s, 10704 char *cmd) 10705 { 10706 struct wpa_ssid_value ssid, *ssid_p = NULL; 10707 int ret, lci = 0, civic = 0; 10708 char *ssid_s; 10709 10710 ssid_s = os_strstr(cmd, "ssid="); 10711 if (ssid_s) { 10712 if (ssid_parse(ssid_s + 5, &ssid)) { 10713 wpa_msg(wpa_s, MSG_INFO, 10714 "CTRL: Send Neighbor Report: bad SSID"); 10715 return -1; 10716 } 10717 10718 ssid_p = &ssid; 10719 10720 /* 10721 * Move cmd after the SSID text that may include "lci" or 10722 * "civic". 10723 */ 10724 cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' '); 10725 if (cmd) 10726 cmd++; 10727 10728 } 10729 10730 if (cmd && os_strstr(cmd, "lci")) 10731 lci = 1; 10732 10733 if (cmd && os_strstr(cmd, "civic")) 10734 civic = 1; 10735 10736 ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, 10737 wpas_ctrl_neighbor_rep_cb, 10738 wpa_s); 10739 10740 return ret; 10741 } 10742 10743 #endif /* CONFIG_NO_RRM */ 10744 10745 10746 static int wpas_ctrl_iface_erp_flush(struct wpa_supplicant *wpa_s) 10747 { 10748 eapol_sm_erp_flush(wpa_s->eapol); 10749 return 0; 10750 } 10751 10752 10753 static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, 10754 char *cmd) 10755 { 10756 char *token, *context = NULL; 10757 unsigned int enable = ~0, type = 0; 10758 u8 _addr[ETH_ALEN], _mask[ETH_ALEN]; 10759 u8 *addr = NULL, *mask = NULL; 10760 10761 while ((token = str_token(cmd, " ", &context))) { 10762 if (os_strcasecmp(token, "scan") == 0) { 10763 type |= MAC_ADDR_RAND_SCAN; 10764 } else if (os_strcasecmp(token, "sched") == 0) { 10765 type |= MAC_ADDR_RAND_SCHED_SCAN; 10766 } else if (os_strcasecmp(token, "pno") == 0) { 10767 type |= MAC_ADDR_RAND_PNO; 10768 } else if (os_strcasecmp(token, "all") == 0) { 10769 type = wpa_s->mac_addr_rand_supported; 10770 } else if (os_strncasecmp(token, "enable=", 7) == 0) { 10771 enable = atoi(token + 7); 10772 } else if (os_strncasecmp(token, "addr=", 5) == 0) { 10773 addr = _addr; 10774 if (hwaddr_aton(token + 5, addr)) { 10775 wpa_printf(MSG_INFO, 10776 "CTRL: Invalid MAC address: %s", 10777 token); 10778 return -1; 10779 } 10780 } else if (os_strncasecmp(token, "mask=", 5) == 0) { 10781 mask = _mask; 10782 if (hwaddr_aton(token + 5, mask)) { 10783 wpa_printf(MSG_INFO, 10784 "CTRL: Invalid MAC address mask: %s", 10785 token); 10786 return -1; 10787 } 10788 } else { 10789 wpa_printf(MSG_INFO, 10790 "CTRL: Invalid MAC_RAND_SCAN parameter: %s", 10791 token); 10792 return -1; 10793 } 10794 } 10795 10796 if (!type) { 10797 wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN no type specified"); 10798 return -1; 10799 } 10800 10801 if (enable > 1) { 10802 wpa_printf(MSG_INFO, 10803 "CTRL: MAC_RAND_SCAN enable=<0/1> not specified"); 10804 return -1; 10805 } 10806 10807 if (!enable) 10808 return wpas_disable_mac_addr_randomization(wpa_s, type); 10809 10810 return wpas_enable_mac_addr_randomization(wpa_s, type, addr, mask); 10811 } 10812 10813 10814 static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s, 10815 char *buf, size_t buflen) 10816 { 10817 size_t reply_len; 10818 10819 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen); 10820 #ifdef CONFIG_AP 10821 reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len], 10822 buflen - reply_len); 10823 #endif /* CONFIG_AP */ 10824 return reply_len; 10825 } 10826 10827 10828 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) 10829 { 10830 ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE); 10831 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); 10832 #ifdef CONFIG_AP 10833 wpas_ap_pmksa_cache_flush(wpa_s); 10834 #endif /* CONFIG_AP */ 10835 } 10836 10837 10838 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 10839 10840 static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s, 10841 const char *cmd, char *buf, size_t buflen) 10842 { 10843 struct rsn_pmksa_cache_entry *entry; 10844 struct wpa_ssid *ssid; 10845 char *pos, *pos2, *end; 10846 int ret; 10847 struct os_reltime now; 10848 10849 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 10850 if (!ssid) 10851 return -1; 10852 10853 pos = buf; 10854 end = buf + buflen; 10855 10856 os_get_reltime(&now); 10857 10858 /* 10859 * Entry format: 10860 * <BSSID> <PMKID> <PMK> <reauth_time in seconds> 10861 * <expiration in seconds> <akmp> <opportunistic> 10862 * [FILS Cache Identifier] 10863 */ 10864 10865 for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry; 10866 entry = entry->next) { 10867 if (entry->network_ctx != ssid) 10868 continue; 10869 10870 pos2 = pos; 10871 ret = os_snprintf(pos2, end - pos2, MACSTR " ", 10872 MAC2STR(entry->aa)); 10873 if (os_snprintf_error(end - pos2, ret)) 10874 break; 10875 pos2 += ret; 10876 10877 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid, 10878 PMKID_LEN); 10879 10880 ret = os_snprintf(pos2, end - pos2, " "); 10881 if (os_snprintf_error(end - pos2, ret)) 10882 break; 10883 pos2 += ret; 10884 10885 pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk, 10886 entry->pmk_len); 10887 10888 ret = os_snprintf(pos2, end - pos2, " %d %d %d %d", 10889 (int) (entry->reauth_time - now.sec), 10890 (int) (entry->expiration - now.sec), 10891 entry->akmp, 10892 entry->opportunistic); 10893 if (os_snprintf_error(end - pos2, ret)) 10894 break; 10895 pos2 += ret; 10896 10897 if (entry->fils_cache_id_set) { 10898 ret = os_snprintf(pos2, end - pos2, " %02x%02x", 10899 entry->fils_cache_id[0], 10900 entry->fils_cache_id[1]); 10901 if (os_snprintf_error(end - pos2, ret)) 10902 break; 10903 pos2 += ret; 10904 } 10905 10906 ret = os_snprintf(pos2, end - pos2, "\n"); 10907 if (os_snprintf_error(end - pos2, ret)) 10908 break; 10909 pos2 += ret; 10910 10911 pos = pos2; 10912 } 10913 10914 return pos - buf; 10915 } 10916 10917 10918 static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s, 10919 char *cmd) 10920 { 10921 struct rsn_pmksa_cache_entry *entry; 10922 struct wpa_ssid *ssid; 10923 char *pos, *pos2; 10924 int ret = -1; 10925 struct os_reltime now; 10926 int reauth_time = 0, expiration = 0, i; 10927 10928 /* 10929 * Entry format: 10930 * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> 10931 * <expiration in seconds> <akmp> <opportunistic> 10932 * [FILS Cache Identifier] 10933 */ 10934 10935 ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); 10936 if (!ssid) 10937 return -1; 10938 10939 pos = os_strchr(cmd, ' '); 10940 if (!pos) 10941 return -1; 10942 pos++; 10943 10944 entry = os_zalloc(sizeof(*entry)); 10945 if (!entry) 10946 return -1; 10947 10948 if (hwaddr_aton(pos, entry->aa)) 10949 goto fail; 10950 10951 pos = os_strchr(pos, ' '); 10952 if (!pos) 10953 goto fail; 10954 pos++; 10955 10956 if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0) 10957 goto fail; 10958 10959 pos = os_strchr(pos, ' '); 10960 if (!pos) 10961 goto fail; 10962 pos++; 10963 10964 pos2 = os_strchr(pos, ' '); 10965 if (!pos2) 10966 goto fail; 10967 entry->pmk_len = (pos2 - pos) / 2; 10968 if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX || 10969 hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0) 10970 goto fail; 10971 10972 pos = os_strchr(pos, ' '); 10973 if (!pos) 10974 goto fail; 10975 pos++; 10976 10977 if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration, 10978 &entry->akmp, &entry->opportunistic) != 4) 10979 goto fail; 10980 if (reauth_time > expiration) 10981 goto fail; 10982 for (i = 0; i < 4; i++) { 10983 pos = os_strchr(pos, ' '); 10984 if (!pos) { 10985 if (i < 3) 10986 goto fail; 10987 break; 10988 } 10989 pos++; 10990 } 10991 if (pos) { 10992 if (hexstr2bin(pos, entry->fils_cache_id, 10993 FILS_CACHE_ID_LEN) < 0) 10994 goto fail; 10995 entry->fils_cache_id_set = 1; 10996 } 10997 os_get_reltime(&now); 10998 entry->expiration = now.sec + expiration; 10999 entry->reauth_time = now.sec + reauth_time; 11000 11001 entry->network_ctx = ssid; 11002 os_memcpy(entry->spa, wpa_s->own_addr, ETH_ALEN); 11003 11004 entry->external = true; 11005 11006 wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); 11007 entry = NULL; 11008 ret = 0; 11009 fail: 11010 os_free(entry); 11011 return ret; 11012 } 11013 11014 11015 #ifdef CONFIG_MESH 11016 11017 static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, 11018 const char *cmd, char *buf, 11019 size_t buflen) 11020 { 11021 u8 spa[ETH_ALEN]; 11022 11023 if (!wpa_s->ifmsh) 11024 return -1; 11025 11026 if (os_strcasecmp(cmd, "any") == 0) 11027 return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); 11028 11029 if (hwaddr_aton(cmd, spa)) 11030 return -1; 11031 11032 return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); 11033 } 11034 11035 11036 static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, 11037 char *cmd) 11038 { 11039 /* 11040 * We do not check mesh interface existence because PMKSA should be 11041 * stored before wpa_s->ifmsh creation to suppress commit message 11042 * creation. 11043 */ 11044 return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); 11045 } 11046 11047 #endif /* CONFIG_MESH */ 11048 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 11049 11050 11051 #ifdef CONFIG_FILS 11052 static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s, 11053 const char *cmd) 11054 { 11055 struct fils_hlp_req *req; 11056 const char *pos; 11057 11058 /* format: <dst> <packet starting from ethertype> */ 11059 11060 req = os_zalloc(sizeof(*req)); 11061 if (!req) 11062 return -1; 11063 11064 if (hwaddr_aton(cmd, req->dst)) 11065 goto fail; 11066 11067 pos = os_strchr(cmd, ' '); 11068 if (!pos) 11069 goto fail; 11070 pos++; 11071 req->pkt = wpabuf_parse_bin(pos); 11072 if (!req->pkt) 11073 goto fail; 11074 11075 dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list); 11076 return 0; 11077 fail: 11078 wpabuf_free(req->pkt); 11079 os_free(req); 11080 return -1; 11081 } 11082 #endif /* CONFIG_FILS */ 11083 11084 11085 int wpas_ctrl_cmd_debug_level(const char *cmd) 11086 { 11087 if (os_strcmp(cmd, "PING") == 0 || 11088 os_strncmp(cmd, "BSS ", 4) == 0 || 11089 os_strncmp(cmd, "GET_NETWORK ", 12) == 0 || 11090 os_strncmp(cmd, "STATUS", 6) == 0 || 11091 os_strncmp(cmd, "STA ", 4) == 0 || 11092 os_strncmp(cmd, "STA-", 4) == 0) 11093 return MSG_EXCESSIVE; 11094 return MSG_DEBUG; 11095 } 11096 11097 11098 #ifndef CONFIG_NO_ROBUST_AV 11099 static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s, 11100 const char *cmd) 11101 { 11102 size_t frame_classifier_len; 11103 const char *pos, *end; 11104 struct robust_av_data *robust_av = &wpa_s->robust_av; 11105 int val; 11106 11107 /* 11108 * format: 11109 * <add|remove|change> [up_bitmap=<hex byte>] [up_limit=<integer>] 11110 * [stream_timeout=<in TUs>] [frame_classifier=<hex bytes>] 11111 */ 11112 os_memset(robust_av, 0, sizeof(struct robust_av_data)); 11113 if (os_strncmp(cmd, "add ", 4) == 0) { 11114 robust_av->request_type = SCS_REQ_ADD; 11115 } else if (os_strcmp(cmd, "remove") == 0) { 11116 robust_av->request_type = SCS_REQ_REMOVE; 11117 robust_av->valid_config = false; 11118 return wpas_send_mscs_req(wpa_s); 11119 } else if (os_strncmp(cmd, "change ", 7) == 0) { 11120 robust_av->request_type = SCS_REQ_CHANGE; 11121 } else { 11122 return -1; 11123 } 11124 11125 pos = os_strstr(cmd, "up_bitmap="); 11126 if (!pos) 11127 return -1; 11128 11129 val = hex2byte(pos + 10); 11130 if (val < 0) 11131 return -1; 11132 robust_av->up_bitmap = val; 11133 11134 pos = os_strstr(cmd, "up_limit="); 11135 if (!pos) 11136 return -1; 11137 11138 robust_av->up_limit = atoi(pos + 9); 11139 11140 pos = os_strstr(cmd, "stream_timeout="); 11141 if (!pos) 11142 return -1; 11143 11144 robust_av->stream_timeout = atoi(pos + 15); 11145 if (robust_av->stream_timeout == 0) 11146 return -1; 11147 11148 pos = os_strstr(cmd, "frame_classifier="); 11149 if (!pos) 11150 return -1; 11151 11152 pos += 17; 11153 end = os_strchr(pos, ' '); 11154 if (!end) 11155 end = pos + os_strlen(pos); 11156 11157 frame_classifier_len = (end - pos) / 2; 11158 if (frame_classifier_len > sizeof(robust_av->frame_classifier) || 11159 hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len)) 11160 return -1; 11161 11162 robust_av->frame_classifier_len = frame_classifier_len; 11163 robust_av->valid_config = true; 11164 11165 return wpas_send_mscs_req(wpa_s); 11166 } 11167 #endif /* CONFIG_NO_ROBUST_AV */ 11168 11169 11170 #ifdef CONFIG_PASN 11171 static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd) 11172 { 11173 char *token, *context = NULL; 11174 u8 bssid[ETH_ALEN]; 11175 int akmp = -1, cipher = -1, got_bssid = 0; 11176 u16 group = 0xFFFF; 11177 u8 *comeback = NULL; 11178 size_t comeback_len = 0; 11179 int id = 0, ret = -1; 11180 11181 /* 11182 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group> 11183 * [comeback=<hexdump>] 11184 */ 11185 while ((token = str_token(cmd, " ", &context))) { 11186 if (os_strncmp(token, "bssid=", 6) == 0) { 11187 if (hwaddr_aton(token + 6, bssid)) 11188 goto out; 11189 got_bssid = 1; 11190 } else if (os_strcmp(token, "akmp=PASN") == 0) { 11191 akmp = WPA_KEY_MGMT_PASN; 11192 #ifdef CONFIG_IEEE80211R 11193 } else if (os_strcmp(token, "akmp=FT-PSK") == 0) { 11194 akmp = WPA_KEY_MGMT_FT_PSK; 11195 } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) { 11196 akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; 11197 } else if (os_strcmp(token, "akmp=FT-EAP") == 0) { 11198 akmp = WPA_KEY_MGMT_FT_IEEE8021X; 11199 #endif /* CONFIG_IEEE80211R */ 11200 #ifdef CONFIG_SAE 11201 } else if (os_strcmp(token, "akmp=SAE") == 0) { 11202 akmp = WPA_KEY_MGMT_SAE; 11203 } else if (os_strcmp(token, "akmp=SAE-EXT-KEY") == 0) { 11204 akmp = WPA_KEY_MGMT_SAE_EXT_KEY; 11205 #endif /* CONFIG_SAE */ 11206 #ifdef CONFIG_FILS 11207 } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) { 11208 akmp = WPA_KEY_MGMT_FILS_SHA256; 11209 } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) { 11210 akmp = WPA_KEY_MGMT_FILS_SHA384; 11211 #endif /* CONFIG_FILS */ 11212 } else if (os_strcmp(token, "cipher=CCMP-256") == 0) { 11213 cipher = WPA_CIPHER_CCMP_256; 11214 } else if (os_strcmp(token, "cipher=GCMP-256") == 0) { 11215 cipher = WPA_CIPHER_GCMP_256; 11216 } else if (os_strcmp(token, "cipher=CCMP") == 0) { 11217 cipher = WPA_CIPHER_CCMP; 11218 } else if (os_strcmp(token, "cipher=GCMP") == 0) { 11219 cipher = WPA_CIPHER_GCMP; 11220 } else if (os_strncmp(token, "group=", 6) == 0) { 11221 group = atoi(token + 6); 11222 } else if (os_strncmp(token, "nid=", 4) == 0) { 11223 id = atoi(token + 4); 11224 } else if (os_strncmp(token, "comeback=", 9) == 0) { 11225 comeback_len = os_strlen(token + 9); 11226 if (comeback || !comeback_len || comeback_len % 2) 11227 goto out; 11228 11229 comeback_len /= 2; 11230 comeback = os_malloc(comeback_len); 11231 if (!comeback || 11232 hexstr2bin(token + 9, comeback, comeback_len)) 11233 goto out; 11234 } else { 11235 wpa_printf(MSG_DEBUG, 11236 "CTRL: PASN Invalid parameter: '%s'", 11237 token); 11238 goto out; 11239 } 11240 } 11241 11242 if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) { 11243 wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter"); 11244 goto out; 11245 } 11246 11247 ret = wpas_pasn_auth_start(wpa_s, wpa_s->own_addr, bssid, akmp, cipher, 11248 group, id, comeback, comeback_len); 11249 out: 11250 os_free(comeback); 11251 return ret; 11252 } 11253 11254 11255 static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s, 11256 const char *cmd) 11257 { 11258 u8 bssid[ETH_ALEN]; 11259 11260 if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) { 11261 wpa_printf(MSG_DEBUG, 11262 "CTRL: PASN_DEAUTH without valid BSSID"); 11263 return -1; 11264 } 11265 11266 return wpas_pasn_deauthenticate(wpa_s, wpa_s->own_addr, bssid); 11267 } 11268 11269 11270 #ifdef CONFIG_TESTING_OPTIONS 11271 static int wpas_ctrl_iface_pasn_driver(struct wpa_supplicant *wpa_s, 11272 const char *cmd) 11273 { 11274 union wpa_event_data event; 11275 const char *pos = cmd; 11276 u8 addr[ETH_ALEN]; 11277 11278 os_memset(&event, 0, sizeof(event)); 11279 11280 if (os_strncmp(pos, "auth ", 5) == 0) 11281 event.pasn_auth.action = PASN_ACTION_AUTH; 11282 else if (os_strncmp(pos, "del ", 4) == 0) 11283 event.pasn_auth.action = 11284 PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT; 11285 else 11286 return -1; 11287 11288 pos = os_strchr(pos, ' '); 11289 if (!pos) 11290 return -1; 11291 pos++; 11292 while (hwaddr_aton(pos, addr) == 0) { 11293 struct pasn_peer *peer; 11294 11295 if (event.pasn_auth.num_peers == WPAS_MAX_PASN_PEERS) 11296 return -1; 11297 peer = &event.pasn_auth.peer[event.pasn_auth.num_peers]; 11298 os_memcpy(peer->own_addr, wpa_s->own_addr, ETH_ALEN); 11299 os_memcpy(peer->peer_addr, addr, ETH_ALEN); 11300 event.pasn_auth.num_peers++; 11301 11302 pos = os_strchr(pos, ' '); 11303 if (!pos) 11304 break; 11305 pos++; 11306 } 11307 11308 wpa_supplicant_event(wpa_s, EVENT_PASN_AUTH, &event); 11309 return 0; 11310 } 11311 #endif /* CONFIG_TESTING_OPTIONS */ 11312 11313 #endif /* CONFIG_PASN */ 11314 11315 11316 #ifndef CONFIG_NO_ROBUST_AV 11317 11318 static int set_type4_frame_classifier(const char *cmd, 11319 struct type4_params *param) 11320 { 11321 const char *pos, *end; 11322 u8 classifier_mask = 0; 11323 int ret; 11324 char addr[INET6_ADDRSTRLEN]; 11325 size_t alen; 11326 11327 if (os_strstr(cmd, "ip_version=ipv4")) { 11328 param->ip_version = IPV4; 11329 } else if (os_strstr(cmd, "ip_version=ipv6")) { 11330 param->ip_version = IPV6; 11331 } else { 11332 wpa_printf(MSG_ERROR, "IP version missing/invalid"); 11333 return -1; 11334 } 11335 11336 classifier_mask |= BIT(0); 11337 11338 pos = os_strstr(cmd, "src_ip="); 11339 if (pos) { 11340 pos += 7; 11341 end = os_strchr(pos, ' '); 11342 if (!end) 11343 end = pos + os_strlen(pos); 11344 11345 alen = end - pos; 11346 if (alen >= INET6_ADDRSTRLEN) 11347 return -1; 11348 os_memcpy(addr, pos, alen); 11349 addr[alen] = '\0'; 11350 if (param->ip_version == IPV4) 11351 ret = inet_pton(AF_INET, addr, 11352 ¶m->ip_params.v4.src_ip); 11353 else 11354 ret = inet_pton(AF_INET6, addr, 11355 ¶m->ip_params.v6.src_ip); 11356 11357 if (ret != 1) { 11358 wpa_printf(MSG_ERROR, 11359 "Error converting src IP address to binary ret=%d", 11360 ret); 11361 return -1; 11362 } 11363 11364 classifier_mask |= BIT(1); 11365 } 11366 11367 pos = os_strstr(cmd, "dst_ip="); 11368 if (pos) { 11369 pos += 7; 11370 end = os_strchr(pos, ' '); 11371 if (!end) 11372 end = pos + os_strlen(pos); 11373 11374 alen = end - pos; 11375 if (alen >= INET6_ADDRSTRLEN) 11376 return -1; 11377 os_memcpy(addr, pos, alen); 11378 addr[alen] = '\0'; 11379 if (param->ip_version == IPV4) 11380 ret = inet_pton(AF_INET, addr, 11381 ¶m->ip_params.v4.dst_ip); 11382 else 11383 ret = inet_pton(AF_INET6, addr, 11384 ¶m->ip_params.v6.dst_ip); 11385 11386 if (ret != 1) { 11387 wpa_printf(MSG_ERROR, 11388 "Error converting dst IP address to binary ret=%d", 11389 ret); 11390 return -1; 11391 } 11392 11393 classifier_mask |= BIT(2); 11394 } 11395 11396 pos = os_strstr(cmd, "src_port="); 11397 if (pos && atoi(pos + 9) > 0) { 11398 if (param->ip_version == IPV4) 11399 param->ip_params.v4.src_port = atoi(pos + 9); 11400 else 11401 param->ip_params.v6.src_port = atoi(pos + 9); 11402 classifier_mask |= BIT(3); 11403 } 11404 11405 pos = os_strstr(cmd, "dst_port="); 11406 if (pos && atoi(pos + 9) > 0) { 11407 if (param->ip_version == IPV4) 11408 param->ip_params.v4.dst_port = atoi(pos + 9); 11409 else 11410 param->ip_params.v6.dst_port = atoi(pos + 9); 11411 classifier_mask |= BIT(4); 11412 } 11413 11414 pos = os_strstr(cmd, "dscp="); 11415 if (pos && atoi(pos + 5) > 0) { 11416 if (param->ip_version == IPV4) 11417 param->ip_params.v4.dscp = atoi(pos + 5); 11418 else 11419 param->ip_params.v6.dscp = atoi(pos + 5); 11420 classifier_mask |= BIT(5); 11421 } 11422 11423 if (param->ip_version == IPV4) { 11424 pos = os_strstr(cmd, "protocol="); 11425 if (pos) { 11426 if (os_strstr(pos, "udp")) { 11427 param->ip_params.v4.protocol = 17; 11428 } else if (os_strstr(pos, "tcp")) { 11429 param->ip_params.v4.protocol = 6; 11430 } else if (os_strstr(pos, "esp")) { 11431 param->ip_params.v4.protocol = 50; 11432 } else { 11433 wpa_printf(MSG_ERROR, "Invalid protocol"); 11434 return -1; 11435 } 11436 classifier_mask |= BIT(6); 11437 } 11438 } else { 11439 pos = os_strstr(cmd, "next_header="); 11440 if (pos) { 11441 if (os_strstr(pos, "udp")) { 11442 param->ip_params.v6.next_header = 17; 11443 } else if (os_strstr(pos, "tcp")) { 11444 param->ip_params.v6.next_header = 6; 11445 } else if (os_strstr(pos, "esp")) { 11446 param->ip_params.v6.next_header = 50; 11447 } else { 11448 wpa_printf(MSG_ERROR, "Invalid next header"); 11449 return -1; 11450 } 11451 11452 classifier_mask |= BIT(6); 11453 } 11454 11455 pos = os_strstr(cmd, "flow_label="); 11456 if (pos) { 11457 pos += 11; 11458 end = os_strchr(pos, ' '); 11459 if (!end) 11460 end = pos + os_strlen(pos); 11461 11462 if (end - pos != 6 || 11463 hexstr2bin(pos, param->ip_params.v6.flow_label, 11464 3) || 11465 param->ip_params.v6.flow_label[0] > 0x0F) { 11466 wpa_printf(MSG_ERROR, "Invalid flow label"); 11467 return -1; 11468 } 11469 11470 classifier_mask |= BIT(7); 11471 } 11472 } 11473 11474 param->classifier_mask = classifier_mask; 11475 return 0; 11476 } 11477 11478 11479 static int set_type10_frame_classifier(const char *cmd, 11480 struct type10_params *param) 11481 { 11482 const char *pos, *end; 11483 size_t filter_len; 11484 11485 pos = os_strstr(cmd, "prot_instance="); 11486 if (!pos) { 11487 wpa_printf(MSG_ERROR, "Protocol instance missing"); 11488 return -1; 11489 } 11490 param->prot_instance = atoi(pos + 14); 11491 11492 pos = os_strstr(cmd, "prot_number="); 11493 if (!pos) { 11494 wpa_printf(MSG_ERROR, "Protocol number missing"); 11495 return -1; 11496 } 11497 if (os_strstr(pos, "udp")) { 11498 param->prot_number = 17; 11499 } else if (os_strstr(pos, "tcp")) { 11500 param->prot_number = 6; 11501 } else if (os_strstr(pos, "esp")) { 11502 param->prot_number = 50; 11503 } else { 11504 wpa_printf(MSG_ERROR, "Invalid protocol number"); 11505 return -1; 11506 } 11507 11508 pos = os_strstr(cmd, "filter_value="); 11509 if (!pos) { 11510 wpa_printf(MSG_ERROR, 11511 "Classifier parameter filter_value missing"); 11512 return -1; 11513 } 11514 11515 pos += 13; 11516 end = os_strchr(pos, ' '); 11517 if (!end) 11518 end = pos + os_strlen(pos); 11519 11520 filter_len = (end - pos) / 2; 11521 param->filter_value = os_malloc(filter_len); 11522 if (!param->filter_value) 11523 return -1; 11524 11525 if (hexstr2bin(pos, param->filter_value, filter_len)) { 11526 wpa_printf(MSG_ERROR, "Invalid filter_value %s", pos); 11527 goto free; 11528 } 11529 11530 pos = os_strstr(cmd, "filter_mask="); 11531 if (!pos) { 11532 wpa_printf(MSG_ERROR, 11533 "Classifier parameter filter_mask missing"); 11534 goto free; 11535 } 11536 11537 pos += 12; 11538 end = os_strchr(pos, ' '); 11539 if (!end) 11540 end = pos + os_strlen(pos); 11541 11542 if (filter_len != (size_t) (end - pos) / 2) { 11543 wpa_printf(MSG_ERROR, 11544 "Filter mask length mismatch expected=%zu received=%zu", 11545 filter_len, (size_t) (end - pos) / 2); 11546 goto free; 11547 } 11548 11549 param->filter_mask = os_malloc(filter_len); 11550 if (!param->filter_mask) 11551 goto free; 11552 11553 if (hexstr2bin(pos, param->filter_mask, filter_len)) { 11554 wpa_printf(MSG_ERROR, "Invalid filter mask %s", pos); 11555 os_free(param->filter_mask); 11556 param->filter_mask = NULL; 11557 goto free; 11558 } 11559 11560 param->filter_len = filter_len; 11561 return 0; 11562 free: 11563 os_free(param->filter_value); 11564 param->filter_value = NULL; 11565 return -1; 11566 } 11567 11568 11569 static int scs_parse_type4(struct tclas_element *elem, const char *pos) 11570 { 11571 struct type4_params type4_param = { 0 }; 11572 11573 if (set_type4_frame_classifier(pos, &type4_param) == -1) { 11574 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 4"); 11575 return -1; 11576 } 11577 11578 os_memcpy(&elem->frame_classifier.type4_param, 11579 &type4_param, sizeof(struct type4_params)); 11580 return 0; 11581 } 11582 11583 11584 static int scs_parse_type10(struct tclas_element *elem, const char *pos) 11585 { 11586 struct type10_params type10_param = { 0 }; 11587 11588 if (set_type10_frame_classifier(pos, &type10_param) == -1) { 11589 wpa_printf(MSG_ERROR, "Failed to set frame_classifier 10"); 11590 return -1; 11591 } 11592 11593 os_memcpy(&elem->frame_classifier.type10_param, 11594 &type10_param, sizeof(struct type10_params)); 11595 return 0; 11596 } 11597 11598 11599 static int wpas_ctrl_iface_configure_scs(struct wpa_supplicant *wpa_s, 11600 char *cmd) 11601 { 11602 char *pos1, *pos; 11603 struct scs_robust_av_data *scs_data = &wpa_s->scs_robust_av_req; 11604 struct scs_desc_elem desc_elem = { 0 }; 11605 int val; 11606 unsigned int num_scs_desc = 0; 11607 11608 if (wpa_s->ongoing_scs_req) { 11609 wpa_printf(MSG_ERROR, "%s: SCS Request already in queue", 11610 __func__); 11611 return -1; 11612 } 11613 11614 /** 11615 * format: 11616 * [scs_id=<decimal number>] <add|remove|change> [scs_up=<0-7>] 11617 * [classifier_type=<4|10>] 11618 * [classifier params based on classifier type] 11619 * [tclas_processing=<0|1>] 11620 * [qos_characteristics] <up/down/direct> [min_si=<decimal number>] 11621 * [max_si=<decimal number>] [min_data_rate=<decimal number>] 11622 * [delay_bound=<decimal number>] [max_msdu=<decimal number>] 11623 * [service_start_time=<decimal number>] 11624 * [service_start_time_link_id=<decimal number>] 11625 * [mean_data_rate=<decimal number>] [burst_size=<decimal number>] 11626 * [msdu_lifetime=<decimal number>] 11627 * [msdu_delivery_info=<decimal number>] [medium_time=<decimal number>] 11628 * [scs_id=<decimal number>] ... 11629 */ 11630 pos1 = os_strstr(cmd, "scs_id="); 11631 if (!pos1) { 11632 wpa_printf(MSG_ERROR, "SCSID not present"); 11633 return -1; 11634 } 11635 11636 free_up_scs_desc(scs_data); 11637 11638 while (pos1) { 11639 struct scs_desc_elem *n1; 11640 struct active_scs_elem *active_scs_desc; 11641 char *next_scs_desc, *pos2; 11642 unsigned int num_tclas_elem = 0; 11643 bool scsid_active = false, tclas_present = false; 11644 struct qos_characteristics *qos_elem = &desc_elem.qos_char_elem; 11645 11646 desc_elem.scs_id = atoi(pos1 + 7); 11647 pos1 += 7; 11648 11649 next_scs_desc = os_strstr(pos1, "scs_id="); 11650 if (next_scs_desc) { 11651 char temp[20]; 11652 11653 os_snprintf(temp, sizeof(temp), "scs_id=%d ", 11654 desc_elem.scs_id); 11655 if (os_strstr(next_scs_desc, temp)) { 11656 wpa_printf(MSG_ERROR, 11657 "Multiple SCS descriptors configured with same SCSID(=%d)", 11658 desc_elem.scs_id); 11659 goto free_scs_desc; 11660 } 11661 pos1[next_scs_desc - pos1 - 1] = '\0'; 11662 } 11663 11664 dl_list_for_each(active_scs_desc, &wpa_s->active_scs_ids, 11665 struct active_scs_elem, list) { 11666 if (desc_elem.scs_id == active_scs_desc->scs_id) { 11667 scsid_active = true; 11668 break; 11669 } 11670 } 11671 11672 if (os_strstr(pos1, "add ")) { 11673 desc_elem.request_type = SCS_REQ_ADD; 11674 if (scsid_active) { 11675 wpa_printf(MSG_ERROR, "SCSID %d already active", 11676 desc_elem.scs_id); 11677 return -1; 11678 } 11679 } else if (os_strstr(pos1, "remove")) { 11680 desc_elem.request_type = SCS_REQ_REMOVE; 11681 if (!scsid_active) { 11682 wpa_printf(MSG_ERROR, "SCSID %d not active", 11683 desc_elem.scs_id); 11684 return -1; 11685 } 11686 goto scs_desc_end; 11687 } else if (os_strstr(pos1, "change ")) { 11688 desc_elem.request_type = SCS_REQ_CHANGE; 11689 if (!scsid_active) { 11690 wpa_printf(MSG_ERROR, "SCSID %d not active", 11691 desc_elem.scs_id); 11692 return -1; 11693 } 11694 } else { 11695 wpa_printf(MSG_ERROR, "SCS Request type invalid"); 11696 goto free_scs_desc; 11697 } 11698 11699 pos1 = os_strstr(pos1, "scs_up="); 11700 if (!pos1) { 11701 wpa_printf(MSG_ERROR, 11702 "Intra-Access user priority not present"); 11703 goto free_scs_desc; 11704 } 11705 11706 val = atoi(pos1 + 7); 11707 if (val < 0 || val > 7) { 11708 wpa_printf(MSG_ERROR, 11709 "Intra-Access user priority invalid %d", 11710 val); 11711 goto free_scs_desc; 11712 } 11713 11714 desc_elem.intra_access_priority = val; 11715 desc_elem.scs_up_avail = true; 11716 11717 pos = os_strstr(pos1, "classifier_type="); 11718 if (!pos) { 11719 wpa_printf(MSG_ERROR, "classifier type empty"); 11720 goto qos_characteristics; 11721 } 11722 tclas_present = true; 11723 11724 while (pos) { 11725 struct tclas_element elem = { 0 }, *n; 11726 char *next_tclas_elem; 11727 11728 val = atoi(pos + 16); 11729 if (val != 4 && val != 10) { 11730 wpa_printf(MSG_ERROR, 11731 "classifier type invalid %d", val); 11732 goto free_scs_desc; 11733 } 11734 11735 elem.classifier_type = val; 11736 pos += 16; 11737 11738 next_tclas_elem = os_strstr(pos, "classifier_type="); 11739 if (next_tclas_elem) { 11740 pos1 = next_tclas_elem; 11741 pos[next_tclas_elem - pos - 1] = '\0'; 11742 } 11743 11744 switch (val) { 11745 case 4: 11746 if (scs_parse_type4(&elem, pos) < 0) 11747 goto free_scs_desc; 11748 break; 11749 case 10: 11750 if (scs_parse_type10(&elem, pos) < 0) 11751 goto free_scs_desc; 11752 break; 11753 } 11754 11755 n = os_realloc(desc_elem.tclas_elems, 11756 (num_tclas_elem + 1) * sizeof(elem)); 11757 if (!n) 11758 goto free_scs_desc; 11759 11760 desc_elem.tclas_elems = n; 11761 os_memcpy((u8 *) desc_elem.tclas_elems + 11762 num_tclas_elem * sizeof(elem), 11763 &elem, sizeof(elem)); 11764 num_tclas_elem++; 11765 desc_elem.num_tclas_elem = num_tclas_elem; 11766 pos = next_tclas_elem; 11767 } 11768 11769 if (desc_elem.num_tclas_elem > 1) { 11770 pos1 = os_strstr(pos1, "tclas_processing="); 11771 if (!pos1) { 11772 wpa_printf(MSG_ERROR, "tclas_processing empty"); 11773 goto free_scs_desc; 11774 } 11775 11776 val = atoi(pos1 + 17); 11777 if (val != 0 && val != 1) { 11778 wpa_printf(MSG_ERROR, 11779 "tclas_processing invalid"); 11780 goto free_scs_desc; 11781 } 11782 11783 desc_elem.tclas_processing = val; 11784 } 11785 11786 qos_characteristics: 11787 pos1 = os_strstr(pos1, "qos_characteristics"); 11788 if (!pos1 && !tclas_present) 11789 goto free_scs_desc; 11790 if (!pos1) 11791 goto scs_desc_end; 11792 11793 qos_elem->available = true; 11794 if (os_strstr(pos1, "up ")) { 11795 qos_elem->direction = SCS_DIRECTION_UP; 11796 if (tclas_present) { 11797 wpa_printf(MSG_ERROR, 11798 "TCLAS with direction:UP not allowed"); 11799 goto free_scs_desc; 11800 } 11801 } else if (os_strstr(pos1, "down ")) { 11802 qos_elem->direction = SCS_DIRECTION_DOWN; 11803 } else if (os_strstr(pos1, "direct ")) { 11804 qos_elem->direction = SCS_DIRECTION_DIRECT; 11805 } 11806 11807 pos1 = os_strstr(pos1, "min_si="); 11808 if (!pos1) { 11809 wpa_printf(MSG_ERROR, "Min SI is required"); 11810 goto free_scs_desc; 11811 } 11812 qos_elem->min_si = atoi(pos1 + 7); 11813 11814 pos1 = os_strstr(pos1, "max_si="); 11815 if (!pos1) { 11816 wpa_printf(MSG_ERROR, "Max SI is required"); 11817 goto free_scs_desc; 11818 } 11819 qos_elem->max_si = atoi(pos1 + 7); 11820 11821 if (qos_elem->min_si && qos_elem->max_si && 11822 qos_elem->max_si < qos_elem->min_si) { 11823 wpa_printf(MSG_ERROR, "Invalid Max SI"); 11824 goto free_scs_desc; 11825 } 11826 11827 pos1 = os_strstr(pos1, "min_data_rate="); 11828 if (!pos1) { 11829 wpa_printf(MSG_ERROR, "Min data rate is required"); 11830 goto free_scs_desc; 11831 } 11832 qos_elem->min_data_rate = atoi(pos1 + 14); 11833 11834 pos1 = os_strstr(pos1, "delay_bound="); 11835 if (!pos1) { 11836 wpa_printf(MSG_ERROR, "Delay Bound is required"); 11837 goto free_scs_desc; 11838 } 11839 qos_elem->delay_bound = atoi(pos1 + 12); 11840 11841 if (qos_elem->min_data_rate >= BIT(24) || 11842 qos_elem->delay_bound >= BIT(24)) { 11843 wpa_printf(MSG_ERROR, 11844 "Invalid min_data_rate or delay_bound"); 11845 goto free_scs_desc; 11846 } 11847 11848 pos2 = os_strstr(pos1, "max_msdu="); 11849 if (pos2) { 11850 qos_elem->max_msdu_size = atoi(pos2 + 9); 11851 qos_elem->mask |= SCS_QOS_BIT_MAX_MSDU_SIZE; 11852 } 11853 11854 pos2 = os_strstr(pos1, "service_start_time="); 11855 if (pos2) { 11856 qos_elem->service_start_time = atoi(pos2 + 19); 11857 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME; 11858 } 11859 11860 pos2 = os_strstr(pos1, "service_start_time_link_id="); 11861 if (pos2) { 11862 qos_elem->service_start_time_link_id = atoi(pos2 + 27); 11863 qos_elem->mask |= SCS_QOS_BIT_SERVICE_START_TIME_LINKID; 11864 } 11865 11866 pos2 = os_strstr(pos1, "mean_data_rate="); 11867 if (pos2) { 11868 qos_elem->mean_data_rate = atoi(pos2 + 15); 11869 qos_elem->mask |= SCS_QOS_BIT_MEAN_DATA_RATE; 11870 } 11871 11872 pos2 = os_strstr(pos1, "burst_size="); 11873 if (pos2) { 11874 qos_elem->burst_size = atoi(pos2 + 11); 11875 qos_elem->mask |= 11876 SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE; 11877 } 11878 11879 pos2 = os_strstr(pos1, "msdu_lifetime="); 11880 if (pos2) { 11881 qos_elem->msdu_lifetime = atoi(pos2 + 14); 11882 qos_elem->mask |= SCS_QOS_BIT_MSDU_LIFETIME; 11883 } 11884 11885 pos2 = os_strstr(pos1, "msdu_delivery_info="); 11886 if (pos2) { 11887 qos_elem->msdu_delivery_info = atoi(pos2 + 19); 11888 qos_elem->mask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO; 11889 } 11890 11891 pos2 = os_strstr(pos1, "medium_time="); 11892 if (pos2) { 11893 qos_elem->medium_time = atoi(pos2 + 12); 11894 qos_elem->mask |= SCS_QOS_BIT_MEDIUM_TIME; 11895 } 11896 11897 scs_desc_end: 11898 n1 = os_realloc(scs_data->scs_desc_elems, (num_scs_desc + 1) * 11899 sizeof(struct scs_desc_elem)); 11900 if (!n1) 11901 goto free_scs_desc; 11902 11903 scs_data->scs_desc_elems = n1; 11904 os_memcpy((u8 *) scs_data->scs_desc_elems + num_scs_desc * 11905 sizeof(desc_elem), &desc_elem, sizeof(desc_elem)); 11906 num_scs_desc++; 11907 scs_data->num_scs_desc = num_scs_desc; 11908 pos1 = next_scs_desc; 11909 os_memset(&desc_elem, 0, sizeof(desc_elem)); 11910 } 11911 11912 return wpas_send_scs_req(wpa_s); 11913 11914 free_scs_desc: 11915 free_up_tclas_elem(&desc_elem); 11916 free_up_scs_desc(scs_data); 11917 return -1; 11918 } 11919 11920 11921 static int wpas_ctrl_iface_send_dscp_resp(struct wpa_supplicant *wpa_s, 11922 const char *cmd) 11923 { 11924 char *pos; 11925 struct dscp_policy_status *policy = NULL, *n; 11926 int num_policies = 0, ret = -1; 11927 struct dscp_resp_data resp_data; 11928 11929 /* 11930 * format: 11931 * <[reset]>/<[solicited] [policy_id=1 status=0...]> [more] 11932 */ 11933 11934 os_memset(&resp_data, 0, sizeof(resp_data)); 11935 11936 resp_data.more = os_strstr(cmd, "more") != NULL; 11937 11938 if (os_strstr(cmd, "reset")) { 11939 resp_data.reset = true; 11940 resp_data.solicited = false; 11941 goto send_resp; 11942 } 11943 11944 resp_data.solicited = os_strstr(cmd, "solicited") != NULL; 11945 11946 pos = os_strstr(cmd, "policy_id="); 11947 while (pos) { 11948 n = os_realloc(policy, (num_policies + 1) * sizeof(*policy)); 11949 if (!n) 11950 goto fail; 11951 11952 policy = n; 11953 pos += 10; 11954 policy[num_policies].id = atoi(pos); 11955 if (policy[num_policies].id == 0) { 11956 wpa_printf(MSG_ERROR, "DSCP: Invalid policy id"); 11957 goto fail; 11958 } 11959 11960 pos = os_strstr(pos, "status="); 11961 if (!pos) { 11962 wpa_printf(MSG_ERROR, 11963 "DSCP: Status is not found for a policy"); 11964 goto fail; 11965 } 11966 11967 pos += 7; 11968 policy[num_policies].status = atoi(pos); 11969 num_policies++; 11970 11971 pos = os_strstr(pos, "policy_id"); 11972 } 11973 11974 resp_data.policy = policy; 11975 resp_data.num_policies = num_policies; 11976 send_resp: 11977 ret = wpas_send_dscp_response(wpa_s, &resp_data); 11978 if (ret) 11979 wpa_printf(MSG_ERROR, "DSCP: Failed to send DSCP response"); 11980 fail: 11981 os_free(policy); 11982 return ret; 11983 } 11984 11985 11986 static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s, 11987 const char *cmd) 11988 { 11989 char *pos; 11990 11991 /* 11992 * format: 11993 * Wildcard DSCP query 11994 * <wildcard> 11995 * 11996 * DSCP query with a domain name attribute: 11997 * [domain_name=<string>] 11998 */ 11999 12000 if (os_strstr(cmd, "wildcard")) { 12001 wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query"); 12002 return wpas_send_dscp_query(wpa_s, NULL, 0); 12003 } 12004 12005 pos = os_strstr(cmd, "domain_name="); 12006 if (!pos || !os_strlen(pos + 12)) { 12007 wpa_printf(MSG_ERROR, "QM: Domain name not preset"); 12008 return -1; 12009 } 12010 12011 return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12)); 12012 } 12013 12014 #endif /* CONFIG_NO_ROBUST_AV */ 12015 12016 12017 static int wpas_ctrl_iface_mlo_signal_poll(struct wpa_supplicant *wpa_s, 12018 char *buf, size_t buflen) 12019 { 12020 int ret, i; 12021 char *pos, *end; 12022 struct wpa_mlo_signal_info mlo_si; 12023 12024 if (!wpa_s->valid_links) 12025 return -1; 12026 12027 ret = wpa_drv_mlo_signal_poll(wpa_s, &mlo_si); 12028 if (ret) 12029 return -1; 12030 12031 pos = buf; 12032 end = buf + buflen; 12033 12034 for_each_link(mlo_si.valid_links, i) { 12035 ret = os_snprintf(pos, end - pos, 12036 "LINK_ID=%d\nRSSI=%d\nLINKSPEED=%lu\n" 12037 "NOISE=%d\nFREQUENCY=%u\n", 12038 i, mlo_si.links[i].data.signal, 12039 mlo_si.links[i].data.current_tx_rate / 1000, 12040 mlo_si.links[i].current_noise, 12041 mlo_si.links[i].frequency); 12042 if (os_snprintf_error(end - pos, ret)) 12043 return -1; 12044 pos += ret; 12045 12046 if (mlo_si.links[i].chanwidth != CHAN_WIDTH_UNKNOWN) { 12047 ret = os_snprintf(pos, end - pos, "WIDTH=%s\n", 12048 channel_width_to_string( 12049 mlo_si.links[i].chanwidth)); 12050 if (os_snprintf_error(end - pos, ret)) 12051 return -1; 12052 pos += ret; 12053 } 12054 12055 if (mlo_si.links[i].center_frq1 > 0) { 12056 ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", 12057 mlo_si.links[i].center_frq1); 12058 if (os_snprintf_error(end - pos, ret)) 12059 return -1; 12060 pos += ret; 12061 } 12062 12063 if (mlo_si.links[i].center_frq2 > 0) { 12064 ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", 12065 mlo_si.links[i].center_frq2); 12066 if (os_snprintf_error(end - pos, ret)) 12067 return -1; 12068 pos += ret; 12069 } 12070 12071 if (mlo_si.links[i].data.avg_signal) { 12072 ret = os_snprintf(pos, end - pos, 12073 "AVG_RSSI=%d\n", 12074 mlo_si.links[i].data.avg_signal); 12075 if (os_snprintf_error(end - pos, ret)) 12076 return -1; 12077 pos += ret; 12078 } 12079 12080 if (mlo_si.links[i].data.avg_beacon_signal) { 12081 ret = os_snprintf( 12082 pos, end - pos, "AVG_BEACON_RSSI=%d\n", 12083 mlo_si.links[i].data.avg_beacon_signal); 12084 if (os_snprintf_error(end - pos, ret)) 12085 return -1; 12086 pos += ret; 12087 } 12088 } 12089 12090 return pos - buf; 12091 } 12092 12093 12094 static int wpas_ctrl_iface_mlo_status(struct wpa_supplicant *wpa_s, 12095 char *buf, size_t buflen) 12096 { 12097 int ret, i; 12098 char *pos, *end; 12099 12100 if (!wpa_s->valid_links) 12101 return -1; 12102 12103 pos = buf; 12104 end = buf + buflen; 12105 12106 for_each_link(wpa_s->valid_links, i) { 12107 ret = os_snprintf(pos, end - pos, "link_id=%d\nfreq=%u\n" 12108 "ap_link_addr=" MACSTR 12109 "\nsta_link_addr=" MACSTR "\n", 12110 i, wpa_s->links[i].freq, 12111 MAC2STR(wpa_s->links[i].bssid), 12112 MAC2STR(wpa_s->links[i].addr)); 12113 if (os_snprintf_error(end - pos, ret)) 12114 return pos - buf; 12115 pos += ret; 12116 } 12117 12118 return pos - buf; 12119 } 12120 12121 12122 #ifdef CONFIG_TESTING_OPTIONS 12123 static int wpas_ctrl_ml_probe(struct wpa_supplicant *wpa_s, char *cmd) 12124 { 12125 char *token, *context = NULL; 12126 u8 bssid[ETH_ALEN]; 12127 int mld_id = -1, link_id = -1; 12128 struct wpa_bss *bss; 12129 int *freqs; 12130 12131 os_memset(bssid, 0, sizeof(bssid)); 12132 12133 while ((token = str_token(cmd, " ", &context))) { 12134 if (os_strncmp(token, "bssid=", 6) == 0) { 12135 if (hwaddr_aton(token + 6, bssid)) 12136 return -1; 12137 } else if (os_strncmp(token, "mld_id=", 7) == 0) { 12138 mld_id = atoi(token + 7); 12139 } else if (os_strncmp(token, "link_id=", 8) == 0) { 12140 link_id = atoi(token + 8); 12141 } 12142 } 12143 12144 if (is_zero_ether_addr(bssid)) { 12145 wpa_printf(MSG_DEBUG, 12146 "MLD: Failed parsing ML probe request arguments"); 12147 return -1; 12148 } 12149 12150 bss = wpa_bss_get_bssid(wpa_s, bssid); 12151 if (!bss) { 12152 wpa_printf(MSG_DEBUG, 12153 "MLD: Unknown BSS for " MACSTR, MAC2STR(bssid)); 12154 return -1; 12155 } 12156 12157 if (wpa_s->sched_scanning || wpa_s->scanning || 12158 (wpa_s->wpa_state > WPA_SCANNING && 12159 wpa_s->wpa_state != WPA_COMPLETED)) { 12160 wpa_printf(MSG_DEBUG, 12161 "MLO: Ongoing scan: Reject ML probe request"); 12162 return -1; 12163 } 12164 12165 freqs = os_malloc(sizeof(int) * 2); 12166 if (!freqs) 12167 return -1; 12168 12169 freqs[0] = bss->freq; 12170 freqs[1] = 0; 12171 12172 wpa_s->manual_scan_passive = 0; 12173 wpa_s->manual_scan_use_id = 0; 12174 wpa_s->manual_scan_only_new = 0; 12175 wpa_s->scan_id_count = 0; 12176 wpa_s->scan_res_handler = scan_only_handler; 12177 os_free(wpa_s->manual_scan_freqs); 12178 wpa_s->manual_scan_freqs = freqs; 12179 12180 os_memcpy(wpa_s->ml_probe_bssid, bssid, ETH_ALEN); 12181 wpa_s->ml_probe_mld_id = mld_id; 12182 if (link_id >= 0) 12183 wpa_s->ml_probe_links = BIT(link_id); 12184 12185 wpa_s->normal_scans = 0; 12186 wpa_s->scan_req = MANUAL_SCAN_REQ; 12187 wpa_s->after_wps = 0; 12188 wpa_s->known_wps_freq = 0; 12189 wpa_supplicant_req_scan(wpa_s, 0, 0); 12190 12191 return 0; 12192 } 12193 #endif /* CONFIG_TESTING_OPTIONS */ 12194 12195 12196 #ifdef CONFIG_NAN_USD 12197 12198 static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd, 12199 char *buf, size_t buflen) 12200 { 12201 char *token, *context = NULL; 12202 int publish_id; 12203 struct nan_publish_params params; 12204 const char *service_name = NULL; 12205 struct wpabuf *ssi = NULL; 12206 int ret = -1; 12207 enum nan_service_protocol_type srv_proto_type = 0; 12208 int *freq_list = NULL; 12209 12210 os_memset(¶ms, 0, sizeof(params)); 12211 /* USD shall use both solicited and unsolicited transmissions */ 12212 params.unsolicited = true; 12213 params.solicited = true; 12214 /* USD shall require FSD without GAS */ 12215 params.fsd = true; 12216 params.freq = NAN_USD_DEFAULT_FREQ; 12217 12218 while ((token = str_token(cmd, " ", &context))) { 12219 if (os_strncmp(token, "service_name=", 13) == 0) { 12220 service_name = token + 13; 12221 continue; 12222 } 12223 12224 if (os_strncmp(token, "ttl=", 4) == 0) { 12225 params.ttl = atoi(token + 4); 12226 continue; 12227 } 12228 12229 if (os_strncmp(token, "freq=", 5) == 0) { 12230 params.freq = atoi(token + 5); 12231 continue; 12232 } 12233 12234 if (os_strncmp(token, "freq_list=", 10) == 0) { 12235 char *pos = token + 10; 12236 12237 if (os_strcmp(pos, "all") == 0) { 12238 os_free(freq_list); 12239 freq_list = wpas_nan_usd_all_freqs(wpa_s); 12240 params.freq_list = freq_list; 12241 continue; 12242 } 12243 12244 while (pos && pos[0]) { 12245 int_array_add_unique(&freq_list, atoi(pos)); 12246 pos = os_strchr(pos, ','); 12247 if (pos) 12248 pos++; 12249 } 12250 12251 params.freq_list = freq_list; 12252 continue; 12253 } 12254 12255 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 12256 srv_proto_type = atoi(token + 15); 12257 continue; 12258 } 12259 12260 if (os_strncmp(token, "ssi=", 4) == 0) { 12261 if (ssi) 12262 goto fail; 12263 ssi = wpabuf_parse_bin(token + 4); 12264 if (!ssi) 12265 goto fail; 12266 continue; 12267 } 12268 12269 if (os_strcmp(token, "solicited=0") == 0) { 12270 params.solicited = false; 12271 continue; 12272 } 12273 12274 if (os_strcmp(token, "unsolicited=0") == 0) { 12275 params.unsolicited = false; 12276 continue; 12277 } 12278 12279 if (os_strcmp(token, "fsd=0") == 0) { 12280 params.fsd = false; 12281 continue; 12282 } 12283 12284 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s", 12285 token); 12286 goto fail; 12287 } 12288 12289 publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type, 12290 ssi, ¶ms); 12291 if (publish_id > 0) 12292 ret = os_snprintf(buf, buflen, "%d", publish_id); 12293 fail: 12294 wpabuf_free(ssi); 12295 os_free(freq_list); 12296 return ret; 12297 } 12298 12299 12300 static int wpas_ctrl_nan_cancel_publish(struct wpa_supplicant *wpa_s, 12301 char *cmd) 12302 { 12303 char *token, *context = NULL; 12304 int publish_id = 0; 12305 12306 while ((token = str_token(cmd, " ", &context))) { 12307 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 12308 continue; 12309 wpa_printf(MSG_INFO, 12310 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s", 12311 token); 12312 return -1; 12313 } 12314 12315 if (publish_id <= 0) { 12316 wpa_printf(MSG_INFO, 12317 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id"); 12318 return -1; 12319 } 12320 12321 wpas_nan_usd_cancel_publish(wpa_s, publish_id); 12322 return 0; 12323 } 12324 12325 12326 static int wpas_ctrl_nan_update_publish(struct wpa_supplicant *wpa_s, 12327 char *cmd) 12328 { 12329 char *token, *context = NULL; 12330 int publish_id = 0; 12331 struct wpabuf *ssi = NULL; 12332 int ret = -1; 12333 12334 while ((token = str_token(cmd, " ", &context))) { 12335 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 12336 continue; 12337 if (os_strncmp(token, "ssi=", 4) == 0) { 12338 if (ssi) 12339 goto fail; 12340 ssi = wpabuf_parse_bin(token + 4); 12341 if (!ssi) 12342 goto fail; 12343 continue; 12344 } 12345 wpa_printf(MSG_INFO, 12346 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s", 12347 token); 12348 goto fail; 12349 } 12350 12351 if (publish_id <= 0) { 12352 wpa_printf(MSG_INFO, 12353 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id"); 12354 goto fail; 12355 } 12356 12357 ret = wpas_nan_usd_update_publish(wpa_s, publish_id, ssi); 12358 fail: 12359 wpabuf_free(ssi); 12360 return ret; 12361 } 12362 12363 12364 static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd, 12365 char *buf, size_t buflen) 12366 { 12367 char *token, *context = NULL; 12368 int subscribe_id; 12369 struct nan_subscribe_params params; 12370 const char *service_name = NULL; 12371 struct wpabuf *ssi = NULL; 12372 int ret = -1; 12373 enum nan_service_protocol_type srv_proto_type = 0; 12374 12375 os_memset(¶ms, 0, sizeof(params)); 12376 params.freq = NAN_USD_DEFAULT_FREQ; 12377 12378 while ((token = str_token(cmd, " ", &context))) { 12379 if (os_strncmp(token, "service_name=", 13) == 0) { 12380 service_name = token + 13; 12381 continue; 12382 } 12383 12384 if (os_strcmp(token, "active=1") == 0) { 12385 params.active = true; 12386 continue; 12387 } 12388 12389 if (os_strncmp(token, "ttl=", 4) == 0) { 12390 params.ttl = atoi(token + 4); 12391 continue; 12392 } 12393 12394 if (os_strncmp(token, "freq=", 5) == 0) { 12395 params.freq = atoi(token + 5); 12396 continue; 12397 } 12398 12399 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 12400 srv_proto_type = atoi(token + 15); 12401 continue; 12402 } 12403 12404 if (os_strncmp(token, "ssi=", 4) == 0) { 12405 if (ssi) 12406 goto fail; 12407 ssi = wpabuf_parse_bin(token + 4); 12408 if (!ssi) 12409 goto fail; 12410 continue; 12411 } 12412 12413 wpa_printf(MSG_INFO, 12414 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s", 12415 token); 12416 goto fail; 12417 } 12418 12419 subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name, 12420 srv_proto_type, ssi, 12421 ¶ms); 12422 if (subscribe_id > 0) 12423 ret = os_snprintf(buf, buflen, "%d", subscribe_id); 12424 fail: 12425 wpabuf_free(ssi); 12426 return ret; 12427 } 12428 12429 12430 static int wpas_ctrl_nan_cancel_subscribe(struct wpa_supplicant *wpa_s, 12431 char *cmd) 12432 { 12433 char *token, *context = NULL; 12434 int subscribe_id = 0; 12435 12436 while ((token = str_token(cmd, " ", &context))) { 12437 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1) 12438 continue; 12439 wpa_printf(MSG_INFO, 12440 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s", 12441 token); 12442 return -1; 12443 } 12444 12445 if (subscribe_id <= 0) { 12446 wpa_printf(MSG_INFO, 12447 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id"); 12448 return -1; 12449 } 12450 12451 wpas_nan_usd_cancel_subscribe(wpa_s, subscribe_id); 12452 return 0; 12453 } 12454 12455 12456 static int wpas_ctrl_nan_transmit(struct wpa_supplicant *wpa_s, char *cmd) 12457 { 12458 char *token, *context = NULL; 12459 int handle = 0; 12460 int req_instance_id = 0; 12461 struct wpabuf *ssi = NULL; 12462 u8 peer_addr[ETH_ALEN]; 12463 int ret = -1; 12464 12465 os_memset(peer_addr, 0, ETH_ALEN); 12466 12467 while ((token = str_token(cmd, " ", &context))) { 12468 if (sscanf(token, "handle=%i", &handle) == 1) 12469 continue; 12470 12471 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1) 12472 continue; 12473 12474 if (os_strncmp(token, "address=", 8) == 0) { 12475 if (hwaddr_aton(token + 8, peer_addr) < 0) 12476 return -1; 12477 continue; 12478 } 12479 12480 if (os_strncmp(token, "ssi=", 4) == 0) { 12481 if (ssi) 12482 goto fail; 12483 ssi = wpabuf_parse_bin(token + 4); 12484 if (!ssi) 12485 goto fail; 12486 continue; 12487 } 12488 12489 wpa_printf(MSG_INFO, 12490 "CTRL: Invalid NAN_TRANSMIT parameter: %s", 12491 token); 12492 goto fail; 12493 } 12494 12495 if (handle <= 0) { 12496 wpa_printf(MSG_INFO, 12497 "CTRL: Invalid or missing NAN_TRANSMIT handle"); 12498 goto fail; 12499 } 12500 12501 if (is_zero_ether_addr(peer_addr)) { 12502 wpa_printf(MSG_INFO, 12503 "CTRL: Invalid or missing NAN_TRANSMIT address"); 12504 goto fail; 12505 } 12506 12507 ret = wpas_nan_usd_transmit(wpa_s, handle, ssi, NULL, peer_addr, 12508 req_instance_id); 12509 fail: 12510 wpabuf_free(ssi); 12511 return ret; 12512 } 12513 12514 #endif /* CONFIG_NAN_USD */ 12515 12516 12517 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 12518 char *buf, size_t *resp_len) 12519 { 12520 char *reply; 12521 const int reply_size = 4096; 12522 int reply_len; 12523 12524 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 12525 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 12526 os_strncmp(buf, "PMKSA_ADD ", 10) == 0 || 12527 os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 12528 if (wpa_debug_show_keys) 12529 wpa_dbg(wpa_s, MSG_DEBUG, 12530 "Control interface command '%s'", buf); 12531 else 12532 wpa_dbg(wpa_s, MSG_DEBUG, 12533 "Control interface command '%s [REMOVED]'", 12534 os_strncmp(buf, WPA_CTRL_RSP, 12535 os_strlen(WPA_CTRL_RSP)) == 0 ? 12536 WPA_CTRL_RSP : 12537 (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ? 12538 "SET_NETWORK" : "key-add")); 12539 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 12540 os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { 12541 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 12542 (const u8 *) buf, os_strlen(buf)); 12543 } else { 12544 int level = wpas_ctrl_cmd_debug_level(buf); 12545 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 12546 } 12547 12548 reply = os_malloc(reply_size); 12549 if (reply == NULL) { 12550 *resp_len = 1; 12551 return NULL; 12552 } 12553 12554 os_memcpy(reply, "OK\n", 3); 12555 reply_len = 3; 12556 12557 if (os_strcmp(buf, "PING") == 0) { 12558 os_memcpy(reply, "PONG\n", 5); 12559 reply_len = 5; 12560 } else if (os_strcmp(buf, "IFNAME") == 0) { 12561 reply_len = os_strlen(wpa_s->ifname); 12562 os_memcpy(reply, wpa_s->ifname, reply_len); 12563 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 12564 if (wpa_debug_reopen_file() < 0) 12565 reply_len = -1; 12566 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 12567 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 12568 } else if (os_strcmp(buf, "MIB") == 0) { 12569 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 12570 if (reply_len >= 0) { 12571 reply_len += eapol_sm_get_mib(wpa_s->eapol, 12572 reply + reply_len, 12573 reply_size - reply_len); 12574 #ifdef CONFIG_MACSEC 12575 reply_len += ieee802_1x_kay_get_mib( 12576 wpa_s->kay, reply + reply_len, 12577 reply_size - reply_len); 12578 #endif /* CONFIG_MACSEC */ 12579 } 12580 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 12581 reply_len = wpa_supplicant_ctrl_iface_status( 12582 wpa_s, buf + 6, reply, reply_size); 12583 } else if (os_strcmp(buf, "PMKSA") == 0) { 12584 reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); 12585 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 12586 wpas_ctrl_iface_pmksa_flush(wpa_s); 12587 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL 12588 } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) { 12589 reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10, 12590 reply, reply_size); 12591 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 12592 if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) 12593 reply_len = -1; 12594 #ifdef CONFIG_MESH 12595 } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { 12596 reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, 12597 reply, reply_size); 12598 } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { 12599 if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) 12600 reply_len = -1; 12601 #endif /* CONFIG_MESH */ 12602 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ 12603 } else if (os_strncmp(buf, "SET ", 4) == 0) { 12604 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 12605 reply_len = -1; 12606 } else if (os_strncmp(buf, "DUMP", 4) == 0) { 12607 reply_len = wpa_config_dump_values(wpa_s->conf, 12608 reply, reply_size); 12609 } else if (os_strncmp(buf, "GET ", 4) == 0) { 12610 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 12611 reply, reply_size); 12612 } else if (os_strcmp(buf, "LOGON") == 0) { 12613 eapol_sm_notify_logoff(wpa_s->eapol, false); 12614 } else if (os_strcmp(buf, "LOGOFF") == 0) { 12615 eapol_sm_notify_logoff(wpa_s->eapol, true); 12616 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 12617 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 12618 reply_len = -1; 12619 else 12620 wpas_request_connection(wpa_s); 12621 } else if (os_strcmp(buf, "REATTACH") == 0) { 12622 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || 12623 !wpa_s->current_ssid) 12624 reply_len = -1; 12625 else { 12626 wpa_s->reattach = 1; 12627 wpas_request_connection(wpa_s); 12628 } 12629 } else if (os_strcmp(buf, "RECONNECT") == 0) { 12630 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 12631 reply_len = -1; 12632 else if (wpa_s->disconnected) 12633 wpas_request_connection(wpa_s); 12634 #ifdef IEEE8021X_EAPOL 12635 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 12636 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 12637 reply_len = -1; 12638 #endif /* IEEE8021X_EAPOL */ 12639 #ifdef CONFIG_IEEE80211R 12640 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 12641 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 12642 reply_len = -1; 12643 #endif /* CONFIG_IEEE80211R */ 12644 #ifdef CONFIG_WPS 12645 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 12646 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 12647 if (res == -2) { 12648 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12649 reply_len = 17; 12650 } else if (res) 12651 reply_len = -1; 12652 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 12653 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 12654 if (res == -2) { 12655 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12656 reply_len = 17; 12657 } else if (res) 12658 reply_len = -1; 12659 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 12660 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 12661 reply, 12662 reply_size); 12663 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 12664 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 12665 wpa_s, buf + 14, reply, reply_size); 12666 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 12667 if (wpas_wps_cancel(wpa_s)) 12668 reply_len = -1; 12669 #ifdef CONFIG_WPS_NFC 12670 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 12671 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 12672 reply_len = -1; 12673 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 12674 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 12675 reply_len = -1; 12676 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 12677 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_config_token( 12678 wpa_s, buf + 21, reply, reply_size); 12679 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 12680 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 12681 wpa_s, buf + 14, reply, reply_size); 12682 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 12683 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 12684 buf + 17)) 12685 reply_len = -1; 12686 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 12687 reply_len = wpas_ctrl_nfc_get_handover_req( 12688 wpa_s, buf + 21, reply, reply_size); 12689 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 12690 reply_len = wpas_ctrl_nfc_get_handover_sel( 12691 wpa_s, buf + 21, reply, reply_size); 12692 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 12693 if (wpas_ctrl_nfc_report_handover(wpa_s, buf + 20)) 12694 reply_len = -1; 12695 #endif /* CONFIG_WPS_NFC */ 12696 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 12697 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 12698 reply_len = -1; 12699 #ifdef CONFIG_AP 12700 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 12701 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 12702 wpa_s, buf + 11, reply, reply_size); 12703 #endif /* CONFIG_AP */ 12704 #ifdef CONFIG_WPS_ER 12705 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 12706 if (wpas_wps_er_start(wpa_s, NULL)) 12707 reply_len = -1; 12708 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 12709 if (wpas_wps_er_start(wpa_s, buf + 13)) 12710 reply_len = -1; 12711 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 12712 wpas_wps_er_stop(wpa_s); 12713 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 12714 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 12715 reply_len = -1; 12716 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 12717 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 12718 if (ret == -2) { 12719 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 12720 reply_len = 17; 12721 } else if (ret == -3) { 12722 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 12723 reply_len = 18; 12724 } else if (ret == -4) { 12725 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 12726 reply_len = 20; 12727 } else if (ret) 12728 reply_len = -1; 12729 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 12730 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 12731 reply_len = -1; 12732 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 12733 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 12734 buf + 18)) 12735 reply_len = -1; 12736 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 12737 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 12738 reply_len = -1; 12739 #ifdef CONFIG_WPS_NFC 12740 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 12741 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 12742 wpa_s, buf + 24, reply, reply_size); 12743 #endif /* CONFIG_WPS_NFC */ 12744 #endif /* CONFIG_WPS_ER */ 12745 #endif /* CONFIG_WPS */ 12746 #ifdef CONFIG_IBSS_RSN 12747 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 12748 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 12749 reply_len = -1; 12750 #endif /* CONFIG_IBSS_RSN */ 12751 #ifdef CONFIG_MESH 12752 } else if (os_strncmp(buf, "MESH_INTERFACE_ADD ", 19) == 0) { 12753 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 12754 wpa_s, buf + 19, reply, reply_size); 12755 } else if (os_strcmp(buf, "MESH_INTERFACE_ADD") == 0) { 12756 reply_len = wpa_supplicant_ctrl_iface_mesh_interface_add( 12757 wpa_s, "", reply, reply_size); 12758 } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) { 12759 if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15)) 12760 reply_len = -1; 12761 } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) { 12762 if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s, 12763 buf + 18)) 12764 reply_len = -1; 12765 } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) { 12766 if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17)) 12767 reply_len = -1; 12768 } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) { 12769 if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14)) 12770 reply_len = -1; 12771 } else if (os_strncmp(buf, "MESH_LINK_PROBE ", 16) == 0) { 12772 if (wpa_supplicant_ctrl_iface_mesh_link_probe(wpa_s, buf + 16)) 12773 reply_len = -1; 12774 #endif /* CONFIG_MESH */ 12775 #ifdef CONFIG_P2P 12776 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 12777 if (p2p_ctrl_find(wpa_s, buf + 8)) 12778 reply_len = -1; 12779 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 12780 if (p2p_ctrl_find(wpa_s, "")) 12781 reply_len = -1; 12782 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 12783 wpas_p2p_stop_find(wpa_s); 12784 } else if (os_strncmp(buf, "P2P_ASP_PROVISION ", 18) == 0) { 12785 if (p2p_ctrl_asp_provision(wpa_s, buf + 18)) 12786 reply_len = -1; 12787 } else if (os_strncmp(buf, "P2P_ASP_PROVISION_RESP ", 23) == 0) { 12788 if (p2p_ctrl_asp_provision_resp(wpa_s, buf + 23)) 12789 reply_len = -1; 12790 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 12791 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 12792 reply_size); 12793 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 12794 if (p2p_ctrl_listen(wpa_s, buf + 11)) 12795 reply_len = -1; 12796 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 12797 if (p2p_ctrl_listen(wpa_s, "")) 12798 reply_len = -1; 12799 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 12800 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 12801 reply_len = -1; 12802 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 12803 if (p2p_ctrl_group_add(wpa_s, "")) 12804 reply_len = -1; 12805 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 12806 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 12807 reply_len = -1; 12808 } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) { 12809 reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply, 12810 reply_size); 12811 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 12812 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 12813 reply_len = -1; 12814 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 12815 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 12816 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 12817 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 12818 reply_size); 12819 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 12820 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 12821 reply_len = -1; 12822 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 12823 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 12824 reply_len = -1; 12825 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 12826 wpas_p2p_sd_service_update(wpa_s); 12827 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 12828 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 12829 reply_len = -1; 12830 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 12831 wpas_p2p_service_flush(wpa_s); 12832 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 12833 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 12834 reply_len = -1; 12835 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 12836 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 12837 reply_len = -1; 12838 } else if (os_strncmp(buf, "P2P_SERVICE_REP ", 16) == 0) { 12839 if (p2p_ctrl_service_replace(wpa_s, buf + 16) < 0) 12840 reply_len = -1; 12841 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 12842 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 12843 reply_len = -1; 12844 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 12845 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 12846 reply_len = -1; 12847 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 12848 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 12849 reply_size); 12850 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 12851 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 12852 reply_len = -1; 12853 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 12854 p2p_ctrl_flush(wpa_s); 12855 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 12856 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 12857 reply_len = -1; 12858 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 12859 if (wpas_p2p_cancel(wpa_s)) 12860 reply_len = -1; 12861 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 12862 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 12863 reply_len = -1; 12864 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 12865 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 12866 reply_len = -1; 12867 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 12868 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 12869 reply_len = -1; 12870 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 12871 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 12872 reply_len = -1; 12873 } else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) { 12874 if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0) 12875 reply_len = -1; 12876 } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) { 12877 if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13)) 12878 reply_len = -1; 12879 } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) { 12880 if (wpas_p2p_lo_stop(wpa_s)) 12881 reply_len = -1; 12882 #endif /* CONFIG_P2P */ 12883 #ifdef CONFIG_WIFI_DISPLAY 12884 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 12885 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 12886 reply_len = -1; 12887 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 12888 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 12889 reply, reply_size); 12890 #endif /* CONFIG_WIFI_DISPLAY */ 12891 #ifdef CONFIG_INTERWORKING 12892 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 12893 if (interworking_fetch_anqp(wpa_s) < 0) 12894 reply_len = -1; 12895 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 12896 interworking_stop_fetch_anqp(wpa_s); 12897 } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) { 12898 if (ctrl_interworking_select(wpa_s, NULL) < 0) 12899 reply_len = -1; 12900 } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) { 12901 if (ctrl_interworking_select(wpa_s, buf + 20) < 0) 12902 reply_len = -1; 12903 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 12904 if (ctrl_interworking_connect(wpa_s, buf + 21, 0) < 0) 12905 reply_len = -1; 12906 } else if (os_strncmp(buf, "INTERWORKING_ADD_NETWORK ", 25) == 0) { 12907 int id; 12908 12909 id = ctrl_interworking_connect(wpa_s, buf + 25, 1); 12910 if (id < 0) 12911 reply_len = -1; 12912 else { 12913 reply_len = os_snprintf(reply, reply_size, "%d\n", id); 12914 if (os_snprintf_error(reply_size, reply_len)) 12915 reply_len = -1; 12916 } 12917 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 12918 if (get_anqp(wpa_s, buf + 9) < 0) 12919 reply_len = -1; 12920 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 12921 if (gas_request(wpa_s, buf + 12) < 0) 12922 reply_len = -1; 12923 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 12924 reply_len = gas_response_get(wpa_s, buf + 17, reply, 12925 reply_size); 12926 #endif /* CONFIG_INTERWORKING */ 12927 #ifdef CONFIG_HS20 12928 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 12929 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 12930 reply_len = -1; 12931 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 12932 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 12933 reply_len = -1; 12934 } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) { 12935 if (hs20_icon_request(wpa_s, buf + 18, 0) < 0) 12936 reply_len = -1; 12937 } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) { 12938 if (hs20_icon_request(wpa_s, buf + 14, 1) < 0) 12939 reply_len = -1; 12940 } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) { 12941 reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size); 12942 } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) { 12943 if (del_hs20_icon(wpa_s, buf + 14) < 0) 12944 reply_len = -1; 12945 } else if (os_strcmp(buf, "FETCH_OSU") == 0) { 12946 if (hs20_fetch_osu(wpa_s, 0) < 0) 12947 reply_len = -1; 12948 } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) { 12949 if (hs20_fetch_osu(wpa_s, 1) < 0) 12950 reply_len = -1; 12951 } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) { 12952 hs20_cancel_fetch_osu(wpa_s); 12953 #endif /* CONFIG_HS20 */ 12954 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 12955 { 12956 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 12957 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 12958 reply_len = -1; 12959 else { 12960 /* 12961 * Notify response from timeout to allow the control 12962 * interface response to be sent first. 12963 */ 12964 eloop_register_timeout(0, 0, wpas_ctrl_eapol_response, 12965 wpa_s, NULL); 12966 } 12967 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 12968 if (wpa_supplicant_reload_configuration(wpa_s)) 12969 reply_len = -1; 12970 } else if (os_strcmp(buf, "TERMINATE") == 0) { 12971 wpa_supplicant_terminate_proc(wpa_s->global); 12972 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 12973 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 12974 reply_len = -1; 12975 } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) { 12976 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore( 12977 wpa_s, buf + 12, reply, reply_size); 12978 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 12979 /* deprecated backwards compatibility alias for BSSID_IGNORE */ 12980 reply_len = wpa_supplicant_ctrl_iface_bssid_ignore( 12981 wpa_s, buf + 9, reply, reply_size); 12982 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 12983 reply_len = wpa_supplicant_ctrl_iface_log_level( 12984 wpa_s, buf + 9, reply, reply_size); 12985 } else if (os_strncmp(buf, "LIST_NETWORKS ", 14) == 0) { 12986 reply_len = wpa_supplicant_ctrl_iface_list_networks( 12987 wpa_s, buf + 14, reply, reply_size); 12988 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 12989 reply_len = wpa_supplicant_ctrl_iface_list_networks( 12990 wpa_s, NULL, reply, reply_size); 12991 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 12992 wpas_request_disconnection(wpa_s); 12993 } else if (os_strcmp(buf, "SCAN") == 0) { 12994 wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); 12995 } else if (os_strncmp(buf, "SCAN ", 5) == 0) { 12996 wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len); 12997 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 12998 reply_len = wpa_supplicant_ctrl_iface_scan_results( 12999 wpa_s, reply, reply_size); 13000 } else if (os_strcmp(buf, "ABORT_SCAN") == 0) { 13001 if (wpas_abort_ongoing_scan(wpa_s) < 0) 13002 reply_len = -1; 13003 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 13004 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 13005 reply_len = -1; 13006 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 13007 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 13008 reply_len = -1; 13009 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 13010 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 13011 reply_len = -1; 13012 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 13013 reply_len = wpa_supplicant_ctrl_iface_add_network( 13014 wpa_s, reply, reply_size); 13015 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 13016 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 13017 reply_len = -1; 13018 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 13019 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 13020 reply_len = -1; 13021 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 13022 reply_len = wpa_supplicant_ctrl_iface_get_network( 13023 wpa_s, buf + 12, reply, reply_size); 13024 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 13025 if (wpa_supplicant_ctrl_iface_dup_network(wpa_s, buf + 12, 13026 wpa_s)) 13027 reply_len = -1; 13028 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 13029 reply_len = wpa_supplicant_ctrl_iface_list_creds( 13030 wpa_s, reply, reply_size); 13031 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 13032 reply_len = wpa_supplicant_ctrl_iface_add_cred( 13033 wpa_s, reply, reply_size); 13034 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 13035 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 13036 reply_len = -1; 13037 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 13038 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 13039 reply_len = -1; 13040 } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) { 13041 reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9, 13042 reply, 13043 reply_size); 13044 #ifndef CONFIG_NO_CONFIG_WRITE 13045 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 13046 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 13047 reply_len = -1; 13048 #endif /* CONFIG_NO_CONFIG_WRITE */ 13049 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 13050 reply_len = wpa_supplicant_ctrl_iface_get_capability( 13051 wpa_s, buf + 15, reply, reply_size); 13052 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 13053 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 13054 reply_len = -1; 13055 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 13056 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 13057 reply_len = -1; 13058 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 13059 reply_len = wpa_supplicant_global_iface_list( 13060 wpa_s->global, reply, reply_size); 13061 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 13062 reply_len = wpa_supplicant_global_iface_interfaces( 13063 wpa_s->global, buf + 10, reply, reply_size); 13064 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 13065 reply_len = wpa_supplicant_ctrl_iface_bss( 13066 wpa_s, buf + 4, reply, reply_size); 13067 #ifdef CONFIG_AP 13068 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 13069 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 13070 } else if (os_strncmp(buf, "STA ", 4) == 0) { 13071 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 13072 reply_size); 13073 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 13074 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 13075 reply_size); 13076 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 13077 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 13078 reply_len = -1; 13079 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 13080 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 13081 reply_len = -1; 13082 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 13083 if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12)) 13084 reply_len = -1; 13085 } else if (os_strcmp(buf, "STOP_AP") == 0) { 13086 if (wpas_ap_stop_ap(wpa_s)) 13087 reply_len = -1; 13088 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 13089 if (wpas_ap_update_beacon(wpa_s)) 13090 reply_len = -1; 13091 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { 13092 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { 13093 if (ap_ctrl_iface_acl_add_mac(wpa_s, 13094 DENY_UNLESS_ACCEPTED, 13095 buf + 19) || 13096 ap_ctrl_iface_set_acl(wpa_s)) 13097 reply_len = -1; 13098 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { 13099 if (ap_ctrl_iface_acl_del_mac(wpa_s, 13100 DENY_UNLESS_ACCEPTED, 13101 buf + 19) || 13102 ap_ctrl_iface_set_acl(wpa_s) || 13103 ap_ctrl_iface_disassoc_accept_mac(wpa_s)) 13104 reply_len = -1; 13105 } else if (os_strcmp(buf + 11, "SHOW") == 0) { 13106 reply_len = ap_ctrl_iface_acl_show_mac( 13107 wpa_s, DENY_UNLESS_ACCEPTED, 13108 reply, reply_size); 13109 } else if (os_strcmp(buf + 11, "CLEAR") == 0) { 13110 ap_ctrl_iface_acl_clear_list(wpa_s, 13111 DENY_UNLESS_ACCEPTED); 13112 if (ap_ctrl_iface_set_acl(wpa_s) || 13113 ap_ctrl_iface_disassoc_accept_mac(wpa_s)) 13114 reply_len = -1; 13115 } else { 13116 reply_len = -1; 13117 } 13118 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { 13119 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { 13120 if (ap_ctrl_iface_acl_add_mac(wpa_s, 13121 ACCEPT_UNLESS_DENIED, 13122 buf + 17) || 13123 ap_ctrl_iface_set_acl(wpa_s) || 13124 ap_ctrl_iface_disassoc_deny_mac(wpa_s)) 13125 reply_len = -1; 13126 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { 13127 if (ap_ctrl_iface_acl_del_mac(wpa_s, 13128 ACCEPT_UNLESS_DENIED, 13129 buf + 17) || 13130 ap_ctrl_iface_set_acl(wpa_s)) 13131 reply_len = -1; 13132 } else if (os_strcmp(buf + 9, "SHOW") == 0) { 13133 reply_len = ap_ctrl_iface_acl_show_mac( 13134 wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size); 13135 } else if (os_strcmp(buf + 9, "CLEAR") == 0) { 13136 ap_ctrl_iface_acl_clear_list(wpa_s, 13137 ACCEPT_UNLESS_DENIED); 13138 if (ap_ctrl_iface_set_acl(wpa_s)) 13139 reply_len = -1; 13140 } else { 13141 reply_len = -1; 13142 } 13143 #endif /* CONFIG_AP */ 13144 } else if (os_strcmp(buf, "SUSPEND") == 0) { 13145 wpas_notify_suspend(wpa_s->global); 13146 } else if (os_strcmp(buf, "RESUME") == 0) { 13147 wpas_notify_resume(wpa_s->global); 13148 #ifdef CONFIG_TESTING_OPTIONS 13149 } else if (os_strcmp(buf, "DROP_SA") == 0) { 13150 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 13151 #endif /* CONFIG_TESTING_OPTIONS */ 13152 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 13153 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 13154 reply_len = -1; 13155 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 13156 wpa_s->auto_reconnect_disabled = atoi(buf + 16) == 0; 13157 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 13158 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 13159 reply_len = -1; 13160 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 13161 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 13162 buf + 17)) 13163 reply_len = -1; 13164 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 13165 wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10); 13166 #ifdef CONFIG_TDLS 13167 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 13168 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 13169 reply_len = -1; 13170 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 13171 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 13172 reply_len = -1; 13173 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 13174 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 13175 reply_len = -1; 13176 } else if (os_strncmp(buf, "TDLS_CHAN_SWITCH ", 17) == 0) { 13177 if (wpa_supplicant_ctrl_iface_tdls_chan_switch(wpa_s, 13178 buf + 17)) 13179 reply_len = -1; 13180 } else if (os_strncmp(buf, "TDLS_CANCEL_CHAN_SWITCH ", 24) == 0) { 13181 if (wpa_supplicant_ctrl_iface_tdls_cancel_chan_switch(wpa_s, 13182 buf + 24)) 13183 reply_len = -1; 13184 } else if (os_strncmp(buf, "TDLS_LINK_STATUS ", 17) == 0) { 13185 reply_len = wpa_supplicant_ctrl_iface_tdls_link_status( 13186 wpa_s, buf + 17, reply, reply_size); 13187 #endif /* CONFIG_TDLS */ 13188 #ifndef CONFIG_NO_WMM_AC 13189 } else if (os_strcmp(buf, "WMM_AC_STATUS") == 0) { 13190 reply_len = wpas_wmm_ac_status(wpa_s, reply, reply_size); 13191 } else if (os_strncmp(buf, "WMM_AC_ADDTS ", 13) == 0) { 13192 if (wmm_ac_ctrl_addts(wpa_s, buf + 13)) 13193 reply_len = -1; 13194 } else if (os_strncmp(buf, "WMM_AC_DELTS ", 13) == 0) { 13195 if (wmm_ac_ctrl_delts(wpa_s, buf + 13)) 13196 reply_len = -1; 13197 #endif /* CONFIG_NO_WMM_AC */ 13198 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 13199 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 13200 reply_size); 13201 } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) { 13202 if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14)) 13203 reply_len = -1; 13204 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 13205 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 13206 reply_size); 13207 #ifdef CONFIG_AUTOSCAN 13208 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 13209 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 13210 reply_len = -1; 13211 #endif /* CONFIG_AUTOSCAN */ 13212 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 13213 reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, 13214 reply_size); 13215 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { 13216 reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply, 13217 reply_size); 13218 #ifdef ANDROID 13219 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 13220 reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, 13221 reply_size); 13222 #endif /* ANDROID */ 13223 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 13224 reply_len = wpa_supplicant_vendor_cmd(wpa_s, buf + 7, reply, 13225 reply_size); 13226 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 13227 pmksa_cache_clear_current(wpa_s->wpa); 13228 eapol_sm_request_reauth(wpa_s->eapol); 13229 #ifdef CONFIG_WNM 13230 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 13231 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 13232 reply_len = -1; 13233 } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) { 13234 if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14)) 13235 reply_len = -1; 13236 } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) { 13237 if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) 13238 reply_len = -1; 13239 #endif /* CONFIG_WNM */ 13240 #ifdef CONFIG_WNM_AP 13241 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 13242 if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18)) 13243 reply_len = -1; 13244 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 13245 if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13)) 13246 reply_len = -1; 13247 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 13248 if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11)) 13249 reply_len = -1; 13250 #endif /* CONFIG_WNM_AP */ 13251 } else if (os_strcmp(buf, "FLUSH") == 0) { 13252 wpa_supplicant_ctrl_iface_flush(wpa_s); 13253 } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { 13254 reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply, 13255 reply_size); 13256 #ifdef CONFIG_TESTING_OPTIONS 13257 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 13258 if (wpas_ctrl_iface_mgmt_tx(wpa_s, buf + 8) < 0) 13259 reply_len = -1; 13260 } else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) { 13261 wpas_ctrl_iface_mgmt_tx_done(wpa_s); 13262 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 13263 if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0) 13264 reply_len = -1; 13265 } else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) { 13266 if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0) 13267 reply_len = -1; 13268 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 13269 if (wpas_ctrl_iface_eapol_rx(wpa_s, buf + 9) < 0) 13270 reply_len = -1; 13271 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) { 13272 if (wpas_ctrl_iface_eapol_tx(wpa_s, buf + 9) < 0) 13273 reply_len = -1; 13274 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 13275 if (wpas_ctrl_iface_data_test_config(wpa_s, buf + 17) < 0) 13276 reply_len = -1; 13277 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 13278 if (wpas_ctrl_iface_data_test_tx(wpa_s, buf + 13) < 0) 13279 reply_len = -1; 13280 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 13281 if (wpas_ctrl_iface_data_test_frame(wpa_s, buf + 16) < 0) 13282 reply_len = -1; 13283 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 13284 if (testing_set_fail_pattern(true, buf + 16) < 0) 13285 reply_len = -1; 13286 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 13287 reply_len = testing_get_fail_pattern(true, reply, reply_size); 13288 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 13289 if (testing_set_fail_pattern(false, buf + 10) < 0) 13290 reply_len = -1; 13291 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 13292 reply_len = testing_get_fail_pattern(false, reply, reply_size); 13293 } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) { 13294 if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0) 13295 reply_len = -1; 13296 } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) { 13297 if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0) 13298 reply_len = -1; 13299 } else if (os_strncmp(buf, "TEST_EAPOL_M2_ELEMS ", 20) == 0) { 13300 if (wpas_ctrl_test_eapol_m2_elems(wpa_s, buf + 20) < 0) 13301 reply_len = -1; 13302 } else if (os_strncmp(buf, "TEST_EAPOL_M4_ELEMS ", 20) == 0) { 13303 if (wpas_ctrl_test_eapol_m4_elems(wpa_s, buf + 20) < 0) 13304 reply_len = -1; 13305 } else if (os_strcmp(buf, "RESET_PN") == 0) { 13306 if (wpas_ctrl_reset_pn(wpa_s) < 0) 13307 reply_len = -1; 13308 } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { 13309 if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) 13310 reply_len = -1; 13311 } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { 13312 if (wpas_ctrl_resend_assoc(wpa_s) < 0) 13313 reply_len = -1; 13314 } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) { 13315 sme_event_unprot_disconnect( 13316 wpa_s, wpa_s->bssid, NULL, 13317 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); 13318 } else if (os_strncmp(buf, "TWT_SETUP ", 10) == 0) { 13319 if (wpas_ctrl_iface_send_twt_setup(wpa_s, buf + 9)) 13320 reply_len = -1; 13321 } else if (os_strcmp(buf, "TWT_SETUP") == 0) { 13322 if (wpas_ctrl_iface_send_twt_setup(wpa_s, "")) 13323 reply_len = -1; 13324 } else if (os_strncmp(buf, "TWT_TEARDOWN ", 13) == 0) { 13325 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, buf + 12)) 13326 reply_len = -1; 13327 } else if (os_strcmp(buf, "TWT_TEARDOWN") == 0) { 13328 if (wpas_ctrl_iface_send_twt_teardown(wpa_s, "")) 13329 reply_len = -1; 13330 } else if (os_strncmp(buf, "ML_PROBE_REQ ", 13) == 0) { 13331 if (wpas_ctrl_ml_probe(wpa_s, buf + 13)) 13332 reply_len = -1; 13333 #endif /* CONFIG_TESTING_OPTIONS */ 13334 } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { 13335 if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) 13336 reply_len = -1; 13337 } else if (os_strncmp(buf, "VENDOR_ELEM_GET ", 16) == 0) { 13338 reply_len = wpas_ctrl_vendor_elem_get(wpa_s, buf + 16, reply, 13339 reply_size); 13340 } else if (os_strncmp(buf, "VENDOR_ELEM_REMOVE ", 19) == 0) { 13341 if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0) 13342 reply_len = -1; 13343 #ifndef CONFIG_NO_RRM 13344 } else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) { 13345 if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20)) 13346 reply_len = -1; 13347 #endif /* CONFIG_NO_RRM */ 13348 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 13349 wpas_ctrl_iface_erp_flush(wpa_s); 13350 } else if (os_strncmp(buf, "MAC_RAND_SCAN ", 14) == 0) { 13351 if (wpas_ctrl_iface_mac_rand_scan(wpa_s, buf + 14)) 13352 reply_len = -1; 13353 } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { 13354 reply_len = wpas_ctrl_iface_get_pref_freq_list( 13355 wpa_s, buf + 19, reply, reply_size); 13356 #ifdef CONFIG_FILS 13357 } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) { 13358 if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17)) 13359 reply_len = -1; 13360 } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) { 13361 wpas_flush_fils_hlp_req(wpa_s); 13362 #endif /* CONFIG_FILS */ 13363 #ifdef CONFIG_DPP 13364 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 13365 int res; 13366 13367 res = wpas_dpp_qr_code(wpa_s, buf + 12); 13368 if (res < 0) { 13369 reply_len = -1; 13370 } else { 13371 reply_len = os_snprintf(reply, reply_size, "%d", res); 13372 if (os_snprintf_error(reply_size, reply_len)) 13373 reply_len = -1; 13374 } 13375 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) { 13376 int res; 13377 13378 res = wpas_dpp_nfc_uri(wpa_s, buf + 12); 13379 if (res < 0) { 13380 reply_len = -1; 13381 } else { 13382 reply_len = os_snprintf(reply, reply_size, "%d", res); 13383 if (os_snprintf_error(reply_size, reply_len)) 13384 reply_len = -1; 13385 } 13386 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) { 13387 int res; 13388 13389 res = wpas_dpp_nfc_handover_req(wpa_s, buf + 20); 13390 if (res < 0) { 13391 reply_len = -1; 13392 } else { 13393 reply_len = os_snprintf(reply, reply_size, "%d", res); 13394 if (os_snprintf_error(reply_size, reply_len)) 13395 reply_len = -1; 13396 } 13397 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) { 13398 int res; 13399 13400 res = wpas_dpp_nfc_handover_sel(wpa_s, buf + 20); 13401 if (res < 0) { 13402 reply_len = -1; 13403 } else { 13404 reply_len = os_snprintf(reply, reply_size, "%d", res); 13405 if (os_snprintf_error(reply_size, reply_len)) 13406 reply_len = -1; 13407 } 13408 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 13409 int res; 13410 13411 res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); 13412 if (res < 0) { 13413 reply_len = -1; 13414 } else { 13415 reply_len = os_snprintf(reply, reply_size, "%d", res); 13416 if (os_snprintf_error(reply_size, reply_len)) 13417 reply_len = -1; 13418 } 13419 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 13420 if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0) 13421 reply_len = -1; 13422 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 13423 const char *uri; 13424 13425 uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22)); 13426 if (!uri) { 13427 reply_len = -1; 13428 } else { 13429 reply_len = os_snprintf(reply, reply_size, "%s", uri); 13430 if (os_snprintf_error(reply_size, reply_len)) 13431 reply_len = -1; 13432 } 13433 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 13434 reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), 13435 reply, reply_size); 13436 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { 13437 if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18), 13438 os_strchr(buf + 18, ' ')) < 0) 13439 reply_len = -1; 13440 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 13441 if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) 13442 reply_len = -1; 13443 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 13444 if (wpas_dpp_listen(wpa_s, buf + 11) < 0) 13445 reply_len = -1; 13446 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 13447 wpas_dpp_stop(wpa_s); 13448 wpas_dpp_listen_stop(wpa_s); 13449 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 13450 int res; 13451 13452 res = dpp_configurator_add(wpa_s->dpp, buf + 20); 13453 if (res < 0) { 13454 reply_len = -1; 13455 } else { 13456 reply_len = os_snprintf(reply, reply_size, "%d", res); 13457 if (os_snprintf_error(reply_size, reply_len)) 13458 reply_len = -1; 13459 } 13460 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) { 13461 if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0) 13462 reply_len = -1; 13463 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 13464 if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) 13465 reply_len = -1; 13466 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 13467 if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) 13468 reply_len = -1; 13469 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 13470 reply_len = dpp_configurator_get_key_id(wpa_s->dpp, 13471 atoi(buf + 25), 13472 reply, reply_size); 13473 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 13474 int res; 13475 13476 res = wpas_dpp_pkex_add(wpa_s, buf + 12); 13477 if (res < 0) { 13478 reply_len = -1; 13479 } else { 13480 reply_len = os_snprintf(reply, reply_size, "%d", res); 13481 if (os_snprintf_error(reply_size, reply_len)) 13482 reply_len = -1; 13483 } 13484 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 13485 if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) 13486 reply_len = -1; 13487 } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) { 13488 if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0) 13489 reply_len = -1; 13490 #ifdef CONFIG_DPP2 13491 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { 13492 if (wpas_dpp_controller_start(wpa_s, buf + 20) < 0) 13493 reply_len = -1; 13494 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { 13495 if (wpas_dpp_controller_start(wpa_s, NULL) < 0) 13496 reply_len = -1; 13497 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { 13498 dpp_controller_stop(wpa_s->dpp); 13499 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { 13500 if (wpas_dpp_chirp(wpa_s, buf + 9) < 0) 13501 reply_len = -1; 13502 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { 13503 wpas_dpp_chirp_stop(wpa_s); 13504 } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) { 13505 if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0) 13506 reply_len = -1; 13507 } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) { 13508 if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0) 13509 reply_len = -1; 13510 #endif /* CONFIG_DPP2 */ 13511 #ifdef CONFIG_DPP3 13512 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) { 13513 if (wpas_dpp_push_button(wpa_s, NULL) < 0) 13514 reply_len = -1; 13515 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) { 13516 if (wpas_dpp_push_button(wpa_s, buf + 15) < 0) 13517 reply_len = -1; 13518 #endif /* CONFIG_DPP3 */ 13519 #endif /* CONFIG_DPP */ 13520 #ifdef CONFIG_NAN_USD 13521 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) { 13522 reply_len = wpas_ctrl_nan_publish(wpa_s, buf + 12, reply, 13523 reply_size); 13524 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) { 13525 if (wpas_ctrl_nan_cancel_publish(wpa_s, buf + 19) < 0) 13526 reply_len = -1; 13527 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) { 13528 if (wpas_ctrl_nan_update_publish(wpa_s, buf + 19) < 0) 13529 reply_len = -1; 13530 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) { 13531 reply_len = wpas_ctrl_nan_subscribe(wpa_s, buf + 14, reply, 13532 reply_size); 13533 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) { 13534 if (wpas_ctrl_nan_cancel_subscribe(wpa_s, buf + 21) < 0) 13535 reply_len = -1; 13536 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) { 13537 if (wpas_ctrl_nan_transmit(wpa_s, buf + 13) < 0) 13538 reply_len = -1; 13539 #endif /* CONFIG_NAN_USD */ 13540 #ifdef CONFIG_PASN 13541 } else if (os_strncmp(buf, "PASN_START ", 11) == 0) { 13542 if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0) 13543 reply_len = -1; 13544 } else if (os_strcmp(buf, "PASN_STOP") == 0) { 13545 wpas_pasn_auth_stop(wpa_s); 13546 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) { 13547 reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size); 13548 } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) { 13549 if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0) 13550 reply_len = -1; 13551 #ifdef CONFIG_TESTING_OPTIONS 13552 } else if (os_strncmp(buf, "PASN_DRIVER ", 12) == 0) { 13553 if (wpas_ctrl_iface_pasn_driver(wpa_s, buf + 12) < 0) 13554 reply_len = -1; 13555 #endif /* CONFIG_TESTING_OPTIONS */ 13556 #endif /* CONFIG_PASN */ 13557 #ifndef CONFIG_NO_ROBUST_AV 13558 } else if (os_strncmp(buf, "MSCS ", 5) == 0) { 13559 if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5)) 13560 reply_len = -1; 13561 } else if (os_strncmp(buf, "SCS ", 4) == 0) { 13562 if (wpas_ctrl_iface_configure_scs(wpa_s, buf + 4)) 13563 reply_len = -1; 13564 } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) { 13565 if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10)) 13566 reply_len = -1; 13567 } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) { 13568 if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11)) 13569 reply_len = -1; 13570 #endif /* CONFIG_NO_ROBUST_AV */ 13571 } else if (os_strcmp(buf, "MLO_STATUS") == 0) { 13572 reply_len = wpas_ctrl_iface_mlo_status(wpa_s, reply, 13573 reply_size); 13574 } else if (os_strcmp(buf, "MLO_SIGNAL_POLL") == 0) { 13575 reply_len = wpas_ctrl_iface_mlo_signal_poll(wpa_s, reply, 13576 reply_size); 13577 } else { 13578 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 13579 reply_len = 16; 13580 } 13581 13582 if (reply_len < 0) { 13583 os_memcpy(reply, "FAIL\n", 5); 13584 reply_len = 5; 13585 } 13586 13587 *resp_len = reply_len; 13588 return reply; 13589 } 13590 13591 13592 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 13593 char *cmd) 13594 { 13595 struct wpa_interface iface; 13596 char *pos, *extra; 13597 struct wpa_supplicant *wpa_s; 13598 unsigned int create_iface = 0; 13599 u8 mac_addr[ETH_ALEN]; 13600 enum wpa_driver_if_type type = WPA_IF_STATION; 13601 13602 /* 13603 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 13604 * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]] 13605 */ 13606 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 13607 13608 os_memset(&iface, 0, sizeof(iface)); 13609 13610 do { 13611 iface.ifname = pos = cmd; 13612 pos = os_strchr(pos, '\t'); 13613 if (pos) 13614 *pos++ = '\0'; 13615 if (iface.ifname[0] == '\0') 13616 return -1; 13617 if (pos == NULL) 13618 break; 13619 13620 iface.confname = pos; 13621 pos = os_strchr(pos, '\t'); 13622 if (pos) 13623 *pos++ = '\0'; 13624 if (iface.confname[0] == '\0') 13625 iface.confname = NULL; 13626 if (pos == NULL) 13627 break; 13628 13629 iface.driver = pos; 13630 pos = os_strchr(pos, '\t'); 13631 if (pos) 13632 *pos++ = '\0'; 13633 if (iface.driver[0] == '\0') 13634 iface.driver = NULL; 13635 if (pos == NULL) 13636 break; 13637 13638 iface.ctrl_interface = pos; 13639 pos = os_strchr(pos, '\t'); 13640 if (pos) 13641 *pos++ = '\0'; 13642 if (iface.ctrl_interface[0] == '\0') 13643 iface.ctrl_interface = NULL; 13644 if (pos == NULL) 13645 break; 13646 13647 iface.driver_param = pos; 13648 pos = os_strchr(pos, '\t'); 13649 if (pos) 13650 *pos++ = '\0'; 13651 if (iface.driver_param[0] == '\0') 13652 iface.driver_param = NULL; 13653 if (pos == NULL) 13654 break; 13655 13656 iface.bridge_ifname = pos; 13657 pos = os_strchr(pos, '\t'); 13658 if (pos) 13659 *pos++ = '\0'; 13660 if (iface.bridge_ifname[0] == '\0') 13661 iface.bridge_ifname = NULL; 13662 if (pos == NULL) 13663 break; 13664 13665 extra = pos; 13666 pos = os_strchr(pos, '\t'); 13667 if (pos) 13668 *pos++ = '\0'; 13669 if (!extra[0]) 13670 break; 13671 13672 if (os_strcmp(extra, "create") == 0) { 13673 create_iface = 1; 13674 if (!pos) 13675 break; 13676 13677 if (os_strcmp(pos, "sta") == 0) { 13678 type = WPA_IF_STATION; 13679 } else if (os_strcmp(pos, "ap") == 0) { 13680 type = WPA_IF_AP_BSS; 13681 } else { 13682 wpa_printf(MSG_DEBUG, 13683 "INTERFACE_ADD unsupported interface type: '%s'", 13684 pos); 13685 return -1; 13686 } 13687 } else { 13688 wpa_printf(MSG_DEBUG, 13689 "INTERFACE_ADD unsupported extra parameter: '%s'", 13690 extra); 13691 return -1; 13692 } 13693 } while (0); 13694 13695 if (create_iface) { 13696 wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'", 13697 iface.ifname); 13698 if (!global->ifaces) 13699 return -1; 13700 if (wpa_drv_if_add(global->ifaces, type, iface.ifname, 13701 NULL, NULL, NULL, mac_addr, NULL) < 0) { 13702 wpa_printf(MSG_ERROR, 13703 "CTRL_IFACE interface creation failed"); 13704 return -1; 13705 } 13706 13707 wpa_printf(MSG_DEBUG, 13708 "CTRL_IFACE interface '%s' created with MAC addr: " 13709 MACSTR, iface.ifname, MAC2STR(mac_addr)); 13710 } 13711 13712 if (wpa_supplicant_get_iface(global, iface.ifname)) 13713 goto fail; 13714 13715 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); 13716 if (!wpa_s) 13717 goto fail; 13718 wpa_s->added_vif = create_iface; 13719 return 0; 13720 13721 fail: 13722 if (create_iface) { 13723 /* wpa_supplicant does not create multi-BSS AP, so collapse to 13724 * WPA_IF_STATION to avoid unwanted clean up in the driver. */ 13725 wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname); 13726 } 13727 return -1; 13728 } 13729 13730 13731 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 13732 char *cmd) 13733 { 13734 struct wpa_supplicant *wpa_s; 13735 int ret; 13736 unsigned int delete_iface; 13737 13738 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 13739 13740 wpa_s = wpa_supplicant_get_iface(global, cmd); 13741 if (wpa_s == NULL) 13742 return -1; 13743 delete_iface = wpa_s->added_vif; 13744 ret = wpa_supplicant_remove_iface(global, wpa_s, 0); 13745 if (!ret && delete_iface) { 13746 wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'", 13747 cmd); 13748 /* wpa_supplicant does not create multi-BSS AP, so collapse to 13749 * WPA_IF_STATION to avoid unwanted clean up in the driver. */ 13750 ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd); 13751 } 13752 return ret; 13753 } 13754 13755 13756 static void wpa_free_iface_info(struct wpa_interface_info *iface) 13757 { 13758 struct wpa_interface_info *prev; 13759 13760 while (iface) { 13761 prev = iface; 13762 iface = iface->next; 13763 13764 os_free(prev->ifname); 13765 os_free(prev->desc); 13766 os_free(prev); 13767 } 13768 } 13769 13770 13771 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 13772 char *buf, int len) 13773 { 13774 int i, res; 13775 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 13776 char *pos, *end; 13777 13778 for (i = 0; wpa_drivers[i]; i++) { 13779 const struct wpa_driver_ops *drv = wpa_drivers[i]; 13780 if (drv->get_interfaces == NULL) 13781 continue; 13782 tmp = drv->get_interfaces(global->drv_priv[i]); 13783 if (tmp == NULL) 13784 continue; 13785 13786 if (last == NULL) 13787 iface = last = tmp; 13788 else 13789 last->next = tmp; 13790 while (last->next) 13791 last = last->next; 13792 } 13793 13794 pos = buf; 13795 end = buf + len; 13796 for (tmp = iface; tmp; tmp = tmp->next) { 13797 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 13798 tmp->drv_name, tmp->ifname, 13799 tmp->desc ? tmp->desc : ""); 13800 if (os_snprintf_error(end - pos, res)) { 13801 *pos = '\0'; 13802 break; 13803 } 13804 pos += res; 13805 } 13806 13807 wpa_free_iface_info(iface); 13808 13809 return pos - buf; 13810 } 13811 13812 13813 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 13814 const char *input, 13815 char *buf, int len) 13816 { 13817 int res; 13818 char *pos, *end; 13819 struct wpa_supplicant *wpa_s; 13820 int show_ctrl = 0; 13821 13822 if (input) 13823 show_ctrl = !!os_strstr(input, "ctrl"); 13824 13825 wpa_s = global->ifaces; 13826 pos = buf; 13827 end = buf + len; 13828 13829 while (wpa_s) { 13830 if (show_ctrl) 13831 res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n", 13832 wpa_s->ifname, 13833 wpa_s->conf->ctrl_interface ? 13834 wpa_s->conf->ctrl_interface : "N/A"); 13835 else 13836 res = os_snprintf(pos, end - pos, "%s\n", 13837 wpa_s->ifname); 13838 13839 if (os_snprintf_error(end - pos, res)) { 13840 *pos = '\0'; 13841 break; 13842 } 13843 pos += res; 13844 wpa_s = wpa_s->next; 13845 } 13846 return pos - buf; 13847 } 13848 13849 13850 static char * wpas_global_ctrl_iface_ifname(struct wpa_global *global, 13851 const char *ifname, 13852 char *cmd, size_t *resp_len) 13853 { 13854 struct wpa_supplicant *wpa_s; 13855 13856 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 13857 if (os_strcmp(ifname, wpa_s->ifname) == 0) 13858 break; 13859 } 13860 13861 if (wpa_s == NULL) { 13862 char *resp = os_strdup("FAIL-NO-IFNAME-MATCH\n"); 13863 if (resp) 13864 *resp_len = os_strlen(resp); 13865 else 13866 *resp_len = 1; 13867 return resp; 13868 } 13869 13870 return wpa_supplicant_ctrl_iface_process(wpa_s, cmd, resp_len); 13871 } 13872 13873 13874 static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, 13875 char *buf, size_t *resp_len) 13876 { 13877 #ifdef CONFIG_P2P 13878 static const char * cmd[] = { 13879 "LIST_NETWORKS", 13880 "P2P_FIND", 13881 "P2P_STOP_FIND", 13882 "P2P_LISTEN", 13883 "P2P_GROUP_ADD", 13884 "P2P_GET_PASSPHRASE", 13885 "P2P_SERVICE_UPDATE", 13886 "P2P_SERVICE_FLUSH", 13887 "P2P_FLUSH", 13888 "P2P_CANCEL", 13889 "P2P_PRESENCE_REQ", 13890 "P2P_EXT_LISTEN", 13891 #ifdef CONFIG_AP 13892 "STA-FIRST", 13893 #endif /* CONFIG_AP */ 13894 NULL 13895 }; 13896 static const char * prefix[] = { 13897 #ifdef ANDROID 13898 "DRIVER ", 13899 #endif /* ANDROID */ 13900 "GET_CAPABILITY ", 13901 "GET_NETWORK ", 13902 "REMOVE_NETWORK ", 13903 "P2P_FIND ", 13904 "P2P_CONNECT ", 13905 "P2P_LISTEN ", 13906 "P2P_GROUP_REMOVE ", 13907 "P2P_GROUP_ADD ", 13908 "P2P_GROUP_MEMBER ", 13909 "P2P_PROV_DISC ", 13910 "P2P_SERV_DISC_REQ ", 13911 "P2P_SERV_DISC_CANCEL_REQ ", 13912 "P2P_SERV_DISC_RESP ", 13913 "P2P_SERV_DISC_EXTERNAL ", 13914 "P2P_SERVICE_ADD ", 13915 "P2P_SERVICE_DEL ", 13916 "P2P_SERVICE_REP ", 13917 "P2P_REJECT ", 13918 "P2P_INVITE ", 13919 "P2P_PEER ", 13920 "P2P_SET ", 13921 "P2P_UNAUTHORIZE ", 13922 "P2P_PRESENCE_REQ ", 13923 "P2P_EXT_LISTEN ", 13924 "P2P_REMOVE_CLIENT ", 13925 "WPS_NFC_TOKEN ", 13926 "WPS_NFC_TAG_READ ", 13927 "NFC_GET_HANDOVER_SEL ", 13928 "NFC_GET_HANDOVER_REQ ", 13929 "NFC_REPORT_HANDOVER ", 13930 "P2P_ASP_PROVISION ", 13931 "P2P_ASP_PROVISION_RESP ", 13932 #ifdef CONFIG_AP 13933 "STA ", 13934 "STA-NEXT ", 13935 #endif /* CONFIG_AP */ 13936 NULL 13937 }; 13938 int found = 0; 13939 int i; 13940 13941 if (global->p2p_init_wpa_s == NULL) 13942 return NULL; 13943 13944 for (i = 0; !found && cmd[i]; i++) { 13945 if (os_strcmp(buf, cmd[i]) == 0) 13946 found = 1; 13947 } 13948 13949 for (i = 0; !found && prefix[i]; i++) { 13950 if (os_strncmp(buf, prefix[i], os_strlen(prefix[i])) == 0) 13951 found = 1; 13952 } 13953 13954 if (found) 13955 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 13956 buf, resp_len); 13957 #endif /* CONFIG_P2P */ 13958 return NULL; 13959 } 13960 13961 13962 static char * wpas_global_ctrl_iface_redir_wfd(struct wpa_global *global, 13963 char *buf, size_t *resp_len) 13964 { 13965 #ifdef CONFIG_WIFI_DISPLAY 13966 if (global->p2p_init_wpa_s == NULL) 13967 return NULL; 13968 if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0 || 13969 os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) 13970 return wpa_supplicant_ctrl_iface_process(global->p2p_init_wpa_s, 13971 buf, resp_len); 13972 #endif /* CONFIG_WIFI_DISPLAY */ 13973 return NULL; 13974 } 13975 13976 13977 static char * wpas_global_ctrl_iface_redir(struct wpa_global *global, 13978 char *buf, size_t *resp_len) 13979 { 13980 char *ret; 13981 13982 ret = wpas_global_ctrl_iface_redir_p2p(global, buf, resp_len); 13983 if (ret) 13984 return ret; 13985 13986 ret = wpas_global_ctrl_iface_redir_wfd(global, buf, resp_len); 13987 if (ret) 13988 return ret; 13989 13990 return NULL; 13991 } 13992 13993 13994 static int wpas_global_ctrl_iface_set(struct wpa_global *global, char *cmd) 13995 { 13996 char *value; 13997 13998 value = os_strchr(cmd, ' '); 13999 if (value == NULL) 14000 return -1; 14001 *value++ = '\0'; 14002 14003 wpa_printf(MSG_DEBUG, "GLOBAL_CTRL_IFACE SET '%s'='%s'", cmd, value); 14004 14005 #ifdef CONFIG_WIFI_DISPLAY 14006 if (os_strcasecmp(cmd, "wifi_display") == 0) { 14007 wifi_display_enable(global, !!atoi(value)); 14008 return 0; 14009 } 14010 #endif /* CONFIG_WIFI_DISPLAY */ 14011 14012 /* Restore cmd to its original value to allow redirection */ 14013 value[-1] = ' '; 14014 14015 return -1; 14016 } 14017 14018 14019 static int wpas_global_ctrl_iface_dup_network(struct wpa_global *global, 14020 char *cmd) 14021 { 14022 struct wpa_supplicant *wpa_s[2]; /* src, dst */ 14023 char *p; 14024 unsigned int i; 14025 14026 /* cmd: "<src ifname> <dst ifname> <src network id> <dst network id> 14027 * <variable name> */ 14028 14029 for (i = 0; i < ARRAY_SIZE(wpa_s) ; i++) { 14030 p = os_strchr(cmd, ' '); 14031 if (p == NULL) 14032 return -1; 14033 *p = '\0'; 14034 14035 wpa_s[i] = global->ifaces; 14036 for (; wpa_s[i]; wpa_s[i] = wpa_s[i]->next) { 14037 if (os_strcmp(cmd, wpa_s[i]->ifname) == 0) 14038 break; 14039 } 14040 14041 if (!wpa_s[i]) { 14042 wpa_printf(MSG_DEBUG, 14043 "CTRL_IFACE: Could not find iface=%s", cmd); 14044 return -1; 14045 } 14046 14047 cmd = p + 1; 14048 } 14049 14050 return wpa_supplicant_ctrl_iface_dup_network(wpa_s[0], cmd, wpa_s[1]); 14051 } 14052 14053 14054 #ifndef CONFIG_NO_CONFIG_WRITE 14055 static int wpas_global_ctrl_iface_save_config(struct wpa_global *global) 14056 { 14057 int ret = 0, saved = 0; 14058 struct wpa_supplicant *wpa_s; 14059 14060 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 14061 if (!wpa_s->conf->update_config) { 14062 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed to update configuration (update_config=0)"); 14063 continue; 14064 } 14065 14066 if (wpa_config_write(wpa_s->confname, wpa_s->conf)) { 14067 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to update configuration"); 14068 ret = 1; 14069 } else { 14070 wpa_dbg(wpa_s, MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration updated"); 14071 saved++; 14072 } 14073 } 14074 14075 if (!saved && !ret) { 14076 wpa_dbg(wpa_s, MSG_DEBUG, 14077 "CTRL_IFACE: SAVE_CONFIG - No configuration files could be updated"); 14078 ret = 1; 14079 } 14080 14081 return ret; 14082 } 14083 #endif /* CONFIG_NO_CONFIG_WRITE */ 14084 14085 14086 static int wpas_global_ctrl_iface_status(struct wpa_global *global, 14087 char *buf, size_t buflen) 14088 { 14089 char *pos, *end; 14090 int ret; 14091 struct wpa_supplicant *wpa_s; 14092 14093 pos = buf; 14094 end = buf + buflen; 14095 14096 #ifdef CONFIG_P2P 14097 if (global->p2p && !global->p2p_disabled) { 14098 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 14099 "\n" 14100 "p2p_state=%s\n", 14101 MAC2STR(global->p2p_dev_addr), 14102 p2p_get_state_txt(global->p2p)); 14103 if (os_snprintf_error(end - pos, ret)) 14104 return pos - buf; 14105 pos += ret; 14106 } else if (global->p2p) { 14107 ret = os_snprintf(pos, end - pos, "p2p_state=DISABLED\n"); 14108 if (os_snprintf_error(end - pos, ret)) 14109 return pos - buf; 14110 pos += ret; 14111 } 14112 #endif /* CONFIG_P2P */ 14113 14114 #ifdef CONFIG_WIFI_DISPLAY 14115 ret = os_snprintf(pos, end - pos, "wifi_display=%d\n", 14116 !!global->wifi_display); 14117 if (os_snprintf_error(end - pos, ret)) 14118 return pos - buf; 14119 pos += ret; 14120 #endif /* CONFIG_WIFI_DISPLAY */ 14121 14122 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 14123 ret = os_snprintf(pos, end - pos, "ifname=%s\n" 14124 "address=" MACSTR "\n", 14125 wpa_s->ifname, MAC2STR(wpa_s->own_addr)); 14126 if (os_snprintf_error(end - pos, ret)) 14127 return pos - buf; 14128 pos += ret; 14129 } 14130 14131 return pos - buf; 14132 } 14133 14134 14135 #ifdef CONFIG_FST 14136 14137 static int wpas_global_ctrl_iface_fst_attach(struct wpa_global *global, 14138 char *cmd, char *buf, 14139 size_t reply_size) 14140 { 14141 char ifname[IFNAMSIZ + 1]; 14142 struct fst_iface_cfg cfg; 14143 struct wpa_supplicant *wpa_s; 14144 struct fst_wpa_obj iface_obj; 14145 14146 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 14147 wpa_s = wpa_supplicant_get_iface(global, ifname); 14148 if (wpa_s) { 14149 if (wpa_s->fst) { 14150 wpa_printf(MSG_INFO, "FST: Already attached"); 14151 return -1; 14152 } 14153 fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj); 14154 wpa_s->fst = fst_attach(ifname, wpa_s->own_addr, 14155 &iface_obj, &cfg); 14156 if (wpa_s->fst) 14157 return os_snprintf(buf, reply_size, "OK\n"); 14158 } 14159 } 14160 14161 return -1; 14162 } 14163 14164 14165 static int wpas_global_ctrl_iface_fst_detach(struct wpa_global *global, 14166 char *cmd, char *buf, 14167 size_t reply_size) 14168 { 14169 char ifname[IFNAMSIZ + 1]; 14170 struct wpa_supplicant *wpa_s; 14171 14172 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 14173 wpa_s = wpa_supplicant_get_iface(global, ifname); 14174 if (wpa_s) { 14175 if (!fst_iface_detach(ifname)) { 14176 wpa_s->fst = NULL; 14177 return os_snprintf(buf, reply_size, "OK\n"); 14178 } 14179 } 14180 } 14181 14182 return -1; 14183 } 14184 14185 #endif /* CONFIG_FST */ 14186 14187 14188 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 14189 char *buf, size_t *resp_len) 14190 { 14191 char *reply; 14192 const int reply_size = 2048; 14193 int reply_len; 14194 int level = MSG_DEBUG; 14195 14196 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 14197 char *pos = os_strchr(buf + 7, ' '); 14198 if (pos) { 14199 *pos++ = '\0'; 14200 return wpas_global_ctrl_iface_ifname(global, 14201 buf + 7, pos, 14202 resp_len); 14203 } 14204 } 14205 14206 reply = wpas_global_ctrl_iface_redir(global, buf, resp_len); 14207 if (reply) 14208 return reply; 14209 14210 if (os_strcmp(buf, "PING") == 0) 14211 level = MSG_EXCESSIVE; 14212 wpa_hexdump_ascii(level, "RX global ctrl_iface", 14213 (const u8 *) buf, os_strlen(buf)); 14214 14215 reply = os_malloc(reply_size); 14216 if (reply == NULL) { 14217 *resp_len = 1; 14218 return NULL; 14219 } 14220 14221 os_memcpy(reply, "OK\n", 3); 14222 reply_len = 3; 14223 14224 if (os_strcmp(buf, "PING") == 0) { 14225 os_memcpy(reply, "PONG\n", 5); 14226 reply_len = 5; 14227 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 14228 if (wpa_supplicant_global_iface_add(global, buf + 14)) 14229 reply_len = -1; 14230 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 14231 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 14232 reply_len = -1; 14233 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 14234 reply_len = wpa_supplicant_global_iface_list( 14235 global, reply, reply_size); 14236 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 14237 reply_len = wpa_supplicant_global_iface_interfaces( 14238 global, buf + 10, reply, reply_size); 14239 #ifdef CONFIG_FST 14240 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 14241 reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11, 14242 reply, 14243 reply_size); 14244 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 14245 reply_len = wpas_global_ctrl_iface_fst_detach(global, buf + 11, 14246 reply, 14247 reply_size); 14248 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 14249 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 14250 #endif /* CONFIG_FST */ 14251 } else if (os_strcmp(buf, "TERMINATE") == 0) { 14252 wpa_supplicant_terminate_proc(global); 14253 } else if (os_strcmp(buf, "SUSPEND") == 0) { 14254 wpas_notify_suspend(global); 14255 } else if (os_strcmp(buf, "RESUME") == 0) { 14256 wpas_notify_resume(global); 14257 } else if (os_strncmp(buf, "SET ", 4) == 0) { 14258 if (wpas_global_ctrl_iface_set(global, buf + 4)) { 14259 #ifdef CONFIG_P2P 14260 if (global->p2p_init_wpa_s) { 14261 os_free(reply); 14262 /* Check if P2P redirection would work for this 14263 * command. */ 14264 return wpa_supplicant_ctrl_iface_process( 14265 global->p2p_init_wpa_s, 14266 buf, resp_len); 14267 } 14268 #endif /* CONFIG_P2P */ 14269 reply_len = -1; 14270 } 14271 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 14272 if (wpas_global_ctrl_iface_dup_network(global, buf + 12)) 14273 reply_len = -1; 14274 #ifndef CONFIG_NO_CONFIG_WRITE 14275 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 14276 if (wpas_global_ctrl_iface_save_config(global)) 14277 reply_len = -1; 14278 #endif /* CONFIG_NO_CONFIG_WRITE */ 14279 } else if (os_strcmp(buf, "STATUS") == 0) { 14280 reply_len = wpas_global_ctrl_iface_status(global, reply, 14281 reply_size); 14282 #ifdef CONFIG_MODULE_TESTS 14283 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 14284 if (wpas_module_tests() < 0) 14285 reply_len = -1; 14286 #endif /* CONFIG_MODULE_TESTS */ 14287 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 14288 if (wpa_debug_reopen_file() < 0) 14289 reply_len = -1; 14290 } else { 14291 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 14292 reply_len = 16; 14293 } 14294 14295 if (reply_len < 0) { 14296 os_memcpy(reply, "FAIL\n", 5); 14297 reply_len = 5; 14298 } 14299 14300 *resp_len = reply_len; 14301 return reply; 14302 } 14303