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