wpa_cli: Set buffer length the same as in wpa_supplicant_ctrl_iface_process()
[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
2297 static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2298 {
2299         return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2300 }
2301
2302 #endif /* CONFIG_WNM */
2303
2304
2305 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2306 {
2307         if (argc == 0)
2308                 return -1;
2309         return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2310 }
2311
2312
2313 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2314 {
2315         return wpa_ctrl_command(ctrl, "FLUSH");
2316 }
2317
2318
2319 enum wpa_cli_cmd_flags {
2320         cli_cmd_flag_none               = 0x00,
2321         cli_cmd_flag_sensitive          = 0x01
2322 };
2323
2324 struct wpa_cli_cmd {
2325         const char *cmd;
2326         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2327         char ** (*completion)(const char *str, int pos);
2328         enum wpa_cli_cmd_flags flags;
2329         const char *usage;
2330 };
2331
2332 static struct wpa_cli_cmd wpa_cli_commands[] = {
2333         { "status", wpa_cli_cmd_status, NULL,
2334           cli_cmd_flag_none,
2335           "[verbose] = get current WPA/EAPOL/EAP status" },
2336         { "ifname", wpa_cli_cmd_ifname, NULL,
2337           cli_cmd_flag_none,
2338           "= get current interface name" },
2339         { "ping", wpa_cli_cmd_ping, NULL,
2340           cli_cmd_flag_none,
2341           "= pings wpa_supplicant" },
2342         { "relog", wpa_cli_cmd_relog, NULL,
2343           cli_cmd_flag_none,
2344           "= re-open log-file (allow rolling logs)" },
2345         { "note", wpa_cli_cmd_note, NULL,
2346           cli_cmd_flag_none,
2347           "<text> = add a note to wpa_supplicant debug log" },
2348         { "mib", wpa_cli_cmd_mib, NULL,
2349           cli_cmd_flag_none,
2350           "= get MIB variables (dot1x, dot11)" },
2351         { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2352           cli_cmd_flag_none,
2353           "[command] = show usage help" },
2354         { "interface", wpa_cli_cmd_interface, NULL,
2355           cli_cmd_flag_none,
2356           "[ifname] = show interfaces/select interface" },
2357         { "level", wpa_cli_cmd_level, NULL,
2358           cli_cmd_flag_none,
2359           "<debug level> = change debug level" },
2360         { "license", wpa_cli_cmd_license, NULL,
2361           cli_cmd_flag_none,
2362           "= show full wpa_cli license" },
2363         { "quit", wpa_cli_cmd_quit, NULL,
2364           cli_cmd_flag_none,
2365           "= exit wpa_cli" },
2366         { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2367           cli_cmd_flag_none,
2368           "= set variables (shows list of variables when run without "
2369           "arguments)" },
2370         { "get", wpa_cli_cmd_get, NULL,
2371           cli_cmd_flag_none,
2372           "<name> = get information" },
2373         { "logon", wpa_cli_cmd_logon, NULL,
2374           cli_cmd_flag_none,
2375           "= IEEE 802.1X EAPOL state machine logon" },
2376         { "logoff", wpa_cli_cmd_logoff, NULL,
2377           cli_cmd_flag_none,
2378           "= IEEE 802.1X EAPOL state machine logoff" },
2379         { "pmksa", wpa_cli_cmd_pmksa, NULL,
2380           cli_cmd_flag_none,
2381           "= show PMKSA cache" },
2382         { "reassociate", wpa_cli_cmd_reassociate, NULL,
2383           cli_cmd_flag_none,
2384           "= force reassociation" },
2385         { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2386           cli_cmd_flag_none,
2387           "<BSSID> = force preauthentication" },
2388         { "identity", wpa_cli_cmd_identity, NULL,
2389           cli_cmd_flag_none,
2390           "<network id> <identity> = configure identity for an SSID" },
2391         { "password", wpa_cli_cmd_password, NULL,
2392           cli_cmd_flag_sensitive,
2393           "<network id> <password> = configure password for an SSID" },
2394         { "new_password", wpa_cli_cmd_new_password, NULL,
2395           cli_cmd_flag_sensitive,
2396           "<network id> <password> = change password for an SSID" },
2397         { "pin", wpa_cli_cmd_pin, NULL,
2398           cli_cmd_flag_sensitive,
2399           "<network id> <pin> = configure pin for an SSID" },
2400         { "otp", wpa_cli_cmd_otp, NULL,
2401           cli_cmd_flag_sensitive,
2402           "<network id> <password> = configure one-time-password for an SSID"
2403         },
2404         { "passphrase", wpa_cli_cmd_passphrase, NULL,
2405           cli_cmd_flag_sensitive,
2406           "<network id> <passphrase> = configure private key passphrase\n"
2407           "  for an SSID" },
2408         { "bssid", wpa_cli_cmd_bssid, NULL,
2409           cli_cmd_flag_none,
2410           "<network id> <BSSID> = set preferred BSSID for an SSID" },
2411         { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2412           cli_cmd_flag_none,
2413           "<BSSID> = add a BSSID to the blacklist\n"
2414           "blacklist clear = clear the blacklist\n"
2415           "blacklist = display the blacklist" },
2416         { "log_level", wpa_cli_cmd_log_level, NULL,
2417           cli_cmd_flag_none,
2418           "<level> [<timestamp>] = update the log level/timestamp\n"
2419           "log_level = display the current log level and log options" },
2420         { "list_networks", wpa_cli_cmd_list_networks, NULL,
2421           cli_cmd_flag_none,
2422           "= list configured networks" },
2423         { "select_network", wpa_cli_cmd_select_network, NULL,
2424           cli_cmd_flag_none,
2425           "<network id> = select a network (disable others)" },
2426         { "enable_network", wpa_cli_cmd_enable_network, NULL,
2427           cli_cmd_flag_none,
2428           "<network id> = enable a network" },
2429         { "disable_network", wpa_cli_cmd_disable_network, NULL,
2430           cli_cmd_flag_none,
2431           "<network id> = disable a network" },
2432         { "add_network", wpa_cli_cmd_add_network, NULL,
2433           cli_cmd_flag_none,
2434           "= add a network" },
2435         { "remove_network", wpa_cli_cmd_remove_network, NULL,
2436           cli_cmd_flag_none,
2437           "<network id> = remove a network" },
2438         { "set_network", wpa_cli_cmd_set_network, NULL,
2439           cli_cmd_flag_sensitive,
2440           "<network id> <variable> <value> = set network variables (shows\n"
2441           "  list of variables when run without arguments)" },
2442         { "get_network", wpa_cli_cmd_get_network, NULL,
2443           cli_cmd_flag_none,
2444           "<network id> <variable> = get network variables" },
2445         { "list_creds", wpa_cli_cmd_list_creds, NULL,
2446           cli_cmd_flag_none,
2447           "= list configured credentials" },
2448         { "add_cred", wpa_cli_cmd_add_cred, NULL,
2449           cli_cmd_flag_none,
2450           "= add a credential" },
2451         { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2452           cli_cmd_flag_none,
2453           "<cred id> = remove a credential" },
2454         { "set_cred", wpa_cli_cmd_set_cred, NULL,
2455           cli_cmd_flag_sensitive,
2456           "<cred id> <variable> <value> = set credential variables" },
2457         { "save_config", wpa_cli_cmd_save_config, NULL,
2458           cli_cmd_flag_none,
2459           "= save the current configuration" },
2460         { "disconnect", wpa_cli_cmd_disconnect, NULL,
2461           cli_cmd_flag_none,
2462           "= disconnect and wait for reassociate/reconnect command before\n"
2463           "  connecting" },
2464         { "reconnect", wpa_cli_cmd_reconnect, NULL,
2465           cli_cmd_flag_none,
2466           "= like reassociate, but only takes effect if already disconnected"
2467         },
2468         { "scan", wpa_cli_cmd_scan, NULL,
2469           cli_cmd_flag_none,
2470           "= request new BSS scan" },
2471         { "scan_results", wpa_cli_cmd_scan_results, NULL,
2472           cli_cmd_flag_none,
2473           "= get latest scan results" },
2474         { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2475           cli_cmd_flag_none,
2476           "<<idx> | <bssid>> = get detailed scan result info" },
2477         { "get_capability", wpa_cli_cmd_get_capability, NULL,
2478           cli_cmd_flag_none,
2479           "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2480           "= get capabilies" },
2481         { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2482           cli_cmd_flag_none,
2483           "= force wpa_supplicant to re-read its configuration file" },
2484         { "terminate", wpa_cli_cmd_terminate, NULL,
2485           cli_cmd_flag_none,
2486           "= terminate wpa_supplicant" },
2487         { "interface_add", wpa_cli_cmd_interface_add, NULL,
2488           cli_cmd_flag_none,
2489           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2490           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
2491           "  are optional" },
2492         { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2493           cli_cmd_flag_none,
2494           "<ifname> = removes the interface" },
2495         { "interface_list", wpa_cli_cmd_interface_list, NULL,
2496           cli_cmd_flag_none,
2497           "= list available interfaces" },
2498         { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2499           cli_cmd_flag_none,
2500           "<value> = set ap_scan parameter" },
2501         { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2502           cli_cmd_flag_none,
2503           "<value> = set scan_interval parameter (in seconds)" },
2504         { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2505           cli_cmd_flag_none,
2506           "<value> = set BSS expiration age parameter" },
2507         { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2508           cli_cmd_flag_none,
2509           "<value> = set BSS expiration scan count parameter" },
2510         { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2511           cli_cmd_flag_none,
2512           "<value> = set BSS flush age (0 by default)" },
2513         { "stkstart", wpa_cli_cmd_stkstart, NULL,
2514           cli_cmd_flag_none,
2515           "<addr> = request STK negotiation with <addr>" },
2516         { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2517           cli_cmd_flag_none,
2518           "<addr> = request over-the-DS FT with <addr>" },
2519         { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2520           cli_cmd_flag_none,
2521           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2522         { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2523           cli_cmd_flag_sensitive,
2524           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2525           "hardcoded)" },
2526         { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2527           cli_cmd_flag_sensitive,
2528           "<PIN> = verify PIN checksum" },
2529         { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2530           "Cancels the pending WPS operation" },
2531 #ifdef CONFIG_WPS_NFC
2532         { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2533           cli_cmd_flag_none,
2534           "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2535         { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2536           cli_cmd_flag_none,
2537           "<WPS|NDEF> = build configuration token" },
2538         { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2539           cli_cmd_flag_none,
2540           "<WPS|NDEF> = create password token" },
2541         { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2542           cli_cmd_flag_sensitive,
2543           "<hexdump of payload> = report read NFC tag with WPS data" },
2544         { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2545           cli_cmd_flag_none,
2546           "<NDEF> <WPS> = create NFC handover request" },
2547         { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2548           cli_cmd_flag_none,
2549           "<NDEF> <WPS> = create NFC handover select" },
2550         { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2551           cli_cmd_flag_none,
2552           "<hexdump of payload> = report received NFC handover request" },
2553         { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2554           cli_cmd_flag_none,
2555           "<hexdump of payload> = report received NFC handover select" },
2556         { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2557           cli_cmd_flag_none,
2558           "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2559           "NFC handover" },
2560 #endif /* CONFIG_WPS_NFC */
2561         { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2562           cli_cmd_flag_sensitive,
2563           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2564         { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2565           cli_cmd_flag_sensitive,
2566           "[params..] = enable/disable AP PIN" },
2567         { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2568           cli_cmd_flag_none,
2569           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2570         { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2571           cli_cmd_flag_none,
2572           "= stop Wi-Fi Protected Setup External Registrar" },
2573         { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2574           cli_cmd_flag_sensitive,
2575           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2576         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2577           cli_cmd_flag_none,
2578           "<UUID> = accept an Enrollee PBC using External Registrar" },
2579         { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2580           cli_cmd_flag_sensitive,
2581           "<UUID> <PIN> = learn AP configuration" },
2582         { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2583           cli_cmd_flag_none,
2584           "<UUID> <network id> = set AP configuration for enrolling" },
2585         { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2586           cli_cmd_flag_sensitive,
2587           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2588 #ifdef CONFIG_WPS_NFC
2589         { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2590           cli_cmd_flag_none,
2591           "<WPS/NDEF> <UUID> = build NFC configuration token" },
2592 #endif /* CONFIG_WPS_NFC */
2593         { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2594           cli_cmd_flag_none,
2595           "<addr> = request RSN authentication with <addr> in IBSS" },
2596 #ifdef CONFIG_AP
2597         { "sta", wpa_cli_cmd_sta, NULL,
2598           cli_cmd_flag_none,
2599           "<addr> = get information about an associated station (AP)" },
2600         { "all_sta", wpa_cli_cmd_all_sta, NULL,
2601           cli_cmd_flag_none,
2602           "= get information about all associated stations (AP)" },
2603         { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2604           cli_cmd_flag_none,
2605           "<addr> = deauthenticate a station" },
2606         { "disassociate", wpa_cli_cmd_disassociate, NULL,
2607           cli_cmd_flag_none,
2608           "<addr> = disassociate a station" },
2609 #endif /* CONFIG_AP */
2610         { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2611           "= notification of suspend/hibernate" },
2612         { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2613           "= notification of resume/thaw" },
2614         { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2615           "= drop SA without deauth/disassoc (test command)" },
2616         { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2617           cli_cmd_flag_none,
2618           "<addr> = roam to the specified BSS" },
2619 #ifdef CONFIG_P2P
2620         { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2621           cli_cmd_flag_none,
2622           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2623         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2624           "= stop P2P Devices search" },
2625         { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2626           cli_cmd_flag_none,
2627           "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2628         { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2629           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2630         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2631           wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2632           "<ifname> = remove P2P group interface (terminate group if GO)" },
2633         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2634           "[ht40] = add a new P2P group (local end as GO)" },
2635         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2636           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2637           "<addr> <method> = request provisioning discovery" },
2638         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2639           cli_cmd_flag_none,
2640           "= get the passphrase for a group (GO only)" },
2641         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2642           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2643           "<addr> <TLVs> = schedule service discovery request" },
2644         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2645           NULL, cli_cmd_flag_none,
2646           "<id> = cancel pending service discovery request" },
2647         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2648           cli_cmd_flag_none,
2649           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2650         { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2651           cli_cmd_flag_none,
2652           "= indicate change in local services" },
2653         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2654           cli_cmd_flag_none,
2655           "<external> = set external processing of service discovery" },
2656         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2657           cli_cmd_flag_none,
2658           "= remove all stored service entries" },
2659         { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2660           cli_cmd_flag_none,
2661           "<bonjour|upnp> <query|version> <response|service> = add a local "
2662           "service" },
2663         { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2664           cli_cmd_flag_none,
2665           "<bonjour|upnp> <query|version> [|service] = remove a local "
2666           "service" },
2667         { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2668           cli_cmd_flag_none,
2669           "<addr> = reject connection attempts from a specific peer" },
2670         { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2671           cli_cmd_flag_none,
2672           "<cmd> [peer=addr] = invite peer" },
2673         { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2674           "[discovered] = list known (optionally, only fully discovered) P2P "
2675           "peers" },
2676         { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2677           cli_cmd_flag_none,
2678           "<address> = show information about known P2P peer" },
2679         { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
2680           "<field> <value> = set a P2P parameter" },
2681         { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2682           "= flush P2P state" },
2683         { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2684           "= cancel P2P group formation" },
2685         { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2686           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2687           "<address> = unauthorize a peer" },
2688         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2689           cli_cmd_flag_none,
2690           "[<duration> <interval>] [<duration> <interval>] = request GO "
2691           "presence" },
2692         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2693           cli_cmd_flag_none,
2694           "[<period> <interval>] = set extended listen timing" },
2695 #endif /* CONFIG_P2P */
2696 #ifdef CONFIG_WIFI_DISPLAY
2697         { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2698           cli_cmd_flag_none,
2699           "<subelem> [contents] = set Wi-Fi Display subelement" },
2700         { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2701           cli_cmd_flag_none,
2702           "<subelem> = get Wi-Fi Display subelement" },
2703 #endif /* CONFIG_WIFI_DISPLAY */
2704 #ifdef CONFIG_INTERWORKING
2705         { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
2706           "= fetch ANQP information for all APs" },
2707         { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2708           cli_cmd_flag_none,
2709           "= stop fetch_anqp operation" },
2710         { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
2711           cli_cmd_flag_none,
2712           "[auto] = perform Interworking network selection" },
2713         { "interworking_connect", wpa_cli_cmd_interworking_connect,
2714           wpa_cli_complete_bss, cli_cmd_flag_none,
2715           "<BSSID> = connect using Interworking credentials" },
2716         { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2717           cli_cmd_flag_none,
2718           "<addr> <info id>[,<info id>]... = request ANQP information" },
2719         { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2720           cli_cmd_flag_none,
2721           "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2722         { "gas_response_get", wpa_cli_cmd_gas_response_get,
2723           wpa_cli_complete_bss, cli_cmd_flag_none,
2724           "<addr> <dialog token> [start,len] = Fetch last GAS response" },
2725 #endif /* CONFIG_INTERWORKING */
2726 #ifdef CONFIG_HS20
2727         { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2728           cli_cmd_flag_none,
2729           "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2730         },
2731         { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
2732           wpa_cli_complete_bss, cli_cmd_flag_none,
2733           "<addr> <home realm> = get HS20 nai home realm list" },
2734 #endif /* CONFIG_HS20 */
2735         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2736           cli_cmd_flag_none,
2737           "<0/1> = disable/enable automatic reconnection" },
2738         { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
2739           cli_cmd_flag_none,
2740           "<addr> = request TDLS discovery with <addr>" },
2741         { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
2742           cli_cmd_flag_none,
2743           "<addr> = request TDLS setup with <addr>" },
2744         { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
2745           cli_cmd_flag_none,
2746           "<addr> = tear down TDLS with <addr>" },
2747         { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
2748           cli_cmd_flag_none,
2749           "= get signal parameters" },
2750         { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2751           cli_cmd_flag_none,
2752           "= get TX/RX packet counters" },
2753         { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2754           cli_cmd_flag_none,
2755           "= trigger IEEE 802.1X/EAPOL reauthentication" },
2756 #ifdef CONFIG_AUTOSCAN
2757         { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2758           "[params] = Set or unset (if none) autoscan parameters" },
2759 #endif /* CONFIG_AUTOSCAN */
2760 #ifdef CONFIG_WNM
2761         { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2762           "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2763         { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2764           "<query reason> = Send BSS Transition Management Query" },
2765 #endif /* CONFIG_WNM */
2766         { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2767           "<params..> = Sent unprocessed command" },
2768         { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2769           "= flush wpa_supplicant state" },
2770         { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
2771 };
2772
2773
2774 /*
2775  * Prints command usage, lines are padded with the specified string.
2776  */
2777 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2778 {
2779         char c;
2780         size_t n;
2781
2782         printf("%s%s ", pad, cmd->cmd);
2783         for (n = 0; (c = cmd->usage[n]); n++) {
2784                 printf("%c", c);
2785                 if (c == '\n')
2786                         printf("%s", pad);
2787         }
2788         printf("\n");
2789 }
2790
2791
2792 static void print_help(const char *cmd)
2793 {
2794         int n;
2795         printf("commands:\n");
2796         for (n = 0; wpa_cli_commands[n].cmd; n++) {
2797                 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2798                         print_cmd_help(&wpa_cli_commands[n], "  ");
2799         }
2800 }
2801
2802
2803 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2804 {
2805         const char *c, *delim;
2806         int n;
2807         size_t len;
2808
2809         delim = os_strchr(cmd, ' ');
2810         if (delim)
2811                 len = delim - cmd;
2812         else
2813                 len = os_strlen(cmd);
2814
2815         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2816                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2817                         return (wpa_cli_commands[n].flags &
2818                                 cli_cmd_flag_sensitive);
2819         }
2820         return 0;
2821 }
2822
2823
2824 static char ** wpa_list_cmd_list(void)
2825 {
2826         char **res;
2827         int i, count;
2828
2829         count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
2830         res = os_calloc(count, sizeof(char *));
2831         if (res == NULL)
2832                 return NULL;
2833
2834         for (i = 0; wpa_cli_commands[i].cmd; i++) {
2835                 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2836                 if (res[i] == NULL)
2837                         break;
2838         }
2839
2840         return res;
2841 }
2842
2843
2844 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2845                                       int pos)
2846 {
2847         int i;
2848
2849         for (i = 0; wpa_cli_commands[i].cmd; i++) {
2850                 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2851                         if (wpa_cli_commands[i].completion)
2852                                 return wpa_cli_commands[i].completion(str,
2853                                                                       pos);
2854                         edit_clear_line();
2855                         printf("\r%s\n", wpa_cli_commands[i].usage);
2856                         edit_redraw();
2857                         break;
2858                 }
2859         }
2860
2861         return NULL;
2862 }
2863
2864
2865 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2866 {
2867         char **res;
2868         const char *end;
2869         char *cmd;
2870
2871         end = os_strchr(str, ' ');
2872         if (end == NULL || str + pos < end)
2873                 return wpa_list_cmd_list();
2874
2875         cmd = os_malloc(pos + 1);
2876         if (cmd == NULL)
2877                 return NULL;
2878         os_memcpy(cmd, str, pos);
2879         cmd[end - str] = '\0';
2880         res = wpa_cli_cmd_completion(cmd, str, pos);
2881         os_free(cmd);
2882         return res;
2883 }
2884
2885
2886 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2887 {
2888         struct wpa_cli_cmd *cmd, *match = NULL;
2889         int count;
2890         int ret = 0;
2891
2892         count = 0;
2893         cmd = wpa_cli_commands;
2894         while (cmd->cmd) {
2895                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2896                 {
2897                         match = cmd;
2898                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2899                                 /* we have an exact match */
2900                                 count = 1;
2901                                 break;
2902                         }
2903                         count++;
2904                 }
2905                 cmd++;
2906         }
2907
2908         if (count > 1) {
2909                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2910                 cmd = wpa_cli_commands;
2911                 while (cmd->cmd) {
2912                         if (os_strncasecmp(cmd->cmd, argv[0],
2913                                            os_strlen(argv[0])) == 0) {
2914                                 printf(" %s", cmd->cmd);
2915                         }
2916                         cmd++;
2917                 }
2918                 printf("\n");
2919                 ret = 1;
2920         } else if (count == 0) {
2921                 printf("Unknown command '%s'\n", argv[0]);
2922                 ret = 1;
2923         } else {
2924                 ret = match->handler(ctrl, argc - 1, &argv[1]);
2925         }
2926
2927         return ret;
2928 }
2929
2930
2931 static int str_match(const char *a, const char *b)
2932 {
2933         return os_strncmp(a, b, os_strlen(b)) == 0;
2934 }
2935
2936
2937 static int wpa_cli_exec(const char *program, const char *arg1,
2938                         const char *arg2)
2939 {
2940         char *cmd;
2941         size_t len;
2942         int res;
2943         int ret = 0;
2944
2945         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2946         cmd = os_malloc(len);
2947         if (cmd == NULL)
2948                 return -1;
2949         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2950         if (res < 0 || (size_t) res >= len) {
2951                 os_free(cmd);
2952                 return -1;
2953         }
2954         cmd[len - 1] = '\0';
2955 #ifndef _WIN32_WCE
2956         if (system(cmd) < 0)
2957                 ret = -1;
2958 #endif /* _WIN32_WCE */
2959         os_free(cmd);
2960
2961         return ret;
2962 }
2963
2964
2965 static void wpa_cli_action_process(const char *msg)
2966 {
2967         const char *pos;
2968         char *copy = NULL, *id, *pos2;
2969
2970         pos = msg;
2971         if (*pos == '<') {
2972                 /* skip priority */
2973                 pos = os_strchr(pos, '>');
2974                 if (pos)
2975                         pos++;
2976                 else
2977                         pos = msg;
2978         }
2979
2980         if (str_match(pos, WPA_EVENT_CONNECTED)) {
2981                 int new_id = -1;
2982                 os_unsetenv("WPA_ID");
2983                 os_unsetenv("WPA_ID_STR");
2984                 os_unsetenv("WPA_CTRL_DIR");
2985
2986                 pos = os_strstr(pos, "[id=");
2987                 if (pos)
2988                         copy = os_strdup(pos + 4);
2989
2990                 if (copy) {
2991                         pos2 = id = copy;
2992                         while (*pos2 && *pos2 != ' ')
2993                                 pos2++;
2994                         *pos2++ = '\0';
2995                         new_id = atoi(id);
2996                         os_setenv("WPA_ID", id, 1);
2997                         while (*pos2 && *pos2 != '=')
2998                                 pos2++;
2999                         if (*pos2 == '=')
3000                                 pos2++;
3001                         id = pos2;
3002                         while (*pos2 && *pos2 != ']')
3003                                 pos2++;
3004                         *pos2 = '\0';
3005                         os_setenv("WPA_ID_STR", id, 1);
3006                         os_free(copy);
3007                 }
3008
3009                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3010
3011                 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3012                         wpa_cli_connected = 1;
3013                         wpa_cli_last_id = new_id;
3014                         wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3015                 }
3016         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3017                 if (wpa_cli_connected) {
3018                         wpa_cli_connected = 0;
3019                         wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3020                 }
3021         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3022                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3023         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3024                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3025         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3026                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3027         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3028                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3029         } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3030                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3031         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3032                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3033         } else if (str_match(pos, WPS_EVENT_FAIL)) {
3034                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3035         } else if (str_match(pos, AP_STA_CONNECTED)) {
3036                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3037         } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3038                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3039         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3040                 printf("wpa_supplicant is terminating - stop monitoring\n");
3041                 wpa_cli_quit = 1;
3042         }
3043 }
3044
3045
3046 #ifndef CONFIG_ANSI_C_EXTRA
3047 static void wpa_cli_action_cb(char *msg, size_t len)
3048 {
3049         wpa_cli_action_process(msg);
3050 }
3051 #endif /* CONFIG_ANSI_C_EXTRA */
3052
3053
3054 static void wpa_cli_reconnect(void)
3055 {
3056         wpa_cli_close_connection();
3057         if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3058                 return;
3059
3060         if (interactive) {
3061                 edit_clear_line();
3062                 printf("\rConnection to wpa_supplicant re-established\n");
3063                 edit_redraw();
3064         }
3065 }
3066
3067
3068 static void cli_event(const char *str)
3069 {
3070         const char *start, *s;
3071
3072         start = os_strchr(str, '>');
3073         if (start == NULL)
3074                 return;
3075
3076         start++;
3077
3078         if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3079                 s = os_strchr(start, ' ');
3080                 if (s == NULL)
3081                         return;
3082                 s = os_strchr(s + 1, ' ');
3083                 if (s == NULL)
3084                         return;
3085                 cli_txt_list_add(&bsses, s + 1);
3086                 return;
3087         }
3088
3089         if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3090                 s = os_strchr(start, ' ');
3091                 if (s == NULL)
3092                         return;
3093                 s = os_strchr(s + 1, ' ');
3094                 if (s == NULL)
3095                         return;
3096                 cli_txt_list_del_addr(&bsses, s + 1);
3097                 return;
3098         }
3099
3100 #ifdef CONFIG_P2P
3101         if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3102                 s = os_strstr(start, " p2p_dev_addr=");
3103                 if (s == NULL)
3104                         return;
3105                 cli_txt_list_add_addr(&p2p_peers, s + 14);
3106                 return;
3107         }
3108
3109         if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3110                 s = os_strstr(start, " p2p_dev_addr=");
3111                 if (s == NULL)
3112                         return;
3113                 cli_txt_list_del_addr(&p2p_peers, s + 14);
3114                 return;
3115         }
3116
3117         if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3118                 s = os_strchr(start, ' ');
3119                 if (s == NULL)
3120                         return;
3121                 cli_txt_list_add_word(&p2p_groups, s + 1);
3122                 return;
3123         }
3124
3125         if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3126                 s = os_strchr(start, ' ');
3127                 if (s == NULL)
3128                         return;
3129                 cli_txt_list_del_word(&p2p_groups, s + 1);
3130                 return;
3131         }
3132 #endif /* CONFIG_P2P */
3133 }
3134
3135
3136 static int check_terminating(const char *msg)
3137 {
3138         const char *pos = msg;
3139
3140         if (*pos == '<') {
3141                 /* skip priority */
3142                 pos = os_strchr(pos, '>');
3143                 if (pos)
3144                         pos++;
3145                 else
3146                         pos = msg;
3147         }
3148
3149         if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3150                 edit_clear_line();
3151                 printf("\rConnection to wpa_supplicant lost - trying to "
3152                        "reconnect\n");
3153                 edit_redraw();
3154                 wpa_cli_attached = 0;
3155                 wpa_cli_close_connection();
3156                 return 1;
3157         }
3158
3159         return 0;
3160 }
3161
3162
3163 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3164 {
3165         if (ctrl_conn == NULL) {
3166                 wpa_cli_reconnect();
3167                 return;
3168         }
3169         while (wpa_ctrl_pending(ctrl) > 0) {
3170                 char buf[256];
3171                 size_t len = sizeof(buf) - 1;
3172                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3173                         buf[len] = '\0';
3174                         if (action_monitor)
3175                                 wpa_cli_action_process(buf);
3176                         else {
3177                                 cli_event(buf);
3178                                 if (wpa_cli_show_event(buf)) {
3179                                         edit_clear_line();
3180                                         printf("\r%s\n", buf);
3181                                         edit_redraw();
3182                                 }
3183
3184                                 if (interactive && check_terminating(buf) > 0)
3185                                         return;
3186                         }
3187                 } else {
3188                         printf("Could not read pending message.\n");
3189                         break;
3190                 }
3191         }
3192
3193         if (wpa_ctrl_pending(ctrl) < 0) {
3194                 printf("Connection to wpa_supplicant lost - trying to "
3195                        "reconnect\n");
3196                 wpa_cli_reconnect();
3197         }
3198 }
3199
3200 #define max_args 10
3201
3202 static int tokenize_cmd(char *cmd, char *argv[])
3203 {
3204         char *pos;
3205         int argc = 0;
3206
3207         pos = cmd;
3208         for (;;) {
3209                 while (*pos == ' ')
3210                         pos++;
3211                 if (*pos == '\0')
3212                         break;
3213                 argv[argc] = pos;
3214                 argc++;
3215                 if (argc == max_args)
3216                         break;
3217                 if (*pos == '"') {
3218                         char *pos2 = os_strrchr(pos, '"');
3219                         if (pos2)
3220                                 pos = pos2 + 1;
3221                 }
3222                 while (*pos != '\0' && *pos != ' ')
3223                         pos++;
3224                 if (*pos == ' ')
3225                         *pos++ = '\0';
3226         }
3227
3228         return argc;
3229 }
3230
3231
3232 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3233 {
3234         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3235                 printf("Connection to wpa_supplicant lost - trying to "
3236                        "reconnect\n");
3237                 wpa_cli_close_connection();
3238         }
3239         if (!ctrl_conn)
3240                 wpa_cli_reconnect();
3241         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3242 }
3243
3244
3245 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3246 {
3247         wpa_cli_recv_pending(mon_conn, 0);
3248 }
3249
3250
3251 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3252 {
3253         char *argv[max_args];
3254         int argc;
3255         argc = tokenize_cmd(cmd, argv);
3256         if (argc)
3257                 wpa_request(ctrl_conn, argc, argv);
3258 }
3259
3260
3261 static void wpa_cli_edit_eof_cb(void *ctx)
3262 {
3263         eloop_terminate();
3264 }
3265
3266
3267 static int warning_displayed = 0;
3268 static char *hfile = NULL;
3269 static int edit_started = 0;
3270
3271 static void start_edit(void)
3272 {
3273         char *home;
3274         char *ps = NULL;
3275
3276 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3277         ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3278 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3279
3280         home = getenv("HOME");
3281         if (home) {
3282                 const char *fname = ".wpa_cli_history";
3283                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3284                 hfile = os_malloc(hfile_len);
3285                 if (hfile)
3286                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3287         }
3288
3289         if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3290                       wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3291                 eloop_terminate();
3292                 return;
3293         }
3294
3295         edit_started = 1;
3296         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3297 }
3298
3299
3300 static void update_bssid_list(struct wpa_ctrl *ctrl)
3301 {
3302         char buf[4096];
3303         size_t len = sizeof(buf);
3304         int ret;
3305         char *cmd = "BSS RANGE=ALL MASK=0x2";
3306         char *pos, *end;
3307
3308         if (ctrl == NULL)
3309                 return;
3310         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3311         if (ret < 0)
3312                 return;
3313         buf[len] = '\0';
3314
3315         pos = buf;
3316         while (pos) {
3317                 pos = os_strstr(pos, "bssid=");
3318                 if (pos == NULL)
3319                         break;
3320                 pos += 6;
3321                 end = os_strchr(pos, '\n');
3322                 if (end == NULL)
3323                         break;
3324                 *end = '\0';
3325                 cli_txt_list_add(&bsses, pos);
3326                 pos = end + 1;
3327         }
3328 }
3329
3330
3331 static void try_connection(void *eloop_ctx, void *timeout_ctx)
3332 {
3333         if (ctrl_conn)
3334                 goto done;
3335
3336         if (ctrl_ifname == NULL)
3337                 ctrl_ifname = wpa_cli_get_default_ifname();
3338
3339         if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3340                 if (!warning_displayed) {
3341                         printf("Could not connect to wpa_supplicant: "
3342                                "%s - re-trying\n", ctrl_ifname);
3343                         warning_displayed = 1;
3344                 }
3345                 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3346                 return;
3347         }
3348
3349         update_bssid_list(ctrl_conn);
3350
3351         if (warning_displayed)
3352                 printf("Connection established.\n");
3353
3354 done:
3355         start_edit();
3356 }
3357
3358
3359 static void wpa_cli_interactive(void)
3360 {
3361         printf("\nInteractive mode\n\n");
3362
3363         eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3364         eloop_run();
3365         eloop_cancel_timeout(try_connection, NULL, NULL);
3366
3367         cli_txt_list_flush(&p2p_peers);
3368         cli_txt_list_flush(&p2p_groups);
3369         cli_txt_list_flush(&bsses);
3370         if (edit_started)
3371                 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3372         os_free(hfile);
3373         eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3374         wpa_cli_close_connection();
3375 }
3376
3377
3378 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3379 {
3380 #ifdef CONFIG_ANSI_C_EXTRA
3381         /* TODO: ANSI C version(?) */
3382         printf("Action processing not supported in ANSI C build.\n");
3383 #else /* CONFIG_ANSI_C_EXTRA */
3384         fd_set rfds;
3385         int fd, res;
3386         struct timeval tv;
3387         char buf[256]; /* note: large enough to fit in unsolicited messages */
3388         size_t len;
3389
3390         fd = wpa_ctrl_get_fd(ctrl);
3391
3392         while (!wpa_cli_quit) {
3393                 FD_ZERO(&rfds);
3394                 FD_SET(fd, &rfds);
3395                 tv.tv_sec = ping_interval;
3396                 tv.tv_usec = 0;
3397                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3398                 if (res < 0 && errno != EINTR) {
3399                         perror("select");
3400                         break;
3401                 }
3402
3403                 if (FD_ISSET(fd, &rfds))
3404                         wpa_cli_recv_pending(ctrl, 1);
3405                 else {
3406                         /* verify that connection is still working */
3407                         len = sizeof(buf) - 1;
3408                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3409                                              wpa_cli_action_cb) < 0 ||
3410                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3411                                 printf("wpa_supplicant did not reply to PING "
3412                                        "command - exiting\n");
3413                                 break;
3414                         }
3415                 }
3416         }
3417 #endif /* CONFIG_ANSI_C_EXTRA */
3418 }
3419
3420
3421 static void wpa_cli_cleanup(void)
3422 {
3423         wpa_cli_close_connection();
3424         if (pid_file)
3425                 os_daemonize_terminate(pid_file);
3426
3427         os_program_deinit();
3428 }
3429
3430
3431 static void wpa_cli_terminate(int sig, void *ctx)
3432 {
3433         eloop_terminate();
3434 }
3435
3436
3437 static char * wpa_cli_get_default_ifname(void)
3438 {
3439         char *ifname = NULL;
3440
3441 #ifdef CONFIG_CTRL_IFACE_UNIX
3442         struct dirent *dent;
3443         DIR *dir = opendir(ctrl_iface_dir);
3444         if (!dir) {
3445 #ifdef ANDROID
3446                 char ifprop[PROPERTY_VALUE_MAX];
3447                 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3448                         ifname = os_strdup(ifprop);
3449                         printf("Using interface '%s'\n", ifname);
3450                         return ifname;
3451                 }
3452 #endif /* ANDROID */
3453                 return NULL;
3454         }
3455         while ((dent = readdir(dir))) {
3456 #ifdef _DIRENT_HAVE_D_TYPE
3457                 /*
3458                  * Skip the file if it is not a socket. Also accept
3459                  * DT_UNKNOWN (0) in case the C library or underlying
3460                  * file system does not support d_type.
3461                  */
3462                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3463                         continue;
3464 #endif /* _DIRENT_HAVE_D_TYPE */
3465                 if (os_strcmp(dent->d_name, ".") == 0 ||
3466                     os_strcmp(dent->d_name, "..") == 0)
3467                         continue;
3468                 printf("Selected interface '%s'\n", dent->d_name);
3469                 ifname = os_strdup(dent->d_name);
3470                 break;
3471         }
3472         closedir(dir);
3473 #endif /* CONFIG_CTRL_IFACE_UNIX */
3474
3475 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3476         char buf[4096], *pos;
3477         size_t len;
3478         struct wpa_ctrl *ctrl;
3479         int ret;
3480
3481         ctrl = wpa_ctrl_open(NULL);
3482         if (ctrl == NULL)
3483                 return NULL;
3484
3485         len = sizeof(buf) - 1;
3486         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3487         if (ret >= 0) {
3488                 buf[len] = '\0';
3489                 pos = os_strchr(buf, '\n');
3490                 if (pos)
3491                         *pos = '\0';
3492                 ifname = os_strdup(buf);
3493         }
3494         wpa_ctrl_close(ctrl);
3495 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3496
3497         return ifname;
3498 }
3499
3500
3501 int main(int argc, char *argv[])
3502 {
3503         int c;
3504         int daemonize = 0;
3505         int ret = 0;
3506         const char *global = NULL;
3507
3508         if (os_program_init())
3509                 return -1;
3510
3511         for (;;) {
3512                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3513                 if (c < 0)
3514                         break;
3515                 switch (c) {
3516                 case 'a':
3517                         action_file = optarg;
3518                         break;
3519                 case 'B':
3520                         daemonize = 1;
3521                         break;
3522                 case 'g':
3523                         global = optarg;
3524                         break;
3525                 case 'G':
3526                         ping_interval = atoi(optarg);
3527                         break;
3528                 case 'h':
3529                         usage();
3530                         return 0;
3531                 case 'v':
3532                         printf("%s\n", wpa_cli_version);
3533                         return 0;
3534                 case 'i':
3535                         os_free(ctrl_ifname);
3536                         ctrl_ifname = os_strdup(optarg);
3537                         break;
3538                 case 'p':
3539                         ctrl_iface_dir = optarg;
3540                         break;
3541                 case 'P':
3542                         pid_file = optarg;
3543                         break;
3544                 default:
3545                         usage();
3546                         return -1;
3547                 }
3548         }
3549
3550         interactive = (argc == optind) && (action_file == NULL);
3551
3552         if (interactive)
3553                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3554
3555         if (eloop_init())
3556                 return -1;
3557
3558         if (global) {
3559 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3560                 ctrl_conn = wpa_ctrl_open(NULL);
3561 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3562                 ctrl_conn = wpa_ctrl_open(global);
3563 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3564                 if (ctrl_conn == NULL) {
3565                         fprintf(stderr, "Failed to connect to wpa_supplicant "
3566                                 "global interface: %s  error: %s\n",
3567                                 global, strerror(errno));
3568                         return -1;
3569                 }
3570         }
3571
3572         eloop_register_signal_terminate(wpa_cli_terminate, NULL);
3573
3574         if (ctrl_ifname == NULL)
3575                 ctrl_ifname = wpa_cli_get_default_ifname();
3576
3577         if (interactive) {
3578                 wpa_cli_interactive();
3579         } else {
3580                 if (!global &&
3581                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3582                         fprintf(stderr, "Failed to connect to non-global "
3583                                 "ctrl_ifname: %s  error: %s\n",
3584                                 ctrl_ifname, strerror(errno));
3585                         return -1;
3586                 }
3587
3588                 if (action_file) {
3589                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
3590                                 wpa_cli_attached = 1;
3591                         } else {
3592                                 printf("Warning: Failed to attach to "
3593                                        "wpa_supplicant.\n");
3594                                 return -1;
3595                         }
3596                 }
3597
3598                 if (daemonize && os_daemonize(pid_file))
3599                         return -1;
3600
3601                 if (action_file)
3602                         wpa_cli_action(ctrl_conn);
3603                 else
3604                         ret = wpa_request(ctrl_conn, argc - optind,
3605                                           &argv[optind]);
3606         }
3607
3608         os_free(ctrl_ifname);
3609         eloop_destroy();
3610         wpa_cli_cleanup();
3611
3612         return ret;
3613 }
3614
3615 #else /* CONFIG_CTRL_IFACE */
3616 int main(int argc, char *argv[])
3617 {
3618         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3619         return -1;
3620 }
3621 #endif /* CONFIG_CTRL_IFACE */