OSDN Git Service

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