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