wpa_cli.c revision 214734
1139749Simp/*
212496Speter * WPA Supplicant - command line interface for wpa_supplicant daemon
310015Speter * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
410015Speter *
534832Speter * This program is free software; you can redistribute it and/or modify
610015Speter * it under the terms of the GNU General Public License version 2 as
734832Speter * published by the Free Software Foundation.
810015Speter *
910015Speter * Alternatively, this software may be distributed under the terms of BSD
1010015Speter * license.
1110015Speter *
1210015Speter * See README and COPYING for more details.
1310015Speter */
1410015Speter
1510015Speter#include "includes.h"
1610015Speter
1710015Speter#ifdef CONFIG_CTRL_IFACE
1810015Speter
1910015Speter#ifdef CONFIG_CTRL_IFACE_UNIX
2010015Speter#include <dirent.h>
2110015Speter#endif /* CONFIG_CTRL_IFACE_UNIX */
2210015Speter#ifdef CONFIG_READLINE
2310015Speter#include <readline/readline.h>
2410015Speter#include <readline/history.h>
2510015Speter#endif /* CONFIG_READLINE */
2610015Speter#ifdef CONFIG_WPA_CLI_FORK
2710015Speter#include <sys/wait.h>
2810015Speter#endif /* CONFIG_WPA_CLI_FORK */
2910015Speter
3010015Speter#include "common/wpa_ctrl.h"
3110015Speter#include "common.h"
3210015Speter#include "common/version.h"
3350477Speter
3410015Speter
3510015Speterstatic const char *wpa_cli_version =
3629676Sgibbs"wpa_cli v" VERSION_STR "\n"
3729676Sgibbs"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
3810015Speter
39136058Sphk
40136058Sphkstatic const char *wpa_cli_license =
4110015Speter"This program is free software. You can distribute it and/or modify it\n"
4210015Speter"under the terms of the GNU General Public License version 2.\n"
4310015Speter"\n"
4412496Speter"Alternatively, this software may be distributed under the terms of the\n"
4510015Speter"BSD license. See README and COPYING for more details.\n";
46136058Sphk
47136058Sphkstatic const char *wpa_cli_full_license =
4810015Speter"This program is free software; you can redistribute it and/or modify\n"
4910015Speter"it under the terms of the GNU General Public License version 2 as\n"
5010015Speter"published by the Free Software Foundation.\n"
5110015Speter"\n"
5210015Speter"This program is distributed in the hope that it will be useful,\n"
5310015Speter"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
5410015Speter"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
5510015Speter"GNU General Public License for more details.\n"
5610015Speter"\n"
5710015Speter"You should have received a copy of the GNU General Public License\n"
5810015Speter"along with this program; if not, write to the Free Software\n"
5934832Speter"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
6034832Speter"\n"
6110015Speter"Alternatively, this software may be distributed under the terms of the\n"
6210015Speter"BSD license.\n"
6310015Speter"\n"
6410015Speter"Redistribution and use in source and binary forms, with or without\n"
6510015Speter"modification, are permitted provided that the following conditions are\n"
6610015Speter"met:\n"
6710015Speter"\n"
6810015Speter"1. Redistributions of source code must retain the above copyright\n"
6910015Speter"   notice, this list of conditions and the following disclaimer.\n"
7010015Speter"\n"
7110015Speter"2. Redistributions in binary form must reproduce the above copyright\n"
7210015Speter"   notice, this list of conditions and the following disclaimer in the\n"
7310015Speter"   documentation and/or other materials provided with the distribution.\n"
7410015Speter"\n"
7510015Speter"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
7610015Speter"   names of its contributors may be used to endorse or promote products\n"
7710015Speter"   derived from this software without specific prior written permission.\n"
7810015Speter"\n"
7910015Speter"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
8010015Speter"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
8110015Speter"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
8210015Speter"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
8310015Speter"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
8434832Speter"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
8534832Speter"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
8634832Speter"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
8734832Speter"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
8834832Speter"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
8934832Speter"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
9010015Speter"\n";
9110015Speter
9210015Speterstatic struct wpa_ctrl *ctrl_conn;
9310015Speterstatic struct wpa_ctrl *mon_conn;
9410015Speter#ifdef CONFIG_WPA_CLI_FORK
9510015Speterstatic pid_t mon_pid = 0;
9610015Speter#endif /* CONFIG_WPA_CLI_FORK */
9710015Speterstatic int wpa_cli_quit = 0;
9810015Speterstatic int wpa_cli_attached = 0;
9910015Speterstatic int wpa_cli_connected = 0;
10010015Speterstatic int wpa_cli_last_id = 0;
10110015Speterstatic const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
10210015Speterstatic char *ctrl_ifname = NULL;
10310015Speterstatic const char *pid_file = NULL;
10410015Speterstatic const char *action_file = NULL;
10510015Speterstatic int ping_interval = 5;
10610015Speterstatic int interactive = 0;
10710015Speter
10810015Speter
10910015Speterstatic void print_help();
11010015Speter
11110015Speter
11210015Speterstatic void usage(void)
11310015Speter{
11410015Speter	printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
11510015Speter	       "[-a<action file>] \\\n"
11610015Speter	       "        [-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  "
11710015Speter	       "[command..]\n"
11810015Speter	       "  -h = help (show this usage text)\n"
11910015Speter	       "  -v = shown version information\n"
12010015Speter	       "  -a = run in daemon mode executing the action file based on "
12110015Speter	       "events from\n"
12210015Speter	       "       wpa_supplicant\n"
12310015Speter	       "  -B = run a daemon in the background\n"
12410015Speter	       "  default path: /var/run/wpa_supplicant\n"
12510015Speter	       "  default interface: first interface found in socket path\n");
12610015Speter	print_help();
12710015Speter}
12810015Speter
12910015Speter
13010015Speter#ifdef CONFIG_WPA_CLI_FORK
13110015Speterstatic int in_query = 0;
13210015Speter
13310015Speterstatic void wpa_cli_monitor_sig(int sig)
13410015Speter{
13512496Speter	if (sig == SIGUSR1)
13612496Speter		in_query = 1;
13710015Speter	else if (sig == SIGUSR2)
13810015Speter		in_query = 0;
13910015Speter}
14010015Speter
14110015Speterstatic void wpa_cli_monitor(void)
14210015Speter{
14310015Speter	char buf[256];
14410015Speter	size_t len = sizeof(buf) - 1;
14510015Speter	struct timeval tv;
14610015Speter	fd_set rfds;
14710015Speter
14810015Speter	signal(SIGUSR1, wpa_cli_monitor_sig);
14910015Speter	signal(SIGUSR2, wpa_cli_monitor_sig);
15010015Speter
15110015Speter	while (mon_conn) {
15210015Speter		int s = wpa_ctrl_get_fd(mon_conn);
15310015Speter		tv.tv_sec = 5;
15410015Speter		tv.tv_usec = 0;
15510015Speter		FD_ZERO(&rfds);
15610015Speter		FD_SET(s, &rfds);
15710015Speter		if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
15810015Speter			if (errno == EINTR)
15910015Speter				continue;
16010015Speter			perror("select");
16110015Speter			break;
16210015Speter		}
16310015Speter		if (mon_conn == NULL)
16410015Speter			break;
16510015Speter		if (FD_ISSET(s, &rfds)) {
16610015Speter			len = sizeof(buf) - 1;
16710015Speter			int res = wpa_ctrl_recv(mon_conn, buf, &len);
16810015Speter			if (res < 0) {
16910015Speter				perror("wpa_ctrl_recv");
17010015Speter				break;
17110015Speter			}
17210015Speter			buf[len] = '\0';
17310015Speter			if (in_query)
17410015Speter				printf("\r");
17510015Speter			printf("%s\n", buf);
17610015Speter			kill(getppid(), SIGUSR1);
17710015Speter		}
17810015Speter	}
17910015Speter}
18010015Speter#endif /* CONFIG_WPA_CLI_FORK */
18110015Speter
18210015Speter
18310015Speterstatic int wpa_cli_open_connection(const char *ifname, int attach)
18410015Speter{
18510015Speter#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
18610015Speter	ctrl_conn = wpa_ctrl_open(ifname);
18710015Speter	if (ctrl_conn == NULL)
18810015Speter		return -1;
18910015Speter
19010015Speter	if (attach && interactive)
19110015Speter		mon_conn = wpa_ctrl_open(ifname);
19210015Speter	else
19310015Speter		mon_conn = NULL;
19410015Speter#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
19510015Speter	char *cfile;
19610015Speter	int flen, res;
19710015Speter
19810015Speter	if (ifname == NULL)
19910015Speter		return -1;
20010015Speter
20110015Speter	flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
20210015Speter	cfile = os_malloc(flen);
20310015Speter	if (cfile == NULL)
20410015Speter		return -1L;
20510015Speter	res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
20610015Speter	if (res < 0 || res >= flen) {
20710015Speter		os_free(cfile);
20810015Speter		return -1;
20910015Speter	}
21010015Speter
21110015Speter	ctrl_conn = wpa_ctrl_open(cfile);
21210015Speter	if (ctrl_conn == NULL) {
21310015Speter		os_free(cfile);
21410015Speter		return -1;
21510015Speter	}
21610015Speter
21710015Speter	if (attach && interactive)
21810015Speter		mon_conn = wpa_ctrl_open(cfile);
21910015Speter	else
22010015Speter		mon_conn = NULL;
22110015Speter	os_free(cfile);
22210015Speter#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
22310015Speter
22410015Speter	if (mon_conn) {
22510015Speter		if (wpa_ctrl_attach(mon_conn) == 0) {
22610015Speter			wpa_cli_attached = 1;
22710015Speter		} else {
22810015Speter			printf("Warning: Failed to attach to "
22910015Speter			       "wpa_supplicant.\n");
23010015Speter			return -1;
23110015Speter		}
23210015Speter
23310015Speter#ifdef CONFIG_WPA_CLI_FORK
23410015Speter		{
23510015Speter			pid_t p = fork();
23610015Speter			if (p < 0) {
23710015Speter				perror("fork");
23810015Speter				return -1;
23910015Speter			}
24010015Speter			if (p == 0) {
24110015Speter				wpa_cli_monitor();
24210015Speter				exit(0);
24310015Speter			} else
24410015Speter				mon_pid = p;
24510015Speter		}
24610015Speter#endif /* CONFIG_WPA_CLI_FORK */
24710015Speter	}
24810015Speter
24910015Speter	return 0;
25010015Speter}
25110015Speter
25210015Speter
25310015Speterstatic void wpa_cli_close_connection(void)
25410015Speter{
25510015Speter	if (ctrl_conn == NULL)
25610015Speter		return;
25710015Speter
25810015Speter#ifdef CONFIG_WPA_CLI_FORK
25910015Speter	if (mon_pid) {
26010015Speter		int status;
26110015Speter		kill(mon_pid, SIGPIPE);
26210015Speter		wait(&status);
26310015Speter		mon_pid = 0;
26410015Speter	}
26510015Speter#endif /* CONFIG_WPA_CLI_FORK */
26610015Speter
26710015Speter	if (wpa_cli_attached) {
26810015Speter		wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
26910015Speter		wpa_cli_attached = 0;
27010015Speter	}
27110015Speter	wpa_ctrl_close(ctrl_conn);
27210015Speter	ctrl_conn = NULL;
27310015Speter	if (mon_conn) {
27410015Speter		wpa_ctrl_close(mon_conn);
27510015Speter		mon_conn = NULL;
27610015Speter	}
27710015Speter}
27810044Speter
27910015Speter
28010015Speterstatic void wpa_cli_msg_cb(char *msg, size_t len)
28110015Speter{
28210015Speter	printf("%s\n", msg);
28310015Speter}
28410015Speter
28510015Speter
28610015Speterstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
28712174Speter{
28829676Sgibbs	char buf[2048];
28910015Speter	size_t len;
290136058Sphk	int ret;
29110015Speter
29210015Speter	if (ctrl_conn == NULL) {
29310015Speter		printf("Not connected to wpa_supplicant - command dropped.\n");
294136058Sphk		return -1;
29510015Speter	}
29610015Speter	len = sizeof(buf) - 1;
29710015Speter	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
29810015Speter			       wpa_cli_msg_cb);
29910015Speter	if (ret == -2) {
30010015Speter		printf("'%s' command timed out.\n", cmd);
30110015Speter		return -2;
30210015Speter	} else if (ret < 0) {
303179589Speter		printf("'%s' command failed.\n", cmd);
304136058Sphk		return -1;
30510015Speter	}
30610015Speter	if (print) {
30710015Speter		buf[len] = '\0';
30810015Speter		printf("%s", buf);
30910015Speter	}
31010015Speter	return 0;
31110015Speter}
31210015Speter
31310015Speter
31410015Speterstatic int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
31510015Speter{
31610015Speter	return _wpa_ctrl_command(ctrl, cmd, 1);
31710015Speter}
31810015Speter
31910015Speter
32010015Speterstatic int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
32110015Speter{
32210044Speter	int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
32310044Speter	return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
32410015Speter}
32510015Speter
32610015Speter
32710015Speterstatic int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
32810015Speter{
32910015Speter	return wpa_ctrl_command(ctrl, "PING");
33010015Speter}
33110015Speter
33210015Speter
33310015Speterstatic int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
33410015Speter{
33510015Speter	return wpa_ctrl_command(ctrl, "MIB");
33610044Speter}
33710044Speter
33810044Speter
33910044Speterstatic int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
34010044Speter{
34110044Speter	return wpa_ctrl_command(ctrl, "PMKSA");
34210044Speter}
34310044Speter
34410044Speter
34510044Speterstatic int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
34610044Speter{
34710044Speter	print_help();
34810044Speter	return 0;
34910015Speter}
35010015Speter
35110015Speter
35210015Speterstatic int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
35310044Speter{
35410015Speter	printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
35510015Speter	return 0;
35610015Speter}
35710015Speter
35810015Speter
35910015Speterstatic int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
36010015Speter{
36112174Speter	wpa_cli_quit = 1;
36210015Speter	return 0;
36310015Speter}
36410015Speter
36510015Speter
36610015Speterstatic void wpa_cli_show_variables(void)
36710015Speter{
36810015Speter	printf("set variables:\n"
36910044Speter	       "  EAPOL::heldPeriod (EAPOL state machine held period, "
37010015Speter	       "in seconds)\n"
37110015Speter	       "  EAPOL::authPeriod (EAPOL state machine authentication "
37210015Speter	       "period, in seconds)\n"
37310015Speter	       "  EAPOL::startPeriod (EAPOL state machine start period, in "
37412174Speter	       "seconds)\n"
37510015Speter	       "  EAPOL::maxStart (EAPOL state machine maximum start "
37610015Speter	       "attempts)\n");
37710015Speter	printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
37810015Speter	       "seconds)\n"
37912174Speter	       "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
38010044Speter	       " threshold\n\tpercentage)\n"
38110044Speter	       "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
38212174Speter	       "security\n\tassociation in seconds)\n");
38310015Speter}
38410015Speter
38510044Speter
38610044Speterstatic int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
38710044Speter{
38810015Speter	char cmd[256];
38910044Speter	int res;
39010044Speter
39110015Speter	if (argc == 0) {
39210015Speter		wpa_cli_show_variables();
39310015Speter		return 0;
39410015Speter	}
39510015Speter
396	if (argc != 2) {
397		printf("Invalid SET command: needs two arguments (variable "
398		       "name and value)\n");
399		return -1;
400	}
401
402	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
403	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
404		printf("Too long SET command.\n");
405		return -1;
406	}
407	return wpa_ctrl_command(ctrl, cmd);
408}
409
410
411static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
412{
413	return wpa_ctrl_command(ctrl, "LOGOFF");
414}
415
416
417static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
418{
419	return wpa_ctrl_command(ctrl, "LOGON");
420}
421
422
423static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
424				   char *argv[])
425{
426	return wpa_ctrl_command(ctrl, "REASSOCIATE");
427}
428
429
430static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
431				       char *argv[])
432{
433	char cmd[256];
434	int res;
435
436	if (argc != 1) {
437		printf("Invalid PREAUTH command: needs one argument "
438		       "(BSSID)\n");
439		return -1;
440	}
441
442	res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
443	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
444		printf("Too long PREAUTH command.\n");
445		return -1;
446	}
447	return wpa_ctrl_command(ctrl, cmd);
448}
449
450
451static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
452{
453	char cmd[256];
454	int res;
455
456	if (argc != 1) {
457		printf("Invalid AP_SCAN command: needs one argument (ap_scan "
458		       "value)\n");
459		return -1;
460	}
461	res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
462	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
463		printf("Too long AP_SCAN command.\n");
464		return -1;
465	}
466	return wpa_ctrl_command(ctrl, cmd);
467}
468
469
470static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
471				char *argv[])
472{
473	char cmd[256];
474	int res;
475
476	if (argc != 1) {
477		printf("Invalid STKSTART command: needs one argument "
478		       "(Peer STA MAC address)\n");
479		return -1;
480	}
481
482	res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
483	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
484		printf("Too long STKSTART command.\n");
485		return -1;
486	}
487	return wpa_ctrl_command(ctrl, cmd);
488}
489
490
491static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
492{
493	char cmd[256];
494	int res;
495
496	if (argc != 1) {
497		printf("Invalid FT_DS command: needs one argument "
498		       "(Target AP MAC address)\n");
499		return -1;
500	}
501
502	res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
503	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
504		printf("Too long FT_DS command.\n");
505		return -1;
506	}
507	return wpa_ctrl_command(ctrl, cmd);
508}
509
510
511static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513	char cmd[256];
514	int res;
515
516	if (argc == 0) {
517		/* Any BSSID */
518		return wpa_ctrl_command(ctrl, "WPS_PBC");
519	}
520
521	/* Specific BSSID */
522	res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
523	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
524		printf("Too long WPS_PBC command.\n");
525		return -1;
526	}
527	return wpa_ctrl_command(ctrl, cmd);
528}
529
530
531static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
533	char cmd[256];
534	int res;
535
536	if (argc == 0) {
537		printf("Invalid WPS_PIN command: need one or two arguments:\n"
538		       "- BSSID: use 'any' to select any\n"
539		       "- PIN: optional, used only with devices that have no "
540		       "display\n");
541		return -1;
542	}
543
544	if (argc == 1) {
545		/* Use dynamically generated PIN (returned as reply) */
546		res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
547		if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
548			printf("Too long WPS_PIN command.\n");
549			return -1;
550		}
551		return wpa_ctrl_command(ctrl, cmd);
552	}
553
554	/* Use hardcoded PIN from a label */
555	res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
556	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
557		printf("Too long WPS_PIN command.\n");
558		return -1;
559	}
560	return wpa_ctrl_command(ctrl, cmd);
561}
562
563
564#ifdef CONFIG_WPS_OOB
565static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
566{
567	char cmd[256];
568	int res;
569
570	if (argc != 3 && argc != 4) {
571		printf("Invalid WPS_OOB command: need three or four "
572		       "arguments:\n"
573		       "- DEV_TYPE: use 'ufd' or 'nfc'\n"
574		       "- PATH: path of OOB device like '/mnt'\n"
575		       "- METHOD: OOB method 'pin-e' or 'pin-r', "
576		       "'cred'\n"
577		       "- DEV_NAME: (only for NFC) device name like "
578		       "'pn531'\n");
579		return -1;
580	}
581
582	if (argc == 3)
583		res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
584				  argv[0], argv[1], argv[2]);
585	else
586		res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
587				  argv[0], argv[1], argv[2], argv[3]);
588	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
589		printf("Too long WPS_OOB command.\n");
590		return -1;
591	}
592	return wpa_ctrl_command(ctrl, cmd);
593}
594#endif /* CONFIG_WPS_OOB */
595
596
597static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
598{
599	char cmd[256];
600	int res;
601
602	if (argc == 2)
603		res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
604				  argv[0], argv[1]);
605	else if (argc == 6) {
606		char ssid_hex[2 * 32 + 1];
607		char key_hex[2 * 64 + 1];
608		int i;
609
610		ssid_hex[0] = '\0';
611		for (i = 0; i < 32; i++) {
612			if (argv[2][i] == '\0')
613				break;
614			os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
615		}
616
617		key_hex[0] = '\0';
618		for (i = 0; i < 64; i++) {
619			if (argv[5][i] == '\0')
620				break;
621			os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
622		}
623
624		res = os_snprintf(cmd, sizeof(cmd),
625				  "WPS_REG %s %s %s %s %s %s",
626				  argv[0], argv[1], ssid_hex, argv[3], argv[4],
627				  key_hex);
628	} else {
629		printf("Invalid WPS_REG command: need two arguments:\n"
630		       "- BSSID: use 'any' to select any\n"
631		       "- AP PIN\n");
632		printf("Alternatively, six arguments can be used to "
633		       "reconfigure the AP:\n"
634		       "- BSSID: use 'any' to select any\n"
635		       "- AP PIN\n"
636		       "- new SSID\n"
637		       "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
638		       "- new encr (NONE, WEP, TKIP, CCMP)\n"
639		       "- new key\n");
640		return -1;
641	}
642
643	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
644		printf("Too long WPS_REG command.\n");
645		return -1;
646	}
647	return wpa_ctrl_command(ctrl, cmd);
648}
649
650
651static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
652				    char *argv[])
653{
654	return wpa_ctrl_command(ctrl, "WPS_ER_START");
655
656}
657
658
659static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
660				   char *argv[])
661{
662	return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
663
664}
665
666
667static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
668				  char *argv[])
669{
670	char cmd[256];
671	int res;
672
673	if (argc != 2) {
674		printf("Invalid WPS_ER_PIN command: need two arguments:\n"
675		       "- UUID: use 'any' to select any\n"
676		       "- PIN: Enrollee PIN\n");
677		return -1;
678	}
679
680	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
681			  argv[0], argv[1]);
682	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
683		printf("Too long WPS_ER_PIN command.\n");
684		return -1;
685	}
686	return wpa_ctrl_command(ctrl, cmd);
687}
688
689
690static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
691				  char *argv[])
692{
693	char cmd[256];
694	int res;
695
696	if (argc != 1) {
697		printf("Invalid WPS_ER_PBC command: need one argument:\n"
698		       "- UUID: Specify the Enrollee\n");
699		return -1;
700	}
701
702	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
703			  argv[0]);
704	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
705		printf("Too long WPS_ER_PBC command.\n");
706		return -1;
707	}
708	return wpa_ctrl_command(ctrl, cmd);
709}
710
711
712static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
713				    char *argv[])
714{
715	char cmd[256];
716	int res;
717
718	if (argc != 2) {
719		printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
720		       "- UUID: specify which AP to use\n"
721		       "- PIN: AP PIN\n");
722		return -1;
723	}
724
725	res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
726			  argv[0], argv[1]);
727	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
728		printf("Too long WPS_ER_LEARN command.\n");
729		return -1;
730	}
731	return wpa_ctrl_command(ctrl, cmd);
732}
733
734
735static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
736{
737	char cmd[256];
738	int res;
739
740	if (argc != 1) {
741		printf("Invalid IBSS_RSN command: needs one argument "
742		       "(Peer STA MAC address)\n");
743		return -1;
744	}
745
746	res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
747	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
748		printf("Too long IBSS_RSN command.\n");
749		return -1;
750	}
751	return wpa_ctrl_command(ctrl, cmd);
752}
753
754
755static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
756{
757	char cmd[256];
758	int res;
759
760	if (argc != 1) {
761		printf("Invalid LEVEL command: needs one argument (debug "
762		       "level)\n");
763		return -1;
764	}
765	res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
766	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
767		printf("Too long LEVEL command.\n");
768		return -1;
769	}
770	return wpa_ctrl_command(ctrl, cmd);
771}
772
773
774static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
775{
776	char cmd[256], *pos, *end;
777	int i, ret;
778
779	if (argc < 2) {
780		printf("Invalid IDENTITY command: needs two arguments "
781		       "(network id and identity)\n");
782		return -1;
783	}
784
785	end = cmd + sizeof(cmd);
786	pos = cmd;
787	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
788			  argv[0], argv[1]);
789	if (ret < 0 || ret >= end - pos) {
790		printf("Too long IDENTITY command.\n");
791		return -1;
792	}
793	pos += ret;
794	for (i = 2; i < argc; i++) {
795		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
796		if (ret < 0 || ret >= end - pos) {
797			printf("Too long IDENTITY command.\n");
798			return -1;
799		}
800		pos += ret;
801	}
802
803	return wpa_ctrl_command(ctrl, cmd);
804}
805
806
807static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
808{
809	char cmd[256], *pos, *end;
810	int i, ret;
811
812	if (argc < 2) {
813		printf("Invalid PASSWORD command: needs two arguments "
814		       "(network id and password)\n");
815		return -1;
816	}
817
818	end = cmd + sizeof(cmd);
819	pos = cmd;
820	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
821			  argv[0], argv[1]);
822	if (ret < 0 || ret >= end - pos) {
823		printf("Too long PASSWORD command.\n");
824		return -1;
825	}
826	pos += ret;
827	for (i = 2; i < argc; i++) {
828		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
829		if (ret < 0 || ret >= end - pos) {
830			printf("Too long PASSWORD command.\n");
831			return -1;
832		}
833		pos += ret;
834	}
835
836	return wpa_ctrl_command(ctrl, cmd);
837}
838
839
840static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
841				    char *argv[])
842{
843	char cmd[256], *pos, *end;
844	int i, ret;
845
846	if (argc < 2) {
847		printf("Invalid NEW_PASSWORD command: needs two arguments "
848		       "(network id and password)\n");
849		return -1;
850	}
851
852	end = cmd + sizeof(cmd);
853	pos = cmd;
854	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
855			  argv[0], argv[1]);
856	if (ret < 0 || ret >= end - pos) {
857		printf("Too long NEW_PASSWORD command.\n");
858		return -1;
859	}
860	pos += ret;
861	for (i = 2; i < argc; i++) {
862		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
863		if (ret < 0 || ret >= end - pos) {
864			printf("Too long NEW_PASSWORD command.\n");
865			return -1;
866		}
867		pos += ret;
868	}
869
870	return wpa_ctrl_command(ctrl, cmd);
871}
872
873
874static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
875{
876	char cmd[256], *pos, *end;
877	int i, ret;
878
879	if (argc < 2) {
880		printf("Invalid PIN command: needs two arguments "
881		       "(network id and pin)\n");
882		return -1;
883	}
884
885	end = cmd + sizeof(cmd);
886	pos = cmd;
887	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
888			  argv[0], argv[1]);
889	if (ret < 0 || ret >= end - pos) {
890		printf("Too long PIN command.\n");
891		return -1;
892	}
893	pos += ret;
894	for (i = 2; i < argc; i++) {
895		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
896		if (ret < 0 || ret >= end - pos) {
897			printf("Too long PIN command.\n");
898			return -1;
899		}
900		pos += ret;
901	}
902	return wpa_ctrl_command(ctrl, cmd);
903}
904
905
906static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
907{
908	char cmd[256], *pos, *end;
909	int i, ret;
910
911	if (argc < 2) {
912		printf("Invalid OTP command: needs two arguments (network "
913		       "id and password)\n");
914		return -1;
915	}
916
917	end = cmd + sizeof(cmd);
918	pos = cmd;
919	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
920			  argv[0], argv[1]);
921	if (ret < 0 || ret >= end - pos) {
922		printf("Too long OTP command.\n");
923		return -1;
924	}
925	pos += ret;
926	for (i = 2; i < argc; i++) {
927		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
928		if (ret < 0 || ret >= end - pos) {
929			printf("Too long OTP command.\n");
930			return -1;
931		}
932		pos += ret;
933	}
934
935	return wpa_ctrl_command(ctrl, cmd);
936}
937
938
939static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
940				  char *argv[])
941{
942	char cmd[256], *pos, *end;
943	int i, ret;
944
945	if (argc < 2) {
946		printf("Invalid PASSPHRASE command: needs two arguments "
947		       "(network id and passphrase)\n");
948		return -1;
949	}
950
951	end = cmd + sizeof(cmd);
952	pos = cmd;
953	ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
954			  argv[0], argv[1]);
955	if (ret < 0 || ret >= end - pos) {
956		printf("Too long PASSPHRASE command.\n");
957		return -1;
958	}
959	pos += ret;
960	for (i = 2; i < argc; i++) {
961		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
962		if (ret < 0 || ret >= end - pos) {
963			printf("Too long PASSPHRASE command.\n");
964			return -1;
965		}
966		pos += ret;
967	}
968
969	return wpa_ctrl_command(ctrl, cmd);
970}
971
972
973static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
974{
975	char cmd[256], *pos, *end;
976	int i, ret;
977
978	if (argc < 2) {
979		printf("Invalid BSSID command: needs two arguments (network "
980		       "id and BSSID)\n");
981		return -1;
982	}
983
984	end = cmd + sizeof(cmd);
985	pos = cmd;
986	ret = os_snprintf(pos, end - pos, "BSSID");
987	if (ret < 0 || ret >= end - pos) {
988		printf("Too long BSSID command.\n");
989		return -1;
990	}
991	pos += ret;
992	for (i = 0; i < argc; i++) {
993		ret = os_snprintf(pos, end - pos, " %s", argv[i]);
994		if (ret < 0 || ret >= end - pos) {
995			printf("Too long BSSID command.\n");
996			return -1;
997		}
998		pos += ret;
999	}
1000
1001	return wpa_ctrl_command(ctrl, cmd);
1002}
1003
1004
1005static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1006				     char *argv[])
1007{
1008	return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1009}
1010
1011
1012static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1013				      char *argv[])
1014{
1015	char cmd[32];
1016	int res;
1017
1018	if (argc < 1) {
1019		printf("Invalid SELECT_NETWORK command: needs one argument "
1020		       "(network id)\n");
1021		return -1;
1022	}
1023
1024	res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
1025	if (res < 0 || (size_t) res >= sizeof(cmd))
1026		return -1;
1027	cmd[sizeof(cmd) - 1] = '\0';
1028
1029	return wpa_ctrl_command(ctrl, cmd);
1030}
1031
1032
1033static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1034				      char *argv[])
1035{
1036	char cmd[32];
1037	int res;
1038
1039	if (argc < 1) {
1040		printf("Invalid ENABLE_NETWORK command: needs one argument "
1041		       "(network id)\n");
1042		return -1;
1043	}
1044
1045	res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
1046	if (res < 0 || (size_t) res >= sizeof(cmd))
1047		return -1;
1048	cmd[sizeof(cmd) - 1] = '\0';
1049
1050	return wpa_ctrl_command(ctrl, cmd);
1051}
1052
1053
1054static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1055				       char *argv[])
1056{
1057	char cmd[32];
1058	int res;
1059
1060	if (argc < 1) {
1061		printf("Invalid DISABLE_NETWORK command: needs one argument "
1062		       "(network id)\n");
1063		return -1;
1064	}
1065
1066	res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
1067	if (res < 0 || (size_t) res >= sizeof(cmd))
1068		return -1;
1069	cmd[sizeof(cmd) - 1] = '\0';
1070
1071	return wpa_ctrl_command(ctrl, cmd);
1072}
1073
1074
1075static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1076				   char *argv[])
1077{
1078	return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1079}
1080
1081
1082static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1083				      char *argv[])
1084{
1085	char cmd[32];
1086	int res;
1087
1088	if (argc < 1) {
1089		printf("Invalid REMOVE_NETWORK command: needs one argument "
1090		       "(network id)\n");
1091		return -1;
1092	}
1093
1094	res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
1095	if (res < 0 || (size_t) res >= sizeof(cmd))
1096		return -1;
1097	cmd[sizeof(cmd) - 1] = '\0';
1098
1099	return wpa_ctrl_command(ctrl, cmd);
1100}
1101
1102
1103static void wpa_cli_show_network_variables(void)
1104{
1105	printf("set_network variables:\n"
1106	       "  ssid (network name, SSID)\n"
1107	       "  psk (WPA passphrase or pre-shared key)\n"
1108	       "  key_mgmt (key management protocol)\n"
1109	       "  identity (EAP identity)\n"
1110	       "  password (EAP password)\n"
1111	       "  ...\n"
1112	       "\n"
1113	       "Note: Values are entered in the same format as the "
1114	       "configuration file is using,\n"
1115	       "i.e., strings values need to be inside double quotation "
1116	       "marks.\n"
1117	       "For example: set_network 1 ssid \"network name\"\n"
1118	       "\n"
1119	       "Please see wpa_supplicant.conf documentation for full list "
1120	       "of\navailable variables.\n");
1121}
1122
1123
1124static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1125				   char *argv[])
1126{
1127	char cmd[256];
1128	int res;
1129
1130	if (argc == 0) {
1131		wpa_cli_show_network_variables();
1132		return 0;
1133	}
1134
1135	if (argc != 3) {
1136		printf("Invalid SET_NETWORK command: needs three arguments\n"
1137		       "(network id, variable name, and value)\n");
1138		return -1;
1139	}
1140
1141	res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1142			  argv[0], argv[1], argv[2]);
1143	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1144		printf("Too long SET_NETWORK command.\n");
1145		return -1;
1146	}
1147	return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1152				   char *argv[])
1153{
1154	char cmd[256];
1155	int res;
1156
1157	if (argc == 0) {
1158		wpa_cli_show_network_variables();
1159		return 0;
1160	}
1161
1162	if (argc != 2) {
1163		printf("Invalid GET_NETWORK command: needs two arguments\n"
1164		       "(network id and variable name)\n");
1165		return -1;
1166	}
1167
1168	res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1169			  argv[0], argv[1]);
1170	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1171		printf("Too long GET_NETWORK command.\n");
1172		return -1;
1173	}
1174	return wpa_ctrl_command(ctrl, cmd);
1175}
1176
1177
1178static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1179				  char *argv[])
1180{
1181	return wpa_ctrl_command(ctrl, "DISCONNECT");
1182}
1183
1184
1185static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1186				  char *argv[])
1187{
1188	return wpa_ctrl_command(ctrl, "RECONNECT");
1189}
1190
1191
1192static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1193				   char *argv[])
1194{
1195	return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1196}
1197
1198
1199static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1200{
1201	return wpa_ctrl_command(ctrl, "SCAN");
1202}
1203
1204
1205static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1206				    char *argv[])
1207{
1208	return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1209}
1210
1211
1212static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1213{
1214	char cmd[64];
1215	int res;
1216
1217	if (argc != 1) {
1218		printf("Invalid BSS command: need one argument (index or "
1219		       "BSSID)\n");
1220		return -1;
1221	}
1222
1223	res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1224	if (res < 0 || (size_t) res >= sizeof(cmd))
1225		return -1;
1226	cmd[sizeof(cmd) - 1] = '\0';
1227
1228	return wpa_ctrl_command(ctrl, cmd);
1229}
1230
1231
1232static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1233				      char *argv[])
1234{
1235	char cmd[64];
1236	int res;
1237
1238	if (argc < 1 || argc > 2) {
1239		printf("Invalid GET_CAPABILITY command: need either one or "
1240		       "two arguments\n");
1241		return -1;
1242	}
1243
1244	if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1245		printf("Invalid GET_CAPABILITY command: second argument, "
1246		       "if any, must be 'strict'\n");
1247		return -1;
1248	}
1249
1250	res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1251			  (argc == 2) ? " strict" : "");
1252	if (res < 0 || (size_t) res >= sizeof(cmd))
1253		return -1;
1254	cmd[sizeof(cmd) - 1] = '\0';
1255
1256	return wpa_ctrl_command(ctrl, cmd);
1257}
1258
1259
1260static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1261{
1262	printf("Available interfaces:\n");
1263	return wpa_ctrl_command(ctrl, "INTERFACES");
1264}
1265
1266
1267static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1268{
1269	if (argc < 1) {
1270		wpa_cli_list_interfaces(ctrl);
1271		return 0;
1272	}
1273
1274	wpa_cli_close_connection();
1275	os_free(ctrl_ifname);
1276	ctrl_ifname = os_strdup(argv[0]);
1277
1278	if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1279		printf("Connected to interface '%s.\n", ctrl_ifname);
1280	} else {
1281		printf("Could not connect to interface '%s' - re-trying\n",
1282		       ctrl_ifname);
1283	}
1284	return 0;
1285}
1286
1287
1288static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1289				   char *argv[])
1290{
1291	return wpa_ctrl_command(ctrl, "RECONFIGURE");
1292}
1293
1294
1295static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1296				 char *argv[])
1297{
1298	return wpa_ctrl_command(ctrl, "TERMINATE");
1299}
1300
1301
1302static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1303				     char *argv[])
1304{
1305	char cmd[256];
1306	int res;
1307
1308	if (argc < 1) {
1309		printf("Invalid INTERFACE_ADD command: needs at least one "
1310		       "argument (interface name)\n"
1311		       "All arguments: ifname confname driver ctrl_interface "
1312		       "driver_param bridge_name\n");
1313		return -1;
1314	}
1315
1316	/*
1317	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1318	 * <driver_param>TAB<bridge_name>
1319	 */
1320	res = os_snprintf(cmd, sizeof(cmd),
1321			  "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1322			  argv[0],
1323			  argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1324			  argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1325			  argc > 5 ? argv[5] : "");
1326	if (res < 0 || (size_t) res >= sizeof(cmd))
1327		return -1;
1328	cmd[sizeof(cmd) - 1] = '\0';
1329	return wpa_ctrl_command(ctrl, cmd);
1330}
1331
1332
1333static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1334					char *argv[])
1335{
1336	char cmd[128];
1337	int res;
1338
1339	if (argc != 1) {
1340		printf("Invalid INTERFACE_REMOVE command: needs one argument "
1341		       "(interface name)\n");
1342		return -1;
1343	}
1344
1345	res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1346	if (res < 0 || (size_t) res >= sizeof(cmd))
1347		return -1;
1348	cmd[sizeof(cmd) - 1] = '\0';
1349	return wpa_ctrl_command(ctrl, cmd);
1350}
1351
1352
1353static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1354				      char *argv[])
1355{
1356	return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1357}
1358
1359
1360#ifdef CONFIG_AP
1361static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1362{
1363	char buf[64];
1364	if (argc != 1) {
1365		printf("Invalid 'sta' command - exactly one argument, STA "
1366		       "address, is required.\n");
1367		return -1;
1368	}
1369	os_snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1370	return wpa_ctrl_command(ctrl, buf);
1371}
1372
1373
1374static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1375				char *addr, size_t addr_len)
1376{
1377	char buf[4096], *pos;
1378	size_t len;
1379	int ret;
1380
1381	if (ctrl_conn == NULL) {
1382		printf("Not connected to hostapd - command dropped.\n");
1383		return -1;
1384	}
1385	len = sizeof(buf) - 1;
1386	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1387			       wpa_cli_msg_cb);
1388	if (ret == -2) {
1389		printf("'%s' command timed out.\n", cmd);
1390		return -2;
1391	} else if (ret < 0) {
1392		printf("'%s' command failed.\n", cmd);
1393		return -1;
1394	}
1395
1396	buf[len] = '\0';
1397	if (memcmp(buf, "FAIL", 4) == 0)
1398		return -1;
1399	printf("%s", buf);
1400
1401	pos = buf;
1402	while (*pos != '\0' && *pos != '\n')
1403		pos++;
1404	*pos = '\0';
1405	os_strlcpy(addr, buf, addr_len);
1406	return 0;
1407}
1408
1409
1410static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1411{
1412	char addr[32], cmd[64];
1413
1414	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1415		return 0;
1416	do {
1417		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1418	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1419
1420	return -1;
1421}
1422#endif /* CONFIG_AP */
1423
1424
1425static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1426{
1427	return wpa_ctrl_command(ctrl, "SUSPEND");
1428}
1429
1430
1431static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1432{
1433	return wpa_ctrl_command(ctrl, "RESUME");
1434}
1435
1436
1437static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1438{
1439	return wpa_ctrl_command(ctrl, "DROP_SA");
1440}
1441
1442
1443static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1444{
1445	char cmd[128];
1446	int res;
1447
1448	if (argc != 1) {
1449		printf("Invalid ROAM command: needs one argument "
1450		       "(target AP's BSSID)\n");
1451		return -1;
1452	}
1453
1454	res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]);
1455	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1456		printf("Too long ROAM command.\n");
1457		return -1;
1458	}
1459	return wpa_ctrl_command(ctrl, cmd);
1460}
1461
1462
1463enum wpa_cli_cmd_flags {
1464	cli_cmd_flag_none		= 0x00,
1465	cli_cmd_flag_sensitive		= 0x01
1466};
1467
1468struct wpa_cli_cmd {
1469	const char *cmd;
1470	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1471	enum wpa_cli_cmd_flags flags;
1472	const char *usage;
1473};
1474
1475static struct wpa_cli_cmd wpa_cli_commands[] = {
1476	{ "status", wpa_cli_cmd_status,
1477	  cli_cmd_flag_none,
1478	  "[verbose] = get current WPA/EAPOL/EAP status" },
1479	{ "ping", wpa_cli_cmd_ping,
1480	  cli_cmd_flag_none,
1481	  "= pings wpa_supplicant" },
1482	{ "mib", wpa_cli_cmd_mib,
1483	  cli_cmd_flag_none,
1484	  "= get MIB variables (dot1x, dot11)" },
1485	{ "help", wpa_cli_cmd_help,
1486	  cli_cmd_flag_none,
1487	  "= show this usage help" },
1488	{ "interface", wpa_cli_cmd_interface,
1489	  cli_cmd_flag_none,
1490	  "[ifname] = show interfaces/select interface" },
1491	{ "level", wpa_cli_cmd_level,
1492	  cli_cmd_flag_none,
1493	  "<debug level> = change debug level" },
1494	{ "license", wpa_cli_cmd_license,
1495	  cli_cmd_flag_none,
1496	  "= show full wpa_cli license" },
1497	{ "quit", wpa_cli_cmd_quit,
1498	  cli_cmd_flag_none,
1499	  "= exit wpa_cli" },
1500	{ "set", wpa_cli_cmd_set,
1501	  cli_cmd_flag_none,
1502	  "= set variables (shows list of variables when run without "
1503	  "arguments)" },
1504	{ "logon", wpa_cli_cmd_logon,
1505	  cli_cmd_flag_none,
1506	  "= IEEE 802.1X EAPOL state machine logon" },
1507	{ "logoff", wpa_cli_cmd_logoff,
1508	  cli_cmd_flag_none,
1509	  "= IEEE 802.1X EAPOL state machine logoff" },
1510	{ "pmksa", wpa_cli_cmd_pmksa,
1511	  cli_cmd_flag_none,
1512	  "= show PMKSA cache" },
1513	{ "reassociate", wpa_cli_cmd_reassociate,
1514	  cli_cmd_flag_none,
1515	  "= force reassociation" },
1516	{ "preauthenticate", wpa_cli_cmd_preauthenticate,
1517	  cli_cmd_flag_none,
1518	  "<BSSID> = force preauthentication" },
1519	{ "identity", wpa_cli_cmd_identity,
1520	  cli_cmd_flag_none,
1521	  "<network id> <identity> = configure identity for an SSID" },
1522	{ "password", wpa_cli_cmd_password,
1523	  cli_cmd_flag_sensitive,
1524	  "<network id> <password> = configure password for an SSID" },
1525	{ "new_password", wpa_cli_cmd_new_password,
1526	  cli_cmd_flag_sensitive,
1527	  "<network id> <password> = change password for an SSID" },
1528	{ "pin", wpa_cli_cmd_pin,
1529	  cli_cmd_flag_sensitive,
1530	  "<network id> <pin> = configure pin for an SSID" },
1531	{ "otp", wpa_cli_cmd_otp,
1532	  cli_cmd_flag_sensitive,
1533	  "<network id> <password> = configure one-time-password for an SSID"
1534	},
1535	{ "passphrase", wpa_cli_cmd_passphrase,
1536	  cli_cmd_flag_sensitive,
1537	  "<network id> <passphrase> = configure private key passphrase\n"
1538	  "  for an SSID" },
1539	{ "bssid", wpa_cli_cmd_bssid,
1540	  cli_cmd_flag_none,
1541	  "<network id> <BSSID> = set preferred BSSID for an SSID" },
1542	{ "list_networks", wpa_cli_cmd_list_networks,
1543	  cli_cmd_flag_none,
1544	  "= list configured networks" },
1545	{ "select_network", wpa_cli_cmd_select_network,
1546	  cli_cmd_flag_none,
1547	  "<network id> = select a network (disable others)" },
1548	{ "enable_network", wpa_cli_cmd_enable_network,
1549	  cli_cmd_flag_none,
1550	  "<network id> = enable a network" },
1551	{ "disable_network", wpa_cli_cmd_disable_network,
1552	  cli_cmd_flag_none,
1553	  "<network id> = disable a network" },
1554	{ "add_network", wpa_cli_cmd_add_network,
1555	  cli_cmd_flag_none,
1556	  "= add a network" },
1557	{ "remove_network", wpa_cli_cmd_remove_network,
1558	  cli_cmd_flag_none,
1559	  "<network id> = remove a network" },
1560	{ "set_network", wpa_cli_cmd_set_network,
1561	  cli_cmd_flag_sensitive,
1562	  "<network id> <variable> <value> = set network variables (shows\n"
1563	  "  list of variables when run without arguments)" },
1564	{ "get_network", wpa_cli_cmd_get_network,
1565	  cli_cmd_flag_none,
1566	  "<network id> <variable> = get network variables" },
1567	{ "save_config", wpa_cli_cmd_save_config,
1568	  cli_cmd_flag_none,
1569	  "= save the current configuration" },
1570	{ "disconnect", wpa_cli_cmd_disconnect,
1571	  cli_cmd_flag_none,
1572	  "= disconnect and wait for reassociate/reconnect command before\n"
1573	  "  connecting" },
1574	{ "reconnect", wpa_cli_cmd_reconnect,
1575	  cli_cmd_flag_none,
1576	  "= like reassociate, but only takes effect if already disconnected"
1577	},
1578	{ "scan", wpa_cli_cmd_scan,
1579	  cli_cmd_flag_none,
1580	  "= request new BSS scan" },
1581	{ "scan_results", wpa_cli_cmd_scan_results,
1582	  cli_cmd_flag_none,
1583	  "= get latest scan results" },
1584	{ "bss", wpa_cli_cmd_bss,
1585	  cli_cmd_flag_none,
1586	  "<<idx> | <bssid>> = get detailed scan result info" },
1587	{ "get_capability", wpa_cli_cmd_get_capability,
1588	  cli_cmd_flag_none,
1589	  "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
1590	{ "reconfigure", wpa_cli_cmd_reconfigure,
1591	  cli_cmd_flag_none,
1592	  "= force wpa_supplicant to re-read its configuration file" },
1593	{ "terminate", wpa_cli_cmd_terminate,
1594	  cli_cmd_flag_none,
1595	  "= terminate wpa_supplicant" },
1596	{ "interface_add", wpa_cli_cmd_interface_add,
1597	  cli_cmd_flag_none,
1598	  "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1599	  "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
1600	  "  are optional" },
1601	{ "interface_remove", wpa_cli_cmd_interface_remove,
1602	  cli_cmd_flag_none,
1603	  "<ifname> = removes the interface" },
1604	{ "interface_list", wpa_cli_cmd_interface_list,
1605	  cli_cmd_flag_none,
1606	  "= list available interfaces" },
1607	{ "ap_scan", wpa_cli_cmd_ap_scan,
1608	  cli_cmd_flag_none,
1609	  "<value> = set ap_scan parameter" },
1610	{ "stkstart", wpa_cli_cmd_stkstart,
1611	  cli_cmd_flag_none,
1612	  "<addr> = request STK negotiation with <addr>" },
1613	{ "ft_ds", wpa_cli_cmd_ft_ds,
1614	  cli_cmd_flag_none,
1615	  "<addr> = request over-the-DS FT with <addr>" },
1616	{ "wps_pbc", wpa_cli_cmd_wps_pbc,
1617	  cli_cmd_flag_none,
1618	  "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
1619	{ "wps_pin", wpa_cli_cmd_wps_pin,
1620	  cli_cmd_flag_sensitive,
1621	  "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1622	  "hardcoded)" },
1623#ifdef CONFIG_WPS_OOB
1624	{ "wps_oob", wpa_cli_cmd_wps_oob,
1625	  cli_cmd_flag_sensitive,
1626	  "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
1627#endif /* CONFIG_WPS_OOB */
1628	{ "wps_reg", wpa_cli_cmd_wps_reg,
1629	  cli_cmd_flag_sensitive,
1630	  "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
1631	{ "wps_er_start", wpa_cli_cmd_wps_er_start,
1632	  cli_cmd_flag_none,
1633	  "= start Wi-Fi Protected Setup External Registrar" },
1634	{ "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1635	  cli_cmd_flag_none,
1636	  "= stop Wi-Fi Protected Setup External Registrar" },
1637	{ "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1638	  cli_cmd_flag_sensitive,
1639	  "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
1640	{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1641	  cli_cmd_flag_none,
1642	  "<UUID> = accept an Enrollee PBC using External Registrar" },
1643	{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1644	  cli_cmd_flag_sensitive,
1645	  "<UUID> <PIN> = learn AP configuration" },
1646	{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1647	  cli_cmd_flag_none,
1648	  "<addr> = request RSN authentication with <addr> in IBSS" },
1649#ifdef CONFIG_AP
1650	{ "sta", wpa_cli_cmd_sta,
1651	  cli_cmd_flag_none,
1652	  "<addr> = get information about an associated station (AP)" },
1653	{ "all_sta", wpa_cli_cmd_all_sta,
1654	  cli_cmd_flag_none,
1655	  "= get information about all associated stations (AP)" },
1656#endif /* CONFIG_AP */
1657	{ "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
1658	  "= notification of suspend/hibernate" },
1659	{ "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
1660	  "= notification of resume/thaw" },
1661	{ "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
1662	  "= drop SA without deauth/disassoc (test command)" },
1663	{ "roam", wpa_cli_cmd_roam,
1664	  cli_cmd_flag_none,
1665	  "<addr> = roam to the specified BSS" },
1666	{ NULL, NULL, cli_cmd_flag_none, NULL }
1667};
1668
1669
1670/*
1671 * Prints command usage, lines are padded with the specified string.
1672 */
1673static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1674{
1675	char c;
1676	size_t n;
1677
1678	printf("%s%s ", pad, cmd->cmd);
1679	for (n = 0; (c = cmd->usage[n]); n++) {
1680		printf("%c", c);
1681		if (c == '\n')
1682			printf("%s", pad);
1683	}
1684	printf("\n");
1685}
1686
1687
1688static void print_help(void)
1689{
1690	int n;
1691	printf("commands:\n");
1692	for (n = 0; wpa_cli_commands[n].cmd; n++)
1693		print_cmd_help(&wpa_cli_commands[n], "  ");
1694}
1695
1696
1697#ifdef CONFIG_READLINE
1698static int cmd_has_sensitive_data(const char *cmd)
1699{
1700	const char *c, *delim;
1701	int n;
1702	size_t len;
1703
1704	delim = os_strchr(cmd, ' ');
1705	if (delim)
1706		len = delim - cmd;
1707	else
1708		len = os_strlen(cmd);
1709
1710	for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1711		if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1712			return (wpa_cli_commands[n].flags &
1713				cli_cmd_flag_sensitive);
1714	}
1715	return 0;
1716}
1717#endif /* CONFIG_READLINE */
1718
1719
1720static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1721{
1722	struct wpa_cli_cmd *cmd, *match = NULL;
1723	int count;
1724	int ret = 0;
1725
1726	count = 0;
1727	cmd = wpa_cli_commands;
1728	while (cmd->cmd) {
1729		if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1730		{
1731			match = cmd;
1732			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1733				/* we have an exact match */
1734				count = 1;
1735				break;
1736			}
1737			count++;
1738		}
1739		cmd++;
1740	}
1741
1742	if (count > 1) {
1743		printf("Ambiguous command '%s'; possible commands:", argv[0]);
1744		cmd = wpa_cli_commands;
1745		while (cmd->cmd) {
1746			if (os_strncasecmp(cmd->cmd, argv[0],
1747					   os_strlen(argv[0])) == 0) {
1748				printf(" %s", cmd->cmd);
1749			}
1750			cmd++;
1751		}
1752		printf("\n");
1753		ret = 1;
1754	} else if (count == 0) {
1755		printf("Unknown command '%s'\n", argv[0]);
1756		ret = 1;
1757	} else {
1758		ret = match->handler(ctrl, argc - 1, &argv[1]);
1759	}
1760
1761	return ret;
1762}
1763
1764
1765static int str_match(const char *a, const char *b)
1766{
1767	return os_strncmp(a, b, os_strlen(b)) == 0;
1768}
1769
1770
1771static int wpa_cli_exec(const char *program, const char *arg1,
1772			const char *arg2)
1773{
1774	char *cmd;
1775	size_t len;
1776	int res;
1777	int ret = 0;
1778
1779	len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1780	cmd = os_malloc(len);
1781	if (cmd == NULL)
1782		return -1;
1783	res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1784	if (res < 0 || (size_t) res >= len) {
1785		os_free(cmd);
1786		return -1;
1787	}
1788	cmd[len - 1] = '\0';
1789#ifndef _WIN32_WCE
1790	if (system(cmd) < 0)
1791		ret = -1;
1792#endif /* _WIN32_WCE */
1793	os_free(cmd);
1794
1795	return ret;
1796}
1797
1798
1799static void wpa_cli_action_process(const char *msg)
1800{
1801	const char *pos;
1802	char *copy = NULL, *id, *pos2;
1803
1804	pos = msg;
1805	if (*pos == '<') {
1806		/* skip priority */
1807		pos = os_strchr(pos, '>');
1808		if (pos)
1809			pos++;
1810		else
1811			pos = msg;
1812	}
1813
1814	if (str_match(pos, WPA_EVENT_CONNECTED)) {
1815		int new_id = -1;
1816		os_unsetenv("WPA_ID");
1817		os_unsetenv("WPA_ID_STR");
1818		os_unsetenv("WPA_CTRL_DIR");
1819
1820		pos = os_strstr(pos, "[id=");
1821		if (pos)
1822			copy = os_strdup(pos + 4);
1823
1824		if (copy) {
1825			pos2 = id = copy;
1826			while (*pos2 && *pos2 != ' ')
1827				pos2++;
1828			*pos2++ = '\0';
1829			new_id = atoi(id);
1830			os_setenv("WPA_ID", id, 1);
1831			while (*pos2 && *pos2 != '=')
1832				pos2++;
1833			if (*pos2 == '=')
1834				pos2++;
1835			id = pos2;
1836			while (*pos2 && *pos2 != ']')
1837				pos2++;
1838			*pos2 = '\0';
1839			os_setenv("WPA_ID_STR", id, 1);
1840			os_free(copy);
1841		}
1842
1843		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1844
1845		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1846			wpa_cli_connected = 1;
1847			wpa_cli_last_id = new_id;
1848			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1849		}
1850	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1851		if (wpa_cli_connected) {
1852			wpa_cli_connected = 0;
1853			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1854		}
1855	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1856		printf("wpa_supplicant is terminating - stop monitoring\n");
1857		wpa_cli_quit = 1;
1858	}
1859}
1860
1861
1862#ifndef CONFIG_ANSI_C_EXTRA
1863static void wpa_cli_action_cb(char *msg, size_t len)
1864{
1865	wpa_cli_action_process(msg);
1866}
1867#endif /* CONFIG_ANSI_C_EXTRA */
1868
1869
1870static void wpa_cli_reconnect(void)
1871{
1872	wpa_cli_close_connection();
1873	wpa_cli_open_connection(ctrl_ifname, 1);
1874}
1875
1876
1877static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1878				 int action_monitor)
1879{
1880	int first = 1;
1881	if (ctrl_conn == NULL) {
1882		wpa_cli_reconnect();
1883		return;
1884	}
1885	while (wpa_ctrl_pending(ctrl) > 0) {
1886		char buf[256];
1887		size_t len = sizeof(buf) - 1;
1888		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1889			buf[len] = '\0';
1890			if (action_monitor)
1891				wpa_cli_action_process(buf);
1892			else {
1893				if (in_read && first)
1894					printf("\r");
1895				first = 0;
1896				printf("%s\n", buf);
1897#ifdef CONFIG_READLINE
1898				rl_on_new_line();
1899				rl_redisplay();
1900#endif /* CONFIG_READLINE */
1901			}
1902		} else {
1903			printf("Could not read pending message.\n");
1904			break;
1905		}
1906	}
1907
1908	if (wpa_ctrl_pending(ctrl) < 0) {
1909		printf("Connection to wpa_supplicant lost - trying to "
1910		       "reconnect\n");
1911		wpa_cli_reconnect();
1912	}
1913}
1914
1915
1916#ifdef CONFIG_READLINE
1917static char * wpa_cli_cmd_gen(const char *text, int state)
1918{
1919	static int i, len;
1920	const char *cmd;
1921
1922	if (state == 0) {
1923		i = 0;
1924		len = os_strlen(text);
1925	}
1926
1927	while ((cmd = wpa_cli_commands[i].cmd)) {
1928		i++;
1929		if (os_strncasecmp(cmd, text, len) == 0)
1930			return strdup(cmd);
1931	}
1932
1933	return NULL;
1934}
1935
1936
1937static char * wpa_cli_dummy_gen(const char *text, int state)
1938{
1939	int i;
1940
1941	for (i = 0; wpa_cli_commands[i].cmd; i++) {
1942		const char *cmd = wpa_cli_commands[i].cmd;
1943		size_t len = os_strlen(cmd);
1944		if (os_strncasecmp(rl_line_buffer, cmd, len) == 0 &&
1945		    rl_line_buffer[len] == ' ') {
1946			printf("\n%s\n", wpa_cli_commands[i].usage);
1947			rl_on_new_line();
1948			rl_redisplay();
1949			break;
1950		}
1951	}
1952
1953	rl_attempted_completion_over = 1;
1954	return NULL;
1955}
1956
1957
1958static char * wpa_cli_status_gen(const char *text, int state)
1959{
1960	static int i, len;
1961	char *options[] = {
1962		"verbose", NULL
1963	};
1964	char *t;
1965
1966	if (state == 0) {
1967		i = 0;
1968		len = os_strlen(text);
1969	}
1970
1971	while ((t = options[i])) {
1972		i++;
1973		if (os_strncasecmp(t, text, len) == 0)
1974			return strdup(t);
1975	}
1976
1977	rl_attempted_completion_over = 1;
1978	return NULL;
1979}
1980
1981
1982static char ** wpa_cli_completion(const char *text, int start, int end)
1983{
1984	char * (*func)(const char *text, int state);
1985
1986	if (start == 0)
1987		func = wpa_cli_cmd_gen;
1988	else if (os_strncasecmp(rl_line_buffer, "status ", 7) == 0)
1989		func = wpa_cli_status_gen;
1990	else
1991		func = wpa_cli_dummy_gen;
1992	return rl_completion_matches(text, func);
1993}
1994#endif /* CONFIG_READLINE */
1995
1996
1997static void wpa_cli_interactive(void)
1998{
1999#define max_args 10
2000	char cmdbuf[256], *cmd, *argv[max_args], *pos;
2001	int argc;
2002#ifdef CONFIG_READLINE
2003	char *home, *hfile = NULL;
2004#endif /* CONFIG_READLINE */
2005
2006	printf("\nInteractive mode\n\n");
2007
2008#ifdef CONFIG_READLINE
2009	rl_attempted_completion_function = wpa_cli_completion;
2010	home = getenv("HOME");
2011	if (home) {
2012		const char *fname = ".wpa_cli_history";
2013		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
2014		hfile = os_malloc(hfile_len);
2015		if (hfile) {
2016			int res;
2017			res = os_snprintf(hfile, hfile_len, "%s/%s", home,
2018					  fname);
2019			if (res >= 0 && res < hfile_len) {
2020				hfile[hfile_len - 1] = '\0';
2021				read_history(hfile);
2022				stifle_history(100);
2023			}
2024		}
2025	}
2026#endif /* CONFIG_READLINE */
2027
2028	do {
2029		wpa_cli_recv_pending(mon_conn, 0, 0);
2030#ifndef CONFIG_NATIVE_WINDOWS
2031		alarm(ping_interval);
2032#endif /* CONFIG_NATIVE_WINDOWS */
2033#ifdef CONFIG_WPA_CLI_FORK
2034		if (mon_pid)
2035			kill(mon_pid, SIGUSR1);
2036#endif /* CONFIG_WPA_CLI_FORK */
2037#ifdef CONFIG_READLINE
2038		cmd = readline("> ");
2039		if (cmd && *cmd) {
2040			HIST_ENTRY *h;
2041			while (next_history())
2042				;
2043			h = previous_history();
2044			if (h == NULL || os_strcmp(cmd, h->line) != 0)
2045				add_history(cmd);
2046			next_history();
2047		}
2048#else /* CONFIG_READLINE */
2049		printf("> ");
2050		cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
2051#endif /* CONFIG_READLINE */
2052#ifndef CONFIG_NATIVE_WINDOWS
2053		alarm(0);
2054#endif /* CONFIG_NATIVE_WINDOWS */
2055		if (cmd == NULL)
2056			break;
2057		wpa_cli_recv_pending(mon_conn, 0, 0);
2058		pos = cmd;
2059		while (*pos != '\0') {
2060			if (*pos == '\n') {
2061				*pos = '\0';
2062				break;
2063			}
2064			pos++;
2065		}
2066		argc = 0;
2067		pos = cmd;
2068		for (;;) {
2069			while (*pos == ' ')
2070				pos++;
2071			if (*pos == '\0')
2072				break;
2073			argv[argc] = pos;
2074			argc++;
2075			if (argc == max_args)
2076				break;
2077			if (*pos == '"') {
2078				char *pos2 = os_strrchr(pos, '"');
2079				if (pos2)
2080					pos = pos2 + 1;
2081			}
2082			while (*pos != '\0' && *pos != ' ')
2083				pos++;
2084			if (*pos == ' ')
2085				*pos++ = '\0';
2086		}
2087		if (argc)
2088			wpa_request(ctrl_conn, argc, argv);
2089
2090		if (cmd != cmdbuf)
2091			free(cmd);
2092#ifdef CONFIG_WPA_CLI_FORK
2093		if (mon_pid)
2094			kill(mon_pid, SIGUSR2);
2095#endif /* CONFIG_WPA_CLI_FORK */
2096	} while (!wpa_cli_quit);
2097
2098#ifdef CONFIG_READLINE
2099	if (hfile) {
2100		/* Save command history, excluding lines that may contain
2101		 * passwords. */
2102		HIST_ENTRY *h;
2103		history_set_pos(0);
2104		while ((h = current_history())) {
2105			char *p = h->line;
2106			while (*p == ' ' || *p == '\t')
2107				p++;
2108			if (cmd_has_sensitive_data(p)) {
2109				h = remove_history(where_history());
2110				if (h) {
2111					os_free(h->line);
2112					os_free(h->data);
2113					os_free(h);
2114				} else
2115					next_history();
2116			} else
2117				next_history();
2118		}
2119		write_history(hfile);
2120		os_free(hfile);
2121	}
2122#endif /* CONFIG_READLINE */
2123}
2124
2125
2126static void wpa_cli_action(struct wpa_ctrl *ctrl)
2127{
2128#ifdef CONFIG_ANSI_C_EXTRA
2129	/* TODO: ANSI C version(?) */
2130	printf("Action processing not supported in ANSI C build.\n");
2131#else /* CONFIG_ANSI_C_EXTRA */
2132	fd_set rfds;
2133	int fd, res;
2134	struct timeval tv;
2135	char buf[256]; /* note: large enough to fit in unsolicited messages */
2136	size_t len;
2137
2138	fd = wpa_ctrl_get_fd(ctrl);
2139
2140	while (!wpa_cli_quit) {
2141		FD_ZERO(&rfds);
2142		FD_SET(fd, &rfds);
2143		tv.tv_sec = ping_interval;
2144		tv.tv_usec = 0;
2145		res = select(fd + 1, &rfds, NULL, NULL, &tv);
2146		if (res < 0 && errno != EINTR) {
2147			perror("select");
2148			break;
2149		}
2150
2151		if (FD_ISSET(fd, &rfds))
2152			wpa_cli_recv_pending(ctrl, 0, 1);
2153		else {
2154			/* verify that connection is still working */
2155			len = sizeof(buf) - 1;
2156			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
2157					     wpa_cli_action_cb) < 0 ||
2158			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
2159				printf("wpa_supplicant did not reply to PING "
2160				       "command - exiting\n");
2161				break;
2162			}
2163		}
2164	}
2165#endif /* CONFIG_ANSI_C_EXTRA */
2166}
2167
2168
2169static void wpa_cli_cleanup(void)
2170{
2171	wpa_cli_close_connection();
2172	if (pid_file)
2173		os_daemonize_terminate(pid_file);
2174
2175	os_program_deinit();
2176}
2177
2178static void wpa_cli_terminate(int sig)
2179{
2180	wpa_cli_cleanup();
2181	exit(0);
2182}
2183
2184
2185#ifdef CONFIG_WPA_CLI_FORK
2186static void wpa_cli_usr1(int sig)
2187{
2188#ifdef CONFIG_READLINE
2189	rl_on_new_line();
2190	rl_redisplay();
2191#endif /* CONFIG_READLINE */
2192}
2193#endif /* CONFIG_WPA_CLI_FORK */
2194
2195
2196#ifndef CONFIG_NATIVE_WINDOWS
2197static void wpa_cli_alarm(int sig)
2198{
2199	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
2200		printf("Connection to wpa_supplicant lost - trying to "
2201		       "reconnect\n");
2202		wpa_cli_close_connection();
2203	}
2204	if (!ctrl_conn)
2205		wpa_cli_reconnect();
2206	if (mon_conn)
2207		wpa_cli_recv_pending(mon_conn, 1, 0);
2208	alarm(ping_interval);
2209}
2210#endif /* CONFIG_NATIVE_WINDOWS */
2211
2212
2213static char * wpa_cli_get_default_ifname(void)
2214{
2215	char *ifname = NULL;
2216
2217#ifdef CONFIG_CTRL_IFACE_UNIX
2218	struct dirent *dent;
2219	DIR *dir = opendir(ctrl_iface_dir);
2220	if (!dir)
2221		return NULL;
2222	while ((dent = readdir(dir))) {
2223#ifdef _DIRENT_HAVE_D_TYPE
2224		/*
2225		 * Skip the file if it is not a socket. Also accept
2226		 * DT_UNKNOWN (0) in case the C library or underlying
2227		 * file system does not support d_type.
2228		 */
2229		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2230			continue;
2231#endif /* _DIRENT_HAVE_D_TYPE */
2232		if (os_strcmp(dent->d_name, ".") == 0 ||
2233		    os_strcmp(dent->d_name, "..") == 0)
2234			continue;
2235		printf("Selected interface '%s'\n", dent->d_name);
2236		ifname = os_strdup(dent->d_name);
2237		break;
2238	}
2239	closedir(dir);
2240#endif /* CONFIG_CTRL_IFACE_UNIX */
2241
2242#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2243	char buf[2048], *pos;
2244	size_t len;
2245	struct wpa_ctrl *ctrl;
2246	int ret;
2247
2248	ctrl = wpa_ctrl_open(NULL);
2249	if (ctrl == NULL)
2250		return NULL;
2251
2252	len = sizeof(buf) - 1;
2253	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2254	if (ret >= 0) {
2255		buf[len] = '\0';
2256		pos = os_strchr(buf, '\n');
2257		if (pos)
2258			*pos = '\0';
2259		ifname = os_strdup(buf);
2260	}
2261	wpa_ctrl_close(ctrl);
2262#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2263
2264	return ifname;
2265}
2266
2267
2268int main(int argc, char *argv[])
2269{
2270	int warning_displayed = 0;
2271	int c;
2272	int daemonize = 0;
2273	int ret = 0;
2274	const char *global = NULL;
2275
2276	if (os_program_init())
2277		return -1;
2278
2279	for (;;) {
2280		c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
2281		if (c < 0)
2282			break;
2283		switch (c) {
2284		case 'a':
2285			action_file = optarg;
2286			break;
2287		case 'B':
2288			daemonize = 1;
2289			break;
2290		case 'g':
2291			global = optarg;
2292			break;
2293		case 'G':
2294			ping_interval = atoi(optarg);
2295			break;
2296		case 'h':
2297			usage();
2298			return 0;
2299		case 'v':
2300			printf("%s\n", wpa_cli_version);
2301			return 0;
2302		case 'i':
2303			os_free(ctrl_ifname);
2304			ctrl_ifname = os_strdup(optarg);
2305			break;
2306		case 'p':
2307			ctrl_iface_dir = optarg;
2308			break;
2309		case 'P':
2310			pid_file = optarg;
2311			break;
2312		default:
2313			usage();
2314			return -1;
2315		}
2316	}
2317
2318	interactive = (argc == optind) && (action_file == NULL);
2319
2320	if (interactive)
2321		printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2322
2323	if (global) {
2324#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2325		ctrl_conn = wpa_ctrl_open(NULL);
2326#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2327		ctrl_conn = wpa_ctrl_open(global);
2328#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2329		if (ctrl_conn == NULL) {
2330			perror("Failed to connect to wpa_supplicant - "
2331			       "wpa_ctrl_open");
2332			return -1;
2333		}
2334	}
2335
2336#ifndef _WIN32_WCE
2337	signal(SIGINT, wpa_cli_terminate);
2338	signal(SIGTERM, wpa_cli_terminate);
2339#endif /* _WIN32_WCE */
2340#ifndef CONFIG_NATIVE_WINDOWS
2341	signal(SIGALRM, wpa_cli_alarm);
2342#endif /* CONFIG_NATIVE_WINDOWS */
2343#ifdef CONFIG_WPA_CLI_FORK
2344	signal(SIGUSR1, wpa_cli_usr1);
2345#endif /* CONFIG_WPA_CLI_FORK */
2346
2347	if (ctrl_ifname == NULL)
2348		ctrl_ifname = wpa_cli_get_default_ifname();
2349
2350	if (interactive) {
2351		for (; !global;) {
2352			if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
2353				if (warning_displayed)
2354					printf("Connection established.\n");
2355				break;
2356			}
2357
2358			if (!warning_displayed) {
2359				printf("Could not connect to wpa_supplicant - "
2360				       "re-trying\n");
2361				warning_displayed = 1;
2362			}
2363			os_sleep(1, 0);
2364			continue;
2365		}
2366	} else {
2367		if (!global &&
2368		    wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
2369			perror("Failed to connect to wpa_supplicant - "
2370			       "wpa_ctrl_open");
2371			return -1;
2372		}
2373
2374		if (action_file) {
2375			if (wpa_ctrl_attach(ctrl_conn) == 0) {
2376				wpa_cli_attached = 1;
2377			} else {
2378				printf("Warning: Failed to attach to "
2379				       "wpa_supplicant.\n");
2380				return -1;
2381			}
2382		}
2383	}
2384
2385	if (daemonize && os_daemonize(pid_file))
2386		return -1;
2387
2388	if (interactive)
2389		wpa_cli_interactive();
2390	else if (action_file)
2391		wpa_cli_action(ctrl_conn);
2392	else
2393		ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2394
2395	os_free(ctrl_ifname);
2396	wpa_cli_cleanup();
2397
2398	return ret;
2399}
2400
2401#else /* CONFIG_CTRL_IFACE */
2402int main(int argc, char *argv[])
2403{
2404	printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2405	return -1;
2406}
2407#endif /* CONFIG_CTRL_IFACE */
2408