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