2
* WPA Supplicant - command line interface for wpa_supplicant daemon
3
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
9
* Alternatively, this software may be distributed under the terms of BSD
12
* See README and COPYING for more details.
17
#ifdef CONFIG_CTRL_IFACE
19
#ifdef CONFIG_CTRL_IFACE_UNIX
21
#endif /* CONFIG_CTRL_IFACE_UNIX */
22
#ifdef CONFIG_READLINE
23
#include <readline/readline.h>
24
#include <readline/history.h>
25
#endif /* CONFIG_READLINE */
32
static const char *wpa_cli_version =
33
"wpa_cli v" VERSION_STR "\n"
34
"Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> and contributors";
37
static const char *wpa_cli_license =
38
"This program is free software. You can distribute it and/or modify it\n"
39
"under the terms of the GNU General Public License version 2.\n"
41
"Alternatively, this software may be distributed under the terms of the\n"
42
"BSD license. See README and COPYING for more details.\n";
44
static const char *wpa_cli_full_license =
45
"This program is free software; you can redistribute it and/or modify\n"
46
"it under the terms of the GNU General Public License version 2 as\n"
47
"published by the Free Software Foundation.\n"
49
"This program is distributed in the hope that it will be useful,\n"
50
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
52
"GNU General Public License for more details.\n"
54
"You should have received a copy of the GNU General Public License\n"
55
"along with this program; if not, write to the Free Software\n"
56
"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
58
"Alternatively, this software may be distributed under the terms of the\n"
61
"Redistribution and use in source and binary forms, with or without\n"
62
"modification, are permitted provided that the following conditions are\n"
65
"1. Redistributions of source code must retain the above copyright\n"
66
" notice, this list of conditions and the following disclaimer.\n"
68
"2. Redistributions in binary form must reproduce the above copyright\n"
69
" notice, this list of conditions and the following disclaimer in the\n"
70
" documentation and/or other materials provided with the distribution.\n"
72
"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73
" names of its contributors may be used to endorse or promote products\n"
74
" derived from this software without specific prior written permission.\n"
76
"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77
"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78
"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79
"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80
"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81
"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82
"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83
"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84
"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85
"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
89
static const char *commands_help =
91
" status [verbose] = get current WPA/EAPOL/EAP status\n"
92
" mib = get MIB variables (dot1x, dot11)\n"
93
" help = show this usage help\n"
94
" interface [ifname] = show interfaces/select interface\n"
95
" level <debug level> = change debug level\n"
96
" license = show full wpa_cli license\n"
97
" logoff = IEEE 802.1X EAPOL state machine logoff\n"
98
" logon = IEEE 802.1X EAPOL state machine logon\n"
99
" set = set variables (shows list of variables when run without arguments)\n"
100
" pmksa = show PMKSA cache\n"
101
" reassociate = force reassociation\n"
102
" reconfigure = force wpa_supplicant to re-read its configuration file\n"
103
" preauthenticate <BSSID> = force preauthentication\n"
104
" identity <network id> <identity> = configure identity for an SSID\n"
105
" password <network id> <password> = configure password for an SSID\n"
106
" new_password <network id> <password> = change password for an SSID\n"
107
" pin <network id> <pin> = configure pin for an SSID\n"
108
" otp <network id> <password> = configure one-time-password for an SSID\n"
109
" passphrase <network id> <passphrase> = configure private key passphrase\n"
111
" bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
112
" list_networks = list configured networks\n"
113
" select_network <network id> = select a network (disable others)\n"
114
" enable_network <network id> = enable a network\n"
115
" disable_network <network id> = disable a network\n"
116
" add_network = add a network\n"
117
" remove_network <network id> = remove a network\n"
118
" set_network <network id> <variable> <value> = set network variables "
120
" list of variables when run without arguments)\n"
121
" get_network <network id> <variable> = get network variables\n"
122
" save_config = save the current configuration\n"
123
" disconnect = disconnect and wait for reassociate/reconnect command before\n "
125
" reconnect = like reassociate, but only takes effect if already "
127
" scan = request new BSS scan\n"
128
" scan_results = get latest scan results\n"
129
" bss <<idx> | <bssid>> = get detailed scan result info\n"
130
" get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
132
" ap_scan <value> = set ap_scan parameter\n"
133
" stkstart <addr> = request STK negotiation with <addr>\n"
134
" ft_ds <addr> = request over-the-DS FT with <addr>\n"
135
" terminate = terminate wpa_supplicant\n"
136
" quit = exit wpa_cli\n";
138
static struct wpa_ctrl *ctrl_conn;
139
static int wpa_cli_quit = 0;
140
static int wpa_cli_attached = 0;
141
static int wpa_cli_connected = 0;
142
static int wpa_cli_last_id = 0;
143
static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
144
static char *ctrl_ifname = NULL;
145
static const char *pid_file = NULL;
146
static const char *action_file = NULL;
149
static void usage(void)
151
printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
152
"[-a<action file>] \\\n"
153
" [-P<pid file>] [-g<global ctrl>] [command..]\n"
154
" -h = help (show this usage text)\n"
155
" -v = shown version information\n"
156
" -a = run in daemon mode executing the action file based on "
159
" -B = run a daemon in the background\n"
160
" default path: /var/run/wpa_supplicant\n"
161
" default interface: first interface found in socket path\n"
167
static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
169
#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
170
ctrl_conn = wpa_ctrl_open(ifname);
172
#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
179
flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
180
cfile = os_malloc(flen);
183
res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
184
if (res < 0 || res >= flen) {
189
ctrl_conn = wpa_ctrl_open(cfile);
192
#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
196
static void wpa_cli_close_connection(void)
198
if (ctrl_conn == NULL)
201
if (wpa_cli_attached) {
202
wpa_ctrl_detach(ctrl_conn);
203
wpa_cli_attached = 0;
205
wpa_ctrl_close(ctrl_conn);
210
static void wpa_cli_msg_cb(char *msg, size_t len)
216
static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
222
if (ctrl_conn == NULL) {
223
printf("Not connected to wpa_supplicant - command dropped.\n");
226
len = sizeof(buf) - 1;
227
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
230
printf("'%s' command timed out.\n", cmd);
232
} else if (ret < 0) {
233
printf("'%s' command failed.\n", cmd);
244
static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
246
return _wpa_ctrl_command(ctrl, cmd, 1);
250
static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
252
int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
253
return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
257
static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
259
return wpa_ctrl_command(ctrl, "PING");
263
static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
265
return wpa_ctrl_command(ctrl, "MIB");
269
static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
271
return wpa_ctrl_command(ctrl, "PMKSA");
275
static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
277
printf("%s", commands_help);
282
static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
284
printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
289
static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
296
static void wpa_cli_show_variables(void)
298
printf("set variables:\n"
299
" EAPOL::heldPeriod (EAPOL state machine held period, "
301
" EAPOL::authPeriod (EAPOL state machine authentication "
302
"period, in seconds)\n"
303
" EAPOL::startPeriod (EAPOL state machine start period, in "
305
" EAPOL::maxStart (EAPOL state machine maximum start "
307
printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
309
" dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
310
" threshold\n\tpercentage)\n"
311
" dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
312
"security\n\tassociation in seconds)\n");
316
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
322
wpa_cli_show_variables();
327
printf("Invalid SET command: needs two arguments (variable "
328
"name and value)\n");
332
res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
333
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
334
printf("Too long SET command.\n");
337
return wpa_ctrl_command(ctrl, cmd);
341
static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
343
return wpa_ctrl_command(ctrl, "LOGOFF");
347
static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
349
return wpa_ctrl_command(ctrl, "LOGON");
353
static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
356
return wpa_ctrl_command(ctrl, "REASSOCIATE");
360
static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
367
printf("Invalid PREAUTH command: needs one argument "
372
res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
373
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
374
printf("Too long PREAUTH command.\n");
377
return wpa_ctrl_command(ctrl, cmd);
381
static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
387
printf("Invalid AP_SCAN command: needs one argument (ap_scan "
391
res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
392
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
393
printf("Too long AP_SCAN command.\n");
396
return wpa_ctrl_command(ctrl, cmd);
400
static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
407
printf("Invalid STKSTART command: needs one argument "
408
"(Peer STA MAC address)\n");
412
res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
413
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
414
printf("Too long STKSTART command.\n");
417
return wpa_ctrl_command(ctrl, cmd);
421
static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
427
printf("Invalid FT_DS command: needs one argument "
428
"(Target AP MAC address)\n");
432
res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
433
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
434
printf("Too long FT_DS command.\n");
437
return wpa_ctrl_command(ctrl, cmd);
441
static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
447
printf("Invalid LEVEL command: needs one argument (debug "
451
res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
452
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
453
printf("Too long LEVEL command.\n");
456
return wpa_ctrl_command(ctrl, cmd);
460
static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
462
char cmd[256], *pos, *end;
466
printf("Invalid IDENTITY command: needs two arguments "
467
"(network id and identity)\n");
471
end = cmd + sizeof(cmd);
473
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
475
if (ret < 0 || ret >= end - pos) {
476
printf("Too long IDENTITY command.\n");
480
for (i = 2; i < argc; i++) {
481
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
482
if (ret < 0 || ret >= end - pos) {
483
printf("Too long IDENTITY command.\n");
489
return wpa_ctrl_command(ctrl, cmd);
493
static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
495
char cmd[256], *pos, *end;
499
printf("Invalid PASSWORD command: needs two arguments "
500
"(network id and password)\n");
504
end = cmd + sizeof(cmd);
506
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
508
if (ret < 0 || ret >= end - pos) {
509
printf("Too long PASSWORD command.\n");
513
for (i = 2; i < argc; i++) {
514
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
515
if (ret < 0 || ret >= end - pos) {
516
printf("Too long PASSWORD command.\n");
522
return wpa_ctrl_command(ctrl, cmd);
526
static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
529
char cmd[256], *pos, *end;
533
printf("Invalid NEW_PASSWORD command: needs two arguments "
534
"(network id and password)\n");
538
end = cmd + sizeof(cmd);
540
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
542
if (ret < 0 || ret >= end - pos) {
543
printf("Too long NEW_PASSWORD command.\n");
547
for (i = 2; i < argc; i++) {
548
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
549
if (ret < 0 || ret >= end - pos) {
550
printf("Too long NEW_PASSWORD command.\n");
556
return wpa_ctrl_command(ctrl, cmd);
560
static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
562
char cmd[256], *pos, *end;
566
printf("Invalid PIN command: needs two arguments "
567
"(network id and pin)\n");
571
end = cmd + sizeof(cmd);
573
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
575
if (ret < 0 || ret >= end - pos) {
576
printf("Too long PIN command.\n");
580
for (i = 2; i < argc; i++) {
581
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
582
if (ret < 0 || ret >= end - pos) {
583
printf("Too long PIN command.\n");
588
return wpa_ctrl_command(ctrl, cmd);
592
static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
594
char cmd[256], *pos, *end;
598
printf("Invalid OTP command: needs two arguments (network "
599
"id and password)\n");
603
end = cmd + sizeof(cmd);
605
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
607
if (ret < 0 || ret >= end - pos) {
608
printf("Too long OTP command.\n");
612
for (i = 2; i < argc; i++) {
613
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
614
if (ret < 0 || ret >= end - pos) {
615
printf("Too long OTP command.\n");
621
return wpa_ctrl_command(ctrl, cmd);
625
static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
628
char cmd[256], *pos, *end;
632
printf("Invalid PASSPHRASE command: needs two arguments "
633
"(network id and passphrase)\n");
637
end = cmd + sizeof(cmd);
639
ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
641
if (ret < 0 || ret >= end - pos) {
642
printf("Too long PASSPHRASE command.\n");
646
for (i = 2; i < argc; i++) {
647
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
648
if (ret < 0 || ret >= end - pos) {
649
printf("Too long PASSPHRASE command.\n");
655
return wpa_ctrl_command(ctrl, cmd);
659
static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
661
char cmd[256], *pos, *end;
665
printf("Invalid BSSID command: needs two arguments (network "
670
end = cmd + sizeof(cmd);
672
ret = os_snprintf(pos, end - pos, "BSSID");
673
if (ret < 0 || ret >= end - pos) {
674
printf("Too long BSSID command.\n");
678
for (i = 0; i < argc; i++) {
679
ret = os_snprintf(pos, end - pos, " %s", argv[i]);
680
if (ret < 0 || ret >= end - pos) {
681
printf("Too long BSSID command.\n");
687
return wpa_ctrl_command(ctrl, cmd);
691
static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
694
return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
698
static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
705
printf("Invalid SELECT_NETWORK command: needs one argument "
710
res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
711
if (res < 0 || (size_t) res >= sizeof(cmd))
713
cmd[sizeof(cmd) - 1] = '\0';
715
return wpa_ctrl_command(ctrl, cmd);
719
static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
726
printf("Invalid ENABLE_NETWORK command: needs one argument "
731
res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
732
if (res < 0 || (size_t) res >= sizeof(cmd))
734
cmd[sizeof(cmd) - 1] = '\0';
736
return wpa_ctrl_command(ctrl, cmd);
740
static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
747
printf("Invalid DISABLE_NETWORK command: needs one argument "
752
res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
753
if (res < 0 || (size_t) res >= sizeof(cmd))
755
cmd[sizeof(cmd) - 1] = '\0';
757
return wpa_ctrl_command(ctrl, cmd);
761
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
764
return wpa_ctrl_command(ctrl, "ADD_NETWORK");
768
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
775
printf("Invalid REMOVE_NETWORK command: needs one argument "
780
res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
781
if (res < 0 || (size_t) res >= sizeof(cmd))
783
cmd[sizeof(cmd) - 1] = '\0';
785
return wpa_ctrl_command(ctrl, cmd);
789
static void wpa_cli_show_network_variables(void)
791
printf("set_network variables:\n"
792
" ssid (network name, SSID)\n"
793
" psk (WPA passphrase or pre-shared key)\n"
794
" key_mgmt (key management protocol)\n"
795
" identity (EAP identity)\n"
796
" password (EAP password)\n"
799
"Note: Values are entered in the same format as the "
800
"configuration file is using,\n"
801
"i.e., strings values need to be inside double quotation "
803
"For example: set_network 1 ssid \"network name\"\n"
805
"Please see wpa_supplicant.conf documentation for full list "
806
"of\navailable variables.\n");
810
static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
817
wpa_cli_show_network_variables();
822
printf("Invalid SET_NETWORK command: needs three arguments\n"
823
"(network id, variable name, and value)\n");
827
res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
828
argv[0], argv[1], argv[2]);
829
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
830
printf("Too long SET_NETWORK command.\n");
833
return wpa_ctrl_command(ctrl, cmd);
837
static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
844
wpa_cli_show_network_variables();
849
printf("Invalid GET_NETWORK command: needs two arguments\n"
850
"(network id and variable name)\n");
854
res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
856
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857
printf("Too long GET_NETWORK command.\n");
860
return wpa_ctrl_command(ctrl, cmd);
864
static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
867
return wpa_ctrl_command(ctrl, "DISCONNECT");
871
static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
874
return wpa_ctrl_command(ctrl, "RECONNECT");
878
static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
881
return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
885
static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
887
return wpa_ctrl_command(ctrl, "SCAN");
891
static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
894
return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
898
static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
904
printf("Invalid BSS command: need one argument (index or "
909
res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
910
if (res < 0 || (size_t) res >= sizeof(cmd))
912
cmd[sizeof(cmd) - 1] = '\0';
914
return wpa_ctrl_command(ctrl, cmd);
918
static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
924
if (argc < 1 || argc > 2) {
925
printf("Invalid GET_CAPABILITY command: need either one or "
930
if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
931
printf("Invalid GET_CAPABILITY command: second argument, "
932
"if any, must be 'strict'\n");
936
res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
937
(argc == 2) ? " strict" : "");
938
if (res < 0 || (size_t) res >= sizeof(cmd))
940
cmd[sizeof(cmd) - 1] = '\0';
942
return wpa_ctrl_command(ctrl, cmd);
946
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
948
printf("Available interfaces:\n");
949
return wpa_ctrl_command(ctrl, "INTERFACES");
953
static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
956
wpa_cli_list_interfaces(ctrl);
960
wpa_cli_close_connection();
961
os_free(ctrl_ifname);
962
ctrl_ifname = os_strdup(argv[0]);
964
if (wpa_cli_open_connection(ctrl_ifname)) {
965
printf("Connected to interface '%s.\n", ctrl_ifname);
966
if (wpa_ctrl_attach(ctrl_conn) == 0) {
967
wpa_cli_attached = 1;
969
printf("Warning: Failed to attach to "
970
"wpa_supplicant.\n");
973
printf("Could not connect to interface '%s' - re-trying\n",
980
static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
983
return wpa_ctrl_command(ctrl, "RECONFIGURE");
987
static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
990
return wpa_ctrl_command(ctrl, "TERMINATE");
994
static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1001
printf("Invalid INTERFACE_ADD command: needs at least one "
1002
"argument (interface name)\n"
1003
"All arguments: ifname confname driver ctrl_interface "
1004
"driver_param bridge_name\n");
1009
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1010
* <driver_param>TAB<bridge_name>
1012
res = os_snprintf(cmd, sizeof(cmd),
1013
"INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1015
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1016
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1017
argc > 5 ? argv[5] : "");
1018
if (res < 0 || (size_t) res >= sizeof(cmd))
1020
cmd[sizeof(cmd) - 1] = '\0';
1021
return wpa_ctrl_command(ctrl, cmd);
1025
static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1032
printf("Invalid INTERFACE_REMOVE command: needs one argument "
1033
"(interface name)\n");
1037
res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1038
if (res < 0 || (size_t) res >= sizeof(cmd))
1040
cmd[sizeof(cmd) - 1] = '\0';
1041
return wpa_ctrl_command(ctrl, cmd);
1045
struct wpa_cli_cmd {
1047
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1050
static struct wpa_cli_cmd wpa_cli_commands[] = {
1051
{ "status", wpa_cli_cmd_status },
1052
{ "ping", wpa_cli_cmd_ping },
1053
{ "mib", wpa_cli_cmd_mib },
1054
{ "help", wpa_cli_cmd_help },
1055
{ "interface", wpa_cli_cmd_interface },
1056
{ "level", wpa_cli_cmd_level },
1057
{ "license", wpa_cli_cmd_license },
1058
{ "quit", wpa_cli_cmd_quit },
1059
{ "set", wpa_cli_cmd_set },
1060
{ "logon", wpa_cli_cmd_logon },
1061
{ "logoff", wpa_cli_cmd_logoff },
1062
{ "pmksa", wpa_cli_cmd_pmksa },
1063
{ "reassociate", wpa_cli_cmd_reassociate },
1064
{ "preauthenticate", wpa_cli_cmd_preauthenticate },
1065
{ "identity", wpa_cli_cmd_identity },
1066
{ "password", wpa_cli_cmd_password },
1067
{ "new_password", wpa_cli_cmd_new_password },
1068
{ "pin", wpa_cli_cmd_pin },
1069
{ "otp", wpa_cli_cmd_otp },
1070
{ "passphrase", wpa_cli_cmd_passphrase },
1071
{ "bssid", wpa_cli_cmd_bssid },
1072
{ "list_networks", wpa_cli_cmd_list_networks },
1073
{ "select_network", wpa_cli_cmd_select_network },
1074
{ "enable_network", wpa_cli_cmd_enable_network },
1075
{ "disable_network", wpa_cli_cmd_disable_network },
1076
{ "add_network", wpa_cli_cmd_add_network },
1077
{ "remove_network", wpa_cli_cmd_remove_network },
1078
{ "set_network", wpa_cli_cmd_set_network },
1079
{ "get_network", wpa_cli_cmd_get_network },
1080
{ "save_config", wpa_cli_cmd_save_config },
1081
{ "disconnect", wpa_cli_cmd_disconnect },
1082
{ "reconnect", wpa_cli_cmd_reconnect },
1083
{ "scan", wpa_cli_cmd_scan },
1084
{ "scan_results", wpa_cli_cmd_scan_results },
1085
{ "bss", wpa_cli_cmd_bss },
1086
{ "get_capability", wpa_cli_cmd_get_capability },
1087
{ "reconfigure", wpa_cli_cmd_reconfigure },
1088
{ "terminate", wpa_cli_cmd_terminate },
1089
{ "interface_add", wpa_cli_cmd_interface_add },
1090
{ "interface_remove", wpa_cli_cmd_interface_remove },
1091
{ "ap_scan", wpa_cli_cmd_ap_scan },
1092
{ "stkstart", wpa_cli_cmd_stkstart },
1093
{ "ft_ds", wpa_cli_cmd_ft_ds },
1098
static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1100
struct wpa_cli_cmd *cmd, *match = NULL;
1105
cmd = wpa_cli_commands;
1107
if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1110
if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1111
/* we have an exact match */
1121
printf("Ambiguous command '%s'; possible commands:", argv[0]);
1122
cmd = wpa_cli_commands;
1124
if (os_strncasecmp(cmd->cmd, argv[0],
1125
os_strlen(argv[0])) == 0) {
1126
printf(" %s", cmd->cmd);
1132
} else if (count == 0) {
1133
printf("Unknown command '%s'\n", argv[0]);
1136
ret = match->handler(ctrl, argc - 1, &argv[1]);
1143
static int str_match(const char *a, const char *b)
1145
return os_strncmp(a, b, os_strlen(b)) == 0;
1149
static int wpa_cli_exec(const char *program, const char *arg1,
1156
len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1157
cmd = os_malloc(len);
1160
res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1161
if (res < 0 || (size_t) res >= len) {
1165
cmd[len - 1] = '\0';
1168
#endif /* _WIN32_WCE */
1175
static void wpa_cli_action_process(const char *msg)
1178
char *copy = NULL, *id, *pos2;
1183
pos = os_strchr(pos, '>');
1190
if (str_match(pos, WPA_EVENT_CONNECTED)) {
1192
os_unsetenv("WPA_ID");
1193
os_unsetenv("WPA_ID_STR");
1194
os_unsetenv("WPA_CTRL_DIR");
1196
pos = os_strstr(pos, "[id=");
1198
copy = os_strdup(pos + 4);
1202
while (*pos2 && *pos2 != ' ')
1206
os_setenv("WPA_ID", id, 1);
1207
while (*pos2 && *pos2 != '=')
1212
while (*pos2 && *pos2 != ']')
1215
os_setenv("WPA_ID_STR", id, 1);
1219
os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1221
if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1222
wpa_cli_connected = 1;
1223
wpa_cli_last_id = new_id;
1224
wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1226
} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1227
if (wpa_cli_connected) {
1228
wpa_cli_connected = 0;
1229
wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1231
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1232
printf("wpa_supplicant is terminating - stop monitoring\n");
1238
#ifndef CONFIG_ANSI_C_EXTRA
1239
static void wpa_cli_action_cb(char *msg, size_t len)
1241
wpa_cli_action_process(msg);
1243
#endif /* CONFIG_ANSI_C_EXTRA */
1246
static void wpa_cli_reconnect(void)
1248
wpa_cli_close_connection();
1249
ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1251
printf("Connection to wpa_supplicant re-established\n");
1252
if (wpa_ctrl_attach(ctrl_conn) == 0) {
1253
wpa_cli_attached = 1;
1255
printf("Warning: Failed to attach to "
1256
"wpa_supplicant.\n");
1262
static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1266
if (ctrl_conn == NULL) {
1267
wpa_cli_reconnect();
1270
while (wpa_ctrl_pending(ctrl) > 0) {
1272
size_t len = sizeof(buf) - 1;
1273
if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1276
wpa_cli_action_process(buf);
1278
if (in_read && first)
1281
printf("%s\n", buf);
1284
printf("Could not read pending message.\n");
1289
if (wpa_ctrl_pending(ctrl) < 0) {
1290
printf("Connection to wpa_supplicant lost - trying to "
1292
wpa_cli_reconnect();
1297
#ifdef CONFIG_READLINE
1298
static char * wpa_cli_cmd_gen(const char *text, int state)
1305
len = os_strlen(text);
1308
while ((cmd = wpa_cli_commands[i].cmd)) {
1310
if (os_strncasecmp(cmd, text, len) == 0)
1311
return os_strdup(cmd);
1318
static char * wpa_cli_dummy_gen(const char *text, int state)
1324
static char ** wpa_cli_completion(const char *text, int start, int end)
1326
return rl_completion_matches(text, start == 0 ?
1327
wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1329
#endif /* CONFIG_READLINE */
1332
static void wpa_cli_interactive(void)
1335
char cmdbuf[256], *cmd, *argv[max_args], *pos;
1337
#ifdef CONFIG_READLINE
1338
char *home, *hfile = NULL;
1339
#endif /* CONFIG_READLINE */
1341
printf("\nInteractive mode\n\n");
1343
#ifdef CONFIG_READLINE
1344
rl_attempted_completion_function = wpa_cli_completion;
1345
home = getenv("HOME");
1347
const char *fname = ".wpa_cli_history";
1348
int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1349
hfile = os_malloc(hfile_len);
1352
res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1354
if (res >= 0 && res < hfile_len) {
1355
hfile[hfile_len - 1] = '\0';
1356
read_history(hfile);
1357
stifle_history(100);
1361
#endif /* CONFIG_READLINE */
1364
wpa_cli_recv_pending(ctrl_conn, 0, 0);
1365
#ifndef CONFIG_NATIVE_WINDOWS
1367
#endif /* CONFIG_NATIVE_WINDOWS */
1368
#ifdef CONFIG_READLINE
1369
cmd = readline("> ");
1372
while (next_history())
1374
h = previous_history();
1375
if (h == NULL || os_strcmp(cmd, h->line) != 0)
1379
#else /* CONFIG_READLINE */
1381
cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1382
#endif /* CONFIG_READLINE */
1383
#ifndef CONFIG_NATIVE_WINDOWS
1385
#endif /* CONFIG_NATIVE_WINDOWS */
1388
wpa_cli_recv_pending(ctrl_conn, 0, 0);
1390
while (*pos != '\0') {
1406
if (argc == max_args)
1409
char *pos2 = os_strrchr(pos, '"');
1413
while (*pos != '\0' && *pos != ' ')
1419
wpa_request(ctrl_conn, argc, argv);
1423
} while (!wpa_cli_quit);
1425
#ifdef CONFIG_READLINE
1427
/* Save command history, excluding lines that may contain
1434
while (*p == ' ' || *p == '\t')
1436
if (os_strncasecmp(p, "pa", 2) == 0 ||
1437
os_strncasecmp(p, "o", 1) == 0 ||
1438
os_strncasecmp(p, "n", 1)) {
1439
h = remove_history(where_history());
1445
h = current_history();
1450
write_history(hfile);
1453
#endif /* CONFIG_READLINE */
1457
static void wpa_cli_action(struct wpa_ctrl *ctrl)
1459
#ifdef CONFIG_ANSI_C_EXTRA
1460
/* TODO: ANSI C version(?) */
1461
printf("Action processing not supported in ANSI C build.\n");
1462
#else /* CONFIG_ANSI_C_EXTRA */
1466
char buf[256]; /* note: large enough to fit in unsolicited messages */
1469
fd = wpa_ctrl_get_fd(ctrl);
1471
while (!wpa_cli_quit) {
1476
res = select(fd + 1, &rfds, NULL, NULL, &tv);
1477
if (res < 0 && errno != EINTR) {
1482
if (FD_ISSET(fd, &rfds))
1483
wpa_cli_recv_pending(ctrl, 0, 1);
1485
/* verify that connection is still working */
1486
len = sizeof(buf) - 1;
1487
if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1488
wpa_cli_action_cb) < 0 ||
1489
len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1490
printf("wpa_supplicant did not reply to PING "
1491
"command - exiting\n");
1496
#endif /* CONFIG_ANSI_C_EXTRA */
1500
static void wpa_cli_cleanup(void)
1502
wpa_cli_close_connection();
1504
os_daemonize_terminate(pid_file);
1506
os_program_deinit();
1509
static void wpa_cli_terminate(int sig)
1516
#ifndef CONFIG_NATIVE_WINDOWS
1517
static void wpa_cli_alarm(int sig)
1519
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1520
printf("Connection to wpa_supplicant lost - trying to "
1522
wpa_cli_close_connection();
1525
wpa_cli_reconnect();
1527
wpa_cli_recv_pending(ctrl_conn, 1, 0);
1530
#endif /* CONFIG_NATIVE_WINDOWS */
1533
static char * wpa_cli_get_default_ifname(void)
1535
char *ifname = NULL;
1537
#ifdef CONFIG_CTRL_IFACE_UNIX
1538
struct dirent *dent;
1539
DIR *dir = opendir(ctrl_iface_dir);
1542
while ((dent = readdir(dir))) {
1543
#ifdef _DIRENT_HAVE_D_TYPE
1545
* Skip the file if it is not a socket. Also accept
1546
* DT_UNKNOWN (0) in case the C library or underlying
1547
* file system does not support d_type.
1549
if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1551
#endif /* _DIRENT_HAVE_D_TYPE */
1552
if (os_strcmp(dent->d_name, ".") == 0 ||
1553
os_strcmp(dent->d_name, "..") == 0)
1555
printf("Selected interface '%s'\n", dent->d_name);
1556
ifname = os_strdup(dent->d_name);
1560
#endif /* CONFIG_CTRL_IFACE_UNIX */
1562
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1563
char buf[2048], *pos;
1565
struct wpa_ctrl *ctrl;
1568
ctrl = wpa_ctrl_open(NULL);
1572
len = sizeof(buf) - 1;
1573
ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1576
pos = os_strchr(buf, '\n');
1579
ifname = os_strdup(buf);
1581
wpa_ctrl_close(ctrl);
1582
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1588
int main(int argc, char *argv[])
1591
int warning_displayed = 0;
1595
const char *global = NULL;
1597
if (os_program_init())
1601
c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1606
action_file = optarg;
1618
printf("%s\n", wpa_cli_version);
1621
os_free(ctrl_ifname);
1622
ctrl_ifname = os_strdup(optarg);
1625
ctrl_iface_dir = optarg;
1636
interactive = (argc == optind) && (action_file == NULL);
1639
printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1642
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1643
ctrl_conn = wpa_ctrl_open(NULL);
1644
#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1645
ctrl_conn = wpa_ctrl_open(global);
1646
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1647
if (ctrl_conn == NULL) {
1648
perror("Failed to connect to wpa_supplicant - "
1655
if (ctrl_ifname == NULL)
1656
ctrl_ifname = wpa_cli_get_default_ifname();
1657
ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1659
if (warning_displayed)
1660
printf("Connection established.\n");
1665
perror("Failed to connect to wpa_supplicant - "
1670
if (!warning_displayed) {
1671
printf("Could not connect to wpa_supplicant - "
1673
warning_displayed = 1;
1680
signal(SIGINT, wpa_cli_terminate);
1681
signal(SIGTERM, wpa_cli_terminate);
1682
#endif /* _WIN32_WCE */
1683
#ifndef CONFIG_NATIVE_WINDOWS
1684
signal(SIGALRM, wpa_cli_alarm);
1685
#endif /* CONFIG_NATIVE_WINDOWS */
1687
if (interactive || action_file) {
1688
if (wpa_ctrl_attach(ctrl_conn) == 0) {
1689
wpa_cli_attached = 1;
1691
printf("Warning: Failed to attach to "
1692
"wpa_supplicant.\n");
1698
if (daemonize && os_daemonize(pid_file))
1702
wpa_cli_interactive();
1703
else if (action_file)
1704
wpa_cli_action(ctrl_conn);
1706
ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1708
os_free(ctrl_ifname);
1714
#else /* CONFIG_CTRL_IFACE */
1715
int main(int argc, char *argv[])
1717
printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1720
#endif /* CONFIG_CTRL_IFACE */