1 /* 2 * WPA Supplicant - command line interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "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 #ifdef CONFIG_WPA_CLI_FORK 27 #include <sys/wait.h> 28 #endif /* CONFIG_WPA_CLI_FORK */ 29 30 #include "common/wpa_ctrl.h" 31 #include "common.h" 32 #include "common/version.h" 33 34 35 static const char *wpa_cli_version = 36 "wpa_cli v" VERSION_STR "\n" 37 "Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors"; 38 39 40 static const char *wpa_cli_license = 41 "This program is free software. You can distribute it and/or modify it\n" 42 "under the terms of the GNU General Public License version 2.\n" 43 "\n" 44 "Alternatively, this software may be distributed under the terms of the\n" 45 "BSD license. See README and COPYING for more details.\n"; 46 47 static const char *wpa_cli_full_license = 48 "This program is free software; you can redistribute it and/or modify\n" 49 "it under the terms of the GNU General Public License version 2 as\n" 50 "published by the Free Software Foundation.\n" 51 "\n" 52 "This program is distributed in the hope that it will be useful,\n" 53 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 54 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 55 "GNU General Public License for more details.\n" 56 "\n" 57 "You should have received a copy of the GNU General Public License\n" 58 "along with this program; if not, write to the Free Software\n" 59 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" 60 "\n" 61 "Alternatively, this software may be distributed under the terms of the\n" 62 "BSD license.\n" 63 "\n" 64 "Redistribution and use in source and binary forms, with or without\n" 65 "modification, are permitted provided that the following conditions are\n" 66 "met:\n" 67 "\n" 68 "1. Redistributions of source code must retain the above copyright\n" 69 " notice, this list of conditions and the following disclaimer.\n" 70 "\n" 71 "2. Redistributions in binary form must reproduce the above copyright\n" 72 " notice, this list of conditions and the following disclaimer in the\n" 73 " documentation and/or other materials provided with the distribution.\n" 74 "\n" 75 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 76 " names of its contributors may be used to endorse or promote products\n" 77 " derived from this software without specific prior written permission.\n" 78 "\n" 79 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 80 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 81 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 82 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 83 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 84 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 85 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 86 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 87 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 88 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 89 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 90 "\n"; 91 92 static struct wpa_ctrl *ctrl_conn; 93 static struct wpa_ctrl *mon_conn; 94 #ifdef CONFIG_WPA_CLI_FORK 95 static pid_t mon_pid = 0; 96 #endif /* CONFIG_WPA_CLI_FORK */ 97 static int wpa_cli_quit = 0; 98 static int wpa_cli_attached = 0; 99 static int wpa_cli_connected = 0; 100 static int wpa_cli_last_id = 0; 101 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; 102 static char *ctrl_ifname = NULL; 103 static const char *pid_file = NULL; 104 static const char *action_file = NULL; 105 static int ping_interval = 5; 106 static int interactive = 0; 107 108 109 static void print_help(); 110 111 112 static void usage(void) 113 { 114 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " 115 "[-a<action file>] \\\n" 116 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] " 117 "[command..]\n" 118 " -h = help (show this usage text)\n" 119 " -v = shown version information\n" 120 " -a = run in daemon mode executing the action file based on " 121 "events from\n" 122 " wpa_supplicant\n" 123 " -B = run a daemon in the background\n" 124 " default path: /var/run/wpa_supplicant\n" 125 " default interface: first interface found in socket path\n"); 126 print_help(); 127 } 128 129 130 #ifdef CONFIG_WPA_CLI_FORK 131 static int in_query = 0; 132 133 static void wpa_cli_monitor_sig(int sig) 134 { 135 if (sig == SIGUSR1) 136 in_query = 1; 137 else if (sig == SIGUSR2) 138 in_query = 0; 139 } 140 141 static void wpa_cli_monitor(void) 142 { 143 char buf[256]; 144 size_t len = sizeof(buf) - 1; 145 struct timeval tv; 146 fd_set rfds; 147 148 signal(SIGUSR1, wpa_cli_monitor_sig); 149 signal(SIGUSR2, wpa_cli_monitor_sig); 150 151 while (mon_conn) { 152 int s = wpa_ctrl_get_fd(mon_conn); 153 tv.tv_sec = 5; 154 tv.tv_usec = 0; 155 FD_ZERO(&rfds); 156 FD_SET(s, &rfds); 157 if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) { 158 if (errno == EINTR) 159 continue; 160 perror("select"); 161 break; 162 } 163 if (mon_conn == NULL) 164 break; 165 if (FD_ISSET(s, &rfds)) { 166 len = sizeof(buf) - 1; 167 int res = wpa_ctrl_recv(mon_conn, buf, &len); 168 if (res < 0) { 169 perror("wpa_ctrl_recv"); 170 break; 171 } 172 buf[len] = '\0'; 173 if (in_query) 174 printf("\r"); 175 printf("%s\n", buf); 176 kill(getppid(), SIGUSR1); 177 } 178 } 179 } 180 #endif /* CONFIG_WPA_CLI_FORK */ 181 182 183 static int wpa_cli_open_connection(const char *ifname, int attach) 184 { 185 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) 186 ctrl_conn = wpa_ctrl_open(ifname); 187 if (ctrl_conn == NULL) 188 return -1; 189 190 if (attach && interactive) 191 mon_conn = wpa_ctrl_open(ifname); 192 else 193 mon_conn = NULL; 194 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 195 char *cfile; 196 int flen, res; 197 198 if (ifname == NULL) 199 return -1; 200 201 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; 202 cfile = os_malloc(flen); 203 if (cfile == NULL) 204 return -1L; 205 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); 206 if (res < 0 || res >= flen) { 207 os_free(cfile); 208 return -1; 209 } 210 211 ctrl_conn = wpa_ctrl_open(cfile); 212 if (ctrl_conn == NULL) { 213 os_free(cfile); 214 return -1; 215 } 216 217 if (attach && interactive) 218 mon_conn = wpa_ctrl_open(cfile); 219 else 220 mon_conn = NULL; 221 os_free(cfile); 222 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 223 224 if (mon_conn) { 225 if (wpa_ctrl_attach(mon_conn) == 0) { 226 wpa_cli_attached = 1; 227 } else { 228 printf("Warning: Failed to attach to " 229 "wpa_supplicant.\n"); 230 return -1; 231 } 232 233 #ifdef CONFIG_WPA_CLI_FORK 234 { 235 pid_t p = fork(); 236 if (p < 0) { 237 perror("fork"); 238 return -1; 239 } 240 if (p == 0) { 241 wpa_cli_monitor(); 242 exit(0); 243 } else 244 mon_pid = p; 245 } 246 #endif /* CONFIG_WPA_CLI_FORK */ 247 } 248 249 return 0; 250 } 251 252 253 static void wpa_cli_close_connection(void) 254 { 255 if (ctrl_conn == NULL) 256 return; 257 258 #ifdef CONFIG_WPA_CLI_FORK 259 if (mon_pid) { 260 int status; 261 kill(mon_pid, SIGPIPE); 262 wait(&status); 263 mon_pid = 0; 264 } 265 #endif /* CONFIG_WPA_CLI_FORK */ 266 267 if (wpa_cli_attached) { 268 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); 269 wpa_cli_attached = 0; 270 } 271 wpa_ctrl_close(ctrl_conn); 272 ctrl_conn = NULL; 273 if (mon_conn) { 274 wpa_ctrl_close(mon_conn); 275 mon_conn = NULL; 276 } 277 } 278 279 static const char *skip_priority(const char *msg) 280 { 281 const char *pos = msg; 282 283 if (*msg != '<') 284 return msg; 285 286 for (pos = msg + 1; isdigit((unsigned char)*pos); pos++) 287 continue; 288 289 if (*pos != '>') 290 return msg; 291 292 return ++pos; 293 } 294 295 static const char *fmttime(char *buf, size_t buflen) 296 { 297 struct timeval tv; 298 struct tm tm; 299 time_t t; 300 301 if (buflen <= 8) 302 return NULL; 303 304 (void)gettimeofday(&tv, NULL); 305 t = (time_t)tv.tv_sec; 306 (void)localtime_r(&t, &tm); 307 (void)strftime(buf, buflen, "%H:%M:%S", &tm); 308 (void)snprintf(buf + 8, buflen - 8, ".%.3d", (int)(tv.tv_usec / 1000)); 309 return buf; 310 } 311 312 static void wpa_cli_msg_cb(char *msg, size_t len) 313 { 314 char tbuf[32]; 315 printf("%s: %s\n", fmttime(tbuf, sizeof(tbuf)), skip_priority(msg)); 316 } 317 318 319 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) 320 { 321 char buf[2048]; 322 size_t len; 323 int ret; 324 325 if (ctrl_conn == NULL) { 326 printf("Not connected to wpa_supplicant - command dropped.\n"); 327 return -1; 328 } 329 len = sizeof(buf) - 1; 330 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 331 wpa_cli_msg_cb); 332 if (ret == -2) { 333 printf("'%s' command timed out.\n", cmd); 334 return -2; 335 } else if (ret < 0) { 336 printf("'%s' command failed.\n", cmd); 337 return -1; 338 } 339 if (print) { 340 buf[len] = '\0'; 341 wpa_cli_msg_cb(buf, 0); 342 } 343 return 0; 344 } 345 346 347 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) 348 { 349 return _wpa_ctrl_command(ctrl, cmd, 1); 350 } 351 352 353 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 354 { 355 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; 356 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); 357 } 358 359 360 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 361 { 362 return wpa_ctrl_command(ctrl, "PING"); 363 } 364 365 366 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 367 { 368 return wpa_ctrl_command(ctrl, "MIB"); 369 } 370 371 372 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 373 { 374 return wpa_ctrl_command(ctrl, "PMKSA"); 375 } 376 377 378 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 379 { 380 print_help(); 381 return 0; 382 } 383 384 385 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) 386 { 387 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); 388 return 0; 389 } 390 391 392 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 393 { 394 wpa_cli_quit = 1; 395 return 0; 396 } 397 398 399 static void wpa_cli_show_variables(void) 400 { 401 printf("set variables:\n" 402 " EAPOL::heldPeriod (EAPOL state machine held period, " 403 "in seconds)\n" 404 " EAPOL::authPeriod (EAPOL state machine authentication " 405 "period, in seconds)\n" 406 " EAPOL::startPeriod (EAPOL state machine start period, in " 407 "seconds)\n" 408 " EAPOL::maxStart (EAPOL state machine maximum start " 409 "attempts)\n"); 410 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " 411 "seconds)\n" 412 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" 413 " threshold\n\tpercentage)\n" 414 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " 415 "security\n\tassociation in seconds)\n"); 416 } 417 418 419 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 420 { 421 char cmd[256]; 422 int res; 423 424 if (argc == 0) { 425 wpa_cli_show_variables(); 426 return 0; 427 } 428 429 if (argc != 2) { 430 printf("Invalid SET command: needs two arguments (variable " 431 "name and value)\n"); 432 return -1; 433 } 434 435 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); 436 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 437 printf("Too long SET command.\n"); 438 return -1; 439 } 440 return wpa_ctrl_command(ctrl, cmd); 441 } 442 443 444 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) 445 { 446 return wpa_ctrl_command(ctrl, "LOGOFF"); 447 } 448 449 450 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) 451 { 452 return wpa_ctrl_command(ctrl, "LOGON"); 453 } 454 455 456 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, 457 char *argv[]) 458 { 459 return wpa_ctrl_command(ctrl, "REASSOCIATE"); 460 } 461 462 463 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, 464 char *argv[]) 465 { 466 char cmd[256]; 467 int res; 468 469 if (argc != 1) { 470 printf("Invalid PREAUTH command: needs one argument " 471 "(BSSID)\n"); 472 return -1; 473 } 474 475 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); 476 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 477 printf("Too long PREAUTH command.\n"); 478 return -1; 479 } 480 return wpa_ctrl_command(ctrl, cmd); 481 } 482 483 484 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 485 { 486 char cmd[256]; 487 int res; 488 489 if (argc != 1) { 490 printf("Invalid AP_SCAN command: needs one argument (ap_scan " 491 "value)\n"); 492 return -1; 493 } 494 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); 495 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 496 printf("Too long AP_SCAN command.\n"); 497 return -1; 498 } 499 return wpa_ctrl_command(ctrl, cmd); 500 } 501 502 503 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, 504 char *argv[]) 505 { 506 char cmd[256]; 507 int res; 508 509 if (argc != 1) { 510 printf("Invalid STKSTART command: needs one argument " 511 "(Peer STA MAC address)\n"); 512 return -1; 513 } 514 515 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]); 516 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 517 printf("Too long STKSTART command.\n"); 518 return -1; 519 } 520 return wpa_ctrl_command(ctrl, cmd); 521 } 522 523 524 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[]) 525 { 526 char cmd[256]; 527 int res; 528 529 if (argc != 1) { 530 printf("Invalid FT_DS command: needs one argument " 531 "(Target AP MAC address)\n"); 532 return -1; 533 } 534 535 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]); 536 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 537 printf("Too long FT_DS command.\n"); 538 return -1; 539 } 540 return wpa_ctrl_command(ctrl, cmd); 541 } 542 543 544 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) 545 { 546 char cmd[256]; 547 int res; 548 549 if (argc == 0) { 550 /* Any BSSID */ 551 return wpa_ctrl_command(ctrl, "WPS_PBC"); 552 } 553 554 /* Specific BSSID */ 555 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]); 556 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 557 printf("Too long WPS_PBC command.\n"); 558 return -1; 559 } 560 return wpa_ctrl_command(ctrl, cmd); 561 } 562 563 564 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 565 { 566 char cmd[256]; 567 int res; 568 569 if (argc == 0) { 570 printf("Invalid WPS_PIN command: need one or two arguments:\n" 571 "- BSSID: use 'any' to select any\n" 572 "- PIN: optional, used only with devices that have no " 573 "display\n"); 574 return -1; 575 } 576 577 if (argc == 1) { 578 /* Use dynamically generated PIN (returned as reply) */ 579 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]); 580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 581 printf("Too long WPS_PIN command.\n"); 582 return -1; 583 } 584 return wpa_ctrl_command(ctrl, cmd); 585 } 586 587 /* Use hardcoded PIN from a label */ 588 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]); 589 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 590 printf("Too long WPS_PIN command.\n"); 591 return -1; 592 } 593 return wpa_ctrl_command(ctrl, cmd); 594 } 595 596 597 #ifdef CONFIG_WPS_OOB 598 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[]) 599 { 600 char cmd[256]; 601 int res; 602 603 if (argc != 3 && argc != 4) { 604 printf("Invalid WPS_OOB command: need three or four " 605 "arguments:\n" 606 "- DEV_TYPE: use 'ufd' or 'nfc'\n" 607 "- PATH: path of OOB device like '/mnt'\n" 608 "- METHOD: OOB method 'pin-e' or 'pin-r', " 609 "'cred'\n" 610 "- DEV_NAME: (only for NFC) device name like " 611 "'pn531'\n"); 612 return -1; 613 } 614 615 if (argc == 3) 616 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s", 617 argv[0], argv[1], argv[2]); 618 else 619 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s", 620 argv[0], argv[1], argv[2], argv[3]); 621 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 622 printf("Too long WPS_OOB command.\n"); 623 return -1; 624 } 625 return wpa_ctrl_command(ctrl, cmd); 626 } 627 #endif /* CONFIG_WPS_OOB */ 628 629 630 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) 631 { 632 char cmd[256]; 633 int res; 634 635 if (argc == 2) 636 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", 637 argv[0], argv[1]); 638 else if (argc == 6) { 639 char ssid_hex[2 * 32 + 1]; 640 char key_hex[2 * 64 + 1]; 641 int i; 642 643 ssid_hex[0] = '\0'; 644 for (i = 0; i < 32; i++) { 645 if (argv[2][i] == '\0') 646 break; 647 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); 648 } 649 650 key_hex[0] = '\0'; 651 for (i = 0; i < 64; i++) { 652 if (argv[5][i] == '\0') 653 break; 654 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]); 655 } 656 657 res = os_snprintf(cmd, sizeof(cmd), 658 "WPS_REG %s %s %s %s %s %s", 659 argv[0], argv[1], ssid_hex, argv[3], argv[4], 660 key_hex); 661 } else { 662 printf("Invalid WPS_REG command: need two arguments:\n" 663 "- BSSID: use 'any' to select any\n" 664 "- AP PIN\n"); 665 printf("Alternatively, six arguments can be used to " 666 "reconfigure the AP:\n" 667 "- BSSID: use 'any' to select any\n" 668 "- AP PIN\n" 669 "- new SSID\n" 670 "- new auth (OPEN, WPAPSK, WPA2PSK)\n" 671 "- new encr (NONE, WEP, TKIP, CCMP)\n" 672 "- new key\n"); 673 return -1; 674 } 675 676 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 677 printf("Too long WPS_REG command.\n"); 678 return -1; 679 } 680 return wpa_ctrl_command(ctrl, cmd); 681 } 682 683 684 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, 685 char *argv[]) 686 { 687 return wpa_ctrl_command(ctrl, "WPS_ER_START"); 688 689 } 690 691 692 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc, 693 char *argv[]) 694 { 695 return wpa_ctrl_command(ctrl, "WPS_ER_STOP"); 696 697 } 698 699 700 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, 701 char *argv[]) 702 { 703 char cmd[256]; 704 int res; 705 706 if (argc != 2) { 707 printf("Invalid WPS_ER_PIN command: need two arguments:\n" 708 "- UUID: use 'any' to select any\n" 709 "- PIN: Enrollee PIN\n"); 710 return -1; 711 } 712 713 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s", 714 argv[0], argv[1]); 715 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 716 printf("Too long WPS_ER_PIN command.\n"); 717 return -1; 718 } 719 return wpa_ctrl_command(ctrl, cmd); 720 } 721 722 723 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc, 724 char *argv[]) 725 { 726 char cmd[256]; 727 int res; 728 729 if (argc != 1) { 730 printf("Invalid WPS_ER_PBC command: need one argument:\n" 731 "- UUID: Specify the Enrollee\n"); 732 return -1; 733 } 734 735 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s", 736 argv[0]); 737 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 738 printf("Too long WPS_ER_PBC command.\n"); 739 return -1; 740 } 741 return wpa_ctrl_command(ctrl, cmd); 742 } 743 744 745 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, 746 char *argv[]) 747 { 748 char cmd[256]; 749 int res; 750 751 if (argc != 2) { 752 printf("Invalid WPS_ER_LEARN command: need two arguments:\n" 753 "- UUID: specify which AP to use\n" 754 "- PIN: AP PIN\n"); 755 return -1; 756 } 757 758 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s", 759 argv[0], argv[1]); 760 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 761 printf("Too long WPS_ER_LEARN command.\n"); 762 return -1; 763 } 764 return wpa_ctrl_command(ctrl, cmd); 765 } 766 767 768 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) 769 { 770 char cmd[256]; 771 int res; 772 773 if (argc != 1) { 774 printf("Invalid IBSS_RSN command: needs one argument " 775 "(Peer STA MAC address)\n"); 776 return -1; 777 } 778 779 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]); 780 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 781 printf("Too long IBSS_RSN command.\n"); 782 return -1; 783 } 784 return wpa_ctrl_command(ctrl, cmd); 785 } 786 787 788 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 789 { 790 char cmd[256]; 791 int res; 792 793 if (argc != 1) { 794 printf("Invalid LEVEL command: needs one argument (debug " 795 "level)\n"); 796 return -1; 797 } 798 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); 799 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 800 printf("Too long LEVEL command.\n"); 801 return -1; 802 } 803 return wpa_ctrl_command(ctrl, cmd); 804 } 805 806 807 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) 808 { 809 char cmd[256], *pos, *end; 810 int i, ret; 811 812 if (argc < 2) { 813 printf("Invalid IDENTITY command: needs two arguments " 814 "(network id and identity)\n"); 815 return -1; 816 } 817 818 end = cmd + sizeof(cmd); 819 pos = cmd; 820 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", 821 argv[0], argv[1]); 822 if (ret < 0 || ret >= end - pos) { 823 printf("Too long IDENTITY command.\n"); 824 return -1; 825 } 826 pos += ret; 827 for (i = 2; i < argc; i++) { 828 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 829 if (ret < 0 || ret >= end - pos) { 830 printf("Too long IDENTITY command.\n"); 831 return -1; 832 } 833 pos += ret; 834 } 835 836 return wpa_ctrl_command(ctrl, cmd); 837 } 838 839 840 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) 841 { 842 char cmd[256], *pos, *end; 843 int i, ret; 844 845 if (argc < 2) { 846 printf("Invalid PASSWORD command: needs two arguments " 847 "(network id and password)\n"); 848 return -1; 849 } 850 851 end = cmd + sizeof(cmd); 852 pos = cmd; 853 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", 854 argv[0], argv[1]); 855 if (ret < 0 || ret >= end - pos) { 856 printf("Too long PASSWORD command.\n"); 857 return -1; 858 } 859 pos += ret; 860 for (i = 2; i < argc; i++) { 861 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 862 if (ret < 0 || ret >= end - pos) { 863 printf("Too long PASSWORD command.\n"); 864 return -1; 865 } 866 pos += ret; 867 } 868 869 return wpa_ctrl_command(ctrl, cmd); 870 } 871 872 873 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, 874 char *argv[]) 875 { 876 char cmd[256], *pos, *end; 877 int i, ret; 878 879 if (argc < 2) { 880 printf("Invalid NEW_PASSWORD command: needs two arguments " 881 "(network id and password)\n"); 882 return -1; 883 } 884 885 end = cmd + sizeof(cmd); 886 pos = cmd; 887 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", 888 argv[0], argv[1]); 889 if (ret < 0 || ret >= end - pos) { 890 printf("Too long NEW_PASSWORD command.\n"); 891 return -1; 892 } 893 pos += ret; 894 for (i = 2; i < argc; i++) { 895 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 896 if (ret < 0 || ret >= end - pos) { 897 printf("Too long NEW_PASSWORD command.\n"); 898 return -1; 899 } 900 pos += ret; 901 } 902 903 return wpa_ctrl_command(ctrl, cmd); 904 } 905 906 907 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 908 { 909 char cmd[256], *pos, *end; 910 int i, ret; 911 912 if (argc < 2) { 913 printf("Invalid PIN command: needs two arguments " 914 "(network id and pin)\n"); 915 return -1; 916 } 917 918 end = cmd + sizeof(cmd); 919 pos = cmd; 920 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", 921 argv[0], argv[1]); 922 if (ret < 0 || ret >= end - pos) { 923 printf("Too long PIN command.\n"); 924 return -1; 925 } 926 pos += ret; 927 for (i = 2; i < argc; i++) { 928 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 929 if (ret < 0 || ret >= end - pos) { 930 printf("Too long PIN command.\n"); 931 return -1; 932 } 933 pos += ret; 934 } 935 return wpa_ctrl_command(ctrl, cmd); 936 } 937 938 939 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) 940 { 941 char cmd[256], *pos, *end; 942 int i, ret; 943 944 if (argc < 2) { 945 printf("Invalid OTP command: needs two arguments (network " 946 "id and password)\n"); 947 return -1; 948 } 949 950 end = cmd + sizeof(cmd); 951 pos = cmd; 952 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", 953 argv[0], argv[1]); 954 if (ret < 0 || ret >= end - pos) { 955 printf("Too long OTP command.\n"); 956 return -1; 957 } 958 pos += ret; 959 for (i = 2; i < argc; i++) { 960 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 961 if (ret < 0 || ret >= end - pos) { 962 printf("Too long OTP command.\n"); 963 return -1; 964 } 965 pos += ret; 966 } 967 968 return wpa_ctrl_command(ctrl, cmd); 969 } 970 971 972 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, 973 char *argv[]) 974 { 975 char cmd[256], *pos, *end; 976 int i, ret; 977 978 if (argc < 2) { 979 printf("Invalid PASSPHRASE command: needs two arguments " 980 "(network id and passphrase)\n"); 981 return -1; 982 } 983 984 end = cmd + sizeof(cmd); 985 pos = cmd; 986 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", 987 argv[0], argv[1]); 988 if (ret < 0 || ret >= end - pos) { 989 printf("Too long PASSPHRASE command.\n"); 990 return -1; 991 } 992 pos += ret; 993 for (i = 2; i < argc; i++) { 994 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 995 if (ret < 0 || ret >= end - pos) { 996 printf("Too long PASSPHRASE command.\n"); 997 return -1; 998 } 999 pos += ret; 1000 } 1001 1002 return wpa_ctrl_command(ctrl, cmd); 1003 } 1004 1005 1006 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1007 { 1008 char cmd[256], *pos, *end; 1009 int i, ret; 1010 1011 if (argc < 2) { 1012 printf("Invalid BSSID command: needs two arguments (network " 1013 "id and BSSID)\n"); 1014 return -1; 1015 } 1016 1017 end = cmd + sizeof(cmd); 1018 pos = cmd; 1019 ret = os_snprintf(pos, end - pos, "BSSID"); 1020 if (ret < 0 || ret >= end - pos) { 1021 printf("Too long BSSID command.\n"); 1022 return -1; 1023 } 1024 pos += ret; 1025 for (i = 0; i < argc; i++) { 1026 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1027 if (ret < 0 || ret >= end - pos) { 1028 printf("Too long BSSID command.\n"); 1029 return -1; 1030 } 1031 pos += ret; 1032 } 1033 1034 return wpa_ctrl_command(ctrl, cmd); 1035 } 1036 1037 1038 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, 1039 char *argv[]) 1040 { 1041 return wpa_ctrl_command(ctrl, "LIST_NETWORKS"); 1042 } 1043 1044 1045 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, 1046 char *argv[]) 1047 { 1048 char cmd[32]; 1049 int res; 1050 1051 if (argc < 1) { 1052 printf("Invalid SELECT_NETWORK command: needs one argument " 1053 "(network id)\n"); 1054 return -1; 1055 } 1056 1057 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]); 1058 if (res < 0 || (size_t) res >= sizeof(cmd)) 1059 return -1; 1060 cmd[sizeof(cmd) - 1] = '\0'; 1061 1062 return wpa_ctrl_command(ctrl, cmd); 1063 } 1064 1065 1066 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, 1067 char *argv[]) 1068 { 1069 char cmd[32]; 1070 int res; 1071 1072 if (argc < 1) { 1073 printf("Invalid ENABLE_NETWORK command: needs one argument " 1074 "(network id)\n"); 1075 return -1; 1076 } 1077 1078 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]); 1079 if (res < 0 || (size_t) res >= sizeof(cmd)) 1080 return -1; 1081 cmd[sizeof(cmd) - 1] = '\0'; 1082 1083 return wpa_ctrl_command(ctrl, cmd); 1084 } 1085 1086 1087 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, 1088 char *argv[]) 1089 { 1090 char cmd[32]; 1091 int res; 1092 1093 if (argc < 1) { 1094 printf("Invalid DISABLE_NETWORK command: needs one argument " 1095 "(network id)\n"); 1096 return -1; 1097 } 1098 1099 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]); 1100 if (res < 0 || (size_t) res >= sizeof(cmd)) 1101 return -1; 1102 cmd[sizeof(cmd) - 1] = '\0'; 1103 1104 return wpa_ctrl_command(ctrl, cmd); 1105 } 1106 1107 1108 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, 1109 char *argv[]) 1110 { 1111 return wpa_ctrl_command(ctrl, "ADD_NETWORK"); 1112 } 1113 1114 1115 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, 1116 char *argv[]) 1117 { 1118 char cmd[32]; 1119 int res; 1120 1121 if (argc < 1) { 1122 printf("Invalid REMOVE_NETWORK command: needs one argument " 1123 "(network id)\n"); 1124 return -1; 1125 } 1126 1127 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]); 1128 if (res < 0 || (size_t) res >= sizeof(cmd)) 1129 return -1; 1130 cmd[sizeof(cmd) - 1] = '\0'; 1131 1132 return wpa_ctrl_command(ctrl, cmd); 1133 } 1134 1135 1136 static void wpa_cli_show_network_variables(void) 1137 { 1138 printf("set_network variables:\n" 1139 " ssid (network name, SSID)\n" 1140 " psk (WPA passphrase or pre-shared key)\n" 1141 " key_mgmt (key management protocol)\n" 1142 " identity (EAP identity)\n" 1143 " password (EAP password)\n" 1144 " ...\n" 1145 "\n" 1146 "Note: Values are entered in the same format as the " 1147 "configuration file is using,\n" 1148 "i.e., strings values need to be inside double quotation " 1149 "marks.\n" 1150 "For example: set_network 1 ssid \"network name\"\n" 1151 "\n" 1152 "Please see wpa_supplicant.conf documentation for full list " 1153 "of\navailable variables.\n"); 1154 } 1155 1156 1157 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, 1158 char *argv[]) 1159 { 1160 char cmd[256]; 1161 int res; 1162 1163 if (argc == 0) { 1164 wpa_cli_show_network_variables(); 1165 return 0; 1166 } 1167 1168 if (argc != 3) { 1169 printf("Invalid SET_NETWORK command: needs three arguments\n" 1170 "(network id, variable name, and value)\n"); 1171 return -1; 1172 } 1173 1174 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s", 1175 argv[0], argv[1], argv[2]); 1176 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1177 printf("Too long SET_NETWORK command.\n"); 1178 return -1; 1179 } 1180 return wpa_ctrl_command(ctrl, cmd); 1181 } 1182 1183 1184 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, 1185 char *argv[]) 1186 { 1187 char cmd[256]; 1188 int res; 1189 1190 if (argc == 0) { 1191 wpa_cli_show_network_variables(); 1192 return 0; 1193 } 1194 1195 if (argc != 2) { 1196 printf("Invalid GET_NETWORK command: needs two arguments\n" 1197 "(network id and variable name)\n"); 1198 return -1; 1199 } 1200 1201 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s", 1202 argv[0], argv[1]); 1203 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1204 printf("Too long GET_NETWORK command.\n"); 1205 return -1; 1206 } 1207 return wpa_ctrl_command(ctrl, cmd); 1208 } 1209 1210 1211 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, 1212 char *argv[]) 1213 { 1214 return wpa_ctrl_command(ctrl, "DISCONNECT"); 1215 } 1216 1217 1218 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, 1219 char *argv[]) 1220 { 1221 return wpa_ctrl_command(ctrl, "RECONNECT"); 1222 } 1223 1224 1225 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, 1226 char *argv[]) 1227 { 1228 return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); 1229 } 1230 1231 1232 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1233 { 1234 return wpa_ctrl_command(ctrl, "SCAN"); 1235 } 1236 1237 1238 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, 1239 char *argv[]) 1240 { 1241 return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); 1242 } 1243 1244 1245 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1246 { 1247 char cmd[64]; 1248 int res; 1249 1250 if (argc != 1) { 1251 printf("Invalid BSS command: need one argument (index or " 1252 "BSSID)\n"); 1253 return -1; 1254 } 1255 1256 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]); 1257 if (res < 0 || (size_t) res >= sizeof(cmd)) 1258 return -1; 1259 cmd[sizeof(cmd) - 1] = '\0'; 1260 1261 return wpa_ctrl_command(ctrl, cmd); 1262 } 1263 1264 1265 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, 1266 char *argv[]) 1267 { 1268 char cmd[64]; 1269 int res; 1270 1271 if (argc < 1 || argc > 2) { 1272 printf("Invalid GET_CAPABILITY command: need either one or " 1273 "two arguments\n"); 1274 return -1; 1275 } 1276 1277 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { 1278 printf("Invalid GET_CAPABILITY command: second argument, " 1279 "if any, must be 'strict'\n"); 1280 return -1; 1281 } 1282 1283 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0], 1284 (argc == 2) ? " strict" : ""); 1285 if (res < 0 || (size_t) res >= sizeof(cmd)) 1286 return -1; 1287 cmd[sizeof(cmd) - 1] = '\0'; 1288 1289 return wpa_ctrl_command(ctrl, cmd); 1290 } 1291 1292 1293 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) 1294 { 1295 printf("Available interfaces:\n"); 1296 return wpa_ctrl_command(ctrl, "INTERFACES"); 1297 } 1298 1299 1300 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1301 { 1302 if (argc < 1) { 1303 wpa_cli_list_interfaces(ctrl); 1304 return 0; 1305 } 1306 1307 wpa_cli_close_connection(); 1308 os_free(ctrl_ifname); 1309 ctrl_ifname = os_strdup(argv[0]); 1310 1311 if (wpa_cli_open_connection(ctrl_ifname, 1)) { 1312 printf("Connected to interface '%s.\n", ctrl_ifname); 1313 } else { 1314 printf("Could not connect to interface '%s' - re-trying\n", 1315 ctrl_ifname); 1316 } 1317 return 0; 1318 } 1319 1320 1321 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, 1322 char *argv[]) 1323 { 1324 return wpa_ctrl_command(ctrl, "RECONFIGURE"); 1325 } 1326 1327 1328 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, 1329 char *argv[]) 1330 { 1331 return wpa_ctrl_command(ctrl, "TERMINATE"); 1332 } 1333 1334 1335 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, 1336 char *argv[]) 1337 { 1338 char cmd[256]; 1339 int res; 1340 1341 if (argc < 1) { 1342 printf("Invalid INTERFACE_ADD command: needs at least one " 1343 "argument (interface name)\n" 1344 "All arguments: ifname confname driver ctrl_interface " 1345 "driver_param bridge_name\n"); 1346 return -1; 1347 } 1348 1349 /* 1350 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB 1351 * <driver_param>TAB<bridge_name> 1352 */ 1353 res = os_snprintf(cmd, sizeof(cmd), 1354 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", 1355 argv[0], 1356 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", 1357 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", 1358 argc > 5 ? argv[5] : ""); 1359 if (res < 0 || (size_t) res >= sizeof(cmd)) 1360 return -1; 1361 cmd[sizeof(cmd) - 1] = '\0'; 1362 return wpa_ctrl_command(ctrl, cmd); 1363 } 1364 1365 1366 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, 1367 char *argv[]) 1368 { 1369 char cmd[128]; 1370 int res; 1371 1372 if (argc != 1) { 1373 printf("Invalid INTERFACE_REMOVE command: needs one argument " 1374 "(interface name)\n"); 1375 return -1; 1376 } 1377 1378 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]); 1379 if (res < 0 || (size_t) res >= sizeof(cmd)) 1380 return -1; 1381 cmd[sizeof(cmd) - 1] = '\0'; 1382 return wpa_ctrl_command(ctrl, cmd); 1383 } 1384 1385 1386 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, 1387 char *argv[]) 1388 { 1389 return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); 1390 } 1391 1392 1393 #ifdef CONFIG_AP 1394 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1395 { 1396 char buf[64]; 1397 if (argc != 1) { 1398 printf("Invalid 'sta' command - exactly one argument, STA " 1399 "address, is required.\n"); 1400 return -1; 1401 } 1402 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]); 1403 return wpa_ctrl_command(ctrl, buf); 1404 } 1405 1406 1407 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd, 1408 char *addr, size_t addr_len) 1409 { 1410 char buf[4096], *pos; 1411 size_t len; 1412 int ret; 1413 1414 if (ctrl_conn == NULL) { 1415 printf("Not connected to hostapd - command dropped.\n"); 1416 return -1; 1417 } 1418 len = sizeof(buf) - 1; 1419 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, 1420 wpa_cli_msg_cb); 1421 if (ret == -2) { 1422 printf("'%s' command timed out.\n", cmd); 1423 return -2; 1424 } else if (ret < 0) { 1425 printf("'%s' command failed.\n", cmd); 1426 return -1; 1427 } 1428 1429 buf[len] = '\0'; 1430 if (memcmp(buf, "FAIL", 4) == 0) 1431 return -1; 1432 printf("%s", buf); 1433 1434 pos = buf; 1435 while (*pos != '\0' && *pos != '\n') 1436 pos++; 1437 *pos = '\0'; 1438 os_strlcpy(addr, buf, addr_len); 1439 return 0; 1440 } 1441 1442 1443 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1444 { 1445 char addr[32], cmd[64]; 1446 1447 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) 1448 return 0; 1449 do { 1450 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 1451 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); 1452 1453 return -1; 1454 } 1455 #endif /* CONFIG_AP */ 1456 1457 1458 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1459 { 1460 return wpa_ctrl_command(ctrl, "SUSPEND"); 1461 } 1462 1463 1464 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1465 { 1466 return wpa_ctrl_command(ctrl, "RESUME"); 1467 } 1468 1469 1470 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1471 { 1472 return wpa_ctrl_command(ctrl, "DROP_SA"); 1473 } 1474 1475 1476 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1477 { 1478 char cmd[128]; 1479 int res; 1480 1481 if (argc != 1) { 1482 printf("Invalid ROAM command: needs one argument " 1483 "(target AP's BSSID)\n"); 1484 return -1; 1485 } 1486 1487 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]); 1488 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1489 printf("Too long ROAM command.\n"); 1490 return -1; 1491 } 1492 return wpa_ctrl_command(ctrl, cmd); 1493 } 1494 1495 1496 enum wpa_cli_cmd_flags { 1497 cli_cmd_flag_none = 0x00, 1498 cli_cmd_flag_sensitive = 0x01 1499 }; 1500 1501 struct wpa_cli_cmd { 1502 const char *cmd; 1503 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); 1504 enum wpa_cli_cmd_flags flags; 1505 const char *usage; 1506 }; 1507 1508 static struct wpa_cli_cmd wpa_cli_commands[] = { 1509 { "status", wpa_cli_cmd_status, 1510 cli_cmd_flag_none, 1511 "[verbose] = get current WPA/EAPOL/EAP status" }, 1512 { "ping", wpa_cli_cmd_ping, 1513 cli_cmd_flag_none, 1514 "= pings wpa_supplicant" }, 1515 { "mib", wpa_cli_cmd_mib, 1516 cli_cmd_flag_none, 1517 "= get MIB variables (dot1x, dot11)" }, 1518 { "help", wpa_cli_cmd_help, 1519 cli_cmd_flag_none, 1520 "= show this usage help" }, 1521 { "interface", wpa_cli_cmd_interface, 1522 cli_cmd_flag_none, 1523 "[ifname] = show interfaces/select interface" }, 1524 { "level", wpa_cli_cmd_level, 1525 cli_cmd_flag_none, 1526 "<debug level> = change debug level" }, 1527 { "license", wpa_cli_cmd_license, 1528 cli_cmd_flag_none, 1529 "= show full wpa_cli license" }, 1530 { "quit", wpa_cli_cmd_quit, 1531 cli_cmd_flag_none, 1532 "= exit wpa_cli" }, 1533 { "set", wpa_cli_cmd_set, 1534 cli_cmd_flag_none, 1535 "= set variables (shows list of variables when run without " 1536 "arguments)" }, 1537 { "logon", wpa_cli_cmd_logon, 1538 cli_cmd_flag_none, 1539 "= IEEE 802.1X EAPOL state machine logon" }, 1540 { "logoff", wpa_cli_cmd_logoff, 1541 cli_cmd_flag_none, 1542 "= IEEE 802.1X EAPOL state machine logoff" }, 1543 { "pmksa", wpa_cli_cmd_pmksa, 1544 cli_cmd_flag_none, 1545 "= show PMKSA cache" }, 1546 { "reassociate", wpa_cli_cmd_reassociate, 1547 cli_cmd_flag_none, 1548 "= force reassociation" }, 1549 { "preauthenticate", wpa_cli_cmd_preauthenticate, 1550 cli_cmd_flag_none, 1551 "<BSSID> = force preauthentication" }, 1552 { "identity", wpa_cli_cmd_identity, 1553 cli_cmd_flag_none, 1554 "<network id> <identity> = configure identity for an SSID" }, 1555 { "password", wpa_cli_cmd_password, 1556 cli_cmd_flag_sensitive, 1557 "<network id> <password> = configure password for an SSID" }, 1558 { "new_password", wpa_cli_cmd_new_password, 1559 cli_cmd_flag_sensitive, 1560 "<network id> <password> = change password for an SSID" }, 1561 { "pin", wpa_cli_cmd_pin, 1562 cli_cmd_flag_sensitive, 1563 "<network id> <pin> = configure pin for an SSID" }, 1564 { "otp", wpa_cli_cmd_otp, 1565 cli_cmd_flag_sensitive, 1566 "<network id> <password> = configure one-time-password for an SSID" 1567 }, 1568 { "passphrase", wpa_cli_cmd_passphrase, 1569 cli_cmd_flag_sensitive, 1570 "<network id> <passphrase> = configure private key passphrase\n" 1571 " for an SSID" }, 1572 { "bssid", wpa_cli_cmd_bssid, 1573 cli_cmd_flag_none, 1574 "<network id> <BSSID> = set preferred BSSID for an SSID" }, 1575 { "list_networks", wpa_cli_cmd_list_networks, 1576 cli_cmd_flag_none, 1577 "= list configured networks" }, 1578 { "select_network", wpa_cli_cmd_select_network, 1579 cli_cmd_flag_none, 1580 "<network id> = select a network (disable others)" }, 1581 { "enable_network", wpa_cli_cmd_enable_network, 1582 cli_cmd_flag_none, 1583 "<network id> = enable a network" }, 1584 { "disable_network", wpa_cli_cmd_disable_network, 1585 cli_cmd_flag_none, 1586 "<network id> = disable a network" }, 1587 { "add_network", wpa_cli_cmd_add_network, 1588 cli_cmd_flag_none, 1589 "= add a network" }, 1590 { "remove_network", wpa_cli_cmd_remove_network, 1591 cli_cmd_flag_none, 1592 "<network id> = remove a network" }, 1593 { "set_network", wpa_cli_cmd_set_network, 1594 cli_cmd_flag_sensitive, 1595 "<network id> <variable> <value> = set network variables (shows\n" 1596 " list of variables when run without arguments)" }, 1597 { "get_network", wpa_cli_cmd_get_network, 1598 cli_cmd_flag_none, 1599 "<network id> <variable> = get network variables" }, 1600 { "save_config", wpa_cli_cmd_save_config, 1601 cli_cmd_flag_none, 1602 "= save the current configuration" }, 1603 { "disconnect", wpa_cli_cmd_disconnect, 1604 cli_cmd_flag_none, 1605 "= disconnect and wait for reassociate/reconnect command before\n" 1606 " connecting" }, 1607 { "reconnect", wpa_cli_cmd_reconnect, 1608 cli_cmd_flag_none, 1609 "= like reassociate, but only takes effect if already disconnected" 1610 }, 1611 { "scan", wpa_cli_cmd_scan, 1612 cli_cmd_flag_none, 1613 "= request new BSS scan" }, 1614 { "scan_results", wpa_cli_cmd_scan_results, 1615 cli_cmd_flag_none, 1616 "= get latest scan results" }, 1617 { "bss", wpa_cli_cmd_bss, 1618 cli_cmd_flag_none, 1619 "<<idx> | <bssid>> = get detailed scan result info" }, 1620 { "get_capability", wpa_cli_cmd_get_capability, 1621 cli_cmd_flag_none, 1622 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" }, 1623 { "reconfigure", wpa_cli_cmd_reconfigure, 1624 cli_cmd_flag_none, 1625 "= force wpa_supplicant to re-read its configuration file" }, 1626 { "terminate", wpa_cli_cmd_terminate, 1627 cli_cmd_flag_none, 1628 "= terminate wpa_supplicant" }, 1629 { "interface_add", wpa_cli_cmd_interface_add, 1630 cli_cmd_flag_none, 1631 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n" 1632 " <bridge_name> = adds new interface, all parameters but <ifname>\n" 1633 " are optional" }, 1634 { "interface_remove", wpa_cli_cmd_interface_remove, 1635 cli_cmd_flag_none, 1636 "<ifname> = removes the interface" }, 1637 { "interface_list", wpa_cli_cmd_interface_list, 1638 cli_cmd_flag_none, 1639 "= list available interfaces" }, 1640 { "ap_scan", wpa_cli_cmd_ap_scan, 1641 cli_cmd_flag_none, 1642 "<value> = set ap_scan parameter" }, 1643 { "stkstart", wpa_cli_cmd_stkstart, 1644 cli_cmd_flag_none, 1645 "<addr> = request STK negotiation with <addr>" }, 1646 { "ft_ds", wpa_cli_cmd_ft_ds, 1647 cli_cmd_flag_none, 1648 "<addr> = request over-the-DS FT with <addr>" }, 1649 { "wps_pbc", wpa_cli_cmd_wps_pbc, 1650 cli_cmd_flag_none, 1651 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" }, 1652 { "wps_pin", wpa_cli_cmd_wps_pin, 1653 cli_cmd_flag_sensitive, 1654 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not " 1655 "hardcoded)" }, 1656 #ifdef CONFIG_WPS_OOB 1657 { "wps_oob", wpa_cli_cmd_wps_oob, 1658 cli_cmd_flag_sensitive, 1659 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" }, 1660 #endif /* CONFIG_WPS_OOB */ 1661 { "wps_reg", wpa_cli_cmd_wps_reg, 1662 cli_cmd_flag_sensitive, 1663 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" }, 1664 { "wps_er_start", wpa_cli_cmd_wps_er_start, 1665 cli_cmd_flag_none, 1666 "= start Wi-Fi Protected Setup External Registrar" }, 1667 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, 1668 cli_cmd_flag_none, 1669 "= stop Wi-Fi Protected Setup External Registrar" }, 1670 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, 1671 cli_cmd_flag_sensitive, 1672 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" }, 1673 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, 1674 cli_cmd_flag_none, 1675 "<UUID> = accept an Enrollee PBC using External Registrar" }, 1676 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, 1677 cli_cmd_flag_sensitive, 1678 "<UUID> <PIN> = learn AP configuration" }, 1679 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, 1680 cli_cmd_flag_none, 1681 "<addr> = request RSN authentication with <addr> in IBSS" }, 1682 #ifdef CONFIG_AP 1683 { "sta", wpa_cli_cmd_sta, 1684 cli_cmd_flag_none, 1685 "<addr> = get information about an associated station (AP)" }, 1686 { "all_sta", wpa_cli_cmd_all_sta, 1687 cli_cmd_flag_none, 1688 "= get information about all associated stations (AP)" }, 1689 #endif /* CONFIG_AP */ 1690 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none, 1691 "= notification of suspend/hibernate" }, 1692 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none, 1693 "= notification of resume/thaw" }, 1694 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none, 1695 "= drop SA without deauth/disassoc (test command)" }, 1696 { "roam", wpa_cli_cmd_roam, 1697 cli_cmd_flag_none, 1698 "<addr> = roam to the specified BSS" }, 1699 { NULL, NULL, cli_cmd_flag_none, NULL } 1700 }; 1701 1702 1703 /* 1704 * Prints command usage, lines are padded with the specified string. 1705 */ 1706 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad) 1707 { 1708 char c; 1709 size_t n; 1710 1711 printf("%s%s ", pad, cmd->cmd); 1712 for (n = 0; (c = cmd->usage[n]); n++) { 1713 printf("%c", c); 1714 if (c == '\n') 1715 printf("%s", pad); 1716 } 1717 printf("\n"); 1718 } 1719 1720 1721 static void print_help(void) 1722 { 1723 int n; 1724 printf("commands:\n"); 1725 for (n = 0; wpa_cli_commands[n].cmd; n++) 1726 print_cmd_help(&wpa_cli_commands[n], " "); 1727 } 1728 1729 1730 #ifdef CONFIG_READLINE 1731 static int cmd_has_sensitive_data(const char *cmd) 1732 { 1733 const char *c, *delim; 1734 int n; 1735 size_t len; 1736 1737 delim = os_strchr(cmd, ' '); 1738 if (delim) 1739 len = delim - cmd; 1740 else 1741 len = os_strlen(cmd); 1742 1743 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) { 1744 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c)) 1745 return (wpa_cli_commands[n].flags & 1746 cli_cmd_flag_sensitive); 1747 } 1748 return 0; 1749 } 1750 #endif /* CONFIG_READLINE */ 1751 1752 1753 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1754 { 1755 struct wpa_cli_cmd *cmd, *match = NULL; 1756 int count; 1757 int ret = 0; 1758 1759 count = 0; 1760 cmd = wpa_cli_commands; 1761 while (cmd->cmd) { 1762 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) 1763 { 1764 match = cmd; 1765 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { 1766 /* we have an exact match */ 1767 count = 1; 1768 break; 1769 } 1770 count++; 1771 } 1772 cmd++; 1773 } 1774 1775 if (count > 1) { 1776 printf("Ambiguous command '%s'; possible commands:", argv[0]); 1777 cmd = wpa_cli_commands; 1778 while (cmd->cmd) { 1779 if (os_strncasecmp(cmd->cmd, argv[0], 1780 os_strlen(argv[0])) == 0) { 1781 printf(" %s", cmd->cmd); 1782 } 1783 cmd++; 1784 } 1785 printf("\n"); 1786 ret = 1; 1787 } else if (count == 0) { 1788 printf("Unknown command '%s'\n", argv[0]); 1789 ret = 1; 1790 } else { 1791 ret = match->handler(ctrl, argc - 1, &argv[1]); 1792 } 1793 1794 return ret; 1795 } 1796 1797 1798 static int str_match(const char *a, const char *b) 1799 { 1800 return os_strncmp(a, b, os_strlen(b)) == 0; 1801 } 1802 1803 1804 static int wpa_cli_exec(const char *program, const char *arg1, 1805 const char *arg2) 1806 { 1807 char *cmd; 1808 size_t len; 1809 int res; 1810 int ret = 0; 1811 1812 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; 1813 cmd = os_malloc(len); 1814 if (cmd == NULL) 1815 return -1; 1816 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); 1817 if (res < 0 || (size_t) res >= len) { 1818 os_free(cmd); 1819 return -1; 1820 } 1821 cmd[len - 1] = '\0'; 1822 #ifndef _WIN32_WCE 1823 if (system(cmd) < 0) 1824 ret = -1; 1825 #endif /* _WIN32_WCE */ 1826 os_free(cmd); 1827 1828 return ret; 1829 } 1830 1831 1832 static void wpa_cli_action_process(const char *msg) 1833 { 1834 const char *pos = skip_priority(msg); 1835 1836 if (str_match(pos, WPA_EVENT_CONNECTED)) { 1837 int new_id = -1; 1838 char *id, *copy; 1839 os_unsetenv("WPA_ID"); 1840 os_unsetenv("WPA_ID_STR"); 1841 os_unsetenv("WPA_CTRL_DIR"); 1842 1843 pos = os_strstr(pos, "[id="); 1844 copy = pos ? os_strdup(pos + 4) : NULL; 1845 1846 if (copy) { 1847 char *pos2 = id = copy; 1848 while (*pos2 && *pos2 != ' ') 1849 pos2++; 1850 *pos2++ = '\0'; 1851 new_id = atoi(id); 1852 os_setenv("WPA_ID", id, 1); 1853 while (*pos2 && *pos2 != '=') 1854 pos2++; 1855 if (*pos2 == '=') 1856 pos2++; 1857 id = pos2; 1858 while (*pos2 && *pos2 != ']') 1859 pos2++; 1860 *pos2 = '\0'; 1861 os_setenv("WPA_ID_STR", id, 1); 1862 os_free(copy); 1863 } 1864 1865 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); 1866 1867 if (!wpa_cli_connected || new_id != wpa_cli_last_id) { 1868 wpa_cli_connected = 1; 1869 wpa_cli_last_id = new_id; 1870 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); 1871 } 1872 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { 1873 if (wpa_cli_connected) { 1874 wpa_cli_connected = 0; 1875 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); 1876 } 1877 } else if (str_match(pos, WPA_EVENT_TERMINATING)) { 1878 printf("wpa_supplicant is terminating - stop monitoring\n"); 1879 wpa_cli_quit = 1; 1880 } 1881 } 1882 1883 1884 #ifndef CONFIG_ANSI_C_EXTRA 1885 static void wpa_cli_action_cb(char *msg, size_t len) 1886 { 1887 wpa_cli_action_process(msg); 1888 } 1889 #endif /* CONFIG_ANSI_C_EXTRA */ 1890 1891 1892 static void wpa_cli_reconnect(void) 1893 { 1894 wpa_cli_close_connection(); 1895 wpa_cli_open_connection(ctrl_ifname, 1); 1896 } 1897 1898 1899 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, 1900 int action_monitor) 1901 { 1902 int first = 1; 1903 if (ctrl_conn == NULL) { 1904 wpa_cli_reconnect(); 1905 return; 1906 } 1907 while (wpa_ctrl_pending(ctrl) > 0) { 1908 char buf[256]; 1909 size_t len = sizeof(buf) - 1; 1910 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { 1911 buf[len] = '\0'; 1912 if (action_monitor) 1913 wpa_cli_action_process(buf); 1914 else { 1915 if (in_read && first) 1916 printf("\r"); 1917 first = 0; 1918 wpa_cli_msg_cb(buf, 0); 1919 #ifdef CONFIG_READLINE 1920 rl_on_new_line(); 1921 rl_redisplay(); 1922 #endif /* CONFIG_READLINE */ 1923 } 1924 } else { 1925 printf("Could not read pending message.\n"); 1926 break; 1927 } 1928 } 1929 1930 if (wpa_ctrl_pending(ctrl) < 0) { 1931 printf("Connection to wpa_supplicant lost - trying to " 1932 "reconnect\n"); 1933 wpa_cli_reconnect(); 1934 } 1935 } 1936 1937 1938 #ifdef CONFIG_READLINE 1939 static char * wpa_cli_cmd_gen(const char *text, int state) 1940 { 1941 static int i, len; 1942 const char *cmd; 1943 1944 if (state == 0) { 1945 i = 0; 1946 len = os_strlen(text); 1947 } 1948 1949 while ((cmd = wpa_cli_commands[i].cmd)) { 1950 i++; 1951 if (os_strncasecmp(cmd, text, len) == 0) 1952 return strdup(cmd); 1953 } 1954 1955 return NULL; 1956 } 1957 1958 1959 static char * wpa_cli_dummy_gen(const char *text, int state) 1960 { 1961 int i; 1962 1963 for (i = 0; wpa_cli_commands[i].cmd; i++) { 1964 const char *cmd = wpa_cli_commands[i].cmd; 1965 size_t len = os_strlen(cmd); 1966 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 && 1967 rl_line_buffer[len] == ' ') { 1968 printf("\n%s\n", wpa_cli_commands[i].usage); 1969 rl_on_new_line(); 1970 rl_redisplay(); 1971 break; 1972 } 1973 } 1974 1975 rl_attempted_completion_over = 1; 1976 return NULL; 1977 } 1978 1979 1980 static char * wpa_cli_status_gen(const char *text, int state) 1981 { 1982 static int i, len; 1983 char *options[] = { 1984 "verbose", NULL 1985 }; 1986 char *t; 1987 1988 if (state == 0) { 1989 i = 0; 1990 len = os_strlen(text); 1991 } 1992 1993 while ((t = options[i])) { 1994 i++; 1995 if (os_strncasecmp(t, text, len) == 0) 1996 return strdup(t); 1997 } 1998 1999 rl_attempted_completion_over = 1; 2000 return NULL; 2001 } 2002 2003 2004 static char ** wpa_cli_completion(const char *text, int start, int end) 2005 { 2006 char * (*func)(const char *text, int state); 2007 2008 if (start == 0) 2009 func = wpa_cli_cmd_gen; 2010 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0) 2011 func = wpa_cli_status_gen; 2012 else 2013 func = wpa_cli_dummy_gen; 2014 return rl_completion_matches(text, func); 2015 } 2016 #endif /* CONFIG_READLINE */ 2017 2018 2019 static void wpa_cli_interactive(void) 2020 { 2021 #define max_args 10 2022 char cmdbuf[256], *cmd, *argv[max_args], *pos; 2023 int argc; 2024 #ifdef CONFIG_READLINE 2025 char *home, *hfile = NULL; 2026 #endif /* CONFIG_READLINE */ 2027 2028 printf("\nInteractive mode\n\n"); 2029 2030 #ifdef CONFIG_READLINE 2031 rl_attempted_completion_function = wpa_cli_completion; 2032 home = getenv("HOME"); 2033 if (home) { 2034 const char *fname = ".wpa_cli_history"; 2035 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; 2036 hfile = os_malloc(hfile_len); 2037 if (hfile) { 2038 int res; 2039 res = os_snprintf(hfile, hfile_len, "%s/%s", home, 2040 fname); 2041 if (res >= 0 && res < hfile_len) { 2042 hfile[hfile_len - 1] = '\0'; 2043 read_history(hfile); 2044 stifle_history(100); 2045 } 2046 } 2047 } 2048 #endif /* CONFIG_READLINE */ 2049 2050 do { 2051 wpa_cli_recv_pending(mon_conn, 0, 0); 2052 #ifndef CONFIG_NATIVE_WINDOWS 2053 alarm(ping_interval); 2054 #endif /* CONFIG_NATIVE_WINDOWS */ 2055 #ifdef CONFIG_WPA_CLI_FORK 2056 if (mon_pid) 2057 kill(mon_pid, SIGUSR1); 2058 #endif /* CONFIG_WPA_CLI_FORK */ 2059 #ifdef CONFIG_READLINE 2060 cmd = readline("> "); 2061 if (cmd && *cmd) { 2062 HIST_ENTRY *h; 2063 while (next_history()) 2064 ; 2065 h = previous_history(); 2066 if (h == NULL || os_strcmp(cmd, h->line) != 0) 2067 add_history(cmd); 2068 next_history(); 2069 } 2070 #else /* CONFIG_READLINE */ 2071 printf("> "); 2072 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); 2073 #endif /* CONFIG_READLINE */ 2074 #ifndef CONFIG_NATIVE_WINDOWS 2075 alarm(0); 2076 #endif /* CONFIG_NATIVE_WINDOWS */ 2077 if (cmd == NULL) 2078 break; 2079 wpa_cli_recv_pending(mon_conn, 0, 0); 2080 pos = cmd; 2081 while (*pos != '\0') { 2082 if (*pos == '\n') { 2083 *pos = '\0'; 2084 break; 2085 } 2086 pos++; 2087 } 2088 argc = 0; 2089 pos = cmd; 2090 for (;;) { 2091 while (*pos == ' ') 2092 pos++; 2093 if (*pos == '\0') 2094 break; 2095 argv[argc] = pos; 2096 argc++; 2097 if (argc == max_args) 2098 break; 2099 if (*pos == '"') { 2100 char *pos2 = os_strrchr(pos, '"'); 2101 if (pos2) 2102 pos = pos2 + 1; 2103 } 2104 while (*pos != '\0' && *pos != ' ') 2105 pos++; 2106 if (*pos == ' ') 2107 *pos++ = '\0'; 2108 } 2109 if (argc) 2110 wpa_request(ctrl_conn, argc, argv); 2111 2112 if (cmd != cmdbuf) 2113 free(cmd); 2114 #ifdef CONFIG_WPA_CLI_FORK 2115 if (mon_pid) 2116 kill(mon_pid, SIGUSR2); 2117 #endif /* CONFIG_WPA_CLI_FORK */ 2118 } while (!wpa_cli_quit); 2119 2120 #ifdef CONFIG_READLINE 2121 if (hfile) { 2122 /* Save command history, excluding lines that may contain 2123 * passwords. */ 2124 HIST_ENTRY *h; 2125 history_set_pos(0); 2126 while ((h = current_history())) { 2127 const char *p = h->line; 2128 while (*p == ' ' || *p == '\t') 2129 p++; 2130 if (cmd_has_sensitive_data(p)) { 2131 h = remove_history(where_history()); 2132 if (h) { 2133 os_free(__UNCONST(h->line)); 2134 os_free(__UNCONST(h->data)); 2135 os_free(h); 2136 } else 2137 next_history(); 2138 } else 2139 next_history(); 2140 } 2141 write_history(hfile); 2142 os_free(hfile); 2143 } 2144 #endif /* CONFIG_READLINE */ 2145 } 2146 2147 2148 static void wpa_cli_action(struct wpa_ctrl *ctrl) 2149 { 2150 #ifdef CONFIG_ANSI_C_EXTRA 2151 /* TODO: ANSI C version(?) */ 2152 printf("Action processing not supported in ANSI C build.\n"); 2153 #else /* CONFIG_ANSI_C_EXTRA */ 2154 fd_set rfds; 2155 int fd, res; 2156 struct timeval tv; 2157 char buf[256]; /* note: large enough to fit in unsolicited messages */ 2158 size_t len; 2159 2160 fd = wpa_ctrl_get_fd(ctrl); 2161 2162 while (!wpa_cli_quit) { 2163 FD_ZERO(&rfds); 2164 FD_SET(fd, &rfds); 2165 tv.tv_sec = ping_interval; 2166 tv.tv_usec = 0; 2167 res = select(fd + 1, &rfds, NULL, NULL, &tv); 2168 if (res < 0 && errno != EINTR) { 2169 perror("select"); 2170 break; 2171 } 2172 2173 if (FD_ISSET(fd, &rfds)) 2174 wpa_cli_recv_pending(ctrl, 0, 1); 2175 else { 2176 /* verify that connection is still working */ 2177 len = sizeof(buf) - 1; 2178 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, 2179 wpa_cli_action_cb) < 0 || 2180 len < 4 || os_memcmp(buf, "PONG", 4) != 0) { 2181 printf("wpa_supplicant did not reply to PING " 2182 "command - exiting\n"); 2183 break; 2184 } 2185 } 2186 } 2187 #endif /* CONFIG_ANSI_C_EXTRA */ 2188 } 2189 2190 2191 static void wpa_cli_cleanup(void) 2192 { 2193 wpa_cli_close_connection(); 2194 if (pid_file) 2195 os_daemonize_terminate(pid_file); 2196 2197 os_program_deinit(); 2198 } 2199 2200 static void wpa_cli_terminate(int sig) 2201 { 2202 wpa_cli_cleanup(); 2203 exit(0); 2204 } 2205 2206 2207 #ifdef CONFIG_WPA_CLI_FORK 2208 static void wpa_cli_usr1(int sig) 2209 { 2210 #ifdef CONFIG_READLINE 2211 rl_on_new_line(); 2212 rl_redisplay(); 2213 #endif /* CONFIG_READLINE */ 2214 } 2215 #endif /* CONFIG_WPA_CLI_FORK */ 2216 2217 2218 #ifndef CONFIG_NATIVE_WINDOWS 2219 static void wpa_cli_alarm(int sig) 2220 { 2221 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { 2222 printf("Connection to wpa_supplicant lost - trying to " 2223 "reconnect\n"); 2224 wpa_cli_close_connection(); 2225 } 2226 if (!ctrl_conn) 2227 wpa_cli_reconnect(); 2228 if (mon_conn) 2229 wpa_cli_recv_pending(mon_conn, 1, 0); 2230 alarm(ping_interval); 2231 } 2232 #endif /* CONFIG_NATIVE_WINDOWS */ 2233 2234 2235 static char * wpa_cli_get_default_ifname(void) 2236 { 2237 char *ifname = NULL; 2238 2239 #ifdef CONFIG_CTRL_IFACE_UNIX 2240 struct dirent *dent; 2241 DIR *dir = opendir(ctrl_iface_dir); 2242 if (!dir) 2243 return NULL; 2244 while ((dent = readdir(dir))) { 2245 #ifdef _DIRENT_HAVE_D_TYPE 2246 /* 2247 * Skip the file if it is not a socket. Also accept 2248 * DT_UNKNOWN (0) in case the C library or underlying 2249 * file system does not support d_type. 2250 */ 2251 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) 2252 continue; 2253 #endif /* _DIRENT_HAVE_D_TYPE */ 2254 if (os_strcmp(dent->d_name, ".") == 0 || 2255 os_strcmp(dent->d_name, "..") == 0) 2256 continue; 2257 printf("Selected interface '%s'\n", dent->d_name); 2258 ifname = os_strdup(dent->d_name); 2259 break; 2260 } 2261 closedir(dir); 2262 #endif /* CONFIG_CTRL_IFACE_UNIX */ 2263 2264 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 2265 char buf[2048], *pos; 2266 size_t len; 2267 struct wpa_ctrl *ctrl; 2268 int ret; 2269 2270 ctrl = wpa_ctrl_open(NULL); 2271 if (ctrl == NULL) 2272 return NULL; 2273 2274 len = sizeof(buf) - 1; 2275 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); 2276 if (ret >= 0) { 2277 buf[len] = '\0'; 2278 pos = os_strchr(buf, '\n'); 2279 if (pos) 2280 *pos = '\0'; 2281 ifname = os_strdup(buf); 2282 } 2283 wpa_ctrl_close(ctrl); 2284 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2285 2286 return ifname; 2287 } 2288 2289 2290 int main(int argc, char *argv[]) 2291 { 2292 int warning_displayed = 0; 2293 int c; 2294 int daemonize = 0; 2295 int ret = 0; 2296 const char *global = NULL; 2297 2298 if (os_program_init()) 2299 return -1; 2300 2301 for (;;) { 2302 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v"); 2303 if (c < 0) 2304 break; 2305 switch (c) { 2306 case 'a': 2307 action_file = optarg; 2308 break; 2309 case 'B': 2310 daemonize = 1; 2311 break; 2312 case 'g': 2313 global = optarg; 2314 break; 2315 case 'G': 2316 ping_interval = atoi(optarg); 2317 break; 2318 case 'h': 2319 usage(); 2320 return 0; 2321 case 'v': 2322 printf("%s\n", wpa_cli_version); 2323 return 0; 2324 case 'i': 2325 os_free(ctrl_ifname); 2326 ctrl_ifname = os_strdup(optarg); 2327 break; 2328 case 'p': 2329 ctrl_iface_dir = optarg; 2330 break; 2331 case 'P': 2332 pid_file = optarg; 2333 break; 2334 default: 2335 usage(); 2336 return -1; 2337 } 2338 } 2339 2340 interactive = (argc == optind) && (action_file == NULL); 2341 2342 if (interactive) 2343 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); 2344 2345 if (global) { 2346 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 2347 ctrl_conn = wpa_ctrl_open(NULL); 2348 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2349 ctrl_conn = wpa_ctrl_open(global); 2350 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2351 if (ctrl_conn == NULL) { 2352 perror("Failed to connect to wpa_supplicant - " 2353 "wpa_ctrl_open"); 2354 return -1; 2355 } 2356 } 2357 2358 #ifndef _WIN32_WCE 2359 signal(SIGINT, wpa_cli_terminate); 2360 signal(SIGTERM, wpa_cli_terminate); 2361 #endif /* _WIN32_WCE */ 2362 #ifndef CONFIG_NATIVE_WINDOWS 2363 signal(SIGALRM, wpa_cli_alarm); 2364 #endif /* CONFIG_NATIVE_WINDOWS */ 2365 #ifdef CONFIG_WPA_CLI_FORK 2366 signal(SIGUSR1, wpa_cli_usr1); 2367 #endif /* CONFIG_WPA_CLI_FORK */ 2368 2369 if (ctrl_ifname == NULL) 2370 ctrl_ifname = wpa_cli_get_default_ifname(); 2371 2372 if (interactive) { 2373 for (; !global;) { 2374 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { 2375 if (warning_displayed) 2376 printf("Connection established.\n"); 2377 break; 2378 } 2379 2380 if (!warning_displayed) { 2381 printf("Could not connect to wpa_supplicant - " 2382 "re-trying\n"); 2383 warning_displayed = 1; 2384 } 2385 os_sleep(1, 0); 2386 continue; 2387 } 2388 } else { 2389 if (!global && 2390 wpa_cli_open_connection(ctrl_ifname, 0) < 0) { 2391 perror("Failed to connect to wpa_supplicant - " 2392 "wpa_ctrl_open"); 2393 return -1; 2394 } 2395 2396 if (action_file) { 2397 if (wpa_ctrl_attach(ctrl_conn) == 0) { 2398 wpa_cli_attached = 1; 2399 } else { 2400 printf("Warning: Failed to attach to " 2401 "wpa_supplicant.\n"); 2402 return -1; 2403 } 2404 } 2405 } 2406 2407 if (daemonize && os_daemonize(pid_file)) 2408 return -1; 2409 2410 if (interactive) 2411 wpa_cli_interactive(); 2412 else if (action_file) 2413 wpa_cli_action(ctrl_conn); 2414 else 2415 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); 2416 2417 os_free(ctrl_ifname); 2418 wpa_cli_cleanup(); 2419 2420 return ret; 2421 } 2422 2423 #else /* CONFIG_CTRL_IFACE */ 2424 int main(int argc, char *argv[]) 2425 { 2426 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); 2427 return -1; 2428 } 2429 #endif /* CONFIG_CTRL_IFACE */ 2430