1 /* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #include "utils/common.h" 12 #include "utils/eloop.h" 13 #include "common/version.h" 14 #include "common/ieee802_11_defs.h" 15 #include "common/ieee802_11_common.h" 16 #include "common/wpa_ctrl.h" 17 #include "eap_peer/eap.h" 18 #include "eapol_supp/eapol_supp_sm.h" 19 #include "rsn_supp/wpa.h" 20 #include "rsn_supp/preauth.h" 21 #include "rsn_supp/pmksa_cache.h" 22 #include "l2_packet/l2_packet.h" 23 #include "wps/wps.h" 24 #include "config.h" 25 #include "wpa_supplicant_i.h" 26 #include "driver_i.h" 27 #include "wps_supplicant.h" 28 #include "ibss_rsn.h" 29 #include "ap.h" 30 #include "p2p_supplicant.h" 31 #include "p2p/p2p.h" 32 #include "hs20_supplicant.h" 33 #include "wifi_display.h" 34 #include "notify.h" 35 #include "bss.h" 36 #include "scan.h" 37 #include "ctrl_iface.h" 38 #include "interworking.h" 39 #include "blacklist.h" 40 #include "autoscan.h" 41 #include "wnm_sta.h" 42 43 extern struct wpa_driver_ops *wpa_drivers[]; 44 45 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 46 char *buf, int len); 47 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 48 char *buf, int len); 49 50 51 static int pno_start(struct wpa_supplicant *wpa_s) 52 { 53 int ret; 54 size_t i, num_ssid; 55 struct wpa_ssid *ssid; 56 struct wpa_driver_scan_params params; 57 58 if (wpa_s->pno) 59 return 0; 60 61 if (wpa_s->wpa_state == WPA_SCANNING) { 62 wpa_supplicant_cancel_sched_scan(wpa_s); 63 wpa_supplicant_cancel_scan(wpa_s); 64 } 65 66 os_memset(¶ms, 0, sizeof(params)); 67 68 num_ssid = 0; 69 ssid = wpa_s->conf->ssid; 70 while (ssid) { 71 if (!wpas_network_disabled(wpa_s, ssid)) 72 num_ssid++; 73 ssid = ssid->next; 74 } 75 if (num_ssid > WPAS_MAX_SCAN_SSIDS) { 76 wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " 77 "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); 78 num_ssid = WPAS_MAX_SCAN_SSIDS; 79 } 80 81 if (num_ssid == 0) { 82 wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); 83 return -1; 84 } 85 86 params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) * 87 num_ssid); 88 if (params.filter_ssids == NULL) 89 return -1; 90 i = 0; 91 ssid = wpa_s->conf->ssid; 92 while (ssid) { 93 if (!wpas_network_disabled(wpa_s, ssid)) { 94 params.ssids[i].ssid = ssid->ssid; 95 params.ssids[i].ssid_len = ssid->ssid_len; 96 params.num_ssids++; 97 os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, 98 ssid->ssid_len); 99 params.filter_ssids[i].ssid_len = ssid->ssid_len; 100 params.num_filter_ssids++; 101 i++; 102 if (i == num_ssid) 103 break; 104 } 105 ssid = ssid->next; 106 } 107 108 if (wpa_s->conf->filter_rssi) 109 params.filter_rssi = wpa_s->conf->filter_rssi; 110 111 ret = wpa_drv_sched_scan(wpa_s, ¶ms, 10 * 1000); 112 os_free(params.filter_ssids); 113 if (ret == 0) 114 wpa_s->pno = 1; 115 return ret; 116 } 117 118 119 static int pno_stop(struct wpa_supplicant *wpa_s) 120 { 121 int ret = 0; 122 123 if (wpa_s->pno) { 124 wpa_s->pno = 0; 125 ret = wpa_drv_stop_sched_scan(wpa_s); 126 } 127 128 if (wpa_s->wpa_state == WPA_SCANNING) 129 wpa_supplicant_req_scan(wpa_s, 0, 0); 130 131 return ret; 132 } 133 134 135 static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) 136 { 137 char *pos; 138 u8 addr[ETH_ALEN], *filter = NULL, *n; 139 size_t count = 0; 140 141 pos = val; 142 while (pos) { 143 if (*pos == '\0') 144 break; 145 if (hwaddr_aton(pos, addr)) { 146 os_free(filter); 147 return -1; 148 } 149 n = os_realloc_array(filter, count + 1, ETH_ALEN); 150 if (n == NULL) { 151 os_free(filter); 152 return -1; 153 } 154 filter = n; 155 os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN); 156 count++; 157 158 pos = os_strchr(pos, ' '); 159 if (pos) 160 pos++; 161 } 162 163 wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN); 164 os_free(wpa_s->bssid_filter); 165 wpa_s->bssid_filter = filter; 166 wpa_s->bssid_filter_count = count; 167 168 return 0; 169 } 170 171 172 static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val) 173 { 174 char *pos; 175 u8 addr[ETH_ALEN], *bssid = NULL, *n; 176 struct wpa_ssid_value *ssid = NULL, *ns; 177 size_t count = 0, ssid_count = 0; 178 struct wpa_ssid *c; 179 180 /* 181 * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | “” 182 * SSID_SPEC ::= ssid <SSID_HEX> 183 * BSSID_SPEC ::= bssid <BSSID_HEX> 184 */ 185 186 pos = val; 187 while (pos) { 188 if (*pos == '\0') 189 break; 190 if (os_strncmp(pos, "bssid ", 6) == 0) { 191 int res; 192 pos += 6; 193 res = hwaddr_aton2(pos, addr); 194 if (res < 0) { 195 os_free(ssid); 196 os_free(bssid); 197 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 198 "BSSID value '%s'", pos); 199 return -1; 200 } 201 pos += res; 202 n = os_realloc_array(bssid, count + 1, ETH_ALEN); 203 if (n == NULL) { 204 os_free(ssid); 205 os_free(bssid); 206 return -1; 207 } 208 bssid = n; 209 os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN); 210 count++; 211 } else if (os_strncmp(pos, "ssid ", 5) == 0) { 212 char *end; 213 pos += 5; 214 215 end = pos; 216 while (*end) { 217 if (*end == '\0' || *end == ' ') 218 break; 219 end++; 220 } 221 222 ns = os_realloc_array(ssid, ssid_count + 1, 223 sizeof(struct wpa_ssid_value)); 224 if (ns == NULL) { 225 os_free(ssid); 226 os_free(bssid); 227 return -1; 228 } 229 ssid = ns; 230 231 if ((end - pos) & 0x01 || end - pos > 2 * 32 || 232 hexstr2bin(pos, ssid[ssid_count].ssid, 233 (end - pos) / 2) < 0) { 234 os_free(ssid); 235 os_free(bssid); 236 wpa_printf(MSG_DEBUG, "Invalid disallow_aps " 237 "SSID value '%s'", pos); 238 return -1; 239 } 240 ssid[ssid_count].ssid_len = (end - pos) / 2; 241 wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID", 242 ssid[ssid_count].ssid, 243 ssid[ssid_count].ssid_len); 244 ssid_count++; 245 pos = end; 246 } else { 247 wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value " 248 "'%s'", pos); 249 os_free(ssid); 250 os_free(bssid); 251 return -1; 252 } 253 254 pos = os_strchr(pos, ' '); 255 if (pos) 256 pos++; 257 } 258 259 wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN); 260 os_free(wpa_s->disallow_aps_bssid); 261 wpa_s->disallow_aps_bssid = bssid; 262 wpa_s->disallow_aps_bssid_count = count; 263 264 wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count); 265 os_free(wpa_s->disallow_aps_ssid); 266 wpa_s->disallow_aps_ssid = ssid; 267 wpa_s->disallow_aps_ssid_count = ssid_count; 268 269 if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING) 270 return 0; 271 272 c = wpa_s->current_ssid; 273 if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS) 274 return 0; 275 276 if (!disallowed_bssid(wpa_s, wpa_s->bssid) && 277 !disallowed_ssid(wpa_s, c->ssid, c->ssid_len)) 278 return 0; 279 280 wpa_printf(MSG_DEBUG, "Disconnect and try to find another network " 281 "because current AP was marked disallowed"); 282 283 #ifdef CONFIG_SME 284 wpa_s->sme.prev_bssid_set = 0; 285 #endif /* CONFIG_SME */ 286 wpa_s->reassociate = 1; 287 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 288 wpa_supplicant_req_scan(wpa_s, 0, 0); 289 290 return 0; 291 } 292 293 294 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 295 char *cmd) 296 { 297 char *value; 298 int ret = 0; 299 300 value = os_strchr(cmd, ' '); 301 if (value == NULL) 302 return -1; 303 *value++ = '\0'; 304 305 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 306 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 307 eapol_sm_configure(wpa_s->eapol, 308 atoi(value), -1, -1, -1); 309 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 310 eapol_sm_configure(wpa_s->eapol, 311 -1, atoi(value), -1, -1); 312 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 313 eapol_sm_configure(wpa_s->eapol, 314 -1, -1, atoi(value), -1); 315 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 316 eapol_sm_configure(wpa_s->eapol, 317 -1, -1, -1, atoi(value)); 318 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 319 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 320 atoi(value))) 321 ret = -1; 322 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 323 0) { 324 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 325 atoi(value))) 326 ret = -1; 327 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 328 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 329 ret = -1; 330 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 331 wpa_s->wps_fragment_size = atoi(value); 332 #ifdef CONFIG_WPS_TESTING 333 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 334 long int val; 335 val = strtol(value, NULL, 0); 336 if (val < 0 || val > 0xff) { 337 ret = -1; 338 wpa_printf(MSG_DEBUG, "WPS: Invalid " 339 "wps_version_number %ld", val); 340 } else { 341 wps_version_number = val; 342 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 343 "version %u.%u", 344 (wps_version_number & 0xf0) >> 4, 345 wps_version_number & 0x0f); 346 } 347 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 348 wps_testing_dummy_cred = atoi(value); 349 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 350 wps_testing_dummy_cred); 351 #endif /* CONFIG_WPS_TESTING */ 352 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 353 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 354 ret = -1; 355 #ifdef CONFIG_TDLS_TESTING 356 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 357 extern unsigned int tdls_testing; 358 tdls_testing = strtol(value, NULL, 0); 359 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 360 #endif /* CONFIG_TDLS_TESTING */ 361 #ifdef CONFIG_TDLS 362 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 363 int disabled = atoi(value); 364 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 365 if (disabled) { 366 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 367 ret = -1; 368 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 369 ret = -1; 370 wpa_tdls_enable(wpa_s->wpa, !disabled); 371 #endif /* CONFIG_TDLS */ 372 } else if (os_strcasecmp(cmd, "pno") == 0) { 373 if (atoi(value)) 374 ret = pno_start(wpa_s); 375 else 376 ret = pno_stop(wpa_s); 377 } else if (os_strcasecmp(cmd, "radio_disabled") == 0) { 378 int disabled = atoi(value); 379 if (wpa_drv_radio_disable(wpa_s, disabled) < 0) 380 ret = -1; 381 else if (disabled) 382 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); 383 } else if (os_strcasecmp(cmd, "uapsd") == 0) { 384 if (os_strcmp(value, "disable") == 0) 385 wpa_s->set_sta_uapsd = 0; 386 else { 387 int be, bk, vi, vo; 388 char *pos; 389 /* format: BE,BK,VI,VO;max SP Length */ 390 be = atoi(value); 391 pos = os_strchr(value, ','); 392 if (pos == NULL) 393 return -1; 394 pos++; 395 bk = atoi(pos); 396 pos = os_strchr(pos, ','); 397 if (pos == NULL) 398 return -1; 399 pos++; 400 vi = atoi(pos); 401 pos = os_strchr(pos, ','); 402 if (pos == NULL) 403 return -1; 404 pos++; 405 vo = atoi(pos); 406 /* ignore max SP Length for now */ 407 408 wpa_s->set_sta_uapsd = 1; 409 wpa_s->sta_uapsd = 0; 410 if (be) 411 wpa_s->sta_uapsd |= BIT(0); 412 if (bk) 413 wpa_s->sta_uapsd |= BIT(1); 414 if (vi) 415 wpa_s->sta_uapsd |= BIT(2); 416 if (vo) 417 wpa_s->sta_uapsd |= BIT(3); 418 } 419 } else if (os_strcasecmp(cmd, "ps") == 0) { 420 ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1); 421 #ifdef CONFIG_WIFI_DISPLAY 422 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 423 wifi_display_enable(wpa_s->global, !!atoi(value)); 424 #endif /* CONFIG_WIFI_DISPLAY */ 425 } else if (os_strcasecmp(cmd, "bssid_filter") == 0) { 426 ret = set_bssid_filter(wpa_s, value); 427 } else if (os_strcasecmp(cmd, "disallow_aps") == 0) { 428 ret = set_disallow_aps(wpa_s, value); 429 } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { 430 wpa_s->no_keep_alive = !!atoi(value); 431 } else { 432 value[-1] = '='; 433 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 434 if (ret == 0) 435 wpa_supplicant_update_config(wpa_s); 436 } 437 438 return ret; 439 } 440 441 442 static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 443 char *cmd, char *buf, size_t buflen) 444 { 445 int res = -1; 446 447 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 448 449 if (os_strcmp(cmd, "version") == 0) { 450 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 451 } else if (os_strcasecmp(cmd, "country") == 0) { 452 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 453 res = os_snprintf(buf, buflen, "%c%c", 454 wpa_s->conf->country[0], 455 wpa_s->conf->country[1]); 456 #ifdef CONFIG_WIFI_DISPLAY 457 } else if (os_strcasecmp(cmd, "wifi_display") == 0) { 458 res = os_snprintf(buf, buflen, "%d", 459 wpa_s->global->wifi_display); 460 if (res < 0 || (unsigned int) res >= buflen) 461 return -1; 462 return res; 463 #endif /* CONFIG_WIFI_DISPLAY */ 464 } 465 466 if (res < 0 || (unsigned int) res >= buflen) 467 return -1; 468 return res; 469 } 470 471 472 #ifdef IEEE8021X_EAPOL 473 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 474 char *addr) 475 { 476 u8 bssid[ETH_ALEN]; 477 struct wpa_ssid *ssid = wpa_s->current_ssid; 478 479 if (hwaddr_aton(addr, bssid)) { 480 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 481 "'%s'", addr); 482 return -1; 483 } 484 485 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 486 rsn_preauth_deinit(wpa_s->wpa); 487 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 488 return -1; 489 490 return 0; 491 } 492 #endif /* IEEE8021X_EAPOL */ 493 494 495 #ifdef CONFIG_PEERKEY 496 /* MLME-STKSTART.request(peer) */ 497 static int wpa_supplicant_ctrl_iface_stkstart( 498 struct wpa_supplicant *wpa_s, char *addr) 499 { 500 u8 peer[ETH_ALEN]; 501 502 if (hwaddr_aton(addr, peer)) { 503 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 504 "address '%s'", addr); 505 return -1; 506 } 507 508 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 509 MAC2STR(peer)); 510 511 return wpa_sm_stkstart(wpa_s->wpa, peer); 512 } 513 #endif /* CONFIG_PEERKEY */ 514 515 516 #ifdef CONFIG_TDLS 517 518 static int wpa_supplicant_ctrl_iface_tdls_discover( 519 struct wpa_supplicant *wpa_s, char *addr) 520 { 521 u8 peer[ETH_ALEN]; 522 int ret; 523 524 if (hwaddr_aton(addr, peer)) { 525 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 526 "address '%s'", addr); 527 return -1; 528 } 529 530 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 531 MAC2STR(peer)); 532 533 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 534 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 535 else 536 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 537 538 return ret; 539 } 540 541 542 static int wpa_supplicant_ctrl_iface_tdls_setup( 543 struct wpa_supplicant *wpa_s, char *addr) 544 { 545 u8 peer[ETH_ALEN]; 546 int ret; 547 548 if (hwaddr_aton(addr, peer)) { 549 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 550 "address '%s'", addr); 551 return -1; 552 } 553 554 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 555 MAC2STR(peer)); 556 557 ret = wpa_tdls_reneg(wpa_s->wpa, peer); 558 if (ret) { 559 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 560 ret = wpa_tdls_start(wpa_s->wpa, peer); 561 else 562 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 563 } 564 565 return ret; 566 } 567 568 569 static int wpa_supplicant_ctrl_iface_tdls_teardown( 570 struct wpa_supplicant *wpa_s, char *addr) 571 { 572 u8 peer[ETH_ALEN]; 573 574 if (hwaddr_aton(addr, peer)) { 575 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 576 "address '%s'", addr); 577 return -1; 578 } 579 580 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 581 MAC2STR(peer)); 582 583 return wpa_tdls_teardown_link(wpa_s->wpa, peer, 584 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 585 } 586 587 #endif /* CONFIG_TDLS */ 588 589 590 #ifdef CONFIG_IEEE80211R 591 static int wpa_supplicant_ctrl_iface_ft_ds( 592 struct wpa_supplicant *wpa_s, char *addr) 593 { 594 u8 target_ap[ETH_ALEN]; 595 struct wpa_bss *bss; 596 const u8 *mdie; 597 598 if (hwaddr_aton(addr, target_ap)) { 599 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 600 "address '%s'", addr); 601 return -1; 602 } 603 604 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 605 606 bss = wpa_bss_get_bssid(wpa_s, target_ap); 607 if (bss) 608 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 609 else 610 mdie = NULL; 611 612 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 613 } 614 #endif /* CONFIG_IEEE80211R */ 615 616 617 #ifdef CONFIG_WPS 618 static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 619 char *cmd) 620 { 621 u8 bssid[ETH_ALEN], *_bssid = bssid; 622 #ifdef CONFIG_P2P 623 u8 p2p_dev_addr[ETH_ALEN]; 624 #endif /* CONFIG_P2P */ 625 #ifdef CONFIG_AP 626 u8 *_p2p_dev_addr = NULL; 627 #endif /* CONFIG_AP */ 628 629 if (cmd == NULL || os_strcmp(cmd, "any") == 0) { 630 _bssid = NULL; 631 #ifdef CONFIG_P2P 632 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 633 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 634 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 635 "P2P Device Address '%s'", 636 cmd + 13); 637 return -1; 638 } 639 _p2p_dev_addr = p2p_dev_addr; 640 #endif /* CONFIG_P2P */ 641 } else if (hwaddr_aton(cmd, bssid)) { 642 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 643 cmd); 644 return -1; 645 } 646 647 #ifdef CONFIG_AP 648 if (wpa_s->ap_iface) 649 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 650 #endif /* CONFIG_AP */ 651 652 return wpas_wps_start_pbc(wpa_s, _bssid, 0); 653 } 654 655 656 static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 657 char *cmd, char *buf, 658 size_t buflen) 659 { 660 u8 bssid[ETH_ALEN], *_bssid = bssid; 661 char *pin; 662 int ret; 663 664 pin = os_strchr(cmd, ' '); 665 if (pin) 666 *pin++ = '\0'; 667 668 if (os_strcmp(cmd, "any") == 0) 669 _bssid = NULL; 670 else if (os_strcmp(cmd, "get") == 0) { 671 ret = wps_generate_pin(); 672 goto done; 673 } else if (hwaddr_aton(cmd, bssid)) { 674 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 675 cmd); 676 return -1; 677 } 678 679 #ifdef CONFIG_AP 680 if (wpa_s->ap_iface) { 681 int timeout = 0; 682 char *pos; 683 684 if (pin) { 685 pos = os_strchr(pin, ' '); 686 if (pos) { 687 *pos++ = '\0'; 688 timeout = atoi(pos); 689 } 690 } 691 692 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 693 buf, buflen, timeout); 694 } 695 #endif /* CONFIG_AP */ 696 697 if (pin) { 698 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 699 DEV_PW_DEFAULT); 700 if (ret < 0) 701 return -1; 702 ret = os_snprintf(buf, buflen, "%s", pin); 703 if (ret < 0 || (size_t) ret >= buflen) 704 return -1; 705 return ret; 706 } 707 708 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 709 if (ret < 0) 710 return -1; 711 712 done: 713 /* Return the generated PIN */ 714 ret = os_snprintf(buf, buflen, "%08d", ret); 715 if (ret < 0 || (size_t) ret >= buflen) 716 return -1; 717 return ret; 718 } 719 720 721 static int wpa_supplicant_ctrl_iface_wps_check_pin( 722 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 723 { 724 char pin[9]; 725 size_t len; 726 char *pos; 727 int ret; 728 729 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 730 (u8 *) cmd, os_strlen(cmd)); 731 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 732 if (*pos < '0' || *pos > '9') 733 continue; 734 pin[len++] = *pos; 735 if (len == 9) { 736 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 737 return -1; 738 } 739 } 740 if (len != 4 && len != 8) { 741 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 742 return -1; 743 } 744 pin[len] = '\0'; 745 746 if (len == 8) { 747 unsigned int pin_val; 748 pin_val = atoi(pin); 749 if (!wps_pin_valid(pin_val)) { 750 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 751 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 752 if (ret < 0 || (size_t) ret >= buflen) 753 return -1; 754 return ret; 755 } 756 } 757 758 ret = os_snprintf(buf, buflen, "%s", pin); 759 if (ret < 0 || (size_t) ret >= buflen) 760 return -1; 761 762 return ret; 763 } 764 765 766 #ifdef CONFIG_WPS_NFC 767 768 static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s, 769 char *cmd) 770 { 771 u8 bssid[ETH_ALEN], *_bssid = bssid; 772 773 if (cmd == NULL || cmd[0] == '\0') 774 _bssid = NULL; 775 else if (hwaddr_aton(cmd, bssid)) 776 return -1; 777 778 return wpas_wps_start_nfc(wpa_s, _bssid); 779 } 780 781 782 static int wpa_supplicant_ctrl_iface_wps_nfc_token( 783 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 784 { 785 int ndef; 786 struct wpabuf *buf; 787 int res; 788 789 if (os_strcmp(cmd, "WPS") == 0) 790 ndef = 0; 791 else if (os_strcmp(cmd, "NDEF") == 0) 792 ndef = 1; 793 else 794 return -1; 795 796 buf = wpas_wps_nfc_token(wpa_s, ndef); 797 if (buf == NULL) 798 return -1; 799 800 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 801 wpabuf_len(buf)); 802 reply[res++] = '\n'; 803 reply[res] = '\0'; 804 805 wpabuf_free(buf); 806 807 return res; 808 } 809 810 811 static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read( 812 struct wpa_supplicant *wpa_s, char *pos) 813 { 814 size_t len; 815 struct wpabuf *buf; 816 int ret; 817 818 len = os_strlen(pos); 819 if (len & 0x01) 820 return -1; 821 len /= 2; 822 823 buf = wpabuf_alloc(len); 824 if (buf == NULL) 825 return -1; 826 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 827 wpabuf_free(buf); 828 return -1; 829 } 830 831 ret = wpas_wps_nfc_tag_read(wpa_s, buf); 832 wpabuf_free(buf); 833 834 return ret; 835 } 836 837 838 static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s, 839 char *reply, size_t max_len) 840 { 841 struct wpabuf *buf; 842 int res; 843 844 buf = wpas_wps_nfc_handover_req(wpa_s); 845 if (buf == NULL) 846 return -1; 847 848 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 849 wpabuf_len(buf)); 850 reply[res++] = '\n'; 851 reply[res] = '\0'; 852 853 wpabuf_free(buf); 854 855 return res; 856 } 857 858 859 static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s, 860 char *cmd, char *reply, 861 size_t max_len) 862 { 863 char *pos; 864 865 pos = os_strchr(cmd, ' '); 866 if (pos == NULL) 867 return -1; 868 *pos++ = '\0'; 869 870 if (os_strcmp(cmd, "NDEF") != 0) 871 return -1; 872 873 if (os_strcmp(pos, "WPS") == 0) { 874 return wpas_ctrl_nfc_get_handover_req_wps(wpa_s, reply, 875 max_len); 876 } 877 878 return -1; 879 } 880 881 882 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s, 883 char *reply, size_t max_len) 884 { 885 struct wpabuf *buf; 886 int res; 887 888 buf = wpas_wps_nfc_handover_sel(wpa_s); 889 if (buf == NULL) 890 return -1; 891 892 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 893 wpabuf_len(buf)); 894 reply[res++] = '\n'; 895 reply[res] = '\0'; 896 897 wpabuf_free(buf); 898 899 return res; 900 } 901 902 903 static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s, 904 char *cmd, char *reply, 905 size_t max_len) 906 { 907 char *pos; 908 909 pos = os_strchr(cmd, ' '); 910 if (pos == NULL) 911 return -1; 912 *pos++ = '\0'; 913 914 if (os_strcmp(cmd, "NDEF") != 0) 915 return -1; 916 917 if (os_strcmp(pos, "WPS") == 0) { 918 return wpas_ctrl_nfc_get_handover_sel_wps(wpa_s, reply, 919 max_len); 920 } 921 922 return -1; 923 } 924 925 926 static int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s, 927 char *cmd, char *reply, 928 size_t max_len) 929 { 930 size_t len; 931 struct wpabuf *buf; 932 int ret; 933 934 len = os_strlen(cmd); 935 if (len & 0x01) 936 return -1; 937 len /= 2; 938 939 buf = wpabuf_alloc(len); 940 if (buf == NULL) 941 return -1; 942 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 943 wpabuf_free(buf); 944 return -1; 945 } 946 947 ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf); 948 wpabuf_free(buf); 949 950 return ret; 951 } 952 953 954 static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s, 955 char *cmd) 956 { 957 size_t len; 958 struct wpabuf *buf; 959 int ret; 960 961 len = os_strlen(cmd); 962 if (len & 0x01) 963 return -1; 964 len /= 2; 965 966 buf = wpabuf_alloc(len); 967 if (buf == NULL) 968 return -1; 969 if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) { 970 wpabuf_free(buf); 971 return -1; 972 } 973 974 ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf); 975 wpabuf_free(buf); 976 977 return ret; 978 } 979 980 #endif /* CONFIG_WPS_NFC */ 981 982 983 static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 984 char *cmd) 985 { 986 u8 bssid[ETH_ALEN]; 987 char *pin; 988 char *new_ssid; 989 char *new_auth; 990 char *new_encr; 991 char *new_key; 992 struct wps_new_ap_settings ap; 993 994 pin = os_strchr(cmd, ' '); 995 if (pin == NULL) 996 return -1; 997 *pin++ = '\0'; 998 999 if (hwaddr_aton(cmd, bssid)) { 1000 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 1001 cmd); 1002 return -1; 1003 } 1004 1005 new_ssid = os_strchr(pin, ' '); 1006 if (new_ssid == NULL) 1007 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 1008 *new_ssid++ = '\0'; 1009 1010 new_auth = os_strchr(new_ssid, ' '); 1011 if (new_auth == NULL) 1012 return -1; 1013 *new_auth++ = '\0'; 1014 1015 new_encr = os_strchr(new_auth, ' '); 1016 if (new_encr == NULL) 1017 return -1; 1018 *new_encr++ = '\0'; 1019 1020 new_key = os_strchr(new_encr, ' '); 1021 if (new_key == NULL) 1022 return -1; 1023 *new_key++ = '\0'; 1024 1025 os_memset(&ap, 0, sizeof(ap)); 1026 ap.ssid_hex = new_ssid; 1027 ap.auth = new_auth; 1028 ap.encr = new_encr; 1029 ap.key_hex = new_key; 1030 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 1031 } 1032 1033 1034 #ifdef CONFIG_AP 1035 static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 1036 char *cmd, char *buf, 1037 size_t buflen) 1038 { 1039 int timeout = 300; 1040 char *pos; 1041 const char *pin_txt; 1042 1043 if (!wpa_s->ap_iface) 1044 return -1; 1045 1046 pos = os_strchr(cmd, ' '); 1047 if (pos) 1048 *pos++ = '\0'; 1049 1050 if (os_strcmp(cmd, "disable") == 0) { 1051 wpas_wps_ap_pin_disable(wpa_s); 1052 return os_snprintf(buf, buflen, "OK\n"); 1053 } 1054 1055 if (os_strcmp(cmd, "random") == 0) { 1056 if (pos) 1057 timeout = atoi(pos); 1058 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 1059 if (pin_txt == NULL) 1060 return -1; 1061 return os_snprintf(buf, buflen, "%s", pin_txt); 1062 } 1063 1064 if (os_strcmp(cmd, "get") == 0) { 1065 pin_txt = wpas_wps_ap_pin_get(wpa_s); 1066 if (pin_txt == NULL) 1067 return -1; 1068 return os_snprintf(buf, buflen, "%s", pin_txt); 1069 } 1070 1071 if (os_strcmp(cmd, "set") == 0) { 1072 char *pin; 1073 if (pos == NULL) 1074 return -1; 1075 pin = pos; 1076 pos = os_strchr(pos, ' '); 1077 if (pos) { 1078 *pos++ = '\0'; 1079 timeout = atoi(pos); 1080 } 1081 if (os_strlen(pin) > buflen) 1082 return -1; 1083 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 1084 return -1; 1085 return os_snprintf(buf, buflen, "%s", pin); 1086 } 1087 1088 return -1; 1089 } 1090 #endif /* CONFIG_AP */ 1091 1092 1093 #ifdef CONFIG_WPS_ER 1094 static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 1095 char *cmd) 1096 { 1097 char *uuid = cmd, *pin, *pos; 1098 u8 addr_buf[ETH_ALEN], *addr = NULL; 1099 pin = os_strchr(uuid, ' '); 1100 if (pin == NULL) 1101 return -1; 1102 *pin++ = '\0'; 1103 pos = os_strchr(pin, ' '); 1104 if (pos) { 1105 *pos++ = '\0'; 1106 if (hwaddr_aton(pos, addr_buf) == 0) 1107 addr = addr_buf; 1108 } 1109 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 1110 } 1111 1112 1113 static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 1114 char *cmd) 1115 { 1116 char *uuid = cmd, *pin; 1117 pin = os_strchr(uuid, ' '); 1118 if (pin == NULL) 1119 return -1; 1120 *pin++ = '\0'; 1121 return wpas_wps_er_learn(wpa_s, uuid, pin); 1122 } 1123 1124 1125 static int wpa_supplicant_ctrl_iface_wps_er_set_config( 1126 struct wpa_supplicant *wpa_s, char *cmd) 1127 { 1128 char *uuid = cmd, *id; 1129 id = os_strchr(uuid, ' '); 1130 if (id == NULL) 1131 return -1; 1132 *id++ = '\0'; 1133 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 1134 } 1135 1136 1137 static int wpa_supplicant_ctrl_iface_wps_er_config( 1138 struct wpa_supplicant *wpa_s, char *cmd) 1139 { 1140 char *pin; 1141 char *new_ssid; 1142 char *new_auth; 1143 char *new_encr; 1144 char *new_key; 1145 struct wps_new_ap_settings ap; 1146 1147 pin = os_strchr(cmd, ' '); 1148 if (pin == NULL) 1149 return -1; 1150 *pin++ = '\0'; 1151 1152 new_ssid = os_strchr(pin, ' '); 1153 if (new_ssid == NULL) 1154 return -1; 1155 *new_ssid++ = '\0'; 1156 1157 new_auth = os_strchr(new_ssid, ' '); 1158 if (new_auth == NULL) 1159 return -1; 1160 *new_auth++ = '\0'; 1161 1162 new_encr = os_strchr(new_auth, ' '); 1163 if (new_encr == NULL) 1164 return -1; 1165 *new_encr++ = '\0'; 1166 1167 new_key = os_strchr(new_encr, ' '); 1168 if (new_key == NULL) 1169 return -1; 1170 *new_key++ = '\0'; 1171 1172 os_memset(&ap, 0, sizeof(ap)); 1173 ap.ssid_hex = new_ssid; 1174 ap.auth = new_auth; 1175 ap.encr = new_encr; 1176 ap.key_hex = new_key; 1177 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 1178 } 1179 1180 1181 #ifdef CONFIG_WPS_NFC 1182 static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 1183 struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len) 1184 { 1185 int ndef; 1186 struct wpabuf *buf; 1187 int res; 1188 char *uuid; 1189 1190 uuid = os_strchr(cmd, ' '); 1191 if (uuid == NULL) 1192 return -1; 1193 *uuid++ = '\0'; 1194 1195 if (os_strcmp(cmd, "WPS") == 0) 1196 ndef = 0; 1197 else if (os_strcmp(cmd, "NDEF") == 0) 1198 ndef = 1; 1199 else 1200 return -1; 1201 1202 buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid); 1203 if (buf == NULL) 1204 return -1; 1205 1206 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 1207 wpabuf_len(buf)); 1208 reply[res++] = '\n'; 1209 reply[res] = '\0'; 1210 1211 wpabuf_free(buf); 1212 1213 return res; 1214 } 1215 #endif /* CONFIG_WPS_NFC */ 1216 #endif /* CONFIG_WPS_ER */ 1217 1218 #endif /* CONFIG_WPS */ 1219 1220 1221 #ifdef CONFIG_IBSS_RSN 1222 static int wpa_supplicant_ctrl_iface_ibss_rsn( 1223 struct wpa_supplicant *wpa_s, char *addr) 1224 { 1225 u8 peer[ETH_ALEN]; 1226 1227 if (hwaddr_aton(addr, peer)) { 1228 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 1229 "address '%s'", addr); 1230 return -1; 1231 } 1232 1233 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 1234 MAC2STR(peer)); 1235 1236 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 1237 } 1238 #endif /* CONFIG_IBSS_RSN */ 1239 1240 1241 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 1242 char *rsp) 1243 { 1244 #ifdef IEEE8021X_EAPOL 1245 char *pos, *id_pos; 1246 int id; 1247 struct wpa_ssid *ssid; 1248 1249 pos = os_strchr(rsp, '-'); 1250 if (pos == NULL) 1251 return -1; 1252 *pos++ = '\0'; 1253 id_pos = pos; 1254 pos = os_strchr(pos, ':'); 1255 if (pos == NULL) 1256 return -1; 1257 *pos++ = '\0'; 1258 id = atoi(id_pos); 1259 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 1260 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1261 (u8 *) pos, os_strlen(pos)); 1262 1263 ssid = wpa_config_get_network(wpa_s->conf, id); 1264 if (ssid == NULL) { 1265 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1266 "to update", id); 1267 return -1; 1268 } 1269 1270 return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp, 1271 pos); 1272 #else /* IEEE8021X_EAPOL */ 1273 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 1274 return -1; 1275 #endif /* IEEE8021X_EAPOL */ 1276 } 1277 1278 1279 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 1280 const char *params, 1281 char *buf, size_t buflen) 1282 { 1283 char *pos, *end, tmp[30]; 1284 int res, verbose, wps, ret; 1285 1286 verbose = os_strcmp(params, "-VERBOSE") == 0; 1287 wps = os_strcmp(params, "-WPS") == 0; 1288 pos = buf; 1289 end = buf + buflen; 1290 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 1291 struct wpa_ssid *ssid = wpa_s->current_ssid; 1292 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 1293 MAC2STR(wpa_s->bssid)); 1294 if (ret < 0 || ret >= end - pos) 1295 return pos - buf; 1296 pos += ret; 1297 if (ssid) { 1298 u8 *_ssid = ssid->ssid; 1299 size_t ssid_len = ssid->ssid_len; 1300 u8 ssid_buf[MAX_SSID_LEN]; 1301 if (ssid_len == 0) { 1302 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 1303 if (_res < 0) 1304 ssid_len = 0; 1305 else 1306 ssid_len = _res; 1307 _ssid = ssid_buf; 1308 } 1309 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 1310 wpa_ssid_txt(_ssid, ssid_len), 1311 ssid->id); 1312 if (ret < 0 || ret >= end - pos) 1313 return pos - buf; 1314 pos += ret; 1315 1316 if (wps && ssid->passphrase && 1317 wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && 1318 (ssid->mode == WPAS_MODE_AP || 1319 ssid->mode == WPAS_MODE_P2P_GO)) { 1320 ret = os_snprintf(pos, end - pos, 1321 "passphrase=%s\n", 1322 ssid->passphrase); 1323 if (ret < 0 || ret >= end - pos) 1324 return pos - buf; 1325 pos += ret; 1326 } 1327 if (ssid->id_str) { 1328 ret = os_snprintf(pos, end - pos, 1329 "id_str=%s\n", 1330 ssid->id_str); 1331 if (ret < 0 || ret >= end - pos) 1332 return pos - buf; 1333 pos += ret; 1334 } 1335 1336 switch (ssid->mode) { 1337 case WPAS_MODE_INFRA: 1338 ret = os_snprintf(pos, end - pos, 1339 "mode=station\n"); 1340 break; 1341 case WPAS_MODE_IBSS: 1342 ret = os_snprintf(pos, end - pos, 1343 "mode=IBSS\n"); 1344 break; 1345 case WPAS_MODE_AP: 1346 ret = os_snprintf(pos, end - pos, 1347 "mode=AP\n"); 1348 break; 1349 case WPAS_MODE_P2P_GO: 1350 ret = os_snprintf(pos, end - pos, 1351 "mode=P2P GO\n"); 1352 break; 1353 case WPAS_MODE_P2P_GROUP_FORMATION: 1354 ret = os_snprintf(pos, end - pos, 1355 "mode=P2P GO - group " 1356 "formation\n"); 1357 break; 1358 default: 1359 ret = 0; 1360 break; 1361 } 1362 if (ret < 0 || ret >= end - pos) 1363 return pos - buf; 1364 pos += ret; 1365 } 1366 1367 #ifdef CONFIG_AP 1368 if (wpa_s->ap_iface) { 1369 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 1370 end - pos, 1371 verbose); 1372 } else 1373 #endif /* CONFIG_AP */ 1374 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 1375 } 1376 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 1377 wpa_supplicant_state_txt(wpa_s->wpa_state)); 1378 if (ret < 0 || ret >= end - pos) 1379 return pos - buf; 1380 pos += ret; 1381 1382 if (wpa_s->l2 && 1383 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 1384 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 1385 if (ret < 0 || ret >= end - pos) 1386 return pos - buf; 1387 pos += ret; 1388 } 1389 1390 #ifdef CONFIG_P2P 1391 if (wpa_s->global->p2p) { 1392 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 1393 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 1394 if (ret < 0 || ret >= end - pos) 1395 return pos - buf; 1396 pos += ret; 1397 } 1398 #endif /* CONFIG_P2P */ 1399 1400 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 1401 MAC2STR(wpa_s->own_addr)); 1402 if (ret < 0 || ret >= end - pos) 1403 return pos - buf; 1404 pos += ret; 1405 1406 #ifdef CONFIG_HS20 1407 if (wpa_s->current_bss && 1408 wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) && 1409 wpa_s->wpa_proto == WPA_PROTO_RSN && 1410 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 1411 ret = os_snprintf(pos, end - pos, "hs20=1\n"); 1412 if (ret < 0 || ret >= end - pos) 1413 return pos - buf; 1414 pos += ret; 1415 } 1416 1417 if (wpa_s->current_ssid) { 1418 struct wpa_cred *cred; 1419 char *type; 1420 1421 for (cred = wpa_s->conf->cred; cred; cred = cred->next) { 1422 if (wpa_s->current_ssid->parent_cred != cred) 1423 continue; 1424 if (!cred->domain) 1425 continue; 1426 1427 ret = os_snprintf(pos, end - pos, "home_sp=%s\n", 1428 cred->domain); 1429 if (ret < 0 || ret >= end - pos) 1430 return pos - buf; 1431 pos += ret; 1432 1433 if (wpa_s->current_bss == NULL || 1434 wpa_s->current_bss->anqp == NULL) 1435 res = -1; 1436 else 1437 res = interworking_home_sp_cred( 1438 wpa_s, cred, 1439 wpa_s->current_bss->anqp->domain_name); 1440 if (res > 0) 1441 type = "home"; 1442 else if (res == 0) 1443 type = "roaming"; 1444 else 1445 type = "unknown"; 1446 1447 ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type); 1448 if (ret < 0 || ret >= end - pos) 1449 return pos - buf; 1450 pos += ret; 1451 1452 break; 1453 } 1454 } 1455 #endif /* CONFIG_HS20 */ 1456 1457 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 1458 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1459 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 1460 verbose); 1461 if (res >= 0) 1462 pos += res; 1463 } 1464 1465 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 1466 if (res >= 0) 1467 pos += res; 1468 1469 return pos - buf; 1470 } 1471 1472 1473 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 1474 char *cmd) 1475 { 1476 char *pos; 1477 int id; 1478 struct wpa_ssid *ssid; 1479 u8 bssid[ETH_ALEN]; 1480 1481 /* cmd: "<network id> <BSSID>" */ 1482 pos = os_strchr(cmd, ' '); 1483 if (pos == NULL) 1484 return -1; 1485 *pos++ = '\0'; 1486 id = atoi(cmd); 1487 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 1488 if (hwaddr_aton(pos, bssid)) { 1489 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 1490 return -1; 1491 } 1492 1493 ssid = wpa_config_get_network(wpa_s->conf, id); 1494 if (ssid == NULL) { 1495 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 1496 "to update", id); 1497 return -1; 1498 } 1499 1500 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 1501 ssid->bssid_set = !is_zero_ether_addr(bssid); 1502 1503 return 0; 1504 } 1505 1506 1507 static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 1508 char *cmd, char *buf, 1509 size_t buflen) 1510 { 1511 u8 bssid[ETH_ALEN]; 1512 struct wpa_blacklist *e; 1513 char *pos, *end; 1514 int ret; 1515 1516 /* cmd: "BLACKLIST [<BSSID>]" */ 1517 if (*cmd == '\0') { 1518 pos = buf; 1519 end = buf + buflen; 1520 e = wpa_s->blacklist; 1521 while (e) { 1522 ret = os_snprintf(pos, end - pos, MACSTR "\n", 1523 MAC2STR(e->bssid)); 1524 if (ret < 0 || ret >= end - pos) 1525 return pos - buf; 1526 pos += ret; 1527 e = e->next; 1528 } 1529 return pos - buf; 1530 } 1531 1532 cmd++; 1533 if (os_strncmp(cmd, "clear", 5) == 0) { 1534 wpa_blacklist_clear(wpa_s); 1535 os_memcpy(buf, "OK\n", 3); 1536 return 3; 1537 } 1538 1539 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 1540 if (hwaddr_aton(cmd, bssid)) { 1541 wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd); 1542 return -1; 1543 } 1544 1545 /* 1546 * Add the BSSID twice, so its count will be 2, causing it to be 1547 * skipped when processing scan results. 1548 */ 1549 ret = wpa_blacklist_add(wpa_s, bssid); 1550 if (ret != 0) 1551 return -1; 1552 ret = wpa_blacklist_add(wpa_s, bssid); 1553 if (ret != 0) 1554 return -1; 1555 os_memcpy(buf, "OK\n", 3); 1556 return 3; 1557 } 1558 1559 1560 extern int wpa_debug_level; 1561 extern int wpa_debug_timestamp; 1562 1563 static const char * debug_level_str(int level) 1564 { 1565 switch (level) { 1566 case MSG_EXCESSIVE: 1567 return "EXCESSIVE"; 1568 case MSG_MSGDUMP: 1569 return "MSGDUMP"; 1570 case MSG_DEBUG: 1571 return "DEBUG"; 1572 case MSG_INFO: 1573 return "INFO"; 1574 case MSG_WARNING: 1575 return "WARNING"; 1576 case MSG_ERROR: 1577 return "ERROR"; 1578 default: 1579 return "?"; 1580 } 1581 } 1582 1583 1584 static int str_to_debug_level(const char *s) 1585 { 1586 if (os_strcasecmp(s, "EXCESSIVE") == 0) 1587 return MSG_EXCESSIVE; 1588 if (os_strcasecmp(s, "MSGDUMP") == 0) 1589 return MSG_MSGDUMP; 1590 if (os_strcasecmp(s, "DEBUG") == 0) 1591 return MSG_DEBUG; 1592 if (os_strcasecmp(s, "INFO") == 0) 1593 return MSG_INFO; 1594 if (os_strcasecmp(s, "WARNING") == 0) 1595 return MSG_WARNING; 1596 if (os_strcasecmp(s, "ERROR") == 0) 1597 return MSG_ERROR; 1598 return -1; 1599 } 1600 1601 1602 static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 1603 char *cmd, char *buf, 1604 size_t buflen) 1605 { 1606 char *pos, *end, *stamp; 1607 int ret; 1608 1609 if (cmd == NULL) { 1610 return -1; 1611 } 1612 1613 /* cmd: "LOG_LEVEL [<level>]" */ 1614 if (*cmd == '\0') { 1615 pos = buf; 1616 end = buf + buflen; 1617 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 1618 "Timestamp: %d\n", 1619 debug_level_str(wpa_debug_level), 1620 wpa_debug_timestamp); 1621 if (ret < 0 || ret >= end - pos) 1622 ret = 0; 1623 1624 return ret; 1625 } 1626 1627 while (*cmd == ' ') 1628 cmd++; 1629 1630 stamp = os_strchr(cmd, ' '); 1631 if (stamp) { 1632 *stamp++ = '\0'; 1633 while (*stamp == ' ') { 1634 stamp++; 1635 } 1636 } 1637 1638 if (cmd && os_strlen(cmd)) { 1639 int level = str_to_debug_level(cmd); 1640 if (level < 0) 1641 return -1; 1642 wpa_debug_level = level; 1643 } 1644 1645 if (stamp && os_strlen(stamp)) 1646 wpa_debug_timestamp = atoi(stamp); 1647 1648 os_memcpy(buf, "OK\n", 3); 1649 return 3; 1650 } 1651 1652 1653 static int wpa_supplicant_ctrl_iface_list_networks( 1654 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1655 { 1656 char *pos, *end; 1657 struct wpa_ssid *ssid; 1658 int ret; 1659 1660 pos = buf; 1661 end = buf + buflen; 1662 ret = os_snprintf(pos, end - pos, 1663 "network id / ssid / bssid / flags\n"); 1664 if (ret < 0 || ret >= end - pos) 1665 return pos - buf; 1666 pos += ret; 1667 1668 ssid = wpa_s->conf->ssid; 1669 while (ssid) { 1670 ret = os_snprintf(pos, end - pos, "%d\t%s", 1671 ssid->id, 1672 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1673 if (ret < 0 || ret >= end - pos) 1674 return pos - buf; 1675 pos += ret; 1676 if (ssid->bssid_set) { 1677 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 1678 MAC2STR(ssid->bssid)); 1679 } else { 1680 ret = os_snprintf(pos, end - pos, "\tany"); 1681 } 1682 if (ret < 0 || ret >= end - pos) 1683 return pos - buf; 1684 pos += ret; 1685 ret = os_snprintf(pos, end - pos, "\t%s%s%s%s", 1686 ssid == wpa_s->current_ssid ? 1687 "[CURRENT]" : "", 1688 ssid->disabled ? "[DISABLED]" : "", 1689 ssid->disabled_until.sec ? 1690 "[TEMP-DISABLED]" : "", 1691 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 1692 ""); 1693 if (ret < 0 || ret >= end - pos) 1694 return pos - buf; 1695 pos += ret; 1696 ret = os_snprintf(pos, end - pos, "\n"); 1697 if (ret < 0 || ret >= end - pos) 1698 return pos - buf; 1699 pos += ret; 1700 1701 ssid = ssid->next; 1702 } 1703 1704 return pos - buf; 1705 } 1706 1707 1708 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 1709 { 1710 int first = 1, ret; 1711 ret = os_snprintf(pos, end - pos, "-"); 1712 if (ret < 0 || ret >= end - pos) 1713 return pos; 1714 pos += ret; 1715 if (cipher & WPA_CIPHER_NONE) { 1716 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 1717 if (ret < 0 || ret >= end - pos) 1718 return pos; 1719 pos += ret; 1720 first = 0; 1721 } 1722 if (cipher & WPA_CIPHER_WEP40) { 1723 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 1724 if (ret < 0 || ret >= end - pos) 1725 return pos; 1726 pos += ret; 1727 first = 0; 1728 } 1729 if (cipher & WPA_CIPHER_WEP104) { 1730 ret = os_snprintf(pos, end - pos, "%sWEP104", 1731 first ? "" : "+"); 1732 if (ret < 0 || ret >= end - pos) 1733 return pos; 1734 pos += ret; 1735 first = 0; 1736 } 1737 if (cipher & WPA_CIPHER_TKIP) { 1738 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 1739 if (ret < 0 || ret >= end - pos) 1740 return pos; 1741 pos += ret; 1742 first = 0; 1743 } 1744 if (cipher & WPA_CIPHER_CCMP) { 1745 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 1746 if (ret < 0 || ret >= end - pos) 1747 return pos; 1748 pos += ret; 1749 first = 0; 1750 } 1751 if (cipher & WPA_CIPHER_GCMP) { 1752 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+"); 1753 if (ret < 0 || ret >= end - pos) 1754 return pos; 1755 pos += ret; 1756 first = 0; 1757 } 1758 return pos; 1759 } 1760 1761 1762 static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 1763 const u8 *ie, size_t ie_len) 1764 { 1765 struct wpa_ie_data data; 1766 int first, ret; 1767 1768 ret = os_snprintf(pos, end - pos, "[%s-", proto); 1769 if (ret < 0 || ret >= end - pos) 1770 return pos; 1771 pos += ret; 1772 1773 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 1774 ret = os_snprintf(pos, end - pos, "?]"); 1775 if (ret < 0 || ret >= end - pos) 1776 return pos; 1777 pos += ret; 1778 return pos; 1779 } 1780 1781 first = 1; 1782 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1783 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 1784 if (ret < 0 || ret >= end - pos) 1785 return pos; 1786 pos += ret; 1787 first = 0; 1788 } 1789 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 1790 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 1791 if (ret < 0 || ret >= end - pos) 1792 return pos; 1793 pos += ret; 1794 first = 0; 1795 } 1796 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 1797 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 1798 if (ret < 0 || ret >= end - pos) 1799 return pos; 1800 pos += ret; 1801 first = 0; 1802 } 1803 #ifdef CONFIG_IEEE80211R 1804 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1805 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 1806 first ? "" : "+"); 1807 if (ret < 0 || ret >= end - pos) 1808 return pos; 1809 pos += ret; 1810 first = 0; 1811 } 1812 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1813 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 1814 first ? "" : "+"); 1815 if (ret < 0 || ret >= end - pos) 1816 return pos; 1817 pos += ret; 1818 first = 0; 1819 } 1820 #endif /* CONFIG_IEEE80211R */ 1821 #ifdef CONFIG_IEEE80211W 1822 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1823 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 1824 first ? "" : "+"); 1825 if (ret < 0 || ret >= end - pos) 1826 return pos; 1827 pos += ret; 1828 first = 0; 1829 } 1830 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1831 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 1832 first ? "" : "+"); 1833 if (ret < 0 || ret >= end - pos) 1834 return pos; 1835 pos += ret; 1836 first = 0; 1837 } 1838 #endif /* CONFIG_IEEE80211W */ 1839 1840 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 1841 1842 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 1843 ret = os_snprintf(pos, end - pos, "-preauth"); 1844 if (ret < 0 || ret >= end - pos) 1845 return pos; 1846 pos += ret; 1847 } 1848 1849 ret = os_snprintf(pos, end - pos, "]"); 1850 if (ret < 0 || ret >= end - pos) 1851 return pos; 1852 pos += ret; 1853 1854 return pos; 1855 } 1856 1857 1858 #ifdef CONFIG_WPS 1859 static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 1860 char *pos, char *end, 1861 struct wpabuf *wps_ie) 1862 { 1863 int ret; 1864 const char *txt; 1865 1866 if (wps_ie == NULL) 1867 return pos; 1868 if (wps_is_selected_pbc_registrar(wps_ie)) 1869 txt = "[WPS-PBC]"; 1870 #ifdef CONFIG_WPS2 1871 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 1872 txt = "[WPS-AUTH]"; 1873 #endif /* CONFIG_WPS2 */ 1874 else if (wps_is_selected_pin_registrar(wps_ie)) 1875 txt = "[WPS-PIN]"; 1876 else 1877 txt = "[WPS]"; 1878 1879 ret = os_snprintf(pos, end - pos, "%s", txt); 1880 if (ret >= 0 && ret < end - pos) 1881 pos += ret; 1882 wpabuf_free(wps_ie); 1883 return pos; 1884 } 1885 #endif /* CONFIG_WPS */ 1886 1887 1888 static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 1889 char *pos, char *end, 1890 const struct wpa_bss *bss) 1891 { 1892 #ifdef CONFIG_WPS 1893 struct wpabuf *wps_ie; 1894 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 1895 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 1896 #else /* CONFIG_WPS */ 1897 return pos; 1898 #endif /* CONFIG_WPS */ 1899 } 1900 1901 1902 /* Format one result on one text line into a buffer. */ 1903 static int wpa_supplicant_ctrl_iface_scan_result( 1904 struct wpa_supplicant *wpa_s, 1905 const struct wpa_bss *bss, char *buf, size_t buflen) 1906 { 1907 char *pos, *end; 1908 int ret; 1909 const u8 *ie, *ie2, *p2p; 1910 1911 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 1912 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 1913 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 1914 0) 1915 return 0; /* Do not show P2P listen discovery results here */ 1916 1917 pos = buf; 1918 end = buf + buflen; 1919 1920 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 1921 MAC2STR(bss->bssid), bss->freq, bss->level); 1922 if (ret < 0 || ret >= end - pos) 1923 return -1; 1924 pos += ret; 1925 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1926 if (ie) 1927 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1928 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1929 if (ie2) 1930 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1931 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 1932 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1933 ret = os_snprintf(pos, end - pos, "[WEP]"); 1934 if (ret < 0 || ret >= end - pos) 1935 return -1; 1936 pos += ret; 1937 } 1938 if (bss->caps & IEEE80211_CAP_IBSS) { 1939 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1940 if (ret < 0 || ret >= end - pos) 1941 return -1; 1942 pos += ret; 1943 } 1944 if (bss->caps & IEEE80211_CAP_ESS) { 1945 ret = os_snprintf(pos, end - pos, "[ESS]"); 1946 if (ret < 0 || ret >= end - pos) 1947 return -1; 1948 pos += ret; 1949 } 1950 if (p2p) { 1951 ret = os_snprintf(pos, end - pos, "[P2P]"); 1952 if (ret < 0 || ret >= end - pos) 1953 return -1; 1954 pos += ret; 1955 } 1956 #ifdef CONFIG_HS20 1957 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) { 1958 ret = os_snprintf(pos, end - pos, "[HS20]"); 1959 if (ret < 0 || ret >= end - pos) 1960 return -1; 1961 pos += ret; 1962 } 1963 #endif /* CONFIG_HS20 */ 1964 1965 ret = os_snprintf(pos, end - pos, "\t%s", 1966 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 1967 if (ret < 0 || ret >= end - pos) 1968 return -1; 1969 pos += ret; 1970 1971 ret = os_snprintf(pos, end - pos, "\n"); 1972 if (ret < 0 || ret >= end - pos) 1973 return -1; 1974 pos += ret; 1975 1976 return pos - buf; 1977 } 1978 1979 1980 static int wpa_supplicant_ctrl_iface_scan_results( 1981 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1982 { 1983 char *pos, *end; 1984 struct wpa_bss *bss; 1985 int ret; 1986 1987 pos = buf; 1988 end = buf + buflen; 1989 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 1990 "flags / ssid\n"); 1991 if (ret < 0 || ret >= end - pos) 1992 return pos - buf; 1993 pos += ret; 1994 1995 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 1996 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 1997 end - pos); 1998 if (ret < 0 || ret >= end - pos) 1999 return pos - buf; 2000 pos += ret; 2001 } 2002 2003 return pos - buf; 2004 } 2005 2006 2007 static int wpa_supplicant_ctrl_iface_select_network( 2008 struct wpa_supplicant *wpa_s, char *cmd) 2009 { 2010 int id; 2011 struct wpa_ssid *ssid; 2012 2013 /* cmd: "<network id>" or "any" */ 2014 if (os_strcmp(cmd, "any") == 0) { 2015 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 2016 ssid = NULL; 2017 } else { 2018 id = atoi(cmd); 2019 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 2020 2021 ssid = wpa_config_get_network(wpa_s->conf, id); 2022 if (ssid == NULL) { 2023 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2024 "network id=%d", id); 2025 return -1; 2026 } 2027 if (ssid->disabled == 2) { 2028 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2029 "SELECT_NETWORK with persistent P2P group"); 2030 return -1; 2031 } 2032 } 2033 2034 wpa_supplicant_select_network(wpa_s, ssid); 2035 2036 return 0; 2037 } 2038 2039 2040 static int wpa_supplicant_ctrl_iface_enable_network( 2041 struct wpa_supplicant *wpa_s, char *cmd) 2042 { 2043 int id; 2044 struct wpa_ssid *ssid; 2045 2046 /* cmd: "<network id>" or "all" */ 2047 if (os_strcmp(cmd, "all") == 0) { 2048 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 2049 ssid = NULL; 2050 } else { 2051 id = atoi(cmd); 2052 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 2053 2054 ssid = wpa_config_get_network(wpa_s->conf, id); 2055 if (ssid == NULL) { 2056 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2057 "network id=%d", id); 2058 return -1; 2059 } 2060 if (ssid->disabled == 2) { 2061 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2062 "ENABLE_NETWORK with persistent P2P group"); 2063 return -1; 2064 } 2065 2066 if (os_strstr(cmd, " no-connect")) { 2067 ssid->disabled = 0; 2068 return 0; 2069 } 2070 } 2071 wpa_supplicant_enable_network(wpa_s, ssid); 2072 2073 return 0; 2074 } 2075 2076 2077 static int wpa_supplicant_ctrl_iface_disable_network( 2078 struct wpa_supplicant *wpa_s, char *cmd) 2079 { 2080 int id; 2081 struct wpa_ssid *ssid; 2082 2083 /* cmd: "<network id>" or "all" */ 2084 if (os_strcmp(cmd, "all") == 0) { 2085 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 2086 ssid = NULL; 2087 } else { 2088 id = atoi(cmd); 2089 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 2090 2091 ssid = wpa_config_get_network(wpa_s->conf, id); 2092 if (ssid == NULL) { 2093 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 2094 "network id=%d", id); 2095 return -1; 2096 } 2097 if (ssid->disabled == 2) { 2098 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 2099 "DISABLE_NETWORK with persistent P2P " 2100 "group"); 2101 return -1; 2102 } 2103 } 2104 wpa_supplicant_disable_network(wpa_s, ssid); 2105 2106 return 0; 2107 } 2108 2109 2110 static int wpa_supplicant_ctrl_iface_add_network( 2111 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 2112 { 2113 struct wpa_ssid *ssid; 2114 int ret; 2115 2116 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 2117 2118 ssid = wpa_config_add_network(wpa_s->conf); 2119 if (ssid == NULL) 2120 return -1; 2121 2122 wpas_notify_network_added(wpa_s, ssid); 2123 2124 ssid->disabled = 1; 2125 wpa_config_set_network_defaults(ssid); 2126 2127 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 2128 if (ret < 0 || (size_t) ret >= buflen) 2129 return -1; 2130 return ret; 2131 } 2132 2133 2134 static int wpa_supplicant_ctrl_iface_remove_network( 2135 struct wpa_supplicant *wpa_s, char *cmd) 2136 { 2137 int id; 2138 struct wpa_ssid *ssid; 2139 2140 /* cmd: "<network id>" or "all" */ 2141 if (os_strcmp(cmd, "all") == 0) { 2142 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 2143 ssid = wpa_s->conf->ssid; 2144 while (ssid) { 2145 struct wpa_ssid *remove_ssid = ssid; 2146 id = ssid->id; 2147 ssid = ssid->next; 2148 wpas_notify_network_removed(wpa_s, remove_ssid); 2149 wpa_config_remove_network(wpa_s->conf, id); 2150 } 2151 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2152 if (wpa_s->current_ssid) { 2153 #ifdef CONFIG_SME 2154 wpa_s->sme.prev_bssid_set = 0; 2155 #endif /* CONFIG_SME */ 2156 wpa_sm_set_config(wpa_s->wpa, NULL); 2157 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2158 wpa_supplicant_deauthenticate( 2159 wpa_s, WLAN_REASON_DEAUTH_LEAVING); 2160 } 2161 return 0; 2162 } 2163 2164 id = atoi(cmd); 2165 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 2166 2167 ssid = wpa_config_get_network(wpa_s->conf, id); 2168 if (ssid) 2169 wpas_notify_network_removed(wpa_s, ssid); 2170 if (ssid == NULL) { 2171 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2172 "id=%d", id); 2173 return -1; 2174 } 2175 2176 if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) { 2177 #ifdef CONFIG_SME 2178 wpa_s->sme.prev_bssid_set = 0; 2179 #endif /* CONFIG_SME */ 2180 /* 2181 * Invalidate the EAP session cache if the current or 2182 * previously used network is removed. 2183 */ 2184 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2185 } 2186 2187 if (ssid == wpa_s->current_ssid) { 2188 wpa_sm_set_config(wpa_s->wpa, NULL); 2189 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); 2190 2191 wpa_supplicant_deauthenticate(wpa_s, 2192 WLAN_REASON_DEAUTH_LEAVING); 2193 } 2194 2195 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 2196 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the " 2197 "network id=%d", id); 2198 return -1; 2199 } 2200 2201 return 0; 2202 } 2203 2204 2205 static int wpa_supplicant_ctrl_iface_set_network( 2206 struct wpa_supplicant *wpa_s, char *cmd) 2207 { 2208 int id; 2209 struct wpa_ssid *ssid; 2210 char *name, *value; 2211 2212 /* cmd: "<network id> <variable name> <value>" */ 2213 name = os_strchr(cmd, ' '); 2214 if (name == NULL) 2215 return -1; 2216 *name++ = '\0'; 2217 2218 value = os_strchr(name, ' '); 2219 if (value == NULL) 2220 return -1; 2221 *value++ = '\0'; 2222 2223 id = atoi(cmd); 2224 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 2225 id, name); 2226 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2227 (u8 *) value, os_strlen(value)); 2228 2229 ssid = wpa_config_get_network(wpa_s->conf, id); 2230 if (ssid == NULL) { 2231 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2232 "id=%d", id); 2233 return -1; 2234 } 2235 2236 if (wpa_config_set(ssid, name, value, 0) < 0) { 2237 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 2238 "variable '%s'", name); 2239 return -1; 2240 } 2241 2242 if (os_strcmp(name, "bssid") != 0 && 2243 os_strcmp(name, "priority") != 0) 2244 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 2245 2246 if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) { 2247 /* 2248 * Invalidate the EAP session cache if anything in the current 2249 * or previously used configuration changes. 2250 */ 2251 eapol_sm_invalidate_cached_session(wpa_s->eapol); 2252 } 2253 2254 if ((os_strcmp(name, "psk") == 0 && 2255 value[0] == '"' && ssid->ssid_len) || 2256 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 2257 wpa_config_update_psk(ssid); 2258 else if (os_strcmp(name, "priority") == 0) 2259 wpa_config_update_prio_list(wpa_s->conf); 2260 2261 return 0; 2262 } 2263 2264 2265 static int wpa_supplicant_ctrl_iface_get_network( 2266 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 2267 { 2268 int id; 2269 size_t res; 2270 struct wpa_ssid *ssid; 2271 char *name, *value; 2272 2273 /* cmd: "<network id> <variable name>" */ 2274 name = os_strchr(cmd, ' '); 2275 if (name == NULL || buflen == 0) 2276 return -1; 2277 *name++ = '\0'; 2278 2279 id = atoi(cmd); 2280 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 2281 id, name); 2282 2283 ssid = wpa_config_get_network(wpa_s->conf, id); 2284 if (ssid == NULL) { 2285 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 2286 "id=%d", id); 2287 return -1; 2288 } 2289 2290 value = wpa_config_get_no_key(ssid, name); 2291 if (value == NULL) { 2292 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 2293 "variable '%s'", name); 2294 return -1; 2295 } 2296 2297 res = os_strlcpy(buf, value, buflen); 2298 if (res >= buflen) { 2299 os_free(value); 2300 return -1; 2301 } 2302 2303 os_free(value); 2304 2305 return res; 2306 } 2307 2308 2309 static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s, 2310 char *buf, size_t buflen) 2311 { 2312 char *pos, *end; 2313 struct wpa_cred *cred; 2314 int ret; 2315 2316 pos = buf; 2317 end = buf + buflen; 2318 ret = os_snprintf(pos, end - pos, 2319 "cred id / realm / username / domain / imsi\n"); 2320 if (ret < 0 || ret >= end - pos) 2321 return pos - buf; 2322 pos += ret; 2323 2324 cred = wpa_s->conf->cred; 2325 while (cred) { 2326 ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n", 2327 cred->id, cred->realm ? cred->realm : "", 2328 cred->username ? cred->username : "", 2329 cred->domain ? cred->domain : "", 2330 cred->imsi ? cred->imsi : ""); 2331 if (ret < 0 || ret >= end - pos) 2332 return pos - buf; 2333 pos += ret; 2334 2335 cred = cred->next; 2336 } 2337 2338 return pos - buf; 2339 } 2340 2341 2342 static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, 2343 char *buf, size_t buflen) 2344 { 2345 struct wpa_cred *cred; 2346 int ret; 2347 2348 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED"); 2349 2350 cred = wpa_config_add_cred(wpa_s->conf); 2351 if (cred == NULL) 2352 return -1; 2353 2354 ret = os_snprintf(buf, buflen, "%d\n", cred->id); 2355 if (ret < 0 || (size_t) ret >= buflen) 2356 return -1; 2357 return ret; 2358 } 2359 2360 2361 static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, 2362 struct wpa_cred *cred) 2363 { 2364 struct wpa_ssid *ssid; 2365 char str[20]; 2366 2367 if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) { 2368 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); 2369 return -1; 2370 } 2371 2372 /* Remove any network entry created based on the removed credential */ 2373 ssid = wpa_s->conf->ssid; 2374 while (ssid) { 2375 if (ssid->parent_cred == cred) { 2376 wpa_printf(MSG_DEBUG, "Remove network id %d since it " 2377 "used the removed credential", ssid->id); 2378 os_snprintf(str, sizeof(str), "%d", ssid->id); 2379 ssid = ssid->next; 2380 wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); 2381 } else 2382 ssid = ssid->next; 2383 } 2384 2385 return 0; 2386 } 2387 2388 2389 static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, 2390 char *cmd) 2391 { 2392 int id; 2393 struct wpa_cred *cred, *prev; 2394 2395 /* cmd: "<cred id>", "all", or "sp_fqdn=<FQDN>" */ 2396 if (os_strcmp(cmd, "all") == 0) { 2397 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); 2398 cred = wpa_s->conf->cred; 2399 while (cred) { 2400 prev = cred; 2401 cred = cred->next; 2402 wpas_ctrl_remove_cred(wpa_s, prev); 2403 } 2404 return 0; 2405 } 2406 2407 if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { 2408 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED SP FQDN '%s'", 2409 cmd + 8); 2410 cred = wpa_s->conf->cred; 2411 while (cred) { 2412 prev = cred; 2413 cred = cred->next; 2414 if (prev->domain && 2415 os_strcmp(prev->domain, cmd + 8) == 0) 2416 wpas_ctrl_remove_cred(wpa_s, prev); 2417 } 2418 return 0; 2419 } 2420 2421 id = atoi(cmd); 2422 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); 2423 2424 cred = wpa_config_get_cred(wpa_s->conf, id); 2425 return wpas_ctrl_remove_cred(wpa_s, cred); 2426 } 2427 2428 2429 static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s, 2430 char *cmd) 2431 { 2432 int id; 2433 struct wpa_cred *cred; 2434 char *name, *value; 2435 2436 /* cmd: "<cred id> <variable name> <value>" */ 2437 name = os_strchr(cmd, ' '); 2438 if (name == NULL) 2439 return -1; 2440 *name++ = '\0'; 2441 2442 value = os_strchr(name, ' '); 2443 if (value == NULL) 2444 return -1; 2445 *value++ = '\0'; 2446 2447 id = atoi(cmd); 2448 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'", 2449 id, name); 2450 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 2451 (u8 *) value, os_strlen(value)); 2452 2453 cred = wpa_config_get_cred(wpa_s->conf, id); 2454 if (cred == NULL) { 2455 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d", 2456 id); 2457 return -1; 2458 } 2459 2460 if (wpa_config_set_cred(cred, name, value, 0) < 0) { 2461 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred " 2462 "variable '%s'", name); 2463 return -1; 2464 } 2465 2466 return 0; 2467 } 2468 2469 2470 #ifndef CONFIG_NO_CONFIG_WRITE 2471 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 2472 { 2473 int ret; 2474 2475 if (!wpa_s->conf->update_config) { 2476 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 2477 "to update configuration (update_config=0)"); 2478 return -1; 2479 } 2480 2481 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 2482 if (ret) { 2483 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 2484 "update configuration"); 2485 } else { 2486 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 2487 " updated"); 2488 } 2489 2490 return ret; 2491 } 2492 #endif /* CONFIG_NO_CONFIG_WRITE */ 2493 2494 2495 static int ctrl_iface_get_capability_pairwise(int res, char *strict, 2496 struct wpa_driver_capa *capa, 2497 char *buf, size_t buflen) 2498 { 2499 int ret, first = 1; 2500 char *pos, *end; 2501 size_t len; 2502 2503 pos = buf; 2504 end = pos + buflen; 2505 2506 if (res < 0) { 2507 if (strict) 2508 return 0; 2509 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 2510 if (len >= buflen) 2511 return -1; 2512 return len; 2513 } 2514 2515 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2516 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2517 if (ret < 0 || ret >= end - pos) 2518 return pos - buf; 2519 pos += ret; 2520 first = 0; 2521 } 2522 2523 if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2524 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); 2525 if (ret < 0 || ret >= end - pos) 2526 return pos - buf; 2527 pos += ret; 2528 first = 0; 2529 } 2530 2531 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2532 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2533 if (ret < 0 || ret >= end - pos) 2534 return pos - buf; 2535 pos += ret; 2536 first = 0; 2537 } 2538 2539 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2540 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 2541 if (ret < 0 || ret >= end - pos) 2542 return pos - buf; 2543 pos += ret; 2544 first = 0; 2545 } 2546 2547 return pos - buf; 2548 } 2549 2550 2551 static int ctrl_iface_get_capability_group(int res, char *strict, 2552 struct wpa_driver_capa *capa, 2553 char *buf, size_t buflen) 2554 { 2555 int ret, first = 1; 2556 char *pos, *end; 2557 size_t len; 2558 2559 pos = buf; 2560 end = pos + buflen; 2561 2562 if (res < 0) { 2563 if (strict) 2564 return 0; 2565 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 2566 if (len >= buflen) 2567 return -1; 2568 return len; 2569 } 2570 2571 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2572 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 2573 if (ret < 0 || ret >= end - pos) 2574 return pos - buf; 2575 pos += ret; 2576 first = 0; 2577 } 2578 2579 if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2580 ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); 2581 if (ret < 0 || ret >= end - pos) 2582 return pos - buf; 2583 pos += ret; 2584 first = 0; 2585 } 2586 2587 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2588 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 2589 if (ret < 0 || ret >= end - pos) 2590 return pos - buf; 2591 pos += ret; 2592 first = 0; 2593 } 2594 2595 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 2596 ret = os_snprintf(pos, end - pos, "%sWEP104", 2597 first ? "" : " "); 2598 if (ret < 0 || ret >= end - pos) 2599 return pos - buf; 2600 pos += ret; 2601 first = 0; 2602 } 2603 2604 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 2605 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 2606 if (ret < 0 || ret >= end - pos) 2607 return pos - buf; 2608 pos += ret; 2609 first = 0; 2610 } 2611 2612 return pos - buf; 2613 } 2614 2615 2616 static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 2617 struct wpa_driver_capa *capa, 2618 char *buf, size_t buflen) 2619 { 2620 int ret; 2621 char *pos, *end; 2622 size_t len; 2623 2624 pos = buf; 2625 end = pos + buflen; 2626 2627 if (res < 0) { 2628 if (strict) 2629 return 0; 2630 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 2631 "NONE", buflen); 2632 if (len >= buflen) 2633 return -1; 2634 return len; 2635 } 2636 2637 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 2638 if (ret < 0 || ret >= end - pos) 2639 return pos - buf; 2640 pos += ret; 2641 2642 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2643 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2644 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 2645 if (ret < 0 || ret >= end - pos) 2646 return pos - buf; 2647 pos += ret; 2648 } 2649 2650 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2651 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2652 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 2653 if (ret < 0 || ret >= end - pos) 2654 return pos - buf; 2655 pos += ret; 2656 } 2657 2658 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2659 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 2660 if (ret < 0 || ret >= end - pos) 2661 return pos - buf; 2662 pos += ret; 2663 } 2664 2665 return pos - buf; 2666 } 2667 2668 2669 static int ctrl_iface_get_capability_proto(int res, char *strict, 2670 struct wpa_driver_capa *capa, 2671 char *buf, size_t buflen) 2672 { 2673 int ret, first = 1; 2674 char *pos, *end; 2675 size_t len; 2676 2677 pos = buf; 2678 end = pos + buflen; 2679 2680 if (res < 0) { 2681 if (strict) 2682 return 0; 2683 len = os_strlcpy(buf, "RSN WPA", buflen); 2684 if (len >= buflen) 2685 return -1; 2686 return len; 2687 } 2688 2689 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2690 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2691 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 2692 if (ret < 0 || ret >= end - pos) 2693 return pos - buf; 2694 pos += ret; 2695 first = 0; 2696 } 2697 2698 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2699 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 2700 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 2701 if (ret < 0 || ret >= end - pos) 2702 return pos - buf; 2703 pos += ret; 2704 first = 0; 2705 } 2706 2707 return pos - buf; 2708 } 2709 2710 2711 static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 2712 struct wpa_driver_capa *capa, 2713 char *buf, size_t buflen) 2714 { 2715 int ret, first = 1; 2716 char *pos, *end; 2717 size_t len; 2718 2719 pos = buf; 2720 end = pos + buflen; 2721 2722 if (res < 0) { 2723 if (strict) 2724 return 0; 2725 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 2726 if (len >= buflen) 2727 return -1; 2728 return len; 2729 } 2730 2731 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 2732 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 2733 if (ret < 0 || ret >= end - pos) 2734 return pos - buf; 2735 pos += ret; 2736 first = 0; 2737 } 2738 2739 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 2740 ret = os_snprintf(pos, end - pos, "%sSHARED", 2741 first ? "" : " "); 2742 if (ret < 0 || ret >= end - pos) 2743 return pos - buf; 2744 pos += ret; 2745 first = 0; 2746 } 2747 2748 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 2749 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 2750 if (ret < 0 || ret >= end - pos) 2751 return pos - buf; 2752 pos += ret; 2753 first = 0; 2754 } 2755 2756 return pos - buf; 2757 } 2758 2759 2760 static int ctrl_iface_get_capability_channels(struct wpa_supplicant *wpa_s, 2761 char *buf, size_t buflen) 2762 { 2763 struct hostapd_channel_data *chnl; 2764 int ret, i, j; 2765 char *pos, *end, *hmode; 2766 2767 pos = buf; 2768 end = pos + buflen; 2769 2770 for (j = 0; j < wpa_s->hw.num_modes; j++) { 2771 switch (wpa_s->hw.modes[j].mode) { 2772 case HOSTAPD_MODE_IEEE80211B: 2773 hmode = "B"; 2774 break; 2775 case HOSTAPD_MODE_IEEE80211G: 2776 hmode = "G"; 2777 break; 2778 case HOSTAPD_MODE_IEEE80211A: 2779 hmode = "A"; 2780 break; 2781 case HOSTAPD_MODE_IEEE80211AD: 2782 hmode = "AD"; 2783 break; 2784 default: 2785 continue; 2786 } 2787 ret = os_snprintf(pos, end - pos, "Mode[%s] Channels:", hmode); 2788 if (ret < 0 || ret >= end - pos) 2789 return pos - buf; 2790 pos += ret; 2791 chnl = wpa_s->hw.modes[j].channels; 2792 for (i = 0; i < wpa_s->hw.modes[j].num_channels; i++) { 2793 if (chnl[i].flag & HOSTAPD_CHAN_DISABLED) 2794 continue; 2795 ret = os_snprintf(pos, end - pos, " %d", chnl[i].chan); 2796 if (ret < 0 || ret >= end - pos) 2797 return pos - buf; 2798 pos += ret; 2799 } 2800 ret = os_snprintf(pos, end - pos, "\n"); 2801 if (ret < 0 || ret >= end - pos) 2802 return pos - buf; 2803 pos += ret; 2804 } 2805 2806 return pos - buf; 2807 } 2808 2809 2810 static int wpa_supplicant_ctrl_iface_get_capability( 2811 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 2812 size_t buflen) 2813 { 2814 struct wpa_driver_capa capa; 2815 int res; 2816 char *strict; 2817 char field[30]; 2818 size_t len; 2819 2820 /* Determine whether or not strict checking was requested */ 2821 len = os_strlcpy(field, _field, sizeof(field)); 2822 if (len >= sizeof(field)) 2823 return -1; 2824 strict = os_strchr(field, ' '); 2825 if (strict != NULL) { 2826 *strict++ = '\0'; 2827 if (os_strcmp(strict, "strict") != 0) 2828 return -1; 2829 } 2830 2831 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 2832 field, strict ? strict : ""); 2833 2834 if (os_strcmp(field, "eap") == 0) { 2835 return eap_get_names(buf, buflen); 2836 } 2837 2838 res = wpa_drv_get_capa(wpa_s, &capa); 2839 2840 if (os_strcmp(field, "pairwise") == 0) 2841 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 2842 buf, buflen); 2843 2844 if (os_strcmp(field, "group") == 0) 2845 return ctrl_iface_get_capability_group(res, strict, &capa, 2846 buf, buflen); 2847 2848 if (os_strcmp(field, "key_mgmt") == 0) 2849 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 2850 buf, buflen); 2851 2852 if (os_strcmp(field, "proto") == 0) 2853 return ctrl_iface_get_capability_proto(res, strict, &capa, 2854 buf, buflen); 2855 2856 if (os_strcmp(field, "auth_alg") == 0) 2857 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 2858 buf, buflen); 2859 2860 if (os_strcmp(field, "channels") == 0) 2861 return ctrl_iface_get_capability_channels(wpa_s, buf, buflen); 2862 2863 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 2864 field); 2865 2866 return -1; 2867 } 2868 2869 2870 #ifdef CONFIG_INTERWORKING 2871 static char * anqp_add_hex(char *pos, char *end, const char *title, 2872 struct wpabuf *data) 2873 { 2874 char *start = pos; 2875 size_t i; 2876 int ret; 2877 const u8 *d; 2878 2879 if (data == NULL) 2880 return start; 2881 2882 ret = os_snprintf(pos, end - pos, "%s=", title); 2883 if (ret < 0 || ret >= end - pos) 2884 return start; 2885 pos += ret; 2886 2887 d = wpabuf_head_u8(data); 2888 for (i = 0; i < wpabuf_len(data); i++) { 2889 ret = os_snprintf(pos, end - pos, "%02x", *d++); 2890 if (ret < 0 || ret >= end - pos) 2891 return start; 2892 pos += ret; 2893 } 2894 2895 ret = os_snprintf(pos, end - pos, "\n"); 2896 if (ret < 0 || ret >= end - pos) 2897 return start; 2898 pos += ret; 2899 2900 return pos; 2901 } 2902 #endif /* CONFIG_INTERWORKING */ 2903 2904 2905 static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, 2906 unsigned long mask, char *buf, size_t buflen) 2907 { 2908 size_t i; 2909 int ret; 2910 char *pos, *end; 2911 const u8 *ie, *ie2; 2912 2913 pos = buf; 2914 end = buf + buflen; 2915 2916 if (mask & WPA_BSS_MASK_ID) { 2917 ret = os_snprintf(pos, end - pos, "id=%u\n", bss->id); 2918 if (ret < 0 || ret >= end - pos) 2919 return 0; 2920 pos += ret; 2921 } 2922 2923 if (mask & WPA_BSS_MASK_BSSID) { 2924 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 2925 MAC2STR(bss->bssid)); 2926 if (ret < 0 || ret >= end - pos) 2927 return 0; 2928 pos += ret; 2929 } 2930 2931 if (mask & WPA_BSS_MASK_FREQ) { 2932 ret = os_snprintf(pos, end - pos, "freq=%d\n", bss->freq); 2933 if (ret < 0 || ret >= end - pos) 2934 return 0; 2935 pos += ret; 2936 } 2937 2938 if (mask & WPA_BSS_MASK_BEACON_INT) { 2939 ret = os_snprintf(pos, end - pos, "beacon_int=%d\n", 2940 bss->beacon_int); 2941 if (ret < 0 || ret >= end - pos) 2942 return 0; 2943 pos += ret; 2944 } 2945 2946 if (mask & WPA_BSS_MASK_CAPABILITIES) { 2947 ret = os_snprintf(pos, end - pos, "capabilities=0x%04x\n", 2948 bss->caps); 2949 if (ret < 0 || ret >= end - pos) 2950 return 0; 2951 pos += ret; 2952 } 2953 2954 if (mask & WPA_BSS_MASK_QUAL) { 2955 ret = os_snprintf(pos, end - pos, "qual=%d\n", bss->qual); 2956 if (ret < 0 || ret >= end - pos) 2957 return 0; 2958 pos += ret; 2959 } 2960 2961 if (mask & WPA_BSS_MASK_NOISE) { 2962 ret = os_snprintf(pos, end - pos, "noise=%d\n", bss->noise); 2963 if (ret < 0 || ret >= end - pos) 2964 return 0; 2965 pos += ret; 2966 } 2967 2968 if (mask & WPA_BSS_MASK_LEVEL) { 2969 ret = os_snprintf(pos, end - pos, "level=%d\n", bss->level); 2970 if (ret < 0 || ret >= end - pos) 2971 return 0; 2972 pos += ret; 2973 } 2974 2975 if (mask & WPA_BSS_MASK_TSF) { 2976 ret = os_snprintf(pos, end - pos, "tsf=%016llu\n", 2977 (unsigned long long) bss->tsf); 2978 if (ret < 0 || ret >= end - pos) 2979 return 0; 2980 pos += ret; 2981 } 2982 2983 if (mask & WPA_BSS_MASK_AGE) { 2984 struct os_time now; 2985 2986 os_get_time(&now); 2987 ret = os_snprintf(pos, end - pos, "age=%d\n", 2988 (int) (now.sec - bss->last_update.sec)); 2989 if (ret < 0 || ret >= end - pos) 2990 return 0; 2991 pos += ret; 2992 } 2993 2994 if (mask & WPA_BSS_MASK_IE) { 2995 ret = os_snprintf(pos, end - pos, "ie="); 2996 if (ret < 0 || ret >= end - pos) 2997 return 0; 2998 pos += ret; 2999 3000 ie = (const u8 *) (bss + 1); 3001 for (i = 0; i < bss->ie_len; i++) { 3002 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 3003 if (ret < 0 || ret >= end - pos) 3004 return 0; 3005 pos += ret; 3006 } 3007 3008 ret = os_snprintf(pos, end - pos, "\n"); 3009 if (ret < 0 || ret >= end - pos) 3010 return 0; 3011 pos += ret; 3012 } 3013 3014 if (mask & WPA_BSS_MASK_FLAGS) { 3015 ret = os_snprintf(pos, end - pos, "flags="); 3016 if (ret < 0 || ret >= end - pos) 3017 return 0; 3018 pos += ret; 3019 3020 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 3021 if (ie) 3022 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 3023 2 + ie[1]); 3024 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3025 if (ie2) 3026 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 3027 2 + ie2[1]); 3028 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 3029 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 3030 ret = os_snprintf(pos, end - pos, "[WEP]"); 3031 if (ret < 0 || ret >= end - pos) 3032 return 0; 3033 pos += ret; 3034 } 3035 if (bss->caps & IEEE80211_CAP_IBSS) { 3036 ret = os_snprintf(pos, end - pos, "[IBSS]"); 3037 if (ret < 0 || ret >= end - pos) 3038 return 0; 3039 pos += ret; 3040 } 3041 if (bss->caps & IEEE80211_CAP_ESS) { 3042 ret = os_snprintf(pos, end - pos, "[ESS]"); 3043 if (ret < 0 || ret >= end - pos) 3044 return 0; 3045 pos += ret; 3046 } 3047 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { 3048 ret = os_snprintf(pos, end - pos, "[P2P]"); 3049 if (ret < 0 || ret >= end - pos) 3050 return 0; 3051 pos += ret; 3052 } 3053 #ifdef CONFIG_HS20 3054 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { 3055 ret = os_snprintf(pos, end - pos, "[HS20]"); 3056 if (ret < 0 || ret >= end - pos) 3057 return -1; 3058 pos += ret; 3059 } 3060 #endif /* CONFIG_HS20 */ 3061 3062 ret = os_snprintf(pos, end - pos, "\n"); 3063 if (ret < 0 || ret >= end - pos) 3064 return 0; 3065 pos += ret; 3066 } 3067 3068 if (mask & WPA_BSS_MASK_SSID) { 3069 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 3070 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 3071 if (ret < 0 || ret >= end - pos) 3072 return 0; 3073 pos += ret; 3074 } 3075 3076 #ifdef CONFIG_WPS 3077 if (mask & WPA_BSS_MASK_WPS_SCAN) { 3078 ie = (const u8 *) (bss + 1); 3079 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 3080 if (ret < 0 || ret >= end - pos) 3081 return 0; 3082 pos += ret; 3083 } 3084 #endif /* CONFIG_WPS */ 3085 3086 #ifdef CONFIG_P2P 3087 if (mask & WPA_BSS_MASK_P2P_SCAN) { 3088 ie = (const u8 *) (bss + 1); 3089 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 3090 if (ret < 0 || ret >= end - pos) 3091 return 0; 3092 pos += ret; 3093 } 3094 #endif /* CONFIG_P2P */ 3095 3096 #ifdef CONFIG_WIFI_DISPLAY 3097 if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { 3098 struct wpabuf *wfd; 3099 ie = (const u8 *) (bss + 1); 3100 wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, 3101 WFD_IE_VENDOR_TYPE); 3102 if (wfd) { 3103 ret = os_snprintf(pos, end - pos, "wfd_subelems="); 3104 if (ret < 0 || ret >= end - pos) 3105 return pos - buf; 3106 pos += ret; 3107 3108 pos += wpa_snprintf_hex(pos, end - pos, 3109 wpabuf_head(wfd), 3110 wpabuf_len(wfd)); 3111 wpabuf_free(wfd); 3112 3113 ret = os_snprintf(pos, end - pos, "\n"); 3114 if (ret < 0 || ret >= end - pos) 3115 return pos - buf; 3116 pos += ret; 3117 } 3118 } 3119 #endif /* CONFIG_WIFI_DISPLAY */ 3120 3121 #ifdef CONFIG_INTERWORKING 3122 if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) { 3123 struct wpa_bss_anqp *anqp = bss->anqp; 3124 pos = anqp_add_hex(pos, end, "anqp_venue_name", 3125 anqp->venue_name); 3126 pos = anqp_add_hex(pos, end, "anqp_network_auth_type", 3127 anqp->network_auth_type); 3128 pos = anqp_add_hex(pos, end, "anqp_roaming_consortium", 3129 anqp->roaming_consortium); 3130 pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability", 3131 anqp->ip_addr_type_availability); 3132 pos = anqp_add_hex(pos, end, "anqp_nai_realm", 3133 anqp->nai_realm); 3134 pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); 3135 pos = anqp_add_hex(pos, end, "anqp_domain_name", 3136 anqp->domain_name); 3137 #ifdef CONFIG_HS20 3138 pos = anqp_add_hex(pos, end, "hs20_operator_friendly_name", 3139 anqp->hs20_operator_friendly_name); 3140 pos = anqp_add_hex(pos, end, "hs20_wan_metrics", 3141 anqp->hs20_wan_metrics); 3142 pos = anqp_add_hex(pos, end, "hs20_connection_capability", 3143 anqp->hs20_connection_capability); 3144 #endif /* CONFIG_HS20 */ 3145 } 3146 #endif /* CONFIG_INTERWORKING */ 3147 3148 return pos - buf; 3149 } 3150 3151 3152 static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 3153 const char *cmd, char *buf, 3154 size_t buflen) 3155 { 3156 u8 bssid[ETH_ALEN]; 3157 size_t i; 3158 struct wpa_bss *bss; 3159 struct wpa_bss *bsslast = NULL; 3160 struct dl_list *next; 3161 int ret = 0; 3162 int len; 3163 char *ctmp; 3164 unsigned long mask = WPA_BSS_MASK_ALL; 3165 3166 if (os_strncmp(cmd, "RANGE=", 6) == 0) { 3167 if (os_strncmp(cmd + 6, "ALL", 3) == 0) { 3168 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, 3169 list_id); 3170 bsslast = dl_list_last(&wpa_s->bss_id, struct wpa_bss, 3171 list_id); 3172 } else { /* N1-N2 */ 3173 unsigned int id1, id2; 3174 3175 if ((ctmp = os_strchr(cmd + 6, '-')) == NULL) { 3176 wpa_printf(MSG_INFO, "Wrong BSS range " 3177 "format"); 3178 return 0; 3179 } 3180 3181 id1 = atoi(cmd + 6); 3182 bss = wpa_bss_get_id(wpa_s, id1); 3183 id2 = atoi(ctmp + 1); 3184 if (id2 == 0) 3185 bsslast = dl_list_last(&wpa_s->bss_id, 3186 struct wpa_bss, 3187 list_id); 3188 else { 3189 bsslast = wpa_bss_get_id(wpa_s, id2); 3190 if (bsslast == NULL && bss && id2 > id1) { 3191 struct wpa_bss *tmp = bss; 3192 for (;;) { 3193 next = tmp->list_id.next; 3194 if (next == &wpa_s->bss_id) 3195 break; 3196 tmp = dl_list_entry( 3197 next, struct wpa_bss, 3198 list_id); 3199 if (tmp->id > id2) 3200 break; 3201 bsslast = tmp; 3202 } 3203 } 3204 } 3205 } 3206 } else if (os_strcmp(cmd, "FIRST") == 0) 3207 bss = dl_list_first(&wpa_s->bss_id, struct wpa_bss, list_id); 3208 else if (os_strncmp(cmd, "ID-", 3) == 0) { 3209 i = atoi(cmd + 3); 3210 bss = wpa_bss_get_id(wpa_s, i); 3211 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 3212 i = atoi(cmd + 5); 3213 bss = wpa_bss_get_id(wpa_s, i); 3214 if (bss) { 3215 next = bss->list_id.next; 3216 if (next == &wpa_s->bss_id) 3217 bss = NULL; 3218 else 3219 bss = dl_list_entry(next, struct wpa_bss, 3220 list_id); 3221 } 3222 #ifdef CONFIG_P2P 3223 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 3224 if (hwaddr_aton(cmd + 13, bssid) == 0) 3225 bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); 3226 else 3227 bss = NULL; 3228 #endif /* CONFIG_P2P */ 3229 } else if (hwaddr_aton(cmd, bssid) == 0) 3230 bss = wpa_bss_get_bssid(wpa_s, bssid); 3231 else { 3232 struct wpa_bss *tmp; 3233 i = atoi(cmd); 3234 bss = NULL; 3235 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 3236 { 3237 if (i-- == 0) { 3238 bss = tmp; 3239 break; 3240 } 3241 } 3242 } 3243 3244 if ((ctmp = os_strstr(cmd, "MASK=")) != NULL) { 3245 mask = strtoul(ctmp + 5, NULL, 0x10); 3246 if (mask == 0) 3247 mask = WPA_BSS_MASK_ALL; 3248 } 3249 3250 if (bss == NULL) 3251 return 0; 3252 3253 if (bsslast == NULL) 3254 bsslast = bss; 3255 do { 3256 len = print_bss_info(wpa_s, bss, mask, buf, buflen); 3257 ret += len; 3258 buf += len; 3259 buflen -= len; 3260 if (bss == bsslast) 3261 break; 3262 next = bss->list_id.next; 3263 if (next == &wpa_s->bss_id) 3264 break; 3265 bss = dl_list_entry(next, struct wpa_bss, list_id); 3266 } while (bss && len); 3267 3268 return ret; 3269 } 3270 3271 3272 static int wpa_supplicant_ctrl_iface_ap_scan( 3273 struct wpa_supplicant *wpa_s, char *cmd) 3274 { 3275 int ap_scan = atoi(cmd); 3276 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 3277 } 3278 3279 3280 static int wpa_supplicant_ctrl_iface_scan_interval( 3281 struct wpa_supplicant *wpa_s, char *cmd) 3282 { 3283 int scan_int = atoi(cmd); 3284 return wpa_supplicant_set_scan_interval(wpa_s, scan_int); 3285 } 3286 3287 3288 static int wpa_supplicant_ctrl_iface_bss_expire_age( 3289 struct wpa_supplicant *wpa_s, char *cmd) 3290 { 3291 int expire_age = atoi(cmd); 3292 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 3293 } 3294 3295 3296 static int wpa_supplicant_ctrl_iface_bss_expire_count( 3297 struct wpa_supplicant *wpa_s, char *cmd) 3298 { 3299 int expire_count = atoi(cmd); 3300 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 3301 } 3302 3303 3304 static int wpa_supplicant_ctrl_iface_bss_flush( 3305 struct wpa_supplicant *wpa_s, char *cmd) 3306 { 3307 int flush_age = atoi(cmd); 3308 3309 if (flush_age == 0) 3310 wpa_bss_flush(wpa_s); 3311 else 3312 wpa_bss_flush_by_age(wpa_s, flush_age); 3313 return 0; 3314 } 3315 3316 3317 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 3318 { 3319 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 3320 /* MLME-DELETEKEYS.request */ 3321 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 3322 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 3323 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 3324 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 3325 #ifdef CONFIG_IEEE80211W 3326 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 3327 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 3328 #endif /* CONFIG_IEEE80211W */ 3329 3330 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 3331 0); 3332 /* MLME-SETPROTECTION.request(None) */ 3333 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 3334 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 3335 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 3336 wpa_sm_drop_sa(wpa_s->wpa); 3337 } 3338 3339 3340 static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 3341 char *addr) 3342 { 3343 #ifdef CONFIG_NO_SCAN_PROCESSING 3344 return -1; 3345 #else /* CONFIG_NO_SCAN_PROCESSING */ 3346 u8 bssid[ETH_ALEN]; 3347 struct wpa_bss *bss; 3348 struct wpa_ssid *ssid = wpa_s->current_ssid; 3349 3350 if (hwaddr_aton(addr, bssid)) { 3351 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 3352 "address '%s'", addr); 3353 return -1; 3354 } 3355 3356 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 3357 3358 bss = wpa_bss_get_bssid(wpa_s, bssid); 3359 if (!bss) { 3360 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 3361 "from BSS table"); 3362 return -1; 3363 } 3364 3365 /* 3366 * TODO: Find best network configuration block from configuration to 3367 * allow roaming to other networks 3368 */ 3369 3370 if (!ssid) { 3371 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 3372 "configuration known for the target AP"); 3373 return -1; 3374 } 3375 3376 wpa_s->reassociate = 1; 3377 wpa_supplicant_connect(wpa_s, bss, ssid); 3378 3379 return 0; 3380 #endif /* CONFIG_NO_SCAN_PROCESSING */ 3381 } 3382 3383 3384 #ifdef CONFIG_P2P 3385 static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 3386 { 3387 unsigned int timeout = atoi(cmd); 3388 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 3389 u8 dev_id[ETH_ALEN], *_dev_id = NULL; 3390 char *pos; 3391 unsigned int search_delay; 3392 3393 if (os_strstr(cmd, "type=social")) 3394 type = P2P_FIND_ONLY_SOCIAL; 3395 else if (os_strstr(cmd, "type=progressive")) 3396 type = P2P_FIND_PROGRESSIVE; 3397 3398 pos = os_strstr(cmd, "dev_id="); 3399 if (pos) { 3400 pos += 7; 3401 if (hwaddr_aton(pos, dev_id)) 3402 return -1; 3403 _dev_id = dev_id; 3404 } 3405 3406 pos = os_strstr(cmd, "delay="); 3407 if (pos) { 3408 pos += 6; 3409 search_delay = atoi(pos); 3410 } else 3411 search_delay = wpas_p2p_search_delay(wpa_s); 3412 3413 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id, 3414 search_delay); 3415 } 3416 3417 3418 static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 3419 char *buf, size_t buflen) 3420 { 3421 u8 addr[ETH_ALEN]; 3422 char *pos, *pos2; 3423 char *pin = NULL; 3424 enum p2p_wps_method wps_method; 3425 int new_pin; 3426 int ret; 3427 int persistent_group, persistent_id = -1; 3428 int join; 3429 int auth; 3430 int automatic; 3431 int go_intent = -1; 3432 int freq = 0; 3433 int pd; 3434 int ht40; 3435 3436 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] 3437 * [persistent|persistent=<network id>] 3438 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] 3439 * [ht40] */ 3440 3441 if (hwaddr_aton(cmd, addr)) 3442 return -1; 3443 3444 pos = cmd + 17; 3445 if (*pos != ' ') 3446 return -1; 3447 pos++; 3448 3449 persistent_group = os_strstr(pos, " persistent") != NULL; 3450 pos2 = os_strstr(pos, " persistent="); 3451 if (pos2) { 3452 struct wpa_ssid *ssid; 3453 persistent_id = atoi(pos2 + 12); 3454 ssid = wpa_config_get_network(wpa_s->conf, persistent_id); 3455 if (ssid == NULL || ssid->disabled != 2 || 3456 ssid->mode != WPAS_MODE_P2P_GO) { 3457 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 3458 "SSID id=%d for persistent P2P group (GO)", 3459 persistent_id); 3460 return -1; 3461 } 3462 } 3463 join = os_strstr(pos, " join") != NULL; 3464 auth = os_strstr(pos, " auth") != NULL; 3465 automatic = os_strstr(pos, " auto") != NULL; 3466 pd = os_strstr(pos, " provdisc") != NULL; 3467 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3468 3469 pos2 = os_strstr(pos, " go_intent="); 3470 if (pos2) { 3471 pos2 += 11; 3472 go_intent = atoi(pos2); 3473 if (go_intent < 0 || go_intent > 15) 3474 return -1; 3475 } 3476 3477 pos2 = os_strstr(pos, " freq="); 3478 if (pos2) { 3479 pos2 += 6; 3480 freq = atoi(pos2); 3481 if (freq <= 0) 3482 return -1; 3483 } 3484 3485 if (os_strncmp(pos, "pin", 3) == 0) { 3486 /* Request random PIN (to be displayed) and enable the PIN */ 3487 wps_method = WPS_PIN_DISPLAY; 3488 } else if (os_strncmp(pos, "pbc", 3) == 0) { 3489 wps_method = WPS_PBC; 3490 } else { 3491 pin = pos; 3492 pos = os_strchr(pin, ' '); 3493 wps_method = WPS_PIN_KEYPAD; 3494 if (pos) { 3495 *pos++ = '\0'; 3496 if (os_strncmp(pos, "display", 7) == 0) 3497 wps_method = WPS_PIN_DISPLAY; 3498 } 3499 if (!wps_pin_str_valid(pin)) { 3500 os_memcpy(buf, "FAIL-INVALID-PIN\n", 17); 3501 return 17; 3502 } 3503 } 3504 3505 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 3506 persistent_group, automatic, join, 3507 auth, go_intent, freq, persistent_id, pd, 3508 ht40); 3509 if (new_pin == -2) { 3510 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 3511 return 25; 3512 } 3513 if (new_pin == -3) { 3514 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 3515 return 25; 3516 } 3517 if (new_pin < 0) 3518 return -1; 3519 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 3520 ret = os_snprintf(buf, buflen, "%08d", new_pin); 3521 if (ret < 0 || (size_t) ret >= buflen) 3522 return -1; 3523 return ret; 3524 } 3525 3526 os_memcpy(buf, "OK\n", 3); 3527 return 3; 3528 } 3529 3530 3531 static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 3532 { 3533 unsigned int timeout = atoi(cmd); 3534 return wpas_p2p_listen(wpa_s, timeout); 3535 } 3536 3537 3538 static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 3539 { 3540 u8 addr[ETH_ALEN]; 3541 char *pos; 3542 enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG; 3543 3544 /* <addr> <config method> [join|auto] */ 3545 3546 if (hwaddr_aton(cmd, addr)) 3547 return -1; 3548 3549 pos = cmd + 17; 3550 if (*pos != ' ') 3551 return -1; 3552 pos++; 3553 3554 if (os_strstr(pos, " join") != NULL) 3555 use = WPAS_P2P_PD_FOR_JOIN; 3556 else if (os_strstr(pos, " auto") != NULL) 3557 use = WPAS_P2P_PD_AUTO; 3558 3559 return wpas_p2p_prov_disc(wpa_s, addr, pos, use); 3560 } 3561 3562 3563 static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 3564 size_t buflen) 3565 { 3566 struct wpa_ssid *ssid = wpa_s->current_ssid; 3567 3568 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 3569 ssid->passphrase == NULL) 3570 return -1; 3571 3572 os_strlcpy(buf, ssid->passphrase, buflen); 3573 return os_strlen(buf); 3574 } 3575 3576 3577 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 3578 char *buf, size_t buflen) 3579 { 3580 u64 ref; 3581 int res; 3582 u8 dst_buf[ETH_ALEN], *dst; 3583 struct wpabuf *tlvs; 3584 char *pos; 3585 size_t len; 3586 3587 if (hwaddr_aton(cmd, dst_buf)) 3588 return -1; 3589 dst = dst_buf; 3590 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 3591 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 3592 dst = NULL; 3593 pos = cmd + 17; 3594 if (*pos != ' ') 3595 return -1; 3596 pos++; 3597 3598 if (os_strncmp(pos, "upnp ", 5) == 0) { 3599 u8 version; 3600 pos += 5; 3601 if (hexstr2bin(pos, &version, 1) < 0) 3602 return -1; 3603 pos += 2; 3604 if (*pos != ' ') 3605 return -1; 3606 pos++; 3607 ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos); 3608 #ifdef CONFIG_WIFI_DISPLAY 3609 } else if (os_strncmp(pos, "wifi-display ", 13) == 0) { 3610 ref = wpas_p2p_sd_request_wifi_display(wpa_s, dst, pos + 13); 3611 #endif /* CONFIG_WIFI_DISPLAY */ 3612 } else { 3613 len = os_strlen(pos); 3614 if (len & 1) 3615 return -1; 3616 len /= 2; 3617 tlvs = wpabuf_alloc(len); 3618 if (tlvs == NULL) 3619 return -1; 3620 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 3621 wpabuf_free(tlvs); 3622 return -1; 3623 } 3624 3625 ref = wpas_p2p_sd_request(wpa_s, dst, tlvs); 3626 wpabuf_free(tlvs); 3627 } 3628 if (ref == 0) 3629 return -1; 3630 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 3631 if (res < 0 || (unsigned) res >= buflen) 3632 return -1; 3633 return res; 3634 } 3635 3636 3637 static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 3638 char *cmd) 3639 { 3640 long long unsigned val; 3641 u64 req; 3642 if (sscanf(cmd, "%llx", &val) != 1) 3643 return -1; 3644 req = val; 3645 return wpas_p2p_sd_cancel_request(wpa_s, req); 3646 } 3647 3648 3649 static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 3650 { 3651 int freq; 3652 u8 dst[ETH_ALEN]; 3653 u8 dialog_token; 3654 struct wpabuf *resp_tlvs; 3655 char *pos, *pos2; 3656 size_t len; 3657 3658 pos = os_strchr(cmd, ' '); 3659 if (pos == NULL) 3660 return -1; 3661 *pos++ = '\0'; 3662 freq = atoi(cmd); 3663 if (freq == 0) 3664 return -1; 3665 3666 if (hwaddr_aton(pos, dst)) 3667 return -1; 3668 pos += 17; 3669 if (*pos != ' ') 3670 return -1; 3671 pos++; 3672 3673 pos2 = os_strchr(pos, ' '); 3674 if (pos2 == NULL) 3675 return -1; 3676 *pos2++ = '\0'; 3677 dialog_token = atoi(pos); 3678 3679 len = os_strlen(pos2); 3680 if (len & 1) 3681 return -1; 3682 len /= 2; 3683 resp_tlvs = wpabuf_alloc(len); 3684 if (resp_tlvs == NULL) 3685 return -1; 3686 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 3687 wpabuf_free(resp_tlvs); 3688 return -1; 3689 } 3690 3691 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 3692 wpabuf_free(resp_tlvs); 3693 return 0; 3694 } 3695 3696 3697 static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 3698 char *cmd) 3699 { 3700 if (os_strcmp(cmd, "0") && os_strcmp(cmd, "1")) 3701 return -1; 3702 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 3703 return 0; 3704 } 3705 3706 3707 static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 3708 char *cmd) 3709 { 3710 char *pos; 3711 size_t len; 3712 struct wpabuf *query, *resp; 3713 3714 pos = os_strchr(cmd, ' '); 3715 if (pos == NULL) 3716 return -1; 3717 *pos++ = '\0'; 3718 3719 len = os_strlen(cmd); 3720 if (len & 1) 3721 return -1; 3722 len /= 2; 3723 query = wpabuf_alloc(len); 3724 if (query == NULL) 3725 return -1; 3726 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3727 wpabuf_free(query); 3728 return -1; 3729 } 3730 3731 len = os_strlen(pos); 3732 if (len & 1) { 3733 wpabuf_free(query); 3734 return -1; 3735 } 3736 len /= 2; 3737 resp = wpabuf_alloc(len); 3738 if (resp == NULL) { 3739 wpabuf_free(query); 3740 return -1; 3741 } 3742 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 3743 wpabuf_free(query); 3744 wpabuf_free(resp); 3745 return -1; 3746 } 3747 3748 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 3749 wpabuf_free(query); 3750 wpabuf_free(resp); 3751 return -1; 3752 } 3753 return 0; 3754 } 3755 3756 3757 static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3758 { 3759 char *pos; 3760 u8 version; 3761 3762 pos = os_strchr(cmd, ' '); 3763 if (pos == NULL) 3764 return -1; 3765 *pos++ = '\0'; 3766 3767 if (hexstr2bin(cmd, &version, 1) < 0) 3768 return -1; 3769 3770 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 3771 } 3772 3773 3774 static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 3775 { 3776 char *pos; 3777 3778 pos = os_strchr(cmd, ' '); 3779 if (pos == NULL) 3780 return -1; 3781 *pos++ = '\0'; 3782 3783 if (os_strcmp(cmd, "bonjour") == 0) 3784 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 3785 if (os_strcmp(cmd, "upnp") == 0) 3786 return p2p_ctrl_service_add_upnp(wpa_s, pos); 3787 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3788 return -1; 3789 } 3790 3791 3792 static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 3793 char *cmd) 3794 { 3795 size_t len; 3796 struct wpabuf *query; 3797 int ret; 3798 3799 len = os_strlen(cmd); 3800 if (len & 1) 3801 return -1; 3802 len /= 2; 3803 query = wpabuf_alloc(len); 3804 if (query == NULL) 3805 return -1; 3806 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 3807 wpabuf_free(query); 3808 return -1; 3809 } 3810 3811 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 3812 wpabuf_free(query); 3813 return ret; 3814 } 3815 3816 3817 static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 3818 { 3819 char *pos; 3820 u8 version; 3821 3822 pos = os_strchr(cmd, ' '); 3823 if (pos == NULL) 3824 return -1; 3825 *pos++ = '\0'; 3826 3827 if (hexstr2bin(cmd, &version, 1) < 0) 3828 return -1; 3829 3830 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 3831 } 3832 3833 3834 static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 3835 { 3836 char *pos; 3837 3838 pos = os_strchr(cmd, ' '); 3839 if (pos == NULL) 3840 return -1; 3841 *pos++ = '\0'; 3842 3843 if (os_strcmp(cmd, "bonjour") == 0) 3844 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 3845 if (os_strcmp(cmd, "upnp") == 0) 3846 return p2p_ctrl_service_del_upnp(wpa_s, pos); 3847 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 3848 return -1; 3849 } 3850 3851 3852 static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 3853 { 3854 u8 addr[ETH_ALEN]; 3855 3856 /* <addr> */ 3857 3858 if (hwaddr_aton(cmd, addr)) 3859 return -1; 3860 3861 return wpas_p2p_reject(wpa_s, addr); 3862 } 3863 3864 3865 static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 3866 { 3867 char *pos; 3868 int id; 3869 struct wpa_ssid *ssid; 3870 u8 *_peer = NULL, peer[ETH_ALEN]; 3871 int freq = 0; 3872 int ht40; 3873 3874 id = atoi(cmd); 3875 pos = os_strstr(cmd, " peer="); 3876 if (pos) { 3877 pos += 6; 3878 if (hwaddr_aton(pos, peer)) 3879 return -1; 3880 _peer = peer; 3881 } 3882 ssid = wpa_config_get_network(wpa_s->conf, id); 3883 if (ssid == NULL || ssid->disabled != 2) { 3884 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3885 "for persistent P2P group", 3886 id); 3887 return -1; 3888 } 3889 3890 pos = os_strstr(cmd, " freq="); 3891 if (pos) { 3892 pos += 6; 3893 freq = atoi(pos); 3894 if (freq <= 0) 3895 return -1; 3896 } 3897 3898 ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3899 3900 return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40); 3901 } 3902 3903 3904 static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 3905 { 3906 char *pos; 3907 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 3908 3909 pos = os_strstr(cmd, " peer="); 3910 if (!pos) 3911 return -1; 3912 3913 *pos = '\0'; 3914 pos += 6; 3915 if (hwaddr_aton(pos, peer)) { 3916 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 3917 return -1; 3918 } 3919 3920 pos = os_strstr(pos, " go_dev_addr="); 3921 if (pos) { 3922 pos += 13; 3923 if (hwaddr_aton(pos, go_dev_addr)) { 3924 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 3925 pos); 3926 return -1; 3927 } 3928 go_dev = go_dev_addr; 3929 } 3930 3931 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 3932 } 3933 3934 3935 static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 3936 { 3937 if (os_strncmp(cmd, "persistent=", 11) == 0) 3938 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 3939 if (os_strncmp(cmd, "group=", 6) == 0) 3940 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 3941 3942 return -1; 3943 } 3944 3945 3946 static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 3947 char *cmd, int freq, int ht40) 3948 { 3949 int id; 3950 struct wpa_ssid *ssid; 3951 3952 id = atoi(cmd); 3953 ssid = wpa_config_get_network(wpa_s->conf, id); 3954 if (ssid == NULL || ssid->disabled != 2) { 3955 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 3956 "for persistent P2P group", 3957 id); 3958 return -1; 3959 } 3960 3961 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, ht40); 3962 } 3963 3964 3965 static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 3966 { 3967 int freq = 0, ht40; 3968 char *pos; 3969 3970 pos = os_strstr(cmd, "freq="); 3971 if (pos) 3972 freq = atoi(pos + 5); 3973 3974 ht40 = (os_strstr(cmd, "ht40") != NULL) || wpa_s->conf->p2p_go_ht40; 3975 3976 if (os_strncmp(cmd, "persistent=", 11) == 0) 3977 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq, 3978 ht40); 3979 if (os_strcmp(cmd, "persistent") == 0 || 3980 os_strncmp(cmd, "persistent ", 11) == 0) 3981 return wpas_p2p_group_add(wpa_s, 1, freq, ht40); 3982 if (os_strncmp(cmd, "freq=", 5) == 0) 3983 return wpas_p2p_group_add(wpa_s, 0, freq, ht40); 3984 if (ht40) 3985 return wpas_p2p_group_add(wpa_s, 0, freq, ht40); 3986 3987 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'", 3988 cmd); 3989 return -1; 3990 } 3991 3992 3993 static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 3994 char *buf, size_t buflen) 3995 { 3996 u8 addr[ETH_ALEN], *addr_ptr; 3997 int next, res; 3998 const struct p2p_peer_info *info; 3999 char *pos, *end; 4000 char devtype[WPS_DEV_TYPE_BUFSIZE]; 4001 struct wpa_ssid *ssid; 4002 size_t i; 4003 4004 if (!wpa_s->global->p2p) 4005 return -1; 4006 4007 if (os_strcmp(cmd, "FIRST") == 0) { 4008 addr_ptr = NULL; 4009 next = 0; 4010 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 4011 if (hwaddr_aton(cmd + 5, addr) < 0) 4012 return -1; 4013 addr_ptr = addr; 4014 next = 1; 4015 } else { 4016 if (hwaddr_aton(cmd, addr) < 0) 4017 return -1; 4018 addr_ptr = addr; 4019 next = 0; 4020 } 4021 4022 info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); 4023 if (info == NULL) 4024 return -1; 4025 4026 pos = buf; 4027 end = buf + buflen; 4028 4029 res = os_snprintf(pos, end - pos, MACSTR "\n" 4030 "pri_dev_type=%s\n" 4031 "device_name=%s\n" 4032 "manufacturer=%s\n" 4033 "model_name=%s\n" 4034 "model_number=%s\n" 4035 "serial_number=%s\n" 4036 "config_methods=0x%x\n" 4037 "dev_capab=0x%x\n" 4038 "group_capab=0x%x\n" 4039 "level=%d\n", 4040 MAC2STR(info->p2p_device_addr), 4041 wps_dev_type_bin2str(info->pri_dev_type, 4042 devtype, sizeof(devtype)), 4043 info->device_name, 4044 info->manufacturer, 4045 info->model_name, 4046 info->model_number, 4047 info->serial_number, 4048 info->config_methods, 4049 info->dev_capab, 4050 info->group_capab, 4051 info->level); 4052 if (res < 0 || res >= end - pos) 4053 return pos - buf; 4054 pos += res; 4055 4056 for (i = 0; i < info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN; i++) 4057 { 4058 const u8 *t; 4059 t = &info->wps_sec_dev_type_list[i * WPS_DEV_TYPE_LEN]; 4060 res = os_snprintf(pos, end - pos, "sec_dev_type=%s\n", 4061 wps_dev_type_bin2str(t, devtype, 4062 sizeof(devtype))); 4063 if (res < 0 || res >= end - pos) 4064 return pos - buf; 4065 pos += res; 4066 } 4067 4068 ssid = wpas_p2p_get_persistent(wpa_s, info->p2p_device_addr, NULL, 0); 4069 if (ssid) { 4070 res = os_snprintf(pos, end - pos, "persistent=%d\n", ssid->id); 4071 if (res < 0 || res >= end - pos) 4072 return pos - buf; 4073 pos += res; 4074 } 4075 4076 res = p2p_get_peer_info_txt(info, pos, end - pos); 4077 if (res < 0) 4078 return pos - buf; 4079 pos += res; 4080 4081 return pos - buf; 4082 } 4083 4084 4085 static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, 4086 const char *param) 4087 { 4088 struct wpa_freq_range *freq = NULL, *n; 4089 unsigned int count = 0, i; 4090 const char *pos, *pos2, *pos3; 4091 4092 if (wpa_s->global->p2p == NULL) 4093 return -1; 4094 4095 /* 4096 * param includes comma separated frequency range. 4097 * For example: 2412-2432,2462,5000-6000 4098 */ 4099 pos = param; 4100 while (pos && pos[0]) { 4101 n = os_realloc_array(freq, count + 1, 4102 sizeof(struct wpa_freq_range)); 4103 if (n == NULL) { 4104 os_free(freq); 4105 return -1; 4106 } 4107 freq = n; 4108 freq[count].min = atoi(pos); 4109 pos2 = os_strchr(pos, '-'); 4110 pos3 = os_strchr(pos, ','); 4111 if (pos2 && (!pos3 || pos2 < pos3)) { 4112 pos2++; 4113 freq[count].max = atoi(pos2); 4114 } else 4115 freq[count].max = freq[count].min; 4116 pos = pos3; 4117 if (pos) 4118 pos++; 4119 count++; 4120 } 4121 4122 for (i = 0; i < count; i++) { 4123 wpa_printf(MSG_DEBUG, "P2P: Disallowed frequency range %u-%u", 4124 freq[i].min, freq[i].max); 4125 } 4126 4127 os_free(wpa_s->global->p2p_disallow_freq); 4128 wpa_s->global->p2p_disallow_freq = freq; 4129 wpa_s->global->num_p2p_disallow_freq = count; 4130 wpas_p2p_update_channel_list(wpa_s); 4131 return 0; 4132 } 4133 4134 4135 static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 4136 { 4137 char *param; 4138 4139 if (wpa_s->global->p2p == NULL) 4140 return -1; 4141 4142 param = os_strchr(cmd, ' '); 4143 if (param == NULL) 4144 return -1; 4145 *param++ = '\0'; 4146 4147 if (os_strcmp(cmd, "discoverability") == 0) { 4148 p2p_set_client_discoverability(wpa_s->global->p2p, 4149 atoi(param)); 4150 return 0; 4151 } 4152 4153 if (os_strcmp(cmd, "managed") == 0) { 4154 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 4155 return 0; 4156 } 4157 4158 if (os_strcmp(cmd, "listen_channel") == 0) { 4159 return p2p_set_listen_channel(wpa_s->global->p2p, 81, 4160 atoi(param)); 4161 } 4162 4163 if (os_strcmp(cmd, "ssid_postfix") == 0) { 4164 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 4165 os_strlen(param)); 4166 } 4167 4168 if (os_strcmp(cmd, "noa") == 0) { 4169 char *pos; 4170 int count, start, duration; 4171 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 4172 count = atoi(param); 4173 pos = os_strchr(param, ','); 4174 if (pos == NULL) 4175 return -1; 4176 pos++; 4177 start = atoi(pos); 4178 pos = os_strchr(pos, ','); 4179 if (pos == NULL) 4180 return -1; 4181 pos++; 4182 duration = atoi(pos); 4183 if (count < 0 || count > 255 || start < 0 || duration < 0) 4184 return -1; 4185 if (count == 0 && duration > 0) 4186 return -1; 4187 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 4188 "start=%d duration=%d", count, start, duration); 4189 return wpas_p2p_set_noa(wpa_s, count, start, duration); 4190 } 4191 4192 if (os_strcmp(cmd, "ps") == 0) 4193 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 4194 4195 if (os_strcmp(cmd, "oppps") == 0) 4196 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 4197 4198 if (os_strcmp(cmd, "ctwindow") == 0) 4199 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 4200 4201 if (os_strcmp(cmd, "disabled") == 0) { 4202 wpa_s->global->p2p_disabled = atoi(param); 4203 wpa_printf(MSG_DEBUG, "P2P functionality %s", 4204 wpa_s->global->p2p_disabled ? 4205 "disabled" : "enabled"); 4206 if (wpa_s->global->p2p_disabled) { 4207 wpas_p2p_stop_find(wpa_s); 4208 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 4209 p2p_flush(wpa_s->global->p2p); 4210 } 4211 return 0; 4212 } 4213 4214 if (os_strcmp(cmd, "conc_pref") == 0) { 4215 if (os_strcmp(param, "sta") == 0) 4216 wpa_s->global->conc_pref = WPA_CONC_PREF_STA; 4217 else if (os_strcmp(param, "p2p") == 0) 4218 wpa_s->global->conc_pref = WPA_CONC_PREF_P2P; 4219 else { 4220 wpa_printf(MSG_INFO, "Invalid conc_pref value"); 4221 return -1; 4222 } 4223 wpa_printf(MSG_DEBUG, "Single channel concurrency preference: " 4224 "%s", param); 4225 return 0; 4226 } 4227 4228 if (os_strcmp(cmd, "force_long_sd") == 0) { 4229 wpa_s->force_long_sd = atoi(param); 4230 return 0; 4231 } 4232 4233 if (os_strcmp(cmd, "peer_filter") == 0) { 4234 u8 addr[ETH_ALEN]; 4235 if (hwaddr_aton(param, addr)) 4236 return -1; 4237 p2p_set_peer_filter(wpa_s->global->p2p, addr); 4238 return 0; 4239 } 4240 4241 if (os_strcmp(cmd, "cross_connect") == 0) 4242 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 4243 4244 if (os_strcmp(cmd, "go_apsd") == 0) { 4245 if (os_strcmp(param, "disable") == 0) 4246 wpa_s->set_ap_uapsd = 0; 4247 else { 4248 wpa_s->set_ap_uapsd = 1; 4249 wpa_s->ap_uapsd = atoi(param); 4250 } 4251 return 0; 4252 } 4253 4254 if (os_strcmp(cmd, "client_apsd") == 0) { 4255 if (os_strcmp(param, "disable") == 0) 4256 wpa_s->set_sta_uapsd = 0; 4257 else { 4258 int be, bk, vi, vo; 4259 char *pos; 4260 /* format: BE,BK,VI,VO;max SP Length */ 4261 be = atoi(param); 4262 pos = os_strchr(param, ','); 4263 if (pos == NULL) 4264 return -1; 4265 pos++; 4266 bk = atoi(pos); 4267 pos = os_strchr(pos, ','); 4268 if (pos == NULL) 4269 return -1; 4270 pos++; 4271 vi = atoi(pos); 4272 pos = os_strchr(pos, ','); 4273 if (pos == NULL) 4274 return -1; 4275 pos++; 4276 vo = atoi(pos); 4277 /* ignore max SP Length for now */ 4278 4279 wpa_s->set_sta_uapsd = 1; 4280 wpa_s->sta_uapsd = 0; 4281 if (be) 4282 wpa_s->sta_uapsd |= BIT(0); 4283 if (bk) 4284 wpa_s->sta_uapsd |= BIT(1); 4285 if (vi) 4286 wpa_s->sta_uapsd |= BIT(2); 4287 if (vo) 4288 wpa_s->sta_uapsd |= BIT(3); 4289 } 4290 return 0; 4291 } 4292 4293 if (os_strcmp(cmd, "disallow_freq") == 0) 4294 return p2p_ctrl_disallow_freq(wpa_s, param); 4295 4296 if (os_strcmp(cmd, "disc_int") == 0) { 4297 int min_disc_int, max_disc_int, max_disc_tu; 4298 char *pos; 4299 4300 pos = param; 4301 4302 min_disc_int = atoi(pos); 4303 pos = os_strchr(pos, ' '); 4304 if (pos == NULL) 4305 return -1; 4306 *pos++ = '\0'; 4307 4308 max_disc_int = atoi(pos); 4309 pos = os_strchr(pos, ' '); 4310 if (pos == NULL) 4311 return -1; 4312 *pos++ = '\0'; 4313 4314 max_disc_tu = atoi(pos); 4315 4316 return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int, 4317 max_disc_int, max_disc_tu); 4318 } 4319 4320 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 4321 cmd); 4322 4323 return -1; 4324 } 4325 4326 4327 static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 4328 { 4329 char *pos, *pos2; 4330 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 4331 4332 if (cmd[0]) { 4333 pos = os_strchr(cmd, ' '); 4334 if (pos == NULL) 4335 return -1; 4336 *pos++ = '\0'; 4337 dur1 = atoi(cmd); 4338 4339 pos2 = os_strchr(pos, ' '); 4340 if (pos2) 4341 *pos2++ = '\0'; 4342 int1 = atoi(pos); 4343 } else 4344 pos2 = NULL; 4345 4346 if (pos2) { 4347 pos = os_strchr(pos2, ' '); 4348 if (pos == NULL) 4349 return -1; 4350 *pos++ = '\0'; 4351 dur2 = atoi(pos2); 4352 int2 = atoi(pos); 4353 } 4354 4355 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 4356 } 4357 4358 4359 static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 4360 { 4361 char *pos; 4362 unsigned int period = 0, interval = 0; 4363 4364 if (cmd[0]) { 4365 pos = os_strchr(cmd, ' '); 4366 if (pos == NULL) 4367 return -1; 4368 *pos++ = '\0'; 4369 period = atoi(cmd); 4370 interval = atoi(pos); 4371 } 4372 4373 return wpas_p2p_ext_listen(wpa_s, period, interval); 4374 } 4375 4376 #endif /* CONFIG_P2P */ 4377 4378 4379 #ifdef CONFIG_INTERWORKING 4380 static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst) 4381 { 4382 u8 bssid[ETH_ALEN]; 4383 struct wpa_bss *bss; 4384 4385 if (hwaddr_aton(dst, bssid)) { 4386 wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst); 4387 return -1; 4388 } 4389 4390 bss = wpa_bss_get_bssid(wpa_s, bssid); 4391 if (bss == NULL) { 4392 wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, 4393 MAC2STR(bssid)); 4394 return -1; 4395 } 4396 4397 return interworking_connect(wpa_s, bss); 4398 } 4399 4400 4401 static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) 4402 { 4403 u8 dst_addr[ETH_ALEN]; 4404 int used; 4405 char *pos; 4406 #define MAX_ANQP_INFO_ID 100 4407 u16 id[MAX_ANQP_INFO_ID]; 4408 size_t num_id = 0; 4409 4410 used = hwaddr_aton2(dst, dst_addr); 4411 if (used < 0) 4412 return -1; 4413 pos = dst + used; 4414 while (num_id < MAX_ANQP_INFO_ID) { 4415 id[num_id] = atoi(pos); 4416 if (id[num_id]) 4417 num_id++; 4418 pos = os_strchr(pos + 1, ','); 4419 if (pos == NULL) 4420 break; 4421 pos++; 4422 } 4423 4424 if (num_id == 0) 4425 return -1; 4426 4427 return anqp_send_req(wpa_s, dst_addr, id, num_id); 4428 } 4429 4430 4431 static int gas_request(struct wpa_supplicant *wpa_s, char *cmd) 4432 { 4433 u8 dst_addr[ETH_ALEN]; 4434 struct wpabuf *advproto, *query = NULL; 4435 int used, ret = -1; 4436 char *pos, *end; 4437 size_t len; 4438 4439 used = hwaddr_aton2(cmd, dst_addr); 4440 if (used < 0) 4441 return -1; 4442 4443 pos = cmd + used; 4444 while (*pos == ' ') 4445 pos++; 4446 4447 /* Advertisement Protocol ID */ 4448 end = os_strchr(pos, ' '); 4449 if (end) 4450 len = end - pos; 4451 else 4452 len = os_strlen(pos); 4453 if (len & 0x01) 4454 return -1; 4455 len /= 2; 4456 if (len == 0) 4457 return -1; 4458 advproto = wpabuf_alloc(len); 4459 if (advproto == NULL) 4460 return -1; 4461 if (hexstr2bin(pos, wpabuf_put(advproto, len), len) < 0) 4462 goto fail; 4463 4464 if (end) { 4465 /* Optional Query Request */ 4466 pos = end + 1; 4467 while (*pos == ' ') 4468 pos++; 4469 4470 len = os_strlen(pos); 4471 if (len) { 4472 if (len & 0x01) 4473 goto fail; 4474 len /= 2; 4475 if (len == 0) 4476 goto fail; 4477 query = wpabuf_alloc(len); 4478 if (query == NULL) 4479 goto fail; 4480 if (hexstr2bin(pos, wpabuf_put(query, len), len) < 0) 4481 goto fail; 4482 } 4483 } 4484 4485 ret = gas_send_request(wpa_s, dst_addr, advproto, query); 4486 4487 fail: 4488 wpabuf_free(advproto); 4489 wpabuf_free(query); 4490 4491 return ret; 4492 } 4493 4494 4495 static int gas_response_get(struct wpa_supplicant *wpa_s, char *cmd, char *buf, 4496 size_t buflen) 4497 { 4498 u8 addr[ETH_ALEN]; 4499 int dialog_token; 4500 int used; 4501 char *pos; 4502 size_t resp_len, start, requested_len; 4503 4504 if (!wpa_s->last_gas_resp) 4505 return -1; 4506 4507 used = hwaddr_aton2(cmd, addr); 4508 if (used < 0) 4509 return -1; 4510 4511 pos = cmd + used; 4512 while (*pos == ' ') 4513 pos++; 4514 dialog_token = atoi(pos); 4515 4516 if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 || 4517 dialog_token != wpa_s->last_gas_dialog_token) 4518 return -1; 4519 4520 resp_len = wpabuf_len(wpa_s->last_gas_resp); 4521 start = 0; 4522 requested_len = resp_len; 4523 4524 pos = os_strchr(pos, ' '); 4525 if (pos) { 4526 start = atoi(pos); 4527 if (start > resp_len) 4528 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 4529 pos = os_strchr(pos, ','); 4530 if (pos == NULL) 4531 return -1; 4532 pos++; 4533 requested_len = atoi(pos); 4534 if (start + requested_len > resp_len) 4535 return os_snprintf(buf, buflen, "FAIL-Invalid range"); 4536 } 4537 4538 if (requested_len * 2 + 1 > buflen) 4539 return os_snprintf(buf, buflen, "FAIL-Too long response"); 4540 4541 return wpa_snprintf_hex(buf, buflen, 4542 wpabuf_head_u8(wpa_s->last_gas_resp) + start, 4543 requested_len); 4544 } 4545 #endif /* CONFIG_INTERWORKING */ 4546 4547 4548 #ifdef CONFIG_HS20 4549 4550 static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst) 4551 { 4552 u8 dst_addr[ETH_ALEN]; 4553 int used; 4554 char *pos; 4555 u32 subtypes = 0; 4556 4557 used = hwaddr_aton2(dst, dst_addr); 4558 if (used < 0) 4559 return -1; 4560 pos = dst + used; 4561 for (;;) { 4562 int num = atoi(pos); 4563 if (num <= 0 || num > 31) 4564 return -1; 4565 subtypes |= BIT(num); 4566 pos = os_strchr(pos + 1, ','); 4567 if (pos == NULL) 4568 break; 4569 pos++; 4570 } 4571 4572 if (subtypes == 0) 4573 return -1; 4574 4575 return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0); 4576 } 4577 4578 4579 static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s, 4580 const u8 *addr, const char *realm) 4581 { 4582 u8 *buf; 4583 size_t rlen, len; 4584 int ret; 4585 4586 rlen = os_strlen(realm); 4587 len = 3 + rlen; 4588 buf = os_malloc(len); 4589 if (buf == NULL) 4590 return -1; 4591 buf[0] = 1; /* NAI Home Realm Count */ 4592 buf[1] = 0; /* Formatted in accordance with RFC 4282 */ 4593 buf[2] = rlen; 4594 os_memcpy(buf + 3, realm, rlen); 4595 4596 ret = hs20_anqp_send_req(wpa_s, addr, 4597 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4598 buf, len); 4599 4600 os_free(buf); 4601 4602 return ret; 4603 } 4604 4605 4606 static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s, 4607 char *dst) 4608 { 4609 struct wpa_cred *cred = wpa_s->conf->cred; 4610 u8 dst_addr[ETH_ALEN]; 4611 int used; 4612 u8 *buf; 4613 size_t len; 4614 int ret; 4615 4616 used = hwaddr_aton2(dst, dst_addr); 4617 if (used < 0) 4618 return -1; 4619 4620 while (dst[used] == ' ') 4621 used++; 4622 if (os_strncmp(dst + used, "realm=", 6) == 0) 4623 return hs20_nai_home_realm_list(wpa_s, dst_addr, 4624 dst + used + 6); 4625 4626 len = os_strlen(dst + used); 4627 4628 if (len == 0 && cred && cred->realm) 4629 return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm); 4630 4631 if (len % 1) 4632 return -1; 4633 len /= 2; 4634 buf = os_malloc(len); 4635 if (buf == NULL) 4636 return -1; 4637 if (hexstr2bin(dst + used, buf, len) < 0) { 4638 os_free(buf); 4639 return -1; 4640 } 4641 4642 ret = hs20_anqp_send_req(wpa_s, dst_addr, 4643 BIT(HS20_STYPE_NAI_HOME_REALM_QUERY), 4644 buf, len); 4645 os_free(buf); 4646 4647 return ret; 4648 } 4649 4650 #endif /* CONFIG_HS20 */ 4651 4652 4653 static int wpa_supplicant_ctrl_iface_sta_autoconnect( 4654 struct wpa_supplicant *wpa_s, char *cmd) 4655 { 4656 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0; 4657 return 0; 4658 } 4659 4660 4661 #ifdef CONFIG_AUTOSCAN 4662 4663 static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, 4664 char *cmd) 4665 { 4666 enum wpa_states state = wpa_s->wpa_state; 4667 char *new_params = NULL; 4668 4669 if (os_strlen(cmd) > 0) { 4670 new_params = os_strdup(cmd); 4671 if (new_params == NULL) 4672 return -1; 4673 } 4674 4675 os_free(wpa_s->conf->autoscan); 4676 wpa_s->conf->autoscan = new_params; 4677 4678 if (wpa_s->conf->autoscan == NULL) 4679 autoscan_deinit(wpa_s); 4680 else if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 4681 autoscan_init(wpa_s, 1); 4682 else if (state == WPA_SCANNING) 4683 wpa_supplicant_reinit_autoscan(wpa_s); 4684 4685 return 0; 4686 } 4687 4688 #endif /* CONFIG_AUTOSCAN */ 4689 4690 4691 #ifdef CONFIG_WNM 4692 4693 static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) 4694 { 4695 int enter; 4696 int intval = 0; 4697 char *pos; 4698 int ret; 4699 struct wpabuf *tfs_req = NULL; 4700 4701 if (os_strncmp(cmd, "enter", 5) == 0) 4702 enter = 1; 4703 else if (os_strncmp(cmd, "exit", 4) == 0) 4704 enter = 0; 4705 else 4706 return -1; 4707 4708 pos = os_strstr(cmd, " interval="); 4709 if (pos) 4710 intval = atoi(pos + 10); 4711 4712 pos = os_strstr(cmd, " tfs_req="); 4713 if (pos) { 4714 char *end; 4715 size_t len; 4716 pos += 9; 4717 end = os_strchr(pos, ' '); 4718 if (end) 4719 len = end - pos; 4720 else 4721 len = os_strlen(pos); 4722 if (len & 1) 4723 return -1; 4724 len /= 2; 4725 tfs_req = wpabuf_alloc(len); 4726 if (tfs_req == NULL) 4727 return -1; 4728 if (hexstr2bin(pos, wpabuf_put(tfs_req, len), len) < 0) { 4729 wpabuf_free(tfs_req); 4730 return -1; 4731 } 4732 } 4733 4734 ret = ieee802_11_send_wnmsleep_req(wpa_s, enter ? WNM_SLEEP_MODE_ENTER : 4735 WNM_SLEEP_MODE_EXIT, intval, 4736 tfs_req); 4737 wpabuf_free(tfs_req); 4738 4739 return ret; 4740 } 4741 4742 #endif /* CONFIG_WNM */ 4743 4744 4745 static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 4746 size_t buflen) 4747 { 4748 struct wpa_signal_info si; 4749 int ret; 4750 4751 ret = wpa_drv_signal_poll(wpa_s, &si); 4752 if (ret) 4753 return -1; 4754 4755 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n" 4756 "NOISE=%d\nFREQUENCY=%u\n", 4757 si.current_signal, si.current_txrate / 1000, 4758 si.current_noise, si.frequency); 4759 if (ret < 0 || (unsigned int) ret > buflen) 4760 return -1; 4761 return ret; 4762 } 4763 4764 4765 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, 4766 size_t buflen) 4767 { 4768 struct hostap_sta_driver_data sta; 4769 int ret; 4770 4771 ret = wpa_drv_pktcnt_poll(wpa_s, &sta); 4772 if (ret) 4773 return -1; 4774 4775 ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", 4776 sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); 4777 if (ret < 0 || (size_t) ret > buflen) 4778 return -1; 4779 return ret; 4780 } 4781 4782 4783 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 4784 char *buf, size_t *resp_len) 4785 { 4786 char *reply; 4787 const int reply_size = 4096; 4788 int ctrl_rsp = 0; 4789 int reply_len; 4790 4791 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 4792 os_strncmp(buf, "SET_NETWORK ", 12) == 0 || 4793 os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || 4794 os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) { 4795 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 4796 (const u8 *) buf, os_strlen(buf)); 4797 } else { 4798 int level = MSG_DEBUG; 4799 if (os_strcmp(buf, "PING") == 0) 4800 level = MSG_EXCESSIVE; 4801 wpa_hexdump_ascii(level, "RX ctrl_iface", 4802 (const u8 *) buf, os_strlen(buf)); 4803 wpa_dbg(wpa_s, level, "Control interface command '%s'", buf); 4804 } 4805 4806 reply = os_malloc(reply_size); 4807 if (reply == NULL) { 4808 *resp_len = 1; 4809 return NULL; 4810 } 4811 4812 os_memcpy(reply, "OK\n", 3); 4813 reply_len = 3; 4814 4815 if (os_strcmp(buf, "PING") == 0) { 4816 os_memcpy(reply, "PONG\n", 5); 4817 reply_len = 5; 4818 } else if (os_strcmp(buf, "IFNAME") == 0) { 4819 reply_len = os_strlen(wpa_s->ifname); 4820 os_memcpy(reply, wpa_s->ifname, reply_len); 4821 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 4822 if (wpa_debug_reopen_file() < 0) 4823 reply_len = -1; 4824 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 4825 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 4826 } else if (os_strcmp(buf, "MIB") == 0) { 4827 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 4828 if (reply_len >= 0) { 4829 int res; 4830 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 4831 reply_size - reply_len); 4832 if (res < 0) 4833 reply_len = -1; 4834 else 4835 reply_len += res; 4836 } 4837 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 4838 reply_len = wpa_supplicant_ctrl_iface_status( 4839 wpa_s, buf + 6, reply, reply_size); 4840 } else if (os_strcmp(buf, "PMKSA") == 0) { 4841 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 4842 reply_size); 4843 } else if (os_strncmp(buf, "SET ", 4) == 0) { 4844 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 4845 reply_len = -1; 4846 } else if (os_strncmp(buf, "GET ", 4) == 0) { 4847 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 4848 reply, reply_size); 4849 } else if (os_strcmp(buf, "LOGON") == 0) { 4850 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 4851 } else if (os_strcmp(buf, "LOGOFF") == 0) { 4852 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 4853 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 4854 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4855 reply_len = -1; 4856 else 4857 wpas_request_connection(wpa_s); 4858 } else if (os_strcmp(buf, "RECONNECT") == 0) { 4859 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 4860 reply_len = -1; 4861 else if (wpa_s->disconnected) 4862 wpas_request_connection(wpa_s); 4863 #ifdef IEEE8021X_EAPOL 4864 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 4865 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 4866 reply_len = -1; 4867 #endif /* IEEE8021X_EAPOL */ 4868 #ifdef CONFIG_PEERKEY 4869 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 4870 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 4871 reply_len = -1; 4872 #endif /* CONFIG_PEERKEY */ 4873 #ifdef CONFIG_IEEE80211R 4874 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 4875 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 4876 reply_len = -1; 4877 #endif /* CONFIG_IEEE80211R */ 4878 #ifdef CONFIG_WPS 4879 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 4880 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 4881 if (res == -2) { 4882 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4883 reply_len = 17; 4884 } else if (res) 4885 reply_len = -1; 4886 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 4887 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 4888 if (res == -2) { 4889 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4890 reply_len = 17; 4891 } else if (res) 4892 reply_len = -1; 4893 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 4894 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 4895 reply, 4896 reply_size); 4897 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 4898 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 4899 wpa_s, buf + 14, reply, reply_size); 4900 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 4901 if (wpas_wps_cancel(wpa_s)) 4902 reply_len = -1; 4903 #ifdef CONFIG_WPS_NFC 4904 } else if (os_strcmp(buf, "WPS_NFC") == 0) { 4905 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, NULL)) 4906 reply_len = -1; 4907 } else if (os_strncmp(buf, "WPS_NFC ", 8) == 0) { 4908 if (wpa_supplicant_ctrl_iface_wps_nfc(wpa_s, buf + 8)) 4909 reply_len = -1; 4910 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 4911 reply_len = wpa_supplicant_ctrl_iface_wps_nfc_token( 4912 wpa_s, buf + 14, reply, reply_size); 4913 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 4914 if (wpa_supplicant_ctrl_iface_wps_nfc_tag_read(wpa_s, 4915 buf + 17)) 4916 reply_len = -1; 4917 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_REQ ", 21) == 0) { 4918 reply_len = wpas_ctrl_nfc_get_handover_req( 4919 wpa_s, buf + 21, reply, reply_size); 4920 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 4921 reply_len = wpas_ctrl_nfc_get_handover_sel( 4922 wpa_s, buf + 21, reply, reply_size); 4923 } else if (os_strncmp(buf, "NFC_RX_HANDOVER_REQ ", 20) == 0) { 4924 reply_len = wpas_ctrl_nfc_rx_handover_req( 4925 wpa_s, buf + 20, reply, reply_size); 4926 } else if (os_strncmp(buf, "NFC_RX_HANDOVER_SEL ", 20) == 0) { 4927 if (wpas_ctrl_nfc_rx_handover_sel(wpa_s, buf + 20)) 4928 reply_len = -1; 4929 #endif /* CONFIG_WPS_NFC */ 4930 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 4931 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 4932 reply_len = -1; 4933 #ifdef CONFIG_AP 4934 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 4935 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 4936 wpa_s, buf + 11, reply, reply_size); 4937 #endif /* CONFIG_AP */ 4938 #ifdef CONFIG_WPS_ER 4939 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 4940 if (wpas_wps_er_start(wpa_s, NULL)) 4941 reply_len = -1; 4942 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 4943 if (wpas_wps_er_start(wpa_s, buf + 13)) 4944 reply_len = -1; 4945 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 4946 if (wpas_wps_er_stop(wpa_s)) 4947 reply_len = -1; 4948 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 4949 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 4950 reply_len = -1; 4951 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 4952 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 4953 if (ret == -2) { 4954 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 4955 reply_len = 17; 4956 } else if (ret == -3) { 4957 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 4958 reply_len = 18; 4959 } else if (ret == -4) { 4960 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 4961 reply_len = 20; 4962 } else if (ret) 4963 reply_len = -1; 4964 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 4965 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 4966 reply_len = -1; 4967 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 4968 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 4969 buf + 18)) 4970 reply_len = -1; 4971 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 4972 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 4973 reply_len = -1; 4974 #ifdef CONFIG_WPS_NFC 4975 } else if (os_strncmp(buf, "WPS_ER_NFC_CONFIG_TOKEN ", 24) == 0) { 4976 reply_len = wpa_supplicant_ctrl_iface_wps_er_nfc_config_token( 4977 wpa_s, buf + 24, reply, reply_size); 4978 #endif /* CONFIG_WPS_NFC */ 4979 #endif /* CONFIG_WPS_ER */ 4980 #endif /* CONFIG_WPS */ 4981 #ifdef CONFIG_IBSS_RSN 4982 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 4983 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 4984 reply_len = -1; 4985 #endif /* CONFIG_IBSS_RSN */ 4986 #ifdef CONFIG_P2P 4987 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 4988 if (p2p_ctrl_find(wpa_s, buf + 9)) 4989 reply_len = -1; 4990 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 4991 if (p2p_ctrl_find(wpa_s, "")) 4992 reply_len = -1; 4993 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 4994 wpas_p2p_stop_find(wpa_s); 4995 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 4996 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 4997 reply_size); 4998 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 4999 if (p2p_ctrl_listen(wpa_s, buf + 11)) 5000 reply_len = -1; 5001 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 5002 if (p2p_ctrl_listen(wpa_s, "")) 5003 reply_len = -1; 5004 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 5005 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 5006 reply_len = -1; 5007 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 5008 if (wpas_p2p_group_add(wpa_s, 0, 0, 0)) 5009 reply_len = -1; 5010 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 5011 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 5012 reply_len = -1; 5013 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 5014 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 5015 reply_len = -1; 5016 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 5017 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 5018 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 5019 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 5020 reply_size); 5021 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 5022 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 5023 reply_len = -1; 5024 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 5025 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 5026 reply_len = -1; 5027 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 5028 wpas_p2p_sd_service_update(wpa_s); 5029 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 5030 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 5031 reply_len = -1; 5032 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 5033 wpas_p2p_service_flush(wpa_s); 5034 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 5035 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 5036 reply_len = -1; 5037 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 5038 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 5039 reply_len = -1; 5040 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 5041 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 5042 reply_len = -1; 5043 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 5044 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 5045 reply_len = -1; 5046 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 5047 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 5048 reply_size); 5049 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 5050 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 5051 reply_len = -1; 5052 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 5053 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 5054 wpa_s->force_long_sd = 0; 5055 if (wpa_s->global->p2p) 5056 p2p_flush(wpa_s->global->p2p); 5057 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 5058 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 5059 reply_len = -1; 5060 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 5061 if (wpas_p2p_cancel(wpa_s)) 5062 reply_len = -1; 5063 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 5064 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 5065 reply_len = -1; 5066 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 5067 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 5068 reply_len = -1; 5069 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 5070 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 5071 reply_len = -1; 5072 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 5073 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 5074 reply_len = -1; 5075 #endif /* CONFIG_P2P */ 5076 #ifdef CONFIG_WIFI_DISPLAY 5077 } else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) { 5078 if (wifi_display_subelem_set(wpa_s->global, buf + 16) < 0) 5079 reply_len = -1; 5080 } else if (os_strncmp(buf, "WFD_SUBELEM_GET ", 16) == 0) { 5081 reply_len = wifi_display_subelem_get(wpa_s->global, buf + 16, 5082 reply, reply_size); 5083 #endif /* CONFIG_WIFI_DISPLAY */ 5084 #ifdef CONFIG_INTERWORKING 5085 } else if (os_strcmp(buf, "FETCH_ANQP") == 0) { 5086 if (interworking_fetch_anqp(wpa_s) < 0) 5087 reply_len = -1; 5088 } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) { 5089 interworking_stop_fetch_anqp(wpa_s); 5090 } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) { 5091 if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") != 5092 NULL) < 0) 5093 reply_len = -1; 5094 } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) { 5095 if (ctrl_interworking_connect(wpa_s, buf + 21) < 0) 5096 reply_len = -1; 5097 } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) { 5098 if (get_anqp(wpa_s, buf + 9) < 0) 5099 reply_len = -1; 5100 } else if (os_strncmp(buf, "GAS_REQUEST ", 12) == 0) { 5101 if (gas_request(wpa_s, buf + 12) < 0) 5102 reply_len = -1; 5103 } else if (os_strncmp(buf, "GAS_RESPONSE_GET ", 17) == 0) { 5104 reply_len = gas_response_get(wpa_s, buf + 17, reply, 5105 reply_size); 5106 #endif /* CONFIG_INTERWORKING */ 5107 #ifdef CONFIG_HS20 5108 } else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) { 5109 if (get_hs20_anqp(wpa_s, buf + 14) < 0) 5110 reply_len = -1; 5111 } else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) { 5112 if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0) 5113 reply_len = -1; 5114 #endif /* CONFIG_HS20 */ 5115 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 5116 { 5117 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 5118 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 5119 reply_len = -1; 5120 else 5121 ctrl_rsp = 1; 5122 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 5123 if (wpa_supplicant_reload_configuration(wpa_s)) 5124 reply_len = -1; 5125 } else if (os_strcmp(buf, "TERMINATE") == 0) { 5126 wpa_supplicant_terminate_proc(wpa_s->global); 5127 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 5128 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 5129 reply_len = -1; 5130 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 5131 reply_len = wpa_supplicant_ctrl_iface_blacklist( 5132 wpa_s, buf + 9, reply, reply_size); 5133 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 5134 reply_len = wpa_supplicant_ctrl_iface_log_level( 5135 wpa_s, buf + 9, reply, reply_size); 5136 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 5137 reply_len = wpa_supplicant_ctrl_iface_list_networks( 5138 wpa_s, reply, reply_size); 5139 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 5140 #ifdef CONFIG_SME 5141 wpa_s->sme.prev_bssid_set = 0; 5142 #endif /* CONFIG_SME */ 5143 wpa_s->reassociate = 0; 5144 wpa_s->disconnected = 1; 5145 wpa_supplicant_cancel_sched_scan(wpa_s); 5146 wpa_supplicant_cancel_scan(wpa_s); 5147 wpa_supplicant_deauthenticate(wpa_s, 5148 WLAN_REASON_DEAUTH_LEAVING); 5149 } else if (os_strcmp(buf, "SCAN") == 0) { 5150 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 5151 reply_len = -1; 5152 else { 5153 if (!wpa_s->sched_scanning && !wpa_s->scanning && 5154 ((wpa_s->wpa_state <= WPA_SCANNING) || 5155 (wpa_s->wpa_state == WPA_COMPLETED))) { 5156 wpa_s->normal_scans = 0; 5157 wpa_s->scan_req = MANUAL_SCAN_REQ; 5158 wpa_supplicant_req_scan(wpa_s, 0, 0); 5159 } else if (wpa_s->sched_scanning) { 5160 wpa_printf(MSG_DEBUG, "Stop ongoing " 5161 "sched_scan to allow requested " 5162 "full scan to proceed"); 5163 wpa_supplicant_cancel_sched_scan(wpa_s); 5164 wpa_s->scan_req = MANUAL_SCAN_REQ; 5165 wpa_supplicant_req_scan(wpa_s, 0, 0); 5166 } else { 5167 wpa_printf(MSG_DEBUG, "Ongoing scan action - " 5168 "reject new request"); 5169 reply_len = os_snprintf(reply, reply_size, 5170 "FAIL-BUSY\n"); 5171 } 5172 } 5173 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 5174 reply_len = wpa_supplicant_ctrl_iface_scan_results( 5175 wpa_s, reply, reply_size); 5176 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 5177 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 5178 reply_len = -1; 5179 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 5180 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 5181 reply_len = -1; 5182 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 5183 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 5184 reply_len = -1; 5185 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 5186 reply_len = wpa_supplicant_ctrl_iface_add_network( 5187 wpa_s, reply, reply_size); 5188 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 5189 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 5190 reply_len = -1; 5191 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 5192 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 5193 reply_len = -1; 5194 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 5195 reply_len = wpa_supplicant_ctrl_iface_get_network( 5196 wpa_s, buf + 12, reply, reply_size); 5197 } else if (os_strcmp(buf, "LIST_CREDS") == 0) { 5198 reply_len = wpa_supplicant_ctrl_iface_list_creds( 5199 wpa_s, reply, reply_size); 5200 } else if (os_strcmp(buf, "ADD_CRED") == 0) { 5201 reply_len = wpa_supplicant_ctrl_iface_add_cred( 5202 wpa_s, reply, reply_size); 5203 } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) { 5204 if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12)) 5205 reply_len = -1; 5206 } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { 5207 if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) 5208 reply_len = -1; 5209 #ifndef CONFIG_NO_CONFIG_WRITE 5210 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 5211 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 5212 reply_len = -1; 5213 #endif /* CONFIG_NO_CONFIG_WRITE */ 5214 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 5215 reply_len = wpa_supplicant_ctrl_iface_get_capability( 5216 wpa_s, buf + 15, reply, reply_size); 5217 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 5218 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 5219 reply_len = -1; 5220 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 5221 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 5222 reply_len = -1; 5223 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 5224 reply_len = wpa_supplicant_global_iface_list( 5225 wpa_s->global, reply, reply_size); 5226 } else if (os_strcmp(buf, "INTERFACES") == 0) { 5227 reply_len = wpa_supplicant_global_iface_interfaces( 5228 wpa_s->global, reply, reply_size); 5229 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 5230 reply_len = wpa_supplicant_ctrl_iface_bss( 5231 wpa_s, buf + 4, reply, reply_size); 5232 #ifdef CONFIG_AP 5233 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 5234 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 5235 } else if (os_strncmp(buf, "STA ", 4) == 0) { 5236 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 5237 reply_size); 5238 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 5239 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 5240 reply_size); 5241 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 5242 if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15)) 5243 reply_len = -1; 5244 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 5245 if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13)) 5246 reply_len = -1; 5247 #endif /* CONFIG_AP */ 5248 } else if (os_strcmp(buf, "SUSPEND") == 0) { 5249 wpas_notify_suspend(wpa_s->global); 5250 } else if (os_strcmp(buf, "RESUME") == 0) { 5251 wpas_notify_resume(wpa_s->global); 5252 } else if (os_strcmp(buf, "DROP_SA") == 0) { 5253 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 5254 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 5255 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 5256 reply_len = -1; 5257 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 5258 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16)) 5259 reply_len = -1; 5260 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 5261 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 5262 reply_len = -1; 5263 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 5264 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 5265 buf + 17)) 5266 reply_len = -1; 5267 } else if (os_strncmp(buf, "BSS_FLUSH ", 10) == 0) { 5268 if (wpa_supplicant_ctrl_iface_bss_flush(wpa_s, buf + 10)) 5269 reply_len = -1; 5270 #ifdef CONFIG_TDLS 5271 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 5272 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 5273 reply_len = -1; 5274 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 5275 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 5276 reply_len = -1; 5277 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 5278 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 5279 reply_len = -1; 5280 #endif /* CONFIG_TDLS */ 5281 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 5282 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 5283 reply_size); 5284 } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { 5285 reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, 5286 reply_size); 5287 #ifdef CONFIG_AUTOSCAN 5288 } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { 5289 if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) 5290 reply_len = -1; 5291 #endif /* CONFIG_AUTOSCAN */ 5292 } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) { 5293 pmksa_cache_clear_current(wpa_s->wpa); 5294 eapol_sm_request_reauth(wpa_s->eapol); 5295 #ifdef CONFIG_WNM 5296 } else if (os_strncmp(buf, "WNM_SLEEP ", 10) == 0) { 5297 if (wpas_ctrl_iface_wnm_sleep(wpa_s, buf + 10)) 5298 reply_len = -1; 5299 #endif /* CONFIG_WNM */ 5300 } else { 5301 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 5302 reply_len = 16; 5303 } 5304 5305 if (reply_len < 0) { 5306 os_memcpy(reply, "FAIL\n", 5); 5307 reply_len = 5; 5308 } 5309 5310 if (ctrl_rsp) 5311 eapol_sm_notify_ctrl_response(wpa_s->eapol); 5312 5313 *resp_len = reply_len; 5314 return reply; 5315 } 5316 5317 5318 static int wpa_supplicant_global_iface_add(struct wpa_global *global, 5319 char *cmd) 5320 { 5321 struct wpa_interface iface; 5322 char *pos; 5323 5324 /* 5325 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 5326 * TAB<bridge_ifname> 5327 */ 5328 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 5329 5330 os_memset(&iface, 0, sizeof(iface)); 5331 5332 do { 5333 iface.ifname = pos = cmd; 5334 pos = os_strchr(pos, '\t'); 5335 if (pos) 5336 *pos++ = '\0'; 5337 if (iface.ifname[0] == '\0') 5338 return -1; 5339 if (pos == NULL) 5340 break; 5341 5342 iface.confname = pos; 5343 pos = os_strchr(pos, '\t'); 5344 if (pos) 5345 *pos++ = '\0'; 5346 if (iface.confname[0] == '\0') 5347 iface.confname = NULL; 5348 if (pos == NULL) 5349 break; 5350 5351 iface.driver = pos; 5352 pos = os_strchr(pos, '\t'); 5353 if (pos) 5354 *pos++ = '\0'; 5355 if (iface.driver[0] == '\0') 5356 iface.driver = NULL; 5357 if (pos == NULL) 5358 break; 5359 5360 iface.ctrl_interface = pos; 5361 pos = os_strchr(pos, '\t'); 5362 if (pos) 5363 *pos++ = '\0'; 5364 if (iface.ctrl_interface[0] == '\0') 5365 iface.ctrl_interface = NULL; 5366 if (pos == NULL) 5367 break; 5368 5369 iface.driver_param = pos; 5370 pos = os_strchr(pos, '\t'); 5371 if (pos) 5372 *pos++ = '\0'; 5373 if (iface.driver_param[0] == '\0') 5374 iface.driver_param = NULL; 5375 if (pos == NULL) 5376 break; 5377 5378 iface.bridge_ifname = pos; 5379 pos = os_strchr(pos, '\t'); 5380 if (pos) 5381 *pos++ = '\0'; 5382 if (iface.bridge_ifname[0] == '\0') 5383 iface.bridge_ifname = NULL; 5384 if (pos == NULL) 5385 break; 5386 } while (0); 5387 5388 if (wpa_supplicant_get_iface(global, iface.ifname)) 5389 return -1; 5390 5391 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 5392 } 5393 5394 5395 static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 5396 char *cmd) 5397 { 5398 struct wpa_supplicant *wpa_s; 5399 5400 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 5401 5402 wpa_s = wpa_supplicant_get_iface(global, cmd); 5403 if (wpa_s == NULL) 5404 return -1; 5405 return wpa_supplicant_remove_iface(global, wpa_s, 0); 5406 } 5407 5408 5409 static void wpa_free_iface_info(struct wpa_interface_info *iface) 5410 { 5411 struct wpa_interface_info *prev; 5412 5413 while (iface) { 5414 prev = iface; 5415 iface = iface->next; 5416 5417 os_free(prev->ifname); 5418 os_free(prev->desc); 5419 os_free(prev); 5420 } 5421 } 5422 5423 5424 static int wpa_supplicant_global_iface_list(struct wpa_global *global, 5425 char *buf, int len) 5426 { 5427 int i, res; 5428 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 5429 char *pos, *end; 5430 5431 for (i = 0; wpa_drivers[i]; i++) { 5432 struct wpa_driver_ops *drv = wpa_drivers[i]; 5433 if (drv->get_interfaces == NULL) 5434 continue; 5435 tmp = drv->get_interfaces(global->drv_priv[i]); 5436 if (tmp == NULL) 5437 continue; 5438 5439 if (last == NULL) 5440 iface = last = tmp; 5441 else 5442 last->next = tmp; 5443 while (last->next) 5444 last = last->next; 5445 } 5446 5447 pos = buf; 5448 end = buf + len; 5449 for (tmp = iface; tmp; tmp = tmp->next) { 5450 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 5451 tmp->drv_name, tmp->ifname, 5452 tmp->desc ? tmp->desc : ""); 5453 if (res < 0 || res >= end - pos) { 5454 *pos = '\0'; 5455 break; 5456 } 5457 pos += res; 5458 } 5459 5460 wpa_free_iface_info(iface); 5461 5462 return pos - buf; 5463 } 5464 5465 5466 static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 5467 char *buf, int len) 5468 { 5469 int res; 5470 char *pos, *end; 5471 struct wpa_supplicant *wpa_s; 5472 5473 wpa_s = global->ifaces; 5474 pos = buf; 5475 end = buf + len; 5476 5477 while (wpa_s) { 5478 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 5479 if (res < 0 || res >= end - pos) { 5480 *pos = '\0'; 5481 break; 5482 } 5483 pos += res; 5484 wpa_s = wpa_s->next; 5485 } 5486 return pos - buf; 5487 } 5488 5489 5490 char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 5491 char *buf, size_t *resp_len) 5492 { 5493 char *reply; 5494 const int reply_size = 2048; 5495 int reply_len; 5496 int level = MSG_DEBUG; 5497 5498 if (os_strcmp(buf, "PING") == 0) 5499 level = MSG_EXCESSIVE; 5500 wpa_hexdump_ascii(level, "RX global ctrl_iface", 5501 (const u8 *) buf, os_strlen(buf)); 5502 5503 reply = os_malloc(reply_size); 5504 if (reply == NULL) { 5505 *resp_len = 1; 5506 return NULL; 5507 } 5508 5509 os_memcpy(reply, "OK\n", 3); 5510 reply_len = 3; 5511 5512 if (os_strcmp(buf, "PING") == 0) { 5513 os_memcpy(reply, "PONG\n", 5); 5514 reply_len = 5; 5515 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 5516 if (wpa_supplicant_global_iface_add(global, buf + 14)) 5517 reply_len = -1; 5518 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 5519 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 5520 reply_len = -1; 5521 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 5522 reply_len = wpa_supplicant_global_iface_list( 5523 global, reply, reply_size); 5524 } else if (os_strcmp(buf, "INTERFACES") == 0) { 5525 reply_len = wpa_supplicant_global_iface_interfaces( 5526 global, reply, reply_size); 5527 } else if (os_strcmp(buf, "TERMINATE") == 0) { 5528 wpa_supplicant_terminate_proc(global); 5529 } else if (os_strcmp(buf, "SUSPEND") == 0) { 5530 wpas_notify_suspend(global); 5531 } else if (os_strcmp(buf, "RESUME") == 0) { 5532 wpas_notify_resume(global); 5533 } else { 5534 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 5535 reply_len = 16; 5536 } 5537 5538 if (reply_len < 0) { 5539 os_memcpy(reply, "FAIL\n", 5); 5540 reply_len = 5; 5541 } 5542 5543 *resp_len = reply_len; 5544 return reply; 5545 } 5546