2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
17 #ifdef CONFIG_CTRL_IFACE
19 #ifdef CONFIG_CTRL_IFACE_UNIX
21 #endif /* CONFIG_CTRL_IFACE_UNIX */
22 #ifdef CONFIG_READLINE
23 #include <readline/readline.h>
24 #include <readline/history.h>
25 #endif /* CONFIG_READLINE */
32 static const char *wpa_cli_version =
33 "wpa_cli v" VERSION_STR "\n"
34 "Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> and contributors";
37 static const char *wpa_cli_license =
38 "This program is free software. You can distribute it and/or modify it\n"
39 "under the terms of the GNU General Public License version 2.\n"
41 "Alternatively, this software may be distributed under the terms of the\n"
42 "BSD license. See README and COPYING for more details.\n";
44 static const char *wpa_cli_full_license =
45 "This program is free software; you can redistribute it and/or modify\n"
46 "it under the terms of the GNU General Public License version 2 as\n"
47 "published by the Free Software Foundation.\n"
49 "This program is distributed in the hope that it will be useful,\n"
50 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
52 "GNU General Public License for more details.\n"
54 "You should have received a copy of the GNU General Public License\n"
55 "along with this program; if not, write to the Free Software\n"
56 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
58 "Alternatively, this software may be distributed under the terms of the\n"
61 "Redistribution and use in source and binary forms, with or without\n"
62 "modification, are permitted provided that the following conditions are\n"
65 "1. Redistributions of source code must retain the above copyright\n"
66 " notice, this list of conditions and the following disclaimer.\n"
68 "2. Redistributions in binary form must reproduce the above copyright\n"
69 " notice, this list of conditions and the following disclaimer in the\n"
70 " documentation and/or other materials provided with the distribution.\n"
72 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73 " names of its contributors may be used to endorse or promote products\n"
74 " derived from this software without specific prior written permission.\n"
76 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
89 static const char *commands_help =
91 " status [verbose] = get current WPA/EAPOL/EAP status\n"
92 " mib = get MIB variables (dot1x, dot11)\n"
93 " help = show this usage help\n"
94 " interface [ifname] = show interfaces/select interface\n"
95 " level <debug level> = change debug level\n"
96 " license = show full wpa_cli license\n"
97 " logoff = IEEE 802.1X EAPOL state machine logoff\n"
98 " logon = IEEE 802.1X EAPOL state machine logon\n"
99 " set = set variables (shows list of variables when run without arguments)\n"
100 " pmksa = show PMKSA cache\n"
101 " reassociate = force reassociation\n"
102 " reconfigure = force wpa_supplicant to re-read its configuration file\n"
103 " preauthenticate <BSSID> = force preauthentication\n"
104 " identity <network id> <identity> = configure identity for an SSID\n"
105 " password <network id> <password> = configure password for an SSID\n"
106 " new_password <network id> <password> = change password for an SSID\n"
107 " pin <network id> <pin> = configure pin for an SSID\n"
108 " otp <network id> <password> = configure one-time-password for an SSID\n"
109 " passphrase <network id> <passphrase> = configure private key passphrase\n"
111 " bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
112 " list_networks = list configured networks\n"
113 " select_network <network id> = select a network (disable others)\n"
114 " enable_network <network id> = enable a network\n"
115 " disable_network <network id> = disable a network\n"
116 " add_network = add a network\n"
117 " remove_network <network id> = remove a network\n"
118 " set_network <network id> <variable> <value> = set network variables "
120 " list of variables when run without arguments)\n"
121 " get_network <network id> <variable> = get network variables\n"
122 " save_config = save the current configuration\n"
123 " disconnect = disconnect and wait for reassociate/reconnect command before\n "
125 " reconnect = like reassociate, but only takes effect if already "
127 " scan = request new BSS scan\n"
128 " scan_results = get latest scan results\n"
129 " bss <<idx> | <bssid>> = get detailed scan result info\n"
130 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
132 " ap_scan <value> = set ap_scan parameter\n"
133 " stkstart <addr> = request STK negotiation with <addr>\n"
134 " ft_ds <addr> = request over-the-DS FT with <addr>\n"
135 " terminate = terminate wpa_supplicant\n"
136 " quit = exit wpa_cli\n";
138 static struct wpa_ctrl *ctrl_conn;
139 static int wpa_cli_quit = 0;
140 static int wpa_cli_attached = 0;
141 static int wpa_cli_connected = 0;
142 static int wpa_cli_last_id = 0;
143 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
144 static char *ctrl_ifname = NULL;
145 static const char *pid_file = NULL;
146 static const char *action_file = NULL;
149 static void usage(void)
151 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
152 "[-a<action file>] \\\n"
153 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
154 " -h = help (show this usage text)\n"
155 " -v = shown version information\n"
156 " -a = run in daemon mode executing the action file based on "
159 " -B = run a daemon in the background\n"
160 " default path: /var/run/wpa_supplicant\n"
161 " default interface: first interface found in socket path\n"
167 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
169 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
170 ctrl_conn = wpa_ctrl_open(ifname);
172 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
179 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
180 cfile = os_malloc(flen);
183 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
184 if (res < 0 || res >= flen) {
189 ctrl_conn = wpa_ctrl_open(cfile);
192 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
196 static void wpa_cli_close_connection(void)
198 if (ctrl_conn == NULL)
201 if (wpa_cli_attached) {
202 wpa_ctrl_detach(ctrl_conn);
203 wpa_cli_attached = 0;
205 wpa_ctrl_close(ctrl_conn);
210 static void wpa_cli_msg_cb(char *msg, size_t len)
216 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
222 if (ctrl_conn == NULL) {
223 printf("Not connected to wpa_supplicant - command dropped.\n");
226 len = sizeof(buf) - 1;
227 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
230 printf("'%s' command timed out.\n", cmd);
232 } else if (ret < 0) {
233 printf("'%s' command failed.\n", cmd);
244 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
246 return _wpa_ctrl_command(ctrl, cmd, 1);
250 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
252 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
253 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
257 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
259 return wpa_ctrl_command(ctrl, "PING");
263 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
265 return wpa_ctrl_command(ctrl, "MIB");
269 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
271 return wpa_ctrl_command(ctrl, "PMKSA");
275 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
277 printf("%s", commands_help);
282 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
284 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
289 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
296 static void wpa_cli_show_variables(void)
298 printf("set variables:\n"
299 " EAPOL::heldPeriod (EAPOL state machine held period, "
301 " EAPOL::authPeriod (EAPOL state machine authentication "
302 "period, in seconds)\n"
303 " EAPOL::startPeriod (EAPOL state machine start period, in "
305 " EAPOL::maxStart (EAPOL state machine maximum start "
307 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
309 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
310 " threshold\n\tpercentage)\n"
311 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
312 "security\n\tassociation in seconds)\n");
316 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
322 wpa_cli_show_variables();
327 printf("Invalid SET command: needs two arguments (variable "
328 "name and value)\n");
332 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
333 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
334 printf("Too long SET command.\n");
337 return wpa_ctrl_command(ctrl, cmd);
341 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
343 return wpa_ctrl_command(ctrl, "LOGOFF");
347 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
349 return wpa_ctrl_command(ctrl, "LOGON");
353 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
356 return wpa_ctrl_command(ctrl, "REASSOCIATE");
360 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
367 printf("Invalid PREAUTH command: needs one argument "
372 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
373 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
374 printf("Too long PREAUTH command.\n");
377 return wpa_ctrl_command(ctrl, cmd);
381 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
387 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
391 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
392 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
393 printf("Too long AP_SCAN command.\n");
396 return wpa_ctrl_command(ctrl, cmd);
400 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
407 printf("Invalid STKSTART command: needs one argument "
408 "(Peer STA MAC address)\n");
412 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
413 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
414 printf("Too long STKSTART command.\n");
417 return wpa_ctrl_command(ctrl, cmd);
421 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
427 printf("Invalid FT_DS command: needs one argument "
428 "(Target AP MAC address)\n");
432 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
433 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
434 printf("Too long FT_DS command.\n");
437 return wpa_ctrl_command(ctrl, cmd);
441 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
447 printf("Invalid LEVEL command: needs one argument (debug "
451 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
452 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
453 printf("Too long LEVEL command.\n");
456 return wpa_ctrl_command(ctrl, cmd);
460 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
462 char cmd[256], *pos, *end;
466 printf("Invalid IDENTITY command: needs two arguments "
467 "(network id and identity)\n");
471 end = cmd + sizeof(cmd);
473 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
475 if (ret < 0 || ret >= end - pos) {
476 printf("Too long IDENTITY command.\n");
480 for (i = 2; i < argc; i++) {
481 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
482 if (ret < 0 || ret >= end - pos) {
483 printf("Too long IDENTITY command.\n");
489 return wpa_ctrl_command(ctrl, cmd);
493 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
495 char cmd[256], *pos, *end;
499 printf("Invalid PASSWORD command: needs two arguments "
500 "(network id and password)\n");
504 end = cmd + sizeof(cmd);
506 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
508 if (ret < 0 || ret >= end - pos) {
509 printf("Too long PASSWORD command.\n");
513 for (i = 2; i < argc; i++) {
514 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
515 if (ret < 0 || ret >= end - pos) {
516 printf("Too long PASSWORD command.\n");
522 return wpa_ctrl_command(ctrl, cmd);
526 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
529 char cmd[256], *pos, *end;
533 printf("Invalid NEW_PASSWORD command: needs two arguments "
534 "(network id and password)\n");
538 end = cmd + sizeof(cmd);
540 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
542 if (ret < 0 || ret >= end - pos) {
543 printf("Too long NEW_PASSWORD command.\n");
547 for (i = 2; i < argc; i++) {
548 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
549 if (ret < 0 || ret >= end - pos) {
550 printf("Too long NEW_PASSWORD command.\n");
556 return wpa_ctrl_command(ctrl, cmd);
560 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
562 char cmd[256], *pos, *end;
566 printf("Invalid PIN command: needs two arguments "
567 "(network id and pin)\n");
571 end = cmd + sizeof(cmd);
573 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
575 if (ret < 0 || ret >= end - pos) {
576 printf("Too long PIN command.\n");
580 for (i = 2; i < argc; i++) {
581 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
582 if (ret < 0 || ret >= end - pos) {
583 printf("Too long PIN command.\n");
588 return wpa_ctrl_command(ctrl, cmd);
592 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
594 char cmd[256], *pos, *end;
598 printf("Invalid OTP command: needs two arguments (network "
599 "id and password)\n");
603 end = cmd + sizeof(cmd);
605 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
607 if (ret < 0 || ret >= end - pos) {
608 printf("Too long OTP command.\n");
612 for (i = 2; i < argc; i++) {
613 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
614 if (ret < 0 || ret >= end - pos) {
615 printf("Too long OTP command.\n");
621 return wpa_ctrl_command(ctrl, cmd);
625 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
628 char cmd[256], *pos, *end;
632 printf("Invalid PASSPHRASE command: needs two arguments "
633 "(network id and passphrase)\n");
637 end = cmd + sizeof(cmd);
639 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
641 if (ret < 0 || ret >= end - pos) {
642 printf("Too long PASSPHRASE command.\n");
646 for (i = 2; i < argc; i++) {
647 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
648 if (ret < 0 || ret >= end - pos) {
649 printf("Too long PASSPHRASE command.\n");
655 return wpa_ctrl_command(ctrl, cmd);
659 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
661 char cmd[256], *pos, *end;
665 printf("Invalid BSSID command: needs two arguments (network "
670 end = cmd + sizeof(cmd);
672 ret = os_snprintf(pos, end - pos, "BSSID");
673 if (ret < 0 || ret >= end - pos) {
674 printf("Too long BSSID command.\n");
678 for (i = 0; i < argc; i++) {
679 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
680 if (ret < 0 || ret >= end - pos) {
681 printf("Too long BSSID command.\n");
687 return wpa_ctrl_command(ctrl, cmd);
691 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
694 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
698 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
705 printf("Invalid SELECT_NETWORK command: needs one argument "
710 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
711 if (res < 0 || (size_t) res >= sizeof(cmd))
713 cmd[sizeof(cmd) - 1] = '\0';
715 return wpa_ctrl_command(ctrl, cmd);
719 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
726 printf("Invalid ENABLE_NETWORK command: needs one argument "
731 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
732 if (res < 0 || (size_t) res >= sizeof(cmd))
734 cmd[sizeof(cmd) - 1] = '\0';
736 return wpa_ctrl_command(ctrl, cmd);
740 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
747 printf("Invalid DISABLE_NETWORK command: needs one argument "
752 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
753 if (res < 0 || (size_t) res >= sizeof(cmd))
755 cmd[sizeof(cmd) - 1] = '\0';
757 return wpa_ctrl_command(ctrl, cmd);
761 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
764 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
768 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
775 printf("Invalid REMOVE_NETWORK command: needs one argument "
780 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
781 if (res < 0 || (size_t) res >= sizeof(cmd))
783 cmd[sizeof(cmd) - 1] = '\0';
785 return wpa_ctrl_command(ctrl, cmd);
789 static void wpa_cli_show_network_variables(void)
791 printf("set_network variables:\n"
792 " ssid (network name, SSID)\n"
793 " psk (WPA passphrase or pre-shared key)\n"
794 " key_mgmt (key management protocol)\n"
795 " identity (EAP identity)\n"
796 " password (EAP password)\n"
799 "Note: Values are entered in the same format as the "
800 "configuration file is using,\n"
801 "i.e., strings values need to be inside double quotation "
803 "For example: set_network 1 ssid \"network name\"\n"
805 "Please see wpa_supplicant.conf documentation for full list "
806 "of\navailable variables.\n");
810 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
817 wpa_cli_show_network_variables();
822 printf("Invalid SET_NETWORK command: needs three arguments\n"
823 "(network id, variable name, and value)\n");
827 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
828 argv[0], argv[1], argv[2]);
829 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
830 printf("Too long SET_NETWORK command.\n");
833 return wpa_ctrl_command(ctrl, cmd);
837 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
844 wpa_cli_show_network_variables();
849 printf("Invalid GET_NETWORK command: needs two arguments\n"
850 "(network id and variable name)\n");
854 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
856 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857 printf("Too long GET_NETWORK command.\n");
860 return wpa_ctrl_command(ctrl, cmd);
864 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
867 return wpa_ctrl_command(ctrl, "DISCONNECT");
871 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
874 return wpa_ctrl_command(ctrl, "RECONNECT");
878 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
881 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
885 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
887 return wpa_ctrl_command(ctrl, "SCAN");
891 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
894 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
898 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
904 printf("Invalid BSS command: need one argument (index or "
909 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
910 if (res < 0 || (size_t) res >= sizeof(cmd))
912 cmd[sizeof(cmd) - 1] = '\0';
914 return wpa_ctrl_command(ctrl, cmd);
918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
924 if (argc < 1 || argc > 2) {
925 printf("Invalid GET_CAPABILITY command: need either one or "
930 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
931 printf("Invalid GET_CAPABILITY command: second argument, "
932 "if any, must be 'strict'\n");
936 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
937 (argc == 2) ? " strict" : "");
938 if (res < 0 || (size_t) res >= sizeof(cmd))
940 cmd[sizeof(cmd) - 1] = '\0';
942 return wpa_ctrl_command(ctrl, cmd);
946 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
948 printf("Available interfaces:\n");
949 return wpa_ctrl_command(ctrl, "INTERFACES");
953 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
956 wpa_cli_list_interfaces(ctrl);
960 wpa_cli_close_connection();
961 os_free(ctrl_ifname);
962 ctrl_ifname = os_strdup(argv[0]);
964 if (wpa_cli_open_connection(ctrl_ifname)) {
965 printf("Connected to interface '%s.\n", ctrl_ifname);
966 if (wpa_ctrl_attach(ctrl_conn) == 0) {
967 wpa_cli_attached = 1;
969 printf("Warning: Failed to attach to "
970 "wpa_supplicant.\n");
973 printf("Could not connect to interface '%s' - re-trying\n",
980 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
983 return wpa_ctrl_command(ctrl, "RECONFIGURE");
987 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
990 return wpa_ctrl_command(ctrl, "TERMINATE");
994 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1001 printf("Invalid INTERFACE_ADD command: needs at least one "
1002 "argument (interface name)\n"
1003 "All arguments: ifname confname driver ctrl_interface "
1004 "driver_param bridge_name\n");
1009 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1010 * <driver_param>TAB<bridge_name>
1012 res = os_snprintf(cmd, sizeof(cmd),
1013 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1015 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1016 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1017 argc > 5 ? argv[5] : "");
1018 if (res < 0 || (size_t) res >= sizeof(cmd))
1020 cmd[sizeof(cmd) - 1] = '\0';
1021 return wpa_ctrl_command(ctrl, cmd);
1025 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1032 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1033 "(interface name)\n");
1037 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1038 if (res < 0 || (size_t) res >= sizeof(cmd))
1040 cmd[sizeof(cmd) - 1] = '\0';
1041 return wpa_ctrl_command(ctrl, cmd);
1045 struct wpa_cli_cmd {
1047 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1050 static struct wpa_cli_cmd wpa_cli_commands[] = {
1051 { "status", wpa_cli_cmd_status },
1052 { "ping", wpa_cli_cmd_ping },
1053 { "mib", wpa_cli_cmd_mib },
1054 { "help", wpa_cli_cmd_help },
1055 { "interface", wpa_cli_cmd_interface },
1056 { "level", wpa_cli_cmd_level },
1057 { "license", wpa_cli_cmd_license },
1058 { "quit", wpa_cli_cmd_quit },
1059 { "set", wpa_cli_cmd_set },
1060 { "logon", wpa_cli_cmd_logon },
1061 { "logoff", wpa_cli_cmd_logoff },
1062 { "pmksa", wpa_cli_cmd_pmksa },
1063 { "reassociate", wpa_cli_cmd_reassociate },
1064 { "preauthenticate", wpa_cli_cmd_preauthenticate },
1065 { "identity", wpa_cli_cmd_identity },
1066 { "password", wpa_cli_cmd_password },
1067 { "new_password", wpa_cli_cmd_new_password },
1068 { "pin", wpa_cli_cmd_pin },
1069 { "otp", wpa_cli_cmd_otp },
1070 { "passphrase", wpa_cli_cmd_passphrase },
1071 { "bssid", wpa_cli_cmd_bssid },
1072 { "list_networks", wpa_cli_cmd_list_networks },
1073 { "select_network", wpa_cli_cmd_select_network },
1074 { "enable_network", wpa_cli_cmd_enable_network },
1075 { "disable_network", wpa_cli_cmd_disable_network },
1076 { "add_network", wpa_cli_cmd_add_network },
1077 { "remove_network", wpa_cli_cmd_remove_network },
1078 { "set_network", wpa_cli_cmd_set_network },
1079 { "get_network", wpa_cli_cmd_get_network },
1080 { "save_config", wpa_cli_cmd_save_config },
1081 { "disconnect", wpa_cli_cmd_disconnect },
1082 { "reconnect", wpa_cli_cmd_reconnect },
1083 { "scan", wpa_cli_cmd_scan },
1084 { "scan_results", wpa_cli_cmd_scan_results },
1085 { "bss", wpa_cli_cmd_bss },
1086 { "get_capability", wpa_cli_cmd_get_capability },
1087 { "reconfigure", wpa_cli_cmd_reconfigure },
1088 { "terminate", wpa_cli_cmd_terminate },
1089 { "interface_add", wpa_cli_cmd_interface_add },
1090 { "interface_remove", wpa_cli_cmd_interface_remove },
1091 { "ap_scan", wpa_cli_cmd_ap_scan },
1092 { "stkstart", wpa_cli_cmd_stkstart },
1093 { "ft_ds", wpa_cli_cmd_ft_ds },
1098 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1100 struct wpa_cli_cmd *cmd, *match = NULL;
1105 cmd = wpa_cli_commands;
1107 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1110 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1111 /* we have an exact match */
1121 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1122 cmd = wpa_cli_commands;
1124 if (os_strncasecmp(cmd->cmd, argv[0],
1125 os_strlen(argv[0])) == 0) {
1126 printf(" %s", cmd->cmd);
1132 } else if (count == 0) {
1133 printf("Unknown command '%s'\n", argv[0]);
1136 ret = match->handler(ctrl, argc - 1, &argv[1]);
1143 static int str_match(const char *a, const char *b)
1145 return os_strncmp(a, b, os_strlen(b)) == 0;
1149 static int wpa_cli_exec(const char *program, const char *arg1,
1157 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1158 cmd = os_malloc(len);
1161 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1162 if (res < 0 || (size_t) res >= len) {
1166 cmd[len - 1] = '\0';
1168 if (system(cmd) < 0)
1170 #endif /* _WIN32_WCE */
1177 static void wpa_cli_action_process(const char *msg)
1180 char *copy = NULL, *id, *pos2;
1185 pos = os_strchr(pos, '>');
1192 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1194 os_unsetenv("WPA_ID");
1195 os_unsetenv("WPA_ID_STR");
1196 os_unsetenv("WPA_CTRL_DIR");
1198 pos = os_strstr(pos, "[id=");
1200 copy = os_strdup(pos + 4);
1204 while (*pos2 && *pos2 != ' ')
1208 os_setenv("WPA_ID", id, 1);
1209 while (*pos2 && *pos2 != '=')
1214 while (*pos2 && *pos2 != ']')
1217 os_setenv("WPA_ID_STR", id, 1);
1221 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1223 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1224 wpa_cli_connected = 1;
1225 wpa_cli_last_id = new_id;
1226 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1228 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1229 if (wpa_cli_connected) {
1230 wpa_cli_connected = 0;
1231 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1233 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1234 printf("wpa_supplicant is terminating - stop monitoring\n");
1240 #ifndef CONFIG_ANSI_C_EXTRA
1241 static void wpa_cli_action_cb(char *msg, size_t len)
1243 wpa_cli_action_process(msg);
1245 #endif /* CONFIG_ANSI_C_EXTRA */
1248 static void wpa_cli_reconnect(void)
1250 wpa_cli_close_connection();
1251 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1253 printf("Connection to wpa_supplicant re-established\n");
1254 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1255 wpa_cli_attached = 1;
1257 printf("Warning: Failed to attach to "
1258 "wpa_supplicant.\n");
1264 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1268 if (ctrl_conn == NULL) {
1269 wpa_cli_reconnect();
1272 while (wpa_ctrl_pending(ctrl) > 0) {
1274 size_t len = sizeof(buf) - 1;
1275 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1278 wpa_cli_action_process(buf);
1280 if (in_read && first)
1283 printf("%s\n", buf);
1286 printf("Could not read pending message.\n");
1291 if (wpa_ctrl_pending(ctrl) < 0) {
1292 printf("Connection to wpa_supplicant lost - trying to "
1294 wpa_cli_reconnect();
1299 #ifdef CONFIG_READLINE
1300 static char * wpa_cli_cmd_gen(const char *text, int state)
1307 len = os_strlen(text);
1310 while ((cmd = wpa_cli_commands[i].cmd)) {
1312 if (os_strncasecmp(cmd, text, len) == 0)
1313 return os_strdup(cmd);
1320 static char * wpa_cli_dummy_gen(const char *text, int state)
1326 static char ** wpa_cli_completion(const char *text, int start, int end)
1328 return rl_completion_matches(text, start == 0 ?
1329 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1331 #endif /* CONFIG_READLINE */
1334 static void wpa_cli_interactive(void)
1337 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1339 #ifdef CONFIG_READLINE
1340 char *home, *hfile = NULL;
1341 #endif /* CONFIG_READLINE */
1343 printf("\nInteractive mode\n\n");
1345 #ifdef CONFIG_READLINE
1346 rl_attempted_completion_function = wpa_cli_completion;
1347 home = getenv("HOME");
1349 const char *fname = ".wpa_cli_history";
1350 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1351 hfile = os_malloc(hfile_len);
1354 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1356 if (res >= 0 && res < hfile_len) {
1357 hfile[hfile_len - 1] = '\0';
1358 read_history(hfile);
1359 stifle_history(100);
1363 #endif /* CONFIG_READLINE */
1366 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1367 #ifndef CONFIG_NATIVE_WINDOWS
1369 #endif /* CONFIG_NATIVE_WINDOWS */
1370 #ifdef CONFIG_READLINE
1371 cmd = readline("> ");
1374 while (next_history())
1376 h = previous_history();
1377 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1381 #else /* CONFIG_READLINE */
1383 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1384 #endif /* CONFIG_READLINE */
1385 #ifndef CONFIG_NATIVE_WINDOWS
1387 #endif /* CONFIG_NATIVE_WINDOWS */
1390 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1392 while (*pos != '\0') {
1408 if (argc == max_args)
1411 char *pos2 = os_strrchr(pos, '"');
1415 while (*pos != '\0' && *pos != ' ')
1421 wpa_request(ctrl_conn, argc, argv);
1425 } while (!wpa_cli_quit);
1427 #ifdef CONFIG_READLINE
1429 /* Save command history, excluding lines that may contain
1436 while (*p == ' ' || *p == '\t')
1438 if (os_strncasecmp(p, "pa", 2) == 0 ||
1439 os_strncasecmp(p, "o", 1) == 0 ||
1440 os_strncasecmp(p, "n", 1)) {
1441 h = remove_history(where_history());
1447 h = current_history();
1452 write_history(hfile);
1455 #endif /* CONFIG_READLINE */
1459 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1461 #ifdef CONFIG_ANSI_C_EXTRA
1462 /* TODO: ANSI C version(?) */
1463 printf("Action processing not supported in ANSI C build.\n");
1464 #else /* CONFIG_ANSI_C_EXTRA */
1468 char buf[256]; /* note: large enough to fit in unsolicited messages */
1471 fd = wpa_ctrl_get_fd(ctrl);
1473 while (!wpa_cli_quit) {
1478 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1479 if (res < 0 && errno != EINTR) {
1484 if (FD_ISSET(fd, &rfds))
1485 wpa_cli_recv_pending(ctrl, 0, 1);
1487 /* verify that connection is still working */
1488 len = sizeof(buf) - 1;
1489 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1490 wpa_cli_action_cb) < 0 ||
1491 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1492 printf("wpa_supplicant did not reply to PING "
1493 "command - exiting\n");
1498 #endif /* CONFIG_ANSI_C_EXTRA */
1502 static void wpa_cli_cleanup(void)
1504 wpa_cli_close_connection();
1506 os_daemonize_terminate(pid_file);
1508 os_program_deinit();
1511 static void wpa_cli_terminate(int sig)
1518 #ifndef CONFIG_NATIVE_WINDOWS
1519 static void wpa_cli_alarm(int sig)
1521 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1522 printf("Connection to wpa_supplicant lost - trying to "
1524 wpa_cli_close_connection();
1527 wpa_cli_reconnect();
1529 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1532 #endif /* CONFIG_NATIVE_WINDOWS */
1535 static char * wpa_cli_get_default_ifname(void)
1537 char *ifname = NULL;
1539 #ifdef CONFIG_CTRL_IFACE_UNIX
1540 struct dirent *dent;
1541 DIR *dir = opendir(ctrl_iface_dir);
1544 while ((dent = readdir(dir))) {
1545 #ifdef _DIRENT_HAVE_D_TYPE
1547 * Skip the file if it is not a socket. Also accept
1548 * DT_UNKNOWN (0) in case the C library or underlying
1549 * file system does not support d_type.
1551 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1553 #endif /* _DIRENT_HAVE_D_TYPE */
1554 if (os_strcmp(dent->d_name, ".") == 0 ||
1555 os_strcmp(dent->d_name, "..") == 0)
1557 printf("Selected interface '%s'\n", dent->d_name);
1558 ifname = os_strdup(dent->d_name);
1562 #endif /* CONFIG_CTRL_IFACE_UNIX */
1564 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1565 char buf[2048], *pos;
1567 struct wpa_ctrl *ctrl;
1570 ctrl = wpa_ctrl_open(NULL);
1574 len = sizeof(buf) - 1;
1575 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1578 pos = os_strchr(buf, '\n');
1581 ifname = os_strdup(buf);
1583 wpa_ctrl_close(ctrl);
1584 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1590 int main(int argc, char *argv[])
1593 int warning_displayed = 0;
1597 const char *global = NULL;
1599 if (os_program_init())
1603 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1608 action_file = optarg;
1620 printf("%s\n", wpa_cli_version);
1623 os_free(ctrl_ifname);
1624 ctrl_ifname = os_strdup(optarg);
1627 ctrl_iface_dir = optarg;
1638 interactive = (argc == optind) && (action_file == NULL);
1641 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1644 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1645 ctrl_conn = wpa_ctrl_open(NULL);
1646 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1647 ctrl_conn = wpa_ctrl_open(global);
1648 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1649 if (ctrl_conn == NULL) {
1650 perror("Failed to connect to wpa_supplicant - "
1657 if (ctrl_ifname == NULL)
1658 ctrl_ifname = wpa_cli_get_default_ifname();
1659 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1661 if (warning_displayed)
1662 printf("Connection established.\n");
1667 perror("Failed to connect to wpa_supplicant - "
1672 if (!warning_displayed) {
1673 printf("Could not connect to wpa_supplicant - "
1675 warning_displayed = 1;
1682 signal(SIGINT, wpa_cli_terminate);
1683 signal(SIGTERM, wpa_cli_terminate);
1684 #endif /* _WIN32_WCE */
1685 #ifndef CONFIG_NATIVE_WINDOWS
1686 signal(SIGALRM, wpa_cli_alarm);
1687 #endif /* CONFIG_NATIVE_WINDOWS */
1689 if (interactive || action_file) {
1690 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1691 wpa_cli_attached = 1;
1693 printf("Warning: Failed to attach to "
1694 "wpa_supplicant.\n");
1700 if (daemonize && os_daemonize(pid_file))
1704 wpa_cli_interactive();
1705 else if (action_file)
1706 wpa_cli_action(ctrl_conn);
1708 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1710 os_free(ctrl_ifname);
1716 #else /* CONFIG_CTRL_IFACE */
1717 int main(int argc, char *argv[])
1719 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1722 #endif /* CONFIG_CTRL_IFACE */