]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/wpa_cli.c
wpa_cli: Argument completion for p2p_group_remove
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
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
23 #include "common/wpa_ctrl.h"
24 #include "utils/common.h"
25 #include "utils/eloop.h"
26 #include "utils/edit.h"
27 #include "utils/list.h"
28 #include "common/version.h"
29 #ifdef ANDROID
30 #include <cutils/properties.h>
31 #endif /* ANDROID */
32
33
34 static const char *wpa_cli_version =
35 "wpa_cli v" VERSION_STR "\n"
36 "Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> and contributors";
37
38
39 static const char *wpa_cli_license =
40 "This program is free software. You can distribute it and/or modify it\n"
41 "under the terms of the GNU General Public License version 2.\n"
42 "\n"
43 "Alternatively, this software may be distributed under the terms of the\n"
44 "BSD license. See README and COPYING for more details.\n";
45
46 static const char *wpa_cli_full_license =
47 "This program is free software; you can redistribute it and/or modify\n"
48 "it under the terms of the GNU General Public License version 2 as\n"
49 "published by the Free Software Foundation.\n"
50 "\n"
51 "This program is distributed in the hope that it will be useful,\n"
52 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
53 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
54 "GNU General Public License for more details.\n"
55 "\n"
56 "You should have received a copy of the GNU General Public License\n"
57 "along with this program; if not, write to the Free Software\n"
58 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
59 "\n"
60 "Alternatively, this software may be distributed under the terms of the\n"
61 "BSD license.\n"
62 "\n"
63 "Redistribution and use in source and binary forms, with or without\n"
64 "modification, are permitted provided that the following conditions are\n"
65 "met:\n"
66 "\n"
67 "1. Redistributions of source code must retain the above copyright\n"
68 " notice, this list of conditions and the following disclaimer.\n"
69 "\n"
70 "2. Redistributions in binary form must reproduce the above copyright\n"
71 " notice, this list of conditions and the following disclaimer in the\n"
72 " documentation and/or other materials provided with the distribution.\n"
73 "\n"
74 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
75 " names of its contributors may be used to endorse or promote products\n"
76 " derived from this software without specific prior written permission.\n"
77 "\n"
78 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
79 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
80 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
81 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
82 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
83 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
84 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
85 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
86 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
87 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
88 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
89 "\n";
90
91 static struct wpa_ctrl *ctrl_conn;
92 static struct wpa_ctrl *mon_conn;
93 static int wpa_cli_quit = 0;
94 static int wpa_cli_attached = 0;
95 static int wpa_cli_connected = 0;
96 static int wpa_cli_last_id = 0;
97 #ifndef CONFIG_CTRL_IFACE_DIR
98 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
99 #endif /* CONFIG_CTRL_IFACE_DIR */
100 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
101 static char *ctrl_ifname = NULL;
102 static const char *pid_file = NULL;
103 static const char *action_file = NULL;
104 static int ping_interval = 5;
105 static int interactive = 0;
106
107 struct cli_txt_entry {
108 struct dl_list list;
109 char *txt;
110 };
111
112 static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
113 static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
114 static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
115
116
117 static void print_help(void);
118 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
119
120
121 static void usage(void)
122 {
123 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
124 "[-a<action file>] \\\n"
125 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
126 "[command..]\n"
127 " -h = help (show this usage text)\n"
128 " -v = shown version information\n"
129 " -a = run in daemon mode executing the action file based on "
130 "events from\n"
131 " wpa_supplicant\n"
132 " -B = run a daemon in the background\n"
133 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
134 " default interface: first interface found in socket path\n");
135 print_help();
136 }
137
138
139 static void cli_txt_list_free(struct cli_txt_entry *e)
140 {
141 dl_list_del(&e->list);
142 os_free(e->txt);
143 os_free(e);
144 }
145
146
147 static void cli_txt_list_flush(struct dl_list *list)
148 {
149 struct cli_txt_entry *e;
150 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
151 cli_txt_list_free(e);
152 }
153
154
155 static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
156 const char *txt)
157 {
158 struct cli_txt_entry *e;
159 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
160 if (os_strcmp(e->txt, txt) == 0)
161 return e;
162 }
163 return NULL;
164 }
165
166
167 static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
168 {
169 struct cli_txt_entry *e;
170 e = cli_txt_list_get(txt_list, txt);
171 if (e)
172 cli_txt_list_free(e);
173 }
174
175
176 static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
177 {
178 u8 addr[ETH_ALEN];
179 char buf[18];
180 if (hwaddr_aton(txt, addr) < 0)
181 return;
182 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
183 cli_txt_list_del(txt_list, buf);
184 }
185
186
187 static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
188 {
189 const char *end;
190 char *buf;
191 end = os_strchr(txt, ' ');
192 if (end == NULL)
193 end = txt + os_strlen(txt);
194 buf = os_malloc(end - txt + 1);
195 if (buf == NULL)
196 return;
197 os_memcpy(buf, txt, end - txt);
198 buf[end - txt] = '\0';
199 cli_txt_list_del(txt_list, buf);
200 os_free(buf);
201 }
202
203
204 static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
205 {
206 struct cli_txt_entry *e;
207 e = cli_txt_list_get(txt_list, txt);
208 if (e)
209 return 0;
210 e = os_zalloc(sizeof(*e));
211 if (e == NULL)
212 return -1;
213 e->txt = os_strdup(txt);
214 if (e->txt == NULL) {
215 os_free(e);
216 return -1;
217 }
218 dl_list_add(txt_list, &e->list);
219 return 0;
220 }
221
222
223 static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
224 {
225 u8 addr[ETH_ALEN];
226 char buf[18];
227 if (hwaddr_aton(txt, addr) < 0)
228 return -1;
229 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
230 return cli_txt_list_add(txt_list, buf);
231 }
232
233
234 static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
235 {
236 const char *end;
237 char *buf;
238 int ret;
239 end = os_strchr(txt, ' ');
240 if (end == NULL)
241 end = txt + os_strlen(txt);
242 buf = os_malloc(end - txt + 1);
243 if (buf == NULL)
244 return -1;
245 os_memcpy(buf, txt, end - txt);
246 buf[end - txt] = '\0';
247 ret = cli_txt_list_add(txt_list, buf);
248 os_free(buf);
249 return ret;
250 }
251
252
253 static char ** cli_txt_list_array(struct dl_list *txt_list)
254 {
255 unsigned int i, count = dl_list_len(txt_list);
256 char **res;
257 struct cli_txt_entry *e;
258
259 res = os_zalloc((count + 1) * sizeof(char *));
260 if (res == NULL)
261 return NULL;
262
263 i = 0;
264 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
265 res[i] = os_strdup(e->txt);
266 if (res[i] == NULL)
267 break;
268 i++;
269 }
270
271 return res;
272 }
273
274
275 static int get_cmd_arg_num(const char *str, int pos)
276 {
277 int arg = 0, i;
278
279 for (i = 0; i <= pos; i++) {
280 if (str[i] != ' ') {
281 arg++;
282 while (i <= pos && str[i] != ' ')
283 i++;
284 }
285 }
286
287 if (arg > 0)
288 arg--;
289 return arg;
290 }
291
292
293 static int str_starts(const char *src, const char *match)
294 {
295 return os_strncmp(src, match, os_strlen(match)) == 0;
296 }
297
298
299 static int wpa_cli_show_event(const char *event)
300 {
301 const char *start;
302
303 start = os_strchr(event, '>');
304 if (start == NULL)
305 return 1;
306
307 start++;
308 /*
309 * Skip BSS added/removed events since they can be relatively frequent
310 * and are likely of not much use for an interactive user.
311 */
312 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
313 str_starts(start, WPA_EVENT_BSS_REMOVED))
314 return 0;
315
316 return 1;
317 }
318
319
320 static int wpa_cli_open_connection(const char *ifname, int attach)
321 {
322 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
323 ctrl_conn = wpa_ctrl_open(ifname);
324 if (ctrl_conn == NULL)
325 return -1;
326
327 if (attach && interactive)
328 mon_conn = wpa_ctrl_open(ifname);
329 else
330 mon_conn = NULL;
331 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
332 char *cfile = NULL;
333 int flen, res;
334
335 if (ifname == NULL)
336 return -1;
337
338 #ifdef ANDROID
339 if (access(ctrl_iface_dir, F_OK) < 0) {
340 cfile = os_strdup(ifname);
341 if (cfile == NULL)
342 return -1;
343 }
344 #endif /* ANDROID */
345
346 if (cfile == NULL) {
347 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
348 cfile = os_malloc(flen);
349 if (cfile == NULL)
350 return -1;
351 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
352 ifname);
353 if (res < 0 || res >= flen) {
354 os_free(cfile);
355 return -1;
356 }
357 }
358
359 ctrl_conn = wpa_ctrl_open(cfile);
360 if (ctrl_conn == NULL) {
361 os_free(cfile);
362 return -1;
363 }
364
365 if (attach && interactive)
366 mon_conn = wpa_ctrl_open(cfile);
367 else
368 mon_conn = NULL;
369 os_free(cfile);
370 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
371
372 if (mon_conn) {
373 if (wpa_ctrl_attach(mon_conn) == 0) {
374 wpa_cli_attached = 1;
375 if (interactive)
376 eloop_register_read_sock(
377 wpa_ctrl_get_fd(mon_conn),
378 wpa_cli_mon_receive, NULL, NULL);
379 } else {
380 printf("Warning: Failed to attach to "
381 "wpa_supplicant.\n");
382 return -1;
383 }
384 }
385
386 return 0;
387 }
388
389
390 static void wpa_cli_close_connection(void)
391 {
392 if (ctrl_conn == NULL)
393 return;
394
395 if (wpa_cli_attached) {
396 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
397 wpa_cli_attached = 0;
398 }
399 wpa_ctrl_close(ctrl_conn);
400 ctrl_conn = NULL;
401 if (mon_conn) {
402 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
403 wpa_ctrl_close(mon_conn);
404 mon_conn = NULL;
405 }
406 }
407
408
409 static void wpa_cli_msg_cb(char *msg, size_t len)
410 {
411 printf("%s\n", msg);
412 }
413
414
415 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
416 {
417 char buf[2048];
418 size_t len;
419 int ret;
420
421 if (ctrl_conn == NULL) {
422 printf("Not connected to wpa_supplicant - command dropped.\n");
423 return -1;
424 }
425 len = sizeof(buf) - 1;
426 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
427 wpa_cli_msg_cb);
428 if (ret == -2) {
429 printf("'%s' command timed out.\n", cmd);
430 return -2;
431 } else if (ret < 0) {
432 printf("'%s' command failed.\n", cmd);
433 return -1;
434 }
435 if (print) {
436 buf[len] = '\0';
437 printf("%s", buf);
438 if (interactive && len > 0 && buf[len - 1] != '\n')
439 printf("\n");
440 }
441 return 0;
442 }
443
444
445 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
446 {
447 return _wpa_ctrl_command(ctrl, cmd, 1);
448 }
449
450
451 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
452 {
453 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
454 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
455 }
456
457
458 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
459 {
460 return wpa_ctrl_command(ctrl, "PING");
461 }
462
463
464 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
465 {
466 return wpa_ctrl_command(ctrl, "RELOG");
467 }
468
469
470 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
471 {
472 char cmd[256];
473 int ret;
474 if (argc == 0)
475 return -1;
476 ret = os_snprintf(cmd, sizeof(cmd), "NOTE %s", argv[0]);
477 if (ret < 0 || (size_t) ret >= sizeof(cmd))
478 return -1;
479 return wpa_ctrl_command(ctrl, cmd);
480 }
481
482
483 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
484 {
485 return wpa_ctrl_command(ctrl, "MIB");
486 }
487
488
489 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
490 {
491 return wpa_ctrl_command(ctrl, "PMKSA");
492 }
493
494
495 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
496 {
497 print_help();
498 return 0;
499 }
500
501
502 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
503 {
504 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
505 return 0;
506 }
507
508
509 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
510 {
511 wpa_cli_quit = 1;
512 if (interactive)
513 eloop_terminate();
514 return 0;
515 }
516
517
518 static void wpa_cli_show_variables(void)
519 {
520 printf("set variables:\n"
521 " EAPOL::heldPeriod (EAPOL state machine held period, "
522 "in seconds)\n"
523 " EAPOL::authPeriod (EAPOL state machine authentication "
524 "period, in seconds)\n"
525 " EAPOL::startPeriod (EAPOL state machine start period, in "
526 "seconds)\n"
527 " EAPOL::maxStart (EAPOL state machine maximum start "
528 "attempts)\n");
529 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
530 "seconds)\n"
531 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
532 " threshold\n\tpercentage)\n"
533 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
534 "security\n\tassociation in seconds)\n");
535 }
536
537
538 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
539 {
540 char cmd[256];
541 int res;
542
543 if (argc == 0) {
544 wpa_cli_show_variables();
545 return 0;
546 }
547
548 if (argc != 1 && argc != 2) {
549 printf("Invalid SET command: needs two arguments (variable "
550 "name and value)\n");
551 return -1;
552 }
553
554 if (argc == 1)
555 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
556 else
557 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
558 argv[0], argv[1]);
559 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
560 printf("Too long SET command.\n");
561 return -1;
562 }
563 return wpa_ctrl_command(ctrl, cmd);
564 }
565
566
567 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
568 {
569 char cmd[256];
570 int res;
571
572 if (argc != 1) {
573 printf("Invalid GET command: need one argument (variable "
574 "name)\n");
575 return -1;
576 }
577
578 res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
579 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
580 printf("Too long GET command.\n");
581 return -1;
582 }
583 return wpa_ctrl_command(ctrl, cmd);
584 }
585
586
587 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
588 {
589 return wpa_ctrl_command(ctrl, "LOGOFF");
590 }
591
592
593 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
594 {
595 return wpa_ctrl_command(ctrl, "LOGON");
596 }
597
598
599 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
600 char *argv[])
601 {
602 return wpa_ctrl_command(ctrl, "REASSOCIATE");
603 }
604
605
606 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
607 char *argv[])
608 {
609 char cmd[256];
610 int res;
611
612 if (argc != 1) {
613 printf("Invalid PREAUTH command: needs one argument "
614 "(BSSID)\n");
615 return -1;
616 }
617
618 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
619 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
620 printf("Too long PREAUTH command.\n");
621 return -1;
622 }
623 return wpa_ctrl_command(ctrl, cmd);
624 }
625
626
627 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
628 {
629 char cmd[256];
630 int res;
631
632 if (argc != 1) {
633 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
634 "value)\n");
635 return -1;
636 }
637 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
638 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
639 printf("Too long AP_SCAN command.\n");
640 return -1;
641 }
642 return wpa_ctrl_command(ctrl, cmd);
643 }
644
645
646 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
647 char *argv[])
648 {
649 char cmd[256];
650 int res;
651
652 if (argc != 1) {
653 printf("Invalid SCAN_INTERVAL command: needs one argument "
654 "scan_interval value)\n");
655 return -1;
656 }
657 res = os_snprintf(cmd, sizeof(cmd), "SCAN_INTERVAL %s", argv[0]);
658 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
659 printf("Too long SCAN_INTERVAL command.\n");
660 return -1;
661 }
662 return wpa_ctrl_command(ctrl, cmd);
663 }
664
665
666 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
667 char *argv[])
668 {
669 char cmd[256];
670 int res;
671
672 if (argc != 1) {
673 printf("Invalid BSS_EXPIRE_AGE command: needs one argument "
674 "(bss_expire_age value)\n");
675 return -1;
676 }
677 res = os_snprintf(cmd, sizeof(cmd), "BSS_EXPIRE_AGE %s", argv[0]);
678 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
679 printf("Too long BSS_EXPIRE_AGE command.\n");
680 return -1;
681 }
682 return wpa_ctrl_command(ctrl, cmd);
683 }
684
685
686 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
687 char *argv[])
688 {
689 char cmd[256];
690 int res;
691
692 if (argc != 1) {
693 printf("Invalid BSS_EXPIRE_COUNT command: needs one argument "
694 "(bss_expire_count value)\n");
695 return -1;
696 }
697 res = os_snprintf(cmd, sizeof(cmd), "BSS_EXPIRE_COUNT %s", argv[0]);
698 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
699 printf("Too long BSS_EXPIRE_COUNT command.\n");
700 return -1;
701 }
702 return wpa_ctrl_command(ctrl, cmd);
703 }
704
705
706 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
707 char *argv[])
708 {
709 char cmd[256];
710 int res;
711
712 if (argc != 1) {
713 printf("Invalid STKSTART command: needs one argument "
714 "(Peer STA MAC address)\n");
715 return -1;
716 }
717
718 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
719 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
720 printf("Too long STKSTART command.\n");
721 return -1;
722 }
723 return wpa_ctrl_command(ctrl, cmd);
724 }
725
726
727 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
728 {
729 char cmd[256];
730 int res;
731
732 if (argc != 1) {
733 printf("Invalid FT_DS command: needs one argument "
734 "(Target AP MAC address)\n");
735 return -1;
736 }
737
738 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
739 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
740 printf("Too long FT_DS command.\n");
741 return -1;
742 }
743 return wpa_ctrl_command(ctrl, cmd);
744 }
745
746
747 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
748 {
749 char cmd[256];
750 int res;
751
752 if (argc == 0) {
753 /* Any BSSID */
754 return wpa_ctrl_command(ctrl, "WPS_PBC");
755 }
756
757 /* Specific BSSID */
758 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
759 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
760 printf("Too long WPS_PBC command.\n");
761 return -1;
762 }
763 return wpa_ctrl_command(ctrl, cmd);
764 }
765
766
767 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
768 {
769 char cmd[256];
770 int res;
771
772 if (argc == 0) {
773 printf("Invalid WPS_PIN command: need one or two arguments:\n"
774 "- BSSID: use 'any' to select any\n"
775 "- PIN: optional, used only with devices that have no "
776 "display\n");
777 return -1;
778 }
779
780 if (argc == 1) {
781 /* Use dynamically generated PIN (returned as reply) */
782 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
783 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
784 printf("Too long WPS_PIN command.\n");
785 return -1;
786 }
787 return wpa_ctrl_command(ctrl, cmd);
788 }
789
790 /* Use hardcoded PIN from a label */
791 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
792 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
793 printf("Too long WPS_PIN command.\n");
794 return -1;
795 }
796 return wpa_ctrl_command(ctrl, cmd);
797 }
798
799
800 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
801 char *argv[])
802 {
803 char cmd[256];
804 int res;
805
806 if (argc != 1 && argc != 2) {
807 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
808 "- PIN to be verified\n");
809 return -1;
810 }
811
812 if (argc == 2)
813 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
814 argv[0], argv[1]);
815 else
816 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
817 argv[0]);
818 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
819 printf("Too long WPS_CHECK_PIN command.\n");
820 return -1;
821 }
822 return wpa_ctrl_command(ctrl, cmd);
823 }
824
825
826 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
827 char *argv[])
828 {
829 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
830 }
831
832
833 #ifdef CONFIG_WPS_OOB
834 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
835 {
836 char cmd[256];
837 int res;
838
839 if (argc != 3 && argc != 4) {
840 printf("Invalid WPS_OOB command: need three or four "
841 "arguments:\n"
842 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
843 "- PATH: path of OOB device like '/mnt'\n"
844 "- METHOD: OOB method 'pin-e' or 'pin-r', "
845 "'cred'\n"
846 "- DEV_NAME: (only for NFC) device name like "
847 "'pn531'\n");
848 return -1;
849 }
850
851 if (argc == 3)
852 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
853 argv[0], argv[1], argv[2]);
854 else
855 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
856 argv[0], argv[1], argv[2], argv[3]);
857 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
858 printf("Too long WPS_OOB command.\n");
859 return -1;
860 }
861 return wpa_ctrl_command(ctrl, cmd);
862 }
863 #endif /* CONFIG_WPS_OOB */
864
865
866 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
867 {
868 char cmd[256];
869 int res;
870
871 if (argc == 2)
872 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
873 argv[0], argv[1]);
874 else if (argc == 5 || argc == 6) {
875 char ssid_hex[2 * 32 + 1];
876 char key_hex[2 * 64 + 1];
877 int i;
878
879 ssid_hex[0] = '\0';
880 for (i = 0; i < 32; i++) {
881 if (argv[2][i] == '\0')
882 break;
883 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
884 }
885
886 key_hex[0] = '\0';
887 if (argc == 6) {
888 for (i = 0; i < 64; i++) {
889 if (argv[5][i] == '\0')
890 break;
891 os_snprintf(&key_hex[i * 2], 3, "%02x",
892 argv[5][i]);
893 }
894 }
895
896 res = os_snprintf(cmd, sizeof(cmd),
897 "WPS_REG %s %s %s %s %s %s",
898 argv[0], argv[1], ssid_hex, argv[3], argv[4],
899 key_hex);
900 } else {
901 printf("Invalid WPS_REG command: need two arguments:\n"
902 "- BSSID of the target AP\n"
903 "- AP PIN\n");
904 printf("Alternatively, six arguments can be used to "
905 "reconfigure the AP:\n"
906 "- BSSID of the target AP\n"
907 "- AP PIN\n"
908 "- new SSID\n"
909 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
910 "- new encr (NONE, WEP, TKIP, CCMP)\n"
911 "- new key\n");
912 return -1;
913 }
914
915 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
916 printf("Too long WPS_REG command.\n");
917 return -1;
918 }
919 return wpa_ctrl_command(ctrl, cmd);
920 }
921
922
923 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
924 char *argv[])
925 {
926 char cmd[256];
927 int res;
928
929 if (argc < 1) {
930 printf("Invalid WPS_AP_PIN command: needs at least one "
931 "argument\n");
932 return -1;
933 }
934
935 if (argc > 2)
936 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s %s",
937 argv[0], argv[1], argv[2]);
938 else if (argc > 1)
939 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s %s",
940 argv[0], argv[1]);
941 else
942 res = os_snprintf(cmd, sizeof(cmd), "WPS_AP_PIN %s",
943 argv[0]);
944 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
945 printf("Too long WPS_AP_PIN command.\n");
946 return -1;
947 }
948 return wpa_ctrl_command(ctrl, cmd);
949 }
950
951
952 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
953 char *argv[])
954 {
955 char cmd[100];
956 if (argc > 0) {
957 os_snprintf(cmd, sizeof(cmd), "WPS_ER_START %s", argv[0]);
958 return wpa_ctrl_command(ctrl, cmd);
959 }
960 return wpa_ctrl_command(ctrl, "WPS_ER_START");
961 }
962
963
964 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
965 char *argv[])
966 {
967 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
968
969 }
970
971
972 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
973 char *argv[])
974 {
975 char cmd[256];
976 int res;
977
978 if (argc < 2) {
979 printf("Invalid WPS_ER_PIN command: need at least two "
980 "arguments:\n"
981 "- UUID: use 'any' to select any\n"
982 "- PIN: Enrollee PIN\n"
983 "optional: - Enrollee MAC address\n");
984 return -1;
985 }
986
987 if (argc > 2)
988 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s %s",
989 argv[0], argv[1], argv[2]);
990 else
991 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
992 argv[0], argv[1]);
993 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
994 printf("Too long WPS_ER_PIN command.\n");
995 return -1;
996 }
997 return wpa_ctrl_command(ctrl, cmd);
998 }
999
1000
1001 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1002 char *argv[])
1003 {
1004 char cmd[256];
1005 int res;
1006
1007 if (argc != 1) {
1008 printf("Invalid WPS_ER_PBC command: need one argument:\n"
1009 "- UUID: Specify the Enrollee\n");
1010 return -1;
1011 }
1012
1013 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
1014 argv[0]);
1015 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1016 printf("Too long WPS_ER_PBC command.\n");
1017 return -1;
1018 }
1019 return wpa_ctrl_command(ctrl, cmd);
1020 }
1021
1022
1023 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1024 char *argv[])
1025 {
1026 char cmd[256];
1027 int res;
1028
1029 if (argc != 2) {
1030 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1031 "- UUID: specify which AP to use\n"
1032 "- PIN: AP PIN\n");
1033 return -1;
1034 }
1035
1036 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
1037 argv[0], argv[1]);
1038 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1039 printf("Too long WPS_ER_LEARN command.\n");
1040 return -1;
1041 }
1042 return wpa_ctrl_command(ctrl, cmd);
1043 }
1044
1045
1046 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1047 char *argv[])
1048 {
1049 char cmd[256];
1050 int res;
1051
1052 if (argc != 2) {
1053 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1054 "arguments:\n"
1055 "- UUID: specify which AP to use\n"
1056 "- Network configuration id\n");
1057 return -1;
1058 }
1059
1060 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_SET_CONFIG %s %s",
1061 argv[0], argv[1]);
1062 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1063 printf("Too long WPS_ER_SET_CONFIG command.\n");
1064 return -1;
1065 }
1066 return wpa_ctrl_command(ctrl, cmd);
1067 }
1068
1069
1070 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1071 char *argv[])
1072 {
1073 char cmd[256];
1074 int res;
1075
1076 if (argc == 5 || argc == 6) {
1077 char ssid_hex[2 * 32 + 1];
1078 char key_hex[2 * 64 + 1];
1079 int i;
1080
1081 ssid_hex[0] = '\0';
1082 for (i = 0; i < 32; i++) {
1083 if (argv[2][i] == '\0')
1084 break;
1085 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1086 }
1087
1088 key_hex[0] = '\0';
1089 if (argc == 6) {
1090 for (i = 0; i < 64; i++) {
1091 if (argv[5][i] == '\0')
1092 break;
1093 os_snprintf(&key_hex[i * 2], 3, "%02x",
1094 argv[5][i]);
1095 }
1096 }
1097
1098 res = os_snprintf(cmd, sizeof(cmd),
1099 "WPS_ER_CONFIG %s %s %s %s %s %s",
1100 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1101 key_hex);
1102 } else {
1103 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1104 "- AP UUID\n"
1105 "- AP PIN\n"
1106 "- new SSID\n"
1107 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1108 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1109 "- new key\n");
1110 return -1;
1111 }
1112
1113 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1114 printf("Too long WPS_ER_CONFIG command.\n");
1115 return -1;
1116 }
1117 return wpa_ctrl_command(ctrl, cmd);
1118 }
1119
1120
1121 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1122 {
1123 char cmd[256];
1124 int res;
1125
1126 if (argc != 1) {
1127 printf("Invalid IBSS_RSN command: needs one argument "
1128 "(Peer STA MAC address)\n");
1129 return -1;
1130 }
1131
1132 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
1133 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1134 printf("Too long IBSS_RSN command.\n");
1135 return -1;
1136 }
1137 return wpa_ctrl_command(ctrl, cmd);
1138 }
1139
1140
1141 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1142 {
1143 char cmd[256];
1144 int res;
1145
1146 if (argc != 1) {
1147 printf("Invalid LEVEL command: needs one argument (debug "
1148 "level)\n");
1149 return -1;
1150 }
1151 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
1152 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1153 printf("Too long LEVEL command.\n");
1154 return -1;
1155 }
1156 return wpa_ctrl_command(ctrl, cmd);
1157 }
1158
1159
1160 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1161 {
1162 char cmd[256], *pos, *end;
1163 int i, ret;
1164
1165 if (argc < 2) {
1166 printf("Invalid IDENTITY command: needs two arguments "
1167 "(network id and identity)\n");
1168 return -1;
1169 }
1170
1171 end = cmd + sizeof(cmd);
1172 pos = cmd;
1173 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1174 argv[0], argv[1]);
1175 if (ret < 0 || ret >= end - pos) {
1176 printf("Too long IDENTITY command.\n");
1177 return -1;
1178 }
1179 pos += ret;
1180 for (i = 2; i < argc; i++) {
1181 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1182 if (ret < 0 || ret >= end - pos) {
1183 printf("Too long IDENTITY command.\n");
1184 return -1;
1185 }
1186 pos += ret;
1187 }
1188
1189 return wpa_ctrl_command(ctrl, cmd);
1190 }
1191
1192
1193 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1194 {
1195 char cmd[256], *pos, *end;
1196 int i, ret;
1197
1198 if (argc < 2) {
1199 printf("Invalid PASSWORD command: needs two arguments "
1200 "(network id and password)\n");
1201 return -1;
1202 }
1203
1204 end = cmd + sizeof(cmd);
1205 pos = cmd;
1206 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1207 argv[0], argv[1]);
1208 if (ret < 0 || ret >= end - pos) {
1209 printf("Too long PASSWORD command.\n");
1210 return -1;
1211 }
1212 pos += ret;
1213 for (i = 2; i < argc; i++) {
1214 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1215 if (ret < 0 || ret >= end - pos) {
1216 printf("Too long PASSWORD command.\n");
1217 return -1;
1218 }
1219 pos += ret;
1220 }
1221
1222 return wpa_ctrl_command(ctrl, cmd);
1223 }
1224
1225
1226 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1227 char *argv[])
1228 {
1229 char cmd[256], *pos, *end;
1230 int i, ret;
1231
1232 if (argc < 2) {
1233 printf("Invalid NEW_PASSWORD command: needs two arguments "
1234 "(network id and password)\n");
1235 return -1;
1236 }
1237
1238 end = cmd + sizeof(cmd);
1239 pos = cmd;
1240 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1241 argv[0], argv[1]);
1242 if (ret < 0 || ret >= end - pos) {
1243 printf("Too long NEW_PASSWORD command.\n");
1244 return -1;
1245 }
1246 pos += ret;
1247 for (i = 2; i < argc; i++) {
1248 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1249 if (ret < 0 || ret >= end - pos) {
1250 printf("Too long NEW_PASSWORD command.\n");
1251 return -1;
1252 }
1253 pos += ret;
1254 }
1255
1256 return wpa_ctrl_command(ctrl, cmd);
1257 }
1258
1259
1260 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1261 {
1262 char cmd[256], *pos, *end;
1263 int i, ret;
1264
1265 if (argc < 2) {
1266 printf("Invalid PIN command: needs two arguments "
1267 "(network id and pin)\n");
1268 return -1;
1269 }
1270
1271 end = cmd + sizeof(cmd);
1272 pos = cmd;
1273 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1274 argv[0], argv[1]);
1275 if (ret < 0 || ret >= end - pos) {
1276 printf("Too long PIN command.\n");
1277 return -1;
1278 }
1279 pos += ret;
1280 for (i = 2; i < argc; i++) {
1281 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1282 if (ret < 0 || ret >= end - pos) {
1283 printf("Too long PIN command.\n");
1284 return -1;
1285 }
1286 pos += ret;
1287 }
1288 return wpa_ctrl_command(ctrl, cmd);
1289 }
1290
1291
1292 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1293 {
1294 char cmd[256], *pos, *end;
1295 int i, ret;
1296
1297 if (argc < 2) {
1298 printf("Invalid OTP command: needs two arguments (network "
1299 "id and password)\n");
1300 return -1;
1301 }
1302
1303 end = cmd + sizeof(cmd);
1304 pos = cmd;
1305 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1306 argv[0], argv[1]);
1307 if (ret < 0 || ret >= end - pos) {
1308 printf("Too long OTP command.\n");
1309 return -1;
1310 }
1311 pos += ret;
1312 for (i = 2; i < argc; i++) {
1313 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1314 if (ret < 0 || ret >= end - pos) {
1315 printf("Too long OTP command.\n");
1316 return -1;
1317 }
1318 pos += ret;
1319 }
1320
1321 return wpa_ctrl_command(ctrl, cmd);
1322 }
1323
1324
1325 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1326 char *argv[])
1327 {
1328 char cmd[256], *pos, *end;
1329 int i, ret;
1330
1331 if (argc < 2) {
1332 printf("Invalid PASSPHRASE command: needs two arguments "
1333 "(network id and passphrase)\n");
1334 return -1;
1335 }
1336
1337 end = cmd + sizeof(cmd);
1338 pos = cmd;
1339 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1340 argv[0], argv[1]);
1341 if (ret < 0 || ret >= end - pos) {
1342 printf("Too long PASSPHRASE command.\n");
1343 return -1;
1344 }
1345 pos += ret;
1346 for (i = 2; i < argc; i++) {
1347 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1348 if (ret < 0 || ret >= end - pos) {
1349 printf("Too long PASSPHRASE command.\n");
1350 return -1;
1351 }
1352 pos += ret;
1353 }
1354
1355 return wpa_ctrl_command(ctrl, cmd);
1356 }
1357
1358
1359 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1360 {
1361 char cmd[256], *pos, *end;
1362 int i, ret;
1363
1364 if (argc < 2) {
1365 printf("Invalid BSSID command: needs two arguments (network "
1366 "id and BSSID)\n");
1367 return -1;
1368 }
1369
1370 end = cmd + sizeof(cmd);
1371 pos = cmd;
1372 ret = os_snprintf(pos, end - pos, "BSSID");
1373 if (ret < 0 || ret >= end - pos) {
1374 printf("Too long BSSID command.\n");
1375 return -1;
1376 }
1377 pos += ret;
1378 for (i = 0; i < argc; i++) {
1379 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1380 if (ret < 0 || ret >= end - pos) {
1381 printf("Too long BSSID command.\n");
1382 return -1;
1383 }
1384 pos += ret;
1385 }
1386
1387 return wpa_ctrl_command(ctrl, cmd);
1388 }
1389
1390
1391 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1392 {
1393 char cmd[256], *pos, *end;
1394 int i, ret;
1395
1396 end = cmd + sizeof(cmd);
1397 pos = cmd;
1398 ret = os_snprintf(pos, end - pos, "BLACKLIST");
1399 if (ret < 0 || ret >= end - pos) {
1400 printf("Too long BLACKLIST command.\n");
1401 return -1;
1402 }
1403 pos += ret;
1404 for (i = 0; i < argc; i++) {
1405 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1406 if (ret < 0 || ret >= end - pos) {
1407 printf("Too long BLACKLIST command.\n");
1408 return -1;
1409 }
1410 pos += ret;
1411 }
1412
1413 return wpa_ctrl_command(ctrl, cmd);
1414 }
1415
1416
1417 static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1418 {
1419 char cmd[256], *pos, *end;
1420 int i, ret;
1421
1422 end = cmd + sizeof(cmd);
1423 pos = cmd;
1424 ret = os_snprintf(pos, end - pos, "LOG_LEVEL");
1425 if (ret < 0 || ret >= end - pos) {
1426 printf("Too long LOG_LEVEL command.\n");
1427 return -1;
1428 }
1429 pos += ret;
1430 for (i = 0; i < argc; i++) {
1431 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1432 if (ret < 0 || ret >= end - pos) {
1433 printf("Too long LOG_LEVEL command.\n");
1434 return -1;
1435 }
1436 pos += ret;
1437 }
1438
1439 return wpa_ctrl_command(ctrl, cmd);
1440 }
1441
1442
1443 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1444 char *argv[])
1445 {
1446 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1447 }
1448
1449
1450 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1451 char *argv[])
1452 {
1453 char cmd[32];
1454 int res;
1455
1456 if (argc < 1) {
1457 printf("Invalid SELECT_NETWORK command: needs one argument "
1458 "(network id)\n");
1459 return -1;
1460 }
1461
1462 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1463 if (res < 0 || (size_t) res >= sizeof(cmd))
1464 return -1;
1465 cmd[sizeof(cmd) - 1] = '\0';
1466
1467 return wpa_ctrl_command(ctrl, cmd);
1468 }
1469
1470
1471 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1472 char *argv[])
1473 {
1474 char cmd[32];
1475 int res;
1476
1477 if (argc < 1) {
1478 printf("Invalid ENABLE_NETWORK command: needs one argument "
1479 "(network id)\n");
1480 return -1;
1481 }
1482
1483 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1484 if (res < 0 || (size_t) res >= sizeof(cmd))
1485 return -1;
1486 cmd[sizeof(cmd) - 1] = '\0';
1487
1488 return wpa_ctrl_command(ctrl, cmd);
1489 }
1490
1491
1492 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1493 char *argv[])
1494 {
1495 char cmd[32];
1496 int res;
1497
1498 if (argc < 1) {
1499 printf("Invalid DISABLE_NETWORK command: needs one argument "
1500 "(network id)\n");
1501 return -1;
1502 }
1503
1504 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1505 if (res < 0 || (size_t) res >= sizeof(cmd))
1506 return -1;
1507 cmd[sizeof(cmd) - 1] = '\0';
1508
1509 return wpa_ctrl_command(ctrl, cmd);
1510 }
1511
1512
1513 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1514 char *argv[])
1515 {
1516 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1517 }
1518
1519
1520 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1521 char *argv[])
1522 {
1523 char cmd[32];
1524 int res;
1525
1526 if (argc < 1) {
1527 printf("Invalid REMOVE_NETWORK command: needs one argument "
1528 "(network id)\n");
1529 return -1;
1530 }
1531
1532 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1533 if (res < 0 || (size_t) res >= sizeof(cmd))
1534 return -1;
1535 cmd[sizeof(cmd) - 1] = '\0';
1536
1537 return wpa_ctrl_command(ctrl, cmd);
1538 }
1539
1540
1541 static void wpa_cli_show_network_variables(void)
1542 {
1543 printf("set_network variables:\n"
1544 " ssid (network name, SSID)\n"
1545 " psk (WPA passphrase or pre-shared key)\n"
1546 " key_mgmt (key management protocol)\n"
1547 " identity (EAP identity)\n"
1548 " password (EAP password)\n"
1549 " ...\n"
1550 "\n"
1551 "Note: Values are entered in the same format as the "
1552 "configuration file is using,\n"
1553 "i.e., strings values need to be inside double quotation "
1554 "marks.\n"
1555 "For example: set_network 1 ssid \"network name\"\n"
1556 "\n"
1557 "Please see wpa_supplicant.conf documentation for full list "
1558 "of\navailable variables.\n");
1559 }
1560
1561
1562 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1563 char *argv[])
1564 {
1565 char cmd[256];
1566 int res;
1567
1568 if (argc == 0) {
1569 wpa_cli_show_network_variables();
1570 return 0;
1571 }
1572
1573 if (argc != 3) {
1574 printf("Invalid SET_NETWORK command: needs three arguments\n"
1575 "(network id, variable name, and value)\n");
1576 return -1;
1577 }
1578
1579 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1580 argv[0], argv[1], argv[2]);
1581 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1582 printf("Too long SET_NETWORK command.\n");
1583 return -1;
1584 }
1585 return wpa_ctrl_command(ctrl, cmd);
1586 }
1587
1588
1589 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1590 char *argv[])
1591 {
1592 char cmd[256];
1593 int res;
1594
1595 if (argc == 0) {
1596 wpa_cli_show_network_variables();
1597 return 0;
1598 }
1599
1600 if (argc != 2) {
1601 printf("Invalid GET_NETWORK command: needs two arguments\n"
1602 "(network id and variable name)\n");
1603 return -1;
1604 }
1605
1606 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1607 argv[0], argv[1]);
1608 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1609 printf("Too long GET_NETWORK command.\n");
1610 return -1;
1611 }
1612 return wpa_ctrl_command(ctrl, cmd);
1613 }
1614
1615
1616 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1617 char *argv[])
1618 {
1619 return wpa_ctrl_command(ctrl, "DISCONNECT");
1620 }
1621
1622
1623 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1624 char *argv[])
1625 {
1626 return wpa_ctrl_command(ctrl, "RECONNECT");
1627 }
1628
1629
1630 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1631 char *argv[])
1632 {
1633 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1634 }
1635
1636
1637 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1638 {
1639 return wpa_ctrl_command(ctrl, "SCAN");
1640 }
1641
1642
1643 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1644 char *argv[])
1645 {
1646 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1647 }
1648
1649
1650 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1651 {
1652 char cmd[64];
1653 int res;
1654
1655 if (argc != 1) {
1656 printf("Invalid BSS command: need one argument (index or "
1657 "BSSID)\n");
1658 return -1;
1659 }
1660
1661 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1662 if (res < 0 || (size_t) res >= sizeof(cmd))
1663 return -1;
1664 cmd[sizeof(cmd) - 1] = '\0';
1665
1666 return wpa_ctrl_command(ctrl, cmd);
1667 }
1668
1669
1670 static char ** wpa_cli_complete_bss(const char *str, int pos)
1671 {
1672 int arg = get_cmd_arg_num(str, pos);
1673 char **res = NULL;
1674
1675 switch (arg) {
1676 case 1:
1677 res = cli_txt_list_array(&bsses);
1678 break;
1679 }
1680
1681 return res;
1682 }
1683
1684
1685 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1686 char *argv[])
1687 {
1688 char cmd[64];
1689 int res;
1690
1691 if (argc < 1 || argc > 2) {
1692 printf("Invalid GET_CAPABILITY command: need either one or "
1693 "two arguments\n");
1694 return -1;
1695 }
1696
1697 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1698 printf("Invalid GET_CAPABILITY command: second argument, "
1699 "if any, must be 'strict'\n");
1700 return -1;
1701 }
1702
1703 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1704 (argc == 2) ? " strict" : "");
1705 if (res < 0 || (size_t) res >= sizeof(cmd))
1706 return -1;
1707 cmd[sizeof(cmd) - 1] = '\0';
1708
1709 return wpa_ctrl_command(ctrl, cmd);
1710 }
1711
1712
1713 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1714 {
1715 printf("Available interfaces:\n");
1716 return wpa_ctrl_command(ctrl, "INTERFACES");
1717 }
1718
1719
1720 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1721 {
1722 if (argc < 1) {
1723 wpa_cli_list_interfaces(ctrl);
1724 return 0;
1725 }
1726
1727 wpa_cli_close_connection();
1728 os_free(ctrl_ifname);
1729 ctrl_ifname = os_strdup(argv[0]);
1730
1731 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1732 printf("Connected to interface '%s.\n", ctrl_ifname);
1733 } else {
1734 printf("Could not connect to interface '%s' - re-trying\n",
1735 ctrl_ifname);
1736 }
1737 return 0;
1738 }
1739
1740
1741 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1742 char *argv[])
1743 {
1744 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1745 }
1746
1747
1748 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1749 char *argv[])
1750 {
1751 return wpa_ctrl_command(ctrl, "TERMINATE");
1752 }
1753
1754
1755 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1756 char *argv[])
1757 {
1758 char cmd[256];
1759 int res;
1760
1761 if (argc < 1) {
1762 printf("Invalid INTERFACE_ADD command: needs at least one "
1763 "argument (interface name)\n"
1764 "All arguments: ifname confname driver ctrl_interface "
1765 "driver_param bridge_name\n");
1766 return -1;
1767 }
1768
1769 /*
1770 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1771 * <driver_param>TAB<bridge_name>
1772 */
1773 res = os_snprintf(cmd, sizeof(cmd),
1774 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1775 argv[0],
1776 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1777 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1778 argc > 5 ? argv[5] : "");
1779 if (res < 0 || (size_t) res >= sizeof(cmd))
1780 return -1;
1781 cmd[sizeof(cmd) - 1] = '\0';
1782 return wpa_ctrl_command(ctrl, cmd);
1783 }
1784
1785
1786 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1787 char *argv[])
1788 {
1789 char cmd[128];
1790 int res;
1791
1792 if (argc != 1) {
1793 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1794 "(interface name)\n");
1795 return -1;
1796 }
1797
1798 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1799 if (res < 0 || (size_t) res >= sizeof(cmd))
1800 return -1;
1801 cmd[sizeof(cmd) - 1] = '\0';
1802 return wpa_ctrl_command(ctrl, cmd);
1803 }
1804
1805
1806 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1807 char *argv[])
1808 {
1809 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1810 }
1811
1812
1813 #ifdef CONFIG_AP
1814 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1815 {
1816 char buf[64];
1817 if (argc != 1) {
1818 printf("Invalid 'sta' command - exactly one argument, STA "
1819 "address, is required.\n");
1820 return -1;
1821 }
1822 os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1823 return wpa_ctrl_command(ctrl, buf);
1824 }
1825
1826
1827 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1828 char *addr, size_t addr_len)
1829 {
1830 char buf[4096], *pos;
1831 size_t len;
1832 int ret;
1833
1834 if (ctrl_conn == NULL) {
1835 printf("Not connected to hostapd - command dropped.\n");
1836 return -1;
1837 }
1838 len = sizeof(buf) - 1;
1839 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1840 wpa_cli_msg_cb);
1841 if (ret == -2) {
1842 printf("'%s' command timed out.\n", cmd);
1843 return -2;
1844 } else if (ret < 0) {
1845 printf("'%s' command failed.\n", cmd);
1846 return -1;
1847 }
1848
1849 buf[len] = '\0';
1850 if (memcmp(buf, "FAIL", 4) == 0)
1851 return -1;
1852 printf("%s", buf);
1853
1854 pos = buf;
1855 while (*pos != '\0' && *pos != '\n')
1856 pos++;
1857 *pos = '\0';
1858 os_strlcpy(addr, buf, addr_len);
1859 return 0;
1860 }
1861
1862
1863 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1864 {
1865 char addr[32], cmd[64];
1866
1867 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1868 return 0;
1869 do {
1870 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1871 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1872
1873 return -1;
1874 }
1875 #endif /* CONFIG_AP */
1876
1877
1878 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1879 {
1880 return wpa_ctrl_command(ctrl, "SUSPEND");
1881 }
1882
1883
1884 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1885 {
1886 return wpa_ctrl_command(ctrl, "RESUME");
1887 }
1888
1889
1890 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1891 {
1892 return wpa_ctrl_command(ctrl, "DROP_SA");
1893 }
1894
1895
1896 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1897 {
1898 char cmd[128];
1899 int res;
1900
1901 if (argc != 1) {
1902 printf("Invalid ROAM command: needs one argument "
1903 "(target AP's BSSID)\n");
1904 return -1;
1905 }
1906
1907 res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1908 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1909 printf("Too long ROAM command.\n");
1910 return -1;
1911 }
1912 return wpa_ctrl_command(ctrl, cmd);
1913 }
1914
1915
1916 #ifdef CONFIG_P2P
1917
1918 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1919 {
1920 char cmd[128];
1921 int res;
1922
1923 if (argc == 0)
1924 return wpa_ctrl_command(ctrl, "P2P_FIND");
1925
1926 if (argc > 1)
1927 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s",
1928 argv[0], argv[1]);
1929 else
1930 res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %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_stop_find(struct wpa_ctrl *ctrl, int argc,
1939 char *argv[])
1940 {
1941 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1942 }
1943
1944
1945 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1946 char *argv[])
1947 {
1948 char cmd[128];
1949 int res;
1950
1951 if (argc < 2) {
1952 printf("Invalid P2P_CONNECT command: needs at least two "
1953 "arguments (address and pbc/PIN)\n");
1954 return -1;
1955 }
1956
1957 if (argc > 4)
1958 res = os_snprintf(cmd, sizeof(cmd),
1959 "P2P_CONNECT %s %s %s %s %s",
1960 argv[0], argv[1], argv[2], argv[3],
1961 argv[4]);
1962 else if (argc > 3)
1963 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s %s",
1964 argv[0], argv[1], argv[2], argv[3]);
1965 else if (argc > 2)
1966 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s %s",
1967 argv[0], argv[1], argv[2]);
1968 else
1969 res = os_snprintf(cmd, sizeof(cmd), "P2P_CONNECT %s %s",
1970 argv[0], argv[1]);
1971 if (res < 0 || (size_t) res >= sizeof(cmd))
1972 return -1;
1973 cmd[sizeof(cmd) - 1] = '\0';
1974 return wpa_ctrl_command(ctrl, cmd);
1975 }
1976
1977
1978 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1979 {
1980 int arg = get_cmd_arg_num(str, pos);
1981 char **res = NULL;
1982
1983 switch (arg) {
1984 case 1:
1985 res = cli_txt_list_array(&p2p_peers);
1986 break;
1987 }
1988
1989 return res;
1990 }
1991
1992
1993 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1994 char *argv[])
1995 {
1996 char cmd[128];
1997 int res;
1998
1999 if (argc == 0)
2000 return wpa_ctrl_command(ctrl, "P2P_LISTEN");
2001
2002 res = os_snprintf(cmd, sizeof(cmd), "P2P_LISTEN %s", argv[0]);
2003 if (res < 0 || (size_t) res >= sizeof(cmd))
2004 return -1;
2005 cmd[sizeof(cmd) - 1] = '\0';
2006 return wpa_ctrl_command(ctrl, cmd);
2007 }
2008
2009
2010 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2011 char *argv[])
2012 {
2013 char cmd[128];
2014 int res;
2015
2016 if (argc != 1) {
2017 printf("Invalid P2P_GROUP_REMOVE command: needs one argument "
2018 "(interface name)\n");
2019 return -1;
2020 }
2021
2022 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_REMOVE %s", argv[0]);
2023 if (res < 0 || (size_t) res >= sizeof(cmd))
2024 return -1;
2025 cmd[sizeof(cmd) - 1] = '\0';
2026 return wpa_ctrl_command(ctrl, cmd);
2027 }
2028
2029
2030 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2031 {
2032 int arg = get_cmd_arg_num(str, pos);
2033 char **res = NULL;
2034
2035 switch (arg) {
2036 case 1:
2037 res = cli_txt_list_array(&p2p_groups);
2038 break;
2039 }
2040
2041 return res;
2042 }
2043
2044
2045 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2046 char *argv[])
2047 {
2048 char cmd[128];
2049 int res;
2050
2051 if (argc == 0)
2052 return wpa_ctrl_command(ctrl, "P2P_GROUP_ADD");
2053
2054 if (argc > 1)
2055 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s %s",
2056 argv[0], argv[1]);
2057 else
2058 res = os_snprintf(cmd, sizeof(cmd), "P2P_GROUP_ADD %s",
2059 argv[0]);
2060 if (res < 0 || (size_t) res >= sizeof(cmd))
2061 return -1;
2062 cmd[sizeof(cmd) - 1] = '\0';
2063 return wpa_ctrl_command(ctrl, cmd);
2064 }
2065
2066
2067 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2068 char *argv[])
2069 {
2070 char cmd[128];
2071 int res;
2072
2073 if (argc != 2) {
2074 printf("Invalid P2P_PROV_DISC command: needs two arguments "
2075 "(address and config method\n"
2076 "(display, keypad, or pbc)\n");
2077 return -1;
2078 }
2079
2080 res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
2081 argv[0], argv[1]);
2082 if (res < 0 || (size_t) res >= sizeof(cmd))
2083 return -1;
2084 cmd[sizeof(cmd) - 1] = '\0';
2085 return wpa_ctrl_command(ctrl, cmd);
2086 }
2087
2088
2089 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2090 char *argv[])
2091 {
2092 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2093 }
2094
2095
2096 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2097 char *argv[])
2098 {
2099 char cmd[4096];
2100 int res;
2101
2102 if (argc != 2 && argc != 4) {
2103 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2104 "arguments (address and TLVs) or four arguments "
2105 "(address, \"upnp\", version, search target "
2106 "(SSDP ST:)\n");
2107 return -1;
2108 }
2109
2110 if (argc == 4)
2111 res = os_snprintf(cmd, sizeof(cmd),
2112 "P2P_SERV_DISC_REQ %s %s %s %s",
2113 argv[0], argv[1], argv[2], argv[3]);
2114 else
2115 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ %s %s",
2116 argv[0], argv[1]);
2117 if (res < 0 || (size_t) res >= sizeof(cmd))
2118 return -1;
2119 cmd[sizeof(cmd) - 1] = '\0';
2120 return wpa_ctrl_command(ctrl, cmd);
2121 }
2122
2123
2124 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2125 int argc, char *argv[])
2126 {
2127 char cmd[128];
2128 int res;
2129
2130 if (argc != 1) {
2131 printf("Invalid P2P_SERV_DISC_CANCEL_REQ command: needs one "
2132 "argument (pending request identifier)\n");
2133 return -1;
2134 }
2135
2136 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_CANCEL_REQ %s",
2137 argv[0]);
2138 if (res < 0 || (size_t) res >= sizeof(cmd))
2139 return -1;
2140 cmd[sizeof(cmd) - 1] = '\0';
2141 return wpa_ctrl_command(ctrl, cmd);
2142 }
2143
2144
2145 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2146 char *argv[])
2147 {
2148 char cmd[4096];
2149 int res;
2150
2151 if (argc != 4) {
2152 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2153 "arguments (freq, address, dialog token, and TLVs)\n");
2154 return -1;
2155 }
2156
2157 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2158 argv[0], argv[1], argv[2], argv[3]);
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
2166 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2167 char *argv[])
2168 {
2169 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2170 }
2171
2172
2173 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2174 int argc, char *argv[])
2175 {
2176 char cmd[128];
2177 int res;
2178
2179 if (argc != 1) {
2180 printf("Invalid P2P_SERV_DISC_EXTERNAL command: needs one "
2181 "argument (external processing: 0/1)\n");
2182 return -1;
2183 }
2184
2185 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_EXTERNAL %s",
2186 argv[0]);
2187 if (res < 0 || (size_t) res >= sizeof(cmd))
2188 return -1;
2189 cmd[sizeof(cmd) - 1] = '\0';
2190 return wpa_ctrl_command(ctrl, cmd);
2191 }
2192
2193
2194 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2195 char *argv[])
2196 {
2197 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2198 }
2199
2200
2201 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2202 char *argv[])
2203 {
2204 char cmd[4096];
2205 int res;
2206
2207 if (argc != 3 && argc != 4) {
2208 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
2209 "arguments\n");
2210 return -1;
2211 }
2212
2213 if (argc == 4)
2214 res = os_snprintf(cmd, sizeof(cmd),
2215 "P2P_SERVICE_ADD %s %s %s %s",
2216 argv[0], argv[1], argv[2], argv[3]);
2217 else
2218 res = os_snprintf(cmd, sizeof(cmd),
2219 "P2P_SERVICE_ADD %s %s %s",
2220 argv[0], argv[1], argv[2]);
2221 if (res < 0 || (size_t) res >= sizeof(cmd))
2222 return -1;
2223 cmd[sizeof(cmd) - 1] = '\0';
2224 return wpa_ctrl_command(ctrl, cmd);
2225 }
2226
2227
2228 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230 {
2231 char cmd[4096];
2232 int res;
2233
2234 if (argc != 2 && argc != 3) {
2235 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2236 "arguments\n");
2237 return -1;
2238 }
2239
2240 if (argc == 3)
2241 res = os_snprintf(cmd, sizeof(cmd),
2242 "P2P_SERVICE_DEL %s %s %s",
2243 argv[0], argv[1], argv[2]);
2244 else
2245 res = os_snprintf(cmd, sizeof(cmd),
2246 "P2P_SERVICE_DEL %s %s",
2247 argv[0], argv[1]);
2248 if (res < 0 || (size_t) res >= sizeof(cmd))
2249 return -1;
2250 cmd[sizeof(cmd) - 1] = '\0';
2251 return wpa_ctrl_command(ctrl, cmd);
2252 }
2253
2254
2255 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2256 int argc, char *argv[])
2257 {
2258 char cmd[128];
2259 int res;
2260
2261 if (argc != 1) {
2262 printf("Invalid P2P_REJECT command: needs one argument "
2263 "(peer address)\n");
2264 return -1;
2265 }
2266
2267 res = os_snprintf(cmd, sizeof(cmd), "P2P_REJECT %s", argv[0]);
2268 if (res < 0 || (size_t) res >= sizeof(cmd))
2269 return -1;
2270 cmd[sizeof(cmd) - 1] = '\0';
2271 return wpa_ctrl_command(ctrl, cmd);
2272 }
2273
2274
2275 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2276 int argc, char *argv[])
2277 {
2278 char cmd[128];
2279 int res;
2280
2281 if (argc < 1) {
2282 printf("Invalid P2P_INVITE command: needs at least one "
2283 "argument\n");
2284 return -1;
2285 }
2286
2287 if (argc > 2)
2288 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s %s",
2289 argv[0], argv[1], argv[2]);
2290 else if (argc > 1)
2291 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s %s",
2292 argv[0], argv[1]);
2293 else
2294 res = os_snprintf(cmd, sizeof(cmd), "P2P_INVITE %s", argv[0]);
2295 if (res < 0 || (size_t) res >= sizeof(cmd))
2296 return -1;
2297 cmd[sizeof(cmd) - 1] = '\0';
2298 return wpa_ctrl_command(ctrl, cmd);
2299 }
2300
2301
2302 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2303 {
2304 char buf[64];
2305 if (argc != 1) {
2306 printf("Invalid 'p2p_peer' command - exactly one argument, "
2307 "P2P peer device address, is required.\n");
2308 return -1;
2309 }
2310 os_snprintf(buf, sizeof(buf), "P2P_PEER %s", argv[0]);
2311 return wpa_ctrl_command(ctrl, buf);
2312 }
2313
2314
2315 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2316 {
2317 int arg = get_cmd_arg_num(str, pos);
2318 char **res = NULL;
2319
2320 switch (arg) {
2321 case 1:
2322 res = cli_txt_list_array(&p2p_peers);
2323 break;
2324 }
2325
2326 return res;
2327 }
2328
2329
2330 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2331 char *addr, size_t addr_len,
2332 int discovered)
2333 {
2334 char buf[4096], *pos;
2335 size_t len;
2336 int ret;
2337
2338 if (ctrl_conn == NULL)
2339 return -1;
2340 len = sizeof(buf) - 1;
2341 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
2342 wpa_cli_msg_cb);
2343 if (ret == -2) {
2344 printf("'%s' command timed out.\n", cmd);
2345 return -2;
2346 } else if (ret < 0) {
2347 printf("'%s' command failed.\n", cmd);
2348 return -1;
2349 }
2350
2351 buf[len] = '\0';
2352 if (memcmp(buf, "FAIL", 4) == 0)
2353 return -1;
2354
2355 pos = buf;
2356 while (*pos != '\0' && *pos != '\n')
2357 pos++;
2358 *pos++ = '\0';
2359 os_strlcpy(addr, buf, addr_len);
2360 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2361 printf("%s\n", addr);
2362 return 0;
2363 }
2364
2365
2366 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2367 {
2368 char addr[32], cmd[64];
2369 int discovered;
2370
2371 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2372
2373 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2374 addr, sizeof(addr), discovered))
2375 return 0;
2376 do {
2377 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2378 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2379 discovered) == 0);
2380
2381 return -1;
2382 }
2383
2384
2385 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2386 {
2387 char cmd[100];
2388 int res;
2389
2390 if (argc != 2) {
2391 printf("Invalid P2P_SET command: needs two arguments (field, "
2392 "value)\n");
2393 return -1;
2394 }
2395
2396 res = os_snprintf(cmd, sizeof(cmd), "P2P_SET %s %s", argv[0], argv[1]);
2397 if (res < 0 || (size_t) res >= sizeof(cmd))
2398 return -1;
2399 cmd[sizeof(cmd) - 1] = '\0';
2400 return wpa_ctrl_command(ctrl, cmd);
2401 }
2402
2403
2404 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2405 {
2406 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2407 }
2408
2409
2410 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2411 char *argv[])
2412 {
2413 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2414 }
2415
2416
2417 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2418 char *argv[])
2419 {
2420 char cmd[100];
2421 int res;
2422
2423 if (argc != 1) {
2424 printf("Invalid P2P_UNAUTHORIZE command: needs one argument "
2425 "(peer address)\n");
2426 return -1;
2427 }
2428
2429 res = os_snprintf(cmd, sizeof(cmd), "P2P_UNAUTHORIZE %s", argv[0]);
2430
2431 if (res < 0 || (size_t) res >= sizeof(cmd))
2432 return -1;
2433
2434 cmd[sizeof(cmd) - 1] = '\0';
2435 return wpa_ctrl_command(ctrl, cmd);
2436 }
2437
2438
2439 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2440 char *argv[])
2441 {
2442 char cmd[100];
2443 int res;
2444
2445 if (argc != 0 && argc != 2 && argc != 4) {
2446 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2447 "(preferred duration, interval; in microsecods).\n"
2448 "Optional second pair can be used to provide "
2449 "acceptable values.\n");
2450 return -1;
2451 }
2452
2453 if (argc == 4)
2454 res = os_snprintf(cmd, sizeof(cmd),
2455 "P2P_PRESENCE_REQ %s %s %s %s",
2456 argv[0], argv[1], argv[2], argv[3]);
2457 else if (argc == 2)
2458 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ %s %s",
2459 argv[0], argv[1]);
2460 else
2461 res = os_snprintf(cmd, sizeof(cmd), "P2P_PRESENCE_REQ");
2462 if (res < 0 || (size_t) res >= sizeof(cmd))
2463 return -1;
2464 cmd[sizeof(cmd) - 1] = '\0';
2465 return wpa_ctrl_command(ctrl, cmd);
2466 }
2467
2468
2469 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2470 char *argv[])
2471 {
2472 char cmd[100];
2473 int res;
2474
2475 if (argc != 0 && argc != 2) {
2476 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2477 "(availability period, availability interval; in "
2478 "millisecods).\n"
2479 "Extended Listen Timing can be cancelled with this "
2480 "command when used without parameters.\n");
2481 return -1;
2482 }
2483
2484 if (argc == 2)
2485 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN %s %s",
2486 argv[0], argv[1]);
2487 else
2488 res = os_snprintf(cmd, sizeof(cmd), "P2P_EXT_LISTEN");
2489 if (res < 0 || (size_t) res >= sizeof(cmd))
2490 return -1;
2491 cmd[sizeof(cmd) - 1] = '\0';
2492 return wpa_ctrl_command(ctrl, cmd);
2493 }
2494
2495 #endif /* CONFIG_P2P */
2496
2497
2498 #ifdef CONFIG_INTERWORKING
2499 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2500 char *argv[])
2501 {
2502 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2503 }
2504
2505
2506 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2507 char *argv[])
2508 {
2509 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2510 }
2511
2512
2513 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2514 char *argv[])
2515 {
2516 char cmd[100];
2517 int res;
2518
2519 if (argc == 0)
2520 return wpa_ctrl_command(ctrl, "INTERWORKING_SELECT");
2521
2522 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_SELECT %s", argv[0]);
2523 if (res < 0 || (size_t) res >= sizeof(cmd))
2524 return -1;
2525 cmd[sizeof(cmd) - 1] = '\0';
2526 return wpa_ctrl_command(ctrl, cmd);
2527 }
2528
2529
2530 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2531 char *argv[])
2532 {
2533 char cmd[100];
2534 int res;
2535
2536 if (argc != 1) {
2537 printf("Invalid INTERWORKING_CONNECT commands: needs one "
2538 "argument (BSSID)\n");
2539 return -1;
2540 }
2541
2542 res = os_snprintf(cmd, sizeof(cmd), "INTERWORKING_CONNECT %s",
2543 argv[0]);
2544 if (res < 0 || (size_t) res >= sizeof(cmd))
2545 return -1;
2546 cmd[sizeof(cmd) - 1] = '\0';
2547 return wpa_ctrl_command(ctrl, cmd);
2548 }
2549
2550
2551 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2552 {
2553 char cmd[100];
2554 int res;
2555
2556 if (argc != 2) {
2557 printf("Invalid ANQP_GET command: needs two arguments "
2558 "(addr and info id list)\n");
2559 return -1;
2560 }
2561
2562 res = os_snprintf(cmd, sizeof(cmd), "ANQP_GET %s %s",
2563 argv[0], argv[1]);
2564 if (res < 0 || (size_t) res >= sizeof(cmd))
2565 return -1;
2566 cmd[sizeof(cmd) - 1] = '\0';
2567 return wpa_ctrl_command(ctrl, cmd);
2568 }
2569 #endif /* CONFIG_INTERWORKING */
2570
2571
2572 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2573 char *argv[])
2574 {
2575 char cmd[256];
2576 int res;
2577
2578 if (argc != 1) {
2579 printf("Invalid STA_AUTOCONNECT command: needs one argument "
2580 "(0/1 = disable/enable automatic reconnection)\n");
2581 return -1;
2582 }
2583 res = os_snprintf(cmd, sizeof(cmd), "STA_AUTOCONNECT %s", argv[0]);
2584 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2585 printf("Too long STA_AUTOCONNECT command.\n");
2586 return -1;
2587 }
2588 return wpa_ctrl_command(ctrl, cmd);
2589 }
2590
2591
2592 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2593 char *argv[])
2594 {
2595 char cmd[256];
2596 int res;
2597
2598 if (argc != 1) {
2599 printf("Invalid TDLS_DISCOVER command: needs one argument "
2600 "(Peer STA MAC address)\n");
2601 return -1;
2602 }
2603
2604 res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
2605 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2606 printf("Too long TDLS_DISCOVER command.\n");
2607 return -1;
2608 }
2609 return wpa_ctrl_command(ctrl, cmd);
2610 }
2611
2612
2613 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2614 char *argv[])
2615 {
2616 char cmd[256];
2617 int res;
2618
2619 if (argc != 1) {
2620 printf("Invalid TDLS_SETUP command: needs one argument "
2621 "(Peer STA MAC address)\n");
2622 return -1;
2623 }
2624
2625 res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
2626 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2627 printf("Too long TDLS_SETUP command.\n");
2628 return -1;
2629 }
2630 return wpa_ctrl_command(ctrl, cmd);
2631 }
2632
2633
2634 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2635 char *argv[])
2636 {
2637 char cmd[256];
2638 int res;
2639
2640 if (argc != 1) {
2641 printf("Invalid TDLS_TEARDOWN command: needs one argument "
2642 "(Peer STA MAC address)\n");
2643 return -1;
2644 }
2645
2646 res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
2647 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
2648 printf("Too long TDLS_TEARDOWN command.\n");
2649 return -1;
2650 }
2651 return wpa_ctrl_command(ctrl, cmd);
2652 }
2653
2654
2655 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2656 char *argv[])
2657 {
2658 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2659 }
2660
2661
2662 enum wpa_cli_cmd_flags {
2663 cli_cmd_flag_none = 0x00,
2664 cli_cmd_flag_sensitive = 0x01
2665 };
2666
2667 struct wpa_cli_cmd {
2668 const char *cmd;
2669 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2670 enum wpa_cli_cmd_flags flags;
2671 const char *usage;
2672 };
2673
2674 static struct wpa_cli_cmd wpa_cli_commands[] = {
2675 { "status", wpa_cli_cmd_status,
2676 cli_cmd_flag_none,
2677 "[verbose] = get current WPA/EAPOL/EAP status" },
2678 { "ping", wpa_cli_cmd_ping,
2679 cli_cmd_flag_none,
2680 "= pings wpa_supplicant" },
2681 { "relog", wpa_cli_cmd_relog,
2682 cli_cmd_flag_none,
2683 "= re-open log-file (allow rolling logs)" },
2684 { "note", wpa_cli_cmd_note,
2685 cli_cmd_flag_none,
2686 "<text> = add a note to wpa_supplicant debug log" },
2687 { "mib", wpa_cli_cmd_mib,
2688 cli_cmd_flag_none,
2689 "= get MIB variables (dot1x, dot11)" },
2690 { "help", wpa_cli_cmd_help,
2691 cli_cmd_flag_none,
2692 "= show this usage help" },
2693 { "interface", wpa_cli_cmd_interface,
2694 cli_cmd_flag_none,
2695 "[ifname] = show interfaces/select interface" },
2696 { "level", wpa_cli_cmd_level,
2697 cli_cmd_flag_none,
2698 "<debug level> = change debug level" },
2699 { "license", wpa_cli_cmd_license,
2700 cli_cmd_flag_none,
2701 "= show full wpa_cli license" },
2702 { "quit", wpa_cli_cmd_quit,
2703 cli_cmd_flag_none,
2704 "= exit wpa_cli" },
2705 { "set", wpa_cli_cmd_set,
2706 cli_cmd_flag_none,
2707 "= set variables (shows list of variables when run without "
2708 "arguments)" },
2709 { "get", wpa_cli_cmd_get,
2710 cli_cmd_flag_none,
2711 "<name> = get information" },
2712 { "logon", wpa_cli_cmd_logon,
2713 cli_cmd_flag_none,
2714 "= IEEE 802.1X EAPOL state machine logon" },
2715 { "logoff", wpa_cli_cmd_logoff,
2716 cli_cmd_flag_none,
2717 "= IEEE 802.1X EAPOL state machine logoff" },
2718 { "pmksa", wpa_cli_cmd_pmksa,
2719 cli_cmd_flag_none,
2720 "= show PMKSA cache" },
2721 { "reassociate", wpa_cli_cmd_reassociate,
2722 cli_cmd_flag_none,
2723 "= force reassociation" },
2724 { "preauthenticate", wpa_cli_cmd_preauthenticate,
2725 cli_cmd_flag_none,
2726 "<BSSID> = force preauthentication" },
2727 { "identity", wpa_cli_cmd_identity,
2728 cli_cmd_flag_none,
2729 "<network id> <identity> = configure identity for an SSID" },
2730 { "password", wpa_cli_cmd_password,
2731 cli_cmd_flag_sensitive,
2732 "<network id> <password> = configure password for an SSID" },
2733 { "new_password", wpa_cli_cmd_new_password,
2734 cli_cmd_flag_sensitive,
2735 "<network id> <password> = change password for an SSID" },
2736 { "pin", wpa_cli_cmd_pin,
2737 cli_cmd_flag_sensitive,
2738 "<network id> <pin> = configure pin for an SSID" },
2739 { "otp", wpa_cli_cmd_otp,
2740 cli_cmd_flag_sensitive,
2741 "<network id> <password> = configure one-time-password for an SSID"
2742 },
2743 { "passphrase", wpa_cli_cmd_passphrase,
2744 cli_cmd_flag_sensitive,
2745 "<network id> <passphrase> = configure private key passphrase\n"
2746 " for an SSID" },
2747 { "bssid", wpa_cli_cmd_bssid,
2748 cli_cmd_flag_none,
2749 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2750 { "blacklist", wpa_cli_cmd_blacklist,
2751 cli_cmd_flag_none,
2752 "<BSSID> = add a BSSID to the blacklist\n"
2753 "blacklist clear = clear the blacklist\n"
2754 "blacklist = display the blacklist" },
2755 { "log_level", wpa_cli_cmd_log_level,
2756 cli_cmd_flag_none,
2757 "<level> [<timestamp>] = update the log level/timestamp\n"
2758 "log_level = display the current log level and log options" },
2759 { "list_networks", wpa_cli_cmd_list_networks,
2760 cli_cmd_flag_none,
2761 "= list configured networks" },
2762 { "select_network", wpa_cli_cmd_select_network,
2763 cli_cmd_flag_none,
2764 "<network id> = select a network (disable others)" },
2765 { "enable_network", wpa_cli_cmd_enable_network,
2766 cli_cmd_flag_none,
2767 "<network id> = enable a network" },
2768 { "disable_network", wpa_cli_cmd_disable_network,
2769 cli_cmd_flag_none,
2770 "<network id> = disable a network" },
2771 { "add_network", wpa_cli_cmd_add_network,
2772 cli_cmd_flag_none,
2773 "= add a network" },
2774 { "remove_network", wpa_cli_cmd_remove_network,
2775 cli_cmd_flag_none,
2776 "<network id> = remove a network" },
2777 { "set_network", wpa_cli_cmd_set_network,
2778 cli_cmd_flag_sensitive,
2779 "<network id> <variable> <value> = set network variables (shows\n"
2780 " list of variables when run without arguments)" },
2781 { "get_network", wpa_cli_cmd_get_network,
2782 cli_cmd_flag_none,
2783 "<network id> <variable> = get network variables" },
2784 { "save_config", wpa_cli_cmd_save_config,
2785 cli_cmd_flag_none,
2786 "= save the current configuration" },
2787 { "disconnect", wpa_cli_cmd_disconnect,
2788 cli_cmd_flag_none,
2789 "= disconnect and wait for reassociate/reconnect command before\n"
2790 " connecting" },
2791 { "reconnect", wpa_cli_cmd_reconnect,
2792 cli_cmd_flag_none,
2793 "= like reassociate, but only takes effect if already disconnected"
2794 },
2795 { "scan", wpa_cli_cmd_scan,
2796 cli_cmd_flag_none,
2797 "= request new BSS scan" },
2798 { "scan_results", wpa_cli_cmd_scan_results,
2799 cli_cmd_flag_none,
2800 "= get latest scan results" },
2801 { "bss", wpa_cli_cmd_bss,
2802 cli_cmd_flag_none,
2803 "<<idx> | <bssid>> = get detailed scan result info" },
2804 { "get_capability", wpa_cli_cmd_get_capability,
2805 cli_cmd_flag_none,
2806 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
2807 { "reconfigure", wpa_cli_cmd_reconfigure,
2808 cli_cmd_flag_none,
2809 "= force wpa_supplicant to re-read its configuration file" },
2810 { "terminate", wpa_cli_cmd_terminate,
2811 cli_cmd_flag_none,
2812 "= terminate wpa_supplicant" },
2813 { "interface_add", wpa_cli_cmd_interface_add,
2814 cli_cmd_flag_none,
2815 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2816 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2817 " are optional" },
2818 { "interface_remove", wpa_cli_cmd_interface_remove,
2819 cli_cmd_flag_none,
2820 "<ifname> = removes the interface" },
2821 { "interface_list", wpa_cli_cmd_interface_list,
2822 cli_cmd_flag_none,
2823 "= list available interfaces" },
2824 { "ap_scan", wpa_cli_cmd_ap_scan,
2825 cli_cmd_flag_none,
2826 "<value> = set ap_scan parameter" },
2827 { "scan_interval", wpa_cli_cmd_scan_interval,
2828 cli_cmd_flag_none,
2829 "<value> = set scan_interval parameter (in seconds)" },
2830 { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
2831 cli_cmd_flag_none,
2832 "<value> = set BSS expiration age parameter" },
2833 { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
2834 cli_cmd_flag_none,
2835 "<value> = set BSS expiration scan count parameter" },
2836 { "stkstart", wpa_cli_cmd_stkstart,
2837 cli_cmd_flag_none,
2838 "<addr> = request STK negotiation with <addr>" },
2839 { "ft_ds", wpa_cli_cmd_ft_ds,
2840 cli_cmd_flag_none,
2841 "<addr> = request over-the-DS FT with <addr>" },
2842 { "wps_pbc", wpa_cli_cmd_wps_pbc,
2843 cli_cmd_flag_none,
2844 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2845 { "wps_pin", wpa_cli_cmd_wps_pin,
2846 cli_cmd_flag_sensitive,
2847 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2848 "hardcoded)" },
2849 { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
2850 cli_cmd_flag_sensitive,
2851 "<PIN> = verify PIN checksum" },
2852 { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
2853 "Cancels the pending WPS operation" },
2854 #ifdef CONFIG_WPS_OOB
2855 { "wps_oob", wpa_cli_cmd_wps_oob,
2856 cli_cmd_flag_sensitive,
2857 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2858 #endif /* CONFIG_WPS_OOB */
2859 { "wps_reg", wpa_cli_cmd_wps_reg,
2860 cli_cmd_flag_sensitive,
2861 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2862 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
2863 cli_cmd_flag_sensitive,
2864 "[params..] = enable/disable AP PIN" },
2865 { "wps_er_start", wpa_cli_cmd_wps_er_start,
2866 cli_cmd_flag_none,
2867 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2868 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
2869 cli_cmd_flag_none,
2870 "= stop Wi-Fi Protected Setup External Registrar" },
2871 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
2872 cli_cmd_flag_sensitive,
2873 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2874 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
2875 cli_cmd_flag_none,
2876 "<UUID> = accept an Enrollee PBC using External Registrar" },
2877 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
2878 cli_cmd_flag_sensitive,
2879 "<UUID> <PIN> = learn AP configuration" },
2880 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
2881 cli_cmd_flag_none,
2882 "<UUID> <network id> = set AP configuration for enrolling" },
2883 { "wps_er_config", wpa_cli_cmd_wps_er_config,
2884 cli_cmd_flag_sensitive,
2885 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2886 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
2887 cli_cmd_flag_none,
2888 "<addr> = request RSN authentication with <addr> in IBSS" },
2889 #ifdef CONFIG_AP
2890 { "sta", wpa_cli_cmd_sta,
2891 cli_cmd_flag_none,
2892 "<addr> = get information about an associated station (AP)" },
2893 { "all_sta", wpa_cli_cmd_all_sta,
2894 cli_cmd_flag_none,
2895 "= get information about all associated stations (AP)" },
2896 #endif /* CONFIG_AP */
2897 { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
2898 "= notification of suspend/hibernate" },
2899 { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
2900 "= notification of resume/thaw" },
2901 { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
2902 "= drop SA without deauth/disassoc (test command)" },
2903 { "roam", wpa_cli_cmd_roam,
2904 cli_cmd_flag_none,
2905 "<addr> = roam to the specified BSS" },
2906 #ifdef CONFIG_P2P
2907 { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
2908 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2909 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
2910 "= stop P2P Devices search" },
2911 { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
2912 "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
2913 { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
2914 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2915 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
2916 "<ifname> = remove P2P group interface (terminate group if GO)" },
2917 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
2918 "= add a new P2P group (local end as GO)" },
2919 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
2920 "<addr> <method> = request provisioning discovery" },
2921 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
2922 cli_cmd_flag_none,
2923 "= get the passphrase for a group (GO only)" },
2924 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2925 cli_cmd_flag_none,
2926 "<addr> <TLVs> = schedule service discovery request" },
2927 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2928 cli_cmd_flag_none,
2929 "<id> = cancel pending service discovery request" },
2930 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
2931 cli_cmd_flag_none,
2932 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2933 { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
2934 cli_cmd_flag_none,
2935 "= indicate change in local services" },
2936 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
2937 cli_cmd_flag_none,
2938 "<external> = set external processing of service discovery" },
2939 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
2940 cli_cmd_flag_none,
2941 "= remove all stored service entries" },
2942 { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
2943 cli_cmd_flag_none,
2944 "<bonjour|upnp> <query|version> <response|service> = add a local "
2945 "service" },
2946 { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
2947 cli_cmd_flag_none,
2948 "<bonjour|upnp> <query|version> [|service] = remove a local "
2949 "service" },
2950 { "p2p_reject", wpa_cli_cmd_p2p_reject,
2951 cli_cmd_flag_none,
2952 "<addr> = reject connection attempts from a specific peer" },
2953 { "p2p_invite", wpa_cli_cmd_p2p_invite,
2954 cli_cmd_flag_none,
2955 "<cmd> [peer=addr] = invite peer" },
2956 { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
2957 "[discovered] = list known (optionally, only fully discovered) P2P "
2958 "peers" },
2959 { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
2960 "<address> = show information about known P2P peer" },
2961 { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
2962 "<field> <value> = set a P2P parameter" },
2963 { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
2964 "= flush P2P state" },
2965 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
2966 "= cancel P2P group formation" },
2967 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
2968 "<address> = unauthorize a peer" },
2969 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
2970 "[<duration> <interval>] [<duration> <interval>] = request GO "
2971 "presence" },
2972 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
2973 "[<period> <interval>] = set extended listen timing" },
2974 #endif /* CONFIG_P2P */
2975
2976 #ifdef CONFIG_INTERWORKING
2977 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
2978 "= fetch ANQP information for all APs" },
2979 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
2980 "= stop fetch_anqp operation" },
2981 { "interworking_select", wpa_cli_cmd_interworking_select,
2982 cli_cmd_flag_none,
2983 "[auto] = perform Interworking network selection" },
2984 { "interworking_connect", wpa_cli_cmd_interworking_connect,
2985 cli_cmd_flag_none,
2986 "<BSSID> = connect using Interworking credentials" },
2987 { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
2988 "<addr> <info id>[,<info id>]... = request ANQP information" },
2989 #endif /* CONFIG_INTERWORKING */
2990 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
2991 "<0/1> = disable/enable automatic reconnection" },
2992 { "tdls_discover", wpa_cli_cmd_tdls_discover,
2993 cli_cmd_flag_none,
2994 "<addr> = request TDLS discovery with <addr>" },
2995 { "tdls_setup", wpa_cli_cmd_tdls_setup,
2996 cli_cmd_flag_none,
2997 "<addr> = request TDLS setup with <addr>" },
2998 { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
2999 cli_cmd_flag_none,
3000 "<addr> = tear down TDLS with <addr>" },
3001 { "signal_poll", wpa_cli_cmd_signal_poll,
3002 cli_cmd_flag_none,
3003 "= get signal parameters" },
3004 { NULL, NULL, cli_cmd_flag_none, NULL }
3005 };
3006
3007
3008 /*
3009 * Prints command usage, lines are padded with the specified string.
3010 */
3011 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3012 {
3013 char c;
3014 size_t n;
3015
3016 printf("%s%s ", pad, cmd->cmd);
3017 for (n = 0; (c = cmd->usage[n]); n++) {
3018 printf("%c", c);
3019 if (c == '\n')
3020 printf("%s", pad);
3021 }
3022 printf("\n");
3023 }
3024
3025
3026 static void print_help(void)
3027 {
3028 int n;
3029 printf("commands:\n");
3030 for (n = 0; wpa_cli_commands[n].cmd; n++)
3031 print_cmd_help(&wpa_cli_commands[n], " ");
3032 }
3033
3034
3035 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3036 {
3037 const char *c, *delim;
3038 int n;
3039 size_t len;
3040
3041 delim = os_strchr(cmd, ' ');
3042 if (delim)
3043 len = delim - cmd;
3044 else
3045 len = os_strlen(cmd);
3046
3047 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3048 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3049 return (wpa_cli_commands[n].flags &
3050 cli_cmd_flag_sensitive);
3051 }
3052 return 0;
3053 }
3054
3055
3056 static char ** wpa_list_cmd_list(void)
3057 {
3058 char **res;
3059 int i, count;
3060
3061 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
3062 res = os_zalloc(count * sizeof(char *));
3063 if (res == NULL)
3064 return NULL;
3065
3066 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3067 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3068 if (res[i] == NULL)
3069 break;
3070 }
3071
3072 return res;
3073 }
3074
3075
3076 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3077 int pos)
3078 {
3079 int i;
3080
3081 if (os_strcasecmp(cmd, "bss") == 0)
3082 return wpa_cli_complete_bss(str, pos);
3083 #ifdef CONFIG_P2P
3084 if (os_strcasecmp(cmd, "p2p_connect") == 0)
3085 return wpa_cli_complete_p2p_connect(str, pos);
3086 if (os_strcasecmp(cmd, "p2p_peer") == 0)
3087 return wpa_cli_complete_p2p_peer(str, pos);
3088 if (os_strcasecmp(cmd, "p2p_group_remove") == 0)
3089 return wpa_cli_complete_p2p_group_remove(str, pos);
3090 #endif /* CONFIG_P2P */
3091
3092 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3093 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3094 edit_clear_line();
3095 printf("\r%s\n", wpa_cli_commands[i].usage);
3096 edit_redraw();
3097 break;
3098 }
3099 }
3100
3101 return NULL;
3102 }
3103
3104
3105 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3106 {
3107 char **res;
3108 const char *end;
3109 char *cmd;
3110
3111 end = os_strchr(str, ' ');
3112 if (end == NULL || str + pos < end)
3113 return wpa_list_cmd_list();
3114
3115 cmd = os_malloc(pos + 1);
3116 if (cmd == NULL)
3117 return NULL;
3118 os_memcpy(cmd, str, pos);
3119 cmd[end - str] = '\0';
3120 res = wpa_cli_cmd_completion(cmd, str, pos);
3121 os_free(cmd);
3122 return res;
3123 }
3124
3125
3126 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3127 {
3128 struct wpa_cli_cmd *cmd, *match = NULL;
3129 int count;
3130 int ret = 0;
3131
3132 count = 0;
3133 cmd = wpa_cli_commands;
3134 while (cmd->cmd) {
3135 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3136 {
3137 match = cmd;
3138 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3139 /* we have an exact match */
3140 count = 1;
3141 break;
3142 }
3143 count++;
3144 }
3145 cmd++;
3146 }
3147
3148 if (count > 1) {
3149 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3150 cmd = wpa_cli_commands;
3151 while (cmd->cmd) {
3152 if (os_strncasecmp(cmd->cmd, argv[0],
3153 os_strlen(argv[0])) == 0) {
3154 printf(" %s", cmd->cmd);
3155 }
3156 cmd++;
3157 }
3158 printf("\n");
3159 ret = 1;
3160 } else if (count == 0) {
3161 printf("Unknown command '%s'\n", argv[0]);
3162 ret = 1;
3163 } else {
3164 ret = match->handler(ctrl, argc - 1, &argv[1]);
3165 }
3166
3167 return ret;
3168 }
3169
3170
3171 static int str_match(const char *a, const char *b)
3172 {
3173 return os_strncmp(a, b, os_strlen(b)) == 0;
3174 }
3175
3176
3177 static int wpa_cli_exec(const char *program, const char *arg1,
3178 const char *arg2)
3179 {
3180 char *cmd;
3181 size_t len;
3182 int res;
3183 int ret = 0;
3184
3185 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3186 cmd = os_malloc(len);
3187 if (cmd == NULL)
3188 return -1;
3189 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3190 if (res < 0 || (size_t) res >= len) {
3191 os_free(cmd);
3192 return -1;
3193 }
3194 cmd[len - 1] = '\0';
3195 #ifndef _WIN32_WCE
3196 if (system(cmd) < 0)
3197 ret = -1;
3198 #endif /* _WIN32_WCE */
3199 os_free(cmd);
3200
3201 return ret;
3202 }
3203
3204
3205 static void wpa_cli_action_process(const char *msg)
3206 {
3207 const char *pos;
3208 char *copy = NULL, *id, *pos2;
3209
3210 pos = msg;
3211 if (*pos == '<') {
3212 /* skip priority */
3213 pos = os_strchr(pos, '>');
3214 if (pos)
3215 pos++;
3216 else
3217 pos = msg;
3218 }
3219
3220 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3221 int new_id = -1;
3222 os_unsetenv("WPA_ID");
3223 os_unsetenv("WPA_ID_STR");
3224 os_unsetenv("WPA_CTRL_DIR");
3225
3226 pos = os_strstr(pos, "[id=");
3227 if (pos)
3228 copy = os_strdup(pos + 4);
3229
3230 if (copy) {
3231 pos2 = id = copy;
3232 while (*pos2 && *pos2 != ' ')
3233 pos2++;
3234 *pos2++ = '\0';
3235 new_id = atoi(id);
3236 os_setenv("WPA_ID", id, 1);
3237 while (*pos2 && *pos2 != '=')
3238 pos2++;
3239 if (*pos2 == '=')
3240 pos2++;
3241 id = pos2;
3242 while (*pos2 && *pos2 != ']')
3243 pos2++;
3244 *pos2 = '\0';
3245 os_setenv("WPA_ID_STR", id, 1);
3246 os_free(copy);
3247 }
3248
3249 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3250
3251 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3252 wpa_cli_connected = 1;
3253 wpa_cli_last_id = new_id;
3254 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3255 }
3256 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3257 if (wpa_cli_connected) {
3258 wpa_cli_connected = 0;
3259 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3260 }
3261 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3262 wpa_cli_exec(action_file, ctrl_ifname, pos);
3263 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3264 wpa_cli_exec(action_file, ctrl_ifname, pos);
3265 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3266 wpa_cli_exec(action_file, ctrl_ifname, pos);
3267 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3268 wpa_cli_exec(action_file, ctrl_ifname, pos);
3269 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3270 wpa_cli_exec(action_file, ctrl_ifname, pos);
3271 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3272 wpa_cli_exec(action_file, ctrl_ifname, pos);
3273 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3274 printf("wpa_supplicant is terminating - stop monitoring\n");
3275 wpa_cli_quit = 1;
3276 }
3277 }
3278
3279
3280 #ifndef CONFIG_ANSI_C_EXTRA
3281 static void wpa_cli_action_cb(char *msg, size_t len)
3282 {
3283 wpa_cli_action_process(msg);
3284 }
3285 #endif /* CONFIG_ANSI_C_EXTRA */
3286
3287
3288 static void wpa_cli_reconnect(void)
3289 {
3290 wpa_cli_close_connection();
3291 wpa_cli_open_connection(ctrl_ifname, 1);
3292 }
3293
3294
3295 static void cli_event(const char *str)
3296 {
3297 const char *start, *s;
3298
3299 start = os_strchr(str, '>');
3300 if (start == NULL)
3301 return;
3302
3303 start++;
3304
3305 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3306 s = os_strchr(start, ' ');
3307 if (s == NULL)
3308 return;
3309 s = os_strchr(s + 1, ' ');
3310 if (s == NULL)
3311 return;
3312 cli_txt_list_add(&bsses, s + 1);
3313 return;
3314 }
3315
3316 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3317 s = os_strchr(start, ' ');
3318 if (s == NULL)
3319 return;
3320 s = os_strchr(s + 1, ' ');
3321 if (s == NULL)
3322 return;
3323 cli_txt_list_del_addr(&bsses, s + 1);
3324 return;
3325 }
3326
3327 #ifdef CONFIG_P2P
3328 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3329 s = os_strstr(start, " p2p_dev_addr=");
3330 if (s == NULL)
3331 return;
3332 cli_txt_list_add_addr(&p2p_peers, s + 14);
3333 return;
3334 }
3335
3336 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3337 s = os_strstr(start, " p2p_dev_addr=");
3338 if (s == NULL)
3339 return;
3340 cli_txt_list_del_addr(&p2p_peers, s + 14);
3341 return;
3342 }
3343
3344 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3345 s = os_strchr(start, ' ');
3346 if (s == NULL)
3347 return;
3348 cli_txt_list_add_word(&p2p_groups, s + 1);
3349 return;
3350 }
3351
3352 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3353 s = os_strchr(start, ' ');
3354 if (s == NULL)
3355 return;
3356 cli_txt_list_del_word(&p2p_groups, s + 1);
3357 return;
3358 }
3359 #endif /* CONFIG_P2P */
3360 }
3361
3362
3363 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3364 {
3365 if (ctrl_conn == NULL) {
3366 wpa_cli_reconnect();
3367 return;
3368 }
3369 while (wpa_ctrl_pending(ctrl) > 0) {
3370 char buf[256];
3371 size_t len = sizeof(buf) - 1;
3372 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3373 buf[len] = '\0';
3374 if (action_monitor)
3375 wpa_cli_action_process(buf);
3376 else {
3377 cli_event(buf);
3378 if (wpa_cli_show_event(buf)) {
3379 edit_clear_line();
3380 printf("\r%s\n", buf);
3381 edit_redraw();
3382 }
3383 }
3384 } else {
3385 printf("Could not read pending message.\n");
3386 break;
3387 }
3388 }
3389
3390 if (wpa_ctrl_pending(ctrl) < 0) {
3391 printf("Connection to wpa_supplicant lost - trying to "
3392 "reconnect\n");
3393 wpa_cli_reconnect();
3394 }
3395 }
3396
3397 #define max_args 10
3398
3399 static int tokenize_cmd(char *cmd, char *argv[])
3400 {
3401 char *pos;
3402 int argc = 0;
3403
3404 pos = cmd;
3405 for (;;) {
3406 while (*pos == ' ')
3407 pos++;
3408 if (*pos == '\0')
3409 break;
3410 argv[argc] = pos;
3411 argc++;
3412 if (argc == max_args)
3413 break;
3414 if (*pos == '"') {
3415 char *pos2 = os_strrchr(pos, '"');
3416 if (pos2)
3417 pos = pos2 + 1;
3418 }
3419 while (*pos != '\0' && *pos != ' ')
3420 pos++;
3421 if (*pos == ' ')
3422 *pos++ = '\0';
3423 }
3424
3425 return argc;
3426 }
3427
3428
3429 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3430 {
3431 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3432 printf("Connection to wpa_supplicant lost - trying to "
3433 "reconnect\n");
3434 wpa_cli_close_connection();
3435 }
3436 if (!ctrl_conn)
3437 wpa_cli_reconnect();
3438 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3439 }
3440
3441
3442 static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
3443 {
3444 eloop_terminate();
3445 }
3446
3447
3448 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3449 {
3450 wpa_cli_recv_pending(mon_conn, 0);
3451 }
3452
3453
3454 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3455 {
3456 char *argv[max_args];
3457 int argc;
3458 argc = tokenize_cmd(cmd, argv);
3459 if (argc)
3460 wpa_request(ctrl_conn, argc, argv);
3461 }
3462
3463
3464 static void wpa_cli_edit_eof_cb(void *ctx)
3465 {
3466 eloop_terminate();
3467 }
3468
3469
3470 static void wpa_cli_interactive(void)
3471 {
3472 char *home, *hfile = NULL;
3473
3474 printf("\nInteractive mode\n\n");
3475
3476 home = getenv("HOME");
3477 if (home) {
3478 const char *fname = ".wpa_cli_history";
3479 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3480 hfile = os_malloc(hfile_len);
3481 if (hfile)
3482 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3483 }
3484
3485 eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
3486 edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3487 wpa_cli_edit_completion_cb, NULL, hfile);
3488 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3489
3490 eloop_run();
3491
3492 cli_txt_list_flush(&p2p_peers);
3493 cli_txt_list_flush(&p2p_groups);
3494 cli_txt_list_flush(&bsses);
3495 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3496 os_free(hfile);
3497 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3498 wpa_cli_close_connection();
3499 }
3500
3501
3502 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3503 {
3504 #ifdef CONFIG_ANSI_C_EXTRA
3505 /* TODO: ANSI C version(?) */
3506 printf("Action processing not supported in ANSI C build.\n");
3507 #else /* CONFIG_ANSI_C_EXTRA */
3508 fd_set rfds;
3509 int fd, res;
3510 struct timeval tv;
3511 char buf[256]; /* note: large enough to fit in unsolicited messages */
3512 size_t len;
3513
3514 fd = wpa_ctrl_get_fd(ctrl);
3515
3516 while (!wpa_cli_quit) {
3517 FD_ZERO(&rfds);
3518 FD_SET(fd, &rfds);
3519 tv.tv_sec = ping_interval;
3520 tv.tv_usec = 0;
3521 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3522 if (res < 0 && errno != EINTR) {
3523 perror("select");
3524 break;
3525 }
3526
3527 if (FD_ISSET(fd, &rfds))
3528 wpa_cli_recv_pending(ctrl, 1);
3529 else {
3530 /* verify that connection is still working */
3531 len = sizeof(buf) - 1;
3532 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3533 wpa_cli_action_cb) < 0 ||
3534 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3535 printf("wpa_supplicant did not reply to PING "
3536 "command - exiting\n");
3537 break;
3538 }
3539 }
3540 }
3541 #endif /* CONFIG_ANSI_C_EXTRA */
3542 }
3543
3544
3545 static void wpa_cli_cleanup(void)
3546 {
3547 wpa_cli_close_connection();
3548 if (pid_file)
3549 os_daemonize_terminate(pid_file);
3550
3551 os_program_deinit();
3552 }
3553
3554 static void wpa_cli_terminate(int sig)
3555 {
3556 wpa_cli_cleanup();
3557 exit(0);
3558 }
3559
3560
3561 static char * wpa_cli_get_default_ifname(void)
3562 {
3563 char *ifname = NULL;
3564
3565 #ifdef CONFIG_CTRL_IFACE_UNIX
3566 struct dirent *dent;
3567 DIR *dir = opendir(ctrl_iface_dir);
3568 if (!dir) {
3569 #ifdef ANDROID
3570 char ifprop[PROPERTY_VALUE_MAX];
3571 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3572 ifname = os_strdup(ifprop);
3573 printf("Using interface '%s'\n", ifname);
3574 return ifname;
3575 }
3576 #endif /* ANDROID */
3577 return NULL;
3578 }
3579 while ((dent = readdir(dir))) {
3580 #ifdef _DIRENT_HAVE_D_TYPE
3581 /*
3582 * Skip the file if it is not a socket. Also accept
3583 * DT_UNKNOWN (0) in case the C library or underlying
3584 * file system does not support d_type.
3585 */
3586 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3587 continue;
3588 #endif /* _DIRENT_HAVE_D_TYPE */
3589 if (os_strcmp(dent->d_name, ".") == 0 ||
3590 os_strcmp(dent->d_name, "..") == 0)
3591 continue;
3592 printf("Selected interface '%s'\n", dent->d_name);
3593 ifname = os_strdup(dent->d_name);
3594 break;
3595 }
3596 closedir(dir);
3597 #endif /* CONFIG_CTRL_IFACE_UNIX */
3598
3599 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3600 char buf[2048], *pos;
3601 size_t len;
3602 struct wpa_ctrl *ctrl;
3603 int ret;
3604
3605 ctrl = wpa_ctrl_open(NULL);
3606 if (ctrl == NULL)
3607 return NULL;
3608
3609 len = sizeof(buf) - 1;
3610 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3611 if (ret >= 0) {
3612 buf[len] = '\0';
3613 pos = os_strchr(buf, '\n');
3614 if (pos)
3615 *pos = '\0';
3616 ifname = os_strdup(buf);
3617 }
3618 wpa_ctrl_close(ctrl);
3619 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3620
3621 return ifname;
3622 }
3623
3624
3625 int main(int argc, char *argv[])
3626 {
3627 int warning_displayed = 0;
3628 int c;
3629 int daemonize = 0;
3630 int ret = 0;
3631 const char *global = NULL;
3632
3633 if (os_program_init())
3634 return -1;
3635
3636 for (;;) {
3637 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3638 if (c < 0)
3639 break;
3640 switch (c) {
3641 case 'a':
3642 action_file = optarg;
3643 break;
3644 case 'B':
3645 daemonize = 1;
3646 break;
3647 case 'g':
3648 global = optarg;
3649 break;
3650 case 'G':
3651 ping_interval = atoi(optarg);
3652 break;
3653 case 'h':
3654 usage();
3655 return 0;
3656 case 'v':
3657 printf("%s\n", wpa_cli_version);
3658 return 0;
3659 case 'i':
3660 os_free(ctrl_ifname);
3661 ctrl_ifname = os_strdup(optarg);
3662 break;
3663 case 'p':
3664 ctrl_iface_dir = optarg;
3665 break;
3666 case 'P':
3667 pid_file = optarg;
3668 break;
3669 default:
3670 usage();
3671 return -1;
3672 }
3673 }
3674
3675 interactive = (argc == optind) && (action_file == NULL);
3676
3677 if (interactive)
3678 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3679
3680 if (eloop_init())
3681 return -1;
3682
3683 if (global) {
3684 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3685 ctrl_conn = wpa_ctrl_open(NULL);
3686 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3687 ctrl_conn = wpa_ctrl_open(global);
3688 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3689 if (ctrl_conn == NULL) {
3690 perror("Failed to connect to wpa_supplicant - "
3691 "wpa_ctrl_open");
3692 return -1;
3693 }
3694 }
3695
3696 #ifndef _WIN32_WCE
3697 signal(SIGINT, wpa_cli_terminate);
3698 signal(SIGTERM, wpa_cli_terminate);
3699 #endif /* _WIN32_WCE */
3700
3701 if (ctrl_ifname == NULL)
3702 ctrl_ifname = wpa_cli_get_default_ifname();
3703
3704 if (interactive) {
3705 for (; !global;) {
3706 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3707 if (warning_displayed)
3708 printf("Connection established.\n");
3709 break;
3710 }
3711
3712 if (!warning_displayed) {
3713 printf("Could not connect to wpa_supplicant - "
3714 "re-trying\n");
3715 warning_displayed = 1;
3716 }
3717 os_sleep(1, 0);
3718 continue;
3719 }
3720 } else {
3721 if (!global &&
3722 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3723 perror("Failed to connect to wpa_supplicant - "
3724 "wpa_ctrl_open");
3725 return -1;
3726 }
3727
3728 if (action_file) {
3729 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3730 wpa_cli_attached = 1;
3731 } else {
3732 printf("Warning: Failed to attach to "
3733 "wpa_supplicant.\n");
3734 return -1;
3735 }
3736 }
3737 }
3738
3739 if (daemonize && os_daemonize(pid_file))
3740 return -1;
3741
3742 if (interactive)
3743 wpa_cli_interactive();
3744 else if (action_file)
3745 wpa_cli_action(ctrl_conn);
3746 else
3747 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
3748
3749 os_free(ctrl_ifname);
3750 eloop_destroy();
3751 wpa_cli_cleanup();
3752
3753 return ret;
3754 }
3755
3756 #else /* CONFIG_CTRL_IFACE */
3757 int main(int argc, char *argv[])
3758 {
3759 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3760 return -1;
3761 }
3762 #endif /* CONFIG_CTRL_IFACE */