wpa_cli: Add support for vendor_elem_* commands
[mech_eap.git] / wpa_supplicant / wpa_cli.c
1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2015, 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-2015, 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",
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"
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_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1774 {
1775         return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1776 }
1777
1778
1779 static char ** wpa_cli_complete_bss(const char *str, int pos)
1780 {
1781         int arg = get_cmd_arg_num(str, pos);
1782         char **res = NULL;
1783
1784         switch (arg) {
1785         case 1:
1786                 res = cli_txt_list_array(&bsses);
1787                 break;
1788         }
1789
1790         return res;
1791 }
1792
1793
1794 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1795                                       char *argv[])
1796 {
1797         if (argc < 1 || argc > 2) {
1798                 printf("Invalid GET_CAPABILITY command: need either one or "
1799                        "two arguments\n");
1800                 return -1;
1801         }
1802
1803         if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1804                 printf("Invalid GET_CAPABILITY command: second argument, "
1805                        "if any, must be 'strict'\n");
1806                 return -1;
1807         }
1808
1809         return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1810 }
1811
1812
1813 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1814 {
1815         printf("Available interfaces:\n");
1816         return wpa_ctrl_command(ctrl, "INTERFACES");
1817 }
1818
1819
1820 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1821 {
1822         if (argc < 1) {
1823                 wpa_cli_list_interfaces(ctrl);
1824                 return 0;
1825         }
1826
1827         wpa_cli_close_connection();
1828         os_free(ctrl_ifname);
1829         ctrl_ifname = os_strdup(argv[0]);
1830         if (!ctrl_ifname) {
1831                 printf("Failed to allocate memory\n");
1832                 return 0;
1833         }
1834
1835         if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
1836                 printf("Connected to interface '%s.\n", ctrl_ifname);
1837         } else {
1838                 printf("Could not connect to interface '%s' - re-trying\n",
1839                        ctrl_ifname);
1840         }
1841         return 0;
1842 }
1843
1844
1845 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1846                                    char *argv[])
1847 {
1848         return wpa_ctrl_command(ctrl, "RECONFIGURE");
1849 }
1850
1851
1852 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1853                                  char *argv[])
1854 {
1855         return wpa_ctrl_command(ctrl, "TERMINATE");
1856 }
1857
1858
1859 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1860                                      char *argv[])
1861 {
1862         char cmd[256];
1863         int res;
1864
1865         if (argc < 1) {
1866                 printf("Invalid INTERFACE_ADD command: needs at least one "
1867                        "argument (interface name)\n"
1868                        "All arguments: ifname confname driver ctrl_interface "
1869                        "driver_param bridge_name [create]\n");
1870                 return -1;
1871         }
1872
1873         /*
1874          * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1875          * <driver_param>TAB<bridge_name>[TAB<create>]
1876          */
1877         res = os_snprintf(cmd, sizeof(cmd),
1878                           "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
1879                           argv[0],
1880                           argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1881                           argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1882                           argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
1883         if (os_snprintf_error(sizeof(cmd), res))
1884                 return -1;
1885         cmd[sizeof(cmd) - 1] = '\0';
1886         return wpa_ctrl_command(ctrl, cmd);
1887 }
1888
1889
1890 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1891                                         char *argv[])
1892 {
1893         return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1894 }
1895
1896
1897 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1898                                       char *argv[])
1899 {
1900         return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1901 }
1902
1903
1904 #ifdef CONFIG_AP
1905 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1906 {
1907         return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1908 }
1909
1910
1911 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1912                                 char *addr, size_t addr_len)
1913 {
1914         char buf[4096], *pos;
1915         size_t len;
1916         int ret;
1917
1918         if (ctrl_conn == NULL) {
1919                 printf("Not connected to hostapd - command dropped.\n");
1920                 return -1;
1921         }
1922         len = sizeof(buf) - 1;
1923         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1924                                wpa_cli_msg_cb);
1925         if (ret == -2) {
1926                 printf("'%s' command timed out.\n", cmd);
1927                 return -2;
1928         } else if (ret < 0) {
1929                 printf("'%s' command failed.\n", cmd);
1930                 return -1;
1931         }
1932
1933         buf[len] = '\0';
1934         if (os_memcmp(buf, "FAIL", 4) == 0)
1935                 return -1;
1936         printf("%s", buf);
1937
1938         pos = buf;
1939         while (*pos != '\0' && *pos != '\n')
1940                 pos++;
1941         *pos = '\0';
1942         os_strlcpy(addr, buf, addr_len);
1943         return 0;
1944 }
1945
1946
1947 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1948 {
1949         char addr[32], cmd[64];
1950
1951         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1952                 return 0;
1953         do {
1954                 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1955         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1956
1957         return -1;
1958 }
1959
1960
1961 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1962                                       char *argv[])
1963 {
1964         return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1965 }
1966
1967
1968 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1969                                     char *argv[])
1970 {
1971         return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1972 }
1973
1974 static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1975                                     char *argv[])
1976 {
1977         return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1978 }
1979
1980 #endif /* CONFIG_AP */
1981
1982
1983 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1984 {
1985         return wpa_ctrl_command(ctrl, "SUSPEND");
1986 }
1987
1988
1989 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1990 {
1991         return wpa_ctrl_command(ctrl, "RESUME");
1992 }
1993
1994
1995 #ifdef CONFIG_TESTING_OPTIONS
1996 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1997 {
1998         return wpa_ctrl_command(ctrl, "DROP_SA");
1999 }
2000 #endif /* CONFIG_TESTING_OPTIONS */
2001
2002
2003 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
2004 {
2005         return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
2006 }
2007
2008
2009 #ifdef CONFIG_MESH
2010
2011 static int wpa_cli_cmd_mesh_interface_add(struct wpa_ctrl *ctrl, int argc,
2012                                           char *argv[])
2013 {
2014         return wpa_cli_cmd(ctrl, "MESH_INTERFACE_ADD", 0, argc, argv);
2015 }
2016
2017
2018 static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
2019                                       char *argv[])
2020 {
2021         return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
2022 }
2023
2024
2025 static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
2026                                          char *argv[])
2027 {
2028         return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
2029 }
2030
2031 #endif /* CONFIG_MESH */
2032
2033
2034 #ifdef CONFIG_P2P
2035
2036 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
2037 {
2038         return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
2039 }
2040
2041
2042 static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
2043 {
2044         char **res = NULL;
2045         int arg = get_cmd_arg_num(str, pos);
2046
2047         res = os_calloc(6, sizeof(char *));
2048         if (res == NULL)
2049                 return NULL;
2050         res[0] = os_strdup("type=social");
2051         if (res[0] == NULL) {
2052                 os_free(res);
2053                 return NULL;
2054         }
2055         res[1] = os_strdup("type=progressive");
2056         if (res[1] == NULL)
2057                 return res;
2058         res[2] = os_strdup("delay=");
2059         if (res[2] == NULL)
2060                 return res;
2061         res[3] = os_strdup("dev_id=");
2062         if (res[3] == NULL)
2063                 return res;
2064         if (arg == 1)
2065                 res[4] = os_strdup("[timeout]");
2066
2067         return res;
2068 }
2069
2070
2071 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
2072                                      char *argv[])
2073 {
2074         return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
2075 }
2076
2077
2078 static int wpa_cli_cmd_p2p_asp_provision(struct wpa_ctrl *ctrl, int argc,
2079                                          char *argv[])
2080 {
2081         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION", 3, argc, argv);
2082 }
2083
2084
2085 static int wpa_cli_cmd_p2p_asp_provision_resp(struct wpa_ctrl *ctrl, int argc,
2086                                               char *argv[])
2087 {
2088         return wpa_cli_cmd(ctrl, "P2P_ASP_PROVISION_RESP", 2, argc, argv);
2089 }
2090
2091
2092 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
2093                                    char *argv[])
2094 {
2095         return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
2096 }
2097
2098
2099 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
2100 {
2101         int arg = get_cmd_arg_num(str, pos);
2102         char **res = NULL;
2103
2104         switch (arg) {
2105         case 1:
2106                 res = cli_txt_list_array(&p2p_peers);
2107                 break;
2108         }
2109
2110         return res;
2111 }
2112
2113
2114 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
2115                                   char *argv[])
2116 {
2117         return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
2118 }
2119
2120
2121 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
2122                                         char *argv[])
2123 {
2124         return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
2125 }
2126
2127
2128 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
2129 {
2130         int arg = get_cmd_arg_num(str, pos);
2131         char **res = NULL;
2132
2133         switch (arg) {
2134         case 1:
2135                 res = cli_txt_list_array(&p2p_groups);
2136                 break;
2137         }
2138
2139         return res;
2140 }
2141
2142
2143 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
2144                                         char *argv[])
2145 {
2146         return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
2147 }
2148
2149
2150 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
2151                                      char *argv[])
2152 {
2153         if (argc != 2 && argc != 3) {
2154                 printf("Invalid P2P_PROV_DISC command: needs at least "
2155                        "two arguments, address and config method\n"
2156                        "(display, keypad, or pbc) and an optional join\n");
2157                 return -1;
2158         }
2159
2160         return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
2161 }
2162
2163
2164 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
2165                                           char *argv[])
2166 {
2167         return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
2168 }
2169
2170
2171 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
2172                                          char *argv[])
2173 {
2174         char cmd[4096];
2175
2176         if (argc < 2) {
2177                 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
2178                        "or more arguments (address and TLVs)\n");
2179                 return -1;
2180         }
2181
2182         if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
2183                 return -1;
2184         return wpa_ctrl_command(ctrl, cmd);
2185 }
2186
2187
2188 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
2189                                                 int argc, char *argv[])
2190 {
2191         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
2192 }
2193
2194
2195 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
2196                                           char *argv[])
2197 {
2198         char cmd[4096];
2199         int res;
2200
2201         if (argc != 4) {
2202                 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
2203                        "arguments (freq, address, dialog token, and TLVs)\n");
2204                 return -1;
2205         }
2206
2207         res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
2208                           argv[0], argv[1], argv[2], argv[3]);
2209         if (os_snprintf_error(sizeof(cmd), res))
2210                 return -1;
2211         cmd[sizeof(cmd) - 1] = '\0';
2212         return wpa_ctrl_command(ctrl, cmd);
2213 }
2214
2215
2216 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
2217                                           char *argv[])
2218 {
2219         return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
2220 }
2221
2222
2223 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
2224                                               int argc, char *argv[])
2225 {
2226         return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
2227 }
2228
2229
2230 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
2231                                          char *argv[])
2232 {
2233         return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
2234 }
2235
2236
2237 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
2238                                        char *argv[])
2239 {
2240         if (argc < 3) {
2241                 printf("Invalid P2P_SERVICE_ADD command: needs 3-6 arguments\n");
2242                 return -1;
2243         }
2244
2245         return wpa_cli_cmd(ctrl, "P2P_SERVICE_ADD", 3, argc, argv);
2246 }
2247
2248
2249 static int wpa_cli_cmd_p2p_service_rep(struct wpa_ctrl *ctrl, int argc,
2250                                        char *argv[])
2251 {
2252         if (argc < 5 || argc > 6) {
2253                 printf("Invalid P2P_SERVICE_REP command: needs 5-6 "
2254                        "arguments\n");
2255                 return -1;
2256         }
2257
2258         return wpa_cli_cmd(ctrl, "P2P_SERVICE_REP", 5, argc, argv);
2259 }
2260
2261
2262 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
2263                                        char *argv[])
2264 {
2265         char cmd[4096];
2266         int res;
2267
2268         if (argc != 2 && argc != 3) {
2269                 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
2270                        "arguments\n");
2271                 return -1;
2272         }
2273
2274         if (argc == 3)
2275                 res = os_snprintf(cmd, sizeof(cmd),
2276                                   "P2P_SERVICE_DEL %s %s %s",
2277                                   argv[0], argv[1], argv[2]);
2278         else
2279                 res = os_snprintf(cmd, sizeof(cmd),
2280                                   "P2P_SERVICE_DEL %s %s",
2281                                   argv[0], argv[1]);
2282         if (os_snprintf_error(sizeof(cmd), res))
2283                 return -1;
2284         cmd[sizeof(cmd) - 1] = '\0';
2285         return wpa_ctrl_command(ctrl, cmd);
2286 }
2287
2288
2289 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2290                                   int argc, char *argv[])
2291 {
2292         return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
2293 }
2294
2295
2296 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2297                                   int argc, char *argv[])
2298 {
2299         return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
2300 }
2301
2302
2303 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2304 {
2305         return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
2306 }
2307
2308
2309 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2310 {
2311         int arg = get_cmd_arg_num(str, pos);
2312         char **res = NULL;
2313
2314         switch (arg) {
2315         case 1:
2316                 res = cli_txt_list_array(&p2p_peers);
2317                 break;
2318         }
2319
2320         return res;
2321 }
2322
2323
2324 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2325                                      char *addr, size_t addr_len,
2326                                      int discovered)
2327 {
2328         char buf[4096], *pos;
2329         size_t len;
2330         int ret;
2331
2332         if (ctrl_conn == NULL)
2333                 return -1;
2334         len = sizeof(buf) - 1;
2335         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
2336                                wpa_cli_msg_cb);
2337         if (ret == -2) {
2338                 printf("'%s' command timed out.\n", cmd);
2339                 return -2;
2340         } else if (ret < 0) {
2341                 printf("'%s' command failed.\n", cmd);
2342                 return -1;
2343         }
2344
2345         buf[len] = '\0';
2346         if (os_memcmp(buf, "FAIL", 4) == 0)
2347                 return -1;
2348
2349         pos = buf;
2350         while (*pos != '\0' && *pos != '\n')
2351                 pos++;
2352         *pos++ = '\0';
2353         os_strlcpy(addr, buf, addr_len);
2354         if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2355                 printf("%s\n", addr);
2356         return 0;
2357 }
2358
2359
2360 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2361 {
2362         char addr[32], cmd[64];
2363         int discovered;
2364
2365         discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2366
2367         if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2368                                       addr, sizeof(addr), discovered))
2369                 return -1;
2370         do {
2371                 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2372         } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2373                          discovered) == 0);
2374
2375         return 0;
2376 }
2377
2378
2379 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2380 {
2381         return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2382 }
2383
2384
2385 static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2386 {
2387         int arg = get_cmd_arg_num(str, pos);
2388         const char *fields[] = {
2389                 "discoverability",
2390                 "managed",
2391                 "listen_channel",
2392                 "ssid_postfix",
2393                 "noa",
2394                 "ps",
2395                 "oppps",
2396                 "ctwindow",
2397                 "disabled",
2398                 "conc_pref",
2399                 "force_long_sd",
2400                 "peer_filter",
2401                 "cross_connect",
2402                 "go_apsd",
2403                 "client_apsd",
2404                 "disallow_freq",
2405                 "disc_int",
2406                 "per_sta_psk",
2407         };
2408         int i, num_fields = ARRAY_SIZE(fields);
2409
2410         if (arg == 1) {
2411                 char **res = os_calloc(num_fields + 1, sizeof(char *));
2412                 if (res == NULL)
2413                         return NULL;
2414                 for (i = 0; i < num_fields; i++) {
2415                         res[i] = os_strdup(fields[i]);
2416                         if (res[i] == NULL)
2417                                 return res;
2418                 }
2419                 return res;
2420         }
2421
2422         if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2423                 return cli_txt_list_array(&p2p_peers);
2424
2425         return NULL;
2426 }
2427
2428
2429 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2430 {
2431         return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2432 }
2433
2434
2435 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2436                                   char *argv[])
2437 {
2438         return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2439 }
2440
2441
2442 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2443                                        char *argv[])
2444 {
2445         return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2446 }
2447
2448
2449 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2450                                         char *argv[])
2451 {
2452         if (argc != 0 && argc != 2 && argc != 4) {
2453                 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2454                        "(preferred duration, interval; in microsecods).\n"
2455                        "Optional second pair can be used to provide "
2456                        "acceptable values.\n");
2457                 return -1;
2458         }
2459
2460         return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2461 }
2462
2463
2464 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2465                                       char *argv[])
2466 {
2467         if (argc != 0 && argc != 2) {
2468                 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2469                        "(availability period, availability interval; in "
2470                        "millisecods).\n"
2471                        "Extended Listen Timing can be cancelled with this "
2472                        "command when used without parameters.\n");
2473                 return -1;
2474         }
2475
2476         return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2477 }
2478
2479
2480 static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2481                                          char *argv[])
2482 {
2483         return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2484 }
2485
2486
2487 static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
2488                                        char *argv[])
2489 {
2490         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
2491 }
2492
2493
2494 static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
2495                                        char *argv[])
2496 {
2497         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
2498 }
2499
2500
2501 static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
2502                                           char *argv[])
2503 {
2504         return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
2505 }
2506
2507 #endif /* CONFIG_P2P */
2508
2509 #ifdef CONFIG_WIFI_DISPLAY
2510
2511 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2512                                        char *argv[])
2513 {
2514         char cmd[100];
2515         int res;
2516
2517         if (argc != 1 && argc != 2) {
2518                 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2519                        "arguments (subelem, hexdump)\n");
2520                 return -1;
2521         }
2522
2523         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2524                           argv[0], argc > 1 ? argv[1] : "");
2525         if (os_snprintf_error(sizeof(cmd), res))
2526                 return -1;
2527         cmd[sizeof(cmd) - 1] = '\0';
2528         return wpa_ctrl_command(ctrl, cmd);
2529 }
2530
2531
2532 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2533                                        char *argv[])
2534 {
2535         char cmd[100];
2536         int res;
2537
2538         if (argc != 1) {
2539                 printf("Invalid WFD_SUBELEM_GET command: needs one "
2540                        "argument (subelem)\n");
2541                 return -1;
2542         }
2543
2544         res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2545                           argv[0]);
2546         if (os_snprintf_error(sizeof(cmd), res))
2547                 return -1;
2548         cmd[sizeof(cmd) - 1] = '\0';
2549         return wpa_ctrl_command(ctrl, cmd);
2550 }
2551 #endif /* CONFIG_WIFI_DISPLAY */
2552
2553
2554 #ifdef CONFIG_INTERWORKING
2555 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2556                                   char *argv[])
2557 {
2558         return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2559 }
2560
2561
2562 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2563                                        char *argv[])
2564 {
2565         return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2566 }
2567
2568
2569 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2570                                            char *argv[])
2571 {
2572         return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2573 }
2574
2575
2576 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2577                                             char *argv[])
2578 {
2579         return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2580 }
2581
2582
2583 static int wpa_cli_cmd_interworking_add_network(struct wpa_ctrl *ctrl, int argc,
2584                                                 char *argv[])
2585 {
2586         return wpa_cli_cmd(ctrl, "INTERWORKING_ADD_NETWORK", 1, argc, argv);
2587 }
2588
2589
2590 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2591 {
2592         return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2593 }
2594
2595
2596 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2597                                    char *argv[])
2598 {
2599         return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2600 }
2601
2602
2603 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2604                                         char *argv[])
2605 {
2606         return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2607 }
2608 #endif /* CONFIG_INTERWORKING */
2609
2610
2611 #ifdef CONFIG_HS20
2612
2613 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2614                                      char *argv[])
2615 {
2616         return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2617 }
2618
2619
2620 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2621                                                char *argv[])
2622 {
2623         char cmd[512];
2624
2625         if (argc == 0) {
2626                 printf("Command needs one or two arguments (dst mac addr and "
2627                        "optional home realm)\n");
2628                 return -1;
2629         }
2630
2631         if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2632                       argc, argv) < 0)
2633                 return -1;
2634
2635         return wpa_ctrl_command(ctrl, cmd);
2636 }
2637
2638
2639 static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2640                                          char *argv[])
2641 {
2642         char cmd[512];
2643
2644         if (argc < 2) {
2645                 printf("Command needs two arguments (dst mac addr and "
2646                        "icon name)\n");
2647                 return -1;
2648         }
2649
2650         if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2651                 return -1;
2652
2653         return wpa_ctrl_command(ctrl, cmd);
2654 }
2655
2656
2657 static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2658 {
2659         return wpa_ctrl_command(ctrl, "FETCH_OSU");
2660 }
2661
2662
2663 static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2664                                         char *argv[])
2665 {
2666         return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2667 }
2668
2669 #endif /* CONFIG_HS20 */
2670
2671
2672 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2673                                        char *argv[])
2674 {
2675         return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2676 }
2677
2678
2679 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2680                                      char *argv[])
2681 {
2682         return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2683 }
2684
2685
2686 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2687                                   char *argv[])
2688 {
2689         return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2690 }
2691
2692
2693 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2694                                      char *argv[])
2695 {
2696         return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2697 }
2698
2699
2700 static int wpa_cli_cmd_tdls_link_status(struct wpa_ctrl *ctrl, int argc,
2701                                         char *argv[])
2702 {
2703         return wpa_cli_cmd(ctrl, "TDLS_LINK_STATUS", 1, argc, argv);
2704 }
2705
2706
2707 static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2708                                     char *argv[])
2709 {
2710         return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2711 }
2712
2713
2714 static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2715                                     char *argv[])
2716 {
2717         return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2718 }
2719
2720
2721 static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2722                                     char *argv[])
2723 {
2724         return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2725 }
2726
2727
2728 static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2729                                         char *argv[])
2730 {
2731         return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2732 }
2733
2734
2735 static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2736                                                char *argv[])
2737 {
2738         return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2739 }
2740
2741
2742 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2743                                    char *argv[])
2744 {
2745         return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2746 }
2747
2748
2749 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2750                                    char *argv[])
2751 {
2752         return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2753 }
2754
2755
2756 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2757                                       char *argv[])
2758 {
2759         return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2760 }
2761
2762
2763 #ifdef CONFIG_AUTOSCAN
2764
2765 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2766 {
2767         if (argc == 0)
2768                 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2769
2770         return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2771 }
2772
2773 #endif /* CONFIG_AUTOSCAN */
2774
2775
2776 #ifdef CONFIG_WNM
2777
2778 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2779 {
2780         return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2781 }
2782
2783
2784 static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2785 {
2786         return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2787 }
2788
2789 #endif /* CONFIG_WNM */
2790
2791
2792 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2793 {
2794         if (argc == 0)
2795                 return -1;
2796         return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2797 }
2798
2799
2800 #ifdef ANDROID
2801 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2802 {
2803         return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2804 }
2805 #endif /* ANDROID */
2806
2807
2808 static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2809 {
2810         return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2811 }
2812
2813
2814 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2815 {
2816         return wpa_ctrl_command(ctrl, "FLUSH");
2817 }
2818
2819
2820 static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2821 {
2822         return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2823 }
2824
2825
2826 static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2827                                             char *argv[])
2828 {
2829         return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2830 }
2831
2832
2833 static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2834 {
2835         return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2836 }
2837
2838
2839 static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2840                                      char *argv[])
2841 {
2842         return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2843 }
2844
2845
2846 static int wpa_cli_cmd_get_pref_freq_list(struct wpa_ctrl *ctrl, int argc,
2847                                           char *argv[])
2848 {
2849         return wpa_cli_cmd(ctrl, "GET_PREF_FREQ_LIST", 1, argc, argv);
2850 }
2851
2852
2853 enum wpa_cli_cmd_flags {
2854         cli_cmd_flag_none               = 0x00,
2855         cli_cmd_flag_sensitive          = 0x01
2856 };
2857
2858 struct wpa_cli_cmd {
2859         const char *cmd;
2860         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2861         char ** (*completion)(const char *str, int pos);
2862         enum wpa_cli_cmd_flags flags;
2863         const char *usage;
2864 };
2865
2866 static const struct wpa_cli_cmd wpa_cli_commands[] = {
2867         { "status", wpa_cli_cmd_status, NULL,
2868           cli_cmd_flag_none,
2869           "[verbose] = get current WPA/EAPOL/EAP status" },
2870         { "ifname", wpa_cli_cmd_ifname, NULL,
2871           cli_cmd_flag_none,
2872           "= get current interface name" },
2873         { "ping", wpa_cli_cmd_ping, NULL,
2874           cli_cmd_flag_none,
2875           "= pings wpa_supplicant" },
2876         { "relog", wpa_cli_cmd_relog, NULL,
2877           cli_cmd_flag_none,
2878           "= re-open log-file (allow rolling logs)" },
2879         { "note", wpa_cli_cmd_note, NULL,
2880           cli_cmd_flag_none,
2881           "<text> = add a note to wpa_supplicant debug log" },
2882         { "mib", wpa_cli_cmd_mib, NULL,
2883           cli_cmd_flag_none,
2884           "= get MIB variables (dot1x, dot11)" },
2885         { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2886           cli_cmd_flag_none,
2887           "[command] = show usage help" },
2888         { "interface", wpa_cli_cmd_interface, NULL,
2889           cli_cmd_flag_none,
2890           "[ifname] = show interfaces/select interface" },
2891         { "level", wpa_cli_cmd_level, NULL,
2892           cli_cmd_flag_none,
2893           "<debug level> = change debug level" },
2894         { "license", wpa_cli_cmd_license, NULL,
2895           cli_cmd_flag_none,
2896           "= show full wpa_cli license" },
2897         { "quit", wpa_cli_cmd_quit, NULL,
2898           cli_cmd_flag_none,
2899           "= exit wpa_cli" },
2900         { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
2901           cli_cmd_flag_none,
2902           "= set variables (shows list of variables when run without "
2903           "arguments)" },
2904         { "dump", wpa_cli_cmd_dump, NULL,
2905           cli_cmd_flag_none,
2906           "= dump config variables" },
2907         { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
2908           cli_cmd_flag_none,
2909           "<name> = get information" },
2910         { "logon", wpa_cli_cmd_logon, NULL,
2911           cli_cmd_flag_none,
2912           "= IEEE 802.1X EAPOL state machine logon" },
2913         { "logoff", wpa_cli_cmd_logoff, NULL,
2914           cli_cmd_flag_none,
2915           "= IEEE 802.1X EAPOL state machine logoff" },
2916         { "pmksa", wpa_cli_cmd_pmksa, NULL,
2917           cli_cmd_flag_none,
2918           "= show PMKSA cache" },
2919         { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2920           cli_cmd_flag_none,
2921           "= flush PMKSA cache entries" },
2922         { "reassociate", wpa_cli_cmd_reassociate, NULL,
2923           cli_cmd_flag_none,
2924           "= force reassociation" },
2925         { "reattach", wpa_cli_cmd_reattach, NULL,
2926           cli_cmd_flag_none,
2927           "= force reassociation back to the same BSS" },
2928         { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2929           cli_cmd_flag_none,
2930           "<BSSID> = force preauthentication" },
2931         { "identity", wpa_cli_cmd_identity, NULL,
2932           cli_cmd_flag_none,
2933           "<network id> <identity> = configure identity for an SSID" },
2934         { "password", wpa_cli_cmd_password, NULL,
2935           cli_cmd_flag_sensitive,
2936           "<network id> <password> = configure password for an SSID" },
2937         { "new_password", wpa_cli_cmd_new_password, NULL,
2938           cli_cmd_flag_sensitive,
2939           "<network id> <password> = change password for an SSID" },
2940         { "pin", wpa_cli_cmd_pin, NULL,
2941           cli_cmd_flag_sensitive,
2942           "<network id> <pin> = configure pin for an SSID" },
2943         { "otp", wpa_cli_cmd_otp, NULL,
2944           cli_cmd_flag_sensitive,
2945           "<network id> <password> = configure one-time-password for an SSID"
2946         },
2947         { "passphrase", wpa_cli_cmd_passphrase, NULL,
2948           cli_cmd_flag_sensitive,
2949           "<network id> <passphrase> = configure private key passphrase\n"
2950           "  for an SSID" },
2951         { "sim", wpa_cli_cmd_sim, NULL,
2952           cli_cmd_flag_sensitive,
2953           "<network id> <pin> = report SIM operation result" },
2954         { "bssid", wpa_cli_cmd_bssid, NULL,
2955           cli_cmd_flag_none,
2956           "<network id> <BSSID> = set preferred BSSID for an SSID" },
2957         { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2958           cli_cmd_flag_none,
2959           "<BSSID> = add a BSSID to the blacklist\n"
2960           "blacklist clear = clear the blacklist\n"
2961           "blacklist = display the blacklist" },
2962         { "log_level", wpa_cli_cmd_log_level, NULL,
2963           cli_cmd_flag_none,
2964           "<level> [<timestamp>] = update the log level/timestamp\n"
2965           "log_level = display the current log level and log options" },
2966         { "list_networks", wpa_cli_cmd_list_networks, NULL,
2967           cli_cmd_flag_none,
2968           "= list configured networks" },
2969         { "select_network", wpa_cli_cmd_select_network,
2970           wpa_cli_complete_network_id,
2971           cli_cmd_flag_none,
2972           "<network id> = select a network (disable others)" },
2973         { "enable_network", wpa_cli_cmd_enable_network,
2974           wpa_cli_complete_network_id,
2975           cli_cmd_flag_none,
2976           "<network id> = enable a network" },
2977         { "disable_network", wpa_cli_cmd_disable_network,
2978           wpa_cli_complete_network_id,
2979           cli_cmd_flag_none,
2980           "<network id> = disable a network" },
2981         { "add_network", wpa_cli_cmd_add_network, NULL,
2982           cli_cmd_flag_none,
2983           "= add a network" },
2984         { "remove_network", wpa_cli_cmd_remove_network,
2985           wpa_cli_complete_network_id,
2986           cli_cmd_flag_none,
2987           "<network id> = remove a network" },
2988         { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
2989           cli_cmd_flag_sensitive,
2990           "<network id> <variable> <value> = set network variables (shows\n"
2991           "  list of variables when run without arguments)" },
2992         { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
2993           cli_cmd_flag_none,
2994           "<network id> <variable> = get network variables" },
2995         { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
2996           cli_cmd_flag_none,
2997           "<src network id> <dst network id> <variable> = duplicate network variables"
2998         },
2999         { "list_creds", wpa_cli_cmd_list_creds, NULL,
3000           cli_cmd_flag_none,
3001           "= list configured credentials" },
3002         { "add_cred", wpa_cli_cmd_add_cred, NULL,
3003           cli_cmd_flag_none,
3004           "= add a credential" },
3005         { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
3006           cli_cmd_flag_none,
3007           "<cred id> = remove a credential" },
3008         { "set_cred", wpa_cli_cmd_set_cred, NULL,
3009           cli_cmd_flag_sensitive,
3010           "<cred id> <variable> <value> = set credential variables" },
3011         { "get_cred", wpa_cli_cmd_get_cred, NULL,
3012           cli_cmd_flag_none,
3013           "<cred id> <variable> = get credential variables" },
3014         { "save_config", wpa_cli_cmd_save_config, NULL,
3015           cli_cmd_flag_none,
3016           "= save the current configuration" },
3017         { "disconnect", wpa_cli_cmd_disconnect, NULL,
3018           cli_cmd_flag_none,
3019           "= disconnect and wait for reassociate/reconnect command before\n"
3020           "  connecting" },
3021         { "reconnect", wpa_cli_cmd_reconnect, NULL,
3022           cli_cmd_flag_none,
3023           "= like reassociate, but only takes effect if already disconnected"
3024         },
3025         { "scan", wpa_cli_cmd_scan, NULL,
3026           cli_cmd_flag_none,
3027           "= request new BSS scan" },
3028         { "scan_results", wpa_cli_cmd_scan_results, NULL,
3029           cli_cmd_flag_none,
3030           "= get latest scan results" },
3031         { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
3032           cli_cmd_flag_none,
3033           "<<idx> | <bssid>> = get detailed scan result info" },
3034         { "get_capability", wpa_cli_cmd_get_capability, NULL,
3035           cli_cmd_flag_none,
3036           "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
3037           "= get capabilities" },
3038         { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
3039           cli_cmd_flag_none,
3040           "= force wpa_supplicant to re-read its configuration file" },
3041         { "terminate", wpa_cli_cmd_terminate, NULL,
3042           cli_cmd_flag_none,
3043           "= terminate wpa_supplicant" },
3044         { "interface_add", wpa_cli_cmd_interface_add, NULL,
3045           cli_cmd_flag_none,
3046           "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
3047           "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
3048           "  are optional" },
3049         { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
3050           cli_cmd_flag_none,
3051           "<ifname> = removes the interface" },
3052         { "interface_list", wpa_cli_cmd_interface_list, NULL,
3053           cli_cmd_flag_none,
3054           "= list available interfaces" },
3055         { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
3056           cli_cmd_flag_none,
3057           "<value> = set ap_scan parameter" },
3058         { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
3059           cli_cmd_flag_none,
3060           "<value> = set scan_interval parameter (in seconds)" },
3061         { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
3062           cli_cmd_flag_none,
3063           "<value> = set BSS expiration age parameter" },
3064         { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
3065           cli_cmd_flag_none,
3066           "<value> = set BSS expiration scan count parameter" },
3067         { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
3068           cli_cmd_flag_none,
3069           "<value> = set BSS flush age (0 by default)" },
3070         { "stkstart", wpa_cli_cmd_stkstart, NULL,
3071           cli_cmd_flag_none,
3072           "<addr> = request STK negotiation with <addr>" },
3073         { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
3074           cli_cmd_flag_none,
3075           "<addr> = request over-the-DS FT with <addr>" },
3076         { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
3077           cli_cmd_flag_none,
3078           "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
3079         { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
3080           cli_cmd_flag_sensitive,
3081           "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3082           "hardcoded)" },
3083         { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
3084           cli_cmd_flag_sensitive,
3085           "<PIN> = verify PIN checksum" },
3086         { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
3087           "Cancels the pending WPS operation" },
3088 #ifdef CONFIG_WPS_NFC
3089         { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3090           cli_cmd_flag_none,
3091           "[BSSID] = start Wi-Fi Protected Setup: NFC" },
3092         { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3093           cli_cmd_flag_none,
3094           "<WPS|NDEF> = build configuration token" },
3095         { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3096           cli_cmd_flag_none,
3097           "<WPS|NDEF> = create password token" },
3098         { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
3099           cli_cmd_flag_sensitive,
3100           "<hexdump of payload> = report read NFC tag with WPS data" },
3101         { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3102           cli_cmd_flag_none,
3103           "<NDEF> <WPS> = create NFC handover request" },
3104         { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3105           cli_cmd_flag_none,
3106           "<NDEF> <WPS> = create NFC handover select" },
3107         { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3108           cli_cmd_flag_none,
3109           "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3110           "NFC handover" },
3111 #endif /* CONFIG_WPS_NFC */
3112         { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
3113           cli_cmd_flag_sensitive,
3114           "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
3115         { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
3116           cli_cmd_flag_sensitive,
3117           "[params..] = enable/disable AP PIN" },
3118         { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
3119           cli_cmd_flag_none,
3120           "[IP address] = start Wi-Fi Protected Setup External Registrar" },
3121         { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
3122           cli_cmd_flag_none,
3123           "= stop Wi-Fi Protected Setup External Registrar" },
3124         { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
3125           cli_cmd_flag_sensitive,
3126           "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
3127         { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
3128           cli_cmd_flag_none,
3129           "<UUID> = accept an Enrollee PBC using External Registrar" },
3130         { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
3131           cli_cmd_flag_sensitive,
3132           "<UUID> <PIN> = learn AP configuration" },
3133         { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
3134           cli_cmd_flag_none,
3135           "<UUID> <network id> = set AP configuration for enrolling" },
3136         { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
3137           cli_cmd_flag_sensitive,
3138           "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
3139 #ifdef CONFIG_WPS_NFC
3140         { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
3141           cli_cmd_flag_none,
3142           "<WPS/NDEF> <UUID> = build NFC configuration token" },
3143 #endif /* CONFIG_WPS_NFC */
3144         { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
3145           cli_cmd_flag_none,
3146           "<addr> = request RSN authentication with <addr> in IBSS" },
3147 #ifdef CONFIG_AP
3148         { "sta", wpa_cli_cmd_sta, NULL,
3149           cli_cmd_flag_none,
3150           "<addr> = get information about an associated station (AP)" },
3151         { "all_sta", wpa_cli_cmd_all_sta, NULL,
3152           cli_cmd_flag_none,
3153           "= get information about all associated stations (AP)" },
3154         { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
3155           cli_cmd_flag_none,
3156           "<addr> = deauthenticate a station" },
3157         { "disassociate", wpa_cli_cmd_disassociate, NULL,
3158           cli_cmd_flag_none,
3159           "<addr> = disassociate a station" },
3160         { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3161           cli_cmd_flag_none,
3162           "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3163           " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3164           " = CSA parameters" },
3165 #endif /* CONFIG_AP */
3166         { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
3167           "= notification of suspend/hibernate" },
3168         { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
3169           "= notification of resume/thaw" },
3170 #ifdef CONFIG_TESTING_OPTIONS
3171         { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
3172           "= drop SA without deauth/disassoc (test command)" },
3173 #endif /* CONFIG_TESTING_OPTIONS */
3174         { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
3175           cli_cmd_flag_none,
3176           "<addr> = roam to the specified BSS" },
3177 #ifdef CONFIG_MESH
3178         { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3179           cli_cmd_flag_none,
3180           "[ifname] = Create a new mesh interface" },
3181         { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3182           cli_cmd_flag_none,
3183           "<network id> = join a mesh network (disable others)" },
3184         { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3185           cli_cmd_flag_none,
3186           "<ifname> = Remove mesh group interface" },
3187 #endif /* CONFIG_MESH */
3188 #ifdef CONFIG_P2P
3189         { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3190           cli_cmd_flag_none,
3191           "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
3192         { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
3193           "= stop P2P Devices search" },
3194         { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3195           cli_cmd_flag_none,
3196           "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3197         { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3198           cli_cmd_flag_none,
3199           "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
3200         { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3201           cli_cmd_flag_none,
3202           "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
3203         { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
3204           "[timeout] = listen for P2P Devices for up-to timeout seconds" },
3205         { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3206           wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
3207           "<ifname> = remove P2P group interface (terminate group if GO)" },
3208         { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
3209           "[ht40] = add a new P2P group (local end as GO)" },
3210         { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3211           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3212           "<addr> <method> = request provisioning discovery" },
3213         { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
3214           cli_cmd_flag_none,
3215           "= get the passphrase for a group (GO only)" },
3216         { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
3217           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3218           "<addr> <TLVs> = schedule service discovery request" },
3219         { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
3220           NULL, cli_cmd_flag_none,
3221           "<id> = cancel pending service discovery request" },
3222         { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
3223           cli_cmd_flag_none,
3224           "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
3225         { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
3226           cli_cmd_flag_none,
3227           "= indicate change in local services" },
3228         { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
3229           cli_cmd_flag_none,
3230           "<external> = set external processing of service discovery" },
3231         { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
3232           cli_cmd_flag_none,
3233           "= remove all stored service entries" },
3234         { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
3235           cli_cmd_flag_none,
3236           "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
3237           "service" },
3238         { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3239           cli_cmd_flag_none,
3240           "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3241           "local ASP service" },
3242         { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
3243           cli_cmd_flag_none,
3244           "<bonjour|upnp> <query|version> [|service] = remove a local "
3245           "service" },
3246         { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
3247           cli_cmd_flag_none,
3248           "<addr> = reject connection attempts from a specific peer" },
3249         { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
3250           cli_cmd_flag_none,
3251           "<cmd> [peer=addr] = invite peer" },
3252         { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
3253           "[discovered] = list known (optionally, only fully discovered) P2P "
3254           "peers" },
3255         { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3256           cli_cmd_flag_none,
3257           "<address> = show information about known P2P peer" },
3258         { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3259           cli_cmd_flag_none,
3260           "<field> <value> = set a P2P parameter" },
3261         { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
3262           "= flush P2P state" },
3263         { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
3264           "= cancel P2P group formation" },
3265         { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3266           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3267           "<address> = unauthorize a peer" },
3268         { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3269           cli_cmd_flag_none,
3270           "[<duration> <interval>] [<duration> <interval>] = request GO "
3271           "presence" },
3272         { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3273           cli_cmd_flag_none,
3274           "[<period> <interval>] = set extended listen timing" },
3275         { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3276           wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3277           "<address|iface=address> = remove a peer from all groups" },
3278         { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
3279           cli_cmd_flag_none,
3280           "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
3281           VENDOR_ELEM_FRAME_ID },
3282         { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
3283           cli_cmd_flag_none,
3284           "<frame id> = get vendor specific IE(s) to frame(s)\n"
3285           VENDOR_ELEM_FRAME_ID },
3286         { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
3287           cli_cmd_flag_none,
3288           "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
3289           VENDOR_ELEM_FRAME_ID },
3290 #endif /* CONFIG_P2P */
3291 #ifdef CONFIG_WIFI_DISPLAY
3292         { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3293           cli_cmd_flag_none,
3294           "<subelem> [contents] = set Wi-Fi Display subelement" },
3295         { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3296           cli_cmd_flag_none,
3297           "<subelem> = get Wi-Fi Display subelement" },
3298 #endif /* CONFIG_WIFI_DISPLAY */
3299 #ifdef CONFIG_INTERWORKING
3300         { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
3301           "= fetch ANQP information for all APs" },
3302         { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3303           cli_cmd_flag_none,
3304           "= stop fetch_anqp operation" },
3305         { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
3306           cli_cmd_flag_none,
3307           "[auto] = perform Interworking network selection" },
3308         { "interworking_connect", wpa_cli_cmd_interworking_connect,
3309           wpa_cli_complete_bss, cli_cmd_flag_none,
3310           "<BSSID> = connect using Interworking credentials" },
3311         { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3312           wpa_cli_complete_bss, cli_cmd_flag_none,
3313           "<BSSID> = connect using Interworking credentials" },
3314         { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3315           cli_cmd_flag_none,
3316           "<addr> <info id>[,<info id>]... = request ANQP information" },
3317         { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3318           cli_cmd_flag_none,
3319           "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3320         { "gas_response_get", wpa_cli_cmd_gas_response_get,
3321           wpa_cli_complete_bss, cli_cmd_flag_none,
3322           "<addr> <dialog token> [start,len] = Fetch last GAS response" },
3323 #endif /* CONFIG_INTERWORKING */
3324 #ifdef CONFIG_HS20
3325         { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3326           cli_cmd_flag_none,
3327           "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3328         },
3329         { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
3330           wpa_cli_complete_bss, cli_cmd_flag_none,
3331           "<addr> <home realm> = get HS20 nai home realm list" },
3332         { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3333           wpa_cli_complete_bss, cli_cmd_flag_none,
3334           "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
3335         { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3336           "= fetch OSU provider information from all APs" },
3337         { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3338           cli_cmd_flag_none,
3339           "= cancel fetch_osu command" },
3340 #endif /* CONFIG_HS20 */
3341         { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3342           cli_cmd_flag_none,
3343           "<0/1> = disable/enable automatic reconnection" },
3344         { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
3345           cli_cmd_flag_none,
3346           "<addr> = request TDLS discovery with <addr>" },
3347         { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
3348           cli_cmd_flag_none,
3349           "<addr> = request TDLS setup with <addr>" },
3350         { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
3351           cli_cmd_flag_none,
3352           "<addr> = tear down TDLS with <addr>" },
3353         { "tdls_link_status", wpa_cli_cmd_tdls_link_status, NULL,
3354           cli_cmd_flag_none,
3355           "<addr> = TDLS link status with <addr>" },
3356         { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3357           cli_cmd_flag_none,
3358           "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3359           "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3360           "= add WMM-AC traffic stream" },
3361         { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3362           cli_cmd_flag_none,
3363           "<tsid> = delete WMM-AC traffic stream" },
3364         { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3365           cli_cmd_flag_none,
3366           "= show status for Wireless Multi-Media Admission-Control" },
3367         { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3368           cli_cmd_flag_none,
3369           "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3370           "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3371           "with TDLS peer" },
3372         { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3373           cli_cmd_flag_none,
3374           "<addr> = disable channel switching with TDLS peer <addr>" },
3375         { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
3376           cli_cmd_flag_none,
3377           "= get signal parameters" },
3378         { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3379           cli_cmd_flag_none,
3380           "= get TX/RX packet counters" },
3381         { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3382           cli_cmd_flag_none,
3383           "= trigger IEEE 802.1X/EAPOL reauthentication" },
3384 #ifdef CONFIG_AUTOSCAN
3385         { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
3386           "[params] = Set or unset (if none) autoscan parameters" },
3387 #endif /* CONFIG_AUTOSCAN */
3388 #ifdef CONFIG_WNM
3389         { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3390           "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
3391         { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3392           "<query reason> = Send BSS Transition Management Query" },
3393 #endif /* CONFIG_WNM */
3394         { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
3395           "<params..> = Sent unprocessed command" },
3396         { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3397           "= flush wpa_supplicant state" },
3398 #ifdef ANDROID
3399         { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3400           "<command> = driver private commands" },
3401 #endif /* ANDROID */
3402         { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3403           "= radio_work <show/add/done>" },
3404         { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3405           "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3406         },
3407         { "neighbor_rep_request",
3408           wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3409           "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3410           "(with optional given SSID, default: current SSID)"
3411         },
3412         { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3413           "= flush ERP keys" },
3414         { "mac_rand_scan",
3415           wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3416           "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3417           "mask=mac-address-mask] = scan MAC randomization"
3418         },
3419         { "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
3420           cli_cmd_flag_none,
3421           "<interface type> = retrieve preferred freq list for the specified interface type" },
3422         { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
3423 };
3424
3425
3426 /*
3427  * Prints command usage, lines are padded with the specified string.
3428  */
3429 static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
3430 {
3431         char c;
3432         size_t n;
3433
3434         printf("%s%s ", pad, cmd->cmd);
3435         for (n = 0; (c = cmd->usage[n]); n++) {
3436                 printf("%c", c);
3437                 if (c == '\n')
3438                         printf("%s", pad);
3439         }
3440         printf("\n");
3441 }
3442
3443
3444 static void print_help(const char *cmd)
3445 {
3446         int n;
3447         printf("commands:\n");
3448         for (n = 0; wpa_cli_commands[n].cmd; n++) {
3449                 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3450                         print_cmd_help(&wpa_cli_commands[n], "  ");
3451         }
3452 }
3453
3454
3455 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
3456 {
3457         const char *c, *delim;
3458         int n;
3459         size_t len;
3460
3461         delim = os_strchr(cmd, ' ');
3462         if (delim)
3463                 len = delim - cmd;
3464         else
3465                 len = os_strlen(cmd);
3466
3467         for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3468                 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3469                         return (wpa_cli_commands[n].flags &
3470                                 cli_cmd_flag_sensitive);
3471         }
3472         return 0;
3473 }
3474
3475
3476 static char ** wpa_list_cmd_list(void)
3477 {
3478         char **res;
3479         int i, count;
3480         struct cli_txt_entry *e;
3481
3482         count = ARRAY_SIZE(wpa_cli_commands);
3483         count += dl_list_len(&p2p_groups);
3484         count += dl_list_len(&ifnames);
3485         res = os_calloc(count + 1, sizeof(char *));
3486         if (res == NULL)
3487                 return NULL;
3488
3489         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3490                 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3491                 if (res[i] == NULL)
3492                         break;
3493         }
3494
3495         dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3496                 size_t len = 8 + os_strlen(e->txt);
3497                 res[i] = os_malloc(len);
3498                 if (res[i] == NULL)
3499                         break;
3500                 os_snprintf(res[i], len, "ifname=%s", e->txt);
3501                 i++;
3502         }
3503
3504         dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3505                 res[i] = os_strdup(e->txt);
3506                 if (res[i] == NULL)
3507                         break;
3508                 i++;
3509         }
3510
3511         return res;
3512 }
3513
3514
3515 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3516                                       int pos)
3517 {
3518         int i;
3519
3520         for (i = 0; wpa_cli_commands[i].cmd; i++) {
3521                 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
3522                         if (wpa_cli_commands[i].completion)
3523                                 return wpa_cli_commands[i].completion(str,
3524                                                                       pos);
3525                         edit_clear_line();
3526                         printf("\r%s\n", wpa_cli_commands[i].usage);
3527                         edit_redraw();
3528                         break;
3529                 }
3530         }
3531
3532         return NULL;
3533 }
3534
3535
3536 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3537 {
3538         char **res;
3539         const char *end;
3540         char *cmd;
3541
3542         if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3543                 end = os_strchr(str, ' ');
3544                 if (end && pos > end - str) {
3545                         pos -= end - str + 1;
3546                         str = end + 1;
3547                 }
3548         }
3549
3550         end = os_strchr(str, ' ');
3551         if (end == NULL || str + pos < end)
3552                 return wpa_list_cmd_list();
3553
3554         cmd = os_malloc(pos + 1);
3555         if (cmd == NULL)
3556                 return NULL;
3557         os_memcpy(cmd, str, pos);
3558         cmd[end - str] = '\0';
3559         res = wpa_cli_cmd_completion(cmd, str, pos);
3560         os_free(cmd);
3561         return res;
3562 }
3563
3564
3565 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3566 {
3567         const struct wpa_cli_cmd *cmd, *match = NULL;
3568         int count;
3569         int ret = 0;
3570
3571         if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3572                 ifname_prefix = argv[0] + 7;
3573                 argv = &argv[1];
3574                 argc--;
3575         } else
3576                 ifname_prefix = NULL;
3577
3578         if (argc == 0)
3579                 return -1;
3580
3581         count = 0;
3582         cmd = wpa_cli_commands;
3583         while (cmd->cmd) {
3584                 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3585                 {
3586                         match = cmd;
3587                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3588                                 /* we have an exact match */
3589                                 count = 1;
3590                                 break;
3591                         }
3592                         count++;
3593                 }
3594                 cmd++;
3595         }
3596
3597         if (count > 1) {
3598                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3599                 cmd = wpa_cli_commands;
3600                 while (cmd->cmd) {
3601                         if (os_strncasecmp(cmd->cmd, argv[0],
3602                                            os_strlen(argv[0])) == 0) {
3603                                 printf(" %s", cmd->cmd);
3604                         }
3605                         cmd++;
3606                 }
3607                 printf("\n");
3608                 ret = 1;
3609         } else if (count == 0) {
3610                 printf("Unknown command '%s'\n", argv[0]);
3611                 ret = 1;
3612         } else {
3613                 ret = match->handler(ctrl, argc - 1, &argv[1]);
3614         }
3615
3616         return ret;
3617 }
3618
3619
3620 static int str_match(const char *a, const char *b)
3621 {
3622         return os_strncmp(a, b, os_strlen(b)) == 0;
3623 }
3624
3625
3626 static int wpa_cli_exec(const char *program, const char *arg1,
3627                         const char *arg2)
3628 {
3629         char *arg;
3630         size_t len;
3631         int res;
3632
3633         len = os_strlen(arg1) + os_strlen(arg2) + 2;
3634         arg = os_malloc(len);
3635         if (arg == NULL)
3636                 return -1;
3637         os_snprintf(arg, len, "%s %s", arg1, arg2);
3638         res = os_exec(program, arg, 1);
3639         os_free(arg);
3640
3641         return res;
3642 }
3643
3644
3645 static void wpa_cli_action_process(const char *msg)
3646 {
3647         const char *pos;
3648         char *copy = NULL, *id, *pos2;
3649         const char *ifname = ctrl_ifname;
3650         char ifname_buf[100];
3651
3652         if (eloop_terminated())
3653                 return;
3654
3655         pos = msg;
3656         if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3657                 const char *end;
3658                 end = os_strchr(pos + 7, ' ');
3659                 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3660                         pos += 7;
3661                         os_memcpy(ifname_buf, pos, end - pos);
3662                         ifname_buf[end - pos] = '\0';
3663                         ifname = ifname_buf;
3664                         pos = end + 1;
3665                 }
3666         }
3667         if (*pos == '<') {
3668                 const char *prev = pos;
3669                 /* skip priority */
3670                 pos = os_strchr(pos, '>');
3671                 if (pos)
3672                         pos++;
3673                 else
3674                         pos = prev;
3675         }
3676
3677         if (str_match(pos, WPA_EVENT_CONNECTED)) {
3678                 int new_id = -1;
3679                 os_unsetenv("WPA_ID");
3680                 os_unsetenv("WPA_ID_STR");
3681                 os_unsetenv("WPA_CTRL_DIR");
3682
3683                 pos = os_strstr(pos, "[id=");
3684                 if (pos)
3685                         copy = os_strdup(pos + 4);
3686
3687                 if (copy) {
3688                         pos2 = id = copy;
3689                         while (*pos2 && *pos2 != ' ')
3690                                 pos2++;
3691                         *pos2++ = '\0';
3692                         new_id = atoi(id);
3693                         os_setenv("WPA_ID", id, 1);
3694                         while (*pos2 && *pos2 != '=')
3695                                 pos2++;
3696                         if (*pos2 == '=')
3697                                 pos2++;
3698                         id = pos2;
3699                         while (*pos2 && *pos2 != ']')
3700                                 pos2++;
3701                         *pos2 = '\0';
3702                         os_setenv("WPA_ID_STR", id, 1);
3703                         os_free(copy);
3704                 }
3705
3706                 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3707
3708                 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
3709                         wpa_cli_connected = 1;
3710                         wpa_cli_last_id = new_id;
3711                         wpa_cli_exec(action_file, ifname, "CONNECTED");
3712                 }
3713         } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3714                 if (wpa_cli_connected) {
3715                         wpa_cli_connected = 0;
3716                         wpa_cli_exec(action_file, ifname, "DISCONNECTED");
3717                 }
3718         } else if (str_match(pos, MESH_GROUP_STARTED)) {
3719                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3720         } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3721                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3722         } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3723                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3724         } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3725                 wpa_cli_exec(action_file, ctrl_ifname, pos);
3726         } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3727                 wpa_cli_exec(action_file, ifname, pos);
3728         } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3729                 wpa_cli_exec(action_file, ifname, pos);
3730         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3731                 wpa_cli_exec(action_file, ifname, pos);
3732         } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3733                 wpa_cli_exec(action_file, ifname, pos);
3734         } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3735                 wpa_cli_exec(action_file, ifname, pos);
3736         } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3737                 wpa_cli_exec(action_file, ifname, pos);
3738         } else if (str_match(pos, WPS_EVENT_FAIL)) {
3739                 wpa_cli_exec(action_file, ifname, pos);
3740         } else if (str_match(pos, AP_STA_CONNECTED)) {
3741                 wpa_cli_exec(action_file, ifname, pos);
3742         } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3743                 wpa_cli_exec(action_file, ifname, pos);
3744         } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3745                 wpa_cli_exec(action_file, ifname, pos);
3746         } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
3747                 wpa_cli_exec(action_file, ifname, pos);
3748         } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
3749                 wpa_cli_exec(action_file, ifname, pos);
3750         } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3751                 printf("wpa_supplicant is terminating - stop monitoring\n");
3752                 wpa_cli_quit = 1;
3753         }
3754 }
3755
3756
3757 #ifndef CONFIG_ANSI_C_EXTRA
3758 static void wpa_cli_action_cb(char *msg, size_t len)
3759 {
3760         wpa_cli_action_process(msg);
3761 }
3762 #endif /* CONFIG_ANSI_C_EXTRA */
3763
3764
3765 static void wpa_cli_reconnect(void)
3766 {
3767         wpa_cli_close_connection();
3768         if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3769                 return;
3770
3771         if (interactive) {
3772                 edit_clear_line();
3773                 printf("\rConnection to wpa_supplicant re-established\n");
3774                 edit_redraw();
3775         }
3776 }
3777
3778
3779 static void cli_event(const char *str)
3780 {
3781         const char *start, *s;
3782
3783         start = os_strchr(str, '>');
3784         if (start == NULL)
3785                 return;
3786
3787         start++;
3788
3789         if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3790                 s = os_strchr(start, ' ');
3791                 if (s == NULL)
3792                         return;
3793                 s = os_strchr(s + 1, ' ');
3794                 if (s == NULL)
3795                         return;
3796                 cli_txt_list_add(&bsses, s + 1);
3797                 return;
3798         }
3799
3800         if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3801                 s = os_strchr(start, ' ');
3802                 if (s == NULL)
3803                         return;
3804                 s = os_strchr(s + 1, ' ');
3805                 if (s == NULL)
3806                         return;
3807                 cli_txt_list_del_addr(&bsses, s + 1);
3808                 return;
3809         }
3810
3811 #ifdef CONFIG_P2P
3812         if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3813                 s = os_strstr(start, " p2p_dev_addr=");
3814                 if (s == NULL)
3815                         return;
3816                 cli_txt_list_add_addr(&p2p_peers, s + 14);
3817                 return;
3818         }
3819
3820         if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3821                 s = os_strstr(start, " p2p_dev_addr=");
3822                 if (s == NULL)
3823                         return;
3824                 cli_txt_list_del_addr(&p2p_peers, s + 14);
3825                 return;
3826         }
3827
3828         if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3829                 s = os_strchr(start, ' ');
3830                 if (s == NULL)
3831                         return;
3832                 cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
3833                 return;
3834         }
3835
3836         if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3837                 s = os_strchr(start, ' ');
3838                 if (s == NULL)
3839                         return;
3840                 cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
3841                 return;
3842         }
3843 #endif /* CONFIG_P2P */
3844 }
3845
3846
3847 static int check_terminating(const char *msg)
3848 {
3849         const char *pos = msg;
3850
3851         if (*pos == '<') {
3852                 /* skip priority */
3853                 pos = os_strchr(pos, '>');
3854                 if (pos)
3855                         pos++;
3856                 else
3857                         pos = msg;
3858         }
3859
3860         if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3861                 edit_clear_line();
3862                 printf("\rConnection to wpa_supplicant lost - trying to "
3863                        "reconnect\n");
3864                 edit_redraw();
3865                 wpa_cli_attached = 0;
3866                 wpa_cli_close_connection();
3867                 return 1;
3868         }
3869
3870         return 0;
3871 }
3872
3873
3874 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3875 {
3876         if (ctrl_conn == NULL) {
3877                 wpa_cli_reconnect();
3878                 return;
3879         }
3880         while (wpa_ctrl_pending(ctrl) > 0) {
3881                 char buf[4096];
3882                 size_t len = sizeof(buf) - 1;
3883                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3884                         buf[len] = '\0';
3885                         if (action_monitor)
3886                                 wpa_cli_action_process(buf);
3887                         else {
3888                                 cli_event(buf);
3889                                 if (wpa_cli_show_event(buf)) {
3890                                         edit_clear_line();
3891                                         printf("\r%s\n", buf);
3892                                         edit_redraw();
3893                                 }
3894
3895                                 if (interactive && check_terminating(buf) > 0)
3896                                         return;
3897                         }
3898                 } else {
3899                         printf("Could not read pending message.\n");
3900                         break;
3901                 }
3902         }
3903
3904         if (wpa_ctrl_pending(ctrl) < 0) {
3905                 printf("Connection to wpa_supplicant lost - trying to "
3906                        "reconnect\n");
3907                 wpa_cli_reconnect();
3908         }
3909 }
3910
3911 #define max_args 10
3912
3913 static int tokenize_cmd(char *cmd, char *argv[])
3914 {
3915         char *pos;
3916         int argc = 0;
3917
3918         pos = cmd;
3919         for (;;) {
3920                 while (*pos == ' ')
3921                         pos++;
3922                 if (*pos == '\0')
3923                         break;
3924                 argv[argc] = pos;
3925                 argc++;
3926                 if (argc == max_args)
3927                         break;
3928                 if (*pos == '"') {
3929                         char *pos2 = os_strrchr(pos, '"');
3930                         if (pos2)
3931                                 pos = pos2 + 1;
3932                 }
3933                 while (*pos != '\0' && *pos != ' ')
3934                         pos++;
3935                 if (*pos == ' ')
3936                         *pos++ = '\0';
3937         }
3938
3939         return argc;
3940 }
3941
3942
3943 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3944 {
3945         if (ctrl_conn) {
3946                 int res;
3947                 char *prefix = ifname_prefix;
3948
3949                 ifname_prefix = NULL;
3950                 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3951                 ifname_prefix = prefix;
3952                 if (res) {
3953                         printf("Connection to wpa_supplicant lost - trying to "
3954                                "reconnect\n");
3955                         wpa_cli_close_connection();
3956                 }
3957         }
3958         if (!ctrl_conn)
3959                 wpa_cli_reconnect();
3960         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3961 }
3962
3963
3964 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3965 {
3966         wpa_cli_recv_pending(mon_conn, 0);
3967 }
3968
3969
3970 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3971 {
3972         char *argv[max_args];
3973         int argc;
3974         argc = tokenize_cmd(cmd, argv);
3975         if (argc)
3976                 wpa_request(ctrl_conn, argc, argv);
3977 }
3978
3979
3980 static void wpa_cli_edit_eof_cb(void *ctx)
3981 {
3982         eloop_terminate();
3983 }
3984
3985
3986 static int warning_displayed = 0;
3987 static char *hfile = NULL;
3988 static int edit_started = 0;
3989
3990 static void start_edit(void)
3991 {
3992         char *home;
3993         char *ps = NULL;
3994
3995 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3996         ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3997 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3998
3999 #ifdef CONFIG_WPA_CLI_HISTORY_DIR
4000         home = CONFIG_WPA_CLI_HISTORY_DIR;
4001 #else /* CONFIG_WPA_CLI_HISTORY_DIR */
4002         home = getenv("HOME");
4003 #endif /* CONFIG_WPA_CLI_HISTORY_DIR */
4004         if (home) {
4005                 const char *fname = ".wpa_cli_history";
4006                 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
4007                 hfile = os_malloc(hfile_len);
4008                 if (hfile)
4009                         os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
4010         }
4011
4012         if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
4013                       wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4014                 eloop_terminate();
4015                 return;
4016         }
4017
4018         edit_started = 1;
4019         eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4020 }
4021
4022
4023 static void update_bssid_list(struct wpa_ctrl *ctrl)
4024 {
4025         char buf[4096];
4026         size_t len = sizeof(buf);
4027         int ret;
4028         char *cmd = "BSS RANGE=ALL MASK=0x2";
4029         char *pos, *end;
4030
4031         if (ctrl == NULL)
4032                 return;
4033         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4034         if (ret < 0)
4035                 return;
4036         buf[len] = '\0';
4037
4038         pos = buf;
4039         while (pos) {
4040                 pos = os_strstr(pos, "bssid=");
4041                 if (pos == NULL)
4042                         break;
4043                 pos += 6;
4044                 end = os_strchr(pos, '\n');
4045                 if (end == NULL)
4046                         break;
4047                 *end = '\0';
4048                 cli_txt_list_add(&bsses, pos);
4049                 pos = end + 1;
4050         }
4051 }
4052
4053
4054 static void update_ifnames(struct wpa_ctrl *ctrl)
4055 {
4056         char buf[4096];
4057         size_t len = sizeof(buf);
4058         int ret;
4059         char *cmd = "INTERFACES";
4060         char *pos, *end;
4061         char txt[200];
4062
4063         cli_txt_list_flush(&ifnames);
4064
4065         if (ctrl == NULL)
4066                 return;
4067         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4068         if (ret < 0)
4069                 return;
4070         buf[len] = '\0';
4071
4072         pos = buf;
4073         while (pos) {
4074                 end = os_strchr(pos, '\n');
4075                 if (end == NULL)
4076                         break;
4077                 *end = '\0';
4078                 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
4079                 if (!os_snprintf_error(sizeof(txt), ret))
4080                         cli_txt_list_add(&ifnames, txt);
4081                 pos = end + 1;
4082         }
4083 }
4084
4085
4086 static void update_networks(struct wpa_ctrl *ctrl)
4087 {
4088         char buf[4096];
4089         size_t len = sizeof(buf);
4090         int ret;
4091         char *cmd = "LIST_NETWORKS";
4092         char *pos, *end;
4093         int header = 1;
4094
4095         cli_txt_list_flush(&networks);
4096
4097         if (ctrl == NULL)
4098                 return;
4099         ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4100         if (ret < 0)
4101                 return;
4102         buf[len] = '\0';
4103
4104         pos = buf;
4105         while (pos) {
4106                 end = os_strchr(pos, '\n');
4107                 if (end == NULL)
4108                         break;
4109                 *end = '\0';
4110                 if (!header)
4111                         cli_txt_list_add_word(&networks, pos, '\t');
4112                 header = 0;
4113                 pos = end + 1;
4114         }
4115 }
4116
4117
4118 static void try_connection(void *eloop_ctx, void *timeout_ctx)
4119 {
4120         if (ctrl_conn)
4121                 goto done;
4122
4123         if (ctrl_ifname == NULL)
4124                 ctrl_ifname = wpa_cli_get_default_ifname();
4125
4126         if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
4127                 if (!warning_displayed) {
4128                         printf("Could not connect to wpa_supplicant: "
4129                                "%s - re-trying\n",
4130                                ctrl_ifname ? ctrl_ifname : "(nil)");
4131                         warning_displayed = 1;
4132                 }
4133                 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4134                 return;
4135         }
4136
4137         update_bssid_list(ctrl_conn);
4138         update_networks(ctrl_conn);
4139
4140         if (warning_displayed)
4141                 printf("Connection established.\n");
4142
4143 done:
4144         start_edit();
4145 }
4146
4147
4148 static void wpa_cli_interactive(void)
4149 {
4150         printf("\nInteractive mode\n\n");
4151
4152         eloop_register_timeout(0, 0, try_connection, NULL, NULL);
4153         eloop_run();
4154         eloop_cancel_timeout(try_connection, NULL, NULL);
4155
4156         cli_txt_list_flush(&p2p_peers);
4157         cli_txt_list_flush(&p2p_groups);
4158         cli_txt_list_flush(&bsses);
4159         cli_txt_list_flush(&ifnames);
4160         cli_txt_list_flush(&networks);
4161         if (edit_started)
4162                 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
4163         os_free(hfile);
4164         eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4165         wpa_cli_close_connection();
4166 }
4167
4168
4169 static void wpa_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
4170 {
4171         struct wpa_ctrl *ctrl = eloop_ctx;
4172         char buf[256];
4173         size_t len;
4174
4175         /* verify that connection is still working */
4176         len = sizeof(buf) - 1;
4177         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4178                              wpa_cli_action_cb) < 0 ||
4179             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4180                 printf("wpa_supplicant did not reply to PING command - exiting\n");
4181                 eloop_terminate();
4182                 return;
4183         }
4184         eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4185                                ctrl, NULL);
4186 }
4187
4188
4189 static void wpa_cli_action_receive(int sock, void *eloop_ctx, void *sock_ctx)
4190 {
4191         struct wpa_ctrl *ctrl = eloop_ctx;
4192
4193         wpa_cli_recv_pending(ctrl, 1);
4194 }
4195
4196
4197 static void wpa_cli_action(struct wpa_ctrl *ctrl)
4198 {
4199 #ifdef CONFIG_ANSI_C_EXTRA
4200         /* TODO: ANSI C version(?) */
4201         printf("Action processing not supported in ANSI C build.\n");
4202 #else /* CONFIG_ANSI_C_EXTRA */
4203         int fd;
4204
4205         fd = wpa_ctrl_get_fd(ctrl);
4206         eloop_register_timeout(ping_interval, 0, wpa_cli_action_ping,
4207                                ctrl, NULL);
4208         eloop_register_read_sock(fd, wpa_cli_action_receive, ctrl, NULL);
4209         eloop_run();
4210         eloop_cancel_timeout(wpa_cli_action_ping, ctrl, NULL);
4211         eloop_unregister_read_sock(fd);
4212 #endif /* CONFIG_ANSI_C_EXTRA */
4213 }
4214
4215
4216 static void wpa_cli_cleanup(void)
4217 {
4218         wpa_cli_close_connection();
4219         if (pid_file)
4220                 os_daemonize_terminate(pid_file);
4221
4222         os_program_deinit();
4223 }
4224
4225
4226 static void wpa_cli_terminate(int sig, void *ctx)
4227 {
4228         eloop_terminate();
4229 }
4230
4231
4232 static char * wpa_cli_get_default_ifname(void)
4233 {
4234         char *ifname = NULL;
4235
4236 #ifdef ANDROID
4237         char ifprop[PROPERTY_VALUE_MAX];
4238         if (property_get("wifi.interface", ifprop, NULL) != 0) {
4239                 ifname = os_strdup(ifprop);
4240                 printf("Using interface '%s'\n", ifname ? ifname : "N/A");
4241         }
4242 #else /* ANDROID */
4243 #ifdef CONFIG_CTRL_IFACE_UNIX
4244         struct dirent *dent;
4245         DIR *dir = opendir(ctrl_iface_dir);
4246         if (!dir) {
4247                 return NULL;
4248         }
4249         while ((dent = readdir(dir))) {
4250 #ifdef _DIRENT_HAVE_D_TYPE
4251                 /*
4252                  * Skip the file if it is not a socket. Also accept
4253                  * DT_UNKNOWN (0) in case the C library or underlying
4254                  * file system does not support d_type.
4255                  */
4256                 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4257                         continue;
4258 #endif /* _DIRENT_HAVE_D_TYPE */
4259                 if (os_strcmp(dent->d_name, ".") == 0 ||
4260                     os_strcmp(dent->d_name, "..") == 0)
4261                         continue;
4262                 printf("Selected interface '%s'\n", dent->d_name);
4263                 ifname = os_strdup(dent->d_name);
4264                 break;
4265         }
4266         closedir(dir);
4267 #endif /* CONFIG_CTRL_IFACE_UNIX */
4268
4269 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4270         char buf[4096], *pos;
4271         size_t len;
4272         struct wpa_ctrl *ctrl;
4273         int ret;
4274
4275         ctrl = wpa_ctrl_open(NULL);
4276         if (ctrl == NULL)
4277                 return NULL;
4278
4279         len = sizeof(buf) - 1;
4280         ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4281         if (ret >= 0) {
4282                 buf[len] = '\0';
4283                 pos = os_strchr(buf, '\n');
4284                 if (pos)
4285                         *pos = '\0';
4286                 ifname = os_strdup(buf);
4287         }
4288         wpa_ctrl_close(ctrl);
4289 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4290 #endif /* ANDROID */
4291
4292         return ifname;
4293 }
4294
4295
4296 int main(int argc, char *argv[])
4297 {
4298         int c;
4299         int daemonize = 0;
4300         int ret = 0;
4301         const char *global = NULL;
4302
4303         if (os_program_init())
4304                 return -1;
4305
4306         for (;;) {
4307                 c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
4308                 if (c < 0)
4309                         break;
4310                 switch (c) {
4311                 case 'a':
4312                         action_file = optarg;
4313                         break;
4314                 case 'B':
4315                         daemonize = 1;
4316                         break;
4317                 case 'g':
4318                         global = optarg;
4319                         break;
4320                 case 'G':
4321                         ping_interval = atoi(optarg);
4322                         break;
4323                 case 'h':
4324                         usage();
4325                         return 0;
4326                 case 'v':
4327                         printf("%s\n", wpa_cli_version);
4328                         return 0;
4329                 case 'i':
4330                         os_free(ctrl_ifname);
4331                         ctrl_ifname = os_strdup(optarg);
4332                         break;
4333                 case 'p':
4334                         ctrl_iface_dir = optarg;
4335                         break;
4336                 case 'P':
4337                         pid_file = optarg;
4338                         break;
4339                 case 's':
4340                         client_socket_dir = optarg;
4341                         break;
4342                 default:
4343                         usage();
4344                         return -1;
4345                 }
4346         }
4347
4348         interactive = (argc == optind) && (action_file == NULL);
4349
4350         if (interactive)
4351                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4352
4353         if (eloop_init())
4354                 return -1;
4355
4356         if (global) {
4357 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4358                 ctrl_conn = wpa_ctrl_open(NULL);
4359 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4360                 ctrl_conn = wpa_ctrl_open(global);
4361 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4362                 if (ctrl_conn == NULL) {
4363                         fprintf(stderr, "Failed to connect to wpa_supplicant "
4364                                 "global interface: %s  error: %s\n",
4365                                 global, strerror(errno));
4366                         return -1;
4367                 }
4368
4369                 if (interactive) {
4370                         update_ifnames(ctrl_conn);
4371                         mon_conn = wpa_ctrl_open(global);
4372                         if (mon_conn) {
4373                                 if (wpa_ctrl_attach(mon_conn) == 0) {
4374                                         wpa_cli_attached = 1;
4375                                         eloop_register_read_sock(
4376                                                 wpa_ctrl_get_fd(mon_conn),
4377                                                 wpa_cli_mon_receive,
4378                                                 NULL, NULL);
4379                                 } else {
4380                                         printf("Failed to open monitor "
4381                                                "connection through global "
4382                                                "control interface\n");
4383                                 }
4384                         }
4385                 }
4386         }
4387
4388         eloop_register_signal_terminate(wpa_cli_terminate, NULL);
4389
4390         if (ctrl_ifname == NULL)
4391                 ctrl_ifname = wpa_cli_get_default_ifname();
4392
4393         if (interactive) {
4394                 wpa_cli_interactive();
4395         } else {
4396                 if (!global &&
4397                     wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
4398                         fprintf(stderr, "Failed to connect to non-global "
4399                                 "ctrl_ifname: %s  error: %s\n",
4400                                 ctrl_ifname ? ctrl_ifname : "(nil)",
4401                                 strerror(errno));
4402                         return -1;
4403                 }
4404
4405                 if (action_file) {
4406                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
4407                                 wpa_cli_attached = 1;
4408                         } else {
4409                                 printf("Warning: Failed to attach to "
4410                                        "wpa_supplicant.\n");
4411                                 return -1;
4412                         }
4413                 }
4414
4415                 if (daemonize && os_daemonize(pid_file))
4416                         return -1;
4417
4418                 if (action_file)
4419                         wpa_cli_action(ctrl_conn);
4420                 else
4421                         ret = wpa_request(ctrl_conn, argc - optind,
4422                                           &argv[optind]);
4423         }
4424
4425         os_free(ctrl_ifname);
4426         eloop_destroy();
4427         wpa_cli_cleanup();
4428
4429         return ret;
4430 }
4431
4432 #else /* CONFIG_CTRL_IFACE */
4433 int main(int argc, char *argv[])
4434 {
4435         printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4436         return -1;
4437 }
4438 #endif /* CONFIG_CTRL_IFACE */