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