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