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