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