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