Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / wpa / wpa_supplicant / wpa_cli.c
blob16566ac62d4df9b985334109b1d11dfd08ca0c62
1 /*
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
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #ifdef CONFIG_CTRL_IFACE
19 #ifdef CONFIG_CTRL_IFACE_UNIX
20 #include <dirent.h>
21 #endif /* CONFIG_CTRL_IFACE_UNIX */
22 #ifdef CONFIG_READLINE
23 #include <readline/readline.h>
24 #include <readline/history.h>
25 #endif /* CONFIG_READLINE */
27 #include "wpa_ctrl.h"
28 #include "common.h"
29 #include "version.h"
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"
40 "\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"
48 "\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"
53 "\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"
57 "\n"
58 "Alternatively, this software may be distributed under the terms of the\n"
59 "BSD license.\n"
60 "\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"
63 "met:\n"
64 "\n"
65 "1. Redistributions of source code must retain the above copyright\n"
66 " notice, this list of conditions and the following disclaimer.\n"
67 "\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"
71 "\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"
75 "\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"
87 "\n";
89 static const char *commands_help =
90 "commands:\n"
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"
110 " for an SSID\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 "
119 "(shows\n"
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 "
124 " connecting\n"
125 " reconnect = like reassociate, but only takes effect if already "
126 "disconnected\n"
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> = "
131 "get capabilies\n"
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 "
157 "events from\n"
158 " wpa_supplicant\n"
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"
162 "%s",
163 commands_help);
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);
171 return ctrl_conn;
172 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
173 char *cfile;
174 int flen, res;
176 if (ifname == NULL)
177 return NULL;
179 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
180 cfile = os_malloc(flen);
181 if (cfile == NULL)
182 return NULL;
183 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
184 if (res < 0 || res >= flen) {
185 os_free(cfile);
186 return NULL;
189 ctrl_conn = wpa_ctrl_open(cfile);
190 os_free(cfile);
191 return ctrl_conn;
192 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
196 static void wpa_cli_close_connection(void)
198 if (ctrl_conn == NULL)
199 return;
201 if (wpa_cli_attached) {
202 wpa_ctrl_detach(ctrl_conn);
203 wpa_cli_attached = 0;
205 wpa_ctrl_close(ctrl_conn);
206 ctrl_conn = NULL;
210 static const char *skip_priority(const char *msg)
212 const char *pos = msg;
214 if (*msg != '<')
215 return msg;
217 for (pos = msg + 1; isdigit((unsigned char)*pos); pos++)
218 continue;
220 if (*pos != '>')
221 return msg;
223 return ++pos;
226 static const char *fmttime(char *buf, size_t buflen)
228 struct timeval tv;
229 struct tm tm;
230 time_t t;
232 if (buflen <= 8)
233 return NULL;
235 (void)gettimeofday(&tv, NULL);
236 t = (time_t)tv.tv_sec;
237 (void)localtime_r(&t, &tm);
238 (void)strftime(buf, buflen, "%H:%M:%S", &tm);
239 (void)snprintf(buf + 8, buflen - 8, ".%.3d", (int)(tv.tv_usec / 1000));
240 return buf;
243 static void wpa_cli_msg_cb(char *msg, size_t len)
245 char tbuf[32];
246 printf("%s: %s\n", fmttime(tbuf, sizeof(tbuf)), skip_priority(msg));
250 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
252 char buf[2048];
253 size_t len;
254 int ret;
256 if (ctrl_conn == NULL) {
257 printf("Not connected to wpa_supplicant - command dropped.\n");
258 return -1;
260 len = sizeof(buf) - 1;
261 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
262 wpa_cli_msg_cb);
263 if (ret == -2) {
264 printf("'%s' command timed out.\n", cmd);
265 return -2;
266 } else if (ret < 0) {
267 printf("'%s' command failed.\n", cmd);
268 return -1;
270 if (print) {
271 buf[len] = '\0';
272 wpa_cli_msg_cb(buf, 0);
274 return 0;
278 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
280 return _wpa_ctrl_command(ctrl, cmd, 1);
284 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
286 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
287 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
291 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
293 return wpa_ctrl_command(ctrl, "PING");
297 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
299 return wpa_ctrl_command(ctrl, "MIB");
303 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
305 return wpa_ctrl_command(ctrl, "PMKSA");
309 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
311 printf("%s", commands_help);
312 return 0;
316 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
318 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
319 return 0;
323 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
325 wpa_cli_quit = 1;
326 return 0;
330 static void wpa_cli_show_variables(void)
332 printf("set variables:\n"
333 " EAPOL::heldPeriod (EAPOL state machine held period, "
334 "in seconds)\n"
335 " EAPOL::authPeriod (EAPOL state machine authentication "
336 "period, in seconds)\n"
337 " EAPOL::startPeriod (EAPOL state machine start period, in "
338 "seconds)\n"
339 " EAPOL::maxStart (EAPOL state machine maximum start "
340 "attempts)\n");
341 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
342 "seconds)\n"
343 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
344 " threshold\n\tpercentage)\n"
345 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
346 "security\n\tassociation in seconds)\n");
350 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
352 char cmd[256];
353 int res;
355 if (argc == 0) {
356 wpa_cli_show_variables();
357 return 0;
360 if (argc != 2) {
361 printf("Invalid SET command: needs two arguments (variable "
362 "name and value)\n");
363 return -1;
366 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
367 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
368 printf("Too long SET command.\n");
369 return -1;
371 return wpa_ctrl_command(ctrl, cmd);
375 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
377 return wpa_ctrl_command(ctrl, "LOGOFF");
381 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
383 return wpa_ctrl_command(ctrl, "LOGON");
387 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
388 char *argv[])
390 return wpa_ctrl_command(ctrl, "REASSOCIATE");
394 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
395 char *argv[])
397 char cmd[256];
398 int res;
400 if (argc != 1) {
401 printf("Invalid PREAUTH command: needs one argument "
402 "(BSSID)\n");
403 return -1;
406 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
407 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
408 printf("Too long PREAUTH command.\n");
409 return -1;
411 return wpa_ctrl_command(ctrl, cmd);
415 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
417 char cmd[256];
418 int res;
420 if (argc != 1) {
421 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
422 "value)\n");
423 return -1;
425 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
426 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
427 printf("Too long AP_SCAN command.\n");
428 return -1;
430 return wpa_ctrl_command(ctrl, cmd);
434 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
435 char *argv[])
437 char cmd[256];
438 int res;
440 if (argc != 1) {
441 printf("Invalid STKSTART command: needs one argument "
442 "(Peer STA MAC address)\n");
443 return -1;
446 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
447 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
448 printf("Too long STKSTART command.\n");
449 return -1;
451 return wpa_ctrl_command(ctrl, cmd);
455 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
457 char cmd[256];
458 int res;
460 if (argc != 1) {
461 printf("Invalid FT_DS command: needs one argument "
462 "(Target AP MAC address)\n");
463 return -1;
466 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
467 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
468 printf("Too long FT_DS command.\n");
469 return -1;
471 return wpa_ctrl_command(ctrl, cmd);
475 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
477 char cmd[256];
478 int res;
480 if (argc != 1) {
481 printf("Invalid LEVEL command: needs one argument (debug "
482 "level)\n");
483 return -1;
485 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
486 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
487 printf("Too long LEVEL command.\n");
488 return -1;
490 return wpa_ctrl_command(ctrl, cmd);
494 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
496 char cmd[256], *pos, *end;
497 int i, ret;
499 if (argc < 2) {
500 printf("Invalid IDENTITY command: needs two arguments "
501 "(network id and identity)\n");
502 return -1;
505 end = cmd + sizeof(cmd);
506 pos = cmd;
507 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
508 argv[0], argv[1]);
509 if (ret < 0 || ret >= end - pos) {
510 printf("Too long IDENTITY command.\n");
511 return -1;
513 pos += ret;
514 for (i = 2; i < argc; i++) {
515 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
516 if (ret < 0 || ret >= end - pos) {
517 printf("Too long IDENTITY command.\n");
518 return -1;
520 pos += ret;
523 return wpa_ctrl_command(ctrl, cmd);
527 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
529 char cmd[256], *pos, *end;
530 int i, ret;
532 if (argc < 2) {
533 printf("Invalid PASSWORD command: needs two arguments "
534 "(network id and password)\n");
535 return -1;
538 end = cmd + sizeof(cmd);
539 pos = cmd;
540 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
541 argv[0], argv[1]);
542 if (ret < 0 || ret >= end - pos) {
543 printf("Too long PASSWORD command.\n");
544 return -1;
546 pos += ret;
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 PASSWORD command.\n");
551 return -1;
553 pos += ret;
556 return wpa_ctrl_command(ctrl, cmd);
560 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
561 char *argv[])
563 char cmd[256], *pos, *end;
564 int i, ret;
566 if (argc < 2) {
567 printf("Invalid NEW_PASSWORD command: needs two arguments "
568 "(network id and password)\n");
569 return -1;
572 end = cmd + sizeof(cmd);
573 pos = cmd;
574 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
575 argv[0], argv[1]);
576 if (ret < 0 || ret >= end - pos) {
577 printf("Too long NEW_PASSWORD command.\n");
578 return -1;
580 pos += ret;
581 for (i = 2; i < argc; i++) {
582 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
583 if (ret < 0 || ret >= end - pos) {
584 printf("Too long NEW_PASSWORD command.\n");
585 return -1;
587 pos += ret;
590 return wpa_ctrl_command(ctrl, cmd);
594 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
596 char cmd[256], *pos, *end;
597 int i, ret;
599 if (argc < 2) {
600 printf("Invalid PIN command: needs two arguments "
601 "(network id and pin)\n");
602 return -1;
605 end = cmd + sizeof(cmd);
606 pos = cmd;
607 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
608 argv[0], argv[1]);
609 if (ret < 0 || ret >= end - pos) {
610 printf("Too long PIN command.\n");
611 return -1;
613 pos += ret;
614 for (i = 2; i < argc; i++) {
615 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
616 if (ret < 0 || ret >= end - pos) {
617 printf("Too long PIN command.\n");
618 return -1;
620 pos += ret;
622 return wpa_ctrl_command(ctrl, cmd);
626 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
628 char cmd[256], *pos, *end;
629 int i, ret;
631 if (argc < 2) {
632 printf("Invalid OTP command: needs two arguments (network "
633 "id and password)\n");
634 return -1;
637 end = cmd + sizeof(cmd);
638 pos = cmd;
639 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
640 argv[0], argv[1]);
641 if (ret < 0 || ret >= end - pos) {
642 printf("Too long OTP command.\n");
643 return -1;
645 pos += ret;
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 OTP command.\n");
650 return -1;
652 pos += ret;
655 return wpa_ctrl_command(ctrl, cmd);
659 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
660 char *argv[])
662 char cmd[256], *pos, *end;
663 int i, ret;
665 if (argc < 2) {
666 printf("Invalid PASSPHRASE command: needs two arguments "
667 "(network id and passphrase)\n");
668 return -1;
671 end = cmd + sizeof(cmd);
672 pos = cmd;
673 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
674 argv[0], argv[1]);
675 if (ret < 0 || ret >= end - pos) {
676 printf("Too long PASSPHRASE command.\n");
677 return -1;
679 pos += ret;
680 for (i = 2; i < argc; i++) {
681 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
682 if (ret < 0 || ret >= end - pos) {
683 printf("Too long PASSPHRASE command.\n");
684 return -1;
686 pos += ret;
689 return wpa_ctrl_command(ctrl, cmd);
693 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
695 char cmd[256], *pos, *end;
696 int i, ret;
698 if (argc < 2) {
699 printf("Invalid BSSID command: needs two arguments (network "
700 "id and BSSID)\n");
701 return -1;
704 end = cmd + sizeof(cmd);
705 pos = cmd;
706 ret = os_snprintf(pos, end - pos, "BSSID");
707 if (ret < 0 || ret >= end - pos) {
708 printf("Too long BSSID command.\n");
709 return -1;
711 pos += ret;
712 for (i = 0; i < argc; i++) {
713 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
714 if (ret < 0 || ret >= end - pos) {
715 printf("Too long BSSID command.\n");
716 return -1;
718 pos += ret;
721 return wpa_ctrl_command(ctrl, cmd);
725 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
728 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
732 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
733 char *argv[])
735 char cmd[32];
736 int res;
738 if (argc < 1) {
739 printf("Invalid SELECT_NETWORK command: needs one argument "
740 "(network id)\n");
741 return -1;
744 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
745 if (res < 0 || (size_t) res >= sizeof(cmd))
746 return -1;
747 cmd[sizeof(cmd) - 1] = '\0';
749 return wpa_ctrl_command(ctrl, cmd);
753 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
754 char *argv[])
756 char cmd[32];
757 int res;
759 if (argc < 1) {
760 printf("Invalid ENABLE_NETWORK command: needs one argument "
761 "(network id)\n");
762 return -1;
765 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
766 if (res < 0 || (size_t) res >= sizeof(cmd))
767 return -1;
768 cmd[sizeof(cmd) - 1] = '\0';
770 return wpa_ctrl_command(ctrl, cmd);
774 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
775 char *argv[])
777 char cmd[32];
778 int res;
780 if (argc < 1) {
781 printf("Invalid DISABLE_NETWORK command: needs one argument "
782 "(network id)\n");
783 return -1;
786 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
787 if (res < 0 || (size_t) res >= sizeof(cmd))
788 return -1;
789 cmd[sizeof(cmd) - 1] = '\0';
791 return wpa_ctrl_command(ctrl, cmd);
795 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
796 char *argv[])
798 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
802 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
803 char *argv[])
805 char cmd[32];
806 int res;
808 if (argc < 1) {
809 printf("Invalid REMOVE_NETWORK command: needs one argument "
810 "(network id)\n");
811 return -1;
814 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
815 if (res < 0 || (size_t) res >= sizeof(cmd))
816 return -1;
817 cmd[sizeof(cmd) - 1] = '\0';
819 return wpa_ctrl_command(ctrl, cmd);
823 static void wpa_cli_show_network_variables(void)
825 printf("set_network variables:\n"
826 " ssid (network name, SSID)\n"
827 " psk (WPA passphrase or pre-shared key)\n"
828 " key_mgmt (key management protocol)\n"
829 " identity (EAP identity)\n"
830 " password (EAP password)\n"
831 " ...\n"
832 "\n"
833 "Note: Values are entered in the same format as the "
834 "configuration file is using,\n"
835 "i.e., strings values need to be inside double quotation "
836 "marks.\n"
837 "For example: set_network 1 ssid \"network name\"\n"
838 "\n"
839 "Please see wpa_supplicant.conf documentation for full list "
840 "of\navailable variables.\n");
844 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
845 char *argv[])
847 char cmd[256];
848 int res;
850 if (argc == 0) {
851 wpa_cli_show_network_variables();
852 return 0;
855 if (argc != 3) {
856 printf("Invalid SET_NETWORK command: needs three arguments\n"
857 "(network id, variable name, and value)\n");
858 return -1;
861 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
862 argv[0], argv[1], argv[2]);
863 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
864 printf("Too long SET_NETWORK command.\n");
865 return -1;
867 return wpa_ctrl_command(ctrl, cmd);
871 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
872 char *argv[])
874 char cmd[256];
875 int res;
877 if (argc == 0) {
878 wpa_cli_show_network_variables();
879 return 0;
882 if (argc != 2) {
883 printf("Invalid GET_NETWORK command: needs two arguments\n"
884 "(network id and variable name)\n");
885 return -1;
888 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
889 argv[0], argv[1]);
890 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
891 printf("Too long GET_NETWORK command.\n");
892 return -1;
894 return wpa_ctrl_command(ctrl, cmd);
898 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
899 char *argv[])
901 return wpa_ctrl_command(ctrl, "DISCONNECT");
905 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
906 char *argv[])
908 return wpa_ctrl_command(ctrl, "RECONNECT");
912 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
913 char *argv[])
915 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
919 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
921 return wpa_ctrl_command(ctrl, "SCAN");
925 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
928 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
932 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
934 char cmd[64];
935 int res;
937 if (argc != 1) {
938 printf("Invalid BSS command: need one argument (index or "
939 "BSSID)\n");
940 return -1;
943 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
944 if (res < 0 || (size_t) res >= sizeof(cmd))
945 return -1;
946 cmd[sizeof(cmd) - 1] = '\0';
948 return wpa_ctrl_command(ctrl, cmd);
952 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
953 char *argv[])
955 char cmd[64];
956 int res;
958 if (argc < 1 || argc > 2) {
959 printf("Invalid GET_CAPABILITY command: need either one or "
960 "two arguments\n");
961 return -1;
964 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
965 printf("Invalid GET_CAPABILITY command: second argument, "
966 "if any, must be 'strict'\n");
967 return -1;
970 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
971 (argc == 2) ? " strict" : "");
972 if (res < 0 || (size_t) res >= sizeof(cmd))
973 return -1;
974 cmd[sizeof(cmd) - 1] = '\0';
976 return wpa_ctrl_command(ctrl, cmd);
980 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
982 printf("Available interfaces:\n");
983 return wpa_ctrl_command(ctrl, "INTERFACES");
987 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
989 if (argc < 1) {
990 wpa_cli_list_interfaces(ctrl);
991 return 0;
994 wpa_cli_close_connection();
995 os_free(ctrl_ifname);
996 ctrl_ifname = os_strdup(argv[0]);
998 if (wpa_cli_open_connection(ctrl_ifname)) {
999 printf("Connected to interface '%s.\n", ctrl_ifname);
1000 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1001 wpa_cli_attached = 1;
1002 } else {
1003 printf("Warning: Failed to attach to "
1004 "wpa_supplicant.\n");
1006 } else {
1007 printf("Could not connect to interface '%s' - re-trying\n",
1008 ctrl_ifname);
1010 return 0;
1014 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1015 char *argv[])
1017 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1021 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1022 char *argv[])
1024 return wpa_ctrl_command(ctrl, "TERMINATE");
1028 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1029 char *argv[])
1031 char cmd[256];
1032 int res;
1034 if (argc < 1) {
1035 printf("Invalid INTERFACE_ADD command: needs at least one "
1036 "argument (interface name)\n"
1037 "All arguments: ifname confname driver ctrl_interface "
1038 "driver_param bridge_name\n");
1039 return -1;
1043 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1044 * <driver_param>TAB<bridge_name>
1046 res = os_snprintf(cmd, sizeof(cmd),
1047 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1048 argv[0],
1049 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1050 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1051 argc > 5 ? argv[5] : "");
1052 if (res < 0 || (size_t) res >= sizeof(cmd))
1053 return -1;
1054 cmd[sizeof(cmd) - 1] = '\0';
1055 return wpa_ctrl_command(ctrl, cmd);
1059 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1060 char *argv[])
1062 char cmd[128];
1063 int res;
1065 if (argc != 1) {
1066 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1067 "(interface name)\n");
1068 return -1;
1071 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1072 if (res < 0 || (size_t) res >= sizeof(cmd))
1073 return -1;
1074 cmd[sizeof(cmd) - 1] = '\0';
1075 return wpa_ctrl_command(ctrl, cmd);
1079 struct wpa_cli_cmd {
1080 const char *cmd;
1081 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1084 static struct wpa_cli_cmd wpa_cli_commands[] = {
1085 { "status", wpa_cli_cmd_status },
1086 { "ping", wpa_cli_cmd_ping },
1087 { "mib", wpa_cli_cmd_mib },
1088 { "help", wpa_cli_cmd_help },
1089 { "interface", wpa_cli_cmd_interface },
1090 { "level", wpa_cli_cmd_level },
1091 { "license", wpa_cli_cmd_license },
1092 { "quit", wpa_cli_cmd_quit },
1093 { "set", wpa_cli_cmd_set },
1094 { "logon", wpa_cli_cmd_logon },
1095 { "logoff", wpa_cli_cmd_logoff },
1096 { "pmksa", wpa_cli_cmd_pmksa },
1097 { "reassociate", wpa_cli_cmd_reassociate },
1098 { "preauthenticate", wpa_cli_cmd_preauthenticate },
1099 { "identity", wpa_cli_cmd_identity },
1100 { "password", wpa_cli_cmd_password },
1101 { "new_password", wpa_cli_cmd_new_password },
1102 { "pin", wpa_cli_cmd_pin },
1103 { "otp", wpa_cli_cmd_otp },
1104 { "passphrase", wpa_cli_cmd_passphrase },
1105 { "bssid", wpa_cli_cmd_bssid },
1106 { "list_networks", wpa_cli_cmd_list_networks },
1107 { "select_network", wpa_cli_cmd_select_network },
1108 { "enable_network", wpa_cli_cmd_enable_network },
1109 { "disable_network", wpa_cli_cmd_disable_network },
1110 { "add_network", wpa_cli_cmd_add_network },
1111 { "remove_network", wpa_cli_cmd_remove_network },
1112 { "set_network", wpa_cli_cmd_set_network },
1113 { "get_network", wpa_cli_cmd_get_network },
1114 { "save_config", wpa_cli_cmd_save_config },
1115 { "disconnect", wpa_cli_cmd_disconnect },
1116 { "reconnect", wpa_cli_cmd_reconnect },
1117 { "scan", wpa_cli_cmd_scan },
1118 { "scan_results", wpa_cli_cmd_scan_results },
1119 { "bss", wpa_cli_cmd_bss },
1120 { "get_capability", wpa_cli_cmd_get_capability },
1121 { "reconfigure", wpa_cli_cmd_reconfigure },
1122 { "terminate", wpa_cli_cmd_terminate },
1123 { "interface_add", wpa_cli_cmd_interface_add },
1124 { "interface_remove", wpa_cli_cmd_interface_remove },
1125 { "ap_scan", wpa_cli_cmd_ap_scan },
1126 { "stkstart", wpa_cli_cmd_stkstart },
1127 { "ft_ds", wpa_cli_cmd_ft_ds },
1128 { NULL, NULL }
1132 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1134 struct wpa_cli_cmd *cmd, *match = NULL;
1135 int count;
1136 int ret = 0;
1138 count = 0;
1139 cmd = wpa_cli_commands;
1140 while (cmd->cmd) {
1141 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1143 match = cmd;
1144 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1145 /* we have an exact match */
1146 count = 1;
1147 break;
1149 count++;
1151 cmd++;
1154 if (count > 1) {
1155 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1156 cmd = wpa_cli_commands;
1157 while (cmd->cmd) {
1158 if (os_strncasecmp(cmd->cmd, argv[0],
1159 os_strlen(argv[0])) == 0) {
1160 printf(" %s", cmd->cmd);
1162 cmd++;
1164 printf("\n");
1165 ret = 1;
1166 } else if (count == 0) {
1167 printf("Unknown command '%s'\n", argv[0]);
1168 ret = 1;
1169 } else {
1170 ret = match->handler(ctrl, argc - 1, &argv[1]);
1173 return ret;
1177 static int str_match(const char *a, const char *b)
1179 return os_strncmp(a, b, os_strlen(b)) == 0;
1183 static int wpa_cli_exec(const char *program, const char *arg1,
1184 const char *arg2)
1186 char *cmd;
1187 size_t len;
1188 int res;
1190 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1191 cmd = os_malloc(len);
1192 if (cmd == NULL)
1193 return -1;
1194 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1195 if (res < 0 || (size_t) res >= len) {
1196 os_free(cmd);
1197 return -1;
1199 cmd[len - 1] = '\0';
1200 #ifndef _WIN32_WCE
1201 system(cmd);
1202 #endif /* _WIN32_WCE */
1203 os_free(cmd);
1205 return 0;
1209 static void wpa_cli_action_process(const char *msg)
1211 const char *pos = skip_priority(msg);
1213 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1214 int new_id = -1;
1215 char *id, *copy;
1216 os_unsetenv("WPA_ID");
1217 os_unsetenv("WPA_ID_STR");
1218 os_unsetenv("WPA_CTRL_DIR");
1220 pos = os_strstr(pos, "[id=");
1221 copy = pos ? os_strdup(pos + 4) : NULL;
1223 if (copy) {
1224 char *pos2 = id = copy;
1225 while (*pos2 && *pos2 != ' ')
1226 pos2++;
1227 *pos2++ = '\0';
1228 new_id = atoi(id);
1229 os_setenv("WPA_ID", id, 1);
1230 while (*pos2 && *pos2 != '=')
1231 pos2++;
1232 if (*pos2 == '=')
1233 pos2++;
1234 id = pos2;
1235 while (*pos2 && *pos2 != ']')
1236 pos2++;
1237 *pos2 = '\0';
1238 os_setenv("WPA_ID_STR", id, 1);
1239 os_free(copy);
1242 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1244 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1245 wpa_cli_connected = 1;
1246 wpa_cli_last_id = new_id;
1247 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1249 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1250 if (wpa_cli_connected) {
1251 wpa_cli_connected = 0;
1252 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1254 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1255 printf("wpa_supplicant is terminating - stop monitoring\n");
1256 wpa_cli_quit = 1;
1261 #ifndef CONFIG_ANSI_C_EXTRA
1262 static void wpa_cli_action_cb(char *msg, size_t len)
1264 wpa_cli_action_process(msg);
1266 #endif /* CONFIG_ANSI_C_EXTRA */
1269 static void wpa_cli_reconnect(void)
1271 wpa_cli_close_connection();
1272 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1273 if (ctrl_conn) {
1274 printf("Connection to wpa_supplicant re-established\n");
1275 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1276 wpa_cli_attached = 1;
1277 } else {
1278 printf("Warning: Failed to attach to "
1279 "wpa_supplicant.\n");
1284 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1285 int action_monitor)
1287 int first = 1;
1288 if (ctrl_conn == NULL) {
1289 wpa_cli_reconnect();
1290 return;
1292 while (wpa_ctrl_pending(ctrl) > 0) {
1293 char buf[256];
1294 size_t len = sizeof(buf) - 1;
1295 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1296 buf[len] = '\0';
1297 if (action_monitor)
1298 wpa_cli_action_process(buf);
1299 else {
1300 if (in_read && first)
1301 printf("\n");
1302 first = 0;
1303 wpa_cli_msg_cb(buf, 0);
1305 } else {
1306 printf("Could not read pending message.\n");
1307 break;
1311 if (wpa_ctrl_pending(ctrl) < 0) {
1312 printf("Connection to wpa_supplicant lost - trying to "
1313 "reconnect\n");
1314 wpa_cli_reconnect();
1319 #ifdef CONFIG_READLINE
1320 static char * wpa_cli_cmd_gen(const char *text, int state)
1322 static int i, len;
1323 const char *cmd;
1325 if (state == 0) {
1326 i = 0;
1327 len = os_strlen(text);
1330 while ((cmd = wpa_cli_commands[i].cmd)) {
1331 i++;
1332 if (os_strncasecmp(cmd, text, len) == 0)
1333 return os_strdup(cmd);
1336 return NULL;
1340 static char * wpa_cli_dummy_gen(const char *text, int state)
1342 return NULL;
1346 static char ** wpa_cli_completion(const char *text, int start, int end)
1348 return rl_completion_matches(text, start == 0 ?
1349 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1351 #endif /* CONFIG_READLINE */
1354 static void wpa_cli_interactive(void)
1356 #define max_args 10
1357 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1358 int argc;
1359 #ifdef CONFIG_READLINE
1360 char *home, *hfile = NULL;
1361 #endif /* CONFIG_READLINE */
1363 printf("\nInteractive mode\n\n");
1365 #ifdef CONFIG_READLINE
1366 rl_attempted_completion_function = wpa_cli_completion;
1367 home = getenv("HOME");
1368 if (home) {
1369 const char *fname = ".wpa_cli_history";
1370 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1371 hfile = os_malloc(hfile_len);
1372 if (hfile) {
1373 int res;
1374 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1375 fname);
1376 if (res >= 0 && res < hfile_len) {
1377 hfile[hfile_len - 1] = '\0';
1378 read_history(hfile);
1379 stifle_history(100);
1383 #endif /* CONFIG_READLINE */
1385 do {
1386 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1387 #ifndef CONFIG_NATIVE_WINDOWS
1388 alarm(1);
1389 #endif /* CONFIG_NATIVE_WINDOWS */
1390 #ifdef CONFIG_READLINE
1391 cmd = readline("> ");
1392 if (cmd && *cmd) {
1393 HIST_ENTRY *h;
1394 while (next_history())
1396 h = previous_history();
1397 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1398 add_history(cmd);
1399 next_history();
1401 #else /* CONFIG_READLINE */
1402 printf("> ");
1403 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1404 #endif /* CONFIG_READLINE */
1405 #ifndef CONFIG_NATIVE_WINDOWS
1406 alarm(0);
1407 #endif /* CONFIG_NATIVE_WINDOWS */
1408 if (cmd == NULL)
1409 break;
1410 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1411 pos = cmd;
1412 while (*pos != '\0') {
1413 if (*pos == '\n') {
1414 *pos = '\0';
1415 break;
1417 pos++;
1419 argc = 0;
1420 pos = cmd;
1421 for (;;) {
1422 while (*pos == ' ')
1423 pos++;
1424 if (*pos == '\0')
1425 break;
1426 argv[argc] = pos;
1427 argc++;
1428 if (argc == max_args)
1429 break;
1430 if (*pos == '"') {
1431 char *pos2 = os_strrchr(pos, '"');
1432 if (pos2)
1433 pos = pos2 + 1;
1435 while (*pos != '\0' && *pos != ' ')
1436 pos++;
1437 if (*pos == ' ')
1438 *pos++ = '\0';
1440 if (argc)
1441 wpa_request(ctrl_conn, argc, argv);
1443 if (cmd != cmdbuf)
1444 os_free(cmd);
1445 } while (!wpa_cli_quit);
1447 #ifdef CONFIG_READLINE
1448 if (hfile) {
1449 /* Save command history, excluding lines that may contain
1450 * passwords. */
1451 HIST_ENTRY *h;
1452 history_set_pos(0);
1453 h = next_history();
1454 while (h) {
1455 const char *p = h->line;
1456 while (*p == ' ' || *p == '\t')
1457 p++;
1458 if (os_strncasecmp(p, "pa", 2) == 0 ||
1459 os_strncasecmp(p, "o", 1) == 0 ||
1460 os_strncasecmp(p, "n", 1)) {
1461 h = remove_history(where_history());
1462 if (h) {
1463 os_free(__UNCONST(h->line));
1464 os_free(__UNCONST(h->data));
1465 os_free(h);
1467 h = current_history();
1468 } else {
1469 h = next_history();
1472 write_history(hfile);
1473 os_free(hfile);
1475 #endif /* CONFIG_READLINE */
1479 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1481 #ifdef CONFIG_ANSI_C_EXTRA
1482 /* TODO: ANSI C version(?) */
1483 printf("Action processing not supported in ANSI C build.\n");
1484 #else /* CONFIG_ANSI_C_EXTRA */
1485 fd_set rfds;
1486 int fd, res;
1487 struct timeval tv;
1488 char buf[256]; /* note: large enough to fit in unsolicited messages */
1489 size_t len;
1491 fd = wpa_ctrl_get_fd(ctrl);
1493 while (!wpa_cli_quit) {
1494 FD_ZERO(&rfds);
1495 FD_SET(fd, &rfds);
1496 tv.tv_sec = 2;
1497 tv.tv_usec = 0;
1498 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1499 if (res < 0 && errno != EINTR) {
1500 perror("select");
1501 break;
1504 if (FD_ISSET(fd, &rfds))
1505 wpa_cli_recv_pending(ctrl, 0, 1);
1506 else {
1507 /* verify that connection is still working */
1508 len = sizeof(buf) - 1;
1509 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1510 wpa_cli_action_cb) < 0 ||
1511 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1512 printf("wpa_supplicant did not reply to PING "
1513 "command - exiting\n");
1514 break;
1518 #endif /* CONFIG_ANSI_C_EXTRA */
1522 static void wpa_cli_cleanup(void)
1524 wpa_cli_close_connection();
1525 if (pid_file)
1526 os_daemonize_terminate(pid_file);
1528 os_program_deinit();
1531 static void wpa_cli_terminate(int sig)
1533 wpa_cli_cleanup();
1534 exit(0);
1538 #ifndef CONFIG_NATIVE_WINDOWS
1539 static void wpa_cli_alarm(int sig)
1541 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1542 printf("Connection to wpa_supplicant lost - trying to "
1543 "reconnect\n");
1544 wpa_cli_close_connection();
1546 if (!ctrl_conn)
1547 wpa_cli_reconnect();
1548 if (ctrl_conn)
1549 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1550 alarm(1);
1552 #endif /* CONFIG_NATIVE_WINDOWS */
1555 static char * wpa_cli_get_default_ifname(void)
1557 char *ifname = NULL;
1559 #ifdef CONFIG_CTRL_IFACE_UNIX
1560 struct dirent *dent;
1561 DIR *dir = opendir(ctrl_iface_dir);
1562 if (!dir)
1563 return NULL;
1564 while ((dent = readdir(dir))) {
1565 #ifdef _DIRENT_HAVE_D_TYPE
1567 * Skip the file if it is not a socket. Also accept
1568 * DT_UNKNOWN (0) in case the C library or underlying
1569 * file system does not support d_type.
1571 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1572 continue;
1573 #endif /* _DIRENT_HAVE_D_TYPE */
1574 if (os_strcmp(dent->d_name, ".") == 0 ||
1575 os_strcmp(dent->d_name, "..") == 0)
1576 continue;
1577 printf("Selected interface '%s'\n", dent->d_name);
1578 ifname = os_strdup(dent->d_name);
1579 break;
1581 closedir(dir);
1582 #endif /* CONFIG_CTRL_IFACE_UNIX */
1584 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1585 char buf[2048], *pos;
1586 size_t len;
1587 struct wpa_ctrl *ctrl;
1588 int ret;
1590 ctrl = wpa_ctrl_open(NULL);
1591 if (ctrl == NULL)
1592 return NULL;
1594 len = sizeof(buf) - 1;
1595 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1596 if (ret >= 0) {
1597 buf[len] = '\0';
1598 pos = os_strchr(buf, '\n');
1599 if (pos)
1600 *pos = '\0';
1601 ifname = os_strdup(buf);
1603 wpa_ctrl_close(ctrl);
1604 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1606 return ifname;
1610 int main(int argc, char *argv[])
1612 int interactive;
1613 int warning_displayed = 0;
1614 int c;
1615 int daemonize = 0;
1616 int ret = 0;
1617 const char *global = NULL;
1619 if (os_program_init())
1620 return -1;
1622 for (;;) {
1623 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1624 if (c < 0)
1625 break;
1626 switch (c) {
1627 case 'a':
1628 action_file = optarg;
1629 break;
1630 case 'B':
1631 daemonize = 1;
1632 break;
1633 case 'g':
1634 global = optarg;
1635 break;
1636 case 'h':
1637 usage();
1638 return 0;
1639 case 'v':
1640 printf("%s\n", wpa_cli_version);
1641 return 0;
1642 case 'i':
1643 os_free(ctrl_ifname);
1644 ctrl_ifname = os_strdup(optarg);
1645 break;
1646 case 'p':
1647 ctrl_iface_dir = optarg;
1648 break;
1649 case 'P':
1650 pid_file = optarg;
1651 break;
1652 default:
1653 usage();
1654 return -1;
1658 interactive = (argc == optind) && (action_file == NULL);
1660 if (interactive)
1661 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1663 if (global) {
1664 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1665 ctrl_conn = wpa_ctrl_open(NULL);
1666 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1667 ctrl_conn = wpa_ctrl_open(global);
1668 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1669 if (ctrl_conn == NULL) {
1670 perror("Failed to connect to wpa_supplicant - "
1671 "wpa_ctrl_open");
1672 return -1;
1676 for (; !global;) {
1677 if (ctrl_ifname == NULL)
1678 ctrl_ifname = wpa_cli_get_default_ifname();
1679 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1680 if (ctrl_conn) {
1681 if (warning_displayed)
1682 printf("Connection established.\n");
1683 break;
1686 if (!interactive) {
1687 perror("Failed to connect to wpa_supplicant - "
1688 "wpa_ctrl_open");
1689 return -1;
1692 if (!warning_displayed) {
1693 printf("Could not connect to wpa_supplicant - "
1694 "re-trying\n");
1695 warning_displayed = 1;
1697 os_sleep(1, 0);
1698 continue;
1701 #ifndef _WIN32_WCE
1702 signal(SIGINT, wpa_cli_terminate);
1703 signal(SIGTERM, wpa_cli_terminate);
1704 #endif /* _WIN32_WCE */
1705 #ifndef CONFIG_NATIVE_WINDOWS
1706 signal(SIGALRM, wpa_cli_alarm);
1707 #endif /* CONFIG_NATIVE_WINDOWS */
1709 if (interactive || action_file) {
1710 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1711 wpa_cli_attached = 1;
1712 } else {
1713 printf("Warning: Failed to attach to "
1714 "wpa_supplicant.\n");
1715 if (!interactive)
1716 return -1;
1720 if (daemonize && os_daemonize(pid_file))
1721 return -1;
1723 if (interactive)
1724 wpa_cli_interactive();
1725 else if (action_file)
1726 wpa_cli_action(ctrl_conn);
1727 else
1728 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1730 os_free(ctrl_ifname);
1731 wpa_cli_cleanup();
1733 return ret;
1736 #else /* CONFIG_CTRL_IFACE */
1737 int main(int argc, char *argv[])
1739 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1740 return -1;
1742 #endif /* CONFIG_CTRL_IFACE */