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