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