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