kernel - TMPFS - Stabilization pass, fix rename, symlink issues
[dragonfly.git] / contrib / wpa_supplicant / wpa_supplicant / wpa_cli.c
blob7de65348cb79cc851b02fdf4312ba1b073026c40
1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
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-2009, Jouni Malinen <j@w1.fi> and contributors";
37 static const char *wpa_cli_license =
38 "This program is free software. You can distribute it and/or modify it\n"
39 "under the terms of the GNU General Public License version 2.\n"
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 struct wpa_ctrl *ctrl_conn;
90 static int wpa_cli_quit = 0;
91 static int wpa_cli_attached = 0;
92 static int wpa_cli_connected = 0;
93 static int wpa_cli_last_id = 0;
94 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95 static char *ctrl_ifname = NULL;
96 static const char *pid_file = NULL;
97 static const char *action_file = NULL;
98 static int ping_interval = 5;
101 static void print_help();
104 static void usage(void)
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: /var/run/wpa_supplicant\n"
117 " default interface: first interface found in socket path\n");
118 print_help();
122 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
124 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
125 ctrl_conn = wpa_ctrl_open(ifname);
126 return ctrl_conn;
127 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
128 char *cfile;
129 int flen, res;
131 if (ifname == NULL)
132 return NULL;
134 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
135 cfile = os_malloc(flen);
136 if (cfile == NULL)
137 return NULL;
138 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
139 if (res < 0 || res >= flen) {
140 os_free(cfile);
141 return NULL;
144 ctrl_conn = wpa_ctrl_open(cfile);
145 os_free(cfile);
146 return ctrl_conn;
147 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
151 static void wpa_cli_close_connection(void)
153 if (ctrl_conn == NULL)
154 return;
156 if (wpa_cli_attached) {
157 wpa_ctrl_detach(ctrl_conn);
158 wpa_cli_attached = 0;
160 wpa_ctrl_close(ctrl_conn);
161 ctrl_conn = NULL;
165 static void wpa_cli_msg_cb(char *msg, size_t len)
167 printf("%s\n", msg);
171 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
173 char buf[2048];
174 size_t len;
175 int ret;
177 if (ctrl_conn == NULL) {
178 printf("Not connected to wpa_supplicant - command dropped.\n");
179 return -1;
181 len = sizeof(buf) - 1;
182 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
183 wpa_cli_msg_cb);
184 if (ret == -2) {
185 printf("'%s' command timed out.\n", cmd);
186 return -2;
187 } else if (ret < 0) {
188 printf("'%s' command failed.\n", cmd);
189 return -1;
191 if (print) {
192 buf[len] = '\0';
193 printf("%s", buf);
195 return 0;
199 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
201 return _wpa_ctrl_command(ctrl, cmd, 1);
205 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
207 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
208 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
212 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
214 return wpa_ctrl_command(ctrl, "PING");
218 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
220 return wpa_ctrl_command(ctrl, "MIB");
224 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
226 return wpa_ctrl_command(ctrl, "PMKSA");
230 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
232 print_help();
233 return 0;
237 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
239 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
240 return 0;
244 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
246 wpa_cli_quit = 1;
247 return 0;
251 static void wpa_cli_show_variables(void)
253 printf("set variables:\n"
254 " EAPOL::heldPeriod (EAPOL state machine held period, "
255 "in seconds)\n"
256 " EAPOL::authPeriod (EAPOL state machine authentication "
257 "period, in seconds)\n"
258 " EAPOL::startPeriod (EAPOL state machine start period, in "
259 "seconds)\n"
260 " EAPOL::maxStart (EAPOL state machine maximum start "
261 "attempts)\n");
262 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
263 "seconds)\n"
264 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
265 " threshold\n\tpercentage)\n"
266 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
267 "security\n\tassociation in seconds)\n");
271 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
273 char cmd[256];
274 int res;
276 if (argc == 0) {
277 wpa_cli_show_variables();
278 return 0;
281 if (argc != 2) {
282 printf("Invalid SET command: needs two arguments (variable "
283 "name and value)\n");
284 return -1;
287 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
288 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
289 printf("Too long SET command.\n");
290 return -1;
292 return wpa_ctrl_command(ctrl, cmd);
296 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
298 return wpa_ctrl_command(ctrl, "LOGOFF");
302 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
304 return wpa_ctrl_command(ctrl, "LOGON");
308 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
309 char *argv[])
311 return wpa_ctrl_command(ctrl, "REASSOCIATE");
315 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
316 char *argv[])
318 char cmd[256];
319 int res;
321 if (argc != 1) {
322 printf("Invalid PREAUTH command: needs one argument "
323 "(BSSID)\n");
324 return -1;
327 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
328 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
329 printf("Too long PREAUTH command.\n");
330 return -1;
332 return wpa_ctrl_command(ctrl, cmd);
336 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
338 char cmd[256];
339 int res;
341 if (argc != 1) {
342 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
343 "value)\n");
344 return -1;
346 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
347 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
348 printf("Too long AP_SCAN command.\n");
349 return -1;
351 return wpa_ctrl_command(ctrl, cmd);
355 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
356 char *argv[])
358 char cmd[256];
359 int res;
361 if (argc != 1) {
362 printf("Invalid STKSTART command: needs one argument "
363 "(Peer STA MAC address)\n");
364 return -1;
367 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
368 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
369 printf("Too long STKSTART command.\n");
370 return -1;
372 return wpa_ctrl_command(ctrl, cmd);
376 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
378 char cmd[256];
379 int res;
381 if (argc != 1) {
382 printf("Invalid FT_DS command: needs one argument "
383 "(Target AP MAC address)\n");
384 return -1;
387 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
388 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389 printf("Too long FT_DS command.\n");
390 return -1;
392 return wpa_ctrl_command(ctrl, cmd);
396 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
398 char cmd[256];
399 int res;
401 if (argc == 0) {
402 /* Any BSSID */
403 return wpa_ctrl_command(ctrl, "WPS_PBC");
406 /* Specific BSSID */
407 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
408 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
409 printf("Too long WPS_PBC command.\n");
410 return -1;
412 return wpa_ctrl_command(ctrl, cmd);
416 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
418 char cmd[256];
419 int res;
421 if (argc == 0) {
422 printf("Invalid WPS_PIN command: need one or two arguments:\n"
423 "- BSSID: use 'any' to select any\n"
424 "- PIN: optional, used only with devices that have no "
425 "display\n");
426 return -1;
429 if (argc == 1) {
430 /* Use dynamically generated PIN (returned as reply) */
431 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
432 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
433 printf("Too long WPS_PIN command.\n");
434 return -1;
436 return wpa_ctrl_command(ctrl, cmd);
439 /* Use hardcoded PIN from a label */
440 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
441 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
442 printf("Too long WPS_PIN command.\n");
443 return -1;
445 return wpa_ctrl_command(ctrl, cmd);
449 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
451 char cmd[256];
452 int res;
454 if (argc != 2) {
455 printf("Invalid WPS_REG command: need two arguments:\n"
456 "- BSSID: use 'any' to select any\n"
457 "- AP PIN\n");
458 return -1;
461 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
462 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
463 printf("Too long WPS_REG command.\n");
464 return -1;
466 return wpa_ctrl_command(ctrl, cmd);
470 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
472 char cmd[256];
473 int res;
475 if (argc != 1) {
476 printf("Invalid LEVEL command: needs one argument (debug "
477 "level)\n");
478 return -1;
480 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
481 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
482 printf("Too long LEVEL command.\n");
483 return -1;
485 return wpa_ctrl_command(ctrl, cmd);
489 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
491 char cmd[256], *pos, *end;
492 int i, ret;
494 if (argc < 2) {
495 printf("Invalid IDENTITY command: needs two arguments "
496 "(network id and identity)\n");
497 return -1;
500 end = cmd + sizeof(cmd);
501 pos = cmd;
502 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
503 argv[0], argv[1]);
504 if (ret < 0 || ret >= end - pos) {
505 printf("Too long IDENTITY command.\n");
506 return -1;
508 pos += ret;
509 for (i = 2; i < argc; i++) {
510 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
511 if (ret < 0 || ret >= end - pos) {
512 printf("Too long IDENTITY command.\n");
513 return -1;
515 pos += ret;
518 return wpa_ctrl_command(ctrl, cmd);
522 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
524 char cmd[256], *pos, *end;
525 int i, ret;
527 if (argc < 2) {
528 printf("Invalid PASSWORD command: needs two arguments "
529 "(network id and password)\n");
530 return -1;
533 end = cmd + sizeof(cmd);
534 pos = cmd;
535 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
536 argv[0], argv[1]);
537 if (ret < 0 || ret >= end - pos) {
538 printf("Too long PASSWORD command.\n");
539 return -1;
541 pos += ret;
542 for (i = 2; i < argc; i++) {
543 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
544 if (ret < 0 || ret >= end - pos) {
545 printf("Too long PASSWORD command.\n");
546 return -1;
548 pos += ret;
551 return wpa_ctrl_command(ctrl, cmd);
555 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
556 char *argv[])
558 char cmd[256], *pos, *end;
559 int i, ret;
561 if (argc < 2) {
562 printf("Invalid NEW_PASSWORD command: needs two arguments "
563 "(network id and password)\n");
564 return -1;
567 end = cmd + sizeof(cmd);
568 pos = cmd;
569 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
570 argv[0], argv[1]);
571 if (ret < 0 || ret >= end - pos) {
572 printf("Too long NEW_PASSWORD command.\n");
573 return -1;
575 pos += ret;
576 for (i = 2; i < argc; i++) {
577 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
578 if (ret < 0 || ret >= end - pos) {
579 printf("Too long NEW_PASSWORD command.\n");
580 return -1;
582 pos += ret;
585 return wpa_ctrl_command(ctrl, cmd);
589 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
591 char cmd[256], *pos, *end;
592 int i, ret;
594 if (argc < 2) {
595 printf("Invalid PIN command: needs two arguments "
596 "(network id and pin)\n");
597 return -1;
600 end = cmd + sizeof(cmd);
601 pos = cmd;
602 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
603 argv[0], argv[1]);
604 if (ret < 0 || ret >= end - pos) {
605 printf("Too long PIN command.\n");
606 return -1;
608 pos += ret;
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 PIN command.\n");
613 return -1;
615 pos += ret;
617 return wpa_ctrl_command(ctrl, cmd);
621 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
623 char cmd[256], *pos, *end;
624 int i, ret;
626 if (argc < 2) {
627 printf("Invalid OTP command: needs two arguments (network "
628 "id and password)\n");
629 return -1;
632 end = cmd + sizeof(cmd);
633 pos = cmd;
634 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
635 argv[0], argv[1]);
636 if (ret < 0 || ret >= end - pos) {
637 printf("Too long OTP command.\n");
638 return -1;
640 pos += ret;
641 for (i = 2; i < argc; i++) {
642 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
643 if (ret < 0 || ret >= end - pos) {
644 printf("Too long OTP command.\n");
645 return -1;
647 pos += ret;
650 return wpa_ctrl_command(ctrl, cmd);
654 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
655 char *argv[])
657 char cmd[256], *pos, *end;
658 int i, ret;
660 if (argc < 2) {
661 printf("Invalid PASSPHRASE command: needs two arguments "
662 "(network id and passphrase)\n");
663 return -1;
666 end = cmd + sizeof(cmd);
667 pos = cmd;
668 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
669 argv[0], argv[1]);
670 if (ret < 0 || ret >= end - pos) {
671 printf("Too long PASSPHRASE command.\n");
672 return -1;
674 pos += ret;
675 for (i = 2; i < argc; i++) {
676 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
677 if (ret < 0 || ret >= end - pos) {
678 printf("Too long PASSPHRASE command.\n");
679 return -1;
681 pos += ret;
684 return wpa_ctrl_command(ctrl, cmd);
688 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
690 char cmd[256], *pos, *end;
691 int i, ret;
693 if (argc < 2) {
694 printf("Invalid BSSID command: needs two arguments (network "
695 "id and BSSID)\n");
696 return -1;
699 end = cmd + sizeof(cmd);
700 pos = cmd;
701 ret = os_snprintf(pos, end - pos, "BSSID");
702 if (ret < 0 || ret >= end - pos) {
703 printf("Too long BSSID command.\n");
704 return -1;
706 pos += ret;
707 for (i = 0; i < argc; i++) {
708 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
709 if (ret < 0 || ret >= end - pos) {
710 printf("Too long BSSID command.\n");
711 return -1;
713 pos += ret;
716 return wpa_ctrl_command(ctrl, cmd);
720 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
721 char *argv[])
723 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
727 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
728 char *argv[])
730 char cmd[32];
731 int res;
733 if (argc < 1) {
734 printf("Invalid SELECT_NETWORK command: needs one argument "
735 "(network id)\n");
736 return -1;
739 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
740 if (res < 0 || (size_t) res >= sizeof(cmd))
741 return -1;
742 cmd[sizeof(cmd) - 1] = '\0';
744 return wpa_ctrl_command(ctrl, cmd);
748 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
749 char *argv[])
751 char cmd[32];
752 int res;
754 if (argc < 1) {
755 printf("Invalid ENABLE_NETWORK command: needs one argument "
756 "(network id)\n");
757 return -1;
760 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
761 if (res < 0 || (size_t) res >= sizeof(cmd))
762 return -1;
763 cmd[sizeof(cmd) - 1] = '\0';
765 return wpa_ctrl_command(ctrl, cmd);
769 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
772 char cmd[32];
773 int res;
775 if (argc < 1) {
776 printf("Invalid DISABLE_NETWORK command: needs one argument "
777 "(network id)\n");
778 return -1;
781 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
782 if (res < 0 || (size_t) res >= sizeof(cmd))
783 return -1;
784 cmd[sizeof(cmd) - 1] = '\0';
786 return wpa_ctrl_command(ctrl, cmd);
790 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
791 char *argv[])
793 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
797 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
798 char *argv[])
800 char cmd[32];
801 int res;
803 if (argc < 1) {
804 printf("Invalid REMOVE_NETWORK command: needs one argument "
805 "(network id)\n");
806 return -1;
809 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
810 if (res < 0 || (size_t) res >= sizeof(cmd))
811 return -1;
812 cmd[sizeof(cmd) - 1] = '\0';
814 return wpa_ctrl_command(ctrl, cmd);
818 static void wpa_cli_show_network_variables(void)
820 printf("set_network variables:\n"
821 " ssid (network name, SSID)\n"
822 " psk (WPA passphrase or pre-shared key)\n"
823 " key_mgmt (key management protocol)\n"
824 " identity (EAP identity)\n"
825 " password (EAP password)\n"
826 " ...\n"
827 "\n"
828 "Note: Values are entered in the same format as the "
829 "configuration file is using,\n"
830 "i.e., strings values need to be inside double quotation "
831 "marks.\n"
832 "For example: set_network 1 ssid \"network name\"\n"
833 "\n"
834 "Please see wpa_supplicant.conf documentation for full list "
835 "of\navailable variables.\n");
839 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
840 char *argv[])
842 char cmd[256];
843 int res;
845 if (argc == 0) {
846 wpa_cli_show_network_variables();
847 return 0;
850 if (argc != 3) {
851 printf("Invalid SET_NETWORK command: needs three arguments\n"
852 "(network id, variable name, and value)\n");
853 return -1;
856 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
857 argv[0], argv[1], argv[2]);
858 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
859 printf("Too long SET_NETWORK command.\n");
860 return -1;
862 return wpa_ctrl_command(ctrl, cmd);
866 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
867 char *argv[])
869 char cmd[256];
870 int res;
872 if (argc == 0) {
873 wpa_cli_show_network_variables();
874 return 0;
877 if (argc != 2) {
878 printf("Invalid GET_NETWORK command: needs two arguments\n"
879 "(network id and variable name)\n");
880 return -1;
883 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
884 argv[0], argv[1]);
885 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
886 printf("Too long GET_NETWORK command.\n");
887 return -1;
889 return wpa_ctrl_command(ctrl, cmd);
893 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
894 char *argv[])
896 return wpa_ctrl_command(ctrl, "DISCONNECT");
900 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
901 char *argv[])
903 return wpa_ctrl_command(ctrl, "RECONNECT");
907 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
908 char *argv[])
910 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
914 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
916 return wpa_ctrl_command(ctrl, "SCAN");
920 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
921 char *argv[])
923 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
927 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
929 char cmd[64];
930 int res;
932 if (argc != 1) {
933 printf("Invalid BSS command: need one argument (index or "
934 "BSSID)\n");
935 return -1;
938 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
939 if (res < 0 || (size_t) res >= sizeof(cmd))
940 return -1;
941 cmd[sizeof(cmd) - 1] = '\0';
943 return wpa_ctrl_command(ctrl, cmd);
947 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
948 char *argv[])
950 char cmd[64];
951 int res;
953 if (argc < 1 || argc > 2) {
954 printf("Invalid GET_CAPABILITY command: need either one or "
955 "two arguments\n");
956 return -1;
959 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
960 printf("Invalid GET_CAPABILITY command: second argument, "
961 "if any, must be 'strict'\n");
962 return -1;
965 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
966 (argc == 2) ? " strict" : "");
967 if (res < 0 || (size_t) res >= sizeof(cmd))
968 return -1;
969 cmd[sizeof(cmd) - 1] = '\0';
971 return wpa_ctrl_command(ctrl, cmd);
975 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
977 printf("Available interfaces:\n");
978 return wpa_ctrl_command(ctrl, "INTERFACES");
982 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
984 if (argc < 1) {
985 wpa_cli_list_interfaces(ctrl);
986 return 0;
989 wpa_cli_close_connection();
990 os_free(ctrl_ifname);
991 ctrl_ifname = os_strdup(argv[0]);
993 if (wpa_cli_open_connection(ctrl_ifname)) {
994 printf("Connected to interface '%s.\n", ctrl_ifname);
995 if (wpa_ctrl_attach(ctrl_conn) == 0) {
996 wpa_cli_attached = 1;
997 } else {
998 printf("Warning: Failed to attach to "
999 "wpa_supplicant.\n");
1001 } else {
1002 printf("Could not connect to interface '%s' - re-trying\n",
1003 ctrl_ifname);
1005 return 0;
1009 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1010 char *argv[])
1012 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1016 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1017 char *argv[])
1019 return wpa_ctrl_command(ctrl, "TERMINATE");
1023 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1024 char *argv[])
1026 char cmd[256];
1027 int res;
1029 if (argc < 1) {
1030 printf("Invalid INTERFACE_ADD command: needs at least one "
1031 "argument (interface name)\n"
1032 "All arguments: ifname confname driver ctrl_interface "
1033 "driver_param bridge_name\n");
1034 return -1;
1038 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1039 * <driver_param>TAB<bridge_name>
1041 res = os_snprintf(cmd, sizeof(cmd),
1042 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1043 argv[0],
1044 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1045 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1046 argc > 5 ? argv[5] : "");
1047 if (res < 0 || (size_t) res >= sizeof(cmd))
1048 return -1;
1049 cmd[sizeof(cmd) - 1] = '\0';
1050 return wpa_ctrl_command(ctrl, cmd);
1054 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1055 char *argv[])
1057 char cmd[128];
1058 int res;
1060 if (argc != 1) {
1061 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1062 "(interface name)\n");
1063 return -1;
1066 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1067 if (res < 0 || (size_t) res >= sizeof(cmd))
1068 return -1;
1069 cmd[sizeof(cmd) - 1] = '\0';
1070 return wpa_ctrl_command(ctrl, cmd);
1074 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1075 char *argv[])
1077 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1081 enum wpa_cli_cmd_flags {
1082 cli_cmd_flag_none = 0x00,
1083 cli_cmd_flag_sensitive = 0x01
1086 struct wpa_cli_cmd {
1087 const char *cmd;
1088 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1089 enum wpa_cli_cmd_flags flags;
1090 const char *usage;
1093 static struct wpa_cli_cmd wpa_cli_commands[] = {
1094 { "status", wpa_cli_cmd_status,
1095 cli_cmd_flag_none,
1096 "[verbose] = get current WPA/EAPOL/EAP status" },
1097 { "ping", wpa_cli_cmd_ping,
1098 cli_cmd_flag_none,
1099 "= pings wpa_supplicant" },
1100 { "mib", wpa_cli_cmd_mib,
1101 cli_cmd_flag_none,
1102 "= get MIB variables (dot1x, dot11)" },
1103 { "help", wpa_cli_cmd_help,
1104 cli_cmd_flag_none,
1105 "= show this usage help" },
1106 { "interface", wpa_cli_cmd_interface,
1107 cli_cmd_flag_none,
1108 "[ifname] = show interfaces/select interface" },
1109 { "level", wpa_cli_cmd_level,
1110 cli_cmd_flag_none,
1111 "<debug level> = change debug level" },
1112 { "license", wpa_cli_cmd_license,
1113 cli_cmd_flag_none,
1114 "= show full wpa_cli license" },
1115 { "quit", wpa_cli_cmd_quit,
1116 cli_cmd_flag_none,
1117 "= exit wpa_cli" },
1118 { "set", wpa_cli_cmd_set,
1119 cli_cmd_flag_none,
1120 "= set variables (shows list of variables when run without "
1121 "arguments)" },
1122 { "logon", wpa_cli_cmd_logon,
1123 cli_cmd_flag_none,
1124 "= IEEE 802.1X EAPOL state machine logon" },
1125 { "logoff", wpa_cli_cmd_logoff,
1126 cli_cmd_flag_none,
1127 "= IEEE 802.1X EAPOL state machine logoff" },
1128 { "pmksa", wpa_cli_cmd_pmksa,
1129 cli_cmd_flag_none,
1130 "= show PMKSA cache" },
1131 { "reassociate", wpa_cli_cmd_reassociate,
1132 cli_cmd_flag_none,
1133 "= force reassociation" },
1134 { "preauthenticate", wpa_cli_cmd_preauthenticate,
1135 cli_cmd_flag_none,
1136 "<BSSID> = force preauthentication" },
1137 { "identity", wpa_cli_cmd_identity,
1138 cli_cmd_flag_none,
1139 "<network id> <identity> = configure identity for an SSID" },
1140 { "password", wpa_cli_cmd_password,
1141 cli_cmd_flag_sensitive,
1142 "<network id> <password> = configure password for an SSID" },
1143 { "new_password", wpa_cli_cmd_new_password,
1144 cli_cmd_flag_sensitive,
1145 "<network id> <password> = change password for an SSID" },
1146 { "pin", wpa_cli_cmd_pin,
1147 cli_cmd_flag_sensitive,
1148 "<network id> <pin> = configure pin for an SSID" },
1149 { "otp", wpa_cli_cmd_otp,
1150 cli_cmd_flag_sensitive,
1151 "<network id> <password> = configure one-time-password for an SSID"
1153 { "passphrase", wpa_cli_cmd_passphrase,
1154 cli_cmd_flag_sensitive,
1155 "<network id> <passphrase> = configure private key passphrase\n"
1156 " for an SSID" },
1157 { "bssid", wpa_cli_cmd_bssid,
1158 cli_cmd_flag_none,
1159 "<network id> <BSSID> = set preferred BSSID for an SSID" },
1160 { "list_networks", wpa_cli_cmd_list_networks,
1161 cli_cmd_flag_none,
1162 "= list configured networks" },
1163 { "select_network", wpa_cli_cmd_select_network,
1164 cli_cmd_flag_none,
1165 "<network id> = select a network (disable others)" },
1166 { "enable_network", wpa_cli_cmd_enable_network,
1167 cli_cmd_flag_none,
1168 "<network id> = enable a network" },
1169 { "disable_network", wpa_cli_cmd_disable_network,
1170 cli_cmd_flag_none,
1171 "<network id> = disable a network" },
1172 { "add_network", wpa_cli_cmd_add_network,
1173 cli_cmd_flag_none,
1174 "= add a network" },
1175 { "remove_network", wpa_cli_cmd_remove_network,
1176 cli_cmd_flag_none,
1177 "<network id> = remove a network" },
1178 { "set_network", wpa_cli_cmd_set_network,
1179 cli_cmd_flag_sensitive,
1180 "<network id> <variable> <value> = set network variables (shows\n"
1181 " list of variables when run without arguments)" },
1182 { "get_network", wpa_cli_cmd_get_network,
1183 cli_cmd_flag_none,
1184 "<network id> <variable> = get network variables" },
1185 { "save_config", wpa_cli_cmd_save_config,
1186 cli_cmd_flag_none,
1187 "= save the current configuration" },
1188 { "disconnect", wpa_cli_cmd_disconnect,
1189 cli_cmd_flag_none,
1190 "= disconnect and wait for reassociate/reconnect command before\n"
1191 " connecting" },
1192 { "reconnect", wpa_cli_cmd_reconnect,
1193 cli_cmd_flag_none,
1194 "= like reassociate, but only takes effect if already disconnected"
1196 { "scan", wpa_cli_cmd_scan,
1197 cli_cmd_flag_none,
1198 "= request new BSS scan" },
1199 { "scan_results", wpa_cli_cmd_scan_results,
1200 cli_cmd_flag_none,
1201 "= get latest scan results" },
1202 { "bss", wpa_cli_cmd_bss,
1203 cli_cmd_flag_none,
1204 "<<idx> | <bssid>> = get detailed scan result info" },
1205 { "get_capability", wpa_cli_cmd_get_capability,
1206 cli_cmd_flag_none,
1207 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1208 { "reconfigure", wpa_cli_cmd_reconfigure,
1209 cli_cmd_flag_none,
1210 "= force wpa_supplicant to re-read its configuration file" },
1211 { "terminate", wpa_cli_cmd_terminate,
1212 cli_cmd_flag_none,
1213 "= terminate wpa_supplicant" },
1214 { "interface_add", wpa_cli_cmd_interface_add,
1215 cli_cmd_flag_none,
1216 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1217 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1218 " are optional" },
1219 { "interface_remove", wpa_cli_cmd_interface_remove,
1220 cli_cmd_flag_none,
1221 "<ifname> = removes the interface" },
1222 { "interface_list", wpa_cli_cmd_interface_list,
1223 cli_cmd_flag_none,
1224 "= list available interfaces" },
1225 { "ap_scan", wpa_cli_cmd_ap_scan,
1226 cli_cmd_flag_none,
1227 "<value> = set ap_scan parameter" },
1228 { "stkstart", wpa_cli_cmd_stkstart,
1229 cli_cmd_flag_none,
1230 "<addr> = request STK negotiation with <addr>" },
1231 { "ft_ds", wpa_cli_cmd_ft_ds,
1232 cli_cmd_flag_none,
1233 "<addr> = request over-the-DS FT with <addr>" },
1234 { "wps_pbc", wpa_cli_cmd_wps_pbc,
1235 cli_cmd_flag_none,
1236 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1237 { "wps_pin", wpa_cli_cmd_wps_pin,
1238 cli_cmd_flag_sensitive,
1239 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1240 "hardcoded)" },
1241 { "wps_reg", wpa_cli_cmd_wps_reg,
1242 cli_cmd_flag_sensitive,
1243 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1244 { NULL, NULL, cli_cmd_flag_none, NULL }
1249 * Prints command usage, lines are padded with the specified string.
1251 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1253 char c;
1254 size_t n;
1256 printf("%s%s ", pad, cmd->cmd);
1257 for (n = 0; (c = cmd->usage[n]); n++) {
1258 printf("%c", c);
1259 if (c == '\n')
1260 printf("%s", pad);
1262 printf("\n");
1266 static void print_help(void)
1268 int n;
1269 printf("commands:\n");
1270 for (n = 0; wpa_cli_commands[n].cmd; n++)
1271 print_cmd_help(&wpa_cli_commands[n], " ");
1275 #ifdef CONFIG_READLINE
1276 static int cmd_has_sensitive_data(const char *cmd)
1278 const char *c, *delim;
1279 int n;
1280 size_t len;
1282 delim = os_strchr(cmd, ' ');
1283 if (delim)
1284 len = delim - cmd;
1285 else
1286 len = os_strlen(cmd);
1288 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1289 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1290 return (wpa_cli_commands[n].flags &
1291 cli_cmd_flag_sensitive);
1293 return 0;
1295 #endif /* CONFIG_READLINE */
1298 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1300 struct wpa_cli_cmd *cmd, *match = NULL;
1301 int count;
1302 int ret = 0;
1304 count = 0;
1305 cmd = wpa_cli_commands;
1306 while (cmd->cmd) {
1307 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1309 match = cmd;
1310 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1311 /* we have an exact match */
1312 count = 1;
1313 break;
1315 count++;
1317 cmd++;
1320 if (count > 1) {
1321 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1322 cmd = wpa_cli_commands;
1323 while (cmd->cmd) {
1324 if (os_strncasecmp(cmd->cmd, argv[0],
1325 os_strlen(argv[0])) == 0) {
1326 printf(" %s", cmd->cmd);
1328 cmd++;
1330 printf("\n");
1331 ret = 1;
1332 } else if (count == 0) {
1333 printf("Unknown command '%s'\n", argv[0]);
1334 ret = 1;
1335 } else {
1336 ret = match->handler(ctrl, argc - 1, &argv[1]);
1339 return ret;
1343 static int str_match(const char *a, const char *b)
1345 return os_strncmp(a, b, os_strlen(b)) == 0;
1349 static int wpa_cli_exec(const char *program, const char *arg1,
1350 const char *arg2)
1352 char *cmd;
1353 size_t len;
1354 int res;
1355 int ret = 0;
1357 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1358 cmd = os_malloc(len);
1359 if (cmd == NULL)
1360 return -1;
1361 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1362 if (res < 0 || (size_t) res >= len) {
1363 os_free(cmd);
1364 return -1;
1366 cmd[len - 1] = '\0';
1367 #ifndef _WIN32_WCE
1368 if (system(cmd) < 0)
1369 ret = -1;
1370 #endif /* _WIN32_WCE */
1371 os_free(cmd);
1373 return ret;
1377 static void wpa_cli_action_process(const char *msg)
1379 const char *pos;
1380 char *copy = NULL, *id, *pos2;
1382 pos = msg;
1383 if (*pos == '<') {
1384 /* skip priority */
1385 pos = os_strchr(pos, '>');
1386 if (pos)
1387 pos++;
1388 else
1389 pos = msg;
1392 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1393 int new_id = -1;
1394 os_unsetenv("WPA_ID");
1395 os_unsetenv("WPA_ID_STR");
1396 os_unsetenv("WPA_CTRL_DIR");
1398 pos = os_strstr(pos, "[id=");
1399 if (pos)
1400 copy = os_strdup(pos + 4);
1402 if (copy) {
1403 pos2 = id = copy;
1404 while (*pos2 && *pos2 != ' ')
1405 pos2++;
1406 *pos2++ = '\0';
1407 new_id = atoi(id);
1408 os_setenv("WPA_ID", id, 1);
1409 while (*pos2 && *pos2 != '=')
1410 pos2++;
1411 if (*pos2 == '=')
1412 pos2++;
1413 id = pos2;
1414 while (*pos2 && *pos2 != ']')
1415 pos2++;
1416 *pos2 = '\0';
1417 os_setenv("WPA_ID_STR", id, 1);
1418 os_free(copy);
1421 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1423 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1424 wpa_cli_connected = 1;
1425 wpa_cli_last_id = new_id;
1426 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1428 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1429 if (wpa_cli_connected) {
1430 wpa_cli_connected = 0;
1431 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1433 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1434 printf("wpa_supplicant is terminating - stop monitoring\n");
1435 wpa_cli_quit = 1;
1440 #ifndef CONFIG_ANSI_C_EXTRA
1441 static void wpa_cli_action_cb(char *msg, size_t len)
1443 wpa_cli_action_process(msg);
1445 #endif /* CONFIG_ANSI_C_EXTRA */
1448 static void wpa_cli_reconnect(void)
1450 wpa_cli_close_connection();
1451 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1452 if (ctrl_conn) {
1453 printf("Connection to wpa_supplicant re-established\n");
1454 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1455 wpa_cli_attached = 1;
1456 } else {
1457 printf("Warning: Failed to attach to "
1458 "wpa_supplicant.\n");
1464 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1465 int action_monitor)
1467 int first = 1;
1468 if (ctrl_conn == NULL) {
1469 wpa_cli_reconnect();
1470 return;
1472 while (wpa_ctrl_pending(ctrl) > 0) {
1473 char buf[256];
1474 size_t len = sizeof(buf) - 1;
1475 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1476 buf[len] = '\0';
1477 if (action_monitor)
1478 wpa_cli_action_process(buf);
1479 else {
1480 if (in_read && first)
1481 printf("\n");
1482 first = 0;
1483 printf("%s\n", buf);
1485 } else {
1486 printf("Could not read pending message.\n");
1487 break;
1491 if (wpa_ctrl_pending(ctrl) < 0) {
1492 printf("Connection to wpa_supplicant lost - trying to "
1493 "reconnect\n");
1494 wpa_cli_reconnect();
1499 #ifdef CONFIG_READLINE
1500 static char * wpa_cli_cmd_gen(const char *text, int state)
1502 static int i, len;
1503 const char *cmd;
1505 if (state == 0) {
1506 i = 0;
1507 len = os_strlen(text);
1510 while ((cmd = wpa_cli_commands[i].cmd)) {
1511 i++;
1512 if (os_strncasecmp(cmd, text, len) == 0)
1513 return os_strdup(cmd);
1516 return NULL;
1520 static char * wpa_cli_dummy_gen(const char *text, int state)
1522 return NULL;
1526 static char ** wpa_cli_completion(const char *text, int start, int end)
1528 return rl_completion_matches(text, start == 0 ?
1529 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1531 #endif /* CONFIG_READLINE */
1534 static void wpa_cli_interactive(void)
1536 #define max_args 10
1537 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1538 int argc;
1539 #ifdef CONFIG_READLINE
1540 char *home, *hfile = NULL;
1541 #endif /* CONFIG_READLINE */
1543 printf("\nInteractive mode\n\n");
1545 #ifdef CONFIG_READLINE
1546 rl_attempted_completion_function = wpa_cli_completion;
1547 home = getenv("HOME");
1548 if (home) {
1549 const char *fname = ".wpa_cli_history";
1550 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1551 hfile = os_malloc(hfile_len);
1552 if (hfile) {
1553 int res;
1554 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1555 fname);
1556 if (res >= 0 && res < hfile_len) {
1557 hfile[hfile_len - 1] = '\0';
1558 read_history(hfile);
1559 stifle_history(100);
1563 #endif /* CONFIG_READLINE */
1565 do {
1566 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1567 #ifndef CONFIG_NATIVE_WINDOWS
1568 alarm(ping_interval);
1569 #endif /* CONFIG_NATIVE_WINDOWS */
1570 #ifdef CONFIG_READLINE
1571 cmd = readline("> ");
1572 if (cmd && *cmd) {
1573 HIST_ENTRY *h;
1574 while (next_history())
1576 h = previous_history();
1577 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1578 add_history(cmd);
1579 next_history();
1581 #else /* CONFIG_READLINE */
1582 printf("> ");
1583 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1584 #endif /* CONFIG_READLINE */
1585 #ifndef CONFIG_NATIVE_WINDOWS
1586 alarm(0);
1587 #endif /* CONFIG_NATIVE_WINDOWS */
1588 if (cmd == NULL)
1589 break;
1590 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1591 pos = cmd;
1592 while (*pos != '\0') {
1593 if (*pos == '\n') {
1594 *pos = '\0';
1595 break;
1597 pos++;
1599 argc = 0;
1600 pos = cmd;
1601 for (;;) {
1602 while (*pos == ' ')
1603 pos++;
1604 if (*pos == '\0')
1605 break;
1606 argv[argc] = pos;
1607 argc++;
1608 if (argc == max_args)
1609 break;
1610 if (*pos == '"') {
1611 char *pos2 = os_strrchr(pos, '"');
1612 if (pos2)
1613 pos = pos2 + 1;
1615 while (*pos != '\0' && *pos != ' ')
1616 pos++;
1617 if (*pos == ' ')
1618 *pos++ = '\0';
1620 if (argc)
1621 wpa_request(ctrl_conn, argc, argv);
1623 if (cmd != cmdbuf)
1624 os_free(cmd);
1625 } while (!wpa_cli_quit);
1627 #ifdef CONFIG_READLINE
1628 if (hfile) {
1629 /* Save command history, excluding lines that may contain
1630 * passwords. */
1631 HIST_ENTRY *h;
1632 history_set_pos(0);
1633 while ((h = current_history())) {
1634 char *p = h->line;
1635 while (*p == ' ' || *p == '\t')
1636 p++;
1637 if (cmd_has_sensitive_data(p)) {
1638 h = remove_history(where_history());
1639 if (h) {
1640 os_free(h->line);
1641 os_free(h->data);
1642 os_free(h);
1643 } else
1644 next_history();
1645 } else
1646 next_history();
1648 write_history(hfile);
1649 os_free(hfile);
1651 #endif /* CONFIG_READLINE */
1655 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1657 #ifdef CONFIG_ANSI_C_EXTRA
1658 /* TODO: ANSI C version(?) */
1659 printf("Action processing not supported in ANSI C build.\n");
1660 #else /* CONFIG_ANSI_C_EXTRA */
1661 fd_set rfds;
1662 int fd, res;
1663 struct timeval tv;
1664 char buf[256]; /* note: large enough to fit in unsolicited messages */
1665 size_t len;
1667 fd = wpa_ctrl_get_fd(ctrl);
1669 while (!wpa_cli_quit) {
1670 FD_ZERO(&rfds);
1671 FD_SET(fd, &rfds);
1672 tv.tv_sec = ping_interval;
1673 tv.tv_usec = 0;
1674 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1675 if (res < 0 && errno != EINTR) {
1676 perror("select");
1677 break;
1680 if (FD_ISSET(fd, &rfds))
1681 wpa_cli_recv_pending(ctrl, 0, 1);
1682 else {
1683 /* verify that connection is still working */
1684 len = sizeof(buf) - 1;
1685 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1686 wpa_cli_action_cb) < 0 ||
1687 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1688 printf("wpa_supplicant did not reply to PING "
1689 "command - exiting\n");
1690 break;
1694 #endif /* CONFIG_ANSI_C_EXTRA */
1698 static void wpa_cli_cleanup(void)
1700 wpa_cli_close_connection();
1701 if (pid_file)
1702 os_daemonize_terminate(pid_file);
1704 os_program_deinit();
1707 static void wpa_cli_terminate(int sig)
1709 wpa_cli_cleanup();
1710 exit(0);
1714 #ifndef CONFIG_NATIVE_WINDOWS
1715 static void wpa_cli_alarm(int sig)
1717 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1718 printf("Connection to wpa_supplicant lost - trying to "
1719 "reconnect\n");
1720 wpa_cli_close_connection();
1722 if (!ctrl_conn)
1723 wpa_cli_reconnect();
1724 if (ctrl_conn)
1725 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1726 alarm(ping_interval);
1728 #endif /* CONFIG_NATIVE_WINDOWS */
1731 static char * wpa_cli_get_default_ifname(void)
1733 char *ifname = NULL;
1735 #ifdef CONFIG_CTRL_IFACE_UNIX
1736 struct dirent *dent;
1737 DIR *dir = opendir(ctrl_iface_dir);
1738 if (!dir)
1739 return NULL;
1740 while ((dent = readdir(dir))) {
1741 #ifdef _DIRENT_HAVE_D_TYPE
1743 * Skip the file if it is not a socket. Also accept
1744 * DT_UNKNOWN (0) in case the C library or underlying
1745 * file system does not support d_type.
1747 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1748 continue;
1749 #endif /* _DIRENT_HAVE_D_TYPE */
1750 if (os_strcmp(dent->d_name, ".") == 0 ||
1751 os_strcmp(dent->d_name, "..") == 0)
1752 continue;
1753 printf("Selected interface '%s'\n", dent->d_name);
1754 ifname = os_strdup(dent->d_name);
1755 break;
1757 closedir(dir);
1758 #endif /* CONFIG_CTRL_IFACE_UNIX */
1760 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1761 char buf[2048], *pos;
1762 size_t len;
1763 struct wpa_ctrl *ctrl;
1764 int ret;
1766 ctrl = wpa_ctrl_open(NULL);
1767 if (ctrl == NULL)
1768 return NULL;
1770 len = sizeof(buf) - 1;
1771 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1772 if (ret >= 0) {
1773 buf[len] = '\0';
1774 pos = os_strchr(buf, '\n');
1775 if (pos)
1776 *pos = '\0';
1777 ifname = os_strdup(buf);
1779 wpa_ctrl_close(ctrl);
1780 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1782 return ifname;
1786 int main(int argc, char *argv[])
1788 int interactive;
1789 int warning_displayed = 0;
1790 int c;
1791 int daemonize = 0;
1792 int ret = 0;
1793 const char *global = NULL;
1795 if (os_program_init())
1796 return -1;
1798 for (;;) {
1799 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
1800 if (c < 0)
1801 break;
1802 switch (c) {
1803 case 'a':
1804 action_file = optarg;
1805 break;
1806 case 'B':
1807 daemonize = 1;
1808 break;
1809 case 'g':
1810 global = optarg;
1811 break;
1812 case 'G':
1813 ping_interval = atoi(optarg);
1814 break;
1815 case 'h':
1816 usage();
1817 return 0;
1818 case 'v':
1819 printf("%s\n", wpa_cli_version);
1820 return 0;
1821 case 'i':
1822 os_free(ctrl_ifname);
1823 ctrl_ifname = os_strdup(optarg);
1824 break;
1825 case 'p':
1826 ctrl_iface_dir = optarg;
1827 break;
1828 case 'P':
1829 pid_file = optarg;
1830 break;
1831 default:
1832 usage();
1833 return -1;
1837 interactive = (argc == optind) && (action_file == NULL);
1839 if (interactive)
1840 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1842 if (global) {
1843 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1844 ctrl_conn = wpa_ctrl_open(NULL);
1845 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1846 ctrl_conn = wpa_ctrl_open(global);
1847 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1848 if (ctrl_conn == NULL) {
1849 perror("Failed to connect to wpa_supplicant - "
1850 "wpa_ctrl_open");
1851 return -1;
1855 for (; !global;) {
1856 if (ctrl_ifname == NULL)
1857 ctrl_ifname = wpa_cli_get_default_ifname();
1858 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1859 if (ctrl_conn) {
1860 if (warning_displayed)
1861 printf("Connection established.\n");
1862 break;
1865 if (!interactive) {
1866 perror("Failed to connect to wpa_supplicant - "
1867 "wpa_ctrl_open");
1868 return -1;
1871 if (!warning_displayed) {
1872 printf("Could not connect to wpa_supplicant - "
1873 "re-trying\n");
1874 warning_displayed = 1;
1876 os_sleep(1, 0);
1877 continue;
1880 #ifndef _WIN32_WCE
1881 signal(SIGINT, wpa_cli_terminate);
1882 signal(SIGTERM, wpa_cli_terminate);
1883 #endif /* _WIN32_WCE */
1884 #ifndef CONFIG_NATIVE_WINDOWS
1885 signal(SIGALRM, wpa_cli_alarm);
1886 #endif /* CONFIG_NATIVE_WINDOWS */
1888 if (interactive || action_file) {
1889 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1890 wpa_cli_attached = 1;
1891 } else {
1892 printf("Warning: Failed to attach to "
1893 "wpa_supplicant.\n");
1894 if (!interactive)
1895 return -1;
1899 if (daemonize && os_daemonize(pid_file))
1900 return -1;
1902 if (interactive)
1903 wpa_cli_interactive();
1904 else if (action_file)
1905 wpa_cli_action(ctrl_conn);
1906 else
1907 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1909 os_free(ctrl_ifname);
1910 wpa_cli_cleanup();
1912 return ret;
1915 #else /* CONFIG_CTRL_IFACE */
1916 int main(int argc, char *argv[])
1918 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1919 return -1;
1921 #endif /* CONFIG_CTRL_IFACE */