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