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,
1086 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1087 cmd = os_malloc(len);
1090 os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1091 cmd[len - 1] = '\0';
1093 if (system(cmd) < 0)
1095 #endif /* _WIN32_WCE */
1102 static void wpa_cli_action_process(const char *msg)
1105 char *copy = NULL, *id, *pos2;
1110 pos = os_strchr(pos, '>');
1117 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1119 os_unsetenv("WPA_ID");
1120 os_unsetenv("WPA_ID_STR");
1121 os_unsetenv("WPA_CTRL_DIR");
1123 pos = os_strstr(pos, "[id=");
1125 copy = os_strdup(pos + 4);
1129 while (*pos2 && *pos2 != ' ')
1133 os_setenv("WPA_ID", id, 1);
1134 while (*pos2 && *pos2 != '=')
1139 while (*pos2 && *pos2 != ']')
1142 os_setenv("WPA_ID_STR", id, 1);
1146 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1148 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1149 wpa_cli_connected = 1;
1150 wpa_cli_last_id = new_id;
1151 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1153 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1154 if (wpa_cli_connected) {
1155 wpa_cli_connected = 0;
1156 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1158 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1159 printf("wpa_supplicant is terminating - stop monitoring\n");
1165 #ifndef CONFIG_ANSI_C_EXTRA
1166 static void wpa_cli_action_cb(char *msg, size_t len)
1168 wpa_cli_action_process(msg);
1170 #endif /* CONFIG_ANSI_C_EXTRA */
1173 static void wpa_cli_reconnect(void)
1175 wpa_cli_close_connection();
1176 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1178 printf("Connection to wpa_supplicant re-established\n");
1179 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1180 wpa_cli_attached = 1;
1182 printf("Warning: Failed to attach to "
1183 "wpa_supplicant.\n");
1189 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1193 if (ctrl_conn == NULL) {
1194 wpa_cli_reconnect();
1197 while (wpa_ctrl_pending(ctrl) > 0) {
1199 size_t len = sizeof(buf) - 1;
1200 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1203 wpa_cli_action_process(buf);
1205 if (in_read && first)
1208 printf("%s\n", buf);
1211 printf("Could not read pending message.\n");
1216 if (wpa_ctrl_pending(ctrl) < 0) {
1217 printf("Connection to wpa_supplicant lost - trying to "
1219 wpa_cli_reconnect();
1224 #ifdef CONFIG_READLINE
1225 static char * wpa_cli_cmd_gen(const char *text, int state)
1232 len = os_strlen(text);
1235 while ((cmd = wpa_cli_commands[i].cmd)) {
1237 if (os_strncasecmp(cmd, text, len) == 0)
1238 return os_strdup(cmd);
1245 static char * wpa_cli_dummy_gen(const char *text, int state)
1251 static char ** wpa_cli_completion(const char *text, int start, int end)
1253 return rl_completion_matches(text, start == 0 ?
1254 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1256 #endif /* CONFIG_READLINE */
1259 static void wpa_cli_interactive(void)
1262 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1264 #ifdef CONFIG_READLINE
1265 char *home, *hfile = NULL;
1266 #endif /* CONFIG_READLINE */
1268 printf("\nInteractive mode\n\n");
1270 #ifdef CONFIG_READLINE
1271 rl_attempted_completion_function = wpa_cli_completion;
1272 home = getenv("HOME");
1274 const char *fname = ".wpa_cli_history";
1275 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1276 hfile = os_malloc(hfile_len);
1278 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1279 hfile[hfile_len - 1] = '\0';
1280 read_history(hfile);
1281 stifle_history(100);
1284 #endif /* CONFIG_READLINE */
1287 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1288 #ifndef CONFIG_NATIVE_WINDOWS
1290 #endif /* CONFIG_NATIVE_WINDOWS */
1291 #ifdef CONFIG_READLINE
1292 cmd = readline("> ");
1295 while (next_history())
1297 h = previous_history();
1298 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1302 #else /* CONFIG_READLINE */
1304 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1305 #endif /* CONFIG_READLINE */
1306 #ifndef CONFIG_NATIVE_WINDOWS
1308 #endif /* CONFIG_NATIVE_WINDOWS */
1311 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1313 while (*pos != '\0') {
1329 if (argc == max_args)
1332 char *pos2 = os_strrchr(pos, '"');
1336 while (*pos != '\0' && *pos != ' ')
1342 wpa_request(ctrl_conn, argc, argv);
1346 } while (!wpa_cli_quit);
1348 #ifdef CONFIG_READLINE
1350 /* Save command history, excluding lines that may contain
1357 while (*p == ' ' || *p == '\t')
1359 if (os_strncasecmp(p, "pa", 2) == 0 ||
1360 os_strncasecmp(p, "o", 1) == 0 ||
1361 os_strncasecmp(p, "n", 1)) {
1362 h = remove_history(where_history());
1368 h = current_history();
1373 write_history(hfile);
1376 #endif /* CONFIG_READLINE */
1380 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1382 #ifdef CONFIG_ANSI_C_EXTRA
1383 /* TODO: ANSI C version(?) */
1384 printf("Action processing not supported in ANSI C build.\n");
1385 #else /* CONFIG_ANSI_C_EXTRA */
1389 char buf[256]; /* note: large enough to fit in unsolicited messages */
1392 fd = wpa_ctrl_get_fd(ctrl);
1394 while (!wpa_cli_quit) {
1399 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1400 if (res < 0 && errno != EINTR) {
1405 if (FD_ISSET(fd, &rfds))
1406 wpa_cli_recv_pending(ctrl, 0, 1);
1408 /* verify that connection is still working */
1409 len = sizeof(buf) - 1;
1410 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1411 wpa_cli_action_cb) < 0 ||
1412 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1413 printf("wpa_supplicant did not reply to PING "
1414 "command - exiting\n");
1419 #endif /* CONFIG_ANSI_C_EXTRA */
1423 static void wpa_cli_cleanup(void)
1425 wpa_cli_close_connection();
1427 os_daemonize_terminate(pid_file);
1429 os_program_deinit();
1432 static void wpa_cli_terminate(int sig)
1439 #ifndef CONFIG_NATIVE_WINDOWS
1440 static void wpa_cli_alarm(int sig)
1442 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1443 printf("Connection to wpa_supplicant lost - trying to "
1445 wpa_cli_close_connection();
1448 wpa_cli_reconnect();
1450 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1453 #endif /* CONFIG_NATIVE_WINDOWS */
1456 static char * wpa_cli_get_default_ifname(void)
1458 char *ifname = NULL;
1460 #ifdef CONFIG_CTRL_IFACE_UNIX
1461 struct dirent *dent;
1462 DIR *dir = opendir(ctrl_iface_dir);
1465 while ((dent = readdir(dir))) {
1466 #ifdef _DIRENT_HAVE_D_TYPE
1468 * Skip the file if it is not a socket. Also accept
1469 * DT_UNKNOWN (0) in case the C library or underlying
1470 * file system does not support d_type.
1472 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1474 #endif /* _DIRENT_HAVE_D_TYPE */
1475 if (os_strcmp(dent->d_name, ".") == 0 ||
1476 os_strcmp(dent->d_name, "..") == 0)
1478 printf("Selected interface '%s'\n", dent->d_name);
1479 ifname = os_strdup(dent->d_name);
1483 #endif /* CONFIG_CTRL_IFACE_UNIX */
1485 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1486 char buf[2048], *pos;
1488 struct wpa_ctrl *ctrl;
1491 ctrl = wpa_ctrl_open(NULL);
1495 len = sizeof(buf) - 1;
1496 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1499 pos = os_strchr(buf, '\n');
1502 ifname = os_strdup(buf);
1504 wpa_ctrl_close(ctrl);
1505 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1511 int main(int argc, char *argv[])
1514 int warning_displayed = 0;
1518 const char *global = NULL;
1520 if (os_program_init())
1524 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1529 action_file = optarg;
1541 printf("%s\n", wpa_cli_version);
1544 os_free(ctrl_ifname);
1545 ctrl_ifname = os_strdup(optarg);
1548 ctrl_iface_dir = optarg;
1559 interactive = (argc == optind) && (action_file == NULL);
1562 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1565 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1566 ctrl_conn = wpa_ctrl_open(NULL);
1567 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1568 ctrl_conn = wpa_ctrl_open(global);
1569 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1570 if (ctrl_conn == NULL) {
1571 perror("Failed to connect to wpa_supplicant - "
1578 if (ctrl_ifname == NULL)
1579 ctrl_ifname = wpa_cli_get_default_ifname();
1580 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1582 if (warning_displayed)
1583 printf("Connection established.\n");
1588 perror("Failed to connect to wpa_supplicant - "
1593 if (!warning_displayed) {
1594 printf("Could not connect to wpa_supplicant - "
1596 warning_displayed = 1;
1603 signal(SIGINT, wpa_cli_terminate);
1604 signal(SIGTERM, wpa_cli_terminate);
1605 #endif /* _WIN32_WCE */
1606 #ifndef CONFIG_NATIVE_WINDOWS
1607 signal(SIGALRM, wpa_cli_alarm);
1608 #endif /* CONFIG_NATIVE_WINDOWS */
1610 if (interactive || action_file) {
1611 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1612 wpa_cli_attached = 1;
1614 printf("Warning: Failed to attach to "
1615 "wpa_supplicant.\n");
1621 if (daemonize && os_daemonize(pid_file))
1625 wpa_cli_interactive();
1626 else if (action_file)
1627 wpa_cli_action(ctrl_conn);
1629 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1631 os_free(ctrl_ifname);
1637 #else /* CONFIG_CTRL_IFACE */
1638 int main(int argc, char *argv[])
1640 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1643 #endif /* CONFIG_CTRL_IFACE */