wpa_cli.c revision 214734
1139749Simp/* 212496Speter * WPA Supplicant - command line interface for wpa_supplicant daemon 310015Speter * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 410015Speter * 534832Speter * This program is free software; you can redistribute it and/or modify 610015Speter * it under the terms of the GNU General Public License version 2 as 734832Speter * published by the Free Software Foundation. 810015Speter * 910015Speter * Alternatively, this software may be distributed under the terms of BSD 1010015Speter * license. 1110015Speter * 1210015Speter * See README and COPYING for more details. 1310015Speter */ 1410015Speter 1510015Speter#include "includes.h" 1610015Speter 1710015Speter#ifdef CONFIG_CTRL_IFACE 1810015Speter 1910015Speter#ifdef CONFIG_CTRL_IFACE_UNIX 2010015Speter#include <dirent.h> 2110015Speter#endif /* CONFIG_CTRL_IFACE_UNIX */ 2210015Speter#ifdef CONFIG_READLINE 2310015Speter#include <readline/readline.h> 2410015Speter#include <readline/history.h> 2510015Speter#endif /* CONFIG_READLINE */ 2610015Speter#ifdef CONFIG_WPA_CLI_FORK 2710015Speter#include <sys/wait.h> 2810015Speter#endif /* CONFIG_WPA_CLI_FORK */ 2910015Speter 3010015Speter#include "common/wpa_ctrl.h" 3110015Speter#include "common.h" 3210015Speter#include "common/version.h" 3350477Speter 3410015Speter 3510015Speterstatic const char *wpa_cli_version = 3629676Sgibbs"wpa_cli v" VERSION_STR "\n" 3729676Sgibbs"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors"; 3810015Speter 39136058Sphk 40136058Sphkstatic const char *wpa_cli_license = 4110015Speter"This program is free software. You can distribute it and/or modify it\n" 4210015Speter"under the terms of the GNU General Public License version 2.\n" 4310015Speter"\n" 4412496Speter"Alternatively, this software may be distributed under the terms of the\n" 4510015Speter"BSD license. See README and COPYING for more details.\n"; 46136058Sphk 47136058Sphkstatic const char *wpa_cli_full_license = 4810015Speter"This program is free software; you can redistribute it and/or modify\n" 4910015Speter"it under the terms of the GNU General Public License version 2 as\n" 5010015Speter"published by the Free Software Foundation.\n" 5110015Speter"\n" 5210015Speter"This program is distributed in the hope that it will be useful,\n" 5310015Speter"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 5410015Speter"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 5510015Speter"GNU General Public License for more details.\n" 5610015Speter"\n" 5710015Speter"You should have received a copy of the GNU General Public License\n" 5810015Speter"along with this program; if not, write to the Free Software\n" 5934832Speter"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" 6034832Speter"\n" 6110015Speter"Alternatively, this software may be distributed under the terms of the\n" 6210015Speter"BSD license.\n" 6310015Speter"\n" 6410015Speter"Redistribution and use in source and binary forms, with or without\n" 6510015Speter"modification, are permitted provided that the following conditions are\n" 6610015Speter"met:\n" 6710015Speter"\n" 6810015Speter"1. Redistributions of source code must retain the above copyright\n" 6910015Speter" notice, this list of conditions and the following disclaimer.\n" 7010015Speter"\n" 7110015Speter"2. Redistributions in binary form must reproduce the above copyright\n" 7210015Speter" notice, this list of conditions and the following disclaimer in the\n" 7310015Speter" documentation and/or other materials provided with the distribution.\n" 7410015Speter"\n" 7510015Speter"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 7610015Speter" names of its contributors may be used to endorse or promote products\n" 7710015Speter" derived from this software without specific prior written permission.\n" 7810015Speter"\n" 7910015Speter"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 8010015Speter"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 8110015Speter"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 8210015Speter"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 8310015Speter"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 8434832Speter"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 8534832Speter"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 8634832Speter"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 8734832Speter"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 8834832Speter"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 8934832Speter"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 9010015Speter"\n"; 9110015Speter 9210015Speterstatic struct wpa_ctrl *ctrl_conn; 9310015Speterstatic struct wpa_ctrl *mon_conn; 9410015Speter#ifdef CONFIG_WPA_CLI_FORK 9510015Speterstatic pid_t mon_pid = 0; 9610015Speter#endif /* CONFIG_WPA_CLI_FORK */ 9710015Speterstatic int wpa_cli_quit = 0; 9810015Speterstatic int wpa_cli_attached = 0; 9910015Speterstatic int wpa_cli_connected = 0; 10010015Speterstatic int wpa_cli_last_id = 0; 10110015Speterstatic const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; 10210015Speterstatic char *ctrl_ifname = NULL; 10310015Speterstatic const char *pid_file = NULL; 10410015Speterstatic const char *action_file = NULL; 10510015Speterstatic int ping_interval = 5; 10610015Speterstatic int interactive = 0; 10710015Speter 10810015Speter 10910015Speterstatic void print_help(); 11010015Speter 11110015Speter 11210015Speterstatic void usage(void) 11310015Speter{ 11410015Speter printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " 11510015Speter "[-a<action file>] \\\n" 11610015Speter " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] " 11710015Speter "[command..]\n" 11810015Speter " -h = help (show this usage text)\n" 11910015Speter " -v = shown version information\n" 12010015Speter " -a = run in daemon mode executing the action file based on " 12110015Speter "events from\n" 12210015Speter " wpa_supplicant\n" 12310015Speter " -B = run a daemon in the background\n" 12410015Speter " default path: /var/run/wpa_supplicant\n" 12510015Speter " default interface: first interface found in socket path\n"); 12610015Speter print_help(); 12710015Speter} 12810015Speter 12910015Speter 13010015Speter#ifdef CONFIG_WPA_CLI_FORK 13110015Speterstatic int in_query = 0; 13210015Speter 13310015Speterstatic void wpa_cli_monitor_sig(int sig) 13410015Speter{ 13512496Speter if (sig == SIGUSR1) 13612496Speter in_query = 1; 13710015Speter else if (sig == SIGUSR2) 13810015Speter in_query = 0; 13910015Speter} 14010015Speter 14110015Speterstatic void wpa_cli_monitor(void) 14210015Speter{ 14310015Speter char buf[256]; 14410015Speter size_t len = sizeof(buf) - 1; 14510015Speter struct timeval tv; 14610015Speter fd_set rfds; 14710015Speter 14810015Speter signal(SIGUSR1, wpa_cli_monitor_sig); 14910015Speter signal(SIGUSR2, wpa_cli_monitor_sig); 15010015Speter 15110015Speter while (mon_conn) { 15210015Speter int s = wpa_ctrl_get_fd(mon_conn); 15310015Speter tv.tv_sec = 5; 15410015Speter tv.tv_usec = 0; 15510015Speter FD_ZERO(&rfds); 15610015Speter FD_SET(s, &rfds); 15710015Speter if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) { 15810015Speter if (errno == EINTR) 15910015Speter continue; 16010015Speter perror("select"); 16110015Speter break; 16210015Speter } 16310015Speter if (mon_conn == NULL) 16410015Speter break; 16510015Speter if (FD_ISSET(s, &rfds)) { 16610015Speter len = sizeof(buf) - 1; 16710015Speter int res = wpa_ctrl_recv(mon_conn, buf, &len); 16810015Speter if (res < 0) { 16910015Speter perror("wpa_ctrl_recv"); 17010015Speter break; 17110015Speter } 17210015Speter buf[len] = '\0'; 17310015Speter if (in_query) 17410015Speter printf("\r"); 17510015Speter printf("%s\n", buf); 17610015Speter kill(getppid(), SIGUSR1); 17710015Speter } 17810015Speter } 17910015Speter} 18010015Speter#endif /* CONFIG_WPA_CLI_FORK */ 18110015Speter 18210015Speter 18310015Speterstatic int wpa_cli_open_connection(const char *ifname, int attach) 18410015Speter{ 18510015Speter#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) 18610015Speter ctrl_conn = wpa_ctrl_open(ifname); 18710015Speter if (ctrl_conn == NULL) 18810015Speter return -1; 18910015Speter 19010015Speter if (attach && interactive) 19110015Speter mon_conn = wpa_ctrl_open(ifname); 19210015Speter else 19310015Speter mon_conn = NULL; 19410015Speter#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 19510015Speter char *cfile; 19610015Speter int flen, res; 19710015Speter 19810015Speter if (ifname == NULL) 19910015Speter return -1; 20010015Speter 20110015Speter flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; 20210015Speter cfile = os_malloc(flen); 20310015Speter if (cfile == NULL) 20410015Speter return -1L; 20510015Speter res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); 20610015Speter if (res < 0 || res >= flen) { 20710015Speter os_free(cfile); 20810015Speter return -1; 20910015Speter } 21010015Speter 21110015Speter ctrl_conn = wpa_ctrl_open(cfile); 21210015Speter if (ctrl_conn == NULL) { 21310015Speter os_free(cfile); 21410015Speter return -1; 21510015Speter } 21610015Speter 21710015Speter if (attach && interactive) 21810015Speter mon_conn = wpa_ctrl_open(cfile); 21910015Speter else 22010015Speter mon_conn = NULL; 22110015Speter os_free(cfile); 22210015Speter#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 22310015Speter 22410015Speter if (mon_conn) { 22510015Speter if (wpa_ctrl_attach(mon_conn) == 0) { 22610015Speter wpa_cli_attached = 1; 22710015Speter } else { 22810015Speter printf("Warning: Failed to attach to " 22910015Speter "wpa_supplicant.\n"); 23010015Speter return -1; 23110015Speter } 23210015Speter 23310015Speter#ifdef CONFIG_WPA_CLI_FORK 23410015Speter { 23510015Speter pid_t p = fork(); 23610015Speter if (p < 0) { 23710015Speter perror("fork"); 23810015Speter return -1; 23910015Speter } 24010015Speter if (p == 0) { 24110015Speter wpa_cli_monitor(); 24210015Speter exit(0); 24310015Speter } else 24410015Speter mon_pid = p; 24510015Speter } 24610015Speter#endif /* CONFIG_WPA_CLI_FORK */ 24710015Speter } 24810015Speter 24910015Speter return 0; 25010015Speter} 25110015Speter 25210015Speter 25310015Speterstatic void wpa_cli_close_connection(void) 25410015Speter{ 25510015Speter if (ctrl_conn == NULL) 25610015Speter return; 25710015Speter 25810015Speter#ifdef CONFIG_WPA_CLI_FORK 25910015Speter if (mon_pid) { 26010015Speter int status; 26110015Speter kill(mon_pid, SIGPIPE); 26210015Speter wait(&status); 26310015Speter mon_pid = 0; 26410015Speter } 26510015Speter#endif /* CONFIG_WPA_CLI_FORK */ 26610015Speter 26710015Speter if (wpa_cli_attached) { 26810015Speter wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); 26910015Speter wpa_cli_attached = 0; 27010015Speter } 27110015Speter wpa_ctrl_close(ctrl_conn); 27210015Speter ctrl_conn = NULL; 27310015Speter if (mon_conn) { 27410015Speter wpa_ctrl_close(mon_conn); 27510015Speter mon_conn = NULL; 27610015Speter } 27710015Speter} 27810044Speter 27910015Speter 28010015Speterstatic void wpa_cli_msg_cb(char *msg, size_t len) 28110015Speter{ 28210015Speter printf("%s\n", msg); 28310015Speter} 28410015Speter 28510015Speter 28610015Speterstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) 28712174Speter{ 28829676Sgibbs char buf[2048]; 28910015Speter size_t len; 290136058Sphk int ret; 29110015Speter 29210015Speter if (ctrl_conn == NULL) { 29310015Speter printf("Not connected to wpa_supplicant - command dropped.\n"); 294136058Sphk return -1; 29510015Speter } 29610015Speter len = sizeof(buf) - 1; 29710015Speter ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 29810015Speter wpa_cli_msg_cb); 29910015Speter if (ret == -2) { 30010015Speter printf("'%s' command timed out.\n", cmd); 30110015Speter return -2; 30210015Speter } else if (ret < 0) { 303179589Speter printf("'%s' command failed.\n", cmd); 304136058Sphk return -1; 30510015Speter } 30610015Speter if (print) { 30710015Speter buf[len] = '\0'; 30810015Speter printf("%s", buf); 30910015Speter } 31010015Speter return 0; 31110015Speter} 31210015Speter 31310015Speter 31410015Speterstatic int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) 31510015Speter{ 31610015Speter return _wpa_ctrl_command(ctrl, cmd, 1); 31710015Speter} 31810015Speter 31910015Speter 32010015Speterstatic int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 32110015Speter{ 32210044Speter int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; 32310044Speter return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); 32410015Speter} 32510015Speter 32610015Speter 32710015Speterstatic int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 32810015Speter{ 32910015Speter return wpa_ctrl_command(ctrl, "PING"); 33010015Speter} 33110015Speter 33210015Speter 33310015Speterstatic int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 33410015Speter{ 33510015Speter return wpa_ctrl_command(ctrl, "MIB"); 33610044Speter} 33710044Speter 33810044Speter 33910044Speterstatic int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 34010044Speter{ 34110044Speter return wpa_ctrl_command(ctrl, "PMKSA"); 34210044Speter} 34310044Speter 34410044Speter 34510044Speterstatic int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 34610044Speter{ 34710044Speter print_help(); 34810044Speter return 0; 34910015Speter} 35010015Speter 35110015Speter 35210015Speterstatic int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) 35310044Speter{ 35410015Speter printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); 35510015Speter return 0; 35610015Speter} 35710015Speter 35810015Speter 35910015Speterstatic int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 36010015Speter{ 36112174Speter wpa_cli_quit = 1; 36210015Speter return 0; 36310015Speter} 36410015Speter 36510015Speter 36610015Speterstatic void wpa_cli_show_variables(void) 36710015Speter{ 36810015Speter printf("set variables:\n" 36910044Speter " EAPOL::heldPeriod (EAPOL state machine held period, " 37010015Speter "in seconds)\n" 37110015Speter " EAPOL::authPeriod (EAPOL state machine authentication " 37210015Speter "period, in seconds)\n" 37310015Speter " EAPOL::startPeriod (EAPOL state machine start period, in " 37412174Speter "seconds)\n" 37510015Speter " EAPOL::maxStart (EAPOL state machine maximum start " 37610015Speter "attempts)\n"); 37710015Speter printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " 37810015Speter "seconds)\n" 37912174Speter " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" 38010044Speter " threshold\n\tpercentage)\n" 38110044Speter " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " 38212174Speter "security\n\tassociation in seconds)\n"); 38310015Speter} 38410015Speter 38510044Speter 38610044Speterstatic int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 38710044Speter{ 38810015Speter char cmd[256]; 38910044Speter int res; 39010044Speter 39110015Speter if (argc == 0) { 39210015Speter wpa_cli_show_variables(); 39310015Speter return 0; 39410015Speter } 39510015Speter 396 if (argc != 2) { 397 printf("Invalid SET command: needs two arguments (variable " 398 "name and value)\n"); 399 return -1; 400 } 401 402 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); 403 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 404 printf("Too long SET command.\n"); 405 return -1; 406 } 407 return wpa_ctrl_command(ctrl, cmd); 408} 409 410 411static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) 412{ 413 return wpa_ctrl_command(ctrl, "LOGOFF"); 414} 415 416 417static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) 418{ 419 return wpa_ctrl_command(ctrl, "LOGON"); 420} 421 422 423static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, 424 char *argv[]) 425{ 426 return wpa_ctrl_command(ctrl, "REASSOCIATE"); 427} 428 429 430static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, 431 char *argv[]) 432{ 433 char cmd[256]; 434 int res; 435 436 if (argc != 1) { 437 printf("Invalid PREAUTH command: needs one argument " 438 "(BSSID)\n"); 439 return -1; 440 } 441 442 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); 443 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 444 printf("Too long PREAUTH command.\n"); 445 return -1; 446 } 447 return wpa_ctrl_command(ctrl, cmd); 448} 449 450 451static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 452{ 453 char cmd[256]; 454 int res; 455 456 if (argc != 1) { 457 printf("Invalid AP_SCAN command: needs one argument (ap_scan " 458 "value)\n"); 459 return -1; 460 } 461 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); 462 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 463 printf("Too long AP_SCAN command.\n"); 464 return -1; 465 } 466 return wpa_ctrl_command(ctrl, cmd); 467} 468 469 470static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, 471 char *argv[]) 472{ 473 char cmd[256]; 474 int res; 475 476 if (argc != 1) { 477 printf("Invalid STKSTART command: needs one argument " 478 "(Peer STA MAC address)\n"); 479 return -1; 480 } 481 482 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]); 483 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 484 printf("Too long STKSTART command.\n"); 485 return -1; 486 } 487 return wpa_ctrl_command(ctrl, cmd); 488} 489 490 491static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[]) 492{ 493 char cmd[256]; 494 int res; 495 496 if (argc != 1) { 497 printf("Invalid FT_DS command: needs one argument " 498 "(Target AP MAC address)\n"); 499 return -1; 500 } 501 502 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]); 503 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 504 printf("Too long FT_DS command.\n"); 505 return -1; 506 } 507 return wpa_ctrl_command(ctrl, cmd); 508} 509 510 511static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) 512{ 513 char cmd[256]; 514 int res; 515 516 if (argc == 0) { 517 /* Any BSSID */ 518 return wpa_ctrl_command(ctrl, "WPS_PBC"); 519 } 520 521 /* Specific BSSID */ 522 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]); 523 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 524 printf("Too long WPS_PBC command.\n"); 525 return -1; 526 } 527 return wpa_ctrl_command(ctrl, cmd); 528} 529 530 531static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 532{ 533 char cmd[256]; 534 int res; 535 536 if (argc == 0) { 537 printf("Invalid WPS_PIN command: need one or two arguments:\n" 538 "- BSSID: use 'any' to select any\n" 539 "- PIN: optional, used only with devices that have no " 540 "display\n"); 541 return -1; 542 } 543 544 if (argc == 1) { 545 /* Use dynamically generated PIN (returned as reply) */ 546 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]); 547 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 548 printf("Too long WPS_PIN command.\n"); 549 return -1; 550 } 551 return wpa_ctrl_command(ctrl, cmd); 552 } 553 554 /* Use hardcoded PIN from a label */ 555 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]); 556 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 557 printf("Too long WPS_PIN command.\n"); 558 return -1; 559 } 560 return wpa_ctrl_command(ctrl, cmd); 561} 562 563 564#ifdef CONFIG_WPS_OOB 565static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[]) 566{ 567 char cmd[256]; 568 int res; 569 570 if (argc != 3 && argc != 4) { 571 printf("Invalid WPS_OOB command: need three or four " 572 "arguments:\n" 573 "- DEV_TYPE: use 'ufd' or 'nfc'\n" 574 "- PATH: path of OOB device like '/mnt'\n" 575 "- METHOD: OOB method 'pin-e' or 'pin-r', " 576 "'cred'\n" 577 "- DEV_NAME: (only for NFC) device name like " 578 "'pn531'\n"); 579 return -1; 580 } 581 582 if (argc == 3) 583 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s", 584 argv[0], argv[1], argv[2]); 585 else 586 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s", 587 argv[0], argv[1], argv[2], argv[3]); 588 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 589 printf("Too long WPS_OOB command.\n"); 590 return -1; 591 } 592 return wpa_ctrl_command(ctrl, cmd); 593} 594#endif /* CONFIG_WPS_OOB */ 595 596 597static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) 598{ 599 char cmd[256]; 600 int res; 601 602 if (argc == 2) 603 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", 604 argv[0], argv[1]); 605 else if (argc == 6) { 606 char ssid_hex[2 * 32 + 1]; 607 char key_hex[2 * 64 + 1]; 608 int i; 609 610 ssid_hex[0] = '\0'; 611 for (i = 0; i < 32; i++) { 612 if (argv[2][i] == '\0') 613 break; 614 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); 615 } 616 617 key_hex[0] = '\0'; 618 for (i = 0; i < 64; i++) { 619 if (argv[5][i] == '\0') 620 break; 621 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]); 622 } 623 624 res = os_snprintf(cmd, sizeof(cmd), 625 "WPS_REG %s %s %s %s %s %s", 626 argv[0], argv[1], ssid_hex, argv[3], argv[4], 627 key_hex); 628 } else { 629 printf("Invalid WPS_REG command: need two arguments:\n" 630 "- BSSID: use 'any' to select any\n" 631 "- AP PIN\n"); 632 printf("Alternatively, six arguments can be used to " 633 "reconfigure the AP:\n" 634 "- BSSID: use 'any' to select any\n" 635 "- AP PIN\n" 636 "- new SSID\n" 637 "- new auth (OPEN, WPAPSK, WPA2PSK)\n" 638 "- new encr (NONE, WEP, TKIP, CCMP)\n" 639 "- new key\n"); 640 return -1; 641 } 642 643 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 644 printf("Too long WPS_REG command.\n"); 645 return -1; 646 } 647 return wpa_ctrl_command(ctrl, cmd); 648} 649 650 651static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, 652 char *argv[]) 653{ 654 return wpa_ctrl_command(ctrl, "WPS_ER_START"); 655 656} 657 658 659static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc, 660 char *argv[]) 661{ 662 return wpa_ctrl_command(ctrl, "WPS_ER_STOP"); 663 664} 665 666 667static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, 668 char *argv[]) 669{ 670 char cmd[256]; 671 int res; 672 673 if (argc != 2) { 674 printf("Invalid WPS_ER_PIN command: need two arguments:\n" 675 "- UUID: use 'any' to select any\n" 676 "- PIN: Enrollee PIN\n"); 677 return -1; 678 } 679 680 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s", 681 argv[0], argv[1]); 682 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 683 printf("Too long WPS_ER_PIN command.\n"); 684 return -1; 685 } 686 return wpa_ctrl_command(ctrl, cmd); 687} 688 689 690static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc, 691 char *argv[]) 692{ 693 char cmd[256]; 694 int res; 695 696 if (argc != 1) { 697 printf("Invalid WPS_ER_PBC command: need one argument:\n" 698 "- UUID: Specify the Enrollee\n"); 699 return -1; 700 } 701 702 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s", 703 argv[0]); 704 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 705 printf("Too long WPS_ER_PBC command.\n"); 706 return -1; 707 } 708 return wpa_ctrl_command(ctrl, cmd); 709} 710 711 712static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, 713 char *argv[]) 714{ 715 char cmd[256]; 716 int res; 717 718 if (argc != 2) { 719 printf("Invalid WPS_ER_LEARN command: need two arguments:\n" 720 "- UUID: specify which AP to use\n" 721 "- PIN: AP PIN\n"); 722 return -1; 723 } 724 725 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s", 726 argv[0], argv[1]); 727 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 728 printf("Too long WPS_ER_LEARN command.\n"); 729 return -1; 730 } 731 return wpa_ctrl_command(ctrl, cmd); 732} 733 734 735static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) 736{ 737 char cmd[256]; 738 int res; 739 740 if (argc != 1) { 741 printf("Invalid IBSS_RSN command: needs one argument " 742 "(Peer STA MAC address)\n"); 743 return -1; 744 } 745 746 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]); 747 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 748 printf("Too long IBSS_RSN command.\n"); 749 return -1; 750 } 751 return wpa_ctrl_command(ctrl, cmd); 752} 753 754 755static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 756{ 757 char cmd[256]; 758 int res; 759 760 if (argc != 1) { 761 printf("Invalid LEVEL command: needs one argument (debug " 762 "level)\n"); 763 return -1; 764 } 765 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); 766 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 767 printf("Too long LEVEL command.\n"); 768 return -1; 769 } 770 return wpa_ctrl_command(ctrl, cmd); 771} 772 773 774static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) 775{ 776 char cmd[256], *pos, *end; 777 int i, ret; 778 779 if (argc < 2) { 780 printf("Invalid IDENTITY command: needs two arguments " 781 "(network id and identity)\n"); 782 return -1; 783 } 784 785 end = cmd + sizeof(cmd); 786 pos = cmd; 787 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", 788 argv[0], argv[1]); 789 if (ret < 0 || ret >= end - pos) { 790 printf("Too long IDENTITY command.\n"); 791 return -1; 792 } 793 pos += ret; 794 for (i = 2; i < argc; i++) { 795 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 796 if (ret < 0 || ret >= end - pos) { 797 printf("Too long IDENTITY command.\n"); 798 return -1; 799 } 800 pos += ret; 801 } 802 803 return wpa_ctrl_command(ctrl, cmd); 804} 805 806 807static int wpa_cli_cmd_password(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 PASSWORD command: needs two arguments " 814 "(network id and password)\n"); 815 return -1; 816 } 817 818 end = cmd + sizeof(cmd); 819 pos = cmd; 820 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", 821 argv[0], argv[1]); 822 if (ret < 0 || ret >= end - pos) { 823 printf("Too long PASSWORD 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 PASSWORD command.\n"); 831 return -1; 832 } 833 pos += ret; 834 } 835 836 return wpa_ctrl_command(ctrl, cmd); 837} 838 839 840static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, 841 char *argv[]) 842{ 843 char cmd[256], *pos, *end; 844 int i, ret; 845 846 if (argc < 2) { 847 printf("Invalid NEW_PASSWORD command: needs two arguments " 848 "(network id and password)\n"); 849 return -1; 850 } 851 852 end = cmd + sizeof(cmd); 853 pos = cmd; 854 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", 855 argv[0], argv[1]); 856 if (ret < 0 || ret >= end - pos) { 857 printf("Too long NEW_PASSWORD command.\n"); 858 return -1; 859 } 860 pos += ret; 861 for (i = 2; i < argc; i++) { 862 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 863 if (ret < 0 || ret >= end - pos) { 864 printf("Too long NEW_PASSWORD command.\n"); 865 return -1; 866 } 867 pos += ret; 868 } 869 870 return wpa_ctrl_command(ctrl, cmd); 871} 872 873 874static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 875{ 876 char cmd[256], *pos, *end; 877 int i, ret; 878 879 if (argc < 2) { 880 printf("Invalid PIN command: needs two arguments " 881 "(network id and pin)\n"); 882 return -1; 883 } 884 885 end = cmd + sizeof(cmd); 886 pos = cmd; 887 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", 888 argv[0], argv[1]); 889 if (ret < 0 || ret >= end - pos) { 890 printf("Too long PIN 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 PIN command.\n"); 898 return -1; 899 } 900 pos += ret; 901 } 902 return wpa_ctrl_command(ctrl, cmd); 903} 904 905 906static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) 907{ 908 char cmd[256], *pos, *end; 909 int i, ret; 910 911 if (argc < 2) { 912 printf("Invalid OTP command: needs two arguments (network " 913 "id and password)\n"); 914 return -1; 915 } 916 917 end = cmd + sizeof(cmd); 918 pos = cmd; 919 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", 920 argv[0], argv[1]); 921 if (ret < 0 || ret >= end - pos) { 922 printf("Too long OTP command.\n"); 923 return -1; 924 } 925 pos += ret; 926 for (i = 2; i < argc; i++) { 927 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 928 if (ret < 0 || ret >= end - pos) { 929 printf("Too long OTP command.\n"); 930 return -1; 931 } 932 pos += ret; 933 } 934 935 return wpa_ctrl_command(ctrl, cmd); 936} 937 938 939static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, 940 char *argv[]) 941{ 942 char cmd[256], *pos, *end; 943 int i, ret; 944 945 if (argc < 2) { 946 printf("Invalid PASSPHRASE command: needs two arguments " 947 "(network id and passphrase)\n"); 948 return -1; 949 } 950 951 end = cmd + sizeof(cmd); 952 pos = cmd; 953 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", 954 argv[0], argv[1]); 955 if (ret < 0 || ret >= end - pos) { 956 printf("Too long PASSPHRASE command.\n"); 957 return -1; 958 } 959 pos += ret; 960 for (i = 2; i < argc; i++) { 961 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 962 if (ret < 0 || ret >= end - pos) { 963 printf("Too long PASSPHRASE command.\n"); 964 return -1; 965 } 966 pos += ret; 967 } 968 969 return wpa_ctrl_command(ctrl, cmd); 970} 971 972 973static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) 974{ 975 char cmd[256], *pos, *end; 976 int i, ret; 977 978 if (argc < 2) { 979 printf("Invalid BSSID command: needs two arguments (network " 980 "id and BSSID)\n"); 981 return -1; 982 } 983 984 end = cmd + sizeof(cmd); 985 pos = cmd; 986 ret = os_snprintf(pos, end - pos, "BSSID"); 987 if (ret < 0 || ret >= end - pos) { 988 printf("Too long BSSID command.\n"); 989 return -1; 990 } 991 pos += ret; 992 for (i = 0; i < argc; i++) { 993 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 994 if (ret < 0 || ret >= end - pos) { 995 printf("Too long BSSID command.\n"); 996 return -1; 997 } 998 pos += ret; 999 } 1000 1001 return wpa_ctrl_command(ctrl, cmd); 1002} 1003 1004 1005static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, 1006 char *argv[]) 1007{ 1008 return wpa_ctrl_command(ctrl, "LIST_NETWORKS"); 1009} 1010 1011 1012static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, 1013 char *argv[]) 1014{ 1015 char cmd[32]; 1016 int res; 1017 1018 if (argc < 1) { 1019 printf("Invalid SELECT_NETWORK command: needs one argument " 1020 "(network id)\n"); 1021 return -1; 1022 } 1023 1024 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]); 1025 if (res < 0 || (size_t) res >= sizeof(cmd)) 1026 return -1; 1027 cmd[sizeof(cmd) - 1] = '\0'; 1028 1029 return wpa_ctrl_command(ctrl, cmd); 1030} 1031 1032 1033static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, 1034 char *argv[]) 1035{ 1036 char cmd[32]; 1037 int res; 1038 1039 if (argc < 1) { 1040 printf("Invalid ENABLE_NETWORK command: needs one argument " 1041 "(network id)\n"); 1042 return -1; 1043 } 1044 1045 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]); 1046 if (res < 0 || (size_t) res >= sizeof(cmd)) 1047 return -1; 1048 cmd[sizeof(cmd) - 1] = '\0'; 1049 1050 return wpa_ctrl_command(ctrl, cmd); 1051} 1052 1053 1054static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, 1055 char *argv[]) 1056{ 1057 char cmd[32]; 1058 int res; 1059 1060 if (argc < 1) { 1061 printf("Invalid DISABLE_NETWORK command: needs one argument " 1062 "(network id)\n"); 1063 return -1; 1064 } 1065 1066 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]); 1067 if (res < 0 || (size_t) res >= sizeof(cmd)) 1068 return -1; 1069 cmd[sizeof(cmd) - 1] = '\0'; 1070 1071 return wpa_ctrl_command(ctrl, cmd); 1072} 1073 1074 1075static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, 1076 char *argv[]) 1077{ 1078 return wpa_ctrl_command(ctrl, "ADD_NETWORK"); 1079} 1080 1081 1082static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, 1083 char *argv[]) 1084{ 1085 char cmd[32]; 1086 int res; 1087 1088 if (argc < 1) { 1089 printf("Invalid REMOVE_NETWORK command: needs one argument " 1090 "(network id)\n"); 1091 return -1; 1092 } 1093 1094 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]); 1095 if (res < 0 || (size_t) res >= sizeof(cmd)) 1096 return -1; 1097 cmd[sizeof(cmd) - 1] = '\0'; 1098 1099 return wpa_ctrl_command(ctrl, cmd); 1100} 1101 1102 1103static void wpa_cli_show_network_variables(void) 1104{ 1105 printf("set_network variables:\n" 1106 " ssid (network name, SSID)\n" 1107 " psk (WPA passphrase or pre-shared key)\n" 1108 " key_mgmt (key management protocol)\n" 1109 " identity (EAP identity)\n" 1110 " password (EAP password)\n" 1111 " ...\n" 1112 "\n" 1113 "Note: Values are entered in the same format as the " 1114 "configuration file is using,\n" 1115 "i.e., strings values need to be inside double quotation " 1116 "marks.\n" 1117 "For example: set_network 1 ssid \"network name\"\n" 1118 "\n" 1119 "Please see wpa_supplicant.conf documentation for full list " 1120 "of\navailable variables.\n"); 1121} 1122 1123 1124static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, 1125 char *argv[]) 1126{ 1127 char cmd[256]; 1128 int res; 1129 1130 if (argc == 0) { 1131 wpa_cli_show_network_variables(); 1132 return 0; 1133 } 1134 1135 if (argc != 3) { 1136 printf("Invalid SET_NETWORK command: needs three arguments\n" 1137 "(network id, variable name, and value)\n"); 1138 return -1; 1139 } 1140 1141 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s", 1142 argv[0], argv[1], argv[2]); 1143 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1144 printf("Too long SET_NETWORK command.\n"); 1145 return -1; 1146 } 1147 return wpa_ctrl_command(ctrl, cmd); 1148} 1149 1150 1151static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, 1152 char *argv[]) 1153{ 1154 char cmd[256]; 1155 int res; 1156 1157 if (argc == 0) { 1158 wpa_cli_show_network_variables(); 1159 return 0; 1160 } 1161 1162 if (argc != 2) { 1163 printf("Invalid GET_NETWORK command: needs two arguments\n" 1164 "(network id and variable name)\n"); 1165 return -1; 1166 } 1167 1168 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s", 1169 argv[0], argv[1]); 1170 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1171 printf("Too long GET_NETWORK command.\n"); 1172 return -1; 1173 } 1174 return wpa_ctrl_command(ctrl, cmd); 1175} 1176 1177 1178static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, 1179 char *argv[]) 1180{ 1181 return wpa_ctrl_command(ctrl, "DISCONNECT"); 1182} 1183 1184 1185static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, 1186 char *argv[]) 1187{ 1188 return wpa_ctrl_command(ctrl, "RECONNECT"); 1189} 1190 1191 1192static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, 1193 char *argv[]) 1194{ 1195 return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); 1196} 1197 1198 1199static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1200{ 1201 return wpa_ctrl_command(ctrl, "SCAN"); 1202} 1203 1204 1205static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, 1206 char *argv[]) 1207{ 1208 return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); 1209} 1210 1211 1212static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1213{ 1214 char cmd[64]; 1215 int res; 1216 1217 if (argc != 1) { 1218 printf("Invalid BSS command: need one argument (index or " 1219 "BSSID)\n"); 1220 return -1; 1221 } 1222 1223 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]); 1224 if (res < 0 || (size_t) res >= sizeof(cmd)) 1225 return -1; 1226 cmd[sizeof(cmd) - 1] = '\0'; 1227 1228 return wpa_ctrl_command(ctrl, cmd); 1229} 1230 1231 1232static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, 1233 char *argv[]) 1234{ 1235 char cmd[64]; 1236 int res; 1237 1238 if (argc < 1 || argc > 2) { 1239 printf("Invalid GET_CAPABILITY command: need either one or " 1240 "two arguments\n"); 1241 return -1; 1242 } 1243 1244 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { 1245 printf("Invalid GET_CAPABILITY command: second argument, " 1246 "if any, must be 'strict'\n"); 1247 return -1; 1248 } 1249 1250 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0], 1251 (argc == 2) ? " strict" : ""); 1252 if (res < 0 || (size_t) res >= sizeof(cmd)) 1253 return -1; 1254 cmd[sizeof(cmd) - 1] = '\0'; 1255 1256 return wpa_ctrl_command(ctrl, cmd); 1257} 1258 1259 1260static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) 1261{ 1262 printf("Available interfaces:\n"); 1263 return wpa_ctrl_command(ctrl, "INTERFACES"); 1264} 1265 1266 1267static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1268{ 1269 if (argc < 1) { 1270 wpa_cli_list_interfaces(ctrl); 1271 return 0; 1272 } 1273 1274 wpa_cli_close_connection(); 1275 os_free(ctrl_ifname); 1276 ctrl_ifname = os_strdup(argv[0]); 1277 1278 if (wpa_cli_open_connection(ctrl_ifname, 1)) { 1279 printf("Connected to interface '%s.\n", ctrl_ifname); 1280 } else { 1281 printf("Could not connect to interface '%s' - re-trying\n", 1282 ctrl_ifname); 1283 } 1284 return 0; 1285} 1286 1287 1288static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, 1289 char *argv[]) 1290{ 1291 return wpa_ctrl_command(ctrl, "RECONFIGURE"); 1292} 1293 1294 1295static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, 1296 char *argv[]) 1297{ 1298 return wpa_ctrl_command(ctrl, "TERMINATE"); 1299} 1300 1301 1302static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, 1303 char *argv[]) 1304{ 1305 char cmd[256]; 1306 int res; 1307 1308 if (argc < 1) { 1309 printf("Invalid INTERFACE_ADD command: needs at least one " 1310 "argument (interface name)\n" 1311 "All arguments: ifname confname driver ctrl_interface " 1312 "driver_param bridge_name\n"); 1313 return -1; 1314 } 1315 1316 /* 1317 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB 1318 * <driver_param>TAB<bridge_name> 1319 */ 1320 res = os_snprintf(cmd, sizeof(cmd), 1321 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", 1322 argv[0], 1323 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", 1324 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", 1325 argc > 5 ? argv[5] : ""); 1326 if (res < 0 || (size_t) res >= sizeof(cmd)) 1327 return -1; 1328 cmd[sizeof(cmd) - 1] = '\0'; 1329 return wpa_ctrl_command(ctrl, cmd); 1330} 1331 1332 1333static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, 1334 char *argv[]) 1335{ 1336 char cmd[128]; 1337 int res; 1338 1339 if (argc != 1) { 1340 printf("Invalid INTERFACE_REMOVE command: needs one argument " 1341 "(interface name)\n"); 1342 return -1; 1343 } 1344 1345 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]); 1346 if (res < 0 || (size_t) res >= sizeof(cmd)) 1347 return -1; 1348 cmd[sizeof(cmd) - 1] = '\0'; 1349 return wpa_ctrl_command(ctrl, cmd); 1350} 1351 1352 1353static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, 1354 char *argv[]) 1355{ 1356 return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); 1357} 1358 1359 1360#ifdef CONFIG_AP 1361static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1362{ 1363 char buf[64]; 1364 if (argc != 1) { 1365 printf("Invalid 'sta' command - exactly one argument, STA " 1366 "address, is required.\n"); 1367 return -1; 1368 } 1369 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]); 1370 return wpa_ctrl_command(ctrl, buf); 1371} 1372 1373 1374static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd, 1375 char *addr, size_t addr_len) 1376{ 1377 char buf[4096], *pos; 1378 size_t len; 1379 int ret; 1380 1381 if (ctrl_conn == NULL) { 1382 printf("Not connected to hostapd - command dropped.\n"); 1383 return -1; 1384 } 1385 len = sizeof(buf) - 1; 1386 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, 1387 wpa_cli_msg_cb); 1388 if (ret == -2) { 1389 printf("'%s' command timed out.\n", cmd); 1390 return -2; 1391 } else if (ret < 0) { 1392 printf("'%s' command failed.\n", cmd); 1393 return -1; 1394 } 1395 1396 buf[len] = '\0'; 1397 if (memcmp(buf, "FAIL", 4) == 0) 1398 return -1; 1399 printf("%s", buf); 1400 1401 pos = buf; 1402 while (*pos != '\0' && *pos != '\n') 1403 pos++; 1404 *pos = '\0'; 1405 os_strlcpy(addr, buf, addr_len); 1406 return 0; 1407} 1408 1409 1410static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1411{ 1412 char addr[32], cmd[64]; 1413 1414 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) 1415 return 0; 1416 do { 1417 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 1418 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); 1419 1420 return -1; 1421} 1422#endif /* CONFIG_AP */ 1423 1424 1425static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1426{ 1427 return wpa_ctrl_command(ctrl, "SUSPEND"); 1428} 1429 1430 1431static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1432{ 1433 return wpa_ctrl_command(ctrl, "RESUME"); 1434} 1435 1436 1437static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1438{ 1439 return wpa_ctrl_command(ctrl, "DROP_SA"); 1440} 1441 1442 1443static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1444{ 1445 char cmd[128]; 1446 int res; 1447 1448 if (argc != 1) { 1449 printf("Invalid ROAM command: needs one argument " 1450 "(target AP's BSSID)\n"); 1451 return -1; 1452 } 1453 1454 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]); 1455 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1456 printf("Too long ROAM command.\n"); 1457 return -1; 1458 } 1459 return wpa_ctrl_command(ctrl, cmd); 1460} 1461 1462 1463enum wpa_cli_cmd_flags { 1464 cli_cmd_flag_none = 0x00, 1465 cli_cmd_flag_sensitive = 0x01 1466}; 1467 1468struct wpa_cli_cmd { 1469 const char *cmd; 1470 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); 1471 enum wpa_cli_cmd_flags flags; 1472 const char *usage; 1473}; 1474 1475static struct wpa_cli_cmd wpa_cli_commands[] = { 1476 { "status", wpa_cli_cmd_status, 1477 cli_cmd_flag_none, 1478 "[verbose] = get current WPA/EAPOL/EAP status" }, 1479 { "ping", wpa_cli_cmd_ping, 1480 cli_cmd_flag_none, 1481 "= pings wpa_supplicant" }, 1482 { "mib", wpa_cli_cmd_mib, 1483 cli_cmd_flag_none, 1484 "= get MIB variables (dot1x, dot11)" }, 1485 { "help", wpa_cli_cmd_help, 1486 cli_cmd_flag_none, 1487 "= show this usage help" }, 1488 { "interface", wpa_cli_cmd_interface, 1489 cli_cmd_flag_none, 1490 "[ifname] = show interfaces/select interface" }, 1491 { "level", wpa_cli_cmd_level, 1492 cli_cmd_flag_none, 1493 "<debug level> = change debug level" }, 1494 { "license", wpa_cli_cmd_license, 1495 cli_cmd_flag_none, 1496 "= show full wpa_cli license" }, 1497 { "quit", wpa_cli_cmd_quit, 1498 cli_cmd_flag_none, 1499 "= exit wpa_cli" }, 1500 { "set", wpa_cli_cmd_set, 1501 cli_cmd_flag_none, 1502 "= set variables (shows list of variables when run without " 1503 "arguments)" }, 1504 { "logon", wpa_cli_cmd_logon, 1505 cli_cmd_flag_none, 1506 "= IEEE 802.1X EAPOL state machine logon" }, 1507 { "logoff", wpa_cli_cmd_logoff, 1508 cli_cmd_flag_none, 1509 "= IEEE 802.1X EAPOL state machine logoff" }, 1510 { "pmksa", wpa_cli_cmd_pmksa, 1511 cli_cmd_flag_none, 1512 "= show PMKSA cache" }, 1513 { "reassociate", wpa_cli_cmd_reassociate, 1514 cli_cmd_flag_none, 1515 "= force reassociation" }, 1516 { "preauthenticate", wpa_cli_cmd_preauthenticate, 1517 cli_cmd_flag_none, 1518 "<BSSID> = force preauthentication" }, 1519 { "identity", wpa_cli_cmd_identity, 1520 cli_cmd_flag_none, 1521 "<network id> <identity> = configure identity for an SSID" }, 1522 { "password", wpa_cli_cmd_password, 1523 cli_cmd_flag_sensitive, 1524 "<network id> <password> = configure password for an SSID" }, 1525 { "new_password", wpa_cli_cmd_new_password, 1526 cli_cmd_flag_sensitive, 1527 "<network id> <password> = change password for an SSID" }, 1528 { "pin", wpa_cli_cmd_pin, 1529 cli_cmd_flag_sensitive, 1530 "<network id> <pin> = configure pin for an SSID" }, 1531 { "otp", wpa_cli_cmd_otp, 1532 cli_cmd_flag_sensitive, 1533 "<network id> <password> = configure one-time-password for an SSID" 1534 }, 1535 { "passphrase", wpa_cli_cmd_passphrase, 1536 cli_cmd_flag_sensitive, 1537 "<network id> <passphrase> = configure private key passphrase\n" 1538 " for an SSID" }, 1539 { "bssid", wpa_cli_cmd_bssid, 1540 cli_cmd_flag_none, 1541 "<network id> <BSSID> = set preferred BSSID for an SSID" }, 1542 { "list_networks", wpa_cli_cmd_list_networks, 1543 cli_cmd_flag_none, 1544 "= list configured networks" }, 1545 { "select_network", wpa_cli_cmd_select_network, 1546 cli_cmd_flag_none, 1547 "<network id> = select a network (disable others)" }, 1548 { "enable_network", wpa_cli_cmd_enable_network, 1549 cli_cmd_flag_none, 1550 "<network id> = enable a network" }, 1551 { "disable_network", wpa_cli_cmd_disable_network, 1552 cli_cmd_flag_none, 1553 "<network id> = disable a network" }, 1554 { "add_network", wpa_cli_cmd_add_network, 1555 cli_cmd_flag_none, 1556 "= add a network" }, 1557 { "remove_network", wpa_cli_cmd_remove_network, 1558 cli_cmd_flag_none, 1559 "<network id> = remove a network" }, 1560 { "set_network", wpa_cli_cmd_set_network, 1561 cli_cmd_flag_sensitive, 1562 "<network id> <variable> <value> = set network variables (shows\n" 1563 " list of variables when run without arguments)" }, 1564 { "get_network", wpa_cli_cmd_get_network, 1565 cli_cmd_flag_none, 1566 "<network id> <variable> = get network variables" }, 1567 { "save_config", wpa_cli_cmd_save_config, 1568 cli_cmd_flag_none, 1569 "= save the current configuration" }, 1570 { "disconnect", wpa_cli_cmd_disconnect, 1571 cli_cmd_flag_none, 1572 "= disconnect and wait for reassociate/reconnect command before\n" 1573 " connecting" }, 1574 { "reconnect", wpa_cli_cmd_reconnect, 1575 cli_cmd_flag_none, 1576 "= like reassociate, but only takes effect if already disconnected" 1577 }, 1578 { "scan", wpa_cli_cmd_scan, 1579 cli_cmd_flag_none, 1580 "= request new BSS scan" }, 1581 { "scan_results", wpa_cli_cmd_scan_results, 1582 cli_cmd_flag_none, 1583 "= get latest scan results" }, 1584 { "bss", wpa_cli_cmd_bss, 1585 cli_cmd_flag_none, 1586 "<<idx> | <bssid>> = get detailed scan result info" }, 1587 { "get_capability", wpa_cli_cmd_get_capability, 1588 cli_cmd_flag_none, 1589 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" }, 1590 { "reconfigure", wpa_cli_cmd_reconfigure, 1591 cli_cmd_flag_none, 1592 "= force wpa_supplicant to re-read its configuration file" }, 1593 { "terminate", wpa_cli_cmd_terminate, 1594 cli_cmd_flag_none, 1595 "= terminate wpa_supplicant" }, 1596 { "interface_add", wpa_cli_cmd_interface_add, 1597 cli_cmd_flag_none, 1598 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n" 1599 " <bridge_name> = adds new interface, all parameters but <ifname>\n" 1600 " are optional" }, 1601 { "interface_remove", wpa_cli_cmd_interface_remove, 1602 cli_cmd_flag_none, 1603 "<ifname> = removes the interface" }, 1604 { "interface_list", wpa_cli_cmd_interface_list, 1605 cli_cmd_flag_none, 1606 "= list available interfaces" }, 1607 { "ap_scan", wpa_cli_cmd_ap_scan, 1608 cli_cmd_flag_none, 1609 "<value> = set ap_scan parameter" }, 1610 { "stkstart", wpa_cli_cmd_stkstart, 1611 cli_cmd_flag_none, 1612 "<addr> = request STK negotiation with <addr>" }, 1613 { "ft_ds", wpa_cli_cmd_ft_ds, 1614 cli_cmd_flag_none, 1615 "<addr> = request over-the-DS FT with <addr>" }, 1616 { "wps_pbc", wpa_cli_cmd_wps_pbc, 1617 cli_cmd_flag_none, 1618 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" }, 1619 { "wps_pin", wpa_cli_cmd_wps_pin, 1620 cli_cmd_flag_sensitive, 1621 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not " 1622 "hardcoded)" }, 1623#ifdef CONFIG_WPS_OOB 1624 { "wps_oob", wpa_cli_cmd_wps_oob, 1625 cli_cmd_flag_sensitive, 1626 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" }, 1627#endif /* CONFIG_WPS_OOB */ 1628 { "wps_reg", wpa_cli_cmd_wps_reg, 1629 cli_cmd_flag_sensitive, 1630 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" }, 1631 { "wps_er_start", wpa_cli_cmd_wps_er_start, 1632 cli_cmd_flag_none, 1633 "= start Wi-Fi Protected Setup External Registrar" }, 1634 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, 1635 cli_cmd_flag_none, 1636 "= stop Wi-Fi Protected Setup External Registrar" }, 1637 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, 1638 cli_cmd_flag_sensitive, 1639 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" }, 1640 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, 1641 cli_cmd_flag_none, 1642 "<UUID> = accept an Enrollee PBC using External Registrar" }, 1643 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, 1644 cli_cmd_flag_sensitive, 1645 "<UUID> <PIN> = learn AP configuration" }, 1646 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, 1647 cli_cmd_flag_none, 1648 "<addr> = request RSN authentication with <addr> in IBSS" }, 1649#ifdef CONFIG_AP 1650 { "sta", wpa_cli_cmd_sta, 1651 cli_cmd_flag_none, 1652 "<addr> = get information about an associated station (AP)" }, 1653 { "all_sta", wpa_cli_cmd_all_sta, 1654 cli_cmd_flag_none, 1655 "= get information about all associated stations (AP)" }, 1656#endif /* CONFIG_AP */ 1657 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none, 1658 "= notification of suspend/hibernate" }, 1659 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none, 1660 "= notification of resume/thaw" }, 1661 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none, 1662 "= drop SA without deauth/disassoc (test command)" }, 1663 { "roam", wpa_cli_cmd_roam, 1664 cli_cmd_flag_none, 1665 "<addr> = roam to the specified BSS" }, 1666 { NULL, NULL, cli_cmd_flag_none, NULL } 1667}; 1668 1669 1670/* 1671 * Prints command usage, lines are padded with the specified string. 1672 */ 1673static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad) 1674{ 1675 char c; 1676 size_t n; 1677 1678 printf("%s%s ", pad, cmd->cmd); 1679 for (n = 0; (c = cmd->usage[n]); n++) { 1680 printf("%c", c); 1681 if (c == '\n') 1682 printf("%s", pad); 1683 } 1684 printf("\n"); 1685} 1686 1687 1688static void print_help(void) 1689{ 1690 int n; 1691 printf("commands:\n"); 1692 for (n = 0; wpa_cli_commands[n].cmd; n++) 1693 print_cmd_help(&wpa_cli_commands[n], " "); 1694} 1695 1696 1697#ifdef CONFIG_READLINE 1698static int cmd_has_sensitive_data(const char *cmd) 1699{ 1700 const char *c, *delim; 1701 int n; 1702 size_t len; 1703 1704 delim = os_strchr(cmd, ' '); 1705 if (delim) 1706 len = delim - cmd; 1707 else 1708 len = os_strlen(cmd); 1709 1710 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) { 1711 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c)) 1712 return (wpa_cli_commands[n].flags & 1713 cli_cmd_flag_sensitive); 1714 } 1715 return 0; 1716} 1717#endif /* CONFIG_READLINE */ 1718 1719 1720static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1721{ 1722 struct wpa_cli_cmd *cmd, *match = NULL; 1723 int count; 1724 int ret = 0; 1725 1726 count = 0; 1727 cmd = wpa_cli_commands; 1728 while (cmd->cmd) { 1729 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) 1730 { 1731 match = cmd; 1732 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { 1733 /* we have an exact match */ 1734 count = 1; 1735 break; 1736 } 1737 count++; 1738 } 1739 cmd++; 1740 } 1741 1742 if (count > 1) { 1743 printf("Ambiguous command '%s'; possible commands:", argv[0]); 1744 cmd = wpa_cli_commands; 1745 while (cmd->cmd) { 1746 if (os_strncasecmp(cmd->cmd, argv[0], 1747 os_strlen(argv[0])) == 0) { 1748 printf(" %s", cmd->cmd); 1749 } 1750 cmd++; 1751 } 1752 printf("\n"); 1753 ret = 1; 1754 } else if (count == 0) { 1755 printf("Unknown command '%s'\n", argv[0]); 1756 ret = 1; 1757 } else { 1758 ret = match->handler(ctrl, argc - 1, &argv[1]); 1759 } 1760 1761 return ret; 1762} 1763 1764 1765static int str_match(const char *a, const char *b) 1766{ 1767 return os_strncmp(a, b, os_strlen(b)) == 0; 1768} 1769 1770 1771static int wpa_cli_exec(const char *program, const char *arg1, 1772 const char *arg2) 1773{ 1774 char *cmd; 1775 size_t len; 1776 int res; 1777 int ret = 0; 1778 1779 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; 1780 cmd = os_malloc(len); 1781 if (cmd == NULL) 1782 return -1; 1783 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); 1784 if (res < 0 || (size_t) res >= len) { 1785 os_free(cmd); 1786 return -1; 1787 } 1788 cmd[len - 1] = '\0'; 1789#ifndef _WIN32_WCE 1790 if (system(cmd) < 0) 1791 ret = -1; 1792#endif /* _WIN32_WCE */ 1793 os_free(cmd); 1794 1795 return ret; 1796} 1797 1798 1799static void wpa_cli_action_process(const char *msg) 1800{ 1801 const char *pos; 1802 char *copy = NULL, *id, *pos2; 1803 1804 pos = msg; 1805 if (*pos == '<') { 1806 /* skip priority */ 1807 pos = os_strchr(pos, '>'); 1808 if (pos) 1809 pos++; 1810 else 1811 pos = msg; 1812 } 1813 1814 if (str_match(pos, WPA_EVENT_CONNECTED)) { 1815 int new_id = -1; 1816 os_unsetenv("WPA_ID"); 1817 os_unsetenv("WPA_ID_STR"); 1818 os_unsetenv("WPA_CTRL_DIR"); 1819 1820 pos = os_strstr(pos, "[id="); 1821 if (pos) 1822 copy = os_strdup(pos + 4); 1823 1824 if (copy) { 1825 pos2 = id = copy; 1826 while (*pos2 && *pos2 != ' ') 1827 pos2++; 1828 *pos2++ = '\0'; 1829 new_id = atoi(id); 1830 os_setenv("WPA_ID", id, 1); 1831 while (*pos2 && *pos2 != '=') 1832 pos2++; 1833 if (*pos2 == '=') 1834 pos2++; 1835 id = pos2; 1836 while (*pos2 && *pos2 != ']') 1837 pos2++; 1838 *pos2 = '\0'; 1839 os_setenv("WPA_ID_STR", id, 1); 1840 os_free(copy); 1841 } 1842 1843 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); 1844 1845 if (!wpa_cli_connected || new_id != wpa_cli_last_id) { 1846 wpa_cli_connected = 1; 1847 wpa_cli_last_id = new_id; 1848 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); 1849 } 1850 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { 1851 if (wpa_cli_connected) { 1852 wpa_cli_connected = 0; 1853 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); 1854 } 1855 } else if (str_match(pos, WPA_EVENT_TERMINATING)) { 1856 printf("wpa_supplicant is terminating - stop monitoring\n"); 1857 wpa_cli_quit = 1; 1858 } 1859} 1860 1861 1862#ifndef CONFIG_ANSI_C_EXTRA 1863static void wpa_cli_action_cb(char *msg, size_t len) 1864{ 1865 wpa_cli_action_process(msg); 1866} 1867#endif /* CONFIG_ANSI_C_EXTRA */ 1868 1869 1870static void wpa_cli_reconnect(void) 1871{ 1872 wpa_cli_close_connection(); 1873 wpa_cli_open_connection(ctrl_ifname, 1); 1874} 1875 1876 1877static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, 1878 int action_monitor) 1879{ 1880 int first = 1; 1881 if (ctrl_conn == NULL) { 1882 wpa_cli_reconnect(); 1883 return; 1884 } 1885 while (wpa_ctrl_pending(ctrl) > 0) { 1886 char buf[256]; 1887 size_t len = sizeof(buf) - 1; 1888 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { 1889 buf[len] = '\0'; 1890 if (action_monitor) 1891 wpa_cli_action_process(buf); 1892 else { 1893 if (in_read && first) 1894 printf("\r"); 1895 first = 0; 1896 printf("%s\n", buf); 1897#ifdef CONFIG_READLINE 1898 rl_on_new_line(); 1899 rl_redisplay(); 1900#endif /* CONFIG_READLINE */ 1901 } 1902 } else { 1903 printf("Could not read pending message.\n"); 1904 break; 1905 } 1906 } 1907 1908 if (wpa_ctrl_pending(ctrl) < 0) { 1909 printf("Connection to wpa_supplicant lost - trying to " 1910 "reconnect\n"); 1911 wpa_cli_reconnect(); 1912 } 1913} 1914 1915 1916#ifdef CONFIG_READLINE 1917static char * wpa_cli_cmd_gen(const char *text, int state) 1918{ 1919 static int i, len; 1920 const char *cmd; 1921 1922 if (state == 0) { 1923 i = 0; 1924 len = os_strlen(text); 1925 } 1926 1927 while ((cmd = wpa_cli_commands[i].cmd)) { 1928 i++; 1929 if (os_strncasecmp(cmd, text, len) == 0) 1930 return strdup(cmd); 1931 } 1932 1933 return NULL; 1934} 1935 1936 1937static char * wpa_cli_dummy_gen(const char *text, int state) 1938{ 1939 int i; 1940 1941 for (i = 0; wpa_cli_commands[i].cmd; i++) { 1942 const char *cmd = wpa_cli_commands[i].cmd; 1943 size_t len = os_strlen(cmd); 1944 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 && 1945 rl_line_buffer[len] == ' ') { 1946 printf("\n%s\n", wpa_cli_commands[i].usage); 1947 rl_on_new_line(); 1948 rl_redisplay(); 1949 break; 1950 } 1951 } 1952 1953 rl_attempted_completion_over = 1; 1954 return NULL; 1955} 1956 1957 1958static char * wpa_cli_status_gen(const char *text, int state) 1959{ 1960 static int i, len; 1961 char *options[] = { 1962 "verbose", NULL 1963 }; 1964 char *t; 1965 1966 if (state == 0) { 1967 i = 0; 1968 len = os_strlen(text); 1969 } 1970 1971 while ((t = options[i])) { 1972 i++; 1973 if (os_strncasecmp(t, text, len) == 0) 1974 return strdup(t); 1975 } 1976 1977 rl_attempted_completion_over = 1; 1978 return NULL; 1979} 1980 1981 1982static char ** wpa_cli_completion(const char *text, int start, int end) 1983{ 1984 char * (*func)(const char *text, int state); 1985 1986 if (start == 0) 1987 func = wpa_cli_cmd_gen; 1988 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0) 1989 func = wpa_cli_status_gen; 1990 else 1991 func = wpa_cli_dummy_gen; 1992 return rl_completion_matches(text, func); 1993} 1994#endif /* CONFIG_READLINE */ 1995 1996 1997static void wpa_cli_interactive(void) 1998{ 1999#define max_args 10 2000 char cmdbuf[256], *cmd, *argv[max_args], *pos; 2001 int argc; 2002#ifdef CONFIG_READLINE 2003 char *home, *hfile = NULL; 2004#endif /* CONFIG_READLINE */ 2005 2006 printf("\nInteractive mode\n\n"); 2007 2008#ifdef CONFIG_READLINE 2009 rl_attempted_completion_function = wpa_cli_completion; 2010 home = getenv("HOME"); 2011 if (home) { 2012 const char *fname = ".wpa_cli_history"; 2013 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; 2014 hfile = os_malloc(hfile_len); 2015 if (hfile) { 2016 int res; 2017 res = os_snprintf(hfile, hfile_len, "%s/%s", home, 2018 fname); 2019 if (res >= 0 && res < hfile_len) { 2020 hfile[hfile_len - 1] = '\0'; 2021 read_history(hfile); 2022 stifle_history(100); 2023 } 2024 } 2025 } 2026#endif /* CONFIG_READLINE */ 2027 2028 do { 2029 wpa_cli_recv_pending(mon_conn, 0, 0); 2030#ifndef CONFIG_NATIVE_WINDOWS 2031 alarm(ping_interval); 2032#endif /* CONFIG_NATIVE_WINDOWS */ 2033#ifdef CONFIG_WPA_CLI_FORK 2034 if (mon_pid) 2035 kill(mon_pid, SIGUSR1); 2036#endif /* CONFIG_WPA_CLI_FORK */ 2037#ifdef CONFIG_READLINE 2038 cmd = readline("> "); 2039 if (cmd && *cmd) { 2040 HIST_ENTRY *h; 2041 while (next_history()) 2042 ; 2043 h = previous_history(); 2044 if (h == NULL || os_strcmp(cmd, h->line) != 0) 2045 add_history(cmd); 2046 next_history(); 2047 } 2048#else /* CONFIG_READLINE */ 2049 printf("> "); 2050 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); 2051#endif /* CONFIG_READLINE */ 2052#ifndef CONFIG_NATIVE_WINDOWS 2053 alarm(0); 2054#endif /* CONFIG_NATIVE_WINDOWS */ 2055 if (cmd == NULL) 2056 break; 2057 wpa_cli_recv_pending(mon_conn, 0, 0); 2058 pos = cmd; 2059 while (*pos != '\0') { 2060 if (*pos == '\n') { 2061 *pos = '\0'; 2062 break; 2063 } 2064 pos++; 2065 } 2066 argc = 0; 2067 pos = cmd; 2068 for (;;) { 2069 while (*pos == ' ') 2070 pos++; 2071 if (*pos == '\0') 2072 break; 2073 argv[argc] = pos; 2074 argc++; 2075 if (argc == max_args) 2076 break; 2077 if (*pos == '"') { 2078 char *pos2 = os_strrchr(pos, '"'); 2079 if (pos2) 2080 pos = pos2 + 1; 2081 } 2082 while (*pos != '\0' && *pos != ' ') 2083 pos++; 2084 if (*pos == ' ') 2085 *pos++ = '\0'; 2086 } 2087 if (argc) 2088 wpa_request(ctrl_conn, argc, argv); 2089 2090 if (cmd != cmdbuf) 2091 free(cmd); 2092#ifdef CONFIG_WPA_CLI_FORK 2093 if (mon_pid) 2094 kill(mon_pid, SIGUSR2); 2095#endif /* CONFIG_WPA_CLI_FORK */ 2096 } while (!wpa_cli_quit); 2097 2098#ifdef CONFIG_READLINE 2099 if (hfile) { 2100 /* Save command history, excluding lines that may contain 2101 * passwords. */ 2102 HIST_ENTRY *h; 2103 history_set_pos(0); 2104 while ((h = current_history())) { 2105 char *p = h->line; 2106 while (*p == ' ' || *p == '\t') 2107 p++; 2108 if (cmd_has_sensitive_data(p)) { 2109 h = remove_history(where_history()); 2110 if (h) { 2111 os_free(h->line); 2112 os_free(h->data); 2113 os_free(h); 2114 } else 2115 next_history(); 2116 } else 2117 next_history(); 2118 } 2119 write_history(hfile); 2120 os_free(hfile); 2121 } 2122#endif /* CONFIG_READLINE */ 2123} 2124 2125 2126static void wpa_cli_action(struct wpa_ctrl *ctrl) 2127{ 2128#ifdef CONFIG_ANSI_C_EXTRA 2129 /* TODO: ANSI C version(?) */ 2130 printf("Action processing not supported in ANSI C build.\n"); 2131#else /* CONFIG_ANSI_C_EXTRA */ 2132 fd_set rfds; 2133 int fd, res; 2134 struct timeval tv; 2135 char buf[256]; /* note: large enough to fit in unsolicited messages */ 2136 size_t len; 2137 2138 fd = wpa_ctrl_get_fd(ctrl); 2139 2140 while (!wpa_cli_quit) { 2141 FD_ZERO(&rfds); 2142 FD_SET(fd, &rfds); 2143 tv.tv_sec = ping_interval; 2144 tv.tv_usec = 0; 2145 res = select(fd + 1, &rfds, NULL, NULL, &tv); 2146 if (res < 0 && errno != EINTR) { 2147 perror("select"); 2148 break; 2149 } 2150 2151 if (FD_ISSET(fd, &rfds)) 2152 wpa_cli_recv_pending(ctrl, 0, 1); 2153 else { 2154 /* verify that connection is still working */ 2155 len = sizeof(buf) - 1; 2156 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, 2157 wpa_cli_action_cb) < 0 || 2158 len < 4 || os_memcmp(buf, "PONG", 4) != 0) { 2159 printf("wpa_supplicant did not reply to PING " 2160 "command - exiting\n"); 2161 break; 2162 } 2163 } 2164 } 2165#endif /* CONFIG_ANSI_C_EXTRA */ 2166} 2167 2168 2169static void wpa_cli_cleanup(void) 2170{ 2171 wpa_cli_close_connection(); 2172 if (pid_file) 2173 os_daemonize_terminate(pid_file); 2174 2175 os_program_deinit(); 2176} 2177 2178static void wpa_cli_terminate(int sig) 2179{ 2180 wpa_cli_cleanup(); 2181 exit(0); 2182} 2183 2184 2185#ifdef CONFIG_WPA_CLI_FORK 2186static void wpa_cli_usr1(int sig) 2187{ 2188#ifdef CONFIG_READLINE 2189 rl_on_new_line(); 2190 rl_redisplay(); 2191#endif /* CONFIG_READLINE */ 2192} 2193#endif /* CONFIG_WPA_CLI_FORK */ 2194 2195 2196#ifndef CONFIG_NATIVE_WINDOWS 2197static void wpa_cli_alarm(int sig) 2198{ 2199 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { 2200 printf("Connection to wpa_supplicant lost - trying to " 2201 "reconnect\n"); 2202 wpa_cli_close_connection(); 2203 } 2204 if (!ctrl_conn) 2205 wpa_cli_reconnect(); 2206 if (mon_conn) 2207 wpa_cli_recv_pending(mon_conn, 1, 0); 2208 alarm(ping_interval); 2209} 2210#endif /* CONFIG_NATIVE_WINDOWS */ 2211 2212 2213static char * wpa_cli_get_default_ifname(void) 2214{ 2215 char *ifname = NULL; 2216 2217#ifdef CONFIG_CTRL_IFACE_UNIX 2218 struct dirent *dent; 2219 DIR *dir = opendir(ctrl_iface_dir); 2220 if (!dir) 2221 return NULL; 2222 while ((dent = readdir(dir))) { 2223#ifdef _DIRENT_HAVE_D_TYPE 2224 /* 2225 * Skip the file if it is not a socket. Also accept 2226 * DT_UNKNOWN (0) in case the C library or underlying 2227 * file system does not support d_type. 2228 */ 2229 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) 2230 continue; 2231#endif /* _DIRENT_HAVE_D_TYPE */ 2232 if (os_strcmp(dent->d_name, ".") == 0 || 2233 os_strcmp(dent->d_name, "..") == 0) 2234 continue; 2235 printf("Selected interface '%s'\n", dent->d_name); 2236 ifname = os_strdup(dent->d_name); 2237 break; 2238 } 2239 closedir(dir); 2240#endif /* CONFIG_CTRL_IFACE_UNIX */ 2241 2242#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 2243 char buf[2048], *pos; 2244 size_t len; 2245 struct wpa_ctrl *ctrl; 2246 int ret; 2247 2248 ctrl = wpa_ctrl_open(NULL); 2249 if (ctrl == NULL) 2250 return NULL; 2251 2252 len = sizeof(buf) - 1; 2253 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); 2254 if (ret >= 0) { 2255 buf[len] = '\0'; 2256 pos = os_strchr(buf, '\n'); 2257 if (pos) 2258 *pos = '\0'; 2259 ifname = os_strdup(buf); 2260 } 2261 wpa_ctrl_close(ctrl); 2262#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2263 2264 return ifname; 2265} 2266 2267 2268int main(int argc, char *argv[]) 2269{ 2270 int warning_displayed = 0; 2271 int c; 2272 int daemonize = 0; 2273 int ret = 0; 2274 const char *global = NULL; 2275 2276 if (os_program_init()) 2277 return -1; 2278 2279 for (;;) { 2280 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v"); 2281 if (c < 0) 2282 break; 2283 switch (c) { 2284 case 'a': 2285 action_file = optarg; 2286 break; 2287 case 'B': 2288 daemonize = 1; 2289 break; 2290 case 'g': 2291 global = optarg; 2292 break; 2293 case 'G': 2294 ping_interval = atoi(optarg); 2295 break; 2296 case 'h': 2297 usage(); 2298 return 0; 2299 case 'v': 2300 printf("%s\n", wpa_cli_version); 2301 return 0; 2302 case 'i': 2303 os_free(ctrl_ifname); 2304 ctrl_ifname = os_strdup(optarg); 2305 break; 2306 case 'p': 2307 ctrl_iface_dir = optarg; 2308 break; 2309 case 'P': 2310 pid_file = optarg; 2311 break; 2312 default: 2313 usage(); 2314 return -1; 2315 } 2316 } 2317 2318 interactive = (argc == optind) && (action_file == NULL); 2319 2320 if (interactive) 2321 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); 2322 2323 if (global) { 2324#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 2325 ctrl_conn = wpa_ctrl_open(NULL); 2326#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2327 ctrl_conn = wpa_ctrl_open(global); 2328#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 2329 if (ctrl_conn == NULL) { 2330 perror("Failed to connect to wpa_supplicant - " 2331 "wpa_ctrl_open"); 2332 return -1; 2333 } 2334 } 2335 2336#ifndef _WIN32_WCE 2337 signal(SIGINT, wpa_cli_terminate); 2338 signal(SIGTERM, wpa_cli_terminate); 2339#endif /* _WIN32_WCE */ 2340#ifndef CONFIG_NATIVE_WINDOWS 2341 signal(SIGALRM, wpa_cli_alarm); 2342#endif /* CONFIG_NATIVE_WINDOWS */ 2343#ifdef CONFIG_WPA_CLI_FORK 2344 signal(SIGUSR1, wpa_cli_usr1); 2345#endif /* CONFIG_WPA_CLI_FORK */ 2346 2347 if (ctrl_ifname == NULL) 2348 ctrl_ifname = wpa_cli_get_default_ifname(); 2349 2350 if (interactive) { 2351 for (; !global;) { 2352 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { 2353 if (warning_displayed) 2354 printf("Connection established.\n"); 2355 break; 2356 } 2357 2358 if (!warning_displayed) { 2359 printf("Could not connect to wpa_supplicant - " 2360 "re-trying\n"); 2361 warning_displayed = 1; 2362 } 2363 os_sleep(1, 0); 2364 continue; 2365 } 2366 } else { 2367 if (!global && 2368 wpa_cli_open_connection(ctrl_ifname, 0) < 0) { 2369 perror("Failed to connect to wpa_supplicant - " 2370 "wpa_ctrl_open"); 2371 return -1; 2372 } 2373 2374 if (action_file) { 2375 if (wpa_ctrl_attach(ctrl_conn) == 0) { 2376 wpa_cli_attached = 1; 2377 } else { 2378 printf("Warning: Failed to attach to " 2379 "wpa_supplicant.\n"); 2380 return -1; 2381 } 2382 } 2383 } 2384 2385 if (daemonize && os_daemonize(pid_file)) 2386 return -1; 2387 2388 if (interactive) 2389 wpa_cli_interactive(); 2390 else if (action_file) 2391 wpa_cli_action(ctrl_conn); 2392 else 2393 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); 2394 2395 os_free(ctrl_ifname); 2396 wpa_cli_cleanup(); 2397 2398 return ret; 2399} 2400 2401#else /* CONFIG_CTRL_IFACE */ 2402int main(int argc, char *argv[]) 2403{ 2404 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); 2405 return -1; 2406} 2407#endif /* CONFIG_CTRL_IFACE */ 2408