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