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