2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2009, 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-2009, 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 struct wpa_ctrl *ctrl_conn;
90 static int wpa_cli_quit = 0;
91 static int wpa_cli_attached = 0;
92 static int wpa_cli_connected = 0;
93 static int wpa_cli_last_id = 0;
94 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95 static char *ctrl_ifname = NULL;
96 static const char *pid_file = NULL;
97 static const char *action_file = NULL;
100 static void print_help();
103 static void usage(void)
105 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
106 "[-a<action file>] \\\n"
107 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
108 " -h = help (show this usage text)\n"
109 " -v = shown version information\n"
110 " -a = run in daemon mode executing the action file based on "
113 " -B = run a daemon in the background\n"
114 " default path: /var/run/wpa_supplicant\n"
115 " default interface: first interface found in socket path\n");
120 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
122 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
123 ctrl_conn = wpa_ctrl_open(ifname);
125 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
132 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
133 cfile = os_malloc(flen);
136 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
137 if (res < 0 || res >= flen) {
142 ctrl_conn = wpa_ctrl_open(cfile);
145 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
149 static void wpa_cli_close_connection(void)
151 if (ctrl_conn == NULL)
154 if (wpa_cli_attached) {
155 wpa_ctrl_detach(ctrl_conn);
156 wpa_cli_attached = 0;
158 wpa_ctrl_close(ctrl_conn);
163 static void wpa_cli_msg_cb(char *msg, size_t len)
169 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
175 if (ctrl_conn == NULL) {
176 printf("Not connected to wpa_supplicant - command dropped.\n");
179 len = sizeof(buf) - 1;
180 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
183 printf("'%s' command timed out.\n", cmd);
185 } else if (ret < 0) {
186 printf("'%s' command failed.\n", cmd);
197 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
199 return _wpa_ctrl_command(ctrl, cmd, 1);
203 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
205 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
206 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
210 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
212 return wpa_ctrl_command(ctrl, "PING");
216 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
218 return wpa_ctrl_command(ctrl, "MIB");
222 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
224 return wpa_ctrl_command(ctrl, "PMKSA");
228 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
235 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
237 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
242 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
249 static void wpa_cli_show_variables(void)
251 printf("set variables:\n"
252 " EAPOL::heldPeriod (EAPOL state machine held period, "
254 " EAPOL::authPeriod (EAPOL state machine authentication "
255 "period, in seconds)\n"
256 " EAPOL::startPeriod (EAPOL state machine start period, in "
258 " EAPOL::maxStart (EAPOL state machine maximum start "
260 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
262 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
263 " threshold\n\tpercentage)\n"
264 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
265 "security\n\tassociation in seconds)\n");
269 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
275 wpa_cli_show_variables();
280 printf("Invalid SET command: needs two arguments (variable "
281 "name and value)\n");
285 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
286 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
287 printf("Too long SET command.\n");
290 return wpa_ctrl_command(ctrl, cmd);
294 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
296 return wpa_ctrl_command(ctrl, "LOGOFF");
300 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
302 return wpa_ctrl_command(ctrl, "LOGON");
306 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
309 return wpa_ctrl_command(ctrl, "REASSOCIATE");
313 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
320 printf("Invalid PREAUTH command: needs one argument "
325 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
326 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
327 printf("Too long PREAUTH command.\n");
330 return wpa_ctrl_command(ctrl, cmd);
334 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
340 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
344 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
345 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
346 printf("Too long AP_SCAN command.\n");
349 return wpa_ctrl_command(ctrl, cmd);
353 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
360 printf("Invalid STKSTART command: needs one argument "
361 "(Peer STA MAC address)\n");
365 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
366 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
367 printf("Too long STKSTART command.\n");
370 return wpa_ctrl_command(ctrl, cmd);
374 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
380 printf("Invalid FT_DS command: needs one argument "
381 "(Target AP MAC address)\n");
385 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
386 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
387 printf("Too long FT_DS command.\n");
390 return wpa_ctrl_command(ctrl, cmd);
394 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
401 return wpa_ctrl_command(ctrl, "WPS_PBC");
405 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
406 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
407 printf("Too long WPS_PBC command.\n");
410 return wpa_ctrl_command(ctrl, cmd);
414 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
420 printf("Invalid WPS_PIN command: need one or two arguments:\n"
421 "- BSSID: use 'any' to select any\n"
422 "- PIN: optional, used only with devices that have no "
428 /* Use dynamically generated PIN (returned as reply) */
429 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
430 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
431 printf("Too long WPS_PIN command.\n");
434 return wpa_ctrl_command(ctrl, cmd);
437 /* Use hardcoded PIN from a label */
438 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
439 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
440 printf("Too long WPS_PIN command.\n");
443 return wpa_ctrl_command(ctrl, cmd);
447 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
453 printf("Invalid WPS_REG command: need two arguments:\n"
454 "- BSSID: use 'any' to select any\n"
459 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
460 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
461 printf("Too long WPS_REG command.\n");
464 return wpa_ctrl_command(ctrl, cmd);
468 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
474 printf("Invalid LEVEL command: needs one argument (debug "
478 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
479 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
480 printf("Too long LEVEL command.\n");
483 return wpa_ctrl_command(ctrl, cmd);
487 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
489 char cmd[256], *pos, *end;
493 printf("Invalid IDENTITY command: needs two arguments "
494 "(network id and identity)\n");
498 end = cmd + sizeof(cmd);
500 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
502 if (ret < 0 || ret >= end - pos) {
503 printf("Too long IDENTITY command.\n");
507 for (i = 2; i < argc; i++) {
508 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
509 if (ret < 0 || ret >= end - pos) {
510 printf("Too long IDENTITY command.\n");
516 return wpa_ctrl_command(ctrl, cmd);
520 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
522 char cmd[256], *pos, *end;
526 printf("Invalid PASSWORD command: needs two arguments "
527 "(network id and password)\n");
531 end = cmd + sizeof(cmd);
533 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
535 if (ret < 0 || ret >= end - pos) {
536 printf("Too long PASSWORD command.\n");
540 for (i = 2; i < argc; i++) {
541 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
542 if (ret < 0 || ret >= end - pos) {
543 printf("Too long PASSWORD command.\n");
549 return wpa_ctrl_command(ctrl, cmd);
553 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
556 char cmd[256], *pos, *end;
560 printf("Invalid NEW_PASSWORD command: needs two arguments "
561 "(network id and password)\n");
565 end = cmd + sizeof(cmd);
567 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
569 if (ret < 0 || ret >= end - pos) {
570 printf("Too long NEW_PASSWORD command.\n");
574 for (i = 2; i < argc; i++) {
575 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
576 if (ret < 0 || ret >= end - pos) {
577 printf("Too long NEW_PASSWORD command.\n");
583 return wpa_ctrl_command(ctrl, cmd);
587 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
589 char cmd[256], *pos, *end;
593 printf("Invalid PIN command: needs two arguments "
594 "(network id and pin)\n");
598 end = cmd + sizeof(cmd);
600 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
602 if (ret < 0 || ret >= end - pos) {
603 printf("Too long PIN command.\n");
607 for (i = 2; i < argc; i++) {
608 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
609 if (ret < 0 || ret >= end - pos) {
610 printf("Too long PIN command.\n");
615 return wpa_ctrl_command(ctrl, cmd);
619 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
621 char cmd[256], *pos, *end;
625 printf("Invalid OTP command: needs two arguments (network "
626 "id and password)\n");
630 end = cmd + sizeof(cmd);
632 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
634 if (ret < 0 || ret >= end - pos) {
635 printf("Too long OTP command.\n");
639 for (i = 2; i < argc; i++) {
640 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
641 if (ret < 0 || ret >= end - pos) {
642 printf("Too long OTP command.\n");
648 return wpa_ctrl_command(ctrl, cmd);
652 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
655 char cmd[256], *pos, *end;
659 printf("Invalid PASSPHRASE command: needs two arguments "
660 "(network id and passphrase)\n");
664 end = cmd + sizeof(cmd);
666 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
668 if (ret < 0 || ret >= end - pos) {
669 printf("Too long PASSPHRASE command.\n");
673 for (i = 2; i < argc; i++) {
674 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
675 if (ret < 0 || ret >= end - pos) {
676 printf("Too long PASSPHRASE command.\n");
682 return wpa_ctrl_command(ctrl, cmd);
686 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
688 char cmd[256], *pos, *end;
692 printf("Invalid BSSID command: needs two arguments (network "
697 end = cmd + sizeof(cmd);
699 ret = os_snprintf(pos, end - pos, "BSSID");
700 if (ret < 0 || ret >= end - pos) {
701 printf("Too long BSSID command.\n");
705 for (i = 0; i < argc; i++) {
706 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
707 if (ret < 0 || ret >= end - pos) {
708 printf("Too long BSSID command.\n");
714 return wpa_ctrl_command(ctrl, cmd);
718 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
721 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
725 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
732 printf("Invalid SELECT_NETWORK command: needs one argument "
737 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
738 if (res < 0 || (size_t) res >= sizeof(cmd))
740 cmd[sizeof(cmd) - 1] = '\0';
742 return wpa_ctrl_command(ctrl, cmd);
746 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
753 printf("Invalid ENABLE_NETWORK command: needs one argument "
758 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
759 if (res < 0 || (size_t) res >= sizeof(cmd))
761 cmd[sizeof(cmd) - 1] = '\0';
763 return wpa_ctrl_command(ctrl, cmd);
767 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
774 printf("Invalid DISABLE_NETWORK command: needs one argument "
779 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
780 if (res < 0 || (size_t) res >= sizeof(cmd))
782 cmd[sizeof(cmd) - 1] = '\0';
784 return wpa_ctrl_command(ctrl, cmd);
788 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
791 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
795 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
802 printf("Invalid REMOVE_NETWORK command: needs one argument "
807 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
808 if (res < 0 || (size_t) res >= sizeof(cmd))
810 cmd[sizeof(cmd) - 1] = '\0';
812 return wpa_ctrl_command(ctrl, cmd);
816 static void wpa_cli_show_network_variables(void)
818 printf("set_network variables:\n"
819 " ssid (network name, SSID)\n"
820 " psk (WPA passphrase or pre-shared key)\n"
821 " key_mgmt (key management protocol)\n"
822 " identity (EAP identity)\n"
823 " password (EAP password)\n"
826 "Note: Values are entered in the same format as the "
827 "configuration file is using,\n"
828 "i.e., strings values need to be inside double quotation "
830 "For example: set_network 1 ssid \"network name\"\n"
832 "Please see wpa_supplicant.conf documentation for full list "
833 "of\navailable variables.\n");
837 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
844 wpa_cli_show_network_variables();
849 printf("Invalid SET_NETWORK command: needs three arguments\n"
850 "(network id, variable name, and value)\n");
854 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
855 argv[0], argv[1], argv[2]);
856 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857 printf("Too long SET_NETWORK command.\n");
860 return wpa_ctrl_command(ctrl, cmd);
864 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
871 wpa_cli_show_network_variables();
876 printf("Invalid GET_NETWORK command: needs two arguments\n"
877 "(network id and variable name)\n");
881 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
883 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
884 printf("Too long GET_NETWORK command.\n");
887 return wpa_ctrl_command(ctrl, cmd);
891 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
894 return wpa_ctrl_command(ctrl, "DISCONNECT");
898 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
901 return wpa_ctrl_command(ctrl, "RECONNECT");
905 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
908 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
912 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
914 return wpa_ctrl_command(ctrl, "SCAN");
918 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
921 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
925 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
931 printf("Invalid BSS command: need one argument (index or "
936 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
937 if (res < 0 || (size_t) res >= sizeof(cmd))
939 cmd[sizeof(cmd) - 1] = '\0';
941 return wpa_ctrl_command(ctrl, cmd);
945 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
951 if (argc < 1 || argc > 2) {
952 printf("Invalid GET_CAPABILITY command: need either one or "
957 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
958 printf("Invalid GET_CAPABILITY command: second argument, "
959 "if any, must be 'strict'\n");
963 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
964 (argc == 2) ? " strict" : "");
965 if (res < 0 || (size_t) res >= sizeof(cmd))
967 cmd[sizeof(cmd) - 1] = '\0';
969 return wpa_ctrl_command(ctrl, cmd);
973 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
975 printf("Available interfaces:\n");
976 return wpa_ctrl_command(ctrl, "INTERFACES");
980 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
983 wpa_cli_list_interfaces(ctrl);
987 wpa_cli_close_connection();
988 os_free(ctrl_ifname);
989 ctrl_ifname = os_strdup(argv[0]);
991 if (wpa_cli_open_connection(ctrl_ifname)) {
992 printf("Connected to interface '%s.\n", ctrl_ifname);
993 if (wpa_ctrl_attach(ctrl_conn) == 0) {
994 wpa_cli_attached = 1;
996 printf("Warning: Failed to attach to "
997 "wpa_supplicant.\n");
1000 printf("Could not connect to interface '%s' - re-trying\n",
1007 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1010 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1014 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1017 return wpa_ctrl_command(ctrl, "TERMINATE");
1021 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1028 printf("Invalid INTERFACE_ADD command: needs at least one "
1029 "argument (interface name)\n"
1030 "All arguments: ifname confname driver ctrl_interface "
1031 "driver_param bridge_name\n");
1036 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1037 * <driver_param>TAB<bridge_name>
1039 res = os_snprintf(cmd, sizeof(cmd),
1040 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1042 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1043 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1044 argc > 5 ? argv[5] : "");
1045 if (res < 0 || (size_t) res >= sizeof(cmd))
1047 cmd[sizeof(cmd) - 1] = '\0';
1048 return wpa_ctrl_command(ctrl, cmd);
1052 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1059 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1060 "(interface name)\n");
1064 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1065 if (res < 0 || (size_t) res >= sizeof(cmd))
1067 cmd[sizeof(cmd) - 1] = '\0';
1068 return wpa_ctrl_command(ctrl, cmd);
1072 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1075 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1079 enum wpa_cli_cmd_flags {
1080 cli_cmd_flag_none = 0x00,
1081 cli_cmd_flag_sensitive = 0x01
1084 struct wpa_cli_cmd {
1086 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1087 enum wpa_cli_cmd_flags flags;
1091 static struct wpa_cli_cmd wpa_cli_commands[] = {
1092 { "status", wpa_cli_cmd_status,
1094 "[verbose] = get current WPA/EAPOL/EAP status" },
1095 { "ping", wpa_cli_cmd_ping,
1097 "= pings wpa_supplicant" },
1098 { "mib", wpa_cli_cmd_mib,
1100 "= get MIB variables (dot1x, dot11)" },
1101 { "help", wpa_cli_cmd_help,
1103 "= show this usage help" },
1104 { "interface", wpa_cli_cmd_interface,
1106 "[ifname] = show interfaces/select interface" },
1107 { "level", wpa_cli_cmd_level,
1109 "<debug level> = change debug level" },
1110 { "license", wpa_cli_cmd_license,
1112 "= show full wpa_cli license" },
1113 { "quit", wpa_cli_cmd_quit,
1116 { "set", wpa_cli_cmd_set,
1118 "= set variables (shows list of variables when run without "
1120 { "logon", wpa_cli_cmd_logon,
1122 "= IEEE 802.1X EAPOL state machine logon" },
1123 { "logoff", wpa_cli_cmd_logoff,
1125 "= IEEE 802.1X EAPOL state machine logoff" },
1126 { "pmksa", wpa_cli_cmd_pmksa,
1128 "= show PMKSA cache" },
1129 { "reassociate", wpa_cli_cmd_reassociate,
1131 "= force reassociation" },
1132 { "preauthenticate", wpa_cli_cmd_preauthenticate,
1134 "<BSSID> = force preauthentication" },
1135 { "identity", wpa_cli_cmd_identity,
1137 "<network id> <identity> = configure identity for an SSID" },
1138 { "password", wpa_cli_cmd_password,
1139 cli_cmd_flag_sensitive,
1140 "<network id> <password> = configure password for an SSID" },
1141 { "new_password", wpa_cli_cmd_new_password,
1142 cli_cmd_flag_sensitive,
1143 "<network id> <password> = change password for an SSID" },
1144 { "pin", wpa_cli_cmd_pin,
1145 cli_cmd_flag_sensitive,
1146 "<network id> <pin> = configure pin for an SSID" },
1147 { "otp", wpa_cli_cmd_otp,
1148 cli_cmd_flag_sensitive,
1149 "<network id> <password> = configure one-time-password for an SSID"
1151 { "passphrase", wpa_cli_cmd_passphrase,
1152 cli_cmd_flag_sensitive,
1153 "<network id> <passphrase> = configure private key passphrase\n"
1155 { "bssid", wpa_cli_cmd_bssid,
1157 "<network id> <BSSID> = set preferred BSSID for an SSID" },
1158 { "list_networks", wpa_cli_cmd_list_networks,
1160 "= list configured networks" },
1161 { "select_network", wpa_cli_cmd_select_network,
1163 "<network id> = select a network (disable others)" },
1164 { "enable_network", wpa_cli_cmd_enable_network,
1166 "<network id> = enable a network" },
1167 { "disable_network", wpa_cli_cmd_disable_network,
1169 "<network id> = disable a network" },
1170 { "add_network", wpa_cli_cmd_add_network,
1172 "= add a network" },
1173 { "remove_network", wpa_cli_cmd_remove_network,
1175 "<network id> = remove a network" },
1176 { "set_network", wpa_cli_cmd_set_network,
1177 cli_cmd_flag_sensitive,
1178 "<network id> <variable> <value> = set network variables (shows\n"
1179 " list of variables when run without arguments)" },
1180 { "get_network", wpa_cli_cmd_get_network,
1182 "<network id> <variable> = get network variables" },
1183 { "save_config", wpa_cli_cmd_save_config,
1185 "= save the current configuration" },
1186 { "disconnect", wpa_cli_cmd_disconnect,
1188 "= disconnect and wait for reassociate/reconnect command before\n"
1190 { "reconnect", wpa_cli_cmd_reconnect,
1192 "= like reassociate, but only takes effect if already disconnected"
1194 { "scan", wpa_cli_cmd_scan,
1196 "= request new BSS scan" },
1197 { "scan_results", wpa_cli_cmd_scan_results,
1199 "= get latest scan results" },
1200 { "bss", wpa_cli_cmd_bss,
1202 "<<idx> | <bssid>> = get detailed scan result info" },
1203 { "get_capability", wpa_cli_cmd_get_capability,
1205 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1206 { "reconfigure", wpa_cli_cmd_reconfigure,
1208 "= force wpa_supplicant to re-read its configuration file" },
1209 { "terminate", wpa_cli_cmd_terminate,
1211 "= terminate wpa_supplicant" },
1212 { "interface_add", wpa_cli_cmd_interface_add,
1214 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1215 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1217 { "interface_remove", wpa_cli_cmd_interface_remove,
1219 "<ifname> = removes the interface" },
1220 { "interface_list", wpa_cli_cmd_interface_list,
1222 "= list available interfaces" },
1223 { "ap_scan", wpa_cli_cmd_ap_scan,
1225 "<value> = set ap_scan parameter" },
1226 { "stkstart", wpa_cli_cmd_stkstart,
1228 "<addr> = request STK negotiation with <addr>" },
1229 { "ft_ds", wpa_cli_cmd_ft_ds,
1231 "<addr> = request over-the-DS FT with <addr>" },
1232 { "wps_pbc", wpa_cli_cmd_wps_pbc,
1234 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1235 { "wps_pin", wpa_cli_cmd_wps_pin,
1236 cli_cmd_flag_sensitive,
1237 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1239 { "wps_reg", wpa_cli_cmd_wps_reg,
1240 cli_cmd_flag_sensitive,
1241 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1242 { NULL, NULL, cli_cmd_flag_none, NULL }
1247 * Prints command usage, lines are padded with the specified string.
1249 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1254 printf("%s%s ", pad, cmd->cmd);
1255 for (n = 0; (c = cmd->usage[n]); n++) {
1264 static void print_help(void)
1267 printf("commands:\n");
1268 for (n = 0; wpa_cli_commands[n].cmd; n++)
1269 print_cmd_help(&wpa_cli_commands[n], " ");
1273 #ifdef CONFIG_READLINE
1274 static int cmd_has_sensitive_data(const char *cmd)
1276 const char *c, *delim;
1280 delim = os_strchr(cmd, ' ');
1284 len = os_strlen(cmd);
1286 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1287 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1288 return (wpa_cli_commands[n].flags &
1289 cli_cmd_flag_sensitive);
1293 #endif /* CONFIG_READLINE */
1296 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1298 struct wpa_cli_cmd *cmd, *match = NULL;
1303 cmd = wpa_cli_commands;
1305 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1308 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1309 /* we have an exact match */
1319 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1320 cmd = wpa_cli_commands;
1322 if (os_strncasecmp(cmd->cmd, argv[0],
1323 os_strlen(argv[0])) == 0) {
1324 printf(" %s", cmd->cmd);
1330 } else if (count == 0) {
1331 printf("Unknown command '%s'\n", argv[0]);
1334 ret = match->handler(ctrl, argc - 1, &argv[1]);
1341 static int str_match(const char *a, const char *b)
1343 return os_strncmp(a, b, os_strlen(b)) == 0;
1347 static int wpa_cli_exec(const char *program, const char *arg1,
1355 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1356 cmd = os_malloc(len);
1359 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1360 if (res < 0 || (size_t) res >= len) {
1364 cmd[len - 1] = '\0';
1366 if (system(cmd) < 0)
1368 #endif /* _WIN32_WCE */
1375 static void wpa_cli_action_process(const char *msg)
1378 char *copy = NULL, *id, *pos2;
1383 pos = os_strchr(pos, '>');
1390 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1392 os_unsetenv("WPA_ID");
1393 os_unsetenv("WPA_ID_STR");
1394 os_unsetenv("WPA_CTRL_DIR");
1396 pos = os_strstr(pos, "[id=");
1398 copy = os_strdup(pos + 4);
1402 while (*pos2 && *pos2 != ' ')
1406 os_setenv("WPA_ID", id, 1);
1407 while (*pos2 && *pos2 != '=')
1412 while (*pos2 && *pos2 != ']')
1415 os_setenv("WPA_ID_STR", id, 1);
1419 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1421 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1422 wpa_cli_connected = 1;
1423 wpa_cli_last_id = new_id;
1424 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1426 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1427 if (wpa_cli_connected) {
1428 wpa_cli_connected = 0;
1429 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1431 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1432 printf("wpa_supplicant is terminating - stop monitoring\n");
1438 #ifndef CONFIG_ANSI_C_EXTRA
1439 static void wpa_cli_action_cb(char *msg, size_t len)
1441 wpa_cli_action_process(msg);
1443 #endif /* CONFIG_ANSI_C_EXTRA */
1446 static void wpa_cli_reconnect(void)
1448 wpa_cli_close_connection();
1449 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1451 printf("Connection to wpa_supplicant re-established\n");
1452 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1453 wpa_cli_attached = 1;
1455 printf("Warning: Failed to attach to "
1456 "wpa_supplicant.\n");
1462 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1466 if (ctrl_conn == NULL) {
1467 wpa_cli_reconnect();
1470 while (wpa_ctrl_pending(ctrl) > 0) {
1472 size_t len = sizeof(buf) - 1;
1473 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1476 wpa_cli_action_process(buf);
1478 if (in_read && first)
1481 printf("%s\n", buf);
1484 printf("Could not read pending message.\n");
1489 if (wpa_ctrl_pending(ctrl) < 0) {
1490 printf("Connection to wpa_supplicant lost - trying to "
1492 wpa_cli_reconnect();
1497 #ifdef CONFIG_READLINE
1498 static char * wpa_cli_cmd_gen(const char *text, int state)
1505 len = os_strlen(text);
1508 while ((cmd = wpa_cli_commands[i].cmd)) {
1510 if (os_strncasecmp(cmd, text, len) == 0)
1511 return os_strdup(cmd);
1518 static char * wpa_cli_dummy_gen(const char *text, int state)
1524 static char ** wpa_cli_completion(const char *text, int start, int end)
1526 return rl_completion_matches(text, start == 0 ?
1527 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1529 #endif /* CONFIG_READLINE */
1532 static void wpa_cli_interactive(void)
1535 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1537 #ifdef CONFIG_READLINE
1538 char *home, *hfile = NULL;
1539 #endif /* CONFIG_READLINE */
1541 printf("\nInteractive mode\n\n");
1543 #ifdef CONFIG_READLINE
1544 rl_attempted_completion_function = wpa_cli_completion;
1545 home = getenv("HOME");
1547 const char *fname = ".wpa_cli_history";
1548 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1549 hfile = os_malloc(hfile_len);
1552 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1554 if (res >= 0 && res < hfile_len) {
1555 hfile[hfile_len - 1] = '\0';
1556 read_history(hfile);
1557 stifle_history(100);
1561 #endif /* CONFIG_READLINE */
1564 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1565 #ifndef CONFIG_NATIVE_WINDOWS
1567 #endif /* CONFIG_NATIVE_WINDOWS */
1568 #ifdef CONFIG_READLINE
1569 cmd = readline("> ");
1572 while (next_history())
1574 h = previous_history();
1575 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1579 #else /* CONFIG_READLINE */
1581 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1582 #endif /* CONFIG_READLINE */
1583 #ifndef CONFIG_NATIVE_WINDOWS
1585 #endif /* CONFIG_NATIVE_WINDOWS */
1588 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1590 while (*pos != '\0') {
1606 if (argc == max_args)
1609 char *pos2 = os_strrchr(pos, '"');
1613 while (*pos != '\0' && *pos != ' ')
1619 wpa_request(ctrl_conn, argc, argv);
1623 } while (!wpa_cli_quit);
1625 #ifdef CONFIG_READLINE
1627 /* Save command history, excluding lines that may contain
1631 while ((h = current_history())) {
1633 while (*p == ' ' || *p == '\t')
1635 if (cmd_has_sensitive_data(p)) {
1636 h = remove_history(where_history());
1646 write_history(hfile);
1649 #endif /* CONFIG_READLINE */
1653 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1655 #ifdef CONFIG_ANSI_C_EXTRA
1656 /* TODO: ANSI C version(?) */
1657 printf("Action processing not supported in ANSI C build.\n");
1658 #else /* CONFIG_ANSI_C_EXTRA */
1662 char buf[256]; /* note: large enough to fit in unsolicited messages */
1665 fd = wpa_ctrl_get_fd(ctrl);
1667 while (!wpa_cli_quit) {
1672 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1673 if (res < 0 && errno != EINTR) {
1678 if (FD_ISSET(fd, &rfds))
1679 wpa_cli_recv_pending(ctrl, 0, 1);
1681 /* verify that connection is still working */
1682 len = sizeof(buf) - 1;
1683 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1684 wpa_cli_action_cb) < 0 ||
1685 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1686 printf("wpa_supplicant did not reply to PING "
1687 "command - exiting\n");
1692 #endif /* CONFIG_ANSI_C_EXTRA */
1696 static void wpa_cli_cleanup(void)
1698 wpa_cli_close_connection();
1700 os_daemonize_terminate(pid_file);
1702 os_program_deinit();
1705 static void wpa_cli_terminate(int sig)
1712 #ifndef CONFIG_NATIVE_WINDOWS
1713 static void wpa_cli_alarm(int sig)
1715 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1716 printf("Connection to wpa_supplicant lost - trying to "
1718 wpa_cli_close_connection();
1721 wpa_cli_reconnect();
1723 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1726 #endif /* CONFIG_NATIVE_WINDOWS */
1729 static char * wpa_cli_get_default_ifname(void)
1731 char *ifname = NULL;
1733 #ifdef CONFIG_CTRL_IFACE_UNIX
1734 struct dirent *dent;
1735 DIR *dir = opendir(ctrl_iface_dir);
1738 while ((dent = readdir(dir))) {
1739 #ifdef _DIRENT_HAVE_D_TYPE
1741 * Skip the file if it is not a socket. Also accept
1742 * DT_UNKNOWN (0) in case the C library or underlying
1743 * file system does not support d_type.
1745 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1747 #endif /* _DIRENT_HAVE_D_TYPE */
1748 if (os_strcmp(dent->d_name, ".") == 0 ||
1749 os_strcmp(dent->d_name, "..") == 0)
1751 printf("Selected interface '%s'\n", dent->d_name);
1752 ifname = os_strdup(dent->d_name);
1756 #endif /* CONFIG_CTRL_IFACE_UNIX */
1758 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1759 char buf[2048], *pos;
1761 struct wpa_ctrl *ctrl;
1764 ctrl = wpa_ctrl_open(NULL);
1768 len = sizeof(buf) - 1;
1769 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1772 pos = os_strchr(buf, '\n');
1775 ifname = os_strdup(buf);
1777 wpa_ctrl_close(ctrl);
1778 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1784 int main(int argc, char *argv[])
1787 int warning_displayed = 0;
1791 const char *global = NULL;
1793 if (os_program_init())
1797 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1802 action_file = optarg;
1814 printf("%s\n", wpa_cli_version);
1817 os_free(ctrl_ifname);
1818 ctrl_ifname = os_strdup(optarg);
1821 ctrl_iface_dir = optarg;
1832 interactive = (argc == optind) && (action_file == NULL);
1835 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1838 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1839 ctrl_conn = wpa_ctrl_open(NULL);
1840 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1841 ctrl_conn = wpa_ctrl_open(global);
1842 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1843 if (ctrl_conn == NULL) {
1844 perror("Failed to connect to wpa_supplicant - "
1851 if (ctrl_ifname == NULL)
1852 ctrl_ifname = wpa_cli_get_default_ifname();
1853 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1855 if (warning_displayed)
1856 printf("Connection established.\n");
1861 perror("Failed to connect to wpa_supplicant - "
1866 if (!warning_displayed) {
1867 printf("Could not connect to wpa_supplicant - "
1869 warning_displayed = 1;
1876 signal(SIGINT, wpa_cli_terminate);
1877 signal(SIGTERM, wpa_cli_terminate);
1878 #endif /* _WIN32_WCE */
1879 #ifndef CONFIG_NATIVE_WINDOWS
1880 signal(SIGALRM, wpa_cli_alarm);
1881 #endif /* CONFIG_NATIVE_WINDOWS */
1883 if (interactive || action_file) {
1884 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1885 wpa_cli_attached = 1;
1887 printf("Warning: Failed to attach to "
1888 "wpa_supplicant.\n");
1894 if (daemonize && os_daemonize(pid_file))
1898 wpa_cli_interactive();
1899 else if (action_file)
1900 wpa_cli_action(ctrl_conn);
1902 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1904 os_free(ctrl_ifname);
1910 #else /* CONFIG_CTRL_IFACE */
1911 int main(int argc, char *argv[])
1913 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1916 #endif /* CONFIG_CTRL_IFACE */