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