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 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
131 " ap_scan <value> = set ap_scan parameter\n"
132 " stkstart <addr> = request STK negotiation with <addr>\n"
133 " terminate = terminate wpa_supplicant\n"
134 " quit = exit wpa_cli\n";
136 static struct wpa_ctrl *ctrl_conn;
137 static int wpa_cli_quit = 0;
138 static int wpa_cli_attached = 0;
139 static int wpa_cli_connected = 0;
140 static int wpa_cli_last_id = 0;
141 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
142 static char *ctrl_ifname = NULL;
143 static const char *pid_file = NULL;
144 static const char *action_file = NULL;
147 static void usage(void)
149 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
150 "[-a<action file>] \\\n"
151 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
152 " -h = help (show this usage text)\n"
153 " -v = shown version information\n"
154 " -a = run in daemon mode executing the action file based on "
157 " -B = run a daemon in the background\n"
158 " default path: /var/run/wpa_supplicant\n"
159 " default interface: first interface found in socket path\n"
165 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
167 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
168 ctrl_conn = wpa_ctrl_open(ifname);
170 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
177 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
178 cfile = os_malloc(flen);
181 os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
183 ctrl_conn = wpa_ctrl_open(cfile);
186 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
190 static void wpa_cli_close_connection(void)
192 if (ctrl_conn == NULL)
195 if (wpa_cli_attached) {
196 wpa_ctrl_detach(ctrl_conn);
197 wpa_cli_attached = 0;
199 wpa_ctrl_close(ctrl_conn);
204 static void wpa_cli_msg_cb(char *msg, size_t len)
210 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
216 if (ctrl_conn == NULL) {
217 printf("Not connected to wpa_supplicant - command dropped.\n");
220 len = sizeof(buf) - 1;
221 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
224 printf("'%s' command timed out.\n", cmd);
226 } else if (ret < 0) {
227 printf("'%s' command failed.\n", cmd);
238 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
240 return _wpa_ctrl_command(ctrl, cmd, 1);
244 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
246 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
247 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
251 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
253 return wpa_ctrl_command(ctrl, "PING");
257 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
259 return wpa_ctrl_command(ctrl, "MIB");
263 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
265 return wpa_ctrl_command(ctrl, "PMKSA");
269 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
271 printf("%s", commands_help);
276 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
278 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
283 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
290 static void wpa_cli_show_variables(void)
292 printf("set variables:\n"
293 " EAPOL::heldPeriod (EAPOL state machine held period, "
295 " EAPOL::authPeriod (EAPOL state machine authentication "
296 "period, in seconds)\n"
297 " EAPOL::startPeriod (EAPOL state machine start period, in "
299 " EAPOL::maxStart (EAPOL state machine maximum start "
301 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
303 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
304 " threshold\n\tpercentage)\n"
305 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
306 "security\n\tassociation in seconds)\n");
310 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
316 wpa_cli_show_variables();
321 printf("Invalid SET command: needs two arguments (variable "
322 "name and value)\n");
326 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
327 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
328 printf("Too long SET command.\n");
331 return wpa_ctrl_command(ctrl, cmd);
335 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
337 return wpa_ctrl_command(ctrl, "LOGOFF");
341 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
343 return wpa_ctrl_command(ctrl, "LOGON");
347 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
350 return wpa_ctrl_command(ctrl, "REASSOCIATE");
354 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
361 printf("Invalid PREAUTH command: needs one argument "
366 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
367 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
368 printf("Too long PREAUTH command.\n");
371 return wpa_ctrl_command(ctrl, cmd);
375 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
381 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
385 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
386 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
387 printf("Too long AP_SCAN command.\n");
390 return wpa_ctrl_command(ctrl, cmd);
394 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
401 printf("Invalid STKSTART command: needs one argument "
402 "(Peer STA MAC address)\n");
406 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
407 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
408 printf("Too long STKSTART command.\n");
411 return wpa_ctrl_command(ctrl, cmd);
415 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
421 printf("Invalid LEVEL command: needs one argument (debug "
425 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
426 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
427 printf("Too long LEVEL command.\n");
430 return wpa_ctrl_command(ctrl, cmd);
434 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
436 char cmd[256], *pos, *end;
440 printf("Invalid IDENTITY command: needs two arguments "
441 "(network id and identity)\n");
445 end = cmd + sizeof(cmd);
447 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
449 if (ret < 0 || ret >= end - pos) {
450 printf("Too long IDENTITY command.\n");
454 for (i = 2; i < argc; i++) {
455 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
456 if (ret < 0 || ret >= end - pos) {
457 printf("Too long IDENTITY command.\n");
463 return wpa_ctrl_command(ctrl, cmd);
467 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
469 char cmd[256], *pos, *end;
473 printf("Invalid PASSWORD command: needs two arguments "
474 "(network id and password)\n");
478 end = cmd + sizeof(cmd);
480 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
482 if (ret < 0 || ret >= end - pos) {
483 printf("Too long PASSWORD command.\n");
487 for (i = 2; i < argc; i++) {
488 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
489 if (ret < 0 || ret >= end - pos) {
490 printf("Too long PASSWORD command.\n");
496 return wpa_ctrl_command(ctrl, cmd);
500 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
503 char cmd[256], *pos, *end;
507 printf("Invalid NEW_PASSWORD command: needs two arguments "
508 "(network id and password)\n");
512 end = cmd + sizeof(cmd);
514 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
516 if (ret < 0 || ret >= end - pos) {
517 printf("Too long NEW_PASSWORD command.\n");
521 for (i = 2; i < argc; i++) {
522 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
523 if (ret < 0 || ret >= end - pos) {
524 printf("Too long NEW_PASSWORD command.\n");
530 return wpa_ctrl_command(ctrl, cmd);
534 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
536 char cmd[256], *pos, *end;
540 printf("Invalid PIN command: needs two arguments "
541 "(network id and pin)\n");
545 end = cmd + sizeof(cmd);
547 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
549 if (ret < 0 || ret >= end - pos) {
550 printf("Too long PIN command.\n");
554 for (i = 2; i < argc; i++) {
555 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
556 if (ret < 0 || ret >= end - pos) {
557 printf("Too long PIN command.\n");
562 return wpa_ctrl_command(ctrl, cmd);
566 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
568 char cmd[256], *pos, *end;
572 printf("Invalid OTP command: needs two arguments (network "
573 "id and password)\n");
577 end = cmd + sizeof(cmd);
579 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
581 if (ret < 0 || ret >= end - pos) {
582 printf("Too long OTP command.\n");
586 for (i = 2; i < argc; i++) {
587 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
588 if (ret < 0 || ret >= end - pos) {
589 printf("Too long OTP command.\n");
595 return wpa_ctrl_command(ctrl, cmd);
599 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
602 char cmd[256], *pos, *end;
606 printf("Invalid PASSPHRASE command: needs two arguments "
607 "(network id and passphrase)\n");
611 end = cmd + sizeof(cmd);
613 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
615 if (ret < 0 || ret >= end - pos) {
616 printf("Too long PASSPHRASE command.\n");
620 for (i = 2; i < argc; i++) {
621 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
622 if (ret < 0 || ret >= end - pos) {
623 printf("Too long PASSPHRASE command.\n");
629 return wpa_ctrl_command(ctrl, cmd);
633 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
635 char cmd[256], *pos, *end;
639 printf("Invalid BSSID command: needs two arguments (network "
644 end = cmd + sizeof(cmd);
646 ret = os_snprintf(pos, end - pos, "BSSID");
647 if (ret < 0 || ret >= end - pos) {
648 printf("Too long BSSID command.\n");
652 for (i = 0; i < argc; i++) {
653 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
654 if (ret < 0 || ret >= end - pos) {
655 printf("Too long BSSID command.\n");
661 return wpa_ctrl_command(ctrl, cmd);
665 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
668 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
672 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
678 printf("Invalid SELECT_NETWORK command: needs one argument "
683 os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
684 cmd[sizeof(cmd) - 1] = '\0';
686 return wpa_ctrl_command(ctrl, cmd);
690 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
696 printf("Invalid ENABLE_NETWORK command: needs one argument "
701 os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
702 cmd[sizeof(cmd) - 1] = '\0';
704 return wpa_ctrl_command(ctrl, cmd);
708 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
714 printf("Invalid DISABLE_NETWORK command: needs one argument "
719 os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
720 cmd[sizeof(cmd) - 1] = '\0';
722 return wpa_ctrl_command(ctrl, cmd);
726 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
729 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
733 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
739 printf("Invalid REMOVE_NETWORK command: needs one argument "
744 os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
745 cmd[sizeof(cmd) - 1] = '\0';
747 return wpa_ctrl_command(ctrl, cmd);
751 static void wpa_cli_show_network_variables(void)
753 printf("set_network variables:\n"
754 " ssid (network name, SSID)\n"
755 " psk (WPA passphrase or pre-shared key)\n"
756 " key_mgmt (key management protocol)\n"
757 " identity (EAP identity)\n"
758 " password (EAP password)\n"
761 "Note: Values are entered in the same format as the "
762 "configuration file is using,\n"
763 "i.e., strings values need to be inside double quotation "
765 "For example: set_network 1 ssid \"network name\"\n"
767 "Please see wpa_supplicant.conf documentation for full list "
768 "of\navailable variables.\n");
772 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
779 wpa_cli_show_network_variables();
784 printf("Invalid SET_NETWORK command: needs three arguments\n"
785 "(network id, variable name, and value)\n");
789 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
790 argv[0], argv[1], argv[2]);
791 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
792 printf("Too long SET_NETWORK command.\n");
795 return wpa_ctrl_command(ctrl, cmd);
799 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
806 wpa_cli_show_network_variables();
811 printf("Invalid GET_NETWORK command: needs two arguments\n"
812 "(network id and variable name)\n");
816 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
818 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
819 printf("Too long GET_NETWORK command.\n");
822 return wpa_ctrl_command(ctrl, cmd);
826 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
829 return wpa_ctrl_command(ctrl, "DISCONNECT");
833 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
836 return wpa_ctrl_command(ctrl, "RECONNECT");
840 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
843 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
847 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
849 return wpa_ctrl_command(ctrl, "SCAN");
853 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
856 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
860 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
865 if (argc < 1 || argc > 2) {
866 printf("Invalid GET_CAPABILITY command: need either one or "
871 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
872 printf("Invalid GET_CAPABILITY command: second argument, "
873 "if any, must be 'strict'\n");
877 os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
878 (argc == 2) ? " strict" : "");
879 cmd[sizeof(cmd) - 1] = '\0';
881 return wpa_ctrl_command(ctrl, cmd);
885 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
887 printf("Available interfaces:\n");
888 return wpa_ctrl_command(ctrl, "INTERFACES");
892 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
895 wpa_cli_list_interfaces(ctrl);
899 wpa_cli_close_connection();
900 os_free(ctrl_ifname);
901 ctrl_ifname = os_strdup(argv[0]);
903 if (wpa_cli_open_connection(ctrl_ifname)) {
904 printf("Connected to interface '%s.\n", ctrl_ifname);
905 if (wpa_ctrl_attach(ctrl_conn) == 0) {
906 wpa_cli_attached = 1;
908 printf("Warning: Failed to attach to "
909 "wpa_supplicant.\n");
912 printf("Could not connect to interface '%s' - re-trying\n",
919 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
922 return wpa_ctrl_command(ctrl, "RECONFIGURE");
926 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
929 return wpa_ctrl_command(ctrl, "TERMINATE");
933 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
939 printf("Invalid INTERFACE_ADD command: needs at least one "
940 "argument (interface name)\n"
941 "All arguments: ifname confname driver ctrl_interface "
942 "driver_param bridge_name\n");
947 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
948 * <driver_param>TAB<bridge_name>
950 os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
952 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
953 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
954 argc > 5 ? argv[5] : "");
955 cmd[sizeof(cmd) - 1] = '\0';
956 return wpa_ctrl_command(ctrl, cmd);
960 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
966 printf("Invalid INTERFACE_REMOVE command: needs one argument "
967 "(interface name)\n");
971 os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
972 cmd[sizeof(cmd) - 1] = '\0';
973 return wpa_ctrl_command(ctrl, cmd);
979 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
982 static struct wpa_cli_cmd wpa_cli_commands[] = {
983 { "status", wpa_cli_cmd_status },
984 { "ping", wpa_cli_cmd_ping },
985 { "mib", wpa_cli_cmd_mib },
986 { "help", wpa_cli_cmd_help },
987 { "interface", wpa_cli_cmd_interface },
988 { "level", wpa_cli_cmd_level },
989 { "license", wpa_cli_cmd_license },
990 { "quit", wpa_cli_cmd_quit },
991 { "set", wpa_cli_cmd_set },
992 { "logon", wpa_cli_cmd_logon },
993 { "logoff", wpa_cli_cmd_logoff },
994 { "pmksa", wpa_cli_cmd_pmksa },
995 { "reassociate", wpa_cli_cmd_reassociate },
996 { "preauthenticate", wpa_cli_cmd_preauthenticate },
997 { "identity", wpa_cli_cmd_identity },
998 { "password", wpa_cli_cmd_password },
999 { "new_password", wpa_cli_cmd_new_password },
1000 { "pin", wpa_cli_cmd_pin },
1001 { "otp", wpa_cli_cmd_otp },
1002 { "passphrase", wpa_cli_cmd_passphrase },
1003 { "bssid", wpa_cli_cmd_bssid },
1004 { "list_networks", wpa_cli_cmd_list_networks },
1005 { "select_network", wpa_cli_cmd_select_network },
1006 { "enable_network", wpa_cli_cmd_enable_network },
1007 { "disable_network", wpa_cli_cmd_disable_network },
1008 { "add_network", wpa_cli_cmd_add_network },
1009 { "remove_network", wpa_cli_cmd_remove_network },
1010 { "set_network", wpa_cli_cmd_set_network },
1011 { "get_network", wpa_cli_cmd_get_network },
1012 { "save_config", wpa_cli_cmd_save_config },
1013 { "disconnect", wpa_cli_cmd_disconnect },
1014 { "reconnect", wpa_cli_cmd_reconnect },
1015 { "scan", wpa_cli_cmd_scan },
1016 { "scan_results", wpa_cli_cmd_scan_results },
1017 { "get_capability", wpa_cli_cmd_get_capability },
1018 { "reconfigure", wpa_cli_cmd_reconfigure },
1019 { "terminate", wpa_cli_cmd_terminate },
1020 { "interface_add", wpa_cli_cmd_interface_add },
1021 { "interface_remove", wpa_cli_cmd_interface_remove },
1022 { "ap_scan", wpa_cli_cmd_ap_scan },
1023 { "stkstart", wpa_cli_cmd_stkstart },
1028 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1030 struct wpa_cli_cmd *cmd, *match = NULL;
1035 cmd = wpa_cli_commands;
1037 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1040 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1041 /* we have an exact match */
1051 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1052 cmd = wpa_cli_commands;
1054 if (os_strncasecmp(cmd->cmd, argv[0],
1055 os_strlen(argv[0])) == 0) {
1056 printf(" %s", cmd->cmd);
1062 } else if (count == 0) {
1063 printf("Unknown command '%s'\n", argv[0]);
1066 ret = match->handler(ctrl, argc - 1, &argv[1]);
1073 static int str_match(const char *a, const char *b)
1075 return os_strncmp(a, b, os_strlen(b)) == 0;
1079 static int wpa_cli_exec(const char *program, const char *arg1,
1085 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1086 cmd = os_malloc(len);
1089 os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1090 cmd[len - 1] = '\0';
1093 #endif /* _WIN32_WCE */
1100 static void wpa_cli_action_process(const char *msg)
1103 char *copy = NULL, *id, *pos2;
1108 pos = os_strchr(pos, '>');
1115 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1117 os_unsetenv("WPA_ID");
1118 os_unsetenv("WPA_ID_STR");
1119 os_unsetenv("WPA_CTRL_DIR");
1121 pos = os_strstr(pos, "[id=");
1123 copy = os_strdup(pos + 4);
1127 while (*pos2 && *pos2 != ' ')
1131 os_setenv("WPA_ID", id, 1);
1132 while (*pos2 && *pos2 != '=')
1137 while (*pos2 && *pos2 != ']')
1140 os_setenv("WPA_ID_STR", id, 1);
1144 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1146 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1147 wpa_cli_connected = 1;
1148 wpa_cli_last_id = new_id;
1149 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1151 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1152 if (wpa_cli_connected) {
1153 wpa_cli_connected = 0;
1154 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1156 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1157 printf("wpa_supplicant is terminating - stop monitoring\n");
1163 #ifndef CONFIG_ANSI_C_EXTRA
1164 static void wpa_cli_action_cb(char *msg, size_t len)
1166 wpa_cli_action_process(msg);
1168 #endif /* CONFIG_ANSI_C_EXTRA */
1171 static void wpa_cli_reconnect(void)
1173 wpa_cli_close_connection();
1174 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1176 printf("Connection to wpa_supplicant re-established\n");
1177 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1178 wpa_cli_attached = 1;
1180 printf("Warning: Failed to attach to "
1181 "wpa_supplicant.\n");
1187 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1191 if (ctrl_conn == NULL) {
1192 wpa_cli_reconnect();
1195 while (wpa_ctrl_pending(ctrl) > 0) {
1197 size_t len = sizeof(buf) - 1;
1198 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1201 wpa_cli_action_process(buf);
1203 if (in_read && first)
1206 printf("%s\n", buf);
1209 printf("Could not read pending message.\n");
1214 if (wpa_ctrl_pending(ctrl) < 0) {
1215 printf("Connection to wpa_supplicant lost - trying to "
1217 wpa_cli_reconnect();
1222 #ifdef CONFIG_READLINE
1223 static char * wpa_cli_cmd_gen(const char *text, int state)
1230 len = os_strlen(text);
1233 while ((cmd = wpa_cli_commands[i].cmd)) {
1235 if (os_strncasecmp(cmd, text, len) == 0)
1236 return os_strdup(cmd);
1243 static char * wpa_cli_dummy_gen(const char *text, int state)
1249 static char ** wpa_cli_completion(const char *text, int start, int end)
1251 return rl_completion_matches(text, start == 0 ?
1252 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1254 #endif /* CONFIG_READLINE */
1257 static void wpa_cli_interactive(void)
1260 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1262 #ifdef CONFIG_READLINE
1263 char *home, *hfile = NULL;
1264 #endif /* CONFIG_READLINE */
1266 printf("\nInteractive mode\n\n");
1268 #ifdef CONFIG_READLINE
1269 rl_attempted_completion_function = wpa_cli_completion;
1270 home = getenv("HOME");
1272 const char *fname = ".wpa_cli_history";
1273 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1274 hfile = os_malloc(hfile_len);
1276 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1277 hfile[hfile_len - 1] = '\0';
1278 read_history(hfile);
1279 stifle_history(100);
1282 #endif /* CONFIG_READLINE */
1285 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1286 #ifndef CONFIG_NATIVE_WINDOWS
1288 #endif /* CONFIG_NATIVE_WINDOWS */
1289 #ifdef CONFIG_READLINE
1290 cmd = readline("> ");
1293 while (next_history())
1295 h = previous_history();
1296 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1300 #else /* CONFIG_READLINE */
1302 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1303 #endif /* CONFIG_READLINE */
1304 #ifndef CONFIG_NATIVE_WINDOWS
1306 #endif /* CONFIG_NATIVE_WINDOWS */
1309 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1311 while (*pos != '\0') {
1327 if (argc == max_args)
1330 char *pos2 = os_strrchr(pos, '"');
1334 while (*pos != '\0' && *pos != ' ')
1340 wpa_request(ctrl_conn, argc, argv);
1344 } while (!wpa_cli_quit);
1346 #ifdef CONFIG_READLINE
1348 /* Save command history, excluding lines that may contain
1355 while (*p == ' ' || *p == '\t')
1357 if (os_strncasecmp(p, "pa", 2) == 0 ||
1358 os_strncasecmp(p, "o", 1) == 0 ||
1359 os_strncasecmp(p, "n", 1)) {
1360 h = remove_history(where_history());
1366 h = current_history();
1371 write_history(hfile);
1374 #endif /* CONFIG_READLINE */
1378 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1380 #ifdef CONFIG_ANSI_C_EXTRA
1381 /* TODO: ANSI C version(?) */
1382 printf("Action processing not supported in ANSI C build.\n");
1383 #else /* CONFIG_ANSI_C_EXTRA */
1387 char buf[256]; /* note: large enough to fit in unsolicited messages */
1390 fd = wpa_ctrl_get_fd(ctrl);
1392 while (!wpa_cli_quit) {
1397 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1398 if (res < 0 && errno != EINTR) {
1403 if (FD_ISSET(fd, &rfds))
1404 wpa_cli_recv_pending(ctrl, 0, 1);
1406 /* verify that connection is still working */
1407 len = sizeof(buf) - 1;
1408 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1409 wpa_cli_action_cb) < 0 ||
1410 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1411 printf("wpa_supplicant did not reply to PING "
1412 "command - exiting\n");
1417 #endif /* CONFIG_ANSI_C_EXTRA */
1421 static void wpa_cli_cleanup(void)
1423 wpa_cli_close_connection();
1425 os_daemonize_terminate(pid_file);
1427 os_program_deinit();
1430 static void wpa_cli_terminate(int sig)
1437 #ifndef CONFIG_NATIVE_WINDOWS
1438 static void wpa_cli_alarm(int sig)
1440 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1441 printf("Connection to wpa_supplicant lost - trying to "
1443 wpa_cli_close_connection();
1446 wpa_cli_reconnect();
1448 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1451 #endif /* CONFIG_NATIVE_WINDOWS */
1454 static char * wpa_cli_get_default_ifname(void)
1456 char *ifname = NULL;
1458 #ifdef CONFIG_CTRL_IFACE_UNIX
1459 struct dirent *dent;
1460 DIR *dir = opendir(ctrl_iface_dir);
1463 while ((dent = readdir(dir))) {
1464 #ifdef _DIRENT_HAVE_D_TYPE
1466 * Skip the file if it is not a socket. Also accept
1467 * DT_UNKNOWN (0) in case the C library or underlying
1468 * file system does not support d_type.
1470 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1472 #endif /* _DIRENT_HAVE_D_TYPE */
1473 if (os_strcmp(dent->d_name, ".") == 0 ||
1474 os_strcmp(dent->d_name, "..") == 0)
1476 printf("Selected interface '%s'\n", dent->d_name);
1477 ifname = os_strdup(dent->d_name);
1481 #endif /* CONFIG_CTRL_IFACE_UNIX */
1483 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1484 char buf[2048], *pos;
1486 struct wpa_ctrl *ctrl;
1489 ctrl = wpa_ctrl_open(NULL);
1493 len = sizeof(buf) - 1;
1494 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1497 pos = os_strchr(buf, '\n');
1500 ifname = os_strdup(buf);
1502 wpa_ctrl_close(ctrl);
1503 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1509 int main(int argc, char *argv[])
1512 int warning_displayed = 0;
1516 const char *global = NULL;
1518 if (os_program_init())
1522 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1527 action_file = optarg;
1539 printf("%s\n", wpa_cli_version);
1542 os_free(ctrl_ifname);
1543 ctrl_ifname = os_strdup(optarg);
1546 ctrl_iface_dir = optarg;
1557 interactive = (argc == optind) && (action_file == NULL);
1560 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1563 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1564 ctrl_conn = wpa_ctrl_open(NULL);
1565 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1566 ctrl_conn = wpa_ctrl_open(global);
1567 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1568 if (ctrl_conn == NULL) {
1569 perror("Failed to connect to wpa_supplicant - "
1576 if (ctrl_ifname == NULL)
1577 ctrl_ifname = wpa_cli_get_default_ifname();
1578 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1580 if (warning_displayed)
1581 printf("Connection established.\n");
1586 perror("Failed to connect to wpa_supplicant - "
1591 if (!warning_displayed) {
1592 printf("Could not connect to wpa_supplicant - "
1594 warning_displayed = 1;
1601 signal(SIGINT, wpa_cli_terminate);
1602 signal(SIGTERM, wpa_cli_terminate);
1603 #endif /* _WIN32_WCE */
1604 #ifndef CONFIG_NATIVE_WINDOWS
1605 signal(SIGALRM, wpa_cli_alarm);
1606 #endif /* CONFIG_NATIVE_WINDOWS */
1608 if (interactive || action_file) {
1609 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1610 wpa_cli_attached = 1;
1612 printf("Warning: Failed to attach to "
1613 "wpa_supplicant.\n");
1619 if (daemonize && os_daemonize(pid_file))
1623 wpa_cli_interactive();
1624 else if (action_file)
1625 wpa_cli_action(ctrl_conn);
1627 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1629 os_free(ctrl_ifname);
1635 #else /* CONFIG_CTRL_IFACE */
1636 int main(int argc, char *argv[])
1638 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1641 #endif /* CONFIG_CTRL_IFACE */