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