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