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