ctrl_iface.c revision 6f3bdcf8c96ad38245e927ac1afe28b98621a4e5
1/* 2 * WPA Supplicant / Control interface (shared code for all backends) 3 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "utils/includes.h" 16 17#include "utils/common.h" 18#include "utils/eloop.h" 19#include "common/version.h" 20#include "common/ieee802_11_defs.h" 21#include "common/wpa_ctrl.h" 22#include "eap_peer/eap.h" 23#include "eapol_supp/eapol_supp_sm.h" 24#include "rsn_supp/wpa.h" 25#include "rsn_supp/preauth.h" 26#include "rsn_supp/pmksa_cache.h" 27#include "l2_packet/l2_packet.h" 28#include "wps/wps.h" 29#include "config.h" 30#include "wpa_supplicant_i.h" 31#include "driver_i.h" 32#include "wps_supplicant.h" 33#include "ibss_rsn.h" 34#include "ap.h" 35#include "p2p_supplicant.h" 36#include "p2p/p2p.h" 37#include "notify.h" 38#include "bss.h" 39#include "scan.h" 40#include "ctrl_iface.h" 41#include "blacklist.h" 42 43extern struct wpa_driver_ops *wpa_drivers[]; 44 45static int wpa_supplicant_global_iface_list(struct wpa_global *global, 46 char *buf, int len); 47static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 48 char *buf, int len); 49 50 51static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, 52 char *cmd) 53{ 54 char *value; 55 int ret = 0; 56 57 value = os_strchr(cmd, ' '); 58 if (value == NULL) 59 return -1; 60 *value++ = '\0'; 61 62 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 63 if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { 64 eapol_sm_configure(wpa_s->eapol, 65 atoi(value), -1, -1, -1); 66 } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { 67 eapol_sm_configure(wpa_s->eapol, 68 -1, atoi(value), -1, -1); 69 } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { 70 eapol_sm_configure(wpa_s->eapol, 71 -1, -1, atoi(value), -1); 72 } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { 73 eapol_sm_configure(wpa_s->eapol, 74 -1, -1, -1, atoi(value)); 75 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { 76 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 77 atoi(value))) 78 ret = -1; 79 } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 80 0) { 81 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 82 atoi(value))) 83 ret = -1; 84 } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { 85 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) 86 ret = -1; 87 } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { 88 wpa_s->wps_fragment_size = atoi(value); 89#ifdef CONFIG_WPS_TESTING 90 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 91 long int val; 92 val = strtol(value, NULL, 0); 93 if (val < 0 || val > 0xff) { 94 ret = -1; 95 wpa_printf(MSG_DEBUG, "WPS: Invalid " 96 "wps_version_number %ld", val); 97 } else { 98 wps_version_number = val; 99 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 100 "version %u.%u", 101 (wps_version_number & 0xf0) >> 4, 102 wps_version_number & 0x0f); 103 } 104 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 105 wps_testing_dummy_cred = atoi(value); 106 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 107 wps_testing_dummy_cred); 108#endif /* CONFIG_WPS_TESTING */ 109 } else if (os_strcasecmp(cmd, "ampdu") == 0) { 110 if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0) 111 ret = -1; 112#ifdef CONFIG_TDLS_TESTING 113 } else if (os_strcasecmp(cmd, "tdls_testing") == 0) { 114 extern unsigned int tdls_testing; 115 tdls_testing = strtol(value, NULL, 0); 116 wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing); 117#endif /* CONFIG_TDLS_TESTING */ 118#ifdef CONFIG_TDLS 119 } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) { 120 int disabled = atoi(value); 121 wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled); 122 if (disabled) { 123 if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0) 124 ret = -1; 125 } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0) 126 ret = -1; 127 wpa_tdls_enable(wpa_s->wpa, !disabled); 128#endif /* CONFIG_TDLS */ 129 } else { 130 value[-1] = '='; 131 ret = wpa_config_process_global(wpa_s->conf, cmd, -1); 132 if (ret == 0) 133 wpa_supplicant_update_config(wpa_s); 134 } 135 136 return ret; 137} 138 139 140static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, 141 char *cmd, char *buf, size_t buflen) 142{ 143 int res = -1; 144 145 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 146 147 if (os_strcmp(cmd, "version") == 0) { 148 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 149 } else if (os_strcasecmp(cmd, "country") == 0) { 150 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) 151 res = os_snprintf(buf, buflen, "%c%c", 152 wpa_s->conf->country[0], 153 wpa_s->conf->country[1]); 154 } 155 156 if (res < 0 || (unsigned int) res >= buflen) 157 return -1; 158 return res; 159} 160 161 162#ifdef IEEE8021X_EAPOL 163static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, 164 char *addr) 165{ 166 u8 bssid[ETH_ALEN]; 167 struct wpa_ssid *ssid = wpa_s->current_ssid; 168 169 if (hwaddr_aton(addr, bssid)) { 170 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " 171 "'%s'", addr); 172 return -1; 173 } 174 175 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); 176 rsn_preauth_deinit(wpa_s->wpa); 177 if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL)) 178 return -1; 179 180 return 0; 181} 182#endif /* IEEE8021X_EAPOL */ 183 184 185#ifdef CONFIG_PEERKEY 186/* MLME-STKSTART.request(peer) */ 187static int wpa_supplicant_ctrl_iface_stkstart( 188 struct wpa_supplicant *wpa_s, char *addr) 189{ 190 u8 peer[ETH_ALEN]; 191 192 if (hwaddr_aton(addr, peer)) { 193 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " 194 "address '%s'", addr); 195 return -1; 196 } 197 198 wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, 199 MAC2STR(peer)); 200 201 return wpa_sm_stkstart(wpa_s->wpa, peer); 202} 203#endif /* CONFIG_PEERKEY */ 204 205 206#ifdef CONFIG_TDLS 207 208static int wpa_supplicant_ctrl_iface_tdls_discover( 209 struct wpa_supplicant *wpa_s, char *addr) 210{ 211 u8 peer[ETH_ALEN]; 212 213 if (hwaddr_aton(addr, peer)) { 214 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid " 215 "address '%s'", addr); 216 return -1; 217 } 218 219 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR, 220 MAC2STR(peer)); 221 222 return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 223} 224 225 226static int wpa_supplicant_ctrl_iface_tdls_setup( 227 struct wpa_supplicant *wpa_s, char *addr) 228{ 229 u8 peer[ETH_ALEN]; 230 int ret; 231 232 if (hwaddr_aton(addr, peer)) { 233 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid " 234 "address '%s'", addr); 235 return -1; 236 } 237 238 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR, 239 MAC2STR(peer)); 240 241 ret = wpa_tdls_reneg(wpa_s->wpa, peer); 242 if (ret) 243 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 244 return ret; 245} 246 247 248static int wpa_supplicant_ctrl_iface_tdls_teardown( 249 struct wpa_supplicant *wpa_s, char *addr) 250{ 251 u8 peer[ETH_ALEN]; 252 253 if (hwaddr_aton(addr, peer)) { 254 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid " 255 "address '%s'", addr); 256 return -1; 257 } 258 259 wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR, 260 MAC2STR(peer)); 261 262 return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 263} 264 265#endif /* CONFIG_TDLS */ 266 267 268#ifdef CONFIG_IEEE80211R 269static int wpa_supplicant_ctrl_iface_ft_ds( 270 struct wpa_supplicant *wpa_s, char *addr) 271{ 272 u8 target_ap[ETH_ALEN]; 273 struct wpa_bss *bss; 274 const u8 *mdie; 275 276 if (hwaddr_aton(addr, target_ap)) { 277 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid " 278 "address '%s'", addr); 279 return -1; 280 } 281 282 wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap)); 283 284 bss = wpa_bss_get_bssid(wpa_s, target_ap); 285 if (bss) 286 mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 287 else 288 mdie = NULL; 289 290 return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie); 291} 292#endif /* CONFIG_IEEE80211R */ 293 294 295#ifdef CONFIG_WPS 296static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, 297 char *cmd) 298{ 299 u8 bssid[ETH_ALEN], *_bssid = bssid; 300 u8 p2p_dev_addr[ETH_ALEN], *_p2p_dev_addr = NULL; 301 302 if (cmd == NULL || os_strcmp(cmd, "any") == 0) { 303 _bssid = NULL; 304#ifdef CONFIG_P2P 305 } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { 306 if (hwaddr_aton(cmd + 13, p2p_dev_addr)) { 307 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid " 308 "P2P Device Address '%s'", 309 cmd + 13); 310 return -1; 311 } 312 _p2p_dev_addr = p2p_dev_addr; 313#endif /* CONFIG_P2P */ 314 } else if (hwaddr_aton(cmd, bssid)) { 315 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", 316 cmd); 317 return -1; 318 } 319 320#ifdef CONFIG_AP 321 if (wpa_s->ap_iface) 322 return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); 323#endif /* CONFIG_AP */ 324 325 return wpas_wps_start_pbc(wpa_s, _bssid, 0); 326} 327 328 329static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s, 330 char *cmd, char *buf, 331 size_t buflen) 332{ 333 u8 bssid[ETH_ALEN], *_bssid = bssid; 334 char *pin; 335 int ret; 336 337 pin = os_strchr(cmd, ' '); 338 if (pin) 339 *pin++ = '\0'; 340 341 if (os_strcmp(cmd, "any") == 0) 342 _bssid = NULL; 343 else if (hwaddr_aton(cmd, bssid)) { 344 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'", 345 cmd); 346 return -1; 347 } 348 349#ifdef CONFIG_AP 350 if (wpa_s->ap_iface) 351 return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin, 352 buf, buflen); 353#endif /* CONFIG_AP */ 354 355 if (pin) { 356 ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0, 357 DEV_PW_DEFAULT); 358 if (ret < 0) 359 return -1; 360 ret = os_snprintf(buf, buflen, "%s", pin); 361 if (ret < 0 || (size_t) ret >= buflen) 362 return -1; 363 return ret; 364 } 365 366 ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT); 367 if (ret < 0) 368 return -1; 369 370 /* Return the generated PIN */ 371 ret = os_snprintf(buf, buflen, "%08d", ret); 372 if (ret < 0 || (size_t) ret >= buflen) 373 return -1; 374 return ret; 375} 376 377 378static int wpa_supplicant_ctrl_iface_wps_check_pin( 379 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 380{ 381 char pin[9]; 382 size_t len; 383 char *pos; 384 int ret; 385 386 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 387 (u8 *) cmd, os_strlen(cmd)); 388 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 389 if (*pos < '0' || *pos > '9') 390 continue; 391 pin[len++] = *pos; 392 if (len == 9) { 393 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 394 return -1; 395 } 396 } 397 if (len != 4 && len != 8) { 398 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 399 return -1; 400 } 401 pin[len] = '\0'; 402 403 if (len == 8) { 404 unsigned int pin_val; 405 pin_val = atoi(pin); 406 if (!wps_pin_valid(pin_val)) { 407 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 408 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 409 if (ret < 0 || (size_t) ret >= buflen) 410 return -1; 411 return ret; 412 } 413 } 414 415 ret = os_snprintf(buf, buflen, "%s", pin); 416 if (ret < 0 || (size_t) ret >= buflen) 417 return -1; 418 419 return ret; 420} 421 422 423#ifdef CONFIG_WPS_OOB 424static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s, 425 char *cmd) 426{ 427 char *path, *method, *name; 428 429 path = os_strchr(cmd, ' '); 430 if (path == NULL) 431 return -1; 432 *path++ = '\0'; 433 434 method = os_strchr(path, ' '); 435 if (method == NULL) 436 return -1; 437 *method++ = '\0'; 438 439 name = os_strchr(method, ' '); 440 if (name != NULL) 441 *name++ = '\0'; 442 443 return wpas_wps_start_oob(wpa_s, cmd, path, method, name); 444} 445#endif /* CONFIG_WPS_OOB */ 446 447 448static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s, 449 char *cmd) 450{ 451 u8 bssid[ETH_ALEN]; 452 char *pin; 453 char *new_ssid; 454 char *new_auth; 455 char *new_encr; 456 char *new_key; 457 struct wps_new_ap_settings ap; 458 459 pin = os_strchr(cmd, ' '); 460 if (pin == NULL) 461 return -1; 462 *pin++ = '\0'; 463 464 if (hwaddr_aton(cmd, bssid)) { 465 wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'", 466 cmd); 467 return -1; 468 } 469 470 new_ssid = os_strchr(pin, ' '); 471 if (new_ssid == NULL) 472 return wpas_wps_start_reg(wpa_s, bssid, pin, NULL); 473 *new_ssid++ = '\0'; 474 475 new_auth = os_strchr(new_ssid, ' '); 476 if (new_auth == NULL) 477 return -1; 478 *new_auth++ = '\0'; 479 480 new_encr = os_strchr(new_auth, ' '); 481 if (new_encr == NULL) 482 return -1; 483 *new_encr++ = '\0'; 484 485 new_key = os_strchr(new_encr, ' '); 486 if (new_key == NULL) 487 return -1; 488 *new_key++ = '\0'; 489 490 os_memset(&ap, 0, sizeof(ap)); 491 ap.ssid_hex = new_ssid; 492 ap.auth = new_auth; 493 ap.encr = new_encr; 494 ap.key_hex = new_key; 495 return wpas_wps_start_reg(wpa_s, bssid, pin, &ap); 496} 497 498 499#ifdef CONFIG_AP 500static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s, 501 char *cmd, char *buf, 502 size_t buflen) 503{ 504 int timeout = 300; 505 char *pos; 506 const char *pin_txt; 507 508 if (!wpa_s->ap_iface) 509 return -1; 510 511 pos = os_strchr(cmd, ' '); 512 if (pos) 513 *pos++ = '\0'; 514 515 if (os_strcmp(cmd, "disable") == 0) { 516 wpas_wps_ap_pin_disable(wpa_s); 517 return os_snprintf(buf, buflen, "OK\n"); 518 } 519 520 if (os_strcmp(cmd, "random") == 0) { 521 if (pos) 522 timeout = atoi(pos); 523 pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout); 524 if (pin_txt == NULL) 525 return -1; 526 return os_snprintf(buf, buflen, "%s", pin_txt); 527 } 528 529 if (os_strcmp(cmd, "get") == 0) { 530 pin_txt = wpas_wps_ap_pin_get(wpa_s); 531 if (pin_txt == NULL) 532 return -1; 533 return os_snprintf(buf, buflen, "%s", pin_txt); 534 } 535 536 if (os_strcmp(cmd, "set") == 0) { 537 char *pin; 538 if (pos == NULL) 539 return -1; 540 pin = pos; 541 pos = os_strchr(pos, ' '); 542 if (pos) { 543 *pos++ = '\0'; 544 timeout = atoi(pos); 545 } 546 if (os_strlen(pin) > buflen) 547 return -1; 548 if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0) 549 return -1; 550 return os_snprintf(buf, buflen, "%s", pin); 551 } 552 553 return -1; 554} 555#endif /* CONFIG_AP */ 556 557 558#ifdef CONFIG_WPS_ER 559static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s, 560 char *cmd) 561{ 562 char *uuid = cmd, *pin, *pos; 563 u8 addr_buf[ETH_ALEN], *addr = NULL; 564 pin = os_strchr(uuid, ' '); 565 if (pin == NULL) 566 return -1; 567 *pin++ = '\0'; 568 pos = os_strchr(pin, ' '); 569 if (pos) { 570 *pos++ = '\0'; 571 if (hwaddr_aton(pos, addr_buf) == 0) 572 addr = addr_buf; 573 } 574 return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin); 575} 576 577 578static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s, 579 char *cmd) 580{ 581 char *uuid = cmd, *pin; 582 pin = os_strchr(uuid, ' '); 583 if (pin == NULL) 584 return -1; 585 *pin++ = '\0'; 586 return wpas_wps_er_learn(wpa_s, uuid, pin); 587} 588 589 590static int wpa_supplicant_ctrl_iface_wps_er_set_config( 591 struct wpa_supplicant *wpa_s, char *cmd) 592{ 593 char *uuid = cmd, *id; 594 id = os_strchr(uuid, ' '); 595 if (id == NULL) 596 return -1; 597 *id++ = '\0'; 598 return wpas_wps_er_set_config(wpa_s, uuid, atoi(id)); 599} 600 601 602static int wpa_supplicant_ctrl_iface_wps_er_config( 603 struct wpa_supplicant *wpa_s, char *cmd) 604{ 605 char *pin; 606 char *new_ssid; 607 char *new_auth; 608 char *new_encr; 609 char *new_key; 610 struct wps_new_ap_settings ap; 611 612 pin = os_strchr(cmd, ' '); 613 if (pin == NULL) 614 return -1; 615 *pin++ = '\0'; 616 617 new_ssid = os_strchr(pin, ' '); 618 if (new_ssid == NULL) 619 return -1; 620 *new_ssid++ = '\0'; 621 622 new_auth = os_strchr(new_ssid, ' '); 623 if (new_auth == NULL) 624 return -1; 625 *new_auth++ = '\0'; 626 627 new_encr = os_strchr(new_auth, ' '); 628 if (new_encr == NULL) 629 return -1; 630 *new_encr++ = '\0'; 631 632 new_key = os_strchr(new_encr, ' '); 633 if (new_key == NULL) 634 return -1; 635 *new_key++ = '\0'; 636 637 os_memset(&ap, 0, sizeof(ap)); 638 ap.ssid_hex = new_ssid; 639 ap.auth = new_auth; 640 ap.encr = new_encr; 641 ap.key_hex = new_key; 642 return wpas_wps_er_config(wpa_s, cmd, pin, &ap); 643} 644#endif /* CONFIG_WPS_ER */ 645 646#endif /* CONFIG_WPS */ 647 648 649#ifdef CONFIG_IBSS_RSN 650static int wpa_supplicant_ctrl_iface_ibss_rsn( 651 struct wpa_supplicant *wpa_s, char *addr) 652{ 653 u8 peer[ETH_ALEN]; 654 655 if (hwaddr_aton(addr, peer)) { 656 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid " 657 "address '%s'", addr); 658 return -1; 659 } 660 661 wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR, 662 MAC2STR(peer)); 663 664 return ibss_rsn_start(wpa_s->ibss_rsn, peer); 665} 666#endif /* CONFIG_IBSS_RSN */ 667 668 669static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, 670 char *rsp) 671{ 672#ifdef IEEE8021X_EAPOL 673 char *pos, *id_pos; 674 int id; 675 struct wpa_ssid *ssid; 676 struct eap_peer_config *eap; 677 678 pos = os_strchr(rsp, '-'); 679 if (pos == NULL) 680 return -1; 681 *pos++ = '\0'; 682 id_pos = pos; 683 pos = os_strchr(pos, ':'); 684 if (pos == NULL) 685 return -1; 686 *pos++ = '\0'; 687 id = atoi(id_pos); 688 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); 689 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 690 (u8 *) pos, os_strlen(pos)); 691 692 ssid = wpa_config_get_network(wpa_s->conf, id); 693 if (ssid == NULL) { 694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 695 "to update", id); 696 return -1; 697 } 698 eap = &ssid->eap; 699 700 if (os_strcmp(rsp, "IDENTITY") == 0) { 701 os_free(eap->identity); 702 eap->identity = (u8 *) os_strdup(pos); 703 eap->identity_len = os_strlen(pos); 704 eap->pending_req_identity = 0; 705 if (ssid == wpa_s->current_ssid) 706 wpa_s->reassociate = 1; 707 } else if (os_strcmp(rsp, "PASSWORD") == 0) { 708 os_free(eap->password); 709 eap->password = (u8 *) os_strdup(pos); 710 eap->password_len = os_strlen(pos); 711 eap->pending_req_password = 0; 712 if (ssid == wpa_s->current_ssid) 713 wpa_s->reassociate = 1; 714 } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { 715 os_free(eap->new_password); 716 eap->new_password = (u8 *) os_strdup(pos); 717 eap->new_password_len = os_strlen(pos); 718 eap->pending_req_new_password = 0; 719 if (ssid == wpa_s->current_ssid) 720 wpa_s->reassociate = 1; 721 } else if (os_strcmp(rsp, "PIN") == 0) { 722 os_free(eap->pin); 723 eap->pin = os_strdup(pos); 724 eap->pending_req_pin = 0; 725 if (ssid == wpa_s->current_ssid) 726 wpa_s->reassociate = 1; 727 } else if (os_strcmp(rsp, "OTP") == 0) { 728 os_free(eap->otp); 729 eap->otp = (u8 *) os_strdup(pos); 730 eap->otp_len = os_strlen(pos); 731 os_free(eap->pending_req_otp); 732 eap->pending_req_otp = NULL; 733 eap->pending_req_otp_len = 0; 734 } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { 735 os_free(eap->private_key_passwd); 736 eap->private_key_passwd = (u8 *) os_strdup(pos); 737 eap->pending_req_passphrase = 0; 738 if (ssid == wpa_s->current_ssid) 739 wpa_s->reassociate = 1; 740 } else { 741 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); 742 return -1; 743 } 744 745 return 0; 746#else /* IEEE8021X_EAPOL */ 747 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 748 return -1; 749#endif /* IEEE8021X_EAPOL */ 750} 751 752 753static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, 754 const char *params, 755 char *buf, size_t buflen) 756{ 757 char *pos, *end, tmp[30]; 758 int res, verbose, ret; 759 760 verbose = os_strcmp(params, "-VERBOSE") == 0; 761 pos = buf; 762 end = buf + buflen; 763 if (wpa_s->wpa_state >= WPA_ASSOCIATED) { 764 struct wpa_ssid *ssid = wpa_s->current_ssid; 765 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", 766 MAC2STR(wpa_s->bssid)); 767 if (ret < 0 || ret >= end - pos) 768 return pos - buf; 769 pos += ret; 770 if (ssid) { 771 u8 *_ssid = ssid->ssid; 772 size_t ssid_len = ssid->ssid_len; 773 u8 ssid_buf[MAX_SSID_LEN]; 774 if (ssid_len == 0) { 775 int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); 776 if (_res < 0) 777 ssid_len = 0; 778 else 779 ssid_len = _res; 780 _ssid = ssid_buf; 781 } 782 ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", 783 wpa_ssid_txt(_ssid, ssid_len), 784 ssid->id); 785 if (ret < 0 || ret >= end - pos) 786 return pos - buf; 787 pos += ret; 788 789 if (ssid->id_str) { 790 ret = os_snprintf(pos, end - pos, 791 "id_str=%s\n", 792 ssid->id_str); 793 if (ret < 0 || ret >= end - pos) 794 return pos - buf; 795 pos += ret; 796 } 797 798 switch (ssid->mode) { 799 case WPAS_MODE_INFRA: 800 ret = os_snprintf(pos, end - pos, 801 "mode=station\n"); 802 break; 803 case WPAS_MODE_IBSS: 804 ret = os_snprintf(pos, end - pos, 805 "mode=IBSS\n"); 806 break; 807 case WPAS_MODE_AP: 808 ret = os_snprintf(pos, end - pos, 809 "mode=AP\n"); 810 break; 811 case WPAS_MODE_P2P_GO: 812 ret = os_snprintf(pos, end - pos, 813 "mode=P2P GO\n"); 814 break; 815 case WPAS_MODE_P2P_GROUP_FORMATION: 816 ret = os_snprintf(pos, end - pos, 817 "mode=P2P GO - group " 818 "formation\n"); 819 break; 820 default: 821 ret = 0; 822 break; 823 } 824 if (ret < 0 || ret >= end - pos) 825 return pos - buf; 826 pos += ret; 827 } 828 829#ifdef CONFIG_AP 830 if (wpa_s->ap_iface) { 831 pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, 832 end - pos, 833 verbose); 834 } else 835#endif /* CONFIG_AP */ 836 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); 837 } 838 ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", 839 wpa_supplicant_state_txt(wpa_s->wpa_state)); 840 if (ret < 0 || ret >= end - pos) 841 return pos - buf; 842 pos += ret; 843 844 if (wpa_s->l2 && 845 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { 846 ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); 847 if (ret < 0 || ret >= end - pos) 848 return pos - buf; 849 pos += ret; 850 } 851 852#ifdef CONFIG_P2P 853 if (wpa_s->global->p2p) { 854 ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR 855 "\n", MAC2STR(wpa_s->global->p2p_dev_addr)); 856 if (ret < 0 || ret >= end - pos) 857 return pos - buf; 858 pos += ret; 859 } 860#endif /* CONFIG_P2P */ 861 862 ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n", 863 MAC2STR(wpa_s->own_addr)); 864 if (ret < 0 || ret >= end - pos) 865 return pos - buf; 866 pos += ret; 867 868 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || 869 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 870 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, 871 verbose); 872 if (res >= 0) 873 pos += res; 874 } 875 876 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); 877 if (res >= 0) 878 pos += res; 879 880 return pos - buf; 881} 882 883 884static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, 885 char *cmd) 886{ 887 char *pos; 888 int id; 889 struct wpa_ssid *ssid; 890 u8 bssid[ETH_ALEN]; 891 892 /* cmd: "<network id> <BSSID>" */ 893 pos = os_strchr(cmd, ' '); 894 if (pos == NULL) 895 return -1; 896 *pos++ = '\0'; 897 id = atoi(cmd); 898 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); 899 if (hwaddr_aton(pos, bssid)) { 900 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); 901 return -1; 902 } 903 904 ssid = wpa_config_get_network(wpa_s->conf, id); 905 if (ssid == NULL) { 906 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 907 "to update", id); 908 return -1; 909 } 910 911 os_memcpy(ssid->bssid, bssid, ETH_ALEN); 912 ssid->bssid_set = !is_zero_ether_addr(bssid); 913 914 return 0; 915} 916 917 918extern int wpa_debug_level; 919extern int wpa_debug_timestamp; 920 921static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s, 922 char *cmd, char *buf, size_t buflen) 923{ 924 char *pos, *end, *stamp; 925 int ret; 926 927 if (cmd == NULL) 928 return -1; 929 /* cmd: "LOG_LEVEL [<level>]" */ 930 if (*cmd == '\0') { 931 pos = buf; 932 end = buf + buflen; 933 ret = os_snprintf(pos, end-pos, "Current level: %d\n" 934 "{0-EXCESSIVE, 1-MSGDUMP, 2-DEBUG, 3-INFO, 4-WARNING, 5-ERROR}\n" 935 "Timestamp: %d\n", wpa_debug_level, wpa_debug_timestamp); 936 if ((ret < 0) || (ret >= end - pos)) 937 ret = 0; 938 return ret; 939 } 940 941 cmd++; 942 stamp = os_strchr(cmd, ' '); 943 if (stamp) { 944 *stamp++ = '\0'; 945 while (*stamp == ' ') 946 stamp++; 947 } 948 949 if (cmd && os_strlen(cmd)) 950 wpa_debug_level = atoi(cmd); 951 952 if (stamp && os_strlen(stamp)) 953 wpa_debug_timestamp = atoi(stamp); 954 955 os_memcpy(buf, "OK\n", 3); 956 return 3; 957} 958 959 960static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s, 961 char *cmd, char *buf, size_t buflen) 962{ 963 u8 bssid[ETH_ALEN]; 964 struct wpa_blacklist *e; 965 char *pos, *end; 966 int ret; 967 968 /* cmd: "BLACKLIST [<BSSID>]" */ 969 if (*cmd == '\0') { 970 pos = buf; 971 end = buf + buflen; 972 e = wpa_s->blacklist; 973 while (e) { 974 ret = os_snprintf(pos, end-pos, MACSTR"\n", MAC2STR(e->bssid)); 975 if ((ret < 0) || (ret >= end - pos)) 976 return pos - buf; 977 pos += ret; 978 e = e->next; 979 } 980 return pos - buf; 981 } 982 983 cmd++; 984 if (os_strncmp(cmd, "clear", 5) == 0) { 985 wpa_blacklist_clear(wpa_s); 986 os_memcpy(buf, "OK\n", 3); 987 return 3; 988 } 989 990 wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd); 991 if (hwaddr_aton(cmd, bssid)) { 992 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", cmd); 993 return -1; 994 } 995 996 /* Add the BSSID twice, so its count will be 2, causing it to be 997 skipped when processing scan results. */ 998 ret = wpa_blacklist_add(wpa_s, bssid); 999 if (ret < 0) 1000 return -1; 1001 ret = wpa_blacklist_add(wpa_s, bssid); 1002 if (ret < 0) 1003 return -1; 1004 os_memcpy(buf, "OK\n", 3); 1005 return 3; 1006} 1007 1008 1009static int wpa_supplicant_ctrl_iface_list_networks( 1010 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1011{ 1012 char *pos, *end; 1013 struct wpa_ssid *ssid; 1014 int ret; 1015 1016 pos = buf; 1017 end = buf + buflen; 1018 ret = os_snprintf(pos, end - pos, 1019 "network id / ssid / bssid / flags\n"); 1020 if (ret < 0 || ret >= end - pos) 1021 return pos - buf; 1022 pos += ret; 1023 1024 ssid = wpa_s->conf->ssid; 1025 while (ssid) { 1026 ret = os_snprintf(pos, end - pos, "%d\t%s", 1027 ssid->id, 1028 wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); 1029 if (ret < 0 || ret >= end - pos) 1030 return pos - buf; 1031 pos += ret; 1032 if (ssid->bssid_set) { 1033 ret = os_snprintf(pos, end - pos, "\t" MACSTR, 1034 MAC2STR(ssid->bssid)); 1035 } else { 1036 ret = os_snprintf(pos, end - pos, "\tany"); 1037 } 1038 if (ret < 0 || ret >= end - pos) 1039 return pos - buf; 1040 pos += ret; 1041 ret = os_snprintf(pos, end - pos, "\t%s%s%s", 1042 ssid == wpa_s->current_ssid ? 1043 "[CURRENT]" : "", 1044 ssid->disabled ? "[DISABLED]" : "", 1045 ssid->disabled == 2 ? "[P2P-PERSISTENT]" : 1046 ""); 1047 if (ret < 0 || ret >= end - pos) 1048 return pos - buf; 1049 pos += ret; 1050 ret = os_snprintf(pos, end - pos, "\n"); 1051 if (ret < 0 || ret >= end - pos) 1052 return pos - buf; 1053 pos += ret; 1054 1055 ssid = ssid->next; 1056 } 1057 1058 return pos - buf; 1059} 1060 1061 1062static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) 1063{ 1064 int first = 1, ret; 1065 ret = os_snprintf(pos, end - pos, "-"); 1066 if (ret < 0 || ret >= end - pos) 1067 return pos; 1068 pos += ret; 1069 if (cipher & WPA_CIPHER_NONE) { 1070 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); 1071 if (ret < 0 || ret >= end - pos) 1072 return pos; 1073 pos += ret; 1074 first = 0; 1075 } 1076 if (cipher & WPA_CIPHER_WEP40) { 1077 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); 1078 if (ret < 0 || ret >= end - pos) 1079 return pos; 1080 pos += ret; 1081 first = 0; 1082 } 1083 if (cipher & WPA_CIPHER_WEP104) { 1084 ret = os_snprintf(pos, end - pos, "%sWEP104", 1085 first ? "" : "+"); 1086 if (ret < 0 || ret >= end - pos) 1087 return pos; 1088 pos += ret; 1089 first = 0; 1090 } 1091 if (cipher & WPA_CIPHER_TKIP) { 1092 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); 1093 if (ret < 0 || ret >= end - pos) 1094 return pos; 1095 pos += ret; 1096 first = 0; 1097 } 1098 if (cipher & WPA_CIPHER_CCMP) { 1099 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); 1100 if (ret < 0 || ret >= end - pos) 1101 return pos; 1102 pos += ret; 1103 first = 0; 1104 } 1105 return pos; 1106} 1107 1108 1109static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, 1110 const u8 *ie, size_t ie_len) 1111{ 1112 struct wpa_ie_data data; 1113 int first, ret; 1114 1115 ret = os_snprintf(pos, end - pos, "[%s-", proto); 1116 if (ret < 0 || ret >= end - pos) 1117 return pos; 1118 pos += ret; 1119 1120 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { 1121 ret = os_snprintf(pos, end - pos, "?]"); 1122 if (ret < 0 || ret >= end - pos) 1123 return pos; 1124 pos += ret; 1125 return pos; 1126 } 1127 1128 first = 1; 1129 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1130 ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); 1131 if (ret < 0 || ret >= end - pos) 1132 return pos; 1133 pos += ret; 1134 first = 0; 1135 } 1136 if (data.key_mgmt & WPA_KEY_MGMT_PSK) { 1137 ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); 1138 if (ret < 0 || ret >= end - pos) 1139 return pos; 1140 pos += ret; 1141 first = 0; 1142 } 1143 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { 1144 ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); 1145 if (ret < 0 || ret >= end - pos) 1146 return pos; 1147 pos += ret; 1148 first = 0; 1149 } 1150#ifdef CONFIG_IEEE80211R 1151 if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1152 ret = os_snprintf(pos, end - pos, "%sFT/EAP", 1153 first ? "" : "+"); 1154 if (ret < 0 || ret >= end - pos) 1155 return pos; 1156 pos += ret; 1157 first = 0; 1158 } 1159 if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1160 ret = os_snprintf(pos, end - pos, "%sFT/PSK", 1161 first ? "" : "+"); 1162 if (ret < 0 || ret >= end - pos) 1163 return pos; 1164 pos += ret; 1165 first = 0; 1166 } 1167#endif /* CONFIG_IEEE80211R */ 1168#ifdef CONFIG_IEEE80211W 1169 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1170 ret = os_snprintf(pos, end - pos, "%sEAP-SHA256", 1171 first ? "" : "+"); 1172 if (ret < 0 || ret >= end - pos) 1173 return pos; 1174 pos += ret; 1175 first = 0; 1176 } 1177 if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1178 ret = os_snprintf(pos, end - pos, "%sPSK-SHA256", 1179 first ? "" : "+"); 1180 if (ret < 0 || ret >= end - pos) 1181 return pos; 1182 pos += ret; 1183 first = 0; 1184 } 1185#endif /* CONFIG_IEEE80211W */ 1186 1187 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); 1188 1189 if (data.capabilities & WPA_CAPABILITY_PREAUTH) { 1190 ret = os_snprintf(pos, end - pos, "-preauth"); 1191 if (ret < 0 || ret >= end - pos) 1192 return pos; 1193 pos += ret; 1194 } 1195 1196 ret = os_snprintf(pos, end - pos, "]"); 1197 if (ret < 0 || ret >= end - pos) 1198 return pos; 1199 pos += ret; 1200 1201 return pos; 1202} 1203 1204 1205#ifdef CONFIG_WPS 1206static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s, 1207 char *pos, char *end, 1208 struct wpabuf *wps_ie) 1209{ 1210 int ret; 1211 const char *txt; 1212 1213 if (wps_ie == NULL) 1214 return pos; 1215 if (wps_is_selected_pbc_registrar(wps_ie)) 1216 txt = "[WPS-PBC]"; 1217#ifdef CONFIG_WPS2 1218 else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0)) 1219 txt = "[WPS-AUTH]"; 1220#endif /* CONFIG_WPS2 */ 1221 else if (wps_is_selected_pin_registrar(wps_ie)) 1222 txt = "[WPS-PIN]"; 1223 else 1224 txt = "[WPS]"; 1225 1226 ret = os_snprintf(pos, end - pos, "%s", txt); 1227 if (ret >= 0 && ret < end - pos) 1228 pos += ret; 1229 wpabuf_free(wps_ie); 1230 return pos; 1231} 1232#endif /* CONFIG_WPS */ 1233 1234 1235static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s, 1236 char *pos, char *end, 1237 const struct wpa_bss *bss) 1238{ 1239#ifdef CONFIG_WPS 1240 struct wpabuf *wps_ie; 1241 wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE); 1242 return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie); 1243#else /* CONFIG_WPS */ 1244 return pos; 1245#endif /* CONFIG_WPS */ 1246} 1247 1248 1249/* Format one result on one text line into a buffer. */ 1250static int wpa_supplicant_ctrl_iface_scan_result( 1251 struct wpa_supplicant *wpa_s, 1252 const struct wpa_bss *bss, char *buf, size_t buflen) 1253{ 1254 char *pos, *end; 1255 int ret; 1256 const u8 *ie, *ie2, *p2p; 1257 1258 p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); 1259 if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN && 1260 os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 1261 0) 1262 return 0; /* Do not show P2P listen discovery results here */ 1263 1264 pos = buf; 1265 end = buf + buflen; 1266 1267 ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", 1268 MAC2STR(bss->bssid), bss->freq, bss->level); 1269 if (ret < 0 || ret >= end - pos) 1270 return -1; 1271 pos += ret; 1272 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 1273 if (ie) 1274 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 1275 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 1276 if (ie2) 1277 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 1278 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 1279 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 1280 ret = os_snprintf(pos, end - pos, "[WEP]"); 1281 if (ret < 0 || ret >= end - pos) 1282 return -1; 1283 pos += ret; 1284 } 1285 if (bss->caps & IEEE80211_CAP_IBSS) { 1286 ret = os_snprintf(pos, end - pos, "[IBSS]"); 1287 if (ret < 0 || ret >= end - pos) 1288 return -1; 1289 pos += ret; 1290 } 1291 if (bss->caps & IEEE80211_CAP_ESS) { 1292 ret = os_snprintf(pos, end - pos, "[ESS]"); 1293 if (ret < 0 || ret >= end - pos) 1294 return -1; 1295 pos += ret; 1296 } 1297 if (p2p) { 1298 ret = os_snprintf(pos, end - pos, "[P2P]"); 1299 if (ret < 0 || ret >= end - pos) 1300 return -1; 1301 pos += ret; 1302 } 1303 1304 ret = os_snprintf(pos, end - pos, "\t%s", 1305 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 1306 if (ret < 0 || ret >= end - pos) 1307 return -1; 1308 pos += ret; 1309 1310 ret = os_snprintf(pos, end - pos, "\n"); 1311 if (ret < 0 || ret >= end - pos) 1312 return -1; 1313 pos += ret; 1314 1315 return pos - buf; 1316} 1317 1318 1319static int wpa_supplicant_ctrl_iface_scan_results( 1320 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1321{ 1322 char *pos, *end; 1323 struct wpa_bss *bss; 1324 int ret; 1325 1326 pos = buf; 1327 end = buf + buflen; 1328 ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " 1329 "flags / ssid\n"); 1330 if (ret < 0 || ret >= end - pos) 1331 return pos - buf; 1332 pos += ret; 1333 1334 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 1335 ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos, 1336 end - pos); 1337 if (ret < 0 || ret >= end - pos) 1338 return pos - buf; 1339 pos += ret; 1340 } 1341 1342 return pos - buf; 1343} 1344 1345 1346static int wpa_supplicant_ctrl_iface_select_network( 1347 struct wpa_supplicant *wpa_s, char *cmd) 1348{ 1349 int id; 1350 struct wpa_ssid *ssid; 1351 1352 /* cmd: "<network id>" or "any" */ 1353 if (os_strcmp(cmd, "any") == 0) { 1354 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); 1355 ssid = NULL; 1356 } else { 1357 id = atoi(cmd); 1358 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); 1359 1360 ssid = wpa_config_get_network(wpa_s->conf, id); 1361 if (ssid == NULL) { 1362 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1363 "network id=%d", id); 1364 return -1; 1365 } 1366 if (ssid->disabled == 2) { 1367 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1368 "SELECT_NETWORK with persistent P2P group"); 1369 return -1; 1370 } 1371 } 1372 1373 wpa_supplicant_select_network(wpa_s, ssid); 1374 1375 return 0; 1376} 1377 1378 1379static int wpa_supplicant_ctrl_iface_enable_network( 1380 struct wpa_supplicant *wpa_s, char *cmd) 1381{ 1382 int id; 1383 struct wpa_ssid *ssid; 1384 1385 /* cmd: "<network id>" or "all" */ 1386 if (os_strcmp(cmd, "all") == 0) { 1387 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all"); 1388 ssid = NULL; 1389 } else { 1390 id = atoi(cmd); 1391 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); 1392 1393 ssid = wpa_config_get_network(wpa_s->conf, id); 1394 if (ssid == NULL) { 1395 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1396 "network id=%d", id); 1397 return -1; 1398 } 1399 if (ssid->disabled == 2) { 1400 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1401 "ENABLE_NETWORK with persistent P2P group"); 1402 return -1; 1403 } 1404 } 1405 wpa_supplicant_enable_network(wpa_s, ssid); 1406 1407 return 0; 1408} 1409 1410 1411static int wpa_supplicant_ctrl_iface_disable_network( 1412 struct wpa_supplicant *wpa_s, char *cmd) 1413{ 1414 int id; 1415 struct wpa_ssid *ssid; 1416 1417 /* cmd: "<network id>" or "all" */ 1418 if (os_strcmp(cmd, "all") == 0) { 1419 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all"); 1420 ssid = NULL; 1421 } else { 1422 id = atoi(cmd); 1423 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); 1424 1425 ssid = wpa_config_get_network(wpa_s->conf, id); 1426 if (ssid == NULL) { 1427 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find " 1428 "network id=%d", id); 1429 return -1; 1430 } 1431 if (ssid->disabled == 2) { 1432 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use " 1433 "DISABLE_NETWORK with persistent P2P " 1434 "group"); 1435 return -1; 1436 } 1437 } 1438 wpa_supplicant_disable_network(wpa_s, ssid); 1439 1440 return 0; 1441} 1442 1443 1444static int wpa_supplicant_ctrl_iface_add_network( 1445 struct wpa_supplicant *wpa_s, char *buf, size_t buflen) 1446{ 1447 struct wpa_ssid *ssid; 1448 int ret; 1449 1450 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); 1451 1452 ssid = wpa_config_add_network(wpa_s->conf); 1453 if (ssid == NULL) 1454 return -1; 1455 1456 wpas_notify_network_added(wpa_s, ssid); 1457 1458 ssid->disabled = 1; 1459 wpa_config_set_network_defaults(ssid); 1460 1461 ret = os_snprintf(buf, buflen, "%d\n", ssid->id); 1462 if (ret < 0 || (size_t) ret >= buflen) 1463 return -1; 1464 return ret; 1465} 1466 1467 1468static int wpa_supplicant_ctrl_iface_remove_network( 1469 struct wpa_supplicant *wpa_s, char *cmd) 1470{ 1471 int id; 1472 struct wpa_ssid *ssid; 1473 1474 /* cmd: "<network id>" or "all" */ 1475 if (os_strcmp(cmd, "all") == 0) { 1476 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); 1477 ssid = wpa_s->conf->ssid; 1478 while (ssid) { 1479 struct wpa_ssid *remove_ssid = ssid; 1480 id = ssid->id; 1481 ssid = ssid->next; 1482 wpas_notify_network_removed(wpa_s, remove_ssid); 1483 wpa_config_remove_network(wpa_s->conf, id); 1484 } 1485 if (wpa_s->current_ssid) { 1486 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1487 wpa_supplicant_disassociate(wpa_s, 1488 WLAN_REASON_DEAUTH_LEAVING); 1489 } 1490 return 0; 1491 } 1492 1493 id = atoi(cmd); 1494 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); 1495 1496 ssid = wpa_config_get_network(wpa_s->conf, id); 1497 if (ssid == NULL || 1498 wpa_config_remove_network(wpa_s->conf, id) < 0) { 1499 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1500 "id=%d", id); 1501 return -1; 1502 } 1503 1504 if (ssid == wpa_s->current_ssid) { 1505 /* 1506 * Invalidate the EAP session cache if the current network is 1507 * removed. 1508 */ 1509 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1510 1511 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1512 } 1513 1514 return 0; 1515} 1516 1517 1518static int wpa_supplicant_ctrl_iface_set_network( 1519 struct wpa_supplicant *wpa_s, char *cmd) 1520{ 1521 int id; 1522 struct wpa_ssid *ssid; 1523 char *name, *value; 1524 1525 /* cmd: "<network id> <variable name> <value>" */ 1526 name = os_strchr(cmd, ' '); 1527 if (name == NULL) 1528 return -1; 1529 *name++ = '\0'; 1530 1531 value = os_strchr(name, ' '); 1532 if (value == NULL) 1533 return -1; 1534 *value++ = '\0'; 1535 1536 id = atoi(cmd); 1537 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", 1538 id, name); 1539 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", 1540 (u8 *) value, os_strlen(value)); 1541 1542 ssid = wpa_config_get_network(wpa_s->conf, id); 1543 if (ssid == NULL) { 1544 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1545 "id=%d", id); 1546 return -1; 1547 } 1548 1549 if (wpa_config_set(ssid, name, value, 0) < 0) { 1550 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " 1551 "variable '%s'", name); 1552 return -1; 1553 } 1554 1555 if (wpa_s->current_ssid == ssid) { 1556 /* 1557 * Invalidate the EAP session cache if anything in the current 1558 * configuration changes. 1559 */ 1560 eapol_sm_invalidate_cached_session(wpa_s->eapol); 1561 } 1562 1563 if ((os_strcmp(name, "psk") == 0 && 1564 value[0] == '"' && ssid->ssid_len) || 1565 (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) 1566 wpa_config_update_psk(ssid); 1567 else if (os_strcmp(name, "priority") == 0) 1568 wpa_config_update_prio_list(wpa_s->conf); 1569 1570 return 0; 1571} 1572 1573 1574static int wpa_supplicant_ctrl_iface_get_network( 1575 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) 1576{ 1577 int id; 1578 size_t res; 1579 struct wpa_ssid *ssid; 1580 char *name, *value; 1581 1582 /* cmd: "<network id> <variable name>" */ 1583 name = os_strchr(cmd, ' '); 1584 if (name == NULL || buflen == 0) 1585 return -1; 1586 *name++ = '\0'; 1587 1588 id = atoi(cmd); 1589 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", 1590 id, name); 1591 1592 ssid = wpa_config_get_network(wpa_s->conf, id); 1593 if (ssid == NULL) { 1594 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " 1595 "id=%d", id); 1596 return -1; 1597 } 1598 1599 value = wpa_config_get_no_key(ssid, name); 1600 if (value == NULL) { 1601 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " 1602 "variable '%s'", name); 1603 return -1; 1604 } 1605 1606 res = os_strlcpy(buf, value, buflen); 1607 if (res >= buflen) { 1608 os_free(value); 1609 return -1; 1610 } 1611 1612 os_free(value); 1613 1614 return res; 1615} 1616 1617 1618#ifndef CONFIG_NO_CONFIG_WRITE 1619static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) 1620{ 1621 int ret; 1622 1623 if (!wpa_s->conf->update_config) { 1624 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " 1625 "to update configuration (update_config=0)"); 1626 return -1; 1627 } 1628 1629 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 1630 if (ret) { 1631 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " 1632 "update configuration"); 1633 } else { 1634 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" 1635 " updated"); 1636 } 1637 1638 return ret; 1639} 1640#endif /* CONFIG_NO_CONFIG_WRITE */ 1641 1642 1643static int ctrl_iface_get_capability_pairwise(int res, char *strict, 1644 struct wpa_driver_capa *capa, 1645 char *buf, size_t buflen) 1646{ 1647 int ret, first = 1; 1648 char *pos, *end; 1649 size_t len; 1650 1651 pos = buf; 1652 end = pos + buflen; 1653 1654 if (res < 0) { 1655 if (strict) 1656 return 0; 1657 len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); 1658 if (len >= buflen) 1659 return -1; 1660 return len; 1661 } 1662 1663 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1664 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1665 if (ret < 0 || ret >= end - pos) 1666 return pos - buf; 1667 pos += ret; 1668 first = 0; 1669 } 1670 1671 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1672 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1673 if (ret < 0 || ret >= end - pos) 1674 return pos - buf; 1675 pos += ret; 1676 first = 0; 1677 } 1678 1679 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1680 ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " "); 1681 if (ret < 0 || ret >= end - pos) 1682 return pos - buf; 1683 pos += ret; 1684 first = 0; 1685 } 1686 1687 return pos - buf; 1688} 1689 1690 1691static int ctrl_iface_get_capability_group(int res, char *strict, 1692 struct wpa_driver_capa *capa, 1693 char *buf, size_t buflen) 1694{ 1695 int ret, first = 1; 1696 char *pos, *end; 1697 size_t len; 1698 1699 pos = buf; 1700 end = pos + buflen; 1701 1702 if (res < 0) { 1703 if (strict) 1704 return 0; 1705 len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); 1706 if (len >= buflen) 1707 return -1; 1708 return len; 1709 } 1710 1711 if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1712 ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " "); 1713 if (ret < 0 || ret >= end - pos) 1714 return pos - buf; 1715 pos += ret; 1716 first = 0; 1717 } 1718 1719 if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1720 ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); 1721 if (ret < 0 || ret >= end - pos) 1722 return pos - buf; 1723 pos += ret; 1724 first = 0; 1725 } 1726 1727 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) { 1728 ret = os_snprintf(pos, end - pos, "%sWEP104", 1729 first ? "" : " "); 1730 if (ret < 0 || ret >= end - pos) 1731 return pos - buf; 1732 pos += ret; 1733 first = 0; 1734 } 1735 1736 if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) { 1737 ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " "); 1738 if (ret < 0 || ret >= end - pos) 1739 return pos - buf; 1740 pos += ret; 1741 first = 0; 1742 } 1743 1744 return pos - buf; 1745} 1746 1747 1748static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, 1749 struct wpa_driver_capa *capa, 1750 char *buf, size_t buflen) 1751{ 1752 int ret; 1753 char *pos, *end; 1754 size_t len; 1755 1756 pos = buf; 1757 end = pos + buflen; 1758 1759 if (res < 0) { 1760 if (strict) 1761 return 0; 1762 len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE " 1763 "NONE", buflen); 1764 if (len >= buflen) 1765 return -1; 1766 return len; 1767 } 1768 1769 ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); 1770 if (ret < 0 || ret >= end - pos) 1771 return pos - buf; 1772 pos += ret; 1773 1774 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1775 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 1776 ret = os_snprintf(pos, end - pos, " WPA-EAP"); 1777 if (ret < 0 || ret >= end - pos) 1778 return pos - buf; 1779 pos += ret; 1780 } 1781 1782 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1783 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1784 ret = os_snprintf(pos, end - pos, " WPA-PSK"); 1785 if (ret < 0 || ret >= end - pos) 1786 return pos - buf; 1787 pos += ret; 1788 } 1789 1790 if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1791 ret = os_snprintf(pos, end - pos, " WPA-NONE"); 1792 if (ret < 0 || ret >= end - pos) 1793 return pos - buf; 1794 pos += ret; 1795 } 1796 1797 return pos - buf; 1798} 1799 1800 1801static int ctrl_iface_get_capability_proto(int res, char *strict, 1802 struct wpa_driver_capa *capa, 1803 char *buf, size_t buflen) 1804{ 1805 int ret, first = 1; 1806 char *pos, *end; 1807 size_t len; 1808 1809 pos = buf; 1810 end = pos + buflen; 1811 1812 if (res < 0) { 1813 if (strict) 1814 return 0; 1815 len = os_strlcpy(buf, "RSN WPA", buflen); 1816 if (len >= buflen) 1817 return -1; 1818 return len; 1819 } 1820 1821 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1822 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1823 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); 1824 if (ret < 0 || ret >= end - pos) 1825 return pos - buf; 1826 pos += ret; 1827 first = 0; 1828 } 1829 1830 if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1831 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 1832 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); 1833 if (ret < 0 || ret >= end - pos) 1834 return pos - buf; 1835 pos += ret; 1836 first = 0; 1837 } 1838 1839 return pos - buf; 1840} 1841 1842 1843static int ctrl_iface_get_capability_auth_alg(int res, char *strict, 1844 struct wpa_driver_capa *capa, 1845 char *buf, size_t buflen) 1846{ 1847 int ret, first = 1; 1848 char *pos, *end; 1849 size_t len; 1850 1851 pos = buf; 1852 end = pos + buflen; 1853 1854 if (res < 0) { 1855 if (strict) 1856 return 0; 1857 len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen); 1858 if (len >= buflen) 1859 return -1; 1860 return len; 1861 } 1862 1863 if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) { 1864 ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " "); 1865 if (ret < 0 || ret >= end - pos) 1866 return pos - buf; 1867 pos += ret; 1868 first = 0; 1869 } 1870 1871 if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) { 1872 ret = os_snprintf(pos, end - pos, "%sSHARED", 1873 first ? "" : " "); 1874 if (ret < 0 || ret >= end - pos) 1875 return pos - buf; 1876 pos += ret; 1877 first = 0; 1878 } 1879 1880 if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) { 1881 ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " "); 1882 if (ret < 0 || ret >= end - pos) 1883 return pos - buf; 1884 pos += ret; 1885 first = 0; 1886 } 1887 1888 return pos - buf; 1889} 1890 1891 1892static int wpa_supplicant_ctrl_iface_get_capability( 1893 struct wpa_supplicant *wpa_s, const char *_field, char *buf, 1894 size_t buflen) 1895{ 1896 struct wpa_driver_capa capa; 1897 int res; 1898 char *strict; 1899 char field[30]; 1900 size_t len; 1901 1902 /* Determine whether or not strict checking was requested */ 1903 len = os_strlcpy(field, _field, sizeof(field)); 1904 if (len >= sizeof(field)) 1905 return -1; 1906 strict = os_strchr(field, ' '); 1907 if (strict != NULL) { 1908 *strict++ = '\0'; 1909 if (os_strcmp(strict, "strict") != 0) 1910 return -1; 1911 } 1912 1913 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", 1914 field, strict ? strict : ""); 1915 1916 if (os_strcmp(field, "eap") == 0) { 1917 return eap_get_names(buf, buflen); 1918 } 1919 1920 res = wpa_drv_get_capa(wpa_s, &capa); 1921 1922 if (os_strcmp(field, "pairwise") == 0) 1923 return ctrl_iface_get_capability_pairwise(res, strict, &capa, 1924 buf, buflen); 1925 1926 if (os_strcmp(field, "group") == 0) 1927 return ctrl_iface_get_capability_group(res, strict, &capa, 1928 buf, buflen); 1929 1930 if (os_strcmp(field, "key_mgmt") == 0) 1931 return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, 1932 buf, buflen); 1933 1934 if (os_strcmp(field, "proto") == 0) 1935 return ctrl_iface_get_capability_proto(res, strict, &capa, 1936 buf, buflen); 1937 1938 if (os_strcmp(field, "auth_alg") == 0) 1939 return ctrl_iface_get_capability_auth_alg(res, strict, &capa, 1940 buf, buflen); 1941 1942 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 1943 field); 1944 1945 return -1; 1946} 1947 1948 1949static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, 1950 const char *cmd, char *buf, 1951 size_t buflen) 1952{ 1953 u8 bssid[ETH_ALEN]; 1954 size_t i; 1955 struct wpa_bss *bss; 1956 int ret; 1957 char *pos, *end; 1958 const u8 *ie, *ie2; 1959 1960 if (os_strcmp(cmd, "FIRST") == 0) 1961 bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list); 1962 else if (os_strncmp(cmd, "ID-", 3) == 0) { 1963 i = atoi(cmd + 3); 1964 bss = wpa_bss_get_id(wpa_s, i); 1965 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 1966 i = atoi(cmd + 5); 1967 bss = wpa_bss_get_id(wpa_s, i); 1968 if (bss) { 1969 struct dl_list *next = bss->list_id.next; 1970 if (next == &wpa_s->bss_id) 1971 bss = NULL; 1972 else 1973 bss = dl_list_entry(next, struct wpa_bss, 1974 list_id); 1975 } 1976 } else if (hwaddr_aton(cmd, bssid) == 0) 1977 bss = wpa_bss_get_bssid(wpa_s, bssid); 1978 else { 1979 struct wpa_bss *tmp; 1980 i = atoi(cmd); 1981 bss = NULL; 1982 dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) 1983 { 1984 if (i-- == 0) { 1985 bss = tmp; 1986 break; 1987 } 1988 } 1989 } 1990 1991 if (bss == NULL) 1992 return 0; 1993 1994 pos = buf; 1995 end = buf + buflen; 1996 ret = os_snprintf(pos, end - pos, 1997 "id=%u\n" 1998 "bssid=" MACSTR "\n" 1999 "freq=%d\n" 2000 "beacon_int=%d\n" 2001 "capabilities=0x%04x\n" 2002 "qual=%d\n" 2003 "noise=%d\n" 2004 "level=%d\n" 2005 "tsf=%016llu\n" 2006 "ie=", 2007 bss->id, 2008 MAC2STR(bss->bssid), bss->freq, bss->beacon_int, 2009 bss->caps, bss->qual, bss->noise, bss->level, 2010 (unsigned long long) bss->tsf); 2011 if (ret < 0 || ret >= end - pos) 2012 return pos - buf; 2013 pos += ret; 2014 2015 ie = (const u8 *) (bss + 1); 2016 for (i = 0; i < bss->ie_len; i++) { 2017 ret = os_snprintf(pos, end - pos, "%02x", *ie++); 2018 if (ret < 0 || ret >= end - pos) 2019 return pos - buf; 2020 pos += ret; 2021 } 2022 if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) { 2023 ret = os_snprintf(pos, end - pos, "[P2P]"); 2024 if (ret < 0 || ret >= end - pos) 2025 return pos - buf; 2026 pos += ret; 2027 } 2028 2029 ret = os_snprintf(pos, end - pos, "\n"); 2030 if (ret < 0 || ret >= end - pos) 2031 return pos - buf; 2032 pos += ret; 2033 2034 ret = os_snprintf(pos, end - pos, "flags="); 2035 if (ret < 0 || ret >= end - pos) 2036 return pos - buf; 2037 pos += ret; 2038 2039 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 2040 if (ie) 2041 pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); 2042 ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); 2043 if (ie2) 2044 pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]); 2045 pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); 2046 if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) { 2047 ret = os_snprintf(pos, end - pos, "[WEP]"); 2048 if (ret < 0 || ret >= end - pos) 2049 return pos - buf; 2050 pos += ret; 2051 } 2052 if (bss->caps & IEEE80211_CAP_IBSS) { 2053 ret = os_snprintf(pos, end - pos, "[IBSS]"); 2054 if (ret < 0 || ret >= end - pos) 2055 return pos - buf; 2056 pos += ret; 2057 } 2058 if (bss->caps & IEEE80211_CAP_ESS) { 2059 ret = os_snprintf(pos, end - pos, "[ESS]"); 2060 if (ret < 0 || ret >= end - pos) 2061 return pos - buf; 2062 pos += ret; 2063 } 2064 2065 ret = os_snprintf(pos, end - pos, "\n"); 2066 if (ret < 0 || ret >= end - pos) 2067 return pos - buf; 2068 pos += ret; 2069 2070 ret = os_snprintf(pos, end - pos, "ssid=%s\n", 2071 wpa_ssid_txt(bss->ssid, bss->ssid_len)); 2072 if (ret < 0 || ret >= end - pos) 2073 return pos - buf; 2074 pos += ret; 2075 2076#ifdef CONFIG_WPS 2077 ie = (const u8 *) (bss + 1); 2078 ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); 2079 if (ret < 0 || ret >= end - pos) 2080 return pos - buf; 2081 pos += ret; 2082#endif /* CONFIG_WPS */ 2083 2084#ifdef CONFIG_P2P 2085 ie = (const u8 *) (bss + 1); 2086 ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); 2087 if (ret < 0 || ret >= end - pos) 2088 return pos - buf; 2089 pos += ret; 2090#endif /* CONFIG_P2P */ 2091 2092 return pos - buf; 2093} 2094 2095 2096static int wpa_supplicant_ctrl_iface_ap_scan( 2097 struct wpa_supplicant *wpa_s, char *cmd) 2098{ 2099 int ap_scan = atoi(cmd); 2100 return wpa_supplicant_set_ap_scan(wpa_s, ap_scan); 2101} 2102 2103 2104static int wpa_supplicant_ctrl_iface_scan_interval( 2105 struct wpa_supplicant *wpa_s, char *cmd) 2106{ 2107 int scan_int = atoi(cmd); 2108 if (scan_int < 0) 2109 return -1; 2110 wpa_s->scan_interval = scan_int; 2111 return 0; 2112} 2113 2114 2115static int wpa_supplicant_ctrl_iface_bss_expire_age( 2116 struct wpa_supplicant *wpa_s, char *cmd) 2117{ 2118 int expire_age = atoi(cmd); 2119 return wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age); 2120} 2121 2122 2123static int wpa_supplicant_ctrl_iface_bss_expire_count( 2124 struct wpa_supplicant *wpa_s, char *cmd) 2125{ 2126 int expire_count = atoi(cmd); 2127 return wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count); 2128} 2129 2130 2131static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) 2132{ 2133 wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication"); 2134 /* MLME-DELETEKEYS.request */ 2135 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0); 2136 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0); 2137 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0); 2138 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0); 2139#ifdef CONFIG_IEEE80211W 2140 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0); 2141 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0); 2142#endif /* CONFIG_IEEE80211W */ 2143 2144 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 2145 0); 2146 /* MLME-SETPROTECTION.request(None) */ 2147 wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, 2148 MLME_SETPROTECTION_PROTECT_TYPE_NONE, 2149 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); 2150 wpa_sm_drop_sa(wpa_s->wpa); 2151} 2152 2153 2154static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, 2155 char *addr) 2156{ 2157 u8 bssid[ETH_ALEN]; 2158 struct wpa_bss *bss; 2159 struct wpa_ssid *ssid = wpa_s->current_ssid; 2160 2161 if (hwaddr_aton(addr, bssid)) { 2162 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " 2163 "address '%s'", addr); 2164 return -1; 2165 } 2166 2167 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); 2168 2169 bss = wpa_bss_get_bssid(wpa_s, bssid); 2170 if (!bss) { 2171 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " 2172 "from BSS table"); 2173 return -1; 2174 } 2175 2176 /* 2177 * TODO: Find best network configuration block from configuration to 2178 * allow roaming to other networks 2179 */ 2180 2181 if (!ssid) { 2182 wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " 2183 "configuration known for the target AP"); 2184 return -1; 2185 } 2186 2187 wpa_s->reassociate = 1; 2188 wpa_supplicant_connect(wpa_s, bss, ssid); 2189 2190 return 0; 2191} 2192 2193 2194#ifdef CONFIG_P2P 2195static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) 2196{ 2197 unsigned int timeout = atoi(cmd); 2198 enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; 2199 2200 if (os_strstr(cmd, "type=social")) 2201 type = P2P_FIND_ONLY_SOCIAL; 2202 else if (os_strstr(cmd, "type=progressive")) 2203 type = P2P_FIND_PROGRESSIVE; 2204 2205 return wpas_p2p_find(wpa_s, timeout, type, 0, NULL); 2206} 2207 2208 2209static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, 2210 char *buf, size_t buflen) 2211{ 2212 u8 addr[ETH_ALEN]; 2213 char *pos, *pos2; 2214 char *pin = NULL; 2215 enum p2p_wps_method wps_method; 2216 int new_pin; 2217 int ret; 2218 int persistent_group; 2219 int join; 2220 int auth; 2221 int go_intent = -1; 2222 int freq = 0; 2223 2224 /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent] 2225 * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */ 2226 2227 if (hwaddr_aton(cmd, addr)) 2228 return -1; 2229 2230 pos = cmd + 17; 2231 if (*pos != ' ') 2232 return -1; 2233 pos++; 2234 2235 persistent_group = os_strstr(pos, " persistent") != NULL; 2236 join = os_strstr(pos, " join") != NULL; 2237 auth = os_strstr(pos, " auth") != NULL; 2238 2239 pos2 = os_strstr(pos, " go_intent="); 2240 if (pos2) { 2241 pos2 += 11; 2242 go_intent = atoi(pos2); 2243 if (go_intent < 0 || go_intent > 15) 2244 return -1; 2245 } 2246 2247 pos2 = os_strstr(pos, " freq="); 2248 if (pos2) { 2249 pos2 += 6; 2250 freq = atoi(pos2); 2251 if (freq <= 0) 2252 return -1; 2253 } 2254 2255 if (os_strncmp(pos, "pin", 3) == 0) { 2256 /* Request random PIN (to be displayed) and enable the PIN */ 2257 wps_method = WPS_PIN_DISPLAY; 2258 } else if (os_strncmp(pos, "pbc", 3) == 0) { 2259 wps_method = WPS_PBC; 2260 } else { 2261 pin = pos; 2262 pos = os_strchr(pin, ' '); 2263 wps_method = WPS_PIN_KEYPAD; 2264 if (pos) { 2265 *pos++ = '\0'; 2266 if (os_strncmp(pos, "label", 5) == 0) 2267 wps_method = WPS_PIN_LABEL; 2268 else if (os_strncmp(pos, "display", 7) == 0) 2269 wps_method = WPS_PIN_DISPLAY; 2270 } 2271 } 2272 2273 new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, 2274 persistent_group, join, auth, go_intent, 2275 freq); 2276 if (new_pin == -2) { 2277 os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); 2278 return 25; 2279 } 2280 if (new_pin == -3) { 2281 os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25); 2282 return 25; 2283 } 2284 if (new_pin < 0) 2285 return -1; 2286 if (wps_method == WPS_PIN_DISPLAY && pin == NULL) { 2287 ret = os_snprintf(buf, buflen, "%08d", new_pin); 2288 if (ret < 0 || (size_t) ret >= buflen) 2289 return -1; 2290 return ret; 2291 } 2292 2293 os_memcpy(buf, "OK\n", 3); 2294 return 3; 2295} 2296 2297 2298static int p2p_ctrl_listen(struct wpa_supplicant *wpa_s, char *cmd) 2299{ 2300 unsigned int timeout = atoi(cmd); 2301 return wpas_p2p_listen(wpa_s, timeout); 2302} 2303 2304 2305static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd) 2306{ 2307 u8 addr[ETH_ALEN]; 2308 char *pos; 2309 2310 /* <addr> <config method> */ 2311 2312 if (hwaddr_aton(cmd, addr)) 2313 return -1; 2314 2315 pos = cmd + 17; 2316 if (*pos != ' ') 2317 return -1; 2318 pos++; 2319 2320 return wpas_p2p_prov_disc(wpa_s, addr, pos); 2321} 2322 2323 2324static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf, 2325 size_t buflen) 2326{ 2327 struct wpa_ssid *ssid = wpa_s->current_ssid; 2328 2329 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || 2330 ssid->passphrase == NULL) 2331 return -1; 2332 2333 os_strlcpy(buf, ssid->passphrase, buflen); 2334 return os_strlen(buf); 2335} 2336 2337 2338static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd, 2339 char *buf, size_t buflen) 2340{ 2341 u64 ref; 2342 int res; 2343 u8 dst_buf[ETH_ALEN], *dst; 2344 struct wpabuf *tlvs; 2345 char *pos; 2346 size_t len; 2347 2348 if (hwaddr_aton(cmd, dst_buf)) 2349 return -1; 2350 dst = dst_buf; 2351 if (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 && 2352 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) 2353 dst = NULL; 2354 pos = cmd + 17; 2355 if (*pos != ' ') 2356 return -1; 2357 pos++; 2358 2359 if (os_strncmp(pos, "upnp ", 5) == 0) { 2360 u8 version; 2361 pos += 5; 2362 if (hexstr2bin(pos, &version, 1) < 0) 2363 return -1; 2364 pos += 2; 2365 if (*pos != ' ') 2366 return -1; 2367 pos++; 2368 ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst, 2369 version, pos); 2370 } else { 2371 len = os_strlen(pos); 2372 if (len & 1) 2373 return -1; 2374 len /= 2; 2375 tlvs = wpabuf_alloc(len); 2376 if (tlvs == NULL) 2377 return -1; 2378 if (hexstr2bin(pos, wpabuf_put(tlvs, len), len) < 0) { 2379 wpabuf_free(tlvs); 2380 return -1; 2381 } 2382 2383 ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs); 2384 wpabuf_free(tlvs); 2385 } 2386 res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref); 2387 if (res < 0 || (unsigned) res >= buflen) 2388 return -1; 2389 return res; 2390} 2391 2392 2393static int p2p_ctrl_serv_disc_cancel_req(struct wpa_supplicant *wpa_s, 2394 char *cmd) 2395{ 2396 long long unsigned val; 2397 u64 req; 2398 if (sscanf(cmd, "%llx", &val) != 1) 2399 return -1; 2400 req = val; 2401 return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req); 2402} 2403 2404 2405static int p2p_ctrl_serv_disc_resp(struct wpa_supplicant *wpa_s, char *cmd) 2406{ 2407 int freq; 2408 u8 dst[ETH_ALEN]; 2409 u8 dialog_token; 2410 struct wpabuf *resp_tlvs; 2411 char *pos, *pos2; 2412 size_t len; 2413 2414 pos = os_strchr(cmd, ' '); 2415 if (pos == NULL) 2416 return -1; 2417 *pos++ = '\0'; 2418 freq = atoi(cmd); 2419 if (freq == 0) 2420 return -1; 2421 2422 if (hwaddr_aton(pos, dst)) 2423 return -1; 2424 pos += 17; 2425 if (*pos != ' ') 2426 return -1; 2427 pos++; 2428 2429 pos2 = os_strchr(pos, ' '); 2430 if (pos2 == NULL) 2431 return -1; 2432 *pos2++ = '\0'; 2433 dialog_token = atoi(pos); 2434 2435 len = os_strlen(pos2); 2436 if (len & 1) 2437 return -1; 2438 len /= 2; 2439 resp_tlvs = wpabuf_alloc(len); 2440 if (resp_tlvs == NULL) 2441 return -1; 2442 if (hexstr2bin(pos2, wpabuf_put(resp_tlvs, len), len) < 0) { 2443 wpabuf_free(resp_tlvs); 2444 return -1; 2445 } 2446 2447 wpas_p2p_sd_response(wpa_s, freq, dst, dialog_token, resp_tlvs); 2448 wpabuf_free(resp_tlvs); 2449 return 0; 2450} 2451 2452 2453static int p2p_ctrl_serv_disc_external(struct wpa_supplicant *wpa_s, 2454 char *cmd) 2455{ 2456 wpa_s->p2p_sd_over_ctrl_iface = atoi(cmd); 2457 return 0; 2458} 2459 2460 2461static int p2p_ctrl_service_add_bonjour(struct wpa_supplicant *wpa_s, 2462 char *cmd) 2463{ 2464 char *pos; 2465 size_t len; 2466 struct wpabuf *query, *resp; 2467 2468 pos = os_strchr(cmd, ' '); 2469 if (pos == NULL) 2470 return -1; 2471 *pos++ = '\0'; 2472 2473 len = os_strlen(cmd); 2474 if (len & 1) 2475 return -1; 2476 len /= 2; 2477 query = wpabuf_alloc(len); 2478 if (query == NULL) 2479 return -1; 2480 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 2481 wpabuf_free(query); 2482 return -1; 2483 } 2484 2485 len = os_strlen(pos); 2486 if (len & 1) { 2487 wpabuf_free(query); 2488 return -1; 2489 } 2490 len /= 2; 2491 resp = wpabuf_alloc(len); 2492 if (resp == NULL) { 2493 wpabuf_free(query); 2494 return -1; 2495 } 2496 if (hexstr2bin(pos, wpabuf_put(resp, len), len) < 0) { 2497 wpabuf_free(query); 2498 wpabuf_free(resp); 2499 return -1; 2500 } 2501 2502 if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) { 2503 wpabuf_free(query); 2504 wpabuf_free(resp); 2505 return -1; 2506 } 2507 return 0; 2508} 2509 2510 2511static int p2p_ctrl_service_add_upnp(struct wpa_supplicant *wpa_s, char *cmd) 2512{ 2513 char *pos; 2514 u8 version; 2515 2516 pos = os_strchr(cmd, ' '); 2517 if (pos == NULL) 2518 return -1; 2519 *pos++ = '\0'; 2520 2521 if (hexstr2bin(cmd, &version, 1) < 0) 2522 return -1; 2523 2524 return wpas_p2p_service_add_upnp(wpa_s, version, pos); 2525} 2526 2527 2528static int p2p_ctrl_service_add(struct wpa_supplicant *wpa_s, char *cmd) 2529{ 2530 char *pos; 2531 2532 pos = os_strchr(cmd, ' '); 2533 if (pos == NULL) 2534 return -1; 2535 *pos++ = '\0'; 2536 2537 if (os_strcmp(cmd, "bonjour") == 0) 2538 return p2p_ctrl_service_add_bonjour(wpa_s, pos); 2539 if (os_strcmp(cmd, "upnp") == 0) 2540 return p2p_ctrl_service_add_upnp(wpa_s, pos); 2541 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 2542 return -1; 2543} 2544 2545 2546static int p2p_ctrl_service_del_bonjour(struct wpa_supplicant *wpa_s, 2547 char *cmd) 2548{ 2549 size_t len; 2550 struct wpabuf *query; 2551 int ret; 2552 2553 len = os_strlen(cmd); 2554 if (len & 1) 2555 return -1; 2556 len /= 2; 2557 query = wpabuf_alloc(len); 2558 if (query == NULL) 2559 return -1; 2560 if (hexstr2bin(cmd, wpabuf_put(query, len), len) < 0) { 2561 wpabuf_free(query); 2562 return -1; 2563 } 2564 2565 ret = wpas_p2p_service_del_bonjour(wpa_s, query); 2566 wpabuf_free(query); 2567 return ret; 2568} 2569 2570 2571static int p2p_ctrl_service_del_upnp(struct wpa_supplicant *wpa_s, char *cmd) 2572{ 2573 char *pos; 2574 u8 version; 2575 2576 pos = os_strchr(cmd, ' '); 2577 if (pos == NULL) 2578 return -1; 2579 *pos++ = '\0'; 2580 2581 if (hexstr2bin(cmd, &version, 1) < 0) 2582 return -1; 2583 2584 return wpas_p2p_service_del_upnp(wpa_s, version, pos); 2585} 2586 2587 2588static int p2p_ctrl_service_del(struct wpa_supplicant *wpa_s, char *cmd) 2589{ 2590 char *pos; 2591 2592 pos = os_strchr(cmd, ' '); 2593 if (pos == NULL) 2594 return -1; 2595 *pos++ = '\0'; 2596 2597 if (os_strcmp(cmd, "bonjour") == 0) 2598 return p2p_ctrl_service_del_bonjour(wpa_s, pos); 2599 if (os_strcmp(cmd, "upnp") == 0) 2600 return p2p_ctrl_service_del_upnp(wpa_s, pos); 2601 wpa_printf(MSG_DEBUG, "Unknown service '%s'", cmd); 2602 return -1; 2603} 2604 2605 2606static int p2p_ctrl_reject(struct wpa_supplicant *wpa_s, char *cmd) 2607{ 2608 u8 addr[ETH_ALEN]; 2609 2610 /* <addr> */ 2611 2612 if (hwaddr_aton(cmd, addr)) 2613 return -1; 2614 2615 return wpas_p2p_reject(wpa_s, addr); 2616} 2617 2618 2619static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) 2620{ 2621 char *pos; 2622 int id; 2623 struct wpa_ssid *ssid; 2624 u8 peer[ETH_ALEN]; 2625 2626 id = atoi(cmd); 2627 pos = os_strstr(cmd, " peer="); 2628 if (pos) { 2629 pos += 6; 2630 if (hwaddr_aton(pos, peer)) 2631 return -1; 2632 } 2633 ssid = wpa_config_get_network(wpa_s->conf, id); 2634 if (ssid == NULL || ssid->disabled != 2) { 2635 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2636 "for persistent P2P group", 2637 id); 2638 return -1; 2639 } 2640 2641 return wpas_p2p_invite(wpa_s, pos ? peer : NULL, ssid, NULL); 2642} 2643 2644 2645static int p2p_ctrl_invite_group(struct wpa_supplicant *wpa_s, char *cmd) 2646{ 2647 char *pos; 2648 u8 peer[ETH_ALEN], go_dev_addr[ETH_ALEN], *go_dev = NULL; 2649 2650 pos = os_strstr(cmd, " peer="); 2651 if (!pos) 2652 return -1; 2653 2654 *pos = '\0'; 2655 pos += 6; 2656 if (hwaddr_aton(pos, peer)) { 2657 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", pos); 2658 return -1; 2659 } 2660 2661 pos = os_strstr(pos, " go_dev_addr="); 2662 if (pos) { 2663 pos += 13; 2664 if (hwaddr_aton(pos, go_dev_addr)) { 2665 wpa_printf(MSG_DEBUG, "P2P: Invalid MAC address '%s'", 2666 pos); 2667 return -1; 2668 } 2669 go_dev = go_dev_addr; 2670 } 2671 2672 return wpas_p2p_invite_group(wpa_s, cmd, peer, go_dev); 2673} 2674 2675 2676static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) 2677{ 2678 if (os_strncmp(cmd, "persistent=", 11) == 0) 2679 return p2p_ctrl_invite_persistent(wpa_s, cmd + 11); 2680 if (os_strncmp(cmd, "group=", 6) == 0) 2681 return p2p_ctrl_invite_group(wpa_s, cmd + 6); 2682 2683 return -1; 2684} 2685 2686 2687static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, 2688 char *cmd, int freq) 2689{ 2690 int id; 2691 struct wpa_ssid *ssid; 2692 2693 id = atoi(cmd); 2694 ssid = wpa_config_get_network(wpa_s->conf, id); 2695 if (ssid == NULL || ssid->disabled != 2) { 2696 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " 2697 "for persistent P2P group", 2698 id); 2699 return -1; 2700 } 2701 2702 return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq); 2703} 2704 2705 2706static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) 2707{ 2708 int freq = 0; 2709 char *pos; 2710 2711 pos = os_strstr(cmd, "freq="); 2712 if (pos) 2713 freq = atoi(pos + 5); 2714 2715 if (os_strncmp(cmd, "persistent=", 11) == 0) 2716 return p2p_ctrl_group_add_persistent(wpa_s, cmd + 11, freq); 2717 if (os_strcmp(cmd, "persistent") == 0 || 2718 os_strncmp(cmd, "persistent ", 11) == 0) 2719 return wpas_p2p_group_add(wpa_s, 1, freq); 2720 if (os_strncmp(cmd, "freq=", 5) == 0) 2721 return wpas_p2p_group_add(wpa_s, 0, freq); 2722 2723 wpa_printf(MSG_DEBUG, "CTRL: Invalid P2P_GROUP_ADD parameters '%s'", 2724 cmd); 2725 return -1; 2726} 2727 2728 2729static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, 2730 char *buf, size_t buflen) 2731{ 2732 u8 addr[ETH_ALEN], *addr_ptr; 2733 int next; 2734 2735 if (!wpa_s->global->p2p) 2736 return -1; 2737 2738 if (os_strcmp(cmd, "FIRST") == 0) { 2739 addr_ptr = NULL; 2740 next = 0; 2741 } else if (os_strncmp(cmd, "NEXT-", 5) == 0) { 2742 if (hwaddr_aton(cmd + 5, addr) < 0) 2743 return -1; 2744 addr_ptr = addr; 2745 next = 1; 2746 } else { 2747 if (hwaddr_aton(cmd, addr) < 0) 2748 return -1; 2749 addr_ptr = addr; 2750 next = 0; 2751 } 2752 2753 return p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next, 2754 buf, buflen); 2755} 2756 2757 2758static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) 2759{ 2760 char *param; 2761 2762 if (wpa_s->global->p2p == NULL) 2763 return -1; 2764 2765 param = os_strchr(cmd, ' '); 2766 if (param == NULL) 2767 return -1; 2768 *param++ = '\0'; 2769 2770 if (os_strcmp(cmd, "discoverability") == 0) { 2771 p2p_set_client_discoverability(wpa_s->global->p2p, 2772 atoi(param)); 2773 return 0; 2774 } 2775 2776 if (os_strcmp(cmd, "managed") == 0) { 2777 p2p_set_managed_oper(wpa_s->global->p2p, atoi(param)); 2778 return 0; 2779 } 2780 2781 if (os_strcmp(cmd, "listen_channel") == 0) { 2782 return p2p_set_listen_channel(wpa_s->global->p2p, 81, 2783 atoi(param)); 2784 } 2785 2786 if (os_strcmp(cmd, "ssid_postfix") == 0) { 2787 return p2p_set_ssid_postfix(wpa_s->global->p2p, (u8 *) param, 2788 os_strlen(param)); 2789 } 2790 2791 if (os_strcmp(cmd, "noa") == 0) { 2792 char *pos; 2793 int count, start, duration; 2794 /* GO NoA parameters: count,start_offset(ms),duration(ms) */ 2795 count = atoi(param); 2796 pos = os_strchr(param, ','); 2797 if (pos == NULL) 2798 return -1; 2799 pos++; 2800 start = atoi(pos); 2801 pos = os_strchr(pos, ','); 2802 if (pos == NULL) 2803 return -1; 2804 pos++; 2805 duration = atoi(pos); 2806 if (count < 0 || count > 255 || start < 0 || duration < 0) 2807 return -1; 2808 if (count == 0 && duration > 0) 2809 return -1; 2810 wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d " 2811 "start=%d duration=%d", count, start, duration); 2812 return wpas_p2p_set_noa(wpa_s, count, start, duration); 2813 } 2814 2815 if (os_strcmp(cmd, "ps") == 0) 2816 return wpa_drv_set_p2p_powersave(wpa_s, atoi(param), -1, -1); 2817 2818 if (os_strcmp(cmd, "oppps") == 0) 2819 return wpa_drv_set_p2p_powersave(wpa_s, -1, atoi(param), -1); 2820 2821 if (os_strcmp(cmd, "ctwindow") == 0) 2822 return wpa_drv_set_p2p_powersave(wpa_s, -1, -1, atoi(param)); 2823 2824 if (os_strcmp(cmd, "disabled") == 0) { 2825 wpa_s->global->p2p_disabled = atoi(param); 2826 wpa_printf(MSG_DEBUG, "P2P functionality %s", 2827 wpa_s->global->p2p_disabled ? 2828 "disabled" : "enabled"); 2829 if (wpa_s->global->p2p_disabled) { 2830 wpas_p2p_stop_find(wpa_s); 2831 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 2832 p2p_flush(wpa_s->global->p2p); 2833 } 2834 return 0; 2835 } 2836 2837 if (os_strcmp(cmd, "force_long_sd") == 0) { 2838 wpa_s->force_long_sd = atoi(param); 2839 return 0; 2840 } 2841 2842 if (os_strcmp(cmd, "peer_filter") == 0) { 2843 u8 addr[ETH_ALEN]; 2844 if (hwaddr_aton(param, addr)) 2845 return -1; 2846 p2p_set_peer_filter(wpa_s->global->p2p, addr); 2847 return 0; 2848 } 2849 2850 if (os_strcmp(cmd, "cross_connect") == 0) 2851 return wpas_p2p_set_cross_connect(wpa_s, atoi(param)); 2852 2853 if (os_strcmp(cmd, "go_apsd") == 0) { 2854 if (os_strcmp(param, "disable") == 0) 2855 wpa_s->set_ap_uapsd = 0; 2856 else { 2857 wpa_s->set_ap_uapsd = 1; 2858 wpa_s->ap_uapsd = atoi(param); 2859 } 2860 return 0; 2861 } 2862 2863 if (os_strcmp(cmd, "client_apsd") == 0) { 2864 if (os_strcmp(param, "disable") == 0) 2865 wpa_s->set_sta_uapsd = 0; 2866 else { 2867 int be, bk, vi, vo; 2868 char *pos; 2869 /* format: BE,BK,VI,VO;max SP Length */ 2870 be = atoi(param); 2871 pos = os_strchr(param, ','); 2872 if (pos == NULL) 2873 return -1; 2874 pos++; 2875 bk = atoi(pos); 2876 pos = os_strchr(pos, ','); 2877 if (pos == NULL) 2878 return -1; 2879 pos++; 2880 vi = atoi(pos); 2881 pos = os_strchr(pos, ','); 2882 if (pos == NULL) 2883 return -1; 2884 pos++; 2885 vo = atoi(pos); 2886 /* ignore max SP Length for now */ 2887 2888 wpa_s->set_sta_uapsd = 1; 2889 wpa_s->sta_uapsd = 0; 2890 if (be) 2891 wpa_s->sta_uapsd |= BIT(0); 2892 if (bk) 2893 wpa_s->sta_uapsd |= BIT(1); 2894 if (vi) 2895 wpa_s->sta_uapsd |= BIT(2); 2896 if (vo) 2897 wpa_s->sta_uapsd |= BIT(3); 2898 } 2899 return 0; 2900 } 2901 2902 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", 2903 cmd); 2904 2905 return -1; 2906} 2907 2908 2909static int p2p_ctrl_presence_req(struct wpa_supplicant *wpa_s, char *cmd) 2910{ 2911 char *pos, *pos2; 2912 unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0; 2913 2914 if (cmd[0]) { 2915 pos = os_strchr(cmd, ' '); 2916 if (pos == NULL) 2917 return -1; 2918 *pos++ = '\0'; 2919 dur1 = atoi(cmd); 2920 2921 pos2 = os_strchr(pos, ' '); 2922 if (pos2) 2923 *pos2++ = '\0'; 2924 int1 = atoi(pos); 2925 } else 2926 pos2 = NULL; 2927 2928 if (pos2) { 2929 pos = os_strchr(pos2, ' '); 2930 if (pos == NULL) 2931 return -1; 2932 *pos++ = '\0'; 2933 dur2 = atoi(pos2); 2934 int2 = atoi(pos); 2935 } 2936 2937 return wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2); 2938} 2939 2940 2941static int p2p_ctrl_ext_listen(struct wpa_supplicant *wpa_s, char *cmd) 2942{ 2943 char *pos; 2944 unsigned int period = 0, interval = 0; 2945 2946 if (cmd[0]) { 2947 pos = os_strchr(cmd, ' '); 2948 if (pos == NULL) 2949 return -1; 2950 *pos++ = '\0'; 2951 period = atoi(cmd); 2952 interval = atoi(pos); 2953 } 2954 2955 return wpas_p2p_ext_listen(wpa_s, period, interval); 2956} 2957 2958#endif /* CONFIG_P2P */ 2959 2960 2961static int wpa_supplicant_ctrl_iface_sta_autoconnect( 2962 struct wpa_supplicant *wpa_s, char *cmd) 2963{ 2964 wpa_s->auto_reconnect_disabled = atoi(cmd) == 0 ? 1 : 0; 2965 return 0; 2966} 2967 2968 2969static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, 2970 size_t buflen) 2971{ 2972 struct wpa_signal_info si; 2973 int ret; 2974 2975 ret = wpa_drv_signal_poll(wpa_s, &si); 2976 if (ret) 2977 return -1; 2978 2979 ret = os_snprintf(buf, buflen, "RSSI=%d\nLINKSPEED=%d\n" 2980 "NOISE=%d\nFREQUENCY=%u\n", 2981 si.current_signal, si.current_txrate / 1000, 2982 si.current_noise, si.frequency); 2983 if (ret < 0 || (unsigned int) ret > buflen) 2984 return -1; 2985 return ret; 2986} 2987 2988 2989char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, 2990 char *buf, size_t *resp_len) 2991{ 2992 char *reply; 2993 const int reply_size = 4096; 2994 int ctrl_rsp = 0; 2995 int reply_len; 2996 2997 if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || 2998 os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 2999 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", 3000 (const u8 *) buf, os_strlen(buf)); 3001 } else { 3002 int level = MSG_DEBUG; 3003 if (os_strcmp(buf, "PING") == 0) 3004 level = MSG_EXCESSIVE; 3005 wpa_hexdump_ascii(level, "RX ctrl_iface", 3006 (const u8 *) buf, os_strlen(buf)); 3007 } 3008 3009 reply = os_malloc(reply_size); 3010 if (reply == NULL) { 3011 *resp_len = 1; 3012 return NULL; 3013 } 3014 3015 os_memcpy(reply, "OK\n", 3); 3016 reply_len = 3; 3017 3018 if (os_strcmp(buf, "PING") == 0) { 3019 os_memcpy(reply, "PONG\n", 5); 3020 reply_len = 5; 3021 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 3022 if (wpa_debug_reopen_file() < 0) 3023 reply_len = -1; 3024 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 3025 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 3026 } else if (os_strcmp(buf, "MIB") == 0) { 3027 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); 3028 if (reply_len >= 0) { 3029 int res; 3030 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, 3031 reply_size - reply_len); 3032 if (res < 0) 3033 reply_len = -1; 3034 else 3035 reply_len += res; 3036 } 3037 } else if (os_strncmp(buf, "STATUS", 6) == 0) { 3038 reply_len = wpa_supplicant_ctrl_iface_status( 3039 wpa_s, buf + 6, reply, reply_size); 3040 } else if (os_strcmp(buf, "PMKSA") == 0) { 3041 reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply, 3042 reply_size); 3043 } else if (os_strncmp(buf, "SET ", 4) == 0) { 3044 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) 3045 reply_len = -1; 3046 } else if (os_strncmp(buf, "GET ", 4) == 0) { 3047 reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, 3048 reply, reply_size); 3049 } else if (os_strcmp(buf, "LOGON") == 0) { 3050 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 3051 } else if (os_strcmp(buf, "LOGOFF") == 0) { 3052 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 3053 } else if (os_strcmp(buf, "REASSOCIATE") == 0) { 3054 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 3055 reply_len = -1; 3056 else { 3057 wpa_s->disconnected = 0; 3058 wpa_s->reassociate = 1; 3059 wpa_supplicant_req_scan(wpa_s, 0, 0); 3060 } 3061 } else if (os_strcmp(buf, "RECONNECT") == 0) { 3062 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 3063 reply_len = -1; 3064 else if (wpa_s->disconnected) { 3065 wpa_s->disconnected = 0; 3066 wpa_s->reassociate = 1; 3067 wpa_supplicant_req_scan(wpa_s, 0, 0); 3068 } 3069#ifdef IEEE8021X_EAPOL 3070 } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { 3071 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) 3072 reply_len = -1; 3073#endif /* IEEE8021X_EAPOL */ 3074#ifdef CONFIG_PEERKEY 3075 } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { 3076 if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) 3077 reply_len = -1; 3078#endif /* CONFIG_PEERKEY */ 3079#ifdef CONFIG_IEEE80211R 3080 } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { 3081 if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) 3082 reply_len = -1; 3083#endif /* CONFIG_IEEE80211R */ 3084#ifdef CONFIG_WPS 3085 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 3086 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL); 3087 if (res == -2) { 3088 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 3089 reply_len = 17; 3090 } else if (res) 3091 reply_len = -1; 3092 } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) { 3093 int res = wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8); 3094 if (res == -2) { 3095 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 3096 reply_len = 17; 3097 } else if (res) 3098 reply_len = -1; 3099 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 3100 reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8, 3101 reply, 3102 reply_size); 3103 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 3104 reply_len = wpa_supplicant_ctrl_iface_wps_check_pin( 3105 wpa_s, buf + 14, reply, reply_size); 3106 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 3107 if (wpas_wps_cancel(wpa_s)) 3108 reply_len = -1; 3109#ifdef CONFIG_WPS_OOB 3110 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 3111 if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8)) 3112 reply_len = -1; 3113#endif /* CONFIG_WPS_OOB */ 3114 } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) { 3115 if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8)) 3116 reply_len = -1; 3117#ifdef CONFIG_AP 3118 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 3119 reply_len = wpa_supplicant_ctrl_iface_wps_ap_pin( 3120 wpa_s, buf + 11, reply, reply_size); 3121#endif /* CONFIG_AP */ 3122#ifdef CONFIG_WPS_ER 3123 } else if (os_strcmp(buf, "WPS_ER_START") == 0) { 3124 if (wpas_wps_er_start(wpa_s, NULL)) 3125 reply_len = -1; 3126 } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) { 3127 if (wpas_wps_er_start(wpa_s, buf + 13)) 3128 reply_len = -1; 3129 } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) { 3130 if (wpas_wps_er_stop(wpa_s)) 3131 reply_len = -1; 3132 } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) { 3133 if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11)) 3134 reply_len = -1; 3135 } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) { 3136 int ret = wpas_wps_er_pbc(wpa_s, buf + 11); 3137 if (ret == -2) { 3138 os_memcpy(reply, "FAIL-PBC-OVERLAP\n", 17); 3139 reply_len = 17; 3140 } else if (ret == -3) { 3141 os_memcpy(reply, "FAIL-UNKNOWN-UUID\n", 18); 3142 reply_len = 18; 3143 } else if (ret == -4) { 3144 os_memcpy(reply, "FAIL-NO-AP-SETTINGS\n", 20); 3145 reply_len = 20; 3146 } else if (ret) 3147 reply_len = -1; 3148 } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) { 3149 if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13)) 3150 reply_len = -1; 3151 } else if (os_strncmp(buf, "WPS_ER_SET_CONFIG ", 18) == 0) { 3152 if (wpa_supplicant_ctrl_iface_wps_er_set_config(wpa_s, 3153 buf + 18)) 3154 reply_len = -1; 3155 } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) { 3156 if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14)) 3157 reply_len = -1; 3158#endif /* CONFIG_WPS_ER */ 3159#endif /* CONFIG_WPS */ 3160#ifdef CONFIG_IBSS_RSN 3161 } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) { 3162 if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9)) 3163 reply_len = -1; 3164#endif /* CONFIG_IBSS_RSN */ 3165#ifdef CONFIG_P2P 3166 } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) { 3167 if (p2p_ctrl_find(wpa_s, buf + 9)) 3168 reply_len = -1; 3169 } else if (os_strcmp(buf, "P2P_FIND") == 0) { 3170 if (p2p_ctrl_find(wpa_s, "")) 3171 reply_len = -1; 3172 } else if (os_strcmp(buf, "P2P_STOP_FIND") == 0) { 3173 wpas_p2p_stop_find(wpa_s); 3174 } else if (os_strncmp(buf, "P2P_CONNECT ", 12) == 0) { 3175 reply_len = p2p_ctrl_connect(wpa_s, buf + 12, reply, 3176 reply_size); 3177 } else if (os_strncmp(buf, "P2P_LISTEN ", 11) == 0) { 3178 if (p2p_ctrl_listen(wpa_s, buf + 11)) 3179 reply_len = -1; 3180 } else if (os_strcmp(buf, "P2P_LISTEN") == 0) { 3181 if (p2p_ctrl_listen(wpa_s, "")) 3182 reply_len = -1; 3183 } else if (os_strncmp(buf, "P2P_GROUP_REMOVE ", 17) == 0) { 3184 if (wpas_p2p_group_remove(wpa_s, buf + 17)) 3185 reply_len = -1; 3186 } else if (os_strcmp(buf, "P2P_GROUP_ADD") == 0) { 3187 if (wpas_p2p_group_add(wpa_s, 0, 0)) 3188 reply_len = -1; 3189 } else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) { 3190 if (p2p_ctrl_group_add(wpa_s, buf + 14)) 3191 reply_len = -1; 3192 } else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) { 3193 if (p2p_ctrl_prov_disc(wpa_s, buf + 14)) 3194 reply_len = -1; 3195 } else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) { 3196 reply_len = p2p_get_passphrase(wpa_s, reply, reply_size); 3197 } else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) { 3198 reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply, 3199 reply_size); 3200 } else if (os_strncmp(buf, "P2P_SERV_DISC_CANCEL_REQ ", 25) == 0) { 3201 if (p2p_ctrl_serv_disc_cancel_req(wpa_s, buf + 25) < 0) 3202 reply_len = -1; 3203 } else if (os_strncmp(buf, "P2P_SERV_DISC_RESP ", 19) == 0) { 3204 if (p2p_ctrl_serv_disc_resp(wpa_s, buf + 19) < 0) 3205 reply_len = -1; 3206 } else if (os_strcmp(buf, "P2P_SERVICE_UPDATE") == 0) { 3207 wpas_p2p_sd_service_update(wpa_s); 3208 } else if (os_strncmp(buf, "P2P_SERV_DISC_EXTERNAL ", 23) == 0) { 3209 if (p2p_ctrl_serv_disc_external(wpa_s, buf + 23) < 0) 3210 reply_len = -1; 3211 } else if (os_strcmp(buf, "P2P_SERVICE_FLUSH") == 0) { 3212 wpas_p2p_service_flush(wpa_s); 3213 } else if (os_strncmp(buf, "P2P_SERVICE_ADD ", 16) == 0) { 3214 if (p2p_ctrl_service_add(wpa_s, buf + 16) < 0) 3215 reply_len = -1; 3216 } else if (os_strncmp(buf, "P2P_SERVICE_DEL ", 16) == 0) { 3217 if (p2p_ctrl_service_del(wpa_s, buf + 16) < 0) 3218 reply_len = -1; 3219 } else if (os_strncmp(buf, "P2P_REJECT ", 11) == 0) { 3220 if (p2p_ctrl_reject(wpa_s, buf + 11) < 0) 3221 reply_len = -1; 3222 } else if (os_strncmp(buf, "P2P_INVITE ", 11) == 0) { 3223 if (p2p_ctrl_invite(wpa_s, buf + 11) < 0) 3224 reply_len = -1; 3225 } else if (os_strncmp(buf, "P2P_PEER ", 9) == 0) { 3226 reply_len = p2p_ctrl_peer(wpa_s, buf + 9, reply, 3227 reply_size); 3228 } else if (os_strncmp(buf, "P2P_SET ", 8) == 0) { 3229 if (p2p_ctrl_set(wpa_s, buf + 8) < 0) 3230 reply_len = -1; 3231 } else if (os_strcmp(buf, "P2P_FLUSH") == 0) { 3232 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); 3233 wpa_s->force_long_sd = 0; 3234 if (wpa_s->global->p2p) 3235 p2p_flush(wpa_s->global->p2p); 3236 } else if (os_strncmp(buf, "P2P_UNAUTHORIZE ", 16) == 0) { 3237 if (wpas_p2p_unauthorize(wpa_s, buf + 16) < 0) 3238 reply_len = -1; 3239 } else if (os_strcmp(buf, "P2P_CANCEL") == 0) { 3240 if (wpas_p2p_cancel(wpa_s)) 3241 reply_len = -1; 3242 } else if (os_strncmp(buf, "P2P_PRESENCE_REQ ", 17) == 0) { 3243 if (p2p_ctrl_presence_req(wpa_s, buf + 17) < 0) 3244 reply_len = -1; 3245 } else if (os_strcmp(buf, "P2P_PRESENCE_REQ") == 0) { 3246 if (p2p_ctrl_presence_req(wpa_s, "") < 0) 3247 reply_len = -1; 3248 } else if (os_strncmp(buf, "P2P_EXT_LISTEN ", 15) == 0) { 3249 if (p2p_ctrl_ext_listen(wpa_s, buf + 15) < 0) 3250 reply_len = -1; 3251 } else if (os_strcmp(buf, "P2P_EXT_LISTEN") == 0) { 3252 if (p2p_ctrl_ext_listen(wpa_s, "") < 0) 3253 reply_len = -1; 3254#endif /* CONFIG_P2P */ 3255 } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) 3256 { 3257 if (wpa_supplicant_ctrl_iface_ctrl_rsp( 3258 wpa_s, buf + os_strlen(WPA_CTRL_RSP))) 3259 reply_len = -1; 3260 else 3261 ctrl_rsp = 1; 3262 } else if (os_strcmp(buf, "RECONFIGURE") == 0) { 3263 if (wpa_supplicant_reload_configuration(wpa_s)) 3264 reply_len = -1; 3265 } else if (os_strcmp(buf, "TERMINATE") == 0) { 3266 wpa_supplicant_terminate_proc(wpa_s->global); 3267 } else if (os_strncmp(buf, "BSSID ", 6) == 0) { 3268 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) 3269 reply_len = -1; 3270 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 3271 reply_len = wpa_supplicant_ctrl_iface_log_level(wpa_s, buf + 9, 3272 reply, reply_size); 3273 } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) { 3274 reply_len = wpa_supplicant_ctrl_iface_blacklist(wpa_s, buf + 9, 3275 reply, reply_size); 3276 } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { 3277 reply_len = wpa_supplicant_ctrl_iface_list_networks( 3278 wpa_s, reply, reply_size); 3279 } else if (os_strcmp(buf, "DISCONNECT") == 0) { 3280 wpa_s->reassociate = 0; 3281 wpa_s->disconnected = 1; 3282 wpa_supplicant_deauthenticate(wpa_s, 3283 WLAN_REASON_DEAUTH_LEAVING); 3284 } else if (os_strcmp(buf, "SCAN") == 0) { 3285 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) 3286 reply_len = -1; 3287 else { 3288 if (!wpa_s->scanning && 3289 ((wpa_s->wpa_state <= WPA_SCANNING) || 3290 (wpa_s->wpa_state == WPA_COMPLETED))) { 3291 wpa_s->scan_req = 2; 3292 wpa_supplicant_req_scan(wpa_s, 0, 0); 3293 } else { 3294 wpa_printf(MSG_DEBUG, "Ongoing scan action - " 3295 "reject new request"); 3296 reply_len = os_snprintf(reply, reply_size, 3297 "FAIL-BUSY\n"); 3298 } 3299 } 3300 } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { 3301 reply_len = wpa_supplicant_ctrl_iface_scan_results( 3302 wpa_s, reply, reply_size); 3303 } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { 3304 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) 3305 reply_len = -1; 3306 } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { 3307 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) 3308 reply_len = -1; 3309 } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { 3310 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) 3311 reply_len = -1; 3312 } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { 3313 reply_len = wpa_supplicant_ctrl_iface_add_network( 3314 wpa_s, reply, reply_size); 3315 } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { 3316 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) 3317 reply_len = -1; 3318 } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { 3319 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) 3320 reply_len = -1; 3321 } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { 3322 reply_len = wpa_supplicant_ctrl_iface_get_network( 3323 wpa_s, buf + 12, reply, reply_size); 3324#ifndef CONFIG_NO_CONFIG_WRITE 3325 } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { 3326 if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) 3327 reply_len = -1; 3328#endif /* CONFIG_NO_CONFIG_WRITE */ 3329 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 3330 reply_len = wpa_supplicant_ctrl_iface_get_capability( 3331 wpa_s, buf + 15, reply, reply_size); 3332 } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { 3333 if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) 3334 reply_len = -1; 3335 } else if (os_strncmp(buf, "SCAN_INTERVAL ", 14) == 0) { 3336 if (wpa_supplicant_ctrl_iface_scan_interval(wpa_s, buf + 14)) 3337 reply_len = -1; 3338 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 3339 reply_len = wpa_supplicant_global_iface_list( 3340 wpa_s->global, reply, reply_size); 3341 } else if (os_strcmp(buf, "INTERFACES") == 0) { 3342 reply_len = wpa_supplicant_global_iface_interfaces( 3343 wpa_s->global, reply, reply_size); 3344 } else if (os_strncmp(buf, "BSS ", 4) == 0) { 3345 reply_len = wpa_supplicant_ctrl_iface_bss( 3346 wpa_s, buf + 4, reply, reply_size); 3347#ifdef CONFIG_AP 3348 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 3349 reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size); 3350 } else if (os_strncmp(buf, "STA ", 4) == 0) { 3351 reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply, 3352 reply_size); 3353 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 3354 reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply, 3355 reply_size); 3356#endif /* CONFIG_AP */ 3357 } else if (os_strcmp(buf, "SUSPEND") == 0) { 3358 wpas_notify_suspend(wpa_s->global); 3359 } else if (os_strcmp(buf, "RESUME") == 0) { 3360 wpas_notify_resume(wpa_s->global); 3361 } else if (os_strcmp(buf, "DROP_SA") == 0) { 3362 wpa_supplicant_ctrl_iface_drop_sa(wpa_s); 3363 } else if (os_strncmp(buf, "ROAM ", 5) == 0) { 3364 if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) 3365 reply_len = -1; 3366 } else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) { 3367 if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16)) 3368 reply_len = -1; 3369 } else if (os_strncmp(buf, "BSS_EXPIRE_AGE ", 15) == 0) { 3370 if (wpa_supplicant_ctrl_iface_bss_expire_age(wpa_s, buf + 15)) 3371 reply_len = -1; 3372 } else if (os_strncmp(buf, "BSS_EXPIRE_COUNT ", 17) == 0) { 3373 if (wpa_supplicant_ctrl_iface_bss_expire_count(wpa_s, 3374 buf + 17)) 3375 reply_len = -1; 3376#ifdef CONFIG_TDLS 3377 } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) { 3378 if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14)) 3379 reply_len = -1; 3380 } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) { 3381 if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11)) 3382 reply_len = -1; 3383 } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) { 3384 if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14)) 3385 reply_len = -1; 3386#endif /* CONFIG_TDLS */ 3387 } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { 3388 reply_len = wpa_supplicant_signal_poll(wpa_s, reply, 3389 reply_size); 3390 } else { 3391 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 3392 reply_len = 16; 3393 } 3394 3395 if (reply_len < 0) { 3396 os_memcpy(reply, "FAIL\n", 5); 3397 reply_len = 5; 3398 } 3399 3400 if (ctrl_rsp) 3401 eapol_sm_notify_ctrl_response(wpa_s->eapol); 3402 3403 *resp_len = reply_len; 3404 return reply; 3405} 3406 3407 3408static int wpa_supplicant_global_iface_add(struct wpa_global *global, 3409 char *cmd) 3410{ 3411 struct wpa_interface iface; 3412 char *pos; 3413 3414 /* 3415 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> 3416 * TAB<bridge_ifname> 3417 */ 3418 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); 3419 3420 os_memset(&iface, 0, sizeof(iface)); 3421 3422 do { 3423 iface.ifname = pos = cmd; 3424 pos = os_strchr(pos, '\t'); 3425 if (pos) 3426 *pos++ = '\0'; 3427 if (iface.ifname[0] == '\0') 3428 return -1; 3429 if (pos == NULL) 3430 break; 3431 3432 iface.confname = pos; 3433 pos = os_strchr(pos, '\t'); 3434 if (pos) 3435 *pos++ = '\0'; 3436 if (iface.confname[0] == '\0') 3437 iface.confname = NULL; 3438 if (pos == NULL) 3439 break; 3440 3441 iface.driver = pos; 3442 pos = os_strchr(pos, '\t'); 3443 if (pos) 3444 *pos++ = '\0'; 3445 if (iface.driver[0] == '\0') 3446 iface.driver = NULL; 3447 if (pos == NULL) 3448 break; 3449 3450 iface.ctrl_interface = pos; 3451 pos = os_strchr(pos, '\t'); 3452 if (pos) 3453 *pos++ = '\0'; 3454 if (iface.ctrl_interface[0] == '\0') 3455 iface.ctrl_interface = NULL; 3456 if (pos == NULL) 3457 break; 3458 3459 iface.driver_param = pos; 3460 pos = os_strchr(pos, '\t'); 3461 if (pos) 3462 *pos++ = '\0'; 3463 if (iface.driver_param[0] == '\0') 3464 iface.driver_param = NULL; 3465 if (pos == NULL) 3466 break; 3467 3468 iface.bridge_ifname = pos; 3469 pos = os_strchr(pos, '\t'); 3470 if (pos) 3471 *pos++ = '\0'; 3472 if (iface.bridge_ifname[0] == '\0') 3473 iface.bridge_ifname = NULL; 3474 if (pos == NULL) 3475 break; 3476 } while (0); 3477 3478 if (wpa_supplicant_get_iface(global, iface.ifname)) 3479 return -1; 3480 3481 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; 3482} 3483 3484 3485static int wpa_supplicant_global_iface_remove(struct wpa_global *global, 3486 char *cmd) 3487{ 3488 struct wpa_supplicant *wpa_s; 3489 3490 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); 3491 3492 wpa_s = wpa_supplicant_get_iface(global, cmd); 3493 if (wpa_s == NULL) 3494 return -1; 3495 return wpa_supplicant_remove_iface(global, wpa_s); 3496} 3497 3498 3499static void wpa_free_iface_info(struct wpa_interface_info *iface) 3500{ 3501 struct wpa_interface_info *prev; 3502 3503 while (iface) { 3504 prev = iface; 3505 iface = iface->next; 3506 3507 os_free(prev->ifname); 3508 os_free(prev->desc); 3509 os_free(prev); 3510 } 3511} 3512 3513 3514static int wpa_supplicant_global_iface_list(struct wpa_global *global, 3515 char *buf, int len) 3516{ 3517 int i, res; 3518 struct wpa_interface_info *iface = NULL, *last = NULL, *tmp; 3519 char *pos, *end; 3520 3521 for (i = 0; wpa_drivers[i]; i++) { 3522 struct wpa_driver_ops *drv = wpa_drivers[i]; 3523 if (drv->get_interfaces == NULL) 3524 continue; 3525 tmp = drv->get_interfaces(global->drv_priv[i]); 3526 if (tmp == NULL) 3527 continue; 3528 3529 if (last == NULL) 3530 iface = last = tmp; 3531 else 3532 last->next = tmp; 3533 while (last->next) 3534 last = last->next; 3535 } 3536 3537 pos = buf; 3538 end = buf + len; 3539 for (tmp = iface; tmp; tmp = tmp->next) { 3540 res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n", 3541 tmp->drv_name, tmp->ifname, 3542 tmp->desc ? tmp->desc : ""); 3543 if (res < 0 || res >= end - pos) { 3544 *pos = '\0'; 3545 break; 3546 } 3547 pos += res; 3548 } 3549 3550 wpa_free_iface_info(iface); 3551 3552 return pos - buf; 3553} 3554 3555 3556static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, 3557 char *buf, int len) 3558{ 3559 int res; 3560 char *pos, *end; 3561 struct wpa_supplicant *wpa_s; 3562 3563 wpa_s = global->ifaces; 3564 pos = buf; 3565 end = buf + len; 3566 3567 while (wpa_s) { 3568 res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); 3569 if (res < 0 || res >= end - pos) { 3570 *pos = '\0'; 3571 break; 3572 } 3573 pos += res; 3574 wpa_s = wpa_s->next; 3575 } 3576 return pos - buf; 3577} 3578 3579 3580char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, 3581 char *buf, size_t *resp_len) 3582{ 3583 char *reply; 3584 const int reply_size = 2048; 3585 int reply_len; 3586 3587 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", 3588 (const u8 *) buf, os_strlen(buf)); 3589 3590 reply = os_malloc(reply_size); 3591 if (reply == NULL) { 3592 *resp_len = 1; 3593 return NULL; 3594 } 3595 3596 os_memcpy(reply, "OK\n", 3); 3597 reply_len = 3; 3598 3599 if (os_strcmp(buf, "PING") == 0) { 3600 os_memcpy(reply, "PONG\n", 5); 3601 reply_len = 5; 3602 } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) { 3603 if (wpa_supplicant_global_iface_add(global, buf + 14)) 3604 reply_len = -1; 3605 } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { 3606 if (wpa_supplicant_global_iface_remove(global, buf + 17)) 3607 reply_len = -1; 3608 } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) { 3609 reply_len = wpa_supplicant_global_iface_list( 3610 global, reply, reply_size); 3611 } else if (os_strcmp(buf, "INTERFACES") == 0) { 3612 reply_len = wpa_supplicant_global_iface_interfaces( 3613 global, reply, reply_size); 3614 } else if (os_strcmp(buf, "TERMINATE") == 0) { 3615 wpa_supplicant_terminate_proc(global); 3616 } else if (os_strcmp(buf, "SUSPEND") == 0) { 3617 wpas_notify_suspend(global); 3618 } else if (os_strcmp(buf, "RESUME") == 0) { 3619 wpas_notify_resume(global); 3620 } else { 3621 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 3622 reply_len = 16; 3623 } 3624 3625 if (reply_len < 0) { 3626 os_memcpy(reply, "FAIL\n", 5); 3627 reply_len = 5; 3628 } 3629 3630 *resp_len = reply_len; 3631 return reply; 3632} 3633