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