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