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