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