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