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