Free readline() output with free(), not os_free()
[hostap-gosc2009.git] / wpa_supplicant / wpa_cli.c
blob76e2166c862b78308005bde03913e233638e274e
1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #ifdef CONFIG_CTRL_IFACE
19 #ifdef CONFIG_CTRL_IFACE_UNIX
20 #include <dirent.h>
21 #endif /* CONFIG_CTRL_IFACE_UNIX */
22 #ifdef CONFIG_READLINE
23 #include <readline/readline.h>
24 #include <readline/history.h>
25 #endif /* CONFIG_READLINE */
27 #include "common/wpa_ctrl.h"
28 #include "common.h"
29 #include "common/version.h"
32 static const char *wpa_cli_version =
33 "wpa_cli v" VERSION_STR "\n"
34 "Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
37 static const char *wpa_cli_license =
38 "This program is free software. You can distribute it and/or modify it\n"
39 "under the terms of the GNU General Public License version 2.\n"
40 "\n"
41 "Alternatively, this software may be distributed under the terms of the\n"
42 "BSD license. See README and COPYING for more details.\n";
44 static const char *wpa_cli_full_license =
45 "This program is free software; you can redistribute it and/or modify\n"
46 "it under the terms of the GNU General Public License version 2 as\n"
47 "published by the Free Software Foundation.\n"
48 "\n"
49 "This program is distributed in the hope that it will be useful,\n"
50 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
52 "GNU General Public License for more details.\n"
53 "\n"
54 "You should have received a copy of the GNU General Public License\n"
55 "along with this program; if not, write to the Free Software\n"
56 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
57 "\n"
58 "Alternatively, this software may be distributed under the terms of the\n"
59 "BSD license.\n"
60 "\n"
61 "Redistribution and use in source and binary forms, with or without\n"
62 "modification, are permitted provided that the following conditions are\n"
63 "met:\n"
64 "\n"
65 "1. Redistributions of source code must retain the above copyright\n"
66 " notice, this list of conditions and the following disclaimer.\n"
67 "\n"
68 "2. Redistributions in binary form must reproduce the above copyright\n"
69 " notice, this list of conditions and the following disclaimer in the\n"
70 " documentation and/or other materials provided with the distribution.\n"
71 "\n"
72 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73 " names of its contributors may be used to endorse or promote products\n"
74 " derived from this software without specific prior written permission.\n"
75 "\n"
76 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87 "\n";
89 static struct wpa_ctrl *ctrl_conn;
90 static int wpa_cli_quit = 0;
91 static int wpa_cli_attached = 0;
92 static int wpa_cli_connected = 0;
93 static int wpa_cli_last_id = 0;
94 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95 static char *ctrl_ifname = NULL;
96 static const char *pid_file = NULL;
97 static const char *action_file = NULL;
98 static int ping_interval = 5;
101 static void print_help();
104 static void usage(void)
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: /var/run/wpa_supplicant\n"
117 " default interface: first interface found in socket path\n");
118 print_help();
122 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
124 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
125 ctrl_conn = wpa_ctrl_open(ifname);
126 return ctrl_conn;
127 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
128 char *cfile;
129 int flen, res;
131 if (ifname == NULL)
132 return NULL;
134 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
135 cfile = os_malloc(flen);
136 if (cfile == NULL)
137 return NULL;
138 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
139 if (res < 0 || res >= flen) {
140 os_free(cfile);
141 return NULL;
144 ctrl_conn = wpa_ctrl_open(cfile);
145 os_free(cfile);
146 return ctrl_conn;
147 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
151 static void wpa_cli_close_connection(void)
153 if (ctrl_conn == NULL)
154 return;
156 if (wpa_cli_attached) {
157 wpa_ctrl_detach(ctrl_conn);
158 wpa_cli_attached = 0;
160 wpa_ctrl_close(ctrl_conn);
161 ctrl_conn = NULL;
165 static void wpa_cli_msg_cb(char *msg, size_t len)
167 printf("%s\n", msg);
171 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
173 char buf[2048];
174 size_t len;
175 int ret;
177 if (ctrl_conn == NULL) {
178 printf("Not connected to wpa_supplicant - command dropped.\n");
179 return -1;
181 len = sizeof(buf) - 1;
182 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
183 wpa_cli_msg_cb);
184 if (ret == -2) {
185 printf("'%s' command timed out.\n", cmd);
186 return -2;
187 } else if (ret < 0) {
188 printf("'%s' command failed.\n", cmd);
189 return -1;
191 if (print) {
192 buf[len] = '\0';
193 printf("%s", buf);
195 return 0;
199 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
201 return _wpa_ctrl_command(ctrl, cmd, 1);
205 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
207 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
208 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
212 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
214 return wpa_ctrl_command(ctrl, "PING");
218 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
220 return wpa_ctrl_command(ctrl, "MIB");
224 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
226 return wpa_ctrl_command(ctrl, "PMKSA");
230 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
232 print_help();
233 return 0;
237 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
239 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
240 return 0;
244 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
246 wpa_cli_quit = 1;
247 return 0;
251 static void wpa_cli_show_variables(void)
253 printf("set variables:\n"
254 " EAPOL::heldPeriod (EAPOL state machine held period, "
255 "in seconds)\n"
256 " EAPOL::authPeriod (EAPOL state machine authentication "
257 "period, in seconds)\n"
258 " EAPOL::startPeriod (EAPOL state machine start period, in "
259 "seconds)\n"
260 " EAPOL::maxStart (EAPOL state machine maximum start "
261 "attempts)\n");
262 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
263 "seconds)\n"
264 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
265 " threshold\n\tpercentage)\n"
266 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
267 "security\n\tassociation in seconds)\n");
271 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
273 char cmd[256];
274 int res;
276 if (argc == 0) {
277 wpa_cli_show_variables();
278 return 0;
281 if (argc != 2) {
282 printf("Invalid SET command: needs two arguments (variable "
283 "name and value)\n");
284 return -1;
287 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
288 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
289 printf("Too long SET command.\n");
290 return -1;
292 return wpa_ctrl_command(ctrl, cmd);
296 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
298 return wpa_ctrl_command(ctrl, "LOGOFF");
302 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
304 return wpa_ctrl_command(ctrl, "LOGON");
308 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
309 char *argv[])
311 return wpa_ctrl_command(ctrl, "REASSOCIATE");
315 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
316 char *argv[])
318 char cmd[256];
319 int res;
321 if (argc != 1) {
322 printf("Invalid PREAUTH command: needs one argument "
323 "(BSSID)\n");
324 return -1;
327 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
328 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
329 printf("Too long PREAUTH command.\n");
330 return -1;
332 return wpa_ctrl_command(ctrl, cmd);
336 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
338 char cmd[256];
339 int res;
341 if (argc != 1) {
342 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
343 "value)\n");
344 return -1;
346 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
347 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
348 printf("Too long AP_SCAN command.\n");
349 return -1;
351 return wpa_ctrl_command(ctrl, cmd);
355 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
356 char *argv[])
358 char cmd[256];
359 int res;
361 if (argc != 1) {
362 printf("Invalid STKSTART command: needs one argument "
363 "(Peer STA MAC address)\n");
364 return -1;
367 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
368 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
369 printf("Too long STKSTART command.\n");
370 return -1;
372 return wpa_ctrl_command(ctrl, cmd);
376 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
378 char cmd[256];
379 int res;
381 if (argc != 1) {
382 printf("Invalid FT_DS command: needs one argument "
383 "(Target AP MAC address)\n");
384 return -1;
387 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
388 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389 printf("Too long FT_DS command.\n");
390 return -1;
392 return wpa_ctrl_command(ctrl, cmd);
396 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
398 char cmd[256];
399 int res;
401 if (argc == 0) {
402 /* Any BSSID */
403 return wpa_ctrl_command(ctrl, "WPS_PBC");
406 /* Specific BSSID */
407 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
408 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
409 printf("Too long WPS_PBC command.\n");
410 return -1;
412 return wpa_ctrl_command(ctrl, cmd);
416 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
418 char cmd[256];
419 int res;
421 if (argc == 0) {
422 printf("Invalid WPS_PIN command: need one or two arguments:\n"
423 "- BSSID: use 'any' to select any\n"
424 "- PIN: optional, used only with devices that have no "
425 "display\n");
426 return -1;
429 if (argc == 1) {
430 /* Use dynamically generated PIN (returned as reply) */
431 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
432 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
433 printf("Too long WPS_PIN command.\n");
434 return -1;
436 return wpa_ctrl_command(ctrl, cmd);
439 /* Use hardcoded PIN from a label */
440 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
441 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
442 printf("Too long WPS_PIN command.\n");
443 return -1;
445 return wpa_ctrl_command(ctrl, cmd);
449 #ifdef CONFIG_WPS_OOB
450 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
452 char cmd[256];
453 int res;
455 if (argc != 3 && argc != 4) {
456 printf("Invalid WPS_OOB command: need three or four "
457 "arguments:\n"
458 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
459 "- PATH: path of OOB device like '/mnt'\n"
460 "- METHOD: OOB method 'pin-e' or 'pin-r', "
461 "'cred'\n"
462 "- DEV_NAME: (only for NFC) device name like "
463 "'pn531'\n");
464 return -1;
467 if (argc == 3)
468 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
469 argv[0], argv[1], argv[2]);
470 else
471 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
472 argv[0], argv[1], argv[2], argv[3]);
473 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
474 printf("Too long WPS_OOB command.\n");
475 return -1;
477 return wpa_ctrl_command(ctrl, cmd);
479 #endif /* CONFIG_WPS_OOB */
482 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
484 char cmd[256];
485 int res;
487 if (argc == 2)
488 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
489 argv[0], argv[1]);
490 else if (argc == 6) {
491 char ssid_hex[2 * 32 + 1];
492 char key_hex[2 * 64 + 1];
493 int i;
495 ssid_hex[0] = '\0';
496 for (i = 0; i < 32; i++) {
497 if (argv[2][i] == '\0')
498 break;
499 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
502 key_hex[0] = '\0';
503 for (i = 0; i < 64; i++) {
504 if (argv[5][i] == '\0')
505 break;
506 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
509 res = os_snprintf(cmd, sizeof(cmd),
510 "WPS_REG %s %s %s %s %s %s",
511 argv[0], argv[1], ssid_hex, argv[3], argv[4],
512 key_hex);
513 } else {
514 printf("Invalid WPS_REG command: need two arguments:\n"
515 "- BSSID: use 'any' to select any\n"
516 "- AP PIN\n");
517 printf("Alternatively, six arguments can be used to "
518 "reconfigure the AP:\n"
519 "- BSSID: use 'any' to select any\n"
520 "- AP PIN\n"
521 "- new SSID\n"
522 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
523 "- new encr (NONE, WEP, TKIP, CCMP)\n"
524 "- new key\n");
525 return -1;
528 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
529 printf("Too long WPS_REG command.\n");
530 return -1;
532 return wpa_ctrl_command(ctrl, cmd);
536 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
537 char *argv[])
539 return wpa_ctrl_command(ctrl, "WPS_ER_START");
544 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
545 char *argv[])
547 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
552 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
553 char *argv[])
555 char cmd[256];
556 int res;
558 if (argc != 2) {
559 printf("Invalid WPS_ER_PIN command: need two arguments:\n"
560 "- UUID: use 'any' to select any\n"
561 "- PIN: Enrollee PIN\n");
562 return -1;
565 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
566 argv[0], argv[1]);
567 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
568 printf("Too long WPS_ER_PIN command.\n");
569 return -1;
571 return wpa_ctrl_command(ctrl, cmd);
575 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
576 char *argv[])
578 char cmd[256];
579 int res;
581 if (argc != 1) {
582 printf("Invalid WPS_ER_PBC command: need one argument:\n"
583 "- UUID: Specify the Enrollee\n");
584 return -1;
587 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
588 argv[0]);
589 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
590 printf("Too long WPS_ER_PBC command.\n");
591 return -1;
593 return wpa_ctrl_command(ctrl, cmd);
597 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
598 char *argv[])
600 char cmd[256];
601 int res;
603 if (argc != 2) {
604 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
605 "- UUID: specify which AP to use\n"
606 "- PIN: AP PIN\n");
607 return -1;
610 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
611 argv[0], argv[1]);
612 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
613 printf("Too long WPS_ER_LEARN command.\n");
614 return -1;
616 return wpa_ctrl_command(ctrl, cmd);
620 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
622 char cmd[256];
623 int res;
625 if (argc != 1) {
626 printf("Invalid IBSS_RSN command: needs one argument "
627 "(Peer STA MAC address)\n");
628 return -1;
631 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
632 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
633 printf("Too long IBSS_RSN command.\n");
634 return -1;
636 return wpa_ctrl_command(ctrl, cmd);
640 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
642 char cmd[256];
643 int res;
645 if (argc != 1) {
646 printf("Invalid LEVEL command: needs one argument (debug "
647 "level)\n");
648 return -1;
650 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
651 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
652 printf("Too long LEVEL command.\n");
653 return -1;
655 return wpa_ctrl_command(ctrl, cmd);
659 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
661 char cmd[256], *pos, *end;
662 int i, ret;
664 if (argc < 2) {
665 printf("Invalid IDENTITY command: needs two arguments "
666 "(network id and identity)\n");
667 return -1;
670 end = cmd + sizeof(cmd);
671 pos = cmd;
672 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
673 argv[0], argv[1]);
674 if (ret < 0 || ret >= end - pos) {
675 printf("Too long IDENTITY command.\n");
676 return -1;
678 pos += ret;
679 for (i = 2; i < argc; i++) {
680 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
681 if (ret < 0 || ret >= end - pos) {
682 printf("Too long IDENTITY command.\n");
683 return -1;
685 pos += ret;
688 return wpa_ctrl_command(ctrl, cmd);
692 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
694 char cmd[256], *pos, *end;
695 int i, ret;
697 if (argc < 2) {
698 printf("Invalid PASSWORD command: needs two arguments "
699 "(network id and password)\n");
700 return -1;
703 end = cmd + sizeof(cmd);
704 pos = cmd;
705 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
706 argv[0], argv[1]);
707 if (ret < 0 || ret >= end - pos) {
708 printf("Too long PASSWORD command.\n");
709 return -1;
711 pos += ret;
712 for (i = 2; i < argc; i++) {
713 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
714 if (ret < 0 || ret >= end - pos) {
715 printf("Too long PASSWORD command.\n");
716 return -1;
718 pos += ret;
721 return wpa_ctrl_command(ctrl, cmd);
725 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
728 char cmd[256], *pos, *end;
729 int i, ret;
731 if (argc < 2) {
732 printf("Invalid NEW_PASSWORD command: needs two arguments "
733 "(network id and password)\n");
734 return -1;
737 end = cmd + sizeof(cmd);
738 pos = cmd;
739 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
740 argv[0], argv[1]);
741 if (ret < 0 || ret >= end - pos) {
742 printf("Too long NEW_PASSWORD command.\n");
743 return -1;
745 pos += ret;
746 for (i = 2; i < argc; i++) {
747 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
748 if (ret < 0 || ret >= end - pos) {
749 printf("Too long NEW_PASSWORD command.\n");
750 return -1;
752 pos += ret;
755 return wpa_ctrl_command(ctrl, cmd);
759 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
761 char cmd[256], *pos, *end;
762 int i, ret;
764 if (argc < 2) {
765 printf("Invalid PIN command: needs two arguments "
766 "(network id and pin)\n");
767 return -1;
770 end = cmd + sizeof(cmd);
771 pos = cmd;
772 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
773 argv[0], argv[1]);
774 if (ret < 0 || ret >= end - pos) {
775 printf("Too long PIN command.\n");
776 return -1;
778 pos += ret;
779 for (i = 2; i < argc; i++) {
780 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
781 if (ret < 0 || ret >= end - pos) {
782 printf("Too long PIN command.\n");
783 return -1;
785 pos += ret;
787 return wpa_ctrl_command(ctrl, cmd);
791 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
793 char cmd[256], *pos, *end;
794 int i, ret;
796 if (argc < 2) {
797 printf("Invalid OTP command: needs two arguments (network "
798 "id and password)\n");
799 return -1;
802 end = cmd + sizeof(cmd);
803 pos = cmd;
804 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
805 argv[0], argv[1]);
806 if (ret < 0 || ret >= end - pos) {
807 printf("Too long OTP command.\n");
808 return -1;
810 pos += ret;
811 for (i = 2; i < argc; i++) {
812 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
813 if (ret < 0 || ret >= end - pos) {
814 printf("Too long OTP command.\n");
815 return -1;
817 pos += ret;
820 return wpa_ctrl_command(ctrl, cmd);
824 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
825 char *argv[])
827 char cmd[256], *pos, *end;
828 int i, ret;
830 if (argc < 2) {
831 printf("Invalid PASSPHRASE command: needs two arguments "
832 "(network id and passphrase)\n");
833 return -1;
836 end = cmd + sizeof(cmd);
837 pos = cmd;
838 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
839 argv[0], argv[1]);
840 if (ret < 0 || ret >= end - pos) {
841 printf("Too long PASSPHRASE command.\n");
842 return -1;
844 pos += ret;
845 for (i = 2; i < argc; i++) {
846 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
847 if (ret < 0 || ret >= end - pos) {
848 printf("Too long PASSPHRASE command.\n");
849 return -1;
851 pos += ret;
854 return wpa_ctrl_command(ctrl, cmd);
858 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
860 char cmd[256], *pos, *end;
861 int i, ret;
863 if (argc < 2) {
864 printf("Invalid BSSID command: needs two arguments (network "
865 "id and BSSID)\n");
866 return -1;
869 end = cmd + sizeof(cmd);
870 pos = cmd;
871 ret = os_snprintf(pos, end - pos, "BSSID");
872 if (ret < 0 || ret >= end - pos) {
873 printf("Too long BSSID command.\n");
874 return -1;
876 pos += ret;
877 for (i = 0; i < argc; i++) {
878 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
879 if (ret < 0 || ret >= end - pos) {
880 printf("Too long BSSID command.\n");
881 return -1;
883 pos += ret;
886 return wpa_ctrl_command(ctrl, cmd);
890 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
891 char *argv[])
893 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
897 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
898 char *argv[])
900 char cmd[32];
901 int res;
903 if (argc < 1) {
904 printf("Invalid SELECT_NETWORK command: needs one argument "
905 "(network id)\n");
906 return -1;
909 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %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);
918 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
921 char cmd[32];
922 int res;
924 if (argc < 1) {
925 printf("Invalid ENABLE_NETWORK command: needs one argument "
926 "(network id)\n");
927 return -1;
930 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
931 if (res < 0 || (size_t) res >= sizeof(cmd))
932 return -1;
933 cmd[sizeof(cmd) - 1] = '\0';
935 return wpa_ctrl_command(ctrl, cmd);
939 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
940 char *argv[])
942 char cmd[32];
943 int res;
945 if (argc < 1) {
946 printf("Invalid DISABLE_NETWORK command: needs one argument "
947 "(network id)\n");
948 return -1;
951 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
952 if (res < 0 || (size_t) res >= sizeof(cmd))
953 return -1;
954 cmd[sizeof(cmd) - 1] = '\0';
956 return wpa_ctrl_command(ctrl, cmd);
960 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
961 char *argv[])
963 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
967 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
968 char *argv[])
970 char cmd[32];
971 int res;
973 if (argc < 1) {
974 printf("Invalid REMOVE_NETWORK command: needs one argument "
975 "(network id)\n");
976 return -1;
979 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
980 if (res < 0 || (size_t) res >= sizeof(cmd))
981 return -1;
982 cmd[sizeof(cmd) - 1] = '\0';
984 return wpa_ctrl_command(ctrl, cmd);
988 static void wpa_cli_show_network_variables(void)
990 printf("set_network variables:\n"
991 " ssid (network name, SSID)\n"
992 " psk (WPA passphrase or pre-shared key)\n"
993 " key_mgmt (key management protocol)\n"
994 " identity (EAP identity)\n"
995 " password (EAP password)\n"
996 " ...\n"
997 "\n"
998 "Note: Values are entered in the same format as the "
999 "configuration file is using,\n"
1000 "i.e., strings values need to be inside double quotation "
1001 "marks.\n"
1002 "For example: set_network 1 ssid \"network name\"\n"
1003 "\n"
1004 "Please see wpa_supplicant.conf documentation for full list "
1005 "of\navailable variables.\n");
1009 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1010 char *argv[])
1012 char cmd[256];
1013 int res;
1015 if (argc == 0) {
1016 wpa_cli_show_network_variables();
1017 return 0;
1020 if (argc != 3) {
1021 printf("Invalid SET_NETWORK command: needs three arguments\n"
1022 "(network id, variable name, and value)\n");
1023 return -1;
1026 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1027 argv[0], argv[1], argv[2]);
1028 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029 printf("Too long SET_NETWORK command.\n");
1030 return -1;
1032 return wpa_ctrl_command(ctrl, cmd);
1036 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1037 char *argv[])
1039 char cmd[256];
1040 int res;
1042 if (argc == 0) {
1043 wpa_cli_show_network_variables();
1044 return 0;
1047 if (argc != 2) {
1048 printf("Invalid GET_NETWORK command: needs two arguments\n"
1049 "(network id and variable name)\n");
1050 return -1;
1053 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1054 argv[0], argv[1]);
1055 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1056 printf("Too long GET_NETWORK command.\n");
1057 return -1;
1059 return wpa_ctrl_command(ctrl, cmd);
1063 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1064 char *argv[])
1066 return wpa_ctrl_command(ctrl, "DISCONNECT");
1070 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1071 char *argv[])
1073 return wpa_ctrl_command(ctrl, "RECONNECT");
1077 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1078 char *argv[])
1080 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1084 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086 return wpa_ctrl_command(ctrl, "SCAN");
1090 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1091 char *argv[])
1093 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1097 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1099 char cmd[64];
1100 int res;
1102 if (argc != 1) {
1103 printf("Invalid BSS command: need one argument (index or "
1104 "BSSID)\n");
1105 return -1;
1108 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1109 if (res < 0 || (size_t) res >= sizeof(cmd))
1110 return -1;
1111 cmd[sizeof(cmd) - 1] = '\0';
1113 return wpa_ctrl_command(ctrl, cmd);
1117 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1118 char *argv[])
1120 char cmd[64];
1121 int res;
1123 if (argc < 1 || argc > 2) {
1124 printf("Invalid GET_CAPABILITY command: need either one or "
1125 "two arguments\n");
1126 return -1;
1129 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1130 printf("Invalid GET_CAPABILITY command: second argument, "
1131 "if any, must be 'strict'\n");
1132 return -1;
1135 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1136 (argc == 2) ? " strict" : "");
1137 if (res < 0 || (size_t) res >= sizeof(cmd))
1138 return -1;
1139 cmd[sizeof(cmd) - 1] = '\0';
1141 return wpa_ctrl_command(ctrl, cmd);
1145 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1147 printf("Available interfaces:\n");
1148 return wpa_ctrl_command(ctrl, "INTERFACES");
1152 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1154 if (argc < 1) {
1155 wpa_cli_list_interfaces(ctrl);
1156 return 0;
1159 wpa_cli_close_connection();
1160 os_free(ctrl_ifname);
1161 ctrl_ifname = os_strdup(argv[0]);
1163 if (wpa_cli_open_connection(ctrl_ifname)) {
1164 printf("Connected to interface '%s.\n", ctrl_ifname);
1165 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1166 wpa_cli_attached = 1;
1167 } else {
1168 printf("Warning: Failed to attach to "
1169 "wpa_supplicant.\n");
1171 } else {
1172 printf("Could not connect to interface '%s' - re-trying\n",
1173 ctrl_ifname);
1175 return 0;
1179 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1180 char *argv[])
1182 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1186 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1187 char *argv[])
1189 return wpa_ctrl_command(ctrl, "TERMINATE");
1193 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1194 char *argv[])
1196 char cmd[256];
1197 int res;
1199 if (argc < 1) {
1200 printf("Invalid INTERFACE_ADD command: needs at least one "
1201 "argument (interface name)\n"
1202 "All arguments: ifname confname driver ctrl_interface "
1203 "driver_param bridge_name\n");
1204 return -1;
1208 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1209 * <driver_param>TAB<bridge_name>
1211 res = os_snprintf(cmd, sizeof(cmd),
1212 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1213 argv[0],
1214 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1215 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1216 argc > 5 ? argv[5] : "");
1217 if (res < 0 || (size_t) res >= sizeof(cmd))
1218 return -1;
1219 cmd[sizeof(cmd) - 1] = '\0';
1220 return wpa_ctrl_command(ctrl, cmd);
1224 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1225 char *argv[])
1227 char cmd[128];
1228 int res;
1230 if (argc != 1) {
1231 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1232 "(interface name)\n");
1233 return -1;
1236 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1237 if (res < 0 || (size_t) res >= sizeof(cmd))
1238 return -1;
1239 cmd[sizeof(cmd) - 1] = '\0';
1240 return wpa_ctrl_command(ctrl, cmd);
1244 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1245 char *argv[])
1247 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1251 #ifdef CONFIG_AP
1252 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1254 char buf[64];
1255 if (argc != 1) {
1256 printf("Invalid 'sta' command - exactly one argument, STA "
1257 "address, is required.\n");
1258 return -1;
1260 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1261 return wpa_ctrl_command(ctrl, buf);
1265 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1266 char *addr, size_t addr_len)
1268 char buf[4096], *pos;
1269 size_t len;
1270 int ret;
1272 if (ctrl_conn == NULL) {
1273 printf("Not connected to hostapd - command dropped.\n");
1274 return -1;
1276 len = sizeof(buf) - 1;
1277 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1278 wpa_cli_msg_cb);
1279 if (ret == -2) {
1280 printf("'%s' command timed out.\n", cmd);
1281 return -2;
1282 } else if (ret < 0) {
1283 printf("'%s' command failed.\n", cmd);
1284 return -1;
1287 buf[len] = '\0';
1288 if (memcmp(buf, "FAIL", 4) == 0)
1289 return -1;
1290 printf("%s", buf);
1292 pos = buf;
1293 while (*pos != '\0' && *pos != '\n')
1294 pos++;
1295 *pos = '\0';
1296 os_strlcpy(addr, buf, addr_len);
1297 return 0;
1301 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1303 char addr[32], cmd[64];
1305 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1306 return 0;
1307 do {
1308 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1309 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1311 return -1;
1313 #endif /* CONFIG_AP */
1316 enum wpa_cli_cmd_flags {
1317 cli_cmd_flag_none = 0x00,
1318 cli_cmd_flag_sensitive = 0x01
1321 struct wpa_cli_cmd {
1322 const char *cmd;
1323 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1324 enum wpa_cli_cmd_flags flags;
1325 const char *usage;
1328 static struct wpa_cli_cmd wpa_cli_commands[] = {
1329 { "status", wpa_cli_cmd_status,
1330 cli_cmd_flag_none,
1331 "[verbose] = get current WPA/EAPOL/EAP status" },
1332 { "ping", wpa_cli_cmd_ping,
1333 cli_cmd_flag_none,
1334 "= pings wpa_supplicant" },
1335 { "mib", wpa_cli_cmd_mib,
1336 cli_cmd_flag_none,
1337 "= get MIB variables (dot1x, dot11)" },
1338 { "help", wpa_cli_cmd_help,
1339 cli_cmd_flag_none,
1340 "= show this usage help" },
1341 { "interface", wpa_cli_cmd_interface,
1342 cli_cmd_flag_none,
1343 "[ifname] = show interfaces/select interface" },
1344 { "level", wpa_cli_cmd_level,
1345 cli_cmd_flag_none,
1346 "<debug level> = change debug level" },
1347 { "license", wpa_cli_cmd_license,
1348 cli_cmd_flag_none,
1349 "= show full wpa_cli license" },
1350 { "quit", wpa_cli_cmd_quit,
1351 cli_cmd_flag_none,
1352 "= exit wpa_cli" },
1353 { "set", wpa_cli_cmd_set,
1354 cli_cmd_flag_none,
1355 "= set variables (shows list of variables when run without "
1356 "arguments)" },
1357 { "logon", wpa_cli_cmd_logon,
1358 cli_cmd_flag_none,
1359 "= IEEE 802.1X EAPOL state machine logon" },
1360 { "logoff", wpa_cli_cmd_logoff,
1361 cli_cmd_flag_none,
1362 "= IEEE 802.1X EAPOL state machine logoff" },
1363 { "pmksa", wpa_cli_cmd_pmksa,
1364 cli_cmd_flag_none,
1365 "= show PMKSA cache" },
1366 { "reassociate", wpa_cli_cmd_reassociate,
1367 cli_cmd_flag_none,
1368 "= force reassociation" },
1369 { "preauthenticate", wpa_cli_cmd_preauthenticate,
1370 cli_cmd_flag_none,
1371 "<BSSID> = force preauthentication" },
1372 { "identity", wpa_cli_cmd_identity,
1373 cli_cmd_flag_none,
1374 "<network id> <identity> = configure identity for an SSID" },
1375 { "password", wpa_cli_cmd_password,
1376 cli_cmd_flag_sensitive,
1377 "<network id> <password> = configure password for an SSID" },
1378 { "new_password", wpa_cli_cmd_new_password,
1379 cli_cmd_flag_sensitive,
1380 "<network id> <password> = change password for an SSID" },
1381 { "pin", wpa_cli_cmd_pin,
1382 cli_cmd_flag_sensitive,
1383 "<network id> <pin> = configure pin for an SSID" },
1384 { "otp", wpa_cli_cmd_otp,
1385 cli_cmd_flag_sensitive,
1386 "<network id> <password> = configure one-time-password for an SSID"
1388 { "passphrase", wpa_cli_cmd_passphrase,
1389 cli_cmd_flag_sensitive,
1390 "<network id> <passphrase> = configure private key passphrase\n"
1391 " for an SSID" },
1392 { "bssid", wpa_cli_cmd_bssid,
1393 cli_cmd_flag_none,
1394 "<network id> <BSSID> = set preferred BSSID for an SSID" },
1395 { "list_networks", wpa_cli_cmd_list_networks,
1396 cli_cmd_flag_none,
1397 "= list configured networks" },
1398 { "select_network", wpa_cli_cmd_select_network,
1399 cli_cmd_flag_none,
1400 "<network id> = select a network (disable others)" },
1401 { "enable_network", wpa_cli_cmd_enable_network,
1402 cli_cmd_flag_none,
1403 "<network id> = enable a network" },
1404 { "disable_network", wpa_cli_cmd_disable_network,
1405 cli_cmd_flag_none,
1406 "<network id> = disable a network" },
1407 { "add_network", wpa_cli_cmd_add_network,
1408 cli_cmd_flag_none,
1409 "= add a network" },
1410 { "remove_network", wpa_cli_cmd_remove_network,
1411 cli_cmd_flag_none,
1412 "<network id> = remove a network" },
1413 { "set_network", wpa_cli_cmd_set_network,
1414 cli_cmd_flag_sensitive,
1415 "<network id> <variable> <value> = set network variables (shows\n"
1416 " list of variables when run without arguments)" },
1417 { "get_network", wpa_cli_cmd_get_network,
1418 cli_cmd_flag_none,
1419 "<network id> <variable> = get network variables" },
1420 { "save_config", wpa_cli_cmd_save_config,
1421 cli_cmd_flag_none,
1422 "= save the current configuration" },
1423 { "disconnect", wpa_cli_cmd_disconnect,
1424 cli_cmd_flag_none,
1425 "= disconnect and wait for reassociate/reconnect command before\n"
1426 " connecting" },
1427 { "reconnect", wpa_cli_cmd_reconnect,
1428 cli_cmd_flag_none,
1429 "= like reassociate, but only takes effect if already disconnected"
1431 { "scan", wpa_cli_cmd_scan,
1432 cli_cmd_flag_none,
1433 "= request new BSS scan" },
1434 { "scan_results", wpa_cli_cmd_scan_results,
1435 cli_cmd_flag_none,
1436 "= get latest scan results" },
1437 { "bss", wpa_cli_cmd_bss,
1438 cli_cmd_flag_none,
1439 "<<idx> | <bssid>> = get detailed scan result info" },
1440 { "get_capability", wpa_cli_cmd_get_capability,
1441 cli_cmd_flag_none,
1442 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1443 { "reconfigure", wpa_cli_cmd_reconfigure,
1444 cli_cmd_flag_none,
1445 "= force wpa_supplicant to re-read its configuration file" },
1446 { "terminate", wpa_cli_cmd_terminate,
1447 cli_cmd_flag_none,
1448 "= terminate wpa_supplicant" },
1449 { "interface_add", wpa_cli_cmd_interface_add,
1450 cli_cmd_flag_none,
1451 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1452 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1453 " are optional" },
1454 { "interface_remove", wpa_cli_cmd_interface_remove,
1455 cli_cmd_flag_none,
1456 "<ifname> = removes the interface" },
1457 { "interface_list", wpa_cli_cmd_interface_list,
1458 cli_cmd_flag_none,
1459 "= list available interfaces" },
1460 { "ap_scan", wpa_cli_cmd_ap_scan,
1461 cli_cmd_flag_none,
1462 "<value> = set ap_scan parameter" },
1463 { "stkstart", wpa_cli_cmd_stkstart,
1464 cli_cmd_flag_none,
1465 "<addr> = request STK negotiation with <addr>" },
1466 { "ft_ds", wpa_cli_cmd_ft_ds,
1467 cli_cmd_flag_none,
1468 "<addr> = request over-the-DS FT with <addr>" },
1469 { "wps_pbc", wpa_cli_cmd_wps_pbc,
1470 cli_cmd_flag_none,
1471 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1472 { "wps_pin", wpa_cli_cmd_wps_pin,
1473 cli_cmd_flag_sensitive,
1474 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1475 "hardcoded)" },
1476 #ifdef CONFIG_WPS_OOB
1477 { "wps_oob", wpa_cli_cmd_wps_oob,
1478 cli_cmd_flag_sensitive,
1479 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
1480 #endif /* CONFIG_WPS_OOB */
1481 { "wps_reg", wpa_cli_cmd_wps_reg,
1482 cli_cmd_flag_sensitive,
1483 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1484 { "wps_er_start", wpa_cli_cmd_wps_er_start,
1485 cli_cmd_flag_none,
1486 "= start Wi-Fi Protected Setup External Registrar" },
1487 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1488 cli_cmd_flag_none,
1489 "= stop Wi-Fi Protected Setup External Registrar" },
1490 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1491 cli_cmd_flag_sensitive,
1492 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
1493 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1494 cli_cmd_flag_none,
1495 "<UUID> = accept an Enrollee PBC using External Registrar" },
1496 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1497 cli_cmd_flag_sensitive,
1498 "<UUID> <PIN> = learn AP configuration" },
1499 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1500 cli_cmd_flag_none,
1501 "<addr> = request RSN authentication with <addr> in IBSS" },
1502 #ifdef CONFIG_AP
1503 { "sta", wpa_cli_cmd_sta,
1504 cli_cmd_flag_none,
1505 "<addr> = get information about an associated station (AP)" },
1506 { "all_sta", wpa_cli_cmd_all_sta,
1507 cli_cmd_flag_none,
1508 "= get information about all associated stations (AP)" },
1509 #endif /* CONFIG_AP */
1510 { NULL, NULL, cli_cmd_flag_none, NULL }
1515 * Prints command usage, lines are padded with the specified string.
1517 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1519 char c;
1520 size_t n;
1522 printf("%s%s ", pad, cmd->cmd);
1523 for (n = 0; (c = cmd->usage[n]); n++) {
1524 printf("%c", c);
1525 if (c == '\n')
1526 printf("%s", pad);
1528 printf("\n");
1532 static void print_help(void)
1534 int n;
1535 printf("commands:\n");
1536 for (n = 0; wpa_cli_commands[n].cmd; n++)
1537 print_cmd_help(&wpa_cli_commands[n], " ");
1541 #ifdef CONFIG_READLINE
1542 static int cmd_has_sensitive_data(const char *cmd)
1544 const char *c, *delim;
1545 int n;
1546 size_t len;
1548 delim = os_strchr(cmd, ' ');
1549 if (delim)
1550 len = delim - cmd;
1551 else
1552 len = os_strlen(cmd);
1554 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1555 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1556 return (wpa_cli_commands[n].flags &
1557 cli_cmd_flag_sensitive);
1559 return 0;
1561 #endif /* CONFIG_READLINE */
1564 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1566 struct wpa_cli_cmd *cmd, *match = NULL;
1567 int count;
1568 int ret = 0;
1570 count = 0;
1571 cmd = wpa_cli_commands;
1572 while (cmd->cmd) {
1573 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1575 match = cmd;
1576 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1577 /* we have an exact match */
1578 count = 1;
1579 break;
1581 count++;
1583 cmd++;
1586 if (count > 1) {
1587 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1588 cmd = wpa_cli_commands;
1589 while (cmd->cmd) {
1590 if (os_strncasecmp(cmd->cmd, argv[0],
1591 os_strlen(argv[0])) == 0) {
1592 printf(" %s", cmd->cmd);
1594 cmd++;
1596 printf("\n");
1597 ret = 1;
1598 } else if (count == 0) {
1599 printf("Unknown command '%s'\n", argv[0]);
1600 ret = 1;
1601 } else {
1602 ret = match->handler(ctrl, argc - 1, &argv[1]);
1605 return ret;
1609 static int str_match(const char *a, const char *b)
1611 return os_strncmp(a, b, os_strlen(b)) == 0;
1615 static int wpa_cli_exec(const char *program, const char *arg1,
1616 const char *arg2)
1618 char *cmd;
1619 size_t len;
1620 int res;
1621 int ret = 0;
1623 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1624 cmd = os_malloc(len);
1625 if (cmd == NULL)
1626 return -1;
1627 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1628 if (res < 0 || (size_t) res >= len) {
1629 os_free(cmd);
1630 return -1;
1632 cmd[len - 1] = '\0';
1633 #ifndef _WIN32_WCE
1634 if (system(cmd) < 0)
1635 ret = -1;
1636 #endif /* _WIN32_WCE */
1637 os_free(cmd);
1639 return ret;
1643 static void wpa_cli_action_process(const char *msg)
1645 const char *pos;
1646 char *copy = NULL, *id, *pos2;
1648 pos = msg;
1649 if (*pos == '<') {
1650 /* skip priority */
1651 pos = os_strchr(pos, '>');
1652 if (pos)
1653 pos++;
1654 else
1655 pos = msg;
1658 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1659 int new_id = -1;
1660 os_unsetenv("WPA_ID");
1661 os_unsetenv("WPA_ID_STR");
1662 os_unsetenv("WPA_CTRL_DIR");
1664 pos = os_strstr(pos, "[id=");
1665 if (pos)
1666 copy = os_strdup(pos + 4);
1668 if (copy) {
1669 pos2 = id = copy;
1670 while (*pos2 && *pos2 != ' ')
1671 pos2++;
1672 *pos2++ = '\0';
1673 new_id = atoi(id);
1674 os_setenv("WPA_ID", id, 1);
1675 while (*pos2 && *pos2 != '=')
1676 pos2++;
1677 if (*pos2 == '=')
1678 pos2++;
1679 id = pos2;
1680 while (*pos2 && *pos2 != ']')
1681 pos2++;
1682 *pos2 = '\0';
1683 os_setenv("WPA_ID_STR", id, 1);
1684 os_free(copy);
1687 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1689 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1690 wpa_cli_connected = 1;
1691 wpa_cli_last_id = new_id;
1692 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1694 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1695 if (wpa_cli_connected) {
1696 wpa_cli_connected = 0;
1697 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1699 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1700 printf("wpa_supplicant is terminating - stop monitoring\n");
1701 wpa_cli_quit = 1;
1706 #ifndef CONFIG_ANSI_C_EXTRA
1707 static void wpa_cli_action_cb(char *msg, size_t len)
1709 wpa_cli_action_process(msg);
1711 #endif /* CONFIG_ANSI_C_EXTRA */
1714 static void wpa_cli_reconnect(void)
1716 wpa_cli_close_connection();
1717 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1718 if (ctrl_conn) {
1719 printf("Connection to wpa_supplicant re-established\n");
1720 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1721 wpa_cli_attached = 1;
1722 } else {
1723 printf("Warning: Failed to attach to "
1724 "wpa_supplicant.\n");
1730 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1731 int action_monitor)
1733 int first = 1;
1734 if (ctrl_conn == NULL) {
1735 wpa_cli_reconnect();
1736 return;
1738 while (wpa_ctrl_pending(ctrl) > 0) {
1739 char buf[256];
1740 size_t len = sizeof(buf) - 1;
1741 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1742 buf[len] = '\0';
1743 if (action_monitor)
1744 wpa_cli_action_process(buf);
1745 else {
1746 if (in_read && first)
1747 printf("\n");
1748 first = 0;
1749 printf("%s\n", buf);
1751 } else {
1752 printf("Could not read pending message.\n");
1753 break;
1757 if (wpa_ctrl_pending(ctrl) < 0) {
1758 printf("Connection to wpa_supplicant lost - trying to "
1759 "reconnect\n");
1760 wpa_cli_reconnect();
1765 #ifdef CONFIG_READLINE
1766 static char * wpa_cli_cmd_gen(const char *text, int state)
1768 static int i, len;
1769 const char *cmd;
1771 if (state == 0) {
1772 i = 0;
1773 len = os_strlen(text);
1776 while ((cmd = wpa_cli_commands[i].cmd)) {
1777 i++;
1778 if (os_strncasecmp(cmd, text, len) == 0)
1779 return os_strdup(cmd);
1782 return NULL;
1786 static char * wpa_cli_dummy_gen(const char *text, int state)
1788 return NULL;
1792 static char ** wpa_cli_completion(const char *text, int start, int end)
1794 return rl_completion_matches(text, start == 0 ?
1795 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1797 #endif /* CONFIG_READLINE */
1800 static void wpa_cli_interactive(void)
1802 #define max_args 10
1803 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1804 int argc;
1805 #ifdef CONFIG_READLINE
1806 char *home, *hfile = NULL;
1807 #endif /* CONFIG_READLINE */
1809 printf("\nInteractive mode\n\n");
1811 #ifdef CONFIG_READLINE
1812 rl_attempted_completion_function = wpa_cli_completion;
1813 home = getenv("HOME");
1814 if (home) {
1815 const char *fname = ".wpa_cli_history";
1816 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1817 hfile = os_malloc(hfile_len);
1818 if (hfile) {
1819 int res;
1820 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1821 fname);
1822 if (res >= 0 && res < hfile_len) {
1823 hfile[hfile_len - 1] = '\0';
1824 read_history(hfile);
1825 stifle_history(100);
1829 #endif /* CONFIG_READLINE */
1831 do {
1832 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1833 #ifndef CONFIG_NATIVE_WINDOWS
1834 alarm(ping_interval);
1835 #endif /* CONFIG_NATIVE_WINDOWS */
1836 #ifdef CONFIG_READLINE
1837 cmd = readline("> ");
1838 if (cmd && *cmd) {
1839 HIST_ENTRY *h;
1840 while (next_history())
1842 h = previous_history();
1843 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1844 add_history(cmd);
1845 next_history();
1847 #else /* CONFIG_READLINE */
1848 printf("> ");
1849 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1850 #endif /* CONFIG_READLINE */
1851 #ifndef CONFIG_NATIVE_WINDOWS
1852 alarm(0);
1853 #endif /* CONFIG_NATIVE_WINDOWS */
1854 if (cmd == NULL)
1855 break;
1856 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1857 pos = cmd;
1858 while (*pos != '\0') {
1859 if (*pos == '\n') {
1860 *pos = '\0';
1861 break;
1863 pos++;
1865 argc = 0;
1866 pos = cmd;
1867 for (;;) {
1868 while (*pos == ' ')
1869 pos++;
1870 if (*pos == '\0')
1871 break;
1872 argv[argc] = pos;
1873 argc++;
1874 if (argc == max_args)
1875 break;
1876 if (*pos == '"') {
1877 char *pos2 = os_strrchr(pos, '"');
1878 if (pos2)
1879 pos = pos2 + 1;
1881 while (*pos != '\0' && *pos != ' ')
1882 pos++;
1883 if (*pos == ' ')
1884 *pos++ = '\0';
1886 if (argc)
1887 wpa_request(ctrl_conn, argc, argv);
1889 if (cmd != cmdbuf)
1890 free(cmd);
1891 } while (!wpa_cli_quit);
1893 #ifdef CONFIG_READLINE
1894 if (hfile) {
1895 /* Save command history, excluding lines that may contain
1896 * passwords. */
1897 HIST_ENTRY *h;
1898 history_set_pos(0);
1899 while ((h = current_history())) {
1900 char *p = h->line;
1901 while (*p == ' ' || *p == '\t')
1902 p++;
1903 if (cmd_has_sensitive_data(p)) {
1904 h = remove_history(where_history());
1905 if (h) {
1906 os_free(h->line);
1907 os_free(h->data);
1908 os_free(h);
1909 } else
1910 next_history();
1911 } else
1912 next_history();
1914 write_history(hfile);
1915 os_free(hfile);
1917 #endif /* CONFIG_READLINE */
1921 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1923 #ifdef CONFIG_ANSI_C_EXTRA
1924 /* TODO: ANSI C version(?) */
1925 printf("Action processing not supported in ANSI C build.\n");
1926 #else /* CONFIG_ANSI_C_EXTRA */
1927 fd_set rfds;
1928 int fd, res;
1929 struct timeval tv;
1930 char buf[256]; /* note: large enough to fit in unsolicited messages */
1931 size_t len;
1933 fd = wpa_ctrl_get_fd(ctrl);
1935 while (!wpa_cli_quit) {
1936 FD_ZERO(&rfds);
1937 FD_SET(fd, &rfds);
1938 tv.tv_sec = ping_interval;
1939 tv.tv_usec = 0;
1940 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1941 if (res < 0 && errno != EINTR) {
1942 perror("select");
1943 break;
1946 if (FD_ISSET(fd, &rfds))
1947 wpa_cli_recv_pending(ctrl, 0, 1);
1948 else {
1949 /* verify that connection is still working */
1950 len = sizeof(buf) - 1;
1951 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1952 wpa_cli_action_cb) < 0 ||
1953 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1954 printf("wpa_supplicant did not reply to PING "
1955 "command - exiting\n");
1956 break;
1960 #endif /* CONFIG_ANSI_C_EXTRA */
1964 static void wpa_cli_cleanup(void)
1966 wpa_cli_close_connection();
1967 if (pid_file)
1968 os_daemonize_terminate(pid_file);
1970 os_program_deinit();
1973 static void wpa_cli_terminate(int sig)
1975 wpa_cli_cleanup();
1976 exit(0);
1980 #ifndef CONFIG_NATIVE_WINDOWS
1981 static void wpa_cli_alarm(int sig)
1983 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1984 printf("Connection to wpa_supplicant lost - trying to "
1985 "reconnect\n");
1986 wpa_cli_close_connection();
1988 if (!ctrl_conn)
1989 wpa_cli_reconnect();
1990 if (ctrl_conn)
1991 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1992 alarm(ping_interval);
1994 #endif /* CONFIG_NATIVE_WINDOWS */
1997 static char * wpa_cli_get_default_ifname(void)
1999 char *ifname = NULL;
2001 #ifdef CONFIG_CTRL_IFACE_UNIX
2002 struct dirent *dent;
2003 DIR *dir = opendir(ctrl_iface_dir);
2004 if (!dir)
2005 return NULL;
2006 while ((dent = readdir(dir))) {
2007 #ifdef _DIRENT_HAVE_D_TYPE
2009 * Skip the file if it is not a socket. Also accept
2010 * DT_UNKNOWN (0) in case the C library or underlying
2011 * file system does not support d_type.
2013 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2014 continue;
2015 #endif /* _DIRENT_HAVE_D_TYPE */
2016 if (os_strcmp(dent->d_name, ".") == 0 ||
2017 os_strcmp(dent->d_name, "..") == 0)
2018 continue;
2019 printf("Selected interface '%s'\n", dent->d_name);
2020 ifname = os_strdup(dent->d_name);
2021 break;
2023 closedir(dir);
2024 #endif /* CONFIG_CTRL_IFACE_UNIX */
2026 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2027 char buf[2048], *pos;
2028 size_t len;
2029 struct wpa_ctrl *ctrl;
2030 int ret;
2032 ctrl = wpa_ctrl_open(NULL);
2033 if (ctrl == NULL)
2034 return NULL;
2036 len = sizeof(buf) - 1;
2037 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2038 if (ret >= 0) {
2039 buf[len] = '\0';
2040 pos = os_strchr(buf, '\n');
2041 if (pos)
2042 *pos = '\0';
2043 ifname = os_strdup(buf);
2045 wpa_ctrl_close(ctrl);
2046 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2048 return ifname;
2052 int main(int argc, char *argv[])
2054 int interactive;
2055 int warning_displayed = 0;
2056 int c;
2057 int daemonize = 0;
2058 int ret = 0;
2059 const char *global = NULL;
2061 if (os_program_init())
2062 return -1;
2064 for (;;) {
2065 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
2066 if (c < 0)
2067 break;
2068 switch (c) {
2069 case 'a':
2070 action_file = optarg;
2071 break;
2072 case 'B':
2073 daemonize = 1;
2074 break;
2075 case 'g':
2076 global = optarg;
2077 break;
2078 case 'G':
2079 ping_interval = atoi(optarg);
2080 break;
2081 case 'h':
2082 usage();
2083 return 0;
2084 case 'v':
2085 printf("%s\n", wpa_cli_version);
2086 return 0;
2087 case 'i':
2088 os_free(ctrl_ifname);
2089 ctrl_ifname = os_strdup(optarg);
2090 break;
2091 case 'p':
2092 ctrl_iface_dir = optarg;
2093 break;
2094 case 'P':
2095 pid_file = optarg;
2096 break;
2097 default:
2098 usage();
2099 return -1;
2103 interactive = (argc == optind) && (action_file == NULL);
2105 if (interactive)
2106 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2108 if (global) {
2109 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2110 ctrl_conn = wpa_ctrl_open(NULL);
2111 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2112 ctrl_conn = wpa_ctrl_open(global);
2113 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2114 if (ctrl_conn == NULL) {
2115 perror("Failed to connect to wpa_supplicant - "
2116 "wpa_ctrl_open");
2117 return -1;
2121 for (; !global;) {
2122 if (ctrl_ifname == NULL)
2123 ctrl_ifname = wpa_cli_get_default_ifname();
2124 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
2125 if (ctrl_conn) {
2126 if (warning_displayed)
2127 printf("Connection established.\n");
2128 break;
2131 if (!interactive) {
2132 perror("Failed to connect to wpa_supplicant - "
2133 "wpa_ctrl_open");
2134 return -1;
2137 if (!warning_displayed) {
2138 printf("Could not connect to wpa_supplicant - "
2139 "re-trying\n");
2140 warning_displayed = 1;
2142 os_sleep(1, 0);
2143 continue;
2146 #ifndef _WIN32_WCE
2147 signal(SIGINT, wpa_cli_terminate);
2148 signal(SIGTERM, wpa_cli_terminate);
2149 #endif /* _WIN32_WCE */
2150 #ifndef CONFIG_NATIVE_WINDOWS
2151 signal(SIGALRM, wpa_cli_alarm);
2152 #endif /* CONFIG_NATIVE_WINDOWS */
2154 if (interactive || action_file) {
2155 if (wpa_ctrl_attach(ctrl_conn) == 0) {
2156 wpa_cli_attached = 1;
2157 } else {
2158 printf("Warning: Failed to attach to "
2159 "wpa_supplicant.\n");
2160 if (!interactive)
2161 return -1;
2165 if (daemonize && os_daemonize(pid_file))
2166 return -1;
2168 if (interactive)
2169 wpa_cli_interactive();
2170 else if (action_file)
2171 wpa_cli_action(ctrl_conn);
2172 else
2173 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2175 os_free(ctrl_ifname);
2176 wpa_cli_cleanup();
2178 return ret;
2181 #else /* CONFIG_CTRL_IFACE */
2182 int main(int argc, char *argv[])
2184 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2185 return -1;
2187 #endif /* CONFIG_CTRL_IFACE */