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