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 " wps_pbc [BSSID] = start Wi-Fi Protected Setup: Push Button Configuration\n"
136 " wps_pin <BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
138 " wps_reg <BSSID> <AP PIN> = start WPS Registrar to configure an AP\n"
139 " terminate = terminate wpa_supplicant\n"
140 " quit = exit wpa_cli\n";
142 static struct wpa_ctrl *ctrl_conn;
143 static int wpa_cli_quit = 0;
144 static int wpa_cli_attached = 0;
145 static int wpa_cli_connected = 0;
146 static int wpa_cli_last_id = 0;
147 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
148 static char *ctrl_ifname = NULL;
149 static const char *pid_file = NULL;
150 static const char *action_file = NULL;
153 static void usage(void)
155 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
156 "[-a<action file>] \\\n"
157 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
158 " -h = help (show this usage text)\n"
159 " -v = shown version information\n"
160 " -a = run in daemon mode executing the action file based on "
163 " -B = run a daemon in the background\n"
164 " default path: /var/run/wpa_supplicant\n"
165 " default interface: first interface found in socket path\n"
171 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
173 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
174 ctrl_conn = wpa_ctrl_open(ifname);
176 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
183 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
184 cfile = os_malloc(flen);
187 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
188 if (res < 0 || res >= flen) {
193 ctrl_conn = wpa_ctrl_open(cfile);
196 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
200 static void wpa_cli_close_connection(void)
202 if (ctrl_conn == NULL)
205 if (wpa_cli_attached) {
206 wpa_ctrl_detach(ctrl_conn);
207 wpa_cli_attached = 0;
209 wpa_ctrl_close(ctrl_conn);
214 static void wpa_cli_msg_cb(char *msg, size_t len)
220 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
226 if (ctrl_conn == NULL) {
227 printf("Not connected to wpa_supplicant - command dropped.\n");
230 len = sizeof(buf) - 1;
231 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
234 printf("'%s' command timed out.\n", cmd);
236 } else if (ret < 0) {
237 printf("'%s' command failed.\n", cmd);
248 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
250 return _wpa_ctrl_command(ctrl, cmd, 1);
254 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
256 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
257 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
261 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
263 return wpa_ctrl_command(ctrl, "PING");
267 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
269 return wpa_ctrl_command(ctrl, "MIB");
273 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
275 return wpa_ctrl_command(ctrl, "PMKSA");
279 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
281 printf("%s", commands_help);
286 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
288 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
293 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
300 static void wpa_cli_show_variables(void)
302 printf("set variables:\n"
303 " EAPOL::heldPeriod (EAPOL state machine held period, "
305 " EAPOL::authPeriod (EAPOL state machine authentication "
306 "period, in seconds)\n"
307 " EAPOL::startPeriod (EAPOL state machine start period, in "
309 " EAPOL::maxStart (EAPOL state machine maximum start "
311 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
313 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
314 " threshold\n\tpercentage)\n"
315 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
316 "security\n\tassociation in seconds)\n");
320 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
326 wpa_cli_show_variables();
331 printf("Invalid SET command: needs two arguments (variable "
332 "name and value)\n");
336 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
337 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
338 printf("Too long SET command.\n");
341 return wpa_ctrl_command(ctrl, cmd);
345 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
347 return wpa_ctrl_command(ctrl, "LOGOFF");
351 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
353 return wpa_ctrl_command(ctrl, "LOGON");
357 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
360 return wpa_ctrl_command(ctrl, "REASSOCIATE");
364 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
371 printf("Invalid PREAUTH command: needs one argument "
376 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
377 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
378 printf("Too long PREAUTH command.\n");
381 return wpa_ctrl_command(ctrl, cmd);
385 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
391 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
395 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
396 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
397 printf("Too long AP_SCAN command.\n");
400 return wpa_ctrl_command(ctrl, cmd);
404 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
411 printf("Invalid STKSTART command: needs one argument "
412 "(Peer STA MAC address)\n");
416 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
417 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
418 printf("Too long STKSTART command.\n");
421 return wpa_ctrl_command(ctrl, cmd);
425 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
431 printf("Invalid FT_DS command: needs one argument "
432 "(Target AP MAC address)\n");
436 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
437 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
438 printf("Too long FT_DS command.\n");
441 return wpa_ctrl_command(ctrl, cmd);
445 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
452 return wpa_ctrl_command(ctrl, "WPS_PBC");
456 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
457 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
458 printf("Too long WPS_PBC command.\n");
461 return wpa_ctrl_command(ctrl, cmd);
465 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
471 printf("Invalid WPS_PIN command: need one or two arguments:\n"
472 "- BSSID: use 'any' to select any\n"
473 "- PIN: optional, used only with devices that have no "
479 /* Use dynamically generated PIN (returned as reply) */
480 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
481 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
482 printf("Too long WPS_PIN command.\n");
485 return wpa_ctrl_command(ctrl, cmd);
488 /* Use hardcoded PIN from a label */
489 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
490 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
491 printf("Too long WPS_PIN command.\n");
494 return wpa_ctrl_command(ctrl, cmd);
498 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
504 printf("Invalid WPS_REG command: need two arguments:\n"
505 "- BSSID: use 'any' to select any\n"
510 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
511 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
512 printf("Too long WPS_REG command.\n");
515 return wpa_ctrl_command(ctrl, cmd);
519 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
525 printf("Invalid LEVEL command: needs one argument (debug "
529 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
530 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
531 printf("Too long LEVEL command.\n");
534 return wpa_ctrl_command(ctrl, cmd);
538 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
540 char cmd[256], *pos, *end;
544 printf("Invalid IDENTITY command: needs two arguments "
545 "(network id and identity)\n");
549 end = cmd + sizeof(cmd);
551 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
553 if (ret < 0 || ret >= end - pos) {
554 printf("Too long IDENTITY command.\n");
558 for (i = 2; i < argc; i++) {
559 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
560 if (ret < 0 || ret >= end - pos) {
561 printf("Too long IDENTITY command.\n");
567 return wpa_ctrl_command(ctrl, cmd);
571 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
573 char cmd[256], *pos, *end;
577 printf("Invalid PASSWORD command: needs two arguments "
578 "(network id and password)\n");
582 end = cmd + sizeof(cmd);
584 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
586 if (ret < 0 || ret >= end - pos) {
587 printf("Too long PASSWORD command.\n");
591 for (i = 2; i < argc; i++) {
592 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
593 if (ret < 0 || ret >= end - pos) {
594 printf("Too long PASSWORD command.\n");
600 return wpa_ctrl_command(ctrl, cmd);
604 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
607 char cmd[256], *pos, *end;
611 printf("Invalid NEW_PASSWORD command: needs two arguments "
612 "(network id and password)\n");
616 end = cmd + sizeof(cmd);
618 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
620 if (ret < 0 || ret >= end - pos) {
621 printf("Too long NEW_PASSWORD command.\n");
625 for (i = 2; i < argc; i++) {
626 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
627 if (ret < 0 || ret >= end - pos) {
628 printf("Too long NEW_PASSWORD command.\n");
634 return wpa_ctrl_command(ctrl, cmd);
638 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
640 char cmd[256], *pos, *end;
644 printf("Invalid PIN command: needs two arguments "
645 "(network id and pin)\n");
649 end = cmd + sizeof(cmd);
651 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
653 if (ret < 0 || ret >= end - pos) {
654 printf("Too long PIN command.\n");
658 for (i = 2; i < argc; i++) {
659 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
660 if (ret < 0 || ret >= end - pos) {
661 printf("Too long PIN command.\n");
666 return wpa_ctrl_command(ctrl, cmd);
670 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
672 char cmd[256], *pos, *end;
676 printf("Invalid OTP command: needs two arguments (network "
677 "id and password)\n");
681 end = cmd + sizeof(cmd);
683 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
685 if (ret < 0 || ret >= end - pos) {
686 printf("Too long OTP command.\n");
690 for (i = 2; i < argc; i++) {
691 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
692 if (ret < 0 || ret >= end - pos) {
693 printf("Too long OTP command.\n");
699 return wpa_ctrl_command(ctrl, cmd);
703 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
706 char cmd[256], *pos, *end;
710 printf("Invalid PASSPHRASE command: needs two arguments "
711 "(network id and passphrase)\n");
715 end = cmd + sizeof(cmd);
717 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
719 if (ret < 0 || ret >= end - pos) {
720 printf("Too long PASSPHRASE command.\n");
724 for (i = 2; i < argc; i++) {
725 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
726 if (ret < 0 || ret >= end - pos) {
727 printf("Too long PASSPHRASE command.\n");
733 return wpa_ctrl_command(ctrl, cmd);
737 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
739 char cmd[256], *pos, *end;
743 printf("Invalid BSSID command: needs two arguments (network "
748 end = cmd + sizeof(cmd);
750 ret = os_snprintf(pos, end - pos, "BSSID");
751 if (ret < 0 || ret >= end - pos) {
752 printf("Too long BSSID command.\n");
756 for (i = 0; i < argc; i++) {
757 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
758 if (ret < 0 || ret >= end - pos) {
759 printf("Too long BSSID command.\n");
765 return wpa_ctrl_command(ctrl, cmd);
769 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
772 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
776 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
783 printf("Invalid SELECT_NETWORK command: needs one argument "
788 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
789 if (res < 0 || (size_t) res >= sizeof(cmd))
791 cmd[sizeof(cmd) - 1] = '\0';
793 return wpa_ctrl_command(ctrl, cmd);
797 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
804 printf("Invalid ENABLE_NETWORK command: needs one argument "
809 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
810 if (res < 0 || (size_t) res >= sizeof(cmd))
812 cmd[sizeof(cmd) - 1] = '\0';
814 return wpa_ctrl_command(ctrl, cmd);
818 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
825 printf("Invalid DISABLE_NETWORK command: needs one argument "
830 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
831 if (res < 0 || (size_t) res >= sizeof(cmd))
833 cmd[sizeof(cmd) - 1] = '\0';
835 return wpa_ctrl_command(ctrl, cmd);
839 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
842 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
846 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
853 printf("Invalid REMOVE_NETWORK command: needs one argument "
858 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
859 if (res < 0 || (size_t) res >= sizeof(cmd))
861 cmd[sizeof(cmd) - 1] = '\0';
863 return wpa_ctrl_command(ctrl, cmd);
867 static void wpa_cli_show_network_variables(void)
869 printf("set_network variables:\n"
870 " ssid (network name, SSID)\n"
871 " psk (WPA passphrase or pre-shared key)\n"
872 " key_mgmt (key management protocol)\n"
873 " identity (EAP identity)\n"
874 " password (EAP password)\n"
877 "Note: Values are entered in the same format as the "
878 "configuration file is using,\n"
879 "i.e., strings values need to be inside double quotation "
881 "For example: set_network 1 ssid \"network name\"\n"
883 "Please see wpa_supplicant.conf documentation for full list "
884 "of\navailable variables.\n");
888 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
895 wpa_cli_show_network_variables();
900 printf("Invalid SET_NETWORK command: needs three arguments\n"
901 "(network id, variable name, and value)\n");
905 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
906 argv[0], argv[1], argv[2]);
907 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
908 printf("Too long SET_NETWORK command.\n");
911 return wpa_ctrl_command(ctrl, cmd);
915 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
922 wpa_cli_show_network_variables();
927 printf("Invalid GET_NETWORK command: needs two arguments\n"
928 "(network id and variable name)\n");
932 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
934 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
935 printf("Too long GET_NETWORK command.\n");
938 return wpa_ctrl_command(ctrl, cmd);
942 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
945 return wpa_ctrl_command(ctrl, "DISCONNECT");
949 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
952 return wpa_ctrl_command(ctrl, "RECONNECT");
956 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
959 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
963 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
965 return wpa_ctrl_command(ctrl, "SCAN");
969 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
972 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
976 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
982 printf("Invalid BSS command: need one argument (index or "
987 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
988 if (res < 0 || (size_t) res >= sizeof(cmd))
990 cmd[sizeof(cmd) - 1] = '\0';
992 return wpa_ctrl_command(ctrl, cmd);
996 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1002 if (argc < 1 || argc > 2) {
1003 printf("Invalid GET_CAPABILITY command: need either one or "
1008 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1009 printf("Invalid GET_CAPABILITY command: second argument, "
1010 "if any, must be 'strict'\n");
1014 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1015 (argc == 2) ? " strict" : "");
1016 if (res < 0 || (size_t) res >= sizeof(cmd))
1018 cmd[sizeof(cmd) - 1] = '\0';
1020 return wpa_ctrl_command(ctrl, cmd);
1024 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1026 printf("Available interfaces:\n");
1027 return wpa_ctrl_command(ctrl, "INTERFACES");
1031 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1034 wpa_cli_list_interfaces(ctrl);
1038 wpa_cli_close_connection();
1039 os_free(ctrl_ifname);
1040 ctrl_ifname = os_strdup(argv[0]);
1042 if (wpa_cli_open_connection(ctrl_ifname)) {
1043 printf("Connected to interface '%s.\n", ctrl_ifname);
1044 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1045 wpa_cli_attached = 1;
1047 printf("Warning: Failed to attach to "
1048 "wpa_supplicant.\n");
1051 printf("Could not connect to interface '%s' - re-trying\n",
1058 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1061 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1065 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1068 return wpa_ctrl_command(ctrl, "TERMINATE");
1072 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1079 printf("Invalid INTERFACE_ADD command: needs at least one "
1080 "argument (interface name)\n"
1081 "All arguments: ifname confname driver ctrl_interface "
1082 "driver_param bridge_name\n");
1087 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1088 * <driver_param>TAB<bridge_name>
1090 res = os_snprintf(cmd, sizeof(cmd),
1091 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1093 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1094 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1095 argc > 5 ? argv[5] : "");
1096 if (res < 0 || (size_t) res >= sizeof(cmd))
1098 cmd[sizeof(cmd) - 1] = '\0';
1099 return wpa_ctrl_command(ctrl, cmd);
1103 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1110 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1111 "(interface name)\n");
1115 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1116 if (res < 0 || (size_t) res >= sizeof(cmd))
1118 cmd[sizeof(cmd) - 1] = '\0';
1119 return wpa_ctrl_command(ctrl, cmd);
1123 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1126 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1130 struct wpa_cli_cmd {
1132 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1135 static struct wpa_cli_cmd wpa_cli_commands[] = {
1136 { "status", wpa_cli_cmd_status },
1137 { "ping", wpa_cli_cmd_ping },
1138 { "mib", wpa_cli_cmd_mib },
1139 { "help", wpa_cli_cmd_help },
1140 { "interface", wpa_cli_cmd_interface },
1141 { "level", wpa_cli_cmd_level },
1142 { "license", wpa_cli_cmd_license },
1143 { "quit", wpa_cli_cmd_quit },
1144 { "set", wpa_cli_cmd_set },
1145 { "logon", wpa_cli_cmd_logon },
1146 { "logoff", wpa_cli_cmd_logoff },
1147 { "pmksa", wpa_cli_cmd_pmksa },
1148 { "reassociate", wpa_cli_cmd_reassociate },
1149 { "preauthenticate", wpa_cli_cmd_preauthenticate },
1150 { "identity", wpa_cli_cmd_identity },
1151 { "password", wpa_cli_cmd_password },
1152 { "new_password", wpa_cli_cmd_new_password },
1153 { "pin", wpa_cli_cmd_pin },
1154 { "otp", wpa_cli_cmd_otp },
1155 { "passphrase", wpa_cli_cmd_passphrase },
1156 { "bssid", wpa_cli_cmd_bssid },
1157 { "list_networks", wpa_cli_cmd_list_networks },
1158 { "select_network", wpa_cli_cmd_select_network },
1159 { "enable_network", wpa_cli_cmd_enable_network },
1160 { "disable_network", wpa_cli_cmd_disable_network },
1161 { "add_network", wpa_cli_cmd_add_network },
1162 { "remove_network", wpa_cli_cmd_remove_network },
1163 { "set_network", wpa_cli_cmd_set_network },
1164 { "get_network", wpa_cli_cmd_get_network },
1165 { "save_config", wpa_cli_cmd_save_config },
1166 { "disconnect", wpa_cli_cmd_disconnect },
1167 { "reconnect", wpa_cli_cmd_reconnect },
1168 { "scan", wpa_cli_cmd_scan },
1169 { "scan_results", wpa_cli_cmd_scan_results },
1170 { "bss", wpa_cli_cmd_bss },
1171 { "get_capability", wpa_cli_cmd_get_capability },
1172 { "reconfigure", wpa_cli_cmd_reconfigure },
1173 { "terminate", wpa_cli_cmd_terminate },
1174 { "interface_add", wpa_cli_cmd_interface_add },
1175 { "interface_remove", wpa_cli_cmd_interface_remove },
1176 { "interface_list", wpa_cli_cmd_interface_list },
1177 { "ap_scan", wpa_cli_cmd_ap_scan },
1178 { "stkstart", wpa_cli_cmd_stkstart },
1179 { "ft_ds", wpa_cli_cmd_ft_ds },
1180 { "wps_pbc", wpa_cli_cmd_wps_pbc },
1181 { "wps_pin", wpa_cli_cmd_wps_pin },
1182 { "wps_reg", wpa_cli_cmd_wps_reg },
1187 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1189 struct wpa_cli_cmd *cmd, *match = NULL;
1194 cmd = wpa_cli_commands;
1196 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1199 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1200 /* we have an exact match */
1210 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1211 cmd = wpa_cli_commands;
1213 if (os_strncasecmp(cmd->cmd, argv[0],
1214 os_strlen(argv[0])) == 0) {
1215 printf(" %s", cmd->cmd);
1221 } else if (count == 0) {
1222 printf("Unknown command '%s'\n", argv[0]);
1225 ret = match->handler(ctrl, argc - 1, &argv[1]);
1232 static int str_match(const char *a, const char *b)
1234 return os_strncmp(a, b, os_strlen(b)) == 0;
1238 static int wpa_cli_exec(const char *program, const char *arg1,
1246 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1247 cmd = os_malloc(len);
1250 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1251 if (res < 0 || (size_t) res >= len) {
1255 cmd[len - 1] = '\0';
1257 if (system(cmd) < 0)
1259 #endif /* _WIN32_WCE */
1266 static void wpa_cli_action_process(const char *msg)
1269 char *copy = NULL, *id, *pos2;
1274 pos = os_strchr(pos, '>');
1281 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1283 os_unsetenv("WPA_ID");
1284 os_unsetenv("WPA_ID_STR");
1285 os_unsetenv("WPA_CTRL_DIR");
1287 pos = os_strstr(pos, "[id=");
1289 copy = os_strdup(pos + 4);
1293 while (*pos2 && *pos2 != ' ')
1297 os_setenv("WPA_ID", id, 1);
1298 while (*pos2 && *pos2 != '=')
1303 while (*pos2 && *pos2 != ']')
1306 os_setenv("WPA_ID_STR", id, 1);
1310 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1312 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1313 wpa_cli_connected = 1;
1314 wpa_cli_last_id = new_id;
1315 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1317 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1318 if (wpa_cli_connected) {
1319 wpa_cli_connected = 0;
1320 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1322 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1323 printf("wpa_supplicant is terminating - stop monitoring\n");
1329 #ifndef CONFIG_ANSI_C_EXTRA
1330 static void wpa_cli_action_cb(char *msg, size_t len)
1332 wpa_cli_action_process(msg);
1334 #endif /* CONFIG_ANSI_C_EXTRA */
1337 static void wpa_cli_reconnect(void)
1339 wpa_cli_close_connection();
1340 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1342 printf("Connection to wpa_supplicant re-established\n");
1343 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1344 wpa_cli_attached = 1;
1346 printf("Warning: Failed to attach to "
1347 "wpa_supplicant.\n");
1353 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1357 if (ctrl_conn == NULL) {
1358 wpa_cli_reconnect();
1361 while (wpa_ctrl_pending(ctrl) > 0) {
1363 size_t len = sizeof(buf) - 1;
1364 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1367 wpa_cli_action_process(buf);
1369 if (in_read && first)
1372 printf("%s\n", buf);
1375 printf("Could not read pending message.\n");
1380 if (wpa_ctrl_pending(ctrl) < 0) {
1381 printf("Connection to wpa_supplicant lost - trying to "
1383 wpa_cli_reconnect();
1388 #ifdef CONFIG_READLINE
1389 static char * wpa_cli_cmd_gen(const char *text, int state)
1396 len = os_strlen(text);
1399 while ((cmd = wpa_cli_commands[i].cmd)) {
1401 if (os_strncasecmp(cmd, text, len) == 0)
1402 return os_strdup(cmd);
1409 static char * wpa_cli_dummy_gen(const char *text, int state)
1415 static char ** wpa_cli_completion(const char *text, int start, int end)
1417 return rl_completion_matches(text, start == 0 ?
1418 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1420 #endif /* CONFIG_READLINE */
1423 static void wpa_cli_interactive(void)
1426 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1428 #ifdef CONFIG_READLINE
1429 char *home, *hfile = NULL;
1430 #endif /* CONFIG_READLINE */
1432 printf("\nInteractive mode\n\n");
1434 #ifdef CONFIG_READLINE
1435 rl_attempted_completion_function = wpa_cli_completion;
1436 home = getenv("HOME");
1438 const char *fname = ".wpa_cli_history";
1439 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1440 hfile = os_malloc(hfile_len);
1443 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1445 if (res >= 0 && res < hfile_len) {
1446 hfile[hfile_len - 1] = '\0';
1447 read_history(hfile);
1448 stifle_history(100);
1452 #endif /* CONFIG_READLINE */
1455 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1456 #ifndef CONFIG_NATIVE_WINDOWS
1458 #endif /* CONFIG_NATIVE_WINDOWS */
1459 #ifdef CONFIG_READLINE
1460 cmd = readline("> ");
1463 while (next_history())
1465 h = previous_history();
1466 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1470 #else /* CONFIG_READLINE */
1472 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1473 #endif /* CONFIG_READLINE */
1474 #ifndef CONFIG_NATIVE_WINDOWS
1476 #endif /* CONFIG_NATIVE_WINDOWS */
1479 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1481 while (*pos != '\0') {
1497 if (argc == max_args)
1500 char *pos2 = os_strrchr(pos, '"');
1504 while (*pos != '\0' && *pos != ' ')
1510 wpa_request(ctrl_conn, argc, argv);
1514 } while (!wpa_cli_quit);
1516 #ifdef CONFIG_READLINE
1518 /* Save command history, excluding lines that may contain
1525 while (*p == ' ' || *p == '\t')
1527 if (os_strncasecmp(p, "pa", 2) == 0 ||
1528 os_strncasecmp(p, "o", 1) == 0 ||
1529 os_strncasecmp(p, "n", 1)) {
1530 h = remove_history(where_history());
1536 h = current_history();
1541 write_history(hfile);
1544 #endif /* CONFIG_READLINE */
1548 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1550 #ifdef CONFIG_ANSI_C_EXTRA
1551 /* TODO: ANSI C version(?) */
1552 printf("Action processing not supported in ANSI C build.\n");
1553 #else /* CONFIG_ANSI_C_EXTRA */
1557 char buf[256]; /* note: large enough to fit in unsolicited messages */
1560 fd = wpa_ctrl_get_fd(ctrl);
1562 while (!wpa_cli_quit) {
1567 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1568 if (res < 0 && errno != EINTR) {
1573 if (FD_ISSET(fd, &rfds))
1574 wpa_cli_recv_pending(ctrl, 0, 1);
1576 /* verify that connection is still working */
1577 len = sizeof(buf) - 1;
1578 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1579 wpa_cli_action_cb) < 0 ||
1580 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1581 printf("wpa_supplicant did not reply to PING "
1582 "command - exiting\n");
1587 #endif /* CONFIG_ANSI_C_EXTRA */
1591 static void wpa_cli_cleanup(void)
1593 wpa_cli_close_connection();
1595 os_daemonize_terminate(pid_file);
1597 os_program_deinit();
1600 static void wpa_cli_terminate(int sig)
1607 #ifndef CONFIG_NATIVE_WINDOWS
1608 static void wpa_cli_alarm(int sig)
1610 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1611 printf("Connection to wpa_supplicant lost - trying to "
1613 wpa_cli_close_connection();
1616 wpa_cli_reconnect();
1618 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1621 #endif /* CONFIG_NATIVE_WINDOWS */
1624 static char * wpa_cli_get_default_ifname(void)
1626 char *ifname = NULL;
1628 #ifdef CONFIG_CTRL_IFACE_UNIX
1629 struct dirent *dent;
1630 DIR *dir = opendir(ctrl_iface_dir);
1633 while ((dent = readdir(dir))) {
1634 #ifdef _DIRENT_HAVE_D_TYPE
1636 * Skip the file if it is not a socket. Also accept
1637 * DT_UNKNOWN (0) in case the C library or underlying
1638 * file system does not support d_type.
1640 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1642 #endif /* _DIRENT_HAVE_D_TYPE */
1643 if (os_strcmp(dent->d_name, ".") == 0 ||
1644 os_strcmp(dent->d_name, "..") == 0)
1646 printf("Selected interface '%s'\n", dent->d_name);
1647 ifname = os_strdup(dent->d_name);
1651 #endif /* CONFIG_CTRL_IFACE_UNIX */
1653 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1654 char buf[2048], *pos;
1656 struct wpa_ctrl *ctrl;
1659 ctrl = wpa_ctrl_open(NULL);
1663 len = sizeof(buf) - 1;
1664 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1667 pos = os_strchr(buf, '\n');
1670 ifname = os_strdup(buf);
1672 wpa_ctrl_close(ctrl);
1673 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1679 int main(int argc, char *argv[])
1682 int warning_displayed = 0;
1686 const char *global = NULL;
1688 if (os_program_init())
1692 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1697 action_file = optarg;
1709 printf("%s\n", wpa_cli_version);
1712 os_free(ctrl_ifname);
1713 ctrl_ifname = os_strdup(optarg);
1716 ctrl_iface_dir = optarg;
1727 interactive = (argc == optind) && (action_file == NULL);
1730 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1733 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1734 ctrl_conn = wpa_ctrl_open(NULL);
1735 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1736 ctrl_conn = wpa_ctrl_open(global);
1737 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1738 if (ctrl_conn == NULL) {
1739 perror("Failed to connect to wpa_supplicant - "
1746 if (ctrl_ifname == NULL)
1747 ctrl_ifname = wpa_cli_get_default_ifname();
1748 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1750 if (warning_displayed)
1751 printf("Connection established.\n");
1756 perror("Failed to connect to wpa_supplicant - "
1761 if (!warning_displayed) {
1762 printf("Could not connect to wpa_supplicant - "
1764 warning_displayed = 1;
1771 signal(SIGINT, wpa_cli_terminate);
1772 signal(SIGTERM, wpa_cli_terminate);
1773 #endif /* _WIN32_WCE */
1774 #ifndef CONFIG_NATIVE_WINDOWS
1775 signal(SIGALRM, wpa_cli_alarm);
1776 #endif /* CONFIG_NATIVE_WINDOWS */
1778 if (interactive || action_file) {
1779 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1780 wpa_cli_attached = 1;
1782 printf("Warning: Failed to attach to "
1783 "wpa_supplicant.\n");
1789 if (daemonize && os_daemonize(pid_file))
1793 wpa_cli_interactive();
1794 else if (action_file)
1795 wpa_cli_action(ctrl_conn);
1797 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1799 os_free(ctrl_ifname);
1805 #else /* CONFIG_CTRL_IFACE */
1806 int main(int argc, char *argv[])
1808 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1811 #endif /* CONFIG_CTRL_IFACE */