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