]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/wpa_cli.c
P2P: Add p2p_cancel command for cancelling ongoing group formation
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
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 */
14
15 #include "includes.h"
16
17 #ifdef CONFIG_CTRL_IFACE
18
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 */
29
30 #include "common/wpa_ctrl.h"
31 #include "common.h"
32 #include "common/version.h"
33
34
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";
38
39
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";
46
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";
91
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;
107
108
109 static void print_help();
110
111
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 }
128
129
130 static void readline_redraw()
131 {
132 #ifdef CONFIG_READLINE
133 rl_on_new_line();
134 rl_redisplay();
135 #endif /* CONFIG_READLINE */
136 }
137
138
139 static int str_starts(const char *src, const char *match)
140 {
141 return os_strncmp(src, match, os_strlen(match)) == 0;
142 }
143
144
145 static int wpa_cli_show_event(const char *event)
146 {
147 const char *start;
148
149 start = os_strchr(event, '>');
150 if (start == NULL)
151 return 1;
152
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;
161
162 return 1;
163 }
164
165
166 #ifdef CONFIG_WPA_CLI_FORK
167 static int in_query = 0;
168
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 }
176
177
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;
185
186 signal(SIGUSR1, wpa_cli_monitor_sig);
187 signal(SIGUSR2, wpa_cli_monitor_sig);
188
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 */
222
223
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;
230
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;
238
239 if (ifname == NULL)
240 return -1;
241
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 }
251
252 ctrl_conn = wpa_ctrl_open(cfile);
253 if (ctrl_conn == NULL) {
254 os_free(cfile);
255 return -1;
256 }
257
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 */
264
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 }
273
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 }
289
290 return 0;
291 }
292
293
294 static void wpa_cli_close_connection(void)
295 {
296 if (ctrl_conn == NULL)
297 return;
298
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 */
307
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 }
319
320
321 static void wpa_cli_msg_cb(char *msg, size_t len)
322 {
323 printf("%s\n", msg);
324 }
325
326
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;
332
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 }
353
354
355 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
356 {
357 return _wpa_ctrl_command(ctrl, cmd, 1);
358 }
359
360
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 }
366
367
368 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
369 {
370 return wpa_ctrl_command(ctrl, "PING");
371 }
372
373
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 }
385
386
387 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
388 {
389 return wpa_ctrl_command(ctrl, "MIB");
390 }
391
392
393 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
394 {
395 return wpa_ctrl_command(ctrl, "PMKSA");
396 }
397
398
399 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
400 {
401 print_help();
402 return 0;
403 }
404
405
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 }
411
412
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 }
418
419
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 }
438
439
440 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
441 {
442 char cmd[256];
443 int res;
444
445 if (argc == 0) {
446 wpa_cli_show_variables();
447 return 0;
448 }
449
450 if (argc != 2) {
451 printf("Invalid SET command: needs two arguments (variable "
452 "name and value)\n");
453 return -1;
454 }
455
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 }
463
464
465 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
466 {
467 return wpa_ctrl_command(ctrl, "LOGOFF");
468 }
469
470
471 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
472 {
473 return wpa_ctrl_command(ctrl, "LOGON");
474 }
475
476
477 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
478 char *argv[])
479 {
480 return wpa_ctrl_command(ctrl, "REASSOCIATE");
481 }
482
483
484 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
485 char *argv[])
486 {
487 char cmd[256];
488 int res;
489
490 if (argc != 1) {
491 printf("Invalid PREAUTH command: needs one argument "
492 "(BSSID)\n");
493 return -1;
494 }
495
496 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
497 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
498 printf("Too long PREAUTH command.\n");
499 return -1;
500 }
501 return wpa_ctrl_command(ctrl, cmd);
502 }
503
504
505 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
506 {
507 char cmd[256];
508 int res;
509
510 if (argc != 1) {
511 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
512 "value)\n");
513 return -1;
514 }
515 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
516 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
517 printf("Too long AP_SCAN command.\n");
518 return -1;
519 }
520 return wpa_ctrl_command(ctrl, cmd);
521 }
522
523
524 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
525 char *argv[])
526 {
527 char cmd[256];
528 int res;
529
530 if (argc != 1) {
531 printf("Invalid STKSTART command: needs one argument "
532 "(Peer STA MAC address)\n");
533 return -1;
534 }
535
536 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
537 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
538 printf("Too long STKSTART command.\n");
539 return -1;
540 }
541 return wpa_ctrl_command(ctrl, cmd);
542 }
543
544
545 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
546 {
547 char cmd[256];
548 int res;
549
550 if (argc != 1) {
551 printf("Invalid FT_DS command: needs one argument "
552 "(Target AP MAC address)\n");
553 return -1;
554 }
555
556 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
557 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
558 printf("Too long FT_DS command.\n");
559 return -1;
560 }
561 return wpa_ctrl_command(ctrl, cmd);
562 }
563
564
565 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
566 {
567 char cmd[256];
568 int res;
569
570 if (argc == 0) {
571 /* Any BSSID */
572 return wpa_ctrl_command(ctrl, "WPS_PBC");
573 }
574
575 /* Specific BSSID */
576 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
577 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
578 printf("Too long WPS_PBC command.\n");
579 return -1;
580 }
581 return wpa_ctrl_command(ctrl, cmd);
582 }
583
584
585 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
586 {
587 char cmd[256];
588 int res;
589
590 if (argc == 0) {
591 printf("Invalid WPS_PIN command: need one or two arguments:\n"
592 "- BSSID: use 'any' to select any\n"
593 "- PIN: optional, used only with devices that have no "
594 "display\n");
595 return -1;
596 }
597
598 if (argc == 1) {
599 /* Use dynamically generated PIN (returned as reply) */
600 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
601 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
602 printf("Too long WPS_PIN command.\n");
603 return -1;
604 }
605 return wpa_ctrl_command(ctrl, cmd);
606 }
607
608 /* Use hardcoded PIN from a label */
609 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
610 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
611 printf("Too long WPS_PIN command.\n");
612 return -1;
613 }
614 return wpa_ctrl_command(ctrl, cmd);
615 }
616
617
618 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
619 char *argv[])
620 {
621 char cmd[256];
622 int res;
623
624 if (argc != 1 && argc != 2) {
625 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
626 "- PIN to be verified\n");
627 return -1;
628 }
629
630 if (argc == 2)
631 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
632 argv[0], argv[1]);
633 else
634 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
635 argv[0]);
636 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
637 printf("Too long WPS_CHECK_PIN command.\n");
638 return -1;
639 }
640 return wpa_ctrl_command(ctrl, cmd);
641 }
642
643
644 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
645 char *argv[])
646 {
647 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
648 }
649
650
651 #ifdef CONFIG_WPS_OOB
652 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
653 {
654 char cmd[256];
655 int res;
656
657 if (argc != 3 && argc != 4) {
658 printf("Invalid WPS_OOB command: need three or four "
659 "arguments:\n"
660 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
661 "- PATH: path of OOB device like '/mnt'\n"
662 "- METHOD: OOB method 'pin-e' or 'pin-r', "
663 "'cred'\n"
664 "- DEV_NAME: (only for NFC) device name like "
665 "'pn531'\n");
666 return -1;
667 }
668
669 if (argc == 3)
670 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
671 argv[0], argv[1], argv[2]);
672 else
673 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
674 argv[0], argv[1], argv[2], argv[3]);
675 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
676 printf("Too long WPS_OOB command.\n");
677 return -1;
678 }
679 return wpa_ctrl_command(ctrl, cmd);
680 }
681 #endif /* CONFIG_WPS_OOB */
682
683
684 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
685 {
686 char cmd[256];
687 int res;
688
689 if (argc == 2)
690 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
691 argv[0], argv[1]);
692 else if (argc == 5 || argc == 6) {
693 char ssid_hex[2 * 32 + 1];
694 char key_hex[2 * 64 + 1];
695 int i;
696
697 ssid_hex[0] = '\0';
698 for (i = 0; i < 32; i++) {
699 if (argv[2][i] == '\0')
700 break;
701 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
702 }
703
704 key_hex[0] = '\0';
705 if (argc == 6) {
706 for (i = 0; i < 64; i++) {
707 if (argv[5][i] == '\0')
708 break;
709 os_snprintf(&key_hex[i * 2], 3, "%02x",
710 argv[5][i]);
711 }
712 }
713
714 res = os_snprintf(cmd, sizeof(cmd),
715 "WPS_REG %s %s %s %s %s %s",
716 argv[0], argv[1], ssid_hex, argv[3], argv[4],
717 key_hex);
718 } else {
719 printf("Invalid WPS_REG command: need two arguments:\n"
720 "- BSSID: use 'any' to select any\n"
721 "- AP PIN\n");
722 printf("Alternatively, six arguments can be used to "
723 "reconfigure the AP:\n"
724 "- BSSID: use 'any' to select any\n"
725 "- AP PIN\n"
726 "- new SSID\n"
727 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
728 "- new encr (NONE, WEP, TKIP, CCMP)\n"
729 "- new key\n");
730 return -1;
731 }
732
733 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
734 printf("Too long WPS_REG command.\n");
735 return -1;
736 }
737 return wpa_ctrl_command(ctrl, cmd);
738 }
739
740
741 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
742 char *argv[])
743 {
744 char cmd[100];
745 if (argc > 0) {
746 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
747 return wpa_ctrl_command(ctrl, cmd);
748 }
749 return wpa_ctrl_command(ctrl, "WPS_ER_START");
750 }
751
752
753 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
754 char *argv[])
755 {
756 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
757
758 }
759
760
761 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
762 char *argv[])
763 {
764 char cmd[256];
765 int res;
766
767 if (argc < 2) {
768 printf("Invalid WPS_ER_PIN command: need at least two "
769 "arguments:\n"
770 "- UUID: use 'any' to select any\n"
771 "- PIN: Enrollee PIN\n"
772 "optional: - Enrollee MAC address\n");
773 return -1;
774 }
775
776 if (argc > 2)
777 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
778 argv[0], argv[1], argv[2]);
779 else
780 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
781 argv[0], argv[1]);
782 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
783 printf("Too long WPS_ER_PIN command.\n");
784 return -1;
785 }
786 return wpa_ctrl_command(ctrl, cmd);
787 }
788
789
790 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
791 char *argv[])
792 {
793 char cmd[256];
794 int res;
795
796 if (argc != 1) {
797 printf("Invalid WPS_ER_PBC command: need one argument:\n"
798 "- UUID: Specify the Enrollee\n");
799 return -1;
800 }
801
802 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
803 argv[0]);
804 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
805 printf("Too long WPS_ER_PBC command.\n");
806 return -1;
807 }
808 return wpa_ctrl_command(ctrl, cmd);
809 }
810
811
812 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
813 char *argv[])
814 {
815 char cmd[256];
816 int res;
817
818 if (argc != 2) {
819 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
820 "- UUID: specify which AP to use\n"
821 "- PIN: AP PIN\n");
822 return -1;
823 }
824
825 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
826 argv[0], argv[1]);
827 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
828 printf("Too long WPS_ER_LEARN command.\n");
829 return -1;
830 }
831 return wpa_ctrl_command(ctrl, cmd);
832 }
833
834
835 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
836 char *argv[])
837 {
838 char cmd[256];
839 int res;
840
841 if (argc == 5 || argc == 6) {
842 char ssid_hex[2 * 32 + 1];
843 char key_hex[2 * 64 + 1];
844 int i;
845
846 ssid_hex[0] = '\0';
847 for (i = 0; i < 32; i++) {
848 if (argv[2][i] == '\0')
849 break;
850 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
851 }
852
853 key_hex[0] = '\0';
854 if (argc == 6) {
855 for (i = 0; i < 64; i++) {
856 if (argv[5][i] == '\0')
857 break;
858 os_snprintf(&key_hex[i * 2], 3, "%02x",
859 argv[5][i]);
860 }
861 }
862
863 res = os_snprintf(cmd, sizeof(cmd),
864 "WPS_ER_CONFIG %s %s %s %s %s %s",
865 argv[0], argv[1], ssid_hex, argv[3], argv[4],
866 key_hex);
867 } else {
868 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
869 "- AP UUID\n"
870 "- AP PIN\n"
871 "- new SSID\n"
872 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
873 "- new encr (NONE, WEP, TKIP, CCMP)\n"
874 "- new key\n");
875 return -1;
876 }
877
878 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
879 printf("Too long WPS_ER_CONFIG command.\n");
880 return -1;
881 }
882 return wpa_ctrl_command(ctrl, cmd);
883 }
884
885
886 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
887 {
888 char cmd[256];
889 int res;
890
891 if (argc != 1) {
892 printf("Invalid IBSS_RSN command: needs one argument "
893 "(Peer STA MAC address)\n");
894 return -1;
895 }
896
897 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
898 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
899 printf("Too long IBSS_RSN command.\n");
900 return -1;
901 }
902 return wpa_ctrl_command(ctrl, cmd);
903 }
904
905
906 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
907 {
908 char cmd[256];
909 int res;
910
911 if (argc != 1) {
912 printf("Invalid LEVEL command: needs one argument (debug "
913 "level)\n");
914 return -1;
915 }
916 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
917 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
918 printf("Too long LEVEL command.\n");
919 return -1;
920 }
921 return wpa_ctrl_command(ctrl, cmd);
922 }
923
924
925 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
926 {
927 char cmd[256], *pos, *end;
928 int i, ret;
929
930 if (argc < 2) {
931 printf("Invalid IDENTITY command: needs two arguments "
932 "(network id and identity)\n");
933 return -1;
934 }
935
936 end = cmd + sizeof(cmd);
937 pos = cmd;
938 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
939 argv[0], argv[1]);
940 if (ret < 0 || ret >= end - pos) {
941 printf("Too long IDENTITY command.\n");
942 return -1;
943 }
944 pos += ret;
945 for (i = 2; i < argc; i++) {
946 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
947 if (ret < 0 || ret >= end - pos) {
948 printf("Too long IDENTITY command.\n");
949 return -1;
950 }
951 pos += ret;
952 }
953
954 return wpa_ctrl_command(ctrl, cmd);
955 }
956
957
958 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
959 {
960 char cmd[256], *pos, *end;
961 int i, ret;
962
963 if (argc < 2) {
964 printf("Invalid PASSWORD command: needs two arguments "
965 "(network id and password)\n");
966 return -1;
967 }
968
969 end = cmd + sizeof(cmd);
970 pos = cmd;
971 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
972 argv[0], argv[1]);
973 if (ret < 0 || ret >= end - pos) {
974 printf("Too long PASSWORD command.\n");
975 return -1;
976 }
977 pos += ret;
978 for (i = 2; i < argc; i++) {
979 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
980 if (ret < 0 || ret >= end - pos) {
981 printf("Too long PASSWORD command.\n");
982 return -1;
983 }
984 pos += ret;
985 }
986
987 return wpa_ctrl_command(ctrl, cmd);
988 }
989
990
991 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
992 char *argv[])
993 {
994 char cmd[256], *pos, *end;
995 int i, ret;
996
997 if (argc < 2) {
998 printf("Invalid NEW_PASSWORD command: needs two arguments "
999 "(network id and password)\n");
1000 return -1;
1001 }
1002
1003 end = cmd + sizeof(cmd);
1004 pos = cmd;
1005 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1006 argv[0], argv[1]);
1007 if (ret < 0 || ret >= end - pos) {
1008 printf("Too long NEW_PASSWORD command.\n");
1009 return -1;
1010 }
1011 pos += ret;
1012 for (i = 2; i < argc; i++) {
1013 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1014 if (ret < 0 || ret >= end - pos) {
1015 printf("Too long NEW_PASSWORD command.\n");
1016 return -1;
1017 }
1018 pos += ret;
1019 }
1020
1021 return wpa_ctrl_command(ctrl, cmd);
1022 }
1023
1024
1025 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1026 {
1027 char cmd[256], *pos, *end;
1028 int i, ret;
1029
1030 if (argc < 2) {
1031 printf("Invalid PIN command: needs two arguments "
1032 "(network id and pin)\n");
1033 return -1;
1034 }
1035
1036 end = cmd + sizeof(cmd);
1037 pos = cmd;
1038 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1039 argv[0], argv[1]);
1040 if (ret < 0 || ret >= end - pos) {
1041 printf("Too long PIN command.\n");
1042 return -1;
1043 }
1044 pos += ret;
1045 for (i = 2; i < argc; i++) {
1046 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1047 if (ret < 0 || ret >= end - pos) {
1048 printf("Too long PIN command.\n");
1049 return -1;
1050 }
1051 pos += ret;
1052 }
1053 return wpa_ctrl_command(ctrl, cmd);
1054 }
1055
1056
1057 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1058 {
1059 char cmd[256], *pos, *end;
1060 int i, ret;
1061
1062 if (argc < 2) {
1063 printf("Invalid OTP command: needs two arguments (network "
1064 "id and password)\n");
1065 return -1;
1066 }
1067
1068 end = cmd + sizeof(cmd);
1069 pos = cmd;
1070 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1071 argv[0], argv[1]);
1072 if (ret < 0 || ret >= end - pos) {
1073 printf("Too long OTP command.\n");
1074 return -1;
1075 }
1076 pos += ret;
1077 for (i = 2; i < argc; i++) {
1078 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1079 if (ret < 0 || ret >= end - pos) {
1080 printf("Too long OTP command.\n");
1081 return -1;
1082 }
1083 pos += ret;
1084 }
1085
1086 return wpa_ctrl_command(ctrl, cmd);
1087 }
1088
1089
1090 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1091 char *argv[])
1092 {
1093 char cmd[256], *pos, *end;
1094 int i, ret;
1095
1096 if (argc < 2) {
1097 printf("Invalid PASSPHRASE command: needs two arguments "
1098 "(network id and passphrase)\n");
1099 return -1;
1100 }
1101
1102 end = cmd + sizeof(cmd);
1103 pos = cmd;
1104 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1105 argv[0], argv[1]);
1106 if (ret < 0 || ret >= end - pos) {
1107 printf("Too long PASSPHRASE command.\n");
1108 return -1;
1109 }
1110 pos += ret;
1111 for (i = 2; i < argc; i++) {
1112 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long PASSPHRASE command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 }
1119
1120 return wpa_ctrl_command(ctrl, cmd);
1121 }
1122
1123
1124 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1125 {
1126 char cmd[256], *pos, *end;
1127 int i, ret;
1128
1129 if (argc < 2) {
1130 printf("Invalid BSSID command: needs two arguments (network "
1131 "id and BSSID)\n");
1132 return -1;
1133 }
1134
1135 end = cmd + sizeof(cmd);
1136 pos = cmd;
1137 ret = os_snprintf(pos, end - pos, "BSSID");
1138 if (ret < 0 || ret >= end - pos) {
1139 printf("Too long BSSID command.\n");
1140 return -1;
1141 }
1142 pos += ret;
1143 for (i = 0; i < argc; i++) {
1144 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1145 if (ret < 0 || ret >= end - pos) {
1146 printf("Too long BSSID command.\n");
1147 return -1;
1148 }
1149 pos += ret;
1150 }
1151
1152 return wpa_ctrl_command(ctrl, cmd);
1153 }
1154
1155
1156 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1157 char *argv[])
1158 {
1159 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1160 }
1161
1162
1163 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1164 char *argv[])
1165 {
1166 char cmd[32];
1167 int res;
1168
1169 if (argc < 1) {
1170 printf("Invalid SELECT_NETWORK command: needs one argument "
1171 "(network id)\n");
1172 return -1;
1173 }
1174
1175 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1176 if (res < 0 || (size_t) res >= sizeof(cmd))
1177 return -1;
1178 cmd[sizeof(cmd) - 1] = '\0';
1179
1180 return wpa_ctrl_command(ctrl, cmd);
1181 }
1182
1183
1184 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1185 char *argv[])
1186 {
1187 char cmd[32];
1188 int res;
1189
1190 if (argc < 1) {
1191 printf("Invalid ENABLE_NETWORK command: needs one argument "
1192 "(network id)\n");
1193 return -1;
1194 }
1195
1196 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1197 if (res < 0 || (size_t) res >= sizeof(cmd))
1198 return -1;
1199 cmd[sizeof(cmd) - 1] = '\0';
1200
1201 return wpa_ctrl_command(ctrl, cmd);
1202 }
1203
1204
1205 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1206 char *argv[])
1207 {
1208 char cmd[32];
1209 int res;
1210
1211 if (argc < 1) {
1212 printf("Invalid DISABLE_NETWORK command: needs one argument "
1213 "(network id)\n");
1214 return -1;
1215 }
1216
1217 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1218 if (res < 0 || (size_t) res >= sizeof(cmd))
1219 return -1;
1220 cmd[sizeof(cmd) - 1] = '\0';
1221
1222 return wpa_ctrl_command(ctrl, cmd);
1223 }
1224
1225
1226 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1227 char *argv[])
1228 {
1229 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1230 }
1231
1232
1233 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1234 char *argv[])
1235 {
1236 char cmd[32];
1237 int res;
1238
1239 if (argc < 1) {
1240 printf("Invalid REMOVE_NETWORK command: needs one argument "
1241 "(network id)\n");
1242 return -1;
1243 }
1244
1245 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1246 if (res < 0 || (size_t) res >= sizeof(cmd))
1247 return -1;
1248 cmd[sizeof(cmd) - 1] = '\0';
1249
1250 return wpa_ctrl_command(ctrl, cmd);
1251 }
1252
1253
1254 static void wpa_cli_show_network_variables(void)
1255 {
1256 printf("set_network variables:\n"
1257 " ssid (network name, SSID)\n"
1258 " psk (WPA passphrase or pre-shared key)\n"
1259 " key_mgmt (key management protocol)\n"
1260 " identity (EAP identity)\n"
1261 " password (EAP password)\n"
1262 " ...\n"
1263 "\n"
1264 "Note: Values are entered in the same format as the "
1265 "configuration file is using,\n"
1266 "i.e., strings values need to be inside double quotation "
1267 "marks.\n"
1268 "For example: set_network 1 ssid \"network name\"\n"
1269 "\n"
1270 "Please see wpa_supplicant.conf documentation for full list "
1271 "of\navailable variables.\n");
1272 }
1273
1274
1275 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1276 char *argv[])
1277 {
1278 char cmd[256];
1279 int res;
1280
1281 if (argc == 0) {
1282 wpa_cli_show_network_variables();
1283 return 0;
1284 }
1285
1286 if (argc != 3) {
1287 printf("Invalid SET_NETWORK command: needs three arguments\n"
1288 "(network id, variable name, and value)\n");
1289 return -1;
1290 }
1291
1292 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1293 argv[0], argv[1], argv[2]);
1294 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1295 printf("Too long SET_NETWORK command.\n");
1296 return -1;
1297 }
1298 return wpa_ctrl_command(ctrl, cmd);
1299 }
1300
1301
1302 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1303 char *argv[])
1304 {
1305 char cmd[256];
1306 int res;
1307
1308 if (argc == 0) {
1309 wpa_cli_show_network_variables();
1310 return 0;
1311 }
1312
1313 if (argc != 2) {
1314 printf("Invalid GET_NETWORK command: needs two arguments\n"
1315 "(network id and variable name)\n");
1316 return -1;
1317 }
1318
1319 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1320 argv[0], argv[1]);
1321 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1322 printf("Too long GET_NETWORK command.\n");
1323 return -1;
1324 }
1325 return wpa_ctrl_command(ctrl, cmd);
1326 }
1327
1328
1329 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1330 char *argv[])
1331 {
1332 return wpa_ctrl_command(ctrl, "DISCONNECT");
1333 }
1334
1335
1336 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1337 char *argv[])
1338 {
1339 return wpa_ctrl_command(ctrl, "RECONNECT");
1340 }
1341
1342
1343 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345 {
1346 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1347 }
1348
1349
1350 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1351 {
1352 return wpa_ctrl_command(ctrl, "SCAN");
1353 }
1354
1355
1356 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1357 char *argv[])
1358 {
1359 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1360 }
1361
1362
1363 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1364 {
1365 char cmd[64];
1366 int res;
1367
1368 if (argc != 1) {
1369 printf("Invalid BSS command: need one argument (index or "
1370 "BSSID)\n");
1371 return -1;
1372 }
1373
1374 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1375 if (res < 0 || (size_t) res >= sizeof(cmd))
1376 return -1;
1377 cmd[sizeof(cmd) - 1] = '\0';
1378
1379 return wpa_ctrl_command(ctrl, cmd);
1380 }
1381
1382
1383 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1384 char *argv[])
1385 {
1386 char cmd[64];
1387 int res;
1388
1389 if (argc < 1 || argc > 2) {
1390 printf("Invalid GET_CAPABILITY command: need either one or "
1391 "two arguments\n");
1392 return -1;
1393 }
1394
1395 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1396 printf("Invalid GET_CAPABILITY command: second argument, "
1397 "if any, must be 'strict'\n");
1398 return -1;
1399 }
1400
1401 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1402 (argc == 2) ? " strict" : "");
1403 if (res < 0 || (size_t) res >= sizeof(cmd))
1404 return -1;
1405 cmd[sizeof(cmd) - 1] = '\0';
1406
1407 return wpa_ctrl_command(ctrl, cmd);
1408 }
1409
1410
1411 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1412 {
1413 printf("Available interfaces:\n");
1414 return wpa_ctrl_command(ctrl, "INTERFACES");
1415 }
1416
1417
1418 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1419 {
1420 if (argc < 1) {
1421 wpa_cli_list_interfaces(ctrl);
1422 return 0;
1423 }
1424
1425 wpa_cli_close_connection();
1426 os_free(ctrl_ifname);
1427 ctrl_ifname = os_strdup(argv[0]);
1428
1429 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1430 printf("Connected to interface '%s.\n", ctrl_ifname);
1431 } else {
1432 printf("Could not connect to interface '%s' - re-trying\n",
1433 ctrl_ifname);
1434 }
1435 return 0;
1436 }
1437
1438
1439 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1440 char *argv[])
1441 {
1442 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1443 }
1444
1445
1446 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1447 char *argv[])
1448 {
1449 return wpa_ctrl_command(ctrl, "TERMINATE");
1450 }
1451
1452
1453 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1454 char *argv[])
1455 {
1456 char cmd[256];
1457 int res;
1458
1459 if (argc < 1) {
1460 printf("Invalid INTERFACE_ADD command: needs at least one "
1461 "argument (interface name)\n"
1462 "All arguments: ifname confname driver ctrl_interface "
1463 "driver_param bridge_name\n");
1464 return -1;
1465 }
1466
1467 /*
1468 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1469 * <driver_param>TAB<bridge_name>
1470 */
1471 res = os_snprintf(cmd, sizeof(cmd),
1472 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1473 argv[0],
1474 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1475 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1476 argc > 5 ? argv[5] : "");
1477 if (res < 0 || (size_t) res >= sizeof(cmd))
1478 return -1;
1479 cmd[sizeof(cmd) - 1] = '\0';
1480 return wpa_ctrl_command(ctrl, cmd);
1481 }
1482
1483
1484 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1485 char *argv[])
1486 {
1487 char cmd[128];
1488 int res;
1489
1490 if (argc != 1) {
1491 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1492 "(interface name)\n");
1493 return -1;
1494 }
1495
1496 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1497 if (res < 0 || (size_t) res >= sizeof(cmd))
1498 return -1;
1499 cmd[sizeof(cmd) - 1] = '\0';
1500 return wpa_ctrl_command(ctrl, cmd);
1501 }
1502
1503
1504 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1505 char *argv[])
1506 {
1507 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1508 }
1509
1510
1511 #ifdef CONFIG_AP
1512 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1513 {
1514 char buf[64];
1515 if (argc != 1) {
1516 printf("Invalid 'sta' command - exactly one argument, STA "
1517 "address, is required.\n");
1518 return -1;
1519 }
1520 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1521 return wpa_ctrl_command(ctrl, buf);
1522 }
1523
1524
1525 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1526 char *addr, size_t addr_len)
1527 {
1528 char buf[4096], *pos;
1529 size_t len;
1530 int ret;
1531
1532 if (ctrl_conn == NULL) {
1533 printf("Not connected to hostapd - command dropped.\n");
1534 return -1;
1535 }
1536 len = sizeof(buf) - 1;
1537 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1538 wpa_cli_msg_cb);
1539 if (ret == -2) {
1540 printf("'%s' command timed out.\n", cmd);
1541 return -2;
1542 } else if (ret < 0) {
1543 printf("'%s' command failed.\n", cmd);
1544 return -1;
1545 }
1546
1547 buf[len] = '\0';
1548 if (memcmp(buf, "FAIL", 4) == 0)
1549 return -1;
1550 printf("%s", buf);
1551
1552 pos = buf;
1553 while (*pos != '\0' && *pos != '\n')
1554 pos++;
1555 *pos = '\0';
1556 os_strlcpy(addr, buf, addr_len);
1557 return 0;
1558 }
1559
1560
1561 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1562 {
1563 char addr[32], cmd[64];
1564
1565 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1566 return 0;
1567 do {
1568 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1569 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1570
1571 return -1;
1572 }
1573 #endif /* CONFIG_AP */
1574
1575
1576 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1577 {
1578 return wpa_ctrl_command(ctrl, "SUSPEND");
1579 }
1580
1581
1582 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1583 {
1584 return wpa_ctrl_command(ctrl, "RESUME");
1585 }
1586
1587
1588 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1589 {
1590 return wpa_ctrl_command(ctrl, "DROP_SA");
1591 }
1592
1593
1594 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1595 {
1596 char cmd[128];
1597 int res;
1598
1599 if (argc != 1) {
1600 printf("Invalid ROAM command: needs one argument "
1601 "(target AP's BSSID)\n");
1602 return -1;
1603 }
1604
1605 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1606 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1607 printf("Too long ROAM command.\n");
1608 return -1;
1609 }
1610 return wpa_ctrl_command(ctrl, cmd);
1611 }
1612
1613
1614 #ifdef CONFIG_P2P
1615
1616 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1617 {
1618 char cmd[128];
1619 int res;
1620
1621 if (argc == 0)
1622 return wpa_ctrl_command(ctrl, "P2P_FIND");
1623
1624 if (argc > 1)
1625 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1626 argv[0], argv[1]);
1627 else
1628 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s", argv[0]);
1629 if (res < 0 || (size_t) res >= sizeof(cmd))
1630 return -1;
1631 cmd[sizeof(cmd) - 1] = '\0';
1632 return wpa_ctrl_command(ctrl, cmd);
1633 }
1634
1635
1636 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1637 char *argv[])
1638 {
1639 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1640 }
1641
1642
1643 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1644 char *argv[])
1645 {
1646 char cmd[128];
1647 int res;
1648
1649 if (argc < 2) {
1650 printf("Invalid P2P_CONNECT command: needs at least two "
1651 "arguments (address and pbc/PIN)\n");
1652 return -1;
1653 }
1654
1655 if (argc > 4)
1656 res = os_snprintf(cmd, sizeof(cmd),
1657 "P2P_CONNECT %s %s %s %s %s",
1658 argv[0], argv[1], argv[2], argv[3],
1659 argv[4]);
1660 else if (argc > 3)
1661 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1662 argv[0], argv[1], argv[2], argv[3]);
1663 else if (argc > 2)
1664 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1665 argv[0], argv[1], argv[2]);
1666 else
1667 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1668 argv[0], argv[1]);
1669 if (res < 0 || (size_t) res >= sizeof(cmd))
1670 return -1;
1671 cmd[sizeof(cmd) - 1] = '\0';
1672 return wpa_ctrl_command(ctrl, cmd);
1673 }
1674
1675
1676 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1677 char *argv[])
1678 {
1679 char cmd[128];
1680 int res;
1681
1682 if (argc == 0)
1683 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
1684
1685 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
1686 if (res < 0 || (size_t) res >= sizeof(cmd))
1687 return -1;
1688 cmd[sizeof(cmd) - 1] = '\0';
1689 return wpa_ctrl_command(ctrl, cmd);
1690 }
1691
1692
1693 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1694 char *argv[])
1695 {
1696 char cmd[128];
1697 int res;
1698
1699 if (argc != 1) {
1700 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
1701 "(interface name)\n");
1702 return -1;
1703 }
1704
1705 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
1706 if (res < 0 || (size_t) res >= sizeof(cmd))
1707 return -1;
1708 cmd[sizeof(cmd) - 1] = '\0';
1709 return wpa_ctrl_command(ctrl, cmd);
1710 }
1711
1712
1713 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1714 char *argv[])
1715 {
1716 char cmd[128];
1717 int res;
1718
1719 if (argc == 0)
1720 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
1721
1722 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s", argv[0]);
1723 if (res < 0 || (size_t) res >= sizeof(cmd))
1724 return -1;
1725 cmd[sizeof(cmd) - 1] = '\0';
1726 return wpa_ctrl_command(ctrl, cmd);
1727 }
1728
1729
1730 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1731 char *argv[])
1732 {
1733 char cmd[128];
1734 int res;
1735
1736 if (argc != 2) {
1737 printf("Invalid P2P_PROV_DISC command: needs two arguments "
1738 "(address and config method\n"
1739 "(display, keypad, or pbc)\n");
1740 return -1;
1741 }
1742
1743 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
1744 argv[0], argv[1]);
1745 if (res < 0 || (size_t) res >= sizeof(cmd))
1746 return -1;
1747 cmd[sizeof(cmd) - 1] = '\0';
1748 return wpa_ctrl_command(ctrl, cmd);
1749 }
1750
1751
1752 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1753 char *argv[])
1754 {
1755 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1756 }
1757
1758
1759 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1760 char *argv[])
1761 {
1762 char cmd[4096];
1763 int res;
1764
1765 if (argc != 2 && argc != 4) {
1766 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1767 "arguments (address and TLVs) or four arguments "
1768 "(address, \"upnp\", version, search target "
1769 "(SSDP ST:)\n");
1770 return -1;
1771 }
1772
1773 if (argc == 4)
1774 res = os_snprintf(cmd, sizeof(cmd),
1775 "P2P_SERV_DISC_REQ %s %s %s %s",
1776 argv[0], argv[1], argv[2], argv[3]);
1777 else
1778 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
1779 argv[0], argv[1]);
1780 if (res < 0 || (size_t) res >= sizeof(cmd))
1781 return -1;
1782 cmd[sizeof(cmd) - 1] = '\0';
1783 return wpa_ctrl_command(ctrl, cmd);
1784 }
1785
1786
1787 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1788 int argc, char *argv[])
1789 {
1790 char cmd[128];
1791 int res;
1792
1793 if (argc != 1) {
1794 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
1795 "argument (pending request identifier)\n");
1796 return -1;
1797 }
1798
1799 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
1800 argv[0]);
1801 if (res < 0 || (size_t) res >= sizeof(cmd))
1802 return -1;
1803 cmd[sizeof(cmd) - 1] = '\0';
1804 return wpa_ctrl_command(ctrl, cmd);
1805 }
1806
1807
1808 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1809 char *argv[])
1810 {
1811 char cmd[4096];
1812 int res;
1813
1814 if (argc != 4) {
1815 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1816 "arguments (freq, address, dialog token, and TLVs)\n");
1817 return -1;
1818 }
1819
1820 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1821 argv[0], argv[1], argv[2], argv[3]);
1822 if (res < 0 || (size_t) res >= sizeof(cmd))
1823 return -1;
1824 cmd[sizeof(cmd) - 1] = '\0';
1825 return wpa_ctrl_command(ctrl, cmd);
1826 }
1827
1828
1829 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1830 char *argv[])
1831 {
1832 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1833 }
1834
1835
1836 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1837 int argc, char *argv[])
1838 {
1839 char cmd[128];
1840 int res;
1841
1842 if (argc != 1) {
1843 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
1844 "argument (external processing: 0/1)\n");
1845 return -1;
1846 }
1847
1848 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
1849 argv[0]);
1850 if (res < 0 || (size_t) res >= sizeof(cmd))
1851 return -1;
1852 cmd[sizeof(cmd) - 1] = '\0';
1853 return wpa_ctrl_command(ctrl, cmd);
1854 }
1855
1856
1857 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1858 char *argv[])
1859 {
1860 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1861 }
1862
1863
1864 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1865 char *argv[])
1866 {
1867 char cmd[4096];
1868 int res;
1869
1870 if (argc != 3 && argc != 4) {
1871 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1872 "arguments\n");
1873 return -1;
1874 }
1875
1876 if (argc == 4)
1877 res = os_snprintf(cmd, sizeof(cmd),
1878 "P2P_SERVICE_ADD %s %s %s %s",
1879 argv[0], argv[1], argv[2], argv[3]);
1880 else
1881 res = os_snprintf(cmd, sizeof(cmd),
1882 "P2P_SERVICE_ADD %s %s %s",
1883 argv[0], argv[1], argv[2]);
1884 if (res < 0 || (size_t) res >= sizeof(cmd))
1885 return -1;
1886 cmd[sizeof(cmd) - 1] = '\0';
1887 return wpa_ctrl_command(ctrl, cmd);
1888 }
1889
1890
1891 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1892 char *argv[])
1893 {
1894 char cmd[4096];
1895 int res;
1896
1897 if (argc != 2 && argc != 3) {
1898 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1899 "arguments\n");
1900 return -1;
1901 }
1902
1903 if (argc == 3)
1904 res = os_snprintf(cmd, sizeof(cmd),
1905 "P2P_SERVICE_DEL %s %s %s",
1906 argv[0], argv[1], argv[2]);
1907 else
1908 res = os_snprintf(cmd, sizeof(cmd),
1909 "P2P_SERVICE_DEL %s %s",
1910 argv[0], argv[1]);
1911 if (res < 0 || (size_t) res >= sizeof(cmd))
1912 return -1;
1913 cmd[sizeof(cmd) - 1] = '\0';
1914 return wpa_ctrl_command(ctrl, cmd);
1915 }
1916
1917
1918 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1919 int argc, char *argv[])
1920 {
1921 char cmd[128];
1922 int res;
1923
1924 if (argc != 1) {
1925 printf("Invalid P2P_REJECT command: needs one argument "
1926 "(peer address)\n");
1927 return -1;
1928 }
1929
1930 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
1931 if (res < 0 || (size_t) res >= sizeof(cmd))
1932 return -1;
1933 cmd[sizeof(cmd) - 1] = '\0';
1934 return wpa_ctrl_command(ctrl, cmd);
1935 }
1936
1937
1938 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1939 int argc, char *argv[])
1940 {
1941 char cmd[128];
1942 int res;
1943
1944 if (argc < 1) {
1945 printf("Invalid P2P_INVITE command: needs at least one "
1946 "argument\n");
1947 return -1;
1948 }
1949
1950 if (argc > 2)
1951 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
1952 argv[0], argv[1], argv[2]);
1953 else if (argc > 1)
1954 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
1955 argv[0], argv[1]);
1956 else
1957 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
1958 if (res < 0 || (size_t) res >= sizeof(cmd))
1959 return -1;
1960 cmd[sizeof(cmd) - 1] = '\0';
1961 return wpa_ctrl_command(ctrl, cmd);
1962 }
1963
1964
1965 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1966 {
1967 char buf[64];
1968 if (argc != 1) {
1969 printf("Invalid 'p2p_peer' command - exactly one argument, "
1970 "P2P peer device address, is required.\n");
1971 return -1;
1972 }
1973 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
1974 return wpa_ctrl_command(ctrl, buf);
1975 }
1976
1977
1978 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1979 char *addr, size_t addr_len,
1980 int discovered)
1981 {
1982 char buf[4096], *pos;
1983 size_t len;
1984 int ret;
1985
1986 if (ctrl_conn == NULL)
1987 return -1;
1988 len = sizeof(buf) - 1;
1989 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1990 wpa_cli_msg_cb);
1991 if (ret == -2) {
1992 printf("'%s' command timed out.\n", cmd);
1993 return -2;
1994 } else if (ret < 0) {
1995 printf("'%s' command failed.\n", cmd);
1996 return -1;
1997 }
1998
1999 buf[len] = '\0';
2000 if (memcmp(buf, "FAIL", 4) == 0)
2001 return -1;
2002
2003 pos = buf;
2004 while (*pos != '\0' && *pos != '\n')
2005 pos++;
2006 *pos++ = '\0';
2007 os_strlcpy(addr, buf, addr_len);
2008 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2009 printf("%s\n", addr);
2010 return 0;
2011 }
2012
2013
2014 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2015 {
2016 char addr[32], cmd[64];
2017 int discovered;
2018
2019 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2020
2021 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2022 addr, sizeof(addr), discovered))
2023 return 0;
2024 do {
2025 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2026 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2027 discovered) == 0);
2028
2029 return -1;
2030 }
2031
2032
2033 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2034 {
2035 char cmd[100];
2036 int res;
2037
2038 if (argc != 2) {
2039 printf("Invalid P2P_SET command: needs two arguments (field, "
2040 "value)\n");
2041 return -1;
2042 }
2043
2044 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2045 if (res < 0 || (size_t) res >= sizeof(cmd))
2046 return -1;
2047 cmd[sizeof(cmd) - 1] = '\0';
2048 return wpa_ctrl_command(ctrl, cmd);
2049 }
2050
2051
2052 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2053 {
2054 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2055 }
2056
2057
2058 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2059 char *argv[])
2060 {
2061 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2062 }
2063
2064
2065 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2066 char *argv[])
2067 {
2068 char cmd[100];
2069 int res;
2070
2071 if (argc != 0 && argc != 2 && argc != 4) {
2072 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2073 "(preferred duration, interval; in microsecods).\n"
2074 "Optional second pair can be used to provide "
2075 "acceptable values.\n");
2076 return -1;
2077 }
2078
2079 if (argc == 4)
2080 res = os_snprintf(cmd, sizeof(cmd),
2081 "P2P_PRESENCE_REQ %s %s %s %s",
2082 argv[0], argv[1], argv[2], argv[3]);
2083 else if (argc == 2)
2084 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2085 argv[0], argv[1]);
2086 else
2087 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2088 if (res < 0 || (size_t) res >= sizeof(cmd))
2089 return -1;
2090 cmd[sizeof(cmd) - 1] = '\0';
2091 return wpa_ctrl_command(ctrl, cmd);
2092 }
2093
2094
2095 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2096 char *argv[])
2097 {
2098 char cmd[100];
2099 int res;
2100
2101 if (argc != 0 && argc != 2) {
2102 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2103 "(availability period, availability interval; in "
2104 "millisecods).\n"
2105 "Extended Listen Timing can be cancelled with this "
2106 "command when used without parameters.\n");
2107 return -1;
2108 }
2109
2110 if (argc == 2)
2111 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2112 argv[0], argv[1]);
2113 else
2114 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2115 if (res < 0 || (size_t) res >= sizeof(cmd))
2116 return -1;
2117 cmd[sizeof(cmd) - 1] = '\0';
2118 return wpa_ctrl_command(ctrl, cmd);
2119 }
2120
2121 #endif /* CONFIG_P2P */
2122
2123
2124 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2125 char *argv[])
2126 {
2127 char cmd[256];
2128 int res;
2129
2130 if (argc != 1) {
2131 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2132 "(0/1 = disable/enable automatic reconnection)\n");
2133 return -1;
2134 }
2135 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2136 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2137 printf("Too long STA_AUTOCONNECT command.\n");
2138 return -1;
2139 }
2140 return wpa_ctrl_command(ctrl, cmd);
2141 }
2142
2143
2144 enum wpa_cli_cmd_flags {
2145 cli_cmd_flag_none = 0x00,
2146 cli_cmd_flag_sensitive = 0x01
2147 };
2148
2149 struct wpa_cli_cmd {
2150 const char *cmd;
2151 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2152 enum wpa_cli_cmd_flags flags;
2153 const char *usage;
2154 };
2155
2156 static struct wpa_cli_cmd wpa_cli_commands[] = {
2157 { "status", wpa_cli_cmd_status,
2158 cli_cmd_flag_none,
2159 "[verbose] = get current WPA/EAPOL/EAP status" },
2160 { "ping", wpa_cli_cmd_ping,
2161 cli_cmd_flag_none,
2162 "= pings wpa_supplicant" },
2163 { "note", wpa_cli_cmd_note,
2164 cli_cmd_flag_none,
2165 "<text> = add a note to wpa_supplicant debug log" },
2166 { "mib", wpa_cli_cmd_mib,
2167 cli_cmd_flag_none,
2168 "= get MIB variables (dot1x, dot11)" },
2169 { "help", wpa_cli_cmd_help,
2170 cli_cmd_flag_none,
2171 "= show this usage help" },
2172 { "interface", wpa_cli_cmd_interface,
2173 cli_cmd_flag_none,
2174 "[ifname] = show interfaces/select interface" },
2175 { "level", wpa_cli_cmd_level,
2176 cli_cmd_flag_none,
2177 "<debug level> = change debug level" },
2178 { "license", wpa_cli_cmd_license,
2179 cli_cmd_flag_none,
2180 "= show full wpa_cli license" },
2181 { "quit", wpa_cli_cmd_quit,
2182 cli_cmd_flag_none,
2183 "= exit wpa_cli" },
2184 { "set", wpa_cli_cmd_set,
2185 cli_cmd_flag_none,
2186 "= set variables (shows list of variables when run without "
2187 "arguments)" },
2188 { "logon", wpa_cli_cmd_logon,
2189 cli_cmd_flag_none,
2190 "= IEEE 802.1X EAPOL state machine logon" },
2191 { "logoff", wpa_cli_cmd_logoff,
2192 cli_cmd_flag_none,
2193 "= IEEE 802.1X EAPOL state machine logoff" },
2194 { "pmksa", wpa_cli_cmd_pmksa,
2195 cli_cmd_flag_none,
2196 "= show PMKSA cache" },
2197 { "reassociate", wpa_cli_cmd_reassociate,
2198 cli_cmd_flag_none,
2199 "= force reassociation" },
2200 { "preauthenticate", wpa_cli_cmd_preauthenticate,
2201 cli_cmd_flag_none,
2202 "<BSSID> = force preauthentication" },
2203 { "identity", wpa_cli_cmd_identity,
2204 cli_cmd_flag_none,
2205 "<network id> <identity> = configure identity for an SSID" },
2206 { "password", wpa_cli_cmd_password,
2207 cli_cmd_flag_sensitive,
2208 "<network id> <password> = configure password for an SSID" },
2209 { "new_password", wpa_cli_cmd_new_password,
2210 cli_cmd_flag_sensitive,
2211 "<network id> <password> = change password for an SSID" },
2212 { "pin", wpa_cli_cmd_pin,
2213 cli_cmd_flag_sensitive,
2214 "<network id> <pin> = configure pin for an SSID" },
2215 { "otp", wpa_cli_cmd_otp,
2216 cli_cmd_flag_sensitive,
2217 "<network id> <password> = configure one-time-password for an SSID"
2218 },
2219 { "passphrase", wpa_cli_cmd_passphrase,
2220 cli_cmd_flag_sensitive,
2221 "<network id> <passphrase> = configure private key passphrase\n"
2222 " for an SSID" },
2223 { "bssid", wpa_cli_cmd_bssid,
2224 cli_cmd_flag_none,
2225 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2226 { "list_networks", wpa_cli_cmd_list_networks,
2227 cli_cmd_flag_none,
2228 "= list configured networks" },
2229 { "select_network", wpa_cli_cmd_select_network,
2230 cli_cmd_flag_none,
2231 "<network id> = select a network (disable others)" },
2232 { "enable_network", wpa_cli_cmd_enable_network,
2233 cli_cmd_flag_none,
2234 "<network id> = enable a network" },
2235 { "disable_network", wpa_cli_cmd_disable_network,
2236 cli_cmd_flag_none,
2237 "<network id> = disable a network" },
2238 { "add_network", wpa_cli_cmd_add_network,
2239 cli_cmd_flag_none,
2240 "= add a network" },
2241 { "remove_network", wpa_cli_cmd_remove_network,
2242 cli_cmd_flag_none,
2243 "<network id> = remove a network" },
2244 { "set_network", wpa_cli_cmd_set_network,
2245 cli_cmd_flag_sensitive,
2246 "<network id> <variable> <value> = set network variables (shows\n"
2247 " list of variables when run without arguments)" },
2248 { "get_network", wpa_cli_cmd_get_network,
2249 cli_cmd_flag_none,
2250 "<network id> <variable> = get network variables" },
2251 { "save_config", wpa_cli_cmd_save_config,
2252 cli_cmd_flag_none,
2253 "= save the current configuration" },
2254 { "disconnect", wpa_cli_cmd_disconnect,
2255 cli_cmd_flag_none,
2256 "= disconnect and wait for reassociate/reconnect command before\n"
2257 " connecting" },
2258 { "reconnect", wpa_cli_cmd_reconnect,
2259 cli_cmd_flag_none,
2260 "= like reassociate, but only takes effect if already disconnected"
2261 },
2262 { "scan", wpa_cli_cmd_scan,
2263 cli_cmd_flag_none,
2264 "= request new BSS scan" },
2265 { "scan_results", wpa_cli_cmd_scan_results,
2266 cli_cmd_flag_none,
2267 "= get latest scan results" },
2268 { "bss", wpa_cli_cmd_bss,
2269 cli_cmd_flag_none,
2270 "<<idx> | <bssid>> = get detailed scan result info" },
2271 { "get_capability", wpa_cli_cmd_get_capability,
2272 cli_cmd_flag_none,
2273 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2274 { "reconfigure", wpa_cli_cmd_reconfigure,
2275 cli_cmd_flag_none,
2276 "= force wpa_supplicant to re-read its configuration file" },
2277 { "terminate", wpa_cli_cmd_terminate,
2278 cli_cmd_flag_none,
2279 "= terminate wpa_supplicant" },
2280 { "interface_add", wpa_cli_cmd_interface_add,
2281 cli_cmd_flag_none,
2282 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2283 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2284 " are optional" },
2285 { "interface_remove", wpa_cli_cmd_interface_remove,
2286 cli_cmd_flag_none,
2287 "<ifname> = removes the interface" },
2288 { "interface_list", wpa_cli_cmd_interface_list,
2289 cli_cmd_flag_none,
2290 "= list available interfaces" },
2291 { "ap_scan", wpa_cli_cmd_ap_scan,
2292 cli_cmd_flag_none,
2293 "<value> = set ap_scan parameter" },
2294 { "stkstart", wpa_cli_cmd_stkstart,
2295 cli_cmd_flag_none,
2296 "<addr> = request STK negotiation with <addr>" },
2297 { "ft_ds", wpa_cli_cmd_ft_ds,
2298 cli_cmd_flag_none,
2299 "<addr> = request over-the-DS FT with <addr>" },
2300 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2301 cli_cmd_flag_none,
2302 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2303 { "wps_pin", wpa_cli_cmd_wps_pin,
2304 cli_cmd_flag_sensitive,
2305 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2306 "hardcoded)" },
2307 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2308 cli_cmd_flag_sensitive,
2309 "<PIN> = verify PIN checksum" },
2310 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2311 "Cancels the pending WPS operation" },
2312 #ifdef CONFIG_WPS_OOB
2313 { "wps_oob", wpa_cli_cmd_wps_oob,
2314 cli_cmd_flag_sensitive,
2315 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2316 #endif /* CONFIG_WPS_OOB */
2317 { "wps_reg", wpa_cli_cmd_wps_reg,
2318 cli_cmd_flag_sensitive,
2319 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2320 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2321 cli_cmd_flag_none,
2322 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2323 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2324 cli_cmd_flag_none,
2325 "= stop Wi-Fi Protected Setup External Registrar" },
2326 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2327 cli_cmd_flag_sensitive,
2328 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2329 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2330 cli_cmd_flag_none,
2331 "<UUID> = accept an Enrollee PBC using External Registrar" },
2332 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2333 cli_cmd_flag_sensitive,
2334 "<UUID> <PIN> = learn AP configuration" },
2335 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2336 cli_cmd_flag_sensitive,
2337 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2338 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2339 cli_cmd_flag_none,
2340 "<addr> = request RSN authentication with <addr> in IBSS" },
2341 #ifdef CONFIG_AP
2342 { "sta", wpa_cli_cmd_sta,
2343 cli_cmd_flag_none,
2344 "<addr> = get information about an associated station (AP)" },
2345 { "all_sta", wpa_cli_cmd_all_sta,
2346 cli_cmd_flag_none,
2347 "= get information about all associated stations (AP)" },
2348 #endif /* CONFIG_AP */
2349 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2350 "= notification of suspend/hibernate" },
2351 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2352 "= notification of resume/thaw" },
2353 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2354 "= drop SA without deauth/disassoc (test command)" },
2355 { "roam", wpa_cli_cmd_roam,
2356 cli_cmd_flag_none,
2357 "<addr> = roam to the specified BSS" },
2358 #ifdef CONFIG_P2P
2359 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2360 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2361 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2362 "= stop P2P Devices search" },
2363 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2364 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2365 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2366 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2367 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2368 "<ifname> = remote P2P group interface (terminate group if GO)" },
2369 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2370 "= add a new P2P group (local end as GO)" },
2371 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2372 "<addr> <method> = request provisioning discovery" },
2373 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2374 cli_cmd_flag_none,
2375 "= get the passphrase for a group (GO only)" },
2376 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2377 cli_cmd_flag_none,
2378 "<addr> <TLVs> = schedule service discovery request" },
2379 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2380 cli_cmd_flag_none,
2381 "<id> = cancel pending service discovery request" },
2382 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2383 cli_cmd_flag_none,
2384 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2385 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2386 cli_cmd_flag_none,
2387 "= indicate change in local services" },
2388 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2389 cli_cmd_flag_none,
2390 "<external> = set external processing of service discovery" },
2391 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2392 cli_cmd_flag_none,
2393 "= remove all stored service entries" },
2394 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2395 cli_cmd_flag_none,
2396 "<bonjour|upnp> <query|version> <response|service> = add a local "
2397 "service" },
2398 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2399 cli_cmd_flag_none,
2400 "<bonjour|upnp> <query|version> [|service] = remove a local "
2401 "service" },
2402 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2403 cli_cmd_flag_none,
2404 "<addr> = reject connection attempts from a specific peer" },
2405 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2406 cli_cmd_flag_none,
2407 "<cmd> [peer=addr] = invite peer" },
2408 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2409 "[discovered] = list known (optionally, only fully discovered) P2P "
2410 "peers" },
2411 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2412 "<address> = show information about known P2P peer" },
2413 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2414 "<field> <value> = set a P2P parameter" },
2415 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2416 "= flush P2P state" },
2417 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2418 "= cancel P2P group formation" },
2419 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2420 "[<duration> <interval>] [<duration> <interval>] = request GO "
2421 "presence" },
2422 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2423 "[<period> <interval>] = set extended listen timing" },
2424 #endif /* CONFIG_P2P */
2425 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2426 "<0/1> = disable/enable automatic reconnection" },
2427 { NULL, NULL, cli_cmd_flag_none, NULL }
2428 };
2429
2430
2431 /*
2432 * Prints command usage, lines are padded with the specified string.
2433 */
2434 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2435 {
2436 char c;
2437 size_t n;
2438
2439 printf("%s%s ", pad, cmd->cmd);
2440 for (n = 0; (c = cmd->usage[n]); n++) {
2441 printf("%c", c);
2442 if (c == '\n')
2443 printf("%s", pad);
2444 }
2445 printf("\n");
2446 }
2447
2448
2449 static void print_help(void)
2450 {
2451 int n;
2452 printf("commands:\n");
2453 for (n = 0; wpa_cli_commands[n].cmd; n++)
2454 print_cmd_help(&wpa_cli_commands[n], " ");
2455 }
2456
2457
2458 #ifdef CONFIG_READLINE
2459 static int cmd_has_sensitive_data(const char *cmd)
2460 {
2461 const char *c, *delim;
2462 int n;
2463 size_t len;
2464
2465 delim = os_strchr(cmd, ' ');
2466 if (delim)
2467 len = delim - cmd;
2468 else
2469 len = os_strlen(cmd);
2470
2471 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2472 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2473 return (wpa_cli_commands[n].flags &
2474 cli_cmd_flag_sensitive);
2475 }
2476 return 0;
2477 }
2478 #endif /* CONFIG_READLINE */
2479
2480
2481 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2482 {
2483 struct wpa_cli_cmd *cmd, *match = NULL;
2484 int count;
2485 int ret = 0;
2486
2487 count = 0;
2488 cmd = wpa_cli_commands;
2489 while (cmd->cmd) {
2490 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2491 {
2492 match = cmd;
2493 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2494 /* we have an exact match */
2495 count = 1;
2496 break;
2497 }
2498 count++;
2499 }
2500 cmd++;
2501 }
2502
2503 if (count > 1) {
2504 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2505 cmd = wpa_cli_commands;
2506 while (cmd->cmd) {
2507 if (os_strncasecmp(cmd->cmd, argv[0],
2508 os_strlen(argv[0])) == 0) {
2509 printf(" %s", cmd->cmd);
2510 }
2511 cmd++;
2512 }
2513 printf("\n");
2514 ret = 1;
2515 } else if (count == 0) {
2516 printf("Unknown command '%s'\n", argv[0]);
2517 ret = 1;
2518 } else {
2519 ret = match->handler(ctrl, argc - 1, &argv[1]);
2520 }
2521
2522 return ret;
2523 }
2524
2525
2526 static int str_match(const char *a, const char *b)
2527 {
2528 return os_strncmp(a, b, os_strlen(b)) == 0;
2529 }
2530
2531
2532 static int wpa_cli_exec(const char *program, const char *arg1,
2533 const char *arg2)
2534 {
2535 char *cmd;
2536 size_t len;
2537 int res;
2538 int ret = 0;
2539
2540 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2541 cmd = os_malloc(len);
2542 if (cmd == NULL)
2543 return -1;
2544 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2545 if (res < 0 || (size_t) res >= len) {
2546 os_free(cmd);
2547 return -1;
2548 }
2549 cmd[len - 1] = '\0';
2550 #ifndef _WIN32_WCE
2551 if (system(cmd) < 0)
2552 ret = -1;
2553 #endif /* _WIN32_WCE */
2554 os_free(cmd);
2555
2556 return ret;
2557 }
2558
2559
2560 static void wpa_cli_action_process(const char *msg)
2561 {
2562 const char *pos;
2563 char *copy = NULL, *id, *pos2;
2564
2565 pos = msg;
2566 if (*pos == '<') {
2567 /* skip priority */
2568 pos = os_strchr(pos, '>');
2569 if (pos)
2570 pos++;
2571 else
2572 pos = msg;
2573 }
2574
2575 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2576 int new_id = -1;
2577 os_unsetenv("WPA_ID");
2578 os_unsetenv("WPA_ID_STR");
2579 os_unsetenv("WPA_CTRL_DIR");
2580
2581 pos = os_strstr(pos, "[id=");
2582 if (pos)
2583 copy = os_strdup(pos + 4);
2584
2585 if (copy) {
2586 pos2 = id = copy;
2587 while (*pos2 && *pos2 != ' ')
2588 pos2++;
2589 *pos2++ = '\0';
2590 new_id = atoi(id);
2591 os_setenv("WPA_ID", id, 1);
2592 while (*pos2 && *pos2 != '=')
2593 pos2++;
2594 if (*pos2 == '=')
2595 pos2++;
2596 id = pos2;
2597 while (*pos2 && *pos2 != ']')
2598 pos2++;
2599 *pos2 = '\0';
2600 os_setenv("WPA_ID_STR", id, 1);
2601 os_free(copy);
2602 }
2603
2604 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2605
2606 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2607 wpa_cli_connected = 1;
2608 wpa_cli_last_id = new_id;
2609 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2610 }
2611 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2612 if (wpa_cli_connected) {
2613 wpa_cli_connected = 0;
2614 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2615 }
2616 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2617 wpa_cli_exec(action_file, ctrl_ifname, pos);
2618 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2619 wpa_cli_exec(action_file, ctrl_ifname, pos);
2620 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2621 wpa_cli_exec(action_file, ctrl_ifname, pos);
2622 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2623 wpa_cli_exec(action_file, ctrl_ifname, pos);
2624 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2625 wpa_cli_exec(action_file, ctrl_ifname, pos);
2626 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2627 wpa_cli_exec(action_file, ctrl_ifname, pos);
2628 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2629 printf("wpa_supplicant is terminating - stop monitoring\n");
2630 wpa_cli_quit = 1;
2631 }
2632 }
2633
2634
2635 #ifndef CONFIG_ANSI_C_EXTRA
2636 static void wpa_cli_action_cb(char *msg, size_t len)
2637 {
2638 wpa_cli_action_process(msg);
2639 }
2640 #endif /* CONFIG_ANSI_C_EXTRA */
2641
2642
2643 static void wpa_cli_reconnect(void)
2644 {
2645 wpa_cli_close_connection();
2646 wpa_cli_open_connection(ctrl_ifname, 1);
2647 }
2648
2649
2650 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
2651 int action_monitor)
2652 {
2653 int first = 1;
2654 if (ctrl_conn == NULL) {
2655 wpa_cli_reconnect();
2656 return;
2657 }
2658 while (wpa_ctrl_pending(ctrl) > 0) {
2659 char buf[256];
2660 size_t len = sizeof(buf) - 1;
2661 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
2662 buf[len] = '\0';
2663 if (action_monitor)
2664 wpa_cli_action_process(buf);
2665 else {
2666 if (wpa_cli_show_event(buf)) {
2667 if (in_read && first)
2668 printf("\r");
2669 first = 0;
2670 printf("%s\n", buf);
2671 readline_redraw();
2672 }
2673 }
2674 } else {
2675 printf("Could not read pending message.\n");
2676 break;
2677 }
2678 }
2679
2680 if (wpa_ctrl_pending(ctrl) < 0) {
2681 printf("Connection to wpa_supplicant lost - trying to "
2682 "reconnect\n");
2683 wpa_cli_reconnect();
2684 }
2685 }
2686
2687
2688 #ifdef CONFIG_READLINE
2689 static char * wpa_cli_cmd_gen(const char *text, int state)
2690 {
2691 static int i, len;
2692 const char *cmd;
2693
2694 if (state == 0) {
2695 i = 0;
2696 len = os_strlen(text);
2697 }
2698
2699 while ((cmd = wpa_cli_commands[i].cmd)) {
2700 i++;
2701 if (os_strncasecmp(cmd, text, len) == 0)
2702 return strdup(cmd);
2703 }
2704
2705 return NULL;
2706 }
2707
2708
2709 static char * wpa_cli_dummy_gen(const char *text, int state)
2710 {
2711 int i;
2712
2713 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2714 const char *cmd = wpa_cli_commands[i].cmd;
2715 size_t len = os_strlen(cmd);
2716 if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
2717 rl_line_buffer[len] == ' ') {
2718 printf("\n%s\n", wpa_cli_commands[i].usage);
2719 readline_redraw();
2720 break;
2721 }
2722 }
2723
2724 rl_attempted_completion_over = 1;
2725 return NULL;
2726 }
2727
2728
2729 static char * wpa_cli_status_gen(const char *text, int state)
2730 {
2731 static int i, len;
2732 char *options[] = {
2733 "verbose", NULL
2734 };
2735 char *t;
2736
2737 if (state == 0) {
2738 i = 0;
2739 len = os_strlen(text);
2740 }
2741
2742 while ((t = options[i])) {
2743 i++;
2744 if (os_strncasecmp(t, text, len) == 0)
2745 return strdup(t);
2746 }
2747
2748 rl_attempted_completion_over = 1;
2749 return NULL;
2750 }
2751
2752
2753 static char ** wpa_cli_completion(const char *text, int start, int end)
2754 {
2755 char * (*func)(const char *text, int state);
2756
2757 if (start == 0)
2758 func = wpa_cli_cmd_gen;
2759 else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2760 func = wpa_cli_status_gen;
2761 else
2762 func = wpa_cli_dummy_gen;
2763 return rl_completion_matches(text, func);
2764 }
2765 #endif /* CONFIG_READLINE */
2766
2767
2768 static void wpa_cli_interactive(void)
2769 {
2770 #define max_args 10
2771 char cmdbuf[256], *cmd, *argv[max_args], *pos;
2772 int argc;
2773 #ifdef CONFIG_READLINE
2774 char *home, *hfile = NULL;
2775 #endif /* CONFIG_READLINE */
2776
2777 printf("\nInteractive mode\n\n");
2778
2779 #ifdef CONFIG_READLINE
2780 rl_attempted_completion_function = wpa_cli_completion;
2781 home = getenv("HOME");
2782 if (home) {
2783 const char *fname = ".wpa_cli_history";
2784 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2785 hfile = os_malloc(hfile_len);
2786 if (hfile) {
2787 int res;
2788 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2789 fname);
2790 if (res >= 0 && res < hfile_len) {
2791 hfile[hfile_len - 1] = '\0';
2792 read_history(hfile);
2793 stifle_history(100);
2794 }
2795 }
2796 }
2797 #endif /* CONFIG_READLINE */
2798
2799 do {
2800 wpa_cli_recv_pending(mon_conn, 0, 0);
2801 #ifndef CONFIG_NATIVE_WINDOWS
2802 alarm(ping_interval);
2803 #endif /* CONFIG_NATIVE_WINDOWS */
2804 #ifdef CONFIG_WPA_CLI_FORK
2805 if (mon_pid)
2806 kill(mon_pid, SIGUSR1);
2807 #endif /* CONFIG_WPA_CLI_FORK */
2808 #ifdef CONFIG_READLINE
2809 cmd = readline("> ");
2810 if (cmd && *cmd) {
2811 HIST_ENTRY *h;
2812 while (next_history())
2813 ;
2814 h = previous_history();
2815 if (h == NULL || os_strcmp(cmd, h->line) != 0)
2816 add_history(cmd);
2817 next_history();
2818 }
2819 #else /* CONFIG_READLINE */
2820 printf("> ");
2821 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2822 #endif /* CONFIG_READLINE */
2823 #ifndef CONFIG_NATIVE_WINDOWS
2824 alarm(0);
2825 #endif /* CONFIG_NATIVE_WINDOWS */
2826 if (cmd == NULL)
2827 break;
2828 wpa_cli_recv_pending(mon_conn, 0, 0);
2829 pos = cmd;
2830 while (*pos != '\0') {
2831 if (*pos == '\n') {
2832 *pos = '\0';
2833 break;
2834 }
2835 pos++;
2836 }
2837 argc = 0;
2838 pos = cmd;
2839 for (;;) {
2840 while (*pos == ' ')
2841 pos++;
2842 if (*pos == '\0')
2843 break;
2844 argv[argc] = pos;
2845 argc++;
2846 if (argc == max_args)
2847 break;
2848 if (*pos == '"') {
2849 char *pos2 = os_strrchr(pos, '"');
2850 if (pos2)
2851 pos = pos2 + 1;
2852 }
2853 while (*pos != '\0' && *pos != ' ')
2854 pos++;
2855 if (*pos == ' ')
2856 *pos++ = '\0';
2857 }
2858 if (argc)
2859 wpa_request(ctrl_conn, argc, argv);
2860
2861 if (cmd != cmdbuf)
2862 free(cmd);
2863 #ifdef CONFIG_WPA_CLI_FORK
2864 if (mon_pid)
2865 kill(mon_pid, SIGUSR2);
2866 #endif /* CONFIG_WPA_CLI_FORK */
2867 } while (!wpa_cli_quit);
2868
2869 #ifdef CONFIG_READLINE
2870 if (hfile) {
2871 /* Save command history, excluding lines that may contain
2872 * passwords. */
2873 HIST_ENTRY *h;
2874 history_set_pos(0);
2875 while ((h = current_history())) {
2876 char *p = h->line;
2877 while (*p == ' ' || *p == '\t')
2878 p++;
2879 if (cmd_has_sensitive_data(p)) {
2880 h = remove_history(where_history());
2881 if (h) {
2882 os_free(h->line);
2883 os_free(h->data);
2884 os_free(h);
2885 } else
2886 next_history();
2887 } else
2888 next_history();
2889 }
2890 write_history(hfile);
2891 os_free(hfile);
2892 }
2893 #endif /* CONFIG_READLINE */
2894 }
2895
2896
2897 static void wpa_cli_action(struct wpa_ctrl *ctrl)
2898 {
2899 #ifdef CONFIG_ANSI_C_EXTRA
2900 /* TODO: ANSI C version(?) */
2901 printf("Action processing not supported in ANSI C build.\n");
2902 #else /* CONFIG_ANSI_C_EXTRA */
2903 fd_set rfds;
2904 int fd, res;
2905 struct timeval tv;
2906 char buf[256]; /* note: large enough to fit in unsolicited messages */
2907 size_t len;
2908
2909 fd = wpa_ctrl_get_fd(ctrl);
2910
2911 while (!wpa_cli_quit) {
2912 FD_ZERO(&rfds);
2913 FD_SET(fd, &rfds);
2914 tv.tv_sec = ping_interval;
2915 tv.tv_usec = 0;
2916 res = select(fd + 1, &rfds, NULL, NULL, &tv);
2917 if (res < 0 && errno != EINTR) {
2918 perror("select");
2919 break;
2920 }
2921
2922 if (FD_ISSET(fd, &rfds))
2923 wpa_cli_recv_pending(ctrl, 0, 1);
2924 else {
2925 /* verify that connection is still working */
2926 len = sizeof(buf) - 1;
2927 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2928 wpa_cli_action_cb) < 0 ||
2929 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2930 printf("wpa_supplicant did not reply to PING "
2931 "command - exiting\n");
2932 break;
2933 }
2934 }
2935 }
2936 #endif /* CONFIG_ANSI_C_EXTRA */
2937 }
2938
2939
2940 static void wpa_cli_cleanup(void)
2941 {
2942 wpa_cli_close_connection();
2943 if (pid_file)
2944 os_daemonize_terminate(pid_file);
2945
2946 os_program_deinit();
2947 }
2948
2949 static void wpa_cli_terminate(int sig)
2950 {
2951 wpa_cli_cleanup();
2952 exit(0);
2953 }
2954
2955
2956 #ifdef CONFIG_WPA_CLI_FORK
2957 static void wpa_cli_usr1(int sig)
2958 {
2959 readline_redraw();
2960 }
2961 #endif /* CONFIG_WPA_CLI_FORK */
2962
2963
2964 #ifndef CONFIG_NATIVE_WINDOWS
2965 static void wpa_cli_alarm(int sig)
2966 {
2967 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2968 printf("Connection to wpa_supplicant lost - trying to "
2969 "reconnect\n");
2970 wpa_cli_close_connection();
2971 }
2972 if (!ctrl_conn)
2973 wpa_cli_reconnect();
2974 if (mon_conn)
2975 wpa_cli_recv_pending(mon_conn, 1, 0);
2976 alarm(ping_interval);
2977 }
2978 #endif /* CONFIG_NATIVE_WINDOWS */
2979
2980
2981 static char * wpa_cli_get_default_ifname(void)
2982 {
2983 char *ifname = NULL;
2984
2985 #ifdef CONFIG_CTRL_IFACE_UNIX
2986 struct dirent *dent;
2987 DIR *dir = opendir(ctrl_iface_dir);
2988 if (!dir)
2989 return NULL;
2990 while ((dent = readdir(dir))) {
2991 #ifdef _DIRENT_HAVE_D_TYPE
2992 /*
2993 * Skip the file if it is not a socket. Also accept
2994 * DT_UNKNOWN (0) in case the C library or underlying
2995 * file system does not support d_type.
2996 */
2997 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2998 continue;
2999 #endif /* _DIRENT_HAVE_D_TYPE */
3000 if (os_strcmp(dent->d_name, ".") == 0 ||
3001 os_strcmp(dent->d_name, "..") == 0)
3002 continue;
3003 printf("Selected interface '%s'\n", dent->d_name);
3004 ifname = os_strdup(dent->d_name);
3005 break;
3006 }
3007 closedir(dir);
3008 #endif /* CONFIG_CTRL_IFACE_UNIX */
3009
3010 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3011 char buf[2048], *pos;
3012 size_t len;
3013 struct wpa_ctrl *ctrl;
3014 int ret;
3015
3016 ctrl = wpa_ctrl_open(NULL);
3017 if (ctrl == NULL)
3018 return NULL;
3019
3020 len = sizeof(buf) - 1;
3021 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3022 if (ret >= 0) {
3023 buf[len] = '\0';
3024 pos = os_strchr(buf, '\n');
3025 if (pos)
3026 *pos = '\0';
3027 ifname = os_strdup(buf);
3028 }
3029 wpa_ctrl_close(ctrl);
3030 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3031
3032 return ifname;
3033 }
3034
3035
3036 int main(int argc, char *argv[])
3037 {
3038 int warning_displayed = 0;
3039 int c;
3040 int daemonize = 0;
3041 int ret = 0;
3042 const char *global = NULL;
3043
3044 if (os_program_init())
3045 return -1;
3046
3047 for (;;) {
3048 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3049 if (c < 0)
3050 break;
3051 switch (c) {
3052 case 'a':
3053 action_file = optarg;
3054 break;
3055 case 'B':
3056 daemonize = 1;
3057 break;
3058 case 'g':
3059 global = optarg;
3060 break;
3061 case 'G':
3062 ping_interval = atoi(optarg);
3063 break;
3064 case 'h':
3065 usage();
3066 return 0;
3067 case 'v':
3068 printf("%s\n", wpa_cli_version);
3069 return 0;
3070 case 'i':
3071 os_free(ctrl_ifname);
3072 ctrl_ifname = os_strdup(optarg);
3073 break;
3074 case 'p':
3075 ctrl_iface_dir = optarg;
3076 break;
3077 case 'P':
3078 pid_file = optarg;
3079 break;
3080 default:
3081 usage();
3082 return -1;
3083 }
3084 }
3085
3086 interactive = (argc == optind) && (action_file == NULL);
3087
3088 if (interactive)
3089 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3090
3091 if (global) {
3092 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3093 ctrl_conn = wpa_ctrl_open(NULL);
3094 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3095 ctrl_conn = wpa_ctrl_open(global);
3096 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3097 if (ctrl_conn == NULL) {
3098 perror("Failed to connect to wpa_supplicant - "
3099 "wpa_ctrl_open");
3100 return -1;
3101 }
3102 }
3103
3104 #ifndef _WIN32_WCE
3105 signal(SIGINT, wpa_cli_terminate);
3106 signal(SIGTERM, wpa_cli_terminate);
3107 #endif /* _WIN32_WCE */
3108 #ifndef CONFIG_NATIVE_WINDOWS
3109 signal(SIGALRM, wpa_cli_alarm);
3110 #endif /* CONFIG_NATIVE_WINDOWS */
3111 #ifdef CONFIG_WPA_CLI_FORK
3112 signal(SIGUSR1, wpa_cli_usr1);
3113 #endif /* CONFIG_WPA_CLI_FORK */
3114
3115 if (ctrl_ifname == NULL)
3116 ctrl_ifname = wpa_cli_get_default_ifname();
3117
3118 if (interactive) {
3119 for (; !global;) {
3120 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3121 if (warning_displayed)
3122 printf("Connection established.\n");
3123 break;
3124 }
3125
3126 if (!warning_displayed) {
3127 printf("Could not connect to wpa_supplicant - "
3128 "re-trying\n");
3129 warning_displayed = 1;
3130 }
3131 os_sleep(1, 0);
3132 continue;
3133 }
3134 } else {
3135 if (!global &&
3136 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3137 perror("Failed to connect to wpa_supplicant - "
3138 "wpa_ctrl_open");
3139 return -1;
3140 }
3141
3142 if (action_file) {
3143 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3144 wpa_cli_attached = 1;
3145 } else {
3146 printf("Warning: Failed to attach to "
3147 "wpa_supplicant.\n");
3148 return -1;
3149 }
3150 }
3151 }
3152
3153 if (daemonize && os_daemonize(pid_file))
3154 return -1;
3155
3156 if (interactive)
3157 wpa_cli_interactive();
3158 else if (action_file)
3159 wpa_cli_action(ctrl_conn);
3160 else
3161 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3162
3163 os_free(ctrl_ifname);
3164 wpa_cli_cleanup();
3165
3166 return ret;
3167 }
3168
3169 #else /* CONFIG_CTRL_IFACE */
3170 int main(int argc, char *argv[])
3171 {
3172 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3173 return -1;
3174 }
3175 #endif /* CONFIG_CTRL_IFACE */