1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2010, 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 #ifdef CONFIG_READLINE
23 #include <readline/readline.h>
24 #include <readline/history.h>
25 #endif /* CONFIG_READLINE */
26 #ifdef CONFIG_WPA_CLI_FORK
27 #include <sys/wait.h>
28 #endif /* CONFIG_WPA_CLI_FORK */
29 
30 #include "common/wpa_ctrl.h"
31 #include "common.h"
32 #include "common/version.h"
33 
34 
35 static const char *wpa_cli_version =
36 "wpa_cli v" VERSION_STR "\n"
37 "Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
38 
39 
40 static const char *wpa_cli_license =
41 "This program is free software. You can distribute it and/or modify it\n"
42 "under the terms of the GNU General Public License version 2.\n"
43 "\n"
44 "Alternatively, this software may be distributed under the terms of the\n"
45 "BSD license. See README and COPYING for more details.\n";
46 
47 static const char *wpa_cli_full_license =
48 "This program is free software; you can redistribute it and/or modify\n"
49 "it under the terms of the GNU General Public License version 2 as\n"
50 "published by the Free Software Foundation.\n"
51 "\n"
52 "This program is distributed in the hope that it will be useful,\n"
53 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
54 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
55 "GNU General Public License for more details.\n"
56 "\n"
57 "You should have received a copy of the GNU General Public License\n"
58 "along with this program; if not, write to the Free Software\n"
59 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
60 "\n"
61 "Alternatively, this software may be distributed under the terms of the\n"
62 "BSD license.\n"
63 "\n"
64 "Redistribution and use in source and binary forms, with or without\n"
65 "modification, are permitted provided that the following conditions are\n"
66 "met:\n"
67 "\n"
68 "1. Redistributions of source code must retain the above copyright\n"
69 "   notice, this list of conditions and the following disclaimer.\n"
70 "\n"
71 "2. Redistributions in binary form must reproduce the above copyright\n"
72 "   notice, this list of conditions and the following disclaimer in the\n"
73 "   documentation and/or other materials provided with the distribution.\n"
74 "\n"
75 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
76 "   names of its contributors may be used to endorse or promote products\n"
77 "   derived from this software without specific prior written permission.\n"
78 "\n"
79 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
80 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
81 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
82 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
83 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
84 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
85 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
86 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
87 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
88 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
89 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
90 "\n";
91 
92 static struct wpa_ctrl *ctrl_conn;
93 static struct wpa_ctrl *mon_conn;
94 #ifdef CONFIG_WPA_CLI_FORK
95 static pid_t mon_pid = 0;
96 #endif /* CONFIG_WPA_CLI_FORK */
97 static int wpa_cli_quit = 0;
98 static int wpa_cli_attached = 0;
99 static int wpa_cli_connected = 0;
100 static int wpa_cli_last_id = 0;
101 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
102 static char *ctrl_ifname = NULL;
103 static const char *pid_file = NULL;
104 static const char *action_file = NULL;
105 static int ping_interval = 5;
106 static int interactive = 0;
107 
108 
109 static void print_help();
110 
111 
112 static void usage(void)
113 {
114 	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
115 	       "[-a<action file>] \\\n"
116 	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
117 	       "[command..]\n"
118 	       "  -h = help (show this usage text)\n"
119 	       "  -v = shown version information\n"
120 	       "  -a = run in daemon mode executing the action file based on "
121 	       "events from\n"
122 	       "       wpa_supplicant\n"
123 	       "  -B = run a daemon in the background\n"
124 	       "  default path: /var/run/wpa_supplicant\n"
125 	       "  default interface: first interface found in socket path\n");
126 	print_help();
127 }
128 
129 
130 #ifdef CONFIG_WPA_CLI_FORK
131 static int in_query = 0;
132 
133 static void wpa_cli_monitor_sig(int sig)
134 {
135 	if (sig == SIGUSR1)
136 		in_query = 1;
137 	else if (sig == SIGUSR2)
138 		in_query = 0;
139 }
140 
141 static void wpa_cli_monitor(void)
142 {
143 	char buf[256];
144 	size_t len = sizeof(buf) - 1;
145 	struct timeval tv;
146 	fd_set rfds;
147 
148 	signal(SIGUSR1, wpa_cli_monitor_sig);
149 	signal(SIGUSR2, wpa_cli_monitor_sig);
150 
151 	while (mon_conn) {
152 		int s = wpa_ctrl_get_fd(mon_conn);
153 		tv.tv_sec = 5;
154 		tv.tv_usec = 0;
155 		FD_ZERO(&rfds);
156 		FD_SET(s, &rfds);
157 		if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
158 			if (errno == EINTR)
159 				continue;
160 			perror("select");
161 			break;
162 		}
163 		if (mon_conn == NULL)
164 			break;
165 		if (FD_ISSET(s, &rfds)) {
166 			len = sizeof(buf) - 1;
167 			int res = wpa_ctrl_recv(mon_conn, buf, &len);
168 			if (res < 0) {
169 				perror("wpa_ctrl_recv");
170 				break;
171 			}
172 			buf[len] = '\0';
173 			if (in_query)
174 				printf("\r");
175 			printf("%s\n", buf);
176 			kill(getppid(), SIGUSR1);
177 		}
178 	}
179 }
180 #endif /* CONFIG_WPA_CLI_FORK */
181 
182 
183 static int wpa_cli_open_connection(const char *ifname, int attach)
184 {
185 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
186 	ctrl_conn = wpa_ctrl_open(ifname);
187 	if (ctrl_conn == NULL)
188 		return -1;
189 
190 	if (attach && interactive)
191 		mon_conn = wpa_ctrl_open(ifname);
192 	else
193 		mon_conn = NULL;
194 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
195 	char *cfile;
196 	int flen, res;
197 
198 	if (ifname == NULL)
199 		return -1;
200 
201 	flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
202 	cfile = os_malloc(flen);
203 	if (cfile == NULL)
204 		return -1L;
205 	res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
206 	if (res < 0 || res >= flen) {
207 		os_free(cfile);
208 		return -1;
209 	}
210 
211 	ctrl_conn = wpa_ctrl_open(cfile);
212 	if (ctrl_conn == NULL) {
213 		os_free(cfile);
214 		return -1;
215 	}
216 
217 	if (attach && interactive)
218 		mon_conn = wpa_ctrl_open(cfile);
219 	else
220 		mon_conn = NULL;
221 	os_free(cfile);
222 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
223 
224 	if (mon_conn) {
225 		if (wpa_ctrl_attach(mon_conn) == 0) {
226 			wpa_cli_attached = 1;
227 		} else {
228 			printf("Warning: Failed to attach to "
229 			       "wpa_supplicant.\n");
230 			return -1;
231 		}
232 
233 #ifdef CONFIG_WPA_CLI_FORK
234 		{
235 			pid_t p = fork();
236 			if (p < 0) {
237 				perror("fork");
238 				return -1;
239 			}
240 			if (p == 0) {
241 				wpa_cli_monitor();
242 				exit(0);
243 			} else
244 				mon_pid = p;
245 		}
246 #endif /* CONFIG_WPA_CLI_FORK */
247 	}
248 
249 	return 0;
250 }
251 
252 
253 static void wpa_cli_close_connection(void)
254 {
255 	if (ctrl_conn == NULL)
256 		return;
257 
258 #ifdef CONFIG_WPA_CLI_FORK
259 	if (mon_pid) {
260 		int status;
261 		kill(mon_pid, SIGPIPE);
262 		wait(&status);
263 		mon_pid = 0;
264 	}
265 #endif /* CONFIG_WPA_CLI_FORK */
266 
267 	if (wpa_cli_attached) {
268 		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
269 		wpa_cli_attached = 0;
270 	}
271 	wpa_ctrl_close(ctrl_conn);
272 	ctrl_conn = NULL;
273 	if (mon_conn) {
274 		wpa_ctrl_close(mon_conn);
275 		mon_conn = NULL;
276 	}
277 }
278 
279 static const char *skip_priority(const char *msg)
280 {
281 	const char *pos = msg;
282 
283 	if (*msg != '<')
284 		return msg;
285 
286 	for (pos = msg + 1; isdigit((unsigned char)*pos); pos++)
287 		continue;
288 
289 	if (*pos != '>')
290 		return msg;
291 
292 	return ++pos;
293 }
294 
295 static const char *fmttime(char *buf, size_t buflen)
296 {
297 	struct timeval tv;
298 	struct tm tm;
299 	time_t t;
300 
301 	if (buflen <= 8)
302 		return NULL;
303 
304 	(void)gettimeofday(&tv, NULL);
305 	t = (time_t)tv.tv_sec;
306 	(void)localtime_r(&t, &tm);
307 	(void)strftime(buf, buflen, "%H:%M:%S", &tm);
308 	(void)snprintf(buf + 8, buflen - 8, ".%.3d", (int)(tv.tv_usec / 1000));
309 	return buf;
310 }
311 
312 static void wpa_cli_msg_cb(char *msg, size_t len)
313 {
314 	char tbuf[32];
315 	printf("%s: %s\n", fmttime(tbuf, sizeof(tbuf)), skip_priority(msg));
316 }
317 
318 
319 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
320 {
321 	char buf[2048];
322 	size_t len;
323 	int ret;
324 
325 	if (ctrl_conn == NULL) {
326 		printf("Not connected to wpa_supplicant - command dropped.\n");
327 		return -1;
328 	}
329 	len = sizeof(buf) - 1;
330 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
331 			       wpa_cli_msg_cb);
332 	if (ret == -2) {
333 		printf("'%s' command timed out.\n", cmd);
334 		return -2;
335 	} else if (ret < 0) {
336 		printf("'%s' command failed.\n", cmd);
337 		return -1;
338 	}
339 	if (print) {
340 		buf[len] = '\0';
341 		wpa_cli_msg_cb(buf, 0);
342 	}
343 	return 0;
344 }
345 
346 
347 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
348 {
349 	return _wpa_ctrl_command(ctrl, cmd, 1);
350 }
351 
352 
353 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
354 {
355 	int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
356 	return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
357 }
358 
359 
360 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
361 {
362 	return wpa_ctrl_command(ctrl, "PING");
363 }
364 
365 
366 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
367 {
368 	return wpa_ctrl_command(ctrl, "MIB");
369 }
370 
371 
372 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
373 {
374 	return wpa_ctrl_command(ctrl, "PMKSA");
375 }
376 
377 
378 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
379 {
380 	print_help();
381 	return 0;
382 }
383 
384 
385 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
386 {
387 	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
388 	return 0;
389 }
390 
391 
392 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
393 {
394 	wpa_cli_quit = 1;
395 	return 0;
396 }
397 
398 
399 static void wpa_cli_show_variables(void)
400 {
401 	printf("set variables:\n"
402 	       "  EAPOL::heldPeriod (EAPOL state machine held period, "
403 	       "in seconds)\n"
404 	       "  EAPOL::authPeriod (EAPOL state machine authentication "
405 	       "period, in seconds)\n"
406 	       "  EAPOL::startPeriod (EAPOL state machine start period, in "
407 	       "seconds)\n"
408 	       "  EAPOL::maxStart (EAPOL state machine maximum start "
409 	       "attempts)\n");
410 	printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
411 	       "seconds)\n"
412 	       "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
413 	       " threshold\n\tpercentage)\n"
414 	       "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
415 	       "security\n\tassociation in seconds)\n");
416 }
417 
418 
419 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
420 {
421 	char cmd[256];
422 	int res;
423 
424 	if (argc == 0) {
425 		wpa_cli_show_variables();
426 		return 0;
427 	}
428 
429 	if (argc != 2) {
430 		printf("Invalid SET command: needs two arguments (variable "
431 		       "name and value)\n");
432 		return -1;
433 	}
434 
435 	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
436 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
437 		printf("Too long SET command.\n");
438 		return -1;
439 	}
440 	return wpa_ctrl_command(ctrl, cmd);
441 }
442 
443 
444 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
445 {
446 	return wpa_ctrl_command(ctrl, "LOGOFF");
447 }
448 
449 
450 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
451 {
452 	return wpa_ctrl_command(ctrl, "LOGON");
453 }
454 
455 
456 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
457 				   char *argv[])
458 {
459 	return wpa_ctrl_command(ctrl, "REASSOCIATE");
460 }
461 
462 
463 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
464 				       char *argv[])
465 {
466 	char cmd[256];
467 	int res;
468 
469 	if (argc != 1) {
470 		printf("Invalid PREAUTH command: needs one argument "
471 		       "(BSSID)\n");
472 		return -1;
473 	}
474 
475 	res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
476 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
477 		printf("Too long PREAUTH command.\n");
478 		return -1;
479 	}
480 	return wpa_ctrl_command(ctrl, cmd);
481 }
482 
483 
484 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
485 {
486 	char cmd[256];
487 	int res;
488 
489 	if (argc != 1) {
490 		printf("Invalid AP_SCAN command: needs one argument (ap_scan "
491 		       "value)\n");
492 		return -1;
493 	}
494 	res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
495 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
496 		printf("Too long AP_SCAN command.\n");
497 		return -1;
498 	}
499 	return wpa_ctrl_command(ctrl, cmd);
500 }
501 
502 
503 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
504 				char *argv[])
505 {
506 	char cmd[256];
507 	int res;
508 
509 	if (argc != 1) {
510 		printf("Invalid STKSTART command: needs one argument "
511 		       "(Peer STA MAC address)\n");
512 		return -1;
513 	}
514 
515 	res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
516 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
517 		printf("Too long STKSTART command.\n");
518 		return -1;
519 	}
520 	return wpa_ctrl_command(ctrl, cmd);
521 }
522 
523 
524 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
525 {
526 	char cmd[256];
527 	int res;
528 
529 	if (argc != 1) {
530 		printf("Invalid FT_DS command: needs one argument "
531 		       "(Target AP MAC address)\n");
532 		return -1;
533 	}
534 
535 	res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
536 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
537 		printf("Too long FT_DS command.\n");
538 		return -1;
539 	}
540 	return wpa_ctrl_command(ctrl, cmd);
541 }
542 
543 
544 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
545 {
546 	char cmd[256];
547 	int res;
548 
549 	if (argc == 0) {
550 		/* Any BSSID */
551 		return wpa_ctrl_command(ctrl, "WPS_PBC");
552 	}
553 
554 	/* Specific BSSID */
555 	res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
556 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
557 		printf("Too long WPS_PBC command.\n");
558 		return -1;
559 	}
560 	return wpa_ctrl_command(ctrl, cmd);
561 }
562 
563 
564 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
565 {
566 	char cmd[256];
567 	int res;
568 
569 	if (argc == 0) {
570 		printf("Invalid WPS_PIN command: need one or two arguments:\n"
571 		       "- BSSID: use 'any' to select any\n"
572 		       "- PIN: optional, used only with devices that have no "
573 		       "display\n");
574 		return -1;
575 	}
576 
577 	if (argc == 1) {
578 		/* Use dynamically generated PIN (returned as reply) */
579 		res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
580 		if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 			printf("Too long WPS_PIN command.\n");
582 			return -1;
583 		}
584 		return wpa_ctrl_command(ctrl, cmd);
585 	}
586 
587 	/* Use hardcoded PIN from a label */
588 	res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
589 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
590 		printf("Too long WPS_PIN command.\n");
591 		return -1;
592 	}
593 	return wpa_ctrl_command(ctrl, cmd);
594 }
595 
596 
597 #ifdef CONFIG_WPS_OOB
598 static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
599 {
600 	char cmd[256];
601 	int res;
602 
603 	if (argc != 3 && argc != 4) {
604 		printf("Invalid WPS_OOB command: need three or four "
605 		       "arguments:\n"
606 		       "- DEV_TYPE: use 'ufd' or 'nfc'\n"
607 		       "- PATH: path of OOB device like '/mnt'\n"
608 		       "- METHOD: OOB method 'pin-e' or 'pin-r', "
609 		       "'cred'\n"
610 		       "- DEV_NAME: (only for NFC) device name like "
611 		       "'pn531'\n");
612 		return -1;
613 	}
614 
615 	if (argc == 3)
616 		res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
617 				  argv[0], argv[1], argv[2]);
618 	else
619 		res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
620 				  argv[0], argv[1], argv[2], argv[3]);
621 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
622 		printf("Too long WPS_OOB command.\n");
623 		return -1;
624 	}
625 	return wpa_ctrl_command(ctrl, cmd);
626 }
627 #endif /* CONFIG_WPS_OOB */
628 
629 
630 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
631 {
632 	char cmd[256];
633 	int res;
634 
635 	if (argc == 2)
636 		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
637 				  argv[0], argv[1]);
638 	else if (argc == 6) {
639 		char ssid_hex[2 * 32 + 1];
640 		char key_hex[2 * 64 + 1];
641 		int i;
642 
643 		ssid_hex[0] = '\0';
644 		for (i = 0; i < 32; i++) {
645 			if (argv[2][i] == '\0')
646 				break;
647 			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
648 		}
649 
650 		key_hex[0] = '\0';
651 		for (i = 0; i < 64; i++) {
652 			if (argv[5][i] == '\0')
653 				break;
654 			os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
655 		}
656 
657 		res = os_snprintf(cmd, sizeof(cmd),
658 				  "WPS_REG %s %s %s %s %s %s",
659 				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
660 				  key_hex);
661 	} else {
662 		printf("Invalid WPS_REG command: need two arguments:\n"
663 		       "- BSSID: use 'any' to select any\n"
664 		       "- AP PIN\n");
665 		printf("Alternatively, six arguments can be used to "
666 		       "reconfigure the AP:\n"
667 		       "- BSSID: use 'any' to select any\n"
668 		       "- AP PIN\n"
669 		       "- new SSID\n"
670 		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
671 		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
672 		       "- new key\n");
673 		return -1;
674 	}
675 
676 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
677 		printf("Too long WPS_REG command.\n");
678 		return -1;
679 	}
680 	return wpa_ctrl_command(ctrl, cmd);
681 }
682 
683 
684 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
685 				    char *argv[])
686 {
687 	return wpa_ctrl_command(ctrl, "WPS_ER_START");
688 
689 }
690 
691 
692 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
693 				   char *argv[])
694 {
695 	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
696 
697 }
698 
699 
700 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
701 				  char *argv[])
702 {
703 	char cmd[256];
704 	int res;
705 
706 	if (argc != 2) {
707 		printf("Invalid WPS_ER_PIN command: need two arguments:\n"
708 		       "- UUID: use 'any' to select any\n"
709 		       "- PIN: Enrollee PIN\n");
710 		return -1;
711 	}
712 
713 	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
714 			  argv[0], argv[1]);
715 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
716 		printf("Too long WPS_ER_PIN command.\n");
717 		return -1;
718 	}
719 	return wpa_ctrl_command(ctrl, cmd);
720 }
721 
722 
723 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
724 				  char *argv[])
725 {
726 	char cmd[256];
727 	int res;
728 
729 	if (argc != 1) {
730 		printf("Invalid WPS_ER_PBC command: need one argument:\n"
731 		       "- UUID: Specify the Enrollee\n");
732 		return -1;
733 	}
734 
735 	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
736 			  argv[0]);
737 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
738 		printf("Too long WPS_ER_PBC command.\n");
739 		return -1;
740 	}
741 	return wpa_ctrl_command(ctrl, cmd);
742 }
743 
744 
745 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
746 				    char *argv[])
747 {
748 	char cmd[256];
749 	int res;
750 
751 	if (argc != 2) {
752 		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
753 		       "- UUID: specify which AP to use\n"
754 		       "- PIN: AP PIN\n");
755 		return -1;
756 	}
757 
758 	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
759 			  argv[0], argv[1]);
760 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
761 		printf("Too long WPS_ER_LEARN command.\n");
762 		return -1;
763 	}
764 	return wpa_ctrl_command(ctrl, cmd);
765 }
766 
767 
768 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
769 {
770 	char cmd[256];
771 	int res;
772 
773 	if (argc != 1) {
774 		printf("Invalid IBSS_RSN command: needs one argument "
775 		       "(Peer STA MAC address)\n");
776 		return -1;
777 	}
778 
779 	res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
780 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
781 		printf("Too long IBSS_RSN command.\n");
782 		return -1;
783 	}
784 	return wpa_ctrl_command(ctrl, cmd);
785 }
786 
787 
788 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
789 {
790 	char cmd[256];
791 	int res;
792 
793 	if (argc != 1) {
794 		printf("Invalid LEVEL command: needs one argument (debug "
795 		       "level)\n");
796 		return -1;
797 	}
798 	res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
799 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
800 		printf("Too long LEVEL command.\n");
801 		return -1;
802 	}
803 	return wpa_ctrl_command(ctrl, cmd);
804 }
805 
806 
807 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
808 {
809 	char cmd[256], *pos, *end;
810 	int i, ret;
811 
812 	if (argc < 2) {
813 		printf("Invalid IDENTITY command: needs two arguments "
814 		       "(network id and identity)\n");
815 		return -1;
816 	}
817 
818 	end = cmd + sizeof(cmd);
819 	pos = cmd;
820 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
821 			  argv[0], argv[1]);
822 	if (ret < 0 || ret >= end - pos) {
823 		printf("Too long IDENTITY command.\n");
824 		return -1;
825 	}
826 	pos += ret;
827 	for (i = 2; i < argc; i++) {
828 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
829 		if (ret < 0 || ret >= end - pos) {
830 			printf("Too long IDENTITY command.\n");
831 			return -1;
832 		}
833 		pos += ret;
834 	}
835 
836 	return wpa_ctrl_command(ctrl, cmd);
837 }
838 
839 
840 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
841 {
842 	char cmd[256], *pos, *end;
843 	int i, ret;
844 
845 	if (argc < 2) {
846 		printf("Invalid PASSWORD command: needs two arguments "
847 		       "(network id and password)\n");
848 		return -1;
849 	}
850 
851 	end = cmd + sizeof(cmd);
852 	pos = cmd;
853 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
854 			  argv[0], argv[1]);
855 	if (ret < 0 || ret >= end - pos) {
856 		printf("Too long PASSWORD command.\n");
857 		return -1;
858 	}
859 	pos += ret;
860 	for (i = 2; i < argc; i++) {
861 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
862 		if (ret < 0 || ret >= end - pos) {
863 			printf("Too long PASSWORD command.\n");
864 			return -1;
865 		}
866 		pos += ret;
867 	}
868 
869 	return wpa_ctrl_command(ctrl, cmd);
870 }
871 
872 
873 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
874 				    char *argv[])
875 {
876 	char cmd[256], *pos, *end;
877 	int i, ret;
878 
879 	if (argc < 2) {
880 		printf("Invalid NEW_PASSWORD command: needs two arguments "
881 		       "(network id and password)\n");
882 		return -1;
883 	}
884 
885 	end = cmd + sizeof(cmd);
886 	pos = cmd;
887 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
888 			  argv[0], argv[1]);
889 	if (ret < 0 || ret >= end - pos) {
890 		printf("Too long NEW_PASSWORD command.\n");
891 		return -1;
892 	}
893 	pos += ret;
894 	for (i = 2; i < argc; i++) {
895 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
896 		if (ret < 0 || ret >= end - pos) {
897 			printf("Too long NEW_PASSWORD command.\n");
898 			return -1;
899 		}
900 		pos += ret;
901 	}
902 
903 	return wpa_ctrl_command(ctrl, cmd);
904 }
905 
906 
907 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
908 {
909 	char cmd[256], *pos, *end;
910 	int i, ret;
911 
912 	if (argc < 2) {
913 		printf("Invalid PIN command: needs two arguments "
914 		       "(network id and pin)\n");
915 		return -1;
916 	}
917 
918 	end = cmd + sizeof(cmd);
919 	pos = cmd;
920 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
921 			  argv[0], argv[1]);
922 	if (ret < 0 || ret >= end - pos) {
923 		printf("Too long PIN command.\n");
924 		return -1;
925 	}
926 	pos += ret;
927 	for (i = 2; i < argc; i++) {
928 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
929 		if (ret < 0 || ret >= end - pos) {
930 			printf("Too long PIN command.\n");
931 			return -1;
932 		}
933 		pos += ret;
934 	}
935 	return wpa_ctrl_command(ctrl, cmd);
936 }
937 
938 
939 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
940 {
941 	char cmd[256], *pos, *end;
942 	int i, ret;
943 
944 	if (argc < 2) {
945 		printf("Invalid OTP command: needs two arguments (network "
946 		       "id and password)\n");
947 		return -1;
948 	}
949 
950 	end = cmd + sizeof(cmd);
951 	pos = cmd;
952 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
953 			  argv[0], argv[1]);
954 	if (ret < 0 || ret >= end - pos) {
955 		printf("Too long OTP command.\n");
956 		return -1;
957 	}
958 	pos += ret;
959 	for (i = 2; i < argc; i++) {
960 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
961 		if (ret < 0 || ret >= end - pos) {
962 			printf("Too long OTP command.\n");
963 			return -1;
964 		}
965 		pos += ret;
966 	}
967 
968 	return wpa_ctrl_command(ctrl, cmd);
969 }
970 
971 
972 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
973 				  char *argv[])
974 {
975 	char cmd[256], *pos, *end;
976 	int i, ret;
977 
978 	if (argc < 2) {
979 		printf("Invalid PASSPHRASE command: needs two arguments "
980 		       "(network id and passphrase)\n");
981 		return -1;
982 	}
983 
984 	end = cmd + sizeof(cmd);
985 	pos = cmd;
986 	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
987 			  argv[0], argv[1]);
988 	if (ret < 0 || ret >= end - pos) {
989 		printf("Too long PASSPHRASE command.\n");
990 		return -1;
991 	}
992 	pos += ret;
993 	for (i = 2; i < argc; i++) {
994 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
995 		if (ret < 0 || ret >= end - pos) {
996 			printf("Too long PASSPHRASE command.\n");
997 			return -1;
998 		}
999 		pos += ret;
1000 	}
1001 
1002 	return wpa_ctrl_command(ctrl, cmd);
1003 }
1004 
1005 
1006 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1007 {
1008 	char cmd[256], *pos, *end;
1009 	int i, ret;
1010 
1011 	if (argc < 2) {
1012 		printf("Invalid BSSID command: needs two arguments (network "
1013 		       "id and BSSID)\n");
1014 		return -1;
1015 	}
1016 
1017 	end = cmd + sizeof(cmd);
1018 	pos = cmd;
1019 	ret = os_snprintf(pos, end - pos, "BSSID");
1020 	if (ret < 0 || ret >= end - pos) {
1021 		printf("Too long BSSID command.\n");
1022 		return -1;
1023 	}
1024 	pos += ret;
1025 	for (i = 0; i < argc; i++) {
1026 		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1027 		if (ret < 0 || ret >= end - pos) {
1028 			printf("Too long BSSID command.\n");
1029 			return -1;
1030 		}
1031 		pos += ret;
1032 	}
1033 
1034 	return wpa_ctrl_command(ctrl, cmd);
1035 }
1036 
1037 
1038 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1039 				     char *argv[])
1040 {
1041 	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1042 }
1043 
1044 
1045 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1046 				      char *argv[])
1047 {
1048 	char cmd[32];
1049 	int res;
1050 
1051 	if (argc < 1) {
1052 		printf("Invalid SELECT_NETWORK command: needs one argument "
1053 		       "(network id)\n");
1054 		return -1;
1055 	}
1056 
1057 	res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1058 	if (res < 0 || (size_t) res >= sizeof(cmd))
1059 		return -1;
1060 	cmd[sizeof(cmd) - 1] = '\0';
1061 
1062 	return wpa_ctrl_command(ctrl, cmd);
1063 }
1064 
1065 
1066 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1067 				      char *argv[])
1068 {
1069 	char cmd[32];
1070 	int res;
1071 
1072 	if (argc < 1) {
1073 		printf("Invalid ENABLE_NETWORK command: needs one argument "
1074 		       "(network id)\n");
1075 		return -1;
1076 	}
1077 
1078 	res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1079 	if (res < 0 || (size_t) res >= sizeof(cmd))
1080 		return -1;
1081 	cmd[sizeof(cmd) - 1] = '\0';
1082 
1083 	return wpa_ctrl_command(ctrl, cmd);
1084 }
1085 
1086 
1087 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1088 				       char *argv[])
1089 {
1090 	char cmd[32];
1091 	int res;
1092 
1093 	if (argc < 1) {
1094 		printf("Invalid DISABLE_NETWORK command: needs one argument "
1095 		       "(network id)\n");
1096 		return -1;
1097 	}
1098 
1099 	res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1100 	if (res < 0 || (size_t) res >= sizeof(cmd))
1101 		return -1;
1102 	cmd[sizeof(cmd) - 1] = '\0';
1103 
1104 	return wpa_ctrl_command(ctrl, cmd);
1105 }
1106 
1107 
1108 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1109 				   char *argv[])
1110 {
1111 	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1112 }
1113 
1114 
1115 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1116 				      char *argv[])
1117 {
1118 	char cmd[32];
1119 	int res;
1120 
1121 	if (argc < 1) {
1122 		printf("Invalid REMOVE_NETWORK command: needs one argument "
1123 		       "(network id)\n");
1124 		return -1;
1125 	}
1126 
1127 	res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1128 	if (res < 0 || (size_t) res >= sizeof(cmd))
1129 		return -1;
1130 	cmd[sizeof(cmd) - 1] = '\0';
1131 
1132 	return wpa_ctrl_command(ctrl, cmd);
1133 }
1134 
1135 
1136 static void wpa_cli_show_network_variables(void)
1137 {
1138 	printf("set_network variables:\n"
1139 	       "  ssid (network name, SSID)\n"
1140 	       "  psk (WPA passphrase or pre-shared key)\n"
1141 	       "  key_mgmt (key management protocol)\n"
1142 	       "  identity (EAP identity)\n"
1143 	       "  password (EAP password)\n"
1144 	       "  ...\n"
1145 	       "\n"
1146 	       "Note: Values are entered in the same format as the "
1147 	       "configuration file is using,\n"
1148 	       "i.e., strings values need to be inside double quotation "
1149 	       "marks.\n"
1150 	       "For example: set_network 1 ssid \"network name\"\n"
1151 	       "\n"
1152 	       "Please see wpa_supplicant.conf documentation for full list "
1153 	       "of\navailable variables.\n");
1154 }
1155 
1156 
1157 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1158 				   char *argv[])
1159 {
1160 	char cmd[256];
1161 	int res;
1162 
1163 	if (argc == 0) {
1164 		wpa_cli_show_network_variables();
1165 		return 0;
1166 	}
1167 
1168 	if (argc != 3) {
1169 		printf("Invalid SET_NETWORK command: needs three arguments\n"
1170 		       "(network id, variable name, and value)\n");
1171 		return -1;
1172 	}
1173 
1174 	res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1175 			  argv[0], argv[1], argv[2]);
1176 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1177 		printf("Too long SET_NETWORK command.\n");
1178 		return -1;
1179 	}
1180 	return wpa_ctrl_command(ctrl, cmd);
1181 }
1182 
1183 
1184 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1185 				   char *argv[])
1186 {
1187 	char cmd[256];
1188 	int res;
1189 
1190 	if (argc == 0) {
1191 		wpa_cli_show_network_variables();
1192 		return 0;
1193 	}
1194 
1195 	if (argc != 2) {
1196 		printf("Invalid GET_NETWORK command: needs two arguments\n"
1197 		       "(network id and variable name)\n");
1198 		return -1;
1199 	}
1200 
1201 	res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1202 			  argv[0], argv[1]);
1203 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1204 		printf("Too long GET_NETWORK command.\n");
1205 		return -1;
1206 	}
1207 	return wpa_ctrl_command(ctrl, cmd);
1208 }
1209 
1210 
1211 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1212 				  char *argv[])
1213 {
1214 	return wpa_ctrl_command(ctrl, "DISCONNECT");
1215 }
1216 
1217 
1218 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1219 				  char *argv[])
1220 {
1221 	return wpa_ctrl_command(ctrl, "RECONNECT");
1222 }
1223 
1224 
1225 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1226 				   char *argv[])
1227 {
1228 	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1229 }
1230 
1231 
1232 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1233 {
1234 	return wpa_ctrl_command(ctrl, "SCAN");
1235 }
1236 
1237 
1238 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1239 				    char *argv[])
1240 {
1241 	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1242 }
1243 
1244 
1245 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1246 {
1247 	char cmd[64];
1248 	int res;
1249 
1250 	if (argc != 1) {
1251 		printf("Invalid BSS command: need one argument (index or "
1252 		       "BSSID)\n");
1253 		return -1;
1254 	}
1255 
1256 	res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1257 	if (res < 0 || (size_t) res >= sizeof(cmd))
1258 		return -1;
1259 	cmd[sizeof(cmd) - 1] = '\0';
1260 
1261 	return wpa_ctrl_command(ctrl, cmd);
1262 }
1263 
1264 
1265 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1266 				      char *argv[])
1267 {
1268 	char cmd[64];
1269 	int res;
1270 
1271 	if (argc < 1 || argc > 2) {
1272 		printf("Invalid GET_CAPABILITY command: need either one or "
1273 		       "two arguments\n");
1274 		return -1;
1275 	}
1276 
1277 	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1278 		printf("Invalid GET_CAPABILITY command: second argument, "
1279 		       "if any, must be 'strict'\n");
1280 		return -1;
1281 	}
1282 
1283 	res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1284 			  (argc == 2) ? " strict" : "");
1285 	if (res < 0 || (size_t) res >= sizeof(cmd))
1286 		return -1;
1287 	cmd[sizeof(cmd) - 1] = '\0';
1288 
1289 	return wpa_ctrl_command(ctrl, cmd);
1290 }
1291 
1292 
1293 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1294 {
1295 	printf("Available interfaces:\n");
1296 	return wpa_ctrl_command(ctrl, "INTERFACES");
1297 }
1298 
1299 
1300 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1301 {
1302 	if (argc < 1) {
1303 		wpa_cli_list_interfaces(ctrl);
1304 		return 0;
1305 	}
1306 
1307 	wpa_cli_close_connection();
1308 	os_free(ctrl_ifname);
1309 	ctrl_ifname = os_strdup(argv[0]);
1310 
1311 	if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1312 		printf("Connected to interface '%s.\n", ctrl_ifname);
1313 	} else {
1314 		printf("Could not connect to interface '%s' - re-trying\n",
1315 		       ctrl_ifname);
1316 	}
1317 	return 0;
1318 }
1319 
1320 
1321 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1322 				   char *argv[])
1323 {
1324 	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1325 }
1326 
1327 
1328 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1329 				 char *argv[])
1330 {
1331 	return wpa_ctrl_command(ctrl, "TERMINATE");
1332 }
1333 
1334 
1335 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1336 				     char *argv[])
1337 {
1338 	char cmd[256];
1339 	int res;
1340 
1341 	if (argc < 1) {
1342 		printf("Invalid INTERFACE_ADD command: needs at least one "
1343 		       "argument (interface name)\n"
1344 		       "All arguments: ifname confname driver ctrl_interface "
1345 		       "driver_param bridge_name\n");
1346 		return -1;
1347 	}
1348 
1349 	/*
1350 	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1351 	 * <driver_param>TAB<bridge_name>
1352 	 */
1353 	res = os_snprintf(cmd, sizeof(cmd),
1354 			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1355 			  argv[0],
1356 			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1357 			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1358 			  argc > 5 ? argv[5] : "");
1359 	if (res < 0 || (size_t) res >= sizeof(cmd))
1360 		return -1;
1361 	cmd[sizeof(cmd) - 1] = '\0';
1362 	return wpa_ctrl_command(ctrl, cmd);
1363 }
1364 
1365 
1366 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1367 					char *argv[])
1368 {
1369 	char cmd[128];
1370 	int res;
1371 
1372 	if (argc != 1) {
1373 		printf("Invalid INTERFACE_REMOVE command: needs one argument "
1374 		       "(interface name)\n");
1375 		return -1;
1376 	}
1377 
1378 	res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1379 	if (res < 0 || (size_t) res >= sizeof(cmd))
1380 		return -1;
1381 	cmd[sizeof(cmd) - 1] = '\0';
1382 	return wpa_ctrl_command(ctrl, cmd);
1383 }
1384 
1385 
1386 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1387 				      char *argv[])
1388 {
1389 	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1390 }
1391 
1392 
1393 #ifdef CONFIG_AP
1394 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1395 {
1396 	char buf[64];
1397 	if (argc != 1) {
1398 		printf("Invalid 'sta' command - exactly one argument, STA "
1399 		       "address, is required.\n");
1400 		return -1;
1401 	}
1402 	os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1403 	return wpa_ctrl_command(ctrl, buf);
1404 }
1405 
1406 
1407 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1408 				char *addr, size_t addr_len)
1409 {
1410 	char buf[4096], *pos;
1411 	size_t len;
1412 	int ret;
1413 
1414 	if (ctrl_conn == NULL) {
1415 		printf("Not connected to hostapd - command dropped.\n");
1416 		return -1;
1417 	}
1418 	len = sizeof(buf) - 1;
1419 	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1420 			       wpa_cli_msg_cb);
1421 	if (ret == -2) {
1422 		printf("'%s' command timed out.\n", cmd);
1423 		return -2;
1424 	} else if (ret < 0) {
1425 		printf("'%s' command failed.\n", cmd);
1426 		return -1;
1427 	}
1428 
1429 	buf[len] = '\0';
1430 	if (memcmp(buf, "FAIL", 4) == 0)
1431 		return -1;
1432 	printf("%s", buf);
1433 
1434 	pos = buf;
1435 	while (*pos != '\0' && *pos != '\n')
1436 		pos++;
1437 	*pos = '\0';
1438 	os_strlcpy(addr, buf, addr_len);
1439 	return 0;
1440 }
1441 
1442 
1443 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1444 {
1445 	char addr[32], cmd[64];
1446 
1447 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1448 		return 0;
1449 	do {
1450 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1451 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1452 
1453 	return -1;
1454 }
1455 #endif /* CONFIG_AP */
1456 
1457 
1458 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1459 {
1460 	return wpa_ctrl_command(ctrl, "SUSPEND");
1461 }
1462 
1463 
1464 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1465 {
1466 	return wpa_ctrl_command(ctrl, "RESUME");
1467 }
1468 
1469 
1470 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471 {
1472 	return wpa_ctrl_command(ctrl, "DROP_SA");
1473 }
1474 
1475 
1476 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1477 {
1478 	char cmd[128];
1479 	int res;
1480 
1481 	if (argc != 1) {
1482 		printf("Invalid ROAM command: needs one argument "
1483 		       "(target AP's BSSID)\n");
1484 		return -1;
1485 	}
1486 
1487 	res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1488 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1489 		printf("Too long ROAM command.\n");
1490 		return -1;
1491 	}
1492 	return wpa_ctrl_command(ctrl, cmd);
1493 }
1494 
1495 
1496 enum wpa_cli_cmd_flags {
1497 	cli_cmd_flag_none		= 0x00,
1498 	cli_cmd_flag_sensitive		= 0x01
1499 };
1500 
1501 struct wpa_cli_cmd {
1502 	const char *cmd;
1503 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1504 	enum wpa_cli_cmd_flags flags;
1505 	const char *usage;
1506 };
1507 
1508 static struct wpa_cli_cmd wpa_cli_commands[] = {
1509 	{ "status", wpa_cli_cmd_status,
1510 	  cli_cmd_flag_none,
1511 	  "[verbose] = get current WPA/EAPOL/EAP status" },
1512 	{ "ping", wpa_cli_cmd_ping,
1513 	  cli_cmd_flag_none,
1514 	  "= pings wpa_supplicant" },
1515 	{ "mib", wpa_cli_cmd_mib,
1516 	  cli_cmd_flag_none,
1517 	  "= get MIB variables (dot1x, dot11)" },
1518 	{ "help", wpa_cli_cmd_help,
1519 	  cli_cmd_flag_none,
1520 	  "= show this usage help" },
1521 	{ "interface", wpa_cli_cmd_interface,
1522 	  cli_cmd_flag_none,
1523 	  "[ifname] = show interfaces/select interface" },
1524 	{ "level", wpa_cli_cmd_level,
1525 	  cli_cmd_flag_none,
1526 	  "<debug level> = change debug level" },
1527 	{ "license", wpa_cli_cmd_license,
1528 	  cli_cmd_flag_none,
1529 	  "= show full wpa_cli license" },
1530 	{ "quit", wpa_cli_cmd_quit,
1531 	  cli_cmd_flag_none,
1532 	  "= exit wpa_cli" },
1533 	{ "set", wpa_cli_cmd_set,
1534 	  cli_cmd_flag_none,
1535 	  "= set variables (shows list of variables when run without "
1536 	  "arguments)" },
1537 	{ "logon", wpa_cli_cmd_logon,
1538 	  cli_cmd_flag_none,
1539 	  "= IEEE 802.1X EAPOL state machine logon" },
1540 	{ "logoff", wpa_cli_cmd_logoff,
1541 	  cli_cmd_flag_none,
1542 	  "= IEEE 802.1X EAPOL state machine logoff" },
1543 	{ "pmksa", wpa_cli_cmd_pmksa,
1544 	  cli_cmd_flag_none,
1545 	  "= show PMKSA cache" },
1546 	{ "reassociate", wpa_cli_cmd_reassociate,
1547 	  cli_cmd_flag_none,
1548 	  "= force reassociation" },
1549 	{ "preauthenticate", wpa_cli_cmd_preauthenticate,
1550 	  cli_cmd_flag_none,
1551 	  "<BSSID> = force preauthentication" },
1552 	{ "identity", wpa_cli_cmd_identity,
1553 	  cli_cmd_flag_none,
1554 	  "<network id> <identity> = configure identity for an SSID" },
1555 	{ "password", wpa_cli_cmd_password,
1556 	  cli_cmd_flag_sensitive,
1557 	  "<network id> <password> = configure password for an SSID" },
1558 	{ "new_password", wpa_cli_cmd_new_password,
1559 	  cli_cmd_flag_sensitive,
1560 	  "<network id> <password> = change password for an SSID" },
1561 	{ "pin", wpa_cli_cmd_pin,
1562 	  cli_cmd_flag_sensitive,
1563 	  "<network id> <pin> = configure pin for an SSID" },
1564 	{ "otp", wpa_cli_cmd_otp,
1565 	  cli_cmd_flag_sensitive,
1566 	  "<network id> <password> = configure one-time-password for an SSID"
1567 	},
1568 	{ "passphrase", wpa_cli_cmd_passphrase,
1569 	  cli_cmd_flag_sensitive,
1570 	  "<network id> <passphrase> = configure private key passphrase\n"
1571 	  "  for an SSID" },
1572 	{ "bssid", wpa_cli_cmd_bssid,
1573 	  cli_cmd_flag_none,
1574 	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
1575 	{ "list_networks", wpa_cli_cmd_list_networks,
1576 	  cli_cmd_flag_none,
1577 	  "= list configured networks" },
1578 	{ "select_network", wpa_cli_cmd_select_network,
1579 	  cli_cmd_flag_none,
1580 	  "<network id> = select a network (disable others)" },
1581 	{ "enable_network", wpa_cli_cmd_enable_network,
1582 	  cli_cmd_flag_none,
1583 	  "<network id> = enable a network" },
1584 	{ "disable_network", wpa_cli_cmd_disable_network,
1585 	  cli_cmd_flag_none,
1586 	  "<network id> = disable a network" },
1587 	{ "add_network", wpa_cli_cmd_add_network,
1588 	  cli_cmd_flag_none,
1589 	  "= add a network" },
1590 	{ "remove_network", wpa_cli_cmd_remove_network,
1591 	  cli_cmd_flag_none,
1592 	  "<network id> = remove a network" },
1593 	{ "set_network", wpa_cli_cmd_set_network,
1594 	  cli_cmd_flag_sensitive,
1595 	  "<network id> <variable> <value> = set network variables (shows\n"
1596 	  "  list of variables when run without arguments)" },
1597 	{ "get_network", wpa_cli_cmd_get_network,
1598 	  cli_cmd_flag_none,
1599 	  "<network id> <variable> = get network variables" },
1600 	{ "save_config", wpa_cli_cmd_save_config,
1601 	  cli_cmd_flag_none,
1602 	  "= save the current configuration" },
1603 	{ "disconnect", wpa_cli_cmd_disconnect,
1604 	  cli_cmd_flag_none,
1605 	  "= disconnect and wait for reassociate/reconnect command before\n"
1606 	  "  connecting" },
1607 	{ "reconnect", wpa_cli_cmd_reconnect,
1608 	  cli_cmd_flag_none,
1609 	  "= like reassociate, but only takes effect if already disconnected"
1610 	},
1611 	{ "scan", wpa_cli_cmd_scan,
1612 	  cli_cmd_flag_none,
1613 	  "= request new BSS scan" },
1614 	{ "scan_results", wpa_cli_cmd_scan_results,
1615 	  cli_cmd_flag_none,
1616 	  "= get latest scan results" },
1617 	{ "bss", wpa_cli_cmd_bss,
1618 	  cli_cmd_flag_none,
1619 	  "<<idx> | <bssid>> = get detailed scan result info" },
1620 	{ "get_capability", wpa_cli_cmd_get_capability,
1621 	  cli_cmd_flag_none,
1622 	  "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1623 	{ "reconfigure", wpa_cli_cmd_reconfigure,
1624 	  cli_cmd_flag_none,
1625 	  "= force wpa_supplicant to re-read its configuration file" },
1626 	{ "terminate", wpa_cli_cmd_terminate,
1627 	  cli_cmd_flag_none,
1628 	  "= terminate wpa_supplicant" },
1629 	{ "interface_add", wpa_cli_cmd_interface_add,
1630 	  cli_cmd_flag_none,
1631 	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1632 	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
1633 	  "  are optional" },
1634 	{ "interface_remove", wpa_cli_cmd_interface_remove,
1635 	  cli_cmd_flag_none,
1636 	  "<ifname> = removes the interface" },
1637 	{ "interface_list", wpa_cli_cmd_interface_list,
1638 	  cli_cmd_flag_none,
1639 	  "= list available interfaces" },
1640 	{ "ap_scan", wpa_cli_cmd_ap_scan,
1641 	  cli_cmd_flag_none,
1642 	  "<value> = set ap_scan parameter" },
1643 	{ "stkstart", wpa_cli_cmd_stkstart,
1644 	  cli_cmd_flag_none,
1645 	  "<addr> = request STK negotiation with <addr>" },
1646 	{ "ft_ds", wpa_cli_cmd_ft_ds,
1647 	  cli_cmd_flag_none,
1648 	  "<addr> = request over-the-DS FT with <addr>" },
1649 	{ "wps_pbc", wpa_cli_cmd_wps_pbc,
1650 	  cli_cmd_flag_none,
1651 	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1652 	{ "wps_pin", wpa_cli_cmd_wps_pin,
1653 	  cli_cmd_flag_sensitive,
1654 	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1655 	  "hardcoded)" },
1656 #ifdef CONFIG_WPS_OOB
1657 	{ "wps_oob", wpa_cli_cmd_wps_oob,
1658 	  cli_cmd_flag_sensitive,
1659 	  "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
1660 #endif /* CONFIG_WPS_OOB */
1661 	{ "wps_reg", wpa_cli_cmd_wps_reg,
1662 	  cli_cmd_flag_sensitive,
1663 	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1664 	{ "wps_er_start", wpa_cli_cmd_wps_er_start,
1665 	  cli_cmd_flag_none,
1666 	  "= start Wi-Fi Protected Setup External Registrar" },
1667 	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1668 	  cli_cmd_flag_none,
1669 	  "= stop Wi-Fi Protected Setup External Registrar" },
1670 	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1671 	  cli_cmd_flag_sensitive,
1672 	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
1673 	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1674 	  cli_cmd_flag_none,
1675 	  "<UUID> = accept an Enrollee PBC using External Registrar" },
1676 	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1677 	  cli_cmd_flag_sensitive,
1678 	  "<UUID> <PIN> = learn AP configuration" },
1679 	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1680 	  cli_cmd_flag_none,
1681 	  "<addr> = request RSN authentication with <addr> in IBSS" },
1682 #ifdef CONFIG_AP
1683 	{ "sta", wpa_cli_cmd_sta,
1684 	  cli_cmd_flag_none,
1685 	  "<addr> = get information about an associated station (AP)" },
1686 	{ "all_sta", wpa_cli_cmd_all_sta,
1687 	  cli_cmd_flag_none,
1688 	  "= get information about all associated stations (AP)" },
1689 #endif /* CONFIG_AP */
1690 	{ "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
1691 	  "= notification of suspend/hibernate" },
1692 	{ "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
1693 	  "= notification of resume/thaw" },
1694 	{ "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
1695 	  "= drop SA without deauth/disassoc (test command)" },
1696 	{ "roam", wpa_cli_cmd_roam,
1697 	  cli_cmd_flag_none,
1698 	  "<addr> = roam to the specified BSS" },
1699 	{ NULL, NULL, cli_cmd_flag_none, NULL }
1700 };
1701 
1702 
1703 /*
1704  * Prints command usage, lines are padded with the specified string.
1705  */
1706 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1707 {
1708 	char c;
1709 	size_t n;
1710 
1711 	printf("%s%s ", pad, cmd->cmd);
1712 	for (n = 0; (c = cmd->usage[n]); n++) {
1713 		printf("%c", c);
1714 		if (c == '\n')
1715 			printf("%s", pad);
1716 	}
1717 	printf("\n");
1718 }
1719 
1720 
1721 static void print_help(void)
1722 {
1723 	int n;
1724 	printf("commands:\n");
1725 	for (n = 0; wpa_cli_commands[n].cmd; n++)
1726 		print_cmd_help(&wpa_cli_commands[n], "  ");
1727 }
1728 
1729 
1730 #ifdef CONFIG_READLINE
1731 static int cmd_has_sensitive_data(const char *cmd)
1732 {
1733 	const char *c, *delim;
1734 	int n;
1735 	size_t len;
1736 
1737 	delim = os_strchr(cmd, ' ');
1738 	if (delim)
1739 		len = delim - cmd;
1740 	else
1741 		len = os_strlen(cmd);
1742 
1743 	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1744 		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1745 			return (wpa_cli_commands[n].flags &
1746 				cli_cmd_flag_sensitive);
1747 	}
1748 	return 0;
1749 }
1750 #endif /* CONFIG_READLINE */
1751 
1752 
1753 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1754 {
1755 	struct wpa_cli_cmd *cmd, *match = NULL;
1756 	int count;
1757 	int ret = 0;
1758 
1759 	count = 0;
1760 	cmd = wpa_cli_commands;
1761 	while (cmd->cmd) {
1762 		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1763 		{
1764 			match = cmd;
1765 			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1766 				/* we have an exact match */
1767 				count = 1;
1768 				break;
1769 			}
1770 			count++;
1771 		}
1772 		cmd++;
1773 	}
1774 
1775 	if (count > 1) {
1776 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
1777 		cmd = wpa_cli_commands;
1778 		while (cmd->cmd) {
1779 			if (os_strncasecmp(cmd->cmd, argv[0],
1780 					   os_strlen(argv[0])) == 0) {
1781 				printf(" %s", cmd->cmd);
1782 			}
1783 			cmd++;
1784 		}
1785 		printf("\n");
1786 		ret = 1;
1787 	} else if (count == 0) {
1788 		printf("Unknown command '%s'\n", argv[0]);
1789 		ret = 1;
1790 	} else {
1791 		ret = match->handler(ctrl, argc - 1, &argv[1]);
1792 	}
1793 
1794 	return ret;
1795 }
1796 
1797 
1798 static int str_match(const char *a, const char *b)
1799 {
1800 	return os_strncmp(a, b, os_strlen(b)) == 0;
1801 }
1802 
1803 
1804 static int wpa_cli_exec(const char *program, const char *arg1,
1805 			const char *arg2)
1806 {
1807 	char *cmd;
1808 	size_t len;
1809 	int res;
1810 	int ret = 0;
1811 
1812 	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1813 	cmd = os_malloc(len);
1814 	if (cmd == NULL)
1815 		return -1;
1816 	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1817 	if (res < 0 || (size_t) res >= len) {
1818 		os_free(cmd);
1819 		return -1;
1820 	}
1821 	cmd[len - 1] = '\0';
1822 #ifndef _WIN32_WCE
1823 	if (system(cmd) < 0)
1824 		ret = -1;
1825 #endif /* _WIN32_WCE */
1826 	os_free(cmd);
1827 
1828 	return ret;
1829 }
1830 
1831 
1832 static void wpa_cli_action_process(const char *msg)
1833 {
1834  	const char *pos = skip_priority(msg);
1835 
1836 	if (str_match(pos, WPA_EVENT_CONNECTED)) {
1837 		int new_id = -1;
1838 		char *id, *copy;
1839 		os_unsetenv("WPA_ID");
1840 		os_unsetenv("WPA_ID_STR");
1841 		os_unsetenv("WPA_CTRL_DIR");
1842 
1843 		pos = os_strstr(pos, "[id=");
1844 		copy = pos ? os_strdup(pos + 4) : NULL;
1845 
1846 		if (copy) {
1847 			char *pos2 = id = copy;
1848 			while (*pos2 && *pos2 != ' ')
1849 				pos2++;
1850 			*pos2++ = '\0';
1851 			new_id = atoi(id);
1852 			os_setenv("WPA_ID", id, 1);
1853 			while (*pos2 && *pos2 != '=')
1854 				pos2++;
1855 			if (*pos2 == '=')
1856 				pos2++;
1857 			id = pos2;
1858 			while (*pos2 && *pos2 != ']')
1859 				pos2++;
1860 			*pos2 = '\0';
1861 			os_setenv("WPA_ID_STR", id, 1);
1862 			os_free(copy);
1863 		}
1864 
1865 		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1866 
1867 		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1868 			wpa_cli_connected = 1;
1869 			wpa_cli_last_id = new_id;
1870 			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1871 		}
1872 	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1873 		if (wpa_cli_connected) {
1874 			wpa_cli_connected = 0;
1875 			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1876 		}
1877 	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1878 		printf("wpa_supplicant is terminating - stop monitoring\n");
1879 		wpa_cli_quit = 1;
1880 	}
1881 }
1882 
1883 
1884 #ifndef CONFIG_ANSI_C_EXTRA
1885 static void wpa_cli_action_cb(char *msg, size_t len)
1886 {
1887 	wpa_cli_action_process(msg);
1888 }
1889 #endif /* CONFIG_ANSI_C_EXTRA */
1890 
1891 
1892 static void wpa_cli_reconnect(void)
1893 {
1894 	wpa_cli_close_connection();
1895 	wpa_cli_open_connection(ctrl_ifname, 1);
1896 }
1897 
1898 
1899 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1900 				 int action_monitor)
1901 {
1902 	int first = 1;
1903 	if (ctrl_conn == NULL) {
1904 		wpa_cli_reconnect();
1905 		return;
1906 	}
1907 	while (wpa_ctrl_pending(ctrl) > 0) {
1908 		char buf[256];
1909 		size_t len = sizeof(buf) - 1;
1910 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1911 			buf[len] = '\0';
1912 			if (action_monitor)
1913 				wpa_cli_action_process(buf);
1914 			else {
1915 				if (in_read && first)
1916 					printf("\r");
1917 				first = 0;
1918 				wpa_cli_msg_cb(buf, 0);
1919 #ifdef CONFIG_READLINE
1920 				rl_on_new_line();
1921 				rl_redisplay();
1922 #endif /* CONFIG_READLINE */
1923 			}
1924 		} else {
1925 			printf("Could not read pending message.\n");
1926 			break;
1927 		}
1928 	}
1929 
1930 	if (wpa_ctrl_pending(ctrl) < 0) {
1931 		printf("Connection to wpa_supplicant lost - trying to "
1932 		       "reconnect\n");
1933 		wpa_cli_reconnect();
1934 	}
1935 }
1936 
1937 
1938 #ifdef CONFIG_READLINE
1939 static char * wpa_cli_cmd_gen(const char *text, int state)
1940 {
1941 	static int i, len;
1942 	const char *cmd;
1943 
1944 	if (state == 0) {
1945 		i = 0;
1946 		len = os_strlen(text);
1947 	}
1948 
1949 	while ((cmd = wpa_cli_commands[i].cmd)) {
1950 		i++;
1951 		if (os_strncasecmp(cmd, text, len) == 0)
1952 			return strdup(cmd);
1953 	}
1954 
1955 	return NULL;
1956 }
1957 
1958 
1959 static char * wpa_cli_dummy_gen(const char *text, int state)
1960 {
1961 	int i;
1962 
1963 	for (i = 0; wpa_cli_commands[i].cmd; i++) {
1964 		const char *cmd = wpa_cli_commands[i].cmd;
1965 		size_t len = os_strlen(cmd);
1966 		if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
1967 		    rl_line_buffer[len] == ' ') {
1968 			printf("\n%s\n", wpa_cli_commands[i].usage);
1969 			rl_on_new_line();
1970 			rl_redisplay();
1971 			break;
1972 		}
1973 	}
1974 
1975 	rl_attempted_completion_over = 1;
1976 	return NULL;
1977 }
1978 
1979 
1980 static char * wpa_cli_status_gen(const char *text, int state)
1981 {
1982 	static int i, len;
1983 	char *options[] = {
1984 		"verbose", NULL
1985 	};
1986 	char *t;
1987 
1988 	if (state == 0) {
1989 		i = 0;
1990 		len = os_strlen(text);
1991 	}
1992 
1993 	while ((t = options[i])) {
1994 		i++;
1995 		if (os_strncasecmp(t, text, len) == 0)
1996 			return strdup(t);
1997 	}
1998 
1999 	rl_attempted_completion_over = 1;
2000 	return NULL;
2001 }
2002 
2003 
2004 static char ** wpa_cli_completion(const char *text, int start, int end)
2005 {
2006 	char * (*func)(const char *text, int state);
2007 
2008 	if (start == 0)
2009 		func = wpa_cli_cmd_gen;
2010 	else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
2011 		func = wpa_cli_status_gen;
2012 	else
2013 		func = wpa_cli_dummy_gen;
2014 	return rl_completion_matches(text, func);
2015 }
2016 #endif /* CONFIG_READLINE */
2017 
2018 
2019 static void wpa_cli_interactive(void)
2020 {
2021 #define max_args 10
2022 	char cmdbuf[256], *cmd, *argv[max_args], *pos;
2023 	int argc;
2024 #ifdef CONFIG_READLINE
2025 	char *home, *hfile = NULL;
2026 #endif /* CONFIG_READLINE */
2027 
2028 	printf("\nInteractive mode\n\n");
2029 
2030 #ifdef CONFIG_READLINE
2031 	rl_attempted_completion_function = wpa_cli_completion;
2032 	home = getenv("HOME");
2033 	if (home) {
2034 		const char *fname = ".wpa_cli_history";
2035 		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2036 		hfile = os_malloc(hfile_len);
2037 		if (hfile) {
2038 			int res;
2039 			res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2040 					  fname);
2041 			if (res >= 0 && res < hfile_len) {
2042 				hfile[hfile_len - 1] = '\0';
2043 				read_history(hfile);
2044 				stifle_history(100);
2045 			}
2046 		}
2047 	}
2048 #endif /* CONFIG_READLINE */
2049 
2050 	do {
2051 		wpa_cli_recv_pending(mon_conn, 0, 0);
2052 #ifndef CONFIG_NATIVE_WINDOWS
2053 		alarm(ping_interval);
2054 #endif /* CONFIG_NATIVE_WINDOWS */
2055 #ifdef CONFIG_WPA_CLI_FORK
2056 		if (mon_pid)
2057 			kill(mon_pid, SIGUSR1);
2058 #endif /* CONFIG_WPA_CLI_FORK */
2059 #ifdef CONFIG_READLINE
2060 		cmd = readline("> ");
2061 		if (cmd && *cmd) {
2062 			HIST_ENTRY *h;
2063 			while (next_history())
2064 				;
2065 			h = previous_history();
2066 			if (h == NULL || os_strcmp(cmd, h->line) != 0)
2067 				add_history(cmd);
2068 			next_history();
2069 		}
2070 #else /* CONFIG_READLINE */
2071 		printf("> ");
2072 		cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2073 #endif /* CONFIG_READLINE */
2074 #ifndef CONFIG_NATIVE_WINDOWS
2075 		alarm(0);
2076 #endif /* CONFIG_NATIVE_WINDOWS */
2077 		if (cmd == NULL)
2078 			break;
2079 		wpa_cli_recv_pending(mon_conn, 0, 0);
2080 		pos = cmd;
2081 		while (*pos != '\0') {
2082 			if (*pos == '\n') {
2083 				*pos = '\0';
2084 				break;
2085 			}
2086 			pos++;
2087 		}
2088 		argc = 0;
2089 		pos = cmd;
2090 		for (;;) {
2091 			while (*pos == ' ')
2092 				pos++;
2093 			if (*pos == '\0')
2094 				break;
2095 			argv[argc] = pos;
2096 			argc++;
2097 			if (argc == max_args)
2098 				break;
2099 			if (*pos == '"') {
2100 				char *pos2 = os_strrchr(pos, '"');
2101 				if (pos2)
2102 					pos = pos2 + 1;
2103 			}
2104 			while (*pos != '\0' && *pos != ' ')
2105 				pos++;
2106 			if (*pos == ' ')
2107 				*pos++ = '\0';
2108 		}
2109 		if (argc)
2110 			wpa_request(ctrl_conn, argc, argv);
2111 
2112 		if (cmd != cmdbuf)
2113 			free(cmd);
2114 #ifdef CONFIG_WPA_CLI_FORK
2115 		if (mon_pid)
2116 			kill(mon_pid, SIGUSR2);
2117 #endif /* CONFIG_WPA_CLI_FORK */
2118 	} while (!wpa_cli_quit);
2119 
2120 #ifdef CONFIG_READLINE
2121 	if (hfile) {
2122 		/* Save command history, excluding lines that may contain
2123 		 * passwords. */
2124 		HIST_ENTRY *h;
2125 		history_set_pos(0);
2126 		while ((h = current_history())) {
2127 			const char *p = h->line;
2128 			while (*p == ' ' || *p == '\t')
2129 				p++;
2130 			if (cmd_has_sensitive_data(p)) {
2131 				h = remove_history(where_history());
2132 				if (h) {
2133 					os_free(__UNCONST(h->line));
2134 					os_free(__UNCONST(h->data));
2135 					os_free(h);
2136 				} else
2137 					next_history();
2138 			} else
2139 				next_history();
2140 		}
2141 		write_history(hfile);
2142 		os_free(hfile);
2143 	}
2144 #endif /* CONFIG_READLINE */
2145 }
2146 
2147 
2148 static void wpa_cli_action(struct wpa_ctrl *ctrl)
2149 {
2150 #ifdef CONFIG_ANSI_C_EXTRA
2151 	/* TODO: ANSI C version(?) */
2152 	printf("Action processing not supported in ANSI C build.\n");
2153 #else /* CONFIG_ANSI_C_EXTRA */
2154 	fd_set rfds;
2155 	int fd, res;
2156 	struct timeval tv;
2157 	char buf[256]; /* note: large enough to fit in unsolicited messages */
2158 	size_t len;
2159 
2160 	fd = wpa_ctrl_get_fd(ctrl);
2161 
2162 	while (!wpa_cli_quit) {
2163 		FD_ZERO(&rfds);
2164 		FD_SET(fd, &rfds);
2165 		tv.tv_sec = ping_interval;
2166 		tv.tv_usec = 0;
2167 		res = select(fd + 1, &rfds, NULL, NULL, &tv);
2168 		if (res < 0 && errno != EINTR) {
2169 			perror("select");
2170 			break;
2171 		}
2172 
2173 		if (FD_ISSET(fd, &rfds))
2174 			wpa_cli_recv_pending(ctrl, 0, 1);
2175 		else {
2176 			/* verify that connection is still working */
2177 			len = sizeof(buf) - 1;
2178 			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2179 					     wpa_cli_action_cb) < 0 ||
2180 			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2181 				printf("wpa_supplicant did not reply to PING "
2182 				       "command - exiting\n");
2183 				break;
2184 			}
2185 		}
2186 	}
2187 #endif /* CONFIG_ANSI_C_EXTRA */
2188 }
2189 
2190 
2191 static void wpa_cli_cleanup(void)
2192 {
2193 	wpa_cli_close_connection();
2194 	if (pid_file)
2195 		os_daemonize_terminate(pid_file);
2196 
2197 	os_program_deinit();
2198 }
2199 
2200 static void wpa_cli_terminate(int sig)
2201 {
2202 	wpa_cli_cleanup();
2203 	exit(0);
2204 }
2205 
2206 
2207 #ifdef CONFIG_WPA_CLI_FORK
2208 static void wpa_cli_usr1(int sig)
2209 {
2210 #ifdef CONFIG_READLINE
2211 	rl_on_new_line();
2212 	rl_redisplay();
2213 #endif /* CONFIG_READLINE */
2214 }
2215 #endif /* CONFIG_WPA_CLI_FORK */
2216 
2217 
2218 #ifndef CONFIG_NATIVE_WINDOWS
2219 static void wpa_cli_alarm(int sig)
2220 {
2221 	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2222 		printf("Connection to wpa_supplicant lost - trying to "
2223 		       "reconnect\n");
2224 		wpa_cli_close_connection();
2225 	}
2226 	if (!ctrl_conn)
2227 		wpa_cli_reconnect();
2228 	if (mon_conn)
2229 		wpa_cli_recv_pending(mon_conn, 1, 0);
2230 	alarm(ping_interval);
2231 }
2232 #endif /* CONFIG_NATIVE_WINDOWS */
2233 
2234 
2235 static char * wpa_cli_get_default_ifname(void)
2236 {
2237 	char *ifname = NULL;
2238 
2239 #ifdef CONFIG_CTRL_IFACE_UNIX
2240 	struct dirent *dent;
2241 	DIR *dir = opendir(ctrl_iface_dir);
2242 	if (!dir)
2243 		return NULL;
2244 	while ((dent = readdir(dir))) {
2245 #ifdef _DIRENT_HAVE_D_TYPE
2246 		/*
2247 		 * Skip the file if it is not a socket. Also accept
2248 		 * DT_UNKNOWN (0) in case the C library or underlying
2249 		 * file system does not support d_type.
2250 		 */
2251 		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2252 			continue;
2253 #endif /* _DIRENT_HAVE_D_TYPE */
2254 		if (os_strcmp(dent->d_name, ".") == 0 ||
2255 		    os_strcmp(dent->d_name, "..") == 0)
2256 			continue;
2257 		printf("Selected interface '%s'\n", dent->d_name);
2258 		ifname = os_strdup(dent->d_name);
2259 		break;
2260 	}
2261 	closedir(dir);
2262 #endif /* CONFIG_CTRL_IFACE_UNIX */
2263 
2264 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2265 	char buf[2048], *pos;
2266 	size_t len;
2267 	struct wpa_ctrl *ctrl;
2268 	int ret;
2269 
2270 	ctrl = wpa_ctrl_open(NULL);
2271 	if (ctrl == NULL)
2272 		return NULL;
2273 
2274 	len = sizeof(buf) - 1;
2275 	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2276 	if (ret >= 0) {
2277 		buf[len] = '\0';
2278 		pos = os_strchr(buf, '\n');
2279 		if (pos)
2280 			*pos = '\0';
2281 		ifname = os_strdup(buf);
2282 	}
2283 	wpa_ctrl_close(ctrl);
2284 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2285 
2286 	return ifname;
2287 }
2288 
2289 
2290 int main(int argc, char *argv[])
2291 {
2292 	int warning_displayed = 0;
2293 	int c;
2294 	int daemonize = 0;
2295 	int ret = 0;
2296 	const char *global = NULL;
2297 
2298 	if (os_program_init())
2299 		return -1;
2300 
2301 	for (;;) {
2302 		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
2303 		if (c < 0)
2304 			break;
2305 		switch (c) {
2306 		case 'a':
2307 			action_file = optarg;
2308 			break;
2309 		case 'B':
2310 			daemonize = 1;
2311 			break;
2312 		case 'g':
2313 			global = optarg;
2314 			break;
2315 		case 'G':
2316 			ping_interval = atoi(optarg);
2317 			break;
2318 		case 'h':
2319 			usage();
2320 			return 0;
2321 		case 'v':
2322 			printf("%s\n", wpa_cli_version);
2323 			return 0;
2324 		case 'i':
2325 			os_free(ctrl_ifname);
2326 			ctrl_ifname = os_strdup(optarg);
2327 			break;
2328 		case 'p':
2329 			ctrl_iface_dir = optarg;
2330 			break;
2331 		case 'P':
2332 			pid_file = optarg;
2333 			break;
2334 		default:
2335 			usage();
2336 			return -1;
2337 		}
2338 	}
2339 
2340 	interactive = (argc == optind) && (action_file == NULL);
2341 
2342 	if (interactive)
2343 		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2344 
2345 	if (global) {
2346 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2347 		ctrl_conn = wpa_ctrl_open(NULL);
2348 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2349 		ctrl_conn = wpa_ctrl_open(global);
2350 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2351 		if (ctrl_conn == NULL) {
2352 			perror("Failed to connect to wpa_supplicant - "
2353 			       "wpa_ctrl_open");
2354 			return -1;
2355 		}
2356 	}
2357 
2358 #ifndef _WIN32_WCE
2359 	signal(SIGINT, wpa_cli_terminate);
2360 	signal(SIGTERM, wpa_cli_terminate);
2361 #endif /* _WIN32_WCE */
2362 #ifndef CONFIG_NATIVE_WINDOWS
2363 	signal(SIGALRM, wpa_cli_alarm);
2364 #endif /* CONFIG_NATIVE_WINDOWS */
2365 #ifdef CONFIG_WPA_CLI_FORK
2366 	signal(SIGUSR1, wpa_cli_usr1);
2367 #endif /* CONFIG_WPA_CLI_FORK */
2368 
2369 	if (ctrl_ifname == NULL)
2370 		ctrl_ifname = wpa_cli_get_default_ifname();
2371 
2372 	if (interactive) {
2373 		for (; !global;) {
2374 			if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
2375 				if (warning_displayed)
2376 					printf("Connection established.\n");
2377 				break;
2378 			}
2379 
2380 			if (!warning_displayed) {
2381 				printf("Could not connect to wpa_supplicant - "
2382 				       "re-trying\n");
2383 				warning_displayed = 1;
2384 			}
2385 			os_sleep(1, 0);
2386 			continue;
2387 		}
2388 	} else {
2389 		if (!global &&
2390 		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
2391 			perror("Failed to connect to wpa_supplicant - "
2392 			       "wpa_ctrl_open");
2393 			return -1;
2394 		}
2395 
2396 		if (action_file) {
2397 			if (wpa_ctrl_attach(ctrl_conn) == 0) {
2398 				wpa_cli_attached = 1;
2399 			} else {
2400 				printf("Warning: Failed to attach to "
2401 				       "wpa_supplicant.\n");
2402 				return -1;
2403 			}
2404 		}
2405 	}
2406 
2407 	if (daemonize && os_daemonize(pid_file))
2408 		return -1;
2409 
2410 	if (interactive)
2411 		wpa_cli_interactive();
2412 	else if (action_file)
2413 		wpa_cli_action(ctrl_conn);
2414 	else
2415 		ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2416 
2417 	os_free(ctrl_ifname);
2418 	wpa_cli_cleanup();
2419 
2420 	return ret;
2421 }
2422 
2423 #else /* CONFIG_CTRL_IFACE */
2424 int main(int argc, char *argv[])
2425 {
2426 	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2427 	return -1;
2428 }
2429 #endif /* CONFIG_CTRL_IFACE */
2430