1 /* 2 * WPA Supplicant - command line interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2008, 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 "includes.h" 16 17 #ifdef CONFIG_CTRL_IFACE 18 19 #ifdef CONFIG_CTRL_IFACE_UNIX 20 #include <dirent.h> 21 #endif /* CONFIG_CTRL_IFACE_UNIX */ 22 #ifdef CONFIG_READLINE 23 #include <readline/readline.h> 24 #include <readline/history.h> 25 #endif /* CONFIG_READLINE */ 26 27 #define CTRL_INTERFACE_2_SOCKETS 28 29 #include "wpa_ctrl.h" 30 #include "common.h" 31 #include "version.h" 32 #ifdef ANDROID 33 #include <cutils/properties.h> 34 #endif 35 36 static const char *wpa_cli_version = 37 "wpa_cli v" VERSION_STR "\n" 38 "Copyright (c) 2004-2008, Jouni Malinen <j (at) w1.fi> and contributors"; 39 40 41 static const char *wpa_cli_license = 42 "This program is free software. You can distribute it and/or modify it\n" 43 "under the terms of the GNU General Public License version 2.\n" 44 "\n" 45 "Alternatively, this software may be distributed under the terms of the\n" 46 "BSD license. See README and COPYING for more details.\n"; 47 48 static const char *wpa_cli_full_license = 49 "This program is free software; you can redistribute it and/or modify\n" 50 "it under the terms of the GNU General Public License version 2 as\n" 51 "published by the Free Software Foundation.\n" 52 "\n" 53 "This program is distributed in the hope that it will be useful,\n" 54 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 55 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 56 "GNU General Public License for more details.\n" 57 "\n" 58 "You should have received a copy of the GNU General Public License\n" 59 "along with this program; if not, write to the Free Software\n" 60 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" 61 "\n" 62 "Alternatively, this software may be distributed under the terms of the\n" 63 "BSD license.\n" 64 "\n" 65 "Redistribution and use in source and binary forms, with or without\n" 66 "modification, are permitted provided that the following conditions are\n" 67 "met:\n" 68 "\n" 69 "1. Redistributions of source code must retain the above copyright\n" 70 " notice, this list of conditions and the following disclaimer.\n" 71 "\n" 72 "2. Redistributions in binary form must reproduce the above copyright\n" 73 " notice, this list of conditions and the following disclaimer in the\n" 74 " documentation and/or other materials provided with the distribution.\n" 75 "\n" 76 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 77 " names of its contributors may be used to endorse or promote products\n" 78 " derived from this software without specific prior written permission.\n" 79 "\n" 80 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 81 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 82 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 83 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 84 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 85 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 86 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 87 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 88 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 89 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 90 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 91 "\n"; 92 93 static const char *commands_help = 94 "commands:\n" 95 " status [verbose] = get current WPA/EAPOL/EAP status\n" 96 " mib = get MIB variables (dot1x, dot11)\n" 97 " help = show this usage help\n" 98 " interface [ifname] = show interfaces/select interface\n" 99 " level <debug level> = change debug level\n" 100 " license = show full wpa_cli license\n" 101 " logoff = IEEE 802.1X EAPOL state machine logoff\n" 102 " logon = IEEE 802.1X EAPOL state machine logon\n" 103 " set = set variables (shows list of variables when run without arguments)\n" 104 " pmksa = show PMKSA cache\n" 105 " reassociate = force reassociation\n" 106 " reconfigure = force wpa_supplicant to re-read its configuration file\n" 107 " preauthenticate <BSSID> = force preauthentication\n" 108 " identity <network id> <identity> = configure identity for an SSID\n" 109 " password <network id> <password> = configure password for an SSID\n" 110 " new_password <network id> <password> = change password for an SSID\n" 111 " pin <network id> <pin> = configure pin for an SSID\n" 112 " otp <network id> <password> = configure one-time-password for an SSID\n" 113 " passphrase <network id> <passphrase> = configure private key passphrase\n" 114 " for an SSID\n" 115 " bssid <network id> <BSSID> = set preferred BSSID for an SSID\n" 116 " blacklist [<BSSID>] = add a BSSID to the blacklist\n" 117 " blacklist clear = clear the blacklist\n" 118 " blacklist = display the blacklist\n" 119 " list_networks = list configured networks\n" 120 " select_network <network id> = select a network (disable others)\n" 121 " enable_network <network id> = enable a network\n" 122 " disable_network <network id> = disable a network\n" 123 " add_network = add a network\n" 124 " remove_network <network id> = remove a network\n" 125 " set_network <network id> <variable> <value> = set network variables " 126 "(shows\n" 127 " list of variables when run without arguments)\n" 128 " get_network <network id> <variable> = get network variables\n" 129 " save_config = save the current configuration\n" 130 " disconnect = disconnect and wait for reassociate/reconnect command before\n " 131 " connecting\n" 132 " reconnect = like reassociate, but only takes effect if already " 133 "disconnected\n" 134 " scan = request new BSS scan\n" 135 " scan_results = get latest scan results\n" 136 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = " 137 "get capabilies\n" 138 " ap_scan <value> = set ap_scan parameter\n" 139 " stkstart <addr> = request STK negotiation with <addr>\n" 140 " terminate = terminate wpa_supplicant\n" 141 " quit = exit wpa_cli\n"; 142 143 static struct wpa_ctrl *ctrl_conn; 144 static struct wpa_ctrl *monitor_conn; 145 static int wpa_cli_quit = 0; 146 static int wpa_cli_attached = 0; 147 static int wpa_cli_connected = 0; 148 static int wpa_cli_last_id = 0; 149 #ifdef ANDROID 150 static const char *ctrl_iface_dir = "/data/misc/wifi/wpa_supplicant"; 151 #else 152 static const char *ctrl_iface_dir = "/tmp/run/wpa_supplicant"; 153 #endif 154 static char *ctrl_ifname = NULL; 155 static const char *pid_file = NULL; 156 static const char *action_file = NULL; 157 158 159 static void usage(void) 160 { 161 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " 162 "[-a<action file>] \\\n" 163 " [-P<pid file>] [-g<global ctrl>] [command..]\n" 164 " -h = help (show this usage text)\n" 165 " -v = shown version information\n" 166 " -a = run in daemon mode executing the action file based on " 167 "events from\n" 168 " wpa_supplicant\n" 169 " -B = run a daemon in the background\n" 170 " default path: /var/run/wpa_supplicant\n" 171 " default interface: first interface found in socket path\n" 172 "%s", 173 commands_help); 174 } 175 176 177 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) 178 { 179 struct wpa_ctrl *cur_conn; 180 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) 181 cur_conn = wpa_ctrl_open(ifname); 182 return cur_conn; 183 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 184 char *cfile; 185 int flen; 186 187 if (ifname == NULL) 188 return NULL; 189 190 #ifdef ANDROID 191 if (access(ctrl_iface_dir, F_OK) < 0) 192 cfile = (char *)ifname; 193 else { 194 #endif 195 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; 196 cfile = os_malloc(flen); 197 if (cfile == NULL) 198 return NULL; 199 os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); 200 #ifdef ANDROID 201 } 202 #endif 203 204 cur_conn = wpa_ctrl_open(cfile); /* Dm: */ 205 #ifdef CTRL_INTERFACE_2_SOCKETS 206 monitor_conn = wpa_ctrl_open(cfile); 207 #else 208 monitor_conn = cur_conn; 209 #endif 210 #ifdef ANDROID 211 if (cfile != ifname) 212 #endif 213 os_free(cfile); 214 return cur_conn; 215 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 216 } 217 218 219 static void wpa_cli_close_connection(void) 220 { 221 if (ctrl_conn == NULL) 222 return; 223 224 if (wpa_cli_attached) { 225 wpa_ctrl_detach(monitor_conn); 226 wpa_cli_attached = 0; 227 } 228 #ifdef CTRL_INTERFACE_2_SOCKETS 229 wpa_ctrl_close(monitor_conn); 230 #endif 231 wpa_ctrl_close(ctrl_conn); 232 ctrl_conn = monitor_conn = NULL; 233 } 234 235 236 static void wpa_cli_msg_cb(char *msg, size_t len) 237 { 238 printf("%s\n", msg); 239 } 240 241 242 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) 243 { 244 char buf[4096]; 245 size_t len; 246 int ret; 247 248 if (ctrl_conn == NULL) { 249 printf("Not connected to wpa_supplicant - command dropped.\n"); 250 return -1; 251 } 252 len = sizeof(buf) - 1; 253 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 254 wpa_cli_msg_cb); 255 if (ret == -2) { 256 printf("'%s' command timed out.\n", cmd); 257 return -2; 258 } else if (ret < 0) { 259 printf("'%s' command failed.\n", cmd); 260 return -1; 261 } 262 if (print) { 263 buf[len] = '\0'; 264 printf("%s", buf); 265 } 266 return 0; 267 } 268 269 270 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) 271 { 272 return _wpa_ctrl_command(ctrl, cmd, 1); 273 } 274 275 276 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 277 { 278 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; 279 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); 280 } 281 282 283 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 284 { 285 return wpa_ctrl_command(ctrl, "PING"); 286 } 287 288 289 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 290 { 291 return wpa_ctrl_command(ctrl, "MIB"); 292 } 293 294 295 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 296 { 297 return wpa_ctrl_command(ctrl, "PMKSA"); 298 } 299 300 301 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 302 { 303 printf("%s", commands_help); 304 return 0; 305 } 306 307 308 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) 309 { 310 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); 311 return 0; 312 } 313 314 315 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 316 { 317 wpa_cli_quit = 1; 318 return 0; 319 } 320 321 322 static void wpa_cli_show_variables(void) 323 { 324 printf("set variables:\n" 325 " EAPOL::heldPeriod (EAPOL state machine held period, " 326 "in seconds)\n" 327 " EAPOL::authPeriod (EAPOL state machine authentication " 328 "period, in seconds)\n" 329 " EAPOL::startPeriod (EAPOL state machine start period, in " 330 "seconds)\n" 331 " EAPOL::maxStart (EAPOL state machine maximum start " 332 "attempts)\n"); 333 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " 334 "seconds)\n" 335 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" 336 " threshold\n\tpercentage)\n" 337 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " 338 "security\n\tassociation in seconds)\n"); 339 } 340 341 342 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 343 { 344 char cmd[256]; 345 int res; 346 347 if (argc == 0) { 348 wpa_cli_show_variables(); 349 return 0; 350 } 351 352 if (argc != 2) { 353 printf("Invalid SET command: needs two arguments (variable " 354 "name and value)\n"); 355 return -1; 356 } 357 358 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); 359 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 360 printf("Too long SET command.\n"); 361 return -1; 362 } 363 return wpa_ctrl_command(ctrl, cmd); 364 } 365 366 367 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) 368 { 369 return wpa_ctrl_command(ctrl, "LOGOFF"); 370 } 371 372 373 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) 374 { 375 return wpa_ctrl_command(ctrl, "LOGON"); 376 } 377 378 379 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, 380 char *argv[]) 381 { 382 return wpa_ctrl_command(ctrl, "REASSOCIATE"); 383 } 384 385 386 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, 387 char *argv[]) 388 { 389 char cmd[256]; 390 int res; 391 392 if (argc != 1) { 393 printf("Invalid PREAUTH command: needs one argument " 394 "(BSSID)\n"); 395 return -1; 396 } 397 398 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); 399 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 400 printf("Too long PREAUTH command.\n"); 401 return -1; 402 } 403 return wpa_ctrl_command(ctrl, cmd); 404 } 405 406 407 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 408 { 409 char cmd[256]; 410 int res; 411 412 if (argc != 1) { 413 printf("Invalid AP_SCAN command: needs one argument (ap_scan " 414 "value)\n"); 415 return -1; 416 } 417 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); 418 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 419 printf("Too long AP_SCAN command.\n"); 420 return -1; 421 } 422 return wpa_ctrl_command(ctrl, cmd); 423 } 424 425 426 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, 427 char *argv[]) 428 { 429 char cmd[256]; 430 int res; 431 432 if (argc != 1) { 433 printf("Invalid STKSTART command: needs one argument " 434 "(Peer STA MAC address)\n"); 435 return -1; 436 } 437 438 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]); 439 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 440 printf("Too long STKSTART command.\n"); 441 return -1; 442 } 443 return wpa_ctrl_command(ctrl, cmd); 444 } 445 446 447 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 448 { 449 char cmd[256]; 450 int res; 451 452 if (argc != 1) { 453 printf("Invalid LEVEL command: needs one argument (debug " 454 "level)\n"); 455 return -1; 456 } 457 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); 458 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 459 printf("Too long LEVEL command.\n"); 460 return -1; 461 } 462 return wpa_ctrl_command(ctrl, cmd); 463 } 464 465 466 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) 467 { 468 char cmd[256], *pos, *end; 469 int i, ret; 470 471 if (argc < 2) { 472 printf("Invalid IDENTITY command: needs two arguments " 473 "(network id and identity)\n"); 474 return -1; 475 } 476 477 end = cmd + sizeof(cmd); 478 pos = cmd; 479 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", 480 argv[0], argv[1]); 481 if (ret < 0 || ret >= end - pos) { 482 printf("Too long IDENTITY command.\n"); 483 return -1; 484 } 485 pos += ret; 486 for (i = 2; i < argc; i++) { 487 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 488 if (ret < 0 || ret >= end - pos) { 489 printf("Too long IDENTITY command.\n"); 490 return -1; 491 } 492 pos += ret; 493 } 494 495 return wpa_ctrl_command(ctrl, cmd); 496 } 497 498 499 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) 500 { 501 char cmd[256], *pos, *end; 502 int i, ret; 503 504 if (argc < 2) { 505 printf("Invalid PASSWORD command: needs two arguments " 506 "(network id and password)\n"); 507 return -1; 508 } 509 510 end = cmd + sizeof(cmd); 511 pos = cmd; 512 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", 513 argv[0], argv[1]); 514 if (ret < 0 || ret >= end - pos) { 515 printf("Too long PASSWORD command.\n"); 516 return -1; 517 } 518 pos += ret; 519 for (i = 2; i < argc; i++) { 520 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 521 if (ret < 0 || ret >= end - pos) { 522 printf("Too long PASSWORD command.\n"); 523 return -1; 524 } 525 pos += ret; 526 } 527 528 return wpa_ctrl_command(ctrl, cmd); 529 } 530 531 532 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, 533 char *argv[]) 534 { 535 char cmd[256], *pos, *end; 536 int i, ret; 537 538 if (argc < 2) { 539 printf("Invalid NEW_PASSWORD command: needs two arguments " 540 "(network id and password)\n"); 541 return -1; 542 } 543 544 end = cmd + sizeof(cmd); 545 pos = cmd; 546 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", 547 argv[0], argv[1]); 548 if (ret < 0 || ret >= end - pos) { 549 printf("Too long NEW_PASSWORD command.\n"); 550 return -1; 551 } 552 pos += ret; 553 for (i = 2; i < argc; i++) { 554 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 555 if (ret < 0 || ret >= end - pos) { 556 printf("Too long NEW_PASSWORD command.\n"); 557 return -1; 558 } 559 pos += ret; 560 } 561 562 return wpa_ctrl_command(ctrl, cmd); 563 } 564 565 566 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 567 { 568 char cmd[256], *pos, *end; 569 int i, ret; 570 571 if (argc < 2) { 572 printf("Invalid PIN command: needs two arguments " 573 "(network id and pin)\n"); 574 return -1; 575 } 576 577 end = cmd + sizeof(cmd); 578 pos = cmd; 579 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", 580 argv[0], argv[1]); 581 if (ret < 0 || ret >= end - pos) { 582 printf("Too long PIN command.\n"); 583 return -1; 584 } 585 pos += ret; 586 for (i = 2; i < argc; i++) { 587 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 588 if (ret < 0 || ret >= end - pos) { 589 printf("Too long PIN command.\n"); 590 return -1; 591 } 592 pos += ret; 593 } 594 return wpa_ctrl_command(ctrl, cmd); 595 } 596 597 598 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) 599 { 600 char cmd[256], *pos, *end; 601 int i, ret; 602 603 if (argc < 2) { 604 printf("Invalid OTP command: needs two arguments (network " 605 "id and password)\n"); 606 return -1; 607 } 608 609 end = cmd + sizeof(cmd); 610 pos = cmd; 611 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", 612 argv[0], argv[1]); 613 if (ret < 0 || ret >= end - pos) { 614 printf("Too long OTP command.\n"); 615 return -1; 616 } 617 pos += ret; 618 for (i = 2; i < argc; i++) { 619 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 620 if (ret < 0 || ret >= end - pos) { 621 printf("Too long OTP command.\n"); 622 return -1; 623 } 624 pos += ret; 625 } 626 627 return wpa_ctrl_command(ctrl, cmd); 628 } 629 630 631 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, 632 char *argv[]) 633 { 634 char cmd[256], *pos, *end; 635 int i, ret; 636 637 if (argc < 2) { 638 printf("Invalid PASSPHRASE command: needs two arguments " 639 "(network id and passphrase)\n"); 640 return -1; 641 } 642 643 end = cmd + sizeof(cmd); 644 pos = cmd; 645 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", 646 argv[0], argv[1]); 647 if (ret < 0 || ret >= end - pos) { 648 printf("Too long PASSPHRASE command.\n"); 649 return -1; 650 } 651 pos += ret; 652 for (i = 2; i < argc; i++) { 653 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 654 if (ret < 0 || ret >= end - pos) { 655 printf("Too long PASSPHRASE command.\n"); 656 return -1; 657 } 658 pos += ret; 659 } 660 661 return wpa_ctrl_command(ctrl, cmd); 662 } 663 664 665 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) 666 { 667 char cmd[256], *pos, *end; 668 int i, ret; 669 670 if (argc < 2) { 671 printf("Invalid BSSID command: needs two arguments (network " 672 "id and BSSID)\n"); 673 return -1; 674 } 675 676 end = cmd + sizeof(cmd); 677 pos = cmd; 678 ret = os_snprintf(pos, end - pos, "BSSID"); 679 if (ret < 0 || ret >= end - pos) { 680 printf("Too long BSSID command.\n"); 681 return -1; 682 } 683 pos += ret; 684 for (i = 0; i < argc; i++) { 685 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 686 if (ret < 0 || ret >= end - pos) { 687 printf("Too long BSSID command.\n"); 688 return -1; 689 } 690 pos += ret; 691 } 692 693 return wpa_ctrl_command(ctrl, cmd); 694 } 695 696 #ifdef ANDROID 697 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[]) 698 { 699 char cmd[256], *pos, *end; 700 int i, ret; 701 702 end = cmd + sizeof(cmd); 703 pos = cmd; 704 ret = os_snprintf(pos, end - pos, "BLACKLIST"); 705 if (ret < 0 || ret >= end - pos) { 706 printf("Too long BLACKLIST command.\n"); 707 return -1; 708 } 709 pos += ret; 710 for (i = 0; i < argc; i++) { 711 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 712 if (ret < 0 || ret >= end - pos) { 713 printf("Too long BLACKLIST command.\n"); 714 return -1; 715 } 716 pos += ret; 717 } 718 719 return wpa_ctrl_command(ctrl, cmd); 720 } 721 #endif 722 723 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, 724 char *argv[]) 725 { 726 return wpa_ctrl_command(ctrl, "LIST_NETWORKS"); 727 } 728 729 730 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, 731 char *argv[]) 732 { 733 char cmd[32]; 734 735 if (argc < 1) { 736 printf("Invalid SELECT_NETWORK command: needs one argument " 737 "(network id)\n"); 738 return -1; 739 } 740 741 os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]); 742 cmd[sizeof(cmd) - 1] = '\0'; 743 744 return wpa_ctrl_command(ctrl, cmd); 745 } 746 747 748 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, 749 char *argv[]) 750 { 751 char cmd[32]; 752 753 if (argc < 1) { 754 printf("Invalid ENABLE_NETWORK command: needs one argument " 755 "(network id)\n"); 756 return -1; 757 } 758 759 os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]); 760 cmd[sizeof(cmd) - 1] = '\0'; 761 762 return wpa_ctrl_command(ctrl, cmd); 763 } 764 765 766 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, 767 char *argv[]) 768 { 769 char cmd[32]; 770 771 if (argc < 1) { 772 printf("Invalid DISABLE_NETWORK command: needs one argument " 773 "(network id)\n"); 774 return -1; 775 } 776 777 os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]); 778 cmd[sizeof(cmd) - 1] = '\0'; 779 780 return wpa_ctrl_command(ctrl, cmd); 781 } 782 783 784 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, 785 char *argv[]) 786 { 787 return wpa_ctrl_command(ctrl, "ADD_NETWORK"); 788 } 789 790 791 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, 792 char *argv[]) 793 { 794 char cmd[32]; 795 796 if (argc < 1) { 797 printf("Invalid REMOVE_NETWORK command: needs one argument " 798 "(network id)\n"); 799 return -1; 800 } 801 802 os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]); 803 cmd[sizeof(cmd) - 1] = '\0'; 804 805 return wpa_ctrl_command(ctrl, cmd); 806 } 807 808 809 static void wpa_cli_show_network_variables(void) 810 { 811 printf("set_network variables:\n" 812 " ssid (network name, SSID)\n" 813 " psk (WPA passphrase or pre-shared key)\n" 814 " key_mgmt (key management protocol)\n" 815 " identity (EAP identity)\n" 816 " password (EAP password)\n" 817 " ...\n" 818 "\n" 819 "Note: Values are entered in the same format as the " 820 "configuration file is using,\n" 821 "i.e., strings values need to be inside double quotation " 822 "marks.\n" 823 "For example: set_network 1 ssid \"network name\"\n" 824 "\n" 825 "Please see wpa_supplicant.conf documentation for full list " 826 "of\navailable variables.\n"); 827 } 828 829 830 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, 831 char *argv[]) 832 { 833 char cmd[256]; 834 int res; 835 836 if (argc == 0) { 837 wpa_cli_show_network_variables(); 838 return 0; 839 } 840 841 if (argc != 3) { 842 printf("Invalid SET_NETWORK command: needs three arguments\n" 843 "(network id, variable name, and value)\n"); 844 return -1; 845 } 846 847 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s", 848 argv[0], argv[1], argv[2]); 849 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 850 printf("Too long SET_NETWORK command.\n"); 851 return -1; 852 } 853 return wpa_ctrl_command(ctrl, cmd); 854 } 855 856 857 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, 858 char *argv[]) 859 { 860 char cmd[256]; 861 int res; 862 863 if (argc == 0) { 864 wpa_cli_show_network_variables(); 865 return 0; 866 } 867 868 if (argc != 2) { 869 printf("Invalid GET_NETWORK command: needs two arguments\n" 870 "(network id and variable name)\n"); 871 return -1; 872 } 873 874 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s", 875 argv[0], argv[1]); 876 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 877 printf("Too long GET_NETWORK command.\n"); 878 return -1; 879 } 880 return wpa_ctrl_command(ctrl, cmd); 881 } 882 883 884 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, 885 char *argv[]) 886 { 887 return wpa_ctrl_command(ctrl, "DISCONNECT"); 888 } 889 890 891 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, 892 char *argv[]) 893 { 894 return wpa_ctrl_command(ctrl, "RECONNECT"); 895 } 896 897 898 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, 899 char *argv[]) 900 { 901 return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); 902 } 903 904 905 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 906 { 907 return wpa_ctrl_command(ctrl, "SCAN"); 908 } 909 910 911 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, 912 char *argv[]) 913 { 914 return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); 915 } 916 917 918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, 919 char *argv[]) 920 { 921 char cmd[64]; 922 923 if (argc < 1 || argc > 2) { 924 printf("Invalid GET_CAPABILITY command: need either one or " 925 "two arguments\n"); 926 return -1; 927 } 928 929 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { 930 printf("Invalid GET_CAPABILITY command: second argument, " 931 "if any, must be 'strict'\n"); 932 return -1; 933 } 934 935 os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0], 936 (argc == 2) ? " strict" : ""); 937 cmd[sizeof(cmd) - 1] = '\0'; 938 939 return wpa_ctrl_command(ctrl, cmd); 940 } 941 942 943 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) 944 { 945 printf("Available interfaces:\n"); 946 return wpa_ctrl_command(ctrl, "INTERFACES"); 947 } 948 949 950 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) 951 { 952 if (argc < 1) { 953 wpa_cli_list_interfaces(ctrl); 954 return 0; 955 } 956 957 wpa_cli_close_connection(); 958 os_free(ctrl_ifname); 959 ctrl_ifname = os_strdup(argv[0]); 960 961 if ((ctrl_conn = wpa_cli_open_connection(ctrl_ifname)) != NULL) { 962 printf("Connected to interface '%s.\n", ctrl_ifname); 963 if (wpa_ctrl_attach(monitor_conn) == 0) { 964 wpa_cli_attached = 1; 965 } else { 966 printf("Warning: Failed to attach to " 967 "wpa_supplicant.\n"); 968 } 969 } else { 970 printf("Could not connect to interface '%s' - re-trying\n", 971 ctrl_ifname); 972 } 973 return 0; 974 } 975 976 977 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, 978 char *argv[]) 979 { 980 return wpa_ctrl_command(ctrl, "RECONFIGURE"); 981 } 982 983 984 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, 985 char *argv[]) 986 { 987 return wpa_ctrl_command(ctrl, "TERMINATE"); 988 } 989 990 991 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, 992 char *argv[]) 993 { 994 char cmd[256]; 995 996 if (argc < 1) { 997 printf("Invalid INTERFACE_ADD command: needs at least one " 998 "argument (interface name)\n" 999 "All arguments: ifname confname driver ctrl_interface " 1000 "driver_param bridge_name\n"); 1001 return -1; 1002 } 1003 1004 /* 1005 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB 1006 * <driver_param>TAB<bridge_name> 1007 */ 1008 os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", 1009 argv[0], 1010 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", 1011 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", 1012 argc > 5 ? argv[5] : ""); 1013 cmd[sizeof(cmd) - 1] = '\0'; 1014 return wpa_ctrl_command(ctrl, cmd); 1015 } 1016 1017 1018 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, 1019 char *argv[]) 1020 { 1021 char cmd[128]; 1022 1023 if (argc != 1) { 1024 printf("Invalid INTERFACE_REMOVE command: needs one argument " 1025 "(interface name)\n"); 1026 return -1; 1027 } 1028 1029 os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]); 1030 cmd[sizeof(cmd) - 1] = '\0'; 1031 return wpa_ctrl_command(ctrl, cmd); 1032 } 1033 1034 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, 1035 char *argv[]) 1036 { 1037 char cmd[32]; 1038 1039 if (argc < 1) { 1040 printf("Invalid DRIVER command: needs one argument (cmd)\n"); 1041 return -1; 1042 } 1043 1044 if (argc > 1) 1045 os_snprintf(cmd, sizeof(cmd), "DRIVER %s %s", argv[0], argv[1]); 1046 else 1047 os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]); 1048 cmd[sizeof(cmd) - 1] = '\0'; 1049 1050 return wpa_ctrl_command(ctrl, cmd); 1051 } 1052 1053 struct wpa_cli_cmd { 1054 const char *cmd; 1055 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); 1056 }; 1057 1058 static struct wpa_cli_cmd wpa_cli_commands[] = { 1059 { "status", wpa_cli_cmd_status }, 1060 { "ping", wpa_cli_cmd_ping }, 1061 { "mib", wpa_cli_cmd_mib }, 1062 { "help", wpa_cli_cmd_help }, 1063 { "interface", wpa_cli_cmd_interface }, 1064 { "level", wpa_cli_cmd_level }, 1065 { "license", wpa_cli_cmd_license }, 1066 { "quit", wpa_cli_cmd_quit }, 1067 { "set", wpa_cli_cmd_set }, 1068 { "logon", wpa_cli_cmd_logon }, 1069 { "logoff", wpa_cli_cmd_logoff }, 1070 { "pmksa", wpa_cli_cmd_pmksa }, 1071 { "reassociate", wpa_cli_cmd_reassociate }, 1072 { "preauthenticate", wpa_cli_cmd_preauthenticate }, 1073 { "identity", wpa_cli_cmd_identity }, 1074 { "password", wpa_cli_cmd_password }, 1075 { "new_password", wpa_cli_cmd_new_password }, 1076 { "pin", wpa_cli_cmd_pin }, 1077 { "otp", wpa_cli_cmd_otp }, 1078 { "passphrase", wpa_cli_cmd_passphrase }, 1079 { "bssid", wpa_cli_cmd_bssid }, 1080 #ifdef ANDROID 1081 { "blacklist", wpa_cli_cmd_blacklist }, 1082 #endif 1083 { "list_networks", wpa_cli_cmd_list_networks }, 1084 { "select_network", wpa_cli_cmd_select_network }, 1085 { "enable_network", wpa_cli_cmd_enable_network }, 1086 { "disable_network", wpa_cli_cmd_disable_network }, 1087 { "add_network", wpa_cli_cmd_add_network }, 1088 { "remove_network", wpa_cli_cmd_remove_network }, 1089 { "set_network", wpa_cli_cmd_set_network }, 1090 { "get_network", wpa_cli_cmd_get_network }, 1091 { "save_config", wpa_cli_cmd_save_config }, 1092 { "disconnect", wpa_cli_cmd_disconnect }, 1093 { "reconnect", wpa_cli_cmd_reconnect }, 1094 { "scan", wpa_cli_cmd_scan }, 1095 { "scan_results", wpa_cli_cmd_scan_results }, 1096 { "get_capability", wpa_cli_cmd_get_capability }, 1097 { "reconfigure", wpa_cli_cmd_reconfigure }, 1098 { "terminate", wpa_cli_cmd_terminate }, 1099 { "interface_add", wpa_cli_cmd_interface_add }, 1100 { "interface_remove", wpa_cli_cmd_interface_remove }, 1101 { "ap_scan", wpa_cli_cmd_ap_scan }, 1102 { "stkstart", wpa_cli_cmd_stkstart }, 1103 { "driver", wpa_cli_cmd_driver }, 1104 { NULL, NULL } 1105 }; 1106 1107 1108 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1109 { 1110 struct wpa_cli_cmd *cmd, *match = NULL; 1111 int count; 1112 int ret = 0; 1113 1114 count = 0; 1115 cmd = wpa_cli_commands; 1116 while (cmd->cmd) { 1117 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) 1118 { 1119 match = cmd; 1120 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { 1121 /* we have an exact match */ 1122 count = 1; 1123 break; 1124 } 1125 count++; 1126 } 1127 cmd++; 1128 } 1129 1130 if (count > 1) { 1131 printf("Ambiguous command '%s'; possible commands:", argv[0]); 1132 cmd = wpa_cli_commands; 1133 while (cmd->cmd) { 1134 if (os_strncasecmp(cmd->cmd, argv[0], 1135 os_strlen(argv[0])) == 0) { 1136 printf(" %s", cmd->cmd); 1137 } 1138 cmd++; 1139 } 1140 printf("\n"); 1141 ret = 1; 1142 } else if (count == 0) { 1143 printf("Unknown command '%s'\n", argv[0]); 1144 ret = 1; 1145 } else { 1146 if( os_strncasecmp( "level", argv[0], os_strlen(argv[0]) ) == 0 ) { 1147 ctrl = monitor_conn; 1148 } 1149 ret = match->handler(ctrl, argc - 1, &argv[1]); 1150 } 1151 1152 return ret; 1153 } 1154 1155 1156 static int str_match(const char *a, const char *b) 1157 { 1158 return os_strncmp(a, b, os_strlen(b)) == 0; 1159 } 1160 1161 1162 static int wpa_cli_exec(const char *program, const char *arg1, 1163 const char *arg2) 1164 { 1165 char *cmd; 1166 size_t len; 1167 1168 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; 1169 cmd = os_malloc(len); 1170 if (cmd == NULL) 1171 return -1; 1172 os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); 1173 cmd[len - 1] = '\0'; 1174 #ifndef _WIN32_WCE 1175 system(cmd); 1176 #endif /* _WIN32_WCE */ 1177 os_free(cmd); 1178 1179 return 0; 1180 } 1181 1182 1183 static void wpa_cli_action_process(const char *msg) 1184 { 1185 const char *pos; 1186 char *copy = NULL, *id, *pos2; 1187 1188 pos = msg; 1189 if (*pos == '<') { 1190 /* skip priority */ 1191 pos = os_strchr(pos, '>'); 1192 if (pos) 1193 pos++; 1194 else 1195 pos = msg; 1196 } 1197 1198 if (str_match(pos, WPA_EVENT_CONNECTED)) { 1199 int new_id = -1; 1200 os_unsetenv("WPA_ID"); 1201 os_unsetenv("WPA_ID_STR"); 1202 os_unsetenv("WPA_CTRL_DIR"); 1203 1204 pos = os_strstr(pos, "[id="); 1205 if (pos) 1206 copy = os_strdup(pos + 4); 1207 1208 if (copy) { 1209 pos2 = id = copy; 1210 while (*pos2 && *pos2 != ' ') 1211 pos2++; 1212 *pos2++ = '\0'; 1213 new_id = atoi(id); 1214 os_setenv("WPA_ID", id, 1); 1215 while (*pos2 && *pos2 != '=') 1216 pos2++; 1217 if (*pos2 == '=') 1218 pos2++; 1219 id = pos2; 1220 while (*pos2 && *pos2 != ']') 1221 pos2++; 1222 *pos2 = '\0'; 1223 os_setenv("WPA_ID_STR", id, 1); 1224 os_free(copy); 1225 } 1226 1227 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); 1228 1229 if (!wpa_cli_connected || new_id != wpa_cli_last_id) { 1230 wpa_cli_connected = 1; 1231 wpa_cli_last_id = new_id; 1232 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); 1233 } 1234 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { 1235 if (wpa_cli_connected) { 1236 wpa_cli_connected = 0; 1237 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); 1238 } 1239 } else if (str_match(pos, WPA_EVENT_TERMINATING)) { 1240 printf("wpa_supplicant is terminating - stop monitoring\n"); 1241 wpa_cli_quit = 1; 1242 } 1243 } 1244 1245 1246 #ifndef CONFIG_ANSI_C_EXTRA 1247 static void wpa_cli_action_cb(char *msg, size_t len) 1248 { 1249 wpa_cli_action_process(msg); 1250 } 1251 #endif /* CONFIG_ANSI_C_EXTRA */ 1252 1253 1254 static void wpa_cli_reconnect(void) 1255 { 1256 wpa_cli_close_connection(); 1257 ctrl_conn = wpa_cli_open_connection(ctrl_ifname); 1258 if (ctrl_conn) { 1259 printf("Connection to wpa_supplicant re-established\n"); 1260 if (wpa_ctrl_attach(monitor_conn) == 0) { 1261 wpa_cli_attached = 1; 1262 } else { 1263 printf("Warning: Failed to attach to " 1264 "wpa_supplicant.\n"); 1265 } 1266 } 1267 } 1268 1269 1270 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, 1271 int action_monitor) 1272 { 1273 int first = 1; 1274 if (ctrl == NULL) { 1275 wpa_cli_reconnect(); 1276 return; 1277 } 1278 while (wpa_ctrl_pending(ctrl) > 0) { 1279 char buf[256]; 1280 size_t len = sizeof(buf) - 1; 1281 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { 1282 buf[len] = '\0'; 1283 if (action_monitor) 1284 wpa_cli_action_process(buf); 1285 else { 1286 if (in_read && first) 1287 printf("\n"); 1288 first = 0; 1289 printf("%s\n", buf); 1290 } 1291 } else { 1292 printf("Could not read pending message.\n"); 1293 break; 1294 } 1295 } 1296 1297 if (wpa_ctrl_pending(ctrl) < 0) { 1298 printf("Connection to wpa_supplicant lost - trying to " 1299 "reconnect\n"); 1300 wpa_cli_reconnect(); 1301 } 1302 } 1303 1304 1305 #ifdef CONFIG_READLINE 1306 static char * wpa_cli_cmd_gen(const char *text, int state) 1307 { 1308 static int i, len; 1309 const char *cmd; 1310 1311 if (state == 0) { 1312 i = 0; 1313 len = os_strlen(text); 1314 } 1315 1316 while ((cmd = wpa_cli_commands[i].cmd)) { 1317 i++; 1318 if (os_strncasecmp(cmd, text, len) == 0) 1319 return os_strdup(cmd); 1320 } 1321 1322 return NULL; 1323 } 1324 1325 1326 static char * wpa_cli_dummy_gen(const char *text, int state) 1327 { 1328 return NULL; 1329 } 1330 1331 1332 static char ** wpa_cli_completion(const char *text, int start, int end) 1333 { 1334 return rl_completion_matches(text, start == 0 ? 1335 wpa_cli_cmd_gen : wpa_cli_dummy_gen); 1336 } 1337 #endif /* CONFIG_READLINE */ 1338 1339 1340 static void wpa_cli_interactive(void) 1341 { 1342 #define max_args 10 1343 char cmdbuf[256], *cmd, *argv[max_args], *pos; 1344 int argc; 1345 #ifdef CONFIG_READLINE 1346 char *home, *hfile = NULL; 1347 #endif /* CONFIG_READLINE */ 1348 1349 printf("\nInteractive mode\n\n"); 1350 1351 #ifdef CONFIG_READLINE 1352 rl_attempted_completion_function = wpa_cli_completion; 1353 home = getenv("HOME"); 1354 if (home) { 1355 const char *fname = ".wpa_cli_history"; 1356 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; 1357 hfile = os_malloc(hfile_len); 1358 if (hfile) { 1359 os_snprintf(hfile, hfile_len, "%s/%s", home, fname); 1360 hfile[hfile_len - 1] = '\0'; 1361 read_history(hfile); 1362 stifle_history(100); 1363 } 1364 } 1365 #endif /* CONFIG_READLINE */ 1366 1367 do { 1368 wpa_cli_recv_pending(monitor_conn, 0, 0); 1369 #ifndef CONFIG_NATIVE_WINDOWS 1370 alarm(1); 1371 #endif /* CONFIG_NATIVE_WINDOWS */ 1372 #ifdef CONFIG_READLINE 1373 cmd = readline("> "); 1374 if (cmd && *cmd) { 1375 HIST_ENTRY *h; 1376 while (next_history()) 1377 ; 1378 h = previous_history(); 1379 if (h == NULL || os_strcmp(cmd, h->line) != 0) 1380 add_history(cmd); 1381 next_history(); 1382 } 1383 #else /* CONFIG_READLINE */ 1384 printf("> "); 1385 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); 1386 #endif /* CONFIG_READLINE */ 1387 #ifndef CONFIG_NATIVE_WINDOWS 1388 alarm(0); 1389 #endif /* CONFIG_NATIVE_WINDOWS */ 1390 if (cmd == NULL) 1391 break; 1392 wpa_cli_recv_pending(monitor_conn, 0, 0); 1393 pos = cmd; 1394 while (*pos != '\0') { 1395 if (*pos == '\n') { 1396 *pos = '\0'; 1397 break; 1398 } 1399 pos++; 1400 } 1401 argc = 0; 1402 pos = cmd; 1403 for (;;) { 1404 while (*pos == ' ') 1405 pos++; 1406 if (*pos == '\0') 1407 break; 1408 argv[argc] = pos; 1409 argc++; 1410 if (argc == max_args) 1411 break; 1412 if (*pos == '"') { 1413 char *pos2 = os_strrchr(pos, '"'); 1414 if (pos2) 1415 pos = pos2 + 1; 1416 } 1417 while (*pos != '\0' && *pos != ' ') 1418 pos++; 1419 if (*pos == ' ') 1420 *pos++ = '\0'; 1421 } 1422 if (argc) 1423 wpa_request(ctrl_conn, argc, argv); 1424 1425 if (cmd != cmdbuf) 1426 os_free(cmd); 1427 } while (!wpa_cli_quit); 1428 1429 #ifdef CONFIG_READLINE 1430 if (hfile) { 1431 /* Save command history, excluding lines that may contain 1432 * passwords. */ 1433 HIST_ENTRY *h; 1434 history_set_pos(0); 1435 h = next_history(); 1436 while (h) { 1437 char *p = h->line; 1438 while (*p == ' ' || *p == '\t') 1439 p++; 1440 if (os_strncasecmp(p, "pa", 2) == 0 || 1441 os_strncasecmp(p, "o", 1) == 0 || 1442 os_strncasecmp(p, "n", 1)) { 1443 h = remove_history(where_history()); 1444 if (h) { 1445 os_free(h->line); 1446 os_free(h->data); 1447 os_free(h); 1448 } 1449 h = current_history(); 1450 } else { 1451 h = next_history(); 1452 } 1453 } 1454 write_history(hfile); 1455 os_free(hfile); 1456 } 1457 #endif /* CONFIG_READLINE */ 1458 } 1459 1460 1461 static void wpa_cli_action(struct wpa_ctrl *ctrl) 1462 { 1463 #ifdef CONFIG_ANSI_C_EXTRA 1464 /* TODO: ANSI C version(?) */ 1465 printf("Action processing not supported in ANSI C build.\n"); 1466 #else /* CONFIG_ANSI_C_EXTRA */ 1467 fd_set rfds; 1468 int fd, res; 1469 struct timeval tv; 1470 char buf[256]; /* note: large enough to fit in unsolicited messages */ 1471 size_t len; 1472 1473 fd = wpa_ctrl_get_fd(ctrl); 1474 1475 while (!wpa_cli_quit) { 1476 FD_ZERO(&rfds); 1477 FD_SET(fd, &rfds); 1478 tv.tv_sec = 2; 1479 tv.tv_usec = 0; 1480 res = select(fd + 1, &rfds, NULL, NULL, &tv); 1481 if (res < 0 && errno != EINTR) { 1482 perror("select"); 1483 break; 1484 } 1485 1486 if (FD_ISSET(fd, &rfds)) 1487 wpa_cli_recv_pending(ctrl, 0, 1); 1488 else { 1489 /* verify that connection is still working */ 1490 len = sizeof(buf) - 1; 1491 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, 1492 wpa_cli_action_cb) < 0 || 1493 len < 4 || os_memcmp(buf, "PONG", 4) != 0) { 1494 printf("wpa_supplicant did not reply to PING " 1495 "command - exiting\n"); 1496 break; 1497 } 1498 } 1499 } 1500 #endif /* CONFIG_ANSI_C_EXTRA */ 1501 } 1502 1503 1504 static void wpa_cli_cleanup(void) 1505 { 1506 wpa_cli_close_connection(); 1507 if (pid_file) 1508 os_daemonize_terminate(pid_file); 1509 1510 os_program_deinit(); 1511 } 1512 1513 static void wpa_cli_terminate(int sig) 1514 { 1515 wpa_cli_cleanup(); 1516 exit(0); 1517 } 1518 1519 1520 #ifndef CONFIG_NATIVE_WINDOWS 1521 static void wpa_cli_alarm(int sig) 1522 { 1523 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { 1524 printf("Connection to wpa_supplicant lost - trying to " 1525 "reconnect\n"); 1526 wpa_cli_close_connection(); 1527 } 1528 if (!monitor_conn) 1529 wpa_cli_reconnect(); 1530 if (monitor_conn) 1531 wpa_cli_recv_pending(monitor_conn, 1, 0); 1532 alarm(1); 1533 } 1534 #endif /* CONFIG_NATIVE_WINDOWS */ 1535 1536 1537 static char * wpa_cli_get_default_ifname(void) 1538 { 1539 char *ifname = NULL; 1540 1541 #ifdef CONFIG_CTRL_IFACE_UNIX 1542 struct dirent *dent; 1543 DIR *dir = opendir(ctrl_iface_dir); 1544 if (!dir) { 1545 #ifdef ANDROID 1546 char ifprop[PROPERTY_VALUE_MAX]; 1547 if (property_get("wifi.interface", ifprop, NULL) != 0) { 1548 ifname = os_strdup(ifprop); 1549 printf("Using interface '%s'\n", ifname); 1550 return ifname; 1551 } 1552 #endif 1553 return NULL; 1554 } 1555 while ((dent = readdir(dir))) { 1556 #ifdef _DIRENT_HAVE_D_TYPE 1557 /* 1558 * Skip the file if it is not a socket. Also accept 1559 * DT_UNKNOWN (0) in case the C library or underlying 1560 * file system does not support d_type. 1561 */ 1562 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) 1563 continue; 1564 #endif /* _DIRENT_HAVE_D_TYPE */ 1565 if (os_strcmp(dent->d_name, ".") == 0 || 1566 os_strcmp(dent->d_name, "..") == 0) 1567 continue; 1568 printf("Selected interface '%s'\n", dent->d_name); 1569 ifname = os_strdup(dent->d_name); 1570 break; 1571 } 1572 closedir(dir); 1573 #endif /* CONFIG_CTRL_IFACE_UNIX */ 1574 1575 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 1576 char buf[4096], *pos; 1577 size_t len; 1578 struct wpa_ctrl *ctrl; 1579 int ret; 1580 1581 ctrl = wpa_ctrl_open(NULL); 1582 if (ctrl == NULL) 1583 return NULL; 1584 1585 len = sizeof(buf) - 1; 1586 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); 1587 if (ret >= 0) { 1588 buf[len] = '\0'; 1589 pos = os_strchr(buf, '\n'); 1590 if (pos) 1591 *pos = '\0'; 1592 ifname = os_strdup(buf); 1593 } 1594 wpa_ctrl_close(ctrl); 1595 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 1596 1597 return ifname; 1598 } 1599 1600 1601 int main(int argc, char *argv[]) 1602 { 1603 int interactive; 1604 int warning_displayed = 0; 1605 int c; 1606 int daemonize = 0; 1607 int ret = 0; 1608 const char *global = NULL; 1609 1610 if (os_program_init()) 1611 return -1; 1612 1613 for (;;) { 1614 c = getopt(argc, argv, "a:Bg:hi:p:P:v"); 1615 if (c < 0) 1616 break; 1617 switch (c) { 1618 case 'a': 1619 action_file = optarg; 1620 break; 1621 case 'B': 1622 daemonize = 1; 1623 break; 1624 case 'g': 1625 global = optarg; 1626 break; 1627 case 'h': 1628 usage(); 1629 return 0; 1630 case 'v': 1631 printf("%s\n", wpa_cli_version); 1632 return 0; 1633 case 'i': 1634 os_free(ctrl_ifname); 1635 ctrl_ifname = os_strdup(optarg); 1636 break; 1637 case 'p': 1638 ctrl_iface_dir = optarg; 1639 break; 1640 case 'P': 1641 pid_file = optarg; 1642 break; 1643 default: 1644 usage(); 1645 return -1; 1646 } 1647 } 1648 1649 interactive = (argc == optind) && (action_file == NULL); 1650 1651 if (interactive) 1652 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); 1653 1654 if (global) { 1655 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 1656 ctrl_conn = wpa_ctrl_open(NULL); 1657 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 1658 ctrl_conn = wpa_ctrl_open(global); 1659 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 1660 if (ctrl_conn == NULL) { 1661 perror("Failed to connect to wpa_supplicant - " 1662 "wpa_ctrl_open"); 1663 return -1; 1664 } 1665 } 1666 1667 for (; !global;) { 1668 if (ctrl_ifname == NULL) 1669 ctrl_ifname = wpa_cli_get_default_ifname(); 1670 ctrl_conn = wpa_cli_open_connection(ctrl_ifname); 1671 if (ctrl_conn) { 1672 if (warning_displayed) 1673 printf("Connection established.\n"); 1674 break; 1675 } 1676 1677 if (!interactive) { 1678 perror("Failed to connect to wpa_supplicant - " 1679 "wpa_ctrl_open"); 1680 return -1; 1681 } 1682 1683 if (!warning_displayed) { 1684 printf("Could not connect to wpa_supplicant - " 1685 "re-trying\n"); 1686 warning_displayed = 1; 1687 } 1688 os_sleep(1, 0); 1689 continue; 1690 } 1691 1692 #ifndef _WIN32_WCE 1693 signal(SIGINT, wpa_cli_terminate); 1694 signal(SIGTERM, wpa_cli_terminate); 1695 #endif /* _WIN32_WCE */ 1696 #ifndef CONFIG_NATIVE_WINDOWS 1697 signal(SIGALRM, wpa_cli_alarm); 1698 #endif /* CONFIG_NATIVE_WINDOWS */ 1699 1700 if (interactive || action_file) { 1701 if (wpa_ctrl_attach(monitor_conn) == 0) { 1702 wpa_cli_attached = 1; 1703 } else { 1704 printf("Warning: Failed to attach to " 1705 "wpa_supplicant.\n"); 1706 if (!interactive) 1707 return -1; 1708 } 1709 } 1710 1711 if (daemonize && os_daemonize(pid_file)) 1712 return -1; 1713 1714 if (interactive) 1715 wpa_cli_interactive(); 1716 else if (action_file) 1717 wpa_cli_action(ctrl_conn); 1718 else 1719 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); 1720 1721 os_free(ctrl_ifname); 1722 wpa_cli_cleanup(); 1723 1724 return ret; 1725 } 1726 1727 #else /* CONFIG_CTRL_IFACE */ 1728 int main(int argc, char *argv[]) 1729 { 1730 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); 1731 return -1; 1732 } 1733 #endif /* CONFIG_CTRL_IFACE */ 1734