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/misc/wifi/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_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
752{
753	char cmd[256], *pos, *end;
754	int i, ret;
755
756	end = cmd + sizeof(cmd);
757	pos = cmd;
758	ret = os_snprintf(pos, end - pos, "BLACKLIST");
759	if (ret < 0 || ret >= end - pos) {
760		printf("Too long BLACKLIST command.\n");
761		return -1;
762	}
763	pos += ret;
764	for (i = 0; i < argc; i++) {
765		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
766		if (ret < 0 || ret >= end - pos) {
767			printf("Too long BLACKLIST command.\n");
768			return -1;
769		}
770		pos += ret;
771	}
772
773	return wpa_ctrl_command(ctrl, cmd);
774}
775
776
777static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
778{
779	char cmd[256], *pos, *end;
780	int i, ret;
781
782	end = cmd + sizeof(cmd);
783	pos = cmd;
784	ret = os_snprintf(pos, end - pos, "LOG_LEVEL");
785	if (ret < 0 || ret >= end - pos) {
786		printf("Too long LOG_LEVEL command.\n");
787		return -1;
788	}
789	pos += ret;
790	for (i = 0; i < argc; i++) {
791		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
792		if (ret < 0 || ret >= end - pos) {
793			printf("Too long LOG_LEVEL command.\n");
794			return -1;
795		}
796		pos += ret;
797	}
798
799	return wpa_ctrl_command(ctrl, cmd);
800}
801#endif /* ANDROID */
802
803
804static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
805				     char *argv[])
806{
807	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
808}
809
810
811static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
812				      char *argv[])
813{
814	char cmd[32];
815	int res;
816
817	if (argc < 1) {
818		printf("Invalid SELECT_NETWORK command: needs one argument "
819		       "(network id)\n");
820		return -1;
821	}
822
823	res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
824	if (res < 0 || (size_t) res >= sizeof(cmd))
825		return -1;
826	cmd[sizeof(cmd) - 1] = '\0';
827
828	return wpa_ctrl_command(ctrl, cmd);
829}
830
831
832static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
833				      char *argv[])
834{
835	char cmd[32];
836	int res;
837
838	if (argc < 1) {
839		printf("Invalid ENABLE_NETWORK command: needs one argument "
840		       "(network id)\n");
841		return -1;
842	}
843
844	res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
845	if (res < 0 || (size_t) res >= sizeof(cmd))
846		return -1;
847	cmd[sizeof(cmd) - 1] = '\0';
848
849	return wpa_ctrl_command(ctrl, cmd);
850}
851
852
853static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
854				       char *argv[])
855{
856	char cmd[32];
857	int res;
858
859	if (argc < 1) {
860		printf("Invalid DISABLE_NETWORK command: needs one argument "
861		       "(network id)\n");
862		return -1;
863	}
864
865	res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
866	if (res < 0 || (size_t) res >= sizeof(cmd))
867		return -1;
868	cmd[sizeof(cmd) - 1] = '\0';
869
870	return wpa_ctrl_command(ctrl, cmd);
871}
872
873
874static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
875				   char *argv[])
876{
877	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
878}
879
880
881static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
882				      char *argv[])
883{
884	char cmd[32];
885	int res;
886
887	if (argc < 1) {
888		printf("Invalid REMOVE_NETWORK command: needs one argument "
889		       "(network id)\n");
890		return -1;
891	}
892
893	res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
894	if (res < 0 || (size_t) res >= sizeof(cmd))
895		return -1;
896	cmd[sizeof(cmd) - 1] = '\0';
897
898	return wpa_ctrl_command(ctrl, cmd);
899}
900
901
902static void wpa_cli_show_network_variables(void)
903{
904	printf("set_network variables:\n"
905	       "  ssid (network name, SSID)\n"
906	       "  psk (WPA passphrase or pre-shared key)\n"
907	       "  key_mgmt (key management protocol)\n"
908	       "  identity (EAP identity)\n"
909	       "  password (EAP password)\n"
910	       "  ...\n"
911	       "\n"
912	       "Note: Values are entered in the same format as the "
913	       "configuration file is using,\n"
914	       "i.e., strings values need to be inside double quotation "
915	       "marks.\n"
916	       "For example: set_network 1 ssid \"network name\"\n"
917	       "\n"
918	       "Please see wpa_supplicant.conf documentation for full list "
919	       "of\navailable variables.\n");
920}
921
922
923static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
924				   char *argv[])
925{
926	char cmd[256];
927	int res;
928
929	if (argc == 0) {
930		wpa_cli_show_network_variables();
931		return 0;
932	}
933
934	if (argc != 3) {
935		printf("Invalid SET_NETWORK command: needs three arguments\n"
936		       "(network id, variable name, and value)\n");
937		return -1;
938	}
939
940	res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
941			  argv[0], argv[1], argv[2]);
942	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
943		printf("Too long SET_NETWORK command.\n");
944		return -1;
945	}
946	return wpa_ctrl_command(ctrl, cmd);
947}
948
949
950static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
951				   char *argv[])
952{
953	char cmd[256];
954	int res;
955
956	if (argc == 0) {
957		wpa_cli_show_network_variables();
958		return 0;
959	}
960
961	if (argc != 2) {
962		printf("Invalid GET_NETWORK command: needs two arguments\n"
963		       "(network id and variable name)\n");
964		return -1;
965	}
966
967	res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
968			  argv[0], argv[1]);
969	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
970		printf("Too long GET_NETWORK command.\n");
971		return -1;
972	}
973	return wpa_ctrl_command(ctrl, cmd);
974}
975
976
977static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
978				  char *argv[])
979{
980	return wpa_ctrl_command(ctrl, "DISCONNECT");
981}
982
983
984static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
985				  char *argv[])
986{
987	return wpa_ctrl_command(ctrl, "RECONNECT");
988}
989
990
991static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
992				   char *argv[])
993{
994	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
995}
996
997
998static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
999{
1000	return wpa_ctrl_command(ctrl, "SCAN");
1001}
1002
1003
1004static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1005				    char *argv[])
1006{
1007	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1008}
1009
1010
1011static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1012{
1013	char cmd[64];
1014	int res;
1015
1016	if (argc != 1) {
1017		printf("Invalid BSS command: need one argument (index or "
1018		       "BSSID)\n");
1019		return -1;
1020	}
1021
1022	res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1023	if (res < 0 || (size_t) res >= sizeof(cmd))
1024		return -1;
1025	cmd[sizeof(cmd) - 1] = '\0';
1026
1027	return wpa_ctrl_command(ctrl, cmd);
1028}
1029
1030
1031static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1032				      char *argv[])
1033{
1034	char cmd[64];
1035	int res;
1036
1037	if (argc < 1 || argc > 2) {
1038		printf("Invalid GET_CAPABILITY command: need either one or "
1039		       "two arguments\n");
1040		return -1;
1041	}
1042
1043	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1044		printf("Invalid GET_CAPABILITY command: second argument, "
1045		       "if any, must be 'strict'\n");
1046		return -1;
1047	}
1048
1049	res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1050			  (argc == 2) ? " strict" : "");
1051	if (res < 0 || (size_t) res >= sizeof(cmd))
1052		return -1;
1053	cmd[sizeof(cmd) - 1] = '\0';
1054
1055	return wpa_ctrl_command(ctrl, cmd);
1056}
1057
1058
1059static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1060{
1061	printf("Available interfaces:\n");
1062	return wpa_ctrl_command(ctrl, "INTERFACES");
1063}
1064
1065
1066static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1067{
1068	if (argc < 1) {
1069		wpa_cli_list_interfaces(ctrl);
1070		return 0;
1071	}
1072
1073	wpa_cli_close_connection();
1074	os_free(ctrl_ifname);
1075	ctrl_ifname = os_strdup(argv[0]);
1076
1077	if ((ctrl_conn = wpa_cli_open_connection(ctrl_ifname)) != NULL) {
1078		printf("Connected to interface '%s.\n", ctrl_ifname);
1079		if (wpa_ctrl_attach(monitor_conn) == 0) {
1080			wpa_cli_attached = 1;
1081		} else {
1082			printf("Warning: Failed to attach to "
1083			       "wpa_supplicant.\n");
1084		}
1085	} else {
1086		printf("Could not connect to interface '%s' - re-trying\n",
1087		       ctrl_ifname);
1088	}
1089	return 0;
1090}
1091
1092
1093static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1094				   char *argv[])
1095{
1096	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1097}
1098
1099
1100static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1101				 char *argv[])
1102{
1103	return wpa_ctrl_command(ctrl, "TERMINATE");
1104}
1105
1106
1107static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1108				     char *argv[])
1109{
1110	char cmd[256];
1111	int res;
1112
1113	if (argc < 1) {
1114		printf("Invalid INTERFACE_ADD command: needs at least one "
1115		       "argument (interface name)\n"
1116		       "All arguments: ifname confname driver ctrl_interface "
1117		       "driver_param bridge_name\n");
1118		return -1;
1119	}
1120
1121	/*
1122	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1123	 * <driver_param>TAB<bridge_name>
1124	 */
1125	res = os_snprintf(cmd, sizeof(cmd),
1126			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1127			  argv[0],
1128			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1129			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1130			  argc > 5 ? argv[5] : "");
1131	if (res < 0 || (size_t) res >= sizeof(cmd))
1132		return -1;
1133	cmd[sizeof(cmd) - 1] = '\0';
1134	return wpa_ctrl_command(ctrl, cmd);
1135}
1136
1137
1138static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1139					char *argv[])
1140{
1141	char cmd[128];
1142	int res;
1143
1144	if (argc != 1) {
1145		printf("Invalid INTERFACE_REMOVE command: needs one argument "
1146		       "(interface name)\n");
1147		return -1;
1148	}
1149
1150	res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
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_list(struct wpa_ctrl *ctrl, int argc,
1159				      char *argv[])
1160{
1161	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1162}
1163
1164
1165static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc,
1166				      char *argv[])
1167{
1168	char cmd[32];
1169
1170	if (argc < 1) {
1171		printf("Invalid DRIVER command: needs one argument (cmd)\n");
1172		return -1;
1173	}
1174
1175	if (argc > 1)
1176		os_snprintf(cmd, sizeof(cmd), "DRIVER %s %s", argv[0], argv[1]);
1177	else
1178		os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
1179	cmd[sizeof(cmd) - 1] = '\0';
1180
1181	return wpa_ctrl_command(ctrl, cmd);
1182}
1183
1184
1185enum wpa_cli_cmd_flags {
1186	cli_cmd_flag_none		= 0x00,
1187	cli_cmd_flag_sensitive		= 0x01
1188};
1189
1190struct wpa_cli_cmd {
1191	const char *cmd;
1192	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1193	enum wpa_cli_cmd_flags flags;
1194	const char *usage;
1195};
1196
1197static struct wpa_cli_cmd wpa_cli_commands[] = {
1198	{ "status", wpa_cli_cmd_status,
1199	  cli_cmd_flag_none,
1200	  "[verbose] = get current WPA/EAPOL/EAP status" },
1201	{ "ping", wpa_cli_cmd_ping,
1202	  cli_cmd_flag_none,
1203	  "= pings wpa_supplicant" },
1204	{ "mib", wpa_cli_cmd_mib,
1205	  cli_cmd_flag_none,
1206	  "= get MIB variables (dot1x, dot11)" },
1207	{ "help", wpa_cli_cmd_help,
1208	  cli_cmd_flag_none,
1209	  "= show this usage help" },
1210	{ "interface", wpa_cli_cmd_interface,
1211	  cli_cmd_flag_none,
1212	  "[ifname] = show interfaces/select interface" },
1213	{ "level", wpa_cli_cmd_level,
1214	  cli_cmd_flag_none,
1215	  "<debug level> = change debug level" },
1216	{ "license", wpa_cli_cmd_license,
1217	  cli_cmd_flag_none,
1218	  "= show full wpa_cli license" },
1219	{ "quit", wpa_cli_cmd_quit,
1220	  cli_cmd_flag_none,
1221	  "= exit wpa_cli" },
1222	{ "set", wpa_cli_cmd_set,
1223	  cli_cmd_flag_none,
1224	  "= set variables (shows list of variables when run without "
1225	  "arguments)" },
1226	{ "logon", wpa_cli_cmd_logon,
1227	  cli_cmd_flag_none,
1228	  "= IEEE 802.1X EAPOL state machine logon" },
1229	{ "logoff", wpa_cli_cmd_logoff,
1230	  cli_cmd_flag_none,
1231	  "= IEEE 802.1X EAPOL state machine logoff" },
1232	{ "pmksa", wpa_cli_cmd_pmksa,
1233	  cli_cmd_flag_none,
1234	  "= show PMKSA cache" },
1235	{ "reassociate", wpa_cli_cmd_reassociate,
1236	  cli_cmd_flag_none,
1237	  "= force reassociation" },
1238	{ "preauthenticate", wpa_cli_cmd_preauthenticate,
1239	  cli_cmd_flag_none,
1240	  "<BSSID> = force preauthentication" },
1241	{ "identity", wpa_cli_cmd_identity,
1242	  cli_cmd_flag_none,
1243	  "<network id> <identity> = configure identity for an SSID" },
1244	{ "password", wpa_cli_cmd_password,
1245	  cli_cmd_flag_sensitive,
1246	  "<network id> <password> = configure password for an SSID" },
1247	{ "new_password", wpa_cli_cmd_new_password,
1248	  cli_cmd_flag_sensitive,
1249	  "<network id> <password> = change password for an SSID" },
1250	{ "pin", wpa_cli_cmd_pin,
1251	  cli_cmd_flag_sensitive,
1252	  "<network id> <pin> = configure pin for an SSID" },
1253	{ "otp", wpa_cli_cmd_otp,
1254	  cli_cmd_flag_sensitive,
1255	  "<network id> <password> = configure one-time-password for an SSID"
1256	},
1257	{ "passphrase", wpa_cli_cmd_passphrase,
1258	  cli_cmd_flag_sensitive,
1259	  "<network id> <passphrase> = configure private key passphrase\n"
1260	  "  for an SSID" },
1261	{ "bssid", wpa_cli_cmd_bssid,
1262	  cli_cmd_flag_none,
1263	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
1264#ifdef ANDROID
1265	{ "blacklist", wpa_cli_cmd_blacklist,
1266	  cli_cmd_flag_none,
1267	  "<BSSID> = add a BSSID to the blacklist\n"
1268	  "blacklist clear = clear the blacklist\n"
1269	  "blacklist = display the blacklist" },
1270	{ "log_level", wpa_cli_cmd_log_level,
1271	  cli_cmd_flag_none,
1272	  "<level> [<timestamp>] = update the log level/timestamp of wpa_supplicant\n"
1273	  "log_level = display the current log level and log options" },
1274#endif
1275    { "list_networks", wpa_cli_cmd_list_networks,
1276	  cli_cmd_flag_none,
1277	  "= list configured networks" },
1278	{ "select_network", wpa_cli_cmd_select_network,
1279	  cli_cmd_flag_none,
1280	  "<network id> = select a network (disable others)" },
1281	{ "enable_network", wpa_cli_cmd_enable_network,
1282	  cli_cmd_flag_none,
1283	  "<network id> = enable a network" },
1284	{ "disable_network", wpa_cli_cmd_disable_network,
1285	  cli_cmd_flag_none,
1286	  "<network id> = disable a network" },
1287	{ "add_network", wpa_cli_cmd_add_network,
1288	  cli_cmd_flag_none,
1289	  "= add a network" },
1290	{ "remove_network", wpa_cli_cmd_remove_network,
1291	  cli_cmd_flag_none,
1292	  "<network id> = remove a network" },
1293	{ "set_network", wpa_cli_cmd_set_network,
1294	  cli_cmd_flag_sensitive,
1295	  "<network id> <variable> <value> = set network variables (shows\n"
1296	  "  list of variables when run without arguments)" },
1297	{ "get_network", wpa_cli_cmd_get_network,
1298	  cli_cmd_flag_none,
1299	  "<network id> <variable> = get network variables" },
1300	{ "save_config", wpa_cli_cmd_save_config,
1301	  cli_cmd_flag_none,
1302	  "= save the current configuration" },
1303	{ "disconnect", wpa_cli_cmd_disconnect,
1304	  cli_cmd_flag_none,
1305	  "= disconnect and wait for reassociate/reconnect command before\n"
1306	  "  connecting" },
1307	{ "reconnect", wpa_cli_cmd_reconnect,
1308	  cli_cmd_flag_none,
1309	  "= like reassociate, but only takes effect if already disconnected"
1310	},
1311	{ "scan", wpa_cli_cmd_scan,
1312	  cli_cmd_flag_none,
1313	  "= request new BSS scan" },
1314	{ "scan_results", wpa_cli_cmd_scan_results,
1315	  cli_cmd_flag_none,
1316	  "= get latest scan results" },
1317	{ "bss", wpa_cli_cmd_bss,
1318	  cli_cmd_flag_none,
1319	  "<<idx> | <bssid>> = get detailed scan result info" },
1320	{ "get_capability", wpa_cli_cmd_get_capability,
1321	  cli_cmd_flag_none,
1322	  "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1323	{ "reconfigure", wpa_cli_cmd_reconfigure,
1324	  cli_cmd_flag_none,
1325	  "= force wpa_supplicant to re-read its configuration file" },
1326	{ "terminate", wpa_cli_cmd_terminate,
1327	  cli_cmd_flag_none,
1328	  "= terminate wpa_supplicant" },
1329	{ "interface_add", wpa_cli_cmd_interface_add,
1330	  cli_cmd_flag_none,
1331	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1332	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
1333	  "  are optional" },
1334	{ "interface_remove", wpa_cli_cmd_interface_remove,
1335	  cli_cmd_flag_none,
1336	  "<ifname> = removes the interface" },
1337	{ "interface_list", wpa_cli_cmd_interface_list,
1338	  cli_cmd_flag_none,
1339	  "= list available interfaces" },
1340	{ "ap_scan", wpa_cli_cmd_ap_scan,
1341	  cli_cmd_flag_none,
1342	  "<value> = set ap_scan parameter" },
1343	{ "stkstart", wpa_cli_cmd_stkstart,
1344	  cli_cmd_flag_none,
1345	  "<addr> = request STK negotiation with <addr>" },
1346	{ "ft_ds", wpa_cli_cmd_ft_ds,
1347	  cli_cmd_flag_none,
1348	  "<addr> = request over-the-DS FT with <addr>" },
1349	{ "wps_pbc", wpa_cli_cmd_wps_pbc,
1350	  cli_cmd_flag_none,
1351	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1352	{ "wps_pin", wpa_cli_cmd_wps_pin,
1353	  cli_cmd_flag_sensitive,
1354	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1355	  "hardcoded)" },
1356	{ "wps_reg", wpa_cli_cmd_wps_reg,
1357	  cli_cmd_flag_sensitive,
1358	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1359	{ "driver", wpa_cli_cmd_driver,
1360	  cli_cmd_flag_none,
1361	  "<command> = driver private commands" },
1362	{ NULL, NULL, cli_cmd_flag_none, NULL }
1363};
1364
1365
1366/*
1367 * Prints command usage, lines are padded with the specified string.
1368 */
1369static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1370{
1371	char c;
1372	size_t n;
1373
1374	printf("%s%s ", pad, cmd->cmd);
1375	for (n = 0; (c = cmd->usage[n]); n++) {
1376		printf("%c", c);
1377		if (c == '\n')
1378			printf("%s", pad);
1379	}
1380	printf("\n");
1381}
1382
1383
1384static void print_help(void)
1385{
1386	int n;
1387	printf("commands:\n");
1388	for (n = 0; wpa_cli_commands[n].cmd; n++)
1389		print_cmd_help(&wpa_cli_commands[n], "  ");
1390}
1391
1392
1393#ifdef CONFIG_READLINE
1394static int cmd_has_sensitive_data(const char *cmd)
1395{
1396	const char *c, *delim;
1397	int n;
1398	size_t len;
1399
1400	delim = os_strchr(cmd, ' ');
1401	if (delim)
1402		len = delim - cmd;
1403	else
1404		len = os_strlen(cmd);
1405
1406	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1407		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1408			return (wpa_cli_commands[n].flags &
1409				cli_cmd_flag_sensitive);
1410	}
1411	return 0;
1412}
1413#endif /* CONFIG_READLINE */
1414
1415
1416static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1417{
1418	struct wpa_cli_cmd *cmd, *match = NULL;
1419	int count;
1420	int ret = 0;
1421
1422	count = 0;
1423	cmd = wpa_cli_commands;
1424	while (cmd->cmd) {
1425		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1426		{
1427			match = cmd;
1428			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1429				/* we have an exact match */
1430				count = 1;
1431				break;
1432			}
1433			count++;
1434		}
1435		cmd++;
1436	}
1437
1438	if (count > 1) {
1439		printf("Ambiguous command '%s'; possible commands:", argv[0]);
1440		cmd = wpa_cli_commands;
1441		while (cmd->cmd) {
1442			if (os_strncasecmp(cmd->cmd, argv[0],
1443					   os_strlen(argv[0])) == 0) {
1444				printf(" %s", cmd->cmd);
1445			}
1446			cmd++;
1447		}
1448		printf("\n");
1449		ret = 1;
1450	} else if (count == 0) {
1451		printf("Unknown command '%s'\n", argv[0]);
1452		ret = 1;
1453	} else {
1454        if( os_strncasecmp( "level", argv[0], os_strlen(argv[0]) ) == 0 )  {
1455            ctrl = monitor_conn;
1456        }
1457		ret = match->handler(ctrl, argc - 1, &argv[1]);
1458	}
1459
1460	return ret;
1461}
1462
1463
1464static int str_match(const char *a, const char *b)
1465{
1466	return os_strncmp(a, b, os_strlen(b)) == 0;
1467}
1468
1469
1470static int wpa_cli_exec(const char *program, const char *arg1,
1471			const char *arg2)
1472{
1473	char *cmd;
1474	size_t len;
1475	int res;
1476	int ret = 0;
1477
1478	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1479	cmd = os_malloc(len);
1480	if (cmd == NULL)
1481		return -1;
1482	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1483	if (res < 0 || (size_t) res >= len) {
1484		os_free(cmd);
1485		return -1;
1486	}
1487	cmd[len - 1] = '\0';
1488#ifndef _WIN32_WCE
1489	if (system(cmd) < 0)
1490		ret = -1;
1491#endif /* _WIN32_WCE */
1492	os_free(cmd);
1493
1494	return ret;
1495}
1496
1497
1498static void wpa_cli_action_process(const char *msg)
1499{
1500	const char *pos;
1501	char *copy = NULL, *id, *pos2;
1502
1503	pos = msg;
1504	if (*pos == '<') {
1505		/* skip priority */
1506		pos = os_strchr(pos, '>');
1507		if (pos)
1508			pos++;
1509		else
1510			pos = msg;
1511	}
1512
1513	if (str_match(pos, WPA_EVENT_CONNECTED)) {
1514		int new_id = -1;
1515		os_unsetenv("WPA_ID");
1516		os_unsetenv("WPA_ID_STR");
1517		os_unsetenv("WPA_CTRL_DIR");
1518
1519		pos = os_strstr(pos, "[id=");
1520		if (pos)
1521			copy = os_strdup(pos + 4);
1522
1523		if (copy) {
1524			pos2 = id = copy;
1525			while (*pos2 && *pos2 != ' ')
1526				pos2++;
1527			*pos2++ = '\0';
1528			new_id = atoi(id);
1529			os_setenv("WPA_ID", id, 1);
1530			while (*pos2 && *pos2 != '=')
1531				pos2++;
1532			if (*pos2 == '=')
1533				pos2++;
1534			id = pos2;
1535			while (*pos2 && *pos2 != ']')
1536				pos2++;
1537			*pos2 = '\0';
1538			os_setenv("WPA_ID_STR", id, 1);
1539			os_free(copy);
1540		}
1541
1542		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1543
1544		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1545			wpa_cli_connected = 1;
1546			wpa_cli_last_id = new_id;
1547			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1548		}
1549	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1550		if (wpa_cli_connected) {
1551			wpa_cli_connected = 0;
1552			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1553		}
1554	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1555		printf("wpa_supplicant is terminating - stop monitoring\n");
1556		wpa_cli_quit = 1;
1557	}
1558}
1559
1560
1561#ifndef CONFIG_ANSI_C_EXTRA
1562static void wpa_cli_action_cb(char *msg, size_t len)
1563{
1564	wpa_cli_action_process(msg);
1565}
1566#endif /* CONFIG_ANSI_C_EXTRA */
1567
1568
1569static void wpa_cli_reconnect(void)
1570{
1571	wpa_cli_close_connection();
1572	ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1573	if (ctrl_conn) {
1574		printf("Connection to wpa_supplicant re-established\n");
1575		if (wpa_ctrl_attach(monitor_conn) == 0) {
1576			wpa_cli_attached = 1;
1577		} else {
1578			printf("Warning: Failed to attach to "
1579			       "wpa_supplicant.\n");
1580		}
1581	}
1582}
1583
1584
1585static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1586				 int action_monitor)
1587{
1588	int first = 1;
1589	if (ctrl == NULL) {
1590		wpa_cli_reconnect();
1591		return;
1592	}
1593	while (wpa_ctrl_pending(ctrl) > 0) {
1594		char buf[256];
1595		size_t len = sizeof(buf) - 1;
1596		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1597			buf[len] = '\0';
1598			if (action_monitor)
1599				wpa_cli_action_process(buf);
1600			else {
1601				if (in_read && first)
1602					printf("\n");
1603				first = 0;
1604				printf("%s\n", buf);
1605			}
1606		} else {
1607			printf("Could not read pending message.\n");
1608			break;
1609		}
1610	}
1611
1612	if (wpa_ctrl_pending(ctrl) < 0) {
1613		printf("Connection to wpa_supplicant lost - trying to "
1614		       "reconnect\n");
1615		wpa_cli_reconnect();
1616	}
1617}
1618
1619
1620#ifdef CONFIG_READLINE
1621static char * wpa_cli_cmd_gen(const char *text, int state)
1622{
1623	static int i, len;
1624	const char *cmd;
1625
1626	if (state == 0) {
1627		i = 0;
1628		len = os_strlen(text);
1629	}
1630
1631	while ((cmd = wpa_cli_commands[i].cmd)) {
1632		i++;
1633		if (os_strncasecmp(cmd, text, len) == 0)
1634			return os_strdup(cmd);
1635	}
1636
1637	return NULL;
1638}
1639
1640
1641static char * wpa_cli_dummy_gen(const char *text, int state)
1642{
1643	return NULL;
1644}
1645
1646
1647static char ** wpa_cli_completion(const char *text, int start, int end)
1648{
1649	return rl_completion_matches(text, start == 0 ?
1650				     wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1651}
1652#endif /* CONFIG_READLINE */
1653
1654
1655static void wpa_cli_interactive(void)
1656{
1657#define max_args 10
1658	char cmdbuf[256], *cmd, *argv[max_args], *pos;
1659	int argc;
1660#ifdef CONFIG_READLINE
1661	char *home, *hfile = NULL;
1662#endif /* CONFIG_READLINE */
1663
1664	printf("\nInteractive mode\n\n");
1665
1666#ifdef CONFIG_READLINE
1667	rl_attempted_completion_function = wpa_cli_completion;
1668	home = getenv("HOME");
1669	if (home) {
1670		const char *fname = ".wpa_cli_history";
1671		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1672		hfile = os_malloc(hfile_len);
1673		if (hfile) {
1674			int res;
1675			res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1676					  fname);
1677			if (res >= 0 && res < hfile_len) {
1678				hfile[hfile_len - 1] = '\0';
1679				read_history(hfile);
1680				stifle_history(100);
1681			}
1682		}
1683	}
1684#endif /* CONFIG_READLINE */
1685
1686	do {
1687		wpa_cli_recv_pending(monitor_conn, 0, 0);
1688#ifndef CONFIG_NATIVE_WINDOWS
1689		alarm(ping_interval);
1690#endif /* CONFIG_NATIVE_WINDOWS */
1691#ifdef CONFIG_READLINE
1692		cmd = readline("> ");
1693		if (cmd && *cmd) {
1694			HIST_ENTRY *h;
1695			while (next_history())
1696				;
1697			h = previous_history();
1698			if (h == NULL || os_strcmp(cmd, h->line) != 0)
1699				add_history(cmd);
1700			next_history();
1701		}
1702#else /* CONFIG_READLINE */
1703		printf("> ");
1704		cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1705#endif /* CONFIG_READLINE */
1706#ifndef CONFIG_NATIVE_WINDOWS
1707		alarm(0);
1708#endif /* CONFIG_NATIVE_WINDOWS */
1709		if (cmd == NULL)
1710			break;
1711		wpa_cli_recv_pending(monitor_conn, 0, 0);
1712		pos = cmd;
1713		while (*pos != '\0') {
1714			if (*pos == '\n') {
1715				*pos = '\0';
1716				break;
1717			}
1718			pos++;
1719		}
1720		argc = 0;
1721		pos = cmd;
1722		for (;;) {
1723			while (*pos == ' ')
1724				pos++;
1725			if (*pos == '\0')
1726				break;
1727			argv[argc] = pos;
1728			argc++;
1729			if (argc == max_args)
1730				break;
1731			if (*pos == '"') {
1732				char *pos2 = os_strrchr(pos, '"');
1733				if (pos2)
1734					pos = pos2 + 1;
1735			}
1736			while (*pos != '\0' && *pos != ' ')
1737				pos++;
1738			if (*pos == ' ')
1739				*pos++ = '\0';
1740		}
1741		if (argc)
1742			wpa_request(ctrl_conn, argc, argv);
1743
1744		if (cmd != cmdbuf)
1745			os_free(cmd);
1746	} while (!wpa_cli_quit);
1747
1748#ifdef CONFIG_READLINE
1749	if (hfile) {
1750		/* Save command history, excluding lines that may contain
1751		 * passwords. */
1752		HIST_ENTRY *h;
1753		history_set_pos(0);
1754		while ((h = current_history())) {
1755			char *p = h->line;
1756			while (*p == ' ' || *p == '\t')
1757				p++;
1758			if (cmd_has_sensitive_data(p)) {
1759				h = remove_history(where_history());
1760				if (h) {
1761					os_free(h->line);
1762					os_free(h->data);
1763					os_free(h);
1764				} else
1765					next_history();
1766			} else
1767				next_history();
1768		}
1769		write_history(hfile);
1770		os_free(hfile);
1771	}
1772#endif /* CONFIG_READLINE */
1773}
1774
1775
1776static void wpa_cli_action(struct wpa_ctrl *ctrl)
1777{
1778#ifdef CONFIG_ANSI_C_EXTRA
1779	/* TODO: ANSI C version(?) */
1780	printf("Action processing not supported in ANSI C build.\n");
1781#else /* CONFIG_ANSI_C_EXTRA */
1782	fd_set rfds;
1783	int fd, res;
1784	struct timeval tv;
1785	char buf[256]; /* note: large enough to fit in unsolicited messages */
1786	size_t len;
1787
1788	fd = wpa_ctrl_get_fd(ctrl);
1789
1790	while (!wpa_cli_quit) {
1791		FD_ZERO(&rfds);
1792		FD_SET(fd, &rfds);
1793		tv.tv_sec = ping_interval;
1794		tv.tv_usec = 0;
1795		res = select(fd + 1, &rfds, NULL, NULL, &tv);
1796		if (res < 0 && errno != EINTR) {
1797			perror("select");
1798			break;
1799		}
1800
1801		if (FD_ISSET(fd, &rfds))
1802			wpa_cli_recv_pending(ctrl, 0, 1);
1803		else {
1804			/* verify that connection is still working */
1805			len = sizeof(buf) - 1;
1806			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1807					     wpa_cli_action_cb) < 0 ||
1808			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1809				printf("wpa_supplicant did not reply to PING "
1810				       "command - exiting\n");
1811				break;
1812			}
1813		}
1814	}
1815#endif /* CONFIG_ANSI_C_EXTRA */
1816}
1817
1818
1819static void wpa_cli_cleanup(void)
1820{
1821	wpa_cli_close_connection();
1822	if (pid_file)
1823		os_daemonize_terminate(pid_file);
1824
1825	os_program_deinit();
1826}
1827
1828static void wpa_cli_terminate(int sig)
1829{
1830	wpa_cli_cleanup();
1831	exit(0);
1832}
1833
1834
1835#ifndef CONFIG_NATIVE_WINDOWS
1836static void wpa_cli_alarm(int sig)
1837{
1838	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1839		printf("Connection to wpa_supplicant lost - trying to "
1840		       "reconnect\n");
1841		wpa_cli_close_connection();
1842	}
1843	if (!monitor_conn)
1844		wpa_cli_reconnect();
1845	if (monitor_conn)
1846		wpa_cli_recv_pending(monitor_conn, 1, 0);
1847	alarm(ping_interval);
1848}
1849#endif /* CONFIG_NATIVE_WINDOWS */
1850
1851
1852static char * wpa_cli_get_default_ifname(void)
1853{
1854	char *ifname = NULL;
1855
1856#ifdef CONFIG_CTRL_IFACE_UNIX
1857	struct dirent *dent;
1858	DIR *dir = opendir(ctrl_iface_dir);
1859	if (!dir) {
1860#ifdef ANDROID
1861		char ifprop[PROPERTY_VALUE_MAX];
1862		if (property_get("wifi.interface", ifprop, NULL) != 0) {
1863			ifname = os_strdup(ifprop);
1864			printf("Using interface '%s'\n", ifname);
1865			return ifname;
1866		}
1867#endif
1868		return NULL;
1869	}
1870	while ((dent = readdir(dir))) {
1871#ifdef _DIRENT_HAVE_D_TYPE
1872		/*
1873		 * Skip the file if it is not a socket. Also accept
1874		 * DT_UNKNOWN (0) in case the C library or underlying
1875		 * file system does not support d_type.
1876		 */
1877		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1878			continue;
1879#endif /* _DIRENT_HAVE_D_TYPE */
1880		if (os_strcmp(dent->d_name, ".") == 0 ||
1881		    os_strcmp(dent->d_name, "..") == 0)
1882			continue;
1883		printf("Selected interface '%s'\n", dent->d_name);
1884		ifname = os_strdup(dent->d_name);
1885		break;
1886	}
1887	closedir(dir);
1888#endif /* CONFIG_CTRL_IFACE_UNIX */
1889
1890#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1891	char buf[4096], *pos;
1892	size_t len;
1893	struct wpa_ctrl *ctrl;
1894	int ret;
1895
1896	ctrl = wpa_ctrl_open(NULL);
1897	if (ctrl == NULL)
1898		return NULL;
1899
1900	len = sizeof(buf) - 1;
1901	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1902	if (ret >= 0) {
1903		buf[len] = '\0';
1904		pos = os_strchr(buf, '\n');
1905		if (pos)
1906			*pos = '\0';
1907		ifname = os_strdup(buf);
1908	}
1909	wpa_ctrl_close(ctrl);
1910#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1911
1912	return ifname;
1913}
1914
1915
1916int main(int argc, char *argv[])
1917{
1918	int interactive;
1919	int warning_displayed = 0;
1920	int c;
1921	int daemonize = 0;
1922	int ret = 0;
1923	const char *global = NULL;
1924
1925	if (os_program_init())
1926		return -1;
1927
1928	for (;;) {
1929		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
1930		if (c < 0)
1931			break;
1932		switch (c) {
1933		case 'a':
1934			action_file = optarg;
1935			break;
1936		case 'B':
1937			daemonize = 1;
1938			break;
1939		case 'g':
1940			global = optarg;
1941			break;
1942		case 'G':
1943			ping_interval = atoi(optarg);
1944			break;
1945		case 'h':
1946			usage();
1947			return 0;
1948		case 'v':
1949			printf("%s\n", wpa_cli_version);
1950			return 0;
1951		case 'i':
1952			os_free(ctrl_ifname);
1953			ctrl_ifname = os_strdup(optarg);
1954			break;
1955		case 'p':
1956			ctrl_iface_dir = optarg;
1957			break;
1958		case 'P':
1959			pid_file = optarg;
1960			break;
1961		default:
1962			usage();
1963			return -1;
1964		}
1965	}
1966
1967	interactive = (argc == optind) && (action_file == NULL);
1968
1969	if (interactive)
1970		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1971
1972	if (global) {
1973#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1974		ctrl_conn = wpa_ctrl_open(NULL);
1975#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1976		ctrl_conn = wpa_ctrl_open(global);
1977#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1978		if (ctrl_conn == NULL) {
1979			perror("Failed to connect to wpa_supplicant - "
1980			       "wpa_ctrl_open");
1981			return -1;
1982		}
1983	}
1984
1985	for (; !global;) {
1986		if (ctrl_ifname == NULL)
1987			ctrl_ifname = wpa_cli_get_default_ifname();
1988		ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1989		if (ctrl_conn) {
1990			if (warning_displayed)
1991				printf("Connection established.\n");
1992			break;
1993		}
1994
1995		if (!interactive) {
1996			perror("Failed to connect to wpa_supplicant - "
1997			       "wpa_ctrl_open");
1998			return -1;
1999		}
2000
2001		if (!warning_displayed) {
2002			printf("Could not connect to wpa_supplicant - "
2003			       "re-trying\n");
2004			warning_displayed = 1;
2005		}
2006		os_sleep(1, 0);
2007		continue;
2008	}
2009
2010#ifndef _WIN32_WCE
2011	signal(SIGINT, wpa_cli_terminate);
2012	signal(SIGTERM, wpa_cli_terminate);
2013#endif /* _WIN32_WCE */
2014#ifndef CONFIG_NATIVE_WINDOWS
2015	signal(SIGALRM, wpa_cli_alarm);
2016#endif /* CONFIG_NATIVE_WINDOWS */
2017
2018	if (interactive || action_file) {
2019		if (wpa_ctrl_attach(monitor_conn) == 0) {
2020			wpa_cli_attached = 1;
2021		} else {
2022			printf("Warning: Failed to attach to "
2023			       "wpa_supplicant.\n");
2024			if (!interactive)
2025				return -1;
2026		}
2027	}
2028
2029	if (daemonize && os_daemonize(pid_file))
2030		return -1;
2031
2032	if (interactive)
2033		wpa_cli_interactive();
2034	else if (action_file)
2035		wpa_cli_action(ctrl_conn);
2036	else
2037		ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2038
2039	os_free(ctrl_ifname);
2040	wpa_cli_cleanup();
2041
2042	return ret;
2043}
2044
2045#else /* CONFIG_CTRL_IFACE */
2046int main(int argc, char *argv[])
2047{
2048	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2049	return -1;
2050}
2051#endif /* CONFIG_CTRL_IFACE */
2052