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