OSDN Git Service

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