wpa_cli.c revision 214734
1189251Ssam/* 2189251Ssam * WPA Supplicant - command line interface for wpa_supplicant daemon 3214734Srpaulo * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam 17189251Ssam#ifdef CONFIG_CTRL_IFACE 18189251Ssam 19189251Ssam#ifdef CONFIG_CTRL_IFACE_UNIX 20189251Ssam#include <dirent.h> 21189251Ssam#endif /* CONFIG_CTRL_IFACE_UNIX */ 22189251Ssam#ifdef CONFIG_READLINE 23189251Ssam#include <readline/readline.h> 24189251Ssam#include <readline/history.h> 25189251Ssam#endif /* CONFIG_READLINE */ 26189251Ssam#ifdef CONFIG_WPA_CLI_FORK 27189251Ssam#include <sys/wait.h> 28189251Ssam#endif /* CONFIG_WPA_CLI_FORK */ 29189251Ssam 30189251Ssam#include "common/wpa_ctrl.h" 31189251Ssam#include "common.h" 32189251Ssam#include "common/version.h" 33189251Ssam 34189251Ssam 35189251Ssamstatic const char *wpa_cli_version = 36214734Srpaulo"wpa_cli v" VERSION_STR "\n" 37189251Ssam"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors"; 38214734Srpaulo 39189251Ssam 40189251Ssamstatic const char *wpa_cli_license = 41189251Ssam"This program is free software. You can distribute it and/or modify it\n" 42189251Ssam"under the terms of the GNU General Public License version 2.\n" 43189251Ssam"\n" 44189251Ssam"Alternatively, this software may be distributed under the terms of the\n" 45189251Ssam"BSD license. See README and COPYING for more details.\n"; 46214734Srpaulo 47189251Ssamstatic const char *wpa_cli_full_license = 48214734Srpaulo"This program is free software; you can redistribute it and/or modify\n" 49189251Ssam"it under the terms of the GNU General Public License version 2 as\n" 50214734Srpaulo"published by the Free Software Foundation.\n" 51189251Ssam"\n" 52214734Srpaulo"This program is distributed in the hope that it will be useful,\n" 53214734Srpaulo"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 54214734Srpaulo"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 55214734Srpaulo"GNU General Public License for more details.\n" 56214734Srpaulo"\n" 57214734Srpaulo"You should have received a copy of the GNU General Public License\n" 58214734Srpaulo"along with this program; if not, write to the Free Software\n" 59214734Srpaulo"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" 60214734Srpaulo"\n" 61214734Srpaulo"Alternatively, this software may be distributed under the terms of the\n" 62214734Srpaulo"BSD license.\n" 63214734Srpaulo"\n" 64214734Srpaulo"Redistribution and use in source and binary forms, with or without\n" 65214734Srpaulo"modification, are permitted provided that the following conditions are\n" 66214734Srpaulo"met:\n" 67189251Ssam"\n" 68189251Ssam"1. Redistributions of source code must retain the above copyright\n" 69189251Ssam" notice, this list of conditions and the following disclaimer.\n" 70189251Ssam"\n" 71189251Ssam"2. Redistributions in binary form must reproduce the above copyright\n" 72214734Srpaulo" notice, this list of conditions and the following disclaimer in the\n" 73189251Ssam" documentation and/or other materials provided with the distribution.\n" 74214734Srpaulo"\n" 75214734Srpaulo"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 76189251Ssam" names of its contributors may be used to endorse or promote products\n" 77189251Ssam" derived from this software without specific prior written permission.\n" 78189251Ssam"\n" 79189251Ssam"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 80189251Ssam"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 81189251Ssam"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 82189251Ssam"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 83189251Ssam"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 84189251Ssam"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 85189251Ssam"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 86189251Ssam"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 87189251Ssam"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 88189251Ssam"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 89189251Ssam"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 90189251Ssam"\n"; 91189251Ssam 92189251Ssamstatic struct wpa_ctrl *ctrl_conn; 93189251Ssamstatic struct wpa_ctrl *mon_conn; 94189251Ssam#ifdef CONFIG_WPA_CLI_FORK 95189251Ssamstatic pid_t mon_pid = 0; 96189251Ssam#endif /* CONFIG_WPA_CLI_FORK */ 97189251Ssamstatic int wpa_cli_quit = 0; 98214734Srpaulostatic int wpa_cli_attached = 0; 99189251Ssamstatic int wpa_cli_connected = 0; 100214734Srpaulostatic int wpa_cli_last_id = 0; 101214734Srpaulostatic const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; 102189251Ssamstatic char *ctrl_ifname = NULL; 103189251Ssamstatic const char *pid_file = NULL; 104189251Ssamstatic const char *action_file = NULL; 105189251Ssamstatic int ping_interval = 5; 106189251Ssamstatic int interactive = 0; 107189251Ssam 108189251Ssam 109189251Ssamstatic void print_help(); 110189251Ssam 111189251Ssam 112189251Ssamstatic void usage(void) 113189251Ssam{ 114189251Ssam printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " 115189251Ssam "[-a<action file>] \\\n" 116189251Ssam " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] " 117189251Ssam "[command..]\n" 118189251Ssam " -h = help (show this usage text)\n" 119189251Ssam " -v = shown version information\n" 120189251Ssam " -a = run in daemon mode executing the action file based on " 121189251Ssam "events from\n" 122189251Ssam " wpa_supplicant\n" 123189251Ssam " -B = run a daemon in the background\n" 124189251Ssam " default path: /var/run/wpa_supplicant\n" 125189251Ssam " default interface: first interface found in socket path\n"); 126189251Ssam print_help(); 127189251Ssam} 128189251Ssam 129189251Ssam 130189251Ssam#ifdef CONFIG_WPA_CLI_FORK 131189251Ssamstatic int in_query = 0; 132189251Ssam 133189251Ssamstatic void wpa_cli_monitor_sig(int sig) 134189251Ssam{ 135189251Ssam if (sig == SIGUSR1) 136189251Ssam in_query = 1; 137189251Ssam else if (sig == SIGUSR2) 138189251Ssam in_query = 0; 139189251Ssam} 140189251Ssam 141189251Ssamstatic void wpa_cli_monitor(void) 142189251Ssam{ 143189251Ssam char buf[256]; 144189251Ssam size_t len = sizeof(buf) - 1; 145189251Ssam struct timeval tv; 146189251Ssam fd_set rfds; 147189251Ssam 148189251Ssam signal(SIGUSR1, wpa_cli_monitor_sig); 149189251Ssam signal(SIGUSR2, wpa_cli_monitor_sig); 150189251Ssam 151189251Ssam while (mon_conn) { 152189251Ssam int s = wpa_ctrl_get_fd(mon_conn); 153189251Ssam tv.tv_sec = 5; 154189251Ssam tv.tv_usec = 0; 155189251Ssam FD_ZERO(&rfds); 156189251Ssam FD_SET(s, &rfds); 157189251Ssam if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) { 158189251Ssam if (errno == EINTR) 159189251Ssam continue; 160189251Ssam perror("select"); 161189251Ssam break; 162189251Ssam } 163189251Ssam if (mon_conn == NULL) 164189251Ssam break; 165189251Ssam if (FD_ISSET(s, &rfds)) { 166189251Ssam len = sizeof(buf) - 1; 167189251Ssam int res = wpa_ctrl_recv(mon_conn, buf, &len); 168189251Ssam if (res < 0) { 169189251Ssam perror("wpa_ctrl_recv"); 170189251Ssam break; 171189251Ssam } 172189251Ssam buf[len] = '\0'; 173189251Ssam if (in_query) 174189251Ssam printf("\r"); 175189251Ssam printf("%s\n", buf); 176189251Ssam kill(getppid(), SIGUSR1); 177189251Ssam } 178189251Ssam } 179189251Ssam} 180189251Ssam#endif /* CONFIG_WPA_CLI_FORK */ 181189251Ssam 182189251Ssam 183189251Ssamstatic int wpa_cli_open_connection(const char *ifname, int attach) 184189251Ssam{ 185189251Ssam#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) 186189251Ssam ctrl_conn = wpa_ctrl_open(ifname); 187189251Ssam if (ctrl_conn == NULL) 188189251Ssam return -1; 189189251Ssam 190189251Ssam if (attach && interactive) 191189251Ssam mon_conn = wpa_ctrl_open(ifname); 192189251Ssam else 193189251Ssam mon_conn = NULL; 194189251Ssam#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 195189251Ssam char *cfile; 196189251Ssam int flen, res; 197189251Ssam 198189251Ssam if (ifname == NULL) 199189251Ssam return -1; 200189251Ssam 201189251Ssam flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; 202189251Ssam cfile = os_malloc(flen); 203189251Ssam if (cfile == NULL) 204189251Ssam return -1L; 205189251Ssam res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); 206189251Ssam if (res < 0 || res >= flen) { 207189251Ssam os_free(cfile); 208189251Ssam return -1; 209189251Ssam } 210189251Ssam 211189251Ssam ctrl_conn = wpa_ctrl_open(cfile); 212189251Ssam if (ctrl_conn == NULL) { 213189251Ssam os_free(cfile); 214189251Ssam return -1; 215189251Ssam } 216189251Ssam 217189251Ssam if (attach && interactive) 218189251Ssam mon_conn = wpa_ctrl_open(cfile); 219189251Ssam else 220189251Ssam mon_conn = NULL; 221189251Ssam os_free(cfile); 222189251Ssam#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 223189251Ssam 224189251Ssam if (mon_conn) { 225189251Ssam if (wpa_ctrl_attach(mon_conn) == 0) { 226189251Ssam wpa_cli_attached = 1; 227189251Ssam } else { 228189251Ssam printf("Warning: Failed to attach to " 229189251Ssam "wpa_supplicant.\n"); 230189251Ssam return -1; 231189251Ssam } 232189251Ssam 233189251Ssam#ifdef CONFIG_WPA_CLI_FORK 234189251Ssam { 235189251Ssam pid_t p = fork(); 236189251Ssam if (p < 0) { 237189251Ssam perror("fork"); 238189251Ssam return -1; 239189251Ssam } 240189251Ssam if (p == 0) { 241189251Ssam wpa_cli_monitor(); 242189251Ssam exit(0); 243189251Ssam } else 244189251Ssam mon_pid = p; 245189251Ssam } 246189251Ssam#endif /* CONFIG_WPA_CLI_FORK */ 247189251Ssam } 248189251Ssam 249189251Ssam return 0; 250189251Ssam} 251189251Ssam 252189251Ssam 253189251Ssamstatic void wpa_cli_close_connection(void) 254189251Ssam{ 255189251Ssam if (ctrl_conn == NULL) 256189251Ssam return; 257189251Ssam 258189251Ssam#ifdef CONFIG_WPA_CLI_FORK 259189251Ssam if (mon_pid) { 260189251Ssam int status; 261189251Ssam kill(mon_pid, SIGPIPE); 262189251Ssam wait(&status); 263189251Ssam mon_pid = 0; 264189251Ssam } 265189251Ssam#endif /* CONFIG_WPA_CLI_FORK */ 266189251Ssam 267189251Ssam if (wpa_cli_attached) { 268189251Ssam wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); 269189251Ssam wpa_cli_attached = 0; 270189251Ssam } 271189251Ssam wpa_ctrl_close(ctrl_conn); 272189251Ssam ctrl_conn = NULL; 273189251Ssam if (mon_conn) { 274189251Ssam wpa_ctrl_close(mon_conn); 275189251Ssam mon_conn = NULL; 276189251Ssam } 277189251Ssam} 278189251Ssam 279189251Ssam 280189251Ssamstatic void wpa_cli_msg_cb(char *msg, size_t len) 281189251Ssam{ 282189251Ssam printf("%s\n", msg); 283189251Ssam} 284189251Ssam 285189251Ssam 286189251Ssamstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) 287189251Ssam{ 288189251Ssam char buf[2048]; 289189251Ssam size_t len; 290189251Ssam int ret; 291189251Ssam 292189251Ssam if (ctrl_conn == NULL) { 293189251Ssam printf("Not connected to wpa_supplicant - command dropped.\n"); 294189251Ssam return -1; 295189251Ssam } 296189251Ssam len = sizeof(buf) - 1; 297189251Ssam ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 298214734Srpaulo wpa_cli_msg_cb); 299189251Ssam if (ret == -2) { 300189251Ssam printf("'%s' command timed out.\n", cmd); 301189251Ssam return -2; 302189251Ssam } else if (ret < 0) { 303189251Ssam printf("'%s' command failed.\n", cmd); 304189251Ssam return -1; 305189251Ssam } 306214734Srpaulo if (print) { 307214734Srpaulo buf[len] = '\0'; 308189251Ssam printf("%s", buf); 309189251Ssam } 310189251Ssam return 0; 311189251Ssam} 312189251Ssam 313189251Ssam 314189251Ssamstatic int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) 315189251Ssam{ 316189251Ssam return _wpa_ctrl_command(ctrl, cmd, 1); 317189251Ssam} 318189251Ssam 319189251Ssam 320189251Ssamstatic int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 321189251Ssam{ 322189251Ssam int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; 323189251Ssam return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); 324189251Ssam} 325189251Ssam 326189251Ssam 327189251Ssamstatic int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 328189251Ssam{ 329189251Ssam return wpa_ctrl_command(ctrl, "PING"); 330189251Ssam} 331189251Ssam 332189251Ssam 333189251Ssamstatic int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 334189251Ssam{ 335189251Ssam return wpa_ctrl_command(ctrl, "MIB"); 336189251Ssam} 337189251Ssam 338189251Ssam 339189251Ssamstatic int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 340189251Ssam{ 341189251Ssam return wpa_ctrl_command(ctrl, "PMKSA"); 342189251Ssam} 343189251Ssam 344189251Ssam 345189251Ssamstatic int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 346189251Ssam{ 347189251Ssam print_help(); 348189251Ssam return 0; 349189251Ssam} 350189251Ssam 351189251Ssam 352189251Ssamstatic int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) 353189251Ssam{ 354189251Ssam printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); 355189251Ssam return 0; 356189251Ssam} 357189251Ssam 358189251Ssam 359189251Ssamstatic int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 360189251Ssam{ 361189251Ssam wpa_cli_quit = 1; 362189251Ssam return 0; 363189251Ssam} 364189251Ssam 365189251Ssam 366189251Ssamstatic void wpa_cli_show_variables(void) 367189251Ssam{ 368189251Ssam printf("set variables:\n" 369189251Ssam " EAPOL::heldPeriod (EAPOL state machine held period, " 370189251Ssam "in seconds)\n" 371189251Ssam " EAPOL::authPeriod (EAPOL state machine authentication " 372189251Ssam "period, in seconds)\n" 373189251Ssam " EAPOL::startPeriod (EAPOL state machine start period, in " 374189251Ssam "seconds)\n" 375189251Ssam " EAPOL::maxStart (EAPOL state machine maximum start " 376189251Ssam "attempts)\n"); 377189251Ssam printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " 378189251Ssam "seconds)\n" 379189251Ssam " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" 380189251Ssam " threshold\n\tpercentage)\n" 381189251Ssam " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " 382189251Ssam "security\n\tassociation in seconds)\n"); 383189251Ssam} 384189251Ssam 385189251Ssam 386189251Ssamstatic int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 387189251Ssam{ 388189251Ssam char cmd[256]; 389189251Ssam int res; 390189251Ssam 391189251Ssam if (argc == 0) { 392189251Ssam wpa_cli_show_variables(); 393189251Ssam return 0; 394189251Ssam } 395189251Ssam 396189251Ssam if (argc != 2) { 397189251Ssam printf("Invalid SET command: needs two arguments (variable " 398189251Ssam "name and value)\n"); 399189251Ssam return -1; 400189251Ssam } 401189251Ssam 402189251Ssam res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); 403189251Ssam if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 404189251Ssam printf("Too long SET command.\n"); 405189251Ssam return -1; 406189251Ssam } 407189251Ssam return wpa_ctrl_command(ctrl, cmd); 408189251Ssam} 409189251Ssam 410189251Ssam 411189251Ssamstatic int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) 412189251Ssam{ 413189251Ssam return wpa_ctrl_command(ctrl, "LOGOFF"); 414189251Ssam} 415189251Ssam 416189251Ssam 417189251Ssamstatic int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) 418189251Ssam{ 419189251Ssam return wpa_ctrl_command(ctrl, "LOGON"); 420189251Ssam} 421189251Ssam 422189251Ssam 423189251Ssamstatic int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, 424189251Ssam char *argv[]) 425189251Ssam{ 426189251Ssam return wpa_ctrl_command(ctrl, "REASSOCIATE"); 427189251Ssam} 428189251Ssam 429189251Ssam 430189251Ssamstatic int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, 431189251Ssam char *argv[]) 432189251Ssam{ 433189251Ssam char cmd[256]; 434189251Ssam int res; 435189251Ssam 436189251Ssam if (argc != 1) { 437189251Ssam printf("Invalid PREAUTH command: needs one argument " 438189251Ssam "(BSSID)\n"); 439189251Ssam return -1; 440189251Ssam } 441189251Ssam 442189251Ssam res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); 443189251Ssam if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 444189251Ssam printf("Too long PREAUTH command.\n"); 445189251Ssam return -1; 446189251Ssam } 447189251Ssam return wpa_ctrl_command(ctrl, cmd); 448189251Ssam} 449189251Ssam 450189251Ssam 451189251Ssamstatic int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 452189251Ssam{ 453214734Srpaulo char cmd[256]; 454214734Srpaulo int res; 455214734Srpaulo 456214734Srpaulo if (argc != 1) { 457214734Srpaulo printf("Invalid AP_SCAN command: needs one argument (ap_scan " 458214734Srpaulo "value)\n"); 459214734Srpaulo return -1; 460214734Srpaulo } 461214734Srpaulo res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); 462214734Srpaulo if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 463214734Srpaulo printf("Too long AP_SCAN command.\n"); 464214734Srpaulo return -1; 465214734Srpaulo } 466214734Srpaulo return wpa_ctrl_command(ctrl, cmd); 467214734Srpaulo} 468214734Srpaulo 469189251Ssam 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