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