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