]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
tests: IBSS RSN regression test for IBSS_RSN prior IBSS setup
[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
df9d340c
MB
2656static int wpa_cli_cmd_wmm_ac_addts(struct wpa_ctrl *ctrl, int argc,
2657 char *argv[])
2658{
2659 return wpa_cli_cmd(ctrl, "WMM_AC_ADDTS", 3, argc, argv);
2660}
2661
2662
2663static int wpa_cli_cmd_wmm_ac_delts(struct wpa_ctrl *ctrl, int argc,
2664 char *argv[])
2665{
2666 return wpa_cli_cmd(ctrl, "WMM_AC_DELTS", 1, argc, argv);
2667}
2668
2669
8506ea6f
MB
2670static int wpa_cli_cmd_wmm_ac_status(struct wpa_ctrl *ctrl, int argc,
2671 char *argv[])
2672{
2673 return wpa_ctrl_command(ctrl, "WMM_AC_STATUS");
2674}
2675
2676
7db53bb8
AN
2677static int wpa_cli_cmd_tdls_chan_switch(struct wpa_ctrl *ctrl, int argc,
2678 char *argv[])
2679{
2680 return wpa_cli_cmd(ctrl, "TDLS_CHAN_SWITCH", 2, argc, argv);
2681}
2682
2683
2684static int wpa_cli_cmd_tdls_cancel_chan_switch(struct wpa_ctrl *ctrl, int argc,
2685 char *argv[])
2686{
2687 return wpa_cli_cmd(ctrl, "TDLS_CANCEL_CHAN_SWITCH", 1, argc, argv);
2688}
2689
2690
60b24b0d
DS
2691static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2692 char *argv[])
2693{
2694 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2695}
2696
2697
dc7785f8
YZ
2698static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2699 char *argv[])
2700{
2701 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2702}
2703
2704
9482426e
JM
2705static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2706 char *argv[])
2707{
2708 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2709}
2710
2711
2bdd8342
TB
2712#ifdef CONFIG_AUTOSCAN
2713
2714static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2715{
2bdd8342
TB
2716 if (argc == 0)
2717 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2718
87c7ba84 2719 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2bdd8342
TB
2720}
2721
2722#endif /* CONFIG_AUTOSCAN */
2723
2724
e9199e31
JM
2725#ifdef CONFIG_WNM
2726
2727static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2728{
2729 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2730}
2731
65bcd0a9
VK
2732
2733static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2734{
2735 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2736}
2737
e9199e31
JM
2738#endif /* CONFIG_WNM */
2739
2740
27b80b5b
JM
2741static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2742{
2743 if (argc == 0)
2744 return -1;
2745 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2746}
2747
2748
5e2c3490
JM
2749#ifdef ANDROID
2750static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2751{
2752 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
2753}
2754#endif /* ANDROID */
2755
2756
adef8948
BL
2757static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2758{
2759 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2760}
2761
2762
acb54643
JM
2763static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2764{
2765 return wpa_ctrl_command(ctrl, "FLUSH");
2766}
2767
2768
1f965e62
JM
2769static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2770{
2771 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2772}
2773
2774
fad14af9
AK
2775static int wpa_cli_cmd_neighbor_rep_request(struct wpa_ctrl *ctrl, int argc,
2776 char *argv[])
2777{
2778 return wpa_cli_cmd(ctrl, "NEIGHBOR_REP_REQUEST", 0, argc, argv);
2779}
2780
2781
65d9a5e2
JM
2782static int wpa_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2783{
2784 return wpa_ctrl_command(ctrl, "ERP_FLUSH");
2785}
2786
2787
8b48e320
IP
2788static int wpa_cli_cmd_mac_rand_scan(struct wpa_ctrl *ctrl, int argc,
2789 char *argv[])
2790{
2791 return wpa_cli_cmd(ctrl, "MAC_RAND_SCAN", 1, argc, argv);
2792}
2793
2794
40fd868c
ER
2795enum wpa_cli_cmd_flags {
2796 cli_cmd_flag_none = 0x00,
2797 cli_cmd_flag_sensitive = 0x01
2798};
2799
6fc6879b
JM
2800struct wpa_cli_cmd {
2801 const char *cmd;
2802 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
b49039bd 2803 char ** (*completion)(const char *str, int pos);
40fd868c 2804 enum wpa_cli_cmd_flags flags;
dfa141b1 2805 const char *usage;
6fc6879b
JM
2806};
2807
8b423edb 2808static const struct wpa_cli_cmd wpa_cli_commands[] = {
b49039bd 2809 { "status", wpa_cli_cmd_status, NULL,
dfa141b1
ER
2810 cli_cmd_flag_none,
2811 "[verbose] = get current WPA/EAPOL/EAP status" },
b49039bd 2812 { "ifname", wpa_cli_cmd_ifname, NULL,
0eed2a8d
JD
2813 cli_cmd_flag_none,
2814 "= get current interface name" },
b49039bd 2815 { "ping", wpa_cli_cmd_ping, NULL,
dfa141b1
ER
2816 cli_cmd_flag_none,
2817 "= pings wpa_supplicant" },
b49039bd 2818 { "relog", wpa_cli_cmd_relog, NULL,
ac6912b5
BG
2819 cli_cmd_flag_none,
2820 "= re-open log-file (allow rolling logs)" },
b49039bd 2821 { "note", wpa_cli_cmd_note, NULL,
77895cd9
JM
2822 cli_cmd_flag_none,
2823 "<text> = add a note to wpa_supplicant debug log" },
b49039bd 2824 { "mib", wpa_cli_cmd_mib, NULL,
dfa141b1
ER
2825 cli_cmd_flag_none,
2826 "= get MIB variables (dot1x, dot11)" },
2af4d404 2827 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
dfa141b1 2828 cli_cmd_flag_none,
2af4d404 2829 "[command] = show usage help" },
b49039bd 2830 { "interface", wpa_cli_cmd_interface, NULL,
dfa141b1
ER
2831 cli_cmd_flag_none,
2832 "[ifname] = show interfaces/select interface" },
b49039bd 2833 { "level", wpa_cli_cmd_level, NULL,
dfa141b1
ER
2834 cli_cmd_flag_none,
2835 "<debug level> = change debug level" },
b49039bd 2836 { "license", wpa_cli_cmd_license, NULL,
dfa141b1
ER
2837 cli_cmd_flag_none,
2838 "= show full wpa_cli license" },
b49039bd 2839 { "quit", wpa_cli_cmd_quit, NULL,
dfa141b1
ER
2840 cli_cmd_flag_none,
2841 "= exit wpa_cli" },
21565872 2842 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
dfa141b1
ER
2843 cli_cmd_flag_none,
2844 "= set variables (shows list of variables when run without "
2845 "arguments)" },
10263dc2
OO
2846 { "dump", wpa_cli_cmd_dump, NULL,
2847 cli_cmd_flag_none,
2848 "= dump config variables" },
0fd9d95f 2849 { "get", wpa_cli_cmd_get, wpa_cli_complete_get,
acec8d32
JM
2850 cli_cmd_flag_none,
2851 "<name> = get information" },
b49039bd 2852 { "logon", wpa_cli_cmd_logon, NULL,
dfa141b1
ER
2853 cli_cmd_flag_none,
2854 "= IEEE 802.1X EAPOL state machine logon" },
b49039bd 2855 { "logoff", wpa_cli_cmd_logoff, NULL,
dfa141b1
ER
2856 cli_cmd_flag_none,
2857 "= IEEE 802.1X EAPOL state machine logoff" },
b49039bd 2858 { "pmksa", wpa_cli_cmd_pmksa, NULL,
dfa141b1
ER
2859 cli_cmd_flag_none,
2860 "= show PMKSA cache" },
79e2b1cc
AK
2861 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2862 cli_cmd_flag_none,
2863 "= flush PMKSA cache entries" },
b49039bd 2864 { "reassociate", wpa_cli_cmd_reassociate, NULL,
dfa141b1
ER
2865 cli_cmd_flag_none,
2866 "= force reassociation" },
0f44ec8e
PQ
2867 { "reattach", wpa_cli_cmd_reattach, NULL,
2868 cli_cmd_flag_none,
2869 "= force reassociation back to the same BSS" },
b49039bd 2870 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
dfa141b1
ER
2871 cli_cmd_flag_none,
2872 "<BSSID> = force preauthentication" },
b49039bd 2873 { "identity", wpa_cli_cmd_identity, NULL,
dfa141b1
ER
2874 cli_cmd_flag_none,
2875 "<network id> <identity> = configure identity for an SSID" },
b49039bd 2876 { "password", wpa_cli_cmd_password, NULL,
dfa141b1
ER
2877 cli_cmd_flag_sensitive,
2878 "<network id> <password> = configure password for an SSID" },
b49039bd 2879 { "new_password", wpa_cli_cmd_new_password, NULL,
dfa141b1
ER
2880 cli_cmd_flag_sensitive,
2881 "<network id> <password> = change password for an SSID" },
b49039bd 2882 { "pin", wpa_cli_cmd_pin, NULL,
dfa141b1
ER
2883 cli_cmd_flag_sensitive,
2884 "<network id> <pin> = configure pin for an SSID" },
b49039bd 2885 { "otp", wpa_cli_cmd_otp, NULL,
dfa141b1
ER
2886 cli_cmd_flag_sensitive,
2887 "<network id> <password> = configure one-time-password for an SSID"
2888 },
b49039bd 2889 { "passphrase", wpa_cli_cmd_passphrase, NULL,
dfa141b1
ER
2890 cli_cmd_flag_sensitive,
2891 "<network id> <passphrase> = configure private key passphrase\n"
2892 " for an SSID" },
a5d44ac0
JM
2893 { "sim", wpa_cli_cmd_sim, NULL,
2894 cli_cmd_flag_sensitive,
2895 "<network id> <pin> = report SIM operation result" },
b49039bd 2896 { "bssid", wpa_cli_cmd_bssid, NULL,
dfa141b1
ER
2897 cli_cmd_flag_none,
2898 "<network id> <BSSID> = set preferred BSSID for an SSID" },
b49039bd 2899 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
9aa10e2b
DS
2900 cli_cmd_flag_none,
2901 "<BSSID> = add a BSSID to the blacklist\n"
2902 "blacklist clear = clear the blacklist\n"
2903 "blacklist = display the blacklist" },
b49039bd 2904 { "log_level", wpa_cli_cmd_log_level, NULL,
0597a5b5
DS
2905 cli_cmd_flag_none,
2906 "<level> [<timestamp>] = update the log level/timestamp\n"
2907 "log_level = display the current log level and log options" },
b49039bd 2908 { "list_networks", wpa_cli_cmd_list_networks, NULL,
dfa141b1
ER
2909 cli_cmd_flag_none,
2910 "= list configured networks" },
1ca6c0f1
MK
2911 { "select_network", wpa_cli_cmd_select_network,
2912 wpa_cli_complete_network_id,
dfa141b1
ER
2913 cli_cmd_flag_none,
2914 "<network id> = select a network (disable others)" },
1ca6c0f1
MK
2915 { "enable_network", wpa_cli_cmd_enable_network,
2916 wpa_cli_complete_network_id,
dfa141b1
ER
2917 cli_cmd_flag_none,
2918 "<network id> = enable a network" },
1ca6c0f1
MK
2919 { "disable_network", wpa_cli_cmd_disable_network,
2920 wpa_cli_complete_network_id,
dfa141b1
ER
2921 cli_cmd_flag_none,
2922 "<network id> = disable a network" },
b49039bd 2923 { "add_network", wpa_cli_cmd_add_network, NULL,
dfa141b1
ER
2924 cli_cmd_flag_none,
2925 "= add a network" },
1ca6c0f1
MK
2926 { "remove_network", wpa_cli_cmd_remove_network,
2927 wpa_cli_complete_network_id,
dfa141b1
ER
2928 cli_cmd_flag_none,
2929 "<network id> = remove a network" },
7e6cc908 2930 { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
dfa141b1
ER
2931 cli_cmd_flag_sensitive,
2932 "<network id> <variable> <value> = set network variables (shows\n"
2933 " list of variables when run without arguments)" },
7e6cc908 2934 { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
dfa141b1
ER
2935 cli_cmd_flag_none,
2936 "<network id> <variable> = get network variables" },
5a997b2f 2937 { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
1c330a2f
DS
2938 cli_cmd_flag_none,
2939 "<src network id> <dst network id> <variable> = duplicate network variables"
2940 },
b49039bd 2941 { "list_creds", wpa_cli_cmd_list_creds, NULL,
d94c9ee6
JM
2942 cli_cmd_flag_none,
2943 "= list configured credentials" },
b49039bd 2944 { "add_cred", wpa_cli_cmd_add_cred, NULL,
d94c9ee6
JM
2945 cli_cmd_flag_none,
2946 "= add a credential" },
b49039bd 2947 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
d94c9ee6
JM
2948 cli_cmd_flag_none,
2949 "<cred id> = remove a credential" },
b49039bd 2950 { "set_cred", wpa_cli_cmd_set_cred, NULL,
d94c9ee6
JM
2951 cli_cmd_flag_sensitive,
2952 "<cred id> <variable> <value> = set credential variables" },
c880ab87
JM
2953 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2954 cli_cmd_flag_none,
2955 "<cred id> <variable> = get credential variables" },
b49039bd 2956 { "save_config", wpa_cli_cmd_save_config, NULL,
dfa141b1
ER
2957 cli_cmd_flag_none,
2958 "= save the current configuration" },
b49039bd 2959 { "disconnect", wpa_cli_cmd_disconnect, NULL,
dfa141b1
ER
2960 cli_cmd_flag_none,
2961 "= disconnect and wait for reassociate/reconnect command before\n"
2962 " connecting" },
b49039bd 2963 { "reconnect", wpa_cli_cmd_reconnect, NULL,
dfa141b1
ER
2964 cli_cmd_flag_none,
2965 "= like reassociate, but only takes effect if already disconnected"
2966 },
b49039bd 2967 { "scan", wpa_cli_cmd_scan, NULL,
dfa141b1
ER
2968 cli_cmd_flag_none,
2969 "= request new BSS scan" },
b49039bd 2970 { "scan_results", wpa_cli_cmd_scan_results, NULL,
dfa141b1
ER
2971 cli_cmd_flag_none,
2972 "= get latest scan results" },
b49039bd 2973 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
dfa141b1
ER
2974 cli_cmd_flag_none,
2975 "<<idx> | <bssid>> = get detailed scan result info" },
b49039bd 2976 { "get_capability", wpa_cli_cmd_get_capability, NULL,
dfa141b1 2977 cli_cmd_flag_none,
06060522 2978 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
4839f7c7 2979 "= get capabilities" },
b49039bd 2980 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
dfa141b1
ER
2981 cli_cmd_flag_none,
2982 "= force wpa_supplicant to re-read its configuration file" },
b49039bd 2983 { "terminate", wpa_cli_cmd_terminate, NULL,
dfa141b1
ER
2984 cli_cmd_flag_none,
2985 "= terminate wpa_supplicant" },
b49039bd 2986 { "interface_add", wpa_cli_cmd_interface_add, NULL,
dfa141b1
ER
2987 cli_cmd_flag_none,
2988 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2989 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2990 " are optional" },
b49039bd 2991 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
dfa141b1
ER
2992 cli_cmd_flag_none,
2993 "<ifname> = removes the interface" },
b49039bd 2994 { "interface_list", wpa_cli_cmd_interface_list, NULL,
dfa141b1
ER
2995 cli_cmd_flag_none,
2996 "= list available interfaces" },
b49039bd 2997 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
dfa141b1
ER
2998 cli_cmd_flag_none,
2999 "<value> = set ap_scan parameter" },
b49039bd 3000 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
67b9bd08
DS
3001 cli_cmd_flag_none,
3002 "<value> = set scan_interval parameter (in seconds)" },
b49039bd 3003 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
78633c37
SL
3004 cli_cmd_flag_none,
3005 "<value> = set BSS expiration age parameter" },
b49039bd 3006 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
78633c37
SL
3007 cli_cmd_flag_none,
3008 "<value> = set BSS expiration scan count parameter" },
b49039bd 3009 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
39ee845f
DS
3010 cli_cmd_flag_none,
3011 "<value> = set BSS flush age (0 by default)" },
b49039bd 3012 { "stkstart", wpa_cli_cmd_stkstart, NULL,
dfa141b1
ER
3013 cli_cmd_flag_none,
3014 "<addr> = request STK negotiation with <addr>" },
b49039bd 3015 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
dfa141b1
ER
3016 cli_cmd_flag_none,
3017 "<addr> = request over-the-DS FT with <addr>" },
b49039bd 3018 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
dfa141b1
ER
3019 cli_cmd_flag_none,
3020 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
b49039bd 3021 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
dfa141b1
ER
3022 cli_cmd_flag_sensitive,
3023 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
3024 "hardcoded)" },
b49039bd 3025 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
3981cb3c
JM
3026 cli_cmd_flag_sensitive,
3027 "<PIN> = verify PIN checksum" },
b49039bd 3028 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2f9929ff 3029 "Cancels the pending WPS operation" },
71892384 3030#ifdef CONFIG_WPS_NFC
b49039bd 3031 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
3f2c8ba6
JM
3032 cli_cmd_flag_none,
3033 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
bbf41865
JM
3034 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
3035 cli_cmd_flag_none,
3036 "<WPS|NDEF> = build configuration token" },
b49039bd 3037 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
3f2c8ba6
JM
3038 cli_cmd_flag_none,
3039 "<WPS|NDEF> = create password token" },
b49039bd 3040 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
d7645d23
JM
3041 cli_cmd_flag_sensitive,
3042 "<hexdump of payload> = report read NFC tag with WPS data" },
e65552dd
JM
3043 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
3044 cli_cmd_flag_none,
3045 "<NDEF> <WPS> = create NFC handover request" },
3046 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
3047 cli_cmd_flag_none,
3048 "<NDEF> <WPS> = create NFC handover select" },
e4758827
JM
3049 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
3050 cli_cmd_flag_none,
3051 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
3052 "NFC handover" },
71892384 3053#endif /* CONFIG_WPS_NFC */
b49039bd 3054 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
dfa141b1
ER
3055 cli_cmd_flag_sensitive,
3056 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
b49039bd 3057 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
70d84f11
JM
3058 cli_cmd_flag_sensitive,
3059 "[params..] = enable/disable AP PIN" },
b49039bd 3060 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
e9bcfebf 3061 cli_cmd_flag_none,
08486685 3062 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
b49039bd 3063 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
e9bcfebf
JM
3064 cli_cmd_flag_none,
3065 "= stop Wi-Fi Protected Setup External Registrar" },
b49039bd 3066 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
72df2f5f
JM
3067 cli_cmd_flag_sensitive,
3068 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
b49039bd 3069 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
564cd7fa
JM
3070 cli_cmd_flag_none,
3071 "<UUID> = accept an Enrollee PBC using External Registrar" },
b49039bd 3072 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
e64dcfd5
JM
3073 cli_cmd_flag_sensitive,
3074 "<UUID> <PIN> = learn AP configuration" },
b49039bd 3075 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
ef10f473
JM
3076 cli_cmd_flag_none,
3077 "<UUID> <network id> = set AP configuration for enrolling" },
b49039bd 3078 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
7d6640a6
JM
3079 cli_cmd_flag_sensitive,
3080 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
1cea09a9 3081#ifdef CONFIG_WPS_NFC
b49039bd 3082 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
1cea09a9
JM
3083 cli_cmd_flag_none,
3084 "<WPS/NDEF> <UUID> = build NFC configuration token" },
3085#endif /* CONFIG_WPS_NFC */
b49039bd 3086 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
11ef8d35
JM
3087 cli_cmd_flag_none,
3088 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622 3089#ifdef CONFIG_AP
b49039bd 3090 { "sta", wpa_cli_cmd_sta, NULL,
e653b622
JM
3091 cli_cmd_flag_none,
3092 "<addr> = get information about an associated station (AP)" },
b49039bd 3093 { "all_sta", wpa_cli_cmd_all_sta, NULL,
e653b622
JM
3094 cli_cmd_flag_none,
3095 "= get information about all associated stations (AP)" },
b49039bd 3096 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
e60b2951
JJ
3097 cli_cmd_flag_none,
3098 "<addr> = deauthenticate a station" },
b49039bd 3099 { "disassociate", wpa_cli_cmd_disassociate, NULL,
e60b2951
JJ
3100 cli_cmd_flag_none,
3101 "<addr> = disassociate a station" },
334bf36a
AO
3102 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
3103 cli_cmd_flag_none,
3104 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
3105 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
3106 " = CSA parameters" },
e653b622 3107#endif /* CONFIG_AP */
b49039bd 3108 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
207ef3fb 3109 "= notification of suspend/hibernate" },
b49039bd 3110 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
207ef3fb 3111 "= notification of resume/thaw" },
9ff4de6d 3112#ifdef CONFIG_TESTING_OPTIONS
b49039bd 3113 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
32d5295f 3114 "= drop SA without deauth/disassoc (test command)" },
9ff4de6d 3115#endif /* CONFIG_TESTING_OPTIONS */
b49039bd 3116 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
86d4f806
JM
3117 cli_cmd_flag_none,
3118 "<addr> = roam to the specified BSS" },
603a3f34 3119#ifdef CONFIG_MESH
5b78493f
MH
3120 { "mesh_interface_add", wpa_cli_cmd_mesh_interface_add, NULL,
3121 cli_cmd_flag_none,
3122 "[ifname] = Create a new mesh interface" },
603a3f34
JL
3123 { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
3124 cli_cmd_flag_none,
3125 "<network id> = join a mesh network (disable others)" },
3126 { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
3127 cli_cmd_flag_none,
3128 "<ifname> = Remove mesh group interface" },
3129#endif /* CONFIG_MESH */
57faa1ce 3130#ifdef CONFIG_P2P
01335e2c
JM
3131 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
3132 cli_cmd_flag_none,
57faa1ce 3133 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
b49039bd 3134 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
57faa1ce 3135 "= stop P2P Devices search" },
f309c18e
KV
3136 { "p2p_asp_provision", wpa_cli_cmd_p2p_asp_provision, NULL,
3137 cli_cmd_flag_none,
3138 "<addr> adv_id=<adv_id> conncap=<conncap> [info=<infodata>] = provision with a P2P ASP Device" },
3139 { "p2p_asp_provision_resp", wpa_cli_cmd_p2p_asp_provision_resp, NULL,
3140 cli_cmd_flag_none,
3141 "<addr> adv_id=<adv_id> [role<conncap>] [info=<infodata>] = provision with a P2P ASP Device" },
b49039bd
JM
3142 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
3143 cli_cmd_flag_none,
e2308e4b 3144 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
b49039bd 3145 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
57faa1ce 3146 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
b49039bd
JM
3147 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
3148 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
4d2ea6a6 3149 "<ifname> = remove P2P group interface (terminate group if GO)" },
b49039bd 3150 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
7aeac985 3151 "[ht40] = add a new P2P group (local end as GO)" },
b49039bd
JM
3152 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
3153 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
57faa1ce 3154 "<addr> <method> = request provisioning discovery" },
b49039bd 3155 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
57faa1ce
JM
3156 cli_cmd_flag_none,
3157 "= get the passphrase for a group (GO only)" },
3158 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
b49039bd 3159 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
57faa1ce
JM
3160 "<addr> <TLVs> = schedule service discovery request" },
3161 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
b49039bd 3162 NULL, cli_cmd_flag_none,
57faa1ce 3163 "<id> = cancel pending service discovery request" },
b49039bd 3164 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
57faa1ce
JM
3165 cli_cmd_flag_none,
3166 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
b49039bd 3167 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
57faa1ce
JM
3168 cli_cmd_flag_none,
3169 "= indicate change in local services" },
b49039bd 3170 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
57faa1ce
JM
3171 cli_cmd_flag_none,
3172 "<external> = set external processing of service discovery" },
b49039bd 3173 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
57faa1ce
JM
3174 cli_cmd_flag_none,
3175 "= remove all stored service entries" },
b49039bd 3176 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
57faa1ce 3177 cli_cmd_flag_none,
ae9d45f3 3178 "<bonjour|upnp|asp> <query|version> <response|service> = add a local "
57faa1ce 3179 "service" },
ae9d45f3
KV
3180 { "p2p_service_rep", wpa_cli_cmd_p2p_service_rep, NULL,
3181 cli_cmd_flag_none,
3182 "asp <auto> <adv_id> <svc_state> <svc_string> [<svc_info>] = replace "
3183 "local ASP service" },
b49039bd 3184 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
57faa1ce
JM
3185 cli_cmd_flag_none,
3186 "<bonjour|upnp> <query|version> [|service] = remove a local "
3187 "service" },
b49039bd 3188 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
57faa1ce
JM
3189 cli_cmd_flag_none,
3190 "<addr> = reject connection attempts from a specific peer" },
b49039bd 3191 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
57faa1ce
JM
3192 cli_cmd_flag_none,
3193 "<cmd> [peer=addr] = invite peer" },
b49039bd 3194 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
57faa1ce
JM
3195 "[discovered] = list known (optionally, only fully discovered) P2P "
3196 "peers" },
b49039bd
JM
3197 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
3198 cli_cmd_flag_none,
57faa1ce 3199 "<address> = show information about known P2P peer" },
698e921b
JM
3200 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
3201 cli_cmd_flag_none,
57faa1ce 3202 "<field> <value> = set a P2P parameter" },
b49039bd 3203 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
57faa1ce 3204 "= flush P2P state" },
b49039bd 3205 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
59eba7a2 3206 "= cancel P2P group formation" },
b49039bd
JM
3207 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
3208 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
9d562b79 3209 "<address> = unauthorize a peer" },
b49039bd
JM
3210 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
3211 cli_cmd_flag_none,
57faa1ce
JM
3212 "[<duration> <interval>] [<duration> <interval>] = request GO "
3213 "presence" },
b49039bd
JM
3214 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
3215 cli_cmd_flag_none,
57faa1ce 3216 "[<period> <interval>] = set extended listen timing" },
f2c56602
JM
3217 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
3218 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
3219 "<address|iface=address> = remove a peer from all groups" },
57faa1ce 3220#endif /* CONFIG_P2P */
9675ce35
JM
3221#ifdef CONFIG_WIFI_DISPLAY
3222 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
3223 cli_cmd_flag_none,
3224 "<subelem> [contents] = set Wi-Fi Display subelement" },
3225 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
3226 cli_cmd_flag_none,
3227 "<subelem> = get Wi-Fi Display subelement" },
3228#endif /* CONFIG_WIFI_DISPLAY */
afc064fe 3229#ifdef CONFIG_INTERWORKING
b49039bd 3230 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
afc064fe 3231 "= fetch ANQP information for all APs" },
b49039bd
JM
3232 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
3233 cli_cmd_flag_none,
afc064fe 3234 "= stop fetch_anqp operation" },
b49039bd 3235 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
b02fe7ff
JM
3236 cli_cmd_flag_none,
3237 "[auto] = perform Interworking network selection" },
3238 { "interworking_connect", wpa_cli_cmd_interworking_connect,
b49039bd 3239 wpa_cli_complete_bss, cli_cmd_flag_none,
b02fe7ff 3240 "<BSSID> = connect using Interworking credentials" },
f91a512f
JM
3241 { "interworking_add_network", wpa_cli_cmd_interworking_add_network,
3242 wpa_cli_complete_bss, cli_cmd_flag_none,
3243 "<BSSID> = connect using Interworking credentials" },
b49039bd
JM
3244 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
3245 cli_cmd_flag_none,
afc064fe 3246 "<addr> <info id>[,<info id>]... = request ANQP information" },
b1f12296
JM
3247 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
3248 cli_cmd_flag_none,
3249 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
3250 { "gas_response_get", wpa_cli_cmd_gas_response_get,
3251 wpa_cli_complete_bss, cli_cmd_flag_none,
3252 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
afc064fe 3253#endif /* CONFIG_INTERWORKING */
a8918e86 3254#ifdef CONFIG_HS20
b49039bd
JM
3255 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
3256 cli_cmd_flag_none,
a8918e86
JK
3257 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
3258 },
3259 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
b49039bd 3260 wpa_cli_complete_bss, cli_cmd_flag_none,
a8918e86 3261 "<addr> <home realm> = get HS20 nai home realm list" },
184e110c
JM
3262 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
3263 wpa_cli_complete_bss, cli_cmd_flag_none,
3264 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
b572df86
JM
3265 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
3266 "= fetch OSU provider information from all APs" },
3267 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
3268 cli_cmd_flag_none,
3269 "= cancel fetch_osu command" },
a8918e86 3270#endif /* CONFIG_HS20 */
b49039bd
JM
3271 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
3272 cli_cmd_flag_none,
0d0a8ca1 3273 "<0/1> = disable/enable automatic reconnection" },
b49039bd 3274 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
281ff0aa
GP
3275 cli_cmd_flag_none,
3276 "<addr> = request TDLS discovery with <addr>" },
b49039bd 3277 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
281ff0aa
GP
3278 cli_cmd_flag_none,
3279 "<addr> = request TDLS setup with <addr>" },
b49039bd 3280 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
281ff0aa
GP
3281 cli_cmd_flag_none,
3282 "<addr> = tear down TDLS with <addr>" },
df9d340c
MB
3283 { "wmm_ac_addts", wpa_cli_cmd_wmm_ac_addts, NULL,
3284 cli_cmd_flag_none,
3285 "<uplink/downlink/bidi> <tsid=0..7> <up=0..7> [nominal_msdu_size=#] "
3286 "[mean_data_rate=#] [min_phy_rate=#] [sba=#] [fixed_nominal_msdu] "
3287 "= add WMM-AC traffic stream" },
3288 { "wmm_ac_delts", wpa_cli_cmd_wmm_ac_delts, NULL,
3289 cli_cmd_flag_none,
3290 "<tsid> = delete WMM-AC traffic stream" },
8506ea6f
MB
3291 { "wmm_ac_status", wpa_cli_cmd_wmm_ac_status, NULL,
3292 cli_cmd_flag_none,
3293 "= show status for Wireless Multi-Media Admission-Control" },
7db53bb8
AN
3294 { "tdls_chan_switch", wpa_cli_cmd_tdls_chan_switch, NULL,
3295 cli_cmd_flag_none,
3296 "<addr> <oper class> <freq> [sec_channel_offset=] [center_freq1=] "
3297 "[center_freq2=] [bandwidth=] [ht|vht] = enable channel switching "
3298 "with TDLS peer" },
3299 { "tdls_cancel_chan_switch", wpa_cli_cmd_tdls_cancel_chan_switch, NULL,
3300 cli_cmd_flag_none,
3301 "<addr> = disable channel switching with TDLS peer <addr>" },
b49039bd 3302 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
60b24b0d
DS
3303 cli_cmd_flag_none,
3304 "= get signal parameters" },
dc7785f8
YZ
3305 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
3306 cli_cmd_flag_none,
3307 "= get TX/RX packet counters" },
b49039bd
JM
3308 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
3309 cli_cmd_flag_none,
9482426e 3310 "= trigger IEEE 802.1X/EAPOL reauthentication" },
2bdd8342 3311#ifdef CONFIG_AUTOSCAN
b49039bd 3312 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2bdd8342
TB
3313 "[params] = Set or unset (if none) autoscan parameters" },
3314#endif /* CONFIG_AUTOSCAN */
e9199e31
JM
3315#ifdef CONFIG_WNM
3316 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
3317 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
65bcd0a9
VK
3318 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
3319 "<query reason> = Send BSS Transition Management Query" },
e9199e31 3320#endif /* CONFIG_WNM */
b49039bd 3321 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
27b80b5b 3322 "<params..> = Sent unprocessed command" },
acb54643
JM
3323 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
3324 "= flush wpa_supplicant state" },
5e2c3490
JM
3325#ifdef ANDROID
3326 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
3327 "<command> = driver private commands" },
3328#endif /* ANDROID */
1f965e62
JM
3329 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
3330 "= radio_work <show/add/done>" },
adef8948
BL
3331 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
3332 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
3333 },
66d21434
AK
3334 { "neighbor_rep_request",
3335 wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
3336 "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
3337 "(with optional given SSID, default: current SSID)"
3338 },
65d9a5e2
JM
3339 { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
3340 "= flush ERP keys" },
8b48e320
IP
3341 { "mac_rand_scan",
3342 wpa_cli_cmd_mac_rand_scan, NULL, cli_cmd_flag_none,
3343 "<scan|sched|pno|all> enable=<0/1> [addr=mac-address "
3344 "mask=mac-address-mask] = scan MAC randomization"
3345 },
b49039bd 3346 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
3347};
3348
3349
dfa141b1
ER
3350/*
3351 * Prints command usage, lines are padded with the specified string.
3352 */
8b423edb 3353static void print_cmd_help(const struct wpa_cli_cmd *cmd, const char *pad)
dfa141b1
ER
3354{
3355 char c;
3356 size_t n;
3357
3358 printf("%s%s ", pad, cmd->cmd);
3359 for (n = 0; (c = cmd->usage[n]); n++) {
3360 printf("%c", c);
3361 if (c == '\n')
3362 printf("%s", pad);
3363 }
3364 printf("\n");
3365}
3366
3367
2af4d404 3368static void print_help(const char *cmd)
dfa141b1
ER
3369{
3370 int n;
3371 printf("commands:\n");
2af4d404
JM
3372 for (n = 0; wpa_cli_commands[n].cmd; n++) {
3373 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
3374 print_cmd_help(&wpa_cli_commands[n], " ");
3375 }
dfa141b1
ER
3376}
3377
3378
e8ecb5fb 3379static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
40fd868c
ER
3380{
3381 const char *c, *delim;
3382 int n;
3383 size_t len;
3384
3385 delim = os_strchr(cmd, ' ');
3386 if (delim)
3387 len = delim - cmd;
3388 else
3389 len = os_strlen(cmd);
3390
3391 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3392 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3393 return (wpa_cli_commands[n].flags &
3394 cli_cmd_flag_sensitive);
3395 }
3396 return 0;
3397}
e8ecb5fb
JM
3398
3399
3400static char ** wpa_list_cmd_list(void)
3401{
3402 char **res;
3403 int i, count;
37620493 3404 struct cli_txt_entry *e;
e8ecb5fb 3405
e7ecab4a 3406 count = ARRAY_SIZE(wpa_cli_commands);
37620493
JM
3407 count += dl_list_len(&p2p_groups);
3408 count += dl_list_len(&ifnames);
3409 res = os_calloc(count + 1, sizeof(char *));
e8ecb5fb
JM
3410 if (res == NULL)
3411 return NULL;
3412
3413 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3414 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3415 if (res[i] == NULL)
3416 break;
3417 }
3418
37620493
JM
3419 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3420 size_t len = 8 + os_strlen(e->txt);
3421 res[i] = os_malloc(len);
3422 if (res[i] == NULL)
3423 break;
3424 os_snprintf(res[i], len, "ifname=%s", e->txt);
3425 i++;
3426 }
3427
3428 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3429 res[i] = os_strdup(e->txt);
3430 if (res[i] == NULL)
3431 break;
3432 i++;
3433 }
3434
e8ecb5fb
JM
3435 return res;
3436}
3437
3438
3439static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3440 int pos)
3441{
3442 int i;
3443
3444 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3445 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
e4f6873c
JM
3446 if (wpa_cli_commands[i].completion)
3447 return wpa_cli_commands[i].completion(str,
3448 pos);
e8ecb5fb
JM
3449 edit_clear_line();
3450 printf("\r%s\n", wpa_cli_commands[i].usage);
3451 edit_redraw();
3452 break;
3453 }
3454 }
3455
3456 return NULL;
3457}
3458
3459
3460static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3461{
3462 char **res;
3463 const char *end;
3464 char *cmd;
3465
37620493
JM
3466 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3467 end = os_strchr(str, ' ');
3468 if (end && pos > end - str) {
3469 pos -= end - str + 1;
3470 str = end + 1;
3471 }
3472 }
3473
e8ecb5fb
JM
3474 end = os_strchr(str, ' ');
3475 if (end == NULL || str + pos < end)
3476 return wpa_list_cmd_list();
3477
3478 cmd = os_malloc(pos + 1);
3479 if (cmd == NULL)
3480 return NULL;
3481 os_memcpy(cmd, str, pos);
3482 cmd[end - str] = '\0';
3483 res = wpa_cli_cmd_completion(cmd, str, pos);
3484 os_free(cmd);
3485 return res;
3486}
40fd868c
ER
3487
3488
6fc6879b
JM
3489static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3490{
8b423edb 3491 const struct wpa_cli_cmd *cmd, *match = NULL;
6fc6879b
JM
3492 int count;
3493 int ret = 0;
3494
13b11ba7
JM
3495 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3496 ifname_prefix = argv[0] + 7;
3497 argv = &argv[1];
3498 argc--;
3499 } else
3500 ifname_prefix = NULL;
3501
3502 if (argc == 0)
3503 return -1;
3504
6fc6879b
JM
3505 count = 0;
3506 cmd = wpa_cli_commands;
3507 while (cmd->cmd) {
3508 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3509 {
3510 match = cmd;
3511 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3512 /* we have an exact match */
3513 count = 1;
3514 break;
3515 }
3516 count++;
3517 }
3518 cmd++;
3519 }
3520
3521 if (count > 1) {
3522 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3523 cmd = wpa_cli_commands;
3524 while (cmd->cmd) {
3525 if (os_strncasecmp(cmd->cmd, argv[0],
3526 os_strlen(argv[0])) == 0) {
3527 printf(" %s", cmd->cmd);
3528 }
3529 cmd++;
3530 }
3531 printf("\n");
3532 ret = 1;
3533 } else if (count == 0) {
3534 printf("Unknown command '%s'\n", argv[0]);
3535 ret = 1;
3536 } else {
3537 ret = match->handler(ctrl, argc - 1, &argv[1]);
3538 }
3539
3540 return ret;
3541}
3542
3543
3544static int str_match(const char *a, const char *b)
3545{
3546 return os_strncmp(a, b, os_strlen(b)) == 0;
3547}
3548
3549
3550static int wpa_cli_exec(const char *program, const char *arg1,
3551 const char *arg2)
3552{
c5f258de 3553 char *arg;
6fc6879b
JM
3554 size_t len;
3555 int res;
3556
c5f258de
JM
3557 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3558 arg = os_malloc(len);
3559 if (arg == NULL)
6fc6879b 3560 return -1;
c5f258de
JM
3561 os_snprintf(arg, len, "%s %s", arg1, arg2);
3562 res = os_exec(program, arg, 1);
3563 os_free(arg);
6fc6879b 3564
c5f258de 3565 return res;
6fc6879b
JM
3566}
3567
3568
3569static void wpa_cli_action_process(const char *msg)
3570{
3571 const char *pos;
3572 char *copy = NULL, *id, *pos2;
55c2bfa9
JM
3573 const char *ifname = ctrl_ifname;
3574 char ifname_buf[100];
6fc6879b
JM
3575
3576 pos = msg;
55c2bfa9
JM
3577 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3578 const char *end;
3579 end = os_strchr(pos + 7, ' ');
3580 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3581 pos += 7;
3582 os_memcpy(ifname_buf, pos, end - pos);
3583 ifname_buf[end - pos] = '\0';
3584 ifname = ifname_buf;
3585 pos = end + 1;
3586 }
3587 }
6fc6879b 3588 if (*pos == '<') {
55c2bfa9 3589 const char *prev = pos;
6fc6879b
JM
3590 /* skip priority */
3591 pos = os_strchr(pos, '>');
3592 if (pos)
3593 pos++;
3594 else
55c2bfa9 3595 pos = prev;
6fc6879b
JM
3596 }
3597
3598 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3599 int new_id = -1;
3600 os_unsetenv("WPA_ID");
3601 os_unsetenv("WPA_ID_STR");
3602 os_unsetenv("WPA_CTRL_DIR");
3603
3604 pos = os_strstr(pos, "[id=");
3605 if (pos)
3606 copy = os_strdup(pos + 4);
3607
3608 if (copy) {
3609 pos2 = id = copy;
3610 while (*pos2 && *pos2 != ' ')
3611 pos2++;
3612 *pos2++ = '\0';
3613 new_id = atoi(id);
3614 os_setenv("WPA_ID", id, 1);
3615 while (*pos2 && *pos2 != '=')
3616 pos2++;
3617 if (*pos2 == '=')
3618 pos2++;
3619 id = pos2;
3620 while (*pos2 && *pos2 != ']')
3621 pos2++;
3622 *pos2 = '\0';
3623 os_setenv("WPA_ID_STR", id, 1);
3624 os_free(copy);
3625 }
3626
3627 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3628
02a3e5c0 3629 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
6fc6879b
JM
3630 wpa_cli_connected = 1;
3631 wpa_cli_last_id = new_id;
55c2bfa9 3632 wpa_cli_exec(action_file, ifname, "CONNECTED");
6fc6879b
JM
3633 }
3634 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3635 if (wpa_cli_connected) {
3636 wpa_cli_connected = 0;
55c2bfa9 3637 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
6fc6879b 3638 }
44a1662a
MH
3639 } else if (str_match(pos, MESH_GROUP_STARTED)) {
3640 wpa_cli_exec(action_file, ctrl_ifname, pos);
3641 } else if (str_match(pos, MESH_GROUP_REMOVED)) {
3642 wpa_cli_exec(action_file, ctrl_ifname, pos);
3643 } else if (str_match(pos, MESH_PEER_CONNECTED)) {
3644 wpa_cli_exec(action_file, ctrl_ifname, pos);
3645 } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
3646 wpa_cli_exec(action_file, ctrl_ifname, pos);
42f0101b 3647 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
55c2bfa9 3648 wpa_cli_exec(action_file, ifname, pos);
42f0101b 3649 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
55c2bfa9 3650 wpa_cli_exec(action_file, ifname, pos);
72044390 3651 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
55c2bfa9 3652 wpa_cli_exec(action_file, ifname, pos);
72044390 3653 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
55c2bfa9 3654 wpa_cli_exec(action_file, ifname, pos);
e670738a 3655 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
55c2bfa9 3656 wpa_cli_exec(action_file, ifname, pos);
876103dc 3657 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
55c2bfa9 3658 wpa_cli_exec(action_file, ifname, pos);
876103dc 3659 } else if (str_match(pos, WPS_EVENT_FAIL)) {
55c2bfa9 3660 wpa_cli_exec(action_file, ifname, pos);
653c4893 3661 } else if (str_match(pos, AP_STA_CONNECTED)) {
55c2bfa9 3662 wpa_cli_exec(action_file, ifname, pos);
653c4893 3663 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
55c2bfa9 3664 wpa_cli_exec(action_file, ifname, pos);
ae8535b6 3665 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
55c2bfa9 3666 wpa_cli_exec(action_file, ifname, pos);
95a3ea94 3667 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
55c2bfa9 3668 wpa_cli_exec(action_file, ifname, pos);
7ef69479 3669 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
55c2bfa9 3670 wpa_cli_exec(action_file, ifname, pos);
6fc6879b
JM
3671 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3672 printf("wpa_supplicant is terminating - stop monitoring\n");
3673 wpa_cli_quit = 1;
3674 }
3675}
3676
3677
3678#ifndef CONFIG_ANSI_C_EXTRA
3679static void wpa_cli_action_cb(char *msg, size_t len)
3680{
3681 wpa_cli_action_process(msg);
3682}
3683#endif /* CONFIG_ANSI_C_EXTRA */
3684
3685
3686static void wpa_cli_reconnect(void)
3687{
3688 wpa_cli_close_connection();
059d3a90
JM
3689 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3690 return;
3691
3692 if (interactive) {
3693 edit_clear_line();
3694 printf("\rConnection to wpa_supplicant re-established\n");
3695 edit_redraw();
3696 }
6fc6879b
JM
3697}
3698
3699
a624f20b
JM
3700static void cli_event(const char *str)
3701{
3702 const char *start, *s;
3703
3704 start = os_strchr(str, '>');
3705 if (start == NULL)
3706 return;
3707
3708 start++;
3709
3710 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3711 s = os_strchr(start, ' ');
3712 if (s == NULL)
3713 return;
3714 s = os_strchr(s + 1, ' ');
3715 if (s == NULL)
3716 return;
3717 cli_txt_list_add(&bsses, s + 1);
3718 return;
3719 }
3720
3721 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3722 s = os_strchr(start, ' ');
3723 if (s == NULL)
3724 return;
3725 s = os_strchr(s + 1, ' ');
3726 if (s == NULL)
3727 return;
3728 cli_txt_list_del_addr(&bsses, s + 1);
3729 return;
3730 }
3731
3732#ifdef CONFIG_P2P
3733 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3734 s = os_strstr(start, " p2p_dev_addr=");
3735 if (s == NULL)
3736 return;
3737 cli_txt_list_add_addr(&p2p_peers, s + 14);
3738 return;
3739 }
3740
3741 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3742 s = os_strstr(start, " p2p_dev_addr=");
3743 if (s == NULL)
3744 return;
3745 cli_txt_list_del_addr(&p2p_peers, s + 14);
3746 return;
3747 }
76788542
JM
3748
3749 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3750 s = os_strchr(start, ' ');
3751 if (s == NULL)
3752 return;
9ccc10f5 3753 cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
76788542
JM
3754 return;
3755 }
3756
3757 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3758 s = os_strchr(start, ' ');
3759 if (s == NULL)
3760 return;
9ccc10f5 3761 cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
76788542
JM
3762 return;
3763 }
a624f20b
JM
3764#endif /* CONFIG_P2P */
3765}
3766
3767
059d3a90
JM
3768static int check_terminating(const char *msg)
3769{
3770 const char *pos = msg;
3771
3772 if (*pos == '<') {
3773 /* skip priority */
3774 pos = os_strchr(pos, '>');
3775 if (pos)
3776 pos++;
3777 else
3778 pos = msg;
3779 }
3780
3781 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3782 edit_clear_line();
3783 printf("\rConnection to wpa_supplicant lost - trying to "
3784 "reconnect\n");
3785 edit_redraw();
3786 wpa_cli_attached = 0;
3787 wpa_cli_close_connection();
3788 return 1;
3789 }
3790
3791 return 0;
3792}
3793
3794
cd101567 3795static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
6fc6879b 3796{
6fc6879b
JM
3797 if (ctrl_conn == NULL) {
3798 wpa_cli_reconnect();
3799 return;
3800 }
3801 while (wpa_ctrl_pending(ctrl) > 0) {
063f8504 3802 char buf[4096];
6fc6879b
JM
3803 size_t len = sizeof(buf) - 1;
3804 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3805 buf[len] = '\0';
3806 if (action_monitor)
3807 wpa_cli_action_process(buf);
3808 else {
a624f20b 3809 cli_event(buf);
f3f0f648 3810 if (wpa_cli_show_event(buf)) {
82a855bd 3811 edit_clear_line();
cd101567 3812 printf("\r%s\n", buf);
bdc45634 3813 edit_redraw();
f3f0f648 3814 }
059d3a90
JM
3815
3816 if (interactive && check_terminating(buf) > 0)
3817 return;
6fc6879b
JM
3818 }
3819 } else {
3820 printf("Could not read pending message.\n");
3821 break;
3822 }
3823 }
3824
3825 if (wpa_ctrl_pending(ctrl) < 0) {
3826 printf("Connection to wpa_supplicant lost - trying to "
3827 "reconnect\n");
3828 wpa_cli_reconnect();
3829 }
3830}
3831
6f1c6549
JM
3832#define max_args 10
3833
3834static int tokenize_cmd(char *cmd, char *argv[])
3835{
3836 char *pos;
3837 int argc = 0;
3838
3839 pos = cmd;
3840 for (;;) {
3841 while (*pos == ' ')
3842 pos++;
3843 if (*pos == '\0')
3844 break;
3845 argv[argc] = pos;
3846 argc++;
3847 if (argc == max_args)
3848 break;
3849 if (*pos == '"') {
3850 char *pos2 = os_strrchr(pos, '"');
3851 if (pos2)
3852 pos = pos2 + 1;
3853 }
3854 while (*pos != '\0' && *pos != ' ')
3855 pos++;
3856 if (*pos == ' ')
3857 *pos++ = '\0';
3858 }
3859
3860 return argc;
3861}
3862
3863
cd101567
JM
3864static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3865{
fa0e9176
JM
3866 if (ctrl_conn) {
3867 int res;
3868 char *prefix = ifname_prefix;
3869
3870 ifname_prefix = NULL;
3871 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3872 ifname_prefix = prefix;
3873 if (res) {
3874 printf("Connection to wpa_supplicant lost - trying to "
3875 "reconnect\n");
3876 wpa_cli_close_connection();
3877 }
cd101567
JM
3878 }
3879 if (!ctrl_conn)
3880 wpa_cli_reconnect();
3881 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3882}
3883
3884
cd101567
JM
3885static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3886{
3887 wpa_cli_recv_pending(mon_conn, 0);
3888}
3889
3890
82a855bd 3891static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
aee680e8
JM
3892{
3893 char *argv[max_args];
3894 int argc;
82a855bd 3895 argc = tokenize_cmd(cmd, argv);
aee680e8
JM
3896 if (argc)
3897 wpa_request(ctrl_conn, argc, argv);
aee680e8
JM
3898}
3899
3900
82a855bd 3901static void wpa_cli_edit_eof_cb(void *ctx)
6f1c6549 3902{
82a855bd 3903 eloop_terminate();
cd101567
JM
3904}
3905
3906
4be9f275
JM
3907static int warning_displayed = 0;
3908static char *hfile = NULL;
3909static int edit_started = 0;
aee680e8 3910
4be9f275
JM
3911static void start_edit(void)
3912{
3913 char *home;
db3a0322
JM
3914 char *ps = NULL;
3915
3916#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3917 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3918#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
cd101567 3919
ba87329d
MK
3920#ifdef CONFIG_WPA_CLI_HISTORY_DIR
3921 home = CONFIG_WPA_CLI_HISTORY_DIR;
3922#else /* CONFIG_WPA_CLI_HISTORY_DIR */
8953e968 3923 home = getenv("HOME");
ba87329d 3924#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
8953e968
JM
3925 if (home) {
3926 const char *fname = ".wpa_cli_history";
3927 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3928 hfile = os_malloc(hfile_len);
3929 if (hfile)
3930 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3931 }
3932
4be9f275 3933 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
db3a0322 3934 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
4be9f275
JM
3935 eloop_terminate();
3936 return;
3937 }
3938
3939 edit_started = 1;
cd101567 3940 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
4be9f275
JM
3941}
3942
3943
9be37143
JM
3944static void update_bssid_list(struct wpa_ctrl *ctrl)
3945{
3946 char buf[4096];
3947 size_t len = sizeof(buf);
3948 int ret;
3949 char *cmd = "BSS RANGE=ALL MASK=0x2";
3950 char *pos, *end;
3951
3952 if (ctrl == NULL)
3953 return;
3954 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3955 if (ret < 0)
3956 return;
3957 buf[len] = '\0';
3958
3959 pos = buf;
3960 while (pos) {
3961 pos = os_strstr(pos, "bssid=");
3962 if (pos == NULL)
3963 break;
3964 pos += 6;
3965 end = os_strchr(pos, '\n');
3966 if (end == NULL)
3967 break;
3968 *end = '\0';
3969 cli_txt_list_add(&bsses, pos);
3970 pos = end + 1;
3971 }
3972}
3973
3974
37620493
JM
3975static void update_ifnames(struct wpa_ctrl *ctrl)
3976{
3977 char buf[4096];
3978 size_t len = sizeof(buf);
3979 int ret;
3980 char *cmd = "INTERFACES";
3981 char *pos, *end;
3982 char txt[200];
3983
3984 cli_txt_list_flush(&ifnames);
3985
3986 if (ctrl == NULL)
3987 return;
3988 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3989 if (ret < 0)
3990 return;
3991 buf[len] = '\0';
3992
3993 pos = buf;
3994 while (pos) {
3995 end = os_strchr(pos, '\n');
3996 if (end == NULL)
3997 break;
3998 *end = '\0';
3999 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
a80ba67a 4000 if (!os_snprintf_error(sizeof(txt), ret))
37620493
JM
4001 cli_txt_list_add(&ifnames, txt);
4002 pos = end + 1;
4003 }
4004}
4005
4006
32a097fd
MK
4007static void update_networks(struct wpa_ctrl *ctrl)
4008{
4009 char buf[4096];
4010 size_t len = sizeof(buf);
4011 int ret;
4012 char *cmd = "LIST_NETWORKS";
4013 char *pos, *end;
4014 int header = 1;
4015
4016 cli_txt_list_flush(&networks);
4017
4018 if (ctrl == NULL)
4019 return;
4020 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
4021 if (ret < 0)
4022 return;
4023 buf[len] = '\0';
4024
4025 pos = buf;
4026 while (pos) {
4027 end = os_strchr(pos, '\n');
4028 if (end == NULL)
4029 break;
4030 *end = '\0';
4031 if (!header)
9ccc10f5 4032 cli_txt_list_add_word(&networks, pos, '\t');
32a097fd
MK
4033 header = 0;
4034 pos = end + 1;
4035 }
4036}
4037
4038
4be9f275
JM
4039static void try_connection(void *eloop_ctx, void *timeout_ctx)
4040{
6fd5ceaf
JM
4041 if (ctrl_conn)
4042 goto done;
4043
8e897ae3
JM
4044 if (ctrl_ifname == NULL)
4045 ctrl_ifname = wpa_cli_get_default_ifname();
4046
4be9f275
JM
4047 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
4048 if (!warning_displayed) {
4049 printf("Could not connect to wpa_supplicant: "
30f459c0
EL
4050 "%s - re-trying\n",
4051 ctrl_ifname ? ctrl_ifname : "(nil)");
4be9f275
JM
4052 warning_displayed = 1;
4053 }
4054 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
4055 return;
4056 }
4057
9be37143 4058 update_bssid_list(ctrl_conn);
32a097fd 4059 update_networks(ctrl_conn);
9be37143 4060
4be9f275
JM
4061 if (warning_displayed)
4062 printf("Connection established.\n");
4063
6fd5ceaf 4064done:
4be9f275
JM
4065 start_edit();
4066}
4067
cd101567 4068
4be9f275
JM
4069static void wpa_cli_interactive(void)
4070{
4071 printf("\nInteractive mode\n\n");
4072
4073 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
cd101567 4074 eloop_run();
4be9f275 4075 eloop_cancel_timeout(try_connection, NULL, NULL);
cd101567 4076
a624f20b 4077 cli_txt_list_flush(&p2p_peers);
76788542 4078 cli_txt_list_flush(&p2p_groups);
a624f20b 4079 cli_txt_list_flush(&bsses);
37620493 4080 cli_txt_list_flush(&ifnames);
32a097fd 4081 cli_txt_list_flush(&networks);
4be9f275
JM
4082 if (edit_started)
4083 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
8953e968 4084 os_free(hfile);
cd101567
JM
4085 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
4086 wpa_cli_close_connection();
6f1c6549
JM
4087}
4088
6fc6879b
JM
4089
4090static void wpa_cli_action(struct wpa_ctrl *ctrl)
4091{
4092#ifdef CONFIG_ANSI_C_EXTRA
4093 /* TODO: ANSI C version(?) */
4094 printf("Action processing not supported in ANSI C build.\n");
4095#else /* CONFIG_ANSI_C_EXTRA */
4096 fd_set rfds;
4097 int fd, res;
4098 struct timeval tv;
4099 char buf[256]; /* note: large enough to fit in unsolicited messages */
4100 size_t len;
4101
4102 fd = wpa_ctrl_get_fd(ctrl);
4103
4104 while (!wpa_cli_quit) {
4105 FD_ZERO(&rfds);
4106 FD_SET(fd, &rfds);
1cc84c1c 4107 tv.tv_sec = ping_interval;
6fc6879b
JM
4108 tv.tv_usec = 0;
4109 res = select(fd + 1, &rfds, NULL, NULL, &tv);
4110 if (res < 0 && errno != EINTR) {
4111 perror("select");
4112 break;
4113 }
4114
4115 if (FD_ISSET(fd, &rfds))
cd101567 4116 wpa_cli_recv_pending(ctrl, 1);
6fc6879b
JM
4117 else {
4118 /* verify that connection is still working */
4119 len = sizeof(buf) - 1;
4120 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
4121 wpa_cli_action_cb) < 0 ||
4122 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
4123 printf("wpa_supplicant did not reply to PING "
4124 "command - exiting\n");
4125 break;
4126 }
4127 }
4128 }
4129#endif /* CONFIG_ANSI_C_EXTRA */
4130}
4131
4132
4133static void wpa_cli_cleanup(void)
4134{
4135 wpa_cli_close_connection();
4136 if (pid_file)
4137 os_daemonize_terminate(pid_file);
4138
4139 os_program_deinit();
4140}
4141
4be9f275
JM
4142
4143static void wpa_cli_terminate(int sig, void *ctx)
6fc6879b 4144{
4be9f275 4145 eloop_terminate();
6fc6879b
JM
4146}
4147
4148
6fc6879b
JM
4149static char * wpa_cli_get_default_ifname(void)
4150{
4151 char *ifname = NULL;
4152
4153#ifdef CONFIG_CTRL_IFACE_UNIX
4154 struct dirent *dent;
4155 DIR *dir = opendir(ctrl_iface_dir);
b1001e4c
DS
4156 if (!dir) {
4157#ifdef ANDROID
4158 char ifprop[PROPERTY_VALUE_MAX];
4159 if (property_get("wifi.interface", ifprop, NULL) != 0) {
4160 ifname = os_strdup(ifprop);
4161 printf("Using interface '%s'\n", ifname);
4162 return ifname;
4163 }
4164#endif /* ANDROID */
6fc6879b 4165 return NULL;
b1001e4c 4166 }
6fc6879b
JM
4167 while ((dent = readdir(dir))) {
4168#ifdef _DIRENT_HAVE_D_TYPE
4169 /*
4170 * Skip the file if it is not a socket. Also accept
4171 * DT_UNKNOWN (0) in case the C library or underlying
4172 * file system does not support d_type.
4173 */
4174 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
4175 continue;
4176#endif /* _DIRENT_HAVE_D_TYPE */
4177 if (os_strcmp(dent->d_name, ".") == 0 ||
4178 os_strcmp(dent->d_name, "..") == 0)
4179 continue;
4180 printf("Selected interface '%s'\n", dent->d_name);
4181 ifname = os_strdup(dent->d_name);
4182 break;
4183 }
4184 closedir(dir);
4185#endif /* CONFIG_CTRL_IFACE_UNIX */
4186
4187#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
89c7ac57 4188 char buf[4096], *pos;
6fc6879b
JM
4189 size_t len;
4190 struct wpa_ctrl *ctrl;
4191 int ret;
4192
4193 ctrl = wpa_ctrl_open(NULL);
4194 if (ctrl == NULL)
4195 return NULL;
4196
4197 len = sizeof(buf) - 1;
4198 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
4199 if (ret >= 0) {
4200 buf[len] = '\0';
4201 pos = os_strchr(buf, '\n');
4202 if (pos)
4203 *pos = '\0';
4204 ifname = os_strdup(buf);
4205 }
4206 wpa_ctrl_close(ctrl);
4207#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4208
4209 return ifname;
4210}
4211
4212
4213int main(int argc, char *argv[])
4214{
6fc6879b
JM
4215 int c;
4216 int daemonize = 0;
4217 int ret = 0;
4218 const char *global = NULL;
4219
4220 if (os_program_init())
4221 return -1;
4222
4223 for (;;) {
1cc84c1c 4224 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
4225 if (c < 0)
4226 break;
4227 switch (c) {
4228 case 'a':
4229 action_file = optarg;
4230 break;
4231 case 'B':
4232 daemonize = 1;
4233 break;
4234 case 'g':
4235 global = optarg;
4236 break;
1cc84c1c
JM
4237 case 'G':
4238 ping_interval = atoi(optarg);
4239 break;
6fc6879b
JM
4240 case 'h':
4241 usage();
4242 return 0;
4243 case 'v':
4244 printf("%s\n", wpa_cli_version);
4245 return 0;
4246 case 'i':
4247 os_free(ctrl_ifname);
4248 ctrl_ifname = os_strdup(optarg);
4249 break;
4250 case 'p':
4251 ctrl_iface_dir = optarg;
4252 break;
4253 case 'P':
4254 pid_file = optarg;
4255 break;
4256 default:
4257 usage();
4258 return -1;
4259 }
4260 }
4261
4262 interactive = (argc == optind) && (action_file == NULL);
4263
4264 if (interactive)
4265 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
4266
cd101567
JM
4267 if (eloop_init())
4268 return -1;
4269
6fc6879b
JM
4270 if (global) {
4271#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
4272 ctrl_conn = wpa_ctrl_open(NULL);
4273#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4274 ctrl_conn = wpa_ctrl_open(global);
4275#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
4276 if (ctrl_conn == NULL) {
5a49459e
BG
4277 fprintf(stderr, "Failed to connect to wpa_supplicant "
4278 "global interface: %s error: %s\n",
4279 global, strerror(errno));
6fc6879b
JM
4280 return -1;
4281 }
214e428b
JM
4282
4283 if (interactive) {
37620493 4284 update_ifnames(ctrl_conn);
214e428b
JM
4285 mon_conn = wpa_ctrl_open(global);
4286 if (mon_conn) {
4287 if (wpa_ctrl_attach(mon_conn) == 0) {
4288 wpa_cli_attached = 1;
4289 eloop_register_read_sock(
4290 wpa_ctrl_get_fd(mon_conn),
4291 wpa_cli_mon_receive,
4292 NULL, NULL);
4293 } else {
4294 printf("Failed to open monitor "
4295 "connection through global "
4296 "control interface\n");
4297 }
4298 }
4299 }
6fc6879b
JM
4300 }
4301
4be9f275 4302 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
6fc6879b 4303
4a3ade4e
JM
4304 if (ctrl_ifname == NULL)
4305 ctrl_ifname = wpa_cli_get_default_ifname();
4306
4307 if (interactive) {
4be9f275 4308 wpa_cli_interactive();
4a3ade4e
JM
4309 } else {
4310 if (!global &&
4311 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
5a49459e
BG
4312 fprintf(stderr, "Failed to connect to non-global "
4313 "ctrl_ifname: %s error: %s\n",
30f459c0
EL
4314 ctrl_ifname ? ctrl_ifname : "(nil)",
4315 strerror(errno));
4a3ade4e
JM
4316 return -1;
4317 }
4318
4319 if (action_file) {
4320 if (wpa_ctrl_attach(ctrl_conn) == 0) {
4321 wpa_cli_attached = 1;
4322 } else {
4323 printf("Warning: Failed to attach to "
4324 "wpa_supplicant.\n");
6fc6879b 4325 return -1;
4a3ade4e 4326 }
6fc6879b 4327 }
6fc6879b 4328
4be9f275
JM
4329 if (daemonize && os_daemonize(pid_file))
4330 return -1;
6fc6879b 4331
4be9f275
JM
4332 if (action_file)
4333 wpa_cli_action(ctrl_conn);
4334 else
4335 ret = wpa_request(ctrl_conn, argc - optind,
4336 &argv[optind]);
4337 }
6fc6879b
JM
4338
4339 os_free(ctrl_ifname);
cd101567 4340 eloop_destroy();
6fc6879b
JM
4341 wpa_cli_cleanup();
4342
4343 return ret;
4344}
4345
4346#else /* CONFIG_CTRL_IFACE */
4347int main(int argc, char *argv[])
4348{
4349 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
4350 return -1;
4351}
4352#endif /* CONFIG_CTRL_IFACE */