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