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