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