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