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