18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - command line interface for hostapd daemon
3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <dirent.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/common.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/eloop.h"
151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/edit.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/version.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *hostapd_cli_version =
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"hostapd_cli v" VERSION_STR "\n"
21fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *hostapd_cli_license =
25c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"This software may be distributed under the terms of the BSD license.\n"
26c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"See README for more details.\n";
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *hostapd_cli_full_license =
29c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt"This software may be distributed under the terms of the BSD license.\n"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"Redistribution and use in source and binary forms, with or without\n"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"modification, are permitted provided that the following conditions are\n"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"met:\n"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"1. Redistributions of source code must retain the above copyright\n"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   notice, this list of conditions and the following disclaimer.\n"
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"2. Redistributions in binary form must reproduce the above copyright\n"
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   notice, this list of conditions and the following disclaimer in the\n"
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   documentation and/or other materials provided with the distribution.\n"
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   names of its contributors may be used to endorse or promote products\n"
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   derived from this software without specific prior written permission.\n"
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n"
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"\n";
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *commands_help =
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"Commands:\n"
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   mib                  get MIB variables (dot1x, dot11, radius)\n"
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   sta <addr>           get MIB variables for one station\n"
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   all_sta              get MIB variables for all stations\n"
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   new_sta <addr>       add a new station\n"
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   deauthenticate <addr>  deauthenticate a station\n"
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   disassociate <addr>  disassociate a station\n"
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   sa_query <addr>      send SA Query to a station\n"
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\n"
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_check_pin <PIN>  verify PIN checksum\n"
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_pbc              indicate button pushed to initiate PBC\n"
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt"   wps_cancel           cancel the pending WPS operation\n"
7504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
7604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_tag_read <hexdump>  report read NFC tag with WPS data\n"
7704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_config_token <WPS/NDEF>  build NFC configuration token\n"
7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt"   wps_nfc_token <WPS/NDEF/enable/disable>  manager NFC password token\n"
7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\n"
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   wps_config <SSID> <auth> <encr> <key>  configure AP\n"
82b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt"   wps_get_status       show current WPS status\n"
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   get_config           show current configuration\n"
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   help                 show this usage help\n"
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   interface [ifname]   show interfaces/select interface\n"
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   level <debug level>  change debug level\n"
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   license              show full hostapd_cli license\n"
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt"   quit                 exit hostapd_cli\n";
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ctrl *ctrl_conn;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_quit = 0;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_attached = 0;
94205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson
95205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#ifndef CONFIG_CTRL_IFACE_DIR
96205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
97205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson#endif /* CONFIG_CTRL_IFACE_DIR */
98205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnsonstatic const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
99205f2142134d2f3475fe1f893575df8f809eede4Jeff Johnson
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *ctrl_ifname = NULL;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pid_file = NULL;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *action_file = NULL;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ping_interval = 5;
1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int interactive = 0;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr, "%s\n", hostapd_cli_version);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fprintf(stderr,
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"[-a<path>] \\\n"
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                   [-G<ping interval>] [command..]\n"
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"\n"
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Options:\n"
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -h           help (show this usage text)\n"
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -v           shown version information\n"
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -p<path>     path to find control sockets (default: "
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"/var/run/hostapd)\n"
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -a<file>     run in daemon mode executing the action file "
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"based on events\n"
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                from hostapd\n"
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -B           run a daemon in the background\n"
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"   -i<ifname>   Interface to listen on (default: first "
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"interface found in the\n"
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"                socket path)\n\n"
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"%s",
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		commands_help);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *cfile;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int flen;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ifname == NULL)
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cfile = malloc(flen);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cfile == NULL)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctrl_conn = wpa_ctrl_open(cfile);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free(cfile);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ctrl_conn;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_close_connection(void)
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL)
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_cli_attached) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ctrl_detach(ctrl_conn);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_attached = 0;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_ctrl_close(ctrl_conn);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctrl_conn = NULL;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_msg_cb(char *msg, size_t len)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s\n", msg);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[4096];
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL) {
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Not connected to hostapd - command dropped.\n");
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(buf) - 1;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hostapd_cli_msg_cb);
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == -2) {
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command timed out.\n", cmd);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret < 0) {
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command failed.\n", cmd);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (print) {
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[len] = '\0';
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s", buf);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return _wpa_ctrl_command(ctrl, cmd, 1);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "PING");
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "RELOG");
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
219cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
220cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{
221fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
222fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
223cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	return wpa_ctrl_command(ctrl, "STATUS");
224cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt}
225cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
226cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
229fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 0) {
230fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		char buf[100];
231fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
232fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return wpa_ctrl_command(ctrl, buf);
233fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "MIB");
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_exec(const char *program, const char *arg1,
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const char *arg2)
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
241772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	char *arg;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
245772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	len = os_strlen(arg1) + os_strlen(arg2) + 2;
246772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	arg = os_malloc(len);
247772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	if (arg == NULL)
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
249772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	os_snprintf(arg, len, "%s %s", arg1, arg2);
250772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	res = os_exec(program, arg, 1);
251772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	os_free(arg);
252772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen
253772e12cfed81754a9fd890be7bc77bc602a549b5Jouni Malinen	return res;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_action_process(char *msg, size_t len)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *pos;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos == '<') {
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(pos, '>');
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos)
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = msg;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_exec(action_file, ctrl_ifname, pos);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
277fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc < 1) {
278fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		printf("Invalid 'sta' command - at least one argument, STA "
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "address, is required.\n");
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
282fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (argc > 1)
283fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
284fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	else
285fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		snprintf(buf, sizeof(buf), "STA %s", argv[0]);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'new_sta' command - exactly one argument, STA "
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "address, is required.\n");
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  char *argv[])
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'deauthenticate' command - exactly one "
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "argument, STA address, is required.\n");
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 1)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    argv[0], argv[1]);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					char *argv[])
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'disassociate' command - exactly one "
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "argument, STA address, is required.\n");
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 1)
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    argv[0], argv[1]);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    char *argv[])
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'sa_query' command - exactly one argument, "
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "STA address, is required.\n");
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 2) {
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_pin' command - at least two arguments, "
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "UUID and PIN, are required.\n");
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2], argv[3]);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 2)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2]);
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 char *argv[])
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1 && argc != 2) {
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "- PIN to be verified\n");
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc == 2)
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  argv[0], argv[1]);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  argv[0]);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long WPS_CHECK_PIN command.\n");
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_PBC");
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
41104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      char *argv[])
41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
41704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    char *argv[])
42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
42204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int ret;
42304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char *buf;
42404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	size_t buflen;
42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_tag_read' command - one argument "
42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "is required.\n");
42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	buflen = 18 + os_strlen(argv[0]);
43304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	buf = os_malloc(buflen);
43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (buf == NULL)
43504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
43604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
43704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
43804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	ret = wpa_ctrl_command(ctrl, buf);
43904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	os_free(buf);
44004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return ret;
44204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
44304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
44504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
44604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						int argc, char *argv[])
44704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
44804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char cmd[64];
44904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int res;
45004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
45104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
45204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_config_token' command - one argument "
45304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "is required.\n");
45404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
45504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
45604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
45704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
45804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			  argv[0]);
45904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
46004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
46104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
46204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
46304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
46404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
46504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
46604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
46704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
46804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 int argc, char *argv[])
46904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
47004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	char cmd[64];
47104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int res;
47204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
47304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (argc != 1) {
47404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Invalid 'wps_nfc_token' command - one argument is "
47504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		       "required.\n");
47604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
47704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
47804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
47904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
48004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
48104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		printf("Too long WPS_NFC_TOKEN command.\n");
48204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return -1;
48304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
48404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
48504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
486f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
487f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
488f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
489f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt						int argc, char *argv[])
490f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{
491f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	char cmd[64];
492f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	int res;
493f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
494f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (argc != 2) {
495f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		printf("Invalid 'nfc_get_handover_sel' command - two arguments "
496f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		       "are required.\n");
497f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return -1;
498f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
499f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
500f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
501f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			  argv[0], argv[1]);
502f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
503f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		printf("Too long NFC_GET_HANDOVER_SEL command.\n");
504f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return -1;
505f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
506f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
507f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt}
508f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
50904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
51004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
51104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_ap_pin' command - at least one argument "
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "is required.\n");
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 2)
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1], argv[2]);
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 1)
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 argv[0], argv[1]);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
533b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
534b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt					  char *argv[])
535b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
536b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
537b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
538b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
539b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ssid_hex[2 * 32 + 1];
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char key_hex[2 * 64 + 1];
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid 'wps_config' command - at least two arguments "
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "are required.\n");
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid_hex[0] = '\0';
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 32; i++) {
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (argv[0][i] == '\0')
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_hex[0] = '\0';
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3) {
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < 64; i++) {
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (argv[3][i] == '\0')
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_snprintf(&key_hex[i * 2], 3, "%02x",
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    argv[3][i]);
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > 3)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1], argv[2], key_hex);
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (argc > 2)
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1], argv[2]);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 ssid_hex, argv[1]);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
585a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
586a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt					     char *argv[])
587a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
588a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[300];
589a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	int res;
590a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
591a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (argc < 2) {
592a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		printf("Invalid 'disassoc_imminent' command - two arguments "
593a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		       "(STA addr and Disassociation Timer) are needed\n");
594a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
595a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
596a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
597a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
598a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			  argv[0], argv[1]);
599a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
600a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		return -1;
601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
603a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					char *argv[])
6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char buf[300];
6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int res;
6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
611b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	if (argc < 3) {
612b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		printf("Invalid 'ess_disassoc' command - three arguments (STA "
613b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		       "addr, disassoc timer, and URL) are needed\n");
6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
6151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
617b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
618b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			  argv[0], argv[1], argv[2]);
6191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
6201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      char *argv[])
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, "GET_CONFIG");
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				char *addr, size_t addr_len)
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[4096], *pos;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL) {
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Not connected to hostapd - command dropped.\n");
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(buf) - 1;
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hostapd_cli_msg_cb);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == -2) {
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command timed out.\n", cmd);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ret < 0) {
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("'%s' command failed.\n", cmd);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf[len] = '\0';
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (memcmp(buf, "FAIL", 4) == 0)
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s", buf);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*pos != '\0' && *pos != '\n')
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = '\0';
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(addr, buf, addr_len);
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char addr[32], cmd[64];
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	do {
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s", commands_help);
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   char *argv[])
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
699051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					   int argc, char *argv[])
700051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
701051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char buf[200];
702051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int res;
703051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
704051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (argc != 1) {
705051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		printf("Invalid 'set_qos_map_set' command - "
706051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "one argument (comma delimited QoS map set) "
707051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "is needed\n");
708051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
709051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
710051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
711051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
712051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
713051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
714051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
715051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
716051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
717051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
718051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
719051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					     int argc, char *argv[])
720051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
721051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char buf[50];
722051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int res;
723051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
724051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (argc != 1) {
725051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		printf("Invalid 'send_qos_map_conf' command - "
726051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		       "one argument (STA addr) is needed\n");
727051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
728051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
729051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
730051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
731051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
732051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return -1;
733051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
734051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
735051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
736051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
737f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
738f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					  char *argv[])
739f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
740f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	char buf[300];
741f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	int res;
742f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
743f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc < 2) {
744f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
745f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       "addr and URL) are needed\n");
746f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
747f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
748f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
749f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
750f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			  argv[0], argv[1]);
751f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
752f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
753f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
754f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
755f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
756f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
757f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtstatic int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
758f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					   char *argv[])
759f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{
760f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	char buf[300];
761f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	int res;
762f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
763f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc < 3) {
764f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
765f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
766f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
767f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
768f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (argc > 3)
769f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		res = os_snprintf(buf, sizeof(buf),
770f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  "HS20_DEAUTH_REQ %s %s %s %s",
771f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  argv[0], argv[1], argv[2], argv[3]);
772f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else
773f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		res = os_snprintf(buf, sizeof(buf),
774f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  "HS20_DEAUTH_REQ %s %s %s",
775f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				  argv[0], argv[1], argv[2]);
776f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (res < 0 || res >= (int) sizeof(buf))
777f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return -1;
778f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	return wpa_ctrl_command(ctrl, buf);
779f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt}
780f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
781f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_quit = 1;
7851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (interactive)
7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		eloop_terminate();
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid LEVEL command: needs one argument (debug "
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "level)\n");
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dirent *dent;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	DIR *dir;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dir = opendir(ctrl_iface_dir);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dir == NULL) {
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Control interface directory '%s' could not be "
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "openned.\n", ctrl_iface_dir);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Available interfaces:\n");
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((dent = readdir(dir))) {
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strcmp(dent->d_name, ".") == 0 ||
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    strcmp(dent->d_name, "..") == 0)
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s\n", dent->d_name);
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	closedir(dir);
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     char *argv[])
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 1) {
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_list_interfaces(ctrl);
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_close_connection();
836717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	os_free(ctrl_ifname);
837717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	ctrl_ifname = os_strdup(argv[0]);
838661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (ctrl_ifname == NULL)
839661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		return -1;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hostapd_cli_open_connection(ctrl_ifname)) {
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Connected to interface '%s.\n", ctrl_ifname);
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_attach(ctrl_conn) == 0) {
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_attached = 1;
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Warning: Failed to attach to "
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "hostapd.\n");
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not connect to interface '%s' - re-trying\n",
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_ifname);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 2) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid SET command: needs two arguments (variable "
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "name and value)\n");
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long SET command.\n");
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char cmd[256];
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc != 1) {
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Invalid GET command: needs one argument (variable "
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "name)\n");
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Too long GET command.\n");
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
897e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtstatic int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
898e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				       int argc, char *argv[])
899e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{
900e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	char cmd[256];
901e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int res;
902e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int i;
903e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	char *tmp;
904e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	int total;
905e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
906e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	if (argc < 2) {
907e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		printf("Invalid chan_switch command: needs at least two "
908e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "arguments (count and freq)\n"
909e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "usage: <cs_count> <freq> [sec_channel_offset=] "
910e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "[center_freq1=] [center_freq2=] [bandwidth=] "
911e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		       "[blocktx] [ht|vht]\n");
912e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		return -1;
913e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
914e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
915e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
916e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			  argv[0], argv[1]);
917e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
918e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		printf("Too long CHAN_SWITCH command.\n");
919e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		return -1;
920e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
921e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
922e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	total = res;
923e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	for (i = 2; i < argc; i++) {
924e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		tmp = cmd + total;
925e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
926e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
927e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			printf("Too long CHAN_SWITCH command.\n");
928e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			return -1;
929e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		}
930e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		total += res;
931e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
932e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
933e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt}
934e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
935e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
936df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
937df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{
938df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	char cmd[256];
939df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	int res;
940df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
941df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	if (argc < 2 || argc > 3) {
942df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		printf("Invalid vendor command\n"
943df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		       "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
944df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		return -1;
945df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	}
946df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
947df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
948df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt			  argc == 3 ? argv[2] : "");
949df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
950df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		printf("Too long VENDOR command.\n");
951df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		return -1;
952df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	}
953df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	return wpa_ctrl_command(ctrl, cmd);
954df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt}
955df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
956df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct hostapd_cli_cmd {
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const char *cmd;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_cli_cmd hostapd_cli_commands[] = {
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "ping", hostapd_cli_cmd_ping },
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "mib", hostapd_cli_cmd_mib },
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "relog", hostapd_cli_cmd_relog },
966cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	{ "status", hostapd_cli_cmd_status },
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "sta", hostapd_cli_cmd_sta },
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "all_sta", hostapd_cli_cmd_all_sta },
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "new_sta", hostapd_cli_cmd_new_sta },
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "deauthenticate", hostapd_cli_cmd_deauthenticate },
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "disassociate", hostapd_cli_cmd_disassociate },
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "sa_query", hostapd_cli_cmd_sa_query },
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_pin", hostapd_cli_cmd_wps_pin },
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
97904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_cancel", hostapd_cli_cmd_wps_cancel },
98004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC
98104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
98204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
98304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
984f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "wps_config", hostapd_cli_cmd_wps_config },
988b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	{ "wps_get_status", hostapd_cli_cmd_wps_get_status },
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
990a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
9911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "get_config", hostapd_cli_cmd_get_config },
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "help", hostapd_cli_cmd_help },
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "interface", hostapd_cli_cmd_interface },
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "level", hostapd_cli_cmd_level },
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "license", hostapd_cli_cmd_license },
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "quit", hostapd_cli_cmd_quit },
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "set", hostapd_cli_cmd_set },
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ "get", hostapd_cli_cmd_get },
1000051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1001051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1002e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	{ "chan_switch", hostapd_cli_cmd_chan_switch },
1003f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1004f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1005df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	{ "vendor", hostapd_cli_cmd_vendor },
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{ NULL, NULL }
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_cli_cmd *cmd, *match = NULL;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = 0;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmd = hostapd_cli_commands;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmd->cmd) {
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			match = cmd;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* we have an exact match */
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				count = 1;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			count++;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd++;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count > 1) {
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Ambiguous command '%s'; possible commands:", argv[0]);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmd = hostapd_cli_commands;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (cmd->cmd) {
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    0) {
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf(" %s", cmd->cmd);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cmd++;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (count == 0) {
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown command '%s'\n", argv[0]);
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		match->handler(ctrl, argc - 1, &argv[1]);
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     int action_monitor)
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int first = 1;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn == NULL)
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (wpa_ctrl_pending(ctrl)) {
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		char buf[256];
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len = sizeof(buf) - 1;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf[len] = '\0';
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (action_monitor)
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hostapd_cli_action_process(buf, len);
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else {
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (in_read && first)
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					printf("\n");
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				first = 0;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("%s\n", buf);
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not read pending message.\n");
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define max_args 10
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int tokenize_cmd(char *cmd, char *argv[])
10791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
10801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *pos;
10811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int argc = 0;
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = cmd;
10841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (;;) {
10851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (*pos == ' ')
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
10871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == '\0')
10881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		argv[argc] = pos;
10901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		argc++;
10911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (argc == max_args)
10921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
10931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == '"') {
10941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			char *pos2 = os_strrchr(pos, '"');
10951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (pos2)
10961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				pos = pos2 + 1;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (*pos != '\0' && *pos != ' ')
10991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			pos++;
11001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (*pos == ' ')
11011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			*pos++ = '\0';
11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return argc;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Connection to hostapd lost - trying to reconnect\n");
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_close_connection();
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ctrl_conn) {
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_conn) {
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Connection to hostapd re-established\n");
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_ctrl_attach(ctrl_conn) == 0) {
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				hostapd_cli_attached = 1;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else {
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Warning: Failed to attach to "
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "hostapd.\n");
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctrl_conn)
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
11291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
11331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_terminate();
11351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
11391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	char *argv[max_args];
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int argc;
11421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	argc = tokenize_cmd(cmd, argv);
11431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (argc)
11441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_request(ctrl_conn, argc, argv);
11451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_edit_eof_cb(void *ctx)
11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_terminate();
11511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_interactive(void)
11551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	printf("\nInteractive mode\n\n");
11571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
11591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
116061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		  NULL, NULL, NULL, NULL);
11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_run();
11641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	edit_deinit(NULL, NULL);
11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
11681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void hostapd_cli_cleanup(void)
11711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
11721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hostapd_cli_close_connection();
11731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (pid_file)
11741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		os_daemonize_terminate(pid_file);
11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_program_deinit();
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_cli_action(struct wpa_ctrl *ctrl)
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd_set rfds;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fd, res;
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct timeval tv;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[256];
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd = wpa_ctrl_get_fd(ctrl);
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (!hostapd_cli_quit) {
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_ZERO(&rfds);
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_SET(fd, &rfds);
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_sec = ping_interval;
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tv.tv_usec = 0;
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = select(fd + 1, &rfds, NULL, NULL, &tv);
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 && errno != EINTR) {
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("select");
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (FD_ISSET(fd, &rfds))
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_recv_pending(ctrl, 0, 1);
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = sizeof(buf) - 1;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     hostapd_cli_action_process) < 0 ||
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("hostapd did not reply to PING "
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "command - exiting\n");
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int warning_displayed = 0;
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int daemonize = 0;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = getopt(argc, argv, "a:BhG:i:p:v");
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'a':
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			action_file = optarg;
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'B':
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			daemonize = 1;
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'G':
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ping_interval = atoi(optarg);
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'h':
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'v':
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%s\n", hostapd_cli_version);
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'i':
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(ctrl_ifname);
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_ifname = os_strdup(optarg);
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'p':
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ctrl_iface_dir = optarg;
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	interactive = (argc == optind) && (action_file == NULL);
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive) {
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s\n\n%s\n\n", hostapd_cli_version,
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       hostapd_cli_license);
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (eloop_init())
12671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
12681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_ifname == NULL) {
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			struct dirent *dent;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			DIR *dir = opendir(ctrl_iface_dir);
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (dir) {
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				while ((dent = readdir(dir))) {
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					if (os_strcmp(dent->d_name, ".") == 0
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    ||
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    os_strcmp(dent->d_name, "..") == 0)
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						continue;
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					printf("Selected interface '%s'\n",
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       dent->d_name);
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ctrl_ifname = os_strdup(dent->d_name);
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					break;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				closedir(dir);
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ctrl_conn) {
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (warning_displayed)
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Connection established.\n");
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!interactive) {
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			perror("Failed to connect to hostapd - "
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "wpa_ctrl_open");
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!warning_displayed) {
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not connect to hostapd - re-trying\n");
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			warning_displayed = 1;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_sleep(1, 0);
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		continue;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive || action_file) {
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_ctrl_attach(ctrl_conn) == 0) {
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_cli_attached = 1;
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Warning: Failed to attach to hostapd.\n");
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (action_file)
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (daemonize && os_daemonize(pid_file))
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (interactive)
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_interactive();
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (action_file)
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_cli_action(ctrl_conn);
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(ctrl_ifname);
13291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_destroy();
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_cli_cleanup();
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1333