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