IBSS: Add fixed_freq network parameter
[mech_eap.git] / wpa_supplicant / wpa_cli.c
1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2015, 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-2015, 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 = -1;
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 (os_snprintf_error(flen, res)) {
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 (os_snprintf_error(end - pos, res))
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 (os_snprintf_error(end - pos, res))
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         if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500                 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
501         return wpa_ctrl_command(ctrl, "STATUS");
502 }
503
504
505 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506 {
507         return wpa_ctrl_command(ctrl, "PING");
508 }
509
510
511 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512 {
513         return wpa_ctrl_command(ctrl, "RELOG");
514 }
515
516
517 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518 {
519         return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
520 }
521
522
523 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524 {
525         return wpa_ctrl_command(ctrl, "MIB");
526 }
527
528
529 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530 {
531         return wpa_ctrl_command(ctrl, "PMKSA");
532 }
533
534
535 static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
536                                    char *argv[])
537 {
538         return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
539 }
540
541
542 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
543 {
544         print_help(argc > 0 ? argv[0] : NULL);
545         return 0;
546 }
547
548
549 static char ** wpa_cli_complete_help(const char *str, int pos)
550 {
551         int arg = get_cmd_arg_num(str, pos);
552         char **res = NULL;
553
554         switch (arg) {
555         case 1:
556                 res = wpa_list_cmd_list();
557                 break;
558         }
559
560         return res;
561 }
562
563
564 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
565 {
566         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
567         return 0;
568 }
569
570
571 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
572 {
573         wpa_cli_quit = 1;
574         if (interactive)
575                 eloop_terminate();
576         return 0;
577 }
578
579
580 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
581 {
582         char cmd[256];
583         int res;
584
585         if (argc == 1) {
586                 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
587                 if (os_snprintf_error(sizeof(cmd), res)) {
588                         printf("Too long SET command.\n");
589                         return -1;
590                 }
591                 return wpa_ctrl_command(ctrl, cmd);
592         }
593
594         return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
595 }
596
597
598 static char ** wpa_cli_complete_set(const char *str, int pos)
599 {
600         int arg = get_cmd_arg_num(str, pos);
601         const char *fields[] = {
602                 /* runtime values */
603                 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
604                 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
605                 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
606                 "wps_fragment_size", "wps_version_number", "ampdu",
607                 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
608                 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
609                 "no_keep_alive",
610                 /* global configuration parameters */
611                 "eapol_version", "ap_scan", "disable_scan_offload",
612                 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
613                 "pkcs11_module_path", "openssl_ciphers",
614                 "pcsc_reader", "pcsc_pin",
615                 "driver_param", "dot11RSNAConfigPMKLifetime",
616                 "dot11RSNAConfigPMKReauthThreshold",
617                 "dot11RSNAConfigSATimeout",
618                 "update_config", "load_dynamic_eap", "uuid", "device_name",
619                 "manufacturer", "model_name", "model_number", "serial_number",
620                 "device_type", "os_version", "config_methods",
621                 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
622                 "p2p_listen_reg_class", "p2p_listen_channel",
623                 "p2p_oper_reg_class", "p2p_oper_channel",
624                 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
625                 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
626                 "p2p_no_go_freq",
627                 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
628                 "p2p_go_vht",
629                 "p2p_ignore_shared_freq", "country", "bss_max_count",
630                 "bss_expiration_age", "bss_expiration_scan_count",
631                 "filter_ssids", "filter_rssi", "max_num_sta",
632                 "disassoc_low_ack", "hs20", "interworking", "hessid",
633                 "access_network_type", "pbc_in_m1", "autoscan",
634                 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
635                 "wps_nfc_dev_pw", "ext_password_backend",
636                 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
637                 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
638                 "ignore_old_scan_res", "freq_list", "external_sim",
639                 "tdls_external_control", "p2p_search_delay"
640         };
641         int i, num_fields = ARRAY_SIZE(fields);
642
643         if (arg == 1) {
644                 char **res = os_calloc(num_fields + 1, sizeof(char *));
645                 if (res == NULL)
646                         return NULL;
647                 for (i = 0; i < num_fields; i++) {
648                         res[i] = os_strdup(fields[i]);
649                         if (res[i] == NULL)
650                                 return res;
651                 }
652                 return res;
653         }
654
655         if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
656                 return cli_txt_list_array(&bsses);
657
658         return NULL;
659 }
660
661 static int wpa_cli_cmd_dump(struct wpa_ctrl *ctrl, int argc, char *argv[])
662 {
663         return wpa_ctrl_command(ctrl, "DUMP");
664 }
665
666
667 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
668 {
669         return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
670 }
671
672
673 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
674 {
675         return wpa_ctrl_command(ctrl, "LOGOFF");
676 }
677
678
679 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
680 {
681         return wpa_ctrl_command(ctrl, "LOGON");
682 }
683
684
685 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
686                                    char *argv[])
687 {
688         return wpa_ctrl_command(ctrl, "REASSOCIATE");
689 }
690
691
692 static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
693 {
694         return wpa_ctrl_command(ctrl, "REATTACH");
695 }
696
697
698 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
699                                        char *argv[])
700 {
701         return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
702 }
703
704
705 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
706 {
707         return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
708 }
709
710
711 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
712                                      char *argv[])
713 {
714         return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
715 }
716
717
718 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
719                                       char *argv[])
720 {
721         return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
722 }
723
724
725 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
726                                         char *argv[])
727 {
728         return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
729 }
730
731
732 static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
733 {
734         char cmd[256];
735         int res;
736
737         if (argc < 1)
738                 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
739         else
740                 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
741         if (os_snprintf_error(sizeof(cmd), res)) {
742                 printf("Too long BSS_FLUSH command.\n");
743                 return -1;
744         }
745         return wpa_ctrl_command(ctrl, cmd);
746 }
747
748
749 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
750                                 char *argv[])
751 {
752         return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
753 }
754
755
756 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
757 {
758         return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
759 }
760
761
762 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
763 {
764         return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
765 }
766
767
768 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
769 {
770         if (argc == 0) {
771                 printf("Invalid WPS_PIN command: need one or two arguments:\n"
772                        "- BSSID: use 'any' to select any\n"
773                        "- PIN: optional, used only with devices that have no "
774                        "display\n");
775                 return -1;
776         }
777
778         return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
779 }
780
781
782 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
783                                      char *argv[])
784 {
785         return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
786 }
787
788
789 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
790                                   char *argv[])
791 {
792         return wpa_ctrl_command(ctrl, "WPS_CANCEL");
793 }
794
795
796 #ifdef CONFIG_WPS_NFC
797
798 static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
799 {
800         return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
801 }
802
803
804 static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
805                                             char *argv[])
806 {
807         return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
808 }
809
810
811 static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
812                                      char *argv[])
813 {
814         return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
815 }
816
817
818 static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
819                                         char *argv[])
820 {
821         int ret;
822         char *buf;
823         size_t buflen;
824
825         if (argc != 1) {
826                 printf("Invalid 'wps_nfc_tag_read' command - one argument "
827                        "is required.\n");
828                 return -1;
829         }
830
831         buflen = 18 + os_strlen(argv[0]);
832         buf = os_malloc(buflen);
833         if (buf == NULL)
834                 return -1;
835         os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
836
837         ret = wpa_ctrl_command(ctrl, buf);
838         os_free(buf);
839
840         return ret;
841 }
842
843
844 static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
845                                             char *argv[])
846 {
847         return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
848 }
849
850
851 static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
852                                             char *argv[])
853 {
854         return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
855 }
856
857
858 static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
859                                            char *argv[])
860 {
861         return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
862 }
863
864 #endif /* CONFIG_WPS_NFC */
865
866
867 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
868 {
869         char cmd[256];
870         int res;
871
872         if (argc == 2)
873                 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
874                                   argv[0], argv[1]);
875         else if (argc == 5 || argc == 6) {
876                 char ssid_hex[2 * 32 + 1];
877                 char key_hex[2 * 64 + 1];
878                 int i;
879
880                 ssid_hex[0] = '\0';
881                 for (i = 0; i < 32; i++) {
882                         if (argv[2][i] == '\0')
883                                 break;
884                         os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
885                 }
886
887                 key_hex[0] = '\0';
888                 if (argc == 6) {
889                         for (i = 0; i < 64; i++) {
890                                 if (argv[5][i] == '\0')
891                                         break;
892                                 os_snprintf(&key_hex[i * 2], 3, "%02x",
893                                             argv[5][i]);
894                         }
895                 }
896
897                 res = os_snprintf(cmd, sizeof(cmd),
898                                   "WPS_REG %s %s %s %s %s %s",
899                                   argv[0], argv[1], ssid_hex, argv[3], argv[4],
900                                   key_hex);
901         } else {
902                 printf("Invalid WPS_REG command: need two arguments:\n"
903                        "- BSSID of the target AP\n"
904                        "- AP PIN\n");
905                 printf("Alternatively, six arguments can be used to "
906                        "reconfigure the AP:\n"
907                        "- BSSID of the target AP\n"
908                        "- AP PIN\n"
909                        "- new SSID\n"
910                        "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
911                        "- new encr (NONE, WEP, TKIP, CCMP)\n"
912                        "- new key\n");
913                 return -1;
914         }
915
916         if (os_snprintf_error(sizeof(cmd), res)) {
917                 printf("Too long WPS_REG command.\n");
918                 return -1;
919         }
920         return wpa_ctrl_command(ctrl, cmd);
921 }
922
923
924 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
925                                   char *argv[])
926 {
927         return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
928 }
929
930
931 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
932                                     char *argv[])
933 {
934         return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
935 }
936
937
938 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
939                                    char *argv[])
940 {
941         return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
942
943 }
944
945
946 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
947                                   char *argv[])
948 {
949         if (argc < 2) {
950                 printf("Invalid WPS_ER_PIN command: need at least two "
951                        "arguments:\n"
952                        "- UUID: use 'any' to select any\n"
953                        "- PIN: Enrollee PIN\n"
954                        "optional: - Enrollee MAC address\n");
955                 return -1;
956         }
957
958         return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
959 }
960
961
962 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
963                                   char *argv[])
964 {
965         return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
966 }
967
968
969 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
970                                     char *argv[])
971 {
972         if (argc != 2) {
973                 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
974                        "- UUID: specify which AP to use\n"
975                        "- PIN: AP PIN\n");
976                 return -1;
977         }
978
979         return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
980 }
981
982
983 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
984                                          char *argv[])
985 {
986         if (argc != 2) {
987                 printf("Invalid WPS_ER_SET_CONFIG command: need two "
988                        "arguments:\n"
989                        "- UUID: specify which AP to use\n"
990                        "- Network configuration id\n");
991                 return -1;
992         }
993
994         return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
995 }
996
997
998 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
999                                      char *argv[])
1000 {
1001         char cmd[256];
1002         int res;
1003
1004         if (argc == 5 || argc == 6) {
1005                 char ssid_hex[2 * 32 + 1];
1006                 char key_hex[2 * 64 + 1];
1007                 int i;
1008
1009                 ssid_hex[0] = '\0';
1010                 for (i = 0; i < 32; i++) {
1011                         if (argv[2][i] == '\0')
1012                                 break;
1013                         os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1014                 }
1015
1016                 key_hex[0] = '\0';
1017                 if (argc == 6) {
1018                         for (i = 0; i < 64; i++) {
1019                                 if (argv[5][i] == '\0')
1020                                         break;
1021                                 os_snprintf(&key_hex[i * 2], 3, "%02x",
1022                                             argv[5][i]);
1023                         }
1024                 }
1025
1026                 res = os_snprintf(cmd, sizeof(cmd),
1027                                   "WPS_ER_CONFIG %s %s %s %s %s %s",
1028                                   argv[0], argv[1], ssid_hex, argv[3], argv[4],
1029                                   key_hex);
1030         } else {
1031                 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1032                        "- AP UUID\n"
1033                        "- AP PIN\n"
1034                        "- new SSID\n"
1035                        "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1036                        "- new encr (NONE, WEP, TKIP, CCMP)\n"
1037                        "- new key\n");
1038                 return -1;
1039         }
1040
1041         if (os_snprintf_error(sizeof(cmd), res)) {
1042                 printf("Too long WPS_ER_CONFIG command.\n");
1043                 return -1;
1044         }
1045         return wpa_ctrl_command(ctrl, cmd);
1046 }
1047
1048
1049 #ifdef CONFIG_WPS_NFC
1050 static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1051                                                char *argv[])
1052 {
1053         if (argc != 2) {
1054                 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1055                        "arguments:\n"
1056                        "- WPS/NDEF: token format\n"
1057                        "- UUID: specify which AP to use\n");
1058                 return -1;
1059         }
1060
1061         return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1062 }
1063 #endif /* CONFIG_WPS_NFC */
1064
1065
1066 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1067 {
1068         return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1069 }
1070
1071
1072 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1073 {
1074         return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1075 }
1076
1077
1078 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1079 {
1080         char cmd[256], *pos, *end;
1081         int i, ret;
1082
1083         if (argc < 2) {
1084                 printf("Invalid IDENTITY command: needs two arguments "
1085                        "(network id and identity)\n");
1086                 return -1;
1087         }
1088
1089         end = cmd + sizeof(cmd);
1090         pos = cmd;
1091         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1092                           argv[0], argv[1]);
1093         if (os_snprintf_error(end - pos, ret)) {
1094                 printf("Too long IDENTITY command.\n");
1095                 return -1;
1096         }
1097         pos += ret;
1098         for (i = 2; i < argc; i++) {
1099                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1100                 if (os_snprintf_error(end - pos, ret)) {
1101                         printf("Too long IDENTITY command.\n");
1102                         return -1;
1103                 }
1104                 pos += ret;
1105         }
1106
1107         return wpa_ctrl_command(ctrl, cmd);
1108 }
1109
1110
1111 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1112 {
1113         char cmd[256], *pos, *end;
1114         int i, ret;
1115
1116         if (argc < 2) {
1117                 printf("Invalid PASSWORD command: needs two arguments "
1118                        "(network id and password)\n");
1119                 return -1;
1120         }
1121
1122         end = cmd + sizeof(cmd);
1123         pos = cmd;
1124         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1125                           argv[0], argv[1]);
1126         if (os_snprintf_error(end - pos, ret)) {
1127                 printf("Too long PASSWORD command.\n");
1128                 return -1;
1129         }
1130         pos += ret;
1131         for (i = 2; i < argc; i++) {
1132                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1133                 if (os_snprintf_error(end - pos, ret)) {
1134                         printf("Too long PASSWORD command.\n");
1135                         return -1;
1136                 }
1137                 pos += ret;
1138         }
1139
1140         return wpa_ctrl_command(ctrl, cmd);
1141 }
1142
1143
1144 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1145                                     char *argv[])
1146 {
1147         char cmd[256], *pos, *end;
1148         int i, ret;
1149
1150         if (argc < 2) {
1151                 printf("Invalid NEW_PASSWORD command: needs two arguments "
1152                        "(network id and password)\n");
1153                 return -1;
1154         }
1155
1156         end = cmd + sizeof(cmd);
1157         pos = cmd;
1158         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1159                           argv[0], argv[1]);
1160         if (os_snprintf_error(end - pos, ret)) {
1161                 printf("Too long NEW_PASSWORD command.\n");
1162                 return -1;
1163         }
1164         pos += ret;
1165         for (i = 2; i < argc; i++) {
1166                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1167                 if (os_snprintf_error(end - pos, ret)) {
1168                         printf("Too long NEW_PASSWORD command.\n");
1169                         return -1;
1170                 }
1171                 pos += ret;
1172         }
1173
1174         return wpa_ctrl_command(ctrl, cmd);
1175 }
1176
1177
1178 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1179 {
1180         char cmd[256], *pos, *end;
1181         int i, ret;
1182
1183         if (argc < 2) {
1184                 printf("Invalid PIN command: needs two arguments "
1185                        "(network id and pin)\n");
1186                 return -1;
1187         }
1188
1189         end = cmd + sizeof(cmd);
1190         pos = cmd;
1191         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1192                           argv[0], argv[1]);
1193         if (os_snprintf_error(end - pos, ret)) {
1194                 printf("Too long PIN command.\n");
1195                 return -1;
1196         }
1197         pos += ret;
1198         for (i = 2; i < argc; i++) {
1199                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1200                 if (os_snprintf_error(end - pos, ret)) {
1201                         printf("Too long PIN command.\n");
1202                         return -1;
1203                 }
1204                 pos += ret;
1205         }
1206         return wpa_ctrl_command(ctrl, cmd);
1207 }
1208
1209
1210 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1211 {
1212         char cmd[256], *pos, *end;
1213         int i, ret;
1214
1215         if (argc < 2) {
1216                 printf("Invalid OTP command: needs two arguments (network "
1217                        "id and password)\n");
1218                 return -1;
1219         }
1220
1221         end = cmd + sizeof(cmd);
1222         pos = cmd;
1223         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1224                           argv[0], argv[1]);
1225         if (os_snprintf_error(end - pos, ret)) {
1226                 printf("Too long OTP command.\n");
1227                 return -1;
1228         }
1229         pos += ret;
1230         for (i = 2; i < argc; i++) {
1231                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1232                 if (os_snprintf_error(end - pos, ret)) {
1233                         printf("Too long OTP command.\n");
1234                         return -1;
1235                 }
1236                 pos += ret;
1237         }
1238
1239         return wpa_ctrl_command(ctrl, cmd);
1240 }
1241
1242
1243 static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1244 {
1245         char cmd[256], *pos, *end;
1246         int i, ret;
1247
1248         if (argc < 2) {
1249                 printf("Invalid SIM command: needs two arguments "
1250                        "(network id and SIM operation response)\n");
1251                 return -1;
1252         }
1253
1254         end = cmd + sizeof(cmd);
1255         pos = cmd;
1256         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1257                           argv[0], argv[1]);
1258         if (os_snprintf_error(end - pos, ret)) {
1259                 printf("Too long SIM command.\n");
1260                 return -1;
1261         }
1262         pos += ret;
1263         for (i = 2; i < argc; i++) {
1264                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1265                 if (os_snprintf_error(end - pos, ret)) {
1266                         printf("Too long SIM command.\n");
1267                         return -1;
1268                 }
1269                 pos += ret;
1270         }
1271         return wpa_ctrl_command(ctrl, cmd);
1272 }
1273
1274
1275 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1276                                   char *argv[])
1277 {
1278         char cmd[256], *pos, *end;
1279         int i, ret;
1280
1281         if (argc < 2) {
1282                 printf("Invalid PASSPHRASE command: needs two arguments "
1283                        "(network id and passphrase)\n");
1284                 return -1;
1285         }
1286
1287         end = cmd + sizeof(cmd);
1288         pos = cmd;
1289         ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1290                           argv[0], argv[1]);
1291         if (os_snprintf_error(end - pos, ret)) {
1292                 printf("Too long PASSPHRASE command.\n");
1293                 return -1;
1294         }
1295         pos += ret;
1296         for (i = 2; i < argc; i++) {
1297                 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1298                 if (os_snprintf_error(end - pos, ret)) {
1299                         printf("Too long PASSPHRASE command.\n");
1300                         return -1;
1301                 }
1302                 pos += ret;
1303         }
1304
1305         return wpa_ctrl_command(ctrl, cmd);
1306 }
1307
1308
1309 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1310 {
1311         if (argc < 2) {
1312                 printf("Invalid BSSID command: needs two arguments (network "
1313                        "id and BSSID)\n");
1314                 return -1;
1315         }
1316
1317         return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1318 }
1319
1320
1321 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322 {
1323         return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1324 }
1325
1326
1327 static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1328 {
1329         return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1330 }
1331
1332
1333 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1334                                      char *argv[])
1335 {
1336         return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1337 }
1338
1339
1340 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1341                                       char *argv[])
1342 {
1343         return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1344 }
1345
1346
1347 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1348                                       char *argv[])
1349 {
1350         return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1351 }
1352
1353
1354 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1355                                        char *argv[])
1356 {
1357         return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1358 }
1359
1360
1361 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1362                                    char *argv[])
1363 {
1364         return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1365 }
1366
1367
1368 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1369                                       char *argv[])
1370 {
1371         return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1372 }
1373
1374
1375 static void wpa_cli_show_network_variables(void)
1376 {
1377         printf("set_network variables:\n"
1378                "  ssid (network name, SSID)\n"
1379                "  psk (WPA passphrase or pre-shared key)\n"
1380                "  key_mgmt (key management protocol)\n"
1381                "  identity (EAP identity)\n"
1382                "  password (EAP password)\n"
1383                "  ...\n"
1384                "\n"
1385                "Note: Values are entered in the same format as the "
1386                "configuration file is using,\n"
1387                "i.e., strings values need to be inside double quotation "
1388                "marks.\n"
1389                "For example: set_network 1 ssid \"network name\"\n"
1390                "\n"
1391                "Please see wpa_supplicant.conf documentation for full list "
1392                "of\navailable variables.\n");
1393 }
1394
1395
1396 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1397                                    char *argv[])
1398 {
1399         if (argc == 0) {
1400                 wpa_cli_show_network_variables();
1401                 return 0;
1402         }
1403
1404         if (argc < 3) {
1405                 printf("Invalid SET_NETWORK command: needs three arguments\n"
1406                        "(network id, variable name, and value)\n");
1407                 return -1;
1408         }
1409
1410         return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1411 }
1412
1413
1414 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1415                                    char *argv[])
1416 {
1417         if (argc == 0) {
1418                 wpa_cli_show_network_variables();
1419                 return 0;
1420         }
1421
1422         if (argc != 2) {
1423                 printf("Invalid GET_NETWORK command: needs two arguments\n"
1424                        "(network id and variable name)\n");
1425                 return -1;
1426         }
1427
1428         return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1429 }
1430
1431
1432 static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1433                                    char *argv[])
1434 {
1435         if (argc == 0) {
1436                 wpa_cli_show_network_variables();
1437                 return 0;
1438         }
1439
1440         if (argc < 3) {
1441                 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1442                        "(src netid, dest netid, and variable name)\n");
1443                 return -1;
1444         }
1445
1446         return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1447 }
1448
1449
1450 static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1451                                   char *argv[])
1452 {
1453         return wpa_ctrl_command(ctrl, "LIST_CREDS");
1454 }
1455
1456
1457 static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458 {
1459         return wpa_ctrl_command(ctrl, "ADD_CRED");
1460 }
1461
1462
1463 static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1464                                    char *argv[])
1465 {
1466         return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1467 }
1468
1469
1470 static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471 {
1472         if (argc != 3) {
1473                 printf("Invalid SET_CRED command: needs three arguments\n"
1474                        "(cred id, variable name, and value)\n");
1475                 return -1;
1476         }
1477
1478         return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1479 }
1480
1481
1482 static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1483 {
1484         if (argc != 2) {
1485                 printf("Invalid GET_CRED command: needs two arguments\n"
1486                        "(cred id, variable name)\n");
1487                 return -1;
1488         }
1489
1490         return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1491 }
1492
1493
1494 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1495                                   char *argv[])
1496 {
1497         return wpa_ctrl_command(ctrl, "DISCONNECT");
1498 }
1499
1500
1501 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1502                                   char *argv[])
1503 {
1504         return wpa_ctrl_command(ctrl, "RECONNECT");
1505 }
1506
1507
1508 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1509                                    char *argv[])
1510 {
1511         return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1512 }
1513
1514
1515 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516 {
1517         return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
1518 }
1519
1520
1521 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1522                                     char *argv[])
1523 {
1524         return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1525 }
1526
1527
1528 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1529 {
1530         return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1531 }
1532
1533
1534 static char ** wpa_cli_complete_bss(const char *str, int pos)
1535 {
1536         int arg = get_cmd_arg_num(str, pos);
1537         char **res = NULL;
1538
1539         switch (arg) {
1540         case 1:
1541                 res = cli_txt_list_array(&bsses);
1542                 break;
1543         }
1544
1545         return res;
1546 }
1547
1548
1549 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1550                                       char *argv[])
1551 {
1552         if (argc < 1 || argc > 2) {
1553                 printf("Invalid GET_CAPABILITY command: need either one or "
1554                        "two arguments\n");
1555                 return -1;
1556         }
1557
1558         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1559                 printf("Invalid GET_CAPABILITY command: second argument, "
1560                        "if any, must be 'strict'\n");
1561                 return -1;
1562         }
1563
1564         return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1565 }
1566
1567
1568 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1569 {
1570         printf("Available interfaces:\n");
1571         return wpa_ctrl_command(ctrl, "INTERFACES");
1572 }
1573
1574
1575 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1576 {
1577         if (argc < 1) {
1578                 wpa_cli_list_interfaces(ctrl);
1579                 return 0;
1580         }
1581
1582         wpa_cli_close_connection();
1583         os_free(ctrl_ifname);
1584         ctrl_ifname = os_strdup(argv[0]);
1585         if (!ctrl_ifname) {
1586                 printf("Failed to allocate memory\n");
1587                 return 0;
1588         }
1589
1590         if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1591                 printf("Connected to interface '%s.\n", ctrl_ifname);
1592         } else {
1593                 printf("Could not connect to interface '%s' - re-trying\n",
1594                        ctrl_ifname);
1595         }
1596         return 0;
1597 }
1598
1599
1600 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1601                                    char *argv[])
1602 {
1603         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1604 }
1605
1606
1607 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1608                                  char *argv[])
1609 {
1610         return wpa_ctrl_command(ctrl, "TERMINATE");
1611 }
1612
1613
1614 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1615                                      char *argv[])
1616 {
1617         char cmd[256];
1618         int res;
1619
1620         if (argc < 1) {
1621                 printf("Invalid INTERFACE_ADD command: needs at least one "
1622                        "argument (interface name)\n"
1623                        "All arguments: ifname confname driver ctrl_interface "
1624                        "driver_param bridge_name\n");
1625                 return -1;
1626         }
1627
1628         /*
1629          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1630          * <driver_param>TAB<bridge_name>
1631          */
1632         res = os_snprintf(cmd, sizeof(cmd),
1633                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1634                           argv[0],
1635                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1636                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1637                           argc > 5 ? argv[5] : "");
1638         if (os_snprintf_error(sizeof(cmd), res))
1639                 return -1;
1640         cmd[sizeof(cmd) - 1] = '\0';
1641         return wpa_ctrl_command(ctrl, cmd);
1642 }
1643
1644
1645 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1646                                         char *argv[])
1647 {
1648         return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1649 }
1650
1651
1652 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1653                                       char *argv[])
1654 {
1655         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1656 }
1657
1658
1659 #ifdef CONFIG_AP
1660 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1661 {
1662         return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1663 }
1664
1665
1666 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1667                                 char *addr, size_t addr_len)
1668 {
1669         char buf[4096], *pos;
1670         size_t len;
1671         int ret;
1672
1673         if (ctrl_conn == NULL) {
1674                 printf("Not connected to hostapd - command dropped.\n");
1675                 return -1;
1676         }
1677         len = sizeof(buf) - 1;
1678         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1679                                wpa_cli_msg_cb);
1680         if (ret == -2) {
1681                 printf("'%s' command timed out.\n", cmd);
1682                 return -2;
1683         } else if (ret < 0) {
1684                 printf("'%s' command failed.\n", cmd);
1685                 return -1;
1686         }
1687
1688         buf[len] = '\0';
1689         if (os_memcmp(buf, "FAIL", 4) == 0)
1690                 return -1;
1691         printf("%s", buf);
1692
1693         pos = buf;
1694         while (*pos != '\0' && *pos != '\n')
1695                 pos++;
1696         *pos = '\0';
1697         os_strlcpy(addr, buf, addr_len);
1698         return 0;
1699 }
1700
1701
1702 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1703 {
1704         char addr[32], cmd[64];
1705
1706         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1707                 return 0;
1708         do {
1709                 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1710         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1711
1712         return -1;
1713 }
1714
1715
1716 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1717                                       char *argv[])
1718 {
1719         return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1720 }
1721
1722
1723 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1724                                     char *argv[])
1725 {
1726         return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1727 }
1728
1729 static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1730                                     char *argv[])
1731 {
1732         return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1733 }
1734
1735 #endif /* CONFIG_AP */
1736
1737
1738 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1739 {
1740         return wpa_ctrl_command(ctrl, "SUSPEND");
1741 }
1742
1743
1744 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1745 {
1746         return wpa_ctrl_command(ctrl, "RESUME");
1747 }
1748
1749
1750 #ifdef CONFIG_TESTING_OPTIONS
1751 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1752 {
1753         return wpa_ctrl_command(ctrl, "DROP_SA");
1754 }
1755 #endif /* CONFIG_TESTING_OPTIONS */
1756
1757
1758 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1759 {
1760         return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
1761 }
1762
1763
1764 #ifdef CONFIG_MESH
1765
1766 static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
1767                                           char *argv[])
1768 {
1769         return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
1770 }
1771
1772
1773 static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
1774                                       char *argv[])
1775 {
1776         return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
1777 }
1778
1779
1780 static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
1781                                          char *argv[])
1782 {
1783         return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
1784 }
1785
1786 #endif /* CONFIG_MESH */
1787
1788
1789 #ifdef CONFIG_P2P
1790
1791 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1792 {
1793         return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1794 }
1795
1796
1797 static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1798 {
1799         char **res = NULL;
1800         int arg = get_cmd_arg_num(str, pos);
1801
1802         res = os_calloc(6, sizeof(char *));
1803         if (res == NULL)
1804                 return NULL;
1805         res[0] = os_strdup("type=social");
1806         if (res[0] == NULL) {
1807                 os_free(res);
1808                 return NULL;
1809         }
1810         res[1] = os_strdup("type=progressive");
1811         if (res[1] == NULL)
1812                 return res;
1813         res[2] = os_strdup("delay=");
1814         if (res[2] == NULL)
1815                 return res;
1816         res[3] = os_strdup("dev_id=");
1817         if (res[3] == NULL)
1818                 return res;
1819         if (arg == 1)
1820                 res[4] = os_strdup("[timeout]");
1821
1822         return res;
1823 }
1824
1825
1826 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1827                                      char *argv[])
1828 {
1829         return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1830 }
1831
1832
1833 static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
1834                                          char *argv[])
1835 {
1836         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
1837 }
1838
1839
1840 static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
1841                                               char *argv[])
1842 {
1843         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
1844 }
1845
1846
1847 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1848                                    char *argv[])
1849 {
1850         return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
1851 }
1852
1853
1854 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1855 {
1856         int arg = get_cmd_arg_num(str, pos);
1857         char **res = NULL;
1858
1859         switch (arg) {
1860         case 1:
1861                 res = cli_txt_list_array(&p2p_peers);
1862                 break;
1863         }
1864
1865         return res;
1866 }
1867
1868
1869 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1870                                   char *argv[])
1871 {
1872         return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
1873 }
1874
1875
1876 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1877                                         char *argv[])
1878 {
1879         return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
1880 }
1881
1882
1883 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1884 {
1885         int arg = get_cmd_arg_num(str, pos);
1886         char **res = NULL;
1887
1888         switch (arg) {
1889         case 1:
1890                 res = cli_txt_list_array(&p2p_groups);
1891                 break;
1892         }
1893
1894         return res;
1895 }
1896
1897
1898 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1899                                         char *argv[])
1900 {
1901         return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
1902 }
1903
1904
1905 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1906                                      char *argv[])
1907 {
1908         if (argc != 2 && argc != 3) {
1909                 printf("Invalid P2P_PROV_DISC command: needs at least "
1910                        "two arguments, address and config method\n"
1911                        "(display, keypad, or pbc) and an optional join\n");
1912                 return -1;
1913         }
1914
1915         return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
1916 }
1917
1918
1919 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1920                                           char *argv[])
1921 {
1922         return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1923 }
1924
1925
1926 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1927                                          char *argv[])
1928 {
1929         char cmd[4096];
1930
1931         if (argc < 2) {
1932                 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1933                        "or more arguments (address and TLVs)\n");
1934                 return -1;
1935         }
1936
1937         if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
1938                 return -1;
1939         return wpa_ctrl_command(ctrl, cmd);
1940 }
1941
1942
1943 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1944                                                 int argc, char *argv[])
1945 {
1946         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
1947 }
1948
1949
1950 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1951                                           char *argv[])
1952 {
1953         char cmd[4096];
1954         int res;
1955
1956         if (argc != 4) {
1957                 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1958                        "arguments (freq, address, dialog token, and TLVs)\n");
1959                 return -1;
1960         }
1961
1962         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1963                           argv[0], argv[1], argv[2], argv[3]);
1964         if (os_snprintf_error(sizeof(cmd), res))
1965                 return -1;
1966         cmd[sizeof(cmd) - 1] = '\0';
1967         return wpa_ctrl_command(ctrl, cmd);
1968 }
1969
1970
1971 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1972                                           char *argv[])
1973 {
1974         return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1975 }
1976
1977
1978 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1979                                               int argc, char *argv[])
1980 {
1981         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
1982 }
1983
1984
1985 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1986                                          char *argv[])
1987 {
1988         return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1989 }
1990
1991
1992 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1993                                        char *argv[])
1994 {
1995         if (argc < 3) {
1996                 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
1997                 return -1;
1998         }
1999
2000         return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2001 }
2002
2003
2004 static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2005                                        char *argv[])
2006 {
2007         if (argc < 5 || argc > 6) {
2008                 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
2009                        "arguments\n");
2010                 return -1;
2011         }
2012
2013         return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
2014 }
2015
2016
2017 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2018                                        char *argv[])
2019 {
2020         char cmd[4096];
2021         int res;
2022
2023         if (argc != 2 && argc != 3) {
2024                 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2025                        "arguments\n");
2026                 return -1;
2027         }
2028
2029         if (argc == 3)
2030                 res = os_snprintf(cmd, sizeof(cmd),
2031                                   "P2P_SERVICE_DEL %s %s %s",
2032                                   argv[0], argv[1], argv[2]);
2033         else
2034                 res = os_snprintf(cmd, sizeof(cmd),
2035                                   "P2P_SERVICE_DEL %s %s",
2036                                   argv[0], argv[1]);
2037         if (os_snprintf_error(sizeof(cmd), res))
2038                 return -1;
2039         cmd[sizeof(cmd) - 1] = '\0';
2040         return wpa_ctrl_command(ctrl, cmd);
2041 }
2042
2043
2044 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2045                                   int argc, char *argv[])
2046 {
2047         return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
2048 }
2049
2050
2051 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2052                                   int argc, char *argv[])
2053 {
2054         return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2055 }
2056
2057
2058 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2059 {
2060         return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2061 }
2062
2063
2064 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2065 {
2066         int arg = get_cmd_arg_num(str, pos);
2067         char **res = NULL;
2068
2069         switch (arg) {
2070         case 1:
2071                 res = cli_txt_list_array(&p2p_peers);
2072                 break;
2073         }
2074
2075         return res;
2076 }
2077
2078
2079 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2080                                      char *addr, size_t addr_len,
2081                                      int discovered)
2082 {
2083         char buf[4096], *pos;
2084         size_t len;
2085         int ret;
2086
2087         if (ctrl_conn == NULL)
2088                 return -1;
2089         len = sizeof(buf) - 1;
2090         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2091                                wpa_cli_msg_cb);
2092         if (ret == -2) {
2093                 printf("'%s' command timed out.\n", cmd);
2094                 return -2;
2095         } else if (ret < 0) {
2096                 printf("'%s' command failed.\n", cmd);
2097                 return -1;
2098         }
2099
2100         buf[len] = '\0';
2101         if (os_memcmp(buf, "FAIL", 4) == 0)
2102                 return -1;
2103
2104         pos = buf;
2105         while (*pos != '\0' && *pos != '\n')
2106                 pos++;
2107         *pos++ = '\0';
2108         os_strlcpy(addr, buf, addr_len);
2109         if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2110                 printf("%s\n", addr);
2111         return 0;
2112 }
2113
2114
2115 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2116 {
2117         char addr[32], cmd[64];
2118         int discovered;
2119
2120         discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2121
2122         if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2123                                       addr, sizeof(addr), discovered))
2124                 return -1;
2125         do {
2126                 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2127         } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2128                          discovered) == 0);
2129
2130         return 0;
2131 }
2132
2133
2134 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2135 {
2136         return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2137 }
2138
2139
2140 static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2141 {
2142         int arg = get_cmd_arg_num(str, pos);
2143         const char *fields[] = {
2144                 "discoverability",
2145                 "managed",
2146                 "listen_channel",
2147                 "ssid_postfix",
2148                 "noa",
2149                 "ps",
2150                 "oppps",
2151                 "ctwindow",
2152                 "disabled",
2153                 "conc_pref",
2154                 "force_long_sd",
2155                 "peer_filter",
2156                 "cross_connect",
2157                 "go_apsd",
2158                 "client_apsd",
2159                 "disallow_freq",
2160                 "disc_int",
2161                 "per_sta_psk",
2162         };
2163         int i, num_fields = ARRAY_SIZE(fields);
2164
2165         if (arg == 1) {
2166                 char **res = os_calloc(num_fields + 1, sizeof(char *));
2167                 if (res == NULL)
2168                         return NULL;
2169                 for (i = 0; i < num_fields; i++) {
2170                         res[i] = os_strdup(fields[i]);
2171                         if (res[i] == NULL)
2172                                 return res;
2173                 }
2174                 return res;
2175         }
2176
2177         if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2178                 return cli_txt_list_array(&p2p_peers);
2179
2180         return NULL;
2181 }
2182
2183
2184 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2185 {
2186         return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2187 }
2188
2189
2190 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2191                                   char *argv[])
2192 {
2193         return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2194 }
2195
2196
2197 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2198                                        char *argv[])
2199 {
2200         return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2201 }
2202
2203
2204 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2205                                         char *argv[])
2206 {
2207         if (argc != 0 && argc != 2 && argc != 4) {
2208                 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2209                        "(preferred duration, interval; in microsecods).\n"
2210                        "Optional second pair can be used to provide "
2211                        "acceptable values.\n");
2212                 return -1;
2213         }
2214
2215         return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2216 }
2217
2218
2219 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2220                                       char *argv[])
2221 {
2222         if (argc != 0 && argc != 2) {
2223                 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2224                        "(availability period, availability interval; in "
2225                        "millisecods).\n"
2226                        "Extended Listen Timing can be cancelled with this "
2227                        "command when used without parameters.\n");
2228                 return -1;
2229         }
2230
2231         return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2232 }
2233
2234
2235 static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2236                                          char *argv[])
2237 {
2238         return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2239 }
2240
2241 #endif /* CONFIG_P2P */
2242
2243 #ifdef CONFIG_WIFI_DISPLAY
2244
2245 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2246                                        char *argv[])
2247 {
2248         char cmd[100];
2249         int res;
2250
2251         if (argc != 1 && argc != 2) {
2252                 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2253                        "arguments (subelem, hexdump)\n");
2254                 return -1;
2255         }
2256
2257         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2258                           argv[0], argc > 1 ? argv[1] : "");
2259         if (os_snprintf_error(sizeof(cmd), res))
2260                 return -1;
2261         cmd[sizeof(cmd) - 1] = '\0';
2262         return wpa_ctrl_command(ctrl, cmd);
2263 }
2264
2265
2266 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2267                                        char *argv[])
2268 {
2269         char cmd[100];
2270         int res;
2271
2272         if (argc != 1) {
2273                 printf("Invalid WFD_SUBELEM_GET command: needs one "
2274                        "argument (subelem)\n");
2275                 return -1;
2276         }
2277
2278         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2279                           argv[0]);
2280         if (os_snprintf_error(sizeof(cmd), res))
2281                 return -1;
2282         cmd[sizeof(cmd) - 1] = '\0';
2283         return wpa_ctrl_command(ctrl, cmd);
2284 }
2285 #endif /* CONFIG_WIFI_DISPLAY */
2286
2287
2288 #ifdef CONFIG_INTERWORKING
2289 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2290                                   char *argv[])
2291 {
2292         return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2293 }
2294
2295
2296 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2297                                        char *argv[])
2298 {
2299         return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2300 }
2301
2302
2303 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2304                                            char *argv[])
2305 {
2306         return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2307 }
2308
2309
2310 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2311                                             char *argv[])
2312 {
2313         return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2314 }
2315
2316
2317 static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2318                                                 char *argv[])
2319 {
2320         return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2321 }
2322
2323
2324 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2325 {
2326         return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2327 }
2328
2329
2330 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2331                                    char *argv[])
2332 {
2333         return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2334 }
2335
2336
2337 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2338                                         char *argv[])
2339 {
2340         return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2341 }
2342 #endif /* CONFIG_INTERWORKING */
2343
2344
2345 #ifdef CONFIG_HS20
2346
2347 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2348                                      char *argv[])
2349 {
2350         return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2351 }
2352
2353
2354 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2355                                                char *argv[])
2356 {
2357         char cmd[512];
2358
2359         if (argc == 0) {
2360                 printf("Command needs one or two arguments (dst mac addr and "
2361                        "optional home realm)\n");
2362                 return -1;
2363         }
2364
2365         if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2366                       argc, argv) < 0)
2367                 return -1;
2368
2369         return wpa_ctrl_command(ctrl, cmd);
2370 }
2371
2372
2373 static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2374                                          char *argv[])
2375 {
2376         char cmd[512];
2377
2378         if (argc < 2) {
2379                 printf("Command needs two arguments (dst mac addr and "
2380                        "icon name)\n");
2381                 return -1;
2382         }
2383
2384         if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2385                 return -1;
2386
2387         return wpa_ctrl_command(ctrl, cmd);
2388 }
2389
2390
2391 static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2392 {
2393         return wpa_ctrl_command(ctrl, "FETCH_OSU");
2394 }
2395
2396
2397 static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2398                                         char *argv[])
2399 {
2400         return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2401 }
2402
2403 #endif /* CONFIG_HS20 */
2404
2405
2406 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2407                                        char *argv[])
2408 {
2409         return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2410 }
2411
2412
2413 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2414                                      char *argv[])
2415 {
2416         return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2417 }
2418
2419
2420 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2421                                   char *argv[])
2422 {
2423         return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2424 }
2425
2426
2427 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2428                                      char *argv[])
2429 {
2430         return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2431 }
2432
2433
2434 static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2435                                     char *argv[])
2436 {
2437         return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2438 }
2439
2440
2441 static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2442                                     char *argv[])
2443 {
2444         return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2445 }
2446
2447
2448 static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2449                                     char *argv[])
2450 {
2451         return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2452 }
2453
2454
2455 static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2456                                         char *argv[])
2457 {
2458         return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2459 }
2460
2461
2462 static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2463                                                char *argv[])
2464 {
2465         return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2466 }
2467
2468
2469 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2470                                    char *argv[])
2471 {
2472         return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2473 }
2474
2475
2476 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2477                                    char *argv[])
2478 {
2479         return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2480 }
2481
2482
2483 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2484                                       char *argv[])
2485 {
2486         return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2487 }
2488
2489
2490 #ifdef CONFIG_AUTOSCAN
2491
2492 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2493 {
2494         if (argc == 0)
2495                 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2496
2497         return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2498 }
2499
2500 #endif /* CONFIG_AUTOSCAN */
2501
2502
2503 #ifdef CONFIG_WNM
2504
2505 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2506 {
2507         return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2508 }
2509
2510
2511 static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2512 {
2513         return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2514 }
2515
2516 #endif /* CONFIG_WNM */
2517
2518
2519 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2520 {
2521         if (argc == 0)
2522                 return -1;
2523         return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2524 }
2525
2526
2527 #ifdef ANDROID
2528 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2529 {
2530         return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2531 }
2532 #endif /* ANDROID */
2533
2534
2535 static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2536 {
2537         return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2538 }
2539
2540
2541 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2542 {
2543         return wpa_ctrl_command(ctrl, "FLUSH");
2544 }
2545
2546
2547 static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2548 {
2549         return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2550 }
2551
2552
2553 static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2554                                             char *argv[])
2555 {
2556         return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2557 }
2558
2559
2560 static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2561 {
2562         return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2563 }
2564
2565
2566 static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2567                                      char *argv[])
2568 {
2569         return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2570 }
2571
2572
2573 enum wpa_cli_cmd_flags {
2574         cli_cmd_flag_none               = 0x00,
2575         cli_cmd_flag_sensitive          = 0x01
2576 };
2577
2578 struct wpa_cli_cmd {
2579         const char *cmd;
2580         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2581         char ** (*completion)(const char *str, int pos);
2582         enum wpa_cli_cmd_flags flags;
2583         const char *usage;
2584 };
2585
2586 static struct wpa_cli_cmd wpa_cli_commands[] = {
2587         { "status", wpa_cli_cmd_status, NULL,
2588           cli_cmd_flag_none,
2589           "[verbose] = get current WPA/EAPOL/EAP status" },
2590         { "ifname", wpa_cli_cmd_ifname, NULL,
2591           cli_cmd_flag_none,
2592           "= get current interface name" },
2593         { "ping", wpa_cli_cmd_ping, NULL,
2594           cli_cmd_flag_none,
2595           "= pings wpa_supplicant" },
2596         { "relog", wpa_cli_cmd_relog, NULL,
2597           cli_cmd_flag_none,
2598           "= re-open log-file (allow rolling logs)" },
2599         { "note", wpa_cli_cmd_note, NULL,
2600           cli_cmd_flag_none,
2601           "<text> = add a note to wpa_supplicant debug log" },
2602         { "mib", wpa_cli_cmd_mib, NULL,
2603           cli_cmd_flag_none,
2604           "= get MIB variables (dot1x, dot11)" },
2605         { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2606           cli_cmd_flag_none,
2607           "[command] = show usage help" },
2608         { "interface", wpa_cli_cmd_interface, NULL,
2609           cli_cmd_flag_none,
2610           "[ifname] = show interfaces/select interface" },
2611         { "level", wpa_cli_cmd_level, NULL,
2612           cli_cmd_flag_none,
2613           "<debug level> = change debug level" },
2614         { "license", wpa_cli_cmd_license, NULL,
2615           cli_cmd_flag_none,
2616           "= show full wpa_cli license" },
2617         { "quit", wpa_cli_cmd_quit, NULL,
2618           cli_cmd_flag_none,
2619           "= exit wpa_cli" },
2620         { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2621           cli_cmd_flag_none,
2622           "= set variables (shows list of variables when run without "
2623           "arguments)" },
2624         { "dump", wpa_cli_cmd_dump, NULL,
2625           cli_cmd_flag_none,
2626           "= dump config variables" },
2627         { "get", wpa_cli_cmd_get, NULL,
2628           cli_cmd_flag_none,
2629           "<name> = get information" },
2630         { "logon", wpa_cli_cmd_logon, NULL,
2631           cli_cmd_flag_none,
2632           "= IEEE 802.1X EAPOL state machine logon" },
2633         { "logoff", wpa_cli_cmd_logoff, NULL,
2634           cli_cmd_flag_none,
2635           "= IEEE 802.1X EAPOL state machine logoff" },
2636         { "pmksa", wpa_cli_cmd_pmksa, NULL,
2637           cli_cmd_flag_none,
2638           "= show PMKSA cache" },
2639         { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2640           cli_cmd_flag_none,
2641           "= flush PMKSA cache entries" },
2642         { "reassociate", wpa_cli_cmd_reassociate, NULL,
2643           cli_cmd_flag_none,
2644           "= force reassociation" },
2645         { "reattach", wpa_cli_cmd_reattach, NULL,
2646           cli_cmd_flag_none,
2647           "= force reassociation back to the same BSS" },
2648         { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2649           cli_cmd_flag_none,
2650           "<BSSID> = force preauthentication" },
2651         { "identity", wpa_cli_cmd_identity, NULL,
2652           cli_cmd_flag_none,
2653           "<network id> <identity> = configure identity for an SSID" },
2654         { "password", wpa_cli_cmd_password, NULL,
2655           cli_cmd_flag_sensitive,
2656           "<network id> <password> = configure password for an SSID" },
2657         { "new_password", wpa_cli_cmd_new_password, NULL,
2658           cli_cmd_flag_sensitive,
2659           "<network id> <password> = change password for an SSID" },
2660         { "pin", wpa_cli_cmd_pin, NULL,
2661           cli_cmd_flag_sensitive,
2662           "<network id> <pin> = configure pin for an SSID" },
2663         { "otp", wpa_cli_cmd_otp, NULL,
2664           cli_cmd_flag_sensitive,
2665           "<network id> <password> = configure one-time-password for an SSID"
2666         },
2667         { "passphrase", wpa_cli_cmd_passphrase, NULL,
2668           cli_cmd_flag_sensitive,
2669           "<network id> <passphrase> = configure private key passphrase\n"
2670           "  for an SSID" },
2671         { "sim", wpa_cli_cmd_sim, NULL,
2672           cli_cmd_flag_sensitive,
2673           "<network id> <pin> = report SIM operation result" },
2674         { "bssid", wpa_cli_cmd_bssid, NULL,
2675           cli_cmd_flag_none,
2676           "<network id> <BSSID> = set preferred BSSID for an SSID" },
2677         { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2678           cli_cmd_flag_none,
2679           "<BSSID> = add a BSSID to the blacklist\n"
2680           "blacklist clear = clear the blacklist\n"
2681           "blacklist = display the blacklist" },
2682         { "log_level", wpa_cli_cmd_log_level, NULL,
2683           cli_cmd_flag_none,
2684           "<level> [<timestamp>] = update the log level/timestamp\n"
2685           "log_level = display the current log level and log options" },
2686         { "list_networks", wpa_cli_cmd_list_networks, NULL,
2687           cli_cmd_flag_none,
2688           "= list configured networks" },
2689         { "select_network", wpa_cli_cmd_select_network, NULL,
2690           cli_cmd_flag_none,
2691           "<network id> = select a network (disable others)" },
2692         { "enable_network", wpa_cli_cmd_enable_network, NULL,
2693           cli_cmd_flag_none,
2694           "<network id> = enable a network" },
2695         { "disable_network", wpa_cli_cmd_disable_network, NULL,
2696           cli_cmd_flag_none,
2697           "<network id> = disable a network" },
2698         { "add_network", wpa_cli_cmd_add_network, NULL,
2699           cli_cmd_flag_none,
2700           "= add a network" },
2701         { "remove_network", wpa_cli_cmd_remove_network, NULL,
2702           cli_cmd_flag_none,
2703           "<network id> = remove a network" },
2704         { "set_network", wpa_cli_cmd_set_network, NULL,
2705           cli_cmd_flag_sensitive,
2706           "<network id> <variable> <value> = set network variables (shows\n"
2707           "  list of variables when run without arguments)" },
2708         { "get_network", wpa_cli_cmd_get_network, NULL,
2709           cli_cmd_flag_none,
2710           "<network id> <variable> = get network variables" },
2711         { "dup_network", wpa_cli_cmd_dup_network, NULL,
2712           cli_cmd_flag_none,
2713           "<src network id> <dst network id> <variable> = duplicate network variables"
2714         },
2715         { "list_creds", wpa_cli_cmd_list_creds, NULL,
2716           cli_cmd_flag_none,
2717           "= list configured credentials" },
2718         { "add_cred", wpa_cli_cmd_add_cred, NULL,
2719           cli_cmd_flag_none,
2720           "= add a credential" },
2721         { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2722           cli_cmd_flag_none,
2723           "<cred id> = remove a credential" },
2724         { "set_cred", wpa_cli_cmd_set_cred, NULL,
2725           cli_cmd_flag_sensitive,
2726           "<cred id> <variable> <value> = set credential variables" },
2727         { "get_cred", wpa_cli_cmd_get_cred, NULL,
2728           cli_cmd_flag_none,
2729           "<cred id> <variable> = get credential variables" },
2730         { "save_config", wpa_cli_cmd_save_config, NULL,
2731           cli_cmd_flag_none,
2732           "= save the current configuration" },
2733         { "disconnect", wpa_cli_cmd_disconnect, NULL,
2734           cli_cmd_flag_none,
2735           "= disconnect and wait for reassociate/reconnect command before\n"
2736           "  connecting" },
2737         { "reconnect", wpa_cli_cmd_reconnect, NULL,
2738           cli_cmd_flag_none,
2739           "= like reassociate, but only takes effect if already disconnected"
2740         },
2741         { "scan", wpa_cli_cmd_scan, NULL,
2742           cli_cmd_flag_none,
2743           "= request new BSS scan" },
2744         { "scan_results", wpa_cli_cmd_scan_results, NULL,
2745           cli_cmd_flag_none,
2746           "= get latest scan results" },
2747         { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2748           cli_cmd_flag_none,
2749           "<<idx> | <bssid>> = get detailed scan result info" },
2750         { "get_capability", wpa_cli_cmd_get_capability, NULL,
2751           cli_cmd_flag_none,
2752           "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2753           "= get capabilies" },
2754         { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2755           cli_cmd_flag_none,
2756           "= force wpa_supplicant to re-read its configuration file" },
2757         { "terminate", wpa_cli_cmd_terminate, NULL,
2758           cli_cmd_flag_none,
2759           "= terminate wpa_supplicant" },
2760         { "interface_add", wpa_cli_cmd_interface_add, NULL,
2761           cli_cmd_flag_none,
2762           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2763           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2764           "  are optional" },
2765         { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2766           cli_cmd_flag_none,
2767           "<ifname> = removes the interface" },
2768         { "interface_list", wpa_cli_cmd_interface_list, NULL,
2769           cli_cmd_flag_none,
2770           "= list available interfaces" },
2771         { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2772           cli_cmd_flag_none,
2773           "<value> = set ap_scan parameter" },
2774         { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2775           cli_cmd_flag_none,
2776           "<value> = set scan_interval parameter (in seconds)" },
2777         { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2778           cli_cmd_flag_none,
2779           "<value> = set BSS expiration age parameter" },
2780         { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2781           cli_cmd_flag_none,
2782           "<value> = set BSS expiration scan count parameter" },
2783         { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2784           cli_cmd_flag_none,
2785           "<value> = set BSS flush age (0 by default)" },
2786         { "stkstart", wpa_cli_cmd_stkstart, NULL,
2787           cli_cmd_flag_none,
2788           "<addr> = request STK negotiation with <addr>" },
2789         { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2790           cli_cmd_flag_none,
2791           "<addr> = request over-the-DS FT with <addr>" },
2792         { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2793           cli_cmd_flag_none,
2794           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2795         { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2796           cli_cmd_flag_sensitive,
2797           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2798           "hardcoded)" },
2799         { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2800           cli_cmd_flag_sensitive,
2801           "<PIN> = verify PIN checksum" },
2802         { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2803           "Cancels the pending WPS operation" },
2804 #ifdef CONFIG_WPS_NFC
2805         { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2806           cli_cmd_flag_none,
2807           "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2808         { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2809           cli_cmd_flag_none,
2810           "<WPS|NDEF> = build configuration token" },
2811         { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2812           cli_cmd_flag_none,
2813           "<WPS|NDEF> = create password token" },
2814         { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2815           cli_cmd_flag_sensitive,
2816           "<hexdump of payload> = report read NFC tag with WPS data" },
2817         { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2818           cli_cmd_flag_none,
2819           "<NDEF> <WPS> = create NFC handover request" },
2820         { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2821           cli_cmd_flag_none,
2822           "<NDEF> <WPS> = create NFC handover select" },
2823         { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2824           cli_cmd_flag_none,
2825           "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2826           "NFC handover" },
2827 #endif /* CONFIG_WPS_NFC */
2828         { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2829           cli_cmd_flag_sensitive,
2830           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2831         { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2832           cli_cmd_flag_sensitive,
2833           "[params..] = enable/disable AP PIN" },
2834         { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2835           cli_cmd_flag_none,
2836           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2837         { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2838           cli_cmd_flag_none,
2839           "= stop Wi-Fi Protected Setup External Registrar" },
2840         { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2841           cli_cmd_flag_sensitive,
2842           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2843         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2844           cli_cmd_flag_none,
2845           "<UUID> = accept an Enrollee PBC using External Registrar" },
2846         { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2847           cli_cmd_flag_sensitive,
2848           "<UUID> <PIN> = learn AP configuration" },
2849         { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2850           cli_cmd_flag_none,
2851           "<UUID> <network id> = set AP configuration for enrolling" },
2852         { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2853           cli_cmd_flag_sensitive,
2854           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2855 #ifdef CONFIG_WPS_NFC
2856         { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2857           cli_cmd_flag_none,
2858           "<WPS/NDEF> <UUID> = build NFC configuration token" },
2859 #endif /* CONFIG_WPS_NFC */
2860         { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2861           cli_cmd_flag_none,
2862           "<addr> = request RSN authentication with <addr> in IBSS" },
2863 #ifdef CONFIG_AP
2864         { "sta", wpa_cli_cmd_sta, NULL,
2865           cli_cmd_flag_none,
2866           "<addr> = get information about an associated station (AP)" },
2867         { "all_sta", wpa_cli_cmd_all_sta, NULL,
2868           cli_cmd_flag_none,
2869           "= get information about all associated stations (AP)" },
2870         { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2871           cli_cmd_flag_none,
2872           "<addr> = deauthenticate a station" },
2873         { "disassociate", wpa_cli_cmd_disassociate, NULL,
2874           cli_cmd_flag_none,
2875           "<addr> = disassociate a station" },
2876         { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2877           cli_cmd_flag_none,
2878           "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2879           " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2880           " = CSA parameters" },
2881 #endif /* CONFIG_AP */
2882         { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2883           "= notification of suspend/hibernate" },
2884         { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2885           "= notification of resume/thaw" },
2886 #ifdef CONFIG_TESTING_OPTIONS
2887         { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2888           "= drop SA without deauth/disassoc (test command)" },
2889 #endif /* CONFIG_TESTING_OPTIONS */
2890         { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2891           cli_cmd_flag_none,
2892           "<addr> = roam to the specified BSS" },
2893 #ifdef CONFIG_MESH
2894         { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
2895           cli_cmd_flag_none,
2896           "[ifname] = Create a new mesh interface" },
2897         { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
2898           cli_cmd_flag_none,
2899           "<network id> = join a mesh network (disable others)" },
2900         { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
2901           cli_cmd_flag_none,
2902           "<ifname> = Remove mesh group interface" },
2903 #endif /* CONFIG_MESH */
2904 #ifdef CONFIG_P2P
2905         { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2906           cli_cmd_flag_none,
2907           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2908         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2909           "= stop P2P Devices search" },
2910         { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
2911           cli_cmd_flag_none,
2912           "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
2913         { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
2914           cli_cmd_flag_none,
2915           "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
2916         { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2917           cli_cmd_flag_none,
2918           "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2919         { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2920           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2921         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2922           wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2923           "<ifname> = remove P2P group interface (terminate group if GO)" },
2924         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2925           "[ht40] = add a new P2P group (local end as GO)" },
2926         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2927           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2928           "<addr> <method> = request provisioning discovery" },
2929         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2930           cli_cmd_flag_none,
2931           "= get the passphrase for a group (GO only)" },
2932         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2933           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2934           "<addr> <TLVs> = schedule service discovery request" },
2935         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2936           NULL, cli_cmd_flag_none,
2937           "<id> = cancel pending service discovery request" },
2938         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2939           cli_cmd_flag_none,
2940           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2941         { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2942           cli_cmd_flag_none,
2943           "= indicate change in local services" },
2944         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2945           cli_cmd_flag_none,
2946           "<external> = set external processing of service discovery" },
2947         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2948           cli_cmd_flag_none,
2949           "= remove all stored service entries" },
2950         { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2951           cli_cmd_flag_none,
2952           "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
2953           "service" },
2954         { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
2955           cli_cmd_flag_none,
2956           "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
2957           "local ASP service" },
2958         { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2959           cli_cmd_flag_none,
2960           "<bonjour|upnp> <query|version> [|service] = remove a local "
2961           "service" },
2962         { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2963           cli_cmd_flag_none,
2964           "<addr> = reject connection attempts from a specific peer" },
2965         { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2966           cli_cmd_flag_none,
2967           "<cmd> [peer=addr] = invite peer" },
2968         { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2969           "[discovered] = list known (optionally, only fully discovered) P2P "
2970           "peers" },
2971         { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2972           cli_cmd_flag_none,
2973           "<address> = show information about known P2P peer" },
2974         { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2975           cli_cmd_flag_none,
2976           "<field> <value> = set a P2P parameter" },
2977         { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2978           "= flush P2P state" },
2979         { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2980           "= cancel P2P group formation" },
2981         { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2982           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2983           "<address> = unauthorize a peer" },
2984         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2985           cli_cmd_flag_none,
2986           "[<duration> <interval>] [<duration> <interval>] = request GO "
2987           "presence" },
2988         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2989           cli_cmd_flag_none,
2990           "[<period> <interval>] = set extended listen timing" },
2991         { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2992           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2993           "<address|iface=address> = remove a peer from all groups" },
2994 #endif /* CONFIG_P2P */
2995 #ifdef CONFIG_WIFI_DISPLAY
2996         { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2997           cli_cmd_flag_none,
2998           "<subelem> [contents] = set Wi-Fi Display subelement" },
2999         { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3000           cli_cmd_flag_none,
3001           "<subelem> = get Wi-Fi Display subelement" },
3002 #endif /* CONFIG_WIFI_DISPLAY */
3003 #ifdef CONFIG_INTERWORKING
3004         { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
3005           "= fetch ANQP information for all APs" },
3006         { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3007           cli_cmd_flag_none,
3008           "= stop fetch_anqp operation" },
3009         { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
3010           cli_cmd_flag_none,
3011           "[auto] = perform Interworking network selection" },
3012         { "interworking_connect", wpa_cli_cmd_interworking_connect,
3013           wpa_cli_complete_bss, cli_cmd_flag_none,
3014           "<BSSID> = connect using Interworking credentials" },
3015         { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3016           wpa_cli_complete_bss, cli_cmd_flag_none,
3017           "<BSSID> = connect using Interworking credentials" },
3018         { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3019           cli_cmd_flag_none,
3020           "<addr> <info id>[,<info id>]... = request ANQP information" },
3021         { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3022           cli_cmd_flag_none,
3023           "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3024         { "gas_response_get", wpa_cli_cmd_gas_response_get,
3025           wpa_cli_complete_bss, cli_cmd_flag_none,
3026           "<addr> <dialog token> [start,len] = Fetch last GAS response" },
3027 #endif /* CONFIG_INTERWORKING */
3028 #ifdef CONFIG_HS20
3029         { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3030           cli_cmd_flag_none,
3031           "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3032         },
3033         { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3034           wpa_cli_complete_bss, cli_cmd_flag_none,
3035           "<addr> <home realm> = get HS20 nai home realm list" },
3036         { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3037           wpa_cli_complete_bss, cli_cmd_flag_none,
3038           "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3039         { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3040           "= fetch OSU provider information from all APs" },
3041         { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3042           cli_cmd_flag_none,
3043           "= cancel fetch_osu command" },
3044 #endif /* CONFIG_HS20 */
3045         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3046           cli_cmd_flag_none,
3047           "<0/1> = disable/enable automatic reconnection" },
3048         { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
3049           cli_cmd_flag_none,
3050           "<addr> = request TDLS discovery with <addr>" },
3051         { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
3052           cli_cmd_flag_none,
3053           "<addr> = request TDLS setup with <addr>" },
3054         { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
3055           cli_cmd_flag_none,
3056           "<addr> = tear down TDLS with <addr>" },
3057         { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3058           cli_cmd_flag_none,
3059           "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3060           "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3061           "= add WMM-AC traffic stream" },
3062         { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3063           cli_cmd_flag_none,
3064           "<tsid> = delete WMM-AC traffic stream" },
3065         { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3066           cli_cmd_flag_none,
3067           "= show status for Wireless Multi-Media Admission-Control" },
3068         { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3069           cli_cmd_flag_none,
3070           "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3071           "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3072           "with TDLS peer" },
3073         { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3074           cli_cmd_flag_none,
3075           "<addr> = disable channel switching with TDLS peer <addr>" },
3076         { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
3077           cli_cmd_flag_none,
3078           "= get signal parameters" },
3079         { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3080           cli_cmd_flag_none,
3081           "= get TX/RX packet counters" },
3082         { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3083           cli_cmd_flag_none,
3084           "= trigger IEEE 802.1X/EAPOL reauthentication" },
3085 #ifdef CONFIG_AUTOSCAN
3086         { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3087           "[params] = Set or unset (if none) autoscan parameters" },
3088 #endif /* CONFIG_AUTOSCAN */
3089 #ifdef CONFIG_WNM
3090         { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3091           "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3092         { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3093           "<query reason> = Send BSS Transition Management Query" },
3094 #endif /* CONFIG_WNM */
3095         { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3096           "<params..> = Sent unprocessed command" },
3097         { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3098           "= flush wpa_supplicant state" },
3099 #ifdef ANDROID
3100         { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3101           "<command> = driver private commands" },
3102 #endif /* ANDROID */
3103         { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3104           "= radio_work <show/add/done>" },
3105         { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3106           "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3107         },
3108         { "neighbor_rep_request",
3109           wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3110           "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3111           "(with optional given SSID, default: current SSID)"
3112         },
3113         { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3114           "= flush ERP keys" },
3115         { "mac_rand_scan",
3116           wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3117           "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3118           "mask=mac-address-mask] = scan MAC randomization"
3119         },
3120         { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
3121 };
3122
3123
3124 /*
3125  * Prints command usage, lines are padded with the specified string.
3126  */
3127 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
3128 {
3129         char c;
3130         size_t n;
3131
3132         printf("%s%s ", pad, cmd->cmd);
3133         for (n = 0; (c = cmd->usage[n]); n++) {
3134                 printf("%c", c);
3135                 if (c == '\n')
3136                         printf("%s", pad);
3137         }
3138         printf("\n");
3139 }
3140
3141
3142 static void print_help(const char *cmd)
3143 {
3144         int n;
3145         printf("commands:\n");
3146         for (n = 0; wpa_cli_commands[n].cmd; n++) {
3147                 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3148                         print_cmd_help(&wpa_cli_commands[n], "  ");
3149         }
3150 }
3151
3152
3153 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3154 {
3155         const char *c, *delim;
3156         int n;
3157         size_t len;
3158
3159         delim = os_strchr(cmd, ' ');
3160         if (delim)
3161                 len = delim - cmd;
3162         else
3163                 len = os_strlen(cmd);
3164
3165         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3166                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3167                         return (wpa_cli_commands[n].flags &
3168                                 cli_cmd_flag_sensitive);
3169         }
3170         return 0;
3171 }
3172
3173
3174 static char ** wpa_list_cmd_list(void)
3175 {
3176         char **res;
3177         int i, count;
3178         struct cli_txt_entry *e;
3179
3180         count = ARRAY_SIZE(wpa_cli_commands);
3181         count += dl_list_len(&p2p_groups);
3182         count += dl_list_len(&ifnames);
3183         res = os_calloc(count + 1, sizeof(char *));
3184         if (res == NULL)
3185                 return NULL;
3186
3187         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3188                 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3189                 if (res[i] == NULL)
3190                         break;
3191         }
3192
3193         dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3194                 size_t len = 8 + os_strlen(e->txt);
3195                 res[i] = os_malloc(len);
3196                 if (res[i] == NULL)
3197                         break;
3198                 os_snprintf(res[i], len, "ifname=%s", e->txt);
3199                 i++;
3200         }
3201
3202         dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3203                 res[i] = os_strdup(e->txt);
3204                 if (res[i] == NULL)
3205                         break;
3206                 i++;
3207         }
3208
3209         return res;
3210 }
3211
3212
3213 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3214                                       int pos)
3215 {
3216         int i;
3217
3218         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3219                 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3220                         if (wpa_cli_commands[i].completion)
3221                                 return wpa_cli_commands[i].completion(str,
3222                                                                       pos);
3223                         edit_clear_line();
3224                         printf("\r%s\n", wpa_cli_commands[i].usage);
3225                         edit_redraw();
3226                         break;
3227                 }
3228         }
3229
3230         return NULL;
3231 }
3232
3233
3234 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3235 {
3236         char **res;
3237         const char *end;
3238         char *cmd;
3239
3240         if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3241                 end = os_strchr(str, ' ');
3242                 if (end && pos > end - str) {
3243                         pos -= end - str + 1;
3244                         str = end + 1;
3245                 }
3246         }
3247
3248         end = os_strchr(str, ' ');
3249         if (end == NULL || str + pos < end)
3250                 return wpa_list_cmd_list();
3251
3252         cmd = os_malloc(pos + 1);
3253         if (cmd == NULL)
3254                 return NULL;
3255         os_memcpy(cmd, str, pos);
3256         cmd[end - str] = '\0';
3257         res = wpa_cli_cmd_completion(cmd, str, pos);
3258         os_free(cmd);
3259         return res;
3260 }
3261
3262
3263 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3264 {
3265         struct wpa_cli_cmd *cmd, *match = NULL;
3266         int count;
3267         int ret = 0;
3268
3269         if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3270                 ifname_prefix = argv[0] + 7;
3271                 argv = &argv[1];
3272                 argc--;
3273         } else
3274                 ifname_prefix = NULL;
3275
3276         if (argc == 0)
3277                 return -1;
3278
3279         count = 0;
3280         cmd = wpa_cli_commands;
3281         while (cmd->cmd) {
3282                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3283                 {
3284                         match = cmd;
3285                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3286                                 /* we have an exact match */
3287                                 count = 1;
3288                                 break;
3289                         }
3290                         count++;
3291                 }
3292                 cmd++;
3293         }
3294
3295         if (count > 1) {
3296                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3297                 cmd = wpa_cli_commands;
3298                 while (cmd->cmd) {
3299                         if (os_strncasecmp(cmd->cmd, argv[0],
3300                                            os_strlen(argv[0])) == 0) {
3301                                 printf(" %s", cmd->cmd);
3302                         }
3303                         cmd++;
3304                 }
3305                 printf("\n");
3306                 ret = 1;
3307         } else if (count == 0) {
3308                 printf("Unknown command '%s'\n", argv[0]);
3309                 ret = 1;
3310         } else {
3311                 ret = match->handler(ctrl, argc - 1, &argv[1]);
3312         }
3313
3314         return ret;
3315 }
3316
3317
3318 static int str_match(const char *a, const char *b)
3319 {
3320         return os_strncmp(a, b, os_strlen(b)) == 0;
3321 }
3322
3323
3324 static int wpa_cli_exec(const char *program, const char *arg1,
3325                         const char *arg2)
3326 {
3327         char *arg;
3328         size_t len;
3329         int res;
3330
3331         len = os_strlen(arg1) + os_strlen(arg2) + 2;
3332         arg = os_malloc(len);
3333         if (arg == NULL)
3334                 return -1;
3335         os_snprintf(arg, len, "%s %s", arg1, arg2);
3336         res = os_exec(program, arg, 1);
3337         os_free(arg);
3338
3339         return res;
3340 }
3341
3342
3343 static void wpa_cli_action_process(const char *msg)
3344 {
3345         const char *pos;
3346         char *copy = NULL, *id, *pos2;
3347         const char *ifname = ctrl_ifname;
3348         char ifname_buf[100];
3349
3350         pos = msg;
3351         if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3352                 const char *end;
3353                 end = os_strchr(pos + 7, ' ');
3354                 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3355                         pos += 7;
3356                         os_memcpy(ifname_buf, pos, end - pos);
3357                         ifname_buf[end - pos] = '\0';
3358                         ifname = ifname_buf;
3359                         pos = end + 1;
3360                 }
3361         }
3362         if (*pos == '<') {
3363                 const char *prev = pos;
3364                 /* skip priority */
3365                 pos = os_strchr(pos, '>');
3366                 if (pos)
3367                         pos++;
3368                 else
3369                         pos = prev;
3370         }
3371
3372         if (str_match(pos, WPA_EVENT_CONNECTED)) {
3373                 int new_id = -1;
3374                 os_unsetenv("WPA_ID");
3375                 os_unsetenv("WPA_ID_STR");
3376                 os_unsetenv("WPA_CTRL_DIR");
3377
3378                 pos = os_strstr(pos, "[id=");
3379                 if (pos)
3380                         copy = os_strdup(pos + 4);
3381
3382                 if (copy) {
3383                         pos2 = id = copy;
3384                         while (*pos2 && *pos2 != ' ')
3385                                 pos2++;
3386                         *pos2++ = '\0';
3387                         new_id = atoi(id);
3388                         os_setenv("WPA_ID", id, 1);
3389                         while (*pos2 && *pos2 != '=')
3390                                 pos2++;
3391                         if (*pos2 == '=')
3392                                 pos2++;
3393                         id = pos2;
3394                         while (*pos2 && *pos2 != ']')
3395                                 pos2++;
3396                         *pos2 = '\0';
3397                         os_setenv("WPA_ID_STR", id, 1);
3398                         os_free(copy);
3399                 }
3400
3401                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3402
3403                 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3404                         wpa_cli_connected = 1;
3405                         wpa_cli_last_id = new_id;
3406                         wpa_cli_exec(action_file, ifname, "CONNECTED");
3407                 }
3408         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3409                 if (wpa_cli_connected) {
3410                         wpa_cli_connected = 0;
3411                         wpa_cli_exec(action_file, ifname, "DISCONNECTED");
3412                 }
3413         } else if (str_match(pos, MESH_GROUP_STARTED)) {
3414                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3415         } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3416                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3417         } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3418                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3419         } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3420                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3421         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3422                 wpa_cli_exec(action_file, ifname, pos);
3423         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3424                 wpa_cli_exec(action_file, ifname, pos);
3425         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3426                 wpa_cli_exec(action_file, ifname, pos);
3427         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3428                 wpa_cli_exec(action_file, ifname, pos);
3429         } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3430                 wpa_cli_exec(action_file, ifname, pos);
3431         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3432                 wpa_cli_exec(action_file, ifname, pos);
3433         } else if (str_match(pos, WPS_EVENT_FAIL)) {
3434                 wpa_cli_exec(action_file, ifname, pos);
3435         } else if (str_match(pos, AP_STA_CONNECTED)) {
3436                 wpa_cli_exec(action_file, ifname, pos);
3437         } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3438                 wpa_cli_exec(action_file, ifname, pos);
3439         } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3440                 wpa_cli_exec(action_file, ifname, pos);
3441         } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3442                 wpa_cli_exec(action_file, ifname, pos);
3443         } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3444                 wpa_cli_exec(action_file, ifname, pos);
3445         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3446                 printf("wpa_supplicant is terminating - stop monitoring\n");
3447                 wpa_cli_quit = 1;
3448         }
3449 }
3450
3451
3452 #ifndef CONFIG_ANSI_C_EXTRA
3453 static void wpa_cli_action_cb(char *msg, size_t len)
3454 {
3455         wpa_cli_action_process(msg);
3456 }
3457 #endif /* CONFIG_ANSI_C_EXTRA */
3458
3459
3460 static void wpa_cli_reconnect(void)
3461 {
3462         wpa_cli_close_connection();
3463         if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3464                 return;
3465
3466         if (interactive) {
3467                 edit_clear_line();
3468                 printf("\rConnection to wpa_supplicant re-established\n");
3469                 edit_redraw();
3470         }
3471 }
3472
3473
3474 static void cli_event(const char *str)
3475 {
3476         const char *start, *s;
3477
3478         start = os_strchr(str, '>');
3479         if (start == NULL)
3480                 return;
3481
3482         start++;
3483
3484         if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3485                 s = os_strchr(start, ' ');
3486                 if (s == NULL)
3487                         return;
3488                 s = os_strchr(s + 1, ' ');
3489                 if (s == NULL)
3490                         return;
3491                 cli_txt_list_add(&bsses, s + 1);
3492                 return;
3493         }
3494
3495         if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3496                 s = os_strchr(start, ' ');
3497                 if (s == NULL)
3498                         return;
3499                 s = os_strchr(s + 1, ' ');
3500                 if (s == NULL)
3501                         return;
3502                 cli_txt_list_del_addr(&bsses, s + 1);
3503                 return;
3504         }
3505
3506 #ifdef CONFIG_P2P
3507         if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3508                 s = os_strstr(start, " p2p_dev_addr=");
3509                 if (s == NULL)
3510                         return;
3511                 cli_txt_list_add_addr(&p2p_peers, s + 14);
3512                 return;
3513         }
3514
3515         if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3516                 s = os_strstr(start, " p2p_dev_addr=");
3517                 if (s == NULL)
3518                         return;
3519                 cli_txt_list_del_addr(&p2p_peers, s + 14);
3520                 return;
3521         }
3522
3523         if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3524                 s = os_strchr(start, ' ');
3525                 if (s == NULL)
3526                         return;
3527                 cli_txt_list_add_word(&p2p_groups, s + 1);
3528                 return;
3529         }
3530
3531         if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3532                 s = os_strchr(start, ' ');
3533                 if (s == NULL)
3534                         return;
3535                 cli_txt_list_del_word(&p2p_groups, s + 1);
3536                 return;
3537         }
3538 #endif /* CONFIG_P2P */
3539 }
3540
3541
3542 static int check_terminating(const char *msg)
3543 {
3544         const char *pos = msg;
3545
3546         if (*pos == '<') {
3547                 /* skip priority */
3548                 pos = os_strchr(pos, '>');
3549                 if (pos)
3550                         pos++;
3551                 else
3552                         pos = msg;
3553         }
3554
3555         if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3556                 edit_clear_line();
3557                 printf("\rConnection to wpa_supplicant lost - trying to "
3558                        "reconnect\n");
3559                 edit_redraw();
3560                 wpa_cli_attached = 0;
3561                 wpa_cli_close_connection();
3562                 return 1;
3563         }
3564
3565         return 0;
3566 }
3567
3568
3569 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3570 {
3571         if (ctrl_conn == NULL) {
3572                 wpa_cli_reconnect();
3573                 return;
3574         }
3575         while (wpa_ctrl_pending(ctrl) > 0) {
3576                 char buf[4096];
3577                 size_t len = sizeof(buf) - 1;
3578                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3579                         buf[len] = '\0';
3580                         if (action_monitor)
3581                                 wpa_cli_action_process(buf);
3582                         else {
3583                                 cli_event(buf);
3584                                 if (wpa_cli_show_event(buf)) {
3585                                         edit_clear_line();
3586                                         printf("\r%s\n", buf);
3587                                         edit_redraw();
3588                                 }
3589
3590                                 if (interactive && check_terminating(buf) > 0)
3591                                         return;
3592                         }
3593                 } else {
3594                         printf("Could not read pending message.\n");
3595                         break;
3596                 }
3597         }
3598
3599         if (wpa_ctrl_pending(ctrl) < 0) {
3600                 printf("Connection to wpa_supplicant lost - trying to "
3601                        "reconnect\n");
3602                 wpa_cli_reconnect();
3603         }
3604 }
3605
3606 #define max_args 10
3607
3608 static int tokenize_cmd(char *cmd, char *argv[])
3609 {
3610         char *pos;
3611         int argc = 0;
3612
3613         pos = cmd;
3614         for (;;) {
3615                 while (*pos == ' ')
3616                         pos++;
3617                 if (*pos == '\0')
3618                         break;
3619                 argv[argc] = pos;
3620                 argc++;
3621                 if (argc == max_args)
3622                         break;
3623                 if (*pos == '"') {
3624                         char *pos2 = os_strrchr(pos, '"');
3625                         if (pos2)
3626                                 pos = pos2 + 1;
3627                 }
3628                 while (*pos != '\0' && *pos != ' ')
3629                         pos++;
3630                 if (*pos == ' ')
3631                         *pos++ = '\0';
3632         }
3633
3634         return argc;
3635 }
3636
3637
3638 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3639 {
3640         if (ctrl_conn) {
3641                 int res;
3642                 char *prefix = ifname_prefix;
3643
3644                 ifname_prefix = NULL;
3645                 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3646                 ifname_prefix = prefix;
3647                 if (res) {
3648                         printf("Connection to wpa_supplicant lost - trying to "
3649                                "reconnect\n");
3650                         wpa_cli_close_connection();
3651                 }
3652         }
3653         if (!ctrl_conn)
3654                 wpa_cli_reconnect();
3655         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3656 }
3657
3658
3659 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3660 {
3661         wpa_cli_recv_pending(mon_conn, 0);
3662 }
3663
3664
3665 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3666 {
3667         char *argv[max_args];
3668         int argc;
3669         argc = tokenize_cmd(cmd, argv);
3670         if (argc)
3671                 wpa_request(ctrl_conn, argc, argv);
3672 }
3673
3674
3675 static void wpa_cli_edit_eof_cb(void *ctx)
3676 {
3677         eloop_terminate();
3678 }
3679
3680
3681 static int warning_displayed = 0;
3682 static char *hfile = NULL;
3683 static int edit_started = 0;
3684
3685 static void start_edit(void)
3686 {
3687         char *home;
3688         char *ps = NULL;
3689
3690 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3691         ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3692 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3693
3694         home = getenv("HOME");
3695         if (home) {
3696                 const char *fname = ".wpa_cli_history";
3697                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3698                 hfile = os_malloc(hfile_len);
3699                 if (hfile)
3700                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3701         }
3702
3703         if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3704                       wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3705                 eloop_terminate();
3706                 return;
3707         }
3708
3709         edit_started = 1;
3710         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3711 }
3712
3713
3714 static void update_bssid_list(struct wpa_ctrl *ctrl)
3715 {
3716         char buf[4096];
3717         size_t len = sizeof(buf);
3718         int ret;
3719         char *cmd = "BSS RANGE=ALL MASK=0x2";
3720         char *pos, *end;
3721
3722         if (ctrl == NULL)
3723                 return;
3724         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3725         if (ret < 0)
3726                 return;
3727         buf[len] = '\0';
3728
3729         pos = buf;
3730         while (pos) {
3731                 pos = os_strstr(pos, "bssid=");
3732                 if (pos == NULL)
3733                         break;
3734                 pos += 6;
3735                 end = os_strchr(pos, '\n');
3736                 if (end == NULL)
3737                         break;
3738                 *end = '\0';
3739                 cli_txt_list_add(&bsses, pos);
3740                 pos = end + 1;
3741         }
3742 }
3743
3744
3745 static void update_ifnames(struct wpa_ctrl *ctrl)
3746 {
3747         char buf[4096];
3748         size_t len = sizeof(buf);
3749         int ret;
3750         char *cmd = "INTERFACES";
3751         char *pos, *end;
3752         char txt[200];
3753
3754         cli_txt_list_flush(&ifnames);
3755
3756         if (ctrl == NULL)
3757                 return;
3758         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3759         if (ret < 0)
3760                 return;
3761         buf[len] = '\0';
3762
3763         pos = buf;
3764         while (pos) {
3765                 end = os_strchr(pos, '\n');
3766                 if (end == NULL)
3767                         break;
3768                 *end = '\0';
3769                 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3770                 if (!os_snprintf_error(sizeof(txt), ret))
3771                         cli_txt_list_add(&ifnames, txt);
3772                 pos = end + 1;
3773         }
3774 }
3775
3776
3777 static void try_connection(void *eloop_ctx, void *timeout_ctx)
3778 {
3779         if (ctrl_conn)
3780                 goto done;
3781
3782         if (ctrl_ifname == NULL)
3783                 ctrl_ifname = wpa_cli_get_default_ifname();
3784
3785         if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3786                 if (!warning_displayed) {
3787                         printf("Could not connect to wpa_supplicant: "
3788                                "%s - re-trying\n",
3789                                ctrl_ifname ? ctrl_ifname : "(nil)");
3790                         warning_displayed = 1;
3791                 }
3792                 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3793                 return;
3794         }
3795
3796         update_bssid_list(ctrl_conn);
3797
3798         if (warning_displayed)
3799                 printf("Connection established.\n");
3800
3801 done:
3802         start_edit();
3803 }
3804
3805
3806 static void wpa_cli_interactive(void)
3807 {
3808         printf("\nInteractive mode\n\n");
3809
3810         eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3811         eloop_run();
3812         eloop_cancel_timeout(try_connection, NULL, NULL);
3813
3814         cli_txt_list_flush(&p2p_peers);
3815         cli_txt_list_flush(&p2p_groups);
3816         cli_txt_list_flush(&bsses);
3817         cli_txt_list_flush(&ifnames);
3818         if (edit_started)
3819                 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3820         os_free(hfile);
3821         eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3822         wpa_cli_close_connection();
3823 }
3824
3825
3826 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3827 {
3828 #ifdef CONFIG_ANSI_C_EXTRA
3829         /* TODO: ANSI C version(?) */
3830         printf("Action processing not supported in ANSI C build.\n");
3831 #else /* CONFIG_ANSI_C_EXTRA */
3832         fd_set rfds;
3833         int fd, res;
3834         struct timeval tv;
3835         char buf[256]; /* note: large enough to fit in unsolicited messages */
3836         size_t len;
3837
3838         fd = wpa_ctrl_get_fd(ctrl);
3839
3840         while (!wpa_cli_quit) {
3841                 FD_ZERO(&rfds);
3842                 FD_SET(fd, &rfds);
3843                 tv.tv_sec = ping_interval;
3844                 tv.tv_usec = 0;
3845                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3846                 if (res < 0 && errno != EINTR) {
3847                         perror("select");
3848                         break;
3849                 }
3850
3851                 if (FD_ISSET(fd, &rfds))
3852                         wpa_cli_recv_pending(ctrl, 1);
3853                 else {
3854                         /* verify that connection is still working */
3855                         len = sizeof(buf) - 1;
3856                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3857                                              wpa_cli_action_cb) < 0 ||
3858                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3859                                 printf("wpa_supplicant did not reply to PING "
3860                                        "command - exiting\n");
3861                                 break;
3862                         }
3863                 }
3864         }
3865 #endif /* CONFIG_ANSI_C_EXTRA */
3866 }
3867
3868
3869 static void wpa_cli_cleanup(void)
3870 {
3871         wpa_cli_close_connection();
3872         if (pid_file)
3873                 os_daemonize_terminate(pid_file);
3874
3875         os_program_deinit();
3876 }
3877
3878
3879 static void wpa_cli_terminate(int sig, void *ctx)
3880 {
3881         eloop_terminate();
3882 }
3883
3884
3885 static char * wpa_cli_get_default_ifname(void)
3886 {
3887         char *ifname = NULL;
3888
3889 #ifdef CONFIG_CTRL_IFACE_UNIX
3890         struct dirent *dent;
3891         DIR *dir = opendir(ctrl_iface_dir);
3892         if (!dir) {
3893 #ifdef ANDROID
3894                 char ifprop[PROPERTY_VALUE_MAX];
3895                 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3896                         ifname = os_strdup(ifprop);
3897                         printf("Using interface '%s'\n", ifname);
3898                         return ifname;
3899                 }
3900 #endif /* ANDROID */
3901                 return NULL;
3902         }
3903         while ((dent = readdir(dir))) {
3904 #ifdef _DIRENT_HAVE_D_TYPE
3905                 /*
3906                  * Skip the file if it is not a socket. Also accept
3907                  * DT_UNKNOWN (0) in case the C library or underlying
3908                  * file system does not support d_type.
3909                  */
3910                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3911                         continue;
3912 #endif /* _DIRENT_HAVE_D_TYPE */
3913                 if (os_strcmp(dent->d_name, ".") == 0 ||
3914                     os_strcmp(dent->d_name, "..") == 0)
3915                         continue;
3916                 printf("Selected interface '%s'\n", dent->d_name);
3917                 ifname = os_strdup(dent->d_name);
3918                 break;
3919         }
3920         closedir(dir);
3921 #endif /* CONFIG_CTRL_IFACE_UNIX */
3922
3923 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3924         char buf[4096], *pos;
3925         size_t len;
3926         struct wpa_ctrl *ctrl;
3927         int ret;
3928
3929         ctrl = wpa_ctrl_open(NULL);
3930         if (ctrl == NULL)
3931                 return NULL;
3932
3933         len = sizeof(buf) - 1;
3934         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3935         if (ret >= 0) {
3936                 buf[len] = '\0';
3937                 pos = os_strchr(buf, '\n');
3938                 if (pos)
3939                         *pos = '\0';
3940                 ifname = os_strdup(buf);
3941         }
3942         wpa_ctrl_close(ctrl);
3943 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3944
3945         return ifname;
3946 }
3947
3948
3949 int main(int argc, char *argv[])
3950 {
3951         int c;
3952         int daemonize = 0;
3953         int ret = 0;
3954         const char *global = NULL;
3955
3956         if (os_program_init())
3957                 return -1;
3958
3959         for (;;) {
3960                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3961                 if (c < 0)
3962                         break;
3963                 switch (c) {
3964                 case 'a':
3965                         action_file = optarg;
3966                         break;
3967                 case 'B':
3968                         daemonize = 1;
3969                         break;
3970                 case 'g':
3971                         global = optarg;
3972                         break;
3973                 case 'G':
3974                         ping_interval = atoi(optarg);
3975                         break;
3976                 case 'h':
3977                         usage();
3978                         return 0;
3979                 case 'v':
3980                         printf("%s\n", wpa_cli_version);
3981                         return 0;
3982                 case 'i':
3983                         os_free(ctrl_ifname);
3984                         ctrl_ifname = os_strdup(optarg);
3985                         break;
3986                 case 'p':
3987                         ctrl_iface_dir = optarg;
3988                         break;
3989                 case 'P':
3990                         pid_file = optarg;
3991                         break;
3992                 default:
3993                         usage();
3994                         return -1;
3995                 }
3996         }
3997
3998         interactive = (argc == optind) && (action_file == NULL);
3999
4000         if (interactive)
4001                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4002
4003         if (eloop_init())
4004                 return -1;
4005
4006         if (global) {
4007 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4008                 ctrl_conn = wpa_ctrl_open(NULL);
4009 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4010                 ctrl_conn = wpa_ctrl_open(global);
4011 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4012                 if (ctrl_conn == NULL) {
4013                         fprintf(stderr, "Failed to connect to wpa_supplicant "
4014                                 "global interface: %s  error: %s\n",
4015                                 global, strerror(errno));
4016                         return -1;
4017                 }
4018
4019                 if (interactive) {
4020                         update_ifnames(ctrl_conn);
4021                         mon_conn = wpa_ctrl_open(global);
4022                         if (mon_conn) {
4023                                 if (wpa_ctrl_attach(mon_conn) == 0) {
4024                                         wpa_cli_attached = 1;
4025                                         eloop_register_read_sock(
4026                                                 wpa_ctrl_get_fd(mon_conn),
4027                                                 wpa_cli_mon_receive,
4028                                                 NULL, NULL);
4029                                 } else {
4030                                         printf("Failed to open monitor "
4031                                                "connection through global "
4032                                                "control interface\n");
4033                                 }
4034                         }
4035                 }
4036         }
4037
4038         eloop_register_signal_terminate(wpa_cli_terminate, NULL);
4039
4040         if (ctrl_ifname == NULL)
4041                 ctrl_ifname = wpa_cli_get_default_ifname();
4042
4043         if (interactive) {
4044                 wpa_cli_interactive();
4045         } else {
4046                 if (!global &&
4047                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4048                         fprintf(stderr, "Failed to connect to non-global "
4049                                 "ctrl_ifname: %s  error: %s\n",
4050                                 ctrl_ifname ? ctrl_ifname : "(nil)",
4051                                 strerror(errno));
4052                         return -1;
4053                 }
4054
4055                 if (action_file) {
4056                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
4057                                 wpa_cli_attached = 1;
4058                         } else {
4059                                 printf("Warning: Failed to attach to "
4060                                        "wpa_supplicant.\n");
4061                                 return -1;
4062                         }
4063                 }
4064
4065                 if (daemonize && os_daemonize(pid_file))
4066                         return -1;
4067
4068                 if (action_file)
4069                         wpa_cli_action(ctrl_conn);
4070                 else
4071                         ret = wpa_request(ctrl_conn, argc - optind,
4072                                           &argv[optind]);
4073         }
4074
4075         os_free(ctrl_ifname);
4076         eloop_destroy();
4077         wpa_cli_cleanup();
4078
4079         return ret;
4080 }
4081
4082 #else /* CONFIG_CTRL_IFACE */
4083 int main(int argc, char *argv[])
4084 {
4085         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4086         return -1;
4087 }
4088 #endif /* CONFIG_CTRL_IFACE */