wpa_cli: Implement completion routine for get_capability
[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 char ** wpa_cli_complete_get_capability(const char *str, int pos)
1828 {
1829         int arg = get_cmd_arg_num(str, pos);
1830         const char *fields[] = {
1831                 "eap", "pairwise", "group", "group_mgmt", "key_mgmt",
1832                 "proto", "auth_alg", "modes", "channels", "freq",
1833 #ifdef CONFIG_TDLS
1834                 "tdls",
1835 #endif /* CONFIG_TDLS */
1836 #ifdef CONFIG_ERP
1837                 "erp",
1838 #endif /* CONFIG_ERP */
1839 #ifdef CONFIG_FIPS
1840                 "fips",
1841 #endif /* CONFIG_FIPS */
1842 #ifdef CONFIG_ACS
1843                 "acs",
1844 #endif /* CONFIG_ACS */
1845         };
1846         int i, num_fields = ARRAY_SIZE(fields);
1847         char **res = NULL;
1848
1849         if (arg == 1) {
1850                 res = os_calloc(num_fields + 1, sizeof(char *));
1851                 if (res == NULL)
1852                         return NULL;
1853                 for (i = 0; i < num_fields; i++) {
1854                         res[i] = os_strdup(fields[i]);
1855                         if (res[i] == NULL)
1856                                 return res;
1857                 }
1858         }
1859         if (arg == 2) {
1860                 res = os_calloc(1 + 1, sizeof(char *));
1861                 if (res == NULL)
1862                         return NULL;
1863                 res[0] = os_strdup("strict");
1864         }
1865         return res;
1866 }
1867
1868
1869 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1870 {
1871         printf("Available interfaces:\n");
1872         return wpa_ctrl_command(ctrl, "INTERFACES");
1873 }
1874
1875
1876 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1877 {
1878         if (argc < 1) {
1879                 wpa_cli_list_interfaces(ctrl);
1880                 return 0;
1881         }
1882
1883         wpa_cli_close_connection();
1884         os_free(ctrl_ifname);
1885         ctrl_ifname = os_strdup(argv[0]);
1886         if (!ctrl_ifname) {
1887                 printf("Failed to allocate memory\n");
1888                 return 0;
1889         }
1890
1891         if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1892                 printf("Connected to interface '%s.\n", ctrl_ifname);
1893         } else {
1894                 printf("Could not connect to interface '%s' - re-trying\n",
1895                        ctrl_ifname);
1896         }
1897         return 0;
1898 }
1899
1900
1901 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1902                                    char *argv[])
1903 {
1904         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1905 }
1906
1907
1908 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1909                                  char *argv[])
1910 {
1911         return wpa_ctrl_command(ctrl, "TERMINATE");
1912 }
1913
1914
1915 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1916                                      char *argv[])
1917 {
1918         char cmd[256];
1919         int res;
1920
1921         if (argc < 1) {
1922                 printf("Invalid INTERFACE_ADD command: needs at least one "
1923                        "argument (interface name)\n"
1924                        "All arguments: ifname confname driver ctrl_interface "
1925                        "driver_param bridge_name [create]\n");
1926                 return -1;
1927         }
1928
1929         /*
1930          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1931          * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
1932          */
1933         res = os_snprintf(cmd, sizeof(cmd),
1934                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
1935                           argv[0],
1936                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1937                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1938                           argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
1939                           argc > 7 ? argv[7] : "");
1940         if (os_snprintf_error(sizeof(cmd), res))
1941                 return -1;
1942         cmd[sizeof(cmd) - 1] = '\0';
1943         return wpa_ctrl_command(ctrl, cmd);
1944 }
1945
1946
1947 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1948                                         char *argv[])
1949 {
1950         return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1951 }
1952
1953
1954 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1955                                       char *argv[])
1956 {
1957         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1958 }
1959
1960
1961 #ifdef CONFIG_AP
1962 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1963 {
1964         return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1965 }
1966
1967
1968 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1969                                 char *addr, size_t addr_len)
1970 {
1971         char buf[4096], *pos;
1972         size_t len;
1973         int ret;
1974
1975         if (ctrl_conn == NULL) {
1976                 printf("Not connected to hostapd - command dropped.\n");
1977                 return -1;
1978         }
1979         if (ifname_prefix) {
1980                 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
1981                             ifname_prefix, cmd);
1982                 buf[sizeof(buf) - 1] = '\0';
1983                 cmd = buf;
1984         }
1985         len = sizeof(buf) - 1;
1986         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1987                                wpa_cli_msg_cb);
1988         if (ret == -2) {
1989                 printf("'%s' command timed out.\n", cmd);
1990                 return -2;
1991         } else if (ret < 0) {
1992                 printf("'%s' command failed.\n", cmd);
1993                 return -1;
1994         }
1995
1996         buf[len] = '\0';
1997         if (os_memcmp(buf, "FAIL", 4) == 0)
1998                 return -1;
1999         printf("%s", buf);
2000
2001         pos = buf;
2002         while (*pos != '\0' && *pos != '\n')
2003                 pos++;
2004         *pos = '\0';
2005         os_strlcpy(addr, buf, addr_len);
2006         return 0;
2007 }
2008
2009
2010 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
2011 {
2012         char addr[32], cmd[64];
2013
2014         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
2015                 return 0;
2016         do {
2017                 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
2018         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
2019
2020         return -1;
2021 }
2022
2023
2024 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
2025                                       char *argv[])
2026 {
2027         return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
2028 }
2029
2030
2031 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
2032                                     char *argv[])
2033 {
2034         return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
2035 }
2036
2037 static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
2038                                     char *argv[])
2039 {
2040         return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
2041 }
2042
2043 #endif /* CONFIG_AP */
2044
2045
2046 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
2047 {
2048         return wpa_ctrl_command(ctrl, "SUSPEND");
2049 }
2050
2051
2052 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
2053 {
2054         return wpa_ctrl_command(ctrl, "RESUME");
2055 }
2056
2057
2058 #ifdef CONFIG_TESTING_OPTIONS
2059 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
2060 {
2061         return wpa_ctrl_command(ctrl, "DROP_SA");
2062 }
2063 #endif /* CONFIG_TESTING_OPTIONS */
2064
2065
2066 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
2067 {
2068         return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
2069 }
2070
2071
2072 #ifdef CONFIG_MESH
2073
2074 static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
2075                                           char *argv[])
2076 {
2077         return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
2078 }
2079
2080
2081 static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
2082                                       char *argv[])
2083 {
2084         return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
2085 }
2086
2087
2088 static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
2089                                          char *argv[])
2090 {
2091         return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
2092 }
2093
2094
2095 static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
2096                                         char *argv[])
2097 {
2098         return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
2099 }
2100
2101
2102 static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
2103                                      char *argv[])
2104 {
2105         return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
2106 }
2107
2108 #endif /* CONFIG_MESH */
2109
2110
2111 #ifdef CONFIG_P2P
2112
2113 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2114 {
2115         return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2116 }
2117
2118
2119 static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2120 {
2121         char **res = NULL;
2122         int arg = get_cmd_arg_num(str, pos);
2123
2124         res = os_calloc(6, sizeof(char *));
2125         if (res == NULL)
2126                 return NULL;
2127         res[0] = os_strdup("type=social");
2128         if (res[0] == NULL) {
2129                 os_free(res);
2130                 return NULL;
2131         }
2132         res[1] = os_strdup("type=progressive");
2133         if (res[1] == NULL)
2134                 return res;
2135         res[2] = os_strdup("delay=");
2136         if (res[2] == NULL)
2137                 return res;
2138         res[3] = os_strdup("dev_id=");
2139         if (res[3] == NULL)
2140                 return res;
2141         if (arg == 1)
2142                 res[4] = os_strdup("[timeout]");
2143
2144         return res;
2145 }
2146
2147
2148 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2149                                      char *argv[])
2150 {
2151         return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2152 }
2153
2154
2155 static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
2156                                          char *argv[])
2157 {
2158         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
2159 }
2160
2161
2162 static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
2163                                               char *argv[])
2164 {
2165         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
2166 }
2167
2168
2169 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2170                                    char *argv[])
2171 {
2172         return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
2173 }
2174
2175
2176 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2177 {
2178         int arg = get_cmd_arg_num(str, pos);
2179         char **res = NULL;
2180
2181         switch (arg) {
2182         case 1:
2183                 res = cli_txt_list_array(&p2p_peers);
2184                 break;
2185         }
2186
2187         return res;
2188 }
2189
2190
2191 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2192                                   char *argv[])
2193 {
2194         return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
2195 }
2196
2197
2198 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2199                                         char *argv[])
2200 {
2201         return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
2202 }
2203
2204
2205 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2206 {
2207         int arg = get_cmd_arg_num(str, pos);
2208         char **res = NULL;
2209
2210         switch (arg) {
2211         case 1:
2212                 res = cli_txt_list_array(&p2p_groups);
2213                 break;
2214         }
2215
2216         return res;
2217 }
2218
2219
2220 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2221                                         char *argv[])
2222 {
2223         return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
2224 }
2225
2226
2227 static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc,
2228                                         char *argv[])
2229 {
2230         return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv);
2231 }
2232
2233
2234 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2235                                      char *argv[])
2236 {
2237         if (argc != 2 && argc != 3) {
2238                 printf("Invalid P2P_PROV_DISC command: needs at least "
2239                        "two arguments, address and config method\n"
2240                        "(display, keypad, or pbc) and an optional join\n");
2241                 return -1;
2242         }
2243
2244         return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
2245 }
2246
2247
2248 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2249                                           char *argv[])
2250 {
2251         return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2252 }
2253
2254
2255 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2256                                          char *argv[])
2257 {
2258         char cmd[4096];
2259
2260         if (argc < 2) {
2261                 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2262                        "or more arguments (address and TLVs)\n");
2263                 return -1;
2264         }
2265
2266         if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
2267                 return -1;
2268         return wpa_ctrl_command(ctrl, cmd);
2269 }
2270
2271
2272 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2273                                                 int argc, char *argv[])
2274 {
2275         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
2276 }
2277
2278
2279 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2280                                           char *argv[])
2281 {
2282         char cmd[4096];
2283         int res;
2284
2285         if (argc != 4) {
2286                 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2287                        "arguments (freq, address, dialog token, and TLVs)\n");
2288                 return -1;
2289         }
2290
2291         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2292                           argv[0], argv[1], argv[2], argv[3]);
2293         if (os_snprintf_error(sizeof(cmd), res))
2294                 return -1;
2295         cmd[sizeof(cmd) - 1] = '\0';
2296         return wpa_ctrl_command(ctrl, cmd);
2297 }
2298
2299
2300 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2301                                           char *argv[])
2302 {
2303         return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2304 }
2305
2306
2307 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2308                                               int argc, char *argv[])
2309 {
2310         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
2311 }
2312
2313
2314 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2315                                          char *argv[])
2316 {
2317         return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2318 }
2319
2320
2321 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2322                                        char *argv[])
2323 {
2324         if (argc < 3) {
2325                 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2326                 return -1;
2327         }
2328
2329         return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2330 }
2331
2332
2333 static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2334                                        char *argv[])
2335 {
2336         if (argc < 5 || argc > 6) {
2337                 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
2338                        "arguments\n");
2339                 return -1;
2340         }
2341
2342         return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
2343 }
2344
2345
2346 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2347                                        char *argv[])
2348 {
2349         char cmd[4096];
2350         int res;
2351
2352         if (argc != 2 && argc != 3) {
2353                 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2354                        "arguments\n");
2355                 return -1;
2356         }
2357
2358         if (argc == 3)
2359                 res = os_snprintf(cmd, sizeof(cmd),
2360                                   "P2P_SERVICE_DEL %s %s %s",
2361                                   argv[0], argv[1], argv[2]);
2362         else
2363                 res = os_snprintf(cmd, sizeof(cmd),
2364                                   "P2P_SERVICE_DEL %s %s",
2365                                   argv[0], argv[1]);
2366         if (os_snprintf_error(sizeof(cmd), res))
2367                 return -1;
2368         cmd[sizeof(cmd) - 1] = '\0';
2369         return wpa_ctrl_command(ctrl, cmd);
2370 }
2371
2372
2373 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2374                                   int argc, char *argv[])
2375 {
2376         return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
2377 }
2378
2379
2380 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2381                                   int argc, char *argv[])
2382 {
2383         return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2384 }
2385
2386
2387 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2388 {
2389         return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2390 }
2391
2392
2393 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2394 {
2395         int arg = get_cmd_arg_num(str, pos);
2396         char **res = NULL;
2397
2398         switch (arg) {
2399         case 1:
2400                 res = cli_txt_list_array(&p2p_peers);
2401                 break;
2402         }
2403
2404         return res;
2405 }
2406
2407
2408 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2409                                      char *addr, size_t addr_len,
2410                                      int discovered)
2411 {
2412         char buf[4096], *pos;
2413         size_t len;
2414         int ret;
2415
2416         if (ctrl_conn == NULL)
2417                 return -1;
2418         len = sizeof(buf) - 1;
2419         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2420                                wpa_cli_msg_cb);
2421         if (ret == -2) {
2422                 printf("'%s' command timed out.\n", cmd);
2423                 return -2;
2424         } else if (ret < 0) {
2425                 printf("'%s' command failed.\n", cmd);
2426                 return -1;
2427         }
2428
2429         buf[len] = '\0';
2430         if (os_memcmp(buf, "FAIL", 4) == 0)
2431                 return -1;
2432
2433         pos = buf;
2434         while (*pos != '\0' && *pos != '\n')
2435                 pos++;
2436         *pos++ = '\0';
2437         os_strlcpy(addr, buf, addr_len);
2438         if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2439                 printf("%s\n", addr);
2440         return 0;
2441 }
2442
2443
2444 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2445 {
2446         char addr[32], cmd[64];
2447         int discovered;
2448
2449         discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2450
2451         if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2452                                       addr, sizeof(addr), discovered))
2453                 return -1;
2454         do {
2455                 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2456         } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2457                          discovered) == 0);
2458
2459         return 0;
2460 }
2461
2462
2463 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2464 {
2465         return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2466 }
2467
2468
2469 static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2470 {
2471         int arg = get_cmd_arg_num(str, pos);
2472         const char *fields[] = {
2473                 "discoverability",
2474                 "managed",
2475                 "listen_channel",
2476                 "ssid_postfix",
2477                 "noa",
2478                 "ps",
2479                 "oppps",
2480                 "ctwindow",
2481                 "disabled",
2482                 "conc_pref",
2483                 "force_long_sd",
2484                 "peer_filter",
2485                 "cross_connect",
2486                 "go_apsd",
2487                 "client_apsd",
2488                 "disallow_freq",
2489                 "disc_int",
2490                 "per_sta_psk",
2491         };
2492         int i, num_fields = ARRAY_SIZE(fields);
2493
2494         if (arg == 1) {
2495                 char **res = os_calloc(num_fields + 1, sizeof(char *));
2496                 if (res == NULL)
2497                         return NULL;
2498                 for (i = 0; i < num_fields; i++) {
2499                         res[i] = os_strdup(fields[i]);
2500                         if (res[i] == NULL)
2501                                 return res;
2502                 }
2503                 return res;
2504         }
2505
2506         if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2507                 return cli_txt_list_array(&p2p_peers);
2508
2509         return NULL;
2510 }
2511
2512
2513 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2514 {
2515         return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2516 }
2517
2518
2519 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2520                                   char *argv[])
2521 {
2522         return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2523 }
2524
2525
2526 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2527                                        char *argv[])
2528 {
2529         return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2530 }
2531
2532
2533 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2534                                         char *argv[])
2535 {
2536         if (argc != 0 && argc != 2 && argc != 4) {
2537                 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2538                        "(preferred duration, interval; in microsecods).\n"
2539                        "Optional second pair can be used to provide "
2540                        "acceptable values.\n");
2541                 return -1;
2542         }
2543
2544         return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2545 }
2546
2547
2548 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2549                                       char *argv[])
2550 {
2551         if (argc != 0 && argc != 2) {
2552                 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2553                        "(availability period, availability interval; in "
2554                        "millisecods).\n"
2555                        "Extended Listen Timing can be cancelled with this "
2556                        "command when used without parameters.\n");
2557                 return -1;
2558         }
2559
2560         return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2561 }
2562
2563
2564 static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2565                                          char *argv[])
2566 {
2567         return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2568 }
2569
2570
2571 static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
2572                                        char *argv[])
2573 {
2574         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
2575 }
2576
2577
2578 static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
2579                                        char *argv[])
2580 {
2581         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
2582 }
2583
2584
2585 static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
2586                                           char *argv[])
2587 {
2588         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
2589 }
2590
2591 #endif /* CONFIG_P2P */
2592
2593 #ifdef CONFIG_WIFI_DISPLAY
2594
2595 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2596                                        char *argv[])
2597 {
2598         char cmd[100];
2599         int res;
2600
2601         if (argc != 1 && argc != 2) {
2602                 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2603                        "arguments (subelem, hexdump)\n");
2604                 return -1;
2605         }
2606
2607         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2608                           argv[0], argc > 1 ? argv[1] : "");
2609         if (os_snprintf_error(sizeof(cmd), res))
2610                 return -1;
2611         cmd[sizeof(cmd) - 1] = '\0';
2612         return wpa_ctrl_command(ctrl, cmd);
2613 }
2614
2615
2616 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2617                                        char *argv[])
2618 {
2619         char cmd[100];
2620         int res;
2621
2622         if (argc != 1) {
2623                 printf("Invalid WFD_SUBELEM_GET command: needs one "
2624                        "argument (subelem)\n");
2625                 return -1;
2626         }
2627
2628         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2629                           argv[0]);
2630         if (os_snprintf_error(sizeof(cmd), res))
2631                 return -1;
2632         cmd[sizeof(cmd) - 1] = '\0';
2633         return wpa_ctrl_command(ctrl, cmd);
2634 }
2635 #endif /* CONFIG_WIFI_DISPLAY */
2636
2637
2638 #ifdef CONFIG_INTERWORKING
2639 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2640                                   char *argv[])
2641 {
2642         return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2643 }
2644
2645
2646 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2647                                        char *argv[])
2648 {
2649         return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2650 }
2651
2652
2653 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2654                                            char *argv[])
2655 {
2656         return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2657 }
2658
2659
2660 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2661                                             char *argv[])
2662 {
2663         return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2664 }
2665
2666
2667 static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2668                                                 char *argv[])
2669 {
2670         return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2671 }
2672
2673
2674 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2675 {
2676         return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2677 }
2678
2679
2680 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2681                                    char *argv[])
2682 {
2683         return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2684 }
2685
2686
2687 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2688                                         char *argv[])
2689 {
2690         return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2691 }
2692 #endif /* CONFIG_INTERWORKING */
2693
2694
2695 #ifdef CONFIG_HS20
2696
2697 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2698                                      char *argv[])
2699 {
2700         return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2701 }
2702
2703
2704 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2705                                                char *argv[])
2706 {
2707         char cmd[512];
2708
2709         if (argc == 0) {
2710                 printf("Command needs one or two arguments (dst mac addr and "
2711                        "optional home realm)\n");
2712                 return -1;
2713         }
2714
2715         if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2716                       argc, argv) < 0)
2717                 return -1;
2718
2719         return wpa_ctrl_command(ctrl, cmd);
2720 }
2721
2722
2723 static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2724                                          char *argv[])
2725 {
2726         char cmd[512];
2727
2728         if (argc < 2) {
2729                 printf("Command needs two arguments (dst mac addr and "
2730                        "icon name)\n");
2731                 return -1;
2732         }
2733
2734         if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2735                 return -1;
2736
2737         return wpa_ctrl_command(ctrl, cmd);
2738 }
2739
2740
2741 static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2742 {
2743         return wpa_ctrl_command(ctrl, "FETCH_OSU");
2744 }
2745
2746
2747 static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2748                                         char *argv[])
2749 {
2750         return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2751 }
2752
2753 #endif /* CONFIG_HS20 */
2754
2755
2756 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2757                                        char *argv[])
2758 {
2759         return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2760 }
2761
2762
2763 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2764                                      char *argv[])
2765 {
2766         return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2767 }
2768
2769
2770 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2771                                   char *argv[])
2772 {
2773         return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2774 }
2775
2776
2777 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2778                                      char *argv[])
2779 {
2780         return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2781 }
2782
2783
2784 static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
2785                                         char *argv[])
2786 {
2787         return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
2788 }
2789
2790
2791 static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2792                                     char *argv[])
2793 {
2794         return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2795 }
2796
2797
2798 static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2799                                     char *argv[])
2800 {
2801         return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2802 }
2803
2804
2805 static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2806                                     char *argv[])
2807 {
2808         return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2809 }
2810
2811
2812 static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2813                                         char *argv[])
2814 {
2815         return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2816 }
2817
2818
2819 static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2820                                                char *argv[])
2821 {
2822         return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2823 }
2824
2825
2826 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2827                                    char *argv[])
2828 {
2829         return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2830 }
2831
2832
2833 static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
2834                                    char *argv[])
2835 {
2836         return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
2837 }
2838
2839
2840 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2841                                    char *argv[])
2842 {
2843         return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2844 }
2845
2846
2847 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2848                                       char *argv[])
2849 {
2850         return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2851 }
2852
2853
2854 #ifdef CONFIG_AUTOSCAN
2855
2856 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2857 {
2858         if (argc == 0)
2859                 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2860
2861         return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2862 }
2863
2864 #endif /* CONFIG_AUTOSCAN */
2865
2866
2867 #ifdef CONFIG_WNM
2868
2869 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2870 {
2871         return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2872 }
2873
2874
2875 static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2876 {
2877         return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2878 }
2879
2880 #endif /* CONFIG_WNM */
2881
2882
2883 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2884 {
2885         if (argc == 0)
2886                 return -1;
2887         return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2888 }
2889
2890
2891 #ifdef ANDROID
2892 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2893 {
2894         return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2895 }
2896 #endif /* ANDROID */
2897
2898
2899 static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2900 {
2901         return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2902 }
2903
2904
2905 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2906 {
2907         return wpa_ctrl_command(ctrl, "FLUSH");
2908 }
2909
2910
2911 static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2912 {
2913         return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2914 }
2915
2916
2917 static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2918                                             char *argv[])
2919 {
2920         return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2921 }
2922
2923
2924 static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2925 {
2926         return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2927 }
2928
2929
2930 static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2931                                      char *argv[])
2932 {
2933         return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2934 }
2935
2936
2937 static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
2938                                           char *argv[])
2939 {
2940         return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
2941 }
2942
2943
2944 static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
2945                                     char *argv[])
2946 {
2947         return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
2948 }
2949
2950
2951 static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
2952                                    char *argv[])
2953 {
2954         return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
2955 }
2956
2957
2958 enum wpa_cli_cmd_flags {
2959         cli_cmd_flag_none               = 0x00,
2960         cli_cmd_flag_sensitive          = 0x01
2961 };
2962
2963 struct wpa_cli_cmd {
2964         const char *cmd;
2965         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2966         char ** (*completion)(const char *str, int pos);
2967         enum wpa_cli_cmd_flags flags;
2968         const char *usage;
2969 };
2970
2971 static const struct wpa_cli_cmd wpa_cli_commands[] = {
2972         { "status", wpa_cli_cmd_status, NULL,
2973           cli_cmd_flag_none,
2974           "[verbose] = get current WPA/EAPOL/EAP status" },
2975         { "ifname", wpa_cli_cmd_ifname, NULL,
2976           cli_cmd_flag_none,
2977           "= get current interface name" },
2978         { "ping", wpa_cli_cmd_ping, NULL,
2979           cli_cmd_flag_none,
2980           "= pings wpa_supplicant" },
2981         { "relog", wpa_cli_cmd_relog, NULL,
2982           cli_cmd_flag_none,
2983           "= re-open log-file (allow rolling logs)" },
2984         { "note", wpa_cli_cmd_note, NULL,
2985           cli_cmd_flag_none,
2986           "<text> = add a note to wpa_supplicant debug log" },
2987         { "mib", wpa_cli_cmd_mib, NULL,
2988           cli_cmd_flag_none,
2989           "= get MIB variables (dot1x, dot11)" },
2990         { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2991           cli_cmd_flag_none,
2992           "[command] = show usage help" },
2993         { "interface", wpa_cli_cmd_interface, NULL,
2994           cli_cmd_flag_none,
2995           "[ifname] = show interfaces/select interface" },
2996         { "level", wpa_cli_cmd_level, NULL,
2997           cli_cmd_flag_none,
2998           "<debug level> = change debug level" },
2999         { "license", wpa_cli_cmd_license, NULL,
3000           cli_cmd_flag_none,
3001           "= show full wpa_cli license" },
3002         { "quit", wpa_cli_cmd_quit, NULL,
3003           cli_cmd_flag_none,
3004           "= exit wpa_cli" },
3005         { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
3006           cli_cmd_flag_none,
3007           "= set variables (shows list of variables when run without "
3008           "arguments)" },
3009         { "dump", wpa_cli_cmd_dump, NULL,
3010           cli_cmd_flag_none,
3011           "= dump config variables" },
3012         { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
3013           cli_cmd_flag_none,
3014           "<name> = get information" },
3015         { "driver_flags", wpa_cli_cmd_driver_flags, NULL,
3016           cli_cmd_flag_none,
3017           "= list driver flags" },
3018         { "logon", wpa_cli_cmd_logon, NULL,
3019           cli_cmd_flag_none,
3020           "= IEEE 802.1X EAPOL state machine logon" },
3021         { "logoff", wpa_cli_cmd_logoff, NULL,
3022           cli_cmd_flag_none,
3023           "= IEEE 802.1X EAPOL state machine logoff" },
3024         { "pmksa", wpa_cli_cmd_pmksa, NULL,
3025           cli_cmd_flag_none,
3026           "= show PMKSA cache" },
3027         { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
3028           cli_cmd_flag_none,
3029           "= flush PMKSA cache entries" },
3030         { "reassociate", wpa_cli_cmd_reassociate, NULL,
3031           cli_cmd_flag_none,
3032           "= force reassociation" },
3033         { "reattach", wpa_cli_cmd_reattach, NULL,
3034           cli_cmd_flag_none,
3035           "= force reassociation back to the same BSS" },
3036         { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
3037           cli_cmd_flag_none,
3038           "<BSSID> = force preauthentication" },
3039         { "identity", wpa_cli_cmd_identity, NULL,
3040           cli_cmd_flag_none,
3041           "<network id> <identity> = configure identity for an SSID" },
3042         { "password", wpa_cli_cmd_password, NULL,
3043           cli_cmd_flag_sensitive,
3044           "<network id> <password> = configure password for an SSID" },
3045         { "new_password", wpa_cli_cmd_new_password, NULL,
3046           cli_cmd_flag_sensitive,
3047           "<network id> <password> = change password for an SSID" },
3048         { "pin", wpa_cli_cmd_pin, NULL,
3049           cli_cmd_flag_sensitive,
3050           "<network id> <pin> = configure pin for an SSID" },
3051         { "otp", wpa_cli_cmd_otp, NULL,
3052           cli_cmd_flag_sensitive,
3053           "<network id> <password> = configure one-time-password for an SSID"
3054         },
3055         { "passphrase", wpa_cli_cmd_passphrase, NULL,
3056           cli_cmd_flag_sensitive,
3057           "<network id> <passphrase> = configure private key passphrase\n"
3058           "  for an SSID" },
3059         { "sim", wpa_cli_cmd_sim, NULL,
3060           cli_cmd_flag_sensitive,
3061           "<network id> <pin> = report SIM operation result" },
3062         { "bssid", wpa_cli_cmd_bssid, NULL,
3063           cli_cmd_flag_none,
3064           "<network id> <BSSID> = set preferred BSSID for an SSID" },
3065         { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
3066           cli_cmd_flag_none,
3067           "<BSSID> = add a BSSID to the blacklist\n"
3068           "blacklist clear = clear the blacklist\n"
3069           "blacklist = display the blacklist" },
3070         { "log_level", wpa_cli_cmd_log_level, NULL,
3071           cli_cmd_flag_none,
3072           "<level> [<timestamp>] = update the log level/timestamp\n"
3073           "log_level = display the current log level and log options" },
3074         { "list_networks", wpa_cli_cmd_list_networks, NULL,
3075           cli_cmd_flag_none,
3076           "= list configured networks" },
3077         { "select_network", wpa_cli_cmd_select_network,
3078           wpa_cli_complete_network_id,
3079           cli_cmd_flag_none,
3080           "<network id> = select a network (disable others)" },
3081         { "enable_network", wpa_cli_cmd_enable_network,
3082           wpa_cli_complete_network_id,
3083           cli_cmd_flag_none,
3084           "<network id> = enable a network" },
3085         { "disable_network", wpa_cli_cmd_disable_network,
3086           wpa_cli_complete_network_id,
3087           cli_cmd_flag_none,
3088           "<network id> = disable a network" },
3089         { "add_network", wpa_cli_cmd_add_network, NULL,
3090           cli_cmd_flag_none,
3091           "= add a network" },
3092         { "remove_network", wpa_cli_cmd_remove_network,
3093           wpa_cli_complete_network_id,
3094           cli_cmd_flag_none,
3095           "<network id> = remove a network" },
3096         { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
3097           cli_cmd_flag_sensitive,
3098           "<network id> <variable> <value> = set network variables (shows\n"
3099           "  list of variables when run without arguments)" },
3100         { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
3101           cli_cmd_flag_none,
3102           "<network id> <variable> = get network variables" },
3103         { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
3104           cli_cmd_flag_none,
3105           "<src network id> <dst network id> <variable> = duplicate network variables"
3106         },
3107         { "list_creds", wpa_cli_cmd_list_creds, NULL,
3108           cli_cmd_flag_none,
3109           "= list configured credentials" },
3110         { "add_cred", wpa_cli_cmd_add_cred, NULL,
3111           cli_cmd_flag_none,
3112           "= add a credential" },
3113         { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
3114           cli_cmd_flag_none,
3115           "<cred id> = remove a credential" },
3116         { "set_cred", wpa_cli_cmd_set_cred, NULL,
3117           cli_cmd_flag_sensitive,
3118           "<cred id> <variable> <value> = set credential variables" },
3119         { "get_cred", wpa_cli_cmd_get_cred, NULL,
3120           cli_cmd_flag_none,
3121           "<cred id> <variable> = get credential variables" },
3122         { "save_config", wpa_cli_cmd_save_config, NULL,
3123           cli_cmd_flag_none,
3124           "= save the current configuration" },
3125         { "disconnect", wpa_cli_cmd_disconnect, NULL,
3126           cli_cmd_flag_none,
3127           "= disconnect and wait for reassociate/reconnect command before\n"
3128           "  connecting" },
3129         { "reconnect", wpa_cli_cmd_reconnect, NULL,
3130           cli_cmd_flag_none,
3131           "= like reassociate, but only takes effect if already disconnected"
3132         },
3133         { "scan", wpa_cli_cmd_scan, NULL,
3134           cli_cmd_flag_none,
3135           "= request new BSS scan" },
3136         { "scan_results", wpa_cli_cmd_scan_results, NULL,
3137           cli_cmd_flag_none,
3138           "= get latest scan results" },
3139         { "abort_scan", wpa_cli_cmd_abort_scan, NULL,
3140           cli_cmd_flag_none,
3141           "= request ongoing scan to be aborted" },
3142         { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
3143           cli_cmd_flag_none,
3144           "<<idx> | <bssid>> = get detailed scan result info" },
3145         { "get_capability", wpa_cli_cmd_get_capability,
3146           wpa_cli_complete_get_capability, cli_cmd_flag_none,
3147           "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
3148           "= get capabilities" },
3149         { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
3150           cli_cmd_flag_none,
3151           "= force wpa_supplicant to re-read its configuration file" },
3152         { "terminate", wpa_cli_cmd_terminate, NULL,
3153           cli_cmd_flag_none,
3154           "= terminate wpa_supplicant" },
3155         { "interface_add", wpa_cli_cmd_interface_add, NULL,
3156           cli_cmd_flag_none,
3157           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
3158           "  <bridge_name> <create> <type> = adds new interface, all "
3159           "parameters but\n"
3160           "  <ifname> are optional. Supported types are station ('sta') and "
3161           "AP ('ap')" },
3162         { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
3163           cli_cmd_flag_none,
3164           "<ifname> = removes the interface" },
3165         { "interface_list", wpa_cli_cmd_interface_list, NULL,
3166           cli_cmd_flag_none,
3167           "= list available interfaces" },
3168         { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
3169           cli_cmd_flag_none,
3170           "<value> = set ap_scan parameter" },
3171         { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
3172           cli_cmd_flag_none,
3173           "<value> = set scan_interval parameter (in seconds)" },
3174         { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
3175           cli_cmd_flag_none,
3176           "<value> = set BSS expiration age parameter" },
3177         { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
3178           cli_cmd_flag_none,
3179           "<value> = set BSS expiration scan count parameter" },
3180         { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
3181           cli_cmd_flag_none,
3182           "<value> = set BSS flush age (0 by default)" },
3183         { "stkstart", wpa_cli_cmd_stkstart, NULL,
3184           cli_cmd_flag_none,
3185           "<addr> = request STK negotiation with <addr>" },
3186         { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
3187           cli_cmd_flag_none,
3188           "<addr> = request over-the-DS FT with <addr>" },
3189         { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
3190           cli_cmd_flag_none,
3191           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3192         { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
3193           cli_cmd_flag_sensitive,
3194           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3195           "hardcoded)" },
3196         { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
3197           cli_cmd_flag_sensitive,
3198           "<PIN> = verify PIN checksum" },
3199         { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
3200           "Cancels the pending WPS operation" },
3201 #ifdef CONFIG_WPS_NFC
3202         { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3203           cli_cmd_flag_none,
3204           "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3205         { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3206           cli_cmd_flag_none,
3207           "<WPS|NDEF> = build configuration token" },
3208         { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3209           cli_cmd_flag_none,
3210           "<WPS|NDEF> = create password token" },
3211         { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
3212           cli_cmd_flag_sensitive,
3213           "<hexdump of payload> = report read NFC tag with WPS data" },
3214         { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3215           cli_cmd_flag_none,
3216           "<NDEF> <WPS> = create NFC handover request" },
3217         { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3218           cli_cmd_flag_none,
3219           "<NDEF> <WPS> = create NFC handover select" },
3220         { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3221           cli_cmd_flag_none,
3222           "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3223           "NFC handover" },
3224 #endif /* CONFIG_WPS_NFC */
3225         { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
3226           cli_cmd_flag_sensitive,
3227           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3228         { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
3229           cli_cmd_flag_sensitive,
3230           "[params..] = enable/disable AP PIN" },
3231         { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
3232           cli_cmd_flag_none,
3233           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3234         { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
3235           cli_cmd_flag_none,
3236           "= stop Wi-Fi Protected Setup External Registrar" },
3237         { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
3238           cli_cmd_flag_sensitive,
3239           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3240         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
3241           cli_cmd_flag_none,
3242           "<UUID> = accept an Enrollee PBC using External Registrar" },
3243         { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
3244           cli_cmd_flag_sensitive,
3245           "<UUID> <PIN> = learn AP configuration" },
3246         { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
3247           cli_cmd_flag_none,
3248           "<UUID> <network id> = set AP configuration for enrolling" },
3249         { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
3250           cli_cmd_flag_sensitive,
3251           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
3252 #ifdef CONFIG_WPS_NFC
3253         { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
3254           cli_cmd_flag_none,
3255           "<WPS/NDEF> <UUID> = build NFC configuration token" },
3256 #endif /* CONFIG_WPS_NFC */
3257         { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
3258           cli_cmd_flag_none,
3259           "<addr> = request RSN authentication with <addr> in IBSS" },
3260 #ifdef CONFIG_AP
3261         { "sta", wpa_cli_cmd_sta, NULL,
3262           cli_cmd_flag_none,
3263           "<addr> = get information about an associated station (AP)" },
3264         { "all_sta", wpa_cli_cmd_all_sta, NULL,
3265           cli_cmd_flag_none,
3266           "= get information about all associated stations (AP)" },
3267         { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
3268           cli_cmd_flag_none,
3269           "<addr> = deauthenticate a station" },
3270         { "disassociate", wpa_cli_cmd_disassociate, NULL,
3271           cli_cmd_flag_none,
3272           "<addr> = disassociate a station" },
3273         { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3274           cli_cmd_flag_none,
3275           "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3276           " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3277           " = CSA parameters" },
3278 #endif /* CONFIG_AP */
3279         { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
3280           "= notification of suspend/hibernate" },
3281         { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
3282           "= notification of resume/thaw" },
3283 #ifdef CONFIG_TESTING_OPTIONS
3284         { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
3285           "= drop SA without deauth/disassoc (test command)" },
3286 #endif /* CONFIG_TESTING_OPTIONS */
3287         { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
3288           cli_cmd_flag_none,
3289           "<addr> = roam to the specified BSS" },
3290 #ifdef CONFIG_MESH
3291         { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3292           cli_cmd_flag_none,
3293           "[ifname] = Create a new mesh interface" },
3294         { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3295           cli_cmd_flag_none,
3296           "<network id> = join a mesh network (disable others)" },
3297         { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3298           cli_cmd_flag_none,
3299           "<ifname> = Remove mesh group interface" },
3300         { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
3301           cli_cmd_flag_none,
3302           "<addr> = Remove a mesh peer" },
3303         { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
3304           cli_cmd_flag_none,
3305           "<addr> [duration=<seconds>] = Add a mesh peer" },
3306 #endif /* CONFIG_MESH */
3307 #ifdef CONFIG_P2P
3308         { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3309           cli_cmd_flag_none,
3310           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3311         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
3312           "= stop P2P Devices search" },
3313         { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3314           cli_cmd_flag_none,
3315           "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3316         { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3317           cli_cmd_flag_none,
3318           "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
3319         { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3320           cli_cmd_flag_none,
3321           "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3322         { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
3323           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3324         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3325           wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
3326           "<ifname> = remove P2P group interface (terminate group if GO)" },
3327         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3328           "[ht40] = add a new P2P group (local end as GO)" },
3329         { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL,
3330           cli_cmd_flag_none,
3331           "<dev_addr> = Get peer interface address on local GO using peer Device Address" },
3332         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3333           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3334           "<addr> <method> = request provisioning discovery" },
3335         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
3336           cli_cmd_flag_none,
3337           "= get the passphrase for a group (GO only)" },
3338         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3339           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3340           "<addr> <TLVs> = schedule service discovery request" },
3341         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3342           NULL, cli_cmd_flag_none,
3343           "<id> = cancel pending service discovery request" },
3344         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
3345           cli_cmd_flag_none,
3346           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3347         { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
3348           cli_cmd_flag_none,
3349           "= indicate change in local services" },
3350         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
3351           cli_cmd_flag_none,
3352           "<external> = set external processing of service discovery" },
3353         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
3354           cli_cmd_flag_none,
3355           "= remove all stored service entries" },
3356         { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
3357           cli_cmd_flag_none,
3358           "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
3359           "service" },
3360         { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3361           cli_cmd_flag_none,
3362           "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3363           "local ASP service" },
3364         { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
3365           cli_cmd_flag_none,
3366           "<bonjour|upnp> <query|version> [|service] = remove a local "
3367           "service" },
3368         { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
3369           cli_cmd_flag_none,
3370           "<addr> = reject connection attempts from a specific peer" },
3371         { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
3372           cli_cmd_flag_none,
3373           "<cmd> [peer=addr] = invite peer" },
3374         { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
3375           "[discovered] = list known (optionally, only fully discovered) P2P "
3376           "peers" },
3377         { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3378           cli_cmd_flag_none,
3379           "<address> = show information about known P2P peer" },
3380         { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3381           cli_cmd_flag_none,
3382           "<field> <value> = set a P2P parameter" },
3383         { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
3384           "= flush P2P state" },
3385         { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
3386           "= cancel P2P group formation" },
3387         { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3388           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3389           "<address> = unauthorize a peer" },
3390         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3391           cli_cmd_flag_none,
3392           "[<duration> <interval>] [<duration> <interval>] = request GO "
3393           "presence" },
3394         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3395           cli_cmd_flag_none,
3396           "[<period> <interval>] = set extended listen timing" },
3397         { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3398           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3399           "<address|iface=address> = remove a peer from all groups" },
3400         { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
3401           cli_cmd_flag_none,
3402           "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
3403           VENDOR_ELEM_FRAME_ID },
3404         { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
3405           cli_cmd_flag_none,
3406           "<frame id> = get vendor specific IE(s) to frame(s)\n"
3407           VENDOR_ELEM_FRAME_ID },
3408         { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
3409           cli_cmd_flag_none,
3410           "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
3411           VENDOR_ELEM_FRAME_ID },
3412 #endif /* CONFIG_P2P */
3413 #ifdef CONFIG_WIFI_DISPLAY
3414         { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3415           cli_cmd_flag_none,
3416           "<subelem> [contents] = set Wi-Fi Display subelement" },
3417         { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3418           cli_cmd_flag_none,
3419           "<subelem> = get Wi-Fi Display subelement" },
3420 #endif /* CONFIG_WIFI_DISPLAY */
3421 #ifdef CONFIG_INTERWORKING
3422         { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
3423           "= fetch ANQP information for all APs" },
3424         { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3425           cli_cmd_flag_none,
3426           "= stop fetch_anqp operation" },
3427         { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
3428           cli_cmd_flag_none,
3429           "[auto] = perform Interworking network selection" },
3430         { "interworking_connect", wpa_cli_cmd_interworking_connect,
3431           wpa_cli_complete_bss, cli_cmd_flag_none,
3432           "<BSSID> = connect using Interworking credentials" },
3433         { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3434           wpa_cli_complete_bss, cli_cmd_flag_none,
3435           "<BSSID> = connect using Interworking credentials" },
3436         { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3437           cli_cmd_flag_none,
3438           "<addr> <info id>[,<info id>]... = request ANQP information" },
3439         { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3440           cli_cmd_flag_none,
3441           "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3442         { "gas_response_get", wpa_cli_cmd_gas_response_get,
3443           wpa_cli_complete_bss, cli_cmd_flag_none,
3444           "<addr> <dialog token> [start,len] = Fetch last GAS response" },
3445 #endif /* CONFIG_INTERWORKING */
3446 #ifdef CONFIG_HS20
3447         { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3448           cli_cmd_flag_none,
3449           "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3450         },
3451         { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3452           wpa_cli_complete_bss, cli_cmd_flag_none,
3453           "<addr> <home realm> = get HS20 nai home realm list" },
3454         { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3455           wpa_cli_complete_bss, cli_cmd_flag_none,
3456           "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3457         { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3458           "= fetch OSU provider information from all APs" },
3459         { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3460           cli_cmd_flag_none,
3461           "= cancel fetch_osu command" },
3462 #endif /* CONFIG_HS20 */
3463         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3464           cli_cmd_flag_none,
3465           "<0/1> = disable/enable automatic reconnection" },
3466         { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
3467           cli_cmd_flag_none,
3468           "<addr> = request TDLS discovery with <addr>" },
3469         { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
3470           cli_cmd_flag_none,
3471           "<addr> = request TDLS setup with <addr>" },
3472         { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
3473           cli_cmd_flag_none,
3474           "<addr> = tear down TDLS with <addr>" },
3475         { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
3476           cli_cmd_flag_none,
3477           "<addr> = TDLS link status with <addr>" },
3478         { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3479           cli_cmd_flag_none,
3480           "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3481           "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3482           "= add WMM-AC traffic stream" },
3483         { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3484           cli_cmd_flag_none,
3485           "<tsid> = delete WMM-AC traffic stream" },
3486         { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3487           cli_cmd_flag_none,
3488           "= show status for Wireless Multi-Media Admission-Control" },
3489         { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3490           cli_cmd_flag_none,
3491           "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3492           "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3493           "with TDLS peer" },
3494         { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3495           cli_cmd_flag_none,
3496           "<addr> = disable channel switching with TDLS peer <addr>" },
3497         { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
3498           cli_cmd_flag_none,
3499           "= get signal parameters" },
3500         { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
3501           cli_cmd_flag_none,
3502           "= set signal monitor parameters" },
3503         { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3504           cli_cmd_flag_none,
3505           "= get TX/RX packet counters" },
3506         { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3507           cli_cmd_flag_none,
3508           "= trigger IEEE 802.1X/EAPOL reauthentication" },
3509 #ifdef CONFIG_AUTOSCAN
3510         { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3511           "[params] = Set or unset (if none) autoscan parameters" },
3512 #endif /* CONFIG_AUTOSCAN */
3513 #ifdef CONFIG_WNM
3514         { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3515           "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3516         { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3517           "<query reason> [list] = Send BSS Transition Management Query" },
3518 #endif /* CONFIG_WNM */
3519         { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3520           "<params..> = Sent unprocessed command" },
3521         { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3522           "= flush wpa_supplicant state" },
3523 #ifdef ANDROID
3524         { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3525           "<command> = driver private commands" },
3526 #endif /* ANDROID */
3527         { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3528           "= radio_work <show/add/done>" },
3529         { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3530           "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3531         },
3532         { "neighbor_rep_request",
3533           wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3534           "[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)"
3535         },
3536         { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3537           "= flush ERP keys" },
3538         { "mac_rand_scan",
3539           wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3540           "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3541           "mask=mac-address-mask] = scan MAC randomization"
3542         },
3543         { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
3544           cli_cmd_flag_none,
3545           "<interface type> = retrieve preferred freq list for the specified interface type" },
3546         { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
3547           cli_cmd_flag_none,
3548           "<freq> <period> <interval> <count> = start P2P listen offload" },
3549         { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
3550           cli_cmd_flag_none,
3551           "= stop P2P listen offload" },
3552         { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
3553 };
3554
3555
3556 /*
3557  * Prints command usage, lines are padded with the specified string.
3558  */
3559 static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
3560 {
3561         char c;
3562         size_t n;
3563
3564         printf("%s%s ", pad, cmd->cmd);
3565         for (n = 0; (c = cmd->usage[n]); n++) {
3566                 printf("%c", c);
3567                 if (c == '\n')
3568                         printf("%s", pad);
3569         }
3570         printf("\n");
3571 }
3572
3573
3574 static void print_help(const char *cmd)
3575 {
3576         int n;
3577         printf("commands:\n");
3578         for (n = 0; wpa_cli_commands[n].cmd; n++) {
3579                 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3580                         print_cmd_help(&wpa_cli_commands[n], "  ");
3581         }
3582 }
3583
3584
3585 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3586 {
3587         const char *c, *delim;
3588         int n;
3589         size_t len;
3590
3591         delim = os_strchr(cmd, ' ');
3592         if (delim)
3593                 len = delim - cmd;
3594         else
3595                 len = os_strlen(cmd);
3596
3597         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3598                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3599                         return (wpa_cli_commands[n].flags &
3600                                 cli_cmd_flag_sensitive);
3601         }
3602         return 0;
3603 }
3604
3605
3606 static char ** wpa_list_cmd_list(void)
3607 {
3608         char **res;
3609         int i, count;
3610         struct cli_txt_entry *e;
3611
3612         count = ARRAY_SIZE(wpa_cli_commands);
3613         count += dl_list_len(&p2p_groups);
3614         count += dl_list_len(&ifnames);
3615         res = os_calloc(count + 1, sizeof(char *));
3616         if (res == NULL)
3617                 return NULL;
3618
3619         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3620                 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3621                 if (res[i] == NULL)
3622                         break;
3623         }
3624
3625         dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3626                 size_t len = 8 + os_strlen(e->txt);
3627                 res[i] = os_malloc(len);
3628                 if (res[i] == NULL)
3629                         break;
3630                 os_snprintf(res[i], len, "ifname=%s", e->txt);
3631                 i++;
3632         }
3633
3634         dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3635                 res[i] = os_strdup(e->txt);
3636                 if (res[i] == NULL)
3637                         break;
3638                 i++;
3639         }
3640
3641         return res;
3642 }
3643
3644
3645 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3646                                       int pos)
3647 {
3648         int i;
3649
3650         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3651                 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3652                         if (wpa_cli_commands[i].completion)
3653                                 return wpa_cli_commands[i].completion(str,
3654                                                                       pos);
3655                         edit_clear_line();
3656                         printf("\r%s\n", wpa_cli_commands[i].usage);
3657                         edit_redraw();
3658                         break;
3659                 }
3660         }
3661
3662         return NULL;
3663 }
3664
3665
3666 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3667 {
3668         char **res;
3669         const char *end;
3670         char *cmd;
3671
3672         if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3673                 end = os_strchr(str, ' ');
3674                 if (end && pos > end - str) {
3675                         pos -= end - str + 1;
3676                         str = end + 1;
3677                 }
3678         }
3679
3680         end = os_strchr(str, ' ');
3681         if (end == NULL || str + pos < end)
3682                 return wpa_list_cmd_list();
3683
3684         cmd = os_malloc(pos + 1);
3685         if (cmd == NULL)
3686                 return NULL;
3687         os_memcpy(cmd, str, pos);
3688         cmd[end - str] = '\0';
3689         res = wpa_cli_cmd_completion(cmd, str, pos);
3690         os_free(cmd);
3691         return res;
3692 }
3693
3694
3695 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3696 {
3697         const struct wpa_cli_cmd *cmd, *match = NULL;
3698         int count;
3699         int ret = 0;
3700
3701         if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3702                 ifname_prefix = argv[0] + 7;
3703                 argv = &argv[1];
3704                 argc--;
3705         } else
3706                 ifname_prefix = NULL;
3707
3708         if (argc == 0)
3709                 return -1;
3710
3711         count = 0;
3712         cmd = wpa_cli_commands;
3713         while (cmd->cmd) {
3714                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3715                 {
3716                         match = cmd;
3717                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3718                                 /* we have an exact match */
3719                                 count = 1;
3720                                 break;
3721                         }
3722                         count++;
3723                 }
3724                 cmd++;
3725         }
3726
3727         if (count > 1) {
3728                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3729                 cmd = wpa_cli_commands;
3730                 while (cmd->cmd) {
3731                         if (os_strncasecmp(cmd->cmd, argv[0],
3732                                            os_strlen(argv[0])) == 0) {
3733                                 printf(" %s", cmd->cmd);
3734                         }
3735                         cmd++;
3736                 }
3737                 printf("\n");
3738                 ret = 1;
3739         } else if (count == 0) {
3740                 printf("Unknown command '%s'\n", argv[0]);
3741                 ret = 1;
3742         } else {
3743                 ret = match->handler(ctrl, argc - 1, &argv[1]);
3744         }
3745
3746         return ret;
3747 }
3748
3749
3750 static int str_match(const char *a, const char *b)
3751 {
3752         return os_strncmp(a, b, os_strlen(b)) == 0;
3753 }
3754
3755
3756 static int wpa_cli_exec(const char *program, const char *arg1,
3757                         const char *arg2)
3758 {
3759         char *arg;
3760         size_t len;
3761         int res;
3762
3763         /* If no interface is specified, set the global */
3764         if (!arg1)
3765                 arg1 = "global";
3766
3767         len = os_strlen(arg1) + os_strlen(arg2) + 2;
3768         arg = os_malloc(len);
3769         if (arg == NULL)
3770                 return -1;
3771         os_snprintf(arg, len, "%s %s", arg1, arg2);
3772         res = os_exec(program, arg, 1);
3773         os_free(arg);
3774
3775         return res;
3776 }
3777
3778
3779 static void wpa_cli_action_process(const char *msg)
3780 {
3781         const char *pos;
3782         char *copy = NULL, *id, *pos2;
3783         const char *ifname = ctrl_ifname;
3784         char ifname_buf[100];
3785
3786         if (eloop_terminated())
3787                 return;
3788
3789         pos = msg;
3790         if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3791                 const char *end;
3792                 end = os_strchr(pos + 7, ' ');
3793                 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3794                         pos += 7;
3795                         os_memcpy(ifname_buf, pos, end - pos);
3796                         ifname_buf[end - pos] = '\0';
3797                         ifname = ifname_buf;
3798                         pos = end + 1;
3799                 }
3800         }
3801         if (*pos == '<') {
3802                 const char *prev = pos;
3803                 /* skip priority */
3804                 pos = os_strchr(pos, '>');
3805                 if (pos)
3806                         pos++;
3807                 else
3808                         pos = prev;
3809         }
3810
3811         if (str_match(pos, WPA_EVENT_CONNECTED)) {
3812                 int new_id = -1;
3813                 os_unsetenv("WPA_ID");
3814                 os_unsetenv("WPA_ID_STR");
3815                 os_unsetenv("WPA_CTRL_DIR");
3816
3817                 pos = os_strstr(pos, "[id=");
3818                 if (pos)
3819                         copy = os_strdup(pos + 4);
3820
3821                 if (copy) {
3822                         pos2 = id = copy;
3823                         while (*pos2 && *pos2 != ' ')
3824                                 pos2++;
3825                         *pos2++ = '\0';
3826                         new_id = atoi(id);
3827                         os_setenv("WPA_ID", id, 1);
3828                         while (*pos2 && *pos2 != '=')
3829                                 pos2++;
3830                         if (*pos2 == '=')
3831                                 pos2++;
3832                         id = pos2;
3833                         while (*pos2 && *pos2 != ']')
3834                                 pos2++;
3835                         *pos2 = '\0';
3836                         os_setenv("WPA_ID_STR", id, 1);
3837                         os_free(copy);
3838                 }
3839
3840                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3841
3842                 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3843                         wpa_cli_connected = 1;
3844                         wpa_cli_last_id = new_id;
3845                         wpa_cli_exec(action_file, ifname, "CONNECTED");
3846                 }
3847         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3848                 if (wpa_cli_connected) {
3849                         wpa_cli_connected = 0;
3850                         wpa_cli_exec(action_file, ifname, "DISCONNECTED");
3851                 }
3852         } else if (str_match(pos, AP_EVENT_ENABLED)) {
3853                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3854         } else if (str_match(pos, AP_EVENT_DISABLED)) {
3855                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3856         } else if (str_match(pos, MESH_GROUP_STARTED)) {
3857                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3858         } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3859                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3860         } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3861                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3862         } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3863                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3864         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3865                 wpa_cli_exec(action_file, ifname, pos);
3866         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3867                 wpa_cli_exec(action_file, ifname, pos);
3868         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3869                 wpa_cli_exec(action_file, ifname, pos);
3870         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3871                 wpa_cli_exec(action_file, ifname, pos);
3872         } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3873                 wpa_cli_exec(action_file, ifname, pos);
3874         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3875                 wpa_cli_exec(action_file, ifname, pos);
3876         } else if (str_match(pos, WPS_EVENT_FAIL)) {
3877                 wpa_cli_exec(action_file, ifname, pos);
3878         } else if (str_match(pos, AP_STA_CONNECTED)) {
3879                 wpa_cli_exec(action_file, ifname, pos);
3880         } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3881                 wpa_cli_exec(action_file, ifname, pos);
3882         } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3883                 wpa_cli_exec(action_file, ifname, pos);
3884         } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3885                 wpa_cli_exec(action_file, ifname, pos);
3886         } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3887                 wpa_cli_exec(action_file, ifname, pos);
3888         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3889                 printf("wpa_supplicant is terminating - stop monitoring\n");
3890                 wpa_cli_quit = 1;
3891         }
3892 }
3893
3894
3895 #ifndef CONFIG_ANSI_C_EXTRA
3896 static void wpa_cli_action_cb(char *msg, size_t len)
3897 {
3898         wpa_cli_action_process(msg);
3899 }
3900 #endif /* CONFIG_ANSI_C_EXTRA */
3901
3902
3903 static void wpa_cli_reconnect(void)
3904 {
3905         wpa_cli_close_connection();
3906         if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3907                 return;
3908
3909         if (interactive) {
3910                 edit_clear_line();
3911                 printf("\rConnection to wpa_supplicant re-established\n");
3912                 edit_redraw();
3913         }
3914 }
3915
3916
3917 static void cli_event(const char *str)
3918 {
3919         const char *start, *s;
3920
3921         start = os_strchr(str, '>');
3922         if (start == NULL)
3923                 return;
3924
3925         start++;
3926
3927         if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3928                 s = os_strchr(start, ' ');
3929                 if (s == NULL)
3930                         return;
3931                 s = os_strchr(s + 1, ' ');
3932                 if (s == NULL)
3933                         return;
3934                 cli_txt_list_add(&bsses, s + 1);
3935                 return;
3936         }
3937
3938         if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3939                 s = os_strchr(start, ' ');
3940                 if (s == NULL)
3941                         return;
3942                 s = os_strchr(s + 1, ' ');
3943                 if (s == NULL)
3944                         return;
3945                 cli_txt_list_del_addr(&bsses, s + 1);
3946                 return;
3947         }
3948
3949 #ifdef CONFIG_P2P
3950         if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3951                 s = os_strstr(start, " p2p_dev_addr=");
3952                 if (s == NULL)
3953                         return;
3954                 cli_txt_list_add_addr(&p2p_peers, s + 14);
3955                 return;
3956         }
3957
3958         if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3959                 s = os_strstr(start, " p2p_dev_addr=");
3960                 if (s == NULL)
3961                         return;
3962                 cli_txt_list_del_addr(&p2p_peers, s + 14);
3963                 return;
3964         }
3965
3966         if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3967                 s = os_strchr(start, ' ');
3968                 if (s == NULL)
3969                         return;
3970                 cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
3971                 return;
3972         }
3973
3974         if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3975                 s = os_strchr(start, ' ');
3976                 if (s == NULL)
3977                         return;
3978                 cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
3979                 return;
3980         }
3981 #endif /* CONFIG_P2P */
3982 }
3983
3984
3985 static int check_terminating(const char *msg)
3986 {
3987         const char *pos = msg;
3988
3989         if (*pos == '<') {
3990                 /* skip priority */
3991                 pos = os_strchr(pos, '>');
3992                 if (pos)
3993                         pos++;
3994                 else
3995                         pos = msg;
3996         }
3997
3998         if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3999                 edit_clear_line();
4000                 printf("\rConnection to wpa_supplicant lost - trying to "
4001                        "reconnect\n");
4002                 edit_redraw();
4003                 wpa_cli_attached = 0;
4004                 wpa_cli_close_connection();
4005                 return 1;
4006         }
4007
4008         return 0;
4009 }
4010
4011
4012 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
4013 {
4014         if (ctrl_conn == NULL) {
4015                 wpa_cli_reconnect();
4016                 return;
4017         }
4018         while (wpa_ctrl_pending(ctrl) > 0) {
4019                 char buf[4096];
4020                 size_t len = sizeof(buf) - 1;
4021                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
4022                         buf[len] = '\0';
4023                         if (action_monitor)
4024                                 wpa_cli_action_process(buf);
4025                         else {
4026                                 cli_event(buf);
4027                                 if (wpa_cli_show_event(buf)) {
4028                                         edit_clear_line();
4029                                         printf("\r%s\n", buf);
4030                                         edit_redraw();
4031                                 }
4032
4033                                 if (interactive && check_terminating(buf) > 0)
4034                                         return;
4035                         }
4036                 } else {
4037                         printf("Could not read pending message.\n");
4038                         break;
4039                 }
4040         }
4041
4042         if (wpa_ctrl_pending(ctrl) < 0) {
4043                 printf("Connection to wpa_supplicant lost - trying to "
4044                        "reconnect\n");
4045                 wpa_cli_reconnect();
4046         }
4047 }
4048
4049 #define max_args 10
4050
4051 static int tokenize_cmd(char *cmd, char *argv[])
4052 {
4053         char *pos;
4054         int argc = 0;
4055
4056         pos = cmd;
4057         for (;;) {
4058                 while (*pos == ' ')
4059                         pos++;
4060                 if (*pos == '\0')
4061                         break;
4062                 argv[argc] = pos;
4063                 argc++;
4064                 if (argc == max_args)
4065                         break;
4066                 if (*pos == '"') {
4067                         char *pos2 = os_strrchr(pos, '"');
4068                         if (pos2)
4069                                 pos = pos2 + 1;
4070                 }
4071                 while (*pos != '\0' && *pos != ' ')
4072                         pos++;
4073                 if (*pos == ' ')
4074                         *pos++ = '\0';
4075         }
4076
4077         return argc;
4078 }
4079
4080
4081 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
4082 {
4083         if (ctrl_conn) {
4084                 int res;
4085                 char *prefix = ifname_prefix;
4086
4087                 ifname_prefix = NULL;
4088                 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
4089                 ifname_prefix = prefix;
4090                 if (res) {
4091                         printf("Connection to wpa_supplicant lost - trying to "
4092                                "reconnect\n");
4093                         wpa_cli_close_connection();
4094                 }
4095         }
4096         if (!ctrl_conn)
4097                 wpa_cli_reconnect();
4098         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4099 }
4100
4101
4102 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
4103 {
4104         wpa_cli_recv_pending(mon_conn, 0);
4105 }
4106
4107
4108 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
4109 {
4110         char *argv[max_args];
4111         int argc;
4112         argc = tokenize_cmd(cmd, argv);
4113         if (argc)
4114                 wpa_request(ctrl_conn, argc, argv);
4115 }
4116
4117
4118 static void wpa_cli_edit_eof_cb(void *ctx)
4119 {
4120         eloop_terminate();
4121 }
4122
4123
4124 static int warning_displayed = 0;
4125 static char *hfile = NULL;
4126 static int edit_started = 0;
4127
4128 static void start_edit(void)
4129 {
4130         char *home;
4131         char *ps = NULL;
4132
4133 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
4134         ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
4135 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
4136
4137 #ifdef CONFIG_WPA_CLI_HISTORY_DIR
4138         home = CONFIG_WPA_CLI_HISTORY_DIR;
4139 #else /* CONFIG_WPA_CLI_HISTORY_DIR */
4140         home = getenv("HOME");
4141 #endif /* CONFIG_WPA_CLI_HISTORY_DIR */
4142         if (home) {
4143                 const char *fname = ".wpa_cli_history";
4144                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
4145                 hfile = os_malloc(hfile_len);
4146                 if (hfile)
4147                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
4148         }
4149
4150         if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
4151                       wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4152                 eloop_terminate();
4153                 return;
4154         }
4155
4156         edit_started = 1;
4157         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4158 }
4159
4160
4161 static void update_bssid_list(struct wpa_ctrl *ctrl)
4162 {
4163         char buf[4096];
4164         size_t len = sizeof(buf);
4165         int ret;
4166         char *cmd = "BSS RANGE=ALL MASK=0x2";
4167         char *pos, *end;
4168
4169         if (ctrl == NULL)
4170                 return;
4171         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4172         if (ret < 0)
4173                 return;
4174         buf[len] = '\0';
4175
4176         pos = buf;
4177         while (pos) {
4178                 pos = os_strstr(pos, "bssid=");
4179                 if (pos == NULL)
4180                         break;
4181                 pos += 6;
4182                 end = os_strchr(pos, '\n');
4183                 if (end == NULL)
4184                         break;
4185                 *end = '\0';
4186                 cli_txt_list_add(&bsses, pos);
4187                 pos = end + 1;
4188         }
4189 }
4190
4191
4192 static void update_ifnames(struct wpa_ctrl *ctrl)
4193 {
4194         char buf[4096];
4195         size_t len = sizeof(buf);
4196         int ret;
4197         char *cmd = "INTERFACES";
4198         char *pos, *end;
4199         char txt[200];
4200
4201         cli_txt_list_flush(&ifnames);
4202
4203         if (ctrl == NULL)
4204                 return;
4205         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4206         if (ret < 0)
4207                 return;
4208         buf[len] = '\0';
4209
4210         pos = buf;
4211         while (pos) {
4212                 end = os_strchr(pos, '\n');
4213                 if (end == NULL)
4214                         break;
4215                 *end = '\0';
4216                 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
4217                 if (!os_snprintf_error(sizeof(txt), ret))
4218                         cli_txt_list_add(&ifnames, txt);
4219                 pos = end + 1;
4220         }
4221 }
4222
4223
4224 static void update_networks(struct wpa_ctrl *ctrl)
4225 {
4226         char buf[4096];
4227         size_t len = sizeof(buf);
4228         int ret;
4229         char *cmd = "LIST_NETWORKS";
4230         char *pos, *end;
4231         int header = 1;
4232
4233         cli_txt_list_flush(&networks);
4234
4235         if (ctrl == NULL)
4236                 return;
4237         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4238         if (ret < 0)
4239                 return;
4240         buf[len] = '\0';
4241
4242         pos = buf;
4243         while (pos) {
4244                 end = os_strchr(pos, '\n');
4245                 if (end == NULL)
4246                         break;
4247                 *end = '\0';
4248                 if (!header)
4249                         cli_txt_list_add_word(&networks, pos, '\t');
4250                 header = 0;
4251                 pos = end + 1;
4252         }
4253 }
4254
4255
4256 static void try_connection(void *eloop_ctx, void *timeout_ctx)
4257 {
4258         if (ctrl_conn)
4259                 goto done;
4260
4261         if (ctrl_ifname == NULL)
4262                 ctrl_ifname = wpa_cli_get_default_ifname();
4263
4264         if (wpa_cli_open_connection(ctrl_ifname, 1)) {
4265                 if (!warning_displayed) {
4266                         printf("Could not connect to wpa_supplicant: "
4267                                "%s - re-trying\n",
4268                                ctrl_ifname ? ctrl_ifname : "(nil)");
4269                         warning_displayed = 1;
4270                 }
4271                 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4272                 return;
4273         }
4274
4275         update_bssid_list(ctrl_conn);
4276         update_networks(ctrl_conn);
4277
4278         if (warning_displayed)
4279                 printf("Connection established.\n");
4280
4281 done:
4282         start_edit();
4283 }
4284
4285
4286 static void wpa_cli_interactive(void)
4287 {
4288         printf("\nInteractive mode\n\n");
4289
4290         eloop_register_timeout(0, 0, try_connection, NULL, NULL);
4291         eloop_run();
4292         eloop_cancel_timeout(try_connection, NULL, NULL);
4293
4294         cli_txt_list_flush(&p2p_peers);
4295         cli_txt_list_flush(&p2p_groups);
4296         cli_txt_list_flush(&bsses);
4297         cli_txt_list_flush(&ifnames);
4298         cli_txt_list_flush(&networks);
4299         if (edit_started)
4300                 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
4301         os_free(hfile);
4302         eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4303         wpa_cli_close_connection();
4304 }
4305
4306
4307 static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
4308 {
4309         struct wpa_ctrl *ctrl = eloop_ctx;
4310         char buf[256];
4311         size_t len;
4312
4313         /* verify that connection is still working */
4314         len = sizeof(buf) - 1;
4315         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4316                              wpa_cli_action_cb) < 0 ||
4317             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4318                 printf("wpa_supplicant did not reply to PING command - exiting\n");
4319                 eloop_terminate();
4320                 return;
4321         }
4322         eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4323                                ctrl, NULL);
4324 }
4325
4326
4327 static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
4328 {
4329         struct wpa_ctrl *ctrl = eloop_ctx;
4330
4331         wpa_cli_recv_pending(ctrl, 1);
4332 }
4333
4334
4335 static void wpa_cli_action(struct wpa_ctrl *ctrl)
4336 {
4337 #ifdef CONFIG_ANSI_C_EXTRA
4338         /* TODO: ANSI C version(?) */
4339         printf("Action processing not supported in ANSI C build.\n");
4340 #else /* CONFIG_ANSI_C_EXTRA */
4341         int fd;
4342
4343         fd = wpa_ctrl_get_fd(ctrl);
4344         eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4345                                ctrl, NULL);
4346         eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
4347         eloop_run();
4348         eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
4349         eloop_unregister_read_sock(fd);
4350 #endif /* CONFIG_ANSI_C_EXTRA */
4351 }
4352
4353
4354 static void wpa_cli_cleanup(void)
4355 {
4356         wpa_cli_close_connection();
4357         if (pid_file)
4358                 os_daemonize_terminate(pid_file);
4359
4360         os_program_deinit();
4361 }
4362
4363
4364 static void wpa_cli_terminate(int sig, void *ctx)
4365 {
4366         eloop_terminate();
4367 }
4368
4369
4370 static char * wpa_cli_get_default_ifname(void)
4371 {
4372         char *ifname = NULL;
4373
4374 #ifdef ANDROID
4375         char ifprop[PROPERTY_VALUE_MAX];
4376         if (property_get("wifi.interface", ifprop, NULL) != 0) {
4377                 ifname = os_strdup(ifprop);
4378                 printf("Using interface '%s'\n", ifname ? ifname : "N/A");
4379         }
4380 #else /* ANDROID */
4381 #ifdef CONFIG_CTRL_IFACE_UNIX
4382         struct dirent *dent;
4383         DIR *dir = opendir(ctrl_iface_dir);
4384         if (!dir) {
4385                 return NULL;
4386         }
4387         while ((dent = readdir(dir))) {
4388 #ifdef _DIRENT_HAVE_D_TYPE
4389                 /*
4390                  * Skip the file if it is not a socket. Also accept
4391                  * DT_UNKNOWN (0) in case the C library or underlying
4392                  * file system does not support d_type.
4393                  */
4394                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4395                         continue;
4396 #endif /* _DIRENT_HAVE_D_TYPE */
4397                 if (os_strcmp(dent->d_name, ".") == 0 ||
4398                     os_strcmp(dent->d_name, "..") == 0)
4399                         continue;
4400                 printf("Selected interface '%s'\n", dent->d_name);
4401                 ifname = os_strdup(dent->d_name);
4402                 break;
4403         }
4404         closedir(dir);
4405 #endif /* CONFIG_CTRL_IFACE_UNIX */
4406
4407 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4408         char buf[4096], *pos;
4409         size_t len;
4410         struct wpa_ctrl *ctrl;
4411         int ret;
4412
4413         ctrl = wpa_ctrl_open(NULL);
4414         if (ctrl == NULL)
4415                 return NULL;
4416
4417         len = sizeof(buf) - 1;
4418         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4419         if (ret >= 0) {
4420                 buf[len] = '\0';
4421                 pos = os_strchr(buf, '\n');
4422                 if (pos)
4423                         *pos = '\0';
4424                 ifname = os_strdup(buf);
4425         }
4426         wpa_ctrl_close(ctrl);
4427 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4428 #endif /* ANDROID */
4429
4430         return ifname;
4431 }
4432
4433
4434 int main(int argc, char *argv[])
4435 {
4436         int c;
4437         int daemonize = 0;
4438         int ret = 0;
4439         const char *global = NULL;
4440
4441         if (os_program_init())
4442                 return -1;
4443
4444         for (;;) {
4445                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
4446                 if (c < 0)
4447                         break;
4448                 switch (c) {
4449                 case 'a':
4450                         action_file = optarg;
4451                         break;
4452                 case 'B':
4453                         daemonize = 1;
4454                         break;
4455                 case 'g':
4456                         global = optarg;
4457                         break;
4458                 case 'G':
4459                         ping_interval = atoi(optarg);
4460                         break;
4461                 case 'h':
4462                         usage();
4463                         return 0;
4464                 case 'v':
4465                         printf("%s\n", wpa_cli_version);
4466                         return 0;
4467                 case 'i':
4468                         os_free(ctrl_ifname);
4469                         ctrl_ifname = os_strdup(optarg);
4470                         break;
4471                 case 'p':
4472                         ctrl_iface_dir = optarg;
4473                         break;
4474                 case 'P':
4475                         pid_file = optarg;
4476                         break;
4477                 case 's':
4478                         client_socket_dir = optarg;
4479                         break;
4480                 default:
4481                         usage();
4482                         return -1;
4483                 }
4484         }
4485
4486         interactive = (argc == optind) && (action_file == NULL);
4487
4488         if (interactive)
4489                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4490
4491         if (eloop_init())
4492                 return -1;
4493
4494         if (global) {
4495 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4496                 ctrl_conn = wpa_ctrl_open(NULL);
4497 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4498                 ctrl_conn = wpa_ctrl_open(global);
4499 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4500                 if (ctrl_conn == NULL) {
4501                         fprintf(stderr, "Failed to connect to wpa_supplicant "
4502                                 "global interface: %s  error: %s\n",
4503                                 global, strerror(errno));
4504                         return -1;
4505                 }
4506
4507                 if (interactive) {
4508                         update_ifnames(ctrl_conn);
4509                         mon_conn = wpa_ctrl_open(global);
4510                         if (mon_conn) {
4511                                 if (wpa_ctrl_attach(mon_conn) == 0) {
4512                                         wpa_cli_attached = 1;
4513                                         eloop_register_read_sock(
4514                                                 wpa_ctrl_get_fd(mon_conn),
4515                                                 wpa_cli_mon_receive,
4516                                                 NULL, NULL);
4517                                 } else {
4518                                         printf("Failed to open monitor "
4519                                                "connection through global "
4520                                                "control interface\n");
4521                                 }
4522                         }
4523                 }
4524         }
4525
4526         eloop_register_signal_terminate(wpa_cli_terminate, NULL);
4527
4528         if (ctrl_ifname == NULL)
4529                 ctrl_ifname = wpa_cli_get_default_ifname();
4530
4531         if (interactive) {
4532                 wpa_cli_interactive();
4533         } else {
4534                 if (!global &&
4535                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4536                         fprintf(stderr, "Failed to connect to non-global "
4537                                 "ctrl_ifname: %s  error: %s\n",
4538                                 ctrl_ifname ? ctrl_ifname : "(nil)",
4539                                 strerror(errno));
4540                         return -1;
4541                 }
4542
4543                 if (action_file) {
4544                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
4545                                 wpa_cli_attached = 1;
4546                         } else {
4547                                 printf("Warning: Failed to attach to "
4548                                        "wpa_supplicant.\n");
4549                                 return -1;
4550                         }
4551                 }
4552
4553                 if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
4554                         return -1;
4555
4556                 if (action_file)
4557                         wpa_cli_action(ctrl_conn);
4558                 else
4559                         ret = wpa_request(ctrl_conn, argc - optind,
4560                                           &argv[optind]);
4561         }
4562
4563         os_free(ctrl_ifname);
4564         eloop_destroy();
4565         wpa_cli_cleanup();
4566
4567         return ret;
4568 }
4569
4570 #else /* CONFIG_CTRL_IFACE */
4571 int main(int argc, char *argv[])
4572 {
4573         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4574         return -1;
4575 }
4576 #endif /* CONFIG_CTRL_IFACE */