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