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