Add chan_switch to ctrl interface of wpa_supplicant and hostapd
[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-2013, 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 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2416 {
2417         return wpa_ctrl_command(ctrl, "FLUSH");
2418 }
2419
2420
2421 enum wpa_cli_cmd_flags {
2422         cli_cmd_flag_none               = 0x00,
2423         cli_cmd_flag_sensitive          = 0x01
2424 };
2425
2426 struct wpa_cli_cmd {
2427         const char *cmd;
2428         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2429         char ** (*completion)(const char *str, int pos);
2430         enum wpa_cli_cmd_flags flags;
2431         const char *usage;
2432 };
2433
2434 static struct wpa_cli_cmd wpa_cli_commands[] = {
2435         { "status", wpa_cli_cmd_status, NULL,
2436           cli_cmd_flag_none,
2437           "[verbose] = get current WPA/EAPOL/EAP status" },
2438         { "ifname", wpa_cli_cmd_ifname, NULL,
2439           cli_cmd_flag_none,
2440           "= get current interface name" },
2441         { "ping", wpa_cli_cmd_ping, NULL,
2442           cli_cmd_flag_none,
2443           "= pings wpa_supplicant" },
2444         { "relog", wpa_cli_cmd_relog, NULL,
2445           cli_cmd_flag_none,
2446           "= re-open log-file (allow rolling logs)" },
2447         { "note", wpa_cli_cmd_note, NULL,
2448           cli_cmd_flag_none,
2449           "<text> = add a note to wpa_supplicant debug log" },
2450         { "mib", wpa_cli_cmd_mib, NULL,
2451           cli_cmd_flag_none,
2452           "= get MIB variables (dot1x, dot11)" },
2453         { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2454           cli_cmd_flag_none,
2455           "[command] = show usage help" },
2456         { "interface", wpa_cli_cmd_interface, NULL,
2457           cli_cmd_flag_none,
2458           "[ifname] = show interfaces/select interface" },
2459         { "level", wpa_cli_cmd_level, NULL,
2460           cli_cmd_flag_none,
2461           "<debug level> = change debug level" },
2462         { "license", wpa_cli_cmd_license, NULL,
2463           cli_cmd_flag_none,
2464           "= show full wpa_cli license" },
2465         { "quit", wpa_cli_cmd_quit, NULL,
2466           cli_cmd_flag_none,
2467           "= exit wpa_cli" },
2468         { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2469           cli_cmd_flag_none,
2470           "= set variables (shows list of variables when run without "
2471           "arguments)" },
2472         { "get", wpa_cli_cmd_get, NULL,
2473           cli_cmd_flag_none,
2474           "<name> = get information" },
2475         { "logon", wpa_cli_cmd_logon, NULL,
2476           cli_cmd_flag_none,
2477           "= IEEE 802.1X EAPOL state machine logon" },
2478         { "logoff", wpa_cli_cmd_logoff, NULL,
2479           cli_cmd_flag_none,
2480           "= IEEE 802.1X EAPOL state machine logoff" },
2481         { "pmksa", wpa_cli_cmd_pmksa, NULL,
2482           cli_cmd_flag_none,
2483           "= show PMKSA cache" },
2484         { "reassociate", wpa_cli_cmd_reassociate, NULL,
2485           cli_cmd_flag_none,
2486           "= force reassociation" },
2487         { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2488           cli_cmd_flag_none,
2489           "<BSSID> = force preauthentication" },
2490         { "identity", wpa_cli_cmd_identity, NULL,
2491           cli_cmd_flag_none,
2492           "<network id> <identity> = configure identity for an SSID" },
2493         { "password", wpa_cli_cmd_password, NULL,
2494           cli_cmd_flag_sensitive,
2495           "<network id> <password> = configure password for an SSID" },
2496         { "new_password", wpa_cli_cmd_new_password, NULL,
2497           cli_cmd_flag_sensitive,
2498           "<network id> <password> = change password for an SSID" },
2499         { "pin", wpa_cli_cmd_pin, NULL,
2500           cli_cmd_flag_sensitive,
2501           "<network id> <pin> = configure pin for an SSID" },
2502         { "otp", wpa_cli_cmd_otp, NULL,
2503           cli_cmd_flag_sensitive,
2504           "<network id> <password> = configure one-time-password for an SSID"
2505         },
2506         { "passphrase", wpa_cli_cmd_passphrase, NULL,
2507           cli_cmd_flag_sensitive,
2508           "<network id> <passphrase> = configure private key passphrase\n"
2509           "  for an SSID" },
2510         { "sim", wpa_cli_cmd_sim, NULL,
2511           cli_cmd_flag_sensitive,
2512           "<network id> <pin> = report SIM operation result" },
2513         { "bssid", wpa_cli_cmd_bssid, NULL,
2514           cli_cmd_flag_none,
2515           "<network id> <BSSID> = set preferred BSSID for an SSID" },
2516         { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2517           cli_cmd_flag_none,
2518           "<BSSID> = add a BSSID to the blacklist\n"
2519           "blacklist clear = clear the blacklist\n"
2520           "blacklist = display the blacklist" },
2521         { "log_level", wpa_cli_cmd_log_level, NULL,
2522           cli_cmd_flag_none,
2523           "<level> [<timestamp>] = update the log level/timestamp\n"
2524           "log_level = display the current log level and log options" },
2525         { "list_networks", wpa_cli_cmd_list_networks, NULL,
2526           cli_cmd_flag_none,
2527           "= list configured networks" },
2528         { "select_network", wpa_cli_cmd_select_network, NULL,
2529           cli_cmd_flag_none,
2530           "<network id> = select a network (disable others)" },
2531         { "enable_network", wpa_cli_cmd_enable_network, NULL,
2532           cli_cmd_flag_none,
2533           "<network id> = enable a network" },
2534         { "disable_network", wpa_cli_cmd_disable_network, NULL,
2535           cli_cmd_flag_none,
2536           "<network id> = disable a network" },
2537         { "add_network", wpa_cli_cmd_add_network, NULL,
2538           cli_cmd_flag_none,
2539           "= add a network" },
2540         { "remove_network", wpa_cli_cmd_remove_network, NULL,
2541           cli_cmd_flag_none,
2542           "<network id> = remove a network" },
2543         { "set_network", wpa_cli_cmd_set_network, NULL,
2544           cli_cmd_flag_sensitive,
2545           "<network id> <variable> <value> = set network variables (shows\n"
2546           "  list of variables when run without arguments)" },
2547         { "get_network", wpa_cli_cmd_get_network, NULL,
2548           cli_cmd_flag_none,
2549           "<network id> <variable> = get network variables" },
2550         { "list_creds", wpa_cli_cmd_list_creds, NULL,
2551           cli_cmd_flag_none,
2552           "= list configured credentials" },
2553         { "add_cred", wpa_cli_cmd_add_cred, NULL,
2554           cli_cmd_flag_none,
2555           "= add a credential" },
2556         { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2557           cli_cmd_flag_none,
2558           "<cred id> = remove a credential" },
2559         { "set_cred", wpa_cli_cmd_set_cred, NULL,
2560           cli_cmd_flag_sensitive,
2561           "<cred id> <variable> <value> = set credential variables" },
2562         { "save_config", wpa_cli_cmd_save_config, NULL,
2563           cli_cmd_flag_none,
2564           "= save the current configuration" },
2565         { "disconnect", wpa_cli_cmd_disconnect, NULL,
2566           cli_cmd_flag_none,
2567           "= disconnect and wait for reassociate/reconnect command before\n"
2568           "  connecting" },
2569         { "reconnect", wpa_cli_cmd_reconnect, NULL,
2570           cli_cmd_flag_none,
2571           "= like reassociate, but only takes effect if already disconnected"
2572         },
2573         { "scan", wpa_cli_cmd_scan, NULL,
2574           cli_cmd_flag_none,
2575           "= request new BSS scan" },
2576         { "scan_results", wpa_cli_cmd_scan_results, NULL,
2577           cli_cmd_flag_none,
2578           "= get latest scan results" },
2579         { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2580           cli_cmd_flag_none,
2581           "<<idx> | <bssid>> = get detailed scan result info" },
2582         { "get_capability", wpa_cli_cmd_get_capability, NULL,
2583           cli_cmd_flag_none,
2584           "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2585           "= get capabilies" },
2586         { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2587           cli_cmd_flag_none,
2588           "= force wpa_supplicant to re-read its configuration file" },
2589         { "terminate", wpa_cli_cmd_terminate, NULL,
2590           cli_cmd_flag_none,
2591           "= terminate wpa_supplicant" },
2592         { "interface_add", wpa_cli_cmd_interface_add, NULL,
2593           cli_cmd_flag_none,
2594           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2595           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2596           "  are optional" },
2597         { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2598           cli_cmd_flag_none,
2599           "<ifname> = removes the interface" },
2600         { "interface_list", wpa_cli_cmd_interface_list, NULL,
2601           cli_cmd_flag_none,
2602           "= list available interfaces" },
2603         { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2604           cli_cmd_flag_none,
2605           "<value> = set ap_scan parameter" },
2606         { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2607           cli_cmd_flag_none,
2608           "<value> = set scan_interval parameter (in seconds)" },
2609         { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2610           cli_cmd_flag_none,
2611           "<value> = set BSS expiration age parameter" },
2612         { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2613           cli_cmd_flag_none,
2614           "<value> = set BSS expiration scan count parameter" },
2615         { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2616           cli_cmd_flag_none,
2617           "<value> = set BSS flush age (0 by default)" },
2618         { "stkstart", wpa_cli_cmd_stkstart, NULL,
2619           cli_cmd_flag_none,
2620           "<addr> = request STK negotiation with <addr>" },
2621         { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2622           cli_cmd_flag_none,
2623           "<addr> = request over-the-DS FT with <addr>" },
2624         { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2625           cli_cmd_flag_none,
2626           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2627         { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2628           cli_cmd_flag_sensitive,
2629           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2630           "hardcoded)" },
2631         { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2632           cli_cmd_flag_sensitive,
2633           "<PIN> = verify PIN checksum" },
2634         { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2635           "Cancels the pending WPS operation" },
2636 #ifdef CONFIG_WPS_NFC
2637         { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2638           cli_cmd_flag_none,
2639           "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2640         { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2641           cli_cmd_flag_none,
2642           "<WPS|NDEF> = build configuration token" },
2643         { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2644           cli_cmd_flag_none,
2645           "<WPS|NDEF> = create password token" },
2646         { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2647           cli_cmd_flag_sensitive,
2648           "<hexdump of payload> = report read NFC tag with WPS data" },
2649         { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2650           cli_cmd_flag_none,
2651           "<NDEF> <WPS> = create NFC handover request" },
2652         { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2653           cli_cmd_flag_none,
2654           "<NDEF> <WPS> = create NFC handover select" },
2655         { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2656           cli_cmd_flag_none,
2657           "<hexdump of payload> = report received NFC handover request" },
2658         { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2659           cli_cmd_flag_none,
2660           "<hexdump of payload> = report received NFC handover select" },
2661         { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2662           cli_cmd_flag_none,
2663           "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2664           "NFC handover" },
2665 #endif /* CONFIG_WPS_NFC */
2666         { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2667           cli_cmd_flag_sensitive,
2668           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2669         { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2670           cli_cmd_flag_sensitive,
2671           "[params..] = enable/disable AP PIN" },
2672         { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2673           cli_cmd_flag_none,
2674           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2675         { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2676           cli_cmd_flag_none,
2677           "= stop Wi-Fi Protected Setup External Registrar" },
2678         { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2679           cli_cmd_flag_sensitive,
2680           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2681         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2682           cli_cmd_flag_none,
2683           "<UUID> = accept an Enrollee PBC using External Registrar" },
2684         { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2685           cli_cmd_flag_sensitive,
2686           "<UUID> <PIN> = learn AP configuration" },
2687         { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2688           cli_cmd_flag_none,
2689           "<UUID> <network id> = set AP configuration for enrolling" },
2690         { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2691           cli_cmd_flag_sensitive,
2692           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2693 #ifdef CONFIG_WPS_NFC
2694         { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2695           cli_cmd_flag_none,
2696           "<WPS/NDEF> <UUID> = build NFC configuration token" },
2697 #endif /* CONFIG_WPS_NFC */
2698         { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2699           cli_cmd_flag_none,
2700           "<addr> = request RSN authentication with <addr> in IBSS" },
2701 #ifdef CONFIG_AP
2702         { "sta", wpa_cli_cmd_sta, NULL,
2703           cli_cmd_flag_none,
2704           "<addr> = get information about an associated station (AP)" },
2705         { "all_sta", wpa_cli_cmd_all_sta, NULL,
2706           cli_cmd_flag_none,
2707           "= get information about all associated stations (AP)" },
2708         { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2709           cli_cmd_flag_none,
2710           "<addr> = deauthenticate a station" },
2711         { "disassociate", wpa_cli_cmd_disassociate, NULL,
2712           cli_cmd_flag_none,
2713           "<addr> = disassociate a station" },
2714         { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2715           cli_cmd_flag_none,
2716           "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2717           " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2718           " = CSA parameters" },
2719 #endif /* CONFIG_AP */
2720         { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2721           "= notification of suspend/hibernate" },
2722         { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2723           "= notification of resume/thaw" },
2724         { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2725           "= drop SA without deauth/disassoc (test command)" },
2726         { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2727           cli_cmd_flag_none,
2728           "<addr> = roam to the specified BSS" },
2729 #ifdef CONFIG_P2P
2730         { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2731           cli_cmd_flag_none,
2732           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2733         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2734           "= stop P2P Devices search" },
2735         { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2736           cli_cmd_flag_none,
2737           "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2738         { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2739           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2740         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2741           wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2742           "<ifname> = remove P2P group interface (terminate group if GO)" },
2743         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2744           "[ht40] = add a new P2P group (local end as GO)" },
2745         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2746           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2747           "<addr> <method> = request provisioning discovery" },
2748         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2749           cli_cmd_flag_none,
2750           "= get the passphrase for a group (GO only)" },
2751         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2752           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2753           "<addr> <TLVs> = schedule service discovery request" },
2754         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2755           NULL, cli_cmd_flag_none,
2756           "<id> = cancel pending service discovery request" },
2757         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2758           cli_cmd_flag_none,
2759           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2760         { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2761           cli_cmd_flag_none,
2762           "= indicate change in local services" },
2763         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2764           cli_cmd_flag_none,
2765           "<external> = set external processing of service discovery" },
2766         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2767           cli_cmd_flag_none,
2768           "= remove all stored service entries" },
2769         { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2770           cli_cmd_flag_none,
2771           "<bonjour|upnp> <query|version> <response|service> = add a local "
2772           "service" },
2773         { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2774           cli_cmd_flag_none,
2775           "<bonjour|upnp> <query|version> [|service] = remove a local "
2776           "service" },
2777         { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2778           cli_cmd_flag_none,
2779           "<addr> = reject connection attempts from a specific peer" },
2780         { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2781           cli_cmd_flag_none,
2782           "<cmd> [peer=addr] = invite peer" },
2783         { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2784           "[discovered] = list known (optionally, only fully discovered) P2P "
2785           "peers" },
2786         { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2787           cli_cmd_flag_none,
2788           "<address> = show information about known P2P peer" },
2789         { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2790           cli_cmd_flag_none,
2791           "<field> <value> = set a P2P parameter" },
2792         { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2793           "= flush P2P state" },
2794         { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2795           "= cancel P2P group formation" },
2796         { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2797           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2798           "<address> = unauthorize a peer" },
2799         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2800           cli_cmd_flag_none,
2801           "[<duration> <interval>] [<duration> <interval>] = request GO "
2802           "presence" },
2803         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2804           cli_cmd_flag_none,
2805           "[<period> <interval>] = set extended listen timing" },
2806         { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2807           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2808           "<address|iface=address> = remove a peer from all groups" },
2809 #endif /* CONFIG_P2P */
2810 #ifdef CONFIG_WIFI_DISPLAY
2811         { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2812           cli_cmd_flag_none,
2813           "<subelem> [contents] = set Wi-Fi Display subelement" },
2814         { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2815           cli_cmd_flag_none,
2816           "<subelem> = get Wi-Fi Display subelement" },
2817 #endif /* CONFIG_WIFI_DISPLAY */
2818 #ifdef CONFIG_INTERWORKING
2819         { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
2820           "= fetch ANQP information for all APs" },
2821         { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2822           cli_cmd_flag_none,
2823           "= stop fetch_anqp operation" },
2824         { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
2825           cli_cmd_flag_none,
2826           "[auto] = perform Interworking network selection" },
2827         { "interworking_connect", wpa_cli_cmd_interworking_connect,
2828           wpa_cli_complete_bss, cli_cmd_flag_none,
2829           "<BSSID> = connect using Interworking credentials" },
2830         { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2831           cli_cmd_flag_none,
2832           "<addr> <info id>[,<info id>]... = request ANQP information" },
2833         { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2834           cli_cmd_flag_none,
2835           "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2836         { "gas_response_get", wpa_cli_cmd_gas_response_get,
2837           wpa_cli_complete_bss, cli_cmd_flag_none,
2838           "<addr> <dialog token> [start,len] = Fetch last GAS response" },
2839 #endif /* CONFIG_INTERWORKING */
2840 #ifdef CONFIG_HS20
2841         { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2842           cli_cmd_flag_none,
2843           "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2844         },
2845         { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
2846           wpa_cli_complete_bss, cli_cmd_flag_none,
2847           "<addr> <home realm> = get HS20 nai home realm list" },
2848 #endif /* CONFIG_HS20 */
2849         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2850           cli_cmd_flag_none,
2851           "<0/1> = disable/enable automatic reconnection" },
2852         { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
2853           cli_cmd_flag_none,
2854           "<addr> = request TDLS discovery with <addr>" },
2855         { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
2856           cli_cmd_flag_none,
2857           "<addr> = request TDLS setup with <addr>" },
2858         { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
2859           cli_cmd_flag_none,
2860           "<addr> = tear down TDLS with <addr>" },
2861         { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
2862           cli_cmd_flag_none,
2863           "= get signal parameters" },
2864         { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2865           cli_cmd_flag_none,
2866           "= get TX/RX packet counters" },
2867         { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2868           cli_cmd_flag_none,
2869           "= trigger IEEE 802.1X/EAPOL reauthentication" },
2870 #ifdef CONFIG_AUTOSCAN
2871         { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2872           "[params] = Set or unset (if none) autoscan parameters" },
2873 #endif /* CONFIG_AUTOSCAN */
2874 #ifdef CONFIG_WNM
2875         { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2876           "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2877         { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2878           "<query reason> = Send BSS Transition Management Query" },
2879 #endif /* CONFIG_WNM */
2880         { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2881           "<params..> = Sent unprocessed command" },
2882         { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2883           "= flush wpa_supplicant state" },
2884         { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
2885 };
2886
2887
2888 /*
2889  * Prints command usage, lines are padded with the specified string.
2890  */
2891 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2892 {
2893         char c;
2894         size_t n;
2895
2896         printf("%s%s ", pad, cmd->cmd);
2897         for (n = 0; (c = cmd->usage[n]); n++) {
2898                 printf("%c", c);
2899                 if (c == '\n')
2900                         printf("%s", pad);
2901         }
2902         printf("\n");
2903 }
2904
2905
2906 static void print_help(const char *cmd)
2907 {
2908         int n;
2909         printf("commands:\n");
2910         for (n = 0; wpa_cli_commands[n].cmd; n++) {
2911                 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2912                         print_cmd_help(&wpa_cli_commands[n], "  ");
2913         }
2914 }
2915
2916
2917 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2918 {
2919         const char *c, *delim;
2920         int n;
2921         size_t len;
2922
2923         delim = os_strchr(cmd, ' ');
2924         if (delim)
2925                 len = delim - cmd;
2926         else
2927                 len = os_strlen(cmd);
2928
2929         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2930                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2931                         return (wpa_cli_commands[n].flags &
2932                                 cli_cmd_flag_sensitive);
2933         }
2934         return 0;
2935 }
2936
2937
2938 static char ** wpa_list_cmd_list(void)
2939 {
2940         char **res;
2941         int i, count;
2942         struct cli_txt_entry *e;
2943
2944         count = ARRAY_SIZE(wpa_cli_commands);
2945         count += dl_list_len(&p2p_groups);
2946         count += dl_list_len(&ifnames);
2947         res = os_calloc(count + 1, sizeof(char *));
2948         if (res == NULL)
2949                 return NULL;
2950
2951         for (i = 0; wpa_cli_commands[i].cmd; i++) {
2952                 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2953                 if (res[i] == NULL)
2954                         break;
2955         }
2956
2957         dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2958                 size_t len = 8 + os_strlen(e->txt);
2959                 res[i] = os_malloc(len);
2960                 if (res[i] == NULL)
2961                         break;
2962                 os_snprintf(res[i], len, "ifname=%s", e->txt);
2963                 i++;
2964         }
2965
2966         dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2967                 res[i] = os_strdup(e->txt);
2968                 if (res[i] == NULL)
2969                         break;
2970                 i++;
2971         }
2972
2973         return res;
2974 }
2975
2976
2977 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2978                                       int pos)
2979 {
2980         int i;
2981
2982         for (i = 0; wpa_cli_commands[i].cmd; i++) {
2983                 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2984                         if (wpa_cli_commands[i].completion)
2985                                 return wpa_cli_commands[i].completion(str,
2986                                                                       pos);
2987                         edit_clear_line();
2988                         printf("\r%s\n", wpa_cli_commands[i].usage);
2989                         edit_redraw();
2990                         break;
2991                 }
2992         }
2993
2994         return NULL;
2995 }
2996
2997
2998 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2999 {
3000         char **res;
3001         const char *end;
3002         char *cmd;
3003
3004         if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3005                 end = os_strchr(str, ' ');
3006                 if (end && pos > end - str) {
3007                         pos -= end - str + 1;
3008                         str = end + 1;
3009                 }
3010         }
3011
3012         end = os_strchr(str, ' ');
3013         if (end == NULL || str + pos < end)
3014                 return wpa_list_cmd_list();
3015
3016         cmd = os_malloc(pos + 1);
3017         if (cmd == NULL)
3018                 return NULL;
3019         os_memcpy(cmd, str, pos);
3020         cmd[end - str] = '\0';
3021         res = wpa_cli_cmd_completion(cmd, str, pos);
3022         os_free(cmd);
3023         return res;
3024 }
3025
3026
3027 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3028 {
3029         struct wpa_cli_cmd *cmd, *match = NULL;
3030         int count;
3031         int ret = 0;
3032
3033         if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3034                 ifname_prefix = argv[0] + 7;
3035                 argv = &argv[1];
3036                 argc--;
3037         } else
3038                 ifname_prefix = NULL;
3039
3040         if (argc == 0)
3041                 return -1;
3042
3043         count = 0;
3044         cmd = wpa_cli_commands;
3045         while (cmd->cmd) {
3046                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3047                 {
3048                         match = cmd;
3049                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3050                                 /* we have an exact match */
3051                                 count = 1;
3052                                 break;
3053                         }
3054                         count++;
3055                 }
3056                 cmd++;
3057         }
3058
3059         if (count > 1) {
3060                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3061                 cmd = wpa_cli_commands;
3062                 while (cmd->cmd) {
3063                         if (os_strncasecmp(cmd->cmd, argv[0],
3064                                            os_strlen(argv[0])) == 0) {
3065                                 printf(" %s", cmd->cmd);
3066                         }
3067                         cmd++;
3068                 }
3069                 printf("\n");
3070                 ret = 1;
3071         } else if (count == 0) {
3072                 printf("Unknown command '%s'\n", argv[0]);
3073                 ret = 1;
3074         } else {
3075                 ret = match->handler(ctrl, argc - 1, &argv[1]);
3076         }
3077
3078         return ret;
3079 }
3080
3081
3082 static int str_match(const char *a, const char *b)
3083 {
3084         return os_strncmp(a, b, os_strlen(b)) == 0;
3085 }
3086
3087
3088 static int wpa_cli_exec(const char *program, const char *arg1,
3089                         const char *arg2)
3090 {
3091         char *cmd;
3092         size_t len;
3093         int res;
3094         int ret = 0;
3095
3096         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3097         cmd = os_malloc(len);
3098         if (cmd == NULL)
3099                 return -1;
3100         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3101         if (res < 0 || (size_t) res >= len) {
3102                 os_free(cmd);
3103                 return -1;
3104         }
3105         cmd[len - 1] = '\0';
3106 #ifndef _WIN32_WCE
3107         if (system(cmd) < 0)
3108                 ret = -1;
3109 #endif /* _WIN32_WCE */
3110         os_free(cmd);
3111
3112         return ret;
3113 }
3114
3115
3116 static void wpa_cli_action_process(const char *msg)
3117 {
3118         const char *pos;
3119         char *copy = NULL, *id, *pos2;
3120
3121         pos = msg;
3122         if (*pos == '<') {
3123                 /* skip priority */
3124                 pos = os_strchr(pos, '>');
3125                 if (pos)
3126                         pos++;
3127                 else
3128                         pos = msg;
3129         }
3130
3131         if (str_match(pos, WPA_EVENT_CONNECTED)) {
3132                 int new_id = -1;
3133                 os_unsetenv("WPA_ID");
3134                 os_unsetenv("WPA_ID_STR");
3135                 os_unsetenv("WPA_CTRL_DIR");
3136
3137                 pos = os_strstr(pos, "[id=");
3138                 if (pos)
3139                         copy = os_strdup(pos + 4);
3140
3141                 if (copy) {
3142                         pos2 = id = copy;
3143                         while (*pos2 && *pos2 != ' ')
3144                                 pos2++;
3145                         *pos2++ = '\0';
3146                         new_id = atoi(id);
3147                         os_setenv("WPA_ID", id, 1);
3148                         while (*pos2 && *pos2 != '=')
3149                                 pos2++;
3150                         if (*pos2 == '=')
3151                                 pos2++;
3152                         id = pos2;
3153                         while (*pos2 && *pos2 != ']')
3154                                 pos2++;
3155                         *pos2 = '\0';
3156                         os_setenv("WPA_ID_STR", id, 1);
3157                         os_free(copy);
3158                 }
3159
3160                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3161
3162                 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3163                         wpa_cli_connected = 1;
3164                         wpa_cli_last_id = new_id;
3165                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3166                 }
3167         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3168                 if (wpa_cli_connected) {
3169                         wpa_cli_connected = 0;
3170                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3171                 }
3172         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3173                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3174         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3175                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3176         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3177                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3178         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3179                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3180         } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3181                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3182         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3183                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3184         } else if (str_match(pos, WPS_EVENT_FAIL)) {
3185                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3186         } else if (str_match(pos, AP_STA_CONNECTED)) {
3187                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3188         } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3189                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3190         } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3191                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3192         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3193                 printf("wpa_supplicant is terminating - stop monitoring\n");
3194                 wpa_cli_quit = 1;
3195         }
3196 }
3197
3198
3199 #ifndef CONFIG_ANSI_C_EXTRA
3200 static void wpa_cli_action_cb(char *msg, size_t len)
3201 {
3202         wpa_cli_action_process(msg);
3203 }
3204 #endif /* CONFIG_ANSI_C_EXTRA */
3205
3206
3207 static void wpa_cli_reconnect(void)
3208 {
3209         wpa_cli_close_connection();
3210         if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3211                 return;
3212
3213         if (interactive) {
3214                 edit_clear_line();
3215                 printf("\rConnection to wpa_supplicant re-established\n");
3216                 edit_redraw();
3217         }
3218 }
3219
3220
3221 static void cli_event(const char *str)
3222 {
3223         const char *start, *s;
3224
3225         start = os_strchr(str, '>');
3226         if (start == NULL)
3227                 return;
3228
3229         start++;
3230
3231         if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3232                 s = os_strchr(start, ' ');
3233                 if (s == NULL)
3234                         return;
3235                 s = os_strchr(s + 1, ' ');
3236                 if (s == NULL)
3237                         return;
3238                 cli_txt_list_add(&bsses, s + 1);
3239                 return;
3240         }
3241
3242         if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3243                 s = os_strchr(start, ' ');
3244                 if (s == NULL)
3245                         return;
3246                 s = os_strchr(s + 1, ' ');
3247                 if (s == NULL)
3248                         return;
3249                 cli_txt_list_del_addr(&bsses, s + 1);
3250                 return;
3251         }
3252
3253 #ifdef CONFIG_P2P
3254         if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3255                 s = os_strstr(start, " p2p_dev_addr=");
3256                 if (s == NULL)
3257                         return;
3258                 cli_txt_list_add_addr(&p2p_peers, s + 14);
3259                 return;
3260         }
3261
3262         if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3263                 s = os_strstr(start, " p2p_dev_addr=");
3264                 if (s == NULL)
3265                         return;
3266                 cli_txt_list_del_addr(&p2p_peers, s + 14);
3267                 return;
3268         }
3269
3270         if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3271                 s = os_strchr(start, ' ');
3272                 if (s == NULL)
3273                         return;
3274                 cli_txt_list_add_word(&p2p_groups, s + 1);
3275                 return;
3276         }
3277
3278         if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3279                 s = os_strchr(start, ' ');
3280                 if (s == NULL)
3281                         return;
3282                 cli_txt_list_del_word(&p2p_groups, s + 1);
3283                 return;
3284         }
3285 #endif /* CONFIG_P2P */
3286 }
3287
3288
3289 static int check_terminating(const char *msg)
3290 {
3291         const char *pos = msg;
3292
3293         if (*pos == '<') {
3294                 /* skip priority */
3295                 pos = os_strchr(pos, '>');
3296                 if (pos)
3297                         pos++;
3298                 else
3299                         pos = msg;
3300         }
3301
3302         if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3303                 edit_clear_line();
3304                 printf("\rConnection to wpa_supplicant lost - trying to "
3305                        "reconnect\n");
3306                 edit_redraw();
3307                 wpa_cli_attached = 0;
3308                 wpa_cli_close_connection();
3309                 return 1;
3310         }
3311
3312         return 0;
3313 }
3314
3315
3316 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3317 {
3318         if (ctrl_conn == NULL) {
3319                 wpa_cli_reconnect();
3320                 return;
3321         }
3322         while (wpa_ctrl_pending(ctrl) > 0) {
3323                 char buf[256];
3324                 size_t len = sizeof(buf) - 1;
3325                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3326                         buf[len] = '\0';
3327                         if (action_monitor)
3328                                 wpa_cli_action_process(buf);
3329                         else {
3330                                 cli_event(buf);
3331                                 if (wpa_cli_show_event(buf)) {
3332                                         edit_clear_line();
3333                                         printf("\r%s\n", buf);
3334                                         edit_redraw();
3335                                 }
3336
3337                                 if (interactive && check_terminating(buf) > 0)
3338                                         return;
3339                         }
3340                 } else {
3341                         printf("Could not read pending message.\n");
3342                         break;
3343                 }
3344         }
3345
3346         if (wpa_ctrl_pending(ctrl) < 0) {
3347                 printf("Connection to wpa_supplicant lost - trying to "
3348                        "reconnect\n");
3349                 wpa_cli_reconnect();
3350         }
3351 }
3352
3353 #define max_args 10
3354
3355 static int tokenize_cmd(char *cmd, char *argv[])
3356 {
3357         char *pos;
3358         int argc = 0;
3359
3360         pos = cmd;
3361         for (;;) {
3362                 while (*pos == ' ')
3363                         pos++;
3364                 if (*pos == '\0')
3365                         break;
3366                 argv[argc] = pos;
3367                 argc++;
3368                 if (argc == max_args)
3369                         break;
3370                 if (*pos == '"') {
3371                         char *pos2 = os_strrchr(pos, '"');
3372                         if (pos2)
3373                                 pos = pos2 + 1;
3374                 }
3375                 while (*pos != '\0' && *pos != ' ')
3376                         pos++;
3377                 if (*pos == ' ')
3378                         *pos++ = '\0';
3379         }
3380
3381         return argc;
3382 }
3383
3384
3385 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3386 {
3387         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3388                 printf("Connection to wpa_supplicant lost - trying to "
3389                        "reconnect\n");
3390                 wpa_cli_close_connection();
3391         }
3392         if (!ctrl_conn)
3393                 wpa_cli_reconnect();
3394         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3395 }
3396
3397
3398 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3399 {
3400         wpa_cli_recv_pending(mon_conn, 0);
3401 }
3402
3403
3404 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3405 {
3406         char *argv[max_args];
3407         int argc;
3408         argc = tokenize_cmd(cmd, argv);
3409         if (argc)
3410                 wpa_request(ctrl_conn, argc, argv);
3411 }
3412
3413
3414 static void wpa_cli_edit_eof_cb(void *ctx)
3415 {
3416         eloop_terminate();
3417 }
3418
3419
3420 static int warning_displayed = 0;
3421 static char *hfile = NULL;
3422 static int edit_started = 0;
3423
3424 static void start_edit(void)
3425 {
3426         char *home;
3427         char *ps = NULL;
3428
3429 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3430         ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3431 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3432
3433         home = getenv("HOME");
3434         if (home) {
3435                 const char *fname = ".wpa_cli_history";
3436                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3437                 hfile = os_malloc(hfile_len);
3438                 if (hfile)
3439                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3440         }
3441
3442         if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3443                       wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3444                 eloop_terminate();
3445                 return;
3446         }
3447
3448         edit_started = 1;
3449         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3450 }
3451
3452
3453 static void update_bssid_list(struct wpa_ctrl *ctrl)
3454 {
3455         char buf[4096];
3456         size_t len = sizeof(buf);
3457         int ret;
3458         char *cmd = "BSS RANGE=ALL MASK=0x2";
3459         char *pos, *end;
3460
3461         if (ctrl == NULL)
3462                 return;
3463         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3464         if (ret < 0)
3465                 return;
3466         buf[len] = '\0';
3467
3468         pos = buf;
3469         while (pos) {
3470                 pos = os_strstr(pos, "bssid=");
3471                 if (pos == NULL)
3472                         break;
3473                 pos += 6;
3474                 end = os_strchr(pos, '\n');
3475                 if (end == NULL)
3476                         break;
3477                 *end = '\0';
3478                 cli_txt_list_add(&bsses, pos);
3479                 pos = end + 1;
3480         }
3481 }
3482
3483
3484 static void update_ifnames(struct wpa_ctrl *ctrl)
3485 {
3486         char buf[4096];
3487         size_t len = sizeof(buf);
3488         int ret;
3489         char *cmd = "INTERFACES";
3490         char *pos, *end;
3491         char txt[200];
3492
3493         cli_txt_list_flush(&ifnames);
3494
3495         if (ctrl == NULL)
3496                 return;
3497         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3498         if (ret < 0)
3499                 return;
3500         buf[len] = '\0';
3501
3502         pos = buf;
3503         while (pos) {
3504                 end = os_strchr(pos, '\n');
3505                 if (end == NULL)
3506                         break;
3507                 *end = '\0';
3508                 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3509                 if (ret > 0 && ret < (int) sizeof(txt))
3510                         cli_txt_list_add(&ifnames, txt);
3511                 pos = end + 1;
3512         }
3513 }
3514
3515
3516 static void try_connection(void *eloop_ctx, void *timeout_ctx)
3517 {
3518         if (ctrl_conn)
3519                 goto done;
3520
3521         if (ctrl_ifname == NULL)
3522                 ctrl_ifname = wpa_cli_get_default_ifname();
3523
3524         if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3525                 if (!warning_displayed) {
3526                         printf("Could not connect to wpa_supplicant: "
3527                                "%s - re-trying\n", ctrl_ifname);
3528                         warning_displayed = 1;
3529                 }
3530                 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3531                 return;
3532         }
3533
3534         update_bssid_list(ctrl_conn);
3535
3536         if (warning_displayed)
3537                 printf("Connection established.\n");
3538
3539 done:
3540         start_edit();
3541 }
3542
3543
3544 static void wpa_cli_interactive(void)
3545 {
3546         printf("\nInteractive mode\n\n");
3547
3548         eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3549         eloop_run();
3550         eloop_cancel_timeout(try_connection, NULL, NULL);
3551
3552         cli_txt_list_flush(&p2p_peers);
3553         cli_txt_list_flush(&p2p_groups);
3554         cli_txt_list_flush(&bsses);
3555         cli_txt_list_flush(&ifnames);
3556         if (edit_started)
3557                 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3558         os_free(hfile);
3559         eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3560         wpa_cli_close_connection();
3561 }
3562
3563
3564 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3565 {
3566 #ifdef CONFIG_ANSI_C_EXTRA
3567         /* TODO: ANSI C version(?) */
3568         printf("Action processing not supported in ANSI C build.\n");
3569 #else /* CONFIG_ANSI_C_EXTRA */
3570         fd_set rfds;
3571         int fd, res;
3572         struct timeval tv;
3573         char buf[256]; /* note: large enough to fit in unsolicited messages */
3574         size_t len;
3575
3576         fd = wpa_ctrl_get_fd(ctrl);
3577
3578         while (!wpa_cli_quit) {
3579                 FD_ZERO(&rfds);
3580                 FD_SET(fd, &rfds);
3581                 tv.tv_sec = ping_interval;
3582                 tv.tv_usec = 0;
3583                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3584                 if (res < 0 && errno != EINTR) {
3585                         perror("select");
3586                         break;
3587                 }
3588
3589                 if (FD_ISSET(fd, &rfds))
3590                         wpa_cli_recv_pending(ctrl, 1);
3591                 else {
3592                         /* verify that connection is still working */
3593                         len = sizeof(buf) - 1;
3594                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3595                                              wpa_cli_action_cb) < 0 ||
3596                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3597                                 printf("wpa_supplicant did not reply to PING "
3598                                        "command - exiting\n");
3599                                 break;
3600                         }
3601                 }
3602         }
3603 #endif /* CONFIG_ANSI_C_EXTRA */
3604 }
3605
3606
3607 static void wpa_cli_cleanup(void)
3608 {
3609         wpa_cli_close_connection();
3610         if (pid_file)
3611                 os_daemonize_terminate(pid_file);
3612
3613         os_program_deinit();
3614 }
3615
3616
3617 static void wpa_cli_terminate(int sig, void *ctx)
3618 {
3619         eloop_terminate();
3620 }
3621
3622
3623 static char * wpa_cli_get_default_ifname(void)
3624 {
3625         char *ifname = NULL;
3626
3627 #ifdef CONFIG_CTRL_IFACE_UNIX
3628         struct dirent *dent;
3629         DIR *dir = opendir(ctrl_iface_dir);
3630         if (!dir) {
3631 #ifdef ANDROID
3632                 char ifprop[PROPERTY_VALUE_MAX];
3633                 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3634                         ifname = os_strdup(ifprop);
3635                         printf("Using interface '%s'\n", ifname);
3636                         return ifname;
3637                 }
3638 #endif /* ANDROID */
3639                 return NULL;
3640         }
3641         while ((dent = readdir(dir))) {
3642 #ifdef _DIRENT_HAVE_D_TYPE
3643                 /*
3644                  * Skip the file if it is not a socket. Also accept
3645                  * DT_UNKNOWN (0) in case the C library or underlying
3646                  * file system does not support d_type.
3647                  */
3648                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3649                         continue;
3650 #endif /* _DIRENT_HAVE_D_TYPE */
3651                 if (os_strcmp(dent->d_name, ".") == 0 ||
3652                     os_strcmp(dent->d_name, "..") == 0)
3653                         continue;
3654                 printf("Selected interface '%s'\n", dent->d_name);
3655                 ifname = os_strdup(dent->d_name);
3656                 break;
3657         }
3658         closedir(dir);
3659 #endif /* CONFIG_CTRL_IFACE_UNIX */
3660
3661 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3662         char buf[4096], *pos;
3663         size_t len;
3664         struct wpa_ctrl *ctrl;
3665         int ret;
3666
3667         ctrl = wpa_ctrl_open(NULL);
3668         if (ctrl == NULL)
3669                 return NULL;
3670
3671         len = sizeof(buf) - 1;
3672         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3673         if (ret >= 0) {
3674                 buf[len] = '\0';
3675                 pos = os_strchr(buf, '\n');
3676                 if (pos)
3677                         *pos = '\0';
3678                 ifname = os_strdup(buf);
3679         }
3680         wpa_ctrl_close(ctrl);
3681 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3682
3683         return ifname;
3684 }
3685
3686
3687 int main(int argc, char *argv[])
3688 {
3689         int c;
3690         int daemonize = 0;
3691         int ret = 0;
3692         const char *global = NULL;
3693
3694         if (os_program_init())
3695                 return -1;
3696
3697         for (;;) {
3698                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3699                 if (c < 0)
3700                         break;
3701                 switch (c) {
3702                 case 'a':
3703                         action_file = optarg;
3704                         break;
3705                 case 'B':
3706                         daemonize = 1;
3707                         break;
3708                 case 'g':
3709                         global = optarg;
3710                         break;
3711                 case 'G':
3712                         ping_interval = atoi(optarg);
3713                         break;
3714                 case 'h':
3715                         usage();
3716                         return 0;
3717                 case 'v':
3718                         printf("%s\n", wpa_cli_version);
3719                         return 0;
3720                 case 'i':
3721                         os_free(ctrl_ifname);
3722                         ctrl_ifname = os_strdup(optarg);
3723                         break;
3724                 case 'p':
3725                         ctrl_iface_dir = optarg;
3726                         break;
3727                 case 'P':
3728                         pid_file = optarg;
3729                         break;
3730                 default:
3731                         usage();
3732                         return -1;
3733                 }
3734         }
3735
3736         interactive = (argc == optind) && (action_file == NULL);
3737
3738         if (interactive)
3739                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3740
3741         if (eloop_init())
3742                 return -1;
3743
3744         if (global) {
3745 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3746                 ctrl_conn = wpa_ctrl_open(NULL);
3747 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3748                 ctrl_conn = wpa_ctrl_open(global);
3749 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3750                 if (ctrl_conn == NULL) {
3751                         fprintf(stderr, "Failed to connect to wpa_supplicant "
3752                                 "global interface: %s  error: %s\n",
3753                                 global, strerror(errno));
3754                         return -1;
3755                 }
3756
3757                 if (interactive) {
3758                         update_ifnames(ctrl_conn);
3759                         mon_conn = wpa_ctrl_open(global);
3760                         if (mon_conn) {
3761                                 if (wpa_ctrl_attach(mon_conn) == 0) {
3762                                         wpa_cli_attached = 1;
3763                                         eloop_register_read_sock(
3764                                                 wpa_ctrl_get_fd(mon_conn),
3765                                                 wpa_cli_mon_receive,
3766                                                 NULL, NULL);
3767                                 } else {
3768                                         printf("Failed to open monitor "
3769                                                "connection through global "
3770                                                "control interface\n");
3771                                 }
3772                         }
3773                 }
3774         }
3775
3776         eloop_register_signal_terminate(wpa_cli_terminate, NULL);
3777
3778         if (ctrl_ifname == NULL)
3779                 ctrl_ifname = wpa_cli_get_default_ifname();
3780
3781         if (interactive) {
3782                 wpa_cli_interactive();
3783         } else {
3784                 if (!global &&
3785                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3786                         fprintf(stderr, "Failed to connect to non-global "
3787                                 "ctrl_ifname: %s  error: %s\n",
3788                                 ctrl_ifname, strerror(errno));
3789                         return -1;
3790                 }
3791
3792                 if (action_file) {
3793                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
3794                                 wpa_cli_attached = 1;
3795                         } else {
3796                                 printf("Warning: Failed to attach to "
3797                                        "wpa_supplicant.\n");
3798                                 return -1;
3799                         }
3800                 }
3801
3802                 if (daemonize && os_daemonize(pid_file))
3803                         return -1;
3804
3805                 if (action_file)
3806                         wpa_cli_action(ctrl_conn);
3807                 else
3808                         ret = wpa_request(ctrl_conn, argc - optind,
3809                                           &argv[optind]);
3810         }
3811
3812         os_free(ctrl_ifname);
3813         eloop_destroy();
3814         wpa_cli_cleanup();
3815
3816         return ret;
3817 }
3818
3819 #else /* CONFIG_CTRL_IFACE */
3820 int main(int argc, char *argv[])
3821 {
3822         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3823         return -1;
3824 }
3825 #endif /* CONFIG_CTRL_IFACE */