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