2
* WPA Supplicant - command line interface for wpa_supplicant daemon
3
* Copyright (c) 2004-2007, 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-2007, 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 command before "
125
" scan = request new BSS scan\n"
126
" scan_results = get latest scan results\n"
127
" get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
129
" ap_scan <value> = set ap_scan parameter\n"
130
" stkstart <addr> = request STK negotiation with <addr>\n"
131
" ft_ds <addr> = request over-the-DS FT with <addr>\n"
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 int wpa_cli_connected = 0;
139
static int wpa_cli_last_id = 0;
140
static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
141
static char *ctrl_ifname = NULL;
142
static const char *pid_file = NULL;
143
static const char *action_file = NULL;
146
static void usage(void)
148
printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
149
"[-a<action file>] \\\n"
150
" [-P<pid file>] [-g<global ctrl>] [command..]\n"
151
" -h = help (show this usage text)\n"
152
" -v = shown version information\n"
153
" -a = run in daemon mode executing the action file based on "
156
" -B = run a daemon in the background\n"
157
" default path: /var/run/wpa_supplicant\n"
158
" default interface: first interface found in socket path\n"
164
static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
166
#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
167
ctrl_conn = wpa_ctrl_open(ifname);
169
#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
176
flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
177
cfile = os_malloc(flen);
180
res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
181
if (res < 0 || res >= flen) {
186
ctrl_conn = wpa_ctrl_open(cfile);
189
#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
193
static void wpa_cli_close_connection(void)
195
if (ctrl_conn == NULL)
198
if (wpa_cli_attached) {
199
wpa_ctrl_detach(ctrl_conn);
200
wpa_cli_attached = 0;
202
wpa_ctrl_close(ctrl_conn);
207
static void wpa_cli_msg_cb(char *msg, size_t len)
213
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
219
if (ctrl_conn == NULL) {
220
printf("Not connected to wpa_supplicant - command dropped.\n");
223
len = sizeof(buf) - 1;
224
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
227
printf("'%s' command timed out.\n", cmd);
229
} else if (ret < 0) {
230
printf("'%s' command failed.\n", cmd);
241
static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
243
return _wpa_ctrl_command(ctrl, cmd, 1);
247
static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
249
int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
250
return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
254
static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
256
return wpa_ctrl_command(ctrl, "PING");
260
static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
262
return wpa_ctrl_command(ctrl, "MIB");
266
static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
268
return wpa_ctrl_command(ctrl, "PMKSA");
272
static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
274
printf("%s", commands_help);
279
static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
281
printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
286
static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
293
static void wpa_cli_show_variables(void)
295
printf("set variables:\n"
296
" EAPOL::heldPeriod (EAPOL state machine held period, "
298
" EAPOL::authPeriod (EAPOL state machine authentication "
299
"period, in seconds)\n"
300
" EAPOL::startPeriod (EAPOL state machine start period, in "
302
" EAPOL::maxStart (EAPOL state machine maximum start "
304
printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
306
" dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
307
" threshold\n\tpercentage)\n"
308
" dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
309
"security\n\tassociation in seconds)\n");
313
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
319
wpa_cli_show_variables();
324
printf("Invalid SET command: needs two arguments (variable "
325
"name and value)\n");
329
res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
330
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
331
printf("Too long SET command.\n");
334
return wpa_ctrl_command(ctrl, cmd);
338
static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
340
return wpa_ctrl_command(ctrl, "LOGOFF");
344
static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
346
return wpa_ctrl_command(ctrl, "LOGON");
350
static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
353
return wpa_ctrl_command(ctrl, "REASSOCIATE");
357
static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
364
printf("Invalid PREAUTH command: needs one argument "
369
res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
370
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
371
printf("Too long PREAUTH command.\n");
374
return wpa_ctrl_command(ctrl, cmd);
378
static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
384
printf("Invalid AP_SCAN command: needs one argument (ap_scan "
388
res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
389
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
390
printf("Too long AP_SCAN command.\n");
393
return wpa_ctrl_command(ctrl, cmd);
397
static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
404
printf("Invalid STKSTART command: needs one argument "
405
"(Peer STA MAC address)\n");
409
res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
410
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
411
printf("Too long STKSTART command.\n");
414
return wpa_ctrl_command(ctrl, cmd);
418
static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
424
printf("Invalid FT_DS command: needs one argument "
425
"(Target AP MAC address)\n");
429
res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
430
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
431
printf("Too long FT_DS command.\n");
434
return wpa_ctrl_command(ctrl, cmd);
438
static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
444
printf("Invalid LEVEL command: needs one argument (debug "
448
res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
449
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
450
printf("Too long LEVEL command.\n");
453
return wpa_ctrl_command(ctrl, cmd);
457
static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
459
char cmd[256], *pos, *end;
463
printf("Invalid IDENTITY command: needs two arguments "
464
"(network id and identity)\n");
468
end = cmd + sizeof(cmd);
470
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
472
if (ret < 0 || ret >= end - pos) {
473
printf("Too long IDENTITY command.\n");
477
for (i = 2; i < argc; i++) {
478
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
479
if (ret < 0 || ret >= end - pos) {
480
printf("Too long IDENTITY command.\n");
486
return wpa_ctrl_command(ctrl, cmd);
490
static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
492
char cmd[256], *pos, *end;
496
printf("Invalid PASSWORD command: needs two arguments "
497
"(network id and password)\n");
501
end = cmd + sizeof(cmd);
503
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
505
if (ret < 0 || ret >= end - pos) {
506
printf("Too long PASSWORD command.\n");
510
for (i = 2; i < argc; i++) {
511
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
512
if (ret < 0 || ret >= end - pos) {
513
printf("Too long PASSWORD command.\n");
519
return wpa_ctrl_command(ctrl, cmd);
523
static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
526
char cmd[256], *pos, *end;
530
printf("Invalid NEW_PASSWORD command: needs two arguments "
531
"(network id and password)\n");
535
end = cmd + sizeof(cmd);
537
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
539
if (ret < 0 || ret >= end - pos) {
540
printf("Too long NEW_PASSWORD command.\n");
544
for (i = 2; i < argc; i++) {
545
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
546
if (ret < 0 || ret >= end - pos) {
547
printf("Too long NEW_PASSWORD command.\n");
553
return wpa_ctrl_command(ctrl, cmd);
557
static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
559
char cmd[256], *pos, *end;
563
printf("Invalid PIN command: needs two arguments "
564
"(network id and pin)\n");
568
end = cmd + sizeof(cmd);
570
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
572
if (ret < 0 || ret >= end - pos) {
573
printf("Too long PIN command.\n");
577
for (i = 2; i < argc; i++) {
578
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
579
if (ret < 0 || ret >= end - pos) {
580
printf("Too long PIN command.\n");
585
return wpa_ctrl_command(ctrl, cmd);
589
static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
591
char cmd[256], *pos, *end;
595
printf("Invalid OTP command: needs two arguments (network "
596
"id and password)\n");
600
end = cmd + sizeof(cmd);
602
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
604
if (ret < 0 || ret >= end - pos) {
605
printf("Too long OTP command.\n");
609
for (i = 2; i < argc; i++) {
610
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
611
if (ret < 0 || ret >= end - pos) {
612
printf("Too long OTP command.\n");
618
return wpa_ctrl_command(ctrl, cmd);
622
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
625
char cmd[256], *pos, *end;
629
printf("Invalid PASSPHRASE command: needs two arguments "
630
"(network id and passphrase)\n");
634
end = cmd + sizeof(cmd);
636
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
638
if (ret < 0 || ret >= end - pos) {
639
printf("Too long PASSPHRASE command.\n");
643
for (i = 2; i < argc; i++) {
644
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
645
if (ret < 0 || ret >= end - pos) {
646
printf("Too long PASSPHRASE command.\n");
652
return wpa_ctrl_command(ctrl, cmd);
656
static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
658
char cmd[256], *pos, *end;
662
printf("Invalid BSSID command: needs two arguments (network "
667
end = cmd + sizeof(cmd);
669
ret = os_snprintf(pos, end - pos, "BSSID");
670
if (ret < 0 || ret >= end - pos) {
671
printf("Too long BSSID command.\n");
675
for (i = 0; i < argc; i++) {
676
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
677
if (ret < 0 || ret >= end - pos) {
678
printf("Too long BSSID command.\n");
684
return wpa_ctrl_command(ctrl, cmd);
688
static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
691
return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
695
static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
702
printf("Invalid SELECT_NETWORK command: needs one argument "
707
res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
708
if (res < 0 || (size_t) res >= sizeof(cmd))
710
cmd[sizeof(cmd) - 1] = '\0';
712
return wpa_ctrl_command(ctrl, cmd);
716
static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
723
printf("Invalid ENABLE_NETWORK command: needs one argument "
728
res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
729
if (res < 0 || (size_t) res >= sizeof(cmd))
731
cmd[sizeof(cmd) - 1] = '\0';
733
return wpa_ctrl_command(ctrl, cmd);
737
static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
744
printf("Invalid DISABLE_NETWORK command: needs one argument "
749
res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
750
if (res < 0 || (size_t) res >= sizeof(cmd))
752
cmd[sizeof(cmd) - 1] = '\0';
754
return wpa_ctrl_command(ctrl, cmd);
758
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
761
return wpa_ctrl_command(ctrl, "ADD_NETWORK");
765
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
772
printf("Invalid REMOVE_NETWORK command: needs one argument "
777
res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
778
if (res < 0 || (size_t) res >= sizeof(cmd))
780
cmd[sizeof(cmd) - 1] = '\0';
782
return wpa_ctrl_command(ctrl, cmd);
786
static void wpa_cli_show_network_variables(void)
788
printf("set_network variables:\n"
789
" ssid (network name, SSID)\n"
790
" psk (WPA passphrase or pre-shared key)\n"
791
" key_mgmt (key management protocol)\n"
792
" identity (EAP identity)\n"
793
" password (EAP password)\n"
796
"Note: Values are entered in the same format as the "
797
"configuration file is using,\n"
798
"i.e., strings values need to be inside double quotation "
800
"For example: set_network 1 ssid \"network name\"\n"
802
"Please see wpa_supplicant.conf documentation for full list "
803
"of\navailable variables.\n");
807
static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
814
wpa_cli_show_network_variables();
819
printf("Invalid SET_NETWORK command: needs three arguments\n"
820
"(network id, variable name, and value)\n");
824
res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
825
argv[0], argv[1], argv[2]);
826
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
827
printf("Too long SET_NETWORK command.\n");
830
return wpa_ctrl_command(ctrl, cmd);
834
static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
841
wpa_cli_show_network_variables();
846
printf("Invalid GET_NETWORK command: needs two arguments\n"
847
"(network id and variable name)\n");
851
res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
853
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
854
printf("Too long GET_NETWORK command.\n");
857
return wpa_ctrl_command(ctrl, cmd);
861
static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
864
return wpa_ctrl_command(ctrl, "DISCONNECT");
868
static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
871
return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
875
static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
877
return wpa_ctrl_command(ctrl, "SCAN");
881
static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
884
return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
888
static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
894
if (argc < 1 || argc > 2) {
895
printf("Invalid GET_CAPABILITY command: need either one or "
900
if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
901
printf("Invalid GET_CAPABILITY command: second argument, "
902
"if any, must be 'strict'\n");
906
res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
907
(argc == 2) ? " strict" : "");
908
if (res < 0 || (size_t) res >= sizeof(cmd))
910
cmd[sizeof(cmd) - 1] = '\0';
912
return wpa_ctrl_command(ctrl, cmd);
916
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
918
printf("Available interfaces:\n");
919
return wpa_ctrl_command(ctrl, "INTERFACES");
923
static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
926
wpa_cli_list_interfaces(ctrl);
930
wpa_cli_close_connection();
931
os_free(ctrl_ifname);
932
ctrl_ifname = os_strdup(argv[0]);
934
if (wpa_cli_open_connection(ctrl_ifname)) {
935
printf("Connected to interface '%s.\n", ctrl_ifname);
936
if (wpa_ctrl_attach(ctrl_conn) == 0) {
937
wpa_cli_attached = 1;
939
printf("Warning: Failed to attach to "
940
"wpa_supplicant.\n");
943
printf("Could not connect to interface '%s' - re-trying\n",
950
static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
953
return wpa_ctrl_command(ctrl, "RECONFIGURE");
957
static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
960
return wpa_ctrl_command(ctrl, "TERMINATE");
964
static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
971
printf("Invalid INTERFACE_ADD command: needs at least one "
972
"argument (interface name)\n"
973
"All arguments: ifname confname driver ctrl_interface "
974
"driver_param bridge_name\n");
979
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
980
* <driver_param>TAB<bridge_name>
982
res = os_snprintf(cmd, sizeof(cmd),
983
"INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
985
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
986
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
987
argc > 5 ? argv[5] : "");
988
if (res < 0 || (size_t) res >= sizeof(cmd))
990
cmd[sizeof(cmd) - 1] = '\0';
991
return wpa_ctrl_command(ctrl, cmd);
995
static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1002
printf("Invalid INTERFACE_REMOVE command: needs one argument "
1003
"(interface name)\n");
1007
res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1008
if (res < 0 || (size_t) res >= sizeof(cmd))
1010
cmd[sizeof(cmd) - 1] = '\0';
1011
return wpa_ctrl_command(ctrl, cmd);
1015
struct wpa_cli_cmd {
1017
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1020
static struct wpa_cli_cmd wpa_cli_commands[] = {
1021
{ "status", wpa_cli_cmd_status },
1022
{ "ping", wpa_cli_cmd_ping },
1023
{ "mib", wpa_cli_cmd_mib },
1024
{ "help", wpa_cli_cmd_help },
1025
{ "interface", wpa_cli_cmd_interface },
1026
{ "level", wpa_cli_cmd_level },
1027
{ "license", wpa_cli_cmd_license },
1028
{ "quit", wpa_cli_cmd_quit },
1029
{ "set", wpa_cli_cmd_set },
1030
{ "logon", wpa_cli_cmd_logon },
1031
{ "logoff", wpa_cli_cmd_logoff },
1032
{ "pmksa", wpa_cli_cmd_pmksa },
1033
{ "reassociate", wpa_cli_cmd_reassociate },
1034
{ "preauthenticate", wpa_cli_cmd_preauthenticate },
1035
{ "identity", wpa_cli_cmd_identity },
1036
{ "password", wpa_cli_cmd_password },
1037
{ "new_password", wpa_cli_cmd_new_password },
1038
{ "pin", wpa_cli_cmd_pin },
1039
{ "otp", wpa_cli_cmd_otp },
1040
{ "passphrase", wpa_cli_cmd_passphrase },
1041
{ "bssid", wpa_cli_cmd_bssid },
1042
{ "list_networks", wpa_cli_cmd_list_networks },
1043
{ "select_network", wpa_cli_cmd_select_network },
1044
{ "enable_network", wpa_cli_cmd_enable_network },
1045
{ "disable_network", wpa_cli_cmd_disable_network },
1046
{ "add_network", wpa_cli_cmd_add_network },
1047
{ "remove_network", wpa_cli_cmd_remove_network },
1048
{ "set_network", wpa_cli_cmd_set_network },
1049
{ "get_network", wpa_cli_cmd_get_network },
1050
{ "save_config", wpa_cli_cmd_save_config },
1051
{ "disconnect", wpa_cli_cmd_disconnect },
1052
{ "scan", wpa_cli_cmd_scan },
1053
{ "scan_results", wpa_cli_cmd_scan_results },
1054
{ "get_capability", wpa_cli_cmd_get_capability },
1055
{ "reconfigure", wpa_cli_cmd_reconfigure },
1056
{ "terminate", wpa_cli_cmd_terminate },
1057
{ "interface_add", wpa_cli_cmd_interface_add },
1058
{ "interface_remove", wpa_cli_cmd_interface_remove },
1059
{ "ap_scan", wpa_cli_cmd_ap_scan },
1060
{ "stkstart", wpa_cli_cmd_stkstart },
1061
{ "ft_ds", wpa_cli_cmd_ft_ds },
1066
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1068
struct wpa_cli_cmd *cmd, *match = NULL;
1072
cmd = wpa_cli_commands;
1074
if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1077
if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1078
/* we have an exact match */
1088
printf("Ambiguous command '%s'; possible commands:", argv[0]);
1089
cmd = wpa_cli_commands;
1091
if (os_strncasecmp(cmd->cmd, argv[0],
1092
os_strlen(argv[0])) == 0) {
1093
printf(" %s", cmd->cmd);
1098
} else if (count == 0) {
1099
printf("Unknown command '%s'\n", argv[0]);
1101
match->handler(ctrl, argc - 1, &argv[1]);
1106
static int str_match(const char *a, const char *b)
1108
return os_strncmp(a, b, os_strlen(b)) == 0;
1112
static int wpa_cli_exec(const char *program, const char *arg1,
1119
len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1120
cmd = os_malloc(len);
1123
res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1124
if (res < 0 || (size_t) res >= len) {
1128
cmd[len - 1] = '\0';
1131
#endif /* _WIN32_WCE */
1138
static void wpa_cli_action_process(const char *msg)
1141
char *copy = NULL, *id, *pos2;
1146
pos = os_strchr(pos, '>');
1153
if (str_match(pos, WPA_EVENT_CONNECTED)) {
1155
os_unsetenv("WPA_ID");
1156
os_unsetenv("WPA_ID_STR");
1157
os_unsetenv("WPA_CTRL_DIR");
1159
pos = os_strstr(pos, "[id=");
1161
copy = os_strdup(pos + 4);
1165
while (*pos2 && *pos2 != ' ')
1169
os_setenv("WPA_ID", id, 1);
1170
while (*pos2 && *pos2 != '=')
1175
while (*pos2 && *pos2 != ']')
1178
os_setenv("WPA_ID_STR", id, 1);
1182
os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1184
if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1185
wpa_cli_connected = 1;
1186
wpa_cli_last_id = new_id;
1187
wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1189
} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1190
if (wpa_cli_connected) {
1191
wpa_cli_connected = 0;
1192
wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1194
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1195
printf("wpa_supplicant is terminating - stop monitoring\n");
1201
#ifndef CONFIG_ANSI_C_EXTRA
1202
static void wpa_cli_action_cb(char *msg, size_t len)
1204
wpa_cli_action_process(msg);
1206
#endif /* CONFIG_ANSI_C_EXTRA */
1209
static void wpa_cli_reconnect(void)
1211
wpa_cli_close_connection();
1212
ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1214
printf("Connection to wpa_supplicant re-established\n");
1215
if (wpa_ctrl_attach(ctrl_conn) == 0) {
1216
wpa_cli_attached = 1;
1218
printf("Warning: Failed to attach to "
1219
"wpa_supplicant.\n");
1225
static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1229
if (ctrl_conn == NULL) {
1230
wpa_cli_reconnect();
1233
while (wpa_ctrl_pending(ctrl) > 0) {
1235
size_t len = sizeof(buf) - 1;
1236
if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1239
wpa_cli_action_process(buf);
1241
if (in_read && first)
1244
printf("%s\n", buf);
1247
printf("Could not read pending message.\n");
1252
if (wpa_ctrl_pending(ctrl) < 0) {
1253
printf("Connection to wpa_supplicant lost - trying to "
1255
wpa_cli_reconnect();
1260
#ifdef CONFIG_READLINE
1261
static char * wpa_cli_cmd_gen(const char *text, int state)
1268
len = os_strlen(text);
1271
while ((cmd = wpa_cli_commands[i].cmd)) {
1273
if (os_strncasecmp(cmd, text, len) == 0)
1274
return os_strdup(cmd);
1281
static char * wpa_cli_dummy_gen(const char *text, int state)
1287
static char ** wpa_cli_completion(const char *text, int start, int end)
1289
return rl_completion_matches(text, start == 0 ?
1290
wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1292
#endif /* CONFIG_READLINE */
1295
static void wpa_cli_interactive(void)
1298
char cmdbuf[256], *cmd, *argv[max_args], *pos;
1300
#ifdef CONFIG_READLINE
1301
char *home, *hfile = NULL;
1302
#endif /* CONFIG_READLINE */
1304
printf("\nInteractive mode\n\n");
1306
#ifdef CONFIG_READLINE
1307
rl_attempted_completion_function = wpa_cli_completion;
1308
home = getenv("HOME");
1310
const char *fname = ".wpa_cli_history";
1311
int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1312
hfile = os_malloc(hfile_len);
1315
res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1317
if (res >= 0 && res < hfile_len) {
1318
hfile[hfile_len - 1] = '\0';
1319
read_history(hfile);
1320
stifle_history(100);
1324
#endif /* CONFIG_READLINE */
1327
wpa_cli_recv_pending(ctrl_conn, 0, 0);
1328
#ifndef CONFIG_NATIVE_WINDOWS
1330
#endif /* CONFIG_NATIVE_WINDOWS */
1331
#ifdef CONFIG_READLINE
1332
cmd = readline("> ");
1335
while (next_history())
1337
h = previous_history();
1338
if (h == NULL || os_strcmp(cmd, h->line) != 0)
1342
#else /* CONFIG_READLINE */
1344
cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1345
#endif /* CONFIG_READLINE */
1346
#ifndef CONFIG_NATIVE_WINDOWS
1348
#endif /* CONFIG_NATIVE_WINDOWS */
1351
wpa_cli_recv_pending(ctrl_conn, 0, 0);
1353
while (*pos != '\0') {
1369
if (argc == max_args)
1372
char *pos2 = os_strrchr(pos, '"');
1376
while (*pos != '\0' && *pos != ' ')
1382
wpa_request(ctrl_conn, argc, argv);
1386
} while (!wpa_cli_quit);
1388
#ifdef CONFIG_READLINE
1390
/* Save command history, excluding lines that may contain
1397
while (*p == ' ' || *p == '\t')
1399
if (os_strncasecmp(p, "pa", 2) == 0 ||
1400
os_strncasecmp(p, "o", 1) == 0 ||
1401
os_strncasecmp(p, "n", 1)) {
1402
h = remove_history(where_history());
1408
h = current_history();
1413
write_history(hfile);
1416
#endif /* CONFIG_READLINE */
1420
static void wpa_cli_action(struct wpa_ctrl *ctrl)
1422
#ifdef CONFIG_ANSI_C_EXTRA
1423
/* TODO: ANSI C version(?) */
1424
printf("Action processing not supported in ANSI C build.\n");
1425
#else /* CONFIG_ANSI_C_EXTRA */
1429
char buf[256]; /* note: large enough to fit in unsolicited messages */
1432
fd = wpa_ctrl_get_fd(ctrl);
1434
while (!wpa_cli_quit) {
1439
res = select(fd + 1, &rfds, NULL, NULL, &tv);
1440
if (res < 0 && errno != EINTR) {
1445
if (FD_ISSET(fd, &rfds))
1446
wpa_cli_recv_pending(ctrl, 0, 1);
1448
/* verify that connection is still working */
1449
len = sizeof(buf) - 1;
1450
if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1451
wpa_cli_action_cb) < 0 ||
1452
len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1453
printf("wpa_supplicant did not reply to PING "
1454
"command - exiting\n");
1459
#endif /* CONFIG_ANSI_C_EXTRA */
1463
static void wpa_cli_cleanup(void)
1465
wpa_cli_close_connection();
1467
os_daemonize_terminate(pid_file);
1469
os_program_deinit();
1472
static void wpa_cli_terminate(int sig)
1479
#ifndef CONFIG_NATIVE_WINDOWS
1480
static void wpa_cli_alarm(int sig)
1482
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1483
printf("Connection to wpa_supplicant lost - trying to "
1485
wpa_cli_close_connection();
1488
wpa_cli_reconnect();
1490
wpa_cli_recv_pending(ctrl_conn, 1, 0);
1493
#endif /* CONFIG_NATIVE_WINDOWS */
1496
static char * wpa_cli_get_default_ifname(void)
1498
char *ifname = NULL;
1500
#ifdef CONFIG_CTRL_IFACE_UNIX
1501
struct dirent *dent;
1502
DIR *dir = opendir(ctrl_iface_dir);
1505
while ((dent = readdir(dir))) {
1506
#ifdef _DIRENT_HAVE_D_TYPE
1508
* Skip the file if it is not a socket. Also accept
1509
* DT_UNKNOWN (0) in case the C library or underlying
1510
* file system does not support d_type.
1512
if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1514
#endif /* _DIRENT_HAVE_D_TYPE */
1515
if (os_strcmp(dent->d_name, ".") == 0 ||
1516
os_strcmp(dent->d_name, "..") == 0)
1518
printf("Selected interface '%s'\n", dent->d_name);
1519
ifname = os_strdup(dent->d_name);
1523
#endif /* CONFIG_CTRL_IFACE_UNIX */
1525
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1526
char buf[2048], *pos;
1528
struct wpa_ctrl *ctrl;
1531
ctrl = wpa_ctrl_open(NULL);
1535
len = sizeof(buf) - 1;
1536
ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1539
pos = os_strchr(buf, '\n');
1542
ifname = os_strdup(buf);
1544
wpa_ctrl_close(ctrl);
1545
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1551
int main(int argc, char *argv[])
1554
int warning_displayed = 0;
1557
const char *global = NULL;
1559
if (os_program_init())
1563
c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1568
action_file = optarg;
1580
printf("%s\n", wpa_cli_version);
1583
os_free(ctrl_ifname);
1584
ctrl_ifname = os_strdup(optarg);
1587
ctrl_iface_dir = optarg;
1598
interactive = (argc == optind) && (action_file == NULL);
1601
printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1604
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1605
ctrl_conn = wpa_ctrl_open(NULL);
1606
#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1607
ctrl_conn = wpa_ctrl_open(global);
1608
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1609
if (ctrl_conn == NULL) {
1610
perror("Failed to connect to wpa_supplicant - "
1617
if (ctrl_ifname == NULL)
1618
ctrl_ifname = wpa_cli_get_default_ifname();
1619
ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1621
if (warning_displayed)
1622
printf("Connection established.\n");
1627
perror("Failed to connect to wpa_supplicant - "
1632
if (!warning_displayed) {
1633
printf("Could not connect to wpa_supplicant - "
1635
warning_displayed = 1;
1642
signal(SIGINT, wpa_cli_terminate);
1643
signal(SIGTERM, wpa_cli_terminate);
1644
#endif /* _WIN32_WCE */
1645
#ifndef CONFIG_NATIVE_WINDOWS
1646
signal(SIGALRM, wpa_cli_alarm);
1647
#endif /* CONFIG_NATIVE_WINDOWS */
1649
if (interactive || action_file) {
1650
if (wpa_ctrl_attach(ctrl_conn) == 0) {
1651
wpa_cli_attached = 1;
1653
printf("Warning: Failed to attach to "
1654
"wpa_supplicant.\n");
1660
if (daemonize && os_daemonize(pid_file))
1664
wpa_cli_interactive();
1665
else if (action_file)
1666
wpa_cli_action(ctrl_conn);
1668
wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1670
os_free(ctrl_ifname);
1676
#else /* CONFIG_CTRL_IFACE */
1677
int main(int argc, char *argv[])
1679
printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1682
#endif /* CONFIG_CTRL_IFACE */