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 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;
100 static void print_help();
103 static void usage(void)
104 {
105 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
106 "[-a<action file>] \\\n"
107 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
108 " -h = help (show this usage text)\n"
109 " -v = shown version information\n"
110 " -a = run in daemon mode executing the action file based on "
111 "events from\n"
112 " wpa_supplicant\n"
113 " -B = run a daemon in the background\n"
114 " default path: /var/run/wpa_supplicant\n"
115 " default interface: first interface found in socket path\n");
116 print_help();
117 }
120 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
121 {
122 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
123 ctrl_conn = wpa_ctrl_open(ifname);
124 return ctrl_conn;
125 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
126 char *cfile;
127 int flen, res;
129 if (ifname == NULL)
130 return NULL;
132 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
133 cfile = os_malloc(flen);
134 if (cfile == NULL)
135 return NULL;
136 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
137 if (res < 0 || res >= flen) {
138 os_free(cfile);
139 return NULL;
140 }
142 ctrl_conn = wpa_ctrl_open(cfile);
143 os_free(cfile);
144 return ctrl_conn;
145 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
146 }
149 static void wpa_cli_close_connection(void)
150 {
151 if (ctrl_conn == NULL)
152 return;
154 if (wpa_cli_attached) {
155 wpa_ctrl_detach(ctrl_conn);
156 wpa_cli_attached = 0;
157 }
158 wpa_ctrl_close(ctrl_conn);
159 ctrl_conn = NULL;
160 }
163 static void wpa_cli_msg_cb(char *msg, size_t len)
164 {
165 printf("%s\n", msg);
166 }
169 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
170 {
171 char buf[2048];
172 size_t len;
173 int ret;
175 if (ctrl_conn == NULL) {
176 printf("Not connected to wpa_supplicant - command dropped.\n");
177 return -1;
178 }
179 len = sizeof(buf) - 1;
180 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
181 wpa_cli_msg_cb);
182 if (ret == -2) {
183 printf("'%s' command timed out.\n", cmd);
184 return -2;
185 } else if (ret < 0) {
186 printf("'%s' command failed.\n", cmd);
187 return -1;
188 }
189 if (print) {
190 buf[len] = '\0';
191 printf("%s", buf);
192 }
193 return 0;
194 }
197 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
198 {
199 return _wpa_ctrl_command(ctrl, cmd, 1);
200 }
203 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
204 {
205 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
206 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
207 }
210 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
211 {
212 return wpa_ctrl_command(ctrl, "PING");
213 }
216 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
217 {
218 return wpa_ctrl_command(ctrl, "MIB");
219 }
222 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
223 {
224 return wpa_ctrl_command(ctrl, "PMKSA");
225 }
228 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
229 {
230 print_help();
231 return 0;
232 }
235 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
236 {
237 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
238 return 0;
239 }
242 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
243 {
244 wpa_cli_quit = 1;
245 return 0;
246 }
249 static void wpa_cli_show_variables(void)
250 {
251 printf("set variables:\n"
252 " EAPOL::heldPeriod (EAPOL state machine held period, "
253 "in seconds)\n"
254 " EAPOL::authPeriod (EAPOL state machine authentication "
255 "period, in seconds)\n"
256 " EAPOL::startPeriod (EAPOL state machine start period, in "
257 "seconds)\n"
258 " EAPOL::maxStart (EAPOL state machine maximum start "
259 "attempts)\n");
260 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
261 "seconds)\n"
262 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
263 " threshold\n\tpercentage)\n"
264 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
265 "security\n\tassociation in seconds)\n");
266 }
269 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
270 {
271 char cmd[256];
272 int res;
274 if (argc == 0) {
275 wpa_cli_show_variables();
276 return 0;
277 }
279 if (argc != 2) {
280 printf("Invalid SET command: needs two arguments (variable "
281 "name and value)\n");
282 return -1;
283 }
285 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
286 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
287 printf("Too long SET command.\n");
288 return -1;
289 }
290 return wpa_ctrl_command(ctrl, cmd);
291 }
294 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
295 {
296 return wpa_ctrl_command(ctrl, "LOGOFF");
297 }
300 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
301 {
302 return wpa_ctrl_command(ctrl, "LOGON");
303 }
306 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
307 char *argv[])
308 {
309 return wpa_ctrl_command(ctrl, "REASSOCIATE");
310 }
313 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
314 char *argv[])
315 {
316 char cmd[256];
317 int res;
319 if (argc != 1) {
320 printf("Invalid PREAUTH command: needs one argument "
321 "(BSSID)\n");
322 return -1;
323 }
325 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
326 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
327 printf("Too long PREAUTH command.\n");
328 return -1;
329 }
330 return wpa_ctrl_command(ctrl, cmd);
331 }
334 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
335 {
336 char cmd[256];
337 int res;
339 if (argc != 1) {
340 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
341 "value)\n");
342 return -1;
343 }
344 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
345 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
346 printf("Too long AP_SCAN command.\n");
347 return -1;
348 }
349 return wpa_ctrl_command(ctrl, cmd);
350 }
353 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
354 char *argv[])
355 {
356 char cmd[256];
357 int res;
359 if (argc != 1) {
360 printf("Invalid STKSTART command: needs one argument "
361 "(Peer STA MAC address)\n");
362 return -1;
363 }
365 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
366 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
367 printf("Too long STKSTART command.\n");
368 return -1;
369 }
370 return wpa_ctrl_command(ctrl, cmd);
371 }
374 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
375 {
376 char cmd[256];
377 int res;
379 if (argc != 1) {
380 printf("Invalid FT_DS command: needs one argument "
381 "(Target AP MAC address)\n");
382 return -1;
383 }
385 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
386 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
387 printf("Too long FT_DS command.\n");
388 return -1;
389 }
390 return wpa_ctrl_command(ctrl, cmd);
391 }
394 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
395 {
396 char cmd[256];
397 int res;
399 if (argc == 0) {
400 /* Any BSSID */
401 return wpa_ctrl_command(ctrl, "WPS_PBC");
402 }
404 /* Specific BSSID */
405 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
406 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
407 printf("Too long WPS_PBC command.\n");
408 return -1;
409 }
410 return wpa_ctrl_command(ctrl, cmd);
411 }
414 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
415 {
416 char cmd[256];
417 int res;
419 if (argc == 0) {
420 printf("Invalid WPS_PIN command: need one or two arguments:\n"
421 "- BSSID: use 'any' to select any\n"
422 "- PIN: optional, used only with devices that have no "
423 "display\n");
424 return -1;
425 }
427 if (argc == 1) {
428 /* Use dynamically generated PIN (returned as reply) */
429 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
430 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
431 printf("Too long WPS_PIN command.\n");
432 return -1;
433 }
434 return wpa_ctrl_command(ctrl, cmd);
435 }
437 /* Use hardcoded PIN from a label */
438 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
439 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
440 printf("Too long WPS_PIN command.\n");
441 return -1;
442 }
443 return wpa_ctrl_command(ctrl, cmd);
444 }
447 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
448 {
449 char cmd[256];
450 int res;
452 if (argc != 2) {
453 printf("Invalid WPS_REG command: need two arguments:\n"
454 "- BSSID: use 'any' to select any\n"
455 "- AP PIN\n");
456 return -1;
457 }
459 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
460 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
461 printf("Too long WPS_REG command.\n");
462 return -1;
463 }
464 return wpa_ctrl_command(ctrl, cmd);
465 }
468 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
469 {
470 char cmd[256];
471 int res;
473 if (argc != 1) {
474 printf("Invalid LEVEL command: needs one argument (debug "
475 "level)\n");
476 return -1;
477 }
478 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
479 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
480 printf("Too long LEVEL command.\n");
481 return -1;
482 }
483 return wpa_ctrl_command(ctrl, cmd);
484 }
487 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
488 {
489 char cmd[256], *pos, *end;
490 int i, ret;
492 if (argc < 2) {
493 printf("Invalid IDENTITY command: needs two arguments "
494 "(network id and identity)\n");
495 return -1;
496 }
498 end = cmd + sizeof(cmd);
499 pos = cmd;
500 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
501 argv[0], argv[1]);
502 if (ret < 0 || ret >= end - pos) {
503 printf("Too long IDENTITY command.\n");
504 return -1;
505 }
506 pos += ret;
507 for (i = 2; i < argc; i++) {
508 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
509 if (ret < 0 || ret >= end - pos) {
510 printf("Too long IDENTITY command.\n");
511 return -1;
512 }
513 pos += ret;
514 }
516 return wpa_ctrl_command(ctrl, cmd);
517 }
520 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
521 {
522 char cmd[256], *pos, *end;
523 int i, ret;
525 if (argc < 2) {
526 printf("Invalid PASSWORD command: needs two arguments "
527 "(network id and password)\n");
528 return -1;
529 }
531 end = cmd + sizeof(cmd);
532 pos = cmd;
533 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
534 argv[0], argv[1]);
535 if (ret < 0 || ret >= end - pos) {
536 printf("Too long PASSWORD command.\n");
537 return -1;
538 }
539 pos += ret;
540 for (i = 2; i < argc; i++) {
541 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
542 if (ret < 0 || ret >= end - pos) {
543 printf("Too long PASSWORD command.\n");
544 return -1;
545 }
546 pos += ret;
547 }
549 return wpa_ctrl_command(ctrl, cmd);
550 }
553 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
554 char *argv[])
555 {
556 char cmd[256], *pos, *end;
557 int i, ret;
559 if (argc < 2) {
560 printf("Invalid NEW_PASSWORD command: needs two arguments "
561 "(network id and password)\n");
562 return -1;
563 }
565 end = cmd + sizeof(cmd);
566 pos = cmd;
567 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
568 argv[0], argv[1]);
569 if (ret < 0 || ret >= end - pos) {
570 printf("Too long NEW_PASSWORD command.\n");
571 return -1;
572 }
573 pos += ret;
574 for (i = 2; i < argc; i++) {
575 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
576 if (ret < 0 || ret >= end - pos) {
577 printf("Too long NEW_PASSWORD command.\n");
578 return -1;
579 }
580 pos += ret;
581 }
583 return wpa_ctrl_command(ctrl, cmd);
584 }
587 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
588 {
589 char cmd[256], *pos, *end;
590 int i, ret;
592 if (argc < 2) {
593 printf("Invalid PIN command: needs two arguments "
594 "(network id and pin)\n");
595 return -1;
596 }
598 end = cmd + sizeof(cmd);
599 pos = cmd;
600 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
601 argv[0], argv[1]);
602 if (ret < 0 || ret >= end - pos) {
603 printf("Too long PIN command.\n");
604 return -1;
605 }
606 pos += ret;
607 for (i = 2; i < argc; i++) {
608 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
609 if (ret < 0 || ret >= end - pos) {
610 printf("Too long PIN command.\n");
611 return -1;
612 }
613 pos += ret;
614 }
615 return wpa_ctrl_command(ctrl, cmd);
616 }
619 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
620 {
621 char cmd[256], *pos, *end;
622 int i, ret;
624 if (argc < 2) {
625 printf("Invalid OTP command: needs two arguments (network "
626 "id and password)\n");
627 return -1;
628 }
630 end = cmd + sizeof(cmd);
631 pos = cmd;
632 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
633 argv[0], argv[1]);
634 if (ret < 0 || ret >= end - pos) {
635 printf("Too long OTP command.\n");
636 return -1;
637 }
638 pos += ret;
639 for (i = 2; i < argc; i++) {
640 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
641 if (ret < 0 || ret >= end - pos) {
642 printf("Too long OTP command.\n");
643 return -1;
644 }
645 pos += ret;
646 }
648 return wpa_ctrl_command(ctrl, cmd);
649 }
652 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
653 char *argv[])
654 {
655 char cmd[256], *pos, *end;
656 int i, ret;
658 if (argc < 2) {
659 printf("Invalid PASSPHRASE command: needs two arguments "
660 "(network id and passphrase)\n");
661 return -1;
662 }
664 end = cmd + sizeof(cmd);
665 pos = cmd;
666 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
667 argv[0], argv[1]);
668 if (ret < 0 || ret >= end - pos) {
669 printf("Too long PASSPHRASE command.\n");
670 return -1;
671 }
672 pos += ret;
673 for (i = 2; i < argc; i++) {
674 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
675 if (ret < 0 || ret >= end - pos) {
676 printf("Too long PASSPHRASE command.\n");
677 return -1;
678 }
679 pos += ret;
680 }
682 return wpa_ctrl_command(ctrl, cmd);
683 }
686 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
687 {
688 char cmd[256], *pos, *end;
689 int i, ret;
691 if (argc < 2) {
692 printf("Invalid BSSID command: needs two arguments (network "
693 "id and BSSID)\n");
694 return -1;
695 }
697 end = cmd + sizeof(cmd);
698 pos = cmd;
699 ret = os_snprintf(pos, end - pos, "BSSID");
700 if (ret < 0 || ret >= end - pos) {
701 printf("Too long BSSID command.\n");
702 return -1;
703 }
704 pos += ret;
705 for (i = 0; i < argc; i++) {
706 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
707 if (ret < 0 || ret >= end - pos) {
708 printf("Too long BSSID command.\n");
709 return -1;
710 }
711 pos += ret;
712 }
714 return wpa_ctrl_command(ctrl, cmd);
715 }
718 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
719 char *argv[])
720 {
721 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
722 }
725 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
727 {
728 char cmd[32];
729 int res;
731 if (argc < 1) {
732 printf("Invalid SELECT_NETWORK command: needs one argument "
733 "(network id)\n");
734 return -1;
735 }
737 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
738 if (res < 0 || (size_t) res >= sizeof(cmd))
739 return -1;
740 cmd[sizeof(cmd) - 1] = '\0';
742 return wpa_ctrl_command(ctrl, cmd);
743 }
746 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
747 char *argv[])
748 {
749 char cmd[32];
750 int res;
752 if (argc < 1) {
753 printf("Invalid ENABLE_NETWORK command: needs one argument "
754 "(network id)\n");
755 return -1;
756 }
758 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
759 if (res < 0 || (size_t) res >= sizeof(cmd))
760 return -1;
761 cmd[sizeof(cmd) - 1] = '\0';
763 return wpa_ctrl_command(ctrl, cmd);
764 }
767 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
768 char *argv[])
769 {
770 char cmd[32];
771 int res;
773 if (argc < 1) {
774 printf("Invalid DISABLE_NETWORK command: needs one argument "
775 "(network id)\n");
776 return -1;
777 }
779 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
780 if (res < 0 || (size_t) res >= sizeof(cmd))
781 return -1;
782 cmd[sizeof(cmd) - 1] = '\0';
784 return wpa_ctrl_command(ctrl, cmd);
785 }
788 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
789 char *argv[])
790 {
791 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
792 }
795 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
796 char *argv[])
797 {
798 char cmd[32];
799 int res;
801 if (argc < 1) {
802 printf("Invalid REMOVE_NETWORK command: needs one argument "
803 "(network id)\n");
804 return -1;
805 }
807 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
808 if (res < 0 || (size_t) res >= sizeof(cmd))
809 return -1;
810 cmd[sizeof(cmd) - 1] = '\0';
812 return wpa_ctrl_command(ctrl, cmd);
813 }
816 static void wpa_cli_show_network_variables(void)
817 {
818 printf("set_network variables:\n"
819 " ssid (network name, SSID)\n"
820 " psk (WPA passphrase or pre-shared key)\n"
821 " key_mgmt (key management protocol)\n"
822 " identity (EAP identity)\n"
823 " password (EAP password)\n"
824 " ...\n"
825 "\n"
826 "Note: Values are entered in the same format as the "
827 "configuration file is using,\n"
828 "i.e., strings values need to be inside double quotation "
829 "marks.\n"
830 "For example: set_network 1 ssid \"network name\"\n"
831 "\n"
832 "Please see wpa_supplicant.conf documentation for full list "
833 "of\navailable variables.\n");
834 }
837 static int wpa_cli_cmd_set_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 != 3) {
849 printf("Invalid SET_NETWORK command: needs three arguments\n"
850 "(network id, variable name, and value)\n");
851 return -1;
852 }
854 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
855 argv[0], argv[1], argv[2]);
856 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
857 printf("Too long SET_NETWORK command.\n");
858 return -1;
859 }
860 return wpa_ctrl_command(ctrl, cmd);
861 }
864 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
865 char *argv[])
866 {
867 char cmd[256];
868 int res;
870 if (argc == 0) {
871 wpa_cli_show_network_variables();
872 return 0;
873 }
875 if (argc != 2) {
876 printf("Invalid GET_NETWORK command: needs two arguments\n"
877 "(network id and variable name)\n");
878 return -1;
879 }
881 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
882 argv[0], argv[1]);
883 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
884 printf("Too long GET_NETWORK command.\n");
885 return -1;
886 }
887 return wpa_ctrl_command(ctrl, cmd);
888 }
891 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
892 char *argv[])
893 {
894 return wpa_ctrl_command(ctrl, "DISCONNECT");
895 }
898 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
899 char *argv[])
900 {
901 return wpa_ctrl_command(ctrl, "RECONNECT");
902 }
905 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
906 char *argv[])
907 {
908 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
909 }
912 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
913 {
914 return wpa_ctrl_command(ctrl, "SCAN");
915 }
918 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920 {
921 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
922 }
925 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
926 {
927 char cmd[64];
928 int res;
930 if (argc != 1) {
931 printf("Invalid BSS command: need one argument (index or "
932 "BSSID)\n");
933 return -1;
934 }
936 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
937 if (res < 0 || (size_t) res >= sizeof(cmd))
938 return -1;
939 cmd[sizeof(cmd) - 1] = '\0';
941 return wpa_ctrl_command(ctrl, cmd);
942 }
945 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947 {
948 char cmd[64];
949 int res;
951 if (argc < 1 || argc > 2) {
952 printf("Invalid GET_CAPABILITY command: need either one or "
953 "two arguments\n");
954 return -1;
955 }
957 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
958 printf("Invalid GET_CAPABILITY command: second argument, "
959 "if any, must be 'strict'\n");
960 return -1;
961 }
963 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
964 (argc == 2) ? " strict" : "");
965 if (res < 0 || (size_t) res >= sizeof(cmd))
966 return -1;
967 cmd[sizeof(cmd) - 1] = '\0';
969 return wpa_ctrl_command(ctrl, cmd);
970 }
973 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
974 {
975 printf("Available interfaces:\n");
976 return wpa_ctrl_command(ctrl, "INTERFACES");
977 }
980 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
981 {
982 if (argc < 1) {
983 wpa_cli_list_interfaces(ctrl);
984 return 0;
985 }
987 wpa_cli_close_connection();
988 os_free(ctrl_ifname);
989 ctrl_ifname = os_strdup(argv[0]);
991 if (wpa_cli_open_connection(ctrl_ifname)) {
992 printf("Connected to interface '%s.\n", ctrl_ifname);
993 if (wpa_ctrl_attach(ctrl_conn) == 0) {
994 wpa_cli_attached = 1;
995 } else {
996 printf("Warning: Failed to attach to "
997 "wpa_supplicant.\n");
998 }
999 } else {
1000 printf("Could not connect to interface '%s' - re-trying\n",
1001 ctrl_ifname);
1002 }
1003 return 0;
1004 }
1007 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1008 char *argv[])
1009 {
1010 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1011 }
1014 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1015 char *argv[])
1016 {
1017 return wpa_ctrl_command(ctrl, "TERMINATE");
1018 }
1021 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1022 char *argv[])
1023 {
1024 char cmd[256];
1025 int res;
1027 if (argc < 1) {
1028 printf("Invalid INTERFACE_ADD command: needs at least one "
1029 "argument (interface name)\n"
1030 "All arguments: ifname confname driver ctrl_interface "
1031 "driver_param bridge_name\n");
1032 return -1;
1033 }
1035 /*
1036 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1037 * <driver_param>TAB<bridge_name>
1038 */
1039 res = os_snprintf(cmd, sizeof(cmd),
1040 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1041 argv[0],
1042 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1043 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1044 argc > 5 ? argv[5] : "");
1045 if (res < 0 || (size_t) res >= sizeof(cmd))
1046 return -1;
1047 cmd[sizeof(cmd) - 1] = '\0';
1048 return wpa_ctrl_command(ctrl, cmd);
1049 }
1052 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1053 char *argv[])
1054 {
1055 char cmd[128];
1056 int res;
1058 if (argc != 1) {
1059 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1060 "(interface name)\n");
1061 return -1;
1062 }
1064 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1065 if (res < 0 || (size_t) res >= sizeof(cmd))
1066 return -1;
1067 cmd[sizeof(cmd) - 1] = '\0';
1068 return wpa_ctrl_command(ctrl, cmd);
1069 }
1072 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1073 char *argv[])
1074 {
1075 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1076 }
1079 enum wpa_cli_cmd_flags {
1080 cli_cmd_flag_none = 0x00,
1081 cli_cmd_flag_sensitive = 0x01
1082 };
1084 struct wpa_cli_cmd {
1085 const char *cmd;
1086 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1087 enum wpa_cli_cmd_flags flags;
1088 const char *usage;
1089 };
1091 static struct wpa_cli_cmd wpa_cli_commands[] = {
1092 { "status", wpa_cli_cmd_status,
1093 cli_cmd_flag_none,
1094 "[verbose] = get current WPA/EAPOL/EAP status" },
1095 { "ping", wpa_cli_cmd_ping,
1096 cli_cmd_flag_none,
1097 "= pings wpa_supplicant" },
1098 { "mib", wpa_cli_cmd_mib,
1099 cli_cmd_flag_none,
1100 "= get MIB variables (dot1x, dot11)" },
1101 { "help", wpa_cli_cmd_help,
1102 cli_cmd_flag_none,
1103 "= show this usage help" },
1104 { "interface", wpa_cli_cmd_interface,
1105 cli_cmd_flag_none,
1106 "[ifname] = show interfaces/select interface" },
1107 { "level", wpa_cli_cmd_level,
1108 cli_cmd_flag_none,
1109 "<debug level> = change debug level" },
1110 { "license", wpa_cli_cmd_license,
1111 cli_cmd_flag_none,
1112 "= show full wpa_cli license" },
1113 { "quit", wpa_cli_cmd_quit,
1114 cli_cmd_flag_none,
1115 "= exit wpa_cli" },
1116 { "set", wpa_cli_cmd_set,
1117 cli_cmd_flag_none,
1118 "= set variables (shows list of variables when run without "
1119 "arguments)" },
1120 { "logon", wpa_cli_cmd_logon,
1121 cli_cmd_flag_none,
1122 "= IEEE 802.1X EAPOL state machine logon" },
1123 { "logoff", wpa_cli_cmd_logoff,
1124 cli_cmd_flag_none,
1125 "= IEEE 802.1X EAPOL state machine logoff" },
1126 { "pmksa", wpa_cli_cmd_pmksa,
1127 cli_cmd_flag_none,
1128 "= show PMKSA cache" },
1129 { "reassociate", wpa_cli_cmd_reassociate,
1130 cli_cmd_flag_none,
1131 "= force reassociation" },
1132 { "preauthenticate", wpa_cli_cmd_preauthenticate,
1133 cli_cmd_flag_none,
1134 "<BSSID> = force preauthentication" },
1135 { "identity", wpa_cli_cmd_identity,
1136 cli_cmd_flag_none,
1137 "<network id> <identity> = configure identity for an SSID" },
1138 { "password", wpa_cli_cmd_password,
1139 cli_cmd_flag_sensitive,
1140 "<network id> <password> = configure password for an SSID" },
1141 { "new_password", wpa_cli_cmd_new_password,
1142 cli_cmd_flag_sensitive,
1143 "<network id> <password> = change password for an SSID" },
1144 { "pin", wpa_cli_cmd_pin,
1145 cli_cmd_flag_sensitive,
1146 "<network id> <pin> = configure pin for an SSID" },
1147 { "otp", wpa_cli_cmd_otp,
1148 cli_cmd_flag_sensitive,
1149 "<network id> <password> = configure one-time-password for an SSID"
1150 },
1151 { "passphrase", wpa_cli_cmd_passphrase,
1152 cli_cmd_flag_sensitive,
1153 "<network id> <passphrase> = configure private key passphrase\n"
1154 " for an SSID" },
1155 { "bssid", wpa_cli_cmd_bssid,
1156 cli_cmd_flag_none,
1157 "<network id> <BSSID> = set preferred BSSID for an SSID" },
1158 { "list_networks", wpa_cli_cmd_list_networks,
1159 cli_cmd_flag_none,
1160 "= list configured networks" },
1161 { "select_network", wpa_cli_cmd_select_network,
1162 cli_cmd_flag_none,
1163 "<network id> = select a network (disable others)" },
1164 { "enable_network", wpa_cli_cmd_enable_network,
1165 cli_cmd_flag_none,
1166 "<network id> = enable a network" },
1167 { "disable_network", wpa_cli_cmd_disable_network,
1168 cli_cmd_flag_none,
1169 "<network id> = disable a network" },
1170 { "add_network", wpa_cli_cmd_add_network,
1171 cli_cmd_flag_none,
1172 "= add a network" },
1173 { "remove_network", wpa_cli_cmd_remove_network,
1174 cli_cmd_flag_none,
1175 "<network id> = remove a network" },
1176 { "set_network", wpa_cli_cmd_set_network,
1177 cli_cmd_flag_sensitive,
1178 "<network id> <variable> <value> = set network variables (shows\n"
1179 " list of variables when run without arguments)" },
1180 { "get_network", wpa_cli_cmd_get_network,
1181 cli_cmd_flag_none,
1182 "<network id> <variable> = get network variables" },
1183 { "save_config", wpa_cli_cmd_save_config,
1184 cli_cmd_flag_none,
1185 "= save the current configuration" },
1186 { "disconnect", wpa_cli_cmd_disconnect,
1187 cli_cmd_flag_none,
1188 "= disconnect and wait for reassociate/reconnect command before\n"
1189 " connecting" },
1190 { "reconnect", wpa_cli_cmd_reconnect,
1191 cli_cmd_flag_none,
1192 "= like reassociate, but only takes effect if already disconnected"
1193 },
1194 { "scan", wpa_cli_cmd_scan,
1195 cli_cmd_flag_none,
1196 "= request new BSS scan" },
1197 { "scan_results", wpa_cli_cmd_scan_results,
1198 cli_cmd_flag_none,
1199 "= get latest scan results" },
1200 { "bss", wpa_cli_cmd_bss,
1201 cli_cmd_flag_none,
1202 "<<idx> | <bssid>> = get detailed scan result info" },
1203 { "get_capability", wpa_cli_cmd_get_capability,
1204 cli_cmd_flag_none,
1205 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1206 { "reconfigure", wpa_cli_cmd_reconfigure,
1207 cli_cmd_flag_none,
1208 "= force wpa_supplicant to re-read its configuration file" },
1209 { "terminate", wpa_cli_cmd_terminate,
1210 cli_cmd_flag_none,
1211 "= terminate wpa_supplicant" },
1212 { "interface_add", wpa_cli_cmd_interface_add,
1213 cli_cmd_flag_none,
1214 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1215 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1216 " are optional" },
1217 { "interface_remove", wpa_cli_cmd_interface_remove,
1218 cli_cmd_flag_none,
1219 "<ifname> = removes the interface" },
1220 { "interface_list", wpa_cli_cmd_interface_list,
1221 cli_cmd_flag_none,
1222 "= list available interfaces" },
1223 { "ap_scan", wpa_cli_cmd_ap_scan,
1224 cli_cmd_flag_none,
1225 "<value> = set ap_scan parameter" },
1226 { "stkstart", wpa_cli_cmd_stkstart,
1227 cli_cmd_flag_none,
1228 "<addr> = request STK negotiation with <addr>" },
1229 { "ft_ds", wpa_cli_cmd_ft_ds,
1230 cli_cmd_flag_none,
1231 "<addr> = request over-the-DS FT with <addr>" },
1232 { "wps_pbc", wpa_cli_cmd_wps_pbc,
1233 cli_cmd_flag_none,
1234 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1235 { "wps_pin", wpa_cli_cmd_wps_pin,
1236 cli_cmd_flag_sensitive,
1237 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1238 "hardcoded)" },
1239 { "wps_reg", wpa_cli_cmd_wps_reg,
1240 cli_cmd_flag_sensitive,
1241 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1242 { NULL, NULL, cli_cmd_flag_none, NULL }
1243 };
1246 /*
1247 * Prints command usage, lines are padded with the specified string.
1248 */
1249 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1250 {
1251 char c;
1252 size_t n;
1254 printf("%s%s ", pad, cmd->cmd);
1255 for (n = 0; (c = cmd->usage[n]); n++) {
1256 printf("%c", c);
1257 if (c == '\n')
1258 printf("%s", pad);
1259 }
1260 printf("\n");
1261 }
1264 static void print_help(void)
1265 {
1266 int n;
1267 printf("commands:\n");
1268 for (n = 0; wpa_cli_commands[n].cmd; n++)
1269 print_cmd_help(&wpa_cli_commands[n], " ");
1270 }
1273 #ifdef CONFIG_READLINE
1274 static int cmd_has_sensitive_data(const char *cmd)
1275 {
1276 const char *c, *delim;
1277 int n;
1278 size_t len;
1280 delim = os_strchr(cmd, ' ');
1281 if (delim)
1282 len = delim - cmd;
1283 else
1284 len = os_strlen(cmd);
1286 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1287 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1288 return (wpa_cli_commands[n].flags &
1289 cli_cmd_flag_sensitive);
1290 }
1291 return 0;
1292 }
1293 #endif /* CONFIG_READLINE */
1296 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297 {
1298 struct wpa_cli_cmd *cmd, *match = NULL;
1299 int count;
1300 int ret = 0;
1302 count = 0;
1303 cmd = wpa_cli_commands;
1304 while (cmd->cmd) {
1305 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1306 {
1307 match = cmd;
1308 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1309 /* we have an exact match */
1310 count = 1;
1311 break;
1312 }
1313 count++;
1314 }
1315 cmd++;
1316 }
1318 if (count > 1) {
1319 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1320 cmd = wpa_cli_commands;
1321 while (cmd->cmd) {
1322 if (os_strncasecmp(cmd->cmd, argv[0],
1323 os_strlen(argv[0])) == 0) {
1324 printf(" %s", cmd->cmd);
1325 }
1326 cmd++;
1327 }
1328 printf("\n");
1329 ret = 1;
1330 } else if (count == 0) {
1331 printf("Unknown command '%s'\n", argv[0]);
1332 ret = 1;
1333 } else {
1334 ret = match->handler(ctrl, argc - 1, &argv[1]);
1335 }
1337 return ret;
1338 }
1341 static int str_match(const char *a, const char *b)
1342 {
1343 return os_strncmp(a, b, os_strlen(b)) == 0;
1344 }
1347 static int wpa_cli_exec(const char *program, const char *arg1,
1348 const char *arg2)
1349 {
1350 char *cmd;
1351 size_t len;
1352 int res;
1353 int ret = 0;
1355 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1356 cmd = os_malloc(len);
1357 if (cmd == NULL)
1358 return -1;
1359 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1360 if (res < 0 || (size_t) res >= len) {
1361 os_free(cmd);
1362 return -1;
1363 }
1364 cmd[len - 1] = '\0';
1365 #ifndef _WIN32_WCE
1366 if (system(cmd) < 0)
1367 ret = -1;
1368 #endif /* _WIN32_WCE */
1369 os_free(cmd);
1371 return ret;
1372 }
1375 static void wpa_cli_action_process(const char *msg)
1376 {
1377 const char *pos;
1378 char *copy = NULL, *id, *pos2;
1380 pos = msg;
1381 if (*pos == '<') {
1382 /* skip priority */
1383 pos = os_strchr(pos, '>');
1384 if (pos)
1385 pos++;
1386 else
1387 pos = msg;
1388 }
1390 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1391 int new_id = -1;
1392 os_unsetenv("WPA_ID");
1393 os_unsetenv("WPA_ID_STR");
1394 os_unsetenv("WPA_CTRL_DIR");
1396 pos = os_strstr(pos, "[id=");
1397 if (pos)
1398 copy = os_strdup(pos + 4);
1400 if (copy) {
1401 pos2 = id = copy;
1402 while (*pos2 && *pos2 != ' ')
1403 pos2++;
1404 *pos2++ = '\0';
1405 new_id = atoi(id);
1406 os_setenv("WPA_ID", id, 1);
1407 while (*pos2 && *pos2 != '=')
1408 pos2++;
1409 if (*pos2 == '=')
1410 pos2++;
1411 id = pos2;
1412 while (*pos2 && *pos2 != ']')
1413 pos2++;
1414 *pos2 = '\0';
1415 os_setenv("WPA_ID_STR", id, 1);
1416 os_free(copy);
1417 }
1419 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1421 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1422 wpa_cli_connected = 1;
1423 wpa_cli_last_id = new_id;
1424 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1425 }
1426 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1427 if (wpa_cli_connected) {
1428 wpa_cli_connected = 0;
1429 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1430 }
1431 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1432 printf("wpa_supplicant is terminating - stop monitoring\n");
1433 wpa_cli_quit = 1;
1434 }
1435 }
1438 #ifndef CONFIG_ANSI_C_EXTRA
1439 static void wpa_cli_action_cb(char *msg, size_t len)
1440 {
1441 wpa_cli_action_process(msg);
1442 }
1443 #endif /* CONFIG_ANSI_C_EXTRA */
1446 static void wpa_cli_reconnect(void)
1447 {
1448 wpa_cli_close_connection();
1449 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1450 if (ctrl_conn) {
1451 printf("Connection to wpa_supplicant re-established\n");
1452 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1453 wpa_cli_attached = 1;
1454 } else {
1455 printf("Warning: Failed to attach to "
1456 "wpa_supplicant.\n");
1457 }
1458 }
1459 }
1462 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1463 int action_monitor)
1464 {
1465 int first = 1;
1466 if (ctrl_conn == NULL) {
1467 wpa_cli_reconnect();
1468 return;
1469 }
1470 while (wpa_ctrl_pending(ctrl) > 0) {
1471 char buf[256];
1472 size_t len = sizeof(buf) - 1;
1473 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1474 buf[len] = '\0';
1475 if (action_monitor)
1476 wpa_cli_action_process(buf);
1477 else {
1478 if (in_read && first)
1479 printf("\n");
1480 first = 0;
1481 printf("%s\n", buf);
1482 }
1483 } else {
1484 printf("Could not read pending message.\n");
1485 break;
1486 }
1487 }
1489 if (wpa_ctrl_pending(ctrl) < 0) {
1490 printf("Connection to wpa_supplicant lost - trying to "
1491 "reconnect\n");
1492 wpa_cli_reconnect();
1493 }
1494 }
1497 #ifdef CONFIG_READLINE
1498 static char * wpa_cli_cmd_gen(const char *text, int state)
1499 {
1500 static int i, len;
1501 const char *cmd;
1503 if (state == 0) {
1504 i = 0;
1505 len = os_strlen(text);
1506 }
1508 while ((cmd = wpa_cli_commands[i].cmd)) {
1509 i++;
1510 if (os_strncasecmp(cmd, text, len) == 0)
1511 return os_strdup(cmd);
1512 }
1514 return NULL;
1515 }
1518 static char * wpa_cli_dummy_gen(const char *text, int state)
1519 {
1520 return NULL;
1521 }
1524 static char ** wpa_cli_completion(const char *text, int start, int end)
1525 {
1526 return rl_completion_matches(text, start == 0 ?
1527 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1528 }
1529 #endif /* CONFIG_READLINE */
1532 static void wpa_cli_interactive(void)
1533 {
1534 #define max_args 10
1535 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1536 int argc;
1537 #ifdef CONFIG_READLINE
1538 char *home, *hfile = NULL;
1539 #endif /* CONFIG_READLINE */
1541 printf("\nInteractive mode\n\n");
1543 #ifdef CONFIG_READLINE
1544 rl_attempted_completion_function = wpa_cli_completion;
1545 home = getenv("HOME");
1546 if (home) {
1547 const char *fname = ".wpa_cli_history";
1548 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1549 hfile = os_malloc(hfile_len);
1550 if (hfile) {
1551 int res;
1552 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1553 fname);
1554 if (res >= 0 && res < hfile_len) {
1555 hfile[hfile_len - 1] = '\0';
1556 read_history(hfile);
1557 stifle_history(100);
1558 }
1559 }
1560 }
1561 #endif /* CONFIG_READLINE */
1563 do {
1564 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1565 #ifndef CONFIG_NATIVE_WINDOWS
1566 alarm(1);
1567 #endif /* CONFIG_NATIVE_WINDOWS */
1568 #ifdef CONFIG_READLINE
1569 cmd = readline("> ");
1570 if (cmd && *cmd) {
1571 HIST_ENTRY *h;
1572 while (next_history())
1573 ;
1574 h = previous_history();
1575 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1576 add_history(cmd);
1577 next_history();
1578 }
1579 #else /* CONFIG_READLINE */
1580 printf("> ");
1581 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1582 #endif /* CONFIG_READLINE */
1583 #ifndef CONFIG_NATIVE_WINDOWS
1584 alarm(0);
1585 #endif /* CONFIG_NATIVE_WINDOWS */
1586 if (cmd == NULL)
1587 break;
1588 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1589 pos = cmd;
1590 while (*pos != '\0') {
1591 if (*pos == '\n') {
1592 *pos = '\0';
1593 break;
1594 }
1595 pos++;
1596 }
1597 argc = 0;
1598 pos = cmd;
1599 for (;;) {
1600 while (*pos == ' ')
1601 pos++;
1602 if (*pos == '\0')
1603 break;
1604 argv[argc] = pos;
1605 argc++;
1606 if (argc == max_args)
1607 break;
1608 if (*pos == '"') {
1609 char *pos2 = os_strrchr(pos, '"');
1610 if (pos2)
1611 pos = pos2 + 1;
1612 }
1613 while (*pos != '\0' && *pos != ' ')
1614 pos++;
1615 if (*pos == ' ')
1616 *pos++ = '\0';
1617 }
1618 if (argc)
1619 wpa_request(ctrl_conn, argc, argv);
1621 if (cmd != cmdbuf)
1622 os_free(cmd);
1623 } while (!wpa_cli_quit);
1625 #ifdef CONFIG_READLINE
1626 if (hfile) {
1627 /* Save command history, excluding lines that may contain
1628 * passwords. */
1629 HIST_ENTRY *h;
1630 history_set_pos(0);
1631 while ((h = current_history())) {
1632 char *p = h->line;
1633 while (*p == ' ' || *p == '\t')
1634 p++;
1635 if (cmd_has_sensitive_data(p)) {
1636 h = remove_history(where_history());
1637 if (h) {
1638 os_free(h->line);
1639 os_free(h->data);
1640 os_free(h);
1641 } else
1642 next_history();
1643 } else
1644 next_history();
1645 }
1646 write_history(hfile);
1647 os_free(hfile);
1648 }
1649 #endif /* CONFIG_READLINE */
1650 }
1653 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1654 {
1655 #ifdef CONFIG_ANSI_C_EXTRA
1656 /* TODO: ANSI C version(?) */
1657 printf("Action processing not supported in ANSI C build.\n");
1658 #else /* CONFIG_ANSI_C_EXTRA */
1659 fd_set rfds;
1660 int fd, res;
1661 struct timeval tv;
1662 char buf[256]; /* note: large enough to fit in unsolicited messages */
1663 size_t len;
1665 fd = wpa_ctrl_get_fd(ctrl);
1667 while (!wpa_cli_quit) {
1668 FD_ZERO(&rfds);
1669 FD_SET(fd, &rfds);
1670 tv.tv_sec = 2;
1671 tv.tv_usec = 0;
1672 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1673 if (res < 0 && errno != EINTR) {
1674 perror("select");
1675 break;
1676 }
1678 if (FD_ISSET(fd, &rfds))
1679 wpa_cli_recv_pending(ctrl, 0, 1);
1680 else {
1681 /* verify that connection is still working */
1682 len = sizeof(buf) - 1;
1683 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1684 wpa_cli_action_cb) < 0 ||
1685 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1686 printf("wpa_supplicant did not reply to PING "
1687 "command - exiting\n");
1688 break;
1689 }
1690 }
1691 }
1692 #endif /* CONFIG_ANSI_C_EXTRA */
1693 }
1696 static void wpa_cli_cleanup(void)
1697 {
1698 wpa_cli_close_connection();
1699 if (pid_file)
1700 os_daemonize_terminate(pid_file);
1702 os_program_deinit();
1703 }
1705 static void wpa_cli_terminate(int sig)
1706 {
1707 wpa_cli_cleanup();
1708 exit(0);
1709 }
1712 #ifndef CONFIG_NATIVE_WINDOWS
1713 static void wpa_cli_alarm(int sig)
1714 {
1715 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1716 printf("Connection to wpa_supplicant lost - trying to "
1717 "reconnect\n");
1718 wpa_cli_close_connection();
1719 }
1720 if (!ctrl_conn)
1721 wpa_cli_reconnect();
1722 if (ctrl_conn)
1723 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1724 alarm(1);
1725 }
1726 #endif /* CONFIG_NATIVE_WINDOWS */
1729 static char * wpa_cli_get_default_ifname(void)
1730 {
1731 char *ifname = NULL;
1733 #ifdef CONFIG_CTRL_IFACE_UNIX
1734 struct dirent *dent;
1735 DIR *dir = opendir(ctrl_iface_dir);
1736 if (!dir)
1737 return NULL;
1738 while ((dent = readdir(dir))) {
1739 #ifdef _DIRENT_HAVE_D_TYPE
1740 /*
1741 * Skip the file if it is not a socket. Also accept
1742 * DT_UNKNOWN (0) in case the C library or underlying
1743 * file system does not support d_type.
1744 */
1745 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1746 continue;
1747 #endif /* _DIRENT_HAVE_D_TYPE */
1748 if (os_strcmp(dent->d_name, ".") == 0 ||
1749 os_strcmp(dent->d_name, "..") == 0)
1750 continue;
1751 printf("Selected interface '%s'\n", dent->d_name);
1752 ifname = os_strdup(dent->d_name);
1753 break;
1754 }
1755 closedir(dir);
1756 #endif /* CONFIG_CTRL_IFACE_UNIX */
1758 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1759 char buf[2048], *pos;
1760 size_t len;
1761 struct wpa_ctrl *ctrl;
1762 int ret;
1764 ctrl = wpa_ctrl_open(NULL);
1765 if (ctrl == NULL)
1766 return NULL;
1768 len = sizeof(buf) - 1;
1769 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1770 if (ret >= 0) {
1771 buf[len] = '\0';
1772 pos = os_strchr(buf, '\n');
1773 if (pos)
1774 *pos = '\0';
1775 ifname = os_strdup(buf);
1776 }
1777 wpa_ctrl_close(ctrl);
1778 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1780 return ifname;
1781 }
1784 int main(int argc, char *argv[])
1785 {
1786 int interactive;
1787 int warning_displayed = 0;
1788 int c;
1789 int daemonize = 0;
1790 int ret = 0;
1791 const char *global = NULL;
1793 if (os_program_init())
1794 return -1;
1796 for (;;) {
1797 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1798 if (c < 0)
1799 break;
1800 switch (c) {
1801 case 'a':
1802 action_file = optarg;
1803 break;
1804 case 'B':
1805 daemonize = 1;
1806 break;
1807 case 'g':
1808 global = optarg;
1809 break;
1810 case 'h':
1811 usage();
1812 return 0;
1813 case 'v':
1814 printf("%s\n", wpa_cli_version);
1815 return 0;
1816 case 'i':
1817 os_free(ctrl_ifname);
1818 ctrl_ifname = os_strdup(optarg);
1819 break;
1820 case 'p':
1821 ctrl_iface_dir = optarg;
1822 break;
1823 case 'P':
1824 pid_file = optarg;
1825 break;
1826 default:
1827 usage();
1828 return -1;
1829 }
1830 }
1832 interactive = (argc == optind) && (action_file == NULL);
1834 if (interactive)
1835 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1837 if (global) {
1838 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1839 ctrl_conn = wpa_ctrl_open(NULL);
1840 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1841 ctrl_conn = wpa_ctrl_open(global);
1842 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1843 if (ctrl_conn == NULL) {
1844 perror("Failed to connect to wpa_supplicant - "
1845 "wpa_ctrl_open");
1846 return -1;
1847 }
1848 }
1850 for (; !global;) {
1851 if (ctrl_ifname == NULL)
1852 ctrl_ifname = wpa_cli_get_default_ifname();
1853 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1854 if (ctrl_conn) {
1855 if (warning_displayed)
1856 printf("Connection established.\n");
1857 break;
1858 }
1860 if (!interactive) {
1861 perror("Failed to connect to wpa_supplicant - "
1862 "wpa_ctrl_open");
1863 return -1;
1864 }
1866 if (!warning_displayed) {
1867 printf("Could not connect to wpa_supplicant - "
1868 "re-trying\n");
1869 warning_displayed = 1;
1870 }
1871 os_sleep(1, 0);
1872 continue;
1873 }
1875 #ifndef _WIN32_WCE
1876 signal(SIGINT, wpa_cli_terminate);
1877 signal(SIGTERM, wpa_cli_terminate);
1878 #endif /* _WIN32_WCE */
1879 #ifndef CONFIG_NATIVE_WINDOWS
1880 signal(SIGALRM, wpa_cli_alarm);
1881 #endif /* CONFIG_NATIVE_WINDOWS */
1883 if (interactive || action_file) {
1884 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1885 wpa_cli_attached = 1;
1886 } else {
1887 printf("Warning: Failed to attach to "
1888 "wpa_supplicant.\n");
1889 if (!interactive)
1890 return -1;
1891 }
1892 }
1894 if (daemonize && os_daemonize(pid_file))
1895 return -1;
1897 if (interactive)
1898 wpa_cli_interactive();
1899 else if (action_file)
1900 wpa_cli_action(ctrl_conn);
1901 else
1902 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1904 os_free(ctrl_ifname);
1905 wpa_cli_cleanup();
1907 return ret;
1908 }
1910 #else /* CONFIG_CTRL_IFACE */
1911 int main(int argc, char *argv[])
1912 {
1913 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1914 return -1;
1915 }
1916 #endif /* CONFIG_CTRL_IFACE */