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