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