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