2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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.
23 #ifdef CONFIG_READLINE
24 #include <readline/readline.h>
25 #include <readline/history.h>
26 #endif /* CONFIG_READLINE */
29 #ifdef CONFIG_NATIVE_WINDOWS
31 #endif /* CONFIG_NATIVE_WINDOWS */
35 static const char *wpa_cli_version =
36 "wpa_cli v" VERSION_STR "\n"
37 "Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> and contributors";
40 static const char *wpa_cli_license =
41 "This program is free software. You can distribute it and/or modify it\n"
42 "under the terms of the GNU General Public License version 2.\n"
44 "Alternatively, this software may be distributed under the terms of the\n"
45 "BSD license. See README and COPYING for more details.\n";
47 static const char *wpa_cli_full_license =
48 "This program is free software; you can redistribute it and/or modify\n"
49 "it under the terms of the GNU General Public License version 2 as\n"
50 "published by the Free Software Foundation.\n"
52 "This program is distributed in the hope that it will be useful,\n"
53 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
54 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
55 "GNU General Public License for more details.\n"
57 "You should have received a copy of the GNU General Public License\n"
58 "along with this program; if not, write to the Free Software\n"
59 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
61 "Alternatively, this software may be distributed under the terms of the\n"
64 "Redistribution and use in source and binary forms, with or without\n"
65 "modification, are permitted provided that the following conditions are\n"
68 "1. Redistributions of source code must retain the above copyright\n"
69 " notice, this list of conditions and the following disclaimer.\n"
71 "2. Redistributions in binary form must reproduce the above copyright\n"
72 " notice, this list of conditions and the following disclaimer in the\n"
73 " documentation and/or other materials provided with the distribution.\n"
75 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
76 " names of its contributors may be used to endorse or promote products\n"
77 " derived from this software without specific prior written permission.\n"
79 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
80 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
81 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
82 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
83 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
84 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
85 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
86 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
87 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
88 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
89 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
92 static const char *commands_help =
94 " status [verbose] = get current WPA/EAPOL/EAP status\n"
95 " mib = get MIB variables (dot1x, dot11)\n"
96 " help = show this usage help\n"
97 " interface [ifname] = show interfaces/select interface\n"
98 " level <debug level> = change debug level\n"
99 " license = show full wpa_cli license\n"
100 " logoff = IEEE 802.1X EAPOL state machine logoff\n"
101 " logon = IEEE 802.1X EAPOL state machine logon\n"
102 " set = set variables (shows list of variables when run without arguments)\n"
103 " pmksa = show PMKSA cache\n"
104 " reassociate = force reassociation\n"
105 " reconfigure = force wpa_supplicant to re-read its configuration file\n"
106 " preauthenticate <BSSID> = force preauthentication\n"
107 " identity <network id> <identity> = configure identity for an SSID\n"
108 " password <network id> <password> = configure password for an SSID\n"
109 " new_password <network id> <password> = change password for an SSID\n"
110 " pin <network id> <pin> = configure pin for an SSID\n"
111 " otp <network id> <password> = configure one-time-password for an SSID\n"
112 " passphrase <network id> <passphrase> = configure private key passphrase\n"
114 " bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
115 " list_networks = list configured networks\n"
116 " select_network <network id> = select a network (disable others)\n"
117 " enable_network <network id> = enable a network\n"
118 " disable_network <network id> = disable a network\n"
119 " add_network = add a network\n"
120 " remove_network <network id> = remove a network\n"
121 " set_network <network id> <variable> <value> = set network variables "
123 " list of variables when run without arguments)\n"
124 " get_network <network id> <variable> = get network variables\n"
125 " save_config = save the current configuration\n"
126 " disconnect = disconnect and wait for reassociate command before "
128 " scan = request new BSS scan\n"
129 " scan_results = get latest scan results\n"
130 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
132 " terminate = terminate wpa_supplicant\n"
133 " quit = exit wpa_cli\n";
135 static struct wpa_ctrl *ctrl_conn;
136 static int wpa_cli_quit = 0;
137 static int wpa_cli_attached = 0;
138 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
139 static char *ctrl_ifname = NULL;
140 static const char *pid_file = NULL;
141 static const char *action_file = NULL;
144 static void usage(void)
146 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
147 "[-a<action file>] \\\n"
148 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
149 " -h = help (show this usage text)\n"
150 " -v = shown version information\n"
151 " -a = run in daemon mode executing the action file based on "
154 " -B = run a daemon in the background\n"
155 " default path: /var/run/wpa_supplicant\n"
156 " default interface: first interface found in socket path\n"
162 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
164 #ifdef CONFIG_CTRL_IFACE_UDP
165 ctrl_conn = wpa_ctrl_open("");
167 #else /* CONFIG_CTRL_IFACE_UDP */
174 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
175 cfile = malloc(flen);
178 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
180 ctrl_conn = wpa_ctrl_open(cfile);
183 #endif /* CONFIG_CTRL_IFACE_UDP */
187 static void wpa_cli_close_connection(void)
189 if (ctrl_conn == NULL)
192 if (wpa_cli_attached) {
193 wpa_ctrl_detach(ctrl_conn);
194 wpa_cli_attached = 0;
196 wpa_ctrl_close(ctrl_conn);
201 static void wpa_cli_msg_cb(char *msg, size_t len)
207 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
213 if (ctrl_conn == NULL) {
214 printf("Not connected to wpa_supplicant - command dropped.\n");
217 len = sizeof(buf) - 1;
218 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
221 printf("'%s' command timed out.\n", cmd);
223 } else if (ret < 0) {
224 printf("'%s' command failed.\n", cmd);
235 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
237 return _wpa_ctrl_command(ctrl, cmd, 1);
241 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
243 int verbose = argc > 0 && strcmp(argv[0], "verbose") == 0;
244 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
248 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
250 return wpa_ctrl_command(ctrl, "PING");
254 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
256 return wpa_ctrl_command(ctrl, "MIB");
260 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
262 return wpa_ctrl_command(ctrl, "PMKSA");
266 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
268 printf("%s", commands_help);
273 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
275 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
280 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
287 static void wpa_cli_show_variables(void)
289 printf("set variables:\n"
290 " EAPOL::heldPeriod (EAPOL state machine held period, "
292 " EAPOL::authPeriod (EAPOL state machine authentication "
293 "period, in seconds)\n"
294 " EAPOL::startPeriod (EAPOL state machine start period, in "
296 " EAPOL::maxStart (EAPOL state machine maximum start "
298 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
300 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
301 " threshold\n\tpercentage)\n"
302 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
303 "security\n\tassociation in seconds)\n");
307 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
312 wpa_cli_show_variables();
317 printf("Invalid SET command: needs two arguments (variable "
318 "name and value)\n");
322 if (snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]) >=
324 printf("Too long SET command.\n");
327 return wpa_ctrl_command(ctrl, cmd);
331 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
333 return wpa_ctrl_command(ctrl, "LOGOFF");
337 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
339 return wpa_ctrl_command(ctrl, "LOGON");
343 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
346 return wpa_ctrl_command(ctrl, "REASSOCIATE");
350 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
356 printf("Invalid PREAUTH command: needs one argument "
361 if (snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]) >=
363 printf("Too long PREAUTH command.\n");
366 return wpa_ctrl_command(ctrl, cmd);
370 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
374 printf("Invalid LEVEL command: needs one argument (debug "
378 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
379 return wpa_ctrl_command(ctrl, cmd);
383 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
385 char cmd[256], *pos, *end;
389 printf("Invalid IDENTITY command: needs two arguments "
390 "(network id and identity)\n");
394 end = cmd + sizeof(cmd);
396 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
398 for (i = 2; i < argc; i++)
399 pos += snprintf(pos, end - pos, " %s", argv[i]);
401 return wpa_ctrl_command(ctrl, cmd);
405 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
407 char cmd[256], *pos, *end;
411 printf("Invalid PASSWORD command: needs two arguments "
412 "(network id and password)\n");
416 end = cmd + sizeof(cmd);
418 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
420 for (i = 2; i < argc; i++)
421 pos += snprintf(pos, end - pos, " %s", argv[i]);
423 return wpa_ctrl_command(ctrl, cmd);
427 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
430 char cmd[256], *pos, *end;
434 printf("Invalid NEW_PASSWORD command: needs two arguments "
435 "(network id and password)\n");
439 end = cmd + sizeof(cmd);
441 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
443 for (i = 2; i < argc; i++)
444 pos += snprintf(pos, end - pos, " %s", argv[i]);
446 return wpa_ctrl_command(ctrl, cmd);
450 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
452 char cmd[256], *pos, *end;
456 printf("Invalid PIN command: needs two arguments "
457 "(network id and pin)\n");
461 end = cmd + sizeof(cmd);
463 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
465 for (i = 2; i < argc; i++)
466 pos += snprintf(pos, end - pos, " %s", argv[i]);
468 return wpa_ctrl_command(ctrl, cmd);
472 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
474 char cmd[256], *pos, *end;
478 printf("Invalid OTP command: needs two arguments (network "
479 "id and password)\n");
483 end = cmd + sizeof(cmd);
485 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
487 for (i = 2; i < argc; i++)
488 pos += snprintf(pos, end - pos, " %s", argv[i]);
490 return wpa_ctrl_command(ctrl, cmd);
494 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
497 char cmd[256], *pos, *end;
501 printf("Invalid PASSPHRASE command: needs two arguments "
502 "(network id and passphrase)\n");
506 end = cmd + sizeof(cmd);
508 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
510 for (i = 2; i < argc; i++)
511 pos += snprintf(pos, end - pos, " %s", argv[i]);
513 return wpa_ctrl_command(ctrl, cmd);
517 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
519 char cmd[256], *pos, *end;
523 printf("Invalid BSSID command: needs two arguments (network "
528 end = cmd + sizeof(cmd);
530 pos += snprintf(pos, end - pos, "BSSID");
531 for (i = 0; i < argc; i++)
532 pos += snprintf(pos, end - pos, " %s", argv[i]);
534 return wpa_ctrl_command(ctrl, cmd);
538 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
541 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
545 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
551 printf("Invalid SELECT_NETWORK command: needs one argument "
556 snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
558 return wpa_ctrl_command(ctrl, cmd);
562 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
568 printf("Invalid ENABLE_NETWORK command: needs one argument "
573 snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
575 return wpa_ctrl_command(ctrl, cmd);
579 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
585 printf("Invalid DISABLE_NETWORK command: needs one argument "
590 snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
592 return wpa_ctrl_command(ctrl, cmd);
596 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
599 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
603 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
609 printf("Invalid REMOVE_NETWORK command: needs one argument "
614 snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
616 return wpa_ctrl_command(ctrl, cmd);
620 static void wpa_cli_show_network_variables(void)
622 printf("set_network variables:\n"
623 " ssid (network name, SSID)\n"
624 " psk (WPA passphrase or pre-shared key)\n"
625 " key_mgmt (key management protocol)\n"
626 " identity (EAP identity)\n"
627 " password (EAP password)\n"
630 "Note: Values are entered in the same format as the "
631 "configuration file is using,\n"
632 "i.e., strings values need to be inside double quotation "
634 "For example: set_network 1 ssid \"network name\"\n"
636 "Please see wpa_supplicant.conf documentation for full list "
637 "of\navailable variables.\n");
641 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
647 wpa_cli_show_network_variables();
652 printf("Invalid SET_NETWORK command: needs three arguments\n"
653 "(network id, variable name, and value)\n");
657 if (snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
658 argv[0], argv[1], argv[2]) >= sizeof(cmd) - 1) {
659 printf("Too long SET_NETWORK command.\n");
662 return wpa_ctrl_command(ctrl, cmd);
666 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
672 wpa_cli_show_network_variables();
677 printf("Invalid GET_NETWORK command: needs two arguments\n"
678 "(network id and variable name)\n");
682 if (snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
683 argv[0], argv[1]) >= sizeof(cmd) - 1) {
684 printf("Too long GET_NETWORK command.\n");
687 return wpa_ctrl_command(ctrl, cmd);
691 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
694 return wpa_ctrl_command(ctrl, "DISCONNECT");
698 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
701 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
705 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
707 return wpa_ctrl_command(ctrl, "SCAN");
711 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
714 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
718 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
724 printf("Invalid GET_CAPABILITY command: needs one argument\n");
728 snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s", argv[0]);
730 return wpa_ctrl_command(ctrl, cmd);
734 static void wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
739 dir = opendir(ctrl_iface_dir);
741 printf("Control interface directory '%s' could not be "
742 "openned.\n", ctrl_iface_dir);
746 printf("Available interfaces:\n");
747 while ((dent = readdir(dir))) {
748 if (strcmp(dent->d_name, ".") == 0 ||
749 strcmp(dent->d_name, "..") == 0)
751 printf("%s\n", dent->d_name);
757 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
760 wpa_cli_list_interfaces(ctrl);
764 wpa_cli_close_connection();
766 ctrl_ifname = strdup(argv[0]);
768 if (wpa_cli_open_connection(ctrl_ifname)) {
769 printf("Connected to interface '%s.\n", ctrl_ifname);
770 if (wpa_ctrl_attach(ctrl_conn) == 0) {
771 wpa_cli_attached = 1;
773 printf("Warning: Failed to attach to "
774 "wpa_supplicant.\n");
777 printf("Could not connect to interface '%s' - re-trying\n",
784 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
787 return wpa_ctrl_command(ctrl, "RECONFIGURE");
791 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
794 return wpa_ctrl_command(ctrl, "TERMINATE");
798 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
804 printf("Invalid INTERFACE_ADD command: needs at least one "
805 "argument (interface name)\n"
806 "All arguments: ifname confname driver ctrl_interface "
812 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
815 snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s", argv[0],
816 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
817 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "");
818 return wpa_ctrl_command(ctrl, cmd);
822 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
828 printf("Invalid INTERFACE_REMOVE command: needs one argument "
829 "(interface name)\n");
833 snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
834 return wpa_ctrl_command(ctrl, cmd);
840 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
843 static struct wpa_cli_cmd wpa_cli_commands[] = {
844 { "status", wpa_cli_cmd_status },
845 { "ping", wpa_cli_cmd_ping },
846 { "mib", wpa_cli_cmd_mib },
847 { "help", wpa_cli_cmd_help },
848 { "interface", wpa_cli_cmd_interface },
849 { "level", wpa_cli_cmd_level },
850 { "license", wpa_cli_cmd_license },
851 { "quit", wpa_cli_cmd_quit },
852 { "set", wpa_cli_cmd_set },
853 { "logon", wpa_cli_cmd_logon },
854 { "logoff", wpa_cli_cmd_logoff },
855 { "pmksa", wpa_cli_cmd_pmksa },
856 { "reassociate", wpa_cli_cmd_reassociate },
857 { "preauthenticate", wpa_cli_cmd_preauthenticate },
858 { "identity", wpa_cli_cmd_identity },
859 { "password", wpa_cli_cmd_password },
860 { "new_password", wpa_cli_cmd_new_password },
861 { "pin", wpa_cli_cmd_pin },
862 { "otp", wpa_cli_cmd_otp },
863 { "passphrase", wpa_cli_cmd_passphrase },
864 { "bssid", wpa_cli_cmd_bssid },
865 { "list_networks", wpa_cli_cmd_list_networks },
866 { "select_network", wpa_cli_cmd_select_network },
867 { "enable_network", wpa_cli_cmd_enable_network },
868 { "disable_network", wpa_cli_cmd_disable_network },
869 { "add_network", wpa_cli_cmd_add_network },
870 { "remove_network", wpa_cli_cmd_remove_network },
871 { "set_network", wpa_cli_cmd_set_network },
872 { "get_network", wpa_cli_cmd_get_network },
873 { "save_config", wpa_cli_cmd_save_config },
874 { "disconnect", wpa_cli_cmd_disconnect },
875 { "scan", wpa_cli_cmd_scan },
876 { "scan_results", wpa_cli_cmd_scan_results },
877 { "get_capability", wpa_cli_cmd_get_capability },
878 { "reconfigure", wpa_cli_cmd_reconfigure },
879 { "terminate", wpa_cli_cmd_terminate },
880 { "interface_add", wpa_cli_cmd_interface_add },
881 { "interface_remove", wpa_cli_cmd_interface_remove },
886 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
888 struct wpa_cli_cmd *cmd, *match = NULL;
892 cmd = wpa_cli_commands;
894 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
896 if (strcasecmp(cmd->cmd, argv[0]) == 0) {
897 /* we have an exact match */
907 printf("Ambiguous command '%s'; possible commands:", argv[0]);
908 cmd = wpa_cli_commands;
910 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
912 printf(" %s", cmd->cmd);
917 } else if (count == 0) {
918 printf("Unknown command '%s'\n", argv[0]);
920 match->handler(ctrl, argc - 1, &argv[1]);
925 static int str_match(const char *a, const char *b)
927 return strncmp(a, b, strlen(b)) == 0;
931 static int wpa_cli_exec(const char *program, const char *arg1,
937 len = strlen(program) + strlen(arg1) + strlen(arg2) + 3;
941 snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
949 static void wpa_cli_action_process(const char *msg)
956 pos = strchr(pos, '>');
963 if (str_match(pos, WPA_EVENT_CONNECTED)) {
964 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
965 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
966 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
967 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
968 printf("wpa_supplicant is terminating - stop monitoring\n");
974 static void wpa_cli_action_cb(char *msg, size_t len)
976 wpa_cli_action_process(msg);
980 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
984 if (ctrl_conn == NULL)
986 while (wpa_ctrl_pending(ctrl)) {
988 size_t len = sizeof(buf) - 1;
989 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
992 wpa_cli_action_process(buf);
994 if (in_read && first)
1000 printf("Could not read pending message.\n");
1007 #ifdef CONFIG_READLINE
1008 static char * wpa_cli_cmd_gen(const char *text, int state)
1018 while ((cmd = wpa_cli_commands[i].cmd)) {
1020 if (strncasecmp(cmd, text, len) == 0)
1028 static char * wpa_cli_dummy_gen(const char *text, int state)
1034 static char ** wpa_cli_completion(const char *text, int start, int end)
1036 return rl_completion_matches(text, start == 0 ?
1037 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1039 #endif /* CONFIG_READLINE */
1042 static void wpa_cli_interactive(void)
1045 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1047 #ifdef CONFIG_READLINE
1048 char *home, *hfile = NULL;
1049 #endif /* CONFIG_READLINE */
1051 printf("\nInteractive mode\n\n");
1053 #ifdef CONFIG_READLINE
1054 rl_attempted_completion_function = wpa_cli_completion;
1055 home = getenv("HOME");
1057 const char *fname = ".wpa_cli_history";
1058 int hfile_len = strlen(home) + 1 + strlen(fname) + 1;
1059 hfile = malloc(hfile_len);
1061 snprintf(hfile, hfile_len, "%s/%s", home, fname);
1062 read_history(hfile);
1063 stifle_history(100);
1066 #endif /* CONFIG_READLINE */
1069 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1070 #ifndef CONFIG_NATIVE_WINDOWS
1072 #endif /* CONFIG_NATIVE_WINDOWS */
1073 #ifdef CONFIG_READLINE
1074 cmd = readline("> ");
1077 while (next_history())
1079 h = previous_history();
1080 if (h == NULL || strcmp(cmd, h->line) != 0)
1084 #else /* CONFIG_READLINE */
1086 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1087 #endif /* CONFIG_READLINE */
1088 #ifndef CONFIG_NATIVE_WINDOWS
1090 #endif /* CONFIG_NATIVE_WINDOWS */
1094 while (*pos != '\0') {
1110 if (argc == max_args)
1113 char *pos2 = strrchr(pos, '"');
1117 while (*pos != '\0' && *pos != ' ')
1123 wpa_request(ctrl_conn, argc, argv);
1127 } while (!wpa_cli_quit);
1129 #ifdef CONFIG_READLINE
1131 /* Save command history, excluding lines that may contain
1138 while (*p == ' ' || *p == '\t')
1140 if (strncasecmp(p, "pa", 2) == 0 ||
1141 strncasecmp(p, "o", 1) == 0 ||
1142 strncasecmp(p, "n", 1)) {
1143 h = remove_history(where_history());
1149 h = current_history();
1154 write_history(hfile);
1157 #endif /* CONFIG_READLINE */
1161 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1169 fd = wpa_ctrl_get_fd(ctrl);
1171 while (!wpa_cli_quit) {
1176 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1177 if (res < 0 && errno != EINTR) {
1182 if (FD_ISSET(fd, &rfds))
1183 wpa_cli_recv_pending(ctrl, 0, 1);
1185 /* verify that connection is still working */
1186 len = sizeof(buf) - 1;
1187 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1188 wpa_cli_action_cb) < 0 ||
1189 len < 4 || memcmp(buf, "PONG", 4) != 0) {
1190 printf("wpa_supplicant did not reply to PING "
1191 "command - exiting\n");
1199 static void wpa_cli_cleanup(void)
1201 wpa_cli_close_connection();
1205 #ifdef CONFIG_NATIVE_WINDOWS
1207 #endif /* CONFIG_NATIVE_WINDOWS */
1210 static void wpa_cli_terminate(int sig)
1217 #ifndef CONFIG_NATIVE_WINDOWS
1218 static void wpa_cli_alarm(int sig)
1220 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1221 printf("Connection to wpa_supplicant lost - trying to "
1223 wpa_cli_close_connection();
1226 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1228 printf("Connection to wpa_supplicant "
1229 "re-established\n");
1230 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1231 wpa_cli_attached = 1;
1233 printf("Warning: Failed to attach to "
1234 "wpa_supplicant.\n");
1239 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1242 #endif /* CONFIG_NATIVE_WINDOWS */
1245 int main(int argc, char *argv[])
1248 int warning_displayed = 0;
1252 const char *global = NULL;
1254 #ifdef CONFIG_NATIVE_WINDOWS
1256 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
1257 printf("Could not find a usable WinSock.dll\n");
1260 #endif /* CONFIG_NATIVE_WINDOWS */
1263 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1268 action_file = optarg;
1280 printf("%s\n", wpa_cli_version);
1283 ctrl_ifname = strdup(optarg);
1286 ctrl_iface_dir = optarg;
1297 interactive = (argc == optind) && (action_file == NULL);
1300 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1303 ctrl_conn = wpa_ctrl_open(global);
1304 if (ctrl_conn == NULL) {
1305 perror("Failed to connect to wpa_supplicant - "
1312 if (ctrl_ifname == NULL) {
1313 struct dirent *dent;
1314 DIR *dir = opendir(ctrl_iface_dir);
1316 while ((dent = readdir(dir))) {
1317 if (strcmp(dent->d_name, ".") == 0 ||
1318 strcmp(dent->d_name, "..") == 0)
1320 printf("Selected interface '%s'\n",
1322 ctrl_ifname = strdup(dent->d_name);
1328 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1330 if (warning_displayed)
1331 printf("Connection established.\n");
1336 perror("Failed to connect to wpa_supplicant - "
1341 if (!warning_displayed) {
1342 printf("Could not connect to wpa_supplicant - "
1344 warning_displayed = 1;
1350 signal(SIGINT, wpa_cli_terminate);
1351 signal(SIGTERM, wpa_cli_terminate);
1352 #ifndef CONFIG_NATIVE_WINDOWS
1353 signal(SIGALRM, wpa_cli_alarm);
1354 #endif /* CONFIG_NATIVE_WINDOWS */
1356 if (interactive || action_file) {
1357 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1358 wpa_cli_attached = 1;
1360 printf("Warning: Failed to attach to "
1361 "wpa_supplicant.\n");
1367 if (daemonize && daemon(0, 0)) {
1373 f = fopen(pid_file, "w");
1375 fprintf(f, "%u\n", getpid());
1381 wpa_cli_interactive();
1382 else if (action_file)
1383 wpa_cli_action(ctrl_conn);
1385 wpa_request(ctrl_conn, argc - optind, &argv[optind]);