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