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