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