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