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