1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2011, 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 */
23 #include "common/wpa_ctrl.h"
24 #include "utils/common.h"
25 #include "utils/eloop.h"
26 #include "utils/edit.h"
27 #include "common/version.h"
28 #ifdef ANDROID
29 #include <cutils/properties.h>
30 #endif /* ANDROID */
33 static const char *wpa_cli_version =
34 "wpa_cli v" VERSION_STR "\n"
35 "Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> and contributors";
38 static const char *wpa_cli_license =
39 "This program is free software. You can distribute it and/or modify it\n"
40 "under the terms of the GNU General Public License version 2.\n"
41 "\n"
42 "Alternatively, this software may be distributed under the terms of the\n"
43 "BSD license. See README and COPYING for more details.\n";
45 static const char *wpa_cli_full_license =
46 "This program is free software; you can redistribute it and/or modify\n"
47 "it under the terms of the GNU General Public License version 2 as\n"
48 "published by the Free Software Foundation.\n"
49 "\n"
50 "This program is distributed in the hope that it will be useful,\n"
51 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
52 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
53 "GNU General Public License for more details.\n"
54 "\n"
55 "You should have received a copy of the GNU General Public License\n"
56 "along with this program; if not, write to the Free Software\n"
57 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
58 "\n"
59 "Alternatively, this software may be distributed under the terms of the\n"
60 "BSD license.\n"
61 "\n"
62 "Redistribution and use in source and binary forms, with or without\n"
63 "modification, are permitted provided that the following conditions are\n"
64 "met:\n"
65 "\n"
66 "1. Redistributions of source code must retain the above copyright\n"
67 " notice, this list of conditions and the following disclaimer.\n"
68 "\n"
69 "2. Redistributions in binary form must reproduce the above copyright\n"
70 " notice, this list of conditions and the following disclaimer in the\n"
71 " documentation and/or other materials provided with the distribution.\n"
72 "\n"
73 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
74 " names of its contributors may be used to endorse or promote products\n"
75 " derived from this software without specific prior written permission.\n"
76 "\n"
77 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
78 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
79 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
80 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
81 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
82 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
83 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
84 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
85 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
86 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
87 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
88 "\n";
90 static struct wpa_ctrl *ctrl_conn;
91 static struct wpa_ctrl *mon_conn;
92 static int wpa_cli_quit = 0;
93 static int wpa_cli_attached = 0;
94 static int wpa_cli_connected = 0;
95 static int wpa_cli_last_id = 0;
96 #ifndef CONFIG_CTRL_IFACE_DIR
97 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
98 #endif /* CONFIG_CTRL_IFACE_DIR */
99 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
100 static char *ctrl_ifname = NULL;
101 static const char *pid_file = NULL;
102 static const char *action_file = NULL;
103 static int ping_interval = 5;
104 static int interactive = 0;
107 static void print_help(void);
108 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
111 static void usage(void)
112 {
113 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
114 "[-a<action file>] \\\n"
115 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
116 "[command..]\n"
117 " -h = help (show this usage text)\n"
118 " -v = shown version information\n"
119 " -a = run in daemon mode executing the action file based on "
120 "events from\n"
121 " wpa_supplicant\n"
122 " -B = run a daemon in the background\n"
123 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
124 " default interface: first interface found in socket path\n");
125 print_help();
126 }
129 static int str_starts(const char *src, const char *match)
130 {
131 return os_strncmp(src, match, os_strlen(match)) == 0;
132 }
135 static int wpa_cli_show_event(const char *event)
136 {
137 const char *start;
139 start = os_strchr(event, '>');
140 if (start == NULL)
141 return 1;
143 start++;
144 /*
145 * Skip BSS added/removed events since they can be relatively frequent
146 * and are likely of not much use for an interactive user.
147 */
148 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
149 str_starts(start, WPA_EVENT_BSS_REMOVED))
150 return 0;
152 return 1;
153 }
156 static int wpa_cli_open_connection(const char *ifname, int attach)
157 {
158 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
159 ctrl_conn = wpa_ctrl_open(ifname);
160 if (ctrl_conn == NULL)
161 return -1;
163 if (attach && interactive)
164 mon_conn = wpa_ctrl_open(ifname);
165 else
166 mon_conn = NULL;
167 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
168 char *cfile = NULL;
169 int flen, res;
171 if (ifname == NULL)
172 return -1;
174 #ifdef ANDROID
175 if (access(ctrl_iface_dir, F_OK) < 0) {
176 cfile = os_strdup(ifname);
177 if (cfile == NULL)
178 return -1;
179 }
180 #endif /* ANDROID */
182 if (cfile == NULL) {
183 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
184 cfile = os_malloc(flen);
185 if (cfile == NULL)
186 return -1;
187 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
188 ifname);
189 if (res < 0 || res >= flen) {
190 os_free(cfile);
191 return -1;
192 }
193 }
195 ctrl_conn = wpa_ctrl_open(cfile);
196 if (ctrl_conn == NULL) {
197 os_free(cfile);
198 return -1;
199 }
201 if (attach && interactive)
202 mon_conn = wpa_ctrl_open(cfile);
203 else
204 mon_conn = NULL;
205 os_free(cfile);
206 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
208 if (mon_conn) {
209 if (wpa_ctrl_attach(mon_conn) == 0) {
210 wpa_cli_attached = 1;
211 if (interactive)
212 eloop_register_read_sock(
213 wpa_ctrl_get_fd(mon_conn),
214 wpa_cli_mon_receive, NULL, NULL);
215 } else {
216 printf("Warning: Failed to attach to "
217 "wpa_supplicant.\n");
218 return -1;
219 }
220 }
222 return 0;
223 }
226 static void wpa_cli_close_connection(void)
227 {
228 if (ctrl_conn == NULL)
229 return;
231 if (wpa_cli_attached) {
232 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
233 wpa_cli_attached = 0;
234 }
235 wpa_ctrl_close(ctrl_conn);
236 ctrl_conn = NULL;
237 if (mon_conn) {
238 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
239 wpa_ctrl_close(mon_conn);
240 mon_conn = NULL;
241 }
242 }
245 static void wpa_cli_msg_cb(char *msg, size_t len)
246 {
247 printf("%s\n", msg);
248 }
251 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
252 {
253 char buf[2048];
254 size_t len;
255 int ret;
257 if (ctrl_conn == NULL) {
258 printf("Not connected to wpa_supplicant - command dropped.\n");
259 return -1;
260 }
261 len = sizeof(buf) - 1;
262 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
263 wpa_cli_msg_cb);
264 if (ret == -2) {
265 printf("'%s' command timed out.\n", cmd);
266 return -2;
267 } else if (ret < 0) {
268 printf("'%s' command failed.\n", cmd);
269 return -1;
270 }
271 if (print) {
272 buf[len] = '\0';
273 printf("%s", buf);
274 if (interactive && len > 0 && buf[len - 1] != '\n')
275 printf("\n");
276 }
277 return 0;
278 }
281 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
282 {
283 return _wpa_ctrl_command(ctrl, cmd, 1);
284 }
287 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
288 {
289 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
290 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
291 }
294 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
295 {
296 return wpa_ctrl_command(ctrl, "PING");
297 }
300 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
301 {
302 return wpa_ctrl_command(ctrl, "RELOG");
303 }
306 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
307 {
308 char cmd[256];
309 int ret;
310 if (argc == 0)
311 return -1;
312 ret = os_snprintf(cmd, sizeof(cmd), "NOTE %s", argv[0]);
313 if (ret < 0 || (size_t) ret >= sizeof(cmd))
314 return -1;
315 return wpa_ctrl_command(ctrl, cmd);
316 }
319 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
320 {
321 return wpa_ctrl_command(ctrl, "MIB");
322 }
325 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
326 {
327 return wpa_ctrl_command(ctrl, "PMKSA");
328 }
331 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
332 {
333 print_help();
334 return 0;
335 }
338 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
339 {
340 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
341 return 0;
342 }
345 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
346 {
347 wpa_cli_quit = 1;
348 if (interactive)
349 eloop_terminate();
350 return 0;
351 }
354 static void wpa_cli_show_variables(void)
355 {
356 printf("set variables:\n"
357 " EAPOL::heldPeriod (EAPOL state machine held period, "
358 "in seconds)\n"
359 " EAPOL::authPeriod (EAPOL state machine authentication "
360 "period, in seconds)\n"
361 " EAPOL::startPeriod (EAPOL state machine start period, in "
362 "seconds)\n"
363 " EAPOL::maxStart (EAPOL state machine maximum start "
364 "attempts)\n");
365 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
366 "seconds)\n"
367 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
368 " threshold\n\tpercentage)\n"
369 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
370 "security\n\tassociation in seconds)\n");
371 }
374 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
375 {
376 char cmd[256];
377 int res;
379 if (argc == 0) {
380 wpa_cli_show_variables();
381 return 0;
382 }
384 if (argc != 1 && argc != 2) {
385 printf("Invalid SET command: needs two arguments (variable "
386 "name and value)\n");
387 return -1;
388 }
390 if (argc == 1)
391 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
392 else
393 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
394 argv[0], argv[1]);
395 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
396 printf("Too long SET command.\n");
397 return -1;
398 }
399 return wpa_ctrl_command(ctrl, cmd);
400 }
403 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
404 {
405 char cmd[256];
406 int res;
408 if (argc != 1) {
409 printf("Invalid GET command: need one argument (variable "
410 "name)\n");
411 return -1;
412 }
414 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
415 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
416 printf("Too long GET command.\n");
417 return -1;
418 }
419 return wpa_ctrl_command(ctrl, cmd);
420 }
423 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
424 {
425 return wpa_ctrl_command(ctrl, "LOGOFF");
426 }
429 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
430 {
431 return wpa_ctrl_command(ctrl, "LOGON");
432 }
435 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
436 char *argv[])
437 {
438 return wpa_ctrl_command(ctrl, "REASSOCIATE");
439 }
442 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
443 char *argv[])
444 {
445 char cmd[256];
446 int res;
448 if (argc != 1) {
449 printf("Invalid PREAUTH command: needs one argument "
450 "(BSSID)\n");
451 return -1;
452 }
454 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
455 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
456 printf("Too long PREAUTH command.\n");
457 return -1;
458 }
459 return wpa_ctrl_command(ctrl, cmd);
460 }
463 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
464 {
465 char cmd[256];
466 int res;
468 if (argc != 1) {
469 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
470 "value)\n");
471 return -1;
472 }
473 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
474 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
475 printf("Too long AP_SCAN command.\n");
476 return -1;
477 }
478 return wpa_ctrl_command(ctrl, cmd);
479 }
482 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
483 char *argv[])
484 {
485 char cmd[256];
486 int res;
488 if (argc != 1) {
489 printf("Invalid SCAN_INTERVAL command: needs one argument "
490 "scan_interval value)\n");
491 return -1;
492 }
493 res = os_snprintf(cmd, sizeof(cmd), "SCAN_INTERVAL %s", argv[0]);
494 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
495 printf("Too long SCAN_INTERVAL command.\n");
496 return -1;
497 }
498 return wpa_ctrl_command(ctrl, cmd);
499 }
502 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
503 char *argv[])
504 {
505 char cmd[256];
506 int res;
508 if (argc != 1) {
509 printf("Invalid BSS_EXPIRE_AGE command: needs one argument "
510 "(bss_expire_age value)\n");
511 return -1;
512 }
513 res = os_snprintf(cmd, sizeof(cmd), "BSS_EXPIRE_AGE %s", argv[0]);
514 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
515 printf("Too long BSS_EXPIRE_AGE command.\n");
516 return -1;
517 }
518 return wpa_ctrl_command(ctrl, cmd);
519 }
522 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
523 char *argv[])
524 {
525 char cmd[256];
526 int res;
528 if (argc != 1) {
529 printf("Invalid BSS_EXPIRE_COUNT command: needs one argument "
530 "(bss_expire_count value)\n");
531 return -1;
532 }
533 res = os_snprintf(cmd, sizeof(cmd), "BSS_EXPIRE_COUNT %s", argv[0]);
534 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
535 printf("Too long BSS_EXPIRE_COUNT command.\n");
536 return -1;
537 }
538 return wpa_ctrl_command(ctrl, cmd);
539 }
542 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
543 char *argv[])
544 {
545 char cmd[256];
546 int res;
548 if (argc != 1) {
549 printf("Invalid STKSTART command: needs one argument "
550 "(Peer STA MAC address)\n");
551 return -1;
552 }
554 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
555 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
556 printf("Too long STKSTART command.\n");
557 return -1;
558 }
559 return wpa_ctrl_command(ctrl, cmd);
560 }
563 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
564 {
565 char cmd[256];
566 int res;
568 if (argc != 1) {
569 printf("Invalid FT_DS command: needs one argument "
570 "(Target AP MAC address)\n");
571 return -1;
572 }
574 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
575 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
576 printf("Too long FT_DS command.\n");
577 return -1;
578 }
579 return wpa_ctrl_command(ctrl, cmd);
580 }
583 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
584 {
585 char cmd[256];
586 int res;
588 if (argc == 0) {
589 /* Any BSSID */
590 return wpa_ctrl_command(ctrl, "WPS_PBC");
591 }
593 /* Specific BSSID */
594 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
595 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
596 printf("Too long WPS_PBC command.\n");
597 return -1;
598 }
599 return wpa_ctrl_command(ctrl, cmd);
600 }
603 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
604 {
605 char cmd[256];
606 int res;
608 if (argc == 0) {
609 printf("Invalid WPS_PIN command: need one or two arguments:\n"
610 "- BSSID: use 'any' to select any\n"
611 "- PIN: optional, used only with devices that have no "
612 "display\n");
613 return -1;
614 }
616 if (argc == 1) {
617 /* Use dynamically generated PIN (returned as reply) */
618 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
619 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
620 printf("Too long WPS_PIN command.\n");
621 return -1;
622 }
623 return wpa_ctrl_command(ctrl, cmd);
624 }
626 /* Use hardcoded PIN from a label */
627 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
628 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
629 printf("Too long WPS_PIN command.\n");
630 return -1;
631 }
632 return wpa_ctrl_command(ctrl, cmd);
633 }
636 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
637 char *argv[])
638 {
639 char cmd[256];
640 int res;
642 if (argc != 1 && argc != 2) {
643 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
644 "- PIN to be verified\n");
645 return -1;
646 }
648 if (argc == 2)
649 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
650 argv[0], argv[1]);
651 else
652 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
653 argv[0]);
654 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
655 printf("Too long WPS_CHECK_PIN command.\n");
656 return -1;
657 }
658 return wpa_ctrl_command(ctrl, cmd);
659 }
662 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
663 char *argv[])
664 {
665 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
666 }
669 #ifdef CONFIG_WPS_OOB
670 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
671 {
672 char cmd[256];
673 int res;
675 if (argc != 3 && argc != 4) {
676 printf("Invalid WPS_OOB command: need three or four "
677 "arguments:\n"
678 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
679 "- PATH: path of OOB device like '/mnt'\n"
680 "- METHOD: OOB method 'pin-e' or 'pin-r', "
681 "'cred'\n"
682 "- DEV_NAME: (only for NFC) device name like "
683 "'pn531'\n");
684 return -1;
685 }
687 if (argc == 3)
688 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
689 argv[0], argv[1], argv[2]);
690 else
691 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
692 argv[0], argv[1], argv[2], argv[3]);
693 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
694 printf("Too long WPS_OOB command.\n");
695 return -1;
696 }
697 return wpa_ctrl_command(ctrl, cmd);
698 }
699 #endif /* CONFIG_WPS_OOB */
702 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
703 {
704 char cmd[256];
705 int res;
707 if (argc == 2)
708 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
709 argv[0], argv[1]);
710 else if (argc == 5 || argc == 6) {
711 char ssid_hex[2 * 32 + 1];
712 char key_hex[2 * 64 + 1];
713 int i;
715 ssid_hex[0] = '\0';
716 for (i = 0; i < 32; i++) {
717 if (argv[2][i] == '\0')
718 break;
719 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
720 }
722 key_hex[0] = '\0';
723 if (argc == 6) {
724 for (i = 0; i < 64; i++) {
725 if (argv[5][i] == '\0')
726 break;
727 os_snprintf(&key_hex[i * 2], 3, "%02x",
728 argv[5][i]);
729 }
730 }
732 res = os_snprintf(cmd, sizeof(cmd),
733 "WPS_REG %s %s %s %s %s %s",
734 argv[0], argv[1], ssid_hex, argv[3], argv[4],
735 key_hex);
736 } else {
737 printf("Invalid WPS_REG command: need two arguments:\n"
738 "- BSSID of the target AP\n"
739 "- AP PIN\n");
740 printf("Alternatively, six arguments can be used to "
741 "reconfigure the AP:\n"
742 "- BSSID of the target AP\n"
743 "- AP PIN\n"
744 "- new SSID\n"
745 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
746 "- new encr (NONE, WEP, TKIP, CCMP)\n"
747 "- new key\n");
748 return -1;
749 }
751 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
752 printf("Too long WPS_REG command.\n");
753 return -1;
754 }
755 return wpa_ctrl_command(ctrl, cmd);
756 }
759 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
760 char *argv[])
761 {
762 char cmd[256];
763 int res;
765 if (argc < 1) {
766 printf("Invalid WPS_AP_PIN command: needs at least one "
767 "argument\n");
768 return -1;
769 }
771 if (argc > 2)
772 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s %s",
773 argv[0], argv[1], argv[2]);
774 else if (argc > 1)
775 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s",
776 argv[0], argv[1]);
777 else
778 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s",
779 argv[0]);
780 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
781 printf("Too long WPS_AP_PIN command.\n");
782 return -1;
783 }
784 return wpa_ctrl_command(ctrl, cmd);
785 }
788 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
789 char *argv[])
790 {
791 char cmd[100];
792 if (argc > 0) {
793 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
794 return wpa_ctrl_command(ctrl, cmd);
795 }
796 return wpa_ctrl_command(ctrl, "WPS_ER_START");
797 }
800 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
801 char *argv[])
802 {
803 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
805 }
808 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
809 char *argv[])
810 {
811 char cmd[256];
812 int res;
814 if (argc < 2) {
815 printf("Invalid WPS_ER_PIN command: need at least two "
816 "arguments:\n"
817 "- UUID: use 'any' to select any\n"
818 "- PIN: Enrollee PIN\n"
819 "optional: - Enrollee MAC address\n");
820 return -1;
821 }
823 if (argc > 2)
824 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
825 argv[0], argv[1], argv[2]);
826 else
827 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
828 argv[0], argv[1]);
829 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
830 printf("Too long WPS_ER_PIN command.\n");
831 return -1;
832 }
833 return wpa_ctrl_command(ctrl, cmd);
834 }
837 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
838 char *argv[])
839 {
840 char cmd[256];
841 int res;
843 if (argc != 1) {
844 printf("Invalid WPS_ER_PBC command: need one argument:\n"
845 "- UUID: Specify the Enrollee\n");
846 return -1;
847 }
849 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
850 argv[0]);
851 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
852 printf("Too long WPS_ER_PBC command.\n");
853 return -1;
854 }
855 return wpa_ctrl_command(ctrl, cmd);
856 }
859 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
860 char *argv[])
861 {
862 char cmd[256];
863 int res;
865 if (argc != 2) {
866 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
867 "- UUID: specify which AP to use\n"
868 "- PIN: AP PIN\n");
869 return -1;
870 }
872 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
873 argv[0], argv[1]);
874 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
875 printf("Too long WPS_ER_LEARN command.\n");
876 return -1;
877 }
878 return wpa_ctrl_command(ctrl, cmd);
879 }
882 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
883 char *argv[])
884 {
885 char cmd[256];
886 int res;
888 if (argc != 2) {
889 printf("Invalid WPS_ER_SET_CONFIG command: need two "
890 "arguments:\n"
891 "- UUID: specify which AP to use\n"
892 "- Network configuration id\n");
893 return -1;
894 }
896 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s",
897 argv[0], argv[1]);
898 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
899 printf("Too long WPS_ER_SET_CONFIG command.\n");
900 return -1;
901 }
902 return wpa_ctrl_command(ctrl, cmd);
903 }
906 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
907 char *argv[])
908 {
909 char cmd[256];
910 int res;
912 if (argc == 5 || argc == 6) {
913 char ssid_hex[2 * 32 + 1];
914 char key_hex[2 * 64 + 1];
915 int i;
917 ssid_hex[0] = '\0';
918 for (i = 0; i < 32; i++) {
919 if (argv[2][i] == '\0')
920 break;
921 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
922 }
924 key_hex[0] = '\0';
925 if (argc == 6) {
926 for (i = 0; i < 64; i++) {
927 if (argv[5][i] == '\0')
928 break;
929 os_snprintf(&key_hex[i * 2], 3, "%02x",
930 argv[5][i]);
931 }
932 }
934 res = os_snprintf(cmd, sizeof(cmd),
935 "WPS_ER_CONFIG %s %s %s %s %s %s",
936 argv[0], argv[1], ssid_hex, argv[3], argv[4],
937 key_hex);
938 } else {
939 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
940 "- AP UUID\n"
941 "- AP PIN\n"
942 "- new SSID\n"
943 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
944 "- new encr (NONE, WEP, TKIP, CCMP)\n"
945 "- new key\n");
946 return -1;
947 }
949 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
950 printf("Too long WPS_ER_CONFIG command.\n");
951 return -1;
952 }
953 return wpa_ctrl_command(ctrl, cmd);
954 }
957 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
958 {
959 char cmd[256];
960 int res;
962 if (argc != 1) {
963 printf("Invalid IBSS_RSN command: needs one argument "
964 "(Peer STA MAC address)\n");
965 return -1;
966 }
968 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
969 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
970 printf("Too long IBSS_RSN command.\n");
971 return -1;
972 }
973 return wpa_ctrl_command(ctrl, cmd);
974 }
977 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
978 {
979 char cmd[256];
980 int res;
982 if (argc != 1) {
983 printf("Invalid LEVEL command: needs one argument (debug "
984 "level)\n");
985 return -1;
986 }
987 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
988 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
989 printf("Too long LEVEL command.\n");
990 return -1;
991 }
992 return wpa_ctrl_command(ctrl, cmd);
993 }
996 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
997 {
998 char cmd[256], *pos, *end;
999 int i, ret;
1001 if (argc < 2) {
1002 printf("Invalid IDENTITY command: needs two arguments "
1003 "(network id and identity)\n");
1004 return -1;
1005 }
1007 end = cmd + sizeof(cmd);
1008 pos = cmd;
1009 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1010 argv[0], argv[1]);
1011 if (ret < 0 || ret >= end - pos) {
1012 printf("Too long IDENTITY command.\n");
1013 return -1;
1014 }
1015 pos += ret;
1016 for (i = 2; i < argc; i++) {
1017 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1018 if (ret < 0 || ret >= end - pos) {
1019 printf("Too long IDENTITY command.\n");
1020 return -1;
1021 }
1022 pos += ret;
1023 }
1025 return wpa_ctrl_command(ctrl, cmd);
1026 }
1029 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1030 {
1031 char cmd[256], *pos, *end;
1032 int i, ret;
1034 if (argc < 2) {
1035 printf("Invalid PASSWORD command: needs two arguments "
1036 "(network id and password)\n");
1037 return -1;
1038 }
1040 end = cmd + sizeof(cmd);
1041 pos = cmd;
1042 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1043 argv[0], argv[1]);
1044 if (ret < 0 || ret >= end - pos) {
1045 printf("Too long PASSWORD command.\n");
1046 return -1;
1047 }
1048 pos += ret;
1049 for (i = 2; i < argc; i++) {
1050 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1051 if (ret < 0 || ret >= end - pos) {
1052 printf("Too long PASSWORD command.\n");
1053 return -1;
1054 }
1055 pos += ret;
1056 }
1058 return wpa_ctrl_command(ctrl, cmd);
1059 }
1062 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1063 char *argv[])
1064 {
1065 char cmd[256], *pos, *end;
1066 int i, ret;
1068 if (argc < 2) {
1069 printf("Invalid NEW_PASSWORD command: needs two arguments "
1070 "(network id and password)\n");
1071 return -1;
1072 }
1074 end = cmd + sizeof(cmd);
1075 pos = cmd;
1076 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1077 argv[0], argv[1]);
1078 if (ret < 0 || ret >= end - pos) {
1079 printf("Too long NEW_PASSWORD command.\n");
1080 return -1;
1081 }
1082 pos += ret;
1083 for (i = 2; i < argc; i++) {
1084 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1085 if (ret < 0 || ret >= end - pos) {
1086 printf("Too long NEW_PASSWORD command.\n");
1087 return -1;
1088 }
1089 pos += ret;
1090 }
1092 return wpa_ctrl_command(ctrl, cmd);
1093 }
1096 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1097 {
1098 char cmd[256], *pos, *end;
1099 int i, ret;
1101 if (argc < 2) {
1102 printf("Invalid PIN command: needs two arguments "
1103 "(network id and pin)\n");
1104 return -1;
1105 }
1107 end = cmd + sizeof(cmd);
1108 pos = cmd;
1109 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1110 argv[0], argv[1]);
1111 if (ret < 0 || ret >= end - pos) {
1112 printf("Too long PIN command.\n");
1113 return -1;
1114 }
1115 pos += ret;
1116 for (i = 2; i < argc; i++) {
1117 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1118 if (ret < 0 || ret >= end - pos) {
1119 printf("Too long PIN command.\n");
1120 return -1;
1121 }
1122 pos += ret;
1123 }
1124 return wpa_ctrl_command(ctrl, cmd);
1125 }
1128 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1129 {
1130 char cmd[256], *pos, *end;
1131 int i, ret;
1133 if (argc < 2) {
1134 printf("Invalid OTP command: needs two arguments (network "
1135 "id and password)\n");
1136 return -1;
1137 }
1139 end = cmd + sizeof(cmd);
1140 pos = cmd;
1141 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1142 argv[0], argv[1]);
1143 if (ret < 0 || ret >= end - pos) {
1144 printf("Too long OTP command.\n");
1145 return -1;
1146 }
1147 pos += ret;
1148 for (i = 2; i < argc; i++) {
1149 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1150 if (ret < 0 || ret >= end - pos) {
1151 printf("Too long OTP command.\n");
1152 return -1;
1153 }
1154 pos += ret;
1155 }
1157 return wpa_ctrl_command(ctrl, cmd);
1158 }
1161 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1162 char *argv[])
1163 {
1164 char cmd[256], *pos, *end;
1165 int i, ret;
1167 if (argc < 2) {
1168 printf("Invalid PASSPHRASE command: needs two arguments "
1169 "(network id and passphrase)\n");
1170 return -1;
1171 }
1173 end = cmd + sizeof(cmd);
1174 pos = cmd;
1175 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1176 argv[0], argv[1]);
1177 if (ret < 0 || ret >= end - pos) {
1178 printf("Too long PASSPHRASE command.\n");
1179 return -1;
1180 }
1181 pos += ret;
1182 for (i = 2; i < argc; i++) {
1183 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1184 if (ret < 0 || ret >= end - pos) {
1185 printf("Too long PASSPHRASE command.\n");
1186 return -1;
1187 }
1188 pos += ret;
1189 }
1191 return wpa_ctrl_command(ctrl, cmd);
1192 }
1195 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1196 {
1197 char cmd[256], *pos, *end;
1198 int i, ret;
1200 if (argc < 2) {
1201 printf("Invalid BSSID command: needs two arguments (network "
1202 "id and BSSID)\n");
1203 return -1;
1204 }
1206 end = cmd + sizeof(cmd);
1207 pos = cmd;
1208 ret = os_snprintf(pos, end - pos, "BSSID");
1209 if (ret < 0 || ret >= end - pos) {
1210 printf("Too long BSSID command.\n");
1211 return -1;
1212 }
1213 pos += ret;
1214 for (i = 0; i < argc; i++) {
1215 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1216 if (ret < 0 || ret >= end - pos) {
1217 printf("Too long BSSID command.\n");
1218 return -1;
1219 }
1220 pos += ret;
1221 }
1223 return wpa_ctrl_command(ctrl, cmd);
1224 }
1227 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1228 char *argv[])
1229 {
1230 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1231 }
1234 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1235 char *argv[])
1236 {
1237 char cmd[32];
1238 int res;
1240 if (argc < 1) {
1241 printf("Invalid SELECT_NETWORK command: needs one argument "
1242 "(network id)\n");
1243 return -1;
1244 }
1246 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1247 if (res < 0 || (size_t) res >= sizeof(cmd))
1248 return -1;
1249 cmd[sizeof(cmd) - 1] = '\0';
1251 return wpa_ctrl_command(ctrl, cmd);
1252 }
1255 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1256 char *argv[])
1257 {
1258 char cmd[32];
1259 int res;
1261 if (argc < 1) {
1262 printf("Invalid ENABLE_NETWORK command: needs one argument "
1263 "(network id)\n");
1264 return -1;
1265 }
1267 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1268 if (res < 0 || (size_t) res >= sizeof(cmd))
1269 return -1;
1270 cmd[sizeof(cmd) - 1] = '\0';
1272 return wpa_ctrl_command(ctrl, cmd);
1273 }
1276 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1277 char *argv[])
1278 {
1279 char cmd[32];
1280 int res;
1282 if (argc < 1) {
1283 printf("Invalid DISABLE_NETWORK command: needs one argument "
1284 "(network id)\n");
1285 return -1;
1286 }
1288 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1289 if (res < 0 || (size_t) res >= sizeof(cmd))
1290 return -1;
1291 cmd[sizeof(cmd) - 1] = '\0';
1293 return wpa_ctrl_command(ctrl, cmd);
1294 }
1297 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1298 char *argv[])
1299 {
1300 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1301 }
1304 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1305 char *argv[])
1306 {
1307 char cmd[32];
1308 int res;
1310 if (argc < 1) {
1311 printf("Invalid REMOVE_NETWORK command: needs one argument "
1312 "(network id)\n");
1313 return -1;
1314 }
1316 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1317 if (res < 0 || (size_t) res >= sizeof(cmd))
1318 return -1;
1319 cmd[sizeof(cmd) - 1] = '\0';
1321 return wpa_ctrl_command(ctrl, cmd);
1322 }
1325 static void wpa_cli_show_network_variables(void)
1326 {
1327 printf("set_network variables:\n"
1328 " ssid (network name, SSID)\n"
1329 " psk (WPA passphrase or pre-shared key)\n"
1330 " key_mgmt (key management protocol)\n"
1331 " identity (EAP identity)\n"
1332 " password (EAP password)\n"
1333 " ...\n"
1334 "\n"
1335 "Note: Values are entered in the same format as the "
1336 "configuration file is using,\n"
1337 "i.e., strings values need to be inside double quotation "
1338 "marks.\n"
1339 "For example: set_network 1 ssid \"network name\"\n"
1340 "\n"
1341 "Please see wpa_supplicant.conf documentation for full list "
1342 "of\navailable variables.\n");
1343 }
1346 static int wpa_cli_cmd_set_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 != 3) {
1358 printf("Invalid SET_NETWORK command: needs three arguments\n"
1359 "(network id, variable name, and value)\n");
1360 return -1;
1361 }
1363 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1364 argv[0], argv[1], argv[2]);
1365 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1366 printf("Too long SET_NETWORK command.\n");
1367 return -1;
1368 }
1369 return wpa_ctrl_command(ctrl, cmd);
1370 }
1373 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1374 char *argv[])
1375 {
1376 char cmd[256];
1377 int res;
1379 if (argc == 0) {
1380 wpa_cli_show_network_variables();
1381 return 0;
1382 }
1384 if (argc != 2) {
1385 printf("Invalid GET_NETWORK command: needs two arguments\n"
1386 "(network id and variable name)\n");
1387 return -1;
1388 }
1390 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1391 argv[0], argv[1]);
1392 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1393 printf("Too long GET_NETWORK command.\n");
1394 return -1;
1395 }
1396 return wpa_ctrl_command(ctrl, cmd);
1397 }
1400 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1401 char *argv[])
1402 {
1403 return wpa_ctrl_command(ctrl, "DISCONNECT");
1404 }
1407 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1408 char *argv[])
1409 {
1410 return wpa_ctrl_command(ctrl, "RECONNECT");
1411 }
1414 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1415 char *argv[])
1416 {
1417 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1418 }
1421 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1422 {
1423 return wpa_ctrl_command(ctrl, "SCAN");
1424 }
1427 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1428 char *argv[])
1429 {
1430 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1431 }
1434 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1435 {
1436 char cmd[64];
1437 int res;
1439 if (argc != 1) {
1440 printf("Invalid BSS command: need one argument (index or "
1441 "BSSID)\n");
1442 return -1;
1443 }
1445 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1446 if (res < 0 || (size_t) res >= sizeof(cmd))
1447 return -1;
1448 cmd[sizeof(cmd) - 1] = '\0';
1450 return wpa_ctrl_command(ctrl, cmd);
1451 }
1454 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1455 char *argv[])
1456 {
1457 char cmd[64];
1458 int res;
1460 if (argc < 1 || argc > 2) {
1461 printf("Invalid GET_CAPABILITY command: need either one or "
1462 "two arguments\n");
1463 return -1;
1464 }
1466 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1467 printf("Invalid GET_CAPABILITY command: second argument, "
1468 "if any, must be 'strict'\n");
1469 return -1;
1470 }
1472 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1473 (argc == 2) ? " strict" : "");
1474 if (res < 0 || (size_t) res >= sizeof(cmd))
1475 return -1;
1476 cmd[sizeof(cmd) - 1] = '\0';
1478 return wpa_ctrl_command(ctrl, cmd);
1479 }
1482 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1483 {
1484 printf("Available interfaces:\n");
1485 return wpa_ctrl_command(ctrl, "INTERFACES");
1486 }
1489 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1490 {
1491 if (argc < 1) {
1492 wpa_cli_list_interfaces(ctrl);
1493 return 0;
1494 }
1496 wpa_cli_close_connection();
1497 os_free(ctrl_ifname);
1498 ctrl_ifname = os_strdup(argv[0]);
1500 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1501 printf("Connected to interface '%s.\n", ctrl_ifname);
1502 } else {
1503 printf("Could not connect to interface '%s' - re-trying\n",
1504 ctrl_ifname);
1505 }
1506 return 0;
1507 }
1510 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1511 char *argv[])
1512 {
1513 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1514 }
1517 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1518 char *argv[])
1519 {
1520 return wpa_ctrl_command(ctrl, "TERMINATE");
1521 }
1524 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1525 char *argv[])
1526 {
1527 char cmd[256];
1528 int res;
1530 if (argc < 1) {
1531 printf("Invalid INTERFACE_ADD command: needs at least one "
1532 "argument (interface name)\n"
1533 "All arguments: ifname confname driver ctrl_interface "
1534 "driver_param bridge_name\n");
1535 return -1;
1536 }
1538 /*
1539 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1540 * <driver_param>TAB<bridge_name>
1541 */
1542 res = os_snprintf(cmd, sizeof(cmd),
1543 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1544 argv[0],
1545 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1546 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1547 argc > 5 ? argv[5] : "");
1548 if (res < 0 || (size_t) res >= sizeof(cmd))
1549 return -1;
1550 cmd[sizeof(cmd) - 1] = '\0';
1551 return wpa_ctrl_command(ctrl, cmd);
1552 }
1555 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1556 char *argv[])
1557 {
1558 char cmd[128];
1559 int res;
1561 if (argc != 1) {
1562 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1563 "(interface name)\n");
1564 return -1;
1565 }
1567 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1568 if (res < 0 || (size_t) res >= sizeof(cmd))
1569 return -1;
1570 cmd[sizeof(cmd) - 1] = '\0';
1571 return wpa_ctrl_command(ctrl, cmd);
1572 }
1575 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1576 char *argv[])
1577 {
1578 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1579 }
1582 #ifdef CONFIG_AP
1583 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1584 {
1585 char buf[64];
1586 if (argc != 1) {
1587 printf("Invalid 'sta' command - exactly one argument, STA "
1588 "address, is required.\n");
1589 return -1;
1590 }
1591 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1592 return wpa_ctrl_command(ctrl, buf);
1593 }
1596 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1597 char *addr, size_t addr_len)
1598 {
1599 char buf[4096], *pos;
1600 size_t len;
1601 int ret;
1603 if (ctrl_conn == NULL) {
1604 printf("Not connected to hostapd - command dropped.\n");
1605 return -1;
1606 }
1607 len = sizeof(buf) - 1;
1608 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1609 wpa_cli_msg_cb);
1610 if (ret == -2) {
1611 printf("'%s' command timed out.\n", cmd);
1612 return -2;
1613 } else if (ret < 0) {
1614 printf("'%s' command failed.\n", cmd);
1615 return -1;
1616 }
1618 buf[len] = '\0';
1619 if (memcmp(buf, "FAIL", 4) == 0)
1620 return -1;
1621 printf("%s", buf);
1623 pos = buf;
1624 while (*pos != '\0' && *pos != '\n')
1625 pos++;
1626 *pos = '\0';
1627 os_strlcpy(addr, buf, addr_len);
1628 return 0;
1629 }
1632 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1633 {
1634 char addr[32], cmd[64];
1636 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1637 return 0;
1638 do {
1639 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1640 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1642 return -1;
1643 }
1644 #endif /* CONFIG_AP */
1647 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1648 {
1649 return wpa_ctrl_command(ctrl, "SUSPEND");
1650 }
1653 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1654 {
1655 return wpa_ctrl_command(ctrl, "RESUME");
1656 }
1659 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1660 {
1661 return wpa_ctrl_command(ctrl, "DROP_SA");
1662 }
1665 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1666 {
1667 char cmd[128];
1668 int res;
1670 if (argc != 1) {
1671 printf("Invalid ROAM command: needs one argument "
1672 "(target AP's BSSID)\n");
1673 return -1;
1674 }
1676 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1677 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1678 printf("Too long ROAM command.\n");
1679 return -1;
1680 }
1681 return wpa_ctrl_command(ctrl, cmd);
1682 }
1685 #ifdef CONFIG_P2P
1687 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1688 {
1689 char cmd[128];
1690 int res;
1692 if (argc == 0)
1693 return wpa_ctrl_command(ctrl, "P2P_FIND");
1695 if (argc > 1)
1696 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1697 argv[0], argv[1]);
1698 else
1699 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1700 if (res < 0 || (size_t) res >= sizeof(cmd))
1701 return -1;
1702 cmd[sizeof(cmd) - 1] = '\0';
1703 return wpa_ctrl_command(ctrl, cmd);
1704 }
1707 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1708 char *argv[])
1709 {
1710 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1711 }
1714 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1715 char *argv[])
1716 {
1717 char cmd[128];
1718 int res;
1720 if (argc < 2) {
1721 printf("Invalid P2P_CONNECT command: needs at least two "
1722 "arguments (address and pbc/PIN)\n");
1723 return -1;
1724 }
1726 if (argc > 4)
1727 res = os_snprintf(cmd, sizeof(cmd),
1728 "P2P_CONNECT %s %s %s %s %s",
1729 argv[0], argv[1], argv[2], argv[3],
1730 argv[4]);
1731 else if (argc > 3)
1732 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1733 argv[0], argv[1], argv[2], argv[3]);
1734 else if (argc > 2)
1735 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1736 argv[0], argv[1], argv[2]);
1737 else
1738 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1739 argv[0], argv[1]);
1740 if (res < 0 || (size_t) res >= sizeof(cmd))
1741 return -1;
1742 cmd[sizeof(cmd) - 1] = '\0';
1743 return wpa_ctrl_command(ctrl, cmd);
1744 }
1747 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1748 char *argv[])
1749 {
1750 char cmd[128];
1751 int res;
1753 if (argc == 0)
1754 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1756 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
1757 if (res < 0 || (size_t) res >= sizeof(cmd))
1758 return -1;
1759 cmd[sizeof(cmd) - 1] = '\0';
1760 return wpa_ctrl_command(ctrl, cmd);
1761 }
1764 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1765 char *argv[])
1766 {
1767 char cmd[128];
1768 int res;
1770 if (argc != 1) {
1771 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1772 "(interface name)\n");
1773 return -1;
1774 }
1776 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1777 if (res < 0 || (size_t) res >= sizeof(cmd))
1778 return -1;
1779 cmd[sizeof(cmd) - 1] = '\0';
1780 return wpa_ctrl_command(ctrl, cmd);
1781 }
1784 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1785 char *argv[])
1786 {
1787 char cmd[128];
1788 int res;
1790 if (argc == 0)
1791 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1793 if (argc > 1)
1794 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s %s",
1795 argv[0], argv[1]);
1796 else
1797 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s",
1798 argv[0]);
1799 if (res < 0 || (size_t) res >= sizeof(cmd))
1800 return -1;
1801 cmd[sizeof(cmd) - 1] = '\0';
1802 return wpa_ctrl_command(ctrl, cmd);
1803 }
1806 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1807 char *argv[])
1808 {
1809 char cmd[128];
1810 int res;
1812 if (argc != 2) {
1813 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1814 "(address and config method\n"
1815 "(display, keypad, or pbc)\n");
1816 return -1;
1817 }
1819 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1820 argv[0], argv[1]);
1821 if (res < 0 || (size_t) res >= sizeof(cmd))
1822 return -1;
1823 cmd[sizeof(cmd) - 1] = '\0';
1824 return wpa_ctrl_command(ctrl, cmd);
1825 }
1828 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1829 char *argv[])
1830 {
1831 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1832 }
1835 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1836 char *argv[])
1837 {
1838 char cmd[4096];
1839 int res;
1841 if (argc != 2 && argc != 4) {
1842 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1843 "arguments (address and TLVs) or four arguments "
1844 "(address, \"upnp\", version, search target "
1845 "(SSDP ST:)\n");
1846 return -1;
1847 }
1849 if (argc == 4)
1850 res = os_snprintf(cmd, sizeof(cmd),
1851 "P2P_SERV_DISC_REQ %s %s %s %s",
1852 argv[0], argv[1], argv[2], argv[3]);
1853 else
1854 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1855 argv[0], argv[1]);
1856 if (res < 0 || (size_t) res >= sizeof(cmd))
1857 return -1;
1858 cmd[sizeof(cmd) - 1] = '\0';
1859 return wpa_ctrl_command(ctrl, cmd);
1860 }
1863 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1864 int argc, char *argv[])
1865 {
1866 char cmd[128];
1867 int res;
1869 if (argc != 1) {
1870 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1871 "argument (pending request identifier)\n");
1872 return -1;
1873 }
1875 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1876 argv[0]);
1877 if (res < 0 || (size_t) res >= sizeof(cmd))
1878 return -1;
1879 cmd[sizeof(cmd) - 1] = '\0';
1880 return wpa_ctrl_command(ctrl, cmd);
1881 }
1884 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1885 char *argv[])
1886 {
1887 char cmd[4096];
1888 int res;
1890 if (argc != 4) {
1891 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1892 "arguments (freq, address, dialog token, and TLVs)\n");
1893 return -1;
1894 }
1896 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1897 argv[0], argv[1], argv[2], argv[3]);
1898 if (res < 0 || (size_t) res >= sizeof(cmd))
1899 return -1;
1900 cmd[sizeof(cmd) - 1] = '\0';
1901 return wpa_ctrl_command(ctrl, cmd);
1902 }
1905 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1906 char *argv[])
1907 {
1908 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1909 }
1912 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1913 int argc, char *argv[])
1914 {
1915 char cmd[128];
1916 int res;
1918 if (argc != 1) {
1919 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1920 "argument (external processing: 0/1)\n");
1921 return -1;
1922 }
1924 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1925 argv[0]);
1926 if (res < 0 || (size_t) res >= sizeof(cmd))
1927 return -1;
1928 cmd[sizeof(cmd) - 1] = '\0';
1929 return wpa_ctrl_command(ctrl, cmd);
1930 }
1933 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1934 char *argv[])
1935 {
1936 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1937 }
1940 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1941 char *argv[])
1942 {
1943 char cmd[4096];
1944 int res;
1946 if (argc != 3 && argc != 4) {
1947 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1948 "arguments\n");
1949 return -1;
1950 }
1952 if (argc == 4)
1953 res = os_snprintf(cmd, sizeof(cmd),
1954 "P2P_SERVICE_ADD %s %s %s %s",
1955 argv[0], argv[1], argv[2], argv[3]);
1956 else
1957 res = os_snprintf(cmd, sizeof(cmd),
1958 "P2P_SERVICE_ADD %s %s %s",
1959 argv[0], argv[1], argv[2]);
1960 if (res < 0 || (size_t) res >= sizeof(cmd))
1961 return -1;
1962 cmd[sizeof(cmd) - 1] = '\0';
1963 return wpa_ctrl_command(ctrl, cmd);
1964 }
1967 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1968 char *argv[])
1969 {
1970 char cmd[4096];
1971 int res;
1973 if (argc != 2 && argc != 3) {
1974 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1975 "arguments\n");
1976 return -1;
1977 }
1979 if (argc == 3)
1980 res = os_snprintf(cmd, sizeof(cmd),
1981 "P2P_SERVICE_DEL %s %s %s",
1982 argv[0], argv[1], argv[2]);
1983 else
1984 res = os_snprintf(cmd, sizeof(cmd),
1985 "P2P_SERVICE_DEL %s %s",
1986 argv[0], argv[1]);
1987 if (res < 0 || (size_t) res >= sizeof(cmd))
1988 return -1;
1989 cmd[sizeof(cmd) - 1] = '\0';
1990 return wpa_ctrl_command(ctrl, cmd);
1991 }
1994 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1995 int argc, char *argv[])
1996 {
1997 char cmd[128];
1998 int res;
2000 if (argc != 1) {
2001 printf("Invalid P2P_REJECT command: needs one argument "
2002 "(peer address)\n");
2003 return -1;
2004 }
2006 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
2007 if (res < 0 || (size_t) res >= sizeof(cmd))
2008 return -1;
2009 cmd[sizeof(cmd) - 1] = '\0';
2010 return wpa_ctrl_command(ctrl, cmd);
2011 }
2014 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2015 int argc, char *argv[])
2016 {
2017 char cmd[128];
2018 int res;
2020 if (argc < 1) {
2021 printf("Invalid P2P_INVITE command: needs at least one "
2022 "argument\n");
2023 return -1;
2024 }
2026 if (argc > 2)
2027 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
2028 argv[0], argv[1], argv[2]);
2029 else if (argc > 1)
2030 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
2031 argv[0], argv[1]);
2032 else
2033 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
2034 if (res < 0 || (size_t) res >= sizeof(cmd))
2035 return -1;
2036 cmd[sizeof(cmd) - 1] = '\0';
2037 return wpa_ctrl_command(ctrl, cmd);
2038 }
2041 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2042 {
2043 char buf[64];
2044 if (argc != 1) {
2045 printf("Invalid 'p2p_peer' command - exactly one argument, "
2046 "P2P peer device address, is required.\n");
2047 return -1;
2048 }
2049 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
2050 return wpa_ctrl_command(ctrl, buf);
2051 }
2054 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2055 char *addr, size_t addr_len,
2056 int discovered)
2057 {
2058 char buf[4096], *pos;
2059 size_t len;
2060 int ret;
2062 if (ctrl_conn == NULL)
2063 return -1;
2064 len = sizeof(buf) - 1;
2065 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
2066 wpa_cli_msg_cb);
2067 if (ret == -2) {
2068 printf("'%s' command timed out.\n", cmd);
2069 return -2;
2070 } else if (ret < 0) {
2071 printf("'%s' command failed.\n", cmd);
2072 return -1;
2073 }
2075 buf[len] = '\0';
2076 if (memcmp(buf, "FAIL", 4) == 0)
2077 return -1;
2079 pos = buf;
2080 while (*pos != '\0' && *pos != '\n')
2081 pos++;
2082 *pos++ = '\0';
2083 os_strlcpy(addr, buf, addr_len);
2084 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2085 printf("%s\n", addr);
2086 return 0;
2087 }
2090 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2091 {
2092 char addr[32], cmd[64];
2093 int discovered;
2095 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2097 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2098 addr, sizeof(addr), discovered))
2099 return 0;
2100 do {
2101 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2102 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2103 discovered) == 0);
2105 return -1;
2106 }
2109 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2110 {
2111 char cmd[100];
2112 int res;
2114 if (argc != 2) {
2115 printf("Invalid P2P_SET command: needs two arguments (field, "
2116 "value)\n");
2117 return -1;
2118 }
2120 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2121 if (res < 0 || (size_t) res >= sizeof(cmd))
2122 return -1;
2123 cmd[sizeof(cmd) - 1] = '\0';
2124 return wpa_ctrl_command(ctrl, cmd);
2125 }
2128 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2129 {
2130 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2131 }
2134 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2135 char *argv[])
2136 {
2137 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2138 }
2141 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2142 char *argv[])
2143 {
2144 char cmd[100];
2145 int res;
2147 if (argc != 1) {
2148 printf("Invalid P2P_UNAUTHORIZE command: needs one argument "
2149 "(peer address)\n");
2150 return -1;
2151 }
2153 res = os_snprintf(cmd, sizeof(cmd), "P2P_UNAUTHORIZE %s", argv[0]);
2155 if (res < 0 || (size_t) res >= sizeof(cmd))
2156 return -1;
2158 cmd[sizeof(cmd) - 1] = '\0';
2159 return wpa_ctrl_command(ctrl, cmd);
2160 }
2163 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2164 char *argv[])
2165 {
2166 char cmd[100];
2167 int res;
2169 if (argc != 0 && argc != 2 && argc != 4) {
2170 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2171 "(preferred duration, interval; in microsecods).\n"
2172 "Optional second pair can be used to provide "
2173 "acceptable values.\n");
2174 return -1;
2175 }
2177 if (argc == 4)
2178 res = os_snprintf(cmd, sizeof(cmd),
2179 "P2P_PRESENCE_REQ %s %s %s %s",
2180 argv[0], argv[1], argv[2], argv[3]);
2181 else if (argc == 2)
2182 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2183 argv[0], argv[1]);
2184 else
2185 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2186 if (res < 0 || (size_t) res >= sizeof(cmd))
2187 return -1;
2188 cmd[sizeof(cmd) - 1] = '\0';
2189 return wpa_ctrl_command(ctrl, cmd);
2190 }
2193 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195 {
2196 char cmd[100];
2197 int res;
2199 if (argc != 0 && argc != 2) {
2200 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2201 "(availability period, availability interval; in "
2202 "millisecods).\n"
2203 "Extended Listen Timing can be cancelled with this "
2204 "command when used without parameters.\n");
2205 return -1;
2206 }
2208 if (argc == 2)
2209 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2210 argv[0], argv[1]);
2211 else
2212 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2213 if (res < 0 || (size_t) res >= sizeof(cmd))
2214 return -1;
2215 cmd[sizeof(cmd) - 1] = '\0';
2216 return wpa_ctrl_command(ctrl, cmd);
2217 }
2219 #endif /* CONFIG_P2P */
2222 #ifdef CONFIG_INTERWORKING
2223 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2224 char *argv[])
2225 {
2226 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2227 }
2230 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2231 char *argv[])
2232 {
2233 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2234 }
2237 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2238 {
2239 char cmd[100];
2240 int res;
2242 if (argc != 2) {
2243 printf("Invalid ANQP_GET command: needs two arguments "
2244 "(addr and info id list)\n");
2245 return -1;
2246 }
2248 res = os_snprintf(cmd, sizeof(cmd), "ANQP_GET %s %s",
2249 argv[0], argv[1]);
2250 if (res < 0 || (size_t) res >= sizeof(cmd))
2251 return -1;
2252 cmd[sizeof(cmd) - 1] = '\0';
2253 return wpa_ctrl_command(ctrl, cmd);
2254 }
2255 #endif /* CONFIG_INTERWORKING */
2258 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260 {
2261 char cmd[256];
2262 int res;
2264 if (argc != 1) {
2265 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2266 "(0/1 = disable/enable automatic reconnection)\n");
2267 return -1;
2268 }
2269 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2270 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2271 printf("Too long STA_AUTOCONNECT command.\n");
2272 return -1;
2273 }
2274 return wpa_ctrl_command(ctrl, cmd);
2275 }
2278 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280 {
2281 char cmd[256];
2282 int res;
2284 if (argc != 1) {
2285 printf("Invalid TDLS_DISCOVER command: needs one argument "
2286 "(Peer STA MAC address)\n");
2287 return -1;
2288 }
2290 res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
2291 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2292 printf("Too long TDLS_DISCOVER command.\n");
2293 return -1;
2294 }
2295 return wpa_ctrl_command(ctrl, cmd);
2296 }
2299 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2300 char *argv[])
2301 {
2302 char cmd[256];
2303 int res;
2305 if (argc != 1) {
2306 printf("Invalid TDLS_SETUP command: needs one argument "
2307 "(Peer STA MAC address)\n");
2308 return -1;
2309 }
2311 res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
2312 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2313 printf("Too long TDLS_SETUP command.\n");
2314 return -1;
2315 }
2316 return wpa_ctrl_command(ctrl, cmd);
2317 }
2320 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2321 char *argv[])
2322 {
2323 char cmd[256];
2324 int res;
2326 if (argc != 1) {
2327 printf("Invalid TDLS_TEARDOWN command: needs one argument "
2328 "(Peer STA MAC address)\n");
2329 return -1;
2330 }
2332 res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
2333 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2334 printf("Too long TDLS_TEARDOWN command.\n");
2335 return -1;
2336 }
2337 return wpa_ctrl_command(ctrl, cmd);
2338 }
2341 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2342 char *argv[])
2343 {
2344 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2345 }
2348 enum wpa_cli_cmd_flags {
2349 cli_cmd_flag_none = 0x00,
2350 cli_cmd_flag_sensitive = 0x01
2351 };
2353 struct wpa_cli_cmd {
2354 const char *cmd;
2355 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2356 enum wpa_cli_cmd_flags flags;
2357 const char *usage;
2358 };
2360 static struct wpa_cli_cmd wpa_cli_commands[] = {
2361 { "status", wpa_cli_cmd_status,
2362 cli_cmd_flag_none,
2363 "[verbose] = get current WPA/EAPOL/EAP status" },
2364 { "ping", wpa_cli_cmd_ping,
2365 cli_cmd_flag_none,
2366 "= pings wpa_supplicant" },
2367 { "relog", wpa_cli_cmd_relog,
2368 cli_cmd_flag_none,
2369 "= re-open log-file (allow rolling logs)" },
2370 { "note", wpa_cli_cmd_note,
2371 cli_cmd_flag_none,
2372 "<text> = add a note to wpa_supplicant debug log" },
2373 { "mib", wpa_cli_cmd_mib,
2374 cli_cmd_flag_none,
2375 "= get MIB variables (dot1x, dot11)" },
2376 { "help", wpa_cli_cmd_help,
2377 cli_cmd_flag_none,
2378 "= show this usage help" },
2379 { "interface", wpa_cli_cmd_interface,
2380 cli_cmd_flag_none,
2381 "[ifname] = show interfaces/select interface" },
2382 { "level", wpa_cli_cmd_level,
2383 cli_cmd_flag_none,
2384 "<debug level> = change debug level" },
2385 { "license", wpa_cli_cmd_license,
2386 cli_cmd_flag_none,
2387 "= show full wpa_cli license" },
2388 { "quit", wpa_cli_cmd_quit,
2389 cli_cmd_flag_none,
2390 "= exit wpa_cli" },
2391 { "set", wpa_cli_cmd_set,
2392 cli_cmd_flag_none,
2393 "= set variables (shows list of variables when run without "
2394 "arguments)" },
2395 { "get", wpa_cli_cmd_get,
2396 cli_cmd_flag_none,
2397 "<name> = get information" },
2398 { "logon", wpa_cli_cmd_logon,
2399 cli_cmd_flag_none,
2400 "= IEEE 802.1X EAPOL state machine logon" },
2401 { "logoff", wpa_cli_cmd_logoff,
2402 cli_cmd_flag_none,
2403 "= IEEE 802.1X EAPOL state machine logoff" },
2404 { "pmksa", wpa_cli_cmd_pmksa,
2405 cli_cmd_flag_none,
2406 "= show PMKSA cache" },
2407 { "reassociate", wpa_cli_cmd_reassociate,
2408 cli_cmd_flag_none,
2409 "= force reassociation" },
2410 { "preauthenticate", wpa_cli_cmd_preauthenticate,
2411 cli_cmd_flag_none,
2412 "<BSSID> = force preauthentication" },
2413 { "identity", wpa_cli_cmd_identity,
2414 cli_cmd_flag_none,
2415 "<network id> <identity> = configure identity for an SSID" },
2416 { "password", wpa_cli_cmd_password,
2417 cli_cmd_flag_sensitive,
2418 "<network id> <password> = configure password for an SSID" },
2419 { "new_password", wpa_cli_cmd_new_password,
2420 cli_cmd_flag_sensitive,
2421 "<network id> <password> = change password for an SSID" },
2422 { "pin", wpa_cli_cmd_pin,
2423 cli_cmd_flag_sensitive,
2424 "<network id> <pin> = configure pin for an SSID" },
2425 { "otp", wpa_cli_cmd_otp,
2426 cli_cmd_flag_sensitive,
2427 "<network id> <password> = configure one-time-password for an SSID"
2428 },
2429 { "passphrase", wpa_cli_cmd_passphrase,
2430 cli_cmd_flag_sensitive,
2431 "<network id> <passphrase> = configure private key passphrase\n"
2432 " for an SSID" },
2433 { "bssid", wpa_cli_cmd_bssid,
2434 cli_cmd_flag_none,
2435 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2436 { "list_networks", wpa_cli_cmd_list_networks,
2437 cli_cmd_flag_none,
2438 "= list configured networks" },
2439 { "select_network", wpa_cli_cmd_select_network,
2440 cli_cmd_flag_none,
2441 "<network id> = select a network (disable others)" },
2442 { "enable_network", wpa_cli_cmd_enable_network,
2443 cli_cmd_flag_none,
2444 "<network id> = enable a network" },
2445 { "disable_network", wpa_cli_cmd_disable_network,
2446 cli_cmd_flag_none,
2447 "<network id> = disable a network" },
2448 { "add_network", wpa_cli_cmd_add_network,
2449 cli_cmd_flag_none,
2450 "= add a network" },
2451 { "remove_network", wpa_cli_cmd_remove_network,
2452 cli_cmd_flag_none,
2453 "<network id> = remove a network" },
2454 { "set_network", wpa_cli_cmd_set_network,
2455 cli_cmd_flag_sensitive,
2456 "<network id> <variable> <value> = set network variables (shows\n"
2457 " list of variables when run without arguments)" },
2458 { "get_network", wpa_cli_cmd_get_network,
2459 cli_cmd_flag_none,
2460 "<network id> <variable> = get network variables" },
2461 { "save_config", wpa_cli_cmd_save_config,
2462 cli_cmd_flag_none,
2463 "= save the current configuration" },
2464 { "disconnect", wpa_cli_cmd_disconnect,
2465 cli_cmd_flag_none,
2466 "= disconnect and wait for reassociate/reconnect command before\n"
2467 " connecting" },
2468 { "reconnect", wpa_cli_cmd_reconnect,
2469 cli_cmd_flag_none,
2470 "= like reassociate, but only takes effect if already disconnected"
2471 },
2472 { "scan", wpa_cli_cmd_scan,
2473 cli_cmd_flag_none,
2474 "= request new BSS scan" },
2475 { "scan_results", wpa_cli_cmd_scan_results,
2476 cli_cmd_flag_none,
2477 "= get latest scan results" },
2478 { "bss", wpa_cli_cmd_bss,
2479 cli_cmd_flag_none,
2480 "<<idx> | <bssid>> = get detailed scan result info" },
2481 { "get_capability", wpa_cli_cmd_get_capability,
2482 cli_cmd_flag_none,
2483 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2484 { "reconfigure", wpa_cli_cmd_reconfigure,
2485 cli_cmd_flag_none,
2486 "= force wpa_supplicant to re-read its configuration file" },
2487 { "terminate", wpa_cli_cmd_terminate,
2488 cli_cmd_flag_none,
2489 "= terminate wpa_supplicant" },
2490 { "interface_add", wpa_cli_cmd_interface_add,
2491 cli_cmd_flag_none,
2492 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2493 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2494 " are optional" },
2495 { "interface_remove", wpa_cli_cmd_interface_remove,
2496 cli_cmd_flag_none,
2497 "<ifname> = removes the interface" },
2498 { "interface_list", wpa_cli_cmd_interface_list,
2499 cli_cmd_flag_none,
2500 "= list available interfaces" },
2501 { "ap_scan", wpa_cli_cmd_ap_scan,
2502 cli_cmd_flag_none,
2503 "<value> = set ap_scan parameter" },
2504 { "scan_interval", wpa_cli_cmd_scan_interval,
2505 cli_cmd_flag_none,
2506 "<value> = set scan_interval parameter (in seconds)" },
2507 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2508 cli_cmd_flag_none,
2509 "<value> = set BSS expiration age parameter" },
2510 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2511 cli_cmd_flag_none,
2512 "<value> = set BSS expiration scan count parameter" },
2513 { "stkstart", wpa_cli_cmd_stkstart,
2514 cli_cmd_flag_none,
2515 "<addr> = request STK negotiation with <addr>" },
2516 { "ft_ds", wpa_cli_cmd_ft_ds,
2517 cli_cmd_flag_none,
2518 "<addr> = request over-the-DS FT with <addr>" },
2519 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2520 cli_cmd_flag_none,
2521 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2522 { "wps_pin", wpa_cli_cmd_wps_pin,
2523 cli_cmd_flag_sensitive,
2524 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2525 "hardcoded)" },
2526 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2527 cli_cmd_flag_sensitive,
2528 "<PIN> = verify PIN checksum" },
2529 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2530 "Cancels the pending WPS operation" },
2531 #ifdef CONFIG_WPS_OOB
2532 { "wps_oob", wpa_cli_cmd_wps_oob,
2533 cli_cmd_flag_sensitive,
2534 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2535 #endif /* CONFIG_WPS_OOB */
2536 { "wps_reg", wpa_cli_cmd_wps_reg,
2537 cli_cmd_flag_sensitive,
2538 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2539 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
2540 cli_cmd_flag_sensitive,
2541 "[params..] = enable/disable AP PIN" },
2542 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2543 cli_cmd_flag_none,
2544 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2545 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2546 cli_cmd_flag_none,
2547 "= stop Wi-Fi Protected Setup External Registrar" },
2548 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2549 cli_cmd_flag_sensitive,
2550 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2551 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2552 cli_cmd_flag_none,
2553 "<UUID> = accept an Enrollee PBC using External Registrar" },
2554 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2555 cli_cmd_flag_sensitive,
2556 "<UUID> <PIN> = learn AP configuration" },
2557 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2558 cli_cmd_flag_none,
2559 "<UUID> <network id> = set AP configuration for enrolling" },
2560 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2561 cli_cmd_flag_sensitive,
2562 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2563 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2564 cli_cmd_flag_none,
2565 "<addr> = request RSN authentication with <addr> in IBSS" },
2566 #ifdef CONFIG_AP
2567 { "sta", wpa_cli_cmd_sta,
2568 cli_cmd_flag_none,
2569 "<addr> = get information about an associated station (AP)" },
2570 { "all_sta", wpa_cli_cmd_all_sta,
2571 cli_cmd_flag_none,
2572 "= get information about all associated stations (AP)" },
2573 #endif /* CONFIG_AP */
2574 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2575 "= notification of suspend/hibernate" },
2576 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2577 "= notification of resume/thaw" },
2578 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2579 "= drop SA without deauth/disassoc (test command)" },
2580 { "roam", wpa_cli_cmd_roam,
2581 cli_cmd_flag_none,
2582 "<addr> = roam to the specified BSS" },
2583 #ifdef CONFIG_P2P
2584 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2585 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2586 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2587 "= stop P2P Devices search" },
2588 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2589 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2590 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2591 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2592 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2593 "<ifname> = remove P2P group interface (terminate group if GO)" },
2594 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2595 "= add a new P2P group (local end as GO)" },
2596 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2597 "<addr> <method> = request provisioning discovery" },
2598 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2599 cli_cmd_flag_none,
2600 "= get the passphrase for a group (GO only)" },
2601 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2602 cli_cmd_flag_none,
2603 "<addr> <TLVs> = schedule service discovery request" },
2604 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2605 cli_cmd_flag_none,
2606 "<id> = cancel pending service discovery request" },
2607 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2608 cli_cmd_flag_none,
2609 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2610 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2611 cli_cmd_flag_none,
2612 "= indicate change in local services" },
2613 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2614 cli_cmd_flag_none,
2615 "<external> = set external processing of service discovery" },
2616 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2617 cli_cmd_flag_none,
2618 "= remove all stored service entries" },
2619 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2620 cli_cmd_flag_none,
2621 "<bonjour|upnp> <query|version> <response|service> = add a local "
2622 "service" },
2623 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2624 cli_cmd_flag_none,
2625 "<bonjour|upnp> <query|version> [|service] = remove a local "
2626 "service" },
2627 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2628 cli_cmd_flag_none,
2629 "<addr> = reject connection attempts from a specific peer" },
2630 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2631 cli_cmd_flag_none,
2632 "<cmd> [peer=addr] = invite peer" },
2633 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2634 "[discovered] = list known (optionally, only fully discovered) P2P "
2635 "peers" },
2636 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2637 "<address> = show information about known P2P peer" },
2638 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2639 "<field> <value> = set a P2P parameter" },
2640 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2641 "= flush P2P state" },
2642 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2643 "= cancel P2P group formation" },
2644 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
2645 "<address> = unauthorize a peer" },
2646 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2647 "[<duration> <interval>] [<duration> <interval>] = request GO "
2648 "presence" },
2649 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2650 "[<period> <interval>] = set extended listen timing" },
2651 #endif /* CONFIG_P2P */
2653 #ifdef CONFIG_INTERWORKING
2654 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
2655 "= fetch ANQP information for all APs" },
2656 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
2657 "= stop fetch_anqp operation" },
2658 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
2659 "<addr> <info id>[,<info id>]... = request ANQP information" },
2660 #endif /* CONFIG_INTERWORKING */
2661 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2662 "<0/1> = disable/enable automatic reconnection" },
2663 { "tdls_discover", wpa_cli_cmd_tdls_discover,
2664 cli_cmd_flag_none,
2665 "<addr> = request TDLS discovery with <addr>" },
2666 { "tdls_setup", wpa_cli_cmd_tdls_setup,
2667 cli_cmd_flag_none,
2668 "<addr> = request TDLS setup with <addr>" },
2669 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
2670 cli_cmd_flag_none,
2671 "<addr> = tear down TDLS with <addr>" },
2672 { "signal_poll", wpa_cli_cmd_signal_poll,
2673 cli_cmd_flag_none,
2674 "= get signal parameters" },
2675 { NULL, NULL, cli_cmd_flag_none, NULL }
2676 };
2679 /*
2680 * Prints command usage, lines are padded with the specified string.
2681 */
2682 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2683 {
2684 char c;
2685 size_t n;
2687 printf("%s%s ", pad, cmd->cmd);
2688 for (n = 0; (c = cmd->usage[n]); n++) {
2689 printf("%c", c);
2690 if (c == '\n')
2691 printf("%s", pad);
2692 }
2693 printf("\n");
2694 }
2697 static void print_help(void)
2698 {
2699 int n;
2700 printf("commands:\n");
2701 for (n = 0; wpa_cli_commands[n].cmd; n++)
2702 print_cmd_help(&wpa_cli_commands[n], " ");
2703 }
2706 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2707 {
2708 const char *c, *delim;
2709 int n;
2710 size_t len;
2712 delim = os_strchr(cmd, ' ');
2713 if (delim)
2714 len = delim - cmd;
2715 else
2716 len = os_strlen(cmd);
2718 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2719 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2720 return (wpa_cli_commands[n].flags &
2721 cli_cmd_flag_sensitive);
2722 }
2723 return 0;
2724 }
2727 static char ** wpa_list_cmd_list(void)
2728 {
2729 char **res;
2730 int i, count;
2732 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
2733 res = os_zalloc(count * sizeof(char *));
2734 if (res == NULL)
2735 return NULL;
2737 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2738 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2739 if (res[i] == NULL)
2740 break;
2741 }
2743 return res;
2744 }
2747 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2748 int pos)
2749 {
2750 int i;
2752 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2753 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2754 edit_clear_line();
2755 printf("\r%s\n", wpa_cli_commands[i].usage);
2756 edit_redraw();
2757 break;
2758 }
2759 }
2761 return NULL;
2762 }
2765 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2766 {
2767 char **res;
2768 const char *end;
2769 char *cmd;
2771 end = os_strchr(str, ' ');
2772 if (end == NULL || str + pos < end)
2773 return wpa_list_cmd_list();
2775 cmd = os_malloc(pos + 1);
2776 if (cmd == NULL)
2777 return NULL;
2778 os_memcpy(cmd, str, pos);
2779 cmd[end - str] = '\0';
2780 res = wpa_cli_cmd_completion(cmd, str, pos);
2781 os_free(cmd);
2782 return res;
2783 }
2786 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2787 {
2788 struct wpa_cli_cmd *cmd, *match = NULL;
2789 int count;
2790 int ret = 0;
2792 count = 0;
2793 cmd = wpa_cli_commands;
2794 while (cmd->cmd) {
2795 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2796 {
2797 match = cmd;
2798 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2799 /* we have an exact match */
2800 count = 1;
2801 break;
2802 }
2803 count++;
2804 }
2805 cmd++;
2806 }
2808 if (count > 1) {
2809 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2810 cmd = wpa_cli_commands;
2811 while (cmd->cmd) {
2812 if (os_strncasecmp(cmd->cmd, argv[0],
2813 os_strlen(argv[0])) == 0) {
2814 printf(" %s", cmd->cmd);
2815 }
2816 cmd++;
2817 }
2818 printf("\n");
2819 ret = 1;
2820 } else if (count == 0) {
2821 printf("Unknown command '%s'\n", argv[0]);
2822 ret = 1;
2823 } else {
2824 ret = match->handler(ctrl, argc - 1, &argv[1]);
2825 }
2827 return ret;
2828 }
2831 static int str_match(const char *a, const char *b)
2832 {
2833 return os_strncmp(a, b, os_strlen(b)) == 0;
2834 }
2837 static int wpa_cli_exec(const char *program, const char *arg1,
2838 const char *arg2)
2839 {
2840 char *cmd;
2841 size_t len;
2842 int res;
2843 int ret = 0;
2845 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2846 cmd = os_malloc(len);
2847 if (cmd == NULL)
2848 return -1;
2849 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2850 if (res < 0 || (size_t) res >= len) {
2851 os_free(cmd);
2852 return -1;
2853 }
2854 cmd[len - 1] = '\0';
2855 #ifndef _WIN32_WCE
2856 if (system(cmd) < 0)
2857 ret = -1;
2858 #endif /* _WIN32_WCE */
2859 os_free(cmd);
2861 return ret;
2862 }
2865 static void wpa_cli_action_process(const char *msg)
2866 {
2867 const char *pos;
2868 char *copy = NULL, *id, *pos2;
2870 pos = msg;
2871 if (*pos == '<') {
2872 /* skip priority */
2873 pos = os_strchr(pos, '>');
2874 if (pos)
2875 pos++;
2876 else
2877 pos = msg;
2878 }
2880 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2881 int new_id = -1;
2882 os_unsetenv("WPA_ID");
2883 os_unsetenv("WPA_ID_STR");
2884 os_unsetenv("WPA_CTRL_DIR");
2886 pos = os_strstr(pos, "[id=");
2887 if (pos)
2888 copy = os_strdup(pos + 4);
2890 if (copy) {
2891 pos2 = id = copy;
2892 while (*pos2 && *pos2 != ' ')
2893 pos2++;
2894 *pos2++ = '\0';
2895 new_id = atoi(id);
2896 os_setenv("WPA_ID", id, 1);
2897 while (*pos2 && *pos2 != '=')
2898 pos2++;
2899 if (*pos2 == '=')
2900 pos2++;
2901 id = pos2;
2902 while (*pos2 && *pos2 != ']')
2903 pos2++;
2904 *pos2 = '\0';
2905 os_setenv("WPA_ID_STR", id, 1);
2906 os_free(copy);
2907 }
2909 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2911 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2912 wpa_cli_connected = 1;
2913 wpa_cli_last_id = new_id;
2914 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2915 }
2916 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2917 if (wpa_cli_connected) {
2918 wpa_cli_connected = 0;
2919 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2920 }
2921 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2922 wpa_cli_exec(action_file, ctrl_ifname, pos);
2923 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2924 wpa_cli_exec(action_file, ctrl_ifname, pos);
2925 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2926 wpa_cli_exec(action_file, ctrl_ifname, pos);
2927 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2928 wpa_cli_exec(action_file, ctrl_ifname, pos);
2929 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2930 wpa_cli_exec(action_file, ctrl_ifname, pos);
2931 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2932 wpa_cli_exec(action_file, ctrl_ifname, pos);
2933 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2934 printf("wpa_supplicant is terminating - stop monitoring\n");
2935 wpa_cli_quit = 1;
2936 }
2937 }
2940 #ifndef CONFIG_ANSI_C_EXTRA
2941 static void wpa_cli_action_cb(char *msg, size_t len)
2942 {
2943 wpa_cli_action_process(msg);
2944 }
2945 #endif /* CONFIG_ANSI_C_EXTRA */
2948 static void wpa_cli_reconnect(void)
2949 {
2950 wpa_cli_close_connection();
2951 wpa_cli_open_connection(ctrl_ifname, 1);
2952 }
2955 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
2956 {
2957 if (ctrl_conn == NULL) {
2958 wpa_cli_reconnect();
2959 return;
2960 }
2961 while (wpa_ctrl_pending(ctrl) > 0) {
2962 char buf[256];
2963 size_t len = sizeof(buf) - 1;
2964 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2965 buf[len] = '\0';
2966 if (action_monitor)
2967 wpa_cli_action_process(buf);
2968 else {
2969 if (wpa_cli_show_event(buf)) {
2970 edit_clear_line();
2971 printf("\r%s\n", buf);
2972 edit_redraw();
2973 }
2974 }
2975 } else {
2976 printf("Could not read pending message.\n");
2977 break;
2978 }
2979 }
2981 if (wpa_ctrl_pending(ctrl) < 0) {
2982 printf("Connection to wpa_supplicant lost - trying to "
2983 "reconnect\n");
2984 wpa_cli_reconnect();
2985 }
2986 }
2988 #define max_args 10
2990 static int tokenize_cmd(char *cmd, char *argv[])
2991 {
2992 char *pos;
2993 int argc = 0;
2995 pos = cmd;
2996 for (;;) {
2997 while (*pos == ' ')
2998 pos++;
2999 if (*pos == '\0')
3000 break;
3001 argv[argc] = pos;
3002 argc++;
3003 if (argc == max_args)
3004 break;
3005 if (*pos == '"') {
3006 char *pos2 = os_strrchr(pos, '"');
3007 if (pos2)
3008 pos = pos2 + 1;
3009 }
3010 while (*pos != '\0' && *pos != ' ')
3011 pos++;
3012 if (*pos == ' ')
3013 *pos++ = '\0';
3014 }
3016 return argc;
3017 }
3020 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3021 {
3022 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3023 printf("Connection to wpa_supplicant lost - trying to "
3024 "reconnect\n");
3025 wpa_cli_close_connection();
3026 }
3027 if (!ctrl_conn)
3028 wpa_cli_reconnect();
3029 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3030 }
3033 static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3034 {
3035 eloop_terminate();
3036 }
3039 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3040 {
3041 wpa_cli_recv_pending(mon_conn, 0);
3042 }
3045 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3046 {
3047 char *argv[max_args];
3048 int argc;
3049 argc = tokenize_cmd(cmd, argv);
3050 if (argc)
3051 wpa_request(ctrl_conn, argc, argv);
3052 }
3055 static void wpa_cli_edit_eof_cb(void *ctx)
3056 {
3057 eloop_terminate();
3058 }
3061 static void wpa_cli_interactive(void)
3062 {
3063 char *home, *hfile = NULL;
3065 printf("\nInteractive mode\n\n");
3067 home = getenv("HOME");
3068 if (home) {
3069 const char *fname = ".wpa_cli_history";
3070 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3071 hfile = os_malloc(hfile_len);
3072 if (hfile)
3073 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3074 }
3076 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3077 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3078 wpa_cli_edit_completion_cb, NULL, hfile);
3079 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3081 eloop_run();
3083 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3084 os_free(hfile);
3085 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3086 wpa_cli_close_connection();
3087 }
3090 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3091 {
3092 #ifdef CONFIG_ANSI_C_EXTRA
3093 /* TODO: ANSI C version(?) */
3094 printf("Action processing not supported in ANSI C build.\n");
3095 #else /* CONFIG_ANSI_C_EXTRA */
3096 fd_set rfds;
3097 int fd, res;
3098 struct timeval tv;
3099 char buf[256]; /* note: large enough to fit in unsolicited messages */
3100 size_t len;
3102 fd = wpa_ctrl_get_fd(ctrl);
3104 while (!wpa_cli_quit) {
3105 FD_ZERO(&rfds);
3106 FD_SET(fd, &rfds);
3107 tv.tv_sec = ping_interval;
3108 tv.tv_usec = 0;
3109 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3110 if (res < 0 && errno != EINTR) {
3111 perror("select");
3112 break;
3113 }
3115 if (FD_ISSET(fd, &rfds))
3116 wpa_cli_recv_pending(ctrl, 1);
3117 else {
3118 /* verify that connection is still working */
3119 len = sizeof(buf) - 1;
3120 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3121 wpa_cli_action_cb) < 0 ||
3122 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3123 printf("wpa_supplicant did not reply to PING "
3124 "command - exiting\n");
3125 break;
3126 }
3127 }
3128 }
3129 #endif /* CONFIG_ANSI_C_EXTRA */
3130 }
3133 static void wpa_cli_cleanup(void)
3134 {
3135 wpa_cli_close_connection();
3136 if (pid_file)
3137 os_daemonize_terminate(pid_file);
3139 os_program_deinit();
3140 }
3142 static void wpa_cli_terminate(int sig)
3143 {
3144 wpa_cli_cleanup();
3145 exit(0);
3146 }
3149 static char * wpa_cli_get_default_ifname(void)
3150 {
3151 char *ifname = NULL;
3153 #ifdef CONFIG_CTRL_IFACE_UNIX
3154 struct dirent *dent;
3155 DIR *dir = opendir(ctrl_iface_dir);
3156 if (!dir) {
3157 #ifdef ANDROID
3158 char ifprop[PROPERTY_VALUE_MAX];
3159 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3160 ifname = os_strdup(ifprop);
3161 printf("Using interface '%s'\n", ifname);
3162 return ifname;
3163 }
3164 #endif /* ANDROID */
3165 return NULL;
3166 }
3167 while ((dent = readdir(dir))) {
3168 #ifdef _DIRENT_HAVE_D_TYPE
3169 /*
3170 * Skip the file if it is not a socket. Also accept
3171 * DT_UNKNOWN (0) in case the C library or underlying
3172 * file system does not support d_type.
3173 */
3174 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3175 continue;
3176 #endif /* _DIRENT_HAVE_D_TYPE */
3177 if (os_strcmp(dent->d_name, ".") == 0 ||
3178 os_strcmp(dent->d_name, "..") == 0)
3179 continue;
3180 printf("Selected interface '%s'\n", dent->d_name);
3181 ifname = os_strdup(dent->d_name);
3182 break;
3183 }
3184 closedir(dir);
3185 #endif /* CONFIG_CTRL_IFACE_UNIX */
3187 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3188 char buf[2048], *pos;
3189 size_t len;
3190 struct wpa_ctrl *ctrl;
3191 int ret;
3193 ctrl = wpa_ctrl_open(NULL);
3194 if (ctrl == NULL)
3195 return NULL;
3197 len = sizeof(buf) - 1;
3198 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3199 if (ret >= 0) {
3200 buf[len] = '\0';
3201 pos = os_strchr(buf, '\n');
3202 if (pos)
3203 *pos = '\0';
3204 ifname = os_strdup(buf);
3205 }
3206 wpa_ctrl_close(ctrl);
3207 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3209 return ifname;
3210 }
3213 int main(int argc, char *argv[])
3214 {
3215 int warning_displayed = 0;
3216 int c;
3217 int daemonize = 0;
3218 int ret = 0;
3219 const char *global = NULL;
3221 if (os_program_init())
3222 return -1;
3224 for (;;) {
3225 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3226 if (c < 0)
3227 break;
3228 switch (c) {
3229 case 'a':
3230 action_file = optarg;
3231 break;
3232 case 'B':
3233 daemonize = 1;
3234 break;
3235 case 'g':
3236 global = optarg;
3237 break;
3238 case 'G':
3239 ping_interval = atoi(optarg);
3240 break;
3241 case 'h':
3242 usage();
3243 return 0;
3244 case 'v':
3245 printf("%s\n", wpa_cli_version);
3246 return 0;
3247 case 'i':
3248 os_free(ctrl_ifname);
3249 ctrl_ifname = os_strdup(optarg);
3250 break;
3251 case 'p':
3252 ctrl_iface_dir = optarg;
3253 break;
3254 case 'P':
3255 pid_file = optarg;
3256 break;
3257 default:
3258 usage();
3259 return -1;
3260 }
3261 }
3263 interactive = (argc == optind) && (action_file == NULL);
3265 if (interactive)
3266 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3268 if (eloop_init())
3269 return -1;
3271 if (global) {
3272 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3273 ctrl_conn = wpa_ctrl_open(NULL);
3274 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3275 ctrl_conn = wpa_ctrl_open(global);
3276 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3277 if (ctrl_conn == NULL) {
3278 perror("Failed to connect to wpa_supplicant - "
3279 "wpa_ctrl_open");
3280 return -1;
3281 }
3282 }
3284 #ifndef _WIN32_WCE
3285 signal(SIGINT, wpa_cli_terminate);
3286 signal(SIGTERM, wpa_cli_terminate);
3287 #endif /* _WIN32_WCE */
3289 if (ctrl_ifname == NULL)
3290 ctrl_ifname = wpa_cli_get_default_ifname();
3292 if (interactive) {
3293 for (; !global;) {
3294 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3295 if (warning_displayed)
3296 printf("Connection established.\n");
3297 break;
3298 }
3300 if (!warning_displayed) {
3301 printf("Could not connect to wpa_supplicant - "
3302 "re-trying\n");
3303 warning_displayed = 1;
3304 }
3305 os_sleep(1, 0);
3306 continue;
3307 }
3308 } else {
3309 if (!global &&
3310 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3311 perror("Failed to connect to wpa_supplicant - "
3312 "wpa_ctrl_open");
3313 return -1;
3314 }
3316 if (action_file) {
3317 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3318 wpa_cli_attached = 1;
3319 } else {
3320 printf("Warning: Failed to attach to "
3321 "wpa_supplicant.\n");
3322 return -1;
3323 }
3324 }
3325 }
3327 if (daemonize && os_daemonize(pid_file))
3328 return -1;
3330 if (interactive)
3331 wpa_cli_interactive();
3332 else if (action_file)
3333 wpa_cli_action(ctrl_conn);
3334 else
3335 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3337 os_free(ctrl_ifname);
3338 eloop_destroy();
3339 wpa_cli_cleanup();
3341 return ret;
3342 }
3344 #else /* CONFIG_CTRL_IFACE */
3345 int main(int argc, char *argv[])
3346 {
3347 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3348 return -1;
3349 }
3350 #endif /* CONFIG_CTRL_IFACE */