1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4 *
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.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
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)
150 {
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);
164 }
167 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
168 {
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;
187 }
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 */
193 }
196 static void wpa_cli_close_connection(void)
197 {
198 if (ctrl_conn == NULL)
199 return;
201 if (wpa_cli_attached) {
202 wpa_ctrl_detach(ctrl_conn);
203 wpa_cli_attached = 0;
204 }
205 wpa_ctrl_close(ctrl_conn);
206 ctrl_conn = NULL;
207 }
210 static void wpa_cli_msg_cb(char *msg, size_t len)
211 {
212 printf("%s\n", msg);
213 }
216 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
217 {
218 char buf[2048];
219 size_t len;
220 int ret;
222 if (ctrl_conn == NULL) {
223 printf("Not connected to wpa_supplicant - command dropped.\n");
224 return -1;
225 }
226 len = sizeof(buf) - 1;
227 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
228 wpa_cli_msg_cb);
229 if (ret == -2) {
230 printf("'%s' command timed out.\n", cmd);
231 return -2;
232 } else if (ret < 0) {
233 printf("'%s' command failed.\n", cmd);
234 return -1;
235 }
236 if (print) {
237 buf[len] = '\0';
238 printf("%s", buf);
239 }
240 return 0;
241 }
244 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
245 {
246 return _wpa_ctrl_command(ctrl, cmd, 1);
247 }
250 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
251 {
252 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
253 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
254 }
257 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
258 {
259 return wpa_ctrl_command(ctrl, "PING");
260 }
263 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
264 {
265 return wpa_ctrl_command(ctrl, "MIB");
266 }
269 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
270 {
271 return wpa_ctrl_command(ctrl, "PMKSA");
272 }
275 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
276 {
277 printf("%s", commands_help);
278 return 0;
279 }
282 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
283 {
284 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
285 return 0;
286 }
289 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
290 {
291 wpa_cli_quit = 1;
292 return 0;
293 }
296 static void wpa_cli_show_variables(void)
297 {
298 printf("set variables:\n"
299 " EAPOL::heldPeriod (EAPOL state machine held period, "
300 "in seconds)\n"
301 " EAPOL::authPeriod (EAPOL state machine authentication "
302 "period, in seconds)\n"
303 " EAPOL::startPeriod (EAPOL state machine start period, in "
304 "seconds)\n"
305 " EAPOL::maxStart (EAPOL state machine maximum start "
306 "attempts)\n");
307 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
308 "seconds)\n"
309 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
310 " threshold\n\tpercentage)\n"
311 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
312 "security\n\tassociation in seconds)\n");
313 }
316 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
317 {
318 char cmd[256];
319 int res;
321 if (argc == 0) {
322 wpa_cli_show_variables();
323 return 0;
324 }
326 if (argc != 2) {
327 printf("Invalid SET command: needs two arguments (variable "
328 "name and value)\n");
329 return -1;
330 }
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");
335 return -1;
336 }
337 return wpa_ctrl_command(ctrl, cmd);
338 }
341 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
342 {
343 return wpa_ctrl_command(ctrl, "LOGOFF");
344 }
347 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
348 {
349 return wpa_ctrl_command(ctrl, "LOGON");
350 }
353 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
354 char *argv[])
355 {
356 return wpa_ctrl_command(ctrl, "REASSOCIATE");
357 }
360 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
361 char *argv[])
362 {
363 char cmd[256];
364 int res;
366 if (argc != 1) {
367 printf("Invalid PREAUTH command: needs one argument "
368 "(BSSID)\n");
369 return -1;
370 }
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");
375 return -1;
376 }
377 return wpa_ctrl_command(ctrl, cmd);
378 }
381 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
382 {
383 char cmd[256];
384 int res;
386 if (argc != 1) {
387 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
388 "value)\n");
389 return -1;
390 }
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");
394 return -1;
395 }
396 return wpa_ctrl_command(ctrl, cmd);
397 }
400 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
401 char *argv[])
402 {
403 char cmd[256];
404 int res;
406 if (argc != 1) {
407 printf("Invalid STKSTART command: needs one argument "
408 "(Peer STA MAC address)\n");
409 return -1;
410 }
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");
415 return -1;
416 }
417 return wpa_ctrl_command(ctrl, cmd);
418 }
421 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
422 {
423 char cmd[256];
424 int res;
426 if (argc != 1) {
427 printf("Invalid FT_DS command: needs one argument "
428 "(Target AP MAC address)\n");
429 return -1;
430 }
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");
435 return -1;
436 }
437 return wpa_ctrl_command(ctrl, cmd);
438 }
441 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
442 {
443 char cmd[256];
444 int res;
446 if (argc != 1) {
447 printf("Invalid LEVEL command: needs one argument (debug "
448 "level)\n");
449 return -1;
450 }
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");
454 return -1;
455 }
456 return wpa_ctrl_command(ctrl, cmd);
457 }
460 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
461 {
462 char cmd[256], *pos, *end;
463 int i, ret;
465 if (argc < 2) {
466 printf("Invalid IDENTITY command: needs two arguments "
467 "(network id and identity)\n");
468 return -1;
469 }
471 end = cmd + sizeof(cmd);
472 pos = cmd;
473 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
474 argv[0], argv[1]);
475 if (ret < 0 || ret >= end - pos) {
476 printf("Too long IDENTITY command.\n");
477 return -1;
478 }
479 pos += ret;
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");
484 return -1;
485 }
486 pos += ret;
487 }
489 return wpa_ctrl_command(ctrl, cmd);
490 }
493 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
494 {
495 char cmd[256], *pos, *end;
496 int i, ret;
498 if (argc < 2) {
499 printf("Invalid PASSWORD command: needs two arguments "
500 "(network id and password)\n");
501 return -1;
502 }
504 end = cmd + sizeof(cmd);
505 pos = cmd;
506 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
507 argv[0], argv[1]);
508 if (ret < 0 || ret >= end - pos) {
509 printf("Too long PASSWORD command.\n");
510 return -1;
511 }
512 pos += ret;
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");
517 return -1;
518 }
519 pos += ret;
520 }
522 return wpa_ctrl_command(ctrl, cmd);
523 }
526 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
527 char *argv[])
528 {
529 char cmd[256], *pos, *end;
530 int i, ret;
532 if (argc < 2) {
533 printf("Invalid NEW_PASSWORD command: needs two arguments "
534 "(network id and password)\n");
535 return -1;
536 }
538 end = cmd + sizeof(cmd);
539 pos = cmd;
540 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
541 argv[0], argv[1]);
542 if (ret < 0 || ret >= end - pos) {
543 printf("Too long NEW_PASSWORD command.\n");
544 return -1;
545 }
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 NEW_PASSWORD command.\n");
551 return -1;
552 }
553 pos += ret;
554 }
556 return wpa_ctrl_command(ctrl, cmd);
557 }
560 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
561 {
562 char cmd[256], *pos, *end;
563 int i, ret;
565 if (argc < 2) {
566 printf("Invalid PIN command: needs two arguments "
567 "(network id and pin)\n");
568 return -1;
569 }
571 end = cmd + sizeof(cmd);
572 pos = cmd;
573 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
574 argv[0], argv[1]);
575 if (ret < 0 || ret >= end - pos) {
576 printf("Too long PIN command.\n");
577 return -1;
578 }
579 pos += ret;
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");
584 return -1;
585 }
586 pos += ret;
587 }
588 return wpa_ctrl_command(ctrl, cmd);
589 }
592 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
593 {
594 char cmd[256], *pos, *end;
595 int i, ret;
597 if (argc < 2) {
598 printf("Invalid OTP command: needs two arguments (network "
599 "id and password)\n");
600 return -1;
601 }
603 end = cmd + sizeof(cmd);
604 pos = cmd;
605 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
606 argv[0], argv[1]);
607 if (ret < 0 || ret >= end - pos) {
608 printf("Too long OTP command.\n");
609 return -1;
610 }
611 pos += ret;
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");
616 return -1;
617 }
618 pos += ret;
619 }
621 return wpa_ctrl_command(ctrl, cmd);
622 }
625 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
626 char *argv[])
627 {
628 char cmd[256], *pos, *end;
629 int i, ret;
631 if (argc < 2) {
632 printf("Invalid PASSPHRASE command: needs two arguments "
633 "(network id and passphrase)\n");
634 return -1;
635 }
637 end = cmd + sizeof(cmd);
638 pos = cmd;
639 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
640 argv[0], argv[1]);
641 if (ret < 0 || ret >= end - pos) {
642 printf("Too long PASSPHRASE command.\n");
643 return -1;
644 }
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 PASSPHRASE command.\n");
650 return -1;
651 }
652 pos += ret;
653 }
655 return wpa_ctrl_command(ctrl, cmd);
656 }
659 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
660 {
661 char cmd[256], *pos, *end;
662 int i, ret;
664 if (argc < 2) {
665 printf("Invalid BSSID command: needs two arguments (network "
666 "id and BSSID)\n");
667 return -1;
668 }
670 end = cmd + sizeof(cmd);
671 pos = cmd;
672 ret = os_snprintf(pos, end - pos, "BSSID");
673 if (ret < 0 || ret >= end - pos) {
674 printf("Too long BSSID command.\n");
675 return -1;
676 }
677 pos += ret;
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");
682 return -1;
683 }
684 pos += ret;
685 }
687 return wpa_ctrl_command(ctrl, cmd);
688 }
691 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
692 char *argv[])
693 {
694 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
695 }
698 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
699 char *argv[])
700 {
701 char cmd[32];
702 int res;
704 if (argc < 1) {
705 printf("Invalid SELECT_NETWORK command: needs one argument "
706 "(network id)\n");
707 return -1;
708 }
710 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
711 if (res < 0 || (size_t) res >= sizeof(cmd))
712 return -1;
713 cmd[sizeof(cmd) - 1] = '\0';
715 return wpa_ctrl_command(ctrl, cmd);
716 }
719 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
720 char *argv[])
721 {
722 char cmd[32];
723 int res;
725 if (argc < 1) {
726 printf("Invalid ENABLE_NETWORK command: needs one argument "
727 "(network id)\n");
728 return -1;
729 }
731 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
732 if (res < 0 || (size_t) res >= sizeof(cmd))
733 return -1;
734 cmd[sizeof(cmd) - 1] = '\0';
736 return wpa_ctrl_command(ctrl, cmd);
737 }
740 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
741 char *argv[])
742 {
743 char cmd[32];
744 int res;
746 if (argc < 1) {
747 printf("Invalid DISABLE_NETWORK command: needs one argument "
748 "(network id)\n");
749 return -1;
750 }
752 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
753 if (res < 0 || (size_t) res >= sizeof(cmd))
754 return -1;
755 cmd[sizeof(cmd) - 1] = '\0';
757 return wpa_ctrl_command(ctrl, cmd);
758 }
761 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
762 char *argv[])
763 {
764 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
765 }
768 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
769 char *argv[])
770 {
771 char cmd[32];
772 int res;
774 if (argc < 1) {
775 printf("Invalid REMOVE_NETWORK command: needs one argument "
776 "(network id)\n");
777 return -1;
778 }
780 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
781 if (res < 0 || (size_t) res >= sizeof(cmd))
782 return -1;
783 cmd[sizeof(cmd) - 1] = '\0';
785 return wpa_ctrl_command(ctrl, cmd);
786 }
789 static void wpa_cli_show_network_variables(void)
790 {
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"
797 " ...\n"
798 "\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 "
802 "marks.\n"
803 "For example: set_network 1 ssid \"network name\"\n"
804 "\n"
805 "Please see wpa_supplicant.conf documentation for full list "
806 "of\navailable variables.\n");
807 }
810 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
811 char *argv[])
812 {
813 char cmd[256];
814 int res;
816 if (argc == 0) {
817 wpa_cli_show_network_variables();
818 return 0;
819 }
821 if (argc != 3) {
822 printf("Invalid SET_NETWORK command: needs three arguments\n"
823 "(network id, variable name, and value)\n");
824 return -1;
825 }
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");
831 return -1;
832 }
833 return wpa_ctrl_command(ctrl, cmd);
834 }
837 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
838 char *argv[])
839 {
840 char cmd[256];
841 int res;
843 if (argc == 0) {
844 wpa_cli_show_network_variables();
845 return 0;
846 }
848 if (argc != 2) {
849 printf("Invalid GET_NETWORK command: needs two arguments\n"
850 "(network id and variable name)\n");
851 return -1;
852 }
854 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
855 argv[0], argv[1]);
856 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857 printf("Too long GET_NETWORK command.\n");
858 return -1;
859 }
860 return wpa_ctrl_command(ctrl, cmd);
861 }
864 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
865 char *argv[])
866 {
867 return wpa_ctrl_command(ctrl, "DISCONNECT");
868 }
871 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
872 char *argv[])
873 {
874 return wpa_ctrl_command(ctrl, "RECONNECT");
875 }
878 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
879 char *argv[])
880 {
881 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
882 }
885 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
886 {
887 return wpa_ctrl_command(ctrl, "SCAN");
888 }
891 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
892 char *argv[])
893 {
894 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
895 }
898 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
899 {
900 char cmd[64];
901 int res;
903 if (argc != 1) {
904 printf("Invalid BSS command: need one argument (index or "
905 "BSSID)\n");
906 return -1;
907 }
909 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
910 if (res < 0 || (size_t) res >= sizeof(cmd))
911 return -1;
912 cmd[sizeof(cmd) - 1] = '\0';
914 return wpa_ctrl_command(ctrl, cmd);
915 }
918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920 {
921 char cmd[64];
922 int res;
924 if (argc < 1 || argc > 2) {
925 printf("Invalid GET_CAPABILITY command: need either one or "
926 "two arguments\n");
927 return -1;
928 }
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");
933 return -1;
934 }
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))
939 return -1;
940 cmd[sizeof(cmd) - 1] = '\0';
942 return wpa_ctrl_command(ctrl, cmd);
943 }
946 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
947 {
948 printf("Available interfaces:\n");
949 return wpa_ctrl_command(ctrl, "INTERFACES");
950 }
953 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
954 {
955 if (argc < 1) {
956 wpa_cli_list_interfaces(ctrl);
957 return 0;
958 }
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;
968 } else {
969 printf("Warning: Failed to attach to "
970 "wpa_supplicant.\n");
971 }
972 } else {
973 printf("Could not connect to interface '%s' - re-trying\n",
974 ctrl_ifname);
975 }
976 return 0;
977 }
980 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
981 char *argv[])
982 {
983 return wpa_ctrl_command(ctrl, "RECONFIGURE");
984 }
987 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
988 char *argv[])
989 {
990 return wpa_ctrl_command(ctrl, "TERMINATE");
991 }
994 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
995 char *argv[])
996 {
997 char cmd[256];
998 int res;
1000 if (argc < 1) {
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");
1005 return -1;
1006 }
1008 /*
1009 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1010 * <driver_param>TAB<bridge_name>
1011 */
1012 res = os_snprintf(cmd, sizeof(cmd),
1013 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1014 argv[0],
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))
1019 return -1;
1020 cmd[sizeof(cmd) - 1] = '\0';
1021 return wpa_ctrl_command(ctrl, cmd);
1022 }
1025 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1026 char *argv[])
1027 {
1028 char cmd[128];
1029 int res;
1031 if (argc != 1) {
1032 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1033 "(interface name)\n");
1034 return -1;
1035 }
1037 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1038 if (res < 0 || (size_t) res >= sizeof(cmd))
1039 return -1;
1040 cmd[sizeof(cmd) - 1] = '\0';
1041 return wpa_ctrl_command(ctrl, cmd);
1042 }
1045 struct wpa_cli_cmd {
1046 const char *cmd;
1047 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1048 };
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 },
1094 { NULL, NULL }
1095 };
1098 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099 {
1100 struct wpa_cli_cmd *cmd, *match = NULL;
1101 int count;
1102 int ret = 0;
1104 count = 0;
1105 cmd = wpa_cli_commands;
1106 while (cmd->cmd) {
1107 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1108 {
1109 match = cmd;
1110 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1111 /* we have an exact match */
1112 count = 1;
1113 break;
1114 }
1115 count++;
1116 }
1117 cmd++;
1118 }
1120 if (count > 1) {
1121 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1122 cmd = wpa_cli_commands;
1123 while (cmd->cmd) {
1124 if (os_strncasecmp(cmd->cmd, argv[0],
1125 os_strlen(argv[0])) == 0) {
1126 printf(" %s", cmd->cmd);
1127 }
1128 cmd++;
1129 }
1130 printf("\n");
1131 ret = 1;
1132 } else if (count == 0) {
1133 printf("Unknown command '%s'\n", argv[0]);
1134 ret = 1;
1135 } else {
1136 ret = match->handler(ctrl, argc - 1, &argv[1]);
1137 }
1139 return ret;
1140 }
1143 static int str_match(const char *a, const char *b)
1144 {
1145 return os_strncmp(a, b, os_strlen(b)) == 0;
1146 }
1149 static int wpa_cli_exec(const char *program, const char *arg1,
1150 const char *arg2)
1151 {
1152 char *cmd;
1153 size_t len;
1154 int res;
1156 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1157 cmd = os_malloc(len);
1158 if (cmd == NULL)
1159 return -1;
1160 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1161 if (res < 0 || (size_t) res >= len) {
1162 os_free(cmd);
1163 return -1;
1164 }
1165 cmd[len - 1] = '\0';
1166 #ifndef _WIN32_WCE
1167 system(cmd);
1168 #endif /* _WIN32_WCE */
1169 os_free(cmd);
1171 return 0;
1172 }
1175 static void wpa_cli_action_process(const char *msg)
1176 {
1177 const char *pos;
1178 char *copy = NULL, *id, *pos2;
1180 pos = msg;
1181 if (*pos == '<') {
1182 /* skip priority */
1183 pos = os_strchr(pos, '>');
1184 if (pos)
1185 pos++;
1186 else
1187 pos = msg;
1188 }
1190 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1191 int new_id = -1;
1192 os_unsetenv("WPA_ID");
1193 os_unsetenv("WPA_ID_STR");
1194 os_unsetenv("WPA_CTRL_DIR");
1196 pos = os_strstr(pos, "[id=");
1197 if (pos)
1198 copy = os_strdup(pos + 4);
1200 if (copy) {
1201 pos2 = id = copy;
1202 while (*pos2 && *pos2 != ' ')
1203 pos2++;
1204 *pos2++ = '\0';
1205 new_id = atoi(id);
1206 os_setenv("WPA_ID", id, 1);
1207 while (*pos2 && *pos2 != '=')
1208 pos2++;
1209 if (*pos2 == '=')
1210 pos2++;
1211 id = pos2;
1212 while (*pos2 && *pos2 != ']')
1213 pos2++;
1214 *pos2 = '\0';
1215 os_setenv("WPA_ID_STR", id, 1);
1216 os_free(copy);
1217 }
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");
1225 }
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");
1230 }
1231 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1232 printf("wpa_supplicant is terminating - stop monitoring\n");
1233 wpa_cli_quit = 1;
1234 }
1235 }
1238 #ifndef CONFIG_ANSI_C_EXTRA
1239 static void wpa_cli_action_cb(char *msg, size_t len)
1240 {
1241 wpa_cli_action_process(msg);
1242 }
1243 #endif /* CONFIG_ANSI_C_EXTRA */
1246 static void wpa_cli_reconnect(void)
1247 {
1248 wpa_cli_close_connection();
1249 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1250 if (ctrl_conn) {
1251 printf("Connection to wpa_supplicant re-established\n");
1252 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1253 wpa_cli_attached = 1;
1254 } else {
1255 printf("Warning: Failed to attach to "
1256 "wpa_supplicant.\n");
1257 }
1258 }
1259 }
1262 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1263 int action_monitor)
1264 {
1265 int first = 1;
1266 if (ctrl_conn == NULL) {
1267 wpa_cli_reconnect();
1268 return;
1269 }
1270 while (wpa_ctrl_pending(ctrl) > 0) {
1271 char buf[256];
1272 size_t len = sizeof(buf) - 1;
1273 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1274 buf[len] = '\0';
1275 if (action_monitor)
1276 wpa_cli_action_process(buf);
1277 else {
1278 if (in_read && first)
1279 printf("\n");
1280 first = 0;
1281 printf("%s\n", buf);
1282 }
1283 } else {
1284 printf("Could not read pending message.\n");
1285 break;
1286 }
1287 }
1289 if (wpa_ctrl_pending(ctrl) < 0) {
1290 printf("Connection to wpa_supplicant lost - trying to "
1291 "reconnect\n");
1292 wpa_cli_reconnect();
1293 }
1294 }
1297 #ifdef CONFIG_READLINE
1298 static char * wpa_cli_cmd_gen(const char *text, int state)
1299 {
1300 static int i, len;
1301 const char *cmd;
1303 if (state == 0) {
1304 i = 0;
1305 len = os_strlen(text);
1306 }
1308 while ((cmd = wpa_cli_commands[i].cmd)) {
1309 i++;
1310 if (os_strncasecmp(cmd, text, len) == 0)
1311 return os_strdup(cmd);
1312 }
1314 return NULL;
1315 }
1318 static char * wpa_cli_dummy_gen(const char *text, int state)
1319 {
1320 return NULL;
1321 }
1324 static char ** wpa_cli_completion(const char *text, int start, int end)
1325 {
1326 return rl_completion_matches(text, start == 0 ?
1327 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1328 }
1329 #endif /* CONFIG_READLINE */
1332 static void wpa_cli_interactive(void)
1333 {
1334 #define max_args 10
1335 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1336 int argc;
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");
1346 if (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);
1350 if (hfile) {
1351 int res;
1352 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1353 fname);
1354 if (res >= 0 && res < hfile_len) {
1355 hfile[hfile_len - 1] = '\0';
1356 read_history(hfile);
1357 stifle_history(100);
1358 }
1359 }
1360 }
1361 #endif /* CONFIG_READLINE */
1363 do {
1364 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1365 #ifndef CONFIG_NATIVE_WINDOWS
1366 alarm(1);
1367 #endif /* CONFIG_NATIVE_WINDOWS */
1368 #ifdef CONFIG_READLINE
1369 cmd = readline("> ");
1370 if (cmd && *cmd) {
1371 HIST_ENTRY *h;
1372 while (next_history())
1373 ;
1374 h = previous_history();
1375 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1376 add_history(cmd);
1377 next_history();
1378 }
1379 #else /* CONFIG_READLINE */
1380 printf("> ");
1381 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1382 #endif /* CONFIG_READLINE */
1383 #ifndef CONFIG_NATIVE_WINDOWS
1384 alarm(0);
1385 #endif /* CONFIG_NATIVE_WINDOWS */
1386 if (cmd == NULL)
1387 break;
1388 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1389 pos = cmd;
1390 while (*pos != '\0') {
1391 if (*pos == '\n') {
1392 *pos = '\0';
1393 break;
1394 }
1395 pos++;
1396 }
1397 argc = 0;
1398 pos = cmd;
1399 for (;;) {
1400 while (*pos == ' ')
1401 pos++;
1402 if (*pos == '\0')
1403 break;
1404 argv[argc] = pos;
1405 argc++;
1406 if (argc == max_args)
1407 break;
1408 if (*pos == '"') {
1409 char *pos2 = os_strrchr(pos, '"');
1410 if (pos2)
1411 pos = pos2 + 1;
1412 }
1413 while (*pos != '\0' && *pos != ' ')
1414 pos++;
1415 if (*pos == ' ')
1416 *pos++ = '\0';
1417 }
1418 if (argc)
1419 wpa_request(ctrl_conn, argc, argv);
1421 if (cmd != cmdbuf)
1422 os_free(cmd);
1423 } while (!wpa_cli_quit);
1425 #ifdef CONFIG_READLINE
1426 if (hfile) {
1427 /* Save command history, excluding lines that may contain
1428 * passwords. */
1429 HIST_ENTRY *h;
1430 history_set_pos(0);
1431 h = next_history();
1432 while (h) {
1433 char *p = h->line;
1434 while (*p == ' ' || *p == '\t')
1435 p++;
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());
1440 if (h) {
1441 os_free(h->line);
1442 os_free(h->data);
1443 os_free(h);
1444 }
1445 h = current_history();
1446 } else {
1447 h = next_history();
1448 }
1449 }
1450 write_history(hfile);
1451 os_free(hfile);
1452 }
1453 #endif /* CONFIG_READLINE */
1454 }
1457 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1458 {
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 */
1463 fd_set rfds;
1464 int fd, res;
1465 struct timeval tv;
1466 char buf[256]; /* note: large enough to fit in unsolicited messages */
1467 size_t len;
1469 fd = wpa_ctrl_get_fd(ctrl);
1471 while (!wpa_cli_quit) {
1472 FD_ZERO(&rfds);
1473 FD_SET(fd, &rfds);
1474 tv.tv_sec = 2;
1475 tv.tv_usec = 0;
1476 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1477 if (res < 0 && errno != EINTR) {
1478 perror("select");
1479 break;
1480 }
1482 if (FD_ISSET(fd, &rfds))
1483 wpa_cli_recv_pending(ctrl, 0, 1);
1484 else {
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");
1492 break;
1493 }
1494 }
1495 }
1496 #endif /* CONFIG_ANSI_C_EXTRA */
1497 }
1500 static void wpa_cli_cleanup(void)
1501 {
1502 wpa_cli_close_connection();
1503 if (pid_file)
1504 os_daemonize_terminate(pid_file);
1506 os_program_deinit();
1507 }
1509 static void wpa_cli_terminate(int sig)
1510 {
1511 wpa_cli_cleanup();
1512 exit(0);
1513 }
1516 #ifndef CONFIG_NATIVE_WINDOWS
1517 static void wpa_cli_alarm(int sig)
1518 {
1519 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1520 printf("Connection to wpa_supplicant lost - trying to "
1521 "reconnect\n");
1522 wpa_cli_close_connection();
1523 }
1524 if (!ctrl_conn)
1525 wpa_cli_reconnect();
1526 if (ctrl_conn)
1527 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1528 alarm(1);
1529 }
1530 #endif /* CONFIG_NATIVE_WINDOWS */
1533 static char * wpa_cli_get_default_ifname(void)
1534 {
1535 char *ifname = NULL;
1537 #ifdef CONFIG_CTRL_IFACE_UNIX
1538 struct dirent *dent;
1539 DIR *dir = opendir(ctrl_iface_dir);
1540 if (!dir)
1541 return NULL;
1542 while ((dent = readdir(dir))) {
1543 #ifdef _DIRENT_HAVE_D_TYPE
1544 /*
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.
1548 */
1549 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1550 continue;
1551 #endif /* _DIRENT_HAVE_D_TYPE */
1552 if (os_strcmp(dent->d_name, ".") == 0 ||
1553 os_strcmp(dent->d_name, "..") == 0)
1554 continue;
1555 printf("Selected interface '%s'\n", dent->d_name);
1556 ifname = os_strdup(dent->d_name);
1557 break;
1558 }
1559 closedir(dir);
1560 #endif /* CONFIG_CTRL_IFACE_UNIX */
1562 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1563 char buf[2048], *pos;
1564 size_t len;
1565 struct wpa_ctrl *ctrl;
1566 int ret;
1568 ctrl = wpa_ctrl_open(NULL);
1569 if (ctrl == NULL)
1570 return NULL;
1572 len = sizeof(buf) - 1;
1573 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1574 if (ret >= 0) {
1575 buf[len] = '\0';
1576 pos = os_strchr(buf, '\n');
1577 if (pos)
1578 *pos = '\0';
1579 ifname = os_strdup(buf);
1580 }
1581 wpa_ctrl_close(ctrl);
1582 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1584 return ifname;
1585 }
1588 int main(int argc, char *argv[])
1589 {
1590 int interactive;
1591 int warning_displayed = 0;
1592 int c;
1593 int daemonize = 0;
1594 int ret = 0;
1595 const char *global = NULL;
1597 if (os_program_init())
1598 return -1;
1600 for (;;) {
1601 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1602 if (c < 0)
1603 break;
1604 switch (c) {
1605 case 'a':
1606 action_file = optarg;
1607 break;
1608 case 'B':
1609 daemonize = 1;
1610 break;
1611 case 'g':
1612 global = optarg;
1613 break;
1614 case 'h':
1615 usage();
1616 return 0;
1617 case 'v':
1618 printf("%s\n", wpa_cli_version);
1619 return 0;
1620 case 'i':
1621 os_free(ctrl_ifname);
1622 ctrl_ifname = os_strdup(optarg);
1623 break;
1624 case 'p':
1625 ctrl_iface_dir = optarg;
1626 break;
1627 case 'P':
1628 pid_file = optarg;
1629 break;
1630 default:
1631 usage();
1632 return -1;
1633 }
1634 }
1636 interactive = (argc == optind) && (action_file == NULL);
1638 if (interactive)
1639 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1641 if (global) {
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 - "
1649 "wpa_ctrl_open");
1650 return -1;
1651 }
1652 }
1654 for (; !global;) {
1655 if (ctrl_ifname == NULL)
1656 ctrl_ifname = wpa_cli_get_default_ifname();
1657 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1658 if (ctrl_conn) {
1659 if (warning_displayed)
1660 printf("Connection established.\n");
1661 break;
1662 }
1664 if (!interactive) {
1665 perror("Failed to connect to wpa_supplicant - "
1666 "wpa_ctrl_open");
1667 return -1;
1668 }
1670 if (!warning_displayed) {
1671 printf("Could not connect to wpa_supplicant - "
1672 "re-trying\n");
1673 warning_displayed = 1;
1674 }
1675 os_sleep(1, 0);
1676 continue;
1677 }
1679 #ifndef _WIN32_WCE
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;
1690 } else {
1691 printf("Warning: Failed to attach to "
1692 "wpa_supplicant.\n");
1693 if (!interactive)
1694 return -1;
1695 }
1696 }
1698 if (daemonize && os_daemonize(pid_file))
1699 return -1;
1701 if (interactive)
1702 wpa_cli_interactive();
1703 else if (action_file)
1704 wpa_cli_action(ctrl_conn);
1705 else
1706 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1708 os_free(ctrl_ifname);
1709 wpa_cli_cleanup();
1711 return ret;
1712 }
1714 #else /* CONFIG_CTRL_IFACE */
1715 int main(int argc, char *argv[])
1716 {
1717 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1718 return -1;
1719 }
1720 #endif /* CONFIG_CTRL_IFACE */