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