1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2010, 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 */
26 #ifdef CONFIG_WPA_CLI_FORK
27 #include <sys/wait.h>
28 #endif /* CONFIG_WPA_CLI_FORK */
30 #include "common/wpa_ctrl.h"
31 #include "common.h"
32 #include "common/version.h"
35 static const char *wpa_cli_version =
36 "wpa_cli v" VERSION_STR "\n"
37 "Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
40 static const char *wpa_cli_license =
41 "This program is free software. You can distribute it and/or modify it\n"
42 "under the terms of the GNU General Public License version 2.\n"
43 "\n"
44 "Alternatively, this software may be distributed under the terms of the\n"
45 "BSD license. See README and COPYING for more details.\n";
47 static const char *wpa_cli_full_license =
48 "This program is free software; you can redistribute it and/or modify\n"
49 "it under the terms of the GNU General Public License version 2 as\n"
50 "published by the Free Software Foundation.\n"
51 "\n"
52 "This program is distributed in the hope that it will be useful,\n"
53 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
54 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
55 "GNU General Public License for more details.\n"
56 "\n"
57 "You should have received a copy of the GNU General Public License\n"
58 "along with this program; if not, write to the Free Software\n"
59 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
60 "\n"
61 "Alternatively, this software may be distributed under the terms of the\n"
62 "BSD license.\n"
63 "\n"
64 "Redistribution and use in source and binary forms, with or without\n"
65 "modification, are permitted provided that the following conditions are\n"
66 "met:\n"
67 "\n"
68 "1. Redistributions of source code must retain the above copyright\n"
69 " notice, this list of conditions and the following disclaimer.\n"
70 "\n"
71 "2. Redistributions in binary form must reproduce the above copyright\n"
72 " notice, this list of conditions and the following disclaimer in the\n"
73 " documentation and/or other materials provided with the distribution.\n"
74 "\n"
75 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
76 " names of its contributors may be used to endorse or promote products\n"
77 " derived from this software without specific prior written permission.\n"
78 "\n"
79 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
80 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
81 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
82 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
83 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
84 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
85 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
86 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
87 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
88 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
89 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
90 "\n";
92 static struct wpa_ctrl *ctrl_conn;
93 static struct wpa_ctrl *mon_conn;
94 #ifdef CONFIG_WPA_CLI_FORK
95 static pid_t mon_pid = 0;
96 #endif /* CONFIG_WPA_CLI_FORK */
97 static int wpa_cli_quit = 0;
98 static int wpa_cli_attached = 0;
99 static int wpa_cli_connected = 0;
100 static int wpa_cli_last_id = 0;
101 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
102 static char *ctrl_ifname = NULL;
103 static const char *pid_file = NULL;
104 static const char *action_file = NULL;
105 static int ping_interval = 5;
106 static int interactive = 0;
109 static void print_help();
112 static void usage(void)
113 {
114 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
115 "[-a<action file>] \\\n"
116 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
117 "[command..]\n"
118 " -h = help (show this usage text)\n"
119 " -v = shown version information\n"
120 " -a = run in daemon mode executing the action file based on "
121 "events from\n"
122 " wpa_supplicant\n"
123 " -B = run a daemon in the background\n"
124 " default path: /var/run/wpa_supplicant\n"
125 " default interface: first interface found in socket path\n");
126 print_help();
127 }
130 static void readline_redraw()
131 {
132 #ifdef CONFIG_READLINE
133 rl_on_new_line();
134 rl_redisplay();
135 #endif /* CONFIG_READLINE */
136 }
139 static int str_starts(const char *src, const char *match)
140 {
141 return os_strncmp(src, match, os_strlen(match)) == 0;
142 }
145 static int wpa_cli_show_event(const char *event)
146 {
147 const char *start;
149 start = os_strchr(event, '>');
150 if (start == NULL)
151 return 1;
153 start++;
154 /*
155 * Skip BSS added/removed events since they can be relatively frequent
156 * and are likely of not much use for an interactive user.
157 */
158 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
159 str_starts(start, WPA_EVENT_BSS_REMOVED))
160 return 0;
162 return 1;
163 }
166 #ifdef CONFIG_WPA_CLI_FORK
167 static int in_query = 0;
169 static void wpa_cli_monitor_sig(int sig)
170 {
171 if (sig == SIGUSR1)
172 in_query = 1;
173 else if (sig == SIGUSR2)
174 in_query = 0;
175 }
178 static void wpa_cli_monitor(void)
179 {
180 char buf[256];
181 size_t len = sizeof(buf) - 1;
182 struct timeval tv;
183 fd_set rfds;
184 int ppid;
186 signal(SIGUSR1, wpa_cli_monitor_sig);
187 signal(SIGUSR2, wpa_cli_monitor_sig);
189 ppid = getppid();
190 while (mon_conn) {
191 int s = wpa_ctrl_get_fd(mon_conn);
192 tv.tv_sec = 5;
193 tv.tv_usec = 0;
194 FD_ZERO(&rfds);
195 FD_SET(s, &rfds);
196 if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
197 if (errno == EINTR)
198 continue;
199 perror("select");
200 break;
201 }
202 if (mon_conn == NULL)
203 break;
204 if (FD_ISSET(s, &rfds)) {
205 len = sizeof(buf) - 1;
206 int res = wpa_ctrl_recv(mon_conn, buf, &len);
207 if (res < 0) {
208 perror("wpa_ctrl_recv");
209 break;
210 }
211 buf[len] = '\0';
212 if (wpa_cli_show_event(buf)) {
213 if (in_query)
214 printf("\r");
215 printf("%s\n", buf);
216 kill(ppid, SIGUSR1);
217 }
218 }
219 }
220 }
221 #endif /* CONFIG_WPA_CLI_FORK */
224 static int wpa_cli_open_connection(const char *ifname, int attach)
225 {
226 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
227 ctrl_conn = wpa_ctrl_open(ifname);
228 if (ctrl_conn == NULL)
229 return -1;
231 if (attach && interactive)
232 mon_conn = wpa_ctrl_open(ifname);
233 else
234 mon_conn = NULL;
235 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
236 char *cfile;
237 int flen, res;
239 if (ifname == NULL)
240 return -1;
242 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
243 cfile = os_malloc(flen);
244 if (cfile == NULL)
245 return -1L;
246 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
247 if (res < 0 || res >= flen) {
248 os_free(cfile);
249 return -1;
250 }
252 ctrl_conn = wpa_ctrl_open(cfile);
253 if (ctrl_conn == NULL) {
254 os_free(cfile);
255 return -1;
256 }
258 if (attach && interactive)
259 mon_conn = wpa_ctrl_open(cfile);
260 else
261 mon_conn = NULL;
262 os_free(cfile);
263 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
265 if (mon_conn) {
266 if (wpa_ctrl_attach(mon_conn) == 0) {
267 wpa_cli_attached = 1;
268 } else {
269 printf("Warning: Failed to attach to "
270 "wpa_supplicant.\n");
271 return -1;
272 }
274 #ifdef CONFIG_WPA_CLI_FORK
275 {
276 pid_t p = fork();
277 if (p < 0) {
278 perror("fork");
279 return -1;
280 }
281 if (p == 0) {
282 wpa_cli_monitor();
283 exit(0);
284 } else
285 mon_pid = p;
286 }
287 #endif /* CONFIG_WPA_CLI_FORK */
288 }
290 return 0;
291 }
294 static void wpa_cli_close_connection(void)
295 {
296 if (ctrl_conn == NULL)
297 return;
299 #ifdef CONFIG_WPA_CLI_FORK
300 if (mon_pid) {
301 int status;
302 kill(mon_pid, SIGPIPE);
303 wait(&status);
304 mon_pid = 0;
305 }
306 #endif /* CONFIG_WPA_CLI_FORK */
308 if (wpa_cli_attached) {
309 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
310 wpa_cli_attached = 0;
311 }
312 wpa_ctrl_close(ctrl_conn);
313 ctrl_conn = NULL;
314 if (mon_conn) {
315 wpa_ctrl_close(mon_conn);
316 mon_conn = NULL;
317 }
318 }
321 static void wpa_cli_msg_cb(char *msg, size_t len)
322 {
323 printf("%s\n", msg);
324 }
327 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
328 {
329 char buf[2048];
330 size_t len;
331 int ret;
333 if (ctrl_conn == NULL) {
334 printf("Not connected to wpa_supplicant - command dropped.\n");
335 return -1;
336 }
337 len = sizeof(buf) - 1;
338 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
339 wpa_cli_msg_cb);
340 if (ret == -2) {
341 printf("'%s' command timed out.\n", cmd);
342 return -2;
343 } else if (ret < 0) {
344 printf("'%s' command failed.\n", cmd);
345 return -1;
346 }
347 if (print) {
348 buf[len] = '\0';
349 printf("%s", buf);
350 }
351 return 0;
352 }
355 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
356 {
357 return _wpa_ctrl_command(ctrl, cmd, 1);
358 }
361 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
362 {
363 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
364 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
365 }
368 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
369 {
370 return wpa_ctrl_command(ctrl, "PING");
371 }
374 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
375 {
376 char cmd[256];
377 int ret;
378 if (argc == 0)
379 return -1;
380 ret = os_snprintf(cmd, sizeof(cmd), "NOTE %s", argv[0]);
381 if (ret < 0 || (size_t) ret >= sizeof(cmd))
382 return -1;
383 return wpa_ctrl_command(ctrl, cmd);
384 }
387 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
388 {
389 return wpa_ctrl_command(ctrl, "MIB");
390 }
393 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
394 {
395 return wpa_ctrl_command(ctrl, "PMKSA");
396 }
399 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
400 {
401 print_help();
402 return 0;
403 }
406 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
407 {
408 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
409 return 0;
410 }
413 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
414 {
415 wpa_cli_quit = 1;
416 return 0;
417 }
420 static void wpa_cli_show_variables(void)
421 {
422 printf("set variables:\n"
423 " EAPOL::heldPeriod (EAPOL state machine held period, "
424 "in seconds)\n"
425 " EAPOL::authPeriod (EAPOL state machine authentication "
426 "period, in seconds)\n"
427 " EAPOL::startPeriod (EAPOL state machine start period, in "
428 "seconds)\n"
429 " EAPOL::maxStart (EAPOL state machine maximum start "
430 "attempts)\n");
431 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
432 "seconds)\n"
433 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
434 " threshold\n\tpercentage)\n"
435 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
436 "security\n\tassociation in seconds)\n");
437 }
440 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
441 {
442 char cmd[256];
443 int res;
445 if (argc == 0) {
446 wpa_cli_show_variables();
447 return 0;
448 }
450 if (argc != 2) {
451 printf("Invalid SET command: needs two arguments (variable "
452 "name and value)\n");
453 return -1;
454 }
456 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
457 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
458 printf("Too long SET command.\n");
459 return -1;
460 }
461 return wpa_ctrl_command(ctrl, cmd);
462 }
465 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
466 {
467 char cmd[256];
468 int res;
470 if (argc != 1) {
471 printf("Invalid GET command: need one argument (variable "
472 "name)\n");
473 return -1;
474 }
476 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
477 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
478 printf("Too long GET command.\n");
479 return -1;
480 }
481 return wpa_ctrl_command(ctrl, cmd);
482 }
485 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
486 {
487 return wpa_ctrl_command(ctrl, "LOGOFF");
488 }
491 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
492 {
493 return wpa_ctrl_command(ctrl, "LOGON");
494 }
497 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
498 char *argv[])
499 {
500 return wpa_ctrl_command(ctrl, "REASSOCIATE");
501 }
504 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
505 char *argv[])
506 {
507 char cmd[256];
508 int res;
510 if (argc != 1) {
511 printf("Invalid PREAUTH command: needs one argument "
512 "(BSSID)\n");
513 return -1;
514 }
516 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
517 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
518 printf("Too long PREAUTH command.\n");
519 return -1;
520 }
521 return wpa_ctrl_command(ctrl, cmd);
522 }
525 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
526 {
527 char cmd[256];
528 int res;
530 if (argc != 1) {
531 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
532 "value)\n");
533 return -1;
534 }
535 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
536 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
537 printf("Too long AP_SCAN command.\n");
538 return -1;
539 }
540 return wpa_ctrl_command(ctrl, cmd);
541 }
544 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
545 char *argv[])
546 {
547 char cmd[256];
548 int res;
550 if (argc != 1) {
551 printf("Invalid STKSTART command: needs one argument "
552 "(Peer STA MAC address)\n");
553 return -1;
554 }
556 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
557 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
558 printf("Too long STKSTART command.\n");
559 return -1;
560 }
561 return wpa_ctrl_command(ctrl, cmd);
562 }
565 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
566 {
567 char cmd[256];
568 int res;
570 if (argc != 1) {
571 printf("Invalid FT_DS command: needs one argument "
572 "(Target AP MAC address)\n");
573 return -1;
574 }
576 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
577 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
578 printf("Too long FT_DS command.\n");
579 return -1;
580 }
581 return wpa_ctrl_command(ctrl, cmd);
582 }
585 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
586 {
587 char cmd[256];
588 int res;
590 if (argc == 0) {
591 /* Any BSSID */
592 return wpa_ctrl_command(ctrl, "WPS_PBC");
593 }
595 /* Specific BSSID */
596 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
597 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
598 printf("Too long WPS_PBC command.\n");
599 return -1;
600 }
601 return wpa_ctrl_command(ctrl, cmd);
602 }
605 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
606 {
607 char cmd[256];
608 int res;
610 if (argc == 0) {
611 printf("Invalid WPS_PIN command: need one or two arguments:\n"
612 "- BSSID: use 'any' to select any\n"
613 "- PIN: optional, used only with devices that have no "
614 "display\n");
615 return -1;
616 }
618 if (argc == 1) {
619 /* Use dynamically generated PIN (returned as reply) */
620 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
621 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
622 printf("Too long WPS_PIN command.\n");
623 return -1;
624 }
625 return wpa_ctrl_command(ctrl, cmd);
626 }
628 /* Use hardcoded PIN from a label */
629 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
630 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
631 printf("Too long WPS_PIN command.\n");
632 return -1;
633 }
634 return wpa_ctrl_command(ctrl, cmd);
635 }
638 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
639 char *argv[])
640 {
641 char cmd[256];
642 int res;
644 if (argc != 1 && argc != 2) {
645 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
646 "- PIN to be verified\n");
647 return -1;
648 }
650 if (argc == 2)
651 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
652 argv[0], argv[1]);
653 else
654 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
655 argv[0]);
656 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
657 printf("Too long WPS_CHECK_PIN command.\n");
658 return -1;
659 }
660 return wpa_ctrl_command(ctrl, cmd);
661 }
664 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
665 char *argv[])
666 {
667 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
668 }
671 #ifdef CONFIG_WPS_OOB
672 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
673 {
674 char cmd[256];
675 int res;
677 if (argc != 3 && argc != 4) {
678 printf("Invalid WPS_OOB command: need three or four "
679 "arguments:\n"
680 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
681 "- PATH: path of OOB device like '/mnt'\n"
682 "- METHOD: OOB method 'pin-e' or 'pin-r', "
683 "'cred'\n"
684 "- DEV_NAME: (only for NFC) device name like "
685 "'pn531'\n");
686 return -1;
687 }
689 if (argc == 3)
690 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
691 argv[0], argv[1], argv[2]);
692 else
693 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
694 argv[0], argv[1], argv[2], argv[3]);
695 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
696 printf("Too long WPS_OOB command.\n");
697 return -1;
698 }
699 return wpa_ctrl_command(ctrl, cmd);
700 }
701 #endif /* CONFIG_WPS_OOB */
704 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
705 {
706 char cmd[256];
707 int res;
709 if (argc == 2)
710 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
711 argv[0], argv[1]);
712 else if (argc == 5 || argc == 6) {
713 char ssid_hex[2 * 32 + 1];
714 char key_hex[2 * 64 + 1];
715 int i;
717 ssid_hex[0] = '\0';
718 for (i = 0; i < 32; i++) {
719 if (argv[2][i] == '\0')
720 break;
721 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
722 }
724 key_hex[0] = '\0';
725 if (argc == 6) {
726 for (i = 0; i < 64; i++) {
727 if (argv[5][i] == '\0')
728 break;
729 os_snprintf(&key_hex[i * 2], 3, "%02x",
730 argv[5][i]);
731 }
732 }
734 res = os_snprintf(cmd, sizeof(cmd),
735 "WPS_REG %s %s %s %s %s %s",
736 argv[0], argv[1], ssid_hex, argv[3], argv[4],
737 key_hex);
738 } else {
739 printf("Invalid WPS_REG command: need two arguments:\n"
740 "- BSSID of the target AP\n"
741 "- AP PIN\n");
742 printf("Alternatively, six arguments can be used to "
743 "reconfigure the AP:\n"
744 "- BSSID of the target AP\n"
745 "- AP PIN\n"
746 "- new SSID\n"
747 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
748 "- new encr (NONE, WEP, TKIP, CCMP)\n"
749 "- new key\n");
750 return -1;
751 }
753 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
754 printf("Too long WPS_REG command.\n");
755 return -1;
756 }
757 return wpa_ctrl_command(ctrl, cmd);
758 }
761 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
762 char *argv[])
763 {
764 char cmd[100];
765 if (argc > 0) {
766 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
767 return wpa_ctrl_command(ctrl, cmd);
768 }
769 return wpa_ctrl_command(ctrl, "WPS_ER_START");
770 }
773 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
774 char *argv[])
775 {
776 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
778 }
781 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
782 char *argv[])
783 {
784 char cmd[256];
785 int res;
787 if (argc < 2) {
788 printf("Invalid WPS_ER_PIN command: need at least two "
789 "arguments:\n"
790 "- UUID: use 'any' to select any\n"
791 "- PIN: Enrollee PIN\n"
792 "optional: - Enrollee MAC address\n");
793 return -1;
794 }
796 if (argc > 2)
797 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
798 argv[0], argv[1], argv[2]);
799 else
800 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
801 argv[0], argv[1]);
802 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
803 printf("Too long WPS_ER_PIN command.\n");
804 return -1;
805 }
806 return wpa_ctrl_command(ctrl, cmd);
807 }
810 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
811 char *argv[])
812 {
813 char cmd[256];
814 int res;
816 if (argc != 1) {
817 printf("Invalid WPS_ER_PBC command: need one argument:\n"
818 "- UUID: Specify the Enrollee\n");
819 return -1;
820 }
822 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
823 argv[0]);
824 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
825 printf("Too long WPS_ER_PBC command.\n");
826 return -1;
827 }
828 return wpa_ctrl_command(ctrl, cmd);
829 }
832 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
833 char *argv[])
834 {
835 char cmd[256];
836 int res;
838 if (argc != 2) {
839 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
840 "- UUID: specify which AP to use\n"
841 "- PIN: AP PIN\n");
842 return -1;
843 }
845 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
846 argv[0], argv[1]);
847 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
848 printf("Too long WPS_ER_LEARN command.\n");
849 return -1;
850 }
851 return wpa_ctrl_command(ctrl, cmd);
852 }
855 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
856 char *argv[])
857 {
858 char cmd[256];
859 int res;
861 if (argc != 2) {
862 printf("Invalid WPS_ER_SET_CONFIG command: need two "
863 "arguments:\n"
864 "- UUID: specify which AP to use\n"
865 "- Network configuration id\n");
866 return -1;
867 }
869 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s",
870 argv[0], argv[1]);
871 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
872 printf("Too long WPS_ER_SET_CONFIG command.\n");
873 return -1;
874 }
875 return wpa_ctrl_command(ctrl, cmd);
876 }
879 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
880 char *argv[])
881 {
882 char cmd[256];
883 int res;
885 if (argc == 5 || argc == 6) {
886 char ssid_hex[2 * 32 + 1];
887 char key_hex[2 * 64 + 1];
888 int i;
890 ssid_hex[0] = '\0';
891 for (i = 0; i < 32; i++) {
892 if (argv[2][i] == '\0')
893 break;
894 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
895 }
897 key_hex[0] = '\0';
898 if (argc == 6) {
899 for (i = 0; i < 64; i++) {
900 if (argv[5][i] == '\0')
901 break;
902 os_snprintf(&key_hex[i * 2], 3, "%02x",
903 argv[5][i]);
904 }
905 }
907 res = os_snprintf(cmd, sizeof(cmd),
908 "WPS_ER_CONFIG %s %s %s %s %s %s",
909 argv[0], argv[1], ssid_hex, argv[3], argv[4],
910 key_hex);
911 } else {
912 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
913 "- AP UUID\n"
914 "- AP PIN\n"
915 "- new SSID\n"
916 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
917 "- new encr (NONE, WEP, TKIP, CCMP)\n"
918 "- new key\n");
919 return -1;
920 }
922 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
923 printf("Too long WPS_ER_CONFIG command.\n");
924 return -1;
925 }
926 return wpa_ctrl_command(ctrl, cmd);
927 }
930 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
931 {
932 char cmd[256];
933 int res;
935 if (argc != 1) {
936 printf("Invalid IBSS_RSN command: needs one argument "
937 "(Peer STA MAC address)\n");
938 return -1;
939 }
941 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
942 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
943 printf("Too long IBSS_RSN command.\n");
944 return -1;
945 }
946 return wpa_ctrl_command(ctrl, cmd);
947 }
950 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
951 {
952 char cmd[256];
953 int res;
955 if (argc != 1) {
956 printf("Invalid LEVEL command: needs one argument (debug "
957 "level)\n");
958 return -1;
959 }
960 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
961 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
962 printf("Too long LEVEL command.\n");
963 return -1;
964 }
965 return wpa_ctrl_command(ctrl, cmd);
966 }
969 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
970 {
971 char cmd[256], *pos, *end;
972 int i, ret;
974 if (argc < 2) {
975 printf("Invalid IDENTITY command: needs two arguments "
976 "(network id and identity)\n");
977 return -1;
978 }
980 end = cmd + sizeof(cmd);
981 pos = cmd;
982 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
983 argv[0], argv[1]);
984 if (ret < 0 || ret >= end - pos) {
985 printf("Too long IDENTITY command.\n");
986 return -1;
987 }
988 pos += ret;
989 for (i = 2; i < argc; i++) {
990 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
991 if (ret < 0 || ret >= end - pos) {
992 printf("Too long IDENTITY command.\n");
993 return -1;
994 }
995 pos += ret;
996 }
998 return wpa_ctrl_command(ctrl, cmd);
999 }
1002 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1003 {
1004 char cmd[256], *pos, *end;
1005 int i, ret;
1007 if (argc < 2) {
1008 printf("Invalid PASSWORD command: needs two arguments "
1009 "(network id and password)\n");
1010 return -1;
1011 }
1013 end = cmd + sizeof(cmd);
1014 pos = cmd;
1015 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1016 argv[0], argv[1]);
1017 if (ret < 0 || ret >= end - pos) {
1018 printf("Too long PASSWORD command.\n");
1019 return -1;
1020 }
1021 pos += ret;
1022 for (i = 2; i < argc; i++) {
1023 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1024 if (ret < 0 || ret >= end - pos) {
1025 printf("Too long PASSWORD command.\n");
1026 return -1;
1027 }
1028 pos += ret;
1029 }
1031 return wpa_ctrl_command(ctrl, cmd);
1032 }
1035 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1036 char *argv[])
1037 {
1038 char cmd[256], *pos, *end;
1039 int i, ret;
1041 if (argc < 2) {
1042 printf("Invalid NEW_PASSWORD command: needs two arguments "
1043 "(network id and password)\n");
1044 return -1;
1045 }
1047 end = cmd + sizeof(cmd);
1048 pos = cmd;
1049 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1050 argv[0], argv[1]);
1051 if (ret < 0 || ret >= end - pos) {
1052 printf("Too long NEW_PASSWORD command.\n");
1053 return -1;
1054 }
1055 pos += ret;
1056 for (i = 2; i < argc; i++) {
1057 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1058 if (ret < 0 || ret >= end - pos) {
1059 printf("Too long NEW_PASSWORD command.\n");
1060 return -1;
1061 }
1062 pos += ret;
1063 }
1065 return wpa_ctrl_command(ctrl, cmd);
1066 }
1069 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1070 {
1071 char cmd[256], *pos, *end;
1072 int i, ret;
1074 if (argc < 2) {
1075 printf("Invalid PIN command: needs two arguments "
1076 "(network id and pin)\n");
1077 return -1;
1078 }
1080 end = cmd + sizeof(cmd);
1081 pos = cmd;
1082 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1083 argv[0], argv[1]);
1084 if (ret < 0 || ret >= end - pos) {
1085 printf("Too long PIN command.\n");
1086 return -1;
1087 }
1088 pos += ret;
1089 for (i = 2; i < argc; i++) {
1090 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1091 if (ret < 0 || ret >= end - pos) {
1092 printf("Too long PIN command.\n");
1093 return -1;
1094 }
1095 pos += ret;
1096 }
1097 return wpa_ctrl_command(ctrl, cmd);
1098 }
1101 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1102 {
1103 char cmd[256], *pos, *end;
1104 int i, ret;
1106 if (argc < 2) {
1107 printf("Invalid OTP command: needs two arguments (network "
1108 "id and password)\n");
1109 return -1;
1110 }
1112 end = cmd + sizeof(cmd);
1113 pos = cmd;
1114 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1115 argv[0], argv[1]);
1116 if (ret < 0 || ret >= end - pos) {
1117 printf("Too long OTP command.\n");
1118 return -1;
1119 }
1120 pos += ret;
1121 for (i = 2; i < argc; i++) {
1122 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1123 if (ret < 0 || ret >= end - pos) {
1124 printf("Too long OTP command.\n");
1125 return -1;
1126 }
1127 pos += ret;
1128 }
1130 return wpa_ctrl_command(ctrl, cmd);
1131 }
1134 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1135 char *argv[])
1136 {
1137 char cmd[256], *pos, *end;
1138 int i, ret;
1140 if (argc < 2) {
1141 printf("Invalid PASSPHRASE command: needs two arguments "
1142 "(network id and passphrase)\n");
1143 return -1;
1144 }
1146 end = cmd + sizeof(cmd);
1147 pos = cmd;
1148 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1149 argv[0], argv[1]);
1150 if (ret < 0 || ret >= end - pos) {
1151 printf("Too long PASSPHRASE command.\n");
1152 return -1;
1153 }
1154 pos += ret;
1155 for (i = 2; i < argc; i++) {
1156 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1157 if (ret < 0 || ret >= end - pos) {
1158 printf("Too long PASSPHRASE command.\n");
1159 return -1;
1160 }
1161 pos += ret;
1162 }
1164 return wpa_ctrl_command(ctrl, cmd);
1165 }
1168 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1169 {
1170 char cmd[256], *pos, *end;
1171 int i, ret;
1173 if (argc < 2) {
1174 printf("Invalid BSSID command: needs two arguments (network "
1175 "id and BSSID)\n");
1176 return -1;
1177 }
1179 end = cmd + sizeof(cmd);
1180 pos = cmd;
1181 ret = os_snprintf(pos, end - pos, "BSSID");
1182 if (ret < 0 || ret >= end - pos) {
1183 printf("Too long BSSID command.\n");
1184 return -1;
1185 }
1186 pos += ret;
1187 for (i = 0; i < argc; i++) {
1188 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1189 if (ret < 0 || ret >= end - pos) {
1190 printf("Too long BSSID command.\n");
1191 return -1;
1192 }
1193 pos += ret;
1194 }
1196 return wpa_ctrl_command(ctrl, cmd);
1197 }
1200 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1201 char *argv[])
1202 {
1203 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1204 }
1207 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1208 char *argv[])
1209 {
1210 char cmd[32];
1211 int res;
1213 if (argc < 1) {
1214 printf("Invalid SELECT_NETWORK command: needs one argument "
1215 "(network id)\n");
1216 return -1;
1217 }
1219 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1220 if (res < 0 || (size_t) res >= sizeof(cmd))
1221 return -1;
1222 cmd[sizeof(cmd) - 1] = '\0';
1224 return wpa_ctrl_command(ctrl, cmd);
1225 }
1228 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1229 char *argv[])
1230 {
1231 char cmd[32];
1232 int res;
1234 if (argc < 1) {
1235 printf("Invalid ENABLE_NETWORK command: needs one argument "
1236 "(network id)\n");
1237 return -1;
1238 }
1240 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1241 if (res < 0 || (size_t) res >= sizeof(cmd))
1242 return -1;
1243 cmd[sizeof(cmd) - 1] = '\0';
1245 return wpa_ctrl_command(ctrl, cmd);
1246 }
1249 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1250 char *argv[])
1251 {
1252 char cmd[32];
1253 int res;
1255 if (argc < 1) {
1256 printf("Invalid DISABLE_NETWORK command: needs one argument "
1257 "(network id)\n");
1258 return -1;
1259 }
1261 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1262 if (res < 0 || (size_t) res >= sizeof(cmd))
1263 return -1;
1264 cmd[sizeof(cmd) - 1] = '\0';
1266 return wpa_ctrl_command(ctrl, cmd);
1267 }
1270 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1271 char *argv[])
1272 {
1273 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1274 }
1277 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1278 char *argv[])
1279 {
1280 char cmd[32];
1281 int res;
1283 if (argc < 1) {
1284 printf("Invalid REMOVE_NETWORK command: needs one argument "
1285 "(network id)\n");
1286 return -1;
1287 }
1289 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1290 if (res < 0 || (size_t) res >= sizeof(cmd))
1291 return -1;
1292 cmd[sizeof(cmd) - 1] = '\0';
1294 return wpa_ctrl_command(ctrl, cmd);
1295 }
1298 static void wpa_cli_show_network_variables(void)
1299 {
1300 printf("set_network variables:\n"
1301 " ssid (network name, SSID)\n"
1302 " psk (WPA passphrase or pre-shared key)\n"
1303 " key_mgmt (key management protocol)\n"
1304 " identity (EAP identity)\n"
1305 " password (EAP password)\n"
1306 " ...\n"
1307 "\n"
1308 "Note: Values are entered in the same format as the "
1309 "configuration file is using,\n"
1310 "i.e., strings values need to be inside double quotation "
1311 "marks.\n"
1312 "For example: set_network 1 ssid \"network name\"\n"
1313 "\n"
1314 "Please see wpa_supplicant.conf documentation for full list "
1315 "of\navailable variables.\n");
1316 }
1319 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1320 char *argv[])
1321 {
1322 char cmd[256];
1323 int res;
1325 if (argc == 0) {
1326 wpa_cli_show_network_variables();
1327 return 0;
1328 }
1330 if (argc != 3) {
1331 printf("Invalid SET_NETWORK command: needs three arguments\n"
1332 "(network id, variable name, and value)\n");
1333 return -1;
1334 }
1336 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1337 argv[0], argv[1], argv[2]);
1338 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1339 printf("Too long SET_NETWORK command.\n");
1340 return -1;
1341 }
1342 return wpa_ctrl_command(ctrl, cmd);
1343 }
1346 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1347 char *argv[])
1348 {
1349 char cmd[256];
1350 int res;
1352 if (argc == 0) {
1353 wpa_cli_show_network_variables();
1354 return 0;
1355 }
1357 if (argc != 2) {
1358 printf("Invalid GET_NETWORK command: needs two arguments\n"
1359 "(network id and variable name)\n");
1360 return -1;
1361 }
1363 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1364 argv[0], argv[1]);
1365 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1366 printf("Too long GET_NETWORK command.\n");
1367 return -1;
1368 }
1369 return wpa_ctrl_command(ctrl, cmd);
1370 }
1373 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1374 char *argv[])
1375 {
1376 return wpa_ctrl_command(ctrl, "DISCONNECT");
1377 }
1380 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1381 char *argv[])
1382 {
1383 return wpa_ctrl_command(ctrl, "RECONNECT");
1384 }
1387 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1388 char *argv[])
1389 {
1390 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1391 }
1394 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1395 {
1396 return wpa_ctrl_command(ctrl, "SCAN");
1397 }
1400 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1401 char *argv[])
1402 {
1403 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1404 }
1407 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1408 {
1409 char cmd[64];
1410 int res;
1412 if (argc != 1) {
1413 printf("Invalid BSS command: need one argument (index or "
1414 "BSSID)\n");
1415 return -1;
1416 }
1418 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1419 if (res < 0 || (size_t) res >= sizeof(cmd))
1420 return -1;
1421 cmd[sizeof(cmd) - 1] = '\0';
1423 return wpa_ctrl_command(ctrl, cmd);
1424 }
1427 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1428 char *argv[])
1429 {
1430 char cmd[64];
1431 int res;
1433 if (argc < 1 || argc > 2) {
1434 printf("Invalid GET_CAPABILITY command: need either one or "
1435 "two arguments\n");
1436 return -1;
1437 }
1439 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1440 printf("Invalid GET_CAPABILITY command: second argument, "
1441 "if any, must be 'strict'\n");
1442 return -1;
1443 }
1445 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1446 (argc == 2) ? " strict" : "");
1447 if (res < 0 || (size_t) res >= sizeof(cmd))
1448 return -1;
1449 cmd[sizeof(cmd) - 1] = '\0';
1451 return wpa_ctrl_command(ctrl, cmd);
1452 }
1455 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1456 {
1457 printf("Available interfaces:\n");
1458 return wpa_ctrl_command(ctrl, "INTERFACES");
1459 }
1462 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1463 {
1464 if (argc < 1) {
1465 wpa_cli_list_interfaces(ctrl);
1466 return 0;
1467 }
1469 wpa_cli_close_connection();
1470 os_free(ctrl_ifname);
1471 ctrl_ifname = os_strdup(argv[0]);
1473 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1474 printf("Connected to interface '%s.\n", ctrl_ifname);
1475 } else {
1476 printf("Could not connect to interface '%s' - re-trying\n",
1477 ctrl_ifname);
1478 }
1479 return 0;
1480 }
1483 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1484 char *argv[])
1485 {
1486 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1487 }
1490 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1491 char *argv[])
1492 {
1493 return wpa_ctrl_command(ctrl, "TERMINATE");
1494 }
1497 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1498 char *argv[])
1499 {
1500 char cmd[256];
1501 int res;
1503 if (argc < 1) {
1504 printf("Invalid INTERFACE_ADD command: needs at least one "
1505 "argument (interface name)\n"
1506 "All arguments: ifname confname driver ctrl_interface "
1507 "driver_param bridge_name\n");
1508 return -1;
1509 }
1511 /*
1512 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1513 * <driver_param>TAB<bridge_name>
1514 */
1515 res = os_snprintf(cmd, sizeof(cmd),
1516 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1517 argv[0],
1518 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1519 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1520 argc > 5 ? argv[5] : "");
1521 if (res < 0 || (size_t) res >= sizeof(cmd))
1522 return -1;
1523 cmd[sizeof(cmd) - 1] = '\0';
1524 return wpa_ctrl_command(ctrl, cmd);
1525 }
1528 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1529 char *argv[])
1530 {
1531 char cmd[128];
1532 int res;
1534 if (argc != 1) {
1535 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1536 "(interface name)\n");
1537 return -1;
1538 }
1540 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1541 if (res < 0 || (size_t) res >= sizeof(cmd))
1542 return -1;
1543 cmd[sizeof(cmd) - 1] = '\0';
1544 return wpa_ctrl_command(ctrl, cmd);
1545 }
1548 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1549 char *argv[])
1550 {
1551 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1552 }
1555 #ifdef CONFIG_AP
1556 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1557 {
1558 char buf[64];
1559 if (argc != 1) {
1560 printf("Invalid 'sta' command - exactly one argument, STA "
1561 "address, is required.\n");
1562 return -1;
1563 }
1564 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1565 return wpa_ctrl_command(ctrl, buf);
1566 }
1569 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1570 char *addr, size_t addr_len)
1571 {
1572 char buf[4096], *pos;
1573 size_t len;
1574 int ret;
1576 if (ctrl_conn == NULL) {
1577 printf("Not connected to hostapd - command dropped.\n");
1578 return -1;
1579 }
1580 len = sizeof(buf) - 1;
1581 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1582 wpa_cli_msg_cb);
1583 if (ret == -2) {
1584 printf("'%s' command timed out.\n", cmd);
1585 return -2;
1586 } else if (ret < 0) {
1587 printf("'%s' command failed.\n", cmd);
1588 return -1;
1589 }
1591 buf[len] = '\0';
1592 if (memcmp(buf, "FAIL", 4) == 0)
1593 return -1;
1594 printf("%s", buf);
1596 pos = buf;
1597 while (*pos != '\0' && *pos != '\n')
1598 pos++;
1599 *pos = '\0';
1600 os_strlcpy(addr, buf, addr_len);
1601 return 0;
1602 }
1605 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1606 {
1607 char addr[32], cmd[64];
1609 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1610 return 0;
1611 do {
1612 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1613 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1615 return -1;
1616 }
1617 #endif /* CONFIG_AP */
1620 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1621 {
1622 return wpa_ctrl_command(ctrl, "SUSPEND");
1623 }
1626 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1627 {
1628 return wpa_ctrl_command(ctrl, "RESUME");
1629 }
1632 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1633 {
1634 return wpa_ctrl_command(ctrl, "DROP_SA");
1635 }
1638 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1639 {
1640 char cmd[128];
1641 int res;
1643 if (argc != 1) {
1644 printf("Invalid ROAM command: needs one argument "
1645 "(target AP's BSSID)\n");
1646 return -1;
1647 }
1649 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1650 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1651 printf("Too long ROAM command.\n");
1652 return -1;
1653 }
1654 return wpa_ctrl_command(ctrl, cmd);
1655 }
1658 #ifdef CONFIG_P2P
1660 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1661 {
1662 char cmd[128];
1663 int res;
1665 if (argc == 0)
1666 return wpa_ctrl_command(ctrl, "P2P_FIND");
1668 if (argc > 1)
1669 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1670 argv[0], argv[1]);
1671 else
1672 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1673 if (res < 0 || (size_t) res >= sizeof(cmd))
1674 return -1;
1675 cmd[sizeof(cmd) - 1] = '\0';
1676 return wpa_ctrl_command(ctrl, cmd);
1677 }
1680 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1681 char *argv[])
1682 {
1683 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1684 }
1687 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1688 char *argv[])
1689 {
1690 char cmd[128];
1691 int res;
1693 if (argc < 2) {
1694 printf("Invalid P2P_CONNECT command: needs at least two "
1695 "arguments (address and pbc/PIN)\n");
1696 return -1;
1697 }
1699 if (argc > 4)
1700 res = os_snprintf(cmd, sizeof(cmd),
1701 "P2P_CONNECT %s %s %s %s %s",
1702 argv[0], argv[1], argv[2], argv[3],
1703 argv[4]);
1704 else if (argc > 3)
1705 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1706 argv[0], argv[1], argv[2], argv[3]);
1707 else if (argc > 2)
1708 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1709 argv[0], argv[1], argv[2]);
1710 else
1711 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1712 argv[0], argv[1]);
1713 if (res < 0 || (size_t) res >= sizeof(cmd))
1714 return -1;
1715 cmd[sizeof(cmd) - 1] = '\0';
1716 return wpa_ctrl_command(ctrl, cmd);
1717 }
1720 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1721 char *argv[])
1722 {
1723 char cmd[128];
1724 int res;
1726 if (argc == 0)
1727 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1729 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
1730 if (res < 0 || (size_t) res >= sizeof(cmd))
1731 return -1;
1732 cmd[sizeof(cmd) - 1] = '\0';
1733 return wpa_ctrl_command(ctrl, cmd);
1734 }
1737 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1738 char *argv[])
1739 {
1740 char cmd[128];
1741 int res;
1743 if (argc != 1) {
1744 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1745 "(interface name)\n");
1746 return -1;
1747 }
1749 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1750 if (res < 0 || (size_t) res >= sizeof(cmd))
1751 return -1;
1752 cmd[sizeof(cmd) - 1] = '\0';
1753 return wpa_ctrl_command(ctrl, cmd);
1754 }
1757 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1758 char *argv[])
1759 {
1760 char cmd[128];
1761 int res;
1763 if (argc == 0)
1764 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1766 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]);
1767 if (res < 0 || (size_t) res >= sizeof(cmd))
1768 return -1;
1769 cmd[sizeof(cmd) - 1] = '\0';
1770 return wpa_ctrl_command(ctrl, cmd);
1771 }
1774 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1775 char *argv[])
1776 {
1777 char cmd[128];
1778 int res;
1780 if (argc != 2) {
1781 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1782 "(address and config method\n"
1783 "(display, keypad, or pbc)\n");
1784 return -1;
1785 }
1787 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1788 argv[0], argv[1]);
1789 if (res < 0 || (size_t) res >= sizeof(cmd))
1790 return -1;
1791 cmd[sizeof(cmd) - 1] = '\0';
1792 return wpa_ctrl_command(ctrl, cmd);
1793 }
1796 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1797 char *argv[])
1798 {
1799 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1800 }
1803 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1804 char *argv[])
1805 {
1806 char cmd[4096];
1807 int res;
1809 if (argc != 2 && argc != 4) {
1810 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1811 "arguments (address and TLVs) or four arguments "
1812 "(address, \"upnp\", version, search target "
1813 "(SSDP ST:)\n");
1814 return -1;
1815 }
1817 if (argc == 4)
1818 res = os_snprintf(cmd, sizeof(cmd),
1819 "P2P_SERV_DISC_REQ %s %s %s %s",
1820 argv[0], argv[1], argv[2], argv[3]);
1821 else
1822 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1823 argv[0], argv[1]);
1824 if (res < 0 || (size_t) res >= sizeof(cmd))
1825 return -1;
1826 cmd[sizeof(cmd) - 1] = '\0';
1827 return wpa_ctrl_command(ctrl, cmd);
1828 }
1831 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1832 int argc, char *argv[])
1833 {
1834 char cmd[128];
1835 int res;
1837 if (argc != 1) {
1838 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1839 "argument (pending request identifier)\n");
1840 return -1;
1841 }
1843 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1844 argv[0]);
1845 if (res < 0 || (size_t) res >= sizeof(cmd))
1846 return -1;
1847 cmd[sizeof(cmd) - 1] = '\0';
1848 return wpa_ctrl_command(ctrl, cmd);
1849 }
1852 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1853 char *argv[])
1854 {
1855 char cmd[4096];
1856 int res;
1858 if (argc != 4) {
1859 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1860 "arguments (freq, address, dialog token, and TLVs)\n");
1861 return -1;
1862 }
1864 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1865 argv[0], argv[1], argv[2], argv[3]);
1866 if (res < 0 || (size_t) res >= sizeof(cmd))
1867 return -1;
1868 cmd[sizeof(cmd) - 1] = '\0';
1869 return wpa_ctrl_command(ctrl, cmd);
1870 }
1873 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1874 char *argv[])
1875 {
1876 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1877 }
1880 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1881 int argc, char *argv[])
1882 {
1883 char cmd[128];
1884 int res;
1886 if (argc != 1) {
1887 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1888 "argument (external processing: 0/1)\n");
1889 return -1;
1890 }
1892 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1893 argv[0]);
1894 if (res < 0 || (size_t) res >= sizeof(cmd))
1895 return -1;
1896 cmd[sizeof(cmd) - 1] = '\0';
1897 return wpa_ctrl_command(ctrl, cmd);
1898 }
1901 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1902 char *argv[])
1903 {
1904 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1905 }
1908 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1909 char *argv[])
1910 {
1911 char cmd[4096];
1912 int res;
1914 if (argc != 3 && argc != 4) {
1915 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1916 "arguments\n");
1917 return -1;
1918 }
1920 if (argc == 4)
1921 res = os_snprintf(cmd, sizeof(cmd),
1922 "P2P_SERVICE_ADD %s %s %s %s",
1923 argv[0], argv[1], argv[2], argv[3]);
1924 else
1925 res = os_snprintf(cmd, sizeof(cmd),
1926 "P2P_SERVICE_ADD %s %s %s",
1927 argv[0], argv[1], argv[2]);
1928 if (res < 0 || (size_t) res >= sizeof(cmd))
1929 return -1;
1930 cmd[sizeof(cmd) - 1] = '\0';
1931 return wpa_ctrl_command(ctrl, cmd);
1932 }
1935 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1936 char *argv[])
1937 {
1938 char cmd[4096];
1939 int res;
1941 if (argc != 2 && argc != 3) {
1942 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1943 "arguments\n");
1944 return -1;
1945 }
1947 if (argc == 3)
1948 res = os_snprintf(cmd, sizeof(cmd),
1949 "P2P_SERVICE_DEL %s %s %s",
1950 argv[0], argv[1], argv[2]);
1951 else
1952 res = os_snprintf(cmd, sizeof(cmd),
1953 "P2P_SERVICE_DEL %s %s",
1954 argv[0], argv[1]);
1955 if (res < 0 || (size_t) res >= sizeof(cmd))
1956 return -1;
1957 cmd[sizeof(cmd) - 1] = '\0';
1958 return wpa_ctrl_command(ctrl, cmd);
1959 }
1962 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1963 int argc, char *argv[])
1964 {
1965 char cmd[128];
1966 int res;
1968 if (argc != 1) {
1969 printf("Invalid P2P_REJECT command: needs one argument "
1970 "(peer address)\n");
1971 return -1;
1972 }
1974 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
1975 if (res < 0 || (size_t) res >= sizeof(cmd))
1976 return -1;
1977 cmd[sizeof(cmd) - 1] = '\0';
1978 return wpa_ctrl_command(ctrl, cmd);
1979 }
1982 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1983 int argc, char *argv[])
1984 {
1985 char cmd[128];
1986 int res;
1988 if (argc < 1) {
1989 printf("Invalid P2P_INVITE command: needs at least one "
1990 "argument\n");
1991 return -1;
1992 }
1994 if (argc > 2)
1995 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
1996 argv[0], argv[1], argv[2]);
1997 else if (argc > 1)
1998 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
1999 argv[0], argv[1]);
2000 else
2001 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
2002 if (res < 0 || (size_t) res >= sizeof(cmd))
2003 return -1;
2004 cmd[sizeof(cmd) - 1] = '\0';
2005 return wpa_ctrl_command(ctrl, cmd);
2006 }
2009 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2010 {
2011 char buf[64];
2012 if (argc != 1) {
2013 printf("Invalid 'p2p_peer' command - exactly one argument, "
2014 "P2P peer device address, is required.\n");
2015 return -1;
2016 }
2017 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
2018 return wpa_ctrl_command(ctrl, buf);
2019 }
2022 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2023 char *addr, size_t addr_len,
2024 int discovered)
2025 {
2026 char buf[4096], *pos;
2027 size_t len;
2028 int ret;
2030 if (ctrl_conn == NULL)
2031 return -1;
2032 len = sizeof(buf) - 1;
2033 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
2034 wpa_cli_msg_cb);
2035 if (ret == -2) {
2036 printf("'%s' command timed out.\n", cmd);
2037 return -2;
2038 } else if (ret < 0) {
2039 printf("'%s' command failed.\n", cmd);
2040 return -1;
2041 }
2043 buf[len] = '\0';
2044 if (memcmp(buf, "FAIL", 4) == 0)
2045 return -1;
2047 pos = buf;
2048 while (*pos != '\0' && *pos != '\n')
2049 pos++;
2050 *pos++ = '\0';
2051 os_strlcpy(addr, buf, addr_len);
2052 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2053 printf("%s\n", addr);
2054 return 0;
2055 }
2058 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2059 {
2060 char addr[32], cmd[64];
2061 int discovered;
2063 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2065 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2066 addr, sizeof(addr), discovered))
2067 return 0;
2068 do {
2069 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2070 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2071 discovered) == 0);
2073 return -1;
2074 }
2077 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2078 {
2079 char cmd[100];
2080 int res;
2082 if (argc != 2) {
2083 printf("Invalid P2P_SET command: needs two arguments (field, "
2084 "value)\n");
2085 return -1;
2086 }
2088 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2089 if (res < 0 || (size_t) res >= sizeof(cmd))
2090 return -1;
2091 cmd[sizeof(cmd) - 1] = '\0';
2092 return wpa_ctrl_command(ctrl, cmd);
2093 }
2096 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2097 {
2098 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2099 }
2102 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2103 char *argv[])
2104 {
2105 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2106 }
2109 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2110 char *argv[])
2111 {
2112 char cmd[100];
2113 int res;
2115 if (argc != 0 && argc != 2 && argc != 4) {
2116 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2117 "(preferred duration, interval; in microsecods).\n"
2118 "Optional second pair can be used to provide "
2119 "acceptable values.\n");
2120 return -1;
2121 }
2123 if (argc == 4)
2124 res = os_snprintf(cmd, sizeof(cmd),
2125 "P2P_PRESENCE_REQ %s %s %s %s",
2126 argv[0], argv[1], argv[2], argv[3]);
2127 else if (argc == 2)
2128 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2129 argv[0], argv[1]);
2130 else
2131 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2132 if (res < 0 || (size_t) res >= sizeof(cmd))
2133 return -1;
2134 cmd[sizeof(cmd) - 1] = '\0';
2135 return wpa_ctrl_command(ctrl, cmd);
2136 }
2139 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2140 char *argv[])
2141 {
2142 char cmd[100];
2143 int res;
2145 if (argc != 0 && argc != 2) {
2146 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2147 "(availability period, availability interval; in "
2148 "millisecods).\n"
2149 "Extended Listen Timing can be cancelled with this "
2150 "command when used without parameters.\n");
2151 return -1;
2152 }
2154 if (argc == 2)
2155 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2156 argv[0], argv[1]);
2157 else
2158 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2159 if (res < 0 || (size_t) res >= sizeof(cmd))
2160 return -1;
2161 cmd[sizeof(cmd) - 1] = '\0';
2162 return wpa_ctrl_command(ctrl, cmd);
2163 }
2165 #endif /* CONFIG_P2P */
2168 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2169 char *argv[])
2170 {
2171 char cmd[256];
2172 int res;
2174 if (argc != 1) {
2175 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2176 "(0/1 = disable/enable automatic reconnection)\n");
2177 return -1;
2178 }
2179 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2180 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2181 printf("Too long STA_AUTOCONNECT command.\n");
2182 return -1;
2183 }
2184 return wpa_ctrl_command(ctrl, cmd);
2185 }
2188 enum wpa_cli_cmd_flags {
2189 cli_cmd_flag_none = 0x00,
2190 cli_cmd_flag_sensitive = 0x01
2191 };
2193 struct wpa_cli_cmd {
2194 const char *cmd;
2195 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2196 enum wpa_cli_cmd_flags flags;
2197 const char *usage;
2198 };
2200 static struct wpa_cli_cmd wpa_cli_commands[] = {
2201 { "status", wpa_cli_cmd_status,
2202 cli_cmd_flag_none,
2203 "[verbose] = get current WPA/EAPOL/EAP status" },
2204 { "ping", wpa_cli_cmd_ping,
2205 cli_cmd_flag_none,
2206 "= pings wpa_supplicant" },
2207 { "note", wpa_cli_cmd_note,
2208 cli_cmd_flag_none,
2209 "<text> = add a note to wpa_supplicant debug log" },
2210 { "mib", wpa_cli_cmd_mib,
2211 cli_cmd_flag_none,
2212 "= get MIB variables (dot1x, dot11)" },
2213 { "help", wpa_cli_cmd_help,
2214 cli_cmd_flag_none,
2215 "= show this usage help" },
2216 { "interface", wpa_cli_cmd_interface,
2217 cli_cmd_flag_none,
2218 "[ifname] = show interfaces/select interface" },
2219 { "level", wpa_cli_cmd_level,
2220 cli_cmd_flag_none,
2221 "<debug level> = change debug level" },
2222 { "license", wpa_cli_cmd_license,
2223 cli_cmd_flag_none,
2224 "= show full wpa_cli license" },
2225 { "quit", wpa_cli_cmd_quit,
2226 cli_cmd_flag_none,
2227 "= exit wpa_cli" },
2228 { "set", wpa_cli_cmd_set,
2229 cli_cmd_flag_none,
2230 "= set variables (shows list of variables when run without "
2231 "arguments)" },
2232 { "get", wpa_cli_cmd_get,
2233 cli_cmd_flag_none,
2234 "<name> = get information" },
2235 { "logon", wpa_cli_cmd_logon,
2236 cli_cmd_flag_none,
2237 "= IEEE 802.1X EAPOL state machine logon" },
2238 { "logoff", wpa_cli_cmd_logoff,
2239 cli_cmd_flag_none,
2240 "= IEEE 802.1X EAPOL state machine logoff" },
2241 { "pmksa", wpa_cli_cmd_pmksa,
2242 cli_cmd_flag_none,
2243 "= show PMKSA cache" },
2244 { "reassociate", wpa_cli_cmd_reassociate,
2245 cli_cmd_flag_none,
2246 "= force reassociation" },
2247 { "preauthenticate", wpa_cli_cmd_preauthenticate,
2248 cli_cmd_flag_none,
2249 "<BSSID> = force preauthentication" },
2250 { "identity", wpa_cli_cmd_identity,
2251 cli_cmd_flag_none,
2252 "<network id> <identity> = configure identity for an SSID" },
2253 { "password", wpa_cli_cmd_password,
2254 cli_cmd_flag_sensitive,
2255 "<network id> <password> = configure password for an SSID" },
2256 { "new_password", wpa_cli_cmd_new_password,
2257 cli_cmd_flag_sensitive,
2258 "<network id> <password> = change password for an SSID" },
2259 { "pin", wpa_cli_cmd_pin,
2260 cli_cmd_flag_sensitive,
2261 "<network id> <pin> = configure pin for an SSID" },
2262 { "otp", wpa_cli_cmd_otp,
2263 cli_cmd_flag_sensitive,
2264 "<network id> <password> = configure one-time-password for an SSID"
2265 },
2266 { "passphrase", wpa_cli_cmd_passphrase,
2267 cli_cmd_flag_sensitive,
2268 "<network id> <passphrase> = configure private key passphrase\n"
2269 " for an SSID" },
2270 { "bssid", wpa_cli_cmd_bssid,
2271 cli_cmd_flag_none,
2272 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2273 { "list_networks", wpa_cli_cmd_list_networks,
2274 cli_cmd_flag_none,
2275 "= list configured networks" },
2276 { "select_network", wpa_cli_cmd_select_network,
2277 cli_cmd_flag_none,
2278 "<network id> = select a network (disable others)" },
2279 { "enable_network", wpa_cli_cmd_enable_network,
2280 cli_cmd_flag_none,
2281 "<network id> = enable a network" },
2282 { "disable_network", wpa_cli_cmd_disable_network,
2283 cli_cmd_flag_none,
2284 "<network id> = disable a network" },
2285 { "add_network", wpa_cli_cmd_add_network,
2286 cli_cmd_flag_none,
2287 "= add a network" },
2288 { "remove_network", wpa_cli_cmd_remove_network,
2289 cli_cmd_flag_none,
2290 "<network id> = remove a network" },
2291 { "set_network", wpa_cli_cmd_set_network,
2292 cli_cmd_flag_sensitive,
2293 "<network id> <variable> <value> = set network variables (shows\n"
2294 " list of variables when run without arguments)" },
2295 { "get_network", wpa_cli_cmd_get_network,
2296 cli_cmd_flag_none,
2297 "<network id> <variable> = get network variables" },
2298 { "save_config", wpa_cli_cmd_save_config,
2299 cli_cmd_flag_none,
2300 "= save the current configuration" },
2301 { "disconnect", wpa_cli_cmd_disconnect,
2302 cli_cmd_flag_none,
2303 "= disconnect and wait for reassociate/reconnect command before\n"
2304 " connecting" },
2305 { "reconnect", wpa_cli_cmd_reconnect,
2306 cli_cmd_flag_none,
2307 "= like reassociate, but only takes effect if already disconnected"
2308 },
2309 { "scan", wpa_cli_cmd_scan,
2310 cli_cmd_flag_none,
2311 "= request new BSS scan" },
2312 { "scan_results", wpa_cli_cmd_scan_results,
2313 cli_cmd_flag_none,
2314 "= get latest scan results" },
2315 { "bss", wpa_cli_cmd_bss,
2316 cli_cmd_flag_none,
2317 "<<idx> | <bssid>> = get detailed scan result info" },
2318 { "get_capability", wpa_cli_cmd_get_capability,
2319 cli_cmd_flag_none,
2320 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2321 { "reconfigure", wpa_cli_cmd_reconfigure,
2322 cli_cmd_flag_none,
2323 "= force wpa_supplicant to re-read its configuration file" },
2324 { "terminate", wpa_cli_cmd_terminate,
2325 cli_cmd_flag_none,
2326 "= terminate wpa_supplicant" },
2327 { "interface_add", wpa_cli_cmd_interface_add,
2328 cli_cmd_flag_none,
2329 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2330 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2331 " are optional" },
2332 { "interface_remove", wpa_cli_cmd_interface_remove,
2333 cli_cmd_flag_none,
2334 "<ifname> = removes the interface" },
2335 { "interface_list", wpa_cli_cmd_interface_list,
2336 cli_cmd_flag_none,
2337 "= list available interfaces" },
2338 { "ap_scan", wpa_cli_cmd_ap_scan,
2339 cli_cmd_flag_none,
2340 "<value> = set ap_scan parameter" },
2341 { "stkstart", wpa_cli_cmd_stkstart,
2342 cli_cmd_flag_none,
2343 "<addr> = request STK negotiation with <addr>" },
2344 { "ft_ds", wpa_cli_cmd_ft_ds,
2345 cli_cmd_flag_none,
2346 "<addr> = request over-the-DS FT with <addr>" },
2347 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2348 cli_cmd_flag_none,
2349 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2350 { "wps_pin", wpa_cli_cmd_wps_pin,
2351 cli_cmd_flag_sensitive,
2352 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2353 "hardcoded)" },
2354 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2355 cli_cmd_flag_sensitive,
2356 "<PIN> = verify PIN checksum" },
2357 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2358 "Cancels the pending WPS operation" },
2359 #ifdef CONFIG_WPS_OOB
2360 { "wps_oob", wpa_cli_cmd_wps_oob,
2361 cli_cmd_flag_sensitive,
2362 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2363 #endif /* CONFIG_WPS_OOB */
2364 { "wps_reg", wpa_cli_cmd_wps_reg,
2365 cli_cmd_flag_sensitive,
2366 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2367 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2368 cli_cmd_flag_none,
2369 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2370 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2371 cli_cmd_flag_none,
2372 "= stop Wi-Fi Protected Setup External Registrar" },
2373 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2374 cli_cmd_flag_sensitive,
2375 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2376 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2377 cli_cmd_flag_none,
2378 "<UUID> = accept an Enrollee PBC using External Registrar" },
2379 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2380 cli_cmd_flag_sensitive,
2381 "<UUID> <PIN> = learn AP configuration" },
2382 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2383 cli_cmd_flag_none,
2384 "<UUID> <network id> = set AP configuration for enrolling" },
2385 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2386 cli_cmd_flag_sensitive,
2387 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2388 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2389 cli_cmd_flag_none,
2390 "<addr> = request RSN authentication with <addr> in IBSS" },
2391 #ifdef CONFIG_AP
2392 { "sta", wpa_cli_cmd_sta,
2393 cli_cmd_flag_none,
2394 "<addr> = get information about an associated station (AP)" },
2395 { "all_sta", wpa_cli_cmd_all_sta,
2396 cli_cmd_flag_none,
2397 "= get information about all associated stations (AP)" },
2398 #endif /* CONFIG_AP */
2399 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2400 "= notification of suspend/hibernate" },
2401 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2402 "= notification of resume/thaw" },
2403 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2404 "= drop SA without deauth/disassoc (test command)" },
2405 { "roam", wpa_cli_cmd_roam,
2406 cli_cmd_flag_none,
2407 "<addr> = roam to the specified BSS" },
2408 #ifdef CONFIG_P2P
2409 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2410 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2411 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2412 "= stop P2P Devices search" },
2413 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2414 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2415 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2416 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2417 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2418 "<ifname> = remote P2P group interface (terminate group if GO)" },
2419 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2420 "= add a new P2P group (local end as GO)" },
2421 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2422 "<addr> <method> = request provisioning discovery" },
2423 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2424 cli_cmd_flag_none,
2425 "= get the passphrase for a group (GO only)" },
2426 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2427 cli_cmd_flag_none,
2428 "<addr> <TLVs> = schedule service discovery request" },
2429 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2430 cli_cmd_flag_none,
2431 "<id> = cancel pending service discovery request" },
2432 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2433 cli_cmd_flag_none,
2434 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2435 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2436 cli_cmd_flag_none,
2437 "= indicate change in local services" },
2438 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2439 cli_cmd_flag_none,
2440 "<external> = set external processing of service discovery" },
2441 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2442 cli_cmd_flag_none,
2443 "= remove all stored service entries" },
2444 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2445 cli_cmd_flag_none,
2446 "<bonjour|upnp> <query|version> <response|service> = add a local "
2447 "service" },
2448 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2449 cli_cmd_flag_none,
2450 "<bonjour|upnp> <query|version> [|service] = remove a local "
2451 "service" },
2452 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2453 cli_cmd_flag_none,
2454 "<addr> = reject connection attempts from a specific peer" },
2455 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2456 cli_cmd_flag_none,
2457 "<cmd> [peer=addr] = invite peer" },
2458 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2459 "[discovered] = list known (optionally, only fully discovered) P2P "
2460 "peers" },
2461 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2462 "<address> = show information about known P2P peer" },
2463 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2464 "<field> <value> = set a P2P parameter" },
2465 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2466 "= flush P2P state" },
2467 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2468 "= cancel P2P group formation" },
2469 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2470 "[<duration> <interval>] [<duration> <interval>] = request GO "
2471 "presence" },
2472 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2473 "[<period> <interval>] = set extended listen timing" },
2474 #endif /* CONFIG_P2P */
2475 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2476 "<0/1> = disable/enable automatic reconnection" },
2477 { NULL, NULL, cli_cmd_flag_none, NULL }
2478 };
2481 /*
2482 * Prints command usage, lines are padded with the specified string.
2483 */
2484 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2485 {
2486 char c;
2487 size_t n;
2489 printf("%s%s ", pad, cmd->cmd);
2490 for (n = 0; (c = cmd->usage[n]); n++) {
2491 printf("%c", c);
2492 if (c == '\n')
2493 printf("%s", pad);
2494 }
2495 printf("\n");
2496 }
2499 static void print_help(void)
2500 {
2501 int n;
2502 printf("commands:\n");
2503 for (n = 0; wpa_cli_commands[n].cmd; n++)
2504 print_cmd_help(&wpa_cli_commands[n], " ");
2505 }
2508 #ifdef CONFIG_READLINE
2509 static int cmd_has_sensitive_data(const char *cmd)
2510 {
2511 const char *c, *delim;
2512 int n;
2513 size_t len;
2515 delim = os_strchr(cmd, ' ');
2516 if (delim)
2517 len = delim - cmd;
2518 else
2519 len = os_strlen(cmd);
2521 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2522 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2523 return (wpa_cli_commands[n].flags &
2524 cli_cmd_flag_sensitive);
2525 }
2526 return 0;
2527 }
2528 #endif /* CONFIG_READLINE */
2531 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2532 {
2533 struct wpa_cli_cmd *cmd, *match = NULL;
2534 int count;
2535 int ret = 0;
2537 count = 0;
2538 cmd = wpa_cli_commands;
2539 while (cmd->cmd) {
2540 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2541 {
2542 match = cmd;
2543 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2544 /* we have an exact match */
2545 count = 1;
2546 break;
2547 }
2548 count++;
2549 }
2550 cmd++;
2551 }
2553 if (count > 1) {
2554 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2555 cmd = wpa_cli_commands;
2556 while (cmd->cmd) {
2557 if (os_strncasecmp(cmd->cmd, argv[0],
2558 os_strlen(argv[0])) == 0) {
2559 printf(" %s", cmd->cmd);
2560 }
2561 cmd++;
2562 }
2563 printf("\n");
2564 ret = 1;
2565 } else if (count == 0) {
2566 printf("Unknown command '%s'\n", argv[0]);
2567 ret = 1;
2568 } else {
2569 ret = match->handler(ctrl, argc - 1, &argv[1]);
2570 }
2572 return ret;
2573 }
2576 static int str_match(const char *a, const char *b)
2577 {
2578 return os_strncmp(a, b, os_strlen(b)) == 0;
2579 }
2582 static int wpa_cli_exec(const char *program, const char *arg1,
2583 const char *arg2)
2584 {
2585 char *cmd;
2586 size_t len;
2587 int res;
2588 int ret = 0;
2590 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2591 cmd = os_malloc(len);
2592 if (cmd == NULL)
2593 return -1;
2594 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2595 if (res < 0 || (size_t) res >= len) {
2596 os_free(cmd);
2597 return -1;
2598 }
2599 cmd[len - 1] = '\0';
2600 #ifndef _WIN32_WCE
2601 if (system(cmd) < 0)
2602 ret = -1;
2603 #endif /* _WIN32_WCE */
2604 os_free(cmd);
2606 return ret;
2607 }
2610 static void wpa_cli_action_process(const char *msg)
2611 {
2612 const char *pos;
2613 char *copy = NULL, *id, *pos2;
2615 pos = msg;
2616 if (*pos == '<') {
2617 /* skip priority */
2618 pos = os_strchr(pos, '>');
2619 if (pos)
2620 pos++;
2621 else
2622 pos = msg;
2623 }
2625 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2626 int new_id = -1;
2627 os_unsetenv("WPA_ID");
2628 os_unsetenv("WPA_ID_STR");
2629 os_unsetenv("WPA_CTRL_DIR");
2631 pos = os_strstr(pos, "[id=");
2632 if (pos)
2633 copy = os_strdup(pos + 4);
2635 if (copy) {
2636 pos2 = id = copy;
2637 while (*pos2 && *pos2 != ' ')
2638 pos2++;
2639 *pos2++ = '\0';
2640 new_id = atoi(id);
2641 os_setenv("WPA_ID", id, 1);
2642 while (*pos2 && *pos2 != '=')
2643 pos2++;
2644 if (*pos2 == '=')
2645 pos2++;
2646 id = pos2;
2647 while (*pos2 && *pos2 != ']')
2648 pos2++;
2649 *pos2 = '\0';
2650 os_setenv("WPA_ID_STR", id, 1);
2651 os_free(copy);
2652 }
2654 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2656 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2657 wpa_cli_connected = 1;
2658 wpa_cli_last_id = new_id;
2659 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2660 }
2661 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2662 if (wpa_cli_connected) {
2663 wpa_cli_connected = 0;
2664 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2665 }
2666 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2667 wpa_cli_exec(action_file, ctrl_ifname, pos);
2668 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2669 wpa_cli_exec(action_file, ctrl_ifname, pos);
2670 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2671 wpa_cli_exec(action_file, ctrl_ifname, pos);
2672 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2673 wpa_cli_exec(action_file, ctrl_ifname, pos);
2674 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2675 wpa_cli_exec(action_file, ctrl_ifname, pos);
2676 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2677 wpa_cli_exec(action_file, ctrl_ifname, pos);
2678 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2679 printf("wpa_supplicant is terminating - stop monitoring\n");
2680 wpa_cli_quit = 1;
2681 }
2682 }
2685 #ifndef CONFIG_ANSI_C_EXTRA
2686 static void wpa_cli_action_cb(char *msg, size_t len)
2687 {
2688 wpa_cli_action_process(msg);
2689 }
2690 #endif /* CONFIG_ANSI_C_EXTRA */
2693 static void wpa_cli_reconnect(void)
2694 {
2695 wpa_cli_close_connection();
2696 wpa_cli_open_connection(ctrl_ifname, 1);
2697 }
2700 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
2701 int action_monitor)
2702 {
2703 int first = 1;
2704 if (ctrl_conn == NULL) {
2705 wpa_cli_reconnect();
2706 return;
2707 }
2708 while (wpa_ctrl_pending(ctrl) > 0) {
2709 char buf[256];
2710 size_t len = sizeof(buf) - 1;
2711 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2712 buf[len] = '\0';
2713 if (action_monitor)
2714 wpa_cli_action_process(buf);
2715 else {
2716 if (wpa_cli_show_event(buf)) {
2717 if (in_read && first)
2718 printf("\r");
2719 first = 0;
2720 printf("%s\n", buf);
2721 readline_redraw();
2722 }
2723 }
2724 } else {
2725 printf("Could not read pending message.\n");
2726 break;
2727 }
2728 }
2730 if (wpa_ctrl_pending(ctrl) < 0) {
2731 printf("Connection to wpa_supplicant lost - trying to "
2732 "reconnect\n");
2733 wpa_cli_reconnect();
2734 }
2735 }
2738 #ifdef CONFIG_READLINE
2739 static char * wpa_cli_cmd_gen(const char *text, int state)
2740 {
2741 static int i, len;
2742 const char *cmd;
2744 if (state == 0) {
2745 i = 0;
2746 len = os_strlen(text);
2747 }
2749 while ((cmd = wpa_cli_commands[i].cmd)) {
2750 i++;
2751 if (os_strncasecmp(cmd, text, len) == 0)
2752 return strdup(cmd);
2753 }
2755 return NULL;
2756 }
2759 static char * wpa_cli_dummy_gen(const char *text, int state)
2760 {
2761 int i;
2763 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2764 const char *cmd = wpa_cli_commands[i].cmd;
2765 size_t len = os_strlen(cmd);
2766 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
2767 rl_line_buffer[len] == ' ') {
2768 printf("\n%s\n", wpa_cli_commands[i].usage);
2769 readline_redraw();
2770 break;
2771 }
2772 }
2774 rl_attempted_completion_over = 1;
2775 return NULL;
2776 }
2779 static char * wpa_cli_status_gen(const char *text, int state)
2780 {
2781 static int i, len;
2782 char *options[] = {
2783 "verbose", NULL
2784 };
2785 char *t;
2787 if (state == 0) {
2788 i = 0;
2789 len = os_strlen(text);
2790 }
2792 while ((t = options[i])) {
2793 i++;
2794 if (os_strncasecmp(t, text, len) == 0)
2795 return strdup(t);
2796 }
2798 rl_attempted_completion_over = 1;
2799 return NULL;
2800 }
2803 static char ** wpa_cli_completion(const char *text, int start, int end)
2804 {
2805 char * (*func)(const char *text, int state);
2807 if (start == 0)
2808 func = wpa_cli_cmd_gen;
2809 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2810 func = wpa_cli_status_gen;
2811 else
2812 func = wpa_cli_dummy_gen;
2813 return rl_completion_matches(text, func);
2814 }
2815 #endif /* CONFIG_READLINE */
2818 static void wpa_cli_interactive(void)
2819 {
2820 #define max_args 10
2821 char cmdbuf[256], *cmd, *argv[max_args], *pos;
2822 int argc;
2823 #ifdef CONFIG_READLINE
2824 char *home, *hfile = NULL;
2825 #endif /* CONFIG_READLINE */
2827 printf("\nInteractive mode\n\n");
2829 #ifdef CONFIG_READLINE
2830 rl_attempted_completion_function = wpa_cli_completion;
2831 home = getenv("HOME");
2832 if (home) {
2833 const char *fname = ".wpa_cli_history";
2834 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2835 hfile = os_malloc(hfile_len);
2836 if (hfile) {
2837 int res;
2838 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2839 fname);
2840 if (res >= 0 && res < hfile_len) {
2841 hfile[hfile_len - 1] = '\0';
2842 read_history(hfile);
2843 stifle_history(100);
2844 }
2845 }
2846 }
2847 #endif /* CONFIG_READLINE */
2849 do {
2850 wpa_cli_recv_pending(mon_conn, 0, 0);
2851 #ifndef CONFIG_NATIVE_WINDOWS
2852 alarm(ping_interval);
2853 #endif /* CONFIG_NATIVE_WINDOWS */
2854 #ifdef CONFIG_WPA_CLI_FORK
2855 if (mon_pid)
2856 kill(mon_pid, SIGUSR1);
2857 #endif /* CONFIG_WPA_CLI_FORK */
2858 #ifdef CONFIG_READLINE
2859 cmd = readline("> ");
2860 if (cmd && *cmd) {
2861 HIST_ENTRY *h;
2862 while (next_history())
2863 ;
2864 h = previous_history();
2865 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2866 add_history(cmd);
2867 next_history();
2868 }
2869 #else /* CONFIG_READLINE */
2870 printf("> ");
2871 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2872 #endif /* CONFIG_READLINE */
2873 #ifndef CONFIG_NATIVE_WINDOWS
2874 alarm(0);
2875 #endif /* CONFIG_NATIVE_WINDOWS */
2876 if (cmd == NULL)
2877 break;
2878 wpa_cli_recv_pending(mon_conn, 0, 0);
2879 pos = cmd;
2880 while (*pos != '\0') {
2881 if (*pos == '\n') {
2882 *pos = '\0';
2883 break;
2884 }
2885 pos++;
2886 }
2887 argc = 0;
2888 pos = cmd;
2889 for (;;) {
2890 while (*pos == ' ')
2891 pos++;
2892 if (*pos == '\0')
2893 break;
2894 argv[argc] = pos;
2895 argc++;
2896 if (argc == max_args)
2897 break;
2898 if (*pos == '"') {
2899 char *pos2 = os_strrchr(pos, '"');
2900 if (pos2)
2901 pos = pos2 + 1;
2902 }
2903 while (*pos != '\0' && *pos != ' ')
2904 pos++;
2905 if (*pos == ' ')
2906 *pos++ = '\0';
2907 }
2908 if (argc)
2909 wpa_request(ctrl_conn, argc, argv);
2911 if (cmd != cmdbuf)
2912 free(cmd);
2913 #ifdef CONFIG_WPA_CLI_FORK
2914 if (mon_pid)
2915 kill(mon_pid, SIGUSR2);
2916 #endif /* CONFIG_WPA_CLI_FORK */
2917 } while (!wpa_cli_quit);
2919 #ifdef CONFIG_READLINE
2920 if (hfile) {
2921 /* Save command history, excluding lines that may contain
2922 * passwords. */
2923 HIST_ENTRY *h;
2924 history_set_pos(0);
2925 while ((h = current_history())) {
2926 char *p = h->line;
2927 while (*p == ' ' || *p == '\t')
2928 p++;
2929 if (cmd_has_sensitive_data(p)) {
2930 h = remove_history(where_history());
2931 if (h) {
2932 os_free(h->line);
2933 os_free(h->data);
2934 os_free(h);
2935 } else
2936 next_history();
2937 } else
2938 next_history();
2939 }
2940 write_history(hfile);
2941 os_free(hfile);
2942 }
2943 #endif /* CONFIG_READLINE */
2944 }
2947 static void wpa_cli_action(struct wpa_ctrl *ctrl)
2948 {
2949 #ifdef CONFIG_ANSI_C_EXTRA
2950 /* TODO: ANSI C version(?) */
2951 printf("Action processing not supported in ANSI C build.\n");
2952 #else /* CONFIG_ANSI_C_EXTRA */
2953 fd_set rfds;
2954 int fd, res;
2955 struct timeval tv;
2956 char buf[256]; /* note: large enough to fit in unsolicited messages */
2957 size_t len;
2959 fd = wpa_ctrl_get_fd(ctrl);
2961 while (!wpa_cli_quit) {
2962 FD_ZERO(&rfds);
2963 FD_SET(fd, &rfds);
2964 tv.tv_sec = ping_interval;
2965 tv.tv_usec = 0;
2966 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2967 if (res < 0 && errno != EINTR) {
2968 perror("select");
2969 break;
2970 }
2972 if (FD_ISSET(fd, &rfds))
2973 wpa_cli_recv_pending(ctrl, 0, 1);
2974 else {
2975 /* verify that connection is still working */
2976 len = sizeof(buf) - 1;
2977 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2978 wpa_cli_action_cb) < 0 ||
2979 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2980 printf("wpa_supplicant did not reply to PING "
2981 "command - exiting\n");
2982 break;
2983 }
2984 }
2985 }
2986 #endif /* CONFIG_ANSI_C_EXTRA */
2987 }
2990 static void wpa_cli_cleanup(void)
2991 {
2992 wpa_cli_close_connection();
2993 if (pid_file)
2994 os_daemonize_terminate(pid_file);
2996 os_program_deinit();
2997 }
2999 static void wpa_cli_terminate(int sig)
3000 {
3001 wpa_cli_cleanup();
3002 exit(0);
3003 }
3006 #ifdef CONFIG_WPA_CLI_FORK
3007 static void wpa_cli_usr1(int sig)
3008 {
3009 readline_redraw();
3010 }
3011 #endif /* CONFIG_WPA_CLI_FORK */
3014 #ifndef CONFIG_NATIVE_WINDOWS
3015 static void wpa_cli_alarm(int sig)
3016 {
3017 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3018 printf("Connection to wpa_supplicant lost - trying to "
3019 "reconnect\n");
3020 wpa_cli_close_connection();
3021 }
3022 if (!ctrl_conn)
3023 wpa_cli_reconnect();
3024 if (mon_conn)
3025 wpa_cli_recv_pending(mon_conn, 1, 0);
3026 alarm(ping_interval);
3027 }
3028 #endif /* CONFIG_NATIVE_WINDOWS */
3031 static char * wpa_cli_get_default_ifname(void)
3032 {
3033 char *ifname = NULL;
3035 #ifdef CONFIG_CTRL_IFACE_UNIX
3036 struct dirent *dent;
3037 DIR *dir = opendir(ctrl_iface_dir);
3038 if (!dir)
3039 return NULL;
3040 while ((dent = readdir(dir))) {
3041 #ifdef _DIRENT_HAVE_D_TYPE
3042 /*
3043 * Skip the file if it is not a socket. Also accept
3044 * DT_UNKNOWN (0) in case the C library or underlying
3045 * file system does not support d_type.
3046 */
3047 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3048 continue;
3049 #endif /* _DIRENT_HAVE_D_TYPE */
3050 if (os_strcmp(dent->d_name, ".") == 0 ||
3051 os_strcmp(dent->d_name, "..") == 0)
3052 continue;
3053 printf("Selected interface '%s'\n", dent->d_name);
3054 ifname = os_strdup(dent->d_name);
3055 break;
3056 }
3057 closedir(dir);
3058 #endif /* CONFIG_CTRL_IFACE_UNIX */
3060 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3061 char buf[2048], *pos;
3062 size_t len;
3063 struct wpa_ctrl *ctrl;
3064 int ret;
3066 ctrl = wpa_ctrl_open(NULL);
3067 if (ctrl == NULL)
3068 return NULL;
3070 len = sizeof(buf) - 1;
3071 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3072 if (ret >= 0) {
3073 buf[len] = '\0';
3074 pos = os_strchr(buf, '\n');
3075 if (pos)
3076 *pos = '\0';
3077 ifname = os_strdup(buf);
3078 }
3079 wpa_ctrl_close(ctrl);
3080 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3082 return ifname;
3083 }
3086 int main(int argc, char *argv[])
3087 {
3088 int warning_displayed = 0;
3089 int c;
3090 int daemonize = 0;
3091 int ret = 0;
3092 const char *global = NULL;
3094 if (os_program_init())
3095 return -1;
3097 for (;;) {
3098 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3099 if (c < 0)
3100 break;
3101 switch (c) {
3102 case 'a':
3103 action_file = optarg;
3104 break;
3105 case 'B':
3106 daemonize = 1;
3107 break;
3108 case 'g':
3109 global = optarg;
3110 break;
3111 case 'G':
3112 ping_interval = atoi(optarg);
3113 break;
3114 case 'h':
3115 usage();
3116 return 0;
3117 case 'v':
3118 printf("%s\n", wpa_cli_version);
3119 return 0;
3120 case 'i':
3121 os_free(ctrl_ifname);
3122 ctrl_ifname = os_strdup(optarg);
3123 break;
3124 case 'p':
3125 ctrl_iface_dir = optarg;
3126 break;
3127 case 'P':
3128 pid_file = optarg;
3129 break;
3130 default:
3131 usage();
3132 return -1;
3133 }
3134 }
3136 interactive = (argc == optind) && (action_file == NULL);
3138 if (interactive)
3139 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3141 if (global) {
3142 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3143 ctrl_conn = wpa_ctrl_open(NULL);
3144 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3145 ctrl_conn = wpa_ctrl_open(global);
3146 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3147 if (ctrl_conn == NULL) {
3148 perror("Failed to connect to wpa_supplicant - "
3149 "wpa_ctrl_open");
3150 return -1;
3151 }
3152 }
3154 #ifndef _WIN32_WCE
3155 signal(SIGINT, wpa_cli_terminate);
3156 signal(SIGTERM, wpa_cli_terminate);
3157 #endif /* _WIN32_WCE */
3158 #ifndef CONFIG_NATIVE_WINDOWS
3159 signal(SIGALRM, wpa_cli_alarm);
3160 #endif /* CONFIG_NATIVE_WINDOWS */
3161 #ifdef CONFIG_WPA_CLI_FORK
3162 signal(SIGUSR1, wpa_cli_usr1);
3163 #endif /* CONFIG_WPA_CLI_FORK */
3165 if (ctrl_ifname == NULL)
3166 ctrl_ifname = wpa_cli_get_default_ifname();
3168 if (interactive) {
3169 for (; !global;) {
3170 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3171 if (warning_displayed)
3172 printf("Connection established.\n");
3173 break;
3174 }
3176 if (!warning_displayed) {
3177 printf("Could not connect to wpa_supplicant - "
3178 "re-trying\n");
3179 warning_displayed = 1;
3180 }
3181 os_sleep(1, 0);
3182 continue;
3183 }
3184 } else {
3185 if (!global &&
3186 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3187 perror("Failed to connect to wpa_supplicant - "
3188 "wpa_ctrl_open");
3189 return -1;
3190 }
3192 if (action_file) {
3193 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3194 wpa_cli_attached = 1;
3195 } else {
3196 printf("Warning: Failed to attach to "
3197 "wpa_supplicant.\n");
3198 return -1;
3199 }
3200 }
3201 }
3203 if (daemonize && os_daemonize(pid_file))
3204 return -1;
3206 if (interactive)
3207 wpa_cli_interactive();
3208 else if (action_file)
3209 wpa_cli_action(ctrl_conn);
3210 else
3211 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3213 os_free(ctrl_ifname);
3214 wpa_cli_cleanup();
3216 return ret;
3217 }
3219 #else /* CONFIG_CTRL_IFACE */
3220 int main(int argc, char *argv[])
3221 {
3222 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3223 return -1;
3224 }
3225 #endif /* CONFIG_CTRL_IFACE */