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