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