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