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