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