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